@qvac/harness 0.7.1 → 1.0.0-rc.1
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/README.md +224 -0
- package/dist-lib/index.d.ts +55 -3
- package/dist-lib/index.js +721 -236
- package/dist-lib/lib/capabilities/completion-engine/abort-polyfill.d.ts +1 -0
- package/dist-lib/lib/capabilities/completion-engine/abort-polyfill.js +10 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/answering.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/answering.js +17 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/approval.d.ts +4 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/approval.js +29 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/direct-search.d.ts +4 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/direct-search.js +73 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/execute.d.ts +41 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/execute.js +49 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/executing.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/executing.js +102 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/execution-plan.d.ts +47 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/execution-plan.js +87 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/finishing.d.ts +2 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/finishing.js +32 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/inspect-preload.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/inspect-preload.js +75 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/inspecting.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/inspecting.js +152 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/loading-skill.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/loading-skill.js +94 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preload-failure.d.ts +9 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preload-failure.js +11 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preloading.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preloading.js +114 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preparing.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preparing.js +198 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/rejecting.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/rejecting.js +71 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/rejection.d.ts +18 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/rejection.js +70 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/resolving.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/resolving.js +60 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/stream.d.ts +21 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/stream.js +48 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/streaming.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/streaming.js +156 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/wrap-up.d.ts +7 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/wrap-up.js +61 -0
- package/dist-lib/lib/capabilities/completion-engine/driver.d.ts +25 -0
- package/dist-lib/lib/capabilities/completion-engine/driver.js +553 -0
- package/dist-lib/lib/capabilities/completion-engine/durable.d.ts +61 -0
- package/dist-lib/lib/capabilities/completion-engine/durable.js +150 -0
- package/dist-lib/lib/capabilities/completion-engine/operations.d.ts +6 -0
- package/dist-lib/lib/capabilities/completion-engine/operations.js +239 -0
- package/dist-lib/lib/capabilities/completion-engine/ports.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/ports.js +267 -0
- package/dist-lib/lib/capabilities/completion-engine/session.d.ts +76 -0
- package/dist-lib/lib/capabilities/completion-engine/session.js +70 -0
- package/dist-lib/lib/capabilities/completion-loop/index.d.ts +80 -0
- package/dist-lib/lib/capabilities/completion-loop/index.js +158 -0
- package/dist-lib/lib/capabilities/completion-loop/metrics.d.ts +5 -0
- package/dist-lib/lib/capabilities/completion-loop/metrics.js +29 -0
- package/dist-lib/lib/capabilities/completion-loop/round.d.ts +33 -0
- package/dist-lib/lib/capabilities/completion-loop/round.js +353 -0
- package/dist-lib/lib/capabilities/completion-loop/tool-execution.d.ts +60 -0
- package/dist-lib/lib/capabilities/completion-loop/tool-execution.js +270 -0
- package/dist-lib/lib/capabilities/completion-loop/turns.d.ts +23 -0
- package/dist-lib/lib/capabilities/completion-loop/turns.js +112 -0
- package/dist-lib/lib/capabilities/completion-runtime.d.ts +46 -0
- package/dist-lib/lib/capabilities/completion-runtime.js +74 -0
- package/dist-lib/lib/capabilities/completion.d.ts +18 -335
- package/dist-lib/lib/capabilities/completion.js +20 -1301
- package/dist-lib/lib/capabilities/download.d.ts +1 -1
- package/dist-lib/lib/capabilities/download.js +7 -2
- package/dist-lib/lib/capabilities/invoke.js +5 -3
- package/dist-lib/lib/capabilities/tool-plan.d.ts +35 -0
- package/dist-lib/lib/capabilities/tool-plan.js +66 -0
- package/dist-lib/lib/capabilities/tool-turns.d.ts +11 -2
- package/dist-lib/lib/capabilities/tool-turns.js +30 -2
- package/dist-lib/lib/capabilities/types.d.ts +287 -0
- package/dist-lib/lib/capabilities/types.js +1 -0
- package/dist-lib/lib/completion-lifecycle.d.ts +14 -0
- package/dist-lib/lib/completion-lifecycle.js +126 -0
- package/dist-lib/lib/connect.d.ts +10 -3
- package/dist-lib/lib/connect.js +329 -23
- package/dist-lib/lib/contract-types.d.ts +19 -2
- package/dist-lib/lib/harness-lifecycle.d.ts +66 -0
- package/dist-lib/lib/harness-lifecycle.js +129 -0
- package/dist-lib/lib/helpers/detach-json.d.ts +1 -0
- package/dist-lib/lib/helpers/detach-json.js +146 -0
- package/dist-lib/lib/helpers/markup-scanner.d.ts +26 -0
- package/dist-lib/lib/helpers/markup-scanner.js +156 -0
- package/dist-lib/lib/helpers/markup-stream-filter.js +138 -35
- package/dist-lib/lib/helpers/race-abort.d.ts +9 -4
- package/dist-lib/lib/helpers/race-abort.js +2 -7
- package/dist-lib/lib/helpers/recovery-required.d.ts +1 -0
- package/dist-lib/lib/helpers/recovery-required.js +1 -0
- package/dist-lib/lib/helpers/run-outcome.d.ts +10 -2
- package/dist-lib/lib/helpers/run-outcome.js +8 -5
- package/dist-lib/lib/helpers/tool-call-markup.d.ts +2 -0
- package/dist-lib/lib/helpers/tool-call-markup.js +197 -82
- package/dist-lib/lib/hooks/built-in/arg-repair.d.ts +1 -0
- package/dist-lib/lib/hooks/built-in/arg-repair.js +1 -0
- package/dist-lib/lib/hooks/built-in/egress.d.ts +1 -0
- package/dist-lib/lib/hooks/built-in/egress.js +2 -1
- package/dist-lib/lib/hooks/built-in/sandbox.d.ts +1 -0
- package/dist-lib/lib/hooks/built-in/sandbox.js +6 -1
- package/dist-lib/lib/hooks/built-in/skill-catalog.d.ts +1 -0
- package/dist-lib/lib/hooks/built-in/skill-catalog.js +2 -1
- package/dist-lib/lib/hooks/pipeline.d.ts +4 -1
- package/dist-lib/lib/hooks/pipeline.js +24 -2
- package/dist-lib/lib/hooks/run.d.ts +2 -1
- package/dist-lib/lib/hooks/run.js +19 -7
- package/dist-lib/lib/hooks/types.d.ts +17 -6
- package/dist-lib/lib/machine/completion/actions/approval.d.ts +3 -0
- package/dist-lib/lib/machine/completion/actions/approval.js +16 -0
- package/dist-lib/lib/machine/completion/actions/completion.d.ts +23 -0
- package/dist-lib/lib/machine/completion/actions/completion.js +142 -0
- package/dist-lib/lib/machine/completion/actions/skills.d.ts +9 -0
- package/dist-lib/lib/machine/completion/actions/skills.js +83 -0
- package/dist-lib/lib/machine/completion/actions/tools.d.ts +16 -0
- package/dist-lib/lib/machine/completion/actions/tools.js +173 -0
- package/dist-lib/lib/machine/completion/context.d.ts +9 -0
- package/dist-lib/lib/machine/completion/context.js +44 -0
- package/dist-lib/lib/machine/completion/contract.d.ts +6 -0
- package/dist-lib/lib/machine/completion/contract.js +1 -0
- package/dist-lib/lib/machine/completion/guards/retry.d.ts +9 -0
- package/dist-lib/lib/machine/completion/guards/retry.js +25 -0
- package/dist-lib/lib/machine/completion/implementations.d.ts +81 -0
- package/dist-lib/lib/machine/completion/implementations.js +152 -0
- package/dist-lib/lib/machine/completion/machine.d.ts +375 -0
- package/dist-lib/lib/machine/completion/machine.js +511 -0
- package/dist-lib/lib/machine/completion/ports.d.ts +65 -0
- package/dist-lib/lib/machine/completion/ports.js +224 -0
- package/dist-lib/lib/machine/completion/rules.d.ts +39 -0
- package/dist-lib/lib/machine/completion/rules.js +115 -0
- package/dist-lib/lib/machine/completion/types.d.ts +493 -0
- package/dist-lib/lib/machine/completion/types.js +1 -0
- package/dist-lib/lib/machine/engine.d.ts +93 -0
- package/dist-lib/lib/machine/engine.js +483 -0
- package/dist-lib/lib/machine/errors.d.ts +44 -0
- package/dist-lib/lib/machine/errors.js +373 -0
- package/dist-lib/lib/machine/guards.d.ts +2 -0
- package/dist-lib/lib/machine/guards.js +6 -0
- package/dist-lib/lib/machine/index.d.ts +20 -0
- package/dist-lib/lib/machine/index.js +11 -0
- package/dist-lib/lib/machine/replay-output.d.ts +24 -0
- package/dist-lib/lib/machine/replay-output.js +50 -0
- package/dist-lib/lib/machine/stable-stringify.d.ts +1 -0
- package/dist-lib/lib/machine/stable-stringify.js +11 -0
- package/dist-lib/lib/models/model-pool.d.ts +14 -6
- package/dist-lib/lib/models/model-pool.js +95 -30
- package/dist-lib/lib/run-log/history-codec.d.ts +23 -0
- package/dist-lib/lib/run-log/history-codec.js +973 -0
- package/dist-lib/lib/run-log/patch.d.ts +6 -0
- package/dist-lib/lib/run-log/patch.js +93 -0
- package/dist-lib/lib/run-log/persisted-actor.d.ts +18 -0
- package/dist-lib/lib/run-log/persisted-actor.js +218 -0
- package/dist-lib/lib/run-log/protocol-types.d.ts +153 -0
- package/dist-lib/lib/run-log/protocol-types.js +1 -0
- package/dist-lib/lib/run-log/protocol.d.ts +27 -0
- package/dist-lib/lib/run-log/protocol.js +1056 -0
- package/dist-lib/lib/run-log/replay.d.ts +25 -0
- package/dist-lib/lib/run-log/replay.js +129 -0
- package/dist-lib/lib/run-log/run-journal.d.ts +125 -0
- package/dist-lib/lib/run-log/run-journal.js +783 -0
- package/dist-lib/lib/run-log-inspect.d.ts +25 -0
- package/dist-lib/lib/run-log-inspect.js +627 -0
- package/dist-lib/lib/run-log-protocol.d.ts +2 -0
- package/dist-lib/lib/run-log-protocol.js +1 -0
- package/dist-lib/lib/run-log-redact.d.ts +27 -0
- package/dist-lib/lib/run-log-redact.js +1107 -0
- package/dist-lib/lib/serve.js +307 -11
- package/dist-lib/lib/spawn.js +3 -2
- package/dist-lib/lib/tool-call-display.d.ts +1 -21
- package/dist-lib/lib/tools/exec/adapters/python/wheels.js +2 -1
- package/dist-lib/lib/tools/exec.d.ts +2 -1
- package/dist-lib/lib/tools/exec.js +57 -2
- package/dist-lib/lib/tools/generate-image.js +1 -1
- package/dist-lib/lib/tools/generate-music.js +1 -1
- package/dist-lib/lib/tools/http-request.d.ts +2 -1
- package/dist-lib/lib/tools/http-request.js +2 -1
- package/dist-lib/lib/tools/mcp-call.js +8 -1
- package/dist-lib/lib/tools/operations/builders.d.ts +1 -0
- package/dist-lib/lib/tools/operations/builders.js +1 -0
- package/dist-lib/lib/tools/operations/compile.js +11 -1
- package/dist-lib/lib/tools/operations/manifest.js +1 -0
- package/dist-lib/lib/tools/outbound-guard.d.ts +8 -6
- package/dist-lib/lib/tools/outbound-guard.js +25 -8
- package/dist-lib/lib/tools/skills/catalog.d.ts +1 -0
- package/dist-lib/lib/tools/skills/catalog.js +35 -0
- package/dist-lib/lib/tools/skills/cli-schema-types.d.ts +1 -0
- package/dist-lib/lib/tools/skills/cli-schema.js +25 -0
- package/dist-lib/lib/wire.d.ts +5 -0
- package/dist-lib/lib/wire.js +128 -5
- package/dist-lib/schema/harness.js +20 -5
- package/dist-lib/spec/hrpc/messages.js +95 -15
- package/dist-lib/spec/hyperschema/index.js +95 -15
- package/dist-lib/spec/hyperschema/schema.json +69 -1
- package/dist-lib/spec/hyperschema/types.d.ts +10 -3
- package/package.json +20 -2
- package/patches/@qvac%2Finference@0.20.0.patch +67 -0
- package/patches/bare-stow@0.1.5.patch +68 -0
- package/patches/hypercore-blob-server@1.15.0.patch +15 -0
- package/patches/localwatch@1.4.3.patch +13 -0
- package/patches/pyodide@314.0.2.patch +144 -0
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
import b4a from 'b4a';
|
|
2
|
+
import { randomBytes, createHmac } from 'crypto';
|
|
3
|
+
import { createRunBudget, runToolContext, metricsEvent, reportLandedWrites } from '../completion-loop/index.js';
|
|
4
|
+
import { usageBreakdown } from '../usage-breakdown.js';
|
|
5
|
+
import { contextFromBoot, didDrainTimeOut, emptyCompletionContext, raceDrain, requestFromBoot, rehydrateError, runEngine, safeForkLength as computeSafeForkLength, stableStringify, tagError, unresolvedWriteIds as computeUnresolvedWriteIds, unsettledRedactedIds, forkRepeatsSettledWrite, recoveryAdvice } from '../../machine/index.js';
|
|
6
|
+
import { createSession } from './session.js';
|
|
7
|
+
import { captureFacts } from './durable.js';
|
|
8
|
+
import { completionPorts } from './ports.js';
|
|
9
|
+
import { detachJson } from '../../helpers/detach-json.js';
|
|
10
|
+
import { AbortedError } from '../../helpers/race-abort.js';
|
|
11
|
+
import { hlog } from '../../log.js';
|
|
12
|
+
import { harnessHooks } from '../../hooks/registry.js';
|
|
13
|
+
import { snapshotHooks } from '../../hooks/pipeline.js';
|
|
14
|
+
import { isRecord } from '../../guards.js';
|
|
15
|
+
const completionLockOwner = {};
|
|
16
|
+
const IDENTITY_FIELDS = [
|
|
17
|
+
'model',
|
|
18
|
+
'messages',
|
|
19
|
+
'agent',
|
|
20
|
+
'cacheKey',
|
|
21
|
+
'thinkingDefault',
|
|
22
|
+
'generationParams',
|
|
23
|
+
'responseFormat'
|
|
24
|
+
];
|
|
25
|
+
function requestValues(args) {
|
|
26
|
+
return {
|
|
27
|
+
model: args.model ?? args.modelId,
|
|
28
|
+
messages: args.requestMessages ?? args.messages,
|
|
29
|
+
agent: args.agent,
|
|
30
|
+
cacheKey: args.cacheKey,
|
|
31
|
+
thinkingDefault: args.thinkingDefault,
|
|
32
|
+
generationParams: args.generationParams,
|
|
33
|
+
responseFormat: args.responseFormat
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function digestKey(key, runId) {
|
|
37
|
+
return createHmac('sha256', key).update(`qvac:completion:request:${runId}`).digest();
|
|
38
|
+
}
|
|
39
|
+
function hmac(key, domain, value) {
|
|
40
|
+
return createHmac('sha256', key)
|
|
41
|
+
.update(domain)
|
|
42
|
+
.update('\0')
|
|
43
|
+
.update(stableStringify(value))
|
|
44
|
+
.digest('hex');
|
|
45
|
+
}
|
|
46
|
+
function keyProof(key, runId) {
|
|
47
|
+
return createHmac('sha256', key).update(`qvac:completion:key-proof:${runId}`).digest('hex');
|
|
48
|
+
}
|
|
49
|
+
function hookManifest(hooks) {
|
|
50
|
+
const ordinals = new Map();
|
|
51
|
+
return hooks.map((hook) => {
|
|
52
|
+
const ordinal = (ordinals.get(hook.phase) ?? 0) + 1;
|
|
53
|
+
ordinals.set(hook.phase, ordinal);
|
|
54
|
+
return { phase: hook.phase, name: hook.name?.trim() || `${hook.phase}:${ordinal}` };
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function initialRequest(args, options) {
|
|
58
|
+
const { key, digestRunId, hooks } = options;
|
|
59
|
+
const values = requestValues(args);
|
|
60
|
+
const request = {};
|
|
61
|
+
for (const field of IDENTITY_FIELDS) {
|
|
62
|
+
if (values[field] !== undefined) {
|
|
63
|
+
request[field] = detachJson(values[field]);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (key && digestRunId) {
|
|
67
|
+
const scoped = digestKey(key, digestRunId);
|
|
68
|
+
const proofs = {};
|
|
69
|
+
request.identityVersion = 1;
|
|
70
|
+
for (const field of IDENTITY_FIELDS) {
|
|
71
|
+
if (values[field] !== undefined) {
|
|
72
|
+
proofs[field] = hmac(scoped, `identity:${field}`, request[field]);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
request.identityProofs = proofs;
|
|
76
|
+
request.toolConfigDigest = hmac(scoped, 'tool-config', canonicalToolConfig(args.toolConfigs));
|
|
77
|
+
request.hookConfigDigest = hmac(scoped, 'hook-manifest', hookManifest(hooks));
|
|
78
|
+
request.keyProof = keyProof(key, digestRunId);
|
|
79
|
+
}
|
|
80
|
+
return request;
|
|
81
|
+
}
|
|
82
|
+
function isCompletionMessages(value) {
|
|
83
|
+
return (Array.isArray(value) &&
|
|
84
|
+
value.every((message) => isRecord(message) &&
|
|
85
|
+
typeof message.role === 'string' &&
|
|
86
|
+
typeof message.content === 'string' &&
|
|
87
|
+
(message.attachments === undefined ||
|
|
88
|
+
(Array.isArray(message.attachments) &&
|
|
89
|
+
message.attachments.every((attachment) => isRecord(attachment) && typeof attachment.path === 'string')))));
|
|
90
|
+
}
|
|
91
|
+
function explicitIdentity(provided) {
|
|
92
|
+
const values = requestValues(provided);
|
|
93
|
+
const out = {};
|
|
94
|
+
for (const field of IDENTITY_FIELDS) {
|
|
95
|
+
if (values[field] !== undefined) {
|
|
96
|
+
out[field] = detachJson(values[field]);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
function verifyResumeIdentity({ saved, metadata, key, provided, hooks }) {
|
|
102
|
+
const digestRunId = metadata.digestRunId ?? metadata.runId;
|
|
103
|
+
if (saved.identityVersion !== 1 ||
|
|
104
|
+
typeof saved.keyProof !== 'string' ||
|
|
105
|
+
saved.keyProof !== keyProof(key, digestRunId) ||
|
|
106
|
+
typeof metadata.requestDigest !== 'string') {
|
|
107
|
+
throw new Error('Resume requires the original durable request digest key');
|
|
108
|
+
}
|
|
109
|
+
const scoped = digestKey(key, digestRunId);
|
|
110
|
+
if (typeof saved.hookConfigDigest !== 'string' ||
|
|
111
|
+
saved.hookConfigDigest !== hmac(scoped, 'hook-manifest', hookManifest(hooks))) {
|
|
112
|
+
throw new Error('Resume requires the original hook configuration');
|
|
113
|
+
}
|
|
114
|
+
const proofs = isRecord(saved.identityProofs) ? saved.identityProofs : undefined;
|
|
115
|
+
const supplied = explicitIdentity(provided);
|
|
116
|
+
for (const field of IDENTITY_FIELDS) {
|
|
117
|
+
if (supplied[field] === undefined)
|
|
118
|
+
continue;
|
|
119
|
+
const expected = proofs?.[field];
|
|
120
|
+
if (typeof expected !== 'string' ||
|
|
121
|
+
expected !== hmac(scoped, `identity:${field}`, supplied[field])) {
|
|
122
|
+
throw new Error('Resume cannot replace the original model, conversation, or execution configuration');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (provided.toolConfigs !== undefined) {
|
|
126
|
+
if (!matchesToolConfig(saved, scoped, provided.toolConfigs)) {
|
|
127
|
+
throw new Error('Resume requires the original tool configuration');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else if (!matchesToolConfig(saved, scoped, {})) {
|
|
131
|
+
throw new Error('Resume requires the original tool configuration');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function resumedRequest({ boot, key, provided, hooks, bootRequest, runId }) {
|
|
135
|
+
const metadata = boot?.metadata;
|
|
136
|
+
if (!boot || !metadata) {
|
|
137
|
+
throw new Error(`Run ${runId} does not exist`);
|
|
138
|
+
}
|
|
139
|
+
if (!(key instanceof Uint8Array) || key.byteLength !== 32) {
|
|
140
|
+
throw new Error('Durable completion requires a 32-byte request digest key');
|
|
141
|
+
}
|
|
142
|
+
const stored = bootRequest ?? requestFromBoot(boot);
|
|
143
|
+
if (!isRequestIdentity(stored)) {
|
|
144
|
+
throw new Error('Run boot has malformed original request metadata');
|
|
145
|
+
}
|
|
146
|
+
verifyResumeIdentity({ saved: stored, metadata, key, provided, hooks });
|
|
147
|
+
if (typeof metadata.requestDigest !== 'string') {
|
|
148
|
+
throw new Error('Run boot is missing its request digest');
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
identity: stored,
|
|
152
|
+
metadata,
|
|
153
|
+
key,
|
|
154
|
+
args: argsFromRequest(stored),
|
|
155
|
+
requestDigest: metadata.requestDigest,
|
|
156
|
+
digestRunId: metadata.digestRunId ?? metadata.runId
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function isRequestIdentity(value) {
|
|
160
|
+
if (!isRecord(value)) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
if (value.identityVersion !== undefined && value.identityVersion !== 1) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
if (value.identityProofs !== undefined) {
|
|
167
|
+
if (!isRecord(value.identityProofs)) {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
if (Object.values(value.identityProofs).some((proof) => typeof proof !== 'string')) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return ((value.model === undefined || typeof value.model === 'string') &&
|
|
175
|
+
(value.messages === undefined || isCompletionMessages(value.messages)) &&
|
|
176
|
+
(value.agent === undefined || isAgent(value.agent)) &&
|
|
177
|
+
(value.cacheKey === undefined || typeof value.cacheKey === 'string') &&
|
|
178
|
+
(value.thinkingDefault === undefined || typeof value.thinkingDefault === 'string') &&
|
|
179
|
+
(value.generationParams === undefined || isGenerationParams(value.generationParams)) &&
|
|
180
|
+
(value.responseFormat === undefined || isResponseFormat(value.responseFormat)) &&
|
|
181
|
+
(value.toolConfigDigest === undefined || typeof value.toolConfigDigest === 'string') &&
|
|
182
|
+
(value.hookConfigDigest === undefined || typeof value.hookConfigDigest === 'string') &&
|
|
183
|
+
(value.keyProof === undefined || typeof value.keyProof === 'string'));
|
|
184
|
+
}
|
|
185
|
+
function prepareRequest({ args, options, runId, resume, hooks }) {
|
|
186
|
+
if (resume) {
|
|
187
|
+
const resumed = resumedRequest({
|
|
188
|
+
boot: options.boot,
|
|
189
|
+
key: options.requestDigestKey,
|
|
190
|
+
provided: options.resumeRequest ?? args,
|
|
191
|
+
hooks,
|
|
192
|
+
bootRequest: options.bootRequest,
|
|
193
|
+
runId
|
|
194
|
+
});
|
|
195
|
+
return {
|
|
196
|
+
identity: resumed.identity,
|
|
197
|
+
requestDigest: resumed.requestDigest,
|
|
198
|
+
savedArgs: resumed.args,
|
|
199
|
+
resumed
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
const identity = initialRequest(args, {
|
|
203
|
+
key: options.requestDigestKey,
|
|
204
|
+
digestRunId: runId,
|
|
205
|
+
hooks
|
|
206
|
+
});
|
|
207
|
+
const key = options.requestDigestKey;
|
|
208
|
+
const requestDigest = key ? hmac(digestKey(key, runId), 'request', identity) : undefined;
|
|
209
|
+
return { identity, requestDigest, savedArgs: {}, resumed: undefined };
|
|
210
|
+
}
|
|
211
|
+
function matchesToolConfig(saved, scopedKey, value) {
|
|
212
|
+
return (typeof saved.toolConfigDigest === 'string' &&
|
|
213
|
+
saved.toolConfigDigest === hmac(scopedKey, 'tool-config', canonicalToolConfig(value)));
|
|
214
|
+
}
|
|
215
|
+
function canonicalToolConfig(value) {
|
|
216
|
+
return value === undefined ? {} : detachJson(value);
|
|
217
|
+
}
|
|
218
|
+
function argsFromRequest(request) {
|
|
219
|
+
return {
|
|
220
|
+
model: typeof request.model === 'string' ? request.model : undefined,
|
|
221
|
+
modelId: typeof request.model === 'string' ? request.model : undefined,
|
|
222
|
+
messages: isCompletionMessages(request.messages) ? request.messages : undefined,
|
|
223
|
+
agent: isAgent(request.agent) ? request.agent : undefined,
|
|
224
|
+
cacheKey: typeof request.cacheKey === 'string' ? request.cacheKey : undefined,
|
|
225
|
+
thinkingDefault: typeof request.thinkingDefault === 'string' ? request.thinkingDefault : undefined,
|
|
226
|
+
generationParams: isGenerationParams(request.generationParams)
|
|
227
|
+
? request.generationParams
|
|
228
|
+
: undefined,
|
|
229
|
+
responseFormat: isResponseFormat(request.responseFormat) ? request.responseFormat : undefined
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function isAgent(value) {
|
|
233
|
+
if (!isRecord(value))
|
|
234
|
+
return false;
|
|
235
|
+
const optionalString = (key) => value[key] === undefined || typeof value[key] === 'string';
|
|
236
|
+
const optionalNullableString = (key) => value[key] === undefined || value[key] === null || typeof value[key] === 'string';
|
|
237
|
+
const optionalStringArray = (key) => value[key] === undefined ||
|
|
238
|
+
value[key] === null ||
|
|
239
|
+
(Array.isArray(value[key]) && value[key].every((item) => typeof item === 'string'));
|
|
240
|
+
const optionalNullableNumber = (key) => value[key] === undefined || value[key] === null || typeof value[key] === 'number';
|
|
241
|
+
const optionalEnum = (key, values) => value[key] === undefined || value[key] === null || values.some((entry) => entry === value[key]);
|
|
242
|
+
return (optionalString('id') &&
|
|
243
|
+
optionalString('name') &&
|
|
244
|
+
optionalString('bio') &&
|
|
245
|
+
optionalStringArray('enabledTools') &&
|
|
246
|
+
optionalStringArray('enabledSkills') &&
|
|
247
|
+
optionalEnum('toolsScope', ['all', 'selected']) &&
|
|
248
|
+
optionalEnum('skillsScope', ['all', 'selected']) &&
|
|
249
|
+
optionalEnum('reasoning', ['inherit', 'enabled', 'disabled']) &&
|
|
250
|
+
optionalNullableNumber('ctxSize') &&
|
|
251
|
+
optionalNullableString('kvCacheK') &&
|
|
252
|
+
optionalNullableString('kvCacheV') &&
|
|
253
|
+
optionalNullableString('imageModelChoice') &&
|
|
254
|
+
optionalNullableNumber('imageSteps') &&
|
|
255
|
+
optionalNullableNumber('imageWidth') &&
|
|
256
|
+
optionalNullableNumber('imageHeight') &&
|
|
257
|
+
optionalEnum('approvalMode', ['ask', 'skip-all']) &&
|
|
258
|
+
optionalStringArray('disabledToolsets') &&
|
|
259
|
+
(value.sandboxMode === undefined || typeof value.sandboxMode === 'boolean'));
|
|
260
|
+
}
|
|
261
|
+
function isGenerationParams(value) {
|
|
262
|
+
return (isRecord(value) &&
|
|
263
|
+
(value.reasoning_budget === -1 || value.reasoning_budget === 0) &&
|
|
264
|
+
['temp', 'top_p', 'top_k', 'presence_penalty', 'repeat_penalty', 'frequency_penalty'].every((key) => value[key] === undefined || typeof value[key] === 'number'));
|
|
265
|
+
}
|
|
266
|
+
function isResponseFormat(value) {
|
|
267
|
+
if (!isRecord(value)) {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
if (value.type === 'text' || value.type === 'json_object') {
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
if (value.type !== 'json_schema' || !isRecord(value.json_schema)) {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
return (typeof value.json_schema.name === 'string' &&
|
|
277
|
+
isRecord(value.json_schema.schema) &&
|
|
278
|
+
(value.json_schema.description === undefined ||
|
|
279
|
+
typeof value.json_schema.description === 'string') &&
|
|
280
|
+
(value.json_schema.strict === undefined || typeof value.json_schema.strict === 'boolean'));
|
|
281
|
+
}
|
|
282
|
+
function completionArgs(...parts) {
|
|
283
|
+
const merged = {};
|
|
284
|
+
for (const part of parts) {
|
|
285
|
+
Object.assign(merged, part);
|
|
286
|
+
}
|
|
287
|
+
const modelId = typeof merged.modelId === 'string' ? merged.modelId : merged.model;
|
|
288
|
+
const messages = merged.messages;
|
|
289
|
+
if (typeof modelId !== 'string' || !isCompletionMessages(messages)) {
|
|
290
|
+
throw new Error('A completion requires its original model and messages');
|
|
291
|
+
}
|
|
292
|
+
return { ...merged, modelId, messages };
|
|
293
|
+
}
|
|
294
|
+
function restoredContextMetrics(boot) {
|
|
295
|
+
const context = contextFromBoot(boot);
|
|
296
|
+
if (!isRecord(context) || !isRecord(context.metrics)) {
|
|
297
|
+
return undefined;
|
|
298
|
+
}
|
|
299
|
+
const ctxSize = context.metrics.ctxSize;
|
|
300
|
+
return typeof ctxSize === 'number' ? { ctxSize } : undefined;
|
|
301
|
+
}
|
|
302
|
+
function completionOutputFacts(value) {
|
|
303
|
+
if (!isRecord(value) || !isRecord(value.outcome))
|
|
304
|
+
return undefined;
|
|
305
|
+
const confirmedWrites = readStringArray(value.outcome.confirmedWrites);
|
|
306
|
+
const promptParts = readPromptUsage(value.promptParts);
|
|
307
|
+
const backends = readBackends(value.backends);
|
|
308
|
+
if (!confirmedWrites || promptParts === undefined || !backends) {
|
|
309
|
+
return undefined;
|
|
310
|
+
}
|
|
311
|
+
return { confirmedWrites, promptParts, backends };
|
|
312
|
+
}
|
|
313
|
+
function readStringArray(value) {
|
|
314
|
+
if (!Array.isArray(value))
|
|
315
|
+
return undefined;
|
|
316
|
+
const strings = [];
|
|
317
|
+
for (const entry of value) {
|
|
318
|
+
if (typeof entry !== 'string')
|
|
319
|
+
return undefined;
|
|
320
|
+
strings.push(entry);
|
|
321
|
+
}
|
|
322
|
+
return strings;
|
|
323
|
+
}
|
|
324
|
+
function readPromptUsage(value) {
|
|
325
|
+
if (value === null)
|
|
326
|
+
return null;
|
|
327
|
+
if (!isRecord(value))
|
|
328
|
+
return undefined;
|
|
329
|
+
const { systemPrompt, agentInstructions, activeSkills, toolSchemas } = value;
|
|
330
|
+
if (typeof systemPrompt !== 'number' ||
|
|
331
|
+
typeof agentInstructions !== 'number' ||
|
|
332
|
+
typeof activeSkills !== 'number' ||
|
|
333
|
+
typeof toolSchemas !== 'number') {
|
|
334
|
+
return undefined;
|
|
335
|
+
}
|
|
336
|
+
return { systemPrompt, agentInstructions, activeSkills, toolSchemas };
|
|
337
|
+
}
|
|
338
|
+
function readBackends(value) {
|
|
339
|
+
if (!Array.isArray(value))
|
|
340
|
+
return undefined;
|
|
341
|
+
const backends = [];
|
|
342
|
+
for (const entry of value) {
|
|
343
|
+
if (!isRunBackendUse(entry))
|
|
344
|
+
return undefined;
|
|
345
|
+
backends.push(entry);
|
|
346
|
+
}
|
|
347
|
+
return backends;
|
|
348
|
+
}
|
|
349
|
+
function isRunBackendUse(value) {
|
|
350
|
+
return (isRecord(value) &&
|
|
351
|
+
typeof value.tool === 'string' &&
|
|
352
|
+
typeof value.requestedGpu === 'boolean' &&
|
|
353
|
+
(value.device === 'gpu' || value.device === 'cpu' || value.device === 'unknown') &&
|
|
354
|
+
typeof value.backend === 'string');
|
|
355
|
+
}
|
|
356
|
+
function detachedRequest(args) {
|
|
357
|
+
const detached = { ...args };
|
|
358
|
+
if (Array.isArray(args.messages)) {
|
|
359
|
+
detached.messages = detachJson(args.messages);
|
|
360
|
+
}
|
|
361
|
+
if (Array.isArray(args.requestMessages)) {
|
|
362
|
+
detached.requestMessages = detachJson(args.requestMessages);
|
|
363
|
+
}
|
|
364
|
+
if (args.agent) {
|
|
365
|
+
detached.agent = detachJson(args.agent);
|
|
366
|
+
}
|
|
367
|
+
if (args.generationParams) {
|
|
368
|
+
detached.generationParams = detachJson(args.generationParams);
|
|
369
|
+
}
|
|
370
|
+
if (args.responseFormat) {
|
|
371
|
+
detached.responseFormat = detachJson(args.responseFormat);
|
|
372
|
+
}
|
|
373
|
+
if (args.toolConfigs) {
|
|
374
|
+
detached.toolConfigs = detachJson(args.toolConfigs);
|
|
375
|
+
}
|
|
376
|
+
return detached;
|
|
377
|
+
}
|
|
378
|
+
function safeForkLength(boot) {
|
|
379
|
+
return computeSafeForkLength(boot.receipts, new Map(boot.forkBeforeWrite), boot.unredactedLength);
|
|
380
|
+
}
|
|
381
|
+
function unresolvedWriteIds(boot) {
|
|
382
|
+
const dispatched = computeUnresolvedWriteIds(boot.receipts);
|
|
383
|
+
const queued = unsettledRedactedIds(boot.redactedPendingIds, boot.receipts).filter((id) => !dispatched.includes(id));
|
|
384
|
+
return [...dispatched, ...queued];
|
|
385
|
+
}
|
|
386
|
+
export async function* driveCompletion(args, runtime, options = {}) {
|
|
387
|
+
const hooks = snapshotHooks(harnessHooks);
|
|
388
|
+
const resume = args.resume === true;
|
|
389
|
+
if (resume && !args.runId) {
|
|
390
|
+
throw new Error('Resume requires a runId');
|
|
391
|
+
}
|
|
392
|
+
const runId = args.runId ?? b4a.toHex(randomBytes(16));
|
|
393
|
+
const boot = options.boot;
|
|
394
|
+
const durable = typeof options.onStep === 'function';
|
|
395
|
+
const key = options.requestDigestKey;
|
|
396
|
+
if ((durable || boot) && (!(key instanceof Uint8Array) || key.byteLength !== 32)) {
|
|
397
|
+
throw new Error('Durable completion requires a 32-byte request digest key');
|
|
398
|
+
}
|
|
399
|
+
const now = () => Date.now();
|
|
400
|
+
const prepared = prepareRequest({ args, options, runId, resume, hooks });
|
|
401
|
+
const completionState = {
|
|
402
|
+
session: null,
|
|
403
|
+
final: null
|
|
404
|
+
};
|
|
405
|
+
let full = detachedRequest(completionArgs(prepared.savedArgs, args));
|
|
406
|
+
let reachedPause = false;
|
|
407
|
+
const engine = runEngine({
|
|
408
|
+
runId,
|
|
409
|
+
resume,
|
|
410
|
+
recovery: args.recovery,
|
|
411
|
+
request: options.redact ? options.redact(prepared.identity) : prepared.identity,
|
|
412
|
+
requestDigest: prepared.requestDigest,
|
|
413
|
+
budget: boot?.metadata?.budget ?? createRunBudget(now()),
|
|
414
|
+
signal: args.signal,
|
|
415
|
+
lockOwner: args.lockOwner ?? options.lockOwner ?? completionLockOwner,
|
|
416
|
+
now,
|
|
417
|
+
async start({ operations, invokes, boot: openedBoot }) {
|
|
418
|
+
if (resume &&
|
|
419
|
+
unsettledRedactedIds(openedBoot.redactedPendingIds, openedBoot.receipts).length > 0) {
|
|
420
|
+
const forkAt = safeForkLength(openedBoot);
|
|
421
|
+
const recoveryOperationIds = unresolvedWriteIds(openedBoot);
|
|
422
|
+
const forkSafe = forkAt !== null &&
|
|
423
|
+
!forkRepeatsSettledWrite(openedBoot.receipts, new Map(openedBoot.forkBeforeWrite), forkAt);
|
|
424
|
+
let message = 'This run cannot resume because pending tool arguments were redacted';
|
|
425
|
+
if (forkSafe) {
|
|
426
|
+
message += `; fork at ${forkAt} to continue without them`;
|
|
427
|
+
}
|
|
428
|
+
else if (recoveryOperationIds.length > 0) {
|
|
429
|
+
message += `; ${recoveryAdvice(recoveryOperationIds, openedBoot.receipts, openedBoot.redactedPendingIds)}`;
|
|
430
|
+
}
|
|
431
|
+
throw Object.assign(new Error(message), {
|
|
432
|
+
code: 'PENDING_ARGS_REDACTED',
|
|
433
|
+
forkAt,
|
|
434
|
+
forkSafe,
|
|
435
|
+
recoveryOperationIds
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
if (typeof (full.model ?? full.modelId) !== 'string' ||
|
|
439
|
+
!isCompletionMessages(full.messages)) {
|
|
440
|
+
throw new Error('Completion resume requires its original model and messages');
|
|
441
|
+
}
|
|
442
|
+
const savedContext = restoredContextMetrics(openedBoot);
|
|
443
|
+
if (resume) {
|
|
444
|
+
full.ctxSize = savedContext?.ctxSize;
|
|
445
|
+
}
|
|
446
|
+
const loaded = await runtime(detachedRequest(full));
|
|
447
|
+
full = detachedRequest(completionArgs(full, loaded.args ?? {}));
|
|
448
|
+
if (prepared.resumed &&
|
|
449
|
+
!matchesToolConfig(prepared.resumed.identity, digestKey(prepared.resumed.key, prepared.resumed.digestRunId), full.toolConfigs)) {
|
|
450
|
+
throw new Error('Resume requires the original tool configuration');
|
|
451
|
+
}
|
|
452
|
+
const session = createSession(full, {
|
|
453
|
+
runId,
|
|
454
|
+
invokes,
|
|
455
|
+
now,
|
|
456
|
+
requestDigestKey: prepared.resumed?.key ?? key,
|
|
457
|
+
digestRunId: openedBoot.metadata?.digestRunId ??
|
|
458
|
+
openedBoot.metadata?.runId ??
|
|
459
|
+
prepared.resumed?.digestRunId ??
|
|
460
|
+
runId,
|
|
461
|
+
hooks
|
|
462
|
+
});
|
|
463
|
+
session.startedAt = openedBoot.metadata?.startedAt ?? openedBoot.firstSavedAt ?? now();
|
|
464
|
+
if (openedBoot.metadata?.budget) {
|
|
465
|
+
session.runBudget = { ...openedBoot.metadata.budget };
|
|
466
|
+
}
|
|
467
|
+
session.toolContext = runToolContext(full, session.runBudget);
|
|
468
|
+
const context = emptyCompletionContext({
|
|
469
|
+
runId,
|
|
470
|
+
agentId: full.agent?.id ?? null,
|
|
471
|
+
ctxSize: full.ctxSize ?? savedContext?.ctxSize,
|
|
472
|
+
cacheKey: full.cacheKey ?? null
|
|
473
|
+
});
|
|
474
|
+
context.durable = captureFacts(session);
|
|
475
|
+
completionState.session = session;
|
|
476
|
+
return {
|
|
477
|
+
ports: completionPorts({ sdk: loaded.sdk, args: full, session, operations }),
|
|
478
|
+
context
|
|
479
|
+
};
|
|
480
|
+
},
|
|
481
|
+
settled(snapshot) {
|
|
482
|
+
completionState.final = snapshot;
|
|
483
|
+
}
|
|
484
|
+
}, {
|
|
485
|
+
boot,
|
|
486
|
+
onStep: options.onStep,
|
|
487
|
+
hostAppendTimeoutMs: options.hostAppendTimeoutMs,
|
|
488
|
+
redact: options.redact,
|
|
489
|
+
redactShared: options.redactShared,
|
|
490
|
+
redactOperationResult: options.redactOperationResult,
|
|
491
|
+
redactRecord: options.redactRecord,
|
|
492
|
+
redactStep: options.redactStep,
|
|
493
|
+
lockOwner: args.lockOwner ?? options.lockOwner ?? completionLockOwner,
|
|
494
|
+
onDetached: options.onDetached
|
|
495
|
+
});
|
|
496
|
+
try {
|
|
497
|
+
const result = yield* engine;
|
|
498
|
+
if (result.status === 'replayed') {
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
const snapshot = result.snapshot;
|
|
502
|
+
const facts = completionOutputFacts(snapshot.context.durable);
|
|
503
|
+
const landed = facts?.confirmedWrites ?? [];
|
|
504
|
+
if (result.status === 'error') {
|
|
505
|
+
yield* reportLandedWrites(landed);
|
|
506
|
+
if (result.error &&
|
|
507
|
+
typeof result.error === 'object' &&
|
|
508
|
+
'tag' in result.error &&
|
|
509
|
+
result.error.tag === 'aborted') {
|
|
510
|
+
reachedPause = true;
|
|
511
|
+
throw new AbortedError();
|
|
512
|
+
}
|
|
513
|
+
throw rehydrateError(tagError(result.error));
|
|
514
|
+
}
|
|
515
|
+
if (result.status === 'paused') {
|
|
516
|
+
yield* reportLandedWrites(landed);
|
|
517
|
+
reachedPause = true;
|
|
518
|
+
yield { type: 'paused', runId };
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
if (snapshot.output?.status === 'failure') {
|
|
522
|
+
yield* reportLandedWrites(landed);
|
|
523
|
+
throw rehydrateError(snapshot.context.failure, snapshot.output.error);
|
|
524
|
+
}
|
|
525
|
+
const usage = facts?.promptParts
|
|
526
|
+
? usageBreakdown(facts.promptParts, snapshot.context.metrics.cacheTokens, full.model)
|
|
527
|
+
: null;
|
|
528
|
+
const metrics = metricsEvent({ ...snapshot.context.metrics, backends: facts?.backends }, usage);
|
|
529
|
+
if (metrics) {
|
|
530
|
+
yield { ...metrics, runId };
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
finally {
|
|
534
|
+
const ended = completionState.final;
|
|
535
|
+
const owner = completionState.session;
|
|
536
|
+
if (!durable && owner?.runStarted && ended?.hasTag('paused')) {
|
|
537
|
+
const runEnd = owner.pipeline.onRunEnd({
|
|
538
|
+
runId,
|
|
539
|
+
agentId: full.agent?.id ?? null,
|
|
540
|
+
stats: {
|
|
541
|
+
totalTokens: ended.context.metrics.tokens,
|
|
542
|
+
durationMs: Math.round(ended.context.metrics.durationMs),
|
|
543
|
+
timeToFirstToken: ended.context.metrics.ttft
|
|
544
|
+
},
|
|
545
|
+
outcome: reachedPause ? 'aborted' : 'abandoned'
|
|
546
|
+
});
|
|
547
|
+
if (didDrainTimeOut(await raceDrain(runEnd))) {
|
|
548
|
+
options.onDetached?.(runEnd, runId);
|
|
549
|
+
hlog('runEnd hook still running after completion closed', { runId });
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type RunOutcomeState } from '../../helpers/run-outcome.ts';
|
|
2
|
+
import type { RunBackendUse, RunBudget } from '../completion.ts';
|
|
3
|
+
import type { PromptUsageChars } from '../usage-breakdown.ts';
|
|
4
|
+
import type { CompletionDeps, Session, RuntimeBinding } from './session.ts';
|
|
5
|
+
interface CapabilityPolicy {
|
|
6
|
+
behaviorDigest: string;
|
|
7
|
+
roots: string[];
|
|
8
|
+
writeRoots: string[];
|
|
9
|
+
skills: string[];
|
|
10
|
+
skillContent: (readonly [string, string | null])[];
|
|
11
|
+
grantedOps: (readonly [string, string[]])[];
|
|
12
|
+
}
|
|
13
|
+
export declare function capabilityPolicy(session: Session): CapabilityPolicy;
|
|
14
|
+
export declare function schemaDigest(parameters: object): string;
|
|
15
|
+
interface DurableToolFacts {
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
prompt: unknown;
|
|
19
|
+
policyVersion: string | null;
|
|
20
|
+
parametersDigest: string;
|
|
21
|
+
toolset: string | null | undefined;
|
|
22
|
+
autoApprove: boolean;
|
|
23
|
+
externalWrite: boolean;
|
|
24
|
+
owningSkill: string | null;
|
|
25
|
+
skillGated: boolean;
|
|
26
|
+
rootsRequired: boolean;
|
|
27
|
+
writeRootsRequired: boolean;
|
|
28
|
+
compiled: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface DurableFacts extends Record<string, unknown> {
|
|
31
|
+
bindings: RuntimeBinding[];
|
|
32
|
+
runId: string;
|
|
33
|
+
tools: DurableToolFacts[];
|
|
34
|
+
policy: CapabilityPolicy;
|
|
35
|
+
loadedThisTurn: string[];
|
|
36
|
+
loadedFilesThisTurn: string[];
|
|
37
|
+
loadedSkillFiles: [string, string[]][];
|
|
38
|
+
nudgedSkills: string[];
|
|
39
|
+
backends: RunBackendUse[];
|
|
40
|
+
outcome: RunOutcomeState;
|
|
41
|
+
skillIcon: string | null;
|
|
42
|
+
runBudget: RunBudget;
|
|
43
|
+
startedAt: number;
|
|
44
|
+
runStarted: boolean;
|
|
45
|
+
promptParts: PromptUsageChars | null;
|
|
46
|
+
activation: {
|
|
47
|
+
skillsSelected: boolean;
|
|
48
|
+
enabledSkills: string[];
|
|
49
|
+
mention: string | null;
|
|
50
|
+
loadedSkills: string[];
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export interface ToolOperationFacts {
|
|
54
|
+
backends: RunBackendUse[];
|
|
55
|
+
runBudget: Pick<RunBudget, 'outputBytesUsed'>;
|
|
56
|
+
outcome: Pick<RunOutcomeState, 'confirmedWrites'>;
|
|
57
|
+
}
|
|
58
|
+
export declare function captureFacts(session: Session): DurableFacts;
|
|
59
|
+
export declare function captureToolOperationFacts(session: Session): ToolOperationFacts;
|
|
60
|
+
export declare function restoreFacts(deps: CompletionDeps, facts: DurableFacts): void;
|
|
61
|
+
export {};
|