Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c8cf648
feat(vscode): agent manager seam and copied independent modules (chec…
marius-kilocode Nov 2, 2026
4a2bba7
feat(vscode): agent manager orchestration and branch name plugins (ch…
marius-kilocode Nov 2, 2026
a0e2d8d
feat(vscode): agent manager boundary, panel app and integration fixes…
marius-kilocode Nov 3, 2026
ee3d251
fix(vscode): agent manager composer parity and selection fixes (check…
marius-kilocode Nov 3, 2026
3368f4a
fix(vscode): use the sidebar surface behind the agent manager session
marius-kilocode Nov 3, 2026
06ecaed
fix(vscode): resolve agent manager project to the checkout root
marius-kilocode Nov 3, 2026
692689e
fix(vscode): agent manager history scope and worktree terminal sockets
marius-kilocode Nov 3, 2026
ed5c1d3
fix(vscode): agent manager branch naming, stale sessions and retry state
marius-kilocode Nov 3, 2026
be07303
chore(vscode): agent manager i18n spacing and plan notes
marius-kilocode Nov 3, 2026
eac56ec
merge origin/v2 into am-v2-seam
marius-kilocode Nov 3, 2026
91c60e4
chore(upstream): raise shared-patch limits for the agent manager seams
marius-kilocode Nov 3, 2026
82fd0da
fix(agent-manager): pass CI checks on all platforms
marius-kilocode Nov 3, 2026
6f09c06
fix(kilo-cli): use the canonical directory in the agent manager rpc test
marius-kilocode Nov 3, 2026
5a21c59
fix(kilo-cli): canonicalize the agent manager rpc test root
marius-kilocode Nov 3, 2026
ce560ec
fix(agent-manager): resolve snapshot inputs before the symlink check
marius-kilocode Nov 3, 2026
e5f4792
fix(vscode): close happy-dom windows in the review tests
marius-kilocode Nov 3, 2026
c1eaeb5
test(vscode): keep the Windows directory-lock check out of CI
marius-kilocode Nov 3, 2026
c09abbb
Merge commit '9fd797e70a00aade8c1a30d866d2c1bf5d7621dd' into am-v2-seam
marius-kilocode Nov 3, 2026
2f03db9
fix(agent-manager): address review findings
marius-kilocode Nov 3, 2026
0ccaada
test(plugin): make the guard home expansion assertion portable
marius-kilocode Nov 3, 2026
d10bdba
chore(ci): stream packages test logs to name a stalled task
marius-kilocode Nov 3, 2026
cb99331
fix(client): evict one session's messages without its family
marius-kilocode Nov 3, 2026
c2880ba
chore(client): mark the per-session evict patch
marius-kilocode Nov 3, 2026
759ace7
test(vscode): await rejections directly so Windows timers fire
marius-kilocode Nov 3, 2026
38b9dcd
fix(vscode): make the ported suite pass on Windows
marius-kilocode Nov 3, 2026
34e33a9
fix(vscode): normalize Windows paths and awaits in the ported suite
marius-kilocode Nov 3, 2026
5a11b7b
fix(vscode): finish Windows path handling in the ported suite
marius-kilocode Nov 3, 2026
7ebee69
test(vscode): keep ambient Git coverage and record Windows exclusions
marius-kilocode Nov 3, 2026
ae3a1e5
fix(vscode): stop pool warm-ups on dispose and give Git-heavy tests time
marius-kilocode Nov 3, 2026
7a2e2eb
fix(vscode): await the pool slot refresh before dispose
marius-kilocode Nov 3, 2026
f217d67
Merge commit '5e6b189cfbf7dceb2e7bce42b97c38f32908f9d1' into am-v2-seam
marius-kilocode Nov 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 2 additions & 1 deletion .github/workflows/check-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ jobs:
KILO_TEST_CONCURRENCY=4 GITHUB_ACTIONS=false bun turbo test:ci --concurrency=1 "${affected[@]}" --filter='@kilocode/kilo-cli' &
host=$!
other=0
GITHUB_ACTIONS=false bun turbo test --concurrency=3 "${affected[@]}" --filter='!@opencode/core' --filter='!@opencode/tui' --filter='!@opencode/cli' --filter='!@kilocode/kilo-cli' || other=$?
# kilocode_change - stream task logs so a stalled task names itself instead of hiding until it finishes
GITHUB_ACTIONS=false bun turbo test --concurrency=3 --log-order=stream "${affected[@]}" --filter='!@opencode/core' --filter='!@opencode/tui' --filter='!@opencode/cli' --filter='!@kilocode/kilo-cli' || other=$?
hoststatus=0
wait "$host" || hoststatus=$?
test "$other" -eq 0 && test "$hoststatus" -eq 0
Expand Down
450 changes: 450 additions & 0 deletions .kilo/plans/agent-manager-v2-audit.md

Large diffs are not rendered by default.

72 changes: 72 additions & 0 deletions .kilo/plans/agent-manager-v2-conventions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Agent Manager v2 port: boundary conventions (all agents follow these)

Worktree: /Users/marius/Documents/git/kilocode/.kilo/worktrees/stupendous-borogovia
PKG = packages/kilo-vscode. V1 (read-only extract) = /var/folders/6c/3j3r25ds6pd1dw3nlrfnvv280000gp/T/kilo/v1/packages/kilo-vscode
v1 is also branch `main` (read with `git show main:<path>`, never check it out).

## Hard rules
- Never run git checkout/reset/stash/commit/branch changes. Several agents edit this worktree at once. Touch ONLY the files of your scope. If you need a change in a file outside your scope, post an ASK on the board to the coordinator (main) with the exact change, and continue.
- AGENTS.md style: no `any`, no `as any`, no `@ts-ignore`, no success shims (never return fake success), no dead code, no TODOs, no comments that mention v1/main/"as before". Prefer const, early returns, no else, no unnecessary destructuring.
- Excluded features leave NO trace (no control, import, field, CSS, message type): codebase indexing, sandbox metadata and the inheritance token, browser automation and the browser panel, telemetry (remove calls, keep the wrapped behavior), speech to text, the documents panel, Memory and Feedback providers, attached-session presence.
- Lint: from the worktree root `node_modules/.bin/oxlint --config .oxlintrc.json <your files>` must show 0 problems (complexity max 20/function, max-lines 3000/file). Refactor only offending functions.
- Never copy the v1 session plumbing: services/cli-backend (connection-service, sdk-sse-adapter, server-manager), KiloProvider, SessionProvider, DataBridge, ProviderShell, ChatView, webview-ui/src/context/session*, the v1 session activity/live-session state, permission/question directory maps, session directory override maps. Replace their use with the seam below.

## Host seam (extension host, Node; no Bun APIs in src/)
- `src/agent-manager/connection.ts` `createAgentManagerConnection` -> `AgentManagerConnection`:
- `client(): Promise<OpenCodeClient>` (starts the server if needed), `current(): OpenCodeClient | undefined`
- `state(): "connecting"|"connected"|"disconnected"`, `onState(fn)` -> unsubscribe
- `onEvent(listener, filter?)` -> unsubscribe; `located(() => dirs)` filter helper
- `server(): { url, authorization } | undefined` (for WebSocket URLs)
- `view(sessionIDs)` marks idle transitions of visible sessions viewed (`session.view`), replaces registerVisible.
- One client for all directories: pass the directory in EACH call. Read the exact input shapes in packages/client/src/promise/generated/types.ts (search `export type <Name>Input`). Examples: `session.list({ directory, parentID: null })`, `session.create({ location: { directory }, agent, model, metadata })`, `agent.list({ location: { directory } })`, `pty.create({ location: { directory }, cwd, title, env })`.
- Removed with no replacement (delete their callers): registerDirectoryProvider, registerAttached, getKnownDirectories (use AM's own worktree list), setSessionDirectory/session directory overrides.
- Errors: `getErrorMessage` from src/agent-manager/errors.ts; `sameDirectory` from src/agent-manager/project/paths.ts.
- Platform: `metadata: { kilocode: { platform: "agent-manager" } }` on session.create (see packages/schema/src/kilocode/gateway.ts:306 for the field).

## API mapping (v1 -> v2)
| v1 | v2 |
|---|---|
| session.create | session.create({ location:{directory}, agent, model:{id, providerID, variant?}, metadata }) |
| session.list | session.list({ directory, parentID: null }) |
| session.get | session.get({ sessionID }) |
| promptAsync / sendMessage | session.prompt({ sessionID, text, files, metadata }) (returns after admission; do NOT pass resume:false, that never runs it) |
| synthetic text | session.synthetic({ sessionID, text, metadata }) |
| command | session.command({ sessionID, name, text, files }) |
| abort | session.interrupt({ sessionID }) |
| delete | session.remove({ sessionID }) |
| update title | session.update({ sessionID, title }) |
| fork | session.fork({ sessionID, before? }) -> SessionInfo |
| controlPlane.moveSession | session.move({ sessionID, directory }); handoff = fork then move |
| agent / model switch | session.switchAgent({sessionID, agent}), session.switchModel({sessionID, model}) |
| PTY | client.pty.create/update/remove/list; WebSocket URL = `ws(s)://<server host>/api/pty/${ptyID}/connect?ticket=<ticket>` where `ticket` = (await client.pty.connect.token({ ptyID, location:{directory}, "x-opencode-ticket": "1" })).data.ticket (PtyTicketConnectToken {ticket, expires_in}; single use, short-lived: request a fresh one for every socket open, see packages/client/src/solid/pty.ts) |
| permission.list | permission.request.list |
| question.* | form.list, session.form.reply |
| app.agents, mcp.status | agent.list, mcp.list |
| bulk status | session.active() once (map of sessionID -> {type:"running"}), then events |
| branchName.generate | client.rpc(KiloBranchNameRpc.Definition).generate({ sessionID, prompt, providerID?, modelID? }, { location:{directory} }) -> { branch: string \| null }; import from "@opencode/schema/kilocode/branch-name" |
| /kilocode/agent-manager routes + kilocode.agent_manager.* events | client.rpc(KiloAgentManagerRpc.Definition) methods list/reply/reject and events start/requested/cancelled ("@opencode/schema/kilocode/agent-manager") |

## Event mapping (envelope v1 `{type, properties}` -> v2 `{id, type, data, location}`; `location.directory` is the directory)
| v1 | v2 |
|---|---|
| session.created / updated | session.created, session.metadata.updated, session.renamed, session.moved, session.archived |
| session.deleted | session.deleted |
| session.status (busy/idle/retry) | session.status, session.execution.started/succeeded/failed/interrupted, session.idle, session.retry.scheduled |
| session.error | session.execution.failed |
| question.* | form.created, form.replied, form.cancelled |
| permission.* | permission.asked, permission.replied |
| message.part.* | session.text.*, session.tool.*, session.step.* |
| server.instance.disposed | global.disposed |
| pty.* | pty.created/updated/exited/deleted |

## Webview seam (webview-ui/agent-manager)
- `v2/panel-data.ts` `createPanelData({ post })` -> `PanelData`: one client + one event stream for the panel; `store(directory)` returns the lazily created per-directory `V2` scope (`.api`, `.data` = createData store, `.connection`, `.report`, ...); `release(dir)`, `retain(dirs)`, `receive(message)`.
- `v2/sessions.ts` `createSessions({ panel, directories, directoryOf })`: `sessions()`, `get(id)`, `scope(id)`, `currentSessionID()`, `selectSession(id)`, `clearCurrentSession()`, `activityFor(id)`, `isSubmitting(id)`, `messages(id)`, `loading(id)`, `sync(id)`, `release(id)`, `interrupt(id)`.
- `v2/activity.ts`: `Activity`, `strongest`, `score`, `running`, `label`, `description`, `sessionActivity`.
- `v2/vscode.ts`: `useVSCode()` typed with the AM message contract. Use it instead of the shared context in AM files.
- Session UI: `webview-ui/src/v2/session-view.tsx` `SessionView` (transcript + docks + prompt) inside `<V2Scope value={panel.store(dir)}>` from `webview-ui/src/v2/client.tsx`.
- Message contract: host `src/agent-manager/types.ts` (AgentManagerInMessage/OutMessage) and webview `webview-ui/src/types/messages/agent-manager.ts` (AgentManagerExtensionMessage/WebviewMessage). Keep both in sync when you add/remove a message.

## Verify
- From PKG: `../../node_modules/.bin/tsc --noEmit` (host+tests) and `bun test test/<your tests>`. The webview program has no entry yet; for webview files create a temporary tsconfig extending webview-ui/tsconfig.json with your files and delete it after.
- Port the v1 tests of your modules (V1/tests/unit/*.test.ts and V1/src/agent-manager/__tests__) to PKG/test/<same basename>, bun:test, important assertions unchanged.
73 changes: 73 additions & 0 deletions .kilo/plans/agent-manager-v2-ledger.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Agent Manager v2 port - working ledger

Worktree: /Users/marius/Documents/git/kilocode/.kilo/worktrees/stupendous-borogovia
Branch: am-v2-seam (agent-manager-v2 is checked out by another busy session, carnelian-pram)
v1 extract: /var/folders/6c/3j3r25ds6pd1dw3nlrfnvv280000gp/T/kilo/v1/packages/kilo-vscode

## Limits (checked on v1 source)
- oxlint kilo-vscode: max-lines 3000/file, complexity 20/function. No new per-file caps.
- file-size-ratchet.test.ts caps listed files only (no AM files).
- jscpd duplication over packages/kilo-vscode/src and webview-ui (tests excluded).
- v1 violations (complexity): AgentManagerProvider.ts:622 (48), WorktreeManager.ts:398 (27),
WorktreeStateManager.ts:778 (21), kilo-provider-utils.ts:205 (21) :329 (24) :670 (23),
AgentManagerApp.tsx:223 (37) :1151 (45) :1281 (27) :1373 (50).
- Large files to split: AgentManagerProvider.ts 1899, AgentManagerApp.tsx 2563, WorktreeManager.ts 1637,
types.ts 1395, NewWorktreeDialog.tsx 1378, terminal/state.ts 1048, PRStatusPoller.ts 981.

## Decisions
- globalState not shared: v1 id kilocode.kilo-code, v2 id kilocode.kilo-code-v2. Keys keep v1 names.
- AM protocol types: src/agent-manager/types.ts, imported by host and webview.
- Fan-out: one connection per panel, events routed by location.directory, broadcast when no location
or session.moved.

## Ledger (copied | adapted | rewritten | stubbed(dep) | removed(epic))
### Wave 1 host (agent ses_e61ca2eb)
- copied unchanged: 87 files (AM host independent part, util/process, git-executable, serialize, shared/branch-slug, pr-comment-*, pr-patch, review-comments, diff/shared/*, diff/types, path-utils, pr/pr-types)
- adapted: WorktreeManager (complexity split), WorktreeStateManager (split), constants (-PLATFORM), local-diff-cache+project/route (zeroID), project/session-view, project/state-gate (-browser), prune-subagents (PruneSessionSource), worktree-create (-telemetry), worktree-importer, types.ts (-excluded), host.ts (-SessionProvider etc), util/spotlight
- new: shared/zero-id.ts, agent-manager/errors.ts
- stubbed: project/wiring.ts needs project/settings (boundary, mine)
- tests: 47 files, 1132 pass, 1 fail local-diff timer race (investigate)
### Wave UI-A (agent ses_e61c2331)
- copied 77 unchanged, 39 import-only, 10 adapted (css -documents, side-panel-layout/state -browser/-documents, state-handlers -browser, progress -clearFailedDelete, hydration inline needsLocalDraft, session-filter time.created, navigate, tab-drag, TabBar -telemetry, TerminalTab)
- left out (boundary, mine): initial-message, ProjectSidebarBody, pr/PRMerge (update-from-base), pr/review (edit-preview), ProjectList, apply-to-local, project/local-tabs, pr/PRComments, PRConversation, PRPanelHost
- contract: webview-ui/src/types/messages/agent-manager.ts (aliases ExtensionMessage/WebviewMessage, check usage)
- issue: diff/sources/types.ts pulls Node host modules into webview program
- tests: 19 files, 198 pass
- adapted: local-diff-cache.ts schedule setImmediate->setTimeout(0) (bun test runs immediates between due timers)
- diff/types.ts: PanelContext moved out (saved in T/kilo/diff-panel-context.ts) -> restore as src/diff/context.ts with diff subsystem (PR4)
### Server plugins (agent ses_e61bc822) -> PR5
- schema/kilocode/branch-name.ts: rpc kilocode.branch-name generate({sessionID,prompt,providerID?,modelID?}) -> {branch|null}
- schema/kilocode/agent-manager.ts: rpc kilocode.agent-manager list({}) reply({requestID,result}) reject({requestID,error:{code,message}});
events rpc.kilocode.agent-manager.{start,requested,cancelled}; rpc.events.on(name, handler, {signal})
- kilo-plugin/src/agent-manager/*: tools, service (60s), guard (tool execute.before), permission (evaluate hook)
- metadata reaches projected user message (kilo-cli/test/agent-manager-metadata.test.ts)
- gaps: no sandbox token; tool result has no title
- dispositions to add: see agent report (agent-manager 11 ported, branch-name 2, permission 2)
- lockfile: friendly-words pulls ava/express (v1 same), accepted
### Phase A agents (launched 22:3x)
- terminals ses_e61a50d6, diff ses_e61a4d3d, PR UI ses_e61a4a9a, orchestration ses_e61a4738, provider ses_e61a3f6b, webview app ses_e61a3a63
- chat.ts: CSP connect-src adds ws://127.0.0.1:* for agentManager view
- conventions: T/kilo/am-conventions.md
### Diff agent done (ses_e61a4d3d) -> PR4
- 15 host files + 11 AM webview + ~30 diff-viewer files; tests 231 pass
- CHECK: edit-preview (edit-preview.ts, EditPreviewPanel) has no v2 producer (permission request has no filediff) -> dead? decide
- CHECK: review-settings not ported; verify AM state persists reviewMarkdownRender/diffStyle
- review comments -> window event agentManager.appendReviewComments (composer + terminal must consume)
### PR UI done (ses_e61a4a9a); terminals done + relay follow-up running
### Orchestration done (ses_e61a4738) -> PR5; 64 tests
- gap: overview 'retry' reported as busy (session.active has no retry) -> consider tracking session.retry.scheduled in provider busy set
- provider must forward rpc.kilocode.agent-manager.start via handleToolEvent(event, event.location?.directory, ...)
### Edit preview producer: v2 edit/write permission metadata {files:[FileDiffInfo]} -> add AM preview action to v2 PermissionDock (my task)
### Terminals relay done: pty-relay.ts + terminal/socket.ts; CSP reverted; wsUrl/attach removed
- worktree teardown -> client.debug.location.evict (stable debug endpoint; disposes location services incl PTYs) -> name in PR
- removeSnapshot -> new RPC method kilocode.agent-manager.removeSnapshot (server agent follow-up running); v2 snapshot repos <data>/snapshot/<project>/<hash(worktree)>
- Host.openPanel / unregisterProjectRoutes removed (no shims)
### removeSnapshot RPC done (plugin snapshot.ts, 31 tests); dispositions snapshot: cleanup.ts, snapshot-repository-cleanup.test.ts, api POST /kilocode/snapshot/remove
### App agent done (ses_e61a3a63). My integration fixes:
- restored kilo-ui radio-group/resize-handle/dropdown-menu (v1 ui base + kilo-ui re-exports); copied FullScreenDiffView/DiffScopeControls/BaseBranchPicker
- DragHandle -> ResizeHandle; HistoryView rebuilt on generalized v2 SessionList (rename/delete/search, local+worktree tabs)
- WebviewShell shared by sidebar and AM entry; AM entry imports chat.css
- SessionView: speech=false, onAppendReady, onPreviewEdit; toolActions openDiff/openDiffs -> edit preview; dropped edit-preview window event
- bridge.ts JSX-free types; review-annotations local i18n type; kilo-ui pierre/limits.ts split
- ShortcutHints: removed unused manager() + utils/shortcut-hint.ts; added kilo-code.v2.showShortcutHints setting
- App parity notes from agent: model mention removed, BYOK/data badges dropped, HistoryView cloud tab (cloud = other epic #15306)
Loading
Loading