@myagentroam/agent 0.9.135 → 0.9.137
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/cli/main.js +1 -1
- package/dist/host/local-agent-host.d.ts +9 -7
- package/dist/host/local-agent-host.js +77 -5
- package/dist/host/local-process-executor.d.ts +2 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1 -0
- package/dist/model/catalog-file.d.ts +2 -0
- package/dist/model/configuration.d.ts +5 -0
- package/dist/model/configuration.js +8 -0
- package/dist/model/contracts.d.ts +7 -0
- package/dist/model/openai-responses.d.ts +1 -1
- package/dist/model/openai-responses.js +85 -20
- package/dist/prompts/index.d.ts +2 -1
- package/dist/prompts/index.js +2 -2
- package/dist/prompts/workflow.d.ts +1 -1
- package/dist/prompts/workflow.js +9 -2
- package/dist/runtime/context-gc-runtime.d.ts +1 -0
- package/dist/runtime/context-gc-runtime.js +3 -0
- package/dist/runtime/context-gc-tokens.d.ts +1 -0
- package/dist/runtime/context-gc-tokens.js +1 -1
- package/dist/runtime/context-gc.d.ts +1 -0
- package/dist/runtime/context-gc.js +85 -8
- package/dist/runtime/context-projection.js +19 -2
- package/dist/sandbox/linux/bubblewrap-sandbox-executor.js +29 -2
- package/dist/sdk/agent.js +249 -26
- package/dist/sdk/mcp-catalog.d.ts +13 -0
- package/dist/sdk/mcp-catalog.js +219 -0
- package/dist/sdk/types.d.ts +53 -1
- package/dist/session/context-gc-checkpoint.d.ts +7 -1
- package/dist/session/context-gc-checkpoint.js +28 -2
- package/dist/session/context-gc-replacements.d.ts +7 -0
- package/dist/session/context-gc-replacements.js +26 -0
- package/dist/session/jsonl-store.d.ts +6 -0
- package/dist/session/jsonl-store.js +92 -54
- package/dist/subagent/scheduler.d.ts +3 -3
- package/dist/subagent/session-controller.d.ts +1 -1
- package/dist/tools/agent-cancel.js +1 -0
- package/dist/tools/agent-message.js +1 -0
- package/dist/tools/agent-start.js +1 -0
- package/dist/tools/agent-wait.js +1 -0
- package/dist/tools/apply-patch.js +2 -1
- package/dist/tools/callers.d.ts +6 -0
- package/dist/tools/callers.js +23 -0
- package/dist/tools/code-mode/engine.d.ts +43 -0
- package/dist/tools/code-mode/engine.js +1 -0
- package/dist/tools/code-mode/quickjs-engine.d.ts +2 -0
- package/dist/tools/code-mode/quickjs-engine.js +454 -0
- package/dist/tools/code-mode/state.d.ts +20 -0
- package/dist/tools/code-mode/state.js +82 -0
- package/dist/tools/code-mode/worker.d.ts +1 -0
- package/dist/tools/code-mode/worker.js +65 -0
- package/dist/tools/code-mode.d.ts +8 -4
- package/dist/tools/code-mode.js +154 -120
- package/dist/tools/exec.js +1 -0
- package/dist/tools/execution-limits.d.ts +8 -0
- package/dist/tools/execution-limits.js +8 -0
- package/dist/tools/local-registry.d.ts +2 -0
- package/dist/tools/local-registry.js +1 -1
- package/dist/tools/question.js +1 -0
- package/dist/tools/read.js +1 -0
- package/dist/tools/registry.js +3 -0
- package/dist/tools/runtime-context.d.ts +2 -0
- package/dist/tools/runtime.js +3 -1
- package/dist/tools/skill.js +1 -0
- package/dist/tools/todo-read.js +1 -0
- package/dist/tools/todo-write.js +1 -0
- package/dist/tools/tool-search.d.ts +43 -0
- package/dist/tools/tool-search.js +284 -0
- package/dist/tools/view-image.js +1 -0
- package/dist/tools/web-fetch.js +1 -0
- package/dist/tools/web-search.js +1 -0
- package/package.json +3 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ContextGcCheckpointCache, contextGcBaseFromRecords, contextGcLogicalPathKey, contextGcMinimumUsageGrowth, contextGcRecordSourceHash, contextGcTargetKey, normalizeContextGcReplacements } from '../session/context-gc-checkpoint.js';
|
|
2
|
-
import { contextGcApplyPatchInputReplacement, contextGcExecInputReplacement, contextGcExecOutputReplacement, contextGcPatchResultFromCompletedPayload, contextGcStaleReadReplacement, contextGcWebOutputReplacement, normalizeContextGcExecResult } from '../session/context-gc-replacements.js';
|
|
2
|
+
import { contextGcApplyPatchInputReplacement, contextGcCodeModeInputReplacement, contextGcCodeModeOutputReplacement, contextGcExecInputReplacement, contextGcExecOutputReplacement, contextGcPatchResultFromCompletedPayload, contextGcStaleReadReplacement, contextGcWebOutputReplacement, normalizeContextGcCodeModeInput, normalizeContextGcExecResult } from '../session/context-gc-replacements.js';
|
|
3
3
|
import { contextGcSubagentNeedsRetainedPriorFinal, contextGcSubagentOutputReplacement, contextGcSubagentPriorFinalIsRetained, contextGcSubagentSnapshotIsPreciselyCovered, contextGcSubagentSnapshotIsSuperseded, contextGcSubagentSnapshotTurnId, normalizeContextGcSubagentSnapshot } from '../session/context-gc-subagent.js';
|
|
4
4
|
import { parseReadContextOutput } from '../tools/read-context.js';
|
|
5
5
|
import { CONTEXT_GC_TOKEN_ESTIMATOR, contextGcCacheImpact, contextGcMessageTokens, contextGcPrefixTokens, contextGcReclaimedTokens } from './context-gc-tokens.js';
|
|
@@ -167,8 +167,12 @@ export function inspectContextGc(input) {
|
|
|
167
167
|
});
|
|
168
168
|
if (stageAPlan?.economics.passes) {
|
|
169
169
|
const exec = collectExecCandidates(input, groups, existingTargets, usageRatio);
|
|
170
|
+
const codeMode = collectCodeModeCandidates(input, groups, existingTargets, usageRatio);
|
|
170
171
|
const web = collectWebCandidates(input, groups, existingTargets, usageRatio);
|
|
171
|
-
const protectedCandidateTokens = deterministicProtectedTokens +
|
|
172
|
+
const protectedCandidateTokens = deterministicProtectedTokens +
|
|
173
|
+
exec.protectedTokens +
|
|
174
|
+
codeMode.protectedTokens +
|
|
175
|
+
web.protectedTokens;
|
|
172
176
|
const stageAPlanWithProtectedCandidates = evaluateCandidateSet(input, existing, deterministicCandidates, {
|
|
173
177
|
stage: 'STAGE_A',
|
|
174
178
|
contextUsageTokens,
|
|
@@ -177,7 +181,7 @@ export function inspectContextGc(input) {
|
|
|
177
181
|
normalRolloutOrdinal,
|
|
178
182
|
protectedCandidateTokens
|
|
179
183
|
}) ?? stageAPlan;
|
|
180
|
-
const marginal = mergeMarginalLargeOutputCandidates(input, existing, deterministicCandidates, [...exec.eligible, ...web.eligible], stageAPlanWithProtectedCandidates, {
|
|
184
|
+
const marginal = mergeMarginalLargeOutputCandidates(input, existing, deterministicCandidates, [...exec.eligible, ...codeMode.eligible, ...web.eligible], stageAPlanWithProtectedCandidates, {
|
|
181
185
|
contextUsageTokens,
|
|
182
186
|
usageRatio,
|
|
183
187
|
usageRecord,
|
|
@@ -185,7 +189,7 @@ export function inspectContextGc(input) {
|
|
|
185
189
|
protectedCandidateTokens
|
|
186
190
|
});
|
|
187
191
|
const plan = finalizePlan(input, marginal ?? stageAPlanWithProtectedCandidates);
|
|
188
|
-
const retryAfterRollouts = Math.min(exec.retryAfterRollouts, web.retryAfterRollouts);
|
|
192
|
+
const retryAfterRollouts = Math.min(exec.retryAfterRollouts, codeMode.retryAfterRollouts, web.retryAfterRollouts);
|
|
189
193
|
return plan
|
|
190
194
|
? {
|
|
191
195
|
plan,
|
|
@@ -196,26 +200,99 @@ export function inspectContextGc(input) {
|
|
|
196
200
|
: {};
|
|
197
201
|
}
|
|
198
202
|
const exec = collectExecCandidates(input, groups, existingTargets, usageRatio);
|
|
203
|
+
const codeMode = collectCodeModeCandidates(input, groups, existingTargets, usageRatio);
|
|
199
204
|
const web = collectWebCandidates(input, groups, existingTargets, usageRatio);
|
|
200
|
-
const combined = evaluateCandidateSet(input, existing, [...deterministicCandidates, ...exec.eligible, ...web.eligible], {
|
|
205
|
+
const combined = evaluateCandidateSet(input, existing, [...deterministicCandidates, ...exec.eligible, ...codeMode.eligible, ...web.eligible], {
|
|
201
206
|
stage: 'STAGE_A_AND_EXEC',
|
|
202
207
|
contextUsageTokens,
|
|
203
208
|
usageRatio,
|
|
204
209
|
usageRecord,
|
|
205
210
|
normalRolloutOrdinal,
|
|
206
|
-
protectedCandidateTokens: deterministicProtectedTokens +
|
|
211
|
+
protectedCandidateTokens: deterministicProtectedTokens +
|
|
212
|
+
exec.protectedTokens +
|
|
213
|
+
codeMode.protectedTokens +
|
|
214
|
+
web.protectedTokens
|
|
207
215
|
});
|
|
208
216
|
if (combined?.economics.passes) {
|
|
209
217
|
const plan = finalizePlan(input, combined);
|
|
210
218
|
return plan ? { plan } : {};
|
|
211
219
|
}
|
|
212
|
-
const retryAfterRollouts = Math.min(stageA.retryAfterRollouts, subagent.retryAfterRollouts, exec.retryAfterRollouts, web.retryAfterRollouts);
|
|
213
|
-
return deterministicProtectedTokens +
|
|
220
|
+
const retryAfterRollouts = Math.min(stageA.retryAfterRollouts, subagent.retryAfterRollouts, exec.retryAfterRollouts, codeMode.retryAfterRollouts, web.retryAfterRollouts);
|
|
221
|
+
return deterministicProtectedTokens +
|
|
222
|
+
exec.protectedTokens +
|
|
223
|
+
codeMode.protectedTokens +
|
|
224
|
+
web.protectedTokens >=
|
|
214
225
|
contextGcMinimumReclaimedTokens(contextUsageTokens, input.contextWindowTokens) &&
|
|
215
226
|
Number.isFinite(retryAfterRollouts)
|
|
216
227
|
? { retryAfterRollouts }
|
|
217
228
|
: {};
|
|
218
229
|
}
|
|
230
|
+
function collectCodeModeCandidates(input, groups, existingTargets, usageRatio) {
|
|
231
|
+
const eligible = [];
|
|
232
|
+
let protectedTokens = 0;
|
|
233
|
+
let retryAfterRollouts = Infinity;
|
|
234
|
+
for (const group of [...groups.values()].filter((item) => item.toolName === 'code_mode')) {
|
|
235
|
+
if (!group.call ||
|
|
236
|
+
!group.result ||
|
|
237
|
+
group.failed ||
|
|
238
|
+
!group.completed ||
|
|
239
|
+
group.call.message.role !== 'tool_call' ||
|
|
240
|
+
group.result.message.role !== 'tool' ||
|
|
241
|
+
typeof group.result.message.content !== 'string')
|
|
242
|
+
continue;
|
|
243
|
+
const code = normalizeContextGcCodeModeInput(group.call.message.arguments);
|
|
244
|
+
const completedPayload = group.completed.payload;
|
|
245
|
+
if (!code || !isRecord(completedPayload) || typeof completedPayload.truncated !== 'boolean')
|
|
246
|
+
continue;
|
|
247
|
+
const visibleTokens = contextGcMessageTokens(input, [
|
|
248
|
+
group.call.message,
|
|
249
|
+
group.result.message,
|
|
250
|
+
...group.aliases.map((alias) => alias.message)
|
|
251
|
+
]);
|
|
252
|
+
const minimumVisibleTokens = usageRatio >= COMPACT_CREDIT_ACTIVATION_RATIO
|
|
253
|
+
? HIGH_WATER_LARGE_TERMINAL_OUTPUT_TOKENS
|
|
254
|
+
: LARGE_TERMINAL_OUTPUT_TOKENS;
|
|
255
|
+
if (visibleTokens < minimumVisibleTokens)
|
|
256
|
+
continue;
|
|
257
|
+
const callTarget = targetFor(group.call.record, group.call.message);
|
|
258
|
+
const resultTarget = targetFor(group.result.record, group.result.message);
|
|
259
|
+
if (!callTarget || !resultTarget)
|
|
260
|
+
continue;
|
|
261
|
+
const evidenceSequence = group.result.record.sequence;
|
|
262
|
+
const replacements = [];
|
|
263
|
+
if (!existingTargets.has(contextGcTargetKey(callTarget)))
|
|
264
|
+
replacements.push({
|
|
265
|
+
kind: 'TOOL_CALL_INPUT',
|
|
266
|
+
toolName: 'code_mode',
|
|
267
|
+
callId: group.callId,
|
|
268
|
+
target: callTarget,
|
|
269
|
+
replacementArguments: contextGcCodeModeInputReplacement(code),
|
|
270
|
+
providerAliasTargets: group.aliases
|
|
271
|
+
.map(({ record, message }) => targetFor(record, message))
|
|
272
|
+
.filter((target) => target !== undefined),
|
|
273
|
+
evidenceSequence
|
|
274
|
+
});
|
|
275
|
+
if (!existingTargets.has(contextGcTargetKey(resultTarget)))
|
|
276
|
+
replacements.push({
|
|
277
|
+
kind: 'CODE_MODE_OUTPUT',
|
|
278
|
+
callId: group.callId,
|
|
279
|
+
target: resultTarget,
|
|
280
|
+
replacementContent: contextGcCodeModeOutputReplacement(group.result.message.content, completedPayload.truncated),
|
|
281
|
+
evidenceSequence
|
|
282
|
+
});
|
|
283
|
+
if (replacements.length === 0)
|
|
284
|
+
continue;
|
|
285
|
+
const observedRollouts = successfulRolloutsAfter(input.records, evidenceSequence, input.modelId, input.contextWindowTokens);
|
|
286
|
+
const candidate = { replacements, observedRollouts, evidenceSequence };
|
|
287
|
+
if (observedRollouts >= CONTEXT_GC_POLICY.largeExecProtectionRollouts)
|
|
288
|
+
eligible.push(candidate);
|
|
289
|
+
else {
|
|
290
|
+
protectedTokens += candidateTokens(input, candidate);
|
|
291
|
+
retryAfterRollouts = Math.min(retryAfterRollouts, CONTEXT_GC_POLICY.largeExecProtectionRollouts - observedRollouts);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return { eligible, protectedTokens, retryAfterRollouts };
|
|
295
|
+
}
|
|
219
296
|
function mergeMarginalLargeOutputCandidates(input, existing, deterministicCandidates, execCandidates, stageAPlan, state) {
|
|
220
297
|
let selected = [...deterministicCandidates];
|
|
221
298
|
let current = stageAPlan;
|
|
@@ -61,6 +61,7 @@ export function applyContextGcReplacementsToMessages(messages, messageSources, r
|
|
|
61
61
|
else if (replacement.kind === 'TOOL_CALL_INPUT' && next.role === 'tool_call')
|
|
62
62
|
next = { ...next, arguments: structuredClone(replacement.replacementArguments) };
|
|
63
63
|
else if ((replacement.kind === 'EXEC_OUTPUT' ||
|
|
64
|
+
replacement.kind === 'CODE_MODE_OUTPUT' ||
|
|
64
65
|
replacement.kind === 'SUBAGENT_OUTPUT' ||
|
|
65
66
|
replacement.kind === 'WEB_OUTPUT') &&
|
|
66
67
|
next.role === 'tool')
|
|
@@ -117,7 +118,19 @@ export function restoreModelContext(payload, providerModelId) {
|
|
|
117
118
|
if (payload.role === 'tool' &&
|
|
118
119
|
typeof payload.content === 'string' &&
|
|
119
120
|
typeof payload.callId === 'string')
|
|
120
|
-
return {
|
|
121
|
+
return {
|
|
122
|
+
role: 'tool',
|
|
123
|
+
content: payload.content,
|
|
124
|
+
callId: payload.callId,
|
|
125
|
+
...(Array.isArray(payload.toolSearchTools)
|
|
126
|
+
? {
|
|
127
|
+
toolSearchTools: payload.toolSearchTools.filter((tool) => isRecord(tool) &&
|
|
128
|
+
typeof tool.name === 'string' &&
|
|
129
|
+
typeof tool.description === 'string' &&
|
|
130
|
+
isRecord(tool.inputSchema))
|
|
131
|
+
}
|
|
132
|
+
: {})
|
|
133
|
+
};
|
|
121
134
|
if (payload.role === 'tool_call' &&
|
|
122
135
|
typeof payload.callId === 'string' &&
|
|
123
136
|
typeof payload.name === 'string')
|
|
@@ -164,13 +177,17 @@ export function restoreModelContext(payload, providerModelId) {
|
|
|
164
177
|
export function providerToolCallId(message) {
|
|
165
178
|
if (message.role !== 'provider' || message.provider !== 'OPENAI_RESPONSES' || !message.item)
|
|
166
179
|
return undefined;
|
|
167
|
-
if (message.item.type !== 'function_call' &&
|
|
180
|
+
if (message.item.type !== 'function_call' &&
|
|
181
|
+
message.item.type !== 'custom_tool_call' &&
|
|
182
|
+
message.item.type !== 'tool_search_call')
|
|
168
183
|
return undefined;
|
|
169
184
|
return typeof message.item.call_id === 'string' ? message.item.call_id : undefined;
|
|
170
185
|
}
|
|
171
186
|
export function providerToolName(message) {
|
|
172
187
|
if (message.role !== 'provider' || !message.item)
|
|
173
188
|
return undefined;
|
|
189
|
+
if (message.item.type === 'tool_search_call')
|
|
190
|
+
return 'tool_search';
|
|
174
191
|
return typeof message.item.name === 'string' ? message.item.name : undefined;
|
|
175
192
|
}
|
|
176
193
|
function targetFromMessage(record, message) {
|
|
@@ -61,13 +61,14 @@ export class BubblewrapSandboxExecutor {
|
|
|
61
61
|
validateProfile(this.options.profile);
|
|
62
62
|
await validateBackend(this.#bubblewrapPath);
|
|
63
63
|
const mounts = await this.#mounts();
|
|
64
|
+
const runtimeMounts = await trustedRuntimeMounts(request.runtimeDirectories ?? [], mounts);
|
|
64
65
|
const cwd = await workingDirectory(request, mounts, this.options.profile.workingDirectory);
|
|
65
66
|
const command = sandboxCommand(request, mounts);
|
|
66
67
|
const launchDirectory = await mkdtemp(join(tmpdir(), 'mar-agent-bwrap-launch-'));
|
|
67
68
|
const argumentPath = join(launchDirectory, 'arguments');
|
|
68
69
|
const seccompPath = join(launchDirectory, 'seccomp.bpf');
|
|
69
70
|
try {
|
|
70
|
-
const arguments_ = this.#arguments(mounts, cwd, request);
|
|
71
|
+
const arguments_ = this.#arguments(mounts, cwd, request, runtimeMounts);
|
|
71
72
|
await Promise.all([
|
|
72
73
|
writeFile(argumentPath, `${arguments_.join('\0')}\0`, { mode: 0o600, flag: 'wx' }),
|
|
73
74
|
writeFile(seccompPath, seccompFilter(process.arch), { mode: 0o600, flag: 'wx' })
|
|
@@ -150,7 +151,7 @@ export class BubblewrapSandboxExecutor {
|
|
|
150
151
|
await prepareNestedMountDestinations(ordered);
|
|
151
152
|
return ordered;
|
|
152
153
|
}
|
|
153
|
-
#arguments(mounts, cwd, request) {
|
|
154
|
+
#arguments(mounts, cwd, request, runtimeMounts) {
|
|
154
155
|
const networkMode = this.options.profile.networkMode ?? 'NONE';
|
|
155
156
|
const temporaryDirectory = this.options.profile.temporaryDirectory ?? { kind: 'EPHEMERAL' };
|
|
156
157
|
const args = [
|
|
@@ -186,6 +187,8 @@ export class BubblewrapSandboxExecutor {
|
|
|
186
187
|
'--tmpfs',
|
|
187
188
|
'/',
|
|
188
189
|
...runtimeMountArguments(),
|
|
190
|
+
...sandboxDirectoryArguments(runtimeMounts),
|
|
191
|
+
...runtimeMounts.flatMap((mount) => ['--ro-bind', mount.source, mount.destination]),
|
|
189
192
|
...sandboxDirectoryArguments(mounts),
|
|
190
193
|
...(temporaryDirectory.kind === 'EPHEMERAL' ? ['--tmpfs', '/tmp'] : []),
|
|
191
194
|
'--proc',
|
|
@@ -512,6 +515,30 @@ function sandboxDirectoryArguments(mounts) {
|
|
|
512
515
|
})
|
|
513
516
|
.flatMap((directory) => ['--dir', directory]);
|
|
514
517
|
}
|
|
518
|
+
/** Host assets retain absolute module URLs, but cannot overlay or widen profile mounts. */
|
|
519
|
+
async function trustedRuntimeMounts(directories, mounts) {
|
|
520
|
+
if (!Array.isArray(directories) || directories.length > 16)
|
|
521
|
+
throw policyInvalid();
|
|
522
|
+
const result = [];
|
|
523
|
+
for (const path of directories) {
|
|
524
|
+
if (typeof path !== 'string' || path.length > 4096)
|
|
525
|
+
throw policyInvalid();
|
|
526
|
+
const source = await secureDirectory(path);
|
|
527
|
+
if (source.split('/').filter(Boolean).length < 3)
|
|
528
|
+
throw policyInvalid();
|
|
529
|
+
const overlaps = (left, right) => left === right || within(left, right) || within(right, left);
|
|
530
|
+
if (mounts.some((mount) => overlaps(source, mount.source) || overlaps(source, mount.destination)) ||
|
|
531
|
+
['/home/mar', '/runtime', '/etc', '/proc', '/dev', '/run', '/tmp'].some((root) => overlaps(source, root)))
|
|
532
|
+
throw policyInvalid();
|
|
533
|
+
// These trees are already exposed read-only by the fixed runtime policy.
|
|
534
|
+
if (['/usr', '/bin', '/sbin', '/lib', '/lib64'].some((root) => within(root, source)))
|
|
535
|
+
continue;
|
|
536
|
+
if (result.some((mount) => overlaps(source, mount.source)))
|
|
537
|
+
throw policyInvalid();
|
|
538
|
+
result.push({ source, destination: source, access: 'READ_ONLY' });
|
|
539
|
+
}
|
|
540
|
+
return result;
|
|
541
|
+
}
|
|
515
542
|
function runtimeMountArguments() {
|
|
516
543
|
const args = [];
|
|
517
544
|
const nodeRuntimeDirectory = resolve(process.execPath, '..', '..');
|