Repository navigation
Floating-workspace chats of every native-chat agent keep links in the folder they started in - #26981
Conversation
…ts pinned folder Drop the unused showStructuredAgentSessionChoice and say what the built-in agent check means.
… their pinned folder The renderer now resolves every floating chat's links, images and skills against the folder the chat was pinned to. The ACP (OpenCode/Grok/OMP) and Pi launchers still started the agent in the current floating folder setting, so after the setting moved and the agent relaunched, the agent ran in one folder while links resolved against another (and Pi forked its conversation into the new folder). Both launchers now use resolveAgentSessionLaunchDirectory, the helper Claude and Codex already use: launch in the pin, refuse with the existing "folder this chat ran in no longer exists" message when it is gone, and pin an unpinned floating record on first launch. Worktree and folder chats are unchanged. The tab-directory reader now calls the status bridge's own isStructuredTab instead of restating its predicate inline.
Review summary (two review rounds + release-readiness pass, head 21db2b4)The problem. OpenCode, Grok, OMP and Pi chats in the floating workspace weren't held to the folder they started in, unlike Claude and Codex chats. After the floating folder setting changed, their file links pointed into the new folder. The original version of this PR fixed only that link half. What review found and fixed.
User-facing change. Floating OpenCode/Grok/OMP/Pi chats resolve links, images and skills against their starting folder and run there again after a restart. If that folder has been deleted, sending shows the message Claude and Codex chats already show: "The folder this chat ran in no longer exists. Restore it to continue this chat." Before, they quietly started in another folder. Repo-worktree and folder-workspace chats are unchanged. Deferred (not in this PR).
Verified.
Not verified.
|
… folder they started in (#26981) * fix(native-chat): resolve every registered agent's floating chat to its pinned folder Drop the unused showStructuredAgentSessionChoice and say what the built-in agent check means. * fix(native-chat): launch floating OpenCode, Grok, OMP and Pi chats in their pinned folder The renderer now resolves every floating chat's links, images and skills against the folder the chat was pinned to. The ACP (OpenCode/Grok/OMP) and Pi launchers still started the agent in the current floating folder setting, so after the setting moved and the agent relaunched, the agent ran in one folder while links resolved against another (and Pi forked its conversation into the new folder). Both launchers now use resolveAgentSessionLaunchDirectory, the helper Claude and Codex already use: launch in the pin, refuse with the existing "folder this chat ran in no longer exists" message when it is gone, and pin an unpinned floating record on first launch. Worktree and folder chats are unchanged. The tab-directory reader now calls the status bridge's own isStructuredTab instead of restating its predicate inline. (cherry picked from commit 094f589)
ELI5
An OpenCode, Grok, OMP or Pi chat in the floating workspace now stays in the folder it started in. Its file links point there, and after an app restart the agent runs there again, even if you have since changed the floating workspace folder. Claude and Codex chats already worked this way.
What Changed
The problem. A chat in the floating workspace starts in whatever folder the floating workspace points at. The user can change that folder setting while chats exist. For Claude and Codex, Orca records the chat's starting folder (its "pin") and uses it for two things: launching the agent again (after a restart, for example), and resolving the chat's file links, image paths and skill lookups. For OpenCode, Grok, OMP and Pi floating chats, both used the current setting. So after a folder change:
[the readme](./README.md)in an earlier reply pointed into the new folder, where the file may not exist or may be a different file;Why it happened. Two places used a Claude/Codex-only check (
isAgentSessionHandleProvider) or Claude/Codex-only code to mean "this is a native chat":native-chat-tab-directory.ts);resolveAgentSessionLaunchDirectory, the host's one rule for "which folder does this chat's agent start in". The OpenCode/Grok/OMP and Pi launchers read the current setting instead.When the other agents got native chat (#25225 onward), the status bridge that publishes the pin was switched to "any registered native-chat agent", but these two places weren't. #26776 fixed the same kind of leftover for orchestration workers.
User-facing change. In the floating workspace, OpenCode, Grok, OMP and Pi chats:
Nothing changes for chats in a repo worktree or a folder workspace.
Mechanism.
acp-structured-launch-resolution.ts(OpenCode, Grok, OMP) andpi/rpc-launch-resolution.ts(Pi) now callresolveAgentSessionLaunchDirectory, the function Claude and Codex already use. For floating chats it returns the pin, refuses if the pinned folder is gone, and records a pin for an old floating chat that has none.native-chat-tab-directory.tsnow calls the status bridge's ownisStructuredTabcheck instead of restating it, so the reader and the publisher of the pin can't drift apart again.showStructuredAgentSessionChoicehelper is removed.isAgentSessionHandleProvidernow says what it means: one of the two built-in agents, for features only they have, not "has native chat". I kept the name, because a rename touches about 25 files and would conflict with other open PRs.Leftovers checked and kept. Every other Claude/Codex-only check outside tests guards something only Claude or Codex has (importing an existing conversation, AI vault history, the built-in model lists), or keeps compatibility with older Orca hosts that don't publish their agent list. One more case of the same mistake exists in Session History (an OpenCode native chat's history shows as a plain OpenCode CLI session). It needs per-client capability checks, so it is left for a follow-up rather than added here.
Why
This reuses the launch-folder rule and the native-chat check that already exist, rather than adding a per-agent list. Each chat now has one folder that both the agent and Orca's link handling use, which is the common pattern.
Linked Issue
None. This is a follow-up to #26776, found while looking for other leftovers of the same Claude/Codex-only check.
Visual Proof
From a hidden dev Orca on this branch (21db2b4) on a second Mac, with the real OpenCode CLI against a local test model. The floating folder started as
folder-a; it was then changed tofolder-b. Both folders contain aREADME.md.After an app restart, with the setting on

folder-b, the chat still runs infolder-a:Its link still targets

folder-a/README.md:With

folder-adeleted, sending shows the existing "folder no longer exists" message (no other notice):A new floating chat then runs in

folder-b, and its link targetsfolder-b:The tab title "pwd printed: ..." comes from the local test model, which answered Orca's chat-naming request with its usual reply. A real model writes a normal title.
The earlier screenshots from the laptop run (10382b2) showed the link half only:


There is no "before" screenshot from main. The new tests show the before state instead: with the fix reverted, they fail.
Testing
Manual, macOS (second Mac, hidden dev build, isolated profile, real OpenCode 2.0.21): link keeps the start folder after the setting changes; after a restart the agent runs in the start folder; deleted start folder shows the refusal message and a new chat works; a repo-worktree chat is unchanged. All passed.
Not run live: Grok, OMP and Pi floating chats (same code path as OpenCode for Grok and OMP; Pi is covered by unit tests). Windows and Linux.
Automated:
native-chat-tab-directory.test.ts: one case per agent (OpenCode, Grok, OMP, Pi). All four fail without the fix.acp-structured-launch-resolution.test.tsandrpc-launch-resolution.test.ts: a floating chat launches in its pin after the setting moved (Pi also resumes without copying its conversation); a missing pin folder refuses; an old unpinned floating chat gets pinned; worktree and folder chats unchanged. The floating cases fail without the fix.pnpm tc:node,pnpm tc:webandorca-ci-checkspass.Review
Reviewed in two rounds plus a release-readiness pass; see the review comment.
Agent skill upstream boundary
Notes
cross-version wire compatibilityis red because of main (feat(kiro): report Kiro agent status and list Kiro sessions in history #26695 added Kiro;session-search-agent-set-downgradeandqoder-history-search-downgradeexpect Kiro in an older host's agent list). Not caused by this PR; this PR doesn't touch session search.Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)