Skip to content

feat(vscode): add background task browser - #2998

Open
skymecode wants to merge 3 commits into
MoonshotAI:mainfrom
skymecode:feat/vscode-background-tasks
Open

feat(vscode): add background task browser#2998
skymecode wants to merge 3 commits into
MoonshotAI:mainfrom
skymecode:feat/vscode-background-tasks

Conversation

@skymecode

Copy link
Copy Markdown

Related Issue

No related issue. The problem is described below.

Problem

Kimi Code for VS Code can run background processes, subagents, and question tasks through the shared engine, but the extension does not expose their status or controls. Users cannot see that work is still running, inspect its output, stop it, or recover terminal task status when reopening a session.

What changed

  • Add extension-host bridge methods for listing tasks, reading output, and stopping a task, plus lifecycle broadcasts backed by the public Node SDK session surface.
  • Show task lifecycle cards in the transcript, deduplicate repeated terminal events, and restore terminal cards and current task state when session history is loaded.
  • Add a Tasks badge above the composer and a fullscreen All/Active task browser with live output polling and stop confirmation. Foreground tasks remain hidden until detached, matching the TUI behavior.
  • Add runtime and RPC boundary coverage, document the feature in the extension README, and include a minor changeset for the VS Code package.

Verification

  • pnpm --filter kimi-code test (330 tests)
  • pnpm --filter kimi-code typecheck
  • pnpm --filter kimi-code build:webview
  • pnpm lint (0 errors)
  • pnpm --filter kimi-code package:platform -- --target darwin-arm64 (VSIX package/static audit passed)

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

@changeset-bot

changeset-bot Bot commented Aug 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3bb33dc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
kimi-code Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@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: 6ad05a0709

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

planMode: false,
});
useApprovalStore.getState().clearRequests();
useTasksStore.getState().setTasks([]);

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 Preserve announced tasks when loading session history

When a saved session is selected, the host announces its background tasks inside LoadKimiSessionHistory before returning the RPC result, but loadSession runs afterward and unconditionally replaces that announcement with an empty list here. Because no subsequent refresh occurs, restored completed tasks remain inaccessible and running tasks stay hidden until another lifecycle event arrives, defeating task recovery when reopening a session.

Useful? React with 👍 / 👎.

Comment on lines +78 to +82
.then((result) => {
if (!cancelled) setOutput(result.output);
})
.catch((loadError: unknown) => {
if (!cancelled) setError(loadError instanceof Error ? loadError.message : String(loadError));

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 Clear transient output errors after a successful poll

If any output poll fails transiently, this sets error, but a later successful interval only updates output and never clears that error. Since the render path prioritizes non-null error, a running task continues showing the stale failure even after subsequent polls succeed, until the user collapses and reopens the output.

Useful? React with 👍 / 👎.

@skymecode

Copy link
Copy Markdown
Author

@codex review

@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: 6ad05a0709

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

[Methods.ListBackgroundTasks]: async (_, ctx): Promise<BackgroundTaskInfo[]> => {
const runtime = ctx.getSession();
if (runtime === undefined) return [];
const tasks = await runtime.session.listBackgroundTasks({ activeOnly: 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 Route task controls to the task's owning agent

When a subagent launches its own background Bash, agent, or question task under the default v2 engine, SessionRuntime receives and displays that lifecycle event because the SDK session subscribes to every agent in the session, but these APIs operate only on the interactive main agent. Consequently, refreshing removes the subagent task, reading its output returns empty, and clicking Stop is a no-op while the advertised task keeps running; preserve the event's agentId and route list/output/stop to that owner (or restrict displayed events to tasks these handlers can control).

Useful? React with 👍 / 👎.

@skymecode

Copy link
Copy Markdown
Author

@codex review

@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: cb584c53a8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


refreshTasks: async () => {
const tasks = await bridge.listBackgroundTasks();
set({ tasks });

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 Prevent refresh responses from overwriting newer task events

When a task starts or terminates while listBackgroundTasks() is in flight, the lifecycle broadcast can update the store before the older RPC snapshot resolves, after which this unconditional set overwrites the newer state. Opening or manually refreshing the modal during a transition can therefore hide a newly started task or show a stopped task as running until another event or refresh occurs; discard superseded responses or merge them against lifecycle updates received after the request began.

Useful? React with 👍 / 👎.

Comment thread apps/vscode/webview-ui/src/App.tsx Outdated
useEffect(() => {
const unsubs = [
bridge.on(Events.MCPServersChanged, setMCPServers),
bridge.on(Events.BackgroundTasksChanged, (tasks: BackgroundTaskInfo[]) => setTasks(tasks)),

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 Scope task notifications to their session

BackgroundTasksChanged carries only an array and is accepted without the session filtering used for stream events. Because SessionList allows overlapping asynchronous session selections, announcements for sessions A and B can arrive in one order while their history requests complete in another, leaving the transcript on one session and the task browser showing the other session's tasks; output and Stop can then be routed through a different currently attached runtime. Include the session ID in this notification and ignore updates that do not match the selected/loading session, or make the session switch and task snapshot atomic.

Useful? React with 👍 / 👎.

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.

1 participant