Skip to content

Merge v4-preview into master - #2781

Merged
logancyang merged 241 commits into
masterfrom
v4-preview
Aug 8, 2026
Merged

Merge v4-preview into master#2781
logancyang merged 241 commits into
masterfrom
v4-preview

Conversation

@logancyang

@logancyang logancyang commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Why

master has been parked at the v3.3.3 release since bd8829f5 while all v4 work
accumulated on v4-preview. This brings the two back together so master
carries the v4 codebase.

What

Merges the v4 work from v4-preview into master. The merge is clean — no
conflicts. master had one commit v4-preview lacked (632c1e81, the README v4
promo); because master enforces strict status checks, that commit was first
merged into v4-preview, so this PR is now a straight fast-forward of master.

This publishes nothing. release.yml fires on any PR merged into master
but exits early unless the PR title is a semver string. This title is not, so no
tag is created and no GitHub Release is cut. package.json stays at 3.3.3.

Non goal

  • No version bump. Cutting the v4 release is a separate PR titled with the
    target semver, which is what triggers the release workflow.
  • No release notes, no RELEASES.md entry.
  • No code changes of its own — the diff is exactly what already merged into
    v4-preview PR by PR.

Screenshot

Not applicable — a branch integration with no diff of its own.

Risk

Low

Criterion Status Reason
No behavior change, or a cosmetic/copy/docs/config change visible where it renders, or deterministic tests cover the changed behavior Every commit shipped through its own reviewed PR with CI green on v4-preview
A defect would fail CI or be obvious on first use node.js.yml runs the full suite on this PR
A revert fully restores prior state, including persisted data Revertible as a merge commit; no migration runs at merge time
No auth, permissions, secrets, or input-handling surface changes No changes beyond what is already on v4-preview
No public API, plugin API, message, or on-disk contract changes Same — settled per PR upstream
No core-path concurrency, async-lifecycle, or state-machine changes Same
No hot-path behavior lacks deterministic coverage Same
No new dependency No manifest change relative to v4-preview
Human-only behavior stays in one feature area and surfaces quickly Nothing ships to users until a semver-titled release PR merges

Review: confirm the title is not a semver string, confirm the base is master
and the head is v4-preview, and confirm CI is green. There is no per-file diff
to inspect that was not already reviewed on its own PR.

Verification

  1. Confirm the PR title is not a semver string, so release.yml will exit early.
  2. Confirm CI is green on this PR.
  3. After merge, confirm no new tag or GitHub Release appeared under Releases.
  4. Confirm master and v4-preview now point at the same tree:
    git diff origin/master origin/v4-preview is empty.

zeroliu and others added 30 commits May 20, 2026 19:05
Squashed from 8 commits on zero/acp-test:
- feat(agent-mode): introduce Agent Mode feature (squashed)
- Fix eslint
- hide add context button
- chore: ban parent-relative imports and rewrite existing ones to @/ aliases
- wip(agent-mode): skills management + slash command revamp
- fix(agent-mode): initialize SkillManager before preload probes
- fix(build): align svgr jsxRuntime with tsconfig classic jsx
- fix(test): stub ItemView/WorkspaceLeaf in ChatSingleMessage obsidian mock
Bash tool calls collapse the command to 60 chars in the trail, which is
correct for noise but left the full command unreachable. Add an optional
`expandedDetails` hook on `ToolSummary` and implement it for Bash so
clicking the card surfaces the full command (with `# description`
prefix when present). Drop the `!inline` expand restriction so commands
inside an `AggregateCard` are individually expandable too.

Also adds an AGENTS.md rule requiring `cn()` around any Tailwind class
string that lives outside a literal JSX `className=` attribute so
`eslint-plugin-tailwindcss` actually lints them, and refactors
ActionCard's class composition to follow it.

Includes two unrelated micro-edits already in the working tree:
trailing-whitespace fix in chatModelManager.ts and a stale TODO removal
in AGENT_MODE_TODOS.md.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… GUI PATH (#2480)

macOS GUI apps launched from Finder/Dock inherit a minimal launchd PATH
(`/usr/bin:/bin:/usr/sbin:/sbin`) that omits Homebrew and user install
prefixes, so `which codex-acp` returned nothing and the Auto-detect button
falsely reported "not found." Augment PATH with the well-known prefixes
(`/opt/homebrew/bin`, `/usr/local/bin`) before invoking `which`, sharing
one source of truth with the existing spawn-time augmentation in
`nodeShebangPath`. For Claude, the Auto-detect button now routes through
the existing `resolveClaudeBinary` resolver (Volta/asdf/NVM/Homebrew/
npm-global/`~/.local/bin`) via a new optional `detect` prop on
`BinaryPathSetting`, matching the candidate list already used by the top
status row.
…2481)

