* fix(mobile): keep Agent Mode off the emulated-mobile load path
`app.emulateMobile(true)` flips Platform.isMobile to true (stubbing Node's
built-ins to null) but leaves Platform.isDesktopApp true — so gating Agent Mode
on isDesktopApp still imported the @/agentMode barrel, whose module-scope
`promisify(execFile)` then crashed the whole plugin with
"Cannot read properties of null (reading 'promisify')". Add isDesktopRuntime()
(Platform.isDesktopApp && !Platform.isMobile) and gate every Agent Mode
load/registration on it so the barrel is never imported on a Node-less runtime.
Update the mobile-load smoke gate rule to enforce the new gate and add a unit test.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore(lint): ban Platform.isDesktopApp; route desktop gating through isDesktopRuntime()
Platform.isDesktopApp stays true under app.emulateMobile(true) (which stubs Node),
so it doesn't keep desktop-only/Node code off the emulated-mobile path. Add a
no-restricted-properties ESLint rule banning it (the canonical check in
src/utils/desktopRuntime.ts is exempt via an inline disable), and migrate all 14
existing usages — web viewer, encryption/keychain, Miyo discovery, web-tab and
@-mention chat hooks, and main.ts's web-viewer gates — to isDesktopRuntime().
Behavior is unchanged on real desktop and mobile; only emulateMobile now faithfully
hides these desktop-only features.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(mobile): shim `process` so the bundle survives module-eval on mobile
Follow-up to #2576 (preview issue #125). After the EventEmitter fix, mobile now
crashes at load with "ReferenceError: Can't find variable: process".
Cause: Agent Mode is desktop-only but its modules are statically imported, so
they're evaluated on every platform. Several read the Node global `process` at
module scope (e.g. `InstallCommandRow.tsx`'s `const DEFAULT_LABEL =
process.platform === "win32" ? ...`, the codex/claude/opencode descriptors),
and bundled Node deps read `process.env` at init. Mobile's WebView has no
`process`, so evaluating any of them throws during import and kills the plugin.
Fix: prepend a minimal `process` shim in the esbuild banner —
`var process = globalThis.process || { env:{}, platform:"", ... }`. Desktop
(Electron) has a real `globalThis.process` and uses it unchanged; mobile gets
the stub, so module evaluation no longer throws. The desktop-only code paths
that actually use `process` never run on mobile.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore(test-vault): copy-deploy into iCloud-synced vaults for mobile testing
`npm run test:vault` symlinks main.js/styles.css by default, but iCloud syncs
file contents, not link targets, so a symlinked build never reaches the phone.
Detect iCloud vaults (path under "/Mobile Documents/") and copy real files
instead, so deploying to an iCloud vault makes the build testable on Obsidian
mobile. Mirrors the existing WSL copy-mode rule.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(mobile): keep agent mode off load path
* test(mobile): add load smoke check
* fix(mobile): share agent chat mode constant
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The script previously symlinked `main.js` / `styles.css` into the test
vault and assumed the destination filesystem could resolve POSIX
symlinks. On WSL with a vault under `/mnt/c/...`, Obsidian on Windows
cannot follow WSL-flavored symlinks stored on DrvFs/9p, so the symlinks
appear broken and the plugin fails to load.
Detect WSL (`uname -r` contains "microsoft") with a `/mnt/`-mounted
vault and switch to file copy. macOS / native Linux keep the existing
symlink behavior — no change for the canonical developer path.
Also refuse to deploy when the worktree itself lives inside the target
vault. Otherwise the build artifacts and source tree become vault
content, Obsidian indexes the whole repo on the next reload, and the
plugin directory may coincide with the worktree (deploying onto itself).
* docs(design): add model management redesign spec + data model spec
Replaces the older MODEL_MANAGEMENT_REDESIGN.md with a more focused tech spec,
a data-model spec with review notes, and a portal-container contract doc that
the upcoming reimplementation will follow.
* boostrap new model managmeent
* introduce catalog download service
* Add service APIs
* Add provider and configured model registry
* implement verification logic
* Add backend config registry and byok setup api
* Add BYOK settings modal
* Fix lint error
* Add BYOK settings - agent enablement
* Fix opencode enable model UI
* Fix claude extended thinking
* Render model descriptions
* Fix model picker padding
* improve agent model enabler settings
* Add copilot plus flash support in opencode
* Add vault test with test fixture
* BYOK model management
* introduce model migration script
* feat(skills): redesign skills discovery — discover-in-place, lazy migration
Reverse the import-everything-to-canonical model. The Skills tab now
discovers skills wherever they live (canonical or any agent project
folder) on open — no rescan button, no consent dialog. Identical
duplicates across agents collapse into one row; same-name/different-body
copies stay as disambiguated rows. Cross-agent sharing now goes through
a single explanatory migrate-to-shared confirm, and agents write skills
at their native paths.
Adds project-skill discovery, recursive directory hashing for the
merge rule, a pure toggle-decision helper, and a project→canonical
migration path. Removes the old bulkMove/importDetector/spawnDirective
machinery and the ImportConsentDialog. Fixes the delete dialog to show
the real blast radius for project skills (no phantom canonical copy or
symlink). Includes a seed script for the discovery test scenarios.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore(test-vault): tag deployed manifest with branch + build timestamp
`npm run test:vault` now writes a real `manifest.json` (instead of a symlink
to the worktree copy) with the current git branch and a `yyyymmdd-HHMMSS`
build timestamp appended to `name` and prepended to `description`. Surfaces
the active worktree/build directly in Obsidian's Community plugins list, so
"is my latest build actually loaded?" is a glance instead of a guess.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(chain): stop writing chainType back inside setChain (apply-Plus freeze)
Applying a Copilot Plus license key froze Obsidian. Root cause: ChainManager
ran multiple concurrent `createChainWithNewModel` invocations (one from the
constructor's `initialize()`, plus one each from the settings, model-key, and
chain-type subscribers firing on `applyPlusSettings`). Each captured
`chainType = getChainType()` at its start, awaited `setChatModel(...)`, then
resumed with a now-stale local value and wrote it back to `chainTypeAtom`
via `setChain` → `setChainType`. The write re-fired the chain-type
subscriber in ProjectManager, which scheduled another stale-closure
rebuild, and the atom bounced indefinitely between `LLM_CHAIN` and
`COPILOT_PLUS_CHAIN`.
Inlined `setChain` into `createChainWithNewModel` and removed the redundant
chainType write-back. The atom is owned by the UI dropdowns and
`applyPlusSettings`; this function only reads from it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(chain): fix outdated comment reference to removed test file
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a one-command dev workflow: install + build + symlink main.js /
manifest.json / styles.css from the current worktree into
$COPILOT_TEST_VAULT_PATH/.obsidian/plugins/copilot/, then reload the
plugin via the Obsidian CLI. Removes the manual build/copy/reload loop
across Conductor worktrees. Docs added to CONTRIBUTING.md and AGENTS.md.
* chore(eslint): enable no-explicit-any; fix ~395 violations
Switches @typescript-eslint/no-explicit-any from "off" to "error" and
replaces explicit `any` with proper types or `unknown` + narrowing
across ~100 source files and 15 test files. Eleven eslint-disable
comments remain: one for a BaseLanguageModel prototype patch and ten
for Orama<any> API surfaces where typed alternatives poison Orama's
internal inference to `never`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(scripts): cast chainContext to ChainManager in printPromptDebugEntry
The earlier `as any` → `as unknown` rewrite left buildAgentPromptDebugReport's
chainManager argument typed as `unknown`, which CI's `tsc -noEmit` (without
`--skipLibCheck`) flagged. Restore the cast through the real ChainManager type.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(eslint): fix remaining no-explicit-any and unnecessary-type-assertion errors
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(eslint): drop redundant no-explicit-any rule
Already set to "error" by typescript-eslint/recommendedTypeChecked via
obsidianmd's recommended config.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the `off` override and fixes all 368 violations via type casts,
widened parameter types (unknown / string|null|undefined for functions
that defensively handle non-string inputs), and concrete types in place
of `any` for Lexical nodes, mock objects, and option handlers.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Remove the explicit "off" overrides in eslint.config.mjs so the rules
from obsidianmd.configs.recommended apply. Add a scoped disable for the
sole violation in scripts/printPromptDebug.js, where the dynamic import
targets a controlled path under os.tmpdir() produced by esbuild.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the deferred `"off"` override and rewrites the 55 violations
(all in test/mocks/Node-script files) to use `window.*` instead of
`global.*`. Production code was already cleaned up in #2401.
- 18 test files + __mocks__/obsidian.js + jest.setup.js: mechanical
`global.X` → `window.X` (Jest runs under jsdom, so window === globalThis)
- scripts/printPromptDebugEntry.ts: inline eslint-disable — Node-only
debug script with no window available
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Implement self-host mode
* Migrate from XML tool calls to native tool calls and reimplement agent mode
* Use ChatOpenRouter for copilot-plus-flash for native tool call sse support
* Fix QA exclusion for search v3
* Update plan and remove debug messages in agent
* Migrate chains off of xml and clean up related logic
* Implement agent reasoning block
* Update css for responsiveness
* Implement agent query pre-expansion and proper reasoning block display for search
* Update agent docs
* Refine agent reason block
* Refine agent reasoning UX
* Fallback to plus non-agent if native tool call is not supported by the model
* Fix time filter query
* Update self-host description
* Skip agent reasoning block and old tool call banners during chat save and load
* Fix projects mode switch to plus and chat auto saves as non-project bug
* Building persistent memory for copilot (#1848)
* Implement chat input v3 (#1794)
* Fix chat crash React 409 (#1849)
* Fix mobile typeahead menu size (#1853)
* Enhance progress bar and bug fix (#1814)
* feat: Add edit context for progress card.
* fix: When adding a model, do not set the key in the single model setting.
* fix: fix the width of the popover on mobile.
* Refactor Brevilabs API integration to use models base URL (#1855)
- Updated constants to switch from BREVILABS_API_BASE_URL to BREVILABS_MODELS_BASE_URL for model-related API calls.
- Adjusted ChatModelManager and EmbeddingManager to utilize the new models base URL for configuration settings.
* feat: Add new chat history popover. (#1850)
* feat: Add new chat history popover.
* feat: Add open source file button to chat history popover
- Add ArrowUpRight button to each chat history item
- Implement openChatSourceFile method in main.ts
- Add onOpenSourceFile callback prop chain through components
- Open chat files in new Obsidian tabs when clicked
- Optimize error handling to prevent duplicate notices
* feat: Implement localSearch CiC prompting flow in CopilotPlusChainRunner (#1856)
* Properly extract response text in UserMemoryManager (#1857)
* feat: Temporarily disable autocomplete features (#1858)
* chore: Update version to 3.1.0-preview-250927 in manifest.json
* Support space in typeahead trigger and improve search (#1859)
* More chat input enhancement (#1864)
* Fix dropdown color
* Fix badge border in light theme
* Increase search result number
* support paste image
* fix folder context
* Enhance ChatPersistenceManager with filename sanitization tests (#1865)
- Added tests to ensure proper sanitization of wiki link brackets and illegal characters in filenames when saving chat messages.
- Updated filename generation logic to handle empty sanitized topics by defaulting to 'Untitled Chat'.
- Refactored imports in ChatPersistenceManager for better organization.
* Update ApplyView accept button styles for improved visibility and interaction (#1866)
- Adjusted the positioning of the action button to be further from the bottom of the viewport for better accessibility.
- Increased the z-index to ensure the button is always on top of other elements.
- Added a shadow effect to enhance the button's visibility against the background.
* Expose add selection to chat context to free users (#1867)
* New chat input improvements (#1868)
* Improve search logic in at mention search
* Subscribe to file changes
* Detect changes for folders and tags
* Make context badge tooltip always show
* Add full note path in preview
* Fix enter being blocked when no search result
* Rebuild "Active Note" and more chat input improvement (#1873)
* Performance improvement and extend "active note" to note typeahead menu (#1875)
* Add better agent prompt logging (#1882)
* Add read tool (#1883)
* Add readNote tool for reading notes in chunks
* Enhance readNote tool to support dynamic note path display and linked note extraction
* Refine readNote tool instructions for improved clarity and efficiency in note content retrieval
* Add support for readNote tool: integrate emoji, format results, and refine instructions
* Add inline citation reminder functionality to user questions
* Add an alert when user hits the maxToken limit (#1884)
* Refactor AutonomousAgentChainRunner (#1887)
* Refactor AutonomousAgentChainRunner to enhance agent workflow, streamline context preparation, and improve response handling
* Enhance type safety in addChatHistoryToMessages by specifying message structure
* Improve max iteration limit message for clarity and formatting
* Refactor tool display name handling for improved clarity and maintainability
* Refactor tool call ID generation and visibility handling for improved clarity and uniqueness
* Fix agent tool call ID (#1890)
* Enhance tool call ID generation and improve readNote handling in prompts
Update readNote description for clarity and improve prompt instructions
* Update instructions for registerFileTreeTool to clarify usage guidelines
* Clarify instructions for readNote tool to improve context inference and handling of partial note titles
* Add token counter (#1889)
* Fix index rebuild on semantic search toggle (#1891)
* Update token counter label (#1892)
* Implement tag search v3 (#1893)
* feat: Enhance TieredLexicalRetriever to support tag-based retrieval and improve search scoring
- Added support for returning all matching tags in TieredLexicalRetriever.
- Introduced new options for tag terms and returnAllTags in the retriever.
- Updated FullTextEngine to prioritize tag matches and improve scoring for documents with tags.
- Enhanced tokenization to handle hierarchical tags and prevent splitting hyphenated tags.
- Improved handling of frontmatter tags in documents.
- Updated search tools to accommodate new tag handling features.
- Added tests to verify the functionality of tag-based retrieval and scoring improvements.
* fix: Improve logging for query expansion in SearchCore
* feat: Add explanation for non-tag matches in FullTextEngine search results
* feat: Enhance QueryExpander to preserve standalone terms in tag handling and improve term validation
* feat: Enhance QueryExpander and TieredLexicalRetriever to improve tag handling and standalone term extraction
* Update version to 3.1.0-preview-251006 in manifest.json
* Normalize tag queries for case-insensitive matching and improve search functionality (#1894)
* Implement merge retriever (#1896)
* Fix note read (#1897)
* Enhance note resolution logic and add tests for wiki-linked notes and basename matching
* Implement note resolution outcome types and enhance readNoteTool tests for ambiguous matches
* Add deriveReadNoteDisplayName function and enhance readNoteTool tests for edge cases
* Fix note tool UI freeze (#1898)
* Update how tags work in context (#1895)
* Enhance file creation instructions in modelAdapter and update tool usage guidelines in builtinTools (#1901)
- Added instructions for confirming folder existence before creating new files in modelAdapter.
- Updated custom prompt instructions in builtinTools to clarify the use of getFileTree for folder lookups when creating new notes.
* Do not add url context for youtube url (#1899)
* Update YouTube Script command and modal title to indicate Plus feature (#1903)
* Enhance ChatPersistenceManager to handle file save conflicts (#1904)
* Enhance ChatPersistenceManager to handle file save conflicts and improve epoch handling
* Fix type checking for existing files in ChatPersistenceManager to prevent errors
* Fix verify add (#1905)
- Rename "Verify" button to "Test" in Add Model dialog
- Make verification not required for adding model in Set Keys
- Upgrade chatAnthropic client to fix the Top P -1 error for Claude Opus models
* Enhance XML parsing to handle tool calls missing closing tags
---------
Co-authored-by: Wenzheng Jiang <jwzh.hi@gmail.com>
Co-authored-by: Zero Liu <zero@lumos.com>
Co-authored-by: Emt-lin <41323133+Emt-lin@users.noreply.github.com>