@qvac/harness 0.7.0 → 1.0.0-rc.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 +42 -1
- package/README.md +239 -2
- package/dist-lib/index.d.ts +58 -3
- package/dist-lib/index.js +736 -239
- 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-handle.d.ts +5 -1
- package/dist-lib/lib/models/model-handle.js +8 -3
- package/dist-lib/lib/models/model-list.d.ts +5 -3
- package/dist-lib/lib/models/model-pool.d.ts +18 -7
- package/dist-lib/lib/models/model-pool.js +126 -38
- 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 +308 -12
- 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.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 +22 -6
- package/dist-lib/spec/hrpc/messages.js +100 -18
- package/dist-lib/spec/hyperschema/index.js +100 -18
- package/dist-lib/spec/hyperschema/schema.json +74 -1
- package/dist-lib/spec/hyperschema/types.d.ts +11 -3
- package/package.json +19 -1
- 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
package/dist-lib/lib/serve.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AbortController } from 'bare-abort-controller';
|
|
2
1
|
import b4a from 'b4a';
|
|
2
|
+
import { AbortController } from 'bare-abort-controller';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import { settleOnClose } from './rpc-session.js';
|
|
5
5
|
import { pipeline, Readable } from 'streamx';
|
|
@@ -8,7 +8,8 @@ import HRPC from '../spec/hrpc/index.js';
|
|
|
8
8
|
import { isCapability } from './capabilities/invoke.js';
|
|
9
9
|
import { CUSTOM_TASK_TYPES } from './models/model-catalog.js';
|
|
10
10
|
import { unsupportedKvCacheDeletion } from './capabilities/kv-cache.js';
|
|
11
|
-
import {
|
|
11
|
+
import { validateEngineBoot } from './run-log-protocol.js';
|
|
12
|
+
import { errorMessage, isRecord } from './guards.js';
|
|
12
13
|
import { hlog } from './log.js';
|
|
13
14
|
import { pushQueue } from './queue.js';
|
|
14
15
|
import { TextCoalescer } from './helpers/text-coalescer.js';
|
|
@@ -30,6 +31,168 @@ const WIRE_HIGH_WATER_MARK = 64;
|
|
|
30
31
|
const TEXT_COALESCE_CAP = 8192;
|
|
31
32
|
const TEXT_COALESCE_MS = 60;
|
|
32
33
|
function noop() { }
|
|
34
|
+
function decodeDigestKey(value) {
|
|
35
|
+
if (typeof value !== 'string' || !/^[0-9a-f]{64}$/i.test(value)) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
return b4a.from(value, 'hex');
|
|
39
|
+
}
|
|
40
|
+
function isEngineBoot(value) {
|
|
41
|
+
if (!isEngineBootEnvelope(value)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
validateEngineBoot(value);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function isEngineBootEnvelope(value) {
|
|
53
|
+
if (!isRecord(value)) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
const counter = (name) => typeof value[name] === 'number' && Number.isSafeInteger(value[name]) && value[name] >= 0;
|
|
57
|
+
const metadata = value.metadata;
|
|
58
|
+
const hasMetadata = metadata === null ||
|
|
59
|
+
(isRecord(metadata) && metadata.version === 5 && metadata.type === 'metadata');
|
|
60
|
+
return (value.protocolVersion === 1 &&
|
|
61
|
+
counter('length') &&
|
|
62
|
+
counter('nextSeq') &&
|
|
63
|
+
counter('deltasSinceCheckpoint') &&
|
|
64
|
+
counter('unredactedLength') &&
|
|
65
|
+
(value.machineVersion === null || typeof value.machineVersion === 'number') &&
|
|
66
|
+
(value.xstateVersion === null || typeof value.xstateVersion === 'string') &&
|
|
67
|
+
hasMetadata &&
|
|
68
|
+
'eventState' in value &&
|
|
69
|
+
(value.snapshotSavedAt === undefined || typeof value.snapshotSavedAt === 'number') &&
|
|
70
|
+
(value.firstSavedAt === undefined || typeof value.firstSavedAt === 'number') &&
|
|
71
|
+
(value.redactedPendingArgs === null || typeof value.redactedPendingArgs === 'boolean') &&
|
|
72
|
+
typeof value.restoredRedacted === 'boolean' &&
|
|
73
|
+
Array.isArray(value.forkBeforeWrite) &&
|
|
74
|
+
Array.isArray(value.receipts) &&
|
|
75
|
+
Array.isArray(value.intentArgs));
|
|
76
|
+
}
|
|
77
|
+
const EMPTY_IDENTITY_FIELDS = new Set([
|
|
78
|
+
'model',
|
|
79
|
+
'cacheKey',
|
|
80
|
+
'thinkingDefault',
|
|
81
|
+
'agent.id',
|
|
82
|
+
'agent.name',
|
|
83
|
+
'agent.bio'
|
|
84
|
+
]);
|
|
85
|
+
function startPayloadFrom(value) {
|
|
86
|
+
if (!isRecord(value)) {
|
|
87
|
+
return {};
|
|
88
|
+
}
|
|
89
|
+
const payload = {};
|
|
90
|
+
if (value.resume === null || typeof value.resume === 'boolean') {
|
|
91
|
+
payload.resume = value.resume;
|
|
92
|
+
}
|
|
93
|
+
if (value.recoveryEvents === null || typeof value.recoveryEvents === 'boolean') {
|
|
94
|
+
payload.recoveryEvents = value.recoveryEvents;
|
|
95
|
+
}
|
|
96
|
+
if (Object.hasOwn(value, 'explicitEmptyIdentity')) {
|
|
97
|
+
if (!Array.isArray(value.explicitEmptyIdentity) ||
|
|
98
|
+
value.explicitEmptyIdentity.length > EMPTY_IDENTITY_FIELDS.size) {
|
|
99
|
+
throw new TypeError('Invalid explicit-empty identity marker');
|
|
100
|
+
}
|
|
101
|
+
const fields = new Set();
|
|
102
|
+
for (const field of value.explicitEmptyIdentity) {
|
|
103
|
+
if (typeof field !== 'string' || !EMPTY_IDENTITY_FIELDS.has(field)) {
|
|
104
|
+
throw new TypeError('Invalid explicit-empty identity marker');
|
|
105
|
+
}
|
|
106
|
+
fields.add(field);
|
|
107
|
+
}
|
|
108
|
+
if (fields.size) {
|
|
109
|
+
payload.explicitEmptyIdentity = [...fields];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (Array.isArray(value.resolutions)) {
|
|
113
|
+
payload.resolutions = value.resolutions.map((resolution) => {
|
|
114
|
+
if (!isRecord(resolution) || typeof resolution.operationId !== 'string') {
|
|
115
|
+
throw new TypeError('Invalid run recovery resolution');
|
|
116
|
+
}
|
|
117
|
+
if (resolution.decision === 'retry') {
|
|
118
|
+
return { operationId: resolution.operationId, decision: 'retry' };
|
|
119
|
+
}
|
|
120
|
+
if (resolution.decision === 'result' && 'result' in resolution) {
|
|
121
|
+
return {
|
|
122
|
+
operationId: resolution.operationId,
|
|
123
|
+
decision: 'result',
|
|
124
|
+
result: resolution.result
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
if (resolution.decision === 'skip') {
|
|
128
|
+
return { operationId: resolution.operationId, decision: 'skip' };
|
|
129
|
+
}
|
|
130
|
+
throw new TypeError('Invalid run recovery resolution');
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
if (value.runLog === null) {
|
|
134
|
+
payload.runLog = null;
|
|
135
|
+
}
|
|
136
|
+
else if (value.runLog) {
|
|
137
|
+
const runLog = isRecord(value.runLog) ? value.runLog : {};
|
|
138
|
+
payload.runLog = {
|
|
139
|
+
boot: runLog.boot,
|
|
140
|
+
digestKey: runLog.digestKey,
|
|
141
|
+
hostAppendTimeoutMs: typeof runLog.hostAppendTimeoutMs === 'number' ? runLog.hostAppendTimeoutMs : undefined
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return payload;
|
|
145
|
+
}
|
|
146
|
+
function assertEmptyIdentityMarkersMatchFrame(frame, fields) {
|
|
147
|
+
for (const field of fields) {
|
|
148
|
+
let value;
|
|
149
|
+
switch (field) {
|
|
150
|
+
case 'model':
|
|
151
|
+
value = frame.model;
|
|
152
|
+
break;
|
|
153
|
+
case 'cacheKey':
|
|
154
|
+
value = frame.cacheKey;
|
|
155
|
+
break;
|
|
156
|
+
case 'thinkingDefault':
|
|
157
|
+
value = frame.thinkingDefault;
|
|
158
|
+
break;
|
|
159
|
+
case 'agent.id':
|
|
160
|
+
if (frame.agent === null || frame.agent === undefined) {
|
|
161
|
+
throw new TypeError('Explicit-empty agent identity requires an agent frame');
|
|
162
|
+
}
|
|
163
|
+
value = frame.agent?.id;
|
|
164
|
+
break;
|
|
165
|
+
case 'agent.name':
|
|
166
|
+
if (frame.agent === null || frame.agent === undefined) {
|
|
167
|
+
throw new TypeError('Explicit-empty agent identity requires an agent frame');
|
|
168
|
+
}
|
|
169
|
+
value = frame.agent?.name;
|
|
170
|
+
break;
|
|
171
|
+
case 'agent.bio':
|
|
172
|
+
if (frame.agent === null || frame.agent === undefined) {
|
|
173
|
+
throw new TypeError('Explicit-empty agent identity requires an agent frame');
|
|
174
|
+
}
|
|
175
|
+
value = frame.agent?.bio;
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
if (value !== null && value !== undefined && value !== '') {
|
|
179
|
+
throw new TypeError('Conflicting explicit-empty identity marker');
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function normalizeAgentKnobs(agent) {
|
|
184
|
+
const normalized = { ...agent };
|
|
185
|
+
if (normalized.id === null || normalized.id === undefined) {
|
|
186
|
+
delete normalized.id;
|
|
187
|
+
}
|
|
188
|
+
if (normalized.name === null || normalized.name === undefined) {
|
|
189
|
+
delete normalized.name;
|
|
190
|
+
}
|
|
191
|
+
if (normalized.bio === null || normalized.bio === undefined) {
|
|
192
|
+
delete normalized.bio;
|
|
193
|
+
}
|
|
194
|
+
return normalized;
|
|
195
|
+
}
|
|
33
196
|
function tick() {
|
|
34
197
|
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
35
198
|
}
|
|
@@ -270,7 +433,7 @@ function modelEvents(harness) {
|
|
|
270
433
|
catalogChanged,
|
|
271
434
|
...loaded.map((entry) => `${entry.model}:${entry.refs}`)
|
|
272
435
|
].join('\0');
|
|
273
|
-
if (key === last) {
|
|
436
|
+
if (key === last && !catalogChanged) {
|
|
274
437
|
return;
|
|
275
438
|
}
|
|
276
439
|
last = key;
|
|
@@ -358,10 +521,13 @@ function completion(harness) {
|
|
|
358
521
|
const pendingRag = new Map();
|
|
359
522
|
const pendingQuestion = new Map();
|
|
360
523
|
const pendingDrive = new Map();
|
|
524
|
+
const pendingRunLog = new Map();
|
|
361
525
|
const controller = new AbortController();
|
|
362
526
|
let calls = 0;
|
|
363
527
|
let started = false;
|
|
528
|
+
let clientGone = false;
|
|
364
529
|
const gone = () => {
|
|
530
|
+
clientGone = true;
|
|
365
531
|
controller.abort('client gone');
|
|
366
532
|
for (const resolve of pending.values()) {
|
|
367
533
|
resolve(false);
|
|
@@ -391,6 +557,10 @@ function completion(harness) {
|
|
|
391
557
|
reject(new Error('client gone'));
|
|
392
558
|
}
|
|
393
559
|
pendingDrive.clear();
|
|
560
|
+
for (const { reject } of pendingRunLog.values()) {
|
|
561
|
+
reject(new Error('client gone'));
|
|
562
|
+
}
|
|
563
|
+
pendingRunLog.clear();
|
|
394
564
|
events.end();
|
|
395
565
|
};
|
|
396
566
|
duplex.on('close', gone);
|
|
@@ -501,15 +671,82 @@ function completion(harness) {
|
|
|
501
671
|
waiter.resolve(frame.payload ?? {});
|
|
502
672
|
return;
|
|
503
673
|
}
|
|
674
|
+
if (frame.type === 'pause') {
|
|
675
|
+
controller.abort('paused');
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
if (frame.type === 'run-log-result') {
|
|
679
|
+
if (typeof frame.callId !== 'string') {
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
const waiter = pendingRunLog.get(frame.callId);
|
|
683
|
+
pendingRunLog.delete(frame.callId);
|
|
684
|
+
if (!waiter) {
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
if (frame.message) {
|
|
688
|
+
return waiter.reject(new Error(frame.message));
|
|
689
|
+
}
|
|
690
|
+
waiter.resolve();
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
504
693
|
if (started || (frame.type !== 'start' && frame.type !== 'invoke')) {
|
|
505
694
|
return;
|
|
506
695
|
}
|
|
507
696
|
started = true;
|
|
697
|
+
let startPayload;
|
|
698
|
+
try {
|
|
699
|
+
startPayload = startPayloadFrom(frame.payload);
|
|
700
|
+
assertEmptyIdentityMarkersMatchFrame(frame, startPayload.explicitEmptyIdentity ?? []);
|
|
701
|
+
}
|
|
702
|
+
catch (err) {
|
|
703
|
+
events.push({ type: 'error', message: errorMessage(err) });
|
|
704
|
+
events.push({ type: 'done' });
|
|
705
|
+
events.end();
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
const explicitEmptyIdentity = new Set(startPayload.explicitEmptyIdentity ?? []);
|
|
709
|
+
const runLog = startPayload.runLog;
|
|
710
|
+
const resuming = startPayload.resume === true ||
|
|
711
|
+
Boolean(isEngineBoot(runLog?.boot) && runLog.boot.metadata !== null);
|
|
712
|
+
const requestDigestKey = runLog ? decodeDigestKey(runLog.digestKey) : undefined;
|
|
713
|
+
const agent = normalizeAgentKnobs(frame.agent ?? {});
|
|
714
|
+
if ((frame.agent?.id === null || frame.agent?.id === undefined) &&
|
|
715
|
+
explicitEmptyIdentity.has('agent.id')) {
|
|
716
|
+
agent.id = '';
|
|
717
|
+
}
|
|
718
|
+
if ((frame.agent?.name === null || frame.agent?.name === undefined) &&
|
|
719
|
+
explicitEmptyIdentity.has('agent.name')) {
|
|
720
|
+
agent.name = '';
|
|
721
|
+
}
|
|
722
|
+
if ((frame.agent?.bio === null || frame.agent?.bio === undefined) &&
|
|
723
|
+
explicitEmptyIdentity.has('agent.bio')) {
|
|
724
|
+
agent.bio = '';
|
|
725
|
+
}
|
|
726
|
+
const onStep = runLog
|
|
727
|
+
? (step) => {
|
|
728
|
+
if (clientGone) {
|
|
729
|
+
return Promise.reject(new Error('client gone'));
|
|
730
|
+
}
|
|
731
|
+
return new Promise((resolve, reject) => {
|
|
732
|
+
const callId = String(calls++);
|
|
733
|
+
pendingRunLog.set(callId, { resolve, reject });
|
|
734
|
+
events.push({ type: 'run-log-append', callId, payload: step });
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
: undefined;
|
|
508
738
|
const context = {
|
|
739
|
+
runId: frame.runId || undefined,
|
|
740
|
+
resume: resuming,
|
|
741
|
+
recovery: startPayload.resolutions ?? undefined,
|
|
742
|
+
boot: isEngineBoot(runLog?.boot) ? runLog.boot : undefined,
|
|
743
|
+
onStep,
|
|
744
|
+
requestDigestKey,
|
|
745
|
+
hostAppendTimeoutMs: runLog?.hostAppendTimeoutMs,
|
|
509
746
|
model: frame.model ?? '',
|
|
510
|
-
agent
|
|
511
|
-
cacheKey: frame.cacheKey ?? undefined,
|
|
512
|
-
thinkingDefault: frame.thinkingDefault ?? undefined,
|
|
747
|
+
agent,
|
|
748
|
+
cacheKey: frame.cacheKey ?? (explicitEmptyIdentity.has('cacheKey') ? '' : undefined),
|
|
749
|
+
thinkingDefault: frame.thinkingDefault ?? (explicitEmptyIdentity.has('thinkingDefault') ? '' : undefined),
|
|
513
750
|
generationParams: frame.generationParams ?? undefined,
|
|
514
751
|
responseFormat: frame.responseFormat ?? undefined,
|
|
515
752
|
captureInferenceCalls: frame.captureInferenceCalls ?? undefined,
|
|
@@ -546,7 +783,7 @@ function completion(harness) {
|
|
|
546
783
|
approve: (call) => new Promise((resolve) => {
|
|
547
784
|
const callId = String(calls++);
|
|
548
785
|
pending.set(callId, resolve);
|
|
549
|
-
|
|
786
|
+
const frame = {
|
|
550
787
|
type: 'approval-ask',
|
|
551
788
|
callId,
|
|
552
789
|
name: call.name,
|
|
@@ -555,7 +792,11 @@ function completion(harness) {
|
|
|
555
792
|
effect: call.effect,
|
|
556
793
|
intent: call.intent ?? undefined,
|
|
557
794
|
display: call.display ?? undefined
|
|
558
|
-
}
|
|
795
|
+
};
|
|
796
|
+
if (call.callId !== undefined || call.round !== undefined) {
|
|
797
|
+
frame.payload = { callId: call.callId, round: call.round };
|
|
798
|
+
}
|
|
799
|
+
events.push(frame);
|
|
559
800
|
}),
|
|
560
801
|
attach: async (input) => {
|
|
561
802
|
const staged = await stageFile('attach', input.bytes);
|
|
@@ -613,19 +854,62 @@ function completion(harness) {
|
|
|
613
854
|
});
|
|
614
855
|
})
|
|
615
856
|
};
|
|
857
|
+
if (resuming) {
|
|
858
|
+
for (const key of [
|
|
859
|
+
'model',
|
|
860
|
+
'agent',
|
|
861
|
+
'messages',
|
|
862
|
+
'cacheKey',
|
|
863
|
+
'thinkingDefault',
|
|
864
|
+
'generationParams',
|
|
865
|
+
'responseFormat'
|
|
866
|
+
]) {
|
|
867
|
+
const value = frame[key];
|
|
868
|
+
const explicitEmpty = (key === 'model' &&
|
|
869
|
+
(frame.model === null || frame.model === undefined) &&
|
|
870
|
+
explicitEmptyIdentity.has('model')) ||
|
|
871
|
+
(key === 'cacheKey' &&
|
|
872
|
+
(frame.cacheKey === null || frame.cacheKey === undefined) &&
|
|
873
|
+
explicitEmptyIdentity.has('cacheKey')) ||
|
|
874
|
+
(key === 'thinkingDefault' &&
|
|
875
|
+
(frame.thinkingDefault === null || frame.thinkingDefault === undefined) &&
|
|
876
|
+
explicitEmptyIdentity.has('thinkingDefault'));
|
|
877
|
+
if ((value === null || value === undefined || value === '') && !explicitEmpty) {
|
|
878
|
+
const mutableContext = context;
|
|
879
|
+
delete mutableContext[key];
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
}
|
|
616
883
|
void (async () => {
|
|
617
884
|
let produced = 0;
|
|
618
885
|
let frames = 0;
|
|
886
|
+
const textIdentity = {};
|
|
619
887
|
const text = new TextCoalescer((type, merged) => {
|
|
620
888
|
frames++;
|
|
621
|
-
return events.push({ type, text: merged });
|
|
889
|
+
return events.push({ type, text: merged, ...textIdentity });
|
|
622
890
|
}, { cap: TEXT_COALESCE_CAP, holdMs: TEXT_COALESCE_MS });
|
|
623
891
|
try {
|
|
892
|
+
if (runLog && !requestDigestKey) {
|
|
893
|
+
throw new Error('The host did not provide a valid run-log digest key');
|
|
894
|
+
}
|
|
895
|
+
if (runLog?.boot &&
|
|
896
|
+
(!isEngineBoot(runLog.boot) ||
|
|
897
|
+
(runLog.boot.metadata !== null && runLog.boot.metadata.runId !== frame.runId))) {
|
|
898
|
+
throw new Error('The host did not provide a valid run-log boot');
|
|
899
|
+
}
|
|
900
|
+
if (resuming && !onStep && !(await harness.capability?.())?.completionRecovery) {
|
|
901
|
+
throw new Error('This peer does not support persistent completion recovery');
|
|
902
|
+
}
|
|
624
903
|
for await (const event of runFrame(harness, frame, context)) {
|
|
625
904
|
produced++;
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
905
|
+
if (!startPayload.recoveryEvents &&
|
|
906
|
+
['run-started', 'run-resumed', 'round-reset', 'recovery-required'].includes(event.type)) {
|
|
907
|
+
continue;
|
|
908
|
+
}
|
|
909
|
+
const wire = !startPayload.recoveryEvents && event.type === 'paused'
|
|
910
|
+
? { type: 'aborted' }
|
|
911
|
+
: toWire(event);
|
|
912
|
+
if (await accumulateTextFrame(wire, textIdentity, text)) {
|
|
629
913
|
continue;
|
|
630
914
|
}
|
|
631
915
|
await text.flush();
|
|
@@ -650,6 +934,18 @@ function completion(harness) {
|
|
|
650
934
|
hlog('wire handed off');
|
|
651
935
|
};
|
|
652
936
|
}
|
|
937
|
+
async function accumulateTextFrame(wire, identity, text) {
|
|
938
|
+
if ((wire.type !== 'content' && wire.type !== 'thinking') || !wire.text) {
|
|
939
|
+
return false;
|
|
940
|
+
}
|
|
941
|
+
if (identity.runId !== wire.runId || identity.round !== wire.round) {
|
|
942
|
+
await text.flush();
|
|
943
|
+
}
|
|
944
|
+
identity.runId = wire.runId;
|
|
945
|
+
identity.round = wire.round;
|
|
946
|
+
await text.add(wire.type, wire.text);
|
|
947
|
+
return true;
|
|
948
|
+
}
|
|
653
949
|
function downloadStream(harness, req) {
|
|
654
950
|
const controller = new AbortController();
|
|
655
951
|
const stream = new Readable({
|
package/dist-lib/lib/spawn.js
CHANGED
|
@@ -47,7 +47,8 @@ export function spawnHarness(opts) {
|
|
|
47
47
|
});
|
|
48
48
|
return connectHarness(async () => {
|
|
49
49
|
const { default: Sidecar } = await import('bare-sidecar');
|
|
50
|
-
const
|
|
50
|
+
const stowHost = await import('bare-stow/host');
|
|
51
|
+
const IPC = Reflect.get(stowHost, 'IPC');
|
|
51
52
|
const sidecar = new Sidecar(opts.entry, [
|
|
52
53
|
opts.skillsDir ?? '',
|
|
53
54
|
JSON.stringify(opts.sdkStorage),
|
|
@@ -63,7 +64,7 @@ export function spawnHarness(opts) {
|
|
|
63
64
|
]);
|
|
64
65
|
sidecar.stdout.on('data', (data) => logger?.info('harness', data.toString().trimEnd()));
|
|
65
66
|
sidecar.stderr.on('data', (data) => logger?.warn('harness', data.toString().trimEnd()));
|
|
66
|
-
const ipc =
|
|
67
|
+
const ipc = new IPC(sidecar);
|
|
67
68
|
const died = new Promise((resolve) => {
|
|
68
69
|
sidecar.once('exit', (code) => resolve(`harness exited (${code}) before ready`));
|
|
69
70
|
});
|
|
@@ -1,21 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
readonly label: string;
|
|
3
|
-
readonly description?: string;
|
|
4
|
-
readonly iconEmoji?: string;
|
|
5
|
-
}
|
|
6
|
-
export type ToolExecutionOutcome = {
|
|
7
|
-
readonly kind: 'success';
|
|
8
|
-
} | {
|
|
9
|
-
readonly kind: 'error';
|
|
10
|
-
readonly message?: string;
|
|
11
|
-
readonly error?: unknown;
|
|
12
|
-
} | {
|
|
13
|
-
readonly kind: 'denied';
|
|
14
|
-
readonly reason?: string;
|
|
15
|
-
} | {
|
|
16
|
-
readonly kind: 'blocked';
|
|
17
|
-
readonly reason?: string;
|
|
18
|
-
} | {
|
|
19
|
-
readonly kind: 'guidance';
|
|
20
|
-
readonly message: string;
|
|
21
|
-
};
|
|
1
|
+
export type { ToolCallDisplay, ToolExecutionOutcome } from './machine/index.ts';
|
|
@@ -7,6 +7,7 @@ import type { CredentialStoreFn } from './skills/auth-resolver.ts';
|
|
|
7
7
|
import { type SkillSettingsFn } from './skills/skill-settings.ts';
|
|
8
8
|
export type { ExecResult, KillProcess, SpawnFn } from './exec/runner.ts';
|
|
9
9
|
export interface ExecToolOptions {
|
|
10
|
+
readonly policyVersion?: string;
|
|
10
11
|
readonly spawn?: SpawnFn;
|
|
11
12
|
readonly killProcess?: KillProcess;
|
|
12
13
|
readonly loadPyodide?: LoadPyodideFn;
|
|
@@ -23,4 +24,4 @@ export interface ScriptRun {
|
|
|
23
24
|
trusted: boolean;
|
|
24
25
|
}
|
|
25
26
|
export declare function resolveScriptRun(rawArgs: Record<string, unknown>, skillsDir: string | undefined): ScriptRun | ExecError | null;
|
|
26
|
-
export declare function createExecTool({ spawn, killProcess, loadPyodide, disablePyodide, pythonNetwork, credentialStore, skillSettings, realpath, deniedRoots, skillsDir }?: ExecToolOptions): ToolDefinition;
|
|
27
|
+
export declare function createExecTool({ policyVersion, spawn, killProcess, loadPyodide, disablePyodide, pythonNetwork, credentialStore, skillSettings, realpath, deniedRoots, skillsDir }?: ExecToolOptions): ToolDefinition;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { createHash } from 'crypto';
|
|
4
|
+
import b4a from 'b4a';
|
|
3
5
|
import { AbortedError } from '../helpers/race-abort.js';
|
|
4
6
|
import { checkPdfBuildSource, checkBareLengthArgs, checkPptxBuildSource, checkPythonSource, checkUnstagedRead, createPythonAdapter, isPythonLanguage, parseInputs, parseOutputs, parsePackages, parseWorkdir, pinned, runsThroughPyodide, sandboxInstallError, unwrapPythonSource } from './exec/adapters/python/python-adapter.js';
|
|
5
7
|
import { pythonCreateEffect } from './exec/adapters/python/create-effect.js';
|
|
@@ -223,7 +225,39 @@ export function resolveScriptRun(rawArgs, skillsDir) {
|
|
|
223
225
|
}
|
|
224
226
|
let source;
|
|
225
227
|
try {
|
|
226
|
-
|
|
228
|
+
const scriptPath = path.join(skillsDir, skill, script);
|
|
229
|
+
const regularPath = () => {
|
|
230
|
+
let current = skillsDir;
|
|
231
|
+
for (const segment of segments) {
|
|
232
|
+
current = path.join(current, segment);
|
|
233
|
+
if (fs.lstatSync(current).isSymbolicLink()) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return true;
|
|
238
|
+
};
|
|
239
|
+
if (!regularPath()) {
|
|
240
|
+
return { error: `script not found in skill ${skill}: ${script}` };
|
|
241
|
+
}
|
|
242
|
+
const before = fs.statSync(scriptPath);
|
|
243
|
+
if (!before.isFile()) {
|
|
244
|
+
return { error: `script not found in skill ${skill}: ${script}` };
|
|
245
|
+
}
|
|
246
|
+
const fd = fs.openSync(scriptPath, fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW ?? 0));
|
|
247
|
+
try {
|
|
248
|
+
const opened = fs.fstatSync(fd);
|
|
249
|
+
if (!opened.isFile() || opened.dev !== before.dev || opened.ino !== before.ino) {
|
|
250
|
+
return { error: `script not found in skill ${skill}: ${script}` };
|
|
251
|
+
}
|
|
252
|
+
source = readScriptSource(fd);
|
|
253
|
+
const current = fs.statSync(scriptPath);
|
|
254
|
+
if (!regularPath() || current.dev !== opened.dev || current.ino !== opened.ino) {
|
|
255
|
+
return { error: `script not found in skill ${skill}: ${script}` };
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
finally {
|
|
259
|
+
fs.closeSync(fd);
|
|
260
|
+
}
|
|
227
261
|
}
|
|
228
262
|
catch {
|
|
229
263
|
return { error: `script not found in skill ${skill}: ${script}` };
|
|
@@ -236,6 +270,18 @@ export function resolveScriptRun(rawArgs, skillsDir) {
|
|
|
236
270
|
const command = `import sys\nsys.argv = ${argv}\n${source}`;
|
|
237
271
|
return { args: { ...rawArgs, language: 'python', command, scriptArgs }, trusted: true };
|
|
238
272
|
}
|
|
273
|
+
function readScriptSource(fd) {
|
|
274
|
+
const chunks = [];
|
|
275
|
+
while (true) {
|
|
276
|
+
const buffer = b4a.allocUnsafe(8192);
|
|
277
|
+
const length = fs.readSync(fd, buffer);
|
|
278
|
+
if (length === 0) {
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
chunks.push(buffer.subarray(0, length));
|
|
282
|
+
}
|
|
283
|
+
return b4a.toString(b4a.concat(chunks), 'utf8');
|
|
284
|
+
}
|
|
239
285
|
const SCRIPT_FILE_ARG = /^[\w][\w.-]*\.(pdf|txt|md|csv|docx|xlsx|pptx|png|jpe?g)$/i;
|
|
240
286
|
function stagingGap(rawArgs, scriptArgs) {
|
|
241
287
|
const inputs = parseInputs(rawArgs.inputs);
|
|
@@ -301,11 +347,20 @@ async function skillsEnv(skillSettings, ctx) {
|
|
|
301
347
|
}
|
|
302
348
|
return Object.keys(env).length > 0 ? env : undefined;
|
|
303
349
|
}
|
|
304
|
-
export function createExecTool({ spawn, killProcess, loadPyodide, disablePyodide = false, pythonNetwork = !disablePyodide && pythonReachesNetwork(), credentialStore, skillSettings, realpath = defaultRealpath, deniedRoots, skillsDir } = {}) {
|
|
350
|
+
export function createExecTool({ policyVersion, spawn, killProcess, loadPyodide, disablePyodide = false, pythonNetwork = !disablePyodide && pythonReachesNetwork(), credentialStore, skillSettings, realpath = defaultRealpath, deniedRoots, skillsDir } = {}) {
|
|
305
351
|
const adapters = [createPythonAdapter(disablePyodide, loadPyodide, pythonNetwork)];
|
|
306
352
|
const fallback = createShellAdapter({ spawn, killProcess, loadRuntime: bareRuntime });
|
|
307
353
|
return {
|
|
308
354
|
name: 'exec',
|
|
355
|
+
policyVersion: createHash('sha256')
|
|
356
|
+
.update(JSON.stringify({
|
|
357
|
+
version: 1,
|
|
358
|
+
policyVersion: policyVersion ?? null,
|
|
359
|
+
disablePyodide,
|
|
360
|
+
deniedRoots: [...(deniedRoots ?? [])].sort(),
|
|
361
|
+
skillsDir: skillsDir ?? null
|
|
362
|
+
}))
|
|
363
|
+
.digest('hex'),
|
|
309
364
|
toolset: 'exec',
|
|
310
365
|
description: "Execute a shell command on the user's device, or Python via in-process Pyodide. " +
|
|
311
366
|
'One program per call: chaining, pipes, redirection and shell expansion are rejected. ' +
|
|
@@ -110,7 +110,7 @@ export function createDiffusionRuntime({ loadSdk, onProgress, onLoaded, onBefore
|
|
|
110
110
|
}
|
|
111
111
|
});
|
|
112
112
|
try {
|
|
113
|
-
const modelId = await Promise.race([loads.track(pending), stall.promise]);
|
|
113
|
+
const modelId = await Promise.race([loads.track(pending, sdk), stall.promise]);
|
|
114
114
|
onLoaded?.(diffusionProgressName(set));
|
|
115
115
|
return { modelId, prediction: set.prediction };
|
|
116
116
|
}
|
|
@@ -118,7 +118,7 @@ export function createMusicRuntime({ loadSdk, onProgress, onBeforeLoad, loads =
|
|
|
118
118
|
modelType: 'audiogen',
|
|
119
119
|
modelConfig,
|
|
120
120
|
onProgress: onProgress && ((progress) => onProgress(musicProgressName(stages.dit), progress))
|
|
121
|
-
}));
|
|
121
|
+
}), sdk);
|
|
122
122
|
return { modelId };
|
|
123
123
|
})().catch((err) => {
|
|
124
124
|
loading = null;
|
|
@@ -12,9 +12,10 @@ export type FetchFn = (url: URL, init: FetchInit) => Promise<{
|
|
|
12
12
|
}>;
|
|
13
13
|
export type { CredentialAllowList, CredentialAllowListFn, CredentialRecord, CredentialStoreFn, CredentialStoreValue } from './skills/auth-resolver.ts';
|
|
14
14
|
export interface HttpRequestToolOptions {
|
|
15
|
+
policyVersion?: string;
|
|
15
16
|
fetch?: FetchFn;
|
|
16
17
|
credentialStore?: CredentialStoreFn;
|
|
17
18
|
credentialAllowList?: CredentialAllowListFn;
|
|
18
19
|
resolveHost?: HostResolver;
|
|
19
20
|
}
|
|
20
|
-
export declare function createHttpRequestTool({ fetch: fetchImpl, credentialStore, credentialAllowList, resolveHost }?: HttpRequestToolOptions): ToolDefinition;
|
|
21
|
+
export declare function createHttpRequestTool({ policyVersion, fetch: fetchImpl, credentialStore, credentialAllowList, resolveHost }?: HttpRequestToolOptions): ToolDefinition;
|
|
@@ -10,9 +10,10 @@ import { parseAuth, resolveBearerHeader, resolveRedirectBearerHeader } from './s
|
|
|
10
10
|
import { recordCredentialHealth } from './skills/credential-health.js';
|
|
11
11
|
import { resolveOutboundUrl } from './url-guard.js';
|
|
12
12
|
const MAX_REDIRECTS = 5;
|
|
13
|
-
export function createHttpRequestTool({ fetch: fetchImpl, credentialStore, credentialAllowList, resolveHost = lookupHost } = {}) {
|
|
13
|
+
export function createHttpRequestTool({ policyVersion, fetch: fetchImpl, credentialStore, credentialAllowList, resolveHost = lookupHost } = {}) {
|
|
14
14
|
return {
|
|
15
15
|
name: 'http_request',
|
|
16
|
+
policyVersion,
|
|
16
17
|
toolset: 'http-request',
|
|
17
18
|
description: 'Make an outbound HTTP or HTTPS request and return the response status and body (truncated) as text. Authorization/Cookie headers are stripped before sending. Stored skill credentials are attached automatically for their allow-listed hosts; `auth` is only needed to force a specific credential key. For APIs and text responses only: a URL that serves a file — PDF, .docx, .xlsx, an image, any binary — comes back as truncated garbage here. Use web_fetch for those; it downloads and attaches the file.',
|
|
18
19
|
parameters: {
|
|
@@ -3,8 +3,9 @@ import { AbortController } from 'bare-abort-controller';
|
|
|
3
3
|
import { MCP_CALL_TOOL_NAME } from '../capabilities/tool-names.js';
|
|
4
4
|
import { lookupHost } from '../dns-lookup.js';
|
|
5
5
|
import { AbortedError } from '../helpers/race-abort.js';
|
|
6
|
+
import { writeResult } from '../helpers/run-outcome.js';
|
|
6
7
|
import { isRedirectStatus, parseObjectArg } from './http-request/request.js';
|
|
7
|
-
import { cacheSession, deleteSession, establishSession, flattenMcpResponse, getSession, isNotification, needsSession, normalizeMethod, post, readBody, sessionKey, TIMEOUT_MS } from './mcp/protocol.js';
|
|
8
|
+
import { cacheSession, deleteSession, establishSession, flattenMcpResponse, getSession, isMetadataMethod, isNotification, needsSession, normalizeMethod, post, readBody, sessionKey, TIMEOUT_MS } from './mcp/protocol.js';
|
|
8
9
|
import { parseAuth, resolveBearerHeader } from './skills/auth-resolver.js';
|
|
9
10
|
import { recordCredentialHealth } from './skills/credential-health.js';
|
|
10
11
|
import { resolveOutboundUrl } from './url-guard.js';
|
|
@@ -75,6 +76,12 @@ export function createMcpCallTool({ fetch: fetchImpl, credentialStore, credentia
|
|
|
75
76
|
return null;
|
|
76
77
|
}
|
|
77
78
|
},
|
|
79
|
+
landedWrite(args, output) {
|
|
80
|
+
if (isMetadataMethod(args.method)) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
return writeResult(output);
|
|
84
|
+
},
|
|
78
85
|
async execute(args, ctx) {
|
|
79
86
|
const rawParams = parseMcpParams(args.params);
|
|
80
87
|
if (!rawParams.ok) {
|
|
@@ -12,6 +12,7 @@ export type BuilderOutcome = {
|
|
|
12
12
|
export interface OperationBuilder {
|
|
13
13
|
build: (args: Record<string, unknown>) => BuilderOutcome;
|
|
14
14
|
}
|
|
15
|
+
export declare const BUILDER_POLICY_VERSION = 1;
|
|
15
16
|
export declare const BUILDER_NAMES: readonly ['gmail-send', 'gmail-draft', 'gmail-get', 'calendar-meet-event', 'calendar-add-meet', 'docs-create', 'docs-append-text', 'sheets-create', 'sheets-write-values', 'sheets-append-values', 'drive-create-folder', 'drive-trash', 'notion-create-page', 'notion-insert-content'];
|
|
16
17
|
export type BuilderName = (typeof BUILDER_NAMES)[number];
|
|
17
18
|
export declare const BUILDERS: Record<BuilderName, OperationBuilder>;
|
|
@@ -2,6 +2,7 @@ import { randomBytes } from 'crypto';
|
|
|
2
2
|
import b4a from 'b4a';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { buildGmailMessage, GmailEnvelopeSchema } from './gmail-message.js';
|
|
5
|
+
export const BUILDER_POLICY_VERSION = 1;
|
|
5
6
|
export const BUILDER_NAMES = [
|
|
6
7
|
'gmail-send',
|
|
7
8
|
'gmail-draft',
|