@myagentroam/agent 0.10.43 → 0.10.44
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.
- package/dist/agent-core/prompts/index.d.ts +1 -1
- package/dist/agent-core/prompts/index.js +1 -1
- package/dist/agent-core/prompts/subagent.js +1 -0
- package/dist/agent-core/sdk/session.js +24 -2
- package/dist/agent-core/subagent/model-update.d.ts +2 -0
- package/dist/agent-core/subagent/model-update.js +85 -0
- package/dist/agent-core/subagent/session-controller.d.ts +5 -0
- package/dist/agent-core/subagent/session-controller.js +41 -4
- package/dist/agent-core/tools/agent/agent-wait.js +1 -1
- package/dist/agent-core/tools/code-mode/index.js +20 -18
- package/dist/agent-core/tools/code-mode/quickjs-engine.js +5 -1
- package/dist/agent-core/tools/execution-limits.d.ts +1 -0
- package/dist/agent-core/tools/execution-limits.js +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ExecutionMode } from '../runtime/contracts.js';
|
|
2
2
|
import { type CorePromptPart } from '../extensions/prompt-composition.js';
|
|
3
|
-
export declare const MAR_AGENT_PROMPT_VERSION = "1.
|
|
3
|
+
export declare const MAR_AGENT_PROMPT_VERSION = "1.66";
|
|
4
4
|
interface SystemPromptInput {
|
|
5
5
|
mode: ExecutionMode;
|
|
6
6
|
platform: string;
|
|
@@ -5,7 +5,7 @@ import { modePrompt } from './modes.js';
|
|
|
5
5
|
import { outputStylePrompt } from './output.js';
|
|
6
6
|
import { subagentPrompt } from './subagent.js';
|
|
7
7
|
import { interactionPrompt, longRunningPrompt, safetyPrompt, toolUsagePrompt, workflowPrompt } from './workflow.js';
|
|
8
|
-
export const MAR_AGENT_PROMPT_VERSION = '1.
|
|
8
|
+
export const MAR_AGENT_PROMPT_VERSION = '1.66';
|
|
9
9
|
export function buildSystemPrompt(input) {
|
|
10
10
|
return renderPromptSections(buildSystemPromptSections(input));
|
|
11
11
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export const subagentPrompt = [
|
|
2
2
|
'# Subagents',
|
|
3
|
+
'Unread child messages and terminal results are supplied before the next model request.',
|
|
3
4
|
'Call agent_start, agent_wait, agent_message and agent_cancel directly, never inside code_exec; they are absent from the cell tools namespace.',
|
|
4
5
|
'Delegate bounded, self-contained tasks when independent progress or context savings materially helps. Keep simple or tightly coupled work local; do not split work merely to use agents.',
|
|
5
6
|
'All agents share the filesystem. Give each child an objective, necessary context, expected output, and an exclusive write scope or a read-only boundary; avoid conflicting writes.',
|
|
@@ -30,6 +30,7 @@ import { MAR_AGENT_PROMPT_VERSION, buildSystemPromptSections } from '../prompts/
|
|
|
30
30
|
import { renderPromptSections } from '../extensions/prompt-composition.js';
|
|
31
31
|
import { retainedSessionResourcesSnapshot } from '../prompts/resources.js';
|
|
32
32
|
import { childSubagentInstruction } from '../prompts/subagent.js';
|
|
33
|
+
import { renderSubagentUpdate } from '../subagent/model-update.js';
|
|
33
34
|
import { AsyncQueue } from '../runtime/async-queue.js';
|
|
34
35
|
import { CompactionOperation } from '../runtime/compaction/operation.js';
|
|
35
36
|
import { CompactCoordinator } from '../runtime/compaction/coordinator.js';
|
|
@@ -1516,8 +1517,29 @@ export function createSessionOpener(services) {
|
|
|
1516
1517
|
});
|
|
1517
1518
|
messageSources.set(message, stored);
|
|
1518
1519
|
}),
|
|
1519
|
-
prepareRound: async function prepareRound(pendingOutputContinuation) {
|
|
1520
|
+
prepareRound: async function prepareRound(pendingOutputContinuation, subagentUpdatesCollected = false) {
|
|
1520
1521
|
await appendMailboxMessages();
|
|
1522
|
+
if (!subagentUpdatesCollected && subagents)
|
|
1523
|
+
await withRecordProjection(async () => {
|
|
1524
|
+
controller.signal.throwIfAborted();
|
|
1525
|
+
for (const update of subagents.collectModelUpdates()) {
|
|
1526
|
+
controller.signal.throwIfAborted();
|
|
1527
|
+
const message = {
|
|
1528
|
+
role: 'user',
|
|
1529
|
+
content: renderSubagentUpdate(update.snapshot, update.truncated),
|
|
1530
|
+
contextKind: 'contextual'
|
|
1531
|
+
};
|
|
1532
|
+
const stored = await store.append(sessionId, {
|
|
1533
|
+
type: 'model.context',
|
|
1534
|
+
payload: message,
|
|
1535
|
+
executionId,
|
|
1536
|
+
turnId
|
|
1537
|
+
}, { signal: controller.signal });
|
|
1538
|
+
messages.push(message);
|
|
1539
|
+
messageSources.set(message, stored);
|
|
1540
|
+
update.acknowledge();
|
|
1541
|
+
}
|
|
1542
|
+
});
|
|
1521
1543
|
updateMcpRegistry();
|
|
1522
1544
|
executionTools = mcpRegistry.project(baseTools());
|
|
1523
1545
|
await syncMcpWorldState(messages.length);
|
|
@@ -1587,7 +1609,7 @@ export function createSessionOpener(services) {
|
|
|
1587
1609
|
if (lateCoreChange || lateAdopted) {
|
|
1588
1610
|
// Middleware may admit a blocking join after the initial checkpoint.
|
|
1589
1611
|
// Never sample the candidate assembled against the replaced context.
|
|
1590
|
-
return prepareRound(pendingOutputContinuation);
|
|
1612
|
+
return prepareRound(pendingOutputContinuation, true);
|
|
1591
1613
|
}
|
|
1592
1614
|
return { request, toolScope };
|
|
1593
1615
|
},
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { escapeMarkupText, markupAttributes } from '../prompts/markup.js';
|
|
2
|
+
import { TOOL_EXECUTION_LIMITS } from '../tools/execution-limits.js';
|
|
3
|
+
export function renderSubagentUpdate(snapshot, truncated = false) {
|
|
4
|
+
const attributes = (values) => markupAttributes(Object.fromEntries(Object.entries(values).map(([key, value]) => {
|
|
5
|
+
if (value === undefined)
|
|
6
|
+
return [key, undefined];
|
|
7
|
+
let bounded = '';
|
|
8
|
+
let count = 0;
|
|
9
|
+
for (const point of String(value)) {
|
|
10
|
+
if (count++ === 256) {
|
|
11
|
+
truncated = true;
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
bounded += point;
|
|
15
|
+
}
|
|
16
|
+
return [key, bounded];
|
|
17
|
+
})));
|
|
18
|
+
const root = '<mar_subagent_update' +
|
|
19
|
+
attributes({
|
|
20
|
+
agentId: snapshot.agentId,
|
|
21
|
+
status: snapshot.status,
|
|
22
|
+
modelId: snapshot.modelId,
|
|
23
|
+
modelName: snapshot.modelName,
|
|
24
|
+
reasoningEffort: snapshot.reasoningEffort,
|
|
25
|
+
messageId: snapshot.messageId,
|
|
26
|
+
turnId: snapshot.turnId,
|
|
27
|
+
deliveryStatus: snapshot.deliveryStatus
|
|
28
|
+
});
|
|
29
|
+
const close = '</mar_subagent_update>';
|
|
30
|
+
let remaining = TOOL_EXECUTION_LIMITS.subagentUpdateMaxBytes -
|
|
31
|
+
Buffer.byteLength(root + ' truncated="false">\n' + close);
|
|
32
|
+
const lines = [];
|
|
33
|
+
const field = (name, value, metadata = {}, limit = remaining) => {
|
|
34
|
+
let attrs = attributes(metadata);
|
|
35
|
+
const overhead = Buffer.byteLength(' <' + name + attrs + '></' + name + '>\n');
|
|
36
|
+
if (overhead > remaining) {
|
|
37
|
+
truncated = true;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
let budget = Math.min(limit, remaining - overhead);
|
|
41
|
+
let text = '';
|
|
42
|
+
let clipped = false;
|
|
43
|
+
for (const point of value) {
|
|
44
|
+
const encoded = escapeMarkupText(point);
|
|
45
|
+
const bytes = Buffer.byteLength(encoded);
|
|
46
|
+
if (bytes > budget) {
|
|
47
|
+
clipped = true;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
text += encoded;
|
|
51
|
+
budget -= bytes;
|
|
52
|
+
}
|
|
53
|
+
if (clipped) {
|
|
54
|
+
truncated = true;
|
|
55
|
+
if ('truncated' in metadata)
|
|
56
|
+
attrs = attributes({ ...metadata, truncated: true });
|
|
57
|
+
}
|
|
58
|
+
const opening = ' <' + name + attrs;
|
|
59
|
+
const line = text === '' ? opening + ' />\n' : opening + '>' + text + '</' + name + '>\n';
|
|
60
|
+
remaining -= Buffer.byteLength(line);
|
|
61
|
+
lines.push(line);
|
|
62
|
+
};
|
|
63
|
+
// Preserve failure/permission facts before spending the remaining budget on result text.
|
|
64
|
+
if (snapshot.errorCode !== undefined || snapshot.errorMessage !== undefined)
|
|
65
|
+
field('error', snapshot.errorMessage ?? '', { code: snapshot.errorCode }, 1024);
|
|
66
|
+
if (snapshot.permissionStop)
|
|
67
|
+
field('permission_stop', snapshot.permissionStop.reason, { action: snapshot.permissionStop.action, ...snapshot.permissionStop.source }, 1024);
|
|
68
|
+
field('description', snapshot.description, {}, 1024);
|
|
69
|
+
if (snapshot.latestMessage) {
|
|
70
|
+
const { text, ...metadata } = snapshot.latestMessage;
|
|
71
|
+
truncated ||= metadata.truncated;
|
|
72
|
+
field('message', text, metadata, TOOL_EXECUTION_LIMITS.subagentSummaryMaxBytes);
|
|
73
|
+
}
|
|
74
|
+
if (snapshot.summary !== undefined)
|
|
75
|
+
field('summary', snapshot.summary);
|
|
76
|
+
for (const path of snapshot.changedFiles ?? [])
|
|
77
|
+
field('changed_file', path);
|
|
78
|
+
for (const text of snapshot.verification ?? [])
|
|
79
|
+
field('verification', text);
|
|
80
|
+
for (const { path, startLine, endLine } of snapshot.evidence ?? [])
|
|
81
|
+
field('evidence', path, { startLine, endLine });
|
|
82
|
+
if (snapshot.latestActivity)
|
|
83
|
+
field('activity', '', snapshot.latestActivity);
|
|
84
|
+
return root + ' truncated="' + String(truncated) + '">\n' + lines.join('') + close;
|
|
85
|
+
}
|
|
@@ -107,6 +107,11 @@ export declare class SubagentSessionController implements SubagentController {
|
|
|
107
107
|
withOperation<T>(operation: SubagentParentOperation, run: () => T): T;
|
|
108
108
|
inspect(agentId: string): Promise<SubagentTaskSnapshot>;
|
|
109
109
|
inspectAll(): readonly SubagentTaskSnapshot[];
|
|
110
|
+
collectModelUpdates(): readonly {
|
|
111
|
+
snapshot: SubagentTaskSnapshot;
|
|
112
|
+
truncated: boolean;
|
|
113
|
+
acknowledge(): void;
|
|
114
|
+
}[];
|
|
110
115
|
cancelOwned(ownerInstanceId: string): Promise<void>;
|
|
111
116
|
endParentExecution(executionId: string): void;
|
|
112
117
|
parentExecution(executionId: string): SubagentParentExecution | undefined;
|
|
@@ -86,6 +86,41 @@ export class SubagentSessionController {
|
|
|
86
86
|
throw new MarAgentError('MAR_AGENT_DISPOSED', 'Subagent controller is disposed.');
|
|
87
87
|
return [...this.#agents.values()].map((state) => this.#snapshot(state, { full: true }));
|
|
88
88
|
}
|
|
89
|
+
collectModelUpdates() {
|
|
90
|
+
return [...this.#agents.values()]
|
|
91
|
+
.filter((state) => state.messageRevision > state.observedMessageRevision ||
|
|
92
|
+
(isTerminalState(state) &&
|
|
93
|
+
state.terminalRevision !== undefined &&
|
|
94
|
+
state.terminalRevision > state.observedTerminalRevision))
|
|
95
|
+
.sort((left, right) => left.resourceRevision - right.resourceRevision)
|
|
96
|
+
.slice(0, TOOL_EXECUTION_LIMITS.agentWaitMaxAgents)
|
|
97
|
+
.map((state) => {
|
|
98
|
+
const messageRevision = state.messageRevision;
|
|
99
|
+
const terminalRevision = isTerminalState(state) ? state.terminalRevision : undefined;
|
|
100
|
+
const includeTerminalDetails = terminalRevision !== undefined && terminalRevision > state.observedTerminalRevision;
|
|
101
|
+
const snapshot = this.#snapshot(state, {
|
|
102
|
+
includeLatestMessage: messageRevision > state.observedMessageRevision,
|
|
103
|
+
includeTerminalDetails,
|
|
104
|
+
full: false
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
snapshot,
|
|
108
|
+
truncated: snapshot.latestMessage?.truncated === true ||
|
|
109
|
+
(includeTerminalDetails &&
|
|
110
|
+
(snapshot.summary !== state.summary ||
|
|
111
|
+
(snapshot.changedFiles?.length ?? 0) < state.changedFiles.length ||
|
|
112
|
+
(snapshot.evidence?.length ?? 0) < state.evidence.length ||
|
|
113
|
+
(snapshot.verification?.length ?? 0) < state.verification.length ||
|
|
114
|
+
(snapshot.verification?.some((value, index) => value !== state.verification[index]) ??
|
|
115
|
+
false))),
|
|
116
|
+
acknowledge: () => {
|
|
117
|
+
state.observedMessageRevision = Math.max(state.observedMessageRevision, messageRevision);
|
|
118
|
+
if (includeTerminalDetails)
|
|
119
|
+
state.observedTerminalRevision = Math.max(state.observedTerminalRevision, terminalRevision);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
}
|
|
89
124
|
async cancelOwned(ownerInstanceId) {
|
|
90
125
|
for (const pending of this.#pendingDeliveries)
|
|
91
126
|
if (pending.ownerInstanceId === ownerInstanceId)
|
|
@@ -548,7 +583,7 @@ export class SubagentSessionController {
|
|
|
548
583
|
if (index >= 0)
|
|
549
584
|
this.#queue.splice(index, 1);
|
|
550
585
|
state.status = 'cancelled';
|
|
551
|
-
this.#touchResource(state);
|
|
586
|
+
this.#touchResource(state, true);
|
|
552
587
|
this.#closeReceipt(state);
|
|
553
588
|
state.terminalPending = true;
|
|
554
589
|
await this.#publishTerminal(state);
|
|
@@ -731,7 +766,7 @@ export class SubagentSessionController {
|
|
|
731
766
|
state.errorMessage = result.errorMessage ?? 'Subagent execution failed.';
|
|
732
767
|
}
|
|
733
768
|
state.terminalPending = true;
|
|
734
|
-
this.#touchResource(state);
|
|
769
|
+
this.#touchResource(state, true);
|
|
735
770
|
this.#closeReceipt(state);
|
|
736
771
|
await this.#publishTerminal(state);
|
|
737
772
|
}
|
|
@@ -767,10 +802,12 @@ export class SubagentSessionController {
|
|
|
767
802
|
state.errorCode = diagnostic.code;
|
|
768
803
|
state.errorMessage = diagnostic.message;
|
|
769
804
|
state.terminalPending = true;
|
|
770
|
-
this.#touchResource(state);
|
|
805
|
+
this.#touchResource(state, true);
|
|
771
806
|
}
|
|
772
|
-
#touchResource(state) {
|
|
807
|
+
#touchResource(state, terminal = false) {
|
|
773
808
|
state.resourceRevision = ++this.#resourceRevision;
|
|
809
|
+
if (terminal)
|
|
810
|
+
state.terminalRevision = state.resourceRevision;
|
|
774
811
|
}
|
|
775
812
|
#waitForAnyCompletion(candidates, waitMs, signal) {
|
|
776
813
|
return waitForCompletionNotification(this.#completionWaiters, (state) => candidates.includes(state), waitMs, signal);
|
|
@@ -5,7 +5,7 @@ export const agentWaitToolDefinition = {
|
|
|
5
5
|
name: 'agent_wait',
|
|
6
6
|
allowedCallers: ['direct'],
|
|
7
7
|
parallelSafety: 'serial',
|
|
8
|
-
description: 'Read or wait a bounded time for a child agent result. Wait only when the next local step depends on the child result; otherwise continue useful non-overlapping work. waitFor defaults to "completion"; use "message" only when a fresh public commentary/final message would change the next decision. Omit agentId to wait for whichever live child returns first, matching Codex-style untargeted waiting and avoiding UUID transcription; provide the exact agentId returned by agent_start only when observing a specific child. If no child is live, untargeted waiting reads the most recently created child. For an exec processId, use exec_wait instead (tools.exec_wait in Code Mode). Omitting waitMs waits up to 30 seconds by default; waitMs=0 returns the current snapshot immediately. Positive waits range up to 5 minutes, and positive values below 10 seconds are raised to 10 seconds. When blocked on a live child result, prefer one 300000 ms completion wait rather than repeated short waits. Use agentIds with mode any (default) or all to wait for an explicit non-empty set of up to 8 distinct child IDs; never combine agentId and agentIds or use mode without agentIds. mode and waitFor are independent. A group uses one deadline and returns mode, waitFor, waitOutcome, agents in input order, and pendingAgentIds. Failed, cancelled and interrupted turns also satisfy completion; terminal state satisfies message waits too. Group waitMs=0 returns only snapshots without consuming messages. Single-target and untargeted results include waitOutcome as snapshot, message, completion, or timeout plus the real agentId and description. A message, timeout with unread progress, or first terminal completion result includes the newly observed latest public commentary/final message; snapshots and repeated observations omit previously observed message text. latestActivity can still identify a public message or bounded tool started/completed/failed status. A queued or running result is not completion. A message wait consumes only the latest unread public message in the current Session runtime; tool activity does not wake it, and parent cancellation preserves unread progress for a later Execution. Do not use message waits as heartbeat checks or request progress merely to confirm that a child is still running. First terminal results include bounded summary, changedFiles, verification, and read evidence with path/line ranges; use that evidence to avoid repeating the full exploration, while independently checking consequential edits and claims.',
|
|
8
|
+
description: 'Read or wait a bounded time for a child agent result. Unread child messages and terminal results are supplied automatically before the next model request. Wait only when the next local step depends on the child result; otherwise continue useful non-overlapping work. waitFor defaults to "completion"; use "message" only when a fresh public commentary/final message would change the next decision. Omit agentId to wait for whichever live child returns first, matching Codex-style untargeted waiting and avoiding UUID transcription; provide the exact agentId returned by agent_start only when observing a specific child. If no child is live, untargeted waiting reads the most recently created child. For an exec processId, use exec_wait instead (tools.exec_wait in Code Mode). Omitting waitMs waits up to 30 seconds by default; waitMs=0 returns the current snapshot immediately. Positive waits range up to 5 minutes, and positive values below 10 seconds are raised to 10 seconds. When blocked on a live child result, prefer one 300000 ms completion wait rather than repeated short waits. Use agentIds with mode any (default) or all to wait for an explicit non-empty set of up to 8 distinct child IDs; never combine agentId and agentIds or use mode without agentIds. mode and waitFor are independent. A group uses one deadline and returns mode, waitFor, waitOutcome, agents in input order, and pendingAgentIds. Failed, cancelled and interrupted turns also satisfy completion; terminal state satisfies message waits too. Group waitMs=0 returns only snapshots without consuming messages. Single-target and untargeted results include waitOutcome as snapshot, message, completion, or timeout plus the real agentId and description. A message, timeout with unread progress, or first terminal completion result includes the newly observed latest public commentary/final message; snapshots and repeated observations omit previously observed message text. latestActivity can still identify a public message or bounded tool started/completed/failed status. A queued or running result is not completion. A message wait consumes only the latest unread public message in the current Session runtime; tool activity does not wake it, and parent cancellation preserves unread progress for a later Execution. Do not use message waits as heartbeat checks or request progress merely to confirm that a child is still running. First terminal results include bounded summary, changedFiles, verification, and read evidence with path/line ranges; use that evidence to avoid repeating the full exploration, while independently checking consequential edits and claims.',
|
|
9
9
|
inputSchema: {
|
|
10
10
|
type: 'object',
|
|
11
11
|
properties: {
|
|
@@ -32,7 +32,7 @@ export const codeModeToolDefinition = {
|
|
|
32
32
|
- Use only standard ECMAScript built-ins and the explicitly documented tools, observe, state, catalog and cell namespaces. Do not use Node.js, browser or Web APIs. Module imports, filesystem and network APIs are unavailable. Obtain external capabilities only through available tools. Use tools.exec to start managed processes when permitted; use tools.exec_wait afterward to wait, write stdin or cancel.
|
|
33
33
|
|
|
34
34
|
Tool calls:
|
|
35
|
-
- tools.NAME(input) returns a Promise.
|
|
35
|
+
- tools.NAME(input) returns a Promise. Pass a JavaScript value matching the current catalog inputSchema. For parameterless tools prefer tools.NAME({}); tools.NAME() is accepted only for explicitly closed empty-object schemas.
|
|
36
36
|
- Results use the MAR envelope: { content?: string, data?: unknown, images?: Array<{mimeType:string,dataBase64:string}>, truncated?: boolean }. Redundant JSON content is omitted when it exactly renders data; independent text remains in content. Prefer data for programmatic results: result.data.results[0].text for read source text and result.data.exitCode/result.data.stdout for exec. content, when present, is rendered text, not raw file bytes. Use only fields documented by that tool; do not invent success or ok flags.
|
|
37
37
|
- Tool errors reject with code/message and may be caught, except nested Auto deny, which skips only that call and resolves with data.error/data.message. A failed cell preserves already emitted output alongside its status and error; completed tool effects are not rolled back. Inspect it before retrying completed work. Await every call; unawaited calls fail the cell. Use Promise.all for independent calls and sequential await for dependencies. Runtime preserves safe/serial barriers and Host checks.
|
|
38
38
|
- skill, tool_search, question, code_exec, code_exec_wait and direct-only tools cannot be called here. Load Skills directly and read their instructions before the next tool call. Use direct tool_search before a later code cell for deferred tools; the current cell's tools do not change.
|
|
@@ -41,7 +41,7 @@ Built-in namespaces:
|
|
|
41
41
|
- observe.result(result): void registers an unmodified complete tools.NAME result or caught tool error as a trusted tool_result, using the original text and all images without repeating program data. Non-original, copied or modified values are rejected. This selects evidence for the next model response, not a log and not a new model call. Prefer observe.result for inspecting tool results.
|
|
42
42
|
- observe.text(value): void registers text/JSON values. observe.image(value): void registers one image value when image input is supported. Both accept original tool results for compatibility and use the same complete tool_result observation path; they do not select part of an original result. Extracted single images, copies and computed summaries are value observations, never trusted tool results. Observations are returned in registration order. Only explicitly observed evidence reaches the model; registration does not prove inspection. Sources and types are runtime-assigned. No out or callable observe(value) alias exists.
|
|
43
43
|
- state.get(key), state.has(key), state.set(key, value), state.delete(key) access bounded session JSON state. Mutations commit atomically only when the cell succeeds; failed or cancelled cells discard them.
|
|
44
|
-
- catalog.tools() returns a read-only snapshot of the tools callable in this cell, including name, description
|
|
44
|
+
- catalog.tools() returns a read-only snapshot of the tools callable in this cell, including name, description and inputSchema. It does not discover or authorize additional tools.
|
|
45
45
|
- await cell.sleep(ms) performs a cancellable delay up to ${limits.codeSleepMaxMs} ms.
|
|
46
46
|
- await cell.yield_control() returns accumulated output to the model immediately while this cell continues running.
|
|
47
47
|
- Optionally start source with // @options: {"yieldMs": ${limits.codeDefaultYieldMs}}. yieldMs defaults to ${limits.codeDefaultYieldMs} ms and controls this call's wait window (0..${limits.codeMaxYieldMs}), not nested tool timeouts or wait windows. A running result includes cellId; use direct code_exec_wait for new output, completion or termination.
|
|
@@ -63,7 +63,7 @@ Inspect before a dependent edit; successful await needs no invented success flag
|
|
|
63
63
|
const inspected = await tools.read({ reads: [{ path: "source.txt" }] });
|
|
64
64
|
const sourceText = inspected.data.results[0].text;
|
|
65
65
|
if (!sourceText?.includes("original=1")) throw new Error("Unexpected source");
|
|
66
|
-
const patched = await tools.apply_patch("*** Begin Patch\\n*** Update File: source.txt\\n@@\\n original=1\\n+updated=2\\n*** End Patch");
|
|
66
|
+
const patched = await tools.apply_patch({ patch: "*** Begin Patch\\n*** Update File: source.txt\\n@@\\n original=1\\n+updated=2\\n*** End Patch" });
|
|
67
67
|
observe.result(patched);
|
|
68
68
|
\`\`\``,
|
|
69
69
|
inputMode: 'freeform',
|
|
@@ -102,6 +102,13 @@ export const codeExecWaitToolDefinition = {
|
|
|
102
102
|
allowedCallers: ['direct'],
|
|
103
103
|
parallelSafety: 'safe'
|
|
104
104
|
};
|
|
105
|
+
function projectProgrammaticTool(tool) {
|
|
106
|
+
return {
|
|
107
|
+
name: tool.name,
|
|
108
|
+
description: `Call only as tools.${tool.name} inside code_exec, never as a direct model tool.\nPass a JavaScript value matching inputSchema.\n${tool.description}`,
|
|
109
|
+
inputSchema: stableToolSchema(tool.inputSchema)
|
|
110
|
+
};
|
|
111
|
+
}
|
|
105
112
|
/** Deferred definitions travel in search results, not in the stable Code Mode description. */
|
|
106
113
|
export function projectCodeModeTools(tools, residentTools = tools) {
|
|
107
114
|
const codeModeEnabled = tools.some((tool) => tool.name === 'code_exec' && allowsToolCaller(tool, 'direct'));
|
|
@@ -113,12 +120,7 @@ export function projectCodeModeTools(tools, residentTools = tools) {
|
|
|
113
120
|
const programmatic = orderToolDefinitions(residentTools.filter((tool) => allowsToolCaller(tool, 'programmatic')));
|
|
114
121
|
const directory = JSON.stringify({
|
|
115
122
|
callableNames: programmatic.map((tool) => tool.name),
|
|
116
|
-
programmaticOnly: programmatic.map(
|
|
117
|
-
name: tool.name,
|
|
118
|
-
description: tool.description,
|
|
119
|
-
inputSchema: stableToolSchema(tool.inputSchema),
|
|
120
|
-
inputMode: tool.inputMode ?? 'json'
|
|
121
|
-
}))
|
|
123
|
+
programmaticOnly: programmatic.map(projectProgrammaticTool)
|
|
122
124
|
});
|
|
123
125
|
if (Buffer.byteLength(directory) > 32 * 1024)
|
|
124
126
|
throw new MarAgentError('MAR_AGENT_TOOL_EXPOSURE_LIMIT', 'Programmatic tool directory is too large.');
|
|
@@ -141,12 +143,14 @@ export function projectCodeModeSearchResult(message, codeModeEnabled) {
|
|
|
141
143
|
.map(stableToolDefinition)
|
|
142
144
|
};
|
|
143
145
|
const tools = message.toolSearchTools.map((tool) => ({
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
...(allowsToolCaller(tool, 'programmatic')
|
|
147
|
+
? projectProgrammaticTool(tool)
|
|
148
|
+
: {
|
|
149
|
+
name: tool.name,
|
|
150
|
+
description: tool.description,
|
|
151
|
+
inputSchema: stableToolSchema(tool.inputSchema),
|
|
152
|
+
inputMode: tool.inputMode ?? 'json'
|
|
153
|
+
}),
|
|
150
154
|
caller: allowsToolCaller(tool, 'programmatic') ? 'programmatic' : 'direct'
|
|
151
155
|
}));
|
|
152
156
|
return {
|
|
@@ -631,9 +635,7 @@ export class CodeModeTool {
|
|
|
631
635
|
catalog: context
|
|
632
636
|
.codeMode.tools.filter((tool) => available.has(tool.name))
|
|
633
637
|
.map((tool) => ({
|
|
634
|
-
|
|
635
|
-
description: tool.description,
|
|
636
|
-
inputSchema: tool.inputSchema,
|
|
638
|
+
...projectProgrammaticTool(tool),
|
|
637
639
|
...(tool.parameterless ? { parameterless: true } : {}),
|
|
638
640
|
inputMode: tool.inputMode ?? 'json'
|
|
639
641
|
})),
|
|
@@ -451,7 +451,11 @@ export async function createCodeModeEngine(options) {
|
|
|
451
451
|
stateObject.dispose();
|
|
452
452
|
const catalog = vm.newObject();
|
|
453
453
|
method(catalog, 'tools', () => {
|
|
454
|
-
const value = parse(input.catalog)
|
|
454
|
+
const value = parse(input.catalog.map(({ name, description, inputSchema }) => ({
|
|
455
|
+
name,
|
|
456
|
+
description,
|
|
457
|
+
inputSchema
|
|
458
|
+
})));
|
|
455
459
|
const frozen = callGuest(deepFreeze, vm.undefined, value);
|
|
456
460
|
value.dispose();
|
|
457
461
|
if (frozen.error)
|
|
@@ -52,6 +52,7 @@ export declare const TOOL_EXECUTION_LIMITS: Readonly<{
|
|
|
52
52
|
subagentMessageMaxBytes: 131072;
|
|
53
53
|
subagentReasoningEffortMaxCharacters: 64;
|
|
54
54
|
subagentSummaryMaxBytes: 16384;
|
|
55
|
+
subagentUpdateMaxBytes: 32768;
|
|
55
56
|
subagentRunningLatestMessageMaxCharacters: 2000;
|
|
56
57
|
subagentEvidenceMaxItems: 64;
|
|
57
58
|
subagentVerificationMaxItems: 16;
|
|
@@ -52,6 +52,7 @@ export const TOOL_EXECUTION_LIMITS = Object.freeze({
|
|
|
52
52
|
subagentMessageMaxBytes: 131_072,
|
|
53
53
|
subagentReasoningEffortMaxCharacters: 64,
|
|
54
54
|
subagentSummaryMaxBytes: 16_384,
|
|
55
|
+
subagentUpdateMaxBytes: 32_768,
|
|
55
56
|
subagentRunningLatestMessageMaxCharacters: 2_000,
|
|
56
57
|
subagentEvidenceMaxItems: 64,
|
|
57
58
|
subagentVerificationMaxItems: 16,
|