New installs now start with Agent Mode on. Mobile is locked off at the
sanitizer level so a desktop-synced settings file can't activate the
unsupported subprocess flow.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Support agent image and PDF prompt context

* Use agent read for PDF context
* fix(agent-mode): preserve persisted enabled flag on mobile

Sanitization no longer force-overrides agentMode.enabled on mobile, so
a desktop-synced preference is not silently overwritten the next time
mobile persists settings. Mobile gating now lives at usage sites via a
shared isAgentModeEnabled / useIsAgentModeEnabled helper.

* fix(lint): drop unused Platform import in commands/index.ts

The remaining `Platform.isDesktopApp` site uses a dynamic import that
shadows the top-level binding, so the static import is unused after the
agent-mode gating refactor.
* feat(agent-mode): tint chat input border and mode picker by mode

Plan mode shows a blue border and soft glow; auto mode shows red.
The mode picker label picks up a matching faded color that brightens
on hover/focus, making the active agent mode obvious at a glance.

* fix(agent-mode): preserve mode tint on keyboard focus

The ghost2 button variant applies focus-visible:tw-text-normal, which
overrode the focus: tint on keyboard focus. Switch to focus-visible:
so tailwind-merge resolves the conflict in favor of the mode color.
…2485)

* fix(agent-mode): queue mode/model switch while session is still starting

* fix(agent-mode): disable picker while session is starting instead of queueing

Replace the await-session.ready queueing approach with a UI-level gate:
canSwitchModel/Effort/Mode now return false while status === "starting",
so the picker renders as disabled until the backend session is ready.
The await-during-onChange path made the picker feel buggy because clicks
appeared to do nothing for a beat before applying.

* fix(agent-mode): re-render mode/model picker on session status change

The picker hooks compute a memoization signal that React diffs to decide
when to rebuild the override. Status was not part of the signal, so the
starting → idle transition fired listeners but the snapshot string was
unchanged and the picker stayed disabled forever. Include `getStatus()`
in both signals so the picker re-enables once the session is ready.
Consolidates the three duplicated model configuration surfaces (basic
settings keys, Models settings table, agent mode curation) into a
single design for product designer handoff. Covers unified Models
panel, agent-first onboarding with three paths, per-backend defaults,
and OpenCode/Copilot Plus as system-managed sections.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hoist the agent-mode picker out of the not-generating branch so users
can flip between Auto/Plan/Safe mid-turn instead of having to wait for
the agent to stop. Non-agent chats are unaffected since they don't
pass modePickerOverride.
* Stop persisting agent mode selection

* Force canonical default mode on every new agent session

Restore `applyPersistedMode` as a small coerce helper and wire it back
into every backend's `applyInitialSessionConfig` with a literal
`"default"` — never reading from settings. Codex-acp's natural starting
native mode is `read-only` (canonical `plan`), so without this the
picker landed on Plan on every fresh chat.

For codex specifically, also pin the spawn-time approval/sandbox config
via `-c approval_policy="on-request"` and `-c sandbox_mode="workspace-write"`
so codex-acp's first `currentModeId` already matches the canonical `auto`
preset. Without these, the picker briefly flashed "Plan" before the
post-spawn coerce switched it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Drop redundant post-spawn mode coerce

The codex picker briefly flashing "Plan" was fixed at the spawn level
(`-c approval_policy/sandbox_mode` in CodexBackend). Claude's SDK and
opencode's spawn-time `default_agent` already start in canonical
`default`, so the runtime `applyPersistedMode(session, "default")`
calls on all three backends were dead defense-in-depth. Remove them
along with the now-unused helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Drop stale type-only import comment in settings/model.ts

