@deepstrike/sdk 0.2.61 → 0.2.63
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/LICENSE +106 -0
- package/dist/index.d.ts +10 -4
- package/dist/index.js +7 -1
- package/dist/kernel.d.ts +4 -0
- package/dist/providers/anthropic.d.ts +5 -1
- package/dist/providers/anthropic.js +15 -0
- package/dist/providers/gemini.d.ts +4 -1
- package/dist/providers/gemini.js +15 -1
- package/dist/providers/ollama.d.ts +4 -1
- package/dist/providers/ollama.js +7 -0
- package/dist/providers/openai-responses.d.ts +4 -1
- package/dist/providers/openai-responses.js +16 -0
- package/dist/providers/openai.d.ts +4 -1
- package/dist/providers/openai.js +13 -0
- package/dist/providers/request-plan.d.ts +40 -0
- package/dist/providers/request-plan.js +61 -0
- package/dist/runtime/canonical-kernel-step.d.ts +2 -2
- package/dist/runtime/canonical-kernel-step.js +180 -232
- package/dist/runtime/execution-evidence.d.ts +116 -0
- package/dist/runtime/execution-evidence.js +51 -0
- package/dist/runtime/kernel-doctor.d.ts +36 -0
- package/dist/runtime/kernel-doctor.js +60 -0
- package/dist/runtime/kernel-step.d.ts +13 -4
- package/dist/runtime/kernel-step.js +22 -2
- package/dist/runtime/runner.d.ts +25 -0
- package/dist/runtime/runner.js +235 -49
- package/dist/runtime/session-log.d.ts +32 -3
- package/dist/runtime/session-log.js +144 -0
- package/dist/runtime/session-repair.d.ts +8 -1
- package/dist/runtime/session-repair.js +10 -0
- package/dist/types.d.ts +32 -0
- package/package.json +3 -2
package/dist/runtime/runner.js
CHANGED
|
@@ -7,15 +7,25 @@ import { peekProviderReplay, seedProviderReplayFromEvents } from "./provider-rep
|
|
|
7
7
|
import { sanitizeReplayText } from "./replay-sanitize.js";
|
|
8
8
|
import { buildLlmCompletedEvent, buildRunTerminalEvent, buildWorkflowNodeCompletedEvent, buildWorkflowNodesSubmittedEvent, } from "./session-repair.js";
|
|
9
9
|
import { KernelPrimitivesDashboard } from "./kernel-primitives-dashboard.js";
|
|
10
|
-
import { capabilityMarker, capabilitySkill, capabilityTool, capabilityCommandMount, capabilityCommandUnmount, entropySampleFromObservation, messageToKernelMessage, skillMetadataToKernel, taskUpdateToKernel, toolResultToKernel, toolSchemaToKernel, } from "./kernel-step.js";
|
|
10
|
+
import { capabilityMarker, capabilitySkill, capabilityTool, capabilityCommandMount, capabilityCommandUnmount, archivePresentationFromObservations, entropySampleFromObservation, messageToKernelMessage, skillMetadataToKernel, taskUpdateToKernel, toolResultToKernel, toolSchemaToKernel, } from "./kernel-step.js";
|
|
11
11
|
import { CanonicalKernelRejectedError, CanonicalRunnerRuntime, canonicalKernelAction, canonicalKernelApply, canonicalKernelMaybeAction, canonicalStartAgent, canonicalStartWorkflow, } from "./canonical-kernel-step.js";
|
|
12
|
+
export function stableSemanticArchiveName(effectId) {
|
|
13
|
+
const stableEffectId = effectId.replace(/[^a-zA-Z0-9._:-]/g, "_");
|
|
14
|
+
return `page-out-${stableEffectId || "unknown"}`;
|
|
15
|
+
}
|
|
16
|
+
function compressionAction(action) {
|
|
17
|
+
return action === "snip_compact" || action === "micro_compact" || action === "context_collapse" || action === "auto_compact"
|
|
18
|
+
? action
|
|
19
|
+
: undefined;
|
|
20
|
+
}
|
|
12
21
|
import { agentRunSpecToKernel, MILESTONE_UNVERIFIED_REASON, milestoneCheckFail, milestoneCheckPass, milestoneCheckResultToKernel, subAgentResultToKernel, workflowBudgetNote, workflowNodeSpecToKernel, workflowNodeOutcomeFromKernel, workflowNodeStatusFromTermination, workflowNodeToManifest, workflowNodeToSpec, workflowSpecToKernel, } from "../types/agent.js";
|
|
13
22
|
import { defaultSubAgentOrchestrator } from "./sub-agent-orchestrator.js";
|
|
14
23
|
import { extractJsonValue, schemaInstruction, schemaRetryInstruction, validateAgainstSchema, } from "./output-schema.js";
|
|
15
24
|
import { resolveReducer } from "./reducers.js";
|
|
16
25
|
import { loopInstruction, classifyInstruction, judgeGoal, dependencyOutputsNote, extractClassifyBranch, extractJudgeWinner, } from "./workflow-control-flow.js";
|
|
17
26
|
import { governancePolicyToKernelEvent, governanceFilterSchema } from "../governance.js";
|
|
18
|
-
import { createProviderRequestPlanForProvider, estimateProviderPromptTokens, measurementForPlan, recordPromptMeasurement, } from "../providers/request-plan.js";
|
|
27
|
+
import { createProviderRequestPlanForProvider, estimateProviderPromptTokens, measurementForPlan, recordPromptMeasurement, resolveProviderRoute, } from "../providers/request-plan.js";
|
|
28
|
+
import { FULL_FOOTPRINT_USAGE_ACCOUNTING_POLICY, providerAttemptToRecord, tryNormalizeProviderUsage, } from "./execution-evidence.js";
|
|
19
29
|
import { kernelObservationToSessionEvent } from "./kernel-event-log.js";
|
|
20
30
|
import { assertNativeProfile } from "./os-profile.js";
|
|
21
31
|
import { PayloadStore } from "./payload-store.js";
|
|
@@ -155,6 +165,16 @@ export class RuntimeRunner {
|
|
|
155
165
|
composedSystemPrompt;
|
|
156
166
|
/** H1.2: present only when `opts.nudges` is non-empty; else null and the append funnel is untouched. */
|
|
157
167
|
nudgeEngine;
|
|
168
|
+
/** P4-S1: the run's resolved provider route, assembled once at construction (P4 §0.2 — the
|
|
169
|
+
* provider is fixed for the run today; every attempt references this same route object). */
|
|
170
|
+
providerRoute;
|
|
171
|
+
/** P4-S2: measurement→settlement policy; default = the exact implicit behavior (numbers unchanged). */
|
|
172
|
+
usageAccountingPolicy;
|
|
173
|
+
/** P4 §1.1: the active invocation's derived identity = its chain's FIRST effect_id. Tracked
|
|
174
|
+
* across kernel-driven provider retries (a provider_error commit arms `providerRetryPending`;
|
|
175
|
+
* the next call_provider adopts the pending invocation instead of opening a new one). */
|
|
176
|
+
activeProviderInvocationId;
|
|
177
|
+
providerRetryPending = false;
|
|
158
178
|
constructor(opts) {
|
|
159
179
|
this.opts = opts;
|
|
160
180
|
const schemaAttempts = opts.workflowSchemaValidationAttempts ?? 2;
|
|
@@ -166,6 +186,8 @@ export class RuntimeRunner {
|
|
|
166
186
|
if (opts.memoryPolicy)
|
|
167
187
|
memoryPolicyToKernel(opts.memoryPolicy);
|
|
168
188
|
this.composedSystemPrompt = composeSystemPrompt(opts.systemPrompt, opts.instructions);
|
|
189
|
+
this.providerRoute = resolveProviderRoute(opts.provider);
|
|
190
|
+
this.usageAccountingPolicy = opts.usageAccountingPolicy ?? FULL_FOOTPRINT_USAGE_ACCOUNTING_POLICY;
|
|
169
191
|
if (opts.enableDiagnosticsDashboard) {
|
|
170
192
|
const originalAppend = opts.sessionLog.append.bind(opts.sessionLog);
|
|
171
193
|
opts.sessionLog.append = async (sessionId, event) => {
|
|
@@ -221,6 +243,18 @@ export class RuntimeRunner {
|
|
|
221
243
|
this.fallbackPayloadStore ??= new PayloadStore();
|
|
222
244
|
return this.fallbackPayloadStore;
|
|
223
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* P4-S1 (G1): land one provider_attempt evidence record per effect execution. Pure host
|
|
248
|
+
* evidence (B7) — appended AFTER the transport fact exists (success/failure/abort), never
|
|
249
|
+
* consulted for kernel input. The accounting policy id pins only when a measurement exists,
|
|
250
|
+
* so (usage, policy_id) deterministically recomputes the settlement that crossed the wire.
|
|
251
|
+
*/
|
|
252
|
+
async appendProviderAttempt(sessionId, attempt) {
|
|
253
|
+
await this.opts.sessionLog.append(sessionId, {
|
|
254
|
+
kind: "provider_attempt",
|
|
255
|
+
...providerAttemptToRecord(attempt, attempt.usage ? this.usageAccountingPolicy.policyId : undefined),
|
|
256
|
+
});
|
|
257
|
+
}
|
|
224
258
|
async persistMemoryToStore(memory, agentId) {
|
|
225
259
|
if (!this.opts.memoryStore)
|
|
226
260
|
throw new Error("memory persistence requires memoryStore");
|
|
@@ -745,6 +779,7 @@ export class RuntimeRunner {
|
|
|
745
779
|
goal: `workflow:${spec.nodes.length} nodes`,
|
|
746
780
|
criteria: [],
|
|
747
781
|
agent_id: this.opts.agentId,
|
|
782
|
+
route: this.providerRoute,
|
|
748
783
|
});
|
|
749
784
|
await this.initializeWorkflowKernel(sessionId, runId, groupBudgetScope);
|
|
750
785
|
}
|
|
@@ -1195,6 +1230,7 @@ export class RuntimeRunner {
|
|
|
1195
1230
|
agent_id: this.opts.agentId,
|
|
1196
1231
|
system_prompt: this.composedSystemPrompt,
|
|
1197
1232
|
...(attachments ? { attachments } : {}),
|
|
1233
|
+
route: this.providerRoute,
|
|
1198
1234
|
});
|
|
1199
1235
|
}
|
|
1200
1236
|
yield* this.execute(req.sessionId, req.goal, req.criteria ?? [], req.extensions, prior.length > 0 ? prior : undefined, midRun, attachments, runId);
|
|
@@ -1224,7 +1260,10 @@ export class RuntimeRunner {
|
|
|
1224
1260
|
yield* this.execute(sessionId, start.goal, start.criteria, extensions, events, true, start.attachments, start.run_id);
|
|
1225
1261
|
}
|
|
1226
1262
|
/** Execute a kernel-owned approval effect and return the correlated decision lists. */
|
|
1227
|
-
async resolveApprovalRequests(requests, runtime, sessionId
|
|
1263
|
+
async resolveApprovalRequests(requests, runtime, sessionId,
|
|
1264
|
+
/** P3-S2 (G4): the request_approval effect's id — pinned on the denial's tool_completed
|
|
1265
|
+
* so the denial evidence joins the journal effect chain like an executed tool's does. */
|
|
1266
|
+
effectId) {
|
|
1228
1267
|
const approved = [];
|
|
1229
1268
|
const denied = [];
|
|
1230
1269
|
const events = [];
|
|
@@ -1297,6 +1336,7 @@ export class RuntimeRunner {
|
|
|
1297
1336
|
error_kind: "governance_denied",
|
|
1298
1337
|
content: { blocks: [{ type: "text", text: `permission denied: ${denyReason}` }] },
|
|
1299
1338
|
}],
|
|
1339
|
+
...(effectId !== undefined ? { effect_id: effectId } : {}),
|
|
1300
1340
|
});
|
|
1301
1341
|
}
|
|
1302
1342
|
}
|
|
@@ -1310,6 +1350,8 @@ export class RuntimeRunner {
|
|
|
1310
1350
|
this.pendingPageOutArchives = [];
|
|
1311
1351
|
this.activePageOutArchive = undefined;
|
|
1312
1352
|
this.currentSessionId = sessionId;
|
|
1353
|
+
this.activeProviderInvocationId = undefined;
|
|
1354
|
+
this.providerRetryPending = false;
|
|
1313
1355
|
if (this.opts.enableDiagnosticsDashboard) {
|
|
1314
1356
|
this.dashboard = new KernelPrimitivesDashboard(sessionId);
|
|
1315
1357
|
}
|
|
@@ -1548,6 +1590,18 @@ export class RuntimeRunner {
|
|
|
1548
1590
|
break;
|
|
1549
1591
|
if (action.kind === "call_provider") {
|
|
1550
1592
|
const providerEffectId = action.effectId;
|
|
1593
|
+
// P4 §1.1: invocation identity is derived, never minted — the chain's FIRST effect_id.
|
|
1594
|
+
// A provider_error commit armed `providerRetryPending`, so this effect CONTINUES the
|
|
1595
|
+
// pending invocation; otherwise it opens a new one. The chain itself lives in the
|
|
1596
|
+
// journal (each hop a Failed resolution input → new effect); this is the SessionLog
|
|
1597
|
+
// evidence projection of it.
|
|
1598
|
+
if (!this.providerRetryPending || this.activeProviderInvocationId === undefined) {
|
|
1599
|
+
this.activeProviderInvocationId = providerEffectId;
|
|
1600
|
+
}
|
|
1601
|
+
this.providerRetryPending = false;
|
|
1602
|
+
const invocationId = this.activeProviderInvocationId;
|
|
1603
|
+
// Host wall-clock, pure evidence (B7/DEC-2): never crosses into kernel input.
|
|
1604
|
+
const attemptStartedAtMs = Date.now();
|
|
1551
1605
|
const finalToolCalls = [];
|
|
1552
1606
|
let finalText = "";
|
|
1553
1607
|
// I5: governance schema-level pre-filter. When a declarative GovernancePolicy is loaded
|
|
@@ -1579,6 +1633,9 @@ export class RuntimeRunner {
|
|
|
1579
1633
|
let turnCacheTelemetrySource;
|
|
1580
1634
|
let turnCacheReadBySlot;
|
|
1581
1635
|
let turnStopReason;
|
|
1636
|
+
// P4 §2: the raw postflight provider usage frame, kept whole so the attempt's
|
|
1637
|
+
// measurement carries full fields (only the settlement crosses the kernel boundary, B4).
|
|
1638
|
+
let turnProviderUsage;
|
|
1582
1639
|
const providerPlan = createProviderRequestPlanForProvider(this.opts.provider, context, tools, ext);
|
|
1583
1640
|
const recorded = measurementForPlan(providerPlan, recordedMeasurements.get(providerPlan.fingerprint));
|
|
1584
1641
|
let promptMeasurement = recorded;
|
|
@@ -1605,6 +1662,7 @@ export class RuntimeRunner {
|
|
|
1605
1662
|
kind: "prompt_measured",
|
|
1606
1663
|
turn: runtime.turn(),
|
|
1607
1664
|
measurement: promptMeasurement,
|
|
1665
|
+
effect_id: providerEffectId,
|
|
1608
1666
|
});
|
|
1609
1667
|
}
|
|
1610
1668
|
const reservedPromptTokens = (this.opts.promptBudget?.promptOverheadTokens ?? 0)
|
|
@@ -1617,6 +1675,23 @@ export class RuntimeRunner {
|
|
|
1617
1675
|
&& promptMeasurement.source.kind !== "heuristic"
|
|
1618
1676
|
&& promptMeasurement.inputTokens + reservedPromptTokens > this.opts.maxTokens;
|
|
1619
1677
|
if (context.budgetOverflow || measuredOverflow) {
|
|
1678
|
+
// P4 §1.2: blocked BEFORE any transport — zero rungs, status rejected. The
|
|
1679
|
+
// fingerprint still binds the would-be request to its prompt_measured record (G2).
|
|
1680
|
+
await this.appendProviderAttempt(sessionId, {
|
|
1681
|
+
effectId: providerEffectId,
|
|
1682
|
+
attemptSeq: 1,
|
|
1683
|
+
route: this.providerRoute,
|
|
1684
|
+
requestFingerprint: providerPlan.fingerprint,
|
|
1685
|
+
status: "rejected",
|
|
1686
|
+
transportRungs: 0,
|
|
1687
|
+
lastErrorClass: "context_overflow",
|
|
1688
|
+
startedAtMs: attemptStartedAtMs,
|
|
1689
|
+
finishedAtMs: Date.now(),
|
|
1690
|
+
wireEvidence: {
|
|
1691
|
+
protocol: this.providerRoute.protocol,
|
|
1692
|
+
request_fingerprint: providerPlan.fingerprint,
|
|
1693
|
+
},
|
|
1694
|
+
});
|
|
1620
1695
|
action = await this.commitKernelAction(runtime, this.pendingObservations, {
|
|
1621
1696
|
kind: "provider_error",
|
|
1622
1697
|
effect_id: providerEffectId,
|
|
@@ -1624,6 +1699,7 @@ export class RuntimeRunner {
|
|
|
1624
1699
|
error_kind: "context_overflow",
|
|
1625
1700
|
retryable: false,
|
|
1626
1701
|
});
|
|
1702
|
+
this.providerRetryPending = action.kind === "call_provider";
|
|
1627
1703
|
continue;
|
|
1628
1704
|
}
|
|
1629
1705
|
const abortSignal = this.abortController?.signal;
|
|
@@ -1639,6 +1715,7 @@ export class RuntimeRunner {
|
|
|
1639
1715
|
turnTokens = usageEvt.totalTokens;
|
|
1640
1716
|
turnInputTokens = usageEvt.inputTokens ?? 0;
|
|
1641
1717
|
turnOutputTokens = usageEvt.outputTokens ?? 0;
|
|
1718
|
+
turnProviderUsage = usageEvt.providerUsage ?? turnProviderUsage;
|
|
1642
1719
|
// P0-C: capture the prompt-cache split for the tool-gating hit-rate baseline.
|
|
1643
1720
|
turnCacheReadTokens = usageEvt.cacheReadInputTokens ?? 0;
|
|
1644
1721
|
turnCacheCreationTokens = usageEvt.cacheCreationInputTokens ?? 0;
|
|
@@ -1670,6 +1747,7 @@ export class RuntimeRunner {
|
|
|
1670
1747
|
source: postflight.source,
|
|
1671
1748
|
confidence: postflight.confidence,
|
|
1672
1749
|
},
|
|
1750
|
+
effect_id: providerEffectId,
|
|
1673
1751
|
});
|
|
1674
1752
|
}
|
|
1675
1753
|
// Phase 4: stop_reason drives the kernel's max-output-tokens recovery. The closing
|
|
@@ -1697,6 +1775,26 @@ export class RuntimeRunner {
|
|
|
1697
1775
|
const provider = this.opts.provider.descriptor?.().provider ?? "unknown";
|
|
1698
1776
|
const providerError = classifyProviderError(provider, err);
|
|
1699
1777
|
const message = providerError.message;
|
|
1778
|
+
// P4 §1.2: the transport ladder is exhausted — one attempt record, rung count from
|
|
1779
|
+
// provider telemetry (1 on the single-shot stream path), error CLASS only (B1:
|
|
1780
|
+
// never the raw vendor text).
|
|
1781
|
+
const telemetry = this.opts.provider.peekTransportTelemetry?.();
|
|
1782
|
+
await this.appendProviderAttempt(sessionId, {
|
|
1783
|
+
effectId: providerEffectId,
|
|
1784
|
+
attemptSeq: 1,
|
|
1785
|
+
route: this.providerRoute,
|
|
1786
|
+
requestFingerprint: providerPlan.fingerprint,
|
|
1787
|
+
status: "transport_exhausted",
|
|
1788
|
+
transportRungs: telemetry?.rungs ?? 1,
|
|
1789
|
+
lastErrorClass: providerError.kind,
|
|
1790
|
+
startedAtMs: attemptStartedAtMs,
|
|
1791
|
+
finishedAtMs: Date.now(),
|
|
1792
|
+
wireEvidence: {
|
|
1793
|
+
protocol: this.providerRoute.protocol,
|
|
1794
|
+
request_fingerprint: providerPlan.fingerprint,
|
|
1795
|
+
...(telemetry?.responseId !== undefined ? { response_id: telemetry.responseId } : {}),
|
|
1796
|
+
},
|
|
1797
|
+
});
|
|
1700
1798
|
// Reactive recovery is now a kernel decision. Forward the raw provider error and
|
|
1701
1799
|
// dispatch whatever the kernel returns: `call_provider` to retry with a freshly
|
|
1702
1800
|
// compacted context, or `done` to terminate with an honest `ContextOverflow`. The
|
|
@@ -1710,6 +1808,9 @@ export class RuntimeRunner {
|
|
|
1710
1808
|
message,
|
|
1711
1809
|
...providerErrorEventFields(providerError),
|
|
1712
1810
|
});
|
|
1811
|
+
// P4 §1.1: a kernel-recovered retry CONTINUES this invocation (the journal holds the
|
|
1812
|
+
// causation hop); a terminal closes it.
|
|
1813
|
+
this.providerRetryPending = action.kind === "call_provider";
|
|
1713
1814
|
// Withholding (query.ts parity): surface the raw provider error only when the kernel
|
|
1714
1815
|
// could NOT recover (it returned a terminal). On a recovered retry (`call_provider`)
|
|
1715
1816
|
// the error stays hidden, so embedders that terminate on `error` events don't see a
|
|
@@ -1722,6 +1823,23 @@ export class RuntimeRunner {
|
|
|
1722
1823
|
}
|
|
1723
1824
|
// Do not commit partial provider output after host cancellation.
|
|
1724
1825
|
if (abortSignal?.aborted) {
|
|
1826
|
+
// P4 §1.2: host cancellation mid-stream — the attempt is evidence too.
|
|
1827
|
+
const telemetry = this.opts.provider.peekTransportTelemetry?.();
|
|
1828
|
+
await this.appendProviderAttempt(sessionId, {
|
|
1829
|
+
effectId: providerEffectId,
|
|
1830
|
+
attemptSeq: 1,
|
|
1831
|
+
route: this.providerRoute,
|
|
1832
|
+
requestFingerprint: providerPlan.fingerprint,
|
|
1833
|
+
status: "aborted",
|
|
1834
|
+
transportRungs: telemetry?.rungs ?? 1,
|
|
1835
|
+
startedAtMs: attemptStartedAtMs,
|
|
1836
|
+
finishedAtMs: Date.now(),
|
|
1837
|
+
wireEvidence: {
|
|
1838
|
+
protocol: this.providerRoute.protocol,
|
|
1839
|
+
request_fingerprint: providerPlan.fingerprint,
|
|
1840
|
+
...(telemetry?.responseId !== undefined ? { response_id: telemetry.responseId } : {}),
|
|
1841
|
+
},
|
|
1842
|
+
});
|
|
1725
1843
|
action = await this.commitKernelAction(runtime, this.pendingObservations, {
|
|
1726
1844
|
kind: "cancel_operation",
|
|
1727
1845
|
reason: this.cancellationReason ?? "user",
|
|
@@ -1753,12 +1871,37 @@ export class RuntimeRunner {
|
|
|
1753
1871
|
toolCalls: canonicalToolCalls,
|
|
1754
1872
|
tokenCount: turnOutputTokens || turnTokens || undefined,
|
|
1755
1873
|
};
|
|
1874
|
+
// P4 §2: assemble the measurement from the exact numbers that cross the boundary today
|
|
1875
|
+
// (inputTokens/outputTokens turn counters), enriched with the raw provider frame's cache
|
|
1876
|
+
// split and reasoning fields. An invalid frame degrades to no measurement (evidence
|
|
1877
|
+
// never breaks a run); the settlement then falls back to the raw counts below.
|
|
1878
|
+
const attemptUsage = (turnInputTokens > 0 || turnOutputTokens > 0)
|
|
1879
|
+
? tryNormalizeProviderUsage({
|
|
1880
|
+
inputTokens: turnInputTokens,
|
|
1881
|
+
outputTokens: turnOutputTokens,
|
|
1882
|
+
...(turnProviderUsage?.cacheReadInputTokens !== undefined
|
|
1883
|
+
? { cacheReadInputTokens: turnProviderUsage.cacheReadInputTokens }
|
|
1884
|
+
: turnCacheReadTokens > 0 ? { cacheReadInputTokens: turnCacheReadTokens } : {}),
|
|
1885
|
+
...(turnProviderUsage?.cacheCreationInputTokens !== undefined
|
|
1886
|
+
? { cacheCreationInputTokens: turnProviderUsage.cacheCreationInputTokens }
|
|
1887
|
+
: turnCacheCreationTokens > 0 ? { cacheCreationInputTokens: turnCacheCreationTokens } : {}),
|
|
1888
|
+
...(turnProviderUsage?.reasoningTokens !== undefined
|
|
1889
|
+
? { reasoningTokens: turnProviderUsage.reasoningTokens } : {}),
|
|
1890
|
+
cacheTelemetryStatus: turnCacheTelemetryStatus,
|
|
1891
|
+
...(turnCacheTelemetrySource !== undefined
|
|
1892
|
+
? { cacheTelemetrySource: turnCacheTelemetrySource } : {}),
|
|
1893
|
+
})
|
|
1894
|
+
: undefined;
|
|
1895
|
+
const settlement = attemptUsage ? this.usageAccountingPolicy.settle(attemptUsage) : undefined;
|
|
1756
1896
|
const providerEvent = {
|
|
1757
1897
|
kind: "provider_result",
|
|
1758
1898
|
effect_id: providerEffectId,
|
|
1759
1899
|
message: messageToKernelMessage(assistantMessage),
|
|
1760
|
-
|
|
1761
|
-
|
|
1900
|
+
// P4-S2: observed_* now comes from the pinned policy's settlement of the measurement.
|
|
1901
|
+
// Under the default full-footprint policy these are provably the numbers the runner
|
|
1902
|
+
// has always fed (inputTokens/outputTokens verbatim under the same >0 gates).
|
|
1903
|
+
...(turnInputTokens > 0 ? { observed_input_tokens: settlement?.observed_input_tokens ?? turnInputTokens } : {}),
|
|
1904
|
+
...(turnOutputTokens > 0 ? { observed_output_tokens: settlement?.observed_output_tokens ?? turnOutputTokens } : {}),
|
|
1762
1905
|
...(turnStopReason ? { stop_reason: turnStopReason } : {}),
|
|
1763
1906
|
};
|
|
1764
1907
|
if (this.opts.skillDir) {
|
|
@@ -1789,14 +1932,38 @@ export class RuntimeRunner {
|
|
|
1789
1932
|
}
|
|
1790
1933
|
}
|
|
1791
1934
|
}
|
|
1792
|
-
|
|
1935
|
+
// P4-S1: land the attempt evidence BEFORE the kernel resolution commits — the record
|
|
1936
|
+
// describes the transport fact, which exists regardless of what the kernel decides next.
|
|
1937
|
+
const attemptTelemetry = this.opts.provider.peekTransportTelemetry?.();
|
|
1793
1938
|
const providerReplay = peekProviderReplay(this.opts.provider, finalText, finalToolCalls);
|
|
1939
|
+
const wireEvidence = {
|
|
1940
|
+
protocol: this.providerRoute.protocol,
|
|
1941
|
+
request_fingerprint: providerPlan.fingerprint,
|
|
1942
|
+
...(attemptTelemetry?.responseId !== undefined ? { response_id: attemptTelemetry.responseId } : {}),
|
|
1943
|
+
...(providerReplay !== undefined ? { replay_state: providerReplay } : {}),
|
|
1944
|
+
};
|
|
1945
|
+
await this.appendProviderAttempt(sessionId, {
|
|
1946
|
+
effectId: providerEffectId,
|
|
1947
|
+
attemptSeq: 1,
|
|
1948
|
+
route: this.providerRoute,
|
|
1949
|
+
requestFingerprint: providerPlan.fingerprint,
|
|
1950
|
+
status: "success",
|
|
1951
|
+
transportRungs: attemptTelemetry?.rungs ?? 1,
|
|
1952
|
+
startedAtMs: attemptStartedAtMs,
|
|
1953
|
+
finishedAtMs: Date.now(),
|
|
1954
|
+
...(attemptUsage !== undefined ? { usage: attemptUsage } : {}),
|
|
1955
|
+
wireEvidence,
|
|
1956
|
+
});
|
|
1957
|
+
action = await this.commitKernelAction(runtime, this.pendingObservations, providerEvent);
|
|
1794
1958
|
await this.opts.sessionLog.append(sessionId, buildLlmCompletedEvent({
|
|
1795
1959
|
turn: runtime.turn(),
|
|
1796
1960
|
content: finalText,
|
|
1797
1961
|
tokenCount: turnOutputTokens || turnTokens || undefined,
|
|
1798
1962
|
toolCalls: finalToolCalls,
|
|
1799
1963
|
providerReplay,
|
|
1964
|
+
effectId: providerEffectId,
|
|
1965
|
+
invocationId,
|
|
1966
|
+
wireEvidence,
|
|
1800
1967
|
}));
|
|
1801
1968
|
// P0-C: emit per-turn tool-gating telemetry. `activeSkill` reflects the skill in effect
|
|
1802
1969
|
// GOING INTO this turn; a `skill` call here only takes effect next turn, so emit first, then
|
|
@@ -1831,7 +1998,7 @@ export class RuntimeRunner {
|
|
|
1831
1998
|
}
|
|
1832
1999
|
}
|
|
1833
2000
|
else if (action.kind === "request_approval") {
|
|
1834
|
-
const resolved = await this.resolveApprovalRequests(action.requests, runtime, sessionId);
|
|
2001
|
+
const resolved = await this.resolveApprovalRequests(action.requests, runtime, sessionId, action.effectId);
|
|
1835
2002
|
for (const event of resolved.events)
|
|
1836
2003
|
yield event;
|
|
1837
2004
|
action = await this.commitKernelAction(runtime, this.pendingObservations, {
|
|
@@ -1914,6 +2081,7 @@ export class RuntimeRunner {
|
|
|
1914
2081
|
await this.logMemoryRetrievalResult(sessionId, hits);
|
|
1915
2082
|
}
|
|
1916
2083
|
else if (action.kind === "archive_page_out") {
|
|
2084
|
+
const archiveEffectId = action.effectId;
|
|
1917
2085
|
const archiveMeta = this.activePageOutArchive
|
|
1918
2086
|
?? this.pendingPageOutArchives.shift()
|
|
1919
2087
|
?? {
|
|
@@ -1941,8 +2109,8 @@ export class RuntimeRunner {
|
|
|
1941
2109
|
error = formatToolError(cause);
|
|
1942
2110
|
}
|
|
1943
2111
|
const archived = action.archived ?? [];
|
|
1944
|
-
const archiveAction =
|
|
1945
|
-
const archiveTier =
|
|
2112
|
+
const archiveAction = archiveMeta.action ?? "auto_compact";
|
|
2113
|
+
const archiveTier = archiveMeta.tier;
|
|
1946
2114
|
const compressedSeq = archiveMeta.compressedSeq;
|
|
1947
2115
|
if (!error)
|
|
1948
2116
|
this.activePageOutArchive = undefined;
|
|
@@ -1959,7 +2127,7 @@ export class RuntimeRunner {
|
|
|
1959
2127
|
taskScope.spawn("compressed-summary-upgrade", upgrade);
|
|
1960
2128
|
}
|
|
1961
2129
|
if (archiveTier === "semantic" && archived.length > 0) {
|
|
1962
|
-
taskScope.spawn("semantic-page-out", () => this.archiveSemanticPageOut(archived, archiveAction, sessionId));
|
|
2130
|
+
taskScope.spawn("semantic-page-out", () => this.archiveSemanticPageOut(archived, archiveAction, sessionId, archiveEffectId));
|
|
1963
2131
|
}
|
|
1964
2132
|
}
|
|
1965
2133
|
}
|
|
@@ -2160,6 +2328,7 @@ export class RuntimeRunner {
|
|
|
2160
2328
|
token_count: r.tokenCount,
|
|
2161
2329
|
content: { blocks: toolOutputBlocksToDurable(r.contentParts?.length ? r.contentParts : [{ type: "text", text: r.output }]) },
|
|
2162
2330
|
})),
|
|
2331
|
+
effect_id: toolEffectId,
|
|
2163
2332
|
});
|
|
2164
2333
|
// The canonical provider resolution already activates a successfully resolved `skill` call.
|
|
2165
2334
|
// The host's remaining responsibility is to pin the resolved METHOD content — how to do
|
|
@@ -2516,7 +2685,12 @@ export class RuntimeRunner {
|
|
|
2516
2685
|
const compressedSeq = await this.opts.sessionLog.append(sessionId, event);
|
|
2517
2686
|
if (event.kind === "compressed") {
|
|
2518
2687
|
if ((obs.archived_count ?? 0) > 0) {
|
|
2519
|
-
|
|
2688
|
+
const archivePresentation = archivePresentationFromObservations([obs]);
|
|
2689
|
+
this.pendingPageOutArchives.push({
|
|
2690
|
+
archiveStart: nextArchiveStart,
|
|
2691
|
+
compressedSeq,
|
|
2692
|
+
...archivePresentation,
|
|
2693
|
+
});
|
|
2520
2694
|
}
|
|
2521
2695
|
nextArchiveStart = compressedSeq + 1;
|
|
2522
2696
|
}
|
|
@@ -2529,37 +2703,58 @@ export class RuntimeRunner {
|
|
|
2529
2703
|
}
|
|
2530
2704
|
return nextArchiveStart;
|
|
2531
2705
|
}
|
|
2532
|
-
async archiveSemanticPageOut(archived, action, sessionId) {
|
|
2706
|
+
async archiveSemanticPageOut(archived, action, sessionId, effectId = "unknown") {
|
|
2533
2707
|
if (!this.opts.memoryStore || !this.opts.agentId || !this.opts.memoryScope)
|
|
2534
2708
|
return;
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
:
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2709
|
+
await this.opts.sessionLog.append(sessionId, {
|
|
2710
|
+
kind: "semantic_archive_pending",
|
|
2711
|
+
effect_id: effectId,
|
|
2712
|
+
...(action ? { action } : {}),
|
|
2713
|
+
});
|
|
2714
|
+
try {
|
|
2715
|
+
const summary = this.opts.memorySummarizer
|
|
2716
|
+
? await this.opts.memorySummarizer.summarize(archived, { action })
|
|
2717
|
+
: await summarizeForLongTermMemory(this.opts.memoryProvider ?? this.opts.provider, archived, this.opts.memorySystemPrompt);
|
|
2718
|
+
// P2 write-funnel: route through the ONE gated WriteMemory syscall so validation,
|
|
2719
|
+
// the rolling write quota, dedup, and the memory_written audit all apply. Score is
|
|
2720
|
+
// advisory (0.6) — an automatic summary must never outrank curated content.
|
|
2721
|
+
const now = Date.now();
|
|
2722
|
+
const name = stableSemanticArchiveName(effectId);
|
|
2723
|
+
const recordId = `${this.opts.memoryScope.tenant_id}:${this.opts.memoryScope.namespace}:project:${name}`;
|
|
2724
|
+
await this.writeMemory({
|
|
2725
|
+
record_id: recordId,
|
|
2726
|
+
scope: this.opts.memoryScope,
|
|
2727
|
+
name,
|
|
2728
|
+
kind: "project",
|
|
2729
|
+
content: summary,
|
|
2730
|
+
description: `auto summary of ${action ?? "compaction"} archive`,
|
|
2731
|
+
provenance: {
|
|
2732
|
+
session_id: sessionId,
|
|
2733
|
+
author: "extraction",
|
|
2734
|
+
trust: "untrusted",
|
|
2735
|
+
evidence_refs: [],
|
|
2736
|
+
},
|
|
2737
|
+
created_at: now,
|
|
2738
|
+
updated_at: now,
|
|
2739
|
+
recall_count: 0,
|
|
2740
|
+
confidence: 0.6,
|
|
2741
|
+
links: [],
|
|
2742
|
+
pinned: false,
|
|
2743
|
+
}, { sessionId, agentId: this.opts.agentId });
|
|
2744
|
+
await this.opts.sessionLog.append(sessionId, {
|
|
2745
|
+
kind: "semantic_archive_completed",
|
|
2746
|
+
effect_id: effectId,
|
|
2747
|
+
record_id: recordId,
|
|
2748
|
+
});
|
|
2749
|
+
}
|
|
2750
|
+
catch (error) {
|
|
2751
|
+
await this.opts.sessionLog.append(sessionId, {
|
|
2752
|
+
kind: "semantic_archive_failed",
|
|
2753
|
+
effect_id: effectId,
|
|
2754
|
+
error: formatToolError(error),
|
|
2755
|
+
});
|
|
2756
|
+
throw error;
|
|
2757
|
+
}
|
|
2563
2758
|
}
|
|
2564
2759
|
async upgradeCompressedSummary(sessionId, compressedSeq, archived, action, runtime) {
|
|
2565
2760
|
const summary = await this.opts.asyncSummarizer.summarize(archived, action);
|
|
@@ -2634,15 +2829,6 @@ function attachmentsToKernelMessage(parts) {
|
|
|
2634
2829
|
});
|
|
2635
2830
|
return { role: "user", content };
|
|
2636
2831
|
}
|
|
2637
|
-
function compressionAction(action) {
|
|
2638
|
-
if (action === "snip_compact" ||
|
|
2639
|
-
action === "micro_compact" ||
|
|
2640
|
-
action === "context_collapse" ||
|
|
2641
|
-
action === "auto_compact") {
|
|
2642
|
-
return action;
|
|
2643
|
-
}
|
|
2644
|
-
return undefined;
|
|
2645
|
-
}
|
|
2646
2832
|
async function summarizeForLongTermMemory(provider, archived, systemPrompt) {
|
|
2647
2833
|
const transcript = archived
|
|
2648
2834
|
.map(m => `${m.role}: ${m.content}`)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { KernelPrimitive } from "./kernel-event-log.js";
|
|
2
|
-
import type { ContentPart, ProviderReplay, ToolCall, ToolErrorKind } from "../types.js";
|
|
3
|
-
import type { RecordedPromptMeasurement } from "../providers/request-plan.js";
|
|
2
|
+
import type { ContentPart, ProviderReplay, ProviderWireEvidence, ToolCall, ToolErrorKind } from "../types.js";
|
|
3
|
+
import type { RecordedPromptMeasurement, ResolvedProviderRoute } from "../providers/request-plan.js";
|
|
4
|
+
import type { ProviderAttemptRecord } from "./execution-evidence.js";
|
|
4
5
|
import type { MemoryRecall, MemoryScope } from "../memory/protocols.js";
|
|
5
6
|
import type { KernelJournal } from "./kernel-journal.js";
|
|
6
7
|
export type RollbackReason = {
|
|
@@ -30,6 +31,7 @@ export type SessionEvent = {
|
|
|
30
31
|
agent_id?: string;
|
|
31
32
|
system_prompt?: string;
|
|
32
33
|
attachments?: ContentPart[];
|
|
34
|
+
route?: ResolvedProviderRoute;
|
|
33
35
|
} | {
|
|
34
36
|
kind: "llm_completed";
|
|
35
37
|
turn: number;
|
|
@@ -37,11 +39,17 @@ export type SessionEvent = {
|
|
|
37
39
|
token_count?: number;
|
|
38
40
|
tool_calls: ToolCall[];
|
|
39
41
|
provider_replay?: ProviderReplay;
|
|
42
|
+
effect_id?: string;
|
|
43
|
+
invocation_id?: string;
|
|
44
|
+
wire_evidence?: ProviderWireEvidence;
|
|
40
45
|
} | {
|
|
41
46
|
kind: "prompt_measured";
|
|
42
47
|
turn: number;
|
|
43
48
|
measurement: RecordedPromptMeasurement;
|
|
44
|
-
|
|
49
|
+
effect_id?: string;
|
|
50
|
+
} | ({
|
|
51
|
+
kind: "provider_attempt";
|
|
52
|
+
} & ProviderAttemptRecord) | {
|
|
45
53
|
kind: "tool_requested";
|
|
46
54
|
turn: number;
|
|
47
55
|
calls: ToolCall[];
|
|
@@ -59,6 +67,7 @@ export type SessionEvent = {
|
|
|
59
67
|
blocks: Record<string, unknown>[];
|
|
60
68
|
};
|
|
61
69
|
}>;
|
|
70
|
+
effect_id?: string;
|
|
62
71
|
} | {
|
|
63
72
|
kind: "tool_argument_repaired";
|
|
64
73
|
turn: number;
|
|
@@ -98,6 +107,18 @@ export type SessionEvent = {
|
|
|
98
107
|
tier_hint?: string;
|
|
99
108
|
message_count?: number;
|
|
100
109
|
archive_ref?: string;
|
|
110
|
+
} | {
|
|
111
|
+
kind: "semantic_archive_pending";
|
|
112
|
+
effect_id: string;
|
|
113
|
+
action?: string;
|
|
114
|
+
} | {
|
|
115
|
+
kind: "semantic_archive_completed";
|
|
116
|
+
effect_id: string;
|
|
117
|
+
record_id: string;
|
|
118
|
+
} | {
|
|
119
|
+
kind: "semantic_archive_failed";
|
|
120
|
+
effect_id: string;
|
|
121
|
+
error: string;
|
|
101
122
|
} | {
|
|
102
123
|
kind: "page_in";
|
|
103
124
|
turn: number;
|
|
@@ -314,6 +335,14 @@ export type SessionEvent = {
|
|
|
314
335
|
reason: string;
|
|
315
336
|
coerced_from?: string;
|
|
316
337
|
};
|
|
338
|
+
export type SessionEventKind = SessionEvent["kind"];
|
|
339
|
+
/**
|
|
340
|
+
* The registered session-event vocabulary (F9 / S3, P7-S4). This list is the single authority
|
|
341
|
+
* the cross-SDK manifest fixture pins: a kind added here without the same-commit update to
|
|
342
|
+
* `tests/fixtures/sdk-conformance/canonical/session-event-vocabulary.json` and the python/wasm
|
|
343
|
+
* vocabularies turns cross-SDK conformance red. Declared in `SessionEvent` union order.
|
|
344
|
+
*/
|
|
345
|
+
export declare const SESSION_EVENT_KINDS: readonly ["run_started", "llm_completed", "prompt_measured", "provider_attempt", "tool_requested", "tool_completed", "tool_argument_repaired", "tool_denied", "permission_requested", "permission_resolved", "compressed", "page_out", "semantic_archive_pending", "semantic_archive_completed", "semantic_archive_failed", "page_in", "rollbacked", "capability_changed", "context_renewed", "suspended", "resumed", "tool_gated", "signal_delivery_disposed", "budget_exceeded", "budget_usage_reported", "operation_cancelled", "milestone_advanced", "milestone_blocked", "checkpoint_taken", "entropy_sample", "entropy_alert", "agent_process_changed", "memory_written", "memory_queried", "memory_validation_failed", "memory_write_failed", "memory_query_failed", "memory_retrieval_result", "workflow_node_completed", "workflow_nodes_submitted", "workflow_batch_spawned", "workflow_completed", "kernel_observation", "run_terminal", "summary_upgraded", "group_member_joined", "group_budget_charged", "round_started", "round_paced"];
|
|
317
346
|
/**
|
|
318
347
|
* The business-projection log (spec §9.2): run started/terminal, stream events, observations,
|
|
319
348
|
* provider/tool presentation, audit metadata.
|