@markusylisiurunen/tau 0.3.44 → 0.3.46

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 (75) hide show
  1. package/README.md +4 -4
  2. package/dist/core/agent/agent_runtime.js +1 -1
  3. package/dist/core/agent/agent_runtime.js.map +1 -1
  4. package/dist/core/debug.js +2 -2
  5. package/dist/core/debug.js.map +1 -1
  6. package/dist/core/nook/client.js +11 -4
  7. package/dist/core/nook/client.js.map +1 -1
  8. package/dist/core/nook/setup.js +5 -2
  9. package/dist/core/nook/setup.js.map +1 -1
  10. package/dist/core/runtime/chat_runtime.js +10 -6
  11. package/dist/core/runtime/chat_runtime.js.map +1 -1
  12. package/dist/core/runtime/deps.js +0 -1
  13. package/dist/core/runtime/deps.js.map +1 -1
  14. package/dist/core/runtime/runtime_bootstrap.js +20 -3
  15. package/dist/core/runtime/runtime_bootstrap.js.map +1 -1
  16. package/dist/core/runtime/session_prompt_composer.js +6 -4
  17. package/dist/core/runtime/session_prompt_composer.js.map +1 -1
  18. package/dist/core/session/runner.js +4 -3
  19. package/dist/core/session/runner.js.map +1 -1
  20. package/dist/core/subagents/agent_supervisor.js +64 -31
  21. package/dist/core/subagents/agent_supervisor.js.map +1 -1
  22. package/dist/core/subagents/types.js +0 -1
  23. package/dist/core/subagents/types.js.map +1 -1
  24. package/dist/core/telegram/adapter.js +38 -14
  25. package/dist/core/telegram/adapter.js.map +1 -1
  26. package/dist/core/telegram/session_manager.js +404 -32
  27. package/dist/core/telegram/session_manager.js.map +1 -1
  28. package/dist/core/tools/web.js +5 -1
  29. package/dist/core/tools/web.js.map +1 -1
  30. package/dist/core/utils/context_builder.js +11 -9
  31. package/dist/core/utils/context_builder.js.map +1 -1
  32. package/dist/core/version.js +1 -1
  33. package/dist/host/execution_runtime.js +3 -2
  34. package/dist/host/execution_runtime.js.map +1 -1
  35. package/dist/host/hosted_ephemeral_agent_session.js +3 -2
  36. package/dist/host/hosted_ephemeral_agent_session.js.map +1 -1
  37. package/dist/host/local_session_host.js +90 -32
  38. package/dist/host/local_session_host.js.map +1 -1
  39. package/dist/host/session_host.js.map +1 -1
  40. package/dist/host/session_protocol_handler.js +29 -0
  41. package/dist/host/session_protocol_handler.js.map +1 -1
  42. package/dist/nook/README.md +3 -3
  43. package/dist/nook/worker/index.js +70 -1
  44. package/dist/nook/worker/index.js.map +1 -1
  45. package/dist/protocol/index.d.ts +2 -2
  46. package/dist/protocol/index.js +1 -1
  47. package/dist/protocol/index.js.map +1 -1
  48. package/dist/protocol/session_protocol.d.ts +66 -3
  49. package/dist/protocol/session_protocol.js +297 -1
  50. package/dist/protocol/session_protocol.js.map +1 -1
  51. package/dist/sdk/index.d.ts +4 -4
  52. package/dist/sdk/index.js +1 -1
  53. package/dist/sdk/index.js.map +1 -1
  54. package/dist/sdk/session.js +72 -1
  55. package/dist/sdk/session.js.map +1 -1
  56. package/dist/sdk/types.d.ts +7 -1
  57. package/dist/transport/in_process_session_transport.js +15 -1
  58. package/dist/transport/in_process_session_transport.js.map +1 -1
  59. package/dist/transport/index.d.ts +1 -1
  60. package/dist/transport/index.js.map +1 -1
  61. package/dist/transport/session_protocol_transport_helpers.js +14 -0
  62. package/dist/transport/session_protocol_transport_helpers.js.map +1 -1
  63. package/dist/transport/session_transport.d.ts +3 -1
  64. package/dist/transport/stdio_session_transport.d.ts +3 -1
  65. package/dist/transport/stdio_session_transport.js +15 -1
  66. package/dist/transport/stdio_session_transport.js.map +1 -1
  67. package/dist/transport/websocket_session_transport.d.ts +3 -1
  68. package/dist/transport/websocket_session_transport.js +15 -1
  69. package/dist/transport/websocket_session_transport.js.map +1 -1
  70. package/dist/tui/chat_view.js.map +1 -1
  71. package/dist/tui/session_chat_controller.js +40 -12
  72. package/dist/tui/session_chat_controller.js.map +1 -1
  73. package/dist/tui/ui/subagent_panel.js +25 -48
  74. package/dist/tui/ui/subagent_panel.js.map +1 -1
  75. package/package.json +1 -1
