@myagentroam/agent 0.11.39 → 0.11.41

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 (166) hide show
  1. package/dist/cli/catalog-file.d.ts +2 -0
  2. package/dist/cli/main.js +11 -4
  3. package/dist/cli/subagent/control.d.ts +56 -0
  4. package/dist/cli/subagent/control.js +219 -0
  5. package/dist/cli/subagent/history.d.ts +17 -0
  6. package/dist/cli/subagent/history.js +85 -0
  7. package/dist/cli/subagent/index.d.ts +10 -0
  8. package/dist/cli/subagent/index.js +94 -0
  9. package/dist/cli/subagent/native.d.ts +91 -0
  10. package/dist/cli/subagent/native.js +359 -0
  11. package/dist/cli/subagent/observations.d.ts +57 -0
  12. package/dist/cli/subagent/observations.js +351 -0
  13. package/dist/cli/subagent/query.d.ts +4 -0
  14. package/dist/cli/subagent/query.js +114 -0
  15. package/dist/cli/subagent/resources.d.ts +3 -0
  16. package/dist/cli/subagent/resources.js +112 -0
  17. package/dist/cli/subagent/snapshot.d.ts +77 -0
  18. package/dist/cli/subagent/snapshot.js +127 -0
  19. package/dist/cli/subagent/start.d.ts +24 -0
  20. package/dist/cli/subagent/start.js +201 -0
  21. package/dist/cli/subagent/wait-output.d.ts +19 -0
  22. package/dist/cli/subagent/wait-output.js +56 -0
  23. package/dist/cli/subagent/wait.d.ts +175 -0
  24. package/dist/cli/subagent/wait.js +453 -0
  25. package/dist/extensions/contracts.d.ts +2 -5
  26. package/dist/extensions/manager.d.ts +0 -2
  27. package/dist/extensions/manager.js +1 -2
  28. package/dist/extensions/models.d.ts +3 -0
  29. package/dist/extensions/operation.d.ts +8 -0
  30. package/dist/extensions/operation.js +3 -0
  31. package/dist/extensions/services.d.ts +9 -1
  32. package/dist/extensions/services.js +26 -3
  33. package/dist/extensions/session-context.d.ts +18 -0
  34. package/dist/extensions/session-context.js +4 -0
  35. package/dist/extensions/session-input.d.ts +2 -2
  36. package/dist/extensions/session-input.js +3 -4
  37. package/dist/extensions/session-messages.d.ts +1 -1
  38. package/dist/extensions/session-tools.js +20 -3
  39. package/dist/extensions/session.d.ts +1 -4
  40. package/dist/extensions/session.js +2 -16
  41. package/dist/extensions/tools.js +21 -3
  42. package/dist/extensions.d.ts +5 -2
  43. package/dist/extensions.js +2 -1
  44. package/dist/host/local-agent-host.d.ts +2 -2
  45. package/dist/host/local-exec-tool.d.ts +1 -1
  46. package/dist/host/local-exec-tool.js +28 -3
  47. package/dist/host/local-tool-registry.d.ts +2 -2
  48. package/dist/index.d.ts +2 -2
  49. package/dist/model/configuration.d.ts +3 -1
  50. package/dist/model/configuration.js +1 -0
  51. package/dist/model/openai-responses.js +5 -0
  52. package/dist/model/responses-request.js +9 -0
  53. package/dist/prompts/index.js +1 -3
  54. package/dist/prompts/permissions.d.ts +1 -1
  55. package/dist/prompts/permissions.js +1 -0
  56. package/dist/prompts/resources.d.ts +1 -5
  57. package/dist/prompts/resources.js +3 -12
  58. package/dist/prompts/subagent.d.ts +1 -1
  59. package/dist/prompts/subagent.js +1 -1
  60. package/dist/runtime/context/gc-candidates-web.d.ts +6 -0
  61. package/dist/runtime/context/gc-candidates-web.js +53 -1
  62. package/dist/runtime/context/gc-candidates.js +1 -9
  63. package/dist/runtime/context/gc.js +19 -11
  64. package/dist/runtime/context/projection.js +1 -0
  65. package/dist/runtime/events.d.ts +4 -3
  66. package/dist/runtime/execution-handle.d.ts +2 -0
  67. package/dist/runtime/wait.js +12 -2
  68. package/dist/sdk/agent.js +94 -5
  69. package/dist/sdk/execution-context-coordinator.d.ts +2 -3
  70. package/dist/sdk/execution-context-coordinator.js +3 -3
  71. package/dist/sdk/execution-input.d.ts +3 -4
  72. package/dist/sdk/execution-input.js +31 -25
  73. package/dist/sdk/execution-round-preparation.d.ts +1 -1
  74. package/dist/sdk/execution-round-preparation.js +4 -4
  75. package/dist/sdk/execution-tool-catalog.js +2 -10
  76. package/dist/sdk/execution-tool-scope.d.ts +1 -3
  77. package/dist/sdk/execution-tool-scope.js +10 -12
  78. package/dist/sdk/extension-models.js +3 -0
  79. package/dist/sdk/extension-session-launch.d.ts +3 -2
  80. package/dist/sdk/extension-session-launch.js +2 -3
  81. package/dist/sdk/extension-tools.js +0 -2
  82. package/dist/sdk/native-steer.d.ts +2 -2
  83. package/dist/sdk/native-steer.js +2 -2
  84. package/dist/sdk/session-composition.d.ts +2 -17
  85. package/dist/sdk/session-execution-factory.d.ts +2 -3
  86. package/dist/sdk/session-execution-factory.js +20 -114
  87. package/dist/sdk/session-execution.d.ts +13 -7
  88. package/dist/sdk/session-execution.js +11 -3
  89. package/dist/sdk/session-extension-messages.d.ts +1 -3
  90. package/dist/sdk/session-extension-messages.js +14 -9
  91. package/dist/sdk/session-extension-prompt.js +1 -3
  92. package/dist/sdk/session-maintenance.d.ts +1 -0
  93. package/dist/sdk/session-maintenance.js +16 -7
  94. package/dist/sdk/session-open.d.ts +2 -3
  95. package/dist/sdk/session-open.js +5 -24
  96. package/dist/sdk/session-runtime.d.ts +19 -8
  97. package/dist/sdk/session-runtime.js +36 -30
  98. package/dist/sdk/session.d.ts +3 -2
  99. package/dist/sdk/session.js +22 -89
  100. package/dist/sdk/types.d.ts +36 -0
  101. package/dist/session/catalog.d.ts +22 -1
  102. package/dist/session/catalog.js +102 -0
  103. package/dist/session/context-gc-checkpoint.js +30 -1
  104. package/dist/session/context-gc-contract.d.ts +7 -0
  105. package/dist/session/context-gc-replacements.d.ts +3 -0
  106. package/dist/session/context-gc-replacements.js +26 -0
  107. package/dist/session/store/contracts.d.ts +2 -2
  108. package/dist/session/store/jsonl/directory-index.d.ts +1 -1
  109. package/dist/session/store/jsonl/directory-index.js +18 -17
  110. package/dist/session/store/jsonl/history.js +1 -1
  111. package/dist/session/store/jsonl/index-transaction.js +2 -8
  112. package/dist/session/store/jsonl/jsonl-store.d.ts +1 -1
  113. package/dist/session/store/jsonl/jsonl-store.js +24 -9
  114. package/dist/session/store/jsonl/resources.js +5 -1
  115. package/dist/session/types.d.ts +1 -0
  116. package/dist/tools/agent/sleep.js +1 -1
  117. package/dist/tools/callers.js +1 -12
  118. package/dist/tools/code-mode/dispatch.js +5 -2
  119. package/dist/tools/code-mode/index.d.ts +1 -1
  120. package/dist/tools/code-mode/index.js +4 -2
  121. package/dist/tools/contracts.d.ts +20 -0
  122. package/dist/tools/execution-limits.d.ts +5 -20
  123. package/dist/tools/execution-limits.js +0 -2
  124. package/dist/tools/execution.js +16 -4
  125. package/dist/tools/local/exec.js +8 -2
  126. package/dist/tools/output-projection.d.ts +5 -2
  127. package/dist/tools/output-projection.js +133 -92
  128. package/dist/tools/permissions.d.ts +0 -1
  129. package/dist/tools/permissions.js +1 -9
  130. package/dist/tools/registry.js +1 -13
  131. package/dist/tools/runtime-context.d.ts +1 -21
  132. package/package.json +2 -2
  133. package/dist/extensions/agents.d.ts +0 -100
  134. package/dist/extensions/agents.js +0 -121
  135. package/dist/runtime/context/gc-candidates-subagent.d.ts +0 -6
  136. package/dist/runtime/context/gc-candidates-subagent.js +0 -100
  137. package/dist/sdk/extension-agent-controller.d.ts +0 -3
  138. package/dist/sdk/extension-agent-controller.js +0 -69
  139. package/dist/sdk/extension-agents.d.ts +0 -9
  140. package/dist/sdk/extension-agents.js +0 -58
  141. package/dist/sdk/subagent-backend.d.ts +0 -3
  142. package/dist/sdk/subagent-backend.js +0 -49
  143. package/dist/subagent/contracts.d.ts +0 -107
  144. package/dist/subagent/contracts.js +0 -1
  145. package/dist/subagent/limits.d.ts +0 -17
  146. package/dist/subagent/limits.js +0 -17
  147. package/dist/subagent/model-update.d.ts +0 -2
  148. package/dist/subagent/model-update.js +0 -81
  149. package/dist/subagent/session-controller.d.ts +0 -87
  150. package/dist/subagent/session-controller.js +0 -1343
  151. package/dist/subagent/task.d.ts +0 -134
  152. package/dist/subagent/task.js +0 -436
  153. package/dist/subagent/turn-contracts.d.ts +0 -64
  154. package/dist/subagent/turn-contracts.js +0 -1
  155. package/dist/subagent/wait-targets.d.ts +0 -10
  156. package/dist/subagent/wait-targets.js +0 -26
  157. package/dist/subagent/wait.d.ts +0 -26
  158. package/dist/subagent/wait.js +0 -73
  159. package/dist/tools/agent/agent-cancel.d.ts +0 -7
  160. package/dist/tools/agent/agent-cancel.js +0 -29
  161. package/dist/tools/agent/agent-message.d.ts +0 -7
  162. package/dist/tools/agent/agent-message.js +0 -57
  163. package/dist/tools/agent/agent-start.d.ts +0 -12
  164. package/dist/tools/agent/agent-start.js +0 -106
  165. package/dist/tools/agent/agent-wait.d.ts +0 -7
  166. package/dist/tools/agent/agent-wait.js +0 -91
