@myagentroam/agent 0.11.38 → 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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { contextGcTargetKey } from '../../session/context-gc-checkpoint.js';
|
|
2
|
-
import { contextGcWebOutputReplacement } from '../../session/context-gc-replacements.js';
|
|
2
|
+
import { contextGcWebOutputReplacement, contextGcToolOutputReplacement, isGenericContextGcTool } from '../../session/context-gc-replacements.js';
|
|
3
3
|
import { CONTEXT_GC_POLICY } from './gc-economics.js';
|
|
4
4
|
import { successfulRolloutsAfter, targetFor, isRecord } from './gc-candidates.js';
|
|
5
5
|
export function collectWebCandidates(input, groups, existingTargets, candidateSavings) {
|
|
@@ -53,6 +53,58 @@ export function collectWebCandidates(input, groups, existingTargets, candidateSa
|
|
|
53
53
|
}
|
|
54
54
|
return { eligible, protectedTokens, retryAfterRollouts };
|
|
55
55
|
}
|
|
56
|
+
/** Generic successful tool results share output economics, without inferring resource state. */
|
|
57
|
+
export function collectToolOutputCandidates(input, groups, existingTargets, candidateSavings) {
|
|
58
|
+
const eligible = [];
|
|
59
|
+
let protectedTokens = 0;
|
|
60
|
+
let retryAfterRollouts = Infinity;
|
|
61
|
+
for (const group of groups.values()) {
|
|
62
|
+
if (!isGenericContextGcTool(group.toolName) ||
|
|
63
|
+
group.evidenceOnly ||
|
|
64
|
+
!group.call ||
|
|
65
|
+
!group.result ||
|
|
66
|
+
group.failed ||
|
|
67
|
+
!group.completed ||
|
|
68
|
+
group.call.message.role !== 'tool_call' ||
|
|
69
|
+
group.result.message.role !== 'tool' ||
|
|
70
|
+
typeof group.result.message.content !== 'string' ||
|
|
71
|
+
!isRecord(group.completed.payload) ||
|
|
72
|
+
group.completed.payload.type !== 'tool.completed' ||
|
|
73
|
+
group.completed.payload.callId !== group.callId ||
|
|
74
|
+
group.completed.payload.toolName !== group.toolName ||
|
|
75
|
+
typeof group.completed.payload.truncated !== 'boolean')
|
|
76
|
+
continue;
|
|
77
|
+
const target = targetFor(group.result.record, group.result.message);
|
|
78
|
+
if (!target || existingTargets.has(contextGcTargetKey(target)))
|
|
79
|
+
continue;
|
|
80
|
+
const evidenceSequence = group.result.record.sequence;
|
|
81
|
+
const observedRollouts = successfulRolloutsAfter(input.records, evidenceSequence, input.modelId, input.contextWindowTokens);
|
|
82
|
+
const candidate = {
|
|
83
|
+
replacements: [
|
|
84
|
+
{
|
|
85
|
+
kind: 'TOOL_OUTPUT',
|
|
86
|
+
toolName: group.toolName,
|
|
87
|
+
callId: group.callId,
|
|
88
|
+
target,
|
|
89
|
+
replacementContent: contextGcToolOutputReplacement(group.toolName, group.result.message.content, group.completed.payload.truncated),
|
|
90
|
+
evidenceSequence
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
observedRollouts,
|
|
94
|
+
evidenceSequence
|
|
95
|
+
};
|
|
96
|
+
const reclaimedTokens = candidateSavings(candidate);
|
|
97
|
+
if (reclaimedTokens <= 0)
|
|
98
|
+
continue;
|
|
99
|
+
if (observedRollouts >= CONTEXT_GC_POLICY.largeExecProtectionRollouts)
|
|
100
|
+
eligible.push(candidate);
|
|
101
|
+
else {
|
|
102
|
+
protectedTokens += reclaimedTokens;
|
|
103
|
+
retryAfterRollouts = Math.min(retryAfterRollouts, CONTEXT_GC_POLICY.largeExecProtectionRollouts - observedRollouts);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return { eligible, protectedTokens, retryAfterRollouts };
|
|
107
|
+
}
|
|
56
108
|
function isContextGcWebToolName(value) {
|
|
57
109
|
return value === 'web_search' || value === 'web_fetch';
|
|
58
110
|
}
|
|
@@ -44,15 +44,7 @@ export function buildToolGroups(records, messages, sources) {
|
|
|
44
44
|
continue;
|
|
45
45
|
const record = sources[index];
|
|
46
46
|
for (const entry of message.calls ?? []) {
|
|
47
|
-
if (![
|
|
48
|
-
'apply_patch',
|
|
49
|
-
'exec',
|
|
50
|
-
'exec_wait',
|
|
51
|
-
'agent_start',
|
|
52
|
-
'agent_wait',
|
|
53
|
-
'agent_message',
|
|
54
|
-
'agent_cancel'
|
|
55
|
-
].includes(entry.toolName) ||
|
|
47
|
+
if (!['apply_patch', 'exec', 'exec_wait'].includes(entry.toolName) ||
|
|
56
48
|
(entry.status === 'completed' &&
|
|
57
49
|
message.observations.some((value) => value.type === 'tool_result' && value.source.callId === entry.callId)))
|
|
58
50
|
continue;
|
|
@@ -5,9 +5,8 @@ import { CONTEXT_GC_POLICY, COMPACT_CREDIT_ACTIVATION_RATIO, COMPACT_THRESHOLD_R
|
|
|
5
5
|
import { buildToolGroups, countSuccessfulNormalRollouts, isRecord } from './gc-candidates.js';
|
|
6
6
|
import { collectCodeModeCandidates } from './gc-candidates-code.js';
|
|
7
7
|
import { collectStageACandidates } from './gc-candidates-read-patch.js';
|
|
8
|
-
import { collectSubagentCandidates } from './gc-candidates-subagent.js';
|
|
9
8
|
import { collectExecCandidates } from './gc-candidates-exec.js';
|
|
10
|
-
import { collectWebCandidates } from './gc-candidates-web.js';
|
|
9
|
+
import { collectToolOutputCandidates, collectWebCandidates } from './gc-candidates-web.js';
|
|
11
10
|
export { CONTEXT_GC_POLICY, evaluateContextGcEconomics, contextGcMinimumGrossReductionRate, contextGcMinimumReclaimedTokens, contextGcEligibleUsage, contextGcMarginalCacheInvestmentPaysBack, contextGcImminentCompactAvoidanceCredit, contextGcAppliedCompactCreditCostUnits } from './gc-economics.js';
|
|
12
11
|
export function planContextGc(input) {
|
|
13
12
|
return inspectContextGc(input).plan;
|
|
@@ -110,9 +109,8 @@ function inspectTextGc(input) {
|
|
|
110
109
|
: [])
|
|
111
110
|
]));
|
|
112
111
|
const stageA = collectStageACandidates(input, groups, existing, existingTargets, candidateSavings);
|
|
113
|
-
const
|
|
114
|
-
const
|
|
115
|
-
const deterministicProtectedTokens = stageA.protectedTokens + subagent.protectedTokens;
|
|
112
|
+
const deterministicCandidates = stageA.eligible;
|
|
113
|
+
const deterministicProtectedTokens = stageA.protectedTokens;
|
|
116
114
|
const stageAPlan = evaluateCandidateSet(input, existing, deterministicCandidates, {
|
|
117
115
|
stage: 'STAGE_A',
|
|
118
116
|
contextUsageTokens,
|
|
@@ -125,10 +123,12 @@ function inspectTextGc(input) {
|
|
|
125
123
|
const exec = collectExecCandidates(input, groups, existingTargets, candidateSavings);
|
|
126
124
|
const codeMode = collectCodeModeCandidates(input, groups, existingTargets, candidateSavings);
|
|
127
125
|
const web = collectWebCandidates(input, groups, existingTargets, candidateSavings);
|
|
126
|
+
const tools = collectToolOutputCandidates(input, groups, existingTargets, candidateSavings);
|
|
128
127
|
const protectedCandidateTokens = deterministicProtectedTokens +
|
|
129
128
|
exec.protectedTokens +
|
|
130
129
|
codeMode.protectedTokens +
|
|
131
|
-
web.protectedTokens
|
|
130
|
+
web.protectedTokens +
|
|
131
|
+
tools.protectedTokens;
|
|
132
132
|
const stageAPlanWithProtectedCandidates = evaluateCandidateSet(input, existing, deterministicCandidates, {
|
|
133
133
|
stage: 'STAGE_A',
|
|
134
134
|
contextUsageTokens,
|
|
@@ -137,7 +137,7 @@ function inspectTextGc(input) {
|
|
|
137
137
|
normalRolloutOrdinal,
|
|
138
138
|
protectedCandidateTokens
|
|
139
139
|
}) ?? stageAPlan;
|
|
140
|
-
const marginal = mergeMarginalLargeOutputCandidates(input, existing, deterministicCandidates, [...exec.eligible, ...codeMode.eligible, ...web.eligible], stageAPlanWithProtectedCandidates, {
|
|
140
|
+
const marginal = mergeMarginalLargeOutputCandidates(input, existing, deterministicCandidates, [...exec.eligible, ...codeMode.eligible, ...web.eligible, ...tools.eligible], stageAPlanWithProtectedCandidates, {
|
|
141
141
|
contextUsageTokens,
|
|
142
142
|
usageRatio,
|
|
143
143
|
usageRecord,
|
|
@@ -147,7 +147,7 @@ function inspectTextGc(input) {
|
|
|
147
147
|
const plan = checkpointEligible
|
|
148
148
|
? finalizePlan(input, marginal ?? stageAPlanWithProtectedCandidates)
|
|
149
149
|
: undefined;
|
|
150
|
-
const retryAfterRollouts = Math.min(exec.retryAfterRollouts, codeMode.retryAfterRollouts, web.retryAfterRollouts);
|
|
150
|
+
const retryAfterRollouts = Math.min(exec.retryAfterRollouts, codeMode.retryAfterRollouts, web.retryAfterRollouts, tools.retryAfterRollouts);
|
|
151
151
|
if (!plan && checkpointEligible)
|
|
152
152
|
return {};
|
|
153
153
|
return {
|
|
@@ -160,11 +160,19 @@ function inspectTextGc(input) {
|
|
|
160
160
|
const exec = collectExecCandidates(input, groups, existingTargets, candidateSavings);
|
|
161
161
|
const codeMode = collectCodeModeCandidates(input, groups, existingTargets, candidateSavings);
|
|
162
162
|
const web = collectWebCandidates(input, groups, existingTargets, candidateSavings);
|
|
163
|
+
const tools = collectToolOutputCandidates(input, groups, existingTargets, candidateSavings);
|
|
163
164
|
const protectedCandidateTokens = deterministicProtectedTokens +
|
|
164
165
|
exec.protectedTokens +
|
|
165
166
|
codeMode.protectedTokens +
|
|
166
|
-
web.protectedTokens
|
|
167
|
-
|
|
167
|
+
web.protectedTokens +
|
|
168
|
+
tools.protectedTokens;
|
|
169
|
+
const combined = evaluateCandidateSet(input, existing, [
|
|
170
|
+
...deterministicCandidates,
|
|
171
|
+
...exec.eligible,
|
|
172
|
+
...codeMode.eligible,
|
|
173
|
+
...web.eligible,
|
|
174
|
+
...tools.eligible
|
|
175
|
+
], {
|
|
168
176
|
stage: 'STAGE_A_AND_EXEC',
|
|
169
177
|
contextUsageTokens,
|
|
170
178
|
usageRatio,
|
|
@@ -176,7 +184,7 @@ function inspectTextGc(input) {
|
|
|
176
184
|
const plan = finalizePlan(input, combined);
|
|
177
185
|
return plan ? { plan } : {};
|
|
178
186
|
}
|
|
179
|
-
const retryAfterRollouts = Math.min(stageA.retryAfterRollouts,
|
|
187
|
+
const retryAfterRollouts = Math.min(stageA.retryAfterRollouts, exec.retryAfterRollouts, codeMode.retryAfterRollouts, web.retryAfterRollouts, tools.retryAfterRollouts);
|
|
180
188
|
// A worthwhile mixed set retains every positive protected candidate's retry
|
|
181
189
|
// hint even when the checkpoint interval prevents a durable draft.
|
|
182
190
|
return protectedCandidateTokens > 0 &&
|
|
@@ -101,6 +101,7 @@ export function applyContextGcReplacementsToMessages(messages, messageSources, r
|
|
|
101
101
|
next = { ...next, arguments: structuredClone(replacement.replacementArguments) };
|
|
102
102
|
else if ((replacement.kind === 'EXEC_OUTPUT' ||
|
|
103
103
|
replacement.kind === 'CODE_MODE_OUTPUT' ||
|
|
104
|
+
replacement.kind === 'TOOL_OUTPUT' ||
|
|
104
105
|
replacement.kind === 'SUBAGENT_OUTPUT' ||
|
|
105
106
|
replacement.kind === 'WEB_OUTPUT') &&
|
|
106
107
|
next.role === 'tool')
|
package/dist/runtime/events.d.ts
CHANGED
|
@@ -104,7 +104,7 @@ export type AgentEvent = AgentEventBase & ({
|
|
|
104
104
|
summary: string;
|
|
105
105
|
truncated?: boolean;
|
|
106
106
|
artifacts?: readonly AgentToolArtifact[];
|
|
107
|
-
data?: CodeCellEventData | import('../tools/contracts.js').ExecResult | Omit<import('../tools/contracts.js').ExecResult, 'stdout' | 'stderr'> | import('../tools/contracts.js').ApplyPatchResult | import('../tools/contracts.js').ReadEventData | import('../tools/contracts.js').ViewImageResult | import('../
|
|
107
|
+
data?: CodeCellEventData | import('../tools/contracts.js').ExecResult | Omit<import('../tools/contracts.js').ExecResult, 'stdout' | 'stderr'> | import('../tools/contracts.js').ApplyPatchResult | import('../tools/contracts.js').ReadEventData | import('../tools/contracts.js').ViewImageResult | import('../tools/contracts.js').SleepResult | Readonly<Record<string, unknown>> | import('./public-tool-metadata.js').PublicToolMetadata;
|
|
108
108
|
} | {
|
|
109
109
|
type: 'tool.failed';
|
|
110
110
|
resultExtensions?: readonly import('../tools/result-extension-contract.js').ToolResultExtension[];
|
|
@@ -156,8 +156,9 @@ export type AgentEvent = AgentEventBase & ({
|
|
|
156
156
|
modelId?: string;
|
|
157
157
|
modelName?: string;
|
|
158
158
|
reasoningEffort?: AgentReasoningEffort;
|
|
159
|
-
|
|
160
|
-
|
|
159
|
+
/** Historical event fields retained for reading existing session records. */
|
|
160
|
+
latestMessage?: unknown;
|
|
161
|
+
latestActivity?: unknown;
|
|
161
162
|
errorCode?: string;
|
|
162
163
|
errorMessage?: string;
|
|
163
164
|
} | {
|
|
@@ -3,6 +3,8 @@ import type { AgentEvent } from './events.js';
|
|
|
3
3
|
/** A live execution exposes streamed events separately from its terminal result. */
|
|
4
4
|
export interface ExecutionHandle extends AsyncIterable<AgentEvent> {
|
|
5
5
|
readonly executionId: string;
|
|
6
|
+
/** Identity of the admitted Turn when the operation creates one. */
|
|
7
|
+
readonly turnId?: string;
|
|
6
8
|
result(): Promise<ExecutionResult>;
|
|
7
9
|
/** Signals abort; await result() to observe the terminal status and cleanup. */
|
|
8
10
|
cancel(): void;
|
package/dist/runtime/wait.js
CHANGED
|
@@ -49,8 +49,18 @@ export function waitForToolCondition(input) {
|
|
|
49
49
|
};
|
|
50
50
|
const abort = () => finish('interrupted', input.signal?.reason ??
|
|
51
51
|
new AgentError('MAR_AGENT_EXECUTION_CANCELLED', 'Execution cancelled.'));
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
const releaseSubscription = input.subscribe(check);
|
|
53
|
+
if (settled) {
|
|
54
|
+
releaseSubscription();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
unsubscribe = releaseSubscription;
|
|
58
|
+
const releaseInterrupt = input.interrupt?.subscribe(check) ?? (() => { });
|
|
59
|
+
if (settled) {
|
|
60
|
+
releaseInterrupt();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
unsubscribeInterrupt = releaseInterrupt;
|
|
54
64
|
cancelTimer = waitDeadline(input.waitMs, () => {
|
|
55
65
|
check();
|
|
56
66
|
finish('timeout');
|
package/dist/sdk/agent.js
CHANGED
|
@@ -13,6 +13,7 @@ import { toolCallers } from '../tools/callers.js';
|
|
|
13
13
|
import { AnthropicMessagesAdapter } from '../model/anthropic-messages.js';
|
|
14
14
|
import { OpenAiResponsesAdapter } from '../model/openai-responses.js';
|
|
15
15
|
import { JsonlSessionStore } from '../session/store/jsonl/jsonl-store.js';
|
|
16
|
+
import { createSessionCatalog } from '../session/catalog.js';
|
|
16
17
|
/** Validate models before Host negotiation and expose only built-in protocol adapters. */
|
|
17
18
|
export async function createAgent(options) {
|
|
18
19
|
if (Object.hasOwn(options, 'adapterFactory'))
|
|
@@ -33,6 +34,7 @@ export async function createAgentWithAdapter(options, adapterFactory) {
|
|
|
33
34
|
throw new AgentError('MAR_AGENT_SESSION_STORE_INVALID', 'Session store must not be null.');
|
|
34
35
|
const ownsStore = options.sessionStore === undefined;
|
|
35
36
|
const store = options.sessionStore ?? (await JsonlSessionStore.open(description.homeDirectory));
|
|
37
|
+
const historyCatalog = createSessionCatalog(store, true);
|
|
36
38
|
// The same adapter can be borrowed concurrently by Execution and Extension operations.
|
|
37
39
|
const activeExecutionAdapters = new Map();
|
|
38
40
|
const activeAdapterReferences = {
|
|
@@ -50,6 +52,23 @@ export async function createAgentWithAdapter(options, adapterFactory) {
|
|
|
50
52
|
}
|
|
51
53
|
};
|
|
52
54
|
const sessionRuntimes = new SessionRegistry();
|
|
55
|
+
const executionListeners = new Set();
|
|
56
|
+
const liveSession = (runtime) => ({
|
|
57
|
+
id: runtime.storedSession.id,
|
|
58
|
+
workspace: runtime.storedSession.workspace,
|
|
59
|
+
source: structuredClone(runtime.storedSession.source),
|
|
60
|
+
subscribe: (listener) => runtime.subscribe(listener)
|
|
61
|
+
});
|
|
62
|
+
const onExecutionRegistered = (runtime) => {
|
|
63
|
+
for (const listener of [...executionListeners]) {
|
|
64
|
+
try {
|
|
65
|
+
listener(liveSession(runtime));
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
/* Observers cannot affect execution admission. */
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
53
72
|
const sessionWriterOwner = {};
|
|
54
73
|
let disposed = false;
|
|
55
74
|
let disposal;
|
|
@@ -86,7 +105,6 @@ export async function createAgentWithAdapter(options, adapterFactory) {
|
|
|
86
105
|
'data.checkpoint',
|
|
87
106
|
'data.store',
|
|
88
107
|
'session',
|
|
89
|
-
'agents',
|
|
90
108
|
'settings',
|
|
91
109
|
...(options.host.extensionPorts?.environment ? ['environment'] : []),
|
|
92
110
|
...(options.host.extensionPorts?.files ? ['files'] : []),
|
|
@@ -109,7 +127,6 @@ export async function createAgentWithAdapter(options, adapterFactory) {
|
|
|
109
127
|
agentRole: sessionRuntimes.get(call.sessionId)?.sourceType === 'subagent' ? 'subagent' : 'root'
|
|
110
128
|
})),
|
|
111
129
|
sessionBackend: (id) => sessionRuntimes.get(id)?.sessionBackend,
|
|
112
|
-
agentsBackend: (id) => sessionRuntimes.get(id)?.agentsBackend,
|
|
113
130
|
scheduleTool: (id) => (definition, run) => {
|
|
114
131
|
const schedule = sessionRuntimes.get(id)?.scheduleTool;
|
|
115
132
|
if (!schedule)
|
|
@@ -180,7 +197,8 @@ export async function createAgentWithAdapter(options, adapterFactory) {
|
|
|
180
197
|
agentResources: {
|
|
181
198
|
activeExecutionAdapters: activeAdapterReferences,
|
|
182
199
|
sessionRuntimes,
|
|
183
|
-
sessionWriterOwner
|
|
200
|
+
sessionWriterOwner,
|
|
201
|
+
onExecutionRegistered
|
|
184
202
|
},
|
|
185
203
|
hasCustomAdapters: adapterFactory !== undefined,
|
|
186
204
|
modelState: () => ({ models, defaultModelId, generation: modelGeneration }),
|
|
@@ -197,9 +215,39 @@ export async function createAgentWithAdapter(options, adapterFactory) {
|
|
|
197
215
|
});
|
|
198
216
|
return {
|
|
199
217
|
extensionDiagnostics: () => extensions.diagnostics(),
|
|
218
|
+
observeSessionExecutions: (listener) => {
|
|
219
|
+
assertSessionAdmission();
|
|
220
|
+
executionListeners.add(listener);
|
|
221
|
+
const sessions = [...sessionRuntimes.values()]
|
|
222
|
+
.filter((runtime) => runtime.activeExecutionId !== undefined)
|
|
223
|
+
.map(liveSession);
|
|
224
|
+
return {
|
|
225
|
+
sessions,
|
|
226
|
+
unsubscribe: () => {
|
|
227
|
+
executionListeners.delete(listener);
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
},
|
|
200
231
|
createSession: async (input) => {
|
|
201
232
|
assertSessionAdmission();
|
|
202
|
-
|
|
233
|
+
if (input.source !== undefined &&
|
|
234
|
+
input.parentSessionId !== undefined &&
|
|
235
|
+
input.source.parentSessionId !== input.parentSessionId)
|
|
236
|
+
throw new AgentError('MAR_AGENT_SESSION_SOURCE_INVALID', 'Session source conflicts with its parent.');
|
|
237
|
+
return sessionRuntimes.trackOpen(undefined, async () => {
|
|
238
|
+
const created = await store.createSession({
|
|
239
|
+
workspace: input.workspace,
|
|
240
|
+
...(input.title === undefined ? {} : { title: input.title }),
|
|
241
|
+
...(input.source !== undefined
|
|
242
|
+
? { source: input.source }
|
|
243
|
+
: input.parentSessionId === undefined
|
|
244
|
+
? {}
|
|
245
|
+
: {
|
|
246
|
+
source: { type: 'user', parentSessionId: input.parentSessionId }
|
|
247
|
+
})
|
|
248
|
+
});
|
|
249
|
+
return openSession(created.id, input.workspace);
|
|
250
|
+
});
|
|
203
251
|
},
|
|
204
252
|
openSession: (id) => openSession(id),
|
|
205
253
|
listSessions: async (input) => {
|
|
@@ -210,6 +258,46 @@ export async function createAgentWithAdapter(options, adapterFactory) {
|
|
|
210
258
|
assertSessionAdmission();
|
|
211
259
|
return store.getSession(id);
|
|
212
260
|
},
|
|
261
|
+
sessionHistory: async (id, input) => {
|
|
262
|
+
assertSessionAdmission(id);
|
|
263
|
+
return historyCatalog.history(id, input);
|
|
264
|
+
},
|
|
265
|
+
sessionInputReceipt: async (id, input) => {
|
|
266
|
+
assertSessionAdmission(id);
|
|
267
|
+
return historyCatalog.inputReceipt(id, input);
|
|
268
|
+
},
|
|
269
|
+
sessionExecutionWasInterrupted: async (id, executionId, input) => {
|
|
270
|
+
assertSessionAdmission(id);
|
|
271
|
+
input?.signal?.throwIfAborted();
|
|
272
|
+
// Maintenance admission excludes every writer without adopting pending resources.
|
|
273
|
+
const maintenance = await store.acquireSessionMaintenance(id, 'clear', sessionWriterOwner);
|
|
274
|
+
try {
|
|
275
|
+
input?.signal?.throwIfAborted();
|
|
276
|
+
if (sessionRuntimes.get(id)?.activeExecutionId !== undefined)
|
|
277
|
+
return false;
|
|
278
|
+
let cursor;
|
|
279
|
+
do {
|
|
280
|
+
const page = await historyCatalog.history(id, {
|
|
281
|
+
limit: 100,
|
|
282
|
+
...(cursor === undefined ? {} : { cursor })
|
|
283
|
+
});
|
|
284
|
+
input?.signal?.throwIfAborted();
|
|
285
|
+
const latest = page.entries
|
|
286
|
+
.flatMap((entry) => (entry.kind === 'event' ? [entry.event] : []))
|
|
287
|
+
.findLast((event) => event.type === 'execution.started' ||
|
|
288
|
+
event.type === 'execution.completed' ||
|
|
289
|
+
event.type === 'execution.failed' ||
|
|
290
|
+
event.type === 'execution.cancelled');
|
|
291
|
+
if (latest)
|
|
292
|
+
return latest.type === 'execution.started' && latest.executionId === executionId;
|
|
293
|
+
cursor = page.nextCursor;
|
|
294
|
+
} while (cursor);
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
finally {
|
|
298
|
+
await maintenance.release();
|
|
299
|
+
}
|
|
300
|
+
},
|
|
213
301
|
setSessionTitle: async (id, title, input) => {
|
|
214
302
|
assertSessionAdmission();
|
|
215
303
|
return store.updateTitle(id, title, { ...input, automatic: input?.automatic ?? false }, sessionWriterOwner);
|
|
@@ -293,10 +381,12 @@ export async function createAgentWithAdapter(options, adapterFactory) {
|
|
|
293
381
|
}
|
|
294
382
|
},
|
|
295
383
|
deleteSession: (id) => maintenanceCoordinator.delete(id),
|
|
384
|
+
deleteSessions: (ids) => maintenanceCoordinator.deleteMembers(ids),
|
|
296
385
|
dispose: () => {
|
|
297
386
|
if (disposal)
|
|
298
387
|
return disposal;
|
|
299
388
|
disposed = true;
|
|
389
|
+
executionListeners.clear();
|
|
300
390
|
for (const runtime of sessionRuntimes.values())
|
|
301
391
|
runtime.cancelExecutions();
|
|
302
392
|
// Explicit end observers finish in a separate lifecycle frame before Session retirement.
|
|
@@ -307,7 +397,6 @@ export async function createAgentWithAdapter(options, adapterFactory) {
|
|
|
307
397
|
() => maintenanceCoordinator.join(),
|
|
308
398
|
() => extensions.dispose(),
|
|
309
399
|
...runtimes.map((runtime) => () => runtime.retireInputs()),
|
|
310
|
-
...runtimes.map((runtime) => () => runtime.disposeSubagents()),
|
|
311
400
|
() => Promise.all(runtimes.map((runtime) => runtime.joinExecutions())),
|
|
312
401
|
() => pendingReconfiguration,
|
|
313
402
|
() => SessionRuntime.closeModelAdapters(runtimes),
|
|
@@ -25,7 +25,6 @@ export declare class ExecutionContextCoordinator {
|
|
|
25
25
|
readonly window: number;
|
|
26
26
|
readonly gc: Pick<ContextGcRuntime, 'run'>;
|
|
27
27
|
readonly gcBase: Omit<ContextGcRuntimeInput, 'system' | 'tools' | 'usage' | 'inlineMedia' | 'mediaView' | 'getActiveProcessIds'>;
|
|
28
|
-
readonly child: boolean;
|
|
29
28
|
start(input?: {
|
|
30
29
|
focus?: string;
|
|
31
30
|
async?: boolean;
|
|
@@ -41,9 +40,9 @@ export declare class ExecutionContextCoordinator {
|
|
|
41
40
|
advanceBoundary(): void;
|
|
42
41
|
drainRequests(): boolean;
|
|
43
42
|
prepareInputs(ports: {
|
|
44
|
-
|
|
43
|
+
includeSessionContext: boolean;
|
|
45
44
|
appendMailbox(): Promise<unknown>;
|
|
46
|
-
|
|
45
|
+
appendSessionContext(): Promise<void>;
|
|
47
46
|
refreshTools(): void;
|
|
48
47
|
updateEnvironment(): void;
|
|
49
48
|
}): Promise<void>;
|
|
@@ -26,8 +26,8 @@ export class ExecutionContextCoordinator {
|
|
|
26
26
|
}
|
|
27
27
|
async prepareInputs(ports) {
|
|
28
28
|
await ports.appendMailbox();
|
|
29
|
-
if (ports.
|
|
30
|
-
await ports.
|
|
29
|
+
if (ports.includeSessionContext)
|
|
30
|
+
await ports.appendSessionContext();
|
|
31
31
|
ports.refreshTools();
|
|
32
32
|
await this.ports.context.syncMcpWorldState(this.ports.messages.length);
|
|
33
33
|
this.advanceBoundary();
|
|
@@ -80,7 +80,7 @@ export class ExecutionContextCoordinator {
|
|
|
80
80
|
this.ports.signal.throwIfAborted();
|
|
81
81
|
this.ports.execution.assertContextValid();
|
|
82
82
|
});
|
|
83
|
-
if (!this.ports.compact.pending
|
|
83
|
+
if (!this.ports.compact.pending)
|
|
84
84
|
await this.gc(round, usage, await this.ports.resources.gcCandidate(), true);
|
|
85
85
|
}
|
|
86
86
|
async gc(round, usage, media, includeProcesses = false) {
|
|
@@ -4,6 +4,7 @@ import type { SessionModelMessage as ModelMessage } from '../session/model-reque
|
|
|
4
4
|
import { SessionInputCoordinator, type SessionInputEntry, type ExtensionSessionRequest, type ExtensionSessionActionResult } from '../extensions/session-input.js';
|
|
5
5
|
import type { ExtensionPromptInput, ExtensionPromptResult } from '../extensions/prompt-input.js';
|
|
6
6
|
import type { ExtensionOperationContext } from '../extensions/operation.js';
|
|
7
|
+
import type { ExtensionSessionContextProvider } from '../extensions/session-context.js';
|
|
7
8
|
import type { ResolvedModelConfiguration } from './model-runtime.js';
|
|
8
9
|
import type { SmartCompactionInput } from '../runtime/compaction/smart.js';
|
|
9
10
|
import type { CompactFlight } from '../runtime/compaction/coordinator.js';
|
|
@@ -11,7 +12,6 @@ import { type ResourcePublisher } from '../runtime/resource-publication.js';
|
|
|
11
12
|
import type { createExecutionModelContext } from './execution-model-context.js';
|
|
12
13
|
import type { InternalExecutionOptions } from './session-execution.js';
|
|
13
14
|
import type { RunInput } from './types.js';
|
|
14
|
-
import type { SubagentSessionController } from '../subagent/session-controller.js';
|
|
15
15
|
/** Owns committed input, mailbox admission and live projection for one Execution. */
|
|
16
16
|
export declare function createExecutionInput(input: {
|
|
17
17
|
host: ResourcePublisher;
|
|
@@ -20,7 +20,6 @@ export declare function createExecutionInput(input: {
|
|
|
20
20
|
executionId: string;
|
|
21
21
|
turnId: string;
|
|
22
22
|
mode: 'run' | 'plan' | 'compact';
|
|
23
|
-
source: 'user' | 'subagent';
|
|
24
23
|
controller: AbortController;
|
|
25
24
|
inputs: Pick<SessionInputCoordinator, 'drain' | 'boundarySize'>;
|
|
26
25
|
messages: ModelMessage[];
|
|
@@ -52,7 +51,7 @@ export declare function createExecutionInput(input: {
|
|
|
52
51
|
enqueue(content: ExtensionPromptInput, call: ExtensionOperationContext): Promise<unknown>;
|
|
53
52
|
project(actual: ExtensionPromptInput, metadata: NonNullable<ModelMessage["metadata"]>): void;
|
|
54
53
|
}) => Promise<boolean>;
|
|
55
|
-
receiveSteer: (content: ExtensionPromptInput, clientMessageId: string, call: ExtensionOperationContext) => Promise<SessionRecord>;
|
|
56
|
-
|
|
54
|
+
receiveSteer: (content: ExtensionPromptInput, clientMessageId: string, call: ExtensionOperationContext, source?: import("../extensions/session-input.js").ExtensionInputSource) => Promise<SessionRecord>;
|
|
55
|
+
appendExtensionContext: (provider: ExtensionSessionContextProvider | undefined) => Promise<void>;
|
|
57
56
|
appendMailboxMessages: (restoring?: boolean) => Promise<boolean>;
|
|
58
57
|
};
|
|
@@ -4,11 +4,9 @@ import { inputMetadataFromRecord } from '../session/record-projection.js';
|
|
|
4
4
|
import { AGENT_EXECUTION_POLICY } from '../runtime/execution-policy.js';
|
|
5
5
|
import { publishModelResources } from '../runtime/resource-publication.js';
|
|
6
6
|
import { extensionInputSource } from './extension-session-launch.js';
|
|
7
|
-
import { renderSubagentUpdate } from '../subagent/model-update.js';
|
|
8
7
|
/** Owns committed input, mailbox admission and live projection for one Execution. */
|
|
9
8
|
export function createExecutionInput(input) {
|
|
10
9
|
const { host, store, sessionId, executionId, turnId, mode, controller, inputs, messages, pendingInputs, messageSources, modelContext, model, tokens, setSmartInput, withRecordProjection, appendExtensionMessage, startCompact, compactContext } = input;
|
|
11
|
-
const sessionSource = { type: input.source };
|
|
12
10
|
const writeInputRecord = async (content, type, metadata, call, commitEvidence, projectCommitted) => {
|
|
13
11
|
call.signal.throwIfAborted();
|
|
14
12
|
if (content.images?.length && !model().inputCapabilities.includes('IMAGE'))
|
|
@@ -17,7 +15,6 @@ export function createExecutionInput(input) {
|
|
|
17
15
|
call.signal.throwIfAborted();
|
|
18
16
|
const smartPercent = tokens() === undefined ? undefined : (tokens() * 100) / model().contextWindowTokens;
|
|
19
17
|
const smartCompaction = mode !== 'compact' &&
|
|
20
|
-
sessionSource.type === 'user' &&
|
|
21
18
|
type === 'turn.user' &&
|
|
22
19
|
metadata.inputSource === undefined &&
|
|
23
20
|
smartPercent !== undefined &&
|
|
@@ -64,6 +61,13 @@ export function createExecutionInput(input) {
|
|
|
64
61
|
projectCommitted(actualContent, record.recordId, inputMetadata);
|
|
65
62
|
for (const text of content.modelContext ?? content.context ?? [])
|
|
66
63
|
messages.push({ role: 'user', content: text, contextKind: 'contextual' });
|
|
64
|
+
if (metadata.clientMessageId)
|
|
65
|
+
await store.append(sessionId, {
|
|
66
|
+
type: 'input.applied',
|
|
67
|
+
payload: { inputRef: record.recordId },
|
|
68
|
+
executionId,
|
|
69
|
+
turnId
|
|
70
|
+
});
|
|
67
71
|
});
|
|
68
72
|
};
|
|
69
73
|
const appendMailboxMessages = async (restoring = false) => inputs.drain(async (entry, request, call) => {
|
|
@@ -91,8 +95,7 @@ export function createExecutionInput(input) {
|
|
|
91
95
|
if (images.length && !model().inputCapabilities.includes('IMAGE'))
|
|
92
96
|
throw new AgentError('MAR_AGENT_INPUT_CAPABILITY_UNSUPPORTED', 'Selected model does not support image input.');
|
|
93
97
|
const percent = tokens() === undefined ? undefined : (tokens() * 100) / model().contextWindowTokens;
|
|
94
|
-
const eligible =
|
|
95
|
-
percent !== undefined &&
|
|
98
|
+
const eligible = percent !== undefined &&
|
|
96
99
|
percent >= AGENT_EXECUTION_POLICY.smartCompactionPercent &&
|
|
97
100
|
percent < AGENT_EXECUTION_POLICY.automaticCompactionPercent;
|
|
98
101
|
const actual = {
|
|
@@ -135,7 +138,6 @@ export function createExecutionInput(input) {
|
|
|
135
138
|
return outcome;
|
|
136
139
|
});
|
|
137
140
|
}
|
|
138
|
-
const parent = entry.parentMessage;
|
|
139
141
|
let outcome;
|
|
140
142
|
const content = {
|
|
141
143
|
text: request.input.text,
|
|
@@ -146,15 +148,9 @@ export function createExecutionInput(input) {
|
|
|
146
148
|
: { modelContext: request.input.modelContext }),
|
|
147
149
|
...(request.input.images === undefined ? {} : { images: request.input.images })
|
|
148
150
|
};
|
|
149
|
-
await writeInputRecord(content,
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
...(parent.delivery ? { messageId: parent.delivery.messageId } : {})
|
|
153
|
-
}
|
|
154
|
-
: {
|
|
155
|
-
source: extensionInputSource(call, request.input.provenance, request.input.modelAttribution),
|
|
156
|
-
...(parent?.delivery ? { messageId: parent.delivery.messageId } : {})
|
|
157
|
-
}, call, (recordId) => {
|
|
151
|
+
await writeInputRecord(content, 'extension.input', {
|
|
152
|
+
source: extensionInputSource(call, request.input.provenance, request.input.modelAttribution)
|
|
153
|
+
}, call, (recordId) => {
|
|
158
154
|
outcome = { changed: true, executionId, recordId };
|
|
159
155
|
recordSessionInputCommit(entry, outcome);
|
|
160
156
|
}, (actual, recordId, metadata) => {
|
|
@@ -168,7 +164,6 @@ export function createExecutionInput(input) {
|
|
|
168
164
|
}
|
|
169
165
|
: {})
|
|
170
166
|
});
|
|
171
|
-
parent?.delivery?.applied();
|
|
172
167
|
});
|
|
173
168
|
return outcome;
|
|
174
169
|
}, {
|
|
@@ -195,7 +190,6 @@ export function createExecutionInput(input) {
|
|
|
195
190
|
const { internal, input: request } = ports;
|
|
196
191
|
await writeInputRecord(content, internal.inputSource === 'extension' ? 'extension.input' : 'turn.user', {
|
|
197
192
|
...(internal.extensionSource ? { source: internal.extensionSource } : {}),
|
|
198
|
-
...(internal.delivery ? { messageId: internal.delivery.messageId } : {}),
|
|
199
193
|
...(internal.inputSource === undefined ? {} : { inputSource: internal.inputSource }),
|
|
200
194
|
...(request.clientMessageId ? { clientMessageId: request.clientMessageId } : {})
|
|
201
195
|
}, call, (recordId) => {
|
|
@@ -203,7 +197,6 @@ export function createExecutionInput(input) {
|
|
|
203
197
|
internal.inputCommitted?.(recordId);
|
|
204
198
|
}, (actual, _recordId, metadata) => {
|
|
205
199
|
ports.project(actual, metadata);
|
|
206
|
-
internal.delivery?.applied();
|
|
207
200
|
});
|
|
208
201
|
return {};
|
|
209
202
|
};
|
|
@@ -218,7 +211,7 @@ export function createExecutionInput(input) {
|
|
|
218
211
|
await ports.operation((call) => internal.promptAdmitted ? write(content, call) : ports.admit(content, call, write));
|
|
219
212
|
return entered;
|
|
220
213
|
};
|
|
221
|
-
const receiveSteer = (content, clientMessageId, call) => withRecordProjection(async () => {
|
|
214
|
+
const receiveSteer = (content, clientMessageId, call, source) => withRecordProjection(async () => {
|
|
222
215
|
call.signal.throwIfAborted();
|
|
223
216
|
if (content.images?.length && !model().inputCapabilities.includes('IMAGE'))
|
|
224
217
|
throw new AgentError('MAR_AGENT_INPUT_CAPABILITY_UNSUPPORTED', 'Selected model does not support image input.');
|
|
@@ -234,6 +227,7 @@ export function createExecutionInput(input) {
|
|
|
234
227
|
...(content.modelText === undefined ? {} : { modelText: content.modelText }),
|
|
235
228
|
...(content.context === undefined ? {} : { context: content.context }),
|
|
236
229
|
...(content.modelContext === undefined ? {} : { modelContext: content.modelContext }),
|
|
230
|
+
...(source === undefined ? {} : { source }),
|
|
237
231
|
clientMessageId,
|
|
238
232
|
...(images.length ? { images } : {})
|
|
239
233
|
},
|
|
@@ -243,24 +237,36 @@ export function createExecutionInput(input) {
|
|
|
243
237
|
pendingInputs.set(record.recordId, record);
|
|
244
238
|
return record;
|
|
245
239
|
});
|
|
246
|
-
const
|
|
247
|
-
if (!
|
|
240
|
+
const appendExtensionContext = async (provider) => {
|
|
241
|
+
if (!provider)
|
|
248
242
|
return;
|
|
249
243
|
await withRecordProjection(async () => {
|
|
250
244
|
controller.signal.throwIfAborted();
|
|
251
|
-
|
|
245
|
+
const proposed = await provider.collect(controller.signal);
|
|
246
|
+
controller.signal.throwIfAborted();
|
|
247
|
+
if (!Array.isArray(proposed))
|
|
248
|
+
throw new AgentError('MAR_AGENT_EXTENSION_CONTEXT_INVALID', 'Invalid context batch.');
|
|
249
|
+
const batch = proposed.slice(0, 8);
|
|
250
|
+
for (const item of batch) {
|
|
251
|
+
if (typeof item?.content !== 'string' ||
|
|
252
|
+
item.content.length === 0 ||
|
|
253
|
+
Buffer.byteLength(item.content, 'utf8') > 32_768 ||
|
|
254
|
+
typeof item.acknowledge !== 'function')
|
|
255
|
+
throw new AgentError('MAR_AGENT_EXTENSION_CONTEXT_INVALID', 'Invalid context item.');
|
|
256
|
+
}
|
|
257
|
+
for (const item of batch) {
|
|
252
258
|
controller.signal.throwIfAborted();
|
|
253
259
|
const message = {
|
|
254
260
|
role: 'user',
|
|
255
|
-
content:
|
|
261
|
+
content: item.content,
|
|
256
262
|
contextKind: 'contextual'
|
|
257
263
|
};
|
|
258
264
|
const stored = await store.append(sessionId, { type: 'model.context', payload: message, executionId, turnId }, { signal: controller.signal });
|
|
259
265
|
messages.push(message);
|
|
260
266
|
messageSources.set(message, stored);
|
|
261
|
-
|
|
267
|
+
item.acknowledge();
|
|
262
268
|
}
|
|
263
269
|
});
|
|
264
270
|
};
|
|
265
|
-
return { startInitialInput, receiveSteer,
|
|
271
|
+
return { startInitialInput, receiveSteer, appendExtensionContext, appendMailboxMessages };
|
|
266
272
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Owns round retries when late input or resource collection invalidates a candidate. */
|
|
2
2
|
export declare function createExecutionRoundPreparer<Continuation, Candidate, Round>(ports: {
|
|
3
|
-
prepareInputs(
|
|
3
|
+
prepareInputs(includeSessionContext: boolean): Promise<void>;
|
|
4
4
|
buildCandidate(continuation: Continuation | undefined): Promise<Candidate>;
|
|
5
5
|
adoptLateInput(): Promise<boolean>;
|
|
6
6
|
prepareResources(candidate: Candidate): Promise<{
|