@@ -1,7 +1,14 @@
1
1
  import type { AssistantMessage, Message, TextContent, ThinkingContent, Tool, ToolCall } from "@earendil-works/pi-ai";
2
- export declare const SESSION_PROTOCOL_VERSION: 10;
2
+ export declare const SESSION_PROTOCOL_VERSION: 11;
3
3
  export declare const SESSION_PROTOCOL_MAX_EXEC_CAPTURE_BYTES: number;
4
4
  export declare const SESSION_PROTOCOL_MAX_EXEC_STDIN_BYTES: number;
5
+ export declare const SESSION_PROTOCOL_MAX_SUBAGENT_ACTIVITIES = 64;
6
+ export declare const SESSION_PROTOCOL_MAX_SUBAGENT_SHORT_TEXT_BYTES = 512;
7
+ export declare const SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_SUBJECT_BYTES: number;
8
+ export declare const SESSION_PROTOCOL_MAX_SUBAGENT_ASSISTANT_TEXT_BYTES: number;
9
+ export declare const SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_DETAILS_BYTES: number;
10
+ export declare const SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_METADATA_BYTES: number;
11
+ export declare const SESSION_PROTOCOL_MAX_SUBAGENT_NOTICE_CONTENT_BYTES: number;
5
12
  export declare const SESSION_PROTOCOL_METHODS: readonly ["initialize", "session.create", "session.list", "session.observe", "session.unobserve", "session.record", "session.submit", "session.queue", "session.steer", "session.cancelPendingMessages", "session.retry", "session.exec", "session.cancelExec", "session.sample", "session.interrupt", "session.snapshot", "session.startGoal", "session.resumeGoal", "session.clearGoal", "session.setReasoning", "session.setPersona", "session.resolvePrompt", "session.autocompletePaths", "session.reload", "session.compact", "session.rewind", "session.interruptSubagent", "session.ephemeral.create", "session.ephemeral.submit", "session.ephemeral.close", "session.clientTool.ack", "session.clientTool.result"];
6
13
  export type SessionProtocolMethod = (typeof SESSION_PROTOCOL_METHODS)[number];
