@myagentroam/agent 0.9.143 → 0.9.144
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/runtime/async-queue.js +7 -5
- package/dist/agent-core/runtime/context/gc.js +1 -1
- package/dist/agent-core/runtime/context/projection.js +1 -1
- package/dist/agent-core/sdk/session.js +1 -1
- package/dist/agent-core/session/context-gc-checkpoint.d.ts +1 -1
- package/dist/agent-core/session/context-gc-checkpoint.js +2 -4
- package/dist/agent-core/session/context-gc-observations.js +2 -4
- package/dist/agent-core/session/context-gc-replacements.js +0 -2
- package/dist/agent-core/tools/callers.js +1 -1
- package/dist/agent-core/tools/code-mode/cells.js +3 -1
- package/dist/agent-core/tools/code-mode/index.js +8 -2
- package/dist/agent-core/tools/code-mode/quickjs-engine.js +30 -3
- package/package.json +1 -1
|
@@ -9,15 +9,17 @@ export class AsyncQueue {
|
|
|
9
9
|
push(value) {
|
|
10
10
|
if (this.#closed || this.#discarded)
|
|
11
11
|
return;
|
|
12
|
-
const waiter = this.#waiters[this.#waiterOffset
|
|
12
|
+
const waiter = this.#waiters[this.#waiterOffset];
|
|
13
|
+
if (!waiter) {
|
|
14
|
+
this.#values.push(value);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
this.#waiterOffset++;
|
|
13
18
|
if (this.#waiterOffset > 1024 && this.#waiterOffset * 2 > this.#waiters.length) {
|
|
14
19
|
this.#waiters.splice(0, this.#waiterOffset);
|
|
15
20
|
this.#waiterOffset = 0;
|
|
16
21
|
}
|
|
17
|
-
|
|
18
|
-
waiter({ value, done: false });
|
|
19
|
-
else
|
|
20
|
-
this.#values.push(value);
|
|
22
|
+
waiter({ value, done: false });
|
|
21
23
|
}
|
|
22
24
|
close() {
|
|
23
25
|
if (this.#closed)
|
|
@@ -234,7 +234,7 @@ function collectCodeModeCandidates(input, groups, existingTargets, usageRatio) {
|
|
|
234
234
|
const eligible = [];
|
|
235
235
|
let protectedTokens = 0;
|
|
236
236
|
let retryAfterRollouts = Infinity;
|
|
237
|
-
for (const group of [...groups.values()].filter((item) => ['
|
|
237
|
+
for (const group of [...groups.values()].filter((item) => ['code_exec', 'code_exec_wait'].includes(item.toolName))) {
|
|
238
238
|
if (!group.call ||
|
|
239
239
|
!group.result ||
|
|
240
240
|
group.failed ||
|
|
@@ -134,7 +134,7 @@ export function restoreModelContext(payload, providerModelId) {
|
|
|
134
134
|
: nativeItem?.type === 'custom_tool_call'
|
|
135
135
|
? nativeItem.name
|
|
136
136
|
: undefined;
|
|
137
|
-
const inputLimit = toolName === '
|
|
137
|
+
const inputLimit = toolName === 'code_exec' || toolName === 'code_exec_wait'
|
|
138
138
|
? TOOL_EXECUTION_LIMITS.codeMaxInputBytes
|
|
139
139
|
: toolName === 'apply_patch'
|
|
140
140
|
? TOOL_EXECUTION_LIMITS.patchMaxBytes
|
|
@@ -562,7 +562,7 @@ export function createSessionOpener(services) {
|
|
|
562
562
|
.slice(contextualWorldState.entries.findLast((entry) => entry.kind === 'resources')
|
|
563
563
|
?.index ?? 0)
|
|
564
564
|
.some((message) => message.role === 'tool_call' &&
|
|
565
|
-
['exec', 'code_exec', '
|
|
565
|
+
['exec', 'code_exec', 'agent_start'].includes(message.name ?? '')))
|
|
566
566
|
});
|
|
567
567
|
sessionRuntime.contextualWorldState = contextualWorldState;
|
|
568
568
|
if (!isDeepStrictEqual(previousContextualWorldState, contextualWorldState))
|
|
@@ -52,7 +52,7 @@ export type ContextGcReplacement = {
|
|
|
52
52
|
readonly evidenceSequences: readonly number[];
|
|
53
53
|
} | {
|
|
54
54
|
readonly kind: 'TOOL_CALL_INPUT';
|
|
55
|
-
readonly toolName: 'apply_patch' | 'exec' | 'exec_wait' | '
|
|
55
|
+
readonly toolName: 'apply_patch' | 'exec' | 'exec_wait' | 'code_exec';
|
|
56
56
|
readonly callId: string;
|
|
57
57
|
readonly target: ContextGcTarget;
|
|
58
58
|
readonly replacementArguments: unknown;
|
|
@@ -295,8 +295,7 @@ function replacementMatchesRecords(replacement, records, recordsBySequence, work
|
|
|
295
295
|
result !== undefined &&
|
|
296
296
|
isDeepStrictEqual(replacement.replacementArguments, contextGcApplyPatchInputReplacement(source.payload.arguments, result, replacement.evidenceSequence, applyPatchReplacementFormatVersion(replacement.replacementArguments))));
|
|
297
297
|
}
|
|
298
|
-
if (replacement.kind === 'TOOL_CALL_INPUT' &&
|
|
299
|
-
(replacement.toolName === 'code_mode' || replacement.toolName === 'code_exec')) {
|
|
298
|
+
if (replacement.kind === 'TOOL_CALL_INPUT' && replacement.toolName === 'code_exec') {
|
|
300
299
|
const evidence = successfulToolEvidence(records, recordsBySequence, replacement.evidenceSequence, replacement.toolName);
|
|
301
300
|
const input = normalizeContextGcCodeModeInput(source.payload.arguments);
|
|
302
301
|
return (evidence?.callId === replacement.callId &&
|
|
@@ -308,7 +307,7 @@ function replacementMatchesRecords(replacement, records, recordsBySequence, work
|
|
|
308
307
|
: [])));
|
|
309
308
|
}
|
|
310
309
|
if (replacement.kind === 'CODE_MODE_OUTPUT') {
|
|
311
|
-
const evidence = ['
|
|
310
|
+
const evidence = ['code_exec', 'code_exec_wait']
|
|
312
311
|
.map((name) => successfulToolEvidence(records, recordsBySequence, replacement.evidenceSequence, name))
|
|
313
312
|
.find((item) => item !== undefined);
|
|
314
313
|
return (evidence?.callId === replacement.callId &&
|
|
@@ -715,7 +714,6 @@ function isContextGcReplacement(value) {
|
|
|
715
714
|
(value.toolName === 'apply_patch' ||
|
|
716
715
|
value.toolName === 'exec' ||
|
|
717
716
|
value.toolName === 'exec_wait' ||
|
|
718
|
-
value.toolName === 'code_mode' ||
|
|
719
717
|
value.toolName === 'code_exec') &&
|
|
720
718
|
value.target.toolName === value.toolName &&
|
|
721
719
|
Array.isArray(value.providerAliasTargets) &&
|
|
@@ -20,7 +20,7 @@ export function codeObservationEvidence(records, result, observation) {
|
|
|
20
20
|
isRecord(record.payload) &&
|
|
21
21
|
record.payload.role === 'tool_call' &&
|
|
22
22
|
record.payload.callId === parentId &&
|
|
23
|
-
|
|
23
|
+
record.payload.name === 'code_exec');
|
|
24
24
|
if (!parent)
|
|
25
25
|
return undefined;
|
|
26
26
|
const original = records.find((record) => record.recordId === result.recordId) ?? result;
|
|
@@ -31,9 +31,7 @@ export function codeObservationEvidence(records, result, observation) {
|
|
|
31
31
|
record.type === 'tool.completed' &&
|
|
32
32
|
isRecord(record.payload) &&
|
|
33
33
|
record.payload.callId === outerId &&
|
|
34
|
-
(record.payload.toolName === 'code_exec' ||
|
|
35
|
-
record.payload.toolName === 'code_mode' ||
|
|
36
|
-
record.payload.toolName === 'code_exec_wait'));
|
|
34
|
+
(record.payload.toolName === 'code_exec' || record.payload.toolName === 'code_exec_wait'));
|
|
37
35
|
if (!outer ||
|
|
38
36
|
codeCellCompletionSequence(records, outer) === undefined ||
|
|
39
37
|
records.some((record) => record.sequence < result.sequence &&
|
|
@@ -324,8 +324,6 @@ function isNonnegativeInteger(value) {
|
|
|
324
324
|
export function codeCellCompletionSequence(records, completed) {
|
|
325
325
|
if (!isRecord(completed.payload))
|
|
326
326
|
return undefined;
|
|
327
|
-
if (completed.payload.toolName === 'code_mode')
|
|
328
|
-
return completed.sequence;
|
|
329
327
|
const data = completed.payload.data;
|
|
330
328
|
if (!isRecord(data) || typeof data.cellId !== 'string')
|
|
331
329
|
return undefined;
|
|
@@ -13,7 +13,7 @@ export function toolCallers(tool) {
|
|
|
13
13
|
export function allowsToolCaller(tool, caller) {
|
|
14
14
|
// Control tools cannot be widened by a Host override or historical definition.
|
|
15
15
|
if (caller === 'programmatic' &&
|
|
16
|
-
['code_exec', 'code_exec_wait', '
|
|
16
|
+
['code_exec', 'code_exec_wait', 'tool_search', 'question', 'skill'].includes(tool.name))
|
|
17
17
|
return false;
|
|
18
18
|
return toolCallers(tool).includes(caller);
|
|
19
19
|
}
|
|
@@ -9,7 +9,9 @@ export class CodeCellExecutionError extends MarAgentError {
|
|
|
9
9
|
result;
|
|
10
10
|
constructor(error, result) {
|
|
11
11
|
const diagnostic = describeMarAgentError(error, 'MAR_AGENT_CODE_FAILED');
|
|
12
|
-
super(diagnostic.code, diagnostic.message.
|
|
12
|
+
super(diagnostic.code, diagnostic.message.startsWith(`${diagnostic.code}: `)
|
|
13
|
+
? diagnostic.message.slice(diagnostic.code.length + 2)
|
|
14
|
+
: diagnostic.message, {
|
|
13
15
|
cause: error,
|
|
14
16
|
...(error instanceof MarAgentError ? { retryable: error.retryable } : {})
|
|
15
17
|
});
|
|
@@ -30,7 +30,7 @@ Tool calls:
|
|
|
30
30
|
- 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.
|
|
31
31
|
|
|
32
32
|
Built-in namespaces:
|
|
33
|
-
- 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.
|
|
33
|
+
- 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.
|
|
34
34
|
- observe.text(value): void registers bounded text/JSON values. observe.image(value): void registers one image value using the existing capability, MIME, byte and count limits. 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.
|
|
35
35
|
- 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.
|
|
36
36
|
- catalog.tools() returns a read-only snapshot of the tools callable in this cell, including name, description, inputSchema and inputMode. It does not discover or authorize additional tools.
|
|
@@ -526,7 +526,13 @@ export class CodeModeTool {
|
|
|
526
526
|
await write({
|
|
527
527
|
id,
|
|
528
528
|
ok: false,
|
|
529
|
-
error: {
|
|
529
|
+
error: {
|
|
530
|
+
code: diagnostic.code,
|
|
531
|
+
// The guest carries the code separately; the outer error adds its own prefix.
|
|
532
|
+
message: diagnostic.message.startsWith(`${diagnostic.code}: `)
|
|
533
|
+
? diagnostic.message.slice(diagnostic.code.length + 2)
|
|
534
|
+
: diagnostic.message
|
|
535
|
+
}
|
|
530
536
|
});
|
|
531
537
|
}
|
|
532
538
|
})().catch(fail);
|
|
@@ -34,14 +34,17 @@ export async function createCodeModeEngine(options) {
|
|
|
34
34
|
wake?.();
|
|
35
35
|
wake = undefined;
|
|
36
36
|
};
|
|
37
|
-
const fail = (handle) => {
|
|
37
|
+
const fail = (handle, locateSource = false) => {
|
|
38
38
|
const error = vm.dump(handle);
|
|
39
39
|
handle.dispose();
|
|
40
40
|
if (input.signal.aborted)
|
|
41
41
|
throw input.signal.reason;
|
|
42
42
|
if (Date.now() >= deadline)
|
|
43
43
|
throw diagnostic('MAR_AGENT_CODE_TIMEOUT', 'JavaScript execution exceeded its deadline.');
|
|
44
|
-
|
|
44
|
+
let message = String(error?.message ?? error).slice(0, 4096);
|
|
45
|
+
const location = locateSource ? compilerSourceLocation(error, input.code) : '';
|
|
46
|
+
if (location)
|
|
47
|
+
message = message.slice(0, 4096 - location.length) + location;
|
|
45
48
|
const code = message.includes('out of memory')
|
|
46
49
|
? 'MAR_AGENT_CODE_MEMORY_LIMIT'
|
|
47
50
|
: typeof error?.code === 'string'
|
|
@@ -476,7 +479,7 @@ export async function createCodeModeEngine(options) {
|
|
|
476
479
|
try {
|
|
477
480
|
const evaluated = vm.evalCode(`(async () => {\n${input.code}\n})()`, 'code-mode.js');
|
|
478
481
|
if (evaluated.error)
|
|
479
|
-
fail(evaluated.error);
|
|
482
|
+
fail(evaluated.error, true);
|
|
480
483
|
main = evaluated.value;
|
|
481
484
|
for (;;) {
|
|
482
485
|
input.signal.throwIfAborted();
|
|
@@ -625,6 +628,30 @@ function streamText(value, emit) {
|
|
|
625
628
|
};
|
|
626
629
|
write(value, '');
|
|
627
630
|
}
|
|
631
|
+
function compilerSourceLocation(error, source) {
|
|
632
|
+
if (error?.name !== 'SyntaxError' ||
|
|
633
|
+
error.fileName !== 'code-mode.js' ||
|
|
634
|
+
!Number.isSafeInteger(error.lineNumber) ||
|
|
635
|
+
error.lineNumber <= 1)
|
|
636
|
+
return '';
|
|
637
|
+
// QuickJS counts LF lines and Unicode code-point columns; the wrapper adds one LF line.
|
|
638
|
+
const lines = source.split('\n');
|
|
639
|
+
const line = error.lineNumber - 1;
|
|
640
|
+
if (line > lines.length)
|
|
641
|
+
return ` (code-mode.js:${source.split(/\r\n|[\r\n\u2028\u2029]/u).length}, end of input)`;
|
|
642
|
+
const column = Number(typeof error.stack === 'string'
|
|
643
|
+
? error.stack.match(/^\s*at code-mode\.js:\d+:(\d+)(?:\n|$)/u)?.[1]
|
|
644
|
+
: undefined);
|
|
645
|
+
if (!Number.isSafeInteger(column) || column < 1)
|
|
646
|
+
return '';
|
|
647
|
+
const prefix = [
|
|
648
|
+
...lines.slice(0, line - 1),
|
|
649
|
+
Array.from(lines[line - 1])
|
|
650
|
+
.slice(0, column - 1)
|
|
651
|
+
.join('')
|
|
652
|
+
].join('\n');
|
|
653
|
+
return ` (code-mode.js:${prefix.split(/\r\n|[\r\n\u2028\u2029]/u).length})`;
|
|
654
|
+
}
|
|
628
655
|
function diagnostic(code, message) {
|
|
629
656
|
return Object.assign(new Error(message), { code });
|
|
630
657
|
}
|