@myagentroam/agent 0.11.39 → 0.11.40
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/catalog-file.d.ts +2 -0
- package/dist/cli/main.js +11 -4
- package/dist/cli/subagent/control.d.ts +56 -0
- package/dist/cli/subagent/control.js +219 -0
- package/dist/cli/subagent/history.d.ts +17 -0
- package/dist/cli/subagent/history.js +85 -0
- package/dist/cli/subagent/index.d.ts +10 -0
- package/dist/cli/subagent/index.js +94 -0
- package/dist/cli/subagent/native.d.ts +91 -0
- package/dist/cli/subagent/native.js +359 -0
- package/dist/cli/subagent/observations.d.ts +57 -0
- package/dist/cli/subagent/observations.js +351 -0
- package/dist/cli/subagent/query.d.ts +4 -0
- package/dist/cli/subagent/query.js +114 -0
- package/dist/cli/subagent/resources.d.ts +3 -0
- package/dist/cli/subagent/resources.js +112 -0
- package/dist/cli/subagent/snapshot.d.ts +77 -0
- package/dist/cli/subagent/snapshot.js +127 -0
- package/dist/cli/subagent/start.d.ts +24 -0
- package/dist/cli/subagent/start.js +201 -0
- package/dist/cli/subagent/wait-output.d.ts +19 -0
- package/dist/cli/subagent/wait-output.js +56 -0
- package/dist/cli/subagent/wait.d.ts +175 -0
- package/dist/cli/subagent/wait.js +453 -0
- package/dist/extensions/contracts.d.ts +2 -5
- package/dist/extensions/manager.d.ts +0 -2
- package/dist/extensions/manager.js +1 -2
- package/dist/extensions/models.d.ts +3 -0
- package/dist/extensions/operation.d.ts +8 -0
- package/dist/extensions/operation.js +3 -0
- package/dist/extensions/services.d.ts +9 -1
- package/dist/extensions/services.js +26 -3
- package/dist/extensions/session-context.d.ts +18 -0
- package/dist/extensions/session-context.js +4 -0
- package/dist/extensions/session-input.d.ts +2 -2
- package/dist/extensions/session-input.js +3 -4
- package/dist/extensions/session-messages.d.ts +1 -1
- package/dist/extensions/session-tools.js +20 -3
- package/dist/extensions/session.d.ts +1 -4
- package/dist/extensions/session.js +2 -16
- package/dist/extensions/tools.js +21 -3
- package/dist/extensions.d.ts +5 -2
- package/dist/extensions.js +2 -1
- package/dist/host/local-agent-host.d.ts +2 -2
- package/dist/host/local-exec-tool.d.ts +1 -1
- package/dist/host/local-exec-tool.js +28 -3
- package/dist/host/local-tool-registry.d.ts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/model/configuration.d.ts +3 -1
- package/dist/model/configuration.js +1 -0
- package/dist/model/openai-responses.js +5 -0
- package/dist/model/responses-request.js +9 -0
- package/dist/prompts/index.js +1 -3
- package/dist/prompts/resources.d.ts +1 -5
- package/dist/prompts/resources.js +3 -12
- package/dist/prompts/subagent.d.ts +1 -1
- package/dist/prompts/subagent.js +1 -1
- package/dist/runtime/context/gc-candidates-web.d.ts +6 -0
- package/dist/runtime/context/gc-candidates-web.js +53 -1
- package/dist/runtime/context/gc-candidates.js +1 -9
- package/dist/runtime/context/gc.js +19 -11
- package/dist/runtime/context/projection.js +1 -0
- package/dist/runtime/events.d.ts +4 -3
- package/dist/runtime/execution-handle.d.ts +2 -0
- package/dist/runtime/wait.js +12 -2
- package/dist/sdk/agent.js +94 -5
- package/dist/sdk/execution-context-coordinator.d.ts +2 -3
- package/dist/sdk/execution-context-coordinator.js +3 -3
- package/dist/sdk/execution-input.d.ts +3 -4
- package/dist/sdk/execution-input.js +31 -25
- package/dist/sdk/execution-round-preparation.d.ts +1 -1
- package/dist/sdk/execution-round-preparation.js +4 -4
- package/dist/sdk/execution-tool-catalog.js +2 -10
- package/dist/sdk/execution-tool-scope.d.ts +1 -3
- package/dist/sdk/execution-tool-scope.js +10 -12
- package/dist/sdk/extension-models.js +3 -0
- package/dist/sdk/extension-session-launch.d.ts +3 -2
- package/dist/sdk/extension-session-launch.js +2 -3
- package/dist/sdk/extension-tools.js +0 -2
- package/dist/sdk/native-steer.d.ts +2 -2
- package/dist/sdk/native-steer.js +2 -2
- package/dist/sdk/session-composition.d.ts +2 -17
- package/dist/sdk/session-execution-factory.d.ts +2 -3
- package/dist/sdk/session-execution-factory.js +20 -114
- package/dist/sdk/session-execution.d.ts +13 -7
- package/dist/sdk/session-execution.js +11 -3
- package/dist/sdk/session-extension-messages.d.ts +1 -3
- package/dist/sdk/session-extension-messages.js +14 -9
- package/dist/sdk/session-extension-prompt.js +1 -3
- package/dist/sdk/session-maintenance.d.ts +1 -0
- package/dist/sdk/session-maintenance.js +16 -7
- package/dist/sdk/session-open.d.ts +2 -3
- package/dist/sdk/session-open.js +5 -24
- package/dist/sdk/session-runtime.d.ts +19 -8
- package/dist/sdk/session-runtime.js +36 -30
- package/dist/sdk/session.d.ts +3 -2
- package/dist/sdk/session.js +22 -89
- package/dist/sdk/types.d.ts +36 -0
- package/dist/session/catalog.d.ts +22 -1
- package/dist/session/catalog.js +102 -0
- package/dist/session/context-gc-checkpoint.js +30 -1
- package/dist/session/context-gc-contract.d.ts +7 -0
- package/dist/session/context-gc-replacements.d.ts +3 -0
- package/dist/session/context-gc-replacements.js +26 -0
- package/dist/session/store/contracts.d.ts +2 -2
- package/dist/session/store/jsonl/directory-index.d.ts +1 -1
- package/dist/session/store/jsonl/directory-index.js +18 -17
- package/dist/session/store/jsonl/history.js +1 -1
- package/dist/session/store/jsonl/index-transaction.js +2 -8
- package/dist/session/store/jsonl/jsonl-store.d.ts +1 -1
- package/dist/session/store/jsonl/jsonl-store.js +24 -9
- package/dist/session/types.d.ts +1 -0
- package/dist/tools/agent/sleep.js +1 -1
- package/dist/tools/callers.js +1 -12
- package/dist/tools/code-mode/dispatch.js +5 -2
- package/dist/tools/code-mode/index.d.ts +1 -1
- package/dist/tools/code-mode/index.js +2 -0
- package/dist/tools/contracts.d.ts +20 -0
- package/dist/tools/execution-limits.d.ts +5 -20
- package/dist/tools/execution-limits.js +0 -2
- package/dist/tools/execution.js +16 -4
- package/dist/tools/local/exec.js +8 -2
- package/dist/tools/output-projection.d.ts +5 -2
- package/dist/tools/output-projection.js +133 -92
- package/dist/tools/registry.js +1 -13
- package/dist/tools/runtime-context.d.ts +1 -21
- package/package.json +2 -2
- package/dist/extensions/agents.d.ts +0 -100
- package/dist/extensions/agents.js +0 -121
- package/dist/runtime/context/gc-candidates-subagent.d.ts +0 -6
- package/dist/runtime/context/gc-candidates-subagent.js +0 -100
- package/dist/sdk/extension-agent-controller.d.ts +0 -3
- package/dist/sdk/extension-agent-controller.js +0 -69
- package/dist/sdk/extension-agents.d.ts +0 -9
- package/dist/sdk/extension-agents.js +0 -58
- package/dist/sdk/subagent-backend.d.ts +0 -3
- package/dist/sdk/subagent-backend.js +0 -49
- package/dist/subagent/contracts.d.ts +0 -107
- package/dist/subagent/contracts.js +0 -1
- package/dist/subagent/limits.d.ts +0 -17
- package/dist/subagent/limits.js +0 -17
- package/dist/subagent/model-update.d.ts +0 -2
- package/dist/subagent/model-update.js +0 -81
- package/dist/subagent/session-controller.d.ts +0 -87
- package/dist/subagent/session-controller.js +0 -1343
- package/dist/subagent/task.d.ts +0 -134
- package/dist/subagent/task.js +0 -436
- package/dist/subagent/turn-contracts.d.ts +0 -64
- package/dist/subagent/turn-contracts.js +0 -1
- package/dist/subagent/wait-targets.d.ts +0 -10
- package/dist/subagent/wait-targets.js +0 -26
- package/dist/subagent/wait.d.ts +0 -26
- package/dist/subagent/wait.js +0 -73
- package/dist/tools/agent/agent-cancel.d.ts +0 -7
- package/dist/tools/agent/agent-cancel.js +0 -29
- package/dist/tools/agent/agent-message.d.ts +0 -7
- package/dist/tools/agent/agent-message.js +0 -57
- package/dist/tools/agent/agent-start.d.ts +0 -12
- package/dist/tools/agent/agent-start.js +0 -106
- package/dist/tools/agent/agent-wait.d.ts +0 -7
- package/dist/tools/agent/agent-wait.js +0 -91
package/dist/sdk/types.d.ts
CHANGED
|
@@ -8,6 +8,10 @@ import type { SessionListInput, SessionSource, SessionTitleUpdateInput } from '.
|
|
|
8
8
|
export interface CreateSessionInput {
|
|
9
9
|
workspace: string;
|
|
10
10
|
title?: string;
|
|
11
|
+
/** Optional creation relationship; authorization and depth are owned by the Host. */
|
|
12
|
+
parentSessionId?: string;
|
|
13
|
+
/** Optional provenance snapshot; it cannot contradict the creation relationship. */
|
|
14
|
+
source?: SessionSource;
|
|
11
15
|
}
|
|
12
16
|
export type { SessionTitleUpdateInput } from '../session/types.js';
|
|
13
17
|
export type { HostExecutionExtensions, HostSessionResourceSnapshot, HostSkill, AgentHost } from '../host/contracts.js';
|
|
@@ -35,20 +39,50 @@ export type SteerResult = {
|
|
|
35
39
|
/** A persisted Session permits one active main execution at a time. */
|
|
36
40
|
export interface AgentSession {
|
|
37
41
|
readonly id: string;
|
|
42
|
+
/** Subscribe to future events and atomically capture the currently active Execution, if any. */
|
|
43
|
+
subscribe(listener: (event: import('../runtime/events.js').AgentEvent) => void): {
|
|
44
|
+
readonly activeExecutionId?: string;
|
|
45
|
+
/** Terminal fact already published by the still-admitted Execution, if any. */
|
|
46
|
+
readonly terminalEvent?: Extract<import('../runtime/events.js').AgentEvent, {
|
|
47
|
+
type: 'execution.completed' | 'execution.failed' | 'execution.cancelled';
|
|
48
|
+
}>;
|
|
49
|
+
unsubscribe(): void;
|
|
50
|
+
};
|
|
38
51
|
run(input: RunInput): ExecutionHandle;
|
|
39
52
|
plan(input: RunInput): ExecutionHandle;
|
|
40
53
|
steer(input: SteerInput): Promise<SteerResult>;
|
|
41
54
|
compact(input?: CompactInput): ExecutionHandle;
|
|
42
55
|
cancel(executionId: string): Promise<void>;
|
|
56
|
+
/** Join a currently owned Execution after its cleanup, without cancelling it. */
|
|
57
|
+
joinExecution(executionId: string): Promise<import('../runtime/contracts.js').ExecutionResult> | undefined;
|
|
58
|
+
}
|
|
59
|
+
/** A Session already owned by this Agent, with no history opening or replay. */
|
|
60
|
+
export interface AgentLiveSession {
|
|
61
|
+
readonly id: string;
|
|
62
|
+
readonly workspace: string;
|
|
63
|
+
readonly source: SessionSource;
|
|
64
|
+
readonly subscribe: AgentSession['subscribe'];
|
|
43
65
|
}
|
|
44
66
|
export interface Agent {
|
|
45
67
|
extensionDiagnostics(): readonly import('../extensions/contracts.js').ExtensionDiagnostic[];
|
|
68
|
+
/** Atomically subscribe to future admitted Executions and snapshot currently admitted Sessions. */
|
|
69
|
+
observeSessionExecutions(listener: (session: AgentLiveSession) => void): {
|
|
70
|
+
readonly sessions: readonly AgentLiveSession[];
|
|
71
|
+
unsubscribe(): void;
|
|
72
|
+
};
|
|
46
73
|
createSession(input: CreateSessionInput): Promise<AgentSession>;
|
|
47
74
|
openSession(sessionId: string): Promise<AgentSession>;
|
|
48
75
|
listSessions(input?: SessionListInput): Promise<AgentSessionPage>;
|
|
49
76
|
getSession(sessionId: string): Promise<AgentSessionSummary & {
|
|
50
77
|
automaticTitlePending: boolean;
|
|
51
78
|
}>;
|
|
79
|
+
/** Read persisted Session history without opening or starting an Execution. */
|
|
80
|
+
sessionHistory: import('../session/catalog.js').AgentSessionCatalog['history'];
|
|
81
|
+
sessionInputReceipt: import('../session/catalog.js').AgentSessionCatalog['inputReceipt'];
|
|
82
|
+
/** Check an unfinished persisted Execution under the Session's exclusive writer admission. */
|
|
83
|
+
sessionExecutionWasInterrupted(sessionId: string, executionId: string, input?: {
|
|
84
|
+
readonly signal?: AbortSignal;
|
|
85
|
+
}): Promise<boolean>;
|
|
52
86
|
setSessionTitle(sessionId: string, title: string, input?: SessionTitleUpdateInput): Promise<boolean>;
|
|
53
87
|
clearSession(sessionId: string): Promise<void>;
|
|
54
88
|
/** Updates future execution snapshots only; undefined clears the Host instruction extension. */
|
|
@@ -59,6 +93,8 @@ export interface Agent {
|
|
|
59
93
|
readonly defaultModelId?: string;
|
|
60
94
|
}): Promise<void>;
|
|
61
95
|
deleteSession(sessionId: string): Promise<void>;
|
|
96
|
+
/** Deletes the explicit members under one maintenance admission; never infers descendants. */
|
|
97
|
+
deleteSessions(sessionIds: readonly string[]): Promise<void>;
|
|
62
98
|
/** Joins executions/reconfiguration, closes owned resources, and releases borrowed Store leases. */
|
|
63
99
|
dispose(): Promise<void>;
|
|
64
100
|
}
|
|
@@ -15,6 +15,14 @@ export interface AgentSessionHistoryPage {
|
|
|
15
15
|
entries: AgentSessionHistoryEntry[];
|
|
16
16
|
nextCursor?: string;
|
|
17
17
|
}
|
|
18
|
+
export interface AgentSessionInputReceipt {
|
|
19
|
+
readonly clientMessageId: string;
|
|
20
|
+
readonly executionId: string;
|
|
21
|
+
readonly turnId: string;
|
|
22
|
+
readonly status: 'accepted' | 'applied';
|
|
23
|
+
readonly appliedExecutionId?: string;
|
|
24
|
+
readonly appliedTurnId?: string;
|
|
25
|
+
}
|
|
18
26
|
export interface AgentSessionContextUsage {
|
|
19
27
|
inputTokens: number;
|
|
20
28
|
}
|
|
@@ -40,6 +48,17 @@ export interface AgentSessionCatalog {
|
|
|
40
48
|
limit?: number;
|
|
41
49
|
cursor?: string;
|
|
42
50
|
}): Promise<AgentSessionHistoryPage>;
|
|
51
|
+
/** Read the specified receipt, or the latest receipt associated with the fixed Execution. */
|
|
52
|
+
inputReceipt(sessionId: string, input: {
|
|
53
|
+
clientMessageId?: string;
|
|
54
|
+
executionId: string;
|
|
55
|
+
signal?: AbortSignal;
|
|
56
|
+
source?: {
|
|
57
|
+
sessionId: string;
|
|
58
|
+
extensionId: string;
|
|
59
|
+
actors?: readonly string[];
|
|
60
|
+
};
|
|
61
|
+
}): Promise<AgentSessionInputReceipt | undefined>;
|
|
43
62
|
readImage(sessionId: string, input: {
|
|
44
63
|
readonly sequence: number;
|
|
45
64
|
readonly imageIndex: number;
|
|
@@ -57,6 +76,8 @@ export interface AgentSessionCatalog {
|
|
|
57
76
|
rollback(sessionId: string, input: AgentSessionRollbackInput): Promise<AgentSessionSummary>;
|
|
58
77
|
clear(sessionId: string): Promise<AgentSessionSummary>;
|
|
59
78
|
delete(sessionId: string): Promise<AgentSessionDeleteResult>;
|
|
79
|
+
/** Delete exactly these members after their owners have released their resources. */
|
|
80
|
+
deleteMembers(sessionIds: readonly string[]): Promise<AgentSessionDeleteResult>;
|
|
60
81
|
close(): Promise<void>;
|
|
61
82
|
}
|
|
62
83
|
export type OpenAgentSessionCatalogInput = {
|
|
@@ -66,5 +87,5 @@ export type OpenAgentSessionCatalogInput = {
|
|
|
66
87
|
sessionStore: SessionStore;
|
|
67
88
|
homeDirectory?: never;
|
|
68
89
|
};
|
|
69
|
-
export declare function createSessionCatalog(store: Pick<SessionStore, 'list' | 'firstUserMessagePreview' | 'executionConfiguration' | 'readPage' | 'readInputImage' | 'readResource' | 'readToolResultResource' | 'forkSession' | 'rollbackSession' | 'clearSession' | 'delete' | 'close'>, borrowed: boolean): AgentSessionCatalog;
|
|
90
|
+
export declare function createSessionCatalog(store: Pick<SessionStore, 'list' | 'firstUserMessagePreview' | 'executionConfiguration' | 'readPage' | 'readInputImage' | 'readResource' | 'readToolResultResource' | 'forkSession' | 'rollbackSession' | 'clearSession' | 'delete' | 'acquireSessionMaintenance' | 'close'>, borrowed: boolean): AgentSessionCatalog;
|
|
70
91
|
export declare function imageMetadata(value: unknown): AgentSessionHistoryImageMetadata[];
|
package/dist/session/catalog.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AgentError } from '../error.js';
|
|
2
2
|
import { publicHostedToolEvents } from '../runtime/event-projection.js';
|
|
3
|
+
import { appliedInputRecord } from './deferred-input.js';
|
|
3
4
|
const MAX_INPUT_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
4
5
|
const INPUT_IMAGE_MIME_TYPES = new Set(['image/png', 'image/jpeg', 'image/gif', 'image/webp']);
|
|
5
6
|
export function createSessionCatalog(store, borrowed) {
|
|
@@ -21,6 +22,80 @@ export function createSessionCatalog(store, borrowed) {
|
|
|
21
22
|
assertOpen();
|
|
22
23
|
return store.executionConfiguration(sessionId);
|
|
23
24
|
},
|
|
25
|
+
inputReceipt: async (sessionId, input) => {
|
|
26
|
+
assertOpen();
|
|
27
|
+
if ((input.clientMessageId !== undefined && !input.clientMessageId.trim()) ||
|
|
28
|
+
!input.executionId.trim())
|
|
29
|
+
throw new AgentError('MAR_AGENT_SESSION_INPUT_INVALID', 'Input receipt identity is invalid.');
|
|
30
|
+
const applied = new Map();
|
|
31
|
+
let beforeSequence;
|
|
32
|
+
do {
|
|
33
|
+
input.signal?.throwIfAborted();
|
|
34
|
+
const page = await store.readPage(sessionId, {
|
|
35
|
+
limit: 1000,
|
|
36
|
+
...(beforeSequence === undefined ? {} : { beforeSequence })
|
|
37
|
+
});
|
|
38
|
+
input.signal?.throwIfAborted();
|
|
39
|
+
for (const record of [...page.records].reverse()) {
|
|
40
|
+
if (!isRecord(record.payload))
|
|
41
|
+
continue;
|
|
42
|
+
if (record.type === 'input.applied' &&
|
|
43
|
+
typeof record.payload.inputRef === 'string' &&
|
|
44
|
+
!applied.has(record.payload.inputRef))
|
|
45
|
+
applied.set(record.payload.inputRef, {
|
|
46
|
+
...(record.executionId === undefined ? {} : { executionId: record.executionId }),
|
|
47
|
+
...(record.turnId === undefined ? {} : { turnId: record.turnId })
|
|
48
|
+
});
|
|
49
|
+
if (record.type === 'model.context' &&
|
|
50
|
+
isRecord(record.payload.input) &&
|
|
51
|
+
(input.clientMessageId === undefined ||
|
|
52
|
+
record.payload.input.clientMessageId === input.clientMessageId)) {
|
|
53
|
+
const projected = appliedInputRecord(record);
|
|
54
|
+
if (projected && !applied.has(projected.recordId))
|
|
55
|
+
applied.set(projected.recordId, {
|
|
56
|
+
...(record.executionId === undefined ? {} : { executionId: record.executionId }),
|
|
57
|
+
...(record.turnId === undefined ? {} : { turnId: record.turnId })
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (record.type !== 'turn.user' ||
|
|
61
|
+
!record.executionId ||
|
|
62
|
+
!record.turnId ||
|
|
63
|
+
typeof record.payload.clientMessageId !== 'string' ||
|
|
64
|
+
!record.payload.clientMessageId ||
|
|
65
|
+
(input.clientMessageId !== undefined &&
|
|
66
|
+
record.payload.clientMessageId !== input.clientMessageId))
|
|
67
|
+
continue;
|
|
68
|
+
if (input.source) {
|
|
69
|
+
const source = record.payload.source;
|
|
70
|
+
if (!isRecord(source) ||
|
|
71
|
+
source.sessionId !== input.source.sessionId ||
|
|
72
|
+
source.extensionId !== input.source.extensionId ||
|
|
73
|
+
(input.source.actors && !input.source.actors.includes(String(source.actor))))
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const application = applied.get(record.recordId);
|
|
77
|
+
if (input.clientMessageId === undefined
|
|
78
|
+
? record.executionId !== input.executionId &&
|
|
79
|
+
application?.executionId !== input.executionId
|
|
80
|
+
: record.executionId !== input.executionId)
|
|
81
|
+
continue;
|
|
82
|
+
return {
|
|
83
|
+
clientMessageId: record.payload.clientMessageId,
|
|
84
|
+
executionId: record.executionId,
|
|
85
|
+
turnId: record.turnId,
|
|
86
|
+
status: application ? 'applied' : 'accepted',
|
|
87
|
+
...{
|
|
88
|
+
...(application?.executionId === undefined
|
|
89
|
+
? {}
|
|
90
|
+
: { appliedExecutionId: application.executionId }),
|
|
91
|
+
...(application?.turnId === undefined ? {} : { appliedTurnId: application.turnId })
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
beforeSequence = page.previousBeforeSequence;
|
|
96
|
+
} while (beforeSequence !== undefined);
|
|
97
|
+
return undefined;
|
|
98
|
+
},
|
|
24
99
|
history: async (sessionId, options = {}) => {
|
|
25
100
|
assertOpen();
|
|
26
101
|
const beforeSequence = parseCursor(options.cursor);
|
|
@@ -139,6 +214,33 @@ export function createSessionCatalog(store, borrowed) {
|
|
|
139
214
|
assertOpen();
|
|
140
215
|
return store.delete(sessionId);
|
|
141
216
|
},
|
|
217
|
+
deleteMembers: async (sessionIds) => {
|
|
218
|
+
assertOpen();
|
|
219
|
+
const ids = [...sessionIds];
|
|
220
|
+
if (ids.length === 0 ||
|
|
221
|
+
ids.some((id) => typeof id !== 'string' || id.length === 0) ||
|
|
222
|
+
new Set(ids).size !== ids.length)
|
|
223
|
+
throw new AgentError('MAR_AGENT_SESSION_INVALID', 'Invalid Session maintenance members.');
|
|
224
|
+
ids.sort();
|
|
225
|
+
const maintenance = await store.acquireSessionMaintenance(ids[0], 'delete', undefined, ids);
|
|
226
|
+
let failed = false;
|
|
227
|
+
try {
|
|
228
|
+
return await store.delete(ids[0], maintenance);
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
failed = true;
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
234
|
+
finally {
|
|
235
|
+
try {
|
|
236
|
+
await maintenance.release();
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
if (!failed)
|
|
240
|
+
throw error;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
},
|
|
142
244
|
close: () => {
|
|
143
245
|
closure ??= Promise.resolve().then(() => (borrowed ? undefined : store.close()));
|
|
144
246
|
return closure;
|
|
@@ -3,7 +3,7 @@ import { isDeepStrictEqual } from 'node:util';
|
|
|
3
3
|
import { inlineMediaGcAnchored, parseInlineMediaGc } from './inline-media.js';
|
|
4
4
|
import { codeCallEvidence, codePartialPatchCallEvidence, callsFromRecord, codeObservationEvidence, observationsFromRecord, retainedCodeInputs } from './context-gc-observations.js';
|
|
5
5
|
import { parseReadContextOutput } from '../prompts/read-context.js';
|
|
6
|
-
import { codeCellCompletionSequence, contextGcApplyPatchInputReplacement, contextGcCodeModeInputReplacement, contextGcCodeModeOutputReplacement, contextGcExecInputReplacement, contextGcExecOutputReplacement, contextGcPatchResultFromCompletedPayload, contextGcPatchResultFromFailedPayload, contextGcStaleReadReplacement, contextGcWebOutputReplacement, normalizeContextGcCodeModeInput, normalizeContextGcExecResult } from './context-gc-replacements.js';
|
|
6
|
+
import { codeCellCompletionSequence, contextGcApplyPatchInputReplacement, contextGcCodeModeInputReplacement, contextGcCodeModeOutputReplacement, contextGcExecInputReplacement, contextGcExecOutputReplacement, contextGcPatchResultFromCompletedPayload, contextGcPatchResultFromFailedPayload, contextGcStaleReadReplacement, contextGcToolOutputReplacement, contextGcWebOutputReplacement, isGenericContextGcTool, normalizeContextGcCodeModeInput, normalizeContextGcExecResult } from './context-gc-replacements.js';
|
|
7
7
|
import { contextGcSubagentNeedsRetainedPriorFinal, contextGcSubagentOutputReplacement, contextGcSubagentSnapshotIsPreciselyCovered, contextGcSubagentSnapshotIsSuperseded, normalizeContextGcSubagentSnapshot } from './context-gc-subagent.js';
|
|
8
8
|
export const CONTEXT_GC_CHECKPOINT_VERSION = 1;
|
|
9
9
|
export const CONTEXT_GC_MAX_TARGETS = 4_096;
|
|
@@ -350,6 +350,20 @@ function replacementMatchesRecords(replacement, records, recordsBySequence, work
|
|
|
350
350
|
value.truncated === true) === true
|
|
351
351
|
: evidence.completed.payload.truncated));
|
|
352
352
|
}
|
|
353
|
+
if (replacement.kind === 'TOOL_OUTPUT') {
|
|
354
|
+
const evidence = successfulToolEvidence(records, recordsBySequence, replacement.evidenceSequence, replacement.toolName, replacement.callId);
|
|
355
|
+
return (isGenericContextGcTool(replacement.toolName) &&
|
|
356
|
+
evidence !== undefined &&
|
|
357
|
+
evidence.result.sequence === replacement.target.sequence &&
|
|
358
|
+
!hasFailedToolEvidence(records, evidence.call, evidence.result, replacement.toolName) &&
|
|
359
|
+
isRecord(evidence.completed.payload) &&
|
|
360
|
+
typeof evidence.completed.payload.truncated === 'boolean' &&
|
|
361
|
+
typeof source.payload.content === 'string' &&
|
|
362
|
+
isRecord(evidence.result.payload) &&
|
|
363
|
+
evidence.result.payload.content === source.payload.content &&
|
|
364
|
+
replacement.replacementContent ===
|
|
365
|
+
contextGcToolOutputReplacement(replacement.toolName, source.payload.content, evidence.completed.payload.truncated));
|
|
366
|
+
}
|
|
353
367
|
if (replacement.kind === 'SUBAGENT_OUTPUT') {
|
|
354
368
|
const retainedPriorFinal = replacement.retainedPriorFinal;
|
|
355
369
|
const sourceEvidence = successfulToolEvidence(records, recordsBySequence, source.sequence, replacement.toolName);
|
|
@@ -808,6 +822,21 @@ function isContextGcReplacement(value) {
|
|
|
808
822
|
(value.target.toolName === undefined || value.target.toolName === value.toolName) &&
|
|
809
823
|
isNonemptyString(value.replacementContent) &&
|
|
810
824
|
isPositiveInteger(value.evidenceSequence));
|
|
825
|
+
if (value.kind === 'TOOL_OUTPUT')
|
|
826
|
+
return (hasOnlyKeys(value, [
|
|
827
|
+
'kind',
|
|
828
|
+
'toolName',
|
|
829
|
+
'callId',
|
|
830
|
+
'target',
|
|
831
|
+
'replacementContent',
|
|
832
|
+
'evidenceSequence'
|
|
833
|
+
]) &&
|
|
834
|
+
value.target.role === 'tool' &&
|
|
835
|
+
isNonemptyString(value.toolName) &&
|
|
836
|
+
isGenericContextGcTool(value.toolName) &&
|
|
837
|
+
(value.target.toolName === undefined || value.target.toolName === value.toolName) &&
|
|
838
|
+
isNonemptyString(value.replacementContent) &&
|
|
839
|
+
isPositiveInteger(value.evidenceSequence));
|
|
811
840
|
if (value.kind === 'CODE_MODE_OUTPUT')
|
|
812
841
|
return (hasOnlyKeys(value, ['kind', 'callId', 'target', 'replacementContent', 'evidenceSequence']) &&
|
|
813
842
|
value.target.role === 'tool' &&
|
|
@@ -68,6 +68,13 @@ export type ContextGcReplacement = {
|
|
|
68
68
|
readonly target: ContextGcTarget;
|
|
69
69
|
readonly replacementContent: string;
|
|
70
70
|
readonly evidenceSequence: number;
|
|
71
|
+
} | {
|
|
72
|
+
readonly kind: 'TOOL_OUTPUT';
|
|
73
|
+
readonly toolName: string;
|
|
74
|
+
readonly callId: string;
|
|
75
|
+
readonly target: ContextGcTarget;
|
|
76
|
+
readonly replacementContent: string;
|
|
77
|
+
readonly evidenceSequence: number;
|
|
71
78
|
} | {
|
|
72
79
|
readonly kind: 'SUBAGENT_OUTPUT';
|
|
73
80
|
readonly toolName: 'agent_wait' | 'agent_message' | 'agent_cancel';
|
|
@@ -55,6 +55,9 @@ export declare function contextGcStaleReadReplacement(input: {
|
|
|
55
55
|
readonly operation: Exclude<ContextGcPatchFile['operation'], 'added'>;
|
|
56
56
|
}): string;
|
|
57
57
|
export declare function contextGcWebOutputReplacement(toolName: ContextGcWebToolName, originalContent: string, truncated: boolean): string;
|
|
58
|
+
/** Tools with their own evidence and lifecycle policies are never handled as generic output. */
|
|
59
|
+
export declare function isGenericContextGcTool(toolName: string): boolean;
|
|
60
|
+
export declare function contextGcToolOutputReplacement(toolName: string, originalContent: string, truncated: boolean): string;
|
|
58
61
|
export declare function contextGcExecInputReplacement(arguments_: unknown, toolName?: string): unknown;
|
|
59
62
|
export declare function contextGcExecOutputReplacement(result: ContextGcExecResult): string;
|
|
60
63
|
export declare function normalizeContextGcExecResult(modelContent: unknown, completedPayload: unknown): ContextGcExecResult | undefined;
|
|
@@ -82,6 +82,32 @@ export function contextGcWebOutputReplacement(toolName, originalContent, truncat
|
|
|
82
82
|
contextGc: 'Detailed web tool output was reclaimed after six successful rollouts. An incomplete preview is not the complete search result or page, and GC did not access the network.'
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
|
+
/** Tools with their own evidence and lifecycle policies are never handled as generic output. */
|
|
86
|
+
export function isGenericContextGcTool(toolName) {
|
|
87
|
+
return (toolName.length > 0 &&
|
|
88
|
+
![
|
|
89
|
+
'read',
|
|
90
|
+
'apply_patch',
|
|
91
|
+
'exec',
|
|
92
|
+
'exec_wait',
|
|
93
|
+
'code_exec',
|
|
94
|
+
'code_exec_wait',
|
|
95
|
+
'web_search',
|
|
96
|
+
'web_fetch'
|
|
97
|
+
].includes(toolName));
|
|
98
|
+
}
|
|
99
|
+
export function contextGcToolOutputReplacement(toolName, originalContent, truncated) {
|
|
100
|
+
const preview = unicodeHeadTail(originalContent, EXEC_OUTPUT_PREVIEW_CHARACTERS);
|
|
101
|
+
return JSON.stringify({
|
|
102
|
+
toolName,
|
|
103
|
+
originalBytes: Buffer.byteLength(originalContent),
|
|
104
|
+
lines: lineCount(originalContent),
|
|
105
|
+
truncated,
|
|
106
|
+
preview,
|
|
107
|
+
previewComplete: !truncated && preview === originalContent,
|
|
108
|
+
contextGc: 'Detailed tool output was reclaimed after six successful rollouts. An incomplete preview is not the complete result; the tool was not replayed.'
|
|
109
|
+
});
|
|
110
|
+
}
|
|
85
111
|
export function contextGcExecInputReplacement(arguments_, toolName = 'exec') {
|
|
86
112
|
if (!isRecord(arguments_))
|
|
87
113
|
return contextGcMarkup('terminal_exec_input', {
|
|
@@ -144,8 +144,8 @@ export interface SessionStore {
|
|
|
144
144
|
/** Retention requires the originating owner to hold an active Execution lease. */
|
|
145
145
|
retainSessionLease(sessionId: string, owner: object): Promise<() => Promise<void>>;
|
|
146
146
|
hasRetainedSessionLease(sessionId: string, owner: object): boolean;
|
|
147
|
-
/** Conflicts fail before cleanup; delete
|
|
148
|
-
acquireSessionMaintenance(sessionId: string, kind: 'clear' | 'delete', owner?: object): Promise<SessionStoreMaintenance>;
|
|
147
|
+
/** Conflicts fail before cleanup; delete admits only the explicit members, or the given Session. */
|
|
148
|
+
acquireSessionMaintenance(sessionId: string, kind: 'clear' | 'delete', owner?: object, members?: readonly string[]): Promise<SessionStoreMaintenance>;
|
|
149
149
|
forkSession(sessionId: string, input: {
|
|
150
150
|
readonly boundaryTurnId: string | null;
|
|
151
151
|
readonly title: string;
|
|
@@ -14,7 +14,7 @@ export declare function persistSessionIndex(path: string, index: SessionIndex):
|
|
|
14
14
|
export declare function persistFormatSelection(path: string, index: SessionIndex): Promise<void>;
|
|
15
15
|
export declare function normalizeSessionSource(value: SessionSource | undefined): SessionSource;
|
|
16
16
|
interface SessionListFilter {
|
|
17
|
-
readonly source
|
|
17
|
+
readonly source?: SessionSource['type'];
|
|
18
18
|
readonly parentSessionId?: string;
|
|
19
19
|
readonly rootSessionId?: string;
|
|
20
20
|
}
|
|
@@ -184,8 +184,17 @@ export async function persistFormatSelection(path, index) {
|
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
export function normalizeSessionSource(value) {
|
|
187
|
-
if (value === undefined
|
|
187
|
+
if (value === undefined)
|
|
188
188
|
return { type: 'user' };
|
|
189
|
+
if (value.type === 'user') {
|
|
190
|
+
if (value.parentSessionId !== undefined &&
|
|
191
|
+
(typeof value.parentSessionId !== 'string' || !value.parentSessionId.trim()))
|
|
192
|
+
throw new AgentError('MAR_AGENT_TOOL_INPUT_INVALID', 'Session source is invalid.');
|
|
193
|
+
return {
|
|
194
|
+
type: 'user',
|
|
195
|
+
...(value.parentSessionId === undefined ? {} : { parentSessionId: value.parentSessionId })
|
|
196
|
+
};
|
|
197
|
+
}
|
|
189
198
|
if (value.type !== 'subagent' ||
|
|
190
199
|
typeof value.parentSessionId !== 'string' ||
|
|
191
200
|
!value.parentSessionId.trim() ||
|
|
@@ -221,27 +230,21 @@ export function normalizeSessionSource(value) {
|
|
|
221
230
|
};
|
|
222
231
|
}
|
|
223
232
|
export function sessionListFilter(input) {
|
|
224
|
-
const source = input.source
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if ((source !== 'user' && source !== 'subagent') ||
|
|
229
|
-
(input.parentSessionId !== undefined &&
|
|
230
|
-
(source !== 'subagent' || input.parentSessionId.length === 0)) ||
|
|
231
|
-
(input.rootSessionId !== undefined &&
|
|
232
|
-
(source !== 'subagent' || input.rootSessionId.length === 0)))
|
|
233
|
+
const source = input.source;
|
|
234
|
+
if ((source !== undefined && source !== 'user' && source !== 'subagent') ||
|
|
235
|
+
(input.parentSessionId !== undefined && input.parentSessionId.length === 0) ||
|
|
236
|
+
(input.rootSessionId !== undefined && (source === 'user' || input.rootSessionId.length === 0)))
|
|
233
237
|
throw new AgentError('MAR_AGENT_TOOL_INPUT_INVALID', 'Session list filter is invalid.');
|
|
234
238
|
return {
|
|
235
|
-
source,
|
|
239
|
+
...(source === undefined ? {} : { source }),
|
|
236
240
|
...(input.parentSessionId === undefined ? {} : { parentSessionId: input.parentSessionId }),
|
|
237
241
|
...(input.rootSessionId === undefined ? {} : { rootSessionId: input.rootSessionId })
|
|
238
242
|
};
|
|
239
243
|
}
|
|
240
244
|
export function sessionMatchesFilter(meta, filter) {
|
|
241
245
|
const source = normalizeSessionSource(meta.source);
|
|
242
|
-
return (source.type === filter.source &&
|
|
243
|
-
(filter.parentSessionId === undefined ||
|
|
244
|
-
(source.type === 'subagent' && source.parentSessionId === filter.parentSessionId)) &&
|
|
246
|
+
return ((filter.source === undefined || source.type === filter.source) &&
|
|
247
|
+
(filter.parentSessionId === undefined || source.parentSessionId === filter.parentSessionId) &&
|
|
245
248
|
(filter.rootSessionId === undefined ||
|
|
246
249
|
(source.type === 'subagent' && source.rootSessionId === filter.rootSessionId)));
|
|
247
250
|
}
|
|
@@ -273,9 +276,7 @@ export function sessionTreeIds(sessions, sessionId) {
|
|
|
273
276
|
const parentId = ids[index];
|
|
274
277
|
for (const session of sessions) {
|
|
275
278
|
const source = normalizeSessionSource(session.source);
|
|
276
|
-
if (source.
|
|
277
|
-
source.parentSessionId === parentId &&
|
|
278
|
-
!ids.includes(session.id))
|
|
279
|
+
if (source.parentSessionId === parentId && !ids.includes(session.id))
|
|
279
280
|
ids.push(session.id);
|
|
280
281
|
}
|
|
281
282
|
}
|
|
@@ -155,7 +155,7 @@ export function forkedPayload(type, value, sourceSessionId, targetSessionId, tit
|
|
|
155
155
|
: {})
|
|
156
156
|
};
|
|
157
157
|
};
|
|
158
|
-
if (type === 'model.context')
|
|
158
|
+
if (type === 'model.context' || type === 'input.applied')
|
|
159
159
|
return application(payload);
|
|
160
160
|
if (type === 'compact.completed') {
|
|
161
161
|
if (payload.inlineMediaState)
|
|
@@ -21,7 +21,7 @@ export async function commitSessionIndex(root, snapshot, committed, deletedIds,
|
|
|
21
21
|
if (!created)
|
|
22
22
|
throw new AgentError('MAR_AGENT_SESSION_CORRUPT', 'Session publication is missing.');
|
|
23
23
|
const source = normalizeSessionSource(created.source);
|
|
24
|
-
if (source.
|
|
24
|
+
if (source.parentSessionId === undefined)
|
|
25
25
|
continue;
|
|
26
26
|
if (!disk.sessions.some((entry) => entry.id === source.parentSessionId))
|
|
27
27
|
throw new ParentPublicationRejected('MAR_AGENT_SESSION_NOT_FOUND', 'Parent Session was not found.');
|
|
@@ -35,7 +35,6 @@ export async function commitSessionIndex(root, snapshot, committed, deletedIds,
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
if (deleteExpected) {
|
|
38
|
-
const ids = new Set(deleteExpected.map((entry) => entry.id));
|
|
39
38
|
for (const expected of deleteExpected) {
|
|
40
39
|
const current = disk.sessions.find((entry) => entry.id === expected.id);
|
|
41
40
|
if (!current ||
|
|
@@ -45,12 +44,7 @@ export async function commitSessionIndex(root, snapshot, committed, deletedIds,
|
|
|
45
44
|
!isDeepStrictEqual(current.storage, expected.storage) ||
|
|
46
45
|
current.storageTransactionId !== expected.storageTransactionId ||
|
|
47
46
|
current.nextSequence !== expected.nextSequence)
|
|
48
|
-
throw new AgentError('MAR_AGENT_SESSION_CORRUPT', 'Session
|
|
49
|
-
}
|
|
50
|
-
for (const entry of disk.sessions) {
|
|
51
|
-
const source = normalizeSessionSource(entry.source);
|
|
52
|
-
if (source.type === 'subagent' && ids.has(source.parentSessionId) && !ids.has(entry.id))
|
|
53
|
-
throw new AgentError('MAR_AGENT_SESSION_CORRUPT', 'Session tree changed during deletion.');
|
|
47
|
+
throw new AgentError('MAR_AGENT_SESSION_CORRUPT', 'Session changed during deletion.');
|
|
54
48
|
}
|
|
55
49
|
}
|
|
56
50
|
const local = snapshot();
|
|
@@ -115,7 +115,7 @@ export declare class JsonlSessionStore implements SessionStore {
|
|
|
115
115
|
/** A warm cell retains physical writer ownership between Executions of the same Agent. */
|
|
116
116
|
acquireSessionLease(sessionId: string, owner?: object): Promise<() => Promise<void>>;
|
|
117
117
|
hasRetainedSessionLease(sessionId: string, owner: object): boolean;
|
|
118
|
-
acquireSessionMaintenance(sessionId: string, kind: 'clear' | 'delete', owner?: object): Promise<SessionStoreMaintenance>;
|
|
118
|
+
acquireSessionMaintenance(sessionId: string, kind: 'clear' | 'delete', owner?: object, members?: readonly string[]): Promise<SessionStoreMaintenance>;
|
|
119
119
|
/** Native writes join their Agent's sole writer, without admitting another Execution. */
|
|
120
120
|
acquireSessionWriteLease(sessionId: string, owner: object): Promise<() => Promise<void>>;
|
|
121
121
|
retainSessionLease(sessionId: string, owner: object): Promise<() => Promise<void>>;
|
|
@@ -219,20 +219,21 @@ export class JsonlSessionStore {
|
|
|
219
219
|
async createSession(input) {
|
|
220
220
|
this.#assertOpen();
|
|
221
221
|
const source = normalizeSessionSource(input.source);
|
|
222
|
-
if (source.
|
|
222
|
+
if (source.parentSessionId === undefined)
|
|
223
223
|
return this.#createSession(input, source);
|
|
224
|
+
const parentSessionId = source.parentSessionId;
|
|
224
225
|
// Publish under the parent's existing serial domain so tree admission cannot miss a child.
|
|
225
|
-
return this.#serializeRecordOperation(
|
|
226
|
+
return this.#serializeRecordOperation(parentSessionId, async () => {
|
|
226
227
|
this.#assertOpen();
|
|
227
|
-
if (this.#shared.writerLeases.get(
|
|
228
|
+
if (this.#shared.writerLeases.get(parentSessionId)?.maintenance)
|
|
228
229
|
throw new AgentError('MAR_AGENT_SESSION_LOCKED', 'Session is under maintenance.');
|
|
229
|
-
const release = await this.#acquirePublicationGate(
|
|
230
|
+
const release = await this.#acquirePublicationGate(parentSessionId, 5000);
|
|
230
231
|
let failure;
|
|
231
232
|
try {
|
|
232
|
-
await this.#recoverPendingTreeDelete(
|
|
233
|
-
if (this.#shared.writerLeases.get(
|
|
233
|
+
await this.#recoverPendingTreeDelete(parentSessionId);
|
|
234
|
+
if (this.#shared.writerLeases.get(parentSessionId)?.maintenance)
|
|
234
235
|
throw new AgentError('MAR_AGENT_SESSION_LOCKED', 'Session is under maintenance.');
|
|
235
|
-
await this.getSession(
|
|
236
|
+
await this.getSession(parentSessionId);
|
|
236
237
|
return await this.#createSession(input, source);
|
|
237
238
|
}
|
|
238
239
|
catch (error) {
|
|
@@ -1408,13 +1409,27 @@ export class JsonlSessionStore {
|
|
|
1408
1409
|
const lease = this.#shared.writerLeases.get(sessionId);
|
|
1409
1410
|
return lease?.owner === owner && lease.retained > 0;
|
|
1410
1411
|
}
|
|
1411
|
-
async acquireSessionMaintenance(sessionId, kind, owner) {
|
|
1412
|
+
async acquireSessionMaintenance(sessionId, kind, owner, members) {
|
|
1412
1413
|
this.#assertOpen();
|
|
1414
|
+
const ids = members === undefined ? [sessionId] : [...members];
|
|
1415
|
+
if (ids.length === 0 ||
|
|
1416
|
+
!ids.includes(sessionId) ||
|
|
1417
|
+
new Set(ids).size !== ids.length ||
|
|
1418
|
+
(kind === 'clear' && (ids.length !== 1 || ids[0] !== sessionId)))
|
|
1419
|
+
throw new AgentError('MAR_AGENT_SESSION_INVALID', 'Invalid Session maintenance members.');
|
|
1420
|
+
ids.sort();
|
|
1421
|
+
for (const id of ids)
|
|
1422
|
+
this.#sessionRoot(id);
|
|
1413
1423
|
await this.#recoverPendingTreeDelete(sessionId);
|
|
1414
1424
|
return acquireTreeMaintenance({
|
|
1415
1425
|
sessionId,
|
|
1416
1426
|
kind,
|
|
1417
|
-
tree: () =>
|
|
1427
|
+
tree: async () => {
|
|
1428
|
+
await this.#refreshIndex();
|
|
1429
|
+
if (ids.some((id) => !this.#shared.index.sessions.some((session) => session.id === id)))
|
|
1430
|
+
throw new AgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
|
|
1431
|
+
return ids;
|
|
1432
|
+
},
|
|
1418
1433
|
acquire: (id, holding, registerGate) => this.#serializeRecordOperation(id, async () => {
|
|
1419
1434
|
this.#assertOpen();
|
|
1420
1435
|
registerGate(await this.#acquirePublicationGate(id));
|
package/dist/session/types.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ export async function executeSleep(arguments_, context, callId) {
|
|
|
36
36
|
durationMs,
|
|
37
37
|
startedAt: new Date().toISOString()
|
|
38
38
|
});
|
|
39
|
-
const messages = context.
|
|
39
|
+
const messages = context.contextUpdates;
|
|
40
40
|
const outcome = await waitForToolCondition({
|
|
41
41
|
ready: () => messages?.pending() ?? false,
|
|
42
42
|
subscribe: (notify) => messages?.subscribe(notify) ?? (() => { }),
|
package/dist/tools/callers.js
CHANGED
|
@@ -15,18 +15,7 @@ export function toolCallers(tool) {
|
|
|
15
15
|
export function allowsToolCaller(tool, caller) {
|
|
16
16
|
// Control tools cannot be widened by a Host override or historical definition.
|
|
17
17
|
if (caller === 'programmatic' &&
|
|
18
|
-
[
|
|
19
|
-
'code_exec',
|
|
20
|
-
'code_exec_wait',
|
|
21
|
-
'tool_search',
|
|
22
|
-
'question',
|
|
23
|
-
'skill',
|
|
24
|
-
'sleep',
|
|
25
|
-
'agent_start',
|
|
26
|
-
'agent_wait',
|
|
27
|
-
'agent_message',
|
|
28
|
-
'agent_cancel'
|
|
29
|
-
].includes(tool.name))
|
|
18
|
+
['code_exec', 'code_exec_wait', 'tool_search', 'question', 'skill', 'sleep'].includes(tool.name))
|
|
30
19
|
return false;
|
|
31
20
|
return toolCallers(tool).includes(caller);
|
|
32
21
|
}
|
|
@@ -32,7 +32,9 @@ export function createCodeToolDispatch(input) {
|
|
|
32
32
|
...(expected ? { expectedMcpTool: expected } : {})
|
|
33
33
|
}, 'programmatic');
|
|
34
34
|
const bounded = boundedModelToolOutput(call.name, result.content, result.data);
|
|
35
|
-
const data = structuredToolEventData(call.name,
|
|
35
|
+
const data = structuredToolEventData(call.name, call.name === 'exec' || call.name === 'exec_wait'
|
|
36
|
+
? (result.eventData ?? result.data)
|
|
37
|
+
: result.data);
|
|
36
38
|
const preview = toolEventSummary(result.content);
|
|
37
39
|
input.assertLive();
|
|
38
40
|
await input.emit({
|
|
@@ -44,8 +46,9 @@ export function createCodeToolDispatch(input) {
|
|
|
44
46
|
truncated: result.truncated === true || bounded.truncated || preview.truncated,
|
|
45
47
|
...(result.artifacts ? { artifacts: result.artifacts } : {})
|
|
46
48
|
});
|
|
49
|
+
const { eventData: _eventData, ...guestResult } = result;
|
|
47
50
|
return {
|
|
48
|
-
...
|
|
51
|
+
...guestResult,
|
|
49
52
|
content: bounded.content,
|
|
50
53
|
truncated: result.truncated === true || bounded.truncated
|
|
51
54
|
};
|
|
@@ -22,7 +22,7 @@ export declare class CodeModeTool {
|
|
|
22
22
|
wait(value: unknown, context: ToolExecutionContext): Promise<ToolExecutionResult>;
|
|
23
23
|
listSessionResources(sessionId: string): {
|
|
24
24
|
cellId: string;
|
|
25
|
-
status: "
|
|
25
|
+
status: "running" | "failed" | "cancelled" | "completed";
|
|
26
26
|
executionId: string;
|
|
27
27
|
}[];
|
|
28
28
|
constructor(paths: WorkspacePathResolver, environment: NodeJS.ProcessEnv | undefined, executor: LocalProcessExecutor, signalProcessTree: (child: import('node:child_process').ChildProcessWithoutNullStreams, signal: NodeJS.Signals) => Promise<void>, engineFactory?: CodeModeEngineFactory);
|