Skip to content

feat: let the agent start workspaces and check their status — #934 on the global-search stack - #941

Open
danyaberezun wants to merge 10 commits into
global-search-specsfrom
global-search-workspace-tools
Open

danyaberezun wants to merge 10 commits into
global-search-specsfrom
global-search-workspace-tools

Conversation

@danyaberezun

Copy link
Copy Markdown
Collaborator

Problem

#934 (by rsolmano) gives every chat two always-on tools, start_workspace and workspace_status.
With them, "do this in a side workspace" and "run these in parallel" become requests the agent can act
on. #934 was written against main, before this stack's chats without a project (#887) and Continue in
workspace (#888). On top of them it goes wrong in three places:

  • The Chats container counts as an open project.
    • From a chat without a project, start_workspace defaults to Chats and fails on listBranches with
      a git error.
    • Every error lists Chats (chats) as an open project.
    • workspace_status reports chats without a project with base · no PR · diff unknown lines, and the
      name Chat matches all of them.
  • The chat start that feat: let the agent start workspaces and check their status #934 moves into host/chatSession.ts is still copied twice in the stack
    (host/chats.ts, Continue's applyContinuation). Both copies report chat_started as custom
    (pi's placeholder) instead of none for a chat created without a usable model.
  • feat: let the agent start workspaces and check their status #934's card opens the child workspace immediately. The store drops a workspace.created push for
    a project whose workspace list it never loaded. A spawn into a collapsed project therefore opens a
    workspace the store doesn't have. Continue's Open already reloads the list, in its own copy of the same
    action.

Eighth PR of the global-search stack; stacked on #939.

Approach

  • feat: let the agent start workspaces and check their status #934 as written, rebased onto the stack.
  • The workspace tools see open repositories only.
    • The Chats container is never resolved, listed or matched by a status lookup.
    • A chat without a project has no default project. Both tools refuse a call without project:
      "This chat has no project: pass project. Open projects: …".
    • Rejected: filtering listProjects() itself. Welcome, project.list and the Chats UI need the
      container.
    • Rejected: an overview of every repository for workspace_status without arguments in such a chat.
      One rule for both tools is simpler, and that overview can get large.
  • One chat start. chats.ts and applyContinuation now start through feat: let the agent start workspaces and check their status #934's startChatSession,
    which is the host's only createSession call. chat_started follows the analytics spec everywhere.
  • One openWorkspace. chat/openWorkspace.ts serves the start_workspace card, Continue's Open and
    the handoff's link back to its source.
    • A workspace the store knows opens under its own project.
    • An unknown one first reloads its project's workspace.list, as Continue already did, and opens even
      if that reload fails.
    • openContinuation is gone.
  • Deliberately not here:
    • Continue's base branch. It still cuts from the project checkout's HEAD, while start_workspace and
      the New Workspace dialog use the default branch plus a prefetch.
    • Splitting the start_workspace / continue_in_workspace guidance by intent.
    • Making the two Open buttons look alike.
    • A back-link from a spawned workspace to the chat that started it.

Changes

  • rsolmano's seven feat: let the agent start workspaces and check their status #934 commits, conflicts resolved as above.
  • fix(server): start every host-created chat through startChatSession.
    • host/chats.ts loses its private copy; applyContinuation loses its inline one.
    • New authAttribution regression test: a chat without a project created without a usable model
      reports none. It failed with custom before the fix.
  • fix(server): keep the Chats container out of start_workspace / workspace_status.
    • host/workspaceTools.ts: resolveProject(ref, fallback | undefined, projects) takes repositories
      only, and a chat-workspace caller has no fallback.
    • The project parameter descriptions say it is required in a chat without a project.
    • Two new unit tests failed before the fix.
  • fix(web): one openWorkspace for every chat card.
  • Specs:
    • host: one chat start; repositories only, with no default project in a chat without one;
    • agent: project is required in a chat without a project;
    • web chat: openWorkspace and Continue's cards.

Screenshots

Nothing looks different from #934. The start_workspace card is #934's, and Continue's cards render as
before (Open now goes through openWorkspace). #934's screenshots, seeded transcript, 1280×900:

start_workspace card

start_workspace and workspace_status in a chat

Testing

These checks ran on the final head 6faaf211d:

  • bun run test → server 1857 pass, 4 skip; web 2009 pass; every other package green.
    • The first run caught my new openWorkspace test leaking a stubbed store action into
      navigation/restore.test.ts. It now drives the real store and resets it with getInitialState().
  • Each fix's regression test failed before its fix:
    • authAttribution → custom instead of none;
    • two workspaceTools tests → a chat without a project was not refused, and startWorkspace
      went on to cut a worktree from Chats;
    • openWorkspace → activated before the list loaded.
  • bun run e2e (full no-agent suite, 8 shards, 651 tests) → all passed.
  • bun run e2e:full e2e/workspace-tools.live.spec.ts e2e/chats-continue.live.spec.ts → 2 passed
    with a real model.
  • Lint and type gates → green:
    • bun run lint (biome, 1794 files);
    • bun run typecheck (22 packages);
    • check:deps, check:boundaries, check:seams, check:spec-surface, check:i18n,
      check:compiler.
  • feat: let the agent start workspaces and check their status #934's seven commits are unchanged except for the conflict resolutions above. Before the fixes, the
    rebased tree passed typecheck, biome, and the affected tests (123 server + 16 web, feat: let the agent start workspaces and check their status #934's own
    among them).

Related issues

Part of the global-search stack (#804 → #805 → #806 → #887 → #888 → #933 → #939 → this). It carries
#934 onto the stack; #934 itself is untouched.

Checklist

  • Fast gates pass: bun run lint, bun run typecheck, bun run test
  • E2E suite passes for app-affecting changes (bun run e2e, or bun run e2e:full when touching agent behavior)
  • Before/after screenshots are included for frontend changes, or marked not applicable
  • Relevant SPEC.md / top-level specs updated to reflect any boundary, contract, or behavior change
  • I have read the Contributing guide and agree to the Code of Conduct

@jetbrains-air jetbrains-air Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved — ready to merge.

Rinat S (rsolmano) and others added 10 commits October 28, 2026 04:24
…so a model-less chat reports none

chats.ts kept a private copy of the chat start and Continue in workspace an
inline one; both reported chat_started with the created session's model, so a
chat without a project or a continued chat created without any usable model
bucketed pi's placeholder as custom instead of none. Both now start through
#934's host/chatSession.ts, the host's only createSession call.
…space_status

The workspace tools took every open registry entry as a project, so a chat
without a project defaulted to the Chats container: start_workspace failed on
listBranches with a git error, every error listed Chats as an open project,
and workspace_status reported the container's chats with git lines. The tools
now see open repositories only, and a chat without a project must pass
`project` — both tools refuse without it and list the open repositories.
…ce that loads an unknown project first

addWorkspace drops a workspace.created push for a project whose list was
never loaded, so a spawn into a collapsed project opened a record the store
did not hold. Continue in workspace already reloaded the list in its own
openContinuation. One openWorkspace (chat/openWorkspace.ts) now serves the
start_workspace card, Continue's Open and the handoff's source: a known
workspace opens under its own project, an unknown one reloads its project's
workspace.list first and opens even if that fails.
@danyaberezun
danyaberezun force-pushed the global-search-workspace-tools branch from 6faaf21 to 5ebcb63 Compare October 28, 2026 03:25

@jetbrains-air jetbrains-air Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved — ready to merge.

.request("workspace.list", { projectId })
.then((rows) => useAppStore.getState().setWorkspaces(projectId, rows))
.catch(() => {})
.finally(() => activate(projectId));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Non-blocking:
Problem: An unknown workspace is activated unconditionally after loading, allowing an older Open action to override newer navigation.
Failure scenario: Open the new start_workspace card for a project whose workspace list is unloaded, then select another project or chat while workspace.list is pending. When the request settles, this callback switches back to the earlier workspace. This reproduces with the real store.
Suggested fix: Capture a navigation/request stamp before loading and activate only while that intent is still current, invalidating it on later navigation or another Open action.

@jetbrains-air jetbrains-air Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved — ready to merge.

promptSnippet: "Start a new workspace with its own chat to work on a task in parallel",
promptGuidelines: START_GUIDELINES,
parameters: StartWorkspaceSchema,
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Non-blocking:
Problem: start_workspace discards Pi's abort signal, so cancelling preparation does not cancel the pending launch.
Failure scenario: Press Stop while the default-branch prefetch awaits a slow remote. With pinned Pi 1.4.0, Stop waits for this tool; after the fetch finishes, it still creates the workspace and prompts its child, although Stop preceded both operations.
Suggested fix: Forward the signal through WorkspaceToolsHost.start, make preparation abortable, and check cancellation before creation and child startup. Children already launched can remain independent.

This branch has not been deployed

No deployments
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.

2 participants