@arnilo/prism 0.6.0 → 0.8.0
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/CHANGELOG.md +79 -5
- package/README.md +12 -11
- package/dist/agent-approval.d.ts +4 -0
- package/dist/agent-approval.js +5 -1
- package/dist/agent-definitions.js +1 -0
- package/dist/agent-run-lifecycle.js +39 -4
- package/dist/agent-run-state.d.ts +18 -0
- package/dist/agent-run-state.js +39 -9
- package/dist/agent-session/helpers.js +6 -1
- package/dist/agent-session/session/assemble.js +159 -7
- package/dist/agent-session/session/persist.d.ts +16 -0
- package/dist/agent-session/session/persist.js +64 -4
- package/dist/agent-session/session/provider-round.d.ts +3 -3
- package/dist/agent-session/session/provider-round.js +12 -6
- package/dist/agent-session/session/tool-round.js +5 -1
- package/dist/agent-session/session/types.d.ts +22 -1
- package/dist/agent-session/session.d.ts +16 -0
- package/dist/agent-session/session.js +42 -3
- package/dist/artifacts.d.ts +39 -1
- package/dist/artifacts.js +73 -0
- package/dist/attention-compiler.d.ts +121 -0
- package/dist/attention-compiler.js +479 -0
- package/dist/checkpoints.js +7 -11
- package/dist/cli-init.js +20 -6
- package/dist/context-budget.d.ts +20 -1
- package/dist/context-budget.js +10 -1
- package/dist/contracts-core/agent.d.ts +7 -0
- package/dist/contracts-core/attention.d.ts +66 -0
- package/dist/contracts-core/attention.js +2 -0
- package/dist/contracts-core/compaction.d.ts +59 -0
- package/dist/contracts-core/compaction.js +77 -1
- package/dist/contracts-core/content.d.ts +5 -0
- package/dist/contracts-core/loop.d.ts +42 -0
- package/dist/contracts-core/provider.d.ts +4 -0
- package/dist/contracts-core/run-limits.d.ts +2 -0
- package/dist/contracts-core.d.ts +1 -0
- package/dist/contracts-core.js +1 -0
- package/dist/contracts-protocol.d.ts +44 -3
- package/dist/contracts-run-state.d.ts +32 -5
- package/dist/evidence-grounding.d.ts +29 -0
- package/dist/evidence-grounding.js +162 -0
- package/dist/host-composition.d.ts +91 -0
- package/dist/host-composition.js +279 -0
- package/dist/index.d.ts +13 -6
- package/dist/index.js +7 -4
- package/dist/input.d.ts +13 -1
- package/dist/input.js +40 -1
- package/dist/provider-events.d.ts +3 -1
- package/dist/provider-events.js +2 -2
- package/dist/providers/transport.d.ts +3 -1
- package/dist/providers/transport.js +36 -0
- package/dist/redaction.js +18 -2
- package/dist/run-bundle.d.ts +89 -0
- package/dist/run-bundle.js +149 -0
- package/dist/secure-agent.d.ts +2 -0
- package/dist/secure-agent.js +6 -1
- package/dist/testing/state-concurrency-conformance.js +5 -12
- package/dist/tool-result-fold.d.ts +12 -0
- package/dist/tool-result-fold.js +13 -6
- package/dist/tools.d.ts +10 -0
- package/dist/tools.js +41 -0
- package/docs/acp-agent.md +42 -11
- package/docs/acp.md +2 -1
- package/docs/ag-ui.md +10 -3
- package/docs/agent-definitions.md +9 -1
- package/docs/agent-events.md +4 -1
- package/docs/agent-loops.md +33 -0
- package/docs/agent-session-runtime.md +8 -7
- package/docs/attention-compiler.md +272 -0
- package/docs/cli-rpc.md +4 -2
- package/docs/coding-agent-tools.md +1 -1
- package/docs/coding-security.md +6 -3
- package/docs/coding-tools.md +0 -1
- package/docs/coding-workspaces.md +22 -0
- package/docs/compaction-and-retry.md +36 -4
- package/docs/compaction-observational-memory.md +63 -10
- package/docs/connected-apps.md +116 -0
- package/docs/context-and-skills.md +17 -2
- package/docs/conversations.md +1 -1
- package/docs/core.md +1 -1
- package/docs/dev-inspector.md +4 -0
- package/docs/device-adapters.md +1 -0
- package/docs/diagrams.md +6 -6
- package/docs/document-reader.md +18 -10
- package/docs/documents.md +40 -11
- package/docs/durable-runs.md +87 -0
- package/docs/enterprise-postgres-state.md +6 -2
- package/docs/evaluations.md +168 -4
- package/docs/execution-timeline.md +186 -0
- package/docs/guardrails.md +33 -0
- package/docs/history/0.7.0-primitive-review.md +254 -0
- package/docs/history/079-messaging-primitive-review.md +391 -0
- package/docs/history/080-messaging-followon-primitive-review.md +234 -0
- package/docs/history/081-connected-apps-primitive-review.md +74 -0
- package/docs/history/083-prism-work-primitive-review.md +84 -0
- package/docs/history/084-primitive-review.md +96 -0
- package/docs/history/085-honesty-and-cut-primitive-review.md +91 -0
- package/docs/history/README.md +5 -0
- package/docs/history/migration-0.0.md +2 -2
- package/docs/history/release-handoffs.md +75 -1
- package/docs/host-compositions.md +149 -0
- package/docs/host-security.md +2 -2
- package/docs/hosted-sandboxes.md +94 -0
- package/docs/index.md +82 -45
- package/docs/input-and-prompt-assembly.md +1 -0
- package/docs/knowledge-sync.md +84 -0
- package/docs/language-intelligence.md +1 -1
- package/docs/live-testing.md +8 -3
- package/docs/mcp-tools.md +3 -1
- package/docs/memory-fabric.md +416 -0
- package/docs/messaging-channel-operations.md +166 -0
- package/docs/messaging-channels.md +150 -0
- package/docs/migrate-to-0.5.md +1 -1
- package/docs/migrate-to-0.6.md +1 -0
- package/docs/migrate-to-0.7.md +345 -0
- package/docs/migrate-to-0.8.md +124 -0
- package/docs/migration.md +43 -1
- package/docs/model-registry.md +12 -2
- package/docs/model-routing.md +79 -4
- package/docs/multi-agent-patterns.md +20 -6
- package/docs/observability.md +52 -1
- package/docs/openapi-tools.md +1 -1
- package/docs/operations.md +14 -4
- package/docs/options-index.md +47 -3
- package/docs/peer-dependencies.md +12 -10
- package/docs/postgres-persistence.md +1 -1
- package/docs/process-sessions.md +3 -1
- package/docs/prompt-registry.md +1 -1
- package/docs/provider-caching.md +4 -2
- package/docs/provider-conformance.md +1 -1
- package/docs/provider-layer.md +2 -2
- package/docs/provider-packages.md +22 -22
- package/docs/providers/bedrock.md +71 -7
- package/docs/providers/neuralwatt.md +5 -1
- package/docs/providers/openai.md +1 -1
- package/docs/rag.md +24 -8
- package/docs/realtime-voice.md +87 -0
- package/docs/release-and-install.md +53 -45
- package/docs/run-bundle.md +92 -0
- package/docs/runs-and-usage.md +17 -2
- package/docs/server.md +7 -3
- package/docs/sheets.md +9 -9
- package/docs/signal-channel.md +112 -0
- package/docs/speech.md +7 -1
- package/docs/sqlite-persistence.md +1 -1
- package/docs/supervisors.md +33 -5
- package/docs/telegram-channel.md +157 -0
- package/docs/testing.md +2 -2
- package/docs/thinking-and-reasoning.md +3 -1
- package/docs/tools.md +6 -5
- package/docs/web-tools.md +2 -1
- package/docs/wiki.md +1 -1
- package/docs/work-artifacts-and-review.md +14 -4
- package/docs/work-connectors.md +12 -10
- package/docs/work-sandbox.md +115 -0
- package/docs/work-tools.md +50 -18
- package/docs/workflows.md +69 -1
- package/docs/working-and-semantic-memory.md +25 -14
- package/package.json +5 -3
- package/templates/README.md +2 -0
- package/templates/business-worker/README.md.tmpl +19 -0
- package/templates/business-worker/env.example.tmpl +1 -0
- package/templates/business-worker/gitignore.tmpl +11 -0
- package/templates/business-worker/manifest.json +12 -0
- package/templates/business-worker/package.json.tmpl +23 -0
- package/templates/business-worker/src/agent.ts.tmpl +92 -0
- package/templates/business-worker/src/index.ts.tmpl +13 -0
- package/templates/business-worker/src/tests/agent.test.ts.tmpl +77 -0
- package/templates/business-worker/tsconfig.json.tmpl +15 -0
- package/templates/personal-assistant/README.md.tmpl +18 -0
- package/templates/personal-assistant/env.example.tmpl +1 -0
- package/templates/personal-assistant/gitignore.tmpl +11 -0
- package/templates/personal-assistant/manifest.json +11 -0
- package/templates/personal-assistant/package.json.tmpl +23 -0
- package/templates/personal-assistant/src/agent.ts.tmpl +65 -0
- package/templates/personal-assistant/src/index.ts.tmpl +13 -0
- package/templates/personal-assistant/src/tests/agent.test.ts.tmpl +28 -0
- package/templates/personal-assistant/tsconfig.json.tmpl +15 -0
|
@@ -3,6 +3,7 @@ import { AgentRunSuspended } from "../../agent-approval.js";
|
|
|
3
3
|
import { resolveLoop, resolveToolConcurrency } from "../../agent-loops.js";
|
|
4
4
|
import { validateRunStateOptions } from "../../agent-run-state.js";
|
|
5
5
|
import { activeTools } from "../../agent-tool-dispatch.js";
|
|
6
|
+
import { resolveRunAttentionCompiler } from "../../attention-compiler.js";
|
|
6
7
|
import { AgentLoopStateError, AgentRunError, AgentRunStateError } from "../../contracts.js";
|
|
7
8
|
import { assertGuardrailsAllowed, runGuardrails } from "../../guardrails.js";
|
|
8
9
|
import { identityTelemetryAttributes, ownershipFromIdentity, resolveRunIdentity } from "../../identity.js";
|
|
@@ -16,13 +17,106 @@ import { assertStructuredOutputRequestSupported, resolveRunProviderOptions } fro
|
|
|
16
17
|
import { composeSystemPrompt, mergeSystemPromptConfig } from "../../system-prompts.js";
|
|
17
18
|
import { resolveToolResultFold } from "../../tool-result-fold.js";
|
|
18
19
|
import { createSearchToolsTool, createToolSearchState, resolveToolsDisclosure } from "../../tool-search.js";
|
|
19
|
-
import { createToolRegistry } from "../../tools.js";
|
|
20
|
+
import { createToolRegistry, selectRunTools } from "../../tools.js";
|
|
20
21
|
import { bridgeAbort, createUsageAccumulator, inputToMessages, isDurableLoop, isSteerSoftInterrupt, mergeGuardrails, throwIfAborted, } from "../helpers.js";
|
|
21
|
-
import { cleanupRun, persistDurable, persistSucceeded, suspendDurable } from "./persist.js";
|
|
22
|
+
import { checkpointDurableTurn, cleanupRun, persistDurable, persistSucceeded, suspendDurable } from "./persist.js";
|
|
22
23
|
import { generateWithRetry, recordProviderUsage } from "./provider-round.js";
|
|
23
24
|
import { bindChargeToolRound, bindDispatchToolCall, replayDurableNestedAndPending, runLoopUntilSettled, suspendGatedRound, } from "./tool-round.js";
|
|
24
25
|
const PROMPT_VERSION_MAX_NAME_BYTES = 256;
|
|
25
26
|
const PROMPT_VERSION_HASH_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
27
|
+
/** Cap on the host stop detail that reaches the result, ledger, and timeline (plan 084 Task 2). */
|
|
28
|
+
const TURN_STOP_DETAIL_MAX_BYTES = 256;
|
|
29
|
+
/**
|
|
30
|
+
* `RunOptions.turnPolicy` stopped the run at a turn boundary (plan 084 Task 2). Internal control
|
|
31
|
+
* signal: it unwinds any loop shape and `executeRun` turns it into a clean terminal success with
|
|
32
|
+
* `stopReason: "host_policy"` — never a run error.
|
|
33
|
+
*/
|
|
34
|
+
class AgentRunStopped extends Error {
|
|
35
|
+
constructor() {
|
|
36
|
+
super("Agent run stopped by host turn policy");
|
|
37
|
+
this.name = "AgentRunStopped";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Host turn-policy misuse: a throwing or malformed callback fails the run closed. */
|
|
41
|
+
class TurnPolicyError extends Error {
|
|
42
|
+
code = "ERR_PRISM_TURN_POLICY";
|
|
43
|
+
constructor(message, options) {
|
|
44
|
+
super(message, options);
|
|
45
|
+
this.name = "TurnPolicyError";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** Validate `RunOptions.turnPolicy` once, before any provider turn (plan 084 Task 2). */
|
|
49
|
+
function assertTurnPolicy(policy, resolvedLimits) {
|
|
50
|
+
if (policy === undefined)
|
|
51
|
+
return;
|
|
52
|
+
if (typeof policy !== "object" || policy === null)
|
|
53
|
+
throw new TypeError("RunOptions.turnPolicy must be an object");
|
|
54
|
+
if (policy.stop !== undefined && typeof policy.stop !== "function") {
|
|
55
|
+
throw new TypeError("RunOptions.turnPolicy.stop must be a function");
|
|
56
|
+
}
|
|
57
|
+
const maxTurns = policy.maxTurns;
|
|
58
|
+
if (maxTurns === undefined)
|
|
59
|
+
return;
|
|
60
|
+
if (!Number.isSafeInteger(maxTurns) || maxTurns < 1) {
|
|
61
|
+
throw new TypeError("RunOptions.turnPolicy.maxTurns must be a positive safe integer");
|
|
62
|
+
}
|
|
63
|
+
// Same narrowing law as `limits`: a run overlay may tighten the agent's cap, never widen it.
|
|
64
|
+
const configured = resolvedLimits.maxTurns;
|
|
65
|
+
if (configured !== null && maxTurns > configured) {
|
|
66
|
+
throw new TypeError(`RunOptions.turnPolicy.maxTurns (${maxTurns}) cannot widen limits.maxTurns (${configured})`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** Redact and bound a host stop reason; anything unusable fails the run closed. */
|
|
70
|
+
function boundedStopDetail(session, reason) {
|
|
71
|
+
if (typeof reason !== "string" || reason.length === 0) {
|
|
72
|
+
throw new TurnPolicyError("RunOptions.turnPolicy.stop must return a non-empty reason string");
|
|
73
|
+
}
|
|
74
|
+
const redacted = session.redact(reason);
|
|
75
|
+
if (Buffer.byteLength(redacted, "utf8") > TURN_STOP_DETAIL_MAX_BYTES) {
|
|
76
|
+
throw new TurnPolicyError(`RunOptions.turnPolicy.stop reason must be at most ${TURN_STOP_DETAIL_MAX_BYTES} UTF-8 bytes`);
|
|
77
|
+
}
|
|
78
|
+
return redacted;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Evaluate the host turn policy at the current provider-turn boundary (plan 084 Task 2). Returns
|
|
82
|
+
* the stop to record, or `undefined` to run the turn. Omitted policy → nothing is read or called.
|
|
83
|
+
*/
|
|
84
|
+
function evaluateTurnStop(ctx) {
|
|
85
|
+
const policy = ctx.options.turnPolicy;
|
|
86
|
+
if (!policy)
|
|
87
|
+
return undefined;
|
|
88
|
+
const turn = Math.max(1, ctx.session.activeLoopTurn);
|
|
89
|
+
const turns = turn - 1;
|
|
90
|
+
if (policy.maxTurns !== undefined && turns >= policy.maxTurns)
|
|
91
|
+
return { reason: "turn_limit", detail: "maxTurns" };
|
|
92
|
+
if (!policy.stop)
|
|
93
|
+
return undefined;
|
|
94
|
+
const context = {
|
|
95
|
+
sessionId: ctx.session.id,
|
|
96
|
+
runId: ctx.runId,
|
|
97
|
+
turn,
|
|
98
|
+
turns,
|
|
99
|
+
toolCalls: ctx.toolCalls,
|
|
100
|
+
...(ctx.runUsage.value() ? { usage: ctx.runUsage.value() } : {}),
|
|
101
|
+
metadata: ctx.metadata,
|
|
102
|
+
};
|
|
103
|
+
let decision;
|
|
104
|
+
try {
|
|
105
|
+
decision = policy.stop(context);
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
throw new TurnPolicyError("RunOptions.turnPolicy.stop threw", { cause: error });
|
|
109
|
+
}
|
|
110
|
+
if (decision === null || typeof decision !== "object" || typeof decision.then === "function") {
|
|
111
|
+
throw new TurnPolicyError("RunOptions.turnPolicy.stop must synchronously return a TurnStopDecision");
|
|
112
|
+
}
|
|
113
|
+
const action = decision.action;
|
|
114
|
+
if (action === "continue")
|
|
115
|
+
return undefined;
|
|
116
|
+
if (action !== "stop")
|
|
117
|
+
throw new TurnPolicyError('RunOptions.turnPolicy.stop decision action must be "continue" or "stop"');
|
|
118
|
+
return { reason: "host_policy", detail: boundedStopDetail(ctx.session, decision.reason) };
|
|
119
|
+
}
|
|
26
120
|
function assertPromptVersionRef(ref) {
|
|
27
121
|
if (ref === undefined)
|
|
28
122
|
return undefined;
|
|
@@ -61,7 +155,12 @@ async function assembleRoundContext(params) {
|
|
|
61
155
|
};
|
|
62
156
|
await session.activeLedger?.appendRun(redactRunLedgerRecord(startRecord, session.activeRedactor));
|
|
63
157
|
await session.rebuildHistory();
|
|
64
|
-
const {
|
|
158
|
+
const { tools: listed } = activeTools(session.agent.config.tools);
|
|
159
|
+
const selected = selectRunTools(listed, options.toolNames, resumed?.state?.toolNames);
|
|
160
|
+
session.activeToolNames = selected.grant;
|
|
161
|
+
// Run-local snapshot: concurrent runs and MCP refresh must not mutate this registry.
|
|
162
|
+
const activeToolList = selected.tools;
|
|
163
|
+
const baseRegistry = createToolRegistry(activeToolList);
|
|
65
164
|
const toolsDisclosure = resolveToolsDisclosure(options.toolsDisclosure, session.agent.config.toolsDisclosure);
|
|
66
165
|
const toolSearch = toolsDisclosure === "search" && activeToolList.length > 0
|
|
67
166
|
? {
|
|
@@ -115,6 +214,26 @@ async function assembleRoundContext(params) {
|
|
|
115
214
|
const providerOptions = resolveRunProviderOptions(options, session.agent.config);
|
|
116
215
|
assertStructuredOutputRequestSupported(options.model ?? session.agent.config.model, providerOptions);
|
|
117
216
|
const validate = options.validate ?? session.agent.config.validator;
|
|
217
|
+
// Resolved once per run, before any provider turn: a bad setting or a widening run overlay
|
|
218
|
+
// fails here rather than on the turn that happens to cross the ratio (plan 074 C12).
|
|
219
|
+
const attentionCompiler = resolveRunAttentionCompiler(session.agent.config.attentionCompiler, options.attentionCompiler, options.model ?? session.agent.config.model);
|
|
220
|
+
// Telemetry seam (plan 074 T6): one `attention_compiled` per mutated turn, counts and the
|
|
221
|
+
// measured ratio inputs only. Under-ratio turns and compiler-off runs emit nothing.
|
|
222
|
+
const onAttentionReport = attentionCompiler
|
|
223
|
+
? (report) => session.emit({
|
|
224
|
+
type: "attention_compiled",
|
|
225
|
+
sessionId: session.id,
|
|
226
|
+
runId,
|
|
227
|
+
used: report.used,
|
|
228
|
+
usedAfter: report.usedAfter,
|
|
229
|
+
inputCap: report.inputCap,
|
|
230
|
+
triggerRatio: report.triggerRatio,
|
|
231
|
+
droppedThinkingTurns: report.droppedThinkingTurns,
|
|
232
|
+
stubbedToolResults: report.stubbedToolResults,
|
|
233
|
+
stubbedBytes: report.stubbedBytes,
|
|
234
|
+
truncated: report.truncated,
|
|
235
|
+
})
|
|
236
|
+
: undefined;
|
|
118
237
|
const instructionInjectors = options.instructionInjectors ?? session.agent.config.instructionInjectors ?? [];
|
|
119
238
|
const inputLayout = options.inputLayout ?? session.agent.config.inputLayout;
|
|
120
239
|
const loop = resolveLoop(options, session.agent.config);
|
|
@@ -148,6 +267,8 @@ async function assembleRoundContext(params) {
|
|
|
148
267
|
assembledTurn: false,
|
|
149
268
|
artifactFinished: false,
|
|
150
269
|
artifactFailedInfo: undefined,
|
|
270
|
+
toolCalls: 0,
|
|
271
|
+
toolResults: [],
|
|
151
272
|
runUsage,
|
|
152
273
|
loopCtx: undefined,
|
|
153
274
|
};
|
|
@@ -183,6 +304,11 @@ async function assembleRoundContext(params) {
|
|
|
183
304
|
toolsSearch: session.agent.config.toolsSearch,
|
|
184
305
|
activatedTools: session.activatedTools,
|
|
185
306
|
toolResultFold: resolveToolResultFold(options.toolResultFold, session.agent.config.toolResultFold),
|
|
307
|
+
attentionCompiler,
|
|
308
|
+
// Session-owned: a stub made earlier stays applied even on a later under-ratio turn, so
|
|
309
|
+
// the prompt-cache prefix is not rewritten (C10). Undefined when the compiler is off.
|
|
310
|
+
attentionSticky: attentionCompiler ? session.attentionStickyFor() : undefined,
|
|
311
|
+
onAttentionReport,
|
|
186
312
|
loadedSkills: session.loadedSkills,
|
|
187
313
|
tools,
|
|
188
314
|
resourceLoader: session.agent.config.resourceLoader,
|
|
@@ -205,10 +331,24 @@ async function assembleRoundContext(params) {
|
|
|
205
331
|
if (!ctx.assembledTurn)
|
|
206
332
|
limits.charge("maxTurns");
|
|
207
333
|
ctx.assembledTurn = false;
|
|
334
|
+
// Host turn policy (plan 084 Task 2): evaluated at the same turn boundary as the
|
|
335
|
+
// crash-recovery checkpoint below, before any provider work. Throwing unwinds any loop
|
|
336
|
+
// shape; `executeRun` converts it into a clean terminal success with `stopReason`.
|
|
337
|
+
const stop = evaluateTurnStop(ctx);
|
|
338
|
+
if (stop) {
|
|
339
|
+
ctx.runStop = stop;
|
|
340
|
+
ctx.loopCtx.finishReason = stop.reason;
|
|
341
|
+
throw new AgentRunStopped();
|
|
342
|
+
}
|
|
343
|
+
// Crash-recovery boundary (plan 084 Task 1): after the previous turn's tool results are in
|
|
344
|
+
// the store and before this provider request. No-op unless `checkpointPolicy: "every-turn"`.
|
|
345
|
+
if (session.activeDurable?.options.checkpointPolicy === "every-turn") {
|
|
346
|
+
await checkpointDurableTurn(session, { runId, model, limits });
|
|
347
|
+
}
|
|
208
348
|
const policyResult = await session.applyProviderRequestPolicies(request, runId, options, metadata, controller.signal);
|
|
209
349
|
const middlewareRequest = (await session.agent.config.middleware?.run("provider_request", policyResult.request)) ?? policyResult.request;
|
|
210
350
|
try {
|
|
211
|
-
return await generateWithRetry(session, session.redactProviderRequest(middlewareRequest), runId, options, controller.signal, policyResult.secrets, session.activeLoopTurn, (turnUsage, turn, attempt) => recordProviderUsage(ctx, turnUsage, turn, attempt));
|
|
351
|
+
return await generateWithRetry(session, session.redactProviderRequest(middlewareRequest), runId, options, controller.signal, policyResult.secrets, session.activeLoopTurn, (turnUsage, turn, attempt) => recordProviderUsage(ctx, turnUsage, turn, attempt), ctx.toolResults);
|
|
212
352
|
}
|
|
213
353
|
catch (error) {
|
|
214
354
|
if (isSteerSoftInterrupt(error)) {
|
|
@@ -257,6 +397,7 @@ export async function executeRun(session, input, options, runId, resumed) {
|
|
|
257
397
|
}
|
|
258
398
|
const requestedLimits = options.limits;
|
|
259
399
|
const resolvedLimits = resolveRunLimits(session.agent.config.limits, requestedLimits);
|
|
400
|
+
assertTurnPolicy(options.turnPolicy, resolvedLimits);
|
|
260
401
|
const durableOptions = options.runState ?? session.agent.config.runState;
|
|
261
402
|
if (session.agent.config.runState && options.runState && session.agent.config.runState !== options.runState) {
|
|
262
403
|
throw new AgentRunStateError("RunOptions cannot replace agent durable run-state configuration");
|
|
@@ -299,6 +440,9 @@ export async function executeRun(session, input, options, runId, resumed) {
|
|
|
299
440
|
const startedAt = new Date().toISOString();
|
|
300
441
|
let runError;
|
|
301
442
|
let runStatus = "succeeded";
|
|
443
|
+
// Set only on the clean-success path; the finish ledger record carries them (plan 084 Task 2).
|
|
444
|
+
let stopReason;
|
|
445
|
+
let stopDetail;
|
|
302
446
|
const runUsage = createUsageAccumulator();
|
|
303
447
|
let usage;
|
|
304
448
|
const metadata = {
|
|
@@ -343,8 +487,16 @@ export async function executeRun(session, input, options, runId, resumed) {
|
|
|
343
487
|
}
|
|
344
488
|
ctx.loop.restore?.(resumedLoopState.snapshot);
|
|
345
489
|
}
|
|
346
|
-
const loopUsage = await runLoopUntilSettled(ctx)
|
|
347
|
-
|
|
490
|
+
const loopUsage = await runLoopUntilSettled(ctx).catch((error) => {
|
|
491
|
+
// Host turn-policy stop (plan 084 Task 2): the loop was unwound on purpose at a turn
|
|
492
|
+
// boundary. Not an error — the run settles cleanly and stays resumable.
|
|
493
|
+
if (error instanceof AgentRunStopped)
|
|
494
|
+
return undefined;
|
|
495
|
+
throw error;
|
|
496
|
+
});
|
|
497
|
+
stopReason = ctx.runStop?.reason ?? ctx.loopCtx.finishReason;
|
|
498
|
+
stopDetail = ctx.runStop?.detail;
|
|
499
|
+
if (!ctx.runStop && ctx.loop.name === "generate-validate-revise" && !ctx.artifactFinished) {
|
|
348
500
|
throw Object.assign(new Error(ctx.artifactFailedInfo?.message ?? "artifact loop ended without a validated artifact"), {
|
|
349
501
|
name: "ArtifactFailed",
|
|
350
502
|
code: ctx.artifactFailedInfo?.code ?? "artifact_failed",
|
|
@@ -387,7 +539,7 @@ export async function executeRun(session, input, options, runId, resumed) {
|
|
|
387
539
|
throw new AgentRunError(result, { cause: error });
|
|
388
540
|
}
|
|
389
541
|
finally {
|
|
390
|
-
await cleanupRun({ session, controller, cleanupSignal, runId, model, startedAt, runStatus, runError });
|
|
542
|
+
await cleanupRun({ session, controller, cleanupSignal, runId, model, startedAt, runStatus, runError, stopReason, stopDetail });
|
|
391
543
|
}
|
|
392
544
|
}
|
|
393
545
|
//# sourceMappingURL=assemble.js.map
|
|
@@ -15,6 +15,19 @@ export declare function suspendDurable(session: SessionHost, input: {
|
|
|
15
15
|
/** Full replacement when provided; otherwise the recorded nested runs are preserved. */
|
|
16
16
|
readonly nestedRuns?: readonly NestedRunRef[];
|
|
17
17
|
}): Promise<AgentRunState>;
|
|
18
|
+
/**
|
|
19
|
+
* Turn-boundary crash-recovery checkpoint (plan 084 Task 1). Called before each provider
|
|
20
|
+
* request when `checkpointPolicy: "every-turn"`; a no-op otherwise, so default-policy runs keep
|
|
21
|
+
* the 0.8.x checkpoint shape and write count unchanged. Pending-decision markers are dropped:
|
|
22
|
+
* at a turn boundary every gated call has been resolved or the run already suspended, and a
|
|
23
|
+
* stale marker must never replay. The recorded `checkpointPolicy` makes the cadence survive
|
|
24
|
+
* into a resumed run, and loop-local state rides along exactly as it does at suspension.
|
|
25
|
+
*/
|
|
26
|
+
export declare function checkpointDurableTurn(session: SessionHost, input: {
|
|
27
|
+
readonly runId: string;
|
|
28
|
+
readonly model: ModelConfig;
|
|
29
|
+
readonly limits: RunLimitTracker;
|
|
30
|
+
}): Promise<void>;
|
|
18
31
|
export declare function persistSucceeded(ctx: RoundContext, loopUsage: Usage | undefined): Promise<AgentRunResult>;
|
|
19
32
|
export declare function cleanupRun(input: {
|
|
20
33
|
session: SessionHost;
|
|
@@ -25,4 +38,7 @@ export declare function cleanupRun(input: {
|
|
|
25
38
|
startedAt: string;
|
|
26
39
|
runStatus: AgentRunResult["status"];
|
|
27
40
|
runError: ErrorInfo | undefined;
|
|
41
|
+
/** Clean stop taxonomy for the finish record; only written for a succeeded run (plan 084 Task 2). */
|
|
42
|
+
stopReason?: import("../../contracts.js").AgentFinishReason;
|
|
43
|
+
stopDetail?: string;
|
|
28
44
|
}): Promise<void>;
|
|
@@ -9,11 +9,14 @@ export async function persistDurable(session, state) {
|
|
|
9
9
|
const durable = session.activeDurable;
|
|
10
10
|
if (!durable)
|
|
11
11
|
throw new AgentRunStateError("Durable run state is not configured");
|
|
12
|
+
const withGrant = session.activeToolNames !== undefined ? { ...state, toolNames: session.activeToolNames } : state;
|
|
13
|
+
const attentionSticky = session.serializedAttentionSticky();
|
|
12
14
|
const persisted = durable.options.persistSessionState
|
|
13
15
|
? {
|
|
14
|
-
...
|
|
16
|
+
...withGrant,
|
|
15
17
|
sessionState: {
|
|
16
18
|
loadedSkillNames: session.loadedSkills.list(),
|
|
19
|
+
...(attentionSticky ? { attentionSticky } : {}),
|
|
17
20
|
...(session.activatedTools.list().length ? { activatedToolNames: session.activatedTools.list() } : {}),
|
|
18
21
|
...(durable.options.includeSkillBodies
|
|
19
22
|
? {
|
|
@@ -24,7 +27,7 @@ export async function persistDurable(session, state) {
|
|
|
24
27
|
: {}),
|
|
25
28
|
},
|
|
26
29
|
}
|
|
27
|
-
:
|
|
30
|
+
: withGrant;
|
|
28
31
|
const saved = await saveAgentRunState({
|
|
29
32
|
checkpoints: durable.options.checkpoints,
|
|
30
33
|
state: persisted,
|
|
@@ -74,8 +77,50 @@ export async function suspendDurable(session, input) {
|
|
|
74
77
|
counters: input.limits.snapshot(),
|
|
75
78
|
});
|
|
76
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Turn-boundary crash-recovery checkpoint (plan 084 Task 1). Called before each provider
|
|
82
|
+
* request when `checkpointPolicy: "every-turn"`; a no-op otherwise, so default-policy runs keep
|
|
83
|
+
* the 0.8.x checkpoint shape and write count unchanged. Pending-decision markers are dropped:
|
|
84
|
+
* at a turn boundary every gated call has been resolved or the run already suspended, and a
|
|
85
|
+
* stale marker must never replay. The recorded `checkpointPolicy` makes the cadence survive
|
|
86
|
+
* into a resumed run, and loop-local state rides along exactly as it does at suspension.
|
|
87
|
+
*/
|
|
88
|
+
export async function checkpointDurableTurn(session, input) {
|
|
89
|
+
const durable = session.activeDurable;
|
|
90
|
+
if (durable?.options.checkpointPolicy !== "every-turn")
|
|
91
|
+
return;
|
|
92
|
+
const loop = session.activeLoop;
|
|
93
|
+
const loopState = loop?.snapshot ? boundedLoopSnapshot(loop.name, loop.revision ?? "1", loop.snapshot()) : undefined;
|
|
94
|
+
const state = durable.state ??
|
|
95
|
+
initialAgentRunState({
|
|
96
|
+
agent: session.agent,
|
|
97
|
+
options: durable.options,
|
|
98
|
+
runId: input.runId,
|
|
99
|
+
sessionId: session.id,
|
|
100
|
+
leafId: session.currentLeafId,
|
|
101
|
+
model: input.model,
|
|
102
|
+
counters: input.limits.snapshot(),
|
|
103
|
+
deadlineAt: input.limits.deadlineAt,
|
|
104
|
+
status: "running",
|
|
105
|
+
interruptBeforeTool: durable.options.interruptBeforeTool,
|
|
106
|
+
});
|
|
107
|
+
await persistDurable(session, {
|
|
108
|
+
...state,
|
|
109
|
+
leafId: session.currentLeafId,
|
|
110
|
+
status: "running",
|
|
111
|
+
interruption: undefined,
|
|
112
|
+
// The input messages are already in the session store by the time a turn boundary is
|
|
113
|
+
// reached; keeping them would re-append them on a later resume.
|
|
114
|
+
input: undefined,
|
|
115
|
+
pending: undefined,
|
|
116
|
+
pendingCalls: undefined,
|
|
117
|
+
...(loopState ? { loopState } : {}),
|
|
118
|
+
counters: input.limits.snapshot(),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
77
121
|
export async function persistSucceeded(ctx, loopUsage) {
|
|
78
122
|
const { session, runId, runUsage } = ctx;
|
|
123
|
+
const stop = ctx.runStop;
|
|
79
124
|
const usage = runUsage.value() ?? loopUsage;
|
|
80
125
|
if (usage && session.activeLedger) {
|
|
81
126
|
const usageRecord = {
|
|
@@ -94,12 +139,15 @@ export async function persistSucceeded(ctx, loopUsage) {
|
|
|
94
139
|
? await persistDurable(session, {
|
|
95
140
|
...session.activeDurable.state,
|
|
96
141
|
status: "succeeded",
|
|
142
|
+
// Plan 084 Task 2: a host-policy stop is terminal for the run but leaves the frontier
|
|
143
|
+
// intact — the loop state is kept and the state is marked continuable.
|
|
144
|
+
...(stop ? { stopReason: "host_policy", leafId: session.currentLeafId } : {}),
|
|
97
145
|
pending: undefined,
|
|
98
146
|
pendingCalls: undefined,
|
|
99
147
|
nestedRuns: undefined,
|
|
100
148
|
stickyDecisions: undefined,
|
|
101
149
|
interruption: undefined,
|
|
102
|
-
loopState: undefined,
|
|
150
|
+
...(stop ? {} : { loopState: undefined }),
|
|
103
151
|
})
|
|
104
152
|
: undefined;
|
|
105
153
|
session.emit({
|
|
@@ -108,8 +156,17 @@ export async function persistSucceeded(ctx, loopUsage) {
|
|
|
108
156
|
runId,
|
|
109
157
|
usage,
|
|
110
158
|
...(ctx.loopCtx.finishReason ? { finishReason: ctx.loopCtx.finishReason } : {}),
|
|
159
|
+
...(stop?.detail ? { stopDetail: stop.detail } : {}),
|
|
160
|
+
});
|
|
161
|
+
const stopReason = ctx.runStop?.reason ?? ctx.loopCtx.finishReason;
|
|
162
|
+
return session.buildRunResult({
|
|
163
|
+
runId,
|
|
164
|
+
status: "succeeded",
|
|
165
|
+
usage,
|
|
166
|
+
runState,
|
|
167
|
+
...(stopReason ? { stopReason } : {}),
|
|
168
|
+
...(stop?.detail ? { stopDetail: stop.detail } : {}),
|
|
111
169
|
});
|
|
112
|
-
return session.buildRunResult({ runId, status: "succeeded", usage, runState });
|
|
113
170
|
}
|
|
114
171
|
export async function cleanupRun(input) {
|
|
115
172
|
const { session, controller, cleanupSignal, runId, model, startedAt, runStatus, runError } = input;
|
|
@@ -135,6 +192,8 @@ export async function cleanupRun(input) {
|
|
|
135
192
|
status: runStatus,
|
|
136
193
|
startedAt,
|
|
137
194
|
finishedAt: new Date().toISOString(),
|
|
195
|
+
...(input.runStatus === "succeeded" && input.stopReason ? { stopReason: input.stopReason } : {}),
|
|
196
|
+
...(input.runStatus === "succeeded" && input.stopDetail ? { stopDetail: input.stopDetail } : {}),
|
|
138
197
|
abortReason: controller.signal.aborted ? String(controller.signal.reason) : undefined,
|
|
139
198
|
error: runError,
|
|
140
199
|
...(session.activePromptVersion ? { promptVersion: session.activePromptVersion } : {}),
|
|
@@ -155,6 +214,7 @@ export async function cleanupRun(input) {
|
|
|
155
214
|
session.activeMetadata = undefined;
|
|
156
215
|
session.activePromptVersion = undefined;
|
|
157
216
|
session.activeLimits?.dispose();
|
|
217
|
+
session.activeToolNames = undefined;
|
|
158
218
|
session.activeLimits = undefined;
|
|
159
219
|
session.activeLimitOutputBuffer = false;
|
|
160
220
|
session.activeRedactor = undefined;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Provider-round phase of runInternal (plan 059). */
|
|
2
|
-
import type { ProviderRequest, ProviderTurnResult, RunOptions, Usage } from "../../contracts.js";
|
|
2
|
+
import type { ProviderRequest, ProviderTurnResult, RunOptions, ToolResult, Usage } from "../../contracts.js";
|
|
3
3
|
import type { RoundContext, SessionHost } from "./types.js";
|
|
4
4
|
export declare function recordProviderUsage(ctx: RoundContext, turnUsage: Usage | undefined, turn: number, attempt: number): Promise<void>;
|
|
5
|
-
export declare function generateWithRetry(session: SessionHost, request: ProviderRequest, runId: string, options: RunOptions, signal: AbortSignal, requestSecrets?: readonly (string | undefined)[], turn?: number, recordUsage?: (usage: Usage | undefined, turn: number, attempt: number) => Promise<void
|
|
6
|
-
export declare function generateProviderTurn(session: SessionHost, request: ProviderRequest, runId: string, signal: AbortSignal, secrets?: readonly (string | undefined)[], turn?: number, attempt?: number, recordUsage?: (usage: Usage | undefined, turn: number, attempt: number) => Promise<void
|
|
5
|
+
export declare function generateWithRetry(session: SessionHost, request: ProviderRequest, runId: string, options: RunOptions, signal: AbortSignal, requestSecrets?: readonly (string | undefined)[], turn?: number, recordUsage?: (usage: Usage | undefined, turn: number, attempt: number) => Promise<void>, toolResults?: readonly ToolResult[]): Promise<ProviderTurnResult>;
|
|
6
|
+
export declare function generateProviderTurn(session: SessionHost, request: ProviderRequest, runId: string, signal: AbortSignal, secrets?: readonly (string | undefined)[], turn?: number, attempt?: number, recordUsage?: (usage: Usage | undefined, turn: number, attempt: number) => Promise<void>, toolResults?: readonly ToolResult[]): Promise<ProviderTurnResult>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Provider-round phase of runInternal (plan 059). */
|
|
2
2
|
import { assertGuardrailsAllowed, GuardrailError, runGuardrails } from "../../guardrails.js";
|
|
3
3
|
import { createProviderTurnMetadata, readProviderHttpStatus } from "../../observability.js";
|
|
4
|
-
import { providerToolCallDeltaContent } from "../../provider-events.js";
|
|
4
|
+
import { providerError, providerToolCallDeltaContent } from "../../provider-events.js";
|
|
5
5
|
import { errorToErrorInfo, redactRunLedgerRecord, redactSecrets } from "../../redaction.js";
|
|
6
6
|
import { createDefaultRetryPolicy, waitForRetry } from "../../retry.js";
|
|
7
7
|
import { bridgeAbort, errorFromInfo, isSteerSoftInterrupt, jsonBytes, mergeRetry, ProviderTurnFailure, providerContent, randomId, reconstructMissingToolCalls, SteerSoftInterrupt, throwIfAborted, } from "../helpers.js";
|
|
@@ -70,13 +70,13 @@ export async function recordProviderUsage(ctx, turnUsage, turn, attempt) {
|
|
|
70
70
|
};
|
|
71
71
|
await session.activeLedger.appendUsage(redactRunLedgerRecord(usageRecord, session.activeRedactor));
|
|
72
72
|
}
|
|
73
|
-
export async function generateWithRetry(session, request, runId, options, signal, requestSecrets = [], turn = 1, recordUsage) {
|
|
73
|
+
export async function generateWithRetry(session, request, runId, options, signal, requestSecrets = [], turn = 1, recordUsage, toolResults = []) {
|
|
74
74
|
const retry = mergeRetry(session.agent.config.retry, options.retry);
|
|
75
75
|
const secrets = [...requestSecrets, ...(retry?.secrets ?? [])];
|
|
76
76
|
const policy = retry?.policy ?? (retry ? createDefaultRetryPolicy(retry) : undefined);
|
|
77
77
|
for (let attempt = 1;; attempt += 1) {
|
|
78
78
|
try {
|
|
79
|
-
return await generateProviderTurn(session, request, runId, signal, secrets, turn, attempt, recordUsage);
|
|
79
|
+
return await generateProviderTurn(session, request, runId, signal, secrets, turn, attempt, recordUsage, toolResults);
|
|
80
80
|
}
|
|
81
81
|
catch (error) {
|
|
82
82
|
if (error instanceof GuardrailError || isSteerSoftInterrupt(error))
|
|
@@ -100,7 +100,7 @@ export async function generateWithRetry(session, request, runId, options, signal
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
-
export async function generateProviderTurn(session, request, runId, signal, secrets = [], turn = 1, attempt = 1, recordUsage) {
|
|
103
|
+
export async function generateProviderTurn(session, request, runId, signal, secrets = [], turn = 1, attempt = 1, recordUsage, toolResults = []) {
|
|
104
104
|
session.activeLimits.charge("maxProviderAttempts");
|
|
105
105
|
session.activeLimits.charge("maxRequestBytes", jsonBytes(request));
|
|
106
106
|
const startedAt = performance.now();
|
|
@@ -189,7 +189,13 @@ export async function generateProviderTurn(session, request, runId, signal, secr
|
|
|
189
189
|
stage: "output",
|
|
190
190
|
guardrails: session.activeGuardrails,
|
|
191
191
|
value: { content, calls, messageId, started, usage },
|
|
192
|
-
context: {
|
|
192
|
+
context: {
|
|
193
|
+
sessionId: session.id,
|
|
194
|
+
runId,
|
|
195
|
+
metadata: session.activeMetadata ?? {},
|
|
196
|
+
signal: turnAbort.signal,
|
|
197
|
+
toolResults,
|
|
198
|
+
},
|
|
193
199
|
redactor: session.activeRedactor,
|
|
194
200
|
emit: (event) => session.emit(event),
|
|
195
201
|
}));
|
|
@@ -223,7 +229,7 @@ export async function generateProviderTurn(session, request, runId, signal, secr
|
|
|
223
229
|
throw new SteerSoftInterrupt();
|
|
224
230
|
}
|
|
225
231
|
const latencyMs = Math.round(performance.now() - startedAt);
|
|
226
|
-
const info = error instanceof ProviderTurnFailure ? redactSecrets(error.info, secrets) :
|
|
232
|
+
const info = error instanceof ProviderTurnFailure ? redactSecrets(error.info, secrets) : providerError(error, secrets).error;
|
|
227
233
|
await recordTurnUsage();
|
|
228
234
|
session.emit({
|
|
229
235
|
type: "provider_turn_finished",
|
|
@@ -251,8 +251,9 @@ export function bindDispatchToolCall(ctx) {
|
|
|
251
251
|
if (ctx.session.activeGatedRound?.has(call.id)) {
|
|
252
252
|
return { toolCallId: call.id, name: call.name, metadata: { approvalPending: true } };
|
|
253
253
|
}
|
|
254
|
+
ctx.toolCalls += 1;
|
|
254
255
|
try {
|
|
255
|
-
|
|
256
|
+
const result = await dispatchToolCall({
|
|
256
257
|
call,
|
|
257
258
|
registry: ctx.registry,
|
|
258
259
|
context: {
|
|
@@ -278,6 +279,7 @@ export function bindDispatchToolCall(ctx) {
|
|
|
278
279
|
ownership: ctx.session.activeOwnership,
|
|
279
280
|
identity: ctx.session.activeIdentity,
|
|
280
281
|
guardrails: ctx.session.activeGuardrails,
|
|
282
|
+
...(ctx.tools.length > 0 ? { filter: { allow: ctx.tools.map((tool) => tool.name) } } : {}),
|
|
281
283
|
limitTracker: ctx.limits,
|
|
282
284
|
beforeExecute: async (mediatedCall) => {
|
|
283
285
|
const durable = ctx.session.activeDurable;
|
|
@@ -328,6 +330,8 @@ export function bindDispatchToolCall(ctx) {
|
|
|
328
330
|
},
|
|
329
331
|
validate: ctx.validate,
|
|
330
332
|
});
|
|
333
|
+
ctx.toolResults.push(result);
|
|
334
|
+
return result;
|
|
331
335
|
}
|
|
332
336
|
catch (error) {
|
|
333
337
|
if (error instanceof AgentDelegationSuspendedError && !error.toolCall)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/** Shared host/round types for runInternal phase split (plan 059). Internal only. */
|
|
2
2
|
import type { ActiveDurableRun } from "../../agent-approval.js";
|
|
3
3
|
import type { PendingToolCall } from "../../agent-run-state.js";
|
|
4
|
-
import type {
|
|
4
|
+
import type { AttentionStickyFrontier, PersistedAttentionStickyFrontier } from "../../attention-compiler.js";
|
|
5
|
+
import type { Agent, AgentEvent, AgentFinishReason, AgentLoopStrategy, AgentRunResult, AIProvider, ErrorInfo, Guardrails, LoopContext, Message, ModelConfig, OwnershipScope, PendingDecision, PromptVersionRef, ProviderRequest, RunLedger, RunOptions, SessionEntry, SessionStore, Skill, ToolDefinition, ToolEffectStore, ToolRegistry, ToolResult, Usage } from "../../contracts.js";
|
|
5
6
|
import type { AgentIdentity } from "../../identity.js";
|
|
6
7
|
import type { AgentInput } from "../../input.js";
|
|
7
8
|
import type { SecretRedactor } from "../../redaction.js";
|
|
@@ -47,6 +48,15 @@ export type SessionHost = {
|
|
|
47
48
|
readonly activatedTools: ActiveToolSet;
|
|
48
49
|
restoredSkillBodies: readonly LoadedSkillBodiesEntry[];
|
|
49
50
|
activeRunSkills: readonly Skill[];
|
|
51
|
+
/** Names-only grant for this run; undefined means the full registered set. */
|
|
52
|
+
activeToolNames?: readonly string[];
|
|
53
|
+
/** Sticky mutation frontier for this session (plan 074 C10); session-owned so it survives
|
|
54
|
+
* across turns, runs, and provider rounds. Lazily created on first use. */
|
|
55
|
+
attentionStickyFor(): AttentionStickyFrontier;
|
|
56
|
+
/** Plan 074 P3: bounded frontier snapshot for durable checkpoints (undefined before any mutation). */
|
|
57
|
+
serializedAttentionSticky(): PersistedAttentionStickyFrontier | undefined;
|
|
58
|
+
/** Plan 074 P3: restore a frontier that was validated when the checkpoint was loaded. */
|
|
59
|
+
restoreAttentionSticky(persisted: PersistedAttentionStickyFrontier): void;
|
|
50
60
|
invalidateSnapshot(): void;
|
|
51
61
|
resolveRunProvider(options: RunOptions): void;
|
|
52
62
|
emit(event: AgentEvent): void;
|
|
@@ -77,6 +87,11 @@ export type SessionHost = {
|
|
|
77
87
|
snapshot(): Promise<SessionContextSnapshot>;
|
|
78
88
|
};
|
|
79
89
|
export declare function asSessionHost(session: unknown): SessionHost;
|
|
90
|
+
/** Why a run's loop ended, plus the host's stop detail when `RunOptions.turnPolicy` stopped it. */
|
|
91
|
+
export type RunStopInfo = {
|
|
92
|
+
readonly reason: AgentFinishReason;
|
|
93
|
+
readonly detail?: string;
|
|
94
|
+
};
|
|
80
95
|
export type RoundContext = {
|
|
81
96
|
session: SessionHost;
|
|
82
97
|
input: AgentInput;
|
|
@@ -107,6 +122,12 @@ export type RoundContext = {
|
|
|
107
122
|
message: string;
|
|
108
123
|
code?: string | number;
|
|
109
124
|
} | undefined;
|
|
125
|
+
/** Host tool calls dispatched in this run; the turn-boundary context's `toolCalls` (plan 084 Task 2). */
|
|
126
|
+
toolCalls: number;
|
|
127
|
+
/** Completed host tool results from this run, for output evidence guardrails (plan 084 Task 5). */
|
|
128
|
+
toolResults: ToolResult[];
|
|
129
|
+
/** Set when a `RunOptions.turnPolicy` stop ended the loop (plan 084 Task 2). */
|
|
130
|
+
runStop?: RunStopInfo;
|
|
110
131
|
runUsage: {
|
|
111
132
|
add(usage: Usage): void;
|
|
112
133
|
value(): Usage | undefined;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** session (0.2.5 plan 025 Task 1 split). Moved verbatim from agent-session.ts; public surface unchanged behind the barrel. */
|
|
2
2
|
import { ActiveDurableRun } from "../agent-approval.js";
|
|
3
3
|
import type { PendingToolCall, StoredAgentRunState } from "../agent-run-state.js";
|
|
4
|
+
import { type AttentionStickyFrontier, type PersistedAttentionStickyFrontier } from "../attention-compiler.js";
|
|
4
5
|
import type { Agent, AgentEvent, AgentRunResult, AgentRunState, AgentRunStateOptions, AgentSession, AgentSessionConfig, AIProvider, CompactionOptions, CompactionResult, ErrorInfo, Message, OwnershipScope, PendingDecision, PromptVersionRef, ProviderRequest, RunDecision, RunOptions, SessionEntry, Skill, SteerOptions, SubscribeOptions, ToolDefinition, ToolEffectStore, Usage } from "../contracts.js";
|
|
5
6
|
import type { AgentIdentity } from "../identity.js";
|
|
6
7
|
import type { AgentInput } from "../input.js";
|
|
@@ -48,6 +49,19 @@ export declare class RuntimeAgentSession implements AgentSession {
|
|
|
48
49
|
restoredSkillBodies: readonly LoadedSkillBodiesEntry[];
|
|
49
50
|
/** Skills of the current run (for the bodies snapshot); replaced at each run start. */
|
|
50
51
|
activeRunSkills: readonly import("../contracts.js").Skill[];
|
|
52
|
+
/** Per-run tool allow-list (Task 21); undefined means the full registered set. */
|
|
53
|
+
activeToolNames?: readonly string[];
|
|
54
|
+
/** Sticky frontier for this session (plan 074 C10); created on first use, so a session whose
|
|
55
|
+
* agents never enable the compiler allocates nothing. Mutations stay applied once made, so a
|
|
56
|
+
* later under-ratio turn re-applies them instead of rewriting the prompt-cache prefix. */
|
|
57
|
+
private attentionSticky?;
|
|
58
|
+
attentionStickyFor(): AttentionStickyFrontier;
|
|
59
|
+
/** Plan 074 P3: bounded snapshot for a durable checkpoint; `undefined` when the session never
|
|
60
|
+
* mutated anything, so a compiler-off (or never-over-ratio) session persists nothing extra. */
|
|
61
|
+
serializedAttentionSticky(): PersistedAttentionStickyFrontier | undefined;
|
|
62
|
+
/** Plan 074 P3: restore a frontier validated at checkpoint load, so a resumed run keeps its
|
|
63
|
+
* stubs instead of re-deciding its first turn from the ratio. */
|
|
64
|
+
restoreAttentionSticky(persisted: PersistedAttentionStickyFrontier): void;
|
|
51
65
|
/** Plan 015 Task 4: re-add persisted loaded-skill names (names only; bodies re-resolve on demand). */
|
|
52
66
|
restoreLoadedSkills(names: readonly string[]): void;
|
|
53
67
|
/** Plan 041: re-add persisted activated-tool names (names only; inert for absent tools). */
|
|
@@ -81,6 +95,8 @@ export declare class RuntimeAgentSession implements AgentSession {
|
|
|
81
95
|
readonly limit?: import("../contracts.js").RunLimitBreach;
|
|
82
96
|
readonly error?: ErrorInfo;
|
|
83
97
|
readonly abortReason?: string;
|
|
98
|
+
readonly stopReason?: import("../contracts.js").AgentFinishReason;
|
|
99
|
+
readonly stopDetail?: string;
|
|
84
100
|
readonly runState?: AgentRunState;
|
|
85
101
|
readonly interruption?: import("../contracts.js").AgentRunInterruption;
|
|
86
102
|
}): AgentRunResult;
|