`import type` is erased at runtime, so there's no actual cycle to
guard against — the keyword itself already signals "type-only" to
any reader.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…w-up (#2490)

- MODEL_MANAGEMENT_REDESIGN.md: BYOK is now the central, user-bring-only
  registry; drop per-model and per-provider Availability/Capability toggles;
  one global table with provider section rows; Quick Chat added as a 4th
  agent sub-tab; OpenCode/Plus models stay in the Agent panel only.
- QUICK_CHAT_AGENT_INTEGRATION.md (new): follow-up plan for elevating
  LangChain chat into a first-class agent backend (routing service, session
  adapter, v2->v3 settings migration, milestones Q1-Q6).
- AGENT_MODE_TODOS.md: mark shipped items; add notes for opencode/local
  models and subscription-based opencode flows.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the brief "Read Read" / "Edited Edit" flash that appeared while
a tool call's input JSON was still streaming. `targetFromTitle` now
returns an ellipsis when the title is just the vendor tool name (the
SDK's documented placeholder state), and a new `verb()` helper picks the
present-participle form for pending/in_progress calls and the past-tense
form for completed/failed ones — so cards read "Reading notes/foo.md" →
"Read notes/foo.md", "Fetching url" → "Fetched url", etc.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the modal-based permission prompter with inline ToolPermissionCard
rendered at the tail of the chat scroll, matching how plan proposals already
work. Refactor AgentSession status to be derived from underlying primitives
(resolver maps, abortController, etc.) so it cannot drift from reality, and
add tests covering the awaiting_permission lifecycle and turn-error reset.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds an "Environment variables" editor to each Agent Mode backend
(Claude, Codex, opencode) so users can inject vars like
CLAUDE_CONFIG_DIR, CODEX_HOME, XDG_CONFIG_HOME, or HTTPS_PROXY without
polluting the parent shell. Overrides are merged onto process.env at
spawn (Codex, opencode) or per prompt() (Claude SDK), and persisted
through a shared sanitizer that enforces POSIX-style names, drops
control chars, and caps the record at 64 entries. The editor debounces
commits to avoid rewriting settings on every keystroke.

Also relocates BinaryPathSetting into src/agentMode/backends/shared/
to honor the agent-mode layer boundaries.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codex (and other non-Claude agents) silently ignore the Claude-only
frontmatter flags (`disable-model-invocation`, `user-invocable`,
`model`), so hard-disabling their toggles on those skills was overly
restrictive. The inline chips on the row already communicate which
flags are Claude-specific.
`rowsToRecord` was persisting every non-empty trimmed key, so names
failing `ENV_VAR_NAME_RE` (e.g. `BAD KEY`, `FOO=BAR`) flowed through
`onChange` into settings and were applied verbatim by backend spawn
paths, which read `envOverrides` directly without re-sanitizing.
Filter invalid rows at the commit boundary so the persisted record
and subprocess env only contain valid POSIX identifiers.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(agent-mode): teach backends about @-mention pill syntax

The chat editor serializes @-mention pills to `[[note]]`, `{folder}`, and
`{activeNote}` tokens, but only `[[note]]` was understood — the others
were literal strings to the agent. Add a shared pill-syntax directive
appended to opencode, codex, and claude SDK spawn-time instructions
(mirroring the existing skill-creation directive plumbing), and resolve
`{activeNote}` to the real `[[Note Title]]` at send time since the active
file is a client-side concept the agent can't query.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(agent-mode): prune narration comments from pill-syntax change

Cut multi-line JSDoc and inline rationale that explained WHAT or referenced
callers, per the project's "one short line max, only WHY" rule.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(agent-mode): preserve extension when resolving {activeNote}

Non-markdown active files (.pdf, .canvas) lost their extension when
{activeNote} was rewritten via activeFile.basename, leaving the agent
with an ambiguous [[name]] that didn't match the path the pill envelope
carries. Mirror NotePillNode.getTextContent's extension-aware
serialization so the inline token matches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…2503)

* feat(agent-mode): make note links clickable in chat and tool cards

Switches markdown rendering to the modern `MarkdownRenderer.render(app, …)`
API via a shared `renderMarkdown` wrapper, and adds a delegated click
handler so `a.internal-link` inside chat/agent/plan-preview views opens
via `app.workspace.openLinkText` (left-click in current pane, cmd/middle
in a new tab). Tool ActionCards now also expose the collapsed line as
a clickable target once the call has completed.

Threads `app` explicitly through the components and utilities that
previously relied on the global `app` (lexicalTextUtils, notePreviewUtils,
vaultPath, AtMention/Note/Paste/TextInsertion plugins) using the
`useApp()` hook at the leaf, and updates AGENTS.md to discourage new
uses of the global.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(chat): fix ChatSingleMessage mocks for wireInternalLinks

The `renderMarkdown` wrapper now calls `component.register(...)` after
`MarkdownRenderer.render(...)`. The test's `obsidian.Component` mock was
missing `register`, causing the promise to reject and `logError` (which
calls the unmocked `getSettings()`) to crash. Add `register` to the
Component mock and mock `getSettings` as a safety net.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(agent-mode): resolve internal links against active note

Pass the active file path as sourcePath to renderMarkdown so wikilinks
with duplicate basenames or heading-only references resolve to the right
file instead of falling back to vault root.

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 OBSIDIAN_CLI_TEST.md with a field guide for driving the plugin
through the Obsidian desktop CLI: multi-vault targeting (the biggest
gotcha — default routes to whichever window was touched last), popout
window limitations, settings round-trips via eval/saveData, real-input
UI driving via dev:cdp, screenshots, console/error capture, performance
metrics, and a smoke-test scaffold. AGENTS.md now points to it and
keeps only the multi-vault warning inline so there is one source of
truth.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace non-existent `copilot:open-copilot-chat` with the registered
`copilot:agent-chat-open-window` ID in both the "Run a command" example
and the smoke-test scaffold so the documented commands actually work.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…2507)