@@ -4,6 +4,21 @@ import { AGENT_EXECUTION_POLICY } from '../runtime/execution-policy.js';
4
4
  import { countModelTokens, countTextLines, truncateModelText } from '../runtime/token-budget.js';
5
5
  import { TOOL_EXECUTION_LIMITS } from './execution-limits.js';
6
6
  import { publicToolMetadata } from '../runtime/public-tool-metadata.js';
7
+ /** Copy an explicitly public JSON object without exposing the full tool result. */
8
+ export function publicExtensionToolEventData(value) {
9
+ if (!isRecord(value))
10
+ return undefined;
11
+ try {
12
+ const json = JSON.stringify(value);
13
+ if (Buffer.byteLength(json, 'utf8') > 8192)
14
+ return undefined;
15
+ const copy = JSON.parse(json);
16
+ return isRecord(copy) ? copy : undefined;
17
+ }
18
+ catch {
19
+ return undefined;
20
+ }
21
+ }
7
22
  export function currentExecutionImages(modelInputImages, toolImages) {
8
23
  return [
9
24
  ...(modelInputImages ?? [])
@@ -34,6 +49,105 @@ export function boundedModelToolOutput(toolName, value, data) {
34
49
  const result = truncateModelText(value, AGENT_EXECUTION_POLICY.modelToolOutputTokens, 'tool output', execDiagnostics);
35
50
  return { content: result.content, truncated: result.truncated };
36
51
  }
52
+ /** The opted-in allowlist fails closed and never mutates the invocation arguments. */
53
+ export function publicToolEventInput(value, fields) {
54
+ try {
55
+ if (!isRecord(value))
56
+ return {};
57
+ const projected = Object.fromEntries(fields
58
+ .filter((key) => Object.hasOwn(value, key) &&
59
+ (typeof value[key] === 'string' ||
60
+ typeof value[key] === 'boolean' ||
61
+ (typeof value[key] === 'number' && Number.isFinite(value[key])) ||
62
+ value[key] === null))
63
+ .map((key) => [key, value[key]]));
64
+ return publicExtensionToolEventData(projected) ?? {};
65
+ }
66
+ catch {
67
+ return {};
68
+ }
69
+ }
70
+ /** Explicit observations are public, but their event projection must remain bounded. */
71
+ function publicCodeObservations(values, data) {
72
+ if (!Array.isArray(values))
73
+ return data;
74
+ const retained = new Set(data.observations ?? []);
75
+ const selected = [];
76
+ let displayedCount = 0;
77
+ let remaining = 10_000;
78
+ let truncated = false;
79
+ const clip = (text) => {
80
+ let start = Math.max(0, text.length - remaining);
81
+ if (start > 0 && /[\uDC00-\uDFFF]/u.test(text[start]))
82
+ start++;
83
+ const result = text.slice(start);
84
+ remaining -= result.length;
85
+ truncated ||= start > 0;
86
+ return result;
87
+ };
88
+ for (let index = values.length - 1; index >= 0; index--) {
89
+ const entry = values[index];
90
+ if (!isRecord(entry))
91
+ continue;
92
+ if (entry.type === 'value' &&
93
+ typeof entry.value === 'string' &&
94
+ typeof entry.id === 'string' &&
95
+ (entry.format === 'text' || entry.format === 'json' || entry.format === 'image')) {
96
+ if (displayedCount >= 32) {
97
+ truncated = true;
98
+ continue;
99
+ }
100
+ displayedCount++;
101
+ truncated ||= entry.truncated === true;
102
+ const value = clip(entry.value);
103
+ selected.unshift({
104
+ type: 'value',
105
+ id: entry.id,
106
+ format: entry.format,
107
+ value,
108
+ ...(entry.truncated === true || value.length < entry.value.length
109
+ ? { truncated: true }
110
+ : {})
111
+ });
112
+ }
113
+ else if (entry.type === 'tool_result' && isRecord(entry.source) && isRecord(entry.result)) {
114
+ const name = entry.source.toolName;
115
+ if (name !== 'exec' && name !== 'exec_wait') {
116
+ if (retained.has(entry))
117
+ selected.unshift(entry);
118
+ }
119
+ else if ((name === 'exec' || name === 'exec_wait') &&
120
+ typeof entry.id === 'string' &&
121
+ typeof entry.source.callId === 'string' &&
122
+ (entry.outcome === 'completed' || entry.outcome === 'failed')) {
123
+ if (displayedCount >= 32) {
124
+ truncated = true;
125
+ continue;
126
+ }
127
+ displayedCount++;
128
+ truncated ||= entry.result.truncated === true;
129
+ const data = isRecord(entry.result.data) ? entry.result.data : undefined;
130
+ const stderr = typeof data?.stderr === 'string' ? clip(data.stderr) : undefined;
131
+ const stdout = typeof data?.stdout === 'string' ? clip(data.stdout) : undefined;
132
+ const content = stdout === undefined && stderr === undefined && typeof entry.result.content === 'string'
133
+ ? clip(entry.result.content)
134
+ : '';
135
+ selected.unshift({
136
+ type: 'tool_result',
137
+ id: entry.id,
138
+ source: { callId: entry.source.callId, toolName: name, input: null },
139
+ outcome: entry.outcome,
140
+ result: {
141
+ content,
142
+ ...(stdout === undefined && stderr === undefined ? {} : { data: { stdout, stderr } }),
143
+ ...(entry.result.truncated === true || truncated ? { truncated: true } : {})
144
+ }
145
+ });
146
+ }
147
+ }
148
+ }
149
+ return { ...data, observations: selected, ...(truncated ? { truncated: true } : {}) };
150
+ }
37
151
  /** Project only known, validated tool result shapes into public structured events. */
38
152
  export function structuredToolEventData(toolName, value) {
39
153
  if (!isRecord(value))
@@ -57,22 +171,10 @@ export function structuredToolEventData(toolName, value) {
57
171
  elapsedMs: value.elapsedMs,
58
172
  wakeReason: value.wakeReason
59
173
  };
60
- if (toolName === 'agent_wait' &&
61
- (value.mode === 'any' || value.mode === 'all') &&
62
- (value.waitFor === 'completion' || value.waitFor === 'message') &&
63
- ['snapshot', 'message', 'completion', 'timeout', 'interrupted'].includes(String(value.waitOutcome)) &&
64
- Array.isArray(value.agents) &&
65
- value.agents.length > 0 &&
66
- value.agents.length <= TOOL_EXECUTION_LIMITS.agentWaitMaxAgents &&
67
- value.agents.every((agent) => isRecord(agent) && isSubagentTaskSnapshot(agent)) &&
68
- Array.isArray(value.pendingAgentIds) &&
69
- value.pendingAgentIds.every((id) => typeof id === 'string' &&
70
- value.agents.some((agent) => agent.agentId === id)))
71
- return value;
72
174
  if ((toolName === 'code_exec' || toolName === 'code_exec_wait') &&
73
175
  typeof value.cellId === 'string' &&
74
176
  ['running', 'completed', 'failed', 'cancelled'].includes(String(value.status)))
75
- return {
177
+ return publicCodeObservations(value.observations, {
76
178
  cellId: value.cellId,
77
179
  status: value.status,
78
180
  cached: value.cached === true,
@@ -82,6 +184,21 @@ export function structuredToolEventData(toolName, value) {
82
184
  ...(value.waitOutcome === 'interrupted' && value.reason === 'steer'
83
185
  ? { reason: 'steer' }
84
186
  : {}),
187
+ ...(value.truncated === true ? { truncated: true } : {}),
188
+ ...(isRecord(value.error) &&
189
+ typeof value.error.code === 'string' &&
190
+ value.error.code.length > 0 &&
191
+ typeof value.error.message === 'string'
192
+ ? {
193
+ ...(value.error.code.length > 80 || value.error.message.length > 1000
194
+ ? { truncated: true }
195
+ : {}),
196
+ error: {
197
+ code: value.error.code.slice(0, 80).replace(/[\uD800-\uDBFF]$/u, ''),
198
+ message: value.error.message.slice(0, 1000).replace(/[\uD800-\uDBFF]$/u, '')
199
+ }
200
+ }
201
+ : {}),
85
202
  ...(isRecord(value.permissionStop)
86
203
  ? {
87
204
  permissionStop: value.permissionStop
@@ -90,15 +207,7 @@ export function structuredToolEventData(toolName, value) {
90
207
  ...(Array.isArray(value.calls)
91
208
  ? {
92
209
  calls: value.calls.filter((entry) => isRecord(entry) &&
93
- [
94
- 'apply_patch',
95
- 'todo_read',
96
- 'todo_write',
97
- 'agent_start',
98
- 'agent_wait',
99
- 'agent_message',
100
- 'agent_cancel'
101
- ].includes(String(entry.toolName)))
210
+ ['apply_patch', 'todo_read', 'todo_write'].includes(String(entry.toolName)))
102
211
  }
103
212
  : {}),
104
213
  ...(Array.isArray(value.observations)
@@ -106,24 +215,10 @@ export function structuredToolEventData(toolName, value) {
106
215
  observations: value.observations.filter((entry) => isRecord(entry) &&
107
216
  entry.type === 'tool_result' &&
108
217
  isRecord(entry.source) &&
109
- [
110
- 'apply_patch',
111
- 'todo_read',
112
- 'todo_write',
113
- 'agent_start',
114
- 'agent_wait',
115
- 'agent_message',
116
- 'agent_cancel'
117
- ].includes(String(entry.source.toolName)))
218
+ ['apply_patch', 'todo_read', 'todo_write'].includes(String(entry.source.toolName)))
118
219
  }
119
220
  : {})
120
- };
121
- if ((toolName === 'agent_start' ||
122
- toolName === 'agent_wait' ||
123
- toolName === 'agent_message' ||
124
- toolName === 'agent_cancel') &&
125
- isSubagentTaskSnapshot(value))
126
- return value;
221
+ });
127
222
  if (toolName === 'read' &&
128
223
  value.mode === 'batch' &&
129
224
  Array.isArray(value.results) &&
@@ -282,60 +377,6 @@ export function validateToolResult(value) {
282
377
  function isRecord(value) {
283
378
  return value !== null && typeof value === 'object' && !Array.isArray(value);
284
379
  }
285
- function isSubagentTaskSnapshot(value) {
286
- return (typeof value.agentId === 'string' &&
287
- value.agentId.length > 0 &&
288
- value.agentId.length <= 128 &&
289
- typeof value.description === 'string' &&
290
- value.description.length > 0 &&
291
- value.description.length <= TOOL_EXECUTION_LIMITS.subagentDescriptionMaxCharacters &&
292
- (value.status === 'queued' ||
293
- value.status === 'running' ||
294
- value.status === 'completed' ||
295
- value.status === 'failed' ||
296
- value.status === 'cancelled' ||
297
- value.status === 'interrupted') &&
298
- (value.modelId === undefined || typeof value.modelId === 'string') &&
299
- (value.modelName === undefined || typeof value.modelName === 'string') &&
300
- (value.reasoningEffort === undefined ||
301
- (typeof value.reasoningEffort === 'string' &&
302
- ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'].includes(value.reasoningEffort))) &&
303
- (value.waitOutcome === undefined ||
304
- value.waitOutcome === 'snapshot' ||
305
- value.waitOutcome === 'message' ||
306
- value.waitOutcome === 'completion' ||
307
- value.waitOutcome === 'timeout' ||
308
- value.waitOutcome === 'interrupted') &&
309
- (value.latestMessage === undefined ||
310
- (isRecord(value.latestMessage) &&
311
- typeof value.latestMessage.itemId === 'string' &&
312
- typeof value.latestMessage.turnId === 'string' &&
313
- (value.latestMessage.phase === 'commentary' ||
314
- value.latestMessage.phase === 'final_answer') &&
315
- typeof value.latestMessage.text === 'string' &&
316
- typeof value.latestMessage.timestamp === 'string' &&
317
- typeof value.latestMessage.truncated === 'boolean')) &&
318
- (value.summary === undefined || typeof value.summary === 'string') &&
319
- (value.changedFiles === undefined ||
320
- (Array.isArray(value.changedFiles) &&
321
- value.changedFiles.every((path) => typeof path === 'string'))) &&
322
- (value.verification === undefined ||
323
- (Array.isArray(value.verification) &&
324
- value.verification.every((item) => typeof item === 'string'))) &&
325
- (value.evidence === undefined ||
326
- (Array.isArray(value.evidence) &&
327
- value.evidence.every((item) => isRecord(item) &&
328
- typeof item.path === 'string' &&
329
- (item.startLine === undefined ||
330
- (typeof item.startLine === 'number' &&
331
- Number.isInteger(item.startLine) &&
332
- item.startLine >= 1)) &&
333
- (item.endLine === undefined ||
334
- (typeof item.endLine === 'number' &&
335
- Number.isInteger(item.endLine) &&
336
- item.endLine >= 1))))) &&
337
- (value.errorCode === undefined || typeof value.errorCode === 'string'));
338
- }
339
380
  function isNonnegativeInteger(value) {
340
381
  return typeof value === 'number' && Number.isInteger(value) && value >= 0;
341
382
  }
@@ -19,7 +19,6 @@ export declare const permissionSchema: {
19
19
  };
20
20
  reason: {
21
21
  type: string;
22
- description: string;
23
22
  };
24
23
  };
25
24
  required: string[];
@@ -17,10 +17,7 @@ export const permissionSchema = {
17
17
  type: 'object',
18
18
  properties: {
19
19
  action: { type: 'string', enum: ['allow', 'ask', 'deny'] },
20
- reason: {
21
- type: 'string',
22
- description: 'Brief public reason, required for ask/deny; never include secrets.'
23
- }
20
+ reason: { type: 'string' }
24
21
  },
25
22
  required: ['action'],
26
23
  additionalProperties: false
@@ -49,11 +46,6 @@ export function projectPermissionTool(tool) {
49
46
  ...tool,
50
47
  inputMode: 'json',
51
48
  ...(parameterless ? { parameterless: true } : {}),
52
- description: tool.description +
53
- '\nAuto mode: use the declared JSON input. Omit permission (or set null) for routine or already authorized work. Use {action:"ask"|"deny",reason:"brief public reason"} only when required. ' +
54
- (flat
55
- ? 'Permission is metadata, not a business argument.'
56
- : 'Place the unchanged business arguments in input; permission is separate metadata.'),
57
49
  inputSchema: flat
58
50
  ? {
59
51
  ...tool.inputSchema,
@@ -1,7 +1,3 @@
1
- import { agentCancelToolDefinition, executeAgentCancel } from './agent/agent-cancel.js';
2
- import { agentMessageToolDefinition, executeAgentMessage } from './agent/agent-message.js';
3
- import { agentStartToolDefinition, executeAgentStart } from './agent/agent-start.js';
4
- import { agentWaitToolDefinition, executeAgentWait } from './agent/agent-wait.js';
5
1
  import { applyPatchToolDefinition } from './local/apply-patch.js';
6
2
  import { codeExecWaitToolDefinition, codeModeToolDefinition } from './code-mode/index.js';
7
3
  import { execToolDefinition, execWaitToolDefinition } from './local/exec.js';
@@ -27,10 +23,6 @@ export const BUILTIN_TOOL_DEFINITIONS = [
27
23
  questionToolDefinition,
28
24
  todoReadToolDefinition,
29
25
  todoWriteToolDefinition,
30
- agentStartToolDefinition,
31
- agentWaitToolDefinition,
32
- agentMessageToolDefinition,
33
- agentCancelToolDefinition,
34
26
  smartCompactToolDefinition,
35
27
  sleepToolDefinition
36
28
  ];
@@ -41,9 +33,5 @@ export const AGENT_TOOL_HANDLERS = new Map([
41
33
  ['tool_search', executeToolSearch],
42
34
  ['question', executeQuestion],
43
35
  ['todo_read', (_arguments, context) => executeTodoRead(context)],
44
- ['todo_write', executeTodoWrite],
45
- ['agent_start', executeAgentStart],
46
- ['agent_wait', executeAgentWait],
47
- ['agent_message', executeAgentMessage],
48
- ['agent_cancel', executeAgentCancel]
36
+ ['todo_write', executeTodoWrite]
49
37
  ]);
@@ -1,7 +1,6 @@
1
1
  import type { ResourcePublisher, ResourceStore } from '../runtime/resource-publication.js';
2
2
  import type { ExecutionMode } from '../runtime/contracts.js';
3
3
  import type { AgentSkill } from '../runtime/context/instructions.js';
4
- import type { SubagentController, SubagentLatestMessage } from '../subagent/contracts.js';
5
4
  import type { TodoStore } from './agent/todo.js';
6
5
  import type { McpToolCallContext, ToolCall, ToolExecutionContext, ToolExecutionResult } from './contracts.js';
7
6
  export interface ToolHost extends ResourcePublisher {
@@ -40,24 +39,6 @@ export type ToolRuntimeEvent = {
40
39
  } | {
41
40
  type: 'user_input.resolved';
42
41
  requestId: string;
43
- } | {
44
- type: 'subagent.started';
45
- agentId: string;
46
- description: string;
47
- modelId?: string;
48
- modelName?: string;
49
- reasoningEffort?: import('../model/configuration.js').AgentReasoningEffort;
50
- } | {
51
- type: 'subagent.completed';
52
- agentId: string;
53
- description: string;
54
- status: string;
55
- modelId?: string;
56
- modelName?: string;
57
- reasoningEffort?: import('../model/configuration.js').AgentReasoningEffort;
58
- latestMessage?: SubagentLatestMessage;
59
- errorCode?: string;
60
- errorMessage?: string;
61
42
  };
62
43
  export interface ToolRuntimeImage {
63
44
  readonly mimeType: string;
@@ -68,14 +49,13 @@ export interface ToolRuntimeContext {
68
49
  imageStore?: ToolImageStore;
69
50
  todo: TodoStore;
70
51
  requestSmartCompact?: () => void;
71
- subagents?: SubagentController;
72
52
  mode: ExecutionMode;
73
53
  sessionId: string;
74
54
  executionId: string;
75
55
  modelId?: string;
76
56
  signal: AbortSignal;
77
57
  waitInterrupt?: import('./wait.js').ToolWaitInterrupt | undefined;
78
- subagentMessages?: import('./wait.js').ToolWaitInterrupt;
58
+ contextUpdates?: import('./wait.js').ToolWaitInterrupt;
79
59
  permissionPolicy?: import('./permissions.js').ExecutionToolPermissions;
80
60
  parentCallId?: string;
81
61
  writeToolResultResource?: import('./result-extensions.js').ToolResultResourceWriter;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/agent",
3
- "version": "0.11.39",
3
+ "version": "0.11.41",
4
4
  "description": "Embeddable MAR coding agent SDK and CLI.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -58,7 +58,7 @@
58
58
  "vitest": "^4.0.14"
59
59
  },
60
60
  "scripts": {
61
- "build": "node ../scripts/clean-build-output.mjs dist && tsc -p tsconfig.json",
61
+ "build": "node ../scripts/clean-build-output.mjs dist && tsc -p tsconfig.json && tsc -p extensions/subagent/tsconfig.json --outDir dist/cli/subagent",
62
62
  "typecheck": "tsc -p tsconfig.json --noEmit",
63
63
  "test:unit": "pnpm build && vitest run --config vitest.config.ts test/unit",
64
64
  "analyze:session": "node test/tools/session-analyzer.mjs",
@@ -1,100 +0,0 @@
1
- import type { AgentReasoningEffort } from '../model/configuration.js';
2
- import type { SubagentTaskSnapshot, SubagentManyOutput, SubagentHandledResult } from '../subagent/contracts.js';
3
- import type { ExtensionOperationContext } from './operation.js';
4
- import type { ExtensionResourceScope } from './resources.js';
5
- import type { ExtensionHooks } from './hooks.js';
6
- import type { ExtensionCapabilitySnapshot } from './capabilities.js';
7
- export type ExtensionAgentSnapshot = Readonly<SubagentTaskSnapshot>;
8
- export type ExtensionAgentManySnapshot = Readonly<SubagentManyOutput>;
9
- export type ExtensionAgentWaitResult = ExtensionAgentSnapshot | ExtensionAgentManySnapshot;
10
- export type ExtensionAgentHandledResult = SubagentHandledResult;
11
- export type ExtensionAgentSpawnResult = ExtensionAgentSnapshot | ExtensionAgentHandledResult;
12
- export declare function isHandledAgentResult(value: ExtensionAgentSpawnResult | ExtensionAgentManySnapshot): value is ExtensionAgentHandledResult;
13
- export interface ExtensionAgentSpawnInput {
14
- readonly turnSignal?: AbortSignal;
15
- readonly waitFor?: 'start' | 'completion';
16
- readonly background?: boolean;
17
- readonly prompt: string;
18
- readonly description?: string;
19
- readonly modelId?: string;
20
- readonly reasoningEffort?: AgentReasoningEffort;
21
- readonly role?: 'general-purpose' | 'explore';
22
- readonly signal?: AbortSignal;
23
- }
24
- export interface ExtensionAgentTarget {
25
- readonly agentId: string;
26
- readonly signal?: AbortSignal;
27
- }
28
- export interface ExtensionAgentWaitInput {
29
- readonly untilSettled?: true;
30
- readonly agentId?: string;
31
- readonly agentIds?: readonly string[];
32
- readonly mode?: 'any' | 'all';
33
- readonly signal?: AbortSignal;
34
- readonly waitMs?: number;
35
- readonly waitFor?: 'completion' | 'message';
36
- }
37
- export interface ExtensionAgentMessageInput extends ExtensionAgentTarget {
38
- readonly message: string;
39
- readonly delivery?: 'append' | 'replace';
40
- }
41
- export interface ExtensionAgentsBackend {
42
- own(ownerInstanceId: string): () => Promise<void>;
43
- spawn(input: ExtensionAgentSpawnInput, call: ExtensionOperationContext): Promise<ExtensionAgentSnapshot>;
44
- list(call: ExtensionOperationContext): Promise<readonly ExtensionAgentSnapshot[]>;
45
- inspect(input: ExtensionAgentTarget, call: ExtensionOperationContext): Promise<ExtensionAgentSnapshot>;
46
- wait(input: ExtensionAgentWaitInput, call: ExtensionOperationContext): Promise<ExtensionAgentWaitResult>;
47
- message(input: ExtensionAgentMessageInput, call: ExtensionOperationContext): Promise<ExtensionAgentSnapshot>;
48
- cancel(input: ExtensionAgentTarget, call: ExtensionOperationContext): Promise<ExtensionAgentSnapshot>;
49
- }
50
- export interface ExtensionAgentsApi {
51
- spawn(input: ExtensionAgentSpawnInput): Promise<ExtensionAgentSpawnResult>;
52
- list(input?: {
53
- readonly signal?: AbortSignal;
54
- }): Promise<readonly ExtensionAgentSnapshot[]>;
55
- inspect(input: ExtensionAgentTarget): Promise<ExtensionAgentSnapshot>;
56
- wait(input: ExtensionAgentWaitInput & {
57
- readonly agentIds: readonly string[];
58
- }): Promise<ExtensionAgentManySnapshot>;
59
- wait(input: ExtensionAgentWaitInput & {
60
- readonly agentIds?: undefined;
61
- }): Promise<ExtensionAgentSnapshot>;
62
- wait(input: ExtensionAgentWaitInput): Promise<ExtensionAgentWaitResult>;
63
- message(input: ExtensionAgentMessageInput): Promise<ExtensionAgentSnapshot>;
64
- cancel(input: ExtensionAgentTarget): Promise<ExtensionAgentSnapshot>;
65
- }
66
- export interface ExtensionAgentCompletion {
67
- readonly operation: 'spawn' | 'wait' | 'message' | 'cancel';
68
- readonly agentId: string;
69
- readonly status: SubagentTaskSnapshot['status'];
70
- readonly deliveryStatus?: SubagentTaskSnapshot['deliveryStatus'];
71
- }
72
- type AgentOperation = 'agent.spawn' | 'agent.wait' | 'agent.message' | 'agent.cancel';
73
- export type ExtensionAgentAction = <Key extends AgentOperation>(key: Key, input: DomainAgentOperations[Key]['input'], leaf: (input: DomainAgentOperations[Key]['input'], call: ExtensionOperationContext) => Promise<DomainAgentOperations[Key]['output']>) => Promise<DomainAgentOperations[Key]['output']>;
74
- /** All callers share one interception and authoritative leaf-completion boundary. */
75
- export declare function invokeCoreAgentOperation<Key extends AgentOperation>(hooks: Pick<ExtensionHooks<DomainAgentOperations, DomainAgentFacts>, 'invoke' | 'emit'>, key: Key, input: DomainAgentOperations[Key]['input'], call: ExtensionOperationContext, leaf: (input: DomainAgentOperations[Key]['input'], call: ExtensionOperationContext) => Promise<DomainAgentOperations[Key]['output']>): Promise<DomainAgentOperations[Key]['output']>;
76
- export declare function resolveAgentSpawn(input: ExtensionAgentSpawnInput): ExtensionAgentSpawnInput;
77
- export declare function agentCapabilities(capabilities: ExtensionCapabilitySnapshot, available: boolean): ExtensionCapabilitySnapshot;
78
- export declare function bindCoreAgents(backend: ExtensionAgentsBackend, scope: ExtensionResourceScope, run: <Value>(operation: (call: ExtensionOperationContext) => Promise<Value>, signal?: AbortSignal) => Promise<Value>, hooks: Pick<ExtensionHooks<DomainAgentOperations, DomainAgentFacts>, 'invoke' | 'emit'>): ExtensionAgentsApi;
79
- export interface DomainAgentOperations {
80
- 'agent.spawn': {
81
- input: ExtensionAgentSpawnInput;
82
- output: ExtensionAgentSpawnResult;
83
- };
84
- 'agent.wait': {
85
- input: ExtensionAgentWaitInput;
86
- output: ExtensionAgentWaitResult;
87
- };
88
- 'agent.message': {
89
- input: ExtensionAgentMessageInput;
90
- output: ExtensionAgentSnapshot;
91
- };
92
- 'agent.cancel': {
93
- input: ExtensionAgentTarget;
94
- output: ExtensionAgentSnapshot;
95
- };
96
- }
97
- export interface DomainAgentFacts {
98
- 'agent.completed': ExtensionAgentCompletion;
99
- }
100
- export {};
@@ -1,121 +0,0 @@
1
- import { AgentError } from '../error.js';
2
- import { parseAgentWaitTargets } from '../subagent/wait-targets.js';
3
- export function isHandledAgentResult(value) {
4
- return 'outcome' in value && value.outcome === 'handled' && !Object.hasOwn(value, 'agentId');
5
- }
6
- /** All callers share one interception and authoritative leaf-completion boundary. */
7
- export function invokeCoreAgentOperation(hooks, key, input, call, leaf) {
8
- return hooks.invoke(key, input, call, async (input, effective) => {
9
- const result = structuredClone(await leaf(input, effective));
10
- if (isHandledAgentResult(result))
11
- return result;
12
- const agents = Array.isArray(result.agents)
13
- ? result.agents
14
- : [result];
15
- for (const agent of agents)
16
- await hooks.emit('agent.completed', {
17
- operation: key.slice('agent.'.length),
18
- agentId: agent.agentId,
19
- status: agent.status,
20
- ...(agent.deliveryStatus === undefined ? {} : { deliveryStatus: agent.deliveryStatus })
21
- }, effective);
22
- return result;
23
- });
24
- }
25
- export function resolveAgentSpawn(input) {
26
- if (!input ||
27
- typeof input !== 'object' ||
28
- Array.isArray(input) ||
29
- typeof input.prompt !== 'string' ||
30
- !input.prompt.trim() ||
31
- (input.turnSignal !== undefined && !(input.turnSignal instanceof AbortSignal)) ||
32
- (input.description !== undefined &&
33
- (typeof input.description !== 'string' || !input.description.trim())) ||
34
- (input.modelId !== undefined && (typeof input.modelId !== 'string' || !input.modelId)) ||
35
- (input.role !== undefined && input.role !== 'general-purpose' && input.role !== 'explore') ||
36
- (input.background !== undefined && typeof input.background !== 'boolean') ||
37
- (input.waitFor !== undefined && input.waitFor !== 'start' && input.waitFor !== 'completion') ||
38
- (input.reasoningEffort !== undefined &&
39
- !['low', 'medium', 'high', 'xhigh', 'max', 'ultra'].includes(input.reasoningEffort)))
40
- throw invalid('Agent spawn input is invalid.');
41
- return {
42
- prompt: input.prompt,
43
- ...(input.turnSignal === undefined ? {} : { turnSignal: input.turnSignal }),
44
- ...(input.waitFor === undefined ? {} : { waitFor: input.waitFor }),
45
- ...(input.background === undefined ? {} : { background: input.background }),
46
- description: input.description ?? 'Extension agent',
47
- ...(input.signal === undefined ? {} : { signal: input.signal }),
48
- ...(input.modelId === undefined ? {} : { modelId: input.modelId }),
49
- ...(input.reasoningEffort === undefined ? {} : { reasoningEffort: input.reasoningEffort }),
50
- role: input.role ?? 'general-purpose'
51
- };
52
- }
53
- export function agentCapabilities(capabilities, available) {
54
- const values = Object.freeze(capabilities.list().filter((id) => id !== 'agents' || available));
55
- return Object.freeze({ has: (id) => values.includes(id), list: () => values });
56
- }
57
- export function bindCoreAgents(backend, scope, run, hooks) {
58
- scope.effect(() => backend.own(scope.instanceId));
59
- const invoke = (key, input) => run((call) => invokeCoreAgentOperation(hooks, key, input, call, async (effectiveInput, effective) => {
60
- let result;
61
- switch (key) {
62
- case 'agent.spawn':
63
- result = await backend.spawn({
64
- ...resolveAgentSpawn(effectiveInput),
65
- ...(effectiveInput.turnSignal === undefined
66
- ? {}
67
- : {
68
- turnSignal: AbortSignal.any([
69
- scope.signal,
70
- effectiveInput.turnSignal
71
- ])
72
- })
73
- }, effective);
74
- break;
75
- case 'agent.wait':
76
- result = await backend.wait(effectiveInput, effective);
77
- break;
78
- case 'agent.message':
79
- result = await backend.message(effectiveInput, effective);
80
- break;
81
- case 'agent.cancel':
82
- result = await backend.cancel(effectiveInput, effective);
83
- break;
84
- }
85
- return result;
86
- }), input.signal);
87
- const target = (input) => {
88
- if (!input ||
89
- typeof input !== 'object' ||
90
- Array.isArray(input) ||
91
- typeof input.agentId !== 'string' ||
92
- !input.agentId)
93
- throw invalid('Agent target is invalid.');
94
- return { ...input };
95
- };
96
- return {
97
- spawn: (input) => invoke('agent.spawn', { ...input }),
98
- list: async (input = {}) => {
99
- if (!input || typeof input !== 'object' || Array.isArray(input))
100
- throw invalid('Agent list input is invalid.');
101
- return run(async (call) => structuredClone(await backend.list(call)), input.signal);
102
- },
103
- inspect: async (input) => {
104
- const copied = target(input);
105
- return run(async (call) => structuredClone(await backend.inspect(copied, call)), copied.signal);
106
- },
107
- wait: (async (input) => {
108
- if (!input || typeof input !== 'object' || Array.isArray(input))
109
- throw invalid('Agent wait input is invalid.');
110
- const selection = parseAgentWaitTargets(input);
111
- return invoke('agent.wait', input.agentId === undefined
112
- ? { ...input, ...selection }
113
- : target(input));
114
- }),
115
- message: async (input) => invoke('agent.message', target(input)),
116
- cancel: async (input) => invoke('agent.cancel', target(input))
117
- };
118
- }
119
- function invalid(message) {
120
- return new AgentError('MAR_AGENT_EXTENSION_AGENT_INPUT_INVALID', message);
121
- }
@@ -1,6 +0,0 @@
1
- import { type ContextGcPlannerInput, type ContextCandidate, type CandidateSavings, type ToolGroup } from './gc-contracts.js';
2
- export declare function collectSubagentCandidates(input: ContextGcPlannerInput, groups: ReadonlyMap<string, ToolGroup>, existingTargets: ReadonlySet<string>, candidateSavings: CandidateSavings): {
3
- eligible: ContextCandidate[];
4
- protectedTokens: number;
5
- retryAfterRollouts: number;
6
- };