akanjs 3.0.0-beta.15 → 3.0.0-beta.17

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.
@@ -4,6 +4,7 @@ import type {
4
4
  CodeAgentQuestion,
5
5
  CodeAgentSessionInfo,
6
6
  CodeAgentStopReason,
7
+ CodeAgentSubagent,
7
8
  CodeAgentToolOutcome,
8
9
  CodeAgentToolSummary,
9
10
  } from "akanjs/common";
@@ -46,6 +47,7 @@ export class CodeTranscript {
46
47
  #approval: CodeAgentApprovalRequest | undefined;
47
48
  #stopReason: CodeAgentStopReason | undefined;
48
49
  #queue = { steering: 0, followUp: 0 };
50
+ #subagents: CodeAgentSubagent[] = [];
49
51
  #openAssistant: string | undefined;
50
52
  #openThinking: string | undefined;
51
53
  #nextId = 0;
@@ -104,6 +106,11 @@ export class CodeTranscript {
104
106
  return this.#queue;
105
107
  }
106
108
 
109
+ /** The sub-agents running right now. Not a transcript row: they are a state, and the state is the list. */
110
+ get subagents() {
111
+ return this.#subagents;
112
+ }
113
+
107
114
  /** Bumped on every applied event, so a view can tell "changed" from "same" without comparing arrays. */
108
115
  get revision() {
109
116
  return this.#revision;
@@ -202,11 +209,16 @@ export class CodeTranscript {
202
209
  return;
203
210
  case "notice":
204
211
  return this.#notice(event.level, event.message);
212
+ case "subagent":
213
+ this.#subagents = event.agents;
214
+ return;
205
215
  case "error":
206
216
  return this.#notice("error", event.message);
207
217
  case "idle":
208
218
  this.#streaming = false;
209
219
  this.#queue = { steering: 0, followUp: 0 };
220
+
221
+ this.#subagents = [];
210
222
  this.#closeStreams(false);
211
223
  return;
212
224
  case "host":
@@ -31,6 +31,24 @@ export interface CodeAgentMcpServerRef {
31
31
  env?: Record<string, string>;
32
32
  }
33
33
 
34
+ /**
35
+ * One declared MCP server, as the session found it.
36
+ *
37
+ * A server that answered and one that was never reachable are both here: an integration that is silently
38
+ * absent is indistinguishable from one the model simply chose not to use, and the tool names are the only
39
+ * evidence of which of the two happened.
40
+ */
41
+ export interface CodeAgentMcpStatus {
42
+ name: string;
43
+ transport: "stdio" | "http";
44
+ /** The command line or the url — what tells two entries of the same shape apart without opening the file. */
45
+ target: string;
46
+ /** Published tool names, already prefixed with the server the way the model sees them. */
47
+ tools: string[];
48
+ /** Why it published none, when it published none. */
49
+ error?: string;
50
+ }
51
+
34
52
  export interface CodeAgentSubagentBudget {
35
53
  maxDepth: number;
36
54
  maxConcurrent: number;
@@ -154,6 +154,23 @@ export interface CodeAgentApprovalRequest {
154
154
  policy: CodeAgentApprovalPolicy;
155
155
  }
156
156
 
157
+ /**
158
+ * One sub-agent the `task` tool is currently running.
159
+ *
160
+ * `tokens` is read at the moment the frame is made, so a host that draws this rail sees the child's spend
161
+ * climb rather than learning it only once the child is gone — which is the number that decides whether to
162
+ * let it keep going. A finished sub-agent leaves the list: what it did is already in the tool row it closed.
163
+ */
164
+ export interface CodeAgentSubagent {
165
+ /** The `task` call that opened it, so a host can line the row up with the tool row above. */
166
+ id: string;
167
+ kind: string;
168
+ /** The three-to-five words the model named the task with. */
169
+ description: string;
170
+ startedAt: number;
171
+ tokens: number;
172
+ }
173
+
157
174
  export type CodeAgentEventBody =
158
175
  | { type: "session"; info: CodeAgentSessionInfo }
159
176
  | { type: "turn_start"; turnId: string }
@@ -180,6 +197,15 @@ export type CodeAgentEventBody =
180
197
  | { type: "retry"; attempt: number; maxAttempts: number; delayMs: number; message: string }
181
198
  | { type: "queue"; steering: string[]; followUp: string[] }
182
199
  | { type: "notice"; level: "info" | "warning" | "error"; message: string }
200
+ /**
201
+ * Every sub-agent running right now, whole rather than as a delta.
202
+ *
203
+ * A list is re-sent on every change and on a slow tick while any child runs, so a host that missed a frame
204
+ * converges on the next one instead of holding a row for a child that finished. It is the one thing a turn
205
+ * does that the transcript cannot show: a `task` call is one tool row that stays open for minutes while its
206
+ * child spends tokens nobody watching sees spent.
207
+ */
208
+ | { type: "subagent"; agents: CodeAgentSubagent[] }
183
209
  | { type: "error"; message: string; fatal: boolean }
184
210
  | { type: "idle" }
185
211
  /**
@@ -236,6 +262,7 @@ export const codeAgentEventPersistence: { [key in CodeAgentEventType]: "live" |
236
262
  retry: "live",
237
263
  queue: "live",
238
264
  notice: "live",
265
+ subagent: "live",
239
266
  error: "persist",
240
267
  idle: "live",
241
268
  host: "live",
@@ -380,6 +407,10 @@ export const codeAgentEventLabel = (event: CodeAgentEventBody): string => {
380
407
  return `queued ${event.steering.length} steering, ${event.followUp.length} follow-up`;
381
408
  case "notice":
382
409
  return `[${event.level}] ${event.message}`;
410
+ case "subagent":
411
+ return event.agents.length
412
+ ? event.agents.map((agent) => `${agent.kind} · ${agent.description}`).join(" | ")
413
+ : "no sub-agent running";
383
414
  case "error":
384
415
  return `error: ${event.message}`;
385
416
  case "idle":
package/common/index.ts CHANGED
@@ -22,6 +22,7 @@ export {
22
22
  type CodeAgentBuiltinTool,
23
23
  type CodeAgentInteractionMode,
24
24
  type CodeAgentMcpServerRef,
25
+ type CodeAgentMcpStatus,
25
26
  type CodeAgentPresetName,
26
27
  type CodeAgentProfile,
27
28
  type CodeAgentSubagentBudget,
@@ -49,6 +50,7 @@ export {
49
50
  type CodeAgentStartOptions,
50
51
  type CodeAgentState,
51
52
  type CodeAgentStopReason,
53
+ type CodeAgentSubagent,
52
54
  type CodeAgentToolOp,
53
55
  type CodeAgentToolOutcome,
54
56
  type CodeAgentToolSummary,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akanjs",
3
- "version": "3.0.0-beta.15",
3
+ "version": "3.0.0-beta.17",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -1,4 +1,4 @@
1
- import type { CodeAgentApprovalRequest, CodeAgentEvent, CodeAgentQuestion, CodeAgentSessionInfo, CodeAgentStopReason, CodeAgentToolOutcome, CodeAgentToolSummary } from "akanjs/common";
1
+ import type { CodeAgentApprovalRequest, CodeAgentEvent, CodeAgentQuestion, CodeAgentSessionInfo, CodeAgentStopReason, CodeAgentSubagent, CodeAgentToolOutcome, CodeAgentToolSummary } from "akanjs/common";
2
2
  export type CodeTranscriptPart = {
3
3
  kind: "user";
4
4
  id: string;
@@ -77,6 +77,8 @@ export declare class CodeTranscript {
77
77
  steering: number;
78
78
  followUp: number;
79
79
  };
80
+ /** The sub-agents running right now. Not a transcript row: they are a state, and the state is the list. */
81
+ get subagents(): CodeAgentSubagent[];
80
82
  /** Bumped on every applied event, so a view can tell "changed" from "same" without comparing arrays. */
81
83
  get revision(): number;
82
84
  /**
@@ -26,6 +26,23 @@ export interface CodeAgentMcpServerRef {
26
26
  url?: string;
27
27
  env?: Record<string, string>;
28
28
  }
29
+ /**
30
+ * One declared MCP server, as the session found it.
31
+ *
32
+ * A server that answered and one that was never reachable are both here: an integration that is silently
33
+ * absent is indistinguishable from one the model simply chose not to use, and the tool names are the only
34
+ * evidence of which of the two happened.
35
+ */
36
+ export interface CodeAgentMcpStatus {
37
+ name: string;
38
+ transport: "stdio" | "http";
39
+ /** The command line or the url — what tells two entries of the same shape apart without opening the file. */
40
+ target: string;
41
+ /** Published tool names, already prefixed with the server the way the model sees them. */
42
+ tools: string[];
43
+ /** Why it published none, when it published none. */
44
+ error?: string;
45
+ }
29
46
  export interface CodeAgentSubagentBudget {
30
47
  maxDepth: number;
31
48
  maxConcurrent: number;
@@ -147,6 +147,22 @@ export interface CodeAgentApprovalRequest {
147
147
  summary: string;
148
148
  policy: CodeAgentApprovalPolicy;
149
149
  }
150
+ /**
151
+ * One sub-agent the `task` tool is currently running.
152
+ *
153
+ * `tokens` is read at the moment the frame is made, so a host that draws this rail sees the child's spend
154
+ * climb rather than learning it only once the child is gone — which is the number that decides whether to
155
+ * let it keep going. A finished sub-agent leaves the list: what it did is already in the tool row it closed.
156
+ */
157
+ export interface CodeAgentSubagent {
158
+ /** The `task` call that opened it, so a host can line the row up with the tool row above. */
159
+ id: string;
160
+ kind: string;
161
+ /** The three-to-five words the model named the task with. */
162
+ description: string;
163
+ startedAt: number;
164
+ tokens: number;
165
+ }
150
166
  export type CodeAgentEventBody = {
151
167
  type: "session";
152
168
  info: CodeAgentSessionInfo;
@@ -223,6 +239,18 @@ export type CodeAgentEventBody = {
223
239
  type: "notice";
224
240
  level: "info" | "warning" | "error";
225
241
  message: string;
242
+ }
243
+ /**
244
+ * Every sub-agent running right now, whole rather than as a delta.
245
+ *
246
+ * A list is re-sent on every change and on a slow tick while any child runs, so a host that missed a frame
247
+ * converges on the next one instead of holding a row for a child that finished. It is the one thing a turn
248
+ * does that the transcript cannot show: a `task` call is one tool row that stays open for minutes while its
249
+ * child spends tokens nobody watching sees spent.
250
+ */
251
+ | {
252
+ type: "subagent";
253
+ agents: CodeAgentSubagent[];
226
254
  } | {
227
255
  type: "error";
228
256
  message: string;
@@ -5,8 +5,8 @@ export { CodeTranscript, type CodeTranscriptPart } from "./CodeTranscript.d.ts";
5
5
  export { capitalize } from "./capitalize.d.ts";
6
6
  export { clamp } from "./clamp.d.ts";
7
7
  export { clientAddressFromHeaders, clientPortFromHeaders, forwardedHeaders, normalizeIpAddress, } from "./clientAddress.d.ts";
8
- export { type CodeAgentApprovalPolicy, type CodeAgentBuiltinTool, type CodeAgentInteractionMode, type CodeAgentMcpServerRef, type CodeAgentPresetName, type CodeAgentProfile, type CodeAgentSubagentBudget, codeAgentDeniedPaths, codeAgentPresets, codeAgentReadOnlyBuiltins, isCodeAgentPresetName, } from "./codeAgentProfile.d.ts";
9
- export { type CodeAgentAnswer, type CodeAgentApprovalRequest, type CodeAgentCommand, type CodeAgentCommandType, type CodeAgentEffort, type CodeAgentEvent, type CodeAgentEventBody, type CodeAgentEventType, type CodeAgentFrame, type CodeAgentImage, type CodeAgentQuestion, type CodeAgentQuestionOption, type CodeAgentReply, type CodeAgentRequest, type CodeAgentSessionInfo, type CodeAgentStartOptions, type CodeAgentState, type CodeAgentStopReason, type CodeAgentToolOp, type CodeAgentToolOutcome, type CodeAgentToolSummary, codeAgentClip, codeAgentEventLabel, codeAgentEventPersistence, codeAgentLabelChars, codeAgentOutputChars, codeAgentRenderAnswer, codeAgentSessionName, codeAgentShouldPersist, codeAgentWireVersion, isCodeAgentReply, } from "./codeAgentWire.d.ts";
8
+ export { type CodeAgentApprovalPolicy, type CodeAgentBuiltinTool, type CodeAgentInteractionMode, type CodeAgentMcpServerRef, type CodeAgentMcpStatus, type CodeAgentPresetName, type CodeAgentProfile, type CodeAgentSubagentBudget, codeAgentDeniedPaths, codeAgentPresets, codeAgentReadOnlyBuiltins, isCodeAgentPresetName, } from "./codeAgentProfile.d.ts";
9
+ export { type CodeAgentAnswer, type CodeAgentApprovalRequest, type CodeAgentCommand, type CodeAgentCommandType, type CodeAgentEffort, type CodeAgentEvent, type CodeAgentEventBody, type CodeAgentEventType, type CodeAgentFrame, type CodeAgentImage, type CodeAgentQuestion, type CodeAgentQuestionOption, type CodeAgentReply, type CodeAgentRequest, type CodeAgentSessionInfo, type CodeAgentStartOptions, type CodeAgentState, type CodeAgentStopReason, type CodeAgentSubagent, type CodeAgentToolOp, type CodeAgentToolOutcome, type CodeAgentToolSummary, codeAgentClip, codeAgentEventLabel, codeAgentEventPersistence, codeAgentLabelChars, codeAgentOutputChars, codeAgentRenderAnswer, codeAgentSessionName, codeAgentShouldPersist, codeAgentWireVersion, isCodeAgentReply, } from "./codeAgentWire.d.ts";
10
10
  export { deepObjectify } from "./deepObjectify.d.ts";
11
11
  export type { DynamicRecord } from "./dynamicRecord.d.ts";
12
12
  export { EventStream, type EventStreamOptions } from "./eventStream.d.ts";