@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
|
@@ -5,6 +5,7 @@ import { basename, join } from 'node:path';
|
|
|
5
5
|
import { setTimeout as delay } from 'node:timers/promises';
|
|
6
6
|
import { isDeepStrictEqual } from 'node:util';
|
|
7
7
|
import { MarAgentError } from '../error.js';
|
|
8
|
+
import { applyCodeModeStateMutations, parseCodeModeStateMutations, restoreCodeModeState } from '../tools/code-mode/state.js';
|
|
8
9
|
import { todoItemsFromSnapshot } from '../tools/todo.js';
|
|
9
10
|
import { contextGcBaseFromRecords, contextGcBaseSequence, contextGcMinimumUsageGrowth, contextGcSourceProjectionHash, latestValidContextGcCheckpoint, normalizeContextGcReplacements, parseContextGcCheckpoint, sameContextGcBase, validateContextGcCheckpoint } from './context-gc-checkpoint.js';
|
|
10
11
|
import { beginSessionStorageTransaction, isUnjournaledTransactionFile, recoverSessionStorageTransaction } from './transaction-recovery.js';
|
|
@@ -521,20 +522,31 @@ export class JsonlSessionStore {
|
|
|
521
522
|
this.#shared.pendingSessions.set(target.id, target);
|
|
522
523
|
let discard = false;
|
|
523
524
|
try {
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
525
|
+
const copied = [
|
|
526
|
+
{
|
|
527
|
+
schemaVersion: 1,
|
|
528
|
+
recordId: randomUUID(),
|
|
529
|
+
sequence: 1,
|
|
530
|
+
timestamp: createdAt,
|
|
531
|
+
sessionId: target.id,
|
|
532
|
+
type: 'session.created',
|
|
533
|
+
payload: {
|
|
534
|
+
title: target.title,
|
|
535
|
+
workspace: target.workspace,
|
|
536
|
+
automaticTitle: false,
|
|
537
|
+
source: target.source
|
|
538
|
+
}
|
|
531
539
|
}
|
|
532
|
-
|
|
540
|
+
];
|
|
533
541
|
const retained = input.boundaryTurnId === null ? [] : records.slice(1, boundaryIndex + 1);
|
|
534
542
|
for (const record of retained) {
|
|
535
543
|
if (record.type === 'context.gc.completed' || record.type === 'responses.continuation')
|
|
536
544
|
continue;
|
|
537
|
-
|
|
545
|
+
copied.push({
|
|
546
|
+
schemaVersion: 1,
|
|
547
|
+
recordId: randomUUID(),
|
|
548
|
+
sequence: copied.length + 1,
|
|
549
|
+
sessionId: target.id,
|
|
538
550
|
type: record.type,
|
|
539
551
|
payload: forkedPayload(record.type, record.payload, sourceSessionId, target.id, input.title),
|
|
540
552
|
...(record.executionId === undefined ? {} : { executionId: record.executionId }),
|
|
@@ -542,6 +554,15 @@ export class JsonlSessionStore {
|
|
|
542
554
|
timestamp: record.timestamp
|
|
543
555
|
});
|
|
544
556
|
}
|
|
557
|
+
// A fork is unpublished until every segment and referenced image is durable.
|
|
558
|
+
const staged = await stageSessionSegments(this.sessionDirectory(target.id), copied, 'fork');
|
|
559
|
+
for (const file of staged.files)
|
|
560
|
+
await rename(file.temporaryPath, file.path);
|
|
561
|
+
target.segments = staged.segments;
|
|
562
|
+
target.nextSequence = copied.length + 1;
|
|
563
|
+
this.#shared.segments.set(target.id, staged.segments.length);
|
|
564
|
+
for (const record of copied)
|
|
565
|
+
this.#applyRecordToResumeIndex(target, record);
|
|
545
566
|
await copyGeneratedImages(this.sessionDirectory(sourceSessionId), this.sessionDirectory(target.id), generatedImageFileNames(retained));
|
|
546
567
|
await copyInputImages(this.sessionDirectory(sourceSessionId), this.sessionDirectory(target.id), inputImageReferencesFromRecords(retained));
|
|
547
568
|
target.lastActivityAt = target.createdAt;
|
|
@@ -621,7 +642,7 @@ export class JsonlSessionStore {
|
|
|
621
642
|
const retained = records
|
|
622
643
|
.slice(0, boundaryIndex + 1)
|
|
623
644
|
.filter((record) => record.type !== 'responses.continuation');
|
|
624
|
-
const staged = await
|
|
645
|
+
const staged = await stageSessionSegments(this.sessionDirectory(sessionId), retained);
|
|
625
646
|
const transactionId = randomUUID();
|
|
626
647
|
const targetNextSequence = (retained.at(-1)?.sequence ?? 0) + 1;
|
|
627
648
|
const contextualWorldStatePath = join(this.sessionDirectory(sessionId), CONTEXTUAL_WORLD_STATE_FILE);
|
|
@@ -765,7 +786,7 @@ export class JsonlSessionStore {
|
|
|
765
786
|
}
|
|
766
787
|
}
|
|
767
788
|
];
|
|
768
|
-
const staged = await
|
|
789
|
+
const staged = await stageSessionSegments(this.sessionDirectory(sessionId), retained);
|
|
769
790
|
const transactionId = randomUUID();
|
|
770
791
|
const contextualWorldStatePath = join(this.sessionDirectory(sessionId), CONTEXTUAL_WORLD_STATE_FILE);
|
|
771
792
|
const contextualWorldStateBackup = `${contextualWorldStatePath}.2.${transactionId}.clear-backup`;
|
|
@@ -966,6 +987,22 @@ export class JsonlSessionStore {
|
|
|
966
987
|
throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.', { cause });
|
|
967
988
|
}
|
|
968
989
|
}
|
|
990
|
+
async readCodeModeState(sessionId) {
|
|
991
|
+
return restoreCodeModeState(await this.read(sessionId));
|
|
992
|
+
}
|
|
993
|
+
async commitCodeModeState(sessionId, mutations, input) {
|
|
994
|
+
const parsed = parseCodeModeStateMutations(mutations);
|
|
995
|
+
if (parsed.length === 0)
|
|
996
|
+
return this.readCodeModeState(sessionId);
|
|
997
|
+
const state = applyCodeModeStateMutations(await this.readCodeModeState(sessionId), parsed);
|
|
998
|
+
await this.append(sessionId, {
|
|
999
|
+
type: 'code.state.updated',
|
|
1000
|
+
payload: { mutations: parsed },
|
|
1001
|
+
executionId: input.executionId,
|
|
1002
|
+
turnId: input.turnId
|
|
1003
|
+
});
|
|
1004
|
+
return state;
|
|
1005
|
+
}
|
|
969
1006
|
async readExecutionState(sessionId) {
|
|
970
1007
|
this.#assertOpen();
|
|
971
1008
|
const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
|
|
@@ -1637,55 +1674,56 @@ function generatedImageFileNames(records) {
|
|
|
1637
1674
|
}
|
|
1638
1675
|
return [...names];
|
|
1639
1676
|
}
|
|
1640
|
-
async function
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
const line = `${JSON.stringify(record)}\n`;
|
|
1644
|
-
const bytes = Buffer.byteLength(line);
|
|
1645
|
-
let group = groups.at(-1);
|
|
1646
|
-
if (group !== undefined && group.bytes > 0 && group.bytes + bytes > MAX_SEGMENT_BYTES)
|
|
1647
|
-
group = undefined;
|
|
1648
|
-
if (group === undefined) {
|
|
1649
|
-
group = {
|
|
1650
|
-
lines: [],
|
|
1651
|
-
bytes: 0,
|
|
1652
|
-
firstSequence: record.sequence,
|
|
1653
|
-
lastSequence: record.sequence
|
|
1654
|
-
};
|
|
1655
|
-
groups.push(group);
|
|
1656
|
-
}
|
|
1657
|
-
group.lines.push(line);
|
|
1658
|
-
group.bytes += bytes;
|
|
1659
|
-
group.lastSequence = record.sequence;
|
|
1660
|
-
}
|
|
1661
|
-
if (groups.length === 0)
|
|
1677
|
+
async function stageSessionSegments(sessionDirectory, records, operation = 'rollback') {
|
|
1678
|
+
let group;
|
|
1679
|
+
if (records.length === 0)
|
|
1662
1680
|
throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Session history is corrupt.');
|
|
1663
1681
|
const transactionId = randomUUID();
|
|
1664
1682
|
const files = [];
|
|
1683
|
+
const segments = [];
|
|
1684
|
+
const flush = async () => {
|
|
1685
|
+
if (group === undefined)
|
|
1686
|
+
return;
|
|
1687
|
+
const number = segments.length + 1;
|
|
1688
|
+
const path = join(sessionDirectory, `events-${String(number).padStart(6, '0')}.jsonl`);
|
|
1689
|
+
const temporaryPath = `${path}.${transactionId}.${operation}-tmp`;
|
|
1690
|
+
const handle = await open(temporaryPath, 'wx', 0o600);
|
|
1691
|
+
files.push({ path, temporaryPath });
|
|
1692
|
+
try {
|
|
1693
|
+
await handle.writeFile(group.lines.join(''));
|
|
1694
|
+
await handle.sync();
|
|
1695
|
+
}
|
|
1696
|
+
finally {
|
|
1697
|
+
await handle.close();
|
|
1698
|
+
}
|
|
1699
|
+
segments.push({
|
|
1700
|
+
number,
|
|
1701
|
+
firstSequence: group.firstSequence,
|
|
1702
|
+
lastSequence: group.lastSequence,
|
|
1703
|
+
bytes: group.bytes
|
|
1704
|
+
});
|
|
1705
|
+
group = undefined;
|
|
1706
|
+
};
|
|
1665
1707
|
try {
|
|
1666
|
-
for (const
|
|
1667
|
-
const
|
|
1668
|
-
const
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1708
|
+
for (const record of records) {
|
|
1709
|
+
const line = `${JSON.stringify(record)}\n`;
|
|
1710
|
+
const bytes = Buffer.byteLength(line);
|
|
1711
|
+
if (group !== undefined && group.bytes > 0 && group.bytes + bytes > MAX_SEGMENT_BYTES)
|
|
1712
|
+
await flush();
|
|
1713
|
+
if (group === undefined) {
|
|
1714
|
+
group = {
|
|
1715
|
+
lines: [],
|
|
1716
|
+
bytes: 0,
|
|
1717
|
+
firstSequence: record.sequence,
|
|
1718
|
+
lastSequence: record.sequence
|
|
1719
|
+
};
|
|
1677
1720
|
}
|
|
1678
|
-
|
|
1721
|
+
group.lines.push(line);
|
|
1722
|
+
group.bytes += bytes;
|
|
1723
|
+
group.lastSequence = record.sequence;
|
|
1679
1724
|
}
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
segments: groups.map((group, index) => ({
|
|
1683
|
-
number: index + 1,
|
|
1684
|
-
firstSequence: group.firstSequence,
|
|
1685
|
-
lastSequence: group.lastSequence,
|
|
1686
|
-
bytes: group.bytes
|
|
1687
|
-
}))
|
|
1688
|
-
};
|
|
1725
|
+
await flush();
|
|
1726
|
+
return { files, segments };
|
|
1689
1727
|
}
|
|
1690
1728
|
catch (error) {
|
|
1691
1729
|
await Promise.all(files.map((item) => rm(item.temporaryPath, { force: true }))).catch(() => undefined);
|
|
@@ -125,7 +125,7 @@ export declare class SubagentScheduler implements SubagentController {
|
|
|
125
125
|
turnId?: string;
|
|
126
126
|
deliveryStatus?: "accepted" | "applied" | "cancelled" | "failed";
|
|
127
127
|
} | {
|
|
128
|
-
waitOutcome: "
|
|
128
|
+
waitOutcome: "completion" | "timeout";
|
|
129
129
|
agentId: string;
|
|
130
130
|
description: string;
|
|
131
131
|
status: "queued" | "running" | "completed" | "failed" | "cancelled" | "interrupted";
|
|
@@ -172,7 +172,7 @@ export declare class SubagentScheduler implements SubagentController {
|
|
|
172
172
|
turnId?: string;
|
|
173
173
|
deliveryStatus?: "accepted" | "applied" | "cancelled" | "failed";
|
|
174
174
|
} | {
|
|
175
|
-
waitOutcome: "
|
|
175
|
+
waitOutcome: "completion" | "timeout";
|
|
176
176
|
agentId: string;
|
|
177
177
|
description: string;
|
|
178
178
|
status: "queued" | "running" | "completed" | "failed" | "cancelled" | "interrupted";
|
|
@@ -199,7 +199,7 @@ export declare class SubagentScheduler implements SubagentController {
|
|
|
199
199
|
message(_agentId: string, _message: string): Promise<SubagentTaskSnapshot>;
|
|
200
200
|
listSessionResources(): {
|
|
201
201
|
agentId: string;
|
|
202
|
-
status: "completed" | "cancelled" | "running" | "
|
|
202
|
+
status: "completed" | "cancelled" | "running" | "queued" | "failed";
|
|
203
203
|
description: string;
|
|
204
204
|
}[];
|
|
205
205
|
dispose(): Promise<void>;
|
|
@@ -91,7 +91,7 @@ export declare class SubagentSessionController implements SubagentController {
|
|
|
91
91
|
cancel(agentId: string): Promise<SubagentTaskSnapshot>;
|
|
92
92
|
listSessionResources(): {
|
|
93
93
|
agentId: string;
|
|
94
|
-
status: "completed" | "cancelled" | "running" | "
|
|
94
|
+
status: "completed" | "cancelled" | "running" | "queued" | "failed" | "interrupted";
|
|
95
95
|
description: string;
|
|
96
96
|
}[];
|
|
97
97
|
dispose(): Promise<void>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MarAgentError } from '../error.js';
|
|
2
2
|
export const agentCancelToolDefinition = {
|
|
3
3
|
name: 'agent_cancel',
|
|
4
|
+
allowedCallers: ['direct', 'programmatic'],
|
|
4
5
|
parallelSafety: 'serial',
|
|
5
6
|
description: 'Idempotently cancel a child agent using the agentId returned by agent_start. For an exec processId, use exec with action:"cancel" instead. Waits for a running task to reach cancelled and returns its agentId and description.',
|
|
6
7
|
inputSchema: {
|
|
@@ -2,6 +2,7 @@ import { MarAgentError } from '../error.js';
|
|
|
2
2
|
import { TOOL_EXECUTION_LIMITS } from './execution-limits.js';
|
|
3
3
|
export const agentMessageToolDefinition = {
|
|
4
4
|
name: 'agent_message',
|
|
5
|
+
allowedCallers: ['direct', 'programmatic'],
|
|
5
6
|
parallelSafety: 'serial',
|
|
6
7
|
description: 'Send a real user message to an existing child agent. Default delivery=append inserts guidance into a running child turn at the next safe boundary after the current model response or complete tool batch. Explicit delivery=replace immediately requests cancellation, waits for the old turn to close, then starts a new turn in the same Session. When idle, either mode starts a new turn using persisted history. Returns messageId, turnId, deliveryStatus, current status, and model metadata without repeating the child’s previous latestMessage, latestActivity, summary, or verification evidence. accepted means queued in memory; applied means persisted in model context, not that the guidance has been executed. Use agent_wait for subsequent progress or completion. Does not wait for the new task to complete or roll back existing side effects.',
|
|
7
8
|
inputSchema: {
|
|
@@ -3,6 +3,7 @@ import { marAgentReasoningEffortSchema } from '../model/configuration.js';
|
|
|
3
3
|
import { TOOL_EXECUTION_LIMITS } from './execution-limits.js';
|
|
4
4
|
export const agentStartToolDefinition = {
|
|
5
5
|
name: 'agent_start',
|
|
6
|
+
allowedCallers: ['direct', 'programmatic'],
|
|
6
7
|
parallelSafety: 'serial',
|
|
7
8
|
description: 'Start one bounded, non-recursive child agent with self-contained context. Use when an independent investigation would consume substantial main-context space or when safe parallel work has real value; keep small or tightly coupled work in the main context. All agents share the filesystem, so avoid conflicting writes. The optional reasoningEffort overrides the parent effort and must be supported by the selected model; omit it to inherit. Returns agentId for agent_wait, agent_message, or agent_cancel, description, queued/running/completed/failed/cancelled status, bounded summary, changedFiles, verification, and read evidence; background returns immediately while foreground waits for a terminal result.',
|
|
8
9
|
inputSchema: {
|
package/dist/tools/agent-wait.js
CHANGED
|
@@ -2,6 +2,7 @@ import { MarAgentError } from '../error.js';
|
|
|
2
2
|
import { TOOL_EXECUTION_LIMITS } from './execution-limits.js';
|
|
3
3
|
export const agentWaitToolDefinition = {
|
|
4
4
|
name: 'agent_wait',
|
|
5
|
+
allowedCallers: ['direct', 'programmatic'],
|
|
5
6
|
parallelSafety: 'serial',
|
|
6
7
|
description: 'Read or wait a bounded time for a child agent result. 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 with action:"poll" instead. 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. Every result includes 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.',
|
|
7
8
|
inputSchema: {
|
|
@@ -6,8 +6,9 @@ import { MarAgentError } from '../error.js';
|
|
|
6
6
|
import { TOOL_EXECUTION_LIMITS } from './execution-limits.js';
|
|
7
7
|
export const applyPatchToolDefinition = {
|
|
8
8
|
name: 'apply_patch',
|
|
9
|
+
allowedCallers: ['direct', 'programmatic'],
|
|
9
10
|
parallelSafety: 'serial',
|
|
10
|
-
description: `Preferred for precise, reviewable local edits. Do not batch all task files merely to reduce tool calls. Group only a few tightly coupled edits whose combined patch is quick to generate and review; split broad or independent work into successive bounded patches before composing them. Submit a raw *** Begin Patch / *** End Patch patch. Supports Add File, Update File, Delete File, and Move to. Add File may replace an existing regular file, and Move to may replace an existing regular destination; duplicate operations on the same resolved path remain invalid. Update hunks accept @@ or @@ <change context>; context-only hunks may also be used as ordered anchors before a later changing hunk. Context is searched forward with Codex-style exact, whitespace-tolerant, then common Unicode punctuation-tolerant matching. Syntax and resolved paths are validated before writing, then file units are committed in order. Each file unit is atomic, and a Move keeps its source and destination atomic. On MAR_AGENT_PATCH_PARTIAL, earlier files remain applied; the error lists applied, failed, and pending paths, so retry only failed and pending paths. Existing file permissions, line endings, and final-newline state are preserved. Returns changed file paths and operations with per-file and total line counts when all units succeed. Oversized patches are rejected without advertising defensive limits as recommended patch sizes. A first-unit MAR_AGENT_PATCH_CONFLICT applies nothing; hunk match conflicts identify the affected path and hunk so you can reread only that file before retrying.`,
|
|
11
|
+
description: `Preferred for precise, reviewable local edits. Do not batch all task files merely to reduce tool calls. Group only a few tightly coupled edits whose combined patch is quick to generate and review; split broad or independent work into successive bounded patches before composing them. Submit a raw *** Begin Patch / *** End Patch patch. Supports Add File, Update File, Delete File, and Move to. Add File may replace an existing regular file, and Move to may replace an existing regular destination; duplicate operations on the same resolved path remain invalid. Update hunks accept @@ or @@ <change context>; context-only hunks may also be used as ordered anchors before a later changing hunk. Context is searched forward with Codex-style exact, whitespace-tolerant, then common Unicode punctuation-tolerant matching. Syntax and resolved paths are validated before writing, then file units are committed in order. Each file unit is atomic, and a Move keeps its source and destination atomic. On MAR_AGENT_PATCH_PARTIAL, earlier files remain applied; the error lists applied, failed, and pending paths, so retry only failed and pending paths. Existing file permissions, line endings, and final-newline state are preserved. Returns changed file paths and operations with per-file and total line counts when all units succeed. In Code Mode, the Promise resolves on success and rejects with code/message on failure; the returned envelope has data.files and data.totals, not an ok or success flag. Oversized patches are rejected without advertising defensive limits as recommended patch sizes. A first-unit MAR_AGENT_PATCH_CONFLICT applies nothing; hunk match conflicts identify the affected path and hunk so you can reread only that file before retrying.`,
|
|
11
12
|
inputMode: 'freeform',
|
|
12
13
|
outputSchema: {
|
|
13
14
|
type: 'object',
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ClientToolDefinition, ToolCaller } from '../model/contracts.js';
|
|
2
|
+
/** Normalize trusted Host policy independently of discovery, Agent scope and parallel safety. */
|
|
3
|
+
export declare function toolCallers(tool: ClientToolDefinition): readonly ToolCaller[];
|
|
4
|
+
export declare function allowsToolCaller(tool: ClientToolDefinition, caller: ToolCaller): boolean;
|
|
5
|
+
/** Code Mode Only changes model exposure, never the Host's underlying caller permissions. */
|
|
6
|
+
export declare function allowsDirectTool(tool: ClientToolDefinition, codeModeEnabled: boolean): boolean;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { MarAgentError } from '../error.js';
|
|
2
|
+
/** Normalize trusted Host policy independently of discovery, Agent scope and parallel safety. */
|
|
3
|
+
export function toolCallers(tool) {
|
|
4
|
+
const value = tool.allowedCallers;
|
|
5
|
+
if (value === undefined)
|
|
6
|
+
return tool.name.startsWith('mcp__') ? ['direct', 'programmatic'] : ['direct'];
|
|
7
|
+
if (!Array.isArray(value) ||
|
|
8
|
+
value.length === 0 ||
|
|
9
|
+
value.some((caller) => caller !== 'direct' && caller !== 'programmatic'))
|
|
10
|
+
throw new MarAgentError('MAR_AGENT_TOOL_INPUT_INVALID', 'Tool caller policy is invalid.');
|
|
11
|
+
return ['direct', 'programmatic'].filter((caller) => value.includes(caller));
|
|
12
|
+
}
|
|
13
|
+
export function allowsToolCaller(tool, caller) {
|
|
14
|
+
// Control tools cannot be widened by a Host override or historical definition.
|
|
15
|
+
if (caller === 'programmatic' && ['code_mode', 'tool_search', 'question'].includes(tool.name))
|
|
16
|
+
return false;
|
|
17
|
+
return toolCallers(tool).includes(caller);
|
|
18
|
+
}
|
|
19
|
+
/** Code Mode Only changes model exposure, never the Host's underlying caller permissions. */
|
|
20
|
+
export function allowsDirectTool(tool, codeModeEnabled) {
|
|
21
|
+
return (allowsToolCaller(tool, 'direct') &&
|
|
22
|
+
(!codeModeEnabled || !allowsToolCaller(tool, 'programmatic')));
|
|
23
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ToolCall, ToolExecutionResult } from '../../sdk/types.js';
|
|
2
|
+
import type { CodeModeStateEntry, CodeModeStateMutation } from './state.js';
|
|
3
|
+
export interface CodeModeCatalogEntry {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly description: string;
|
|
6
|
+
readonly inputSchema: unknown;
|
|
7
|
+
readonly inputMode: 'json' | 'freeform';
|
|
8
|
+
}
|
|
9
|
+
/** A trusted, replaceable worker-side engine; no engine handles cross this interface. */
|
|
10
|
+
export interface CodeModeEngine {
|
|
11
|
+
execute(input: {
|
|
12
|
+
code: string;
|
|
13
|
+
tools: readonly string[];
|
|
14
|
+
catalog: readonly CodeModeCatalogEntry[];
|
|
15
|
+
state: readonly CodeModeStateEntry[];
|
|
16
|
+
signal: AbortSignal;
|
|
17
|
+
limits: {
|
|
18
|
+
memoryBytes: number;
|
|
19
|
+
stackBytes: number;
|
|
20
|
+
timeoutMs: number;
|
|
21
|
+
outputBytes: number;
|
|
22
|
+
stateEntries: number;
|
|
23
|
+
stateMutations: number;
|
|
24
|
+
stateKeyBytes: number;
|
|
25
|
+
stateValueBytes: number;
|
|
26
|
+
stateTotalBytes: number;
|
|
27
|
+
sleepMs: number;
|
|
28
|
+
};
|
|
29
|
+
onToolCall(call: ToolCall): Promise<ToolExecutionResult>;
|
|
30
|
+
onText(value: string): void;
|
|
31
|
+
onImage(value: unknown): void;
|
|
32
|
+
}): Promise<{
|
|
33
|
+
readonly stateMutations: readonly CodeModeStateMutation[];
|
|
34
|
+
}>;
|
|
35
|
+
dispose(): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
/** Only the Local Host may supply this descriptor; it is never part of model tool input. */
|
|
38
|
+
export interface CodeModeEngineFactory {
|
|
39
|
+
readonly moduleUrl: string;
|
|
40
|
+
readonly runtimeDirectories: readonly string[];
|
|
41
|
+
readonly options?: Readonly<Record<string, unknown>>;
|
|
42
|
+
}
|
|
43
|
+
export type CreateCodeModeEngine = (options: Readonly<Record<string, unknown>>) => Promise<CodeModeEngine>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|