7
14
  export declare const SESSION_PROTOCOL_ERROR_CODES: {
@@ -239,6 +246,47 @@ export type SessionProtocolPendingUserMessagesState = {
239
246
  revision: number;
240
247
  messages: SessionProtocolPendingUserMessage[];
241
248
  };
249
+ export type SessionProtocolSubagentActivity = {
250
+ type: "assistant";
251
+ text: string;
252
+ } | {
253
+ type: "tool";
254
+ toolName: string;
255
+ outcome: "succeeded" | "failed" | "blocked" | "cancelled";
256
+ presentation: {
257
+ action: string;
258
+ operation?: string;
259
+ subject: string;
260
+ subjectWrap: "word" | "character";
261
+ details: Array<{
262
+ text: string;
263
+ tone?: "added" | "removed";
264
+ wrap: "word" | "character";
265
+ }>;
266
+ metadata: string[];
267
+ };
268
+ } | {
269
+ type: "notice";
270
+ severity: "info" | "warn" | "error";
271
+ title: string;
272
+ content?: string[];
273
+ };
274
+ export type SessionProtocolSubagentActivitiesAgentState = {
275
+ runRevision: number;
276
+ activities: SessionProtocolSubagentActivity[];
277
+ };
278
+ export type SessionProtocolSubagentActivitiesState = {
279
+ revision: number;
280
+ agents: Record<string, SessionProtocolSubagentActivitiesAgentState>;
281
+ };
282
+ export type SessionProtocolSubagentActivitiesChange = {
283
+ type: "agent.set";
284
+ agentId: string;
285
+ state: SessionProtocolSubagentActivitiesAgentState;
286
+ } | {
287
+ type: "agent.remove";
288
+ agentId: string;
289
+ };
242
290
  export type SessionProtocolCreateResult = {
243
291
  sessionId: string;
244
292
  };
@@ -248,6 +296,7 @@ export type SessionProtocolClearGoalResult = SessionProtocolSnapshot;
248
296
  export type SessionProtocolObserveResult = {
249
297
  snapshot: SessionProtocolSnapshot;
250
298
  pendingUserMessages: SessionProtocolPendingUserMessagesState;
299
+ subagentActivities: SessionProtocolSubagentActivitiesState;
251
300
  };
252
301
  export type SessionProtocolCancelPendingMessagesResult = {
253
302
  cancelled: SessionProtocolPendingUserMessage[];
@@ -326,6 +375,7 @@ export type SessionProtocolTimelineNotice = {
326
375
  data: Record<string, unknown>;
327
376
  };
328
377
  export declare function projectSessionProtocolNoticePresentation(title: string, content?: readonly string[]): SessionProtocolTimelineNotice["presentation"];
378
+ export declare function projectSessionProtocolSubagentActivity(activity: SessionProtocolSubagentActivity): SessionProtocolSubagentActivity;
329
379
  export type SessionProtocolTimelineItem = {
330
380
  type: "message";
331
381
  id: string;
@@ -886,8 +936,15 @@ export type SessionProtocolPendingUserMessagesMessage = {
886
936
  sessionId: string;
887
937
  state: SessionProtocolPendingUserMessagesState;
888
938
  };
889
- export type SessionProtocolOutgoingMessage = SessionProtocolResponseMessage | SessionProtocolDeltaMessage | SessionProtocolEphemeralMessage | SessionProtocolPendingUserMessagesMessage | SessionProtocolClientToolMessage | SessionProtocolReadyMessage;
890
- export type SessionProtocolParsedOutgoingMessage = SessionProtocolParsedResponseMessage | SessionProtocolDeltaMessage | SessionProtocolEphemeralMessage | SessionProtocolPendingUserMessagesMessage | SessionProtocolClientToolMessage | SessionProtocolReadyMessage;
939
+ export type SessionProtocolSubagentActivitiesMessage = {
940
+ version: typeof SESSION_PROTOCOL_VERSION;
941
+ type: "session.subagentActivities";
942
+ sessionId: string;
943
+ revision: number;
944
+ changes: SessionProtocolSubagentActivitiesChange[];
945
+ };
946
+ export type SessionProtocolOutgoingMessage = SessionProtocolResponseMessage | SessionProtocolDeltaMessage | SessionProtocolEphemeralMessage | SessionProtocolPendingUserMessagesMessage | SessionProtocolSubagentActivitiesMessage | SessionProtocolClientToolMessage | SessionProtocolReadyMessage;
947
+ export type SessionProtocolParsedOutgoingMessage = SessionProtocolParsedResponseMessage | SessionProtocolDeltaMessage | SessionProtocolEphemeralMessage | SessionProtocolPendingUserMessagesMessage | SessionProtocolSubagentActivitiesMessage | SessionProtocolClientToolMessage | SessionProtocolReadyMessage;
891
948
  export type SessionProtocolOutgoingParseFailureReason = "invalid_payload" | "empty_line" | "parse_error" | "unsupported_version" | "unsupported_message_type" | "response_invalid_id";
892
949
  export type SessionProtocolOutgoingParseFailure = {
893
950
  ok: false;
@@ -944,6 +1001,12 @@ export declare function createSessionProtocolPendingUserMessagesMessage(options:
944
1001
  sessionId: string;
945
1002
  state: SessionProtocolPendingUserMessagesState;
946
1003
  }): SessionProtocolPendingUserMessagesMessage;
1004
+ export declare function applySessionProtocolSubagentActivitiesMessage(state: SessionProtocolSubagentActivitiesState, message: SessionProtocolSubagentActivitiesMessage): SessionProtocolSubagentActivitiesState;
1005
+ export declare function createSessionProtocolSubagentActivitiesMessage(options: {
1006
+ sessionId: string;
1007
+ revision: number;
1008
+ changes: SessionProtocolSubagentActivitiesChange[];
1009
+ }): SessionProtocolSubagentActivitiesMessage;
947
1010
  export declare function applySessionProtocolDelta(snapshot: SessionProtocolSnapshot, message: SessionProtocolDeltaMessage): SessionProtocolSnapshot;
948
1011
  export declare function createSessionProtocolReadyMessage(): SessionProtocolReadyMessage;
949
1012
  export declare function serializeSessionProtocolMessage(message: SessionProtocolOutgoingMessage): string;
@@ -1,10 +1,18 @@
1
1
  import { z } from "zod";
2
- export const SESSION_PROTOCOL_VERSION = 10;
2
+ export const SESSION_PROTOCOL_VERSION = 11;
3
3
  export const SESSION_PROTOCOL_MAX_EXEC_CAPTURE_BYTES = 24 * 1024 * 1024;
4
4
  export const SESSION_PROTOCOL_MAX_EXEC_STDIN_BYTES = 16 * 1024 * 1024;
5
+ export const SESSION_PROTOCOL_MAX_SUBAGENT_ACTIVITIES = 64;
6
+ export const SESSION_PROTOCOL_MAX_SUBAGENT_SHORT_TEXT_BYTES = 512;
7
+ export const SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_SUBJECT_BYTES = 4 * 1024;
8
+ export const SESSION_PROTOCOL_MAX_SUBAGENT_ASSISTANT_TEXT_BYTES = 32 * 1024;
9
+ export const SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_DETAILS_BYTES = 32 * 1024;
10
+ export const SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_METADATA_BYTES = 8 * 1024;
11
+ export const SESSION_PROTOCOL_MAX_SUBAGENT_NOTICE_CONTENT_BYTES = 32 * 1024;
5
12
  const SESSION_PROTOCOL_NOTICE_TITLE_MAX_CHARS = 512;
6
13
  const SESSION_PROTOCOL_NOTICE_CONTENT_MAX_ENTRIES = 16;
7
14
  const SESSION_PROTOCOL_NOTICE_CONTENT_ENTRY_MAX_CHARS = 4_096;
15
+ const UTF8_ENCODER = new TextEncoder();
8
16
  export const SESSION_PROTOCOL_METHODS = [
9
17
  "initialize",
10
18
  "session.create",
@@ -79,6 +87,149 @@ export function projectSessionProtocolNoticePresentation(title, content) {
79
87
  ...(projectedContent.length > 0 ? { content: projectedContent } : {}),
80
88
  };
81
89
  }
90
+ export function projectSessionProtocolSubagentActivity(activity) {
91
+ if (activity.type === "assistant") {
92
+ return {
93
+ type: "assistant",
94
+ text: truncateUtf8Middle(activity.text, SESSION_PROTOCOL_MAX_SUBAGENT_ASSISTANT_TEXT_BYTES),
95
+ };
96
+ }
97
+ if (activity.type === "notice") {
98
+ const content = activity.content
99
+ ? truncateSubagentTextValues(activity.content, SESSION_PROTOCOL_MAX_SUBAGENT_NOTICE_CONTENT_BYTES)
100
+ : [];
101
+ return {
102
+ type: "notice",
103
+ severity: activity.severity,
104
+ title: truncateUtf8Middle(activity.title, SESSION_PROTOCOL_MAX_SUBAGENT_SHORT_TEXT_BYTES),
105
+ ...(content.length > 0 ? { content } : {}),
106
+ };
107
+ }
108
+ const toolName = activity.toolName.replace(/\s+/g, " ").trim() || "(invalid tool name)";
109
+ return {
110
+ type: "tool",
111
+ toolName: truncateUtf8Middle(toolName, SESSION_PROTOCOL_MAX_SUBAGENT_SHORT_TEXT_BYTES),
112
+ outcome: activity.outcome,
113
+ presentation: {
114
+ action: truncateUtf8Middle(activity.presentation.action, SESSION_PROTOCOL_MAX_SUBAGENT_SHORT_TEXT_BYTES),
115
+ ...(activity.presentation.operation
116
+ ? {
117
+ operation: truncateUtf8Middle(activity.presentation.operation, SESSION_PROTOCOL_MAX_SUBAGENT_SHORT_TEXT_BYTES),
118
+ }
119
+ : {}),
120
+ subject: truncateUtf8Middle(activity.presentation.subject, SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_SUBJECT_BYTES),
121
+ subjectWrap: activity.presentation.subjectWrap,
122
+ details: truncateSubagentActivityDetails(activity.presentation.details),
123
+ metadata: truncateSubagentTextValues(activity.presentation.metadata, SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_METADATA_BYTES),
124
+ },
125
+ };
126
+ }
127
+ function truncateSubagentActivityDetails(details) {
128
+ return truncateSubagentTextEntries(details, SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_DETAILS_BYTES, (omitted) => ({
129
+ text: `…${omitted} more ${omitted === 1 ? "line" : "lines"}…`,
130
+ wrap: "word",
131
+ }));
132
+ }
133
+ function truncateSubagentTextValues(values, maxBytes) {
134
+ return truncateSubagentTextEntries(values.map((text) => ({ text })), maxBytes, (omitted) => ({
135
+ text: `…${omitted} more ${omitted === 1 ? "entry" : "entries"}…`,
136
+ })).map((entry) => entry.text);
137
+ }
138
+ function truncateSubagentTextEntries(entries, maxBytes, omission) {
139
+ const cloned = structuredClone(entries);
140
+ if (subagentTextEntriesBytes(cloned) <= maxBytes) {
141
+ return cloned;
142
+ }
143
+ const perEntryBytes = cloned.length === 1
144
+ ? maxBytes
145
+ : cloned.length === 2
146
+ ? Math.floor((maxBytes - 1) / 2)
147
+ : Math.floor((maxBytes - utf8ByteLength(omission(cloned.length - 2).text) - 2) / 2);
148
+ const bounded = cloned.map((entry) => ({
149
+ ...entry,
150
+ text: truncateUtf8Middle(entry.text, perEntryBytes),
151
+ }));
152
+ if (subagentTextEntriesBytes(bounded) <= maxBytes) {
153
+ return bounded;
154
+ }
155
+ const itemBytes = bounded.map((entry) => utf8ByteLength(entry.text));
156
+ let headCount = 0;
157
+ let tailCount = 0;
158
+ let headBytes = 0;
159
+ let tailBytes = 0;
160
+ while (headCount + tailCount < bounded.length) {
161
+ const nextKeptCount = headCount + tailCount + 1;
162
+ const omitted = bounded.length - nextKeptCount;
163
+ if (omitted === 0)
164
+ break;
165
+ const headItemBytes = itemBytes[headCount];
166
+ const tailItemBytes = itemBytes[bounded.length - tailCount - 1];
167
+ const headFits = subagentTextEntriesProjectionBytes(nextKeptCount, headBytes + headItemBytes + tailBytes, omission(omitted).text) <= maxBytes;
168
+ const tailFits = subagentTextEntriesProjectionBytes(nextKeptCount, headBytes + tailBytes + tailItemBytes, omission(omitted).text) <= maxBytes;
169
+ if (!headFits && !tailFits)
170
+ break;
171
+ const takeHead = headFits &&
172
+ (!tailFits ||
173
+ Math.abs(headBytes + headItemBytes - tailBytes) <=
174
+ Math.abs(headBytes - tailBytes - tailItemBytes));
175
+ if (takeHead) {
176
+ headCount += 1;
177
+ headBytes += headItemBytes;
178
+ }
179
+ else {
180
+ tailCount += 1;
181
+ tailBytes += tailItemBytes;
182
+ }
183
+ }
184
+ const omitted = bounded.length - headCount - tailCount;
185
+ return [
186
+ ...bounded.slice(0, headCount),
187
+ omission(omitted),
188
+ ...bounded.slice(bounded.length - tailCount),
189
+ ];
190
+ }
191
+ function subagentTextEntriesProjectionBytes(keptCount, keptBytes, omissionText) {
192
+ return keptBytes + utf8ByteLength(omissionText) + keptCount;
193
+ }
194
+ function subagentTextEntriesBytes(entries) {
195
+ if (entries.length === 0)
196
+ return 0;
197
+ return (entries.reduce((total, entry) => total + utf8ByteLength(entry.text), 0) + entries.length - 1);
198
+ }
199
+ function truncateUtf8Middle(value, maxBytes) {
200
+ if (utf8ByteLength(value) <= maxBytes)
201
+ return value;
202
+ const marker = "…";
203
+ const markerBytes = utf8ByteLength(marker);
204
+ const contentBytes = maxBytes - markerBytes;
205
+ const headBudget = Math.ceil(contentBytes / 2);
206
+ const tailBudget = contentBytes - headBudget;
207
+ const characters = Array.from(value);
208
+ let headCount = 0;
209
+ let headBytes = 0;
210
+ while (headCount < characters.length) {
211
+ const nextBytes = utf8ByteLength(characters[headCount]);
212
+ if (headBytes + nextBytes > headBudget)
213
+ break;
214
+ headBytes += nextBytes;
215
+ headCount += 1;
216
+ }
217
+ let tailCount = 0;
218
+ let tailBytes = 0;
219
+ while (tailCount < characters.length - headCount) {
220
+ const nextBytes = utf8ByteLength(characters[characters.length - tailCount - 1]);
221
+ if (tailBytes + nextBytes > tailBudget)
222
+ break;
223
+ tailBytes += nextBytes;
224
+ tailCount += 1;
225
+ }
226
+ return `${characters.slice(0, headCount).join("")}${marker}${characters
227
+ .slice(characters.length - tailCount)
228
+ .join("")}`;
229
+ }
230
+ function utf8ByteLength(value) {
231
+ return UTF8_ENCODER.encode(value).byteLength;
232
+ }
82
233
  function truncateNoticeText(value, maxChars) {
83
234
  if (value.length <= maxChars)
84
235
  return value;
@@ -314,6 +465,7 @@ const sessionProtocolOutgoingRoutingSchema = z
314
465
  "session.delta",
315
466
  "session.ephemeral",
316
467
  "session.pendingUserMessages",
468
+ "session.subagentActivities",
317
469
  "session.clientTool.call",
318
470
  "session.clientTool.cancel",
319
471
  "response",
@@ -1667,6 +1819,97 @@ const sessionProtocolPendingUserMessagesMessageSchema = z
1667
1819
  state: sessionProtocolPendingUserMessagesStateSchema,
1668
1820
  })
1669
1821
  .strip();
1822
+ const subagentActivityLineSchema = z
1823
+ .string()
1824
+ .refine((text) => !text.includes("\n") && !text.includes("\r"), "must be one line");
1825
+ const subagentActivityShortTextSchema = subagentActivityLineSchema
1826
+ .min(1)
1827
+ .refine((text) => text.trim().length > 0)
1828
+ .refine((text) => utf8ByteLength(text) <= SESSION_PROTOCOL_MAX_SUBAGENT_SHORT_TEXT_BYTES, `must not exceed ${SESSION_PROTOCOL_MAX_SUBAGENT_SHORT_TEXT_BYTES} UTF-8 bytes`);
1829
+ const subagentToolPresentationSchema = z
1830
+ .object({
1831
+ action: subagentActivityShortTextSchema,
1832
+ operation: subagentActivityShortTextSchema.optional(),
1833
+ subject: nonEmptyStringSchema.refine((subject) => utf8ByteLength(subject) <= SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_SUBJECT_BYTES, `must not exceed ${SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_SUBJECT_BYTES} UTF-8 bytes`),
1834
+ subjectWrap: z.enum(["word", "character"]),
1835
+ details: z
1836
+ .array(z
1837
+ .object({
1838
+ text: subagentActivityLineSchema,
1839
+ tone: z.enum(["added", "removed"]).optional(),
1840
+ wrap: z.enum(["word", "character"]),
1841
+ })
1842
+ .strip())
1843
+ .refine((details) => subagentTextEntriesBytes(details) <= SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_DETAILS_BYTES, `text must not exceed ${SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_DETAILS_BYTES} UTF-8 bytes`),
1844
+ metadata: z
1845
+ .array(subagentActivityLineSchema)
1846
+ .refine((metadata) => subagentTextEntriesBytes(metadata.map((text) => ({ text }))) <=
1847
+ SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_METADATA_BYTES, `text must not exceed ${SESSION_PROTOCOL_MAX_SUBAGENT_TOOL_METADATA_BYTES} UTF-8 bytes`),
1848
+ })
1849
+ .strip();
1850
+ const sessionProtocolSubagentActivitySchema = z.discriminatedUnion("type", [
1851
+ z
1852
+ .object({
1853
+ type: z.literal("assistant"),
1854
+ text: nonEmptyStringSchema.refine((text) => utf8ByteLength(text) <= SESSION_PROTOCOL_MAX_SUBAGENT_ASSISTANT_TEXT_BYTES, `must not exceed ${SESSION_PROTOCOL_MAX_SUBAGENT_ASSISTANT_TEXT_BYTES} UTF-8 bytes`),
1855
+ })
1856
+ .strip(),
1857
+ z
1858
+ .object({
1859
+ type: z.literal("tool"),
1860
+ toolName: subagentActivityShortTextSchema,
1861
+ outcome: z.enum(["succeeded", "failed", "blocked", "cancelled"]),
1862
+ presentation: subagentToolPresentationSchema,
1863
+ })
1864
+ .strip(),
1865
+ z
1866
+ .object({
1867
+ type: z.literal("notice"),
1868
+ severity: z.enum(["info", "warn", "error"]),
1869
+ title: subagentActivityShortTextSchema,
1870
+ content: z
1871
+ .array(z.string())
1872
+ .refine((content) => subagentTextEntriesBytes(content.map((text) => ({ text }))) <=
1873
+ SESSION_PROTOCOL_MAX_SUBAGENT_NOTICE_CONTENT_BYTES, `text must not exceed ${SESSION_PROTOCOL_MAX_SUBAGENT_NOTICE_CONTENT_BYTES} UTF-8 bytes`)
1874
+ .optional(),
1875
+ })
1876
+ .strip(),
1877
+ ]);
1878
+ const sessionProtocolSubagentActivitiesAgentStateSchema = z
1879
+ .object({
1880
+ runRevision: z.number().int().positive(),
1881
+ activities: z
1882
+ .array(sessionProtocolSubagentActivitySchema)
1883
+ .max(SESSION_PROTOCOL_MAX_SUBAGENT_ACTIVITIES),
1884
+ })
1885
+ .strip();
1886
+ const sessionProtocolSubagentActivitiesStateSchema = z
1887
+ .object({
1888
+ revision: z.number().int().positive(),
1889
+ agents: z.record(nonEmptyStringSchema, sessionProtocolSubagentActivitiesAgentStateSchema),
1890
+ })
1891
+ .strip();
1892
+ const sessionProtocolSubagentActivitiesChangeSchema = z.discriminatedUnion("type", [
1893
+ z
1894
+ .object({
1895
+ type: z.literal("agent.set"),
1896
+ agentId: nonEmptyStringSchema,
1897
+ state: sessionProtocolSubagentActivitiesAgentStateSchema,
1898
+ })
1899
+ .strip(),
1900
+ z.object({ type: z.literal("agent.remove"), agentId: nonEmptyStringSchema }).strip(),
1901
+ ]);
1902
+ const sessionProtocolSubagentActivitiesMessageSchema = z
1903
+ .object({
1904
+ version: z.literal(SESSION_PROTOCOL_VERSION),
1905
+ type: z.literal("session.subagentActivities"),
1906
+ sessionId: nonEmptyStringSchema,
1907
+ revision: z.number().int().positive(),
1908
+ changes: z
1909
+ .array(sessionProtocolSubagentActivitiesChangeSchema)
1910
+ .refine((changes) => new Set(changes.map((change) => change.agentId)).size === changes.length, "must not contain duplicate agent ids"),
1911
+ })
1912
+ .strip();
1670
1913
  const sessionProtocolInitializeResultSchema = z
1671
1914
  .object({
1672
1915
  protocolVersion: z.literal(SESSION_PROTOCOL_VERSION),
@@ -1683,6 +1926,7 @@ const sessionProtocolObserveResultSchema = z
1683
1926
  .object({
1684
1927
  snapshot: sessionProtocolSnapshotSchema,
1685
1928
  pendingUserMessages: sessionProtocolPendingUserMessagesStateSchema,
1929
+ subagentActivities: sessionProtocolSubagentActivitiesStateSchema,
1686
1930
  })
1687
1931
  .strip();
1688
1932
  const sessionProtocolListResultSchema = z
@@ -1904,6 +2148,35 @@ export function createSessionProtocolPendingUserMessagesMessage(options) {
1904
2148
  }
1905
2149
  return parsedMessage.data;
1906
2150
  }
2151
+ export function applySessionProtocolSubagentActivitiesMessage(state, message) {
2152
+ if (message.revision <= state.revision) {
2153
+ return structuredClone(state);
2154
+ }
2155
+ const agents = { ...state.agents };
2156
+ for (const change of message.changes) {
2157
+ if (change.type === "agent.set") {
2158
+ agents[change.agentId] = structuredClone(change.state);
2159
+ }
2160
+ else {
2161
+ delete agents[change.agentId];
2162
+ }
2163
+ }
2164
+ return { revision: message.revision, agents };
2165
+ }
2166
+ export function createSessionProtocolSubagentActivitiesMessage(options) {
2167
+ const message = {
2168
+ version: SESSION_PROTOCOL_VERSION,
2169
+ type: "session.subagentActivities",
2170
+ sessionId: options.sessionId,
2171
+ revision: options.revision,
2172
+ changes: options.changes,
2173
+ };
2174
+ const parsedMessage = sessionProtocolSubagentActivitiesMessageSchema.safeParse(message);
2175
+ if (!parsedMessage.success) {
2176
+ throw new Error(`session protocol subagent activities message is invalid: ${formatZodError(parsedMessage.error)}`);
2177
+ }
2178
+ return parsedMessage.data;
2179
+ }
1907
2180
  function validateSnapshotResetCause(snapshot, message) {
1908
2181
  if (message.delta.type !== "snapshot.reset") {
1909
2182
  return;
@@ -2445,6 +2718,9 @@ export function parseSessionProtocolOutgoingLine(line) {
2445
2718
  if (routing.data.type === "session.pendingUserMessages") {
2446
2719
  return parseSessionProtocolPendingUserMessagesMessage(parsed);
2447
2720
  }
2721
+ if (routing.data.type === "session.subagentActivities") {
2722
+ return parseSessionProtocolSubagentActivitiesMessage(parsed);
2723
+ }
2448
2724
  if (routing.data.type === "session.clientTool.call" ||
2449
2725
  routing.data.type === "session.clientTool.cancel") {
2450
2726
  return parseSessionProtocolClientToolMessage(parsed);
@@ -3133,6 +3409,26 @@ function parseSessionProtocolPendingUserMessagesMessage(payload) {
3133
3409
  message: message.data,
3134
3410
  };
3135
3411
  }
3412
+ function parseSessionProtocolSubagentActivitiesMessage(payload) {
3413
+ const fail = (message) => outgoingParseFailure("session.subagentActivities", null, SESSION_PROTOCOL_ERROR_CODES.invalidRequest, message);
3414
+ const message = sessionProtocolSubagentActivitiesMessageSchema.safeParse(payload);
3415
+ if (!message.success) {
3416
+ if (hasIssue(message.error, ["sessionId"])) {
3417
+ return fail("session.subagentActivities.sessionId must be a non-empty string");
3418
+ }
3419
+ if (hasIssue(message.error, ["revision"])) {
3420
+ return fail("session.subagentActivities.revision is invalid");
3421
+ }
3422
+ if (hasIssue(message.error, ["changes"])) {
3423
+ return fail("session.subagentActivities.changes are invalid");
3424
+ }
3425
+ return fail(`invalid session.subagentActivities message: ${formatZodError(message.error)}`);
3426
+ }
3427
+ return {
3428
+ ok: true,
3429
+ message: message.data,
3430
+ };
3431
+ }
3136
3432
  function parseSessionProtocolResponseMessage(payload) {
3137
3433
  const parsedIdField = sessionProtocolIdFieldSchema.safeParse(payload);
3138
3434
  const responseId = parseNullableRequestId(parsedIdField.success ? parsedIdField.data.id : undefined);