* perf(agent-mode): warm-adopt preload probe to skip first-chat spawn

The preloader's probe subprocess is now retained as a "warm" entry and
adopted by the first chat-open on that backend, so the first session
skips both the subprocess spawn and the `newSession` round-trip. Preload
status is also tracked per-backend: the chat gates on the active
backend's status only, and the picker shows per-backend loading rows for
the others.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(agent-mode): defer model+effort seeding to backend confirmation

- Seed only baseModelId (not effort) so descriptor-style backends
  (Claude) don't see a matching seeded effort and skip the real
  setConfigOption inside applyInitialSessionConfig.
- Gate warm-session `ready` on confirmSeededSelection so sendPrompt
  can't race onto the probe's model before setModel resolves.
- Add regression tests covering both paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…reshes (#2508)

* fix(skills): eliminate Skills Settings UI lag from watcher-driven refreshes

Replaces the time-based watcher suppression with path-scoped expectations:
each SkillManager FS write registers predicates (exists/missing/modified/
subtree-*) and the matching vault events are dropped without triggering a
debounced reconcile. A 10s safety timer backstops never-arriving events.
Toggle/delete/rename/saveProperties now publish incremental in-memory updates
instead of re-running full discovery, so the Properties modal save returns
synchronously and the grid reflects the change on the next render.

* fix(skills): heal drift when expectations expire; preserve external reconciles

Two fixes for the watcher-suppression machinery on PR #2508:

- `armSafetyTimer`: when the 10s backstop fires with expectations still
  pending, schedule a debounced reconcile before clearing. Catches the case
  where an external process undid our change (e.g. deleted a link we expected
  to exist) — the matching event was suppressed, predicate never satisfied,
  and previously the state drifted silently until an unrelated watched event
  fired.

- `runInternalMutation`: stop cancelling pre-existing reconcile timers in
  the finally block. Events fired during the mutation are dropped by the
  depth gate, so any debounce timer left armed was scheduled by an external
  event before the mutation started and still needs servicing.

Adds two regression tests and updates the pre-existing "safety timer clears
stale expectations" test which is superseded by the new healing behavior.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…2513)

Replaces the rescan/import-consent flow with unified discovery across
canonical and agent project folders, lazy migration with a global
suppress flag, and an overflow-menu lockdown for mirrored duplicates.
…sh TODOs (#2514)

- Add `.claude/skills/create-agent-issue/SKILL.md`: project-level skill that
  codifies the standard for one well-formed GitHub issue (title shape, body
  sections, label palette, draft artifact format, reviewer rubric, three-stage
  workflow: draft / review-and-push / all).
- Add `designdocs/todo/AGENT_TODOS_TO_ISSUES_PLAYBOOK.md`: orchestrator
  playbook for migrating `AGENT_MODE_TODOS.md` into GitHub issues with a
  two-subagent (author + reviewer) flow, autonomous triage, parallelism,
  idempotency, and verbatim subagent prompt templates.
- Revamp `designdocs/todo/AGENT_MODE_TODOS.md`: richer per-item context,
  "design needed" markers, reorganized MCP and Codex auth items, current
  pending count is 33 top-level items (P0=7, P1=17, P2=7, P3=2).
- Drop `designdocs/todo/MCP_EXTERNALLY_MANAGED_SERVERS.md` (stale).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces every pending top-level `- [ ]` in `AGENT_MODE_TODOS.md` with a
link to its corresponding issue in logancyang/obsidian-copilot-preview
(#59-#98). Follows the playbook in `AGENT_TODOS_TO_ISSUES_PLAYBOOK.md`:
sub-bullets folded into issue bodies, and "Integrate copilot plus tool
calls" split into 5 child issues (#80-#84) under a now-plain parent
bullet. 39 issues opened end-to-end via paired author/reviewer subagents.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the per-backend install/settings panels with a shared Configure
dialog layout. Introduces ConfigDialogShell + ConfigSection, InstallCommandRow,
and an installStatus badge/status-line module (with tests), and reworks the
Claude, Codex, and opencode Configure dialogs onto it. The settings page now
shows each backend's icon, an install-status badge, and a Configure button,
dropping the old BinaryInstallContent and SimpleBackendSettingsPanel helpers.
Copy is simplified for non-technical users and dialog spacing/dividers are
made consistent.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
zeroliu and others added 27 commits August 6, 2026 15:59
…ts (#2738)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…ering (#2739)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…ctions (#2740)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
#2742)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…line (#2743)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…a time (#2744)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
… control bar (#2758)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…ith the binary path (#2752)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…ault (#2774)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…2773)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
… cap (#2777)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@logancyang
logancyang marked this pull request as ready for review August 8, 2026 04:48

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ae26ffe7a0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/main.ts
).open();
}

updateSetting("upgradedToV8FromLegacy", false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Migrate legacy data before switching folder readers

For upgrades with customized conversation, prompt, skill, or memory folders, the files remain at their legacy paths while the new accessors immediately read only the derived <copilotFolder>/... paths. This method merely opens an informational modal and then clears the upgrade flag regardless of whether the user moved anything, so dismissing or acknowledging it makes existing chats and other persisted data disappear from the plugin with no retry. Migrate the files automatically or retain a compatibility fallback until relocation succeeds.

AGENTS.md reference: AGENTS.md:L74-L79

Useful? React with 👍 / 👎.

Comment on lines +330 to +332
} catch (err) {
failed++;
logError(`[byok-migration] failed to migrate "${descriptor.displayName}"; continuing`, err);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Retry provider migrations before stamping the schema

If setupProvider fails transiently—for example because Keychain is unavailable during this startup—the exception is swallowed here, after which runSettingsMigrations still stamps settingsVersion to v8. Every later startup therefore skips the failed provider permanently, leaving its legacy models absent from the new backend/model registry even after the underlying failure is resolved. Propagate or return the failure so the version is not advanced until every descriptor has migrated; successful descriptors are already deduplicated on retry.

AGENTS.md reference: AGENTS.md:L74-L79

Useful? React with 👍 / 👎.

Comment thread src/main.ts
@@ -184,30 +354,72 @@ export default class CopilotPlugin extends Plugin {
// Single source of truth for Active Web Tab ({activeWebTab}) state
// Preserves activeWebTab when switching to Chat view
// Only run on desktop - Web Viewer is not available on mobile
if (Platform.isDesktopApp) {
if (isDesktopRuntime()) {
const { activeLeafRef, layoutRef } = startActiveWebTabTracking(this.app, {
preserveOnViewTypes: [CHAT_VIEWTYPE],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the active web tab for Agent Chat

When a user switches directly from Obsidian's Web Viewer to the new Agent Chat view, that view type is absent from this preserve list. WebViewerStateManager consequently clears activeWebTabForMentions on the leaf change, while AgentChatInput uses that exact state for its Active Web Tab affordance and send snapshot, so {activeWebTab} and the include-active-tab option stop working specifically in Agent Chat. Include CHAT_AGENT_VIEWTYPE alongside the legacy chat view.

Useful? React with 👍 / 👎.

@logancyang
logancyang merged commit 19951f8 into master Aug 8, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants