@evandu/super-pi 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +79 -2
  2. package/agents/coder.md +10 -0
  3. package/agents/critic.md +20 -0
  4. package/agents/patcher.md +23 -0
  5. package/agents/planner.md +18 -0
  6. package/agents/reviewer.md +13 -0
  7. package/agents/scout.md +23 -0
  8. package/agents/super-pi-task/core.ts +485 -0
  9. package/agents/super-pi-task/index.ts +141 -0
  10. package/agents/verifier.md +21 -0
  11. package/bin/super-pi.js +17 -0
  12. package/dist/client/assets/index-BMQsEdio.js +24 -0
  13. package/dist/client/assets/index-CsbZzuMy.css +1 -0
  14. package/dist/client/index.html +14 -0
  15. package/dist/extension.d.ts +15 -0
  16. package/dist/extension.js +111 -0
  17. package/dist/server/agents.d.ts +177 -0
  18. package/dist/server/agents.js +484 -0
  19. package/dist/server/application/catalog-service.d.ts +44 -0
  20. package/dist/server/application/catalog-service.js +94 -0
  21. package/dist/server/application/conversation-service.d.ts +73 -0
  22. package/dist/server/application/conversation-service.js +202 -0
  23. package/dist/server/application/extension-ui-service.d.ts +28 -0
  24. package/dist/server/application/extension-ui-service.js +73 -0
  25. package/dist/server/application/run-service.d.ts +115 -0
  26. package/dist/server/application/run-service.js +341 -0
  27. package/dist/server/application/workspace-service.d.ts +45 -0
  28. package/dist/server/application/workspace-service.js +106 -0
  29. package/dist/server/command-handler.d.ts +22 -0
  30. package/dist/server/command-handler.js +137 -0
  31. package/dist/server/files.d.ts +202 -0
  32. package/dist/server/files.js +629 -0
  33. package/dist/server/http-server.d.ts +20 -0
  34. package/dist/server/http-server.js +313 -0
  35. package/dist/server/index.d.ts +1 -0
  36. package/dist/server/index.js +103 -0
  37. package/dist/server/pi-command.d.ts +65 -0
  38. package/dist/server/pi-command.js +183 -0
  39. package/dist/server/runtime.d.ts +819 -0
  40. package/dist/server/runtime.js +1470 -0
  41. package/dist/server/server-context.d.ts +46 -0
  42. package/dist/server/server-context.js +1 -0
  43. package/dist/server/store.d.ts +424 -0
  44. package/dist/server/store.js +1121 -0
  45. package/dist/server/subagent-runs.d.ts +142 -0
  46. package/dist/server/subagent-runs.js +315 -0
  47. package/dist/server/subagents.d.ts +194 -0
  48. package/dist/server/subagents.js +542 -0
  49. package/dist/server/task-tool.d.ts +196 -0
  50. package/dist/server/task-tool.js +285 -0
  51. package/dist/server/tool-calls.d.ts +62 -0
  52. package/dist/server/tool-calls.js +141 -0
  53. package/dist/server/types.d.ts +920 -0
  54. package/dist/server/types.js +11 -0
  55. package/dist/server/upload.d.ts +37 -0
  56. package/dist/server/upload.js +169 -0
  57. package/dist/server/ws-server.d.ts +45 -0
  58. package/dist/server/ws-server.js +116 -0
  59. package/package.json +115 -4
@@ -0,0 +1,73 @@
1
+ import { type Store } from "../store.js";
2
+ import type { AgentRuntime } from "../runtime.js";
3
+ import type { SubagentRunRecorder } from "../subagent-runs.js";
4
+ import type { EventBroadcaster } from "../server-context.js";
5
+ import type { CatalogService } from "./catalog-service.js";
6
+ import type { RunService } from "./run-service.js";
7
+ import type { ExtensionUiService } from "./extension-ui-service.js";
8
+ export type ForkConversationResult = {
9
+ ok: true;
10
+ forkedId: string;
11
+ title: string;
12
+ messagesCopied: number;
13
+ piSessionFile?: string;
14
+ } | {
15
+ ok: false;
16
+ message: string;
17
+ };
18
+ /**
19
+ * Service managing conversation lifecycle: creation, selection, archiving,
20
+ * model/thinking/agent configuration, message reversion, and session forking.
21
+ */
22
+ export declare class ConversationService {
23
+ private readonly store;
24
+ private readonly runtime;
25
+ private readonly subagents;
26
+ private readonly broadcaster;
27
+ private readonly catalogService;
28
+ private readonly runService;
29
+ private readonly extensionUiService;
30
+ private readonly agentsDir;
31
+ constructor(store: Store, runtime: AgentRuntime, subagents: SubagentRunRecorder, broadcaster: EventBroadcaster, catalogService: CatalogService, runService: RunService, extensionUiService: ExtensionUiService, agentsDir: string);
32
+ /**
33
+ * Creates a new conversation in a workspace.
34
+ */
35
+ createConversation(workspaceId: string): Promise<void>;
36
+ /**
37
+ * Selects a conversation and broadcasts the catalog for that conversation's model.
38
+ */
39
+ selectConversation(conversationId: string): Promise<void>;
40
+ /**
41
+ * Archives a conversation.
42
+ */
43
+ archiveConversation(conversationId: string): Promise<void>;
44
+ /**
45
+ * Unarchives a conversation.
46
+ */
47
+ unarchiveConversation(conversationId: string): Promise<void>;
48
+ /**
49
+ * Renames a conversation.
50
+ */
51
+ renameConversation(conversationId: string, name: string): Promise<void>;
52
+ /**
53
+ * Sets the active model on a conversation, validating against Pi's catalog.
54
+ */
55
+ setModel(conversationId: string, provider: string, modelId: string): Promise<void>;
56
+ /**
57
+ * Sets the thinking level on a conversation, validating against the model's available levels.
58
+ */
59
+ setThinking(conversationId: string, level: string): Promise<void>;
60
+ /**
61
+ * Configures or clears the primary agent assigned to a conversation.
62
+ */
63
+ setAgent(conversationId: string, agentId: string | null): Promise<void>;
64
+ /**
65
+ * Reverts conversation history to a designated message boundary, truncating both
66
+ * Pi's transcript and state.json.
67
+ */
68
+ revertMessage(conversationId: string, messageId: string): Promise<void>;
69
+ /**
70
+ * Forks an existing conversation into a new parallel branch, cloning the Pi session.
71
+ */
72
+ forkConversation(conversationId: string): Promise<ForkConversationResult>;
73
+ }
@@ -0,0 +1,202 @@
1
+ import { newConversationId } from "../store.js";
2
+ /**
3
+ * Service managing conversation lifecycle: creation, selection, archiving,
4
+ * model/thinking/agent configuration, message reversion, and session forking.
5
+ */
6
+ export class ConversationService {
7
+ store;
8
+ runtime;
9
+ subagents;
10
+ broadcaster;
11
+ catalogService;
12
+ runService;
13
+ extensionUiService;
14
+ agentsDir;
15
+ constructor(store, runtime, subagents, broadcaster, catalogService, runService, extensionUiService, agentsDir) {
16
+ this.store = store;
17
+ this.runtime = runtime;
18
+ this.subagents = subagents;
19
+ this.broadcaster = broadcaster;
20
+ this.catalogService = catalogService;
21
+ this.runService = runService;
22
+ this.extensionUiService = extensionUiService;
23
+ this.agentsDir = agentsDir;
24
+ }
25
+ /**
26
+ * Creates a new conversation in a workspace.
27
+ */
28
+ async createConversation(workspaceId) {
29
+ await this.store.createConversation(workspaceId);
30
+ this.broadcaster.broadcastState();
31
+ }
32
+ /**
33
+ * Selects a conversation and broadcasts the catalog for that conversation's model.
34
+ */
35
+ async selectConversation(conversationId) {
36
+ const conversation = this.store.snapshot().conversations.find((item) => item.id === conversationId);
37
+ await this.catalogService.broadcastCatalog(conversation?.model);
38
+ }
39
+ /**
40
+ * Archives a conversation.
41
+ */
42
+ async archiveConversation(conversationId) {
43
+ await this.store.archiveConversation(conversationId);
44
+ this.broadcaster.broadcastState();
45
+ }
46
+ /**
47
+ * Unarchives a conversation.
48
+ */
49
+ async unarchiveConversation(conversationId) {
50
+ await this.store.unarchiveConversation(conversationId);
51
+ this.broadcaster.broadcastState();
52
+ }
53
+ /**
54
+ * Renames a conversation.
55
+ */
56
+ async renameConversation(conversationId, name) {
57
+ await this.store.renameConversation(conversationId, name);
58
+ this.broadcaster.broadcastState();
59
+ }
60
+ /**
61
+ * Sets the active model on a conversation, validating against Pi's catalog.
62
+ */
63
+ async setModel(conversationId, provider, modelId) {
64
+ const catalog = await this.runtime.catalog();
65
+ const option = catalog.source === "pi"
66
+ ? catalog.models.find((model) => model.provider === provider && model.modelId === modelId)
67
+ : undefined;
68
+ if (catalog.source === "pi" && !option) {
69
+ throw this.catalogService.notOffered(`模型 ${provider}/${modelId}`, catalog);
70
+ }
71
+ const selection = option
72
+ ? { provider: option.provider, modelId: option.modelId, label: option.label }
73
+ : { provider, modelId, label: modelId };
74
+ await this.store.setConversationModel(conversationId, selection);
75
+ this.broadcaster.broadcastState();
76
+ await this.catalogService.broadcastCatalog(selection);
77
+ }
78
+ /**
79
+ * Sets the thinking level on a conversation, validating against the model's available levels.
80
+ */
81
+ async setThinking(conversationId, level) {
82
+ const conversation = this.store.snapshot().conversations.find((item) => item.id === conversationId);
83
+ const catalog = await this.runtime.catalog(conversation?.model);
84
+ if (catalog.source === "pi" && !catalog.levels.includes(level)) {
85
+ throw this.catalogService.notOffered(`思考等级 ${level}`, catalog);
86
+ }
87
+ await this.store.setConversationThinking(conversationId, level);
88
+ this.broadcaster.broadcastState();
89
+ }
90
+ /**
91
+ * Configures or clears the primary agent assigned to a conversation.
92
+ */
93
+ async setAgent(conversationId, agentId) {
94
+ const conversation = this.store.snapshot().conversations.find((item) => item.id === conversationId);
95
+ if (!conversation)
96
+ throw new Error("Conversation not found");
97
+ if (agentId === null) {
98
+ await this.store.setConversationAgent(conversationId, undefined);
99
+ this.broadcaster.broadcastState();
100
+ return;
101
+ }
102
+ const agent = await this.runtime.agentFor?.({ id: conversation.id, agentId });
103
+ if (!agent) {
104
+ throw new Error(`Agent ${JSON.stringify(agentId)} 不存在或不是可用的 primary agent(目录:${this.agentsDir})`);
105
+ }
106
+ if (agent.model) {
107
+ const catalog = await this.runtime.catalog();
108
+ if (catalog.source === "pi" && !catalog.models.some((model) => model.provider === agent.model?.provider && model.modelId === agent.model?.modelId)) {
109
+ throw this.catalogService.notOffered(`Agent ${agent.name} 指定的模型 ${agent.model.provider}/${agent.model.modelId}`, catalog);
110
+ }
111
+ const option = catalog.models.find((model) => model.provider === agent.model?.provider && model.modelId === agent.model?.modelId);
112
+ await this.store.setConversationModel(conversationId, option
113
+ ? { provider: option.provider, modelId: option.modelId, label: option.label }
114
+ : { provider: agent.model.provider, modelId: agent.model.modelId, label: `${agent.model.provider}/${agent.model.modelId}` });
115
+ }
116
+ if (agent.thinkingLevel) {
117
+ const catalog = await this.runtime.catalog(this.store.snapshot().conversations.find((item) => item.id === conversationId)?.model);
118
+ if (catalog.source === "pi" && !catalog.levels.includes(agent.thinkingLevel)) {
119
+ throw this.catalogService.notOffered(`Agent ${agent.name} 指定的思考等级 ${agent.thinkingLevel}`, catalog);
120
+ }
121
+ await this.store.setConversationThinking(conversationId, agent.thinkingLevel);
122
+ }
123
+ await this.store.setConversationAgent(conversationId, agent.id);
124
+ this.broadcaster.broadcastState();
125
+ await this.catalogService.broadcastCatalog(this.store.snapshot().conversations.find((item) => item.id === conversationId)?.model);
126
+ }
127
+ /**
128
+ * Reverts conversation history to a designated message boundary, truncating both
129
+ * Pi's transcript and state.json.
130
+ */
131
+ async revertMessage(conversationId, messageId) {
132
+ const plan = this.store.planRevert(conversationId, messageId);
133
+ const conversation = this.store.snapshot().conversations.find((item) => item.id === conversationId);
134
+ if (!conversation)
135
+ throw new Error("会话不存在");
136
+ const workspace = this.store.snapshot().workspaces.find((item) => item.id === conversation.workspaceId);
137
+ if (!workspace)
138
+ throw new Error(`会话所属的工作区 ${conversation.workspaceId} 已不存在,拒绝回退`);
139
+ if (!this.runtime.revert) {
140
+ throw new Error("当前运行时没有 Pi 会话,无法回退消息");
141
+ }
142
+ if (this.runService.isRunning(conversationId)) {
143
+ this.extensionUiService.cancelPendingUi(conversationId, "aborted");
144
+ await this.runService.stopRun(conversationId);
145
+ }
146
+ for (const runId of plan.doomedRunIds) {
147
+ if (this.subagents.stop(runId)) {
148
+ console.log(`Super Pi: stopped sub-agent run ${runId}, whose turn was reverted away.`);
149
+ }
150
+ }
151
+ const outcome = await this.runtime.revert({
152
+ conversation,
153
+ cwd: workspace.path,
154
+ boundaryEntryId: plan.boundaryEntryId,
155
+ });
156
+ const applied = await this.store.revertMessages(conversationId, messageId);
157
+ console.log(`Super Pi: reverted conversation ${conversationId} to ${applied.boundaryIndex + 1} message(s): ` +
158
+ `${plan.removedMessageIds.length} message(s) and ${applied.doomedRunIds.length} sub-agent run(s) dropped from state.json; ` +
159
+ `Pi's file ${outcome.sessionFile} kept ${outcome.linesKept} line(s) and lost ${outcome.entriesDropped}.`);
160
+ this.broadcaster.broadcastState();
161
+ }
162
+ /**
163
+ * Forks an existing conversation into a new parallel branch, cloning the Pi session.
164
+ */
165
+ async forkConversation(conversationId) {
166
+ const snapshot = this.store.snapshot();
167
+ const conversation = snapshot.conversations.find((item) => item.id === conversationId);
168
+ if (!conversation) {
169
+ return { ok: false, message: "会话不存在" };
170
+ }
171
+ const workspace = snapshot.workspaces.find((item) => item.id === conversation.workspaceId);
172
+ if (!workspace) {
173
+ return { ok: false, message: `会话所属的工作区 ${conversation.workspaceId} 已不存在,拒绝分叉` };
174
+ }
175
+ if (this.runService.isRunning(conversationId)) {
176
+ return { ok: false, message: "这个会话还有一轮任务在跑,等它结束(或先停止它)再分叉" };
177
+ }
178
+ if (!this.runtime.fork) {
179
+ return { ok: false, message: "当前运行时没有 Pi 会话,无法分叉(只能复制可见的历史)" };
180
+ }
181
+ try {
182
+ const forkedId = newConversationId();
183
+ const outcome = await this.runtime.fork({ conversation, cwd: workspace.path, forkedConversationId: forkedId });
184
+ const forked = await this.store.forkConversation(conversationId, forkedId);
185
+ console.log(`Super Pi: forked conversation ${conversation.id} into ${forked.id}: ` +
186
+ `${forked.messages.length} message(s) copied in state.json` +
187
+ `${outcome.sessionFile ? `, ${outcome.entriesCopied} Pi entry/entries copied to ${outcome.sessionFile}` : ", and this conversation had no Pi transcript to copy (no messages)"}.`);
188
+ this.broadcaster.broadcastState();
189
+ return {
190
+ ok: true,
191
+ forkedId: forked.id,
192
+ title: forked.title,
193
+ messagesCopied: forked.messages.length,
194
+ piSessionFile: outcome.sessionFile,
195
+ };
196
+ }
197
+ catch (error) {
198
+ const message = error instanceof Error ? error.message : `分叉失败:${String(error)}`;
199
+ return { ok: false, message };
200
+ }
201
+ }
202
+ }
@@ -0,0 +1,28 @@
1
+ import type { ExtensionUiHost } from "../runtime.js";
2
+ import type { ExtensionUiAnswer, ExtensionUiCloseReason } from "../types.js";
3
+ import type { EventBroadcaster } from "../server-context.js";
4
+ /**
5
+ * Service managing extension UI interactive prompts between Pi / subagents and connected clients.
6
+ */
7
+ export declare class ExtensionUiService {
8
+ private readonly broadcaster;
9
+ private readonly pendingUi;
10
+ constructor(broadcaster: EventBroadcaster);
11
+ private uiKey;
12
+ /**
13
+ * Settles a pending UI request by answering, timing out, or aborting.
14
+ */
15
+ settleUi(key: string, answer: ExtensionUiAnswer, reason: ExtensionUiCloseReason): boolean;
16
+ /**
17
+ * Responds to an extension UI question from the client.
18
+ */
19
+ answerUi(conversationId: string, requestId: string, answer: ExtensionUiAnswer): boolean;
20
+ /**
21
+ * Cancels any pending UI requests for a given conversation.
22
+ */
23
+ cancelPendingUi(conversationId: string, reason: ExtensionUiCloseReason): void;
24
+ /**
25
+ * Creates an ExtensionUiHost interface for a conversation or subagent run.
26
+ */
27
+ createHost(conversationId: string, runId?: string): ExtensionUiHost;
28
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Service managing extension UI interactive prompts between Pi / subagents and connected clients.
3
+ */
4
+ export class ExtensionUiService {
5
+ broadcaster;
6
+ pendingUi = new Map();
7
+ constructor(broadcaster) {
8
+ this.broadcaster = broadcaster;
9
+ }
10
+ uiKey(conversationId, requestId) {
11
+ return `${conversationId}\u0000${requestId}`;
12
+ }
13
+ /**
14
+ * Settles a pending UI request by answering, timing out, or aborting.
15
+ */
16
+ settleUi(key, answer, reason) {
17
+ const pending = this.pendingUi.get(key);
18
+ if (!pending) {
19
+ console.warn(`Super Pi: Extension UI answer for ${key.replace("\u0000", "/")} arrived after that request was already closed - ignored, no second reply sent.`);
20
+ return false;
21
+ }
22
+ this.pendingUi.delete(key);
23
+ if (pending.timer)
24
+ clearTimeout(pending.timer);
25
+ pending.resolve(answer);
26
+ this.broadcaster.broadcast({
27
+ type: "extension.ui.closed",
28
+ conversationId: pending.conversationId,
29
+ requestId: pending.request.requestId,
30
+ reason,
31
+ });
32
+ return true;
33
+ }
34
+ /**
35
+ * Responds to an extension UI question from the client.
36
+ */
37
+ answerUi(conversationId, requestId, answer) {
38
+ return this.settleUi(this.uiKey(conversationId, requestId), answer, answer.cancelled ? "cancelled" : "answered");
39
+ }
40
+ /**
41
+ * Cancels any pending UI requests for a given conversation.
42
+ */
43
+ cancelPendingUi(conversationId, reason) {
44
+ for (const [key, pending] of [...this.pendingUi]) {
45
+ if (pending.conversationId === conversationId) {
46
+ this.settleUi(key, { cancelled: true }, reason);
47
+ }
48
+ }
49
+ }
50
+ /**
51
+ * Creates an ExtensionUiHost interface for a conversation or subagent run.
52
+ */
53
+ createHost(conversationId, runId) {
54
+ const scoped = (request) => runId ? { ...request, requestId: `${runId}:${request.requestId}` } : request;
55
+ return {
56
+ notify: (request) => {
57
+ this.broadcaster.broadcast({ type: "extension.ui", conversationId, request: scoped(request) });
58
+ },
59
+ ask: (request) => new Promise((resolve) => {
60
+ const shown = scoped(request);
61
+ const key = this.uiKey(conversationId, shown.requestId);
62
+ const pending = { conversationId, request: shown, resolve };
63
+ if (shown.timeoutMs !== undefined) {
64
+ pending.timer = setTimeout(() => {
65
+ this.settleUi(key, { cancelled: true }, "timeout");
66
+ }, shown.timeoutMs);
67
+ }
68
+ this.pendingUi.set(key, pending);
69
+ this.broadcaster.broadcast({ type: "extension.ui", conversationId, request: shown });
70
+ }),
71
+ };
72
+ }
73
+ }
@@ -0,0 +1,115 @@
1
+ import type { Store } from "../store.js";
2
+ import type { AgentRuntime } from "../runtime.js";
3
+ import type { SubagentRunRecorder } from "../subagent-runs.js";
4
+ import type { Conversation, Message, MessageImage, PiQueueSnapshot, Workspace } from "../types.js";
5
+ import type { EventBroadcaster } from "../server-context.js";
6
+ import type { ExtensionUiService } from "./extension-ui-service.js";
7
+ export interface SubagentDispatchRequestBody {
8
+ conversationId?: string;
9
+ subagent_type?: string;
10
+ prompt?: string;
11
+ depth?: number;
12
+ parentRunId?: string;
13
+ background?: boolean;
14
+ description?: string;
15
+ loopId?: string;
16
+ role?: string;
17
+ }
18
+ /**
19
+ * Service managing execution of conversation turns, message queueing,
20
+ * follow-ups, and sub-agent dispatching.
21
+ */
22
+ export declare class RunService {
23
+ private readonly store;
24
+ private readonly runtime;
25
+ private readonly subagents;
26
+ private readonly broadcaster;
27
+ private readonly extensionUiService;
28
+ private readonly activeRuns;
29
+ constructor(store: Store, runtime: AgentRuntime, subagents: SubagentRunRecorder, broadcaster: EventBroadcaster, extensionUiService: ExtensionUiService);
30
+ /**
31
+ * Resolves the conversation and workspace synchronously for a run.
32
+ */
33
+ turnContext(conversationId: string): {
34
+ conversation: Conversation;
35
+ workspace: Workspace;
36
+ };
37
+ /**
38
+ * Resolves conversation and workspace working directory for subagent dispatch.
39
+ */
40
+ dispatchContext(conversationId: string): {
41
+ conversation: Conversation;
42
+ cwd: string;
43
+ };
44
+ /**
45
+ * Checks whether a conversation has an active turn running.
46
+ */
47
+ isRunning(conversationId: string): boolean;
48
+ /**
49
+ * Aborts all active conversation runs and sub-agents.
50
+ */
51
+ abortAll(): void;
52
+ /**
53
+ * Stops an active turn run for a conversation.
54
+ */
55
+ stopRun(conversationId: string): Promise<void>;
56
+ /**
57
+ * Handles queue snapshot updates from Pi RPC.
58
+ */
59
+ onPiQueue(conversationId: string, snapshot: PiQueueSnapshot): void;
60
+ /**
61
+ * Opens a turn by creating user and assistant messages in store.
62
+ */
63
+ openTurn(conversationId: string, prompt?: string, images?: MessageImage[]): Promise<{
64
+ user: Message;
65
+ assistant: Message;
66
+ }>;
67
+ /**
68
+ * Streams a turn via AgentRuntime.
69
+ */
70
+ streamTurn(conversation: Conversation, workspace: Workspace, prompt: string, assistant: Message, controller: AbortController, userMessageId: string, images?: MessageImage[]): Promise<void>;
71
+ /**
72
+ * Loops running turns for as long as queued follow-ups exist.
73
+ */
74
+ runConversationTurns(conversation: Conversation, workspace: Workspace, prompt: string, controller: AbortController, initialImages?: MessageImage[]): Promise<void>;
75
+ /**
76
+ * Enqueues or starts execution for a user message.
77
+ */
78
+ enqueueAndRun(conversationId: string, content: string, images?: MessageImage[]): Promise<void>;
79
+ /**
80
+ * Steers a queued message into the in-flight turn.
81
+ */
82
+ steer(conversationId: string, queueId: string): Promise<void>;
83
+ /**
84
+ * Cancels a queued message.
85
+ */
86
+ cancelQueued(conversationId: string, queueId: string): Promise<void>;
87
+ /**
88
+ * Dispatches a subagent from client command (human dispatch).
89
+ */
90
+ dispatchSubagent(params: {
91
+ conversationId: string;
92
+ agentId: string;
93
+ task: string;
94
+ }): Promise<void>;
95
+ /**
96
+ * Dispatches a subagent task requested by the task tool HTTP endpoint.
97
+ */
98
+ dispatchTask(body: SubagentDispatchRequestBody): Promise<{
99
+ mode: "sync";
100
+ status: number;
101
+ body: unknown;
102
+ } | {
103
+ mode: "async";
104
+ status: number;
105
+ body: unknown;
106
+ }>;
107
+ /**
108
+ * Stops a specific subagent run by runId.
109
+ */
110
+ stopSubagent(runId: string): void;
111
+ /**
112
+ * Stops all subagent runs belonging to a conversation.
113
+ */
114
+ stopConversationSubagents(conversationId: string): number;
115
+ }