@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
|
@@ -9,7 +9,12 @@ import type { DeleteModelSummary } from './models/model-delete.ts';
|
|
|
9
9
|
import type { CopyBaseResult, DeleteOverlayResult, ManagedSkill, SkillFileContent } from './tools/skills/overlay-crud.ts';
|
|
10
10
|
import type { SkillSettingEntry } from './tools/skills/skill-settings.ts';
|
|
11
11
|
export declare const HARNESS_DIED = "HARNESS_DIED";
|
|
12
|
-
export
|
|
12
|
+
export interface ConnectOptions {
|
|
13
|
+
pauseGraceMs?: number;
|
|
14
|
+
runLogReleaseTimeoutMs?: number;
|
|
15
|
+
}
|
|
16
|
+
export type { HostRunLog, HostRunLogLease, RunRecord } from './contract-types.ts';
|
|
17
|
+
export declare function connectHarness(transport: Transport, options?: ConnectOptions): RemoteHarness;
|
|
13
18
|
export declare function readEmbeddingDeviceResponse(response: unknown): EmbedDevice;
|
|
14
19
|
export declare class RemoteHarness extends EventEmitter implements HarnessContract {
|
|
15
20
|
on: (event: 'model' | 'status', listener: (...args: never[]) => void) => this;
|
|
@@ -18,11 +23,13 @@ export declare class RemoteHarness extends EventEmitter implements HarnessContra
|
|
|
18
23
|
private _session;
|
|
19
24
|
private _opening;
|
|
20
25
|
private _closed;
|
|
26
|
+
private readonly _pauseGraceMs;
|
|
27
|
+
private readonly _runLogReleaseTimeoutMs;
|
|
21
28
|
private _customModels;
|
|
22
|
-
constructor(transport: Transport);
|
|
29
|
+
constructor(transport: Transport, options?: ConnectOptions);
|
|
23
30
|
private _ensure;
|
|
24
31
|
private _open;
|
|
25
|
-
completion(context: CompletionContext): AsyncIterable<HarnessEvent>;
|
|
32
|
+
completion(context: CompletionContext | import('./contract-types.ts').ResumeCompletionContext): AsyncIterable<HarnessEvent>;
|
|
26
33
|
invoke(context: InvokeContext): AsyncIterable<HarnessEvent>;
|
|
27
34
|
private _run;
|
|
28
35
|
download(context: DownloadContext): AsyncIterable<HarnessEvent>;
|
package/dist-lib/lib/connect.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import b4a from 'b4a';
|
|
2
|
+
import { randomBytes } from 'crypto';
|
|
1
3
|
import EventEmitter from 'events';
|
|
2
4
|
import fs from 'fs';
|
|
3
5
|
import { z } from 'zod';
|
|
@@ -6,6 +8,7 @@ import { harnessClient } from '../spec/calls.js';
|
|
|
6
8
|
import HRPC from '../spec/hrpc/index.js';
|
|
7
9
|
import { unsupportedKvCacheDeletion } from './capabilities/kv-cache.js';
|
|
8
10
|
import { readModelSourcePreview } from './capabilities/preview-model-source.js';
|
|
11
|
+
import { validateEngineBoot } from './run-log-protocol.js';
|
|
9
12
|
import { hlog } from './log.js';
|
|
10
13
|
import { assertEmbedDevice } from './models/embed-config.js';
|
|
11
14
|
import { addonTaskType } from './models/model-task.js';
|
|
@@ -17,8 +20,9 @@ import { SKILL_STATE } from './tools/skills/skill-state.js';
|
|
|
17
20
|
import { asToolset } from './tools/toolsets.js';
|
|
18
21
|
import { fromDownloadWire, fromWire, unpackVectors } from './wire.js';
|
|
19
22
|
export const HARNESS_DIED = 'HARNESS_DIED';
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
const PAUSE_GRACE_MS = 10_000;
|
|
24
|
+
export function connectHarness(transport, options = {}) {
|
|
25
|
+
return new RemoteHarness(transport, options);
|
|
22
26
|
}
|
|
23
27
|
export function readEmbeddingDeviceResponse(response) {
|
|
24
28
|
const device = isRecord(response) ? response.device : undefined;
|
|
@@ -33,10 +37,14 @@ export class RemoteHarness extends EventEmitter {
|
|
|
33
37
|
_session = null;
|
|
34
38
|
_opening = null;
|
|
35
39
|
_closed = false;
|
|
40
|
+
_pauseGraceMs;
|
|
41
|
+
_runLogReleaseTimeoutMs;
|
|
36
42
|
_customModels = [];
|
|
37
|
-
constructor(transport) {
|
|
43
|
+
constructor(transport, options = {}) {
|
|
38
44
|
super();
|
|
39
45
|
this._transport = transport;
|
|
46
|
+
this._pauseGraceMs = options.pauseGraceMs ?? PAUSE_GRACE_MS;
|
|
47
|
+
this._runLogReleaseTimeoutMs = options.runLogReleaseTimeoutMs ?? 5000;
|
|
40
48
|
}
|
|
41
49
|
_ensure() {
|
|
42
50
|
if (this._closed) {
|
|
@@ -97,16 +105,32 @@ export class RemoteHarness extends EventEmitter {
|
|
|
97
105
|
return session;
|
|
98
106
|
}
|
|
99
107
|
async *completion(context) {
|
|
108
|
+
const runId = context.runId ?? b4a.toHex(randomBytes(16));
|
|
109
|
+
if (context.signal?.aborted) {
|
|
110
|
+
yield { type: 'aborted', runId };
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const explicitEmptyIdentity = explicitEmptyIdentityFields(context);
|
|
114
|
+
const payload = {
|
|
115
|
+
resume: context.resume === true,
|
|
116
|
+
recoveryEvents: true,
|
|
117
|
+
resolutions: context.recovery
|
|
118
|
+
};
|
|
119
|
+
if (explicitEmptyIdentity.length) {
|
|
120
|
+
payload.explicitEmptyIdentity = explicitEmptyIdentity;
|
|
121
|
+
}
|
|
100
122
|
yield* this._run({
|
|
101
123
|
type: 'start',
|
|
124
|
+
runId,
|
|
125
|
+
payload,
|
|
102
126
|
model: context.model,
|
|
103
|
-
agent: knobs(context.agent),
|
|
127
|
+
agent: context.agent ? knobs(context.agent) : undefined,
|
|
104
128
|
cacheKey: context.cacheKey,
|
|
105
129
|
thinkingDefault: context.thinkingDefault,
|
|
106
130
|
generationParams: context.generationParams,
|
|
107
131
|
responseFormat: context.responseFormat,
|
|
108
132
|
captureInferenceCalls: context.captureInferenceCalls,
|
|
109
|
-
messages: context.messages
|
|
133
|
+
messages: context.messages?.map(({ role, content, attachments }) => ({
|
|
110
134
|
role,
|
|
111
135
|
content,
|
|
112
136
|
attachments: attachments?.map(({ path: file }) => ({ path: file }))
|
|
@@ -115,7 +139,7 @@ export class RemoteHarness extends EventEmitter {
|
|
|
115
139
|
grantedDirs: context.grantedDirs,
|
|
116
140
|
grantedDrives: context.grantedDrives,
|
|
117
141
|
grantedWriteDirs: context.grantedWriteDirs
|
|
118
|
-
}, context);
|
|
142
|
+
}, { ...context, runId });
|
|
119
143
|
}
|
|
120
144
|
async *invoke(context) {
|
|
121
145
|
const agent = context.agent ?? {};
|
|
@@ -136,8 +160,62 @@ export class RemoteHarness extends EventEmitter {
|
|
|
136
160
|
});
|
|
137
161
|
}
|
|
138
162
|
async *_run(open, context) {
|
|
139
|
-
|
|
163
|
+
if (context.signal?.aborted) {
|
|
164
|
+
yield { type: 'aborted', runId: context.runId ?? open.runId ?? undefined };
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
let session;
|
|
168
|
+
try {
|
|
169
|
+
session = await awaitWithAbort(this._ensure(), context.signal);
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
if (context.signal?.aborted) {
|
|
173
|
+
yield { type: 'aborted', runId: context.runId ?? open.runId ?? undefined };
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
throw err;
|
|
177
|
+
}
|
|
178
|
+
const { client } = session;
|
|
179
|
+
let pausable = false;
|
|
180
|
+
const peer = this.capability().then((c) => {
|
|
181
|
+
pausable = c.hostRunLog === true && c.hostRunLogVersion === 1;
|
|
182
|
+
return c;
|
|
183
|
+
}, () => null);
|
|
184
|
+
const canResume = async () => {
|
|
185
|
+
const c = await peer;
|
|
186
|
+
return context.runLog
|
|
187
|
+
? c?.hostRunLog === true && c.hostRunLogVersion === 1
|
|
188
|
+
: c?.completionRecovery === true;
|
|
189
|
+
};
|
|
190
|
+
let capability;
|
|
191
|
+
try {
|
|
192
|
+
capability = await awaitWithAbort(peer, context.signal);
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
if (context.signal?.aborted) {
|
|
196
|
+
yield { type: 'aborted', runId: context.runId ?? open.runId ?? undefined };
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
throw err;
|
|
200
|
+
}
|
|
201
|
+
if (context.runLog && (capability?.hostRunLog !== true || capability.hostRunLogVersion !== 1)) {
|
|
202
|
+
throw new Error('This peer does not support a host-owned run log');
|
|
203
|
+
}
|
|
204
|
+
if (context.resume && !(await canResume())) {
|
|
205
|
+
throw new Error('This peer does not support persistent completion recovery');
|
|
206
|
+
}
|
|
207
|
+
let activeRunId = context.runId ?? open.runId ?? undefined;
|
|
208
|
+
if (context.signal?.aborted) {
|
|
209
|
+
yield { type: 'aborted', runId: activeRunId };
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const leasedRunId = context.runLog ? activeRunId : undefined;
|
|
213
|
+
if (context.runLog && !leasedRunId) {
|
|
214
|
+
throw new Error('host-owned run log requires a run id');
|
|
215
|
+
}
|
|
216
|
+
let hostLease;
|
|
140
217
|
let duplex = null;
|
|
218
|
+
let startFrame = open;
|
|
141
219
|
let emittedAborted = false;
|
|
142
220
|
const staged = [];
|
|
143
221
|
let closed = false;
|
|
@@ -147,36 +225,67 @@ export class RemoteHarness extends EventEmitter {
|
|
|
147
225
|
void fs.promises.unlink(file).catch(noop);
|
|
148
226
|
}
|
|
149
227
|
};
|
|
150
|
-
|
|
228
|
+
let pauseTimer;
|
|
229
|
+
let started = false;
|
|
230
|
+
const onAbort = () => {
|
|
231
|
+
if (!pausable || !duplex || !started) {
|
|
232
|
+
return duplex?.destroy();
|
|
233
|
+
}
|
|
234
|
+
duplex.write({ type: 'pause' });
|
|
235
|
+
pauseTimer = setTimeout(() => duplex?.destroy(), this._pauseGraceMs);
|
|
236
|
+
};
|
|
151
237
|
try {
|
|
238
|
+
if (context.runLog) {
|
|
239
|
+
const leaseResult = await acquireHostRunLogLease(context.runLog, leasedRunId, context.signal);
|
|
240
|
+
if (leaseResult === null) {
|
|
241
|
+
yield { type: 'aborted', runId: activeRunId };
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
hostLease = leaseResult;
|
|
245
|
+
}
|
|
246
|
+
if (hostLease) {
|
|
247
|
+
validateHostRunLogLease(hostLease, leasedRunId);
|
|
248
|
+
const payload = isRecord(open.payload) ? { ...open.payload } : {};
|
|
249
|
+
payload.resume =
|
|
250
|
+
context.resume === true ||
|
|
251
|
+
(hostLease.boot !== undefined && hostLease.boot.metadata !== null);
|
|
252
|
+
payload.runLog = {
|
|
253
|
+
boot: hostLease.boot ?? null,
|
|
254
|
+
digestKey: b4a.toHex(hostLease.digestKey),
|
|
255
|
+
hostAppendTimeoutMs: context.hostAppendTimeoutMs
|
|
256
|
+
};
|
|
257
|
+
startFrame = { ...open, payload };
|
|
258
|
+
}
|
|
259
|
+
if (context.signal?.aborted) {
|
|
260
|
+
yield { type: 'aborted', runId: activeRunId };
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
context.signal?.addEventListener?.('abort', onAbort, { once: true });
|
|
152
264
|
duplex = client.completion();
|
|
153
|
-
duplex.write(open);
|
|
154
265
|
if (context.signal?.aborted) {
|
|
155
266
|
duplex.destroy();
|
|
156
|
-
yield { type: 'aborted' };
|
|
267
|
+
yield { type: 'aborted', runId: activeRunId };
|
|
157
268
|
return;
|
|
158
269
|
}
|
|
159
|
-
|
|
270
|
+
duplex.write(startFrame);
|
|
271
|
+
started = true;
|
|
160
272
|
hlog('client wire open', { model: context.model, capability: open.capability });
|
|
161
273
|
for await (const event of frames(duplex)) {
|
|
162
274
|
received++;
|
|
163
275
|
if (event.type !== 'content' && event.type !== 'thinking') {
|
|
164
276
|
hlog('client frame', { type: event.type, n: received });
|
|
165
277
|
}
|
|
278
|
+
if (event.type === 'run-started' || event.type === 'run-resumed') {
|
|
279
|
+
activeRunId = event.runId ?? activeRunId;
|
|
280
|
+
}
|
|
166
281
|
if (event.type === 'done') {
|
|
167
282
|
break;
|
|
168
283
|
}
|
|
169
284
|
if (event.type === 'approval-ask') {
|
|
170
285
|
const callId = event.callId;
|
|
286
|
+
const approval = approvalCall(event);
|
|
171
287
|
void Promise.resolve()
|
|
172
|
-
.then(() => context.approve?.(
|
|
173
|
-
name: event.name ?? '',
|
|
174
|
-
arguments: isRecord(event.arguments) ? event.arguments : {},
|
|
175
|
-
resource: event.resource ?? null,
|
|
176
|
-
effect: event.effect === 'read' ? 'read' : 'write',
|
|
177
|
-
intent: event.intent || null,
|
|
178
|
-
display: isToolCallDisplay(event.display) ? event.display : null
|
|
179
|
-
}))
|
|
288
|
+
.then(() => context.approve?.(approval))
|
|
180
289
|
.then((approved) => {
|
|
181
290
|
if (!closed) {
|
|
182
291
|
duplex.write({ type: 'decision', callId, approved: approved === true });
|
|
@@ -248,6 +357,30 @@ export class RemoteHarness extends EventEmitter {
|
|
|
248
357
|
.catch((err) => hlog('drive reply failed', { callId, message: errorMessage(err) }));
|
|
249
358
|
continue;
|
|
250
359
|
}
|
|
360
|
+
if (event.type === 'run-log-append') {
|
|
361
|
+
const callId = event.callId;
|
|
362
|
+
void bridgeRunLog({
|
|
363
|
+
event,
|
|
364
|
+
context,
|
|
365
|
+
runId: leasedRunId,
|
|
366
|
+
generation: hostLease?.generation
|
|
367
|
+
})
|
|
368
|
+
.then((frame) => {
|
|
369
|
+
if (!closed) {
|
|
370
|
+
duplex.write({ ...frame, callId });
|
|
371
|
+
}
|
|
372
|
+
}, (err) => {
|
|
373
|
+
if (!closed) {
|
|
374
|
+
duplex.write({
|
|
375
|
+
type: 'run-log-result',
|
|
376
|
+
callId,
|
|
377
|
+
message: errorMessage(err)
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
})
|
|
381
|
+
.catch((err) => hlog('run-log reply failed', { callId, message: errorMessage(err) }));
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
251
384
|
if (event.type === 'rag-ask') {
|
|
252
385
|
const callId = event.callId;
|
|
253
386
|
void bridgeRag(event, context)
|
|
@@ -283,7 +416,7 @@ export class RemoteHarness extends EventEmitter {
|
|
|
283
416
|
continue;
|
|
284
417
|
}
|
|
285
418
|
const wire = fromWire(event);
|
|
286
|
-
if (wire.type === 'aborted') {
|
|
419
|
+
if (wire.type === 'aborted' || wire.type === 'paused') {
|
|
287
420
|
emittedAborted = true;
|
|
288
421
|
}
|
|
289
422
|
yield wire;
|
|
@@ -293,21 +426,42 @@ export class RemoteHarness extends EventEmitter {
|
|
|
293
426
|
catch (err) {
|
|
294
427
|
if (context.signal?.aborted) {
|
|
295
428
|
if (!emittedAborted) {
|
|
296
|
-
yield { type: 'aborted' };
|
|
429
|
+
yield { type: 'aborted', runId: activeRunId };
|
|
297
430
|
}
|
|
298
431
|
return;
|
|
299
432
|
}
|
|
433
|
+
if (!started) {
|
|
434
|
+
throw err;
|
|
435
|
+
}
|
|
300
436
|
throw died(`harness died mid-run: ${errorMessage(err)}`);
|
|
301
437
|
}
|
|
302
438
|
finally {
|
|
303
439
|
hlog('client run end', { received, aborted: Boolean(context.signal?.aborted) });
|
|
304
440
|
context.signal?.removeEventListener?.('abort', onAbort);
|
|
441
|
+
clearTimeout(pauseTimer);
|
|
305
442
|
duplex?.destroy();
|
|
306
443
|
closed = true;
|
|
307
444
|
reclaim();
|
|
445
|
+
if (hostLease && leasedRunId && context.runLog) {
|
|
446
|
+
let timer;
|
|
447
|
+
try {
|
|
448
|
+
await Promise.race([
|
|
449
|
+
context.runLog.release(leasedRunId, hostLease.generation),
|
|
450
|
+
new Promise((_resolve, reject) => {
|
|
451
|
+
timer = setTimeout(() => reject(new Error('host run-log release timed out')), this._runLogReleaseTimeoutMs);
|
|
452
|
+
})
|
|
453
|
+
]);
|
|
454
|
+
}
|
|
455
|
+
catch (err) {
|
|
456
|
+
hlog('host run-log release failed', { runId: leasedRunId, message: errorMessage(err) });
|
|
457
|
+
}
|
|
458
|
+
finally {
|
|
459
|
+
clearTimeout(timer);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
308
462
|
}
|
|
309
463
|
if (context.signal?.aborted && !emittedAborted) {
|
|
310
|
-
yield { type: 'aborted' };
|
|
464
|
+
yield { type: 'aborted', runId: activeRunId };
|
|
311
465
|
}
|
|
312
466
|
}
|
|
313
467
|
async *download(context) {
|
|
@@ -616,7 +770,7 @@ export class RemoteHarness extends EventEmitter {
|
|
|
616
770
|
const { client } = await this._ensure();
|
|
617
771
|
const response = await client.capability({});
|
|
618
772
|
const memoryBudget = response.memoryBudget;
|
|
619
|
-
|
|
773
|
+
const capability = {
|
|
620
774
|
capabilityProfile: response.capabilityProfile,
|
|
621
775
|
recommendedModelName: response.recommendedModelName,
|
|
622
776
|
memoryBudget: memoryBudget
|
|
@@ -629,6 +783,16 @@ export class RemoteHarness extends EventEmitter {
|
|
|
629
783
|
: undefined,
|
|
630
784
|
mobile: response.mobile === true
|
|
631
785
|
};
|
|
786
|
+
if (response.completionRecovery === true) {
|
|
787
|
+
capability.completionRecovery = true;
|
|
788
|
+
}
|
|
789
|
+
if (response.hostRunLog === true) {
|
|
790
|
+
capability.hostRunLog = true;
|
|
791
|
+
}
|
|
792
|
+
if (response.hostRunLogVersion && response.hostRunLogVersion > 0) {
|
|
793
|
+
capability.hostRunLogVersion = response.hostRunLogVersion;
|
|
794
|
+
}
|
|
795
|
+
return capability;
|
|
632
796
|
}
|
|
633
797
|
close() {
|
|
634
798
|
this._closed = true;
|
|
@@ -719,6 +883,28 @@ function knobs(agent) {
|
|
|
719
883
|
sandboxMode: agent.sandboxMode ?? undefined
|
|
720
884
|
};
|
|
721
885
|
}
|
|
886
|
+
function explicitEmptyIdentityFields(context) {
|
|
887
|
+
const fields = [];
|
|
888
|
+
if (context.model === '') {
|
|
889
|
+
fields.push('model');
|
|
890
|
+
}
|
|
891
|
+
if (context.cacheKey === '') {
|
|
892
|
+
fields.push('cacheKey');
|
|
893
|
+
}
|
|
894
|
+
if (context.thinkingDefault === '') {
|
|
895
|
+
fields.push('thinkingDefault');
|
|
896
|
+
}
|
|
897
|
+
if (context.agent?.id === '') {
|
|
898
|
+
fields.push('agent.id');
|
|
899
|
+
}
|
|
900
|
+
if (context.agent?.name === '') {
|
|
901
|
+
fields.push('agent.name');
|
|
902
|
+
}
|
|
903
|
+
if (context.agent?.bio === '') {
|
|
904
|
+
fields.push('agent.bio');
|
|
905
|
+
}
|
|
906
|
+
return fields;
|
|
907
|
+
}
|
|
722
908
|
async function bridgeAttach(event, attach) {
|
|
723
909
|
try {
|
|
724
910
|
if (!attach) {
|
|
@@ -839,6 +1025,126 @@ function answerQuestion(event, { askUser, reply }) {
|
|
|
839
1025
|
.then((answer) => reply({ type: 'question-result', callId, answer: answer ?? '' }), (err) => reply({ type: 'question-result', callId, message: errorMessage(err) }))
|
|
840
1026
|
.catch((err) => hlog('question reply failed', { callId, message: errorMessage(err) }));
|
|
841
1027
|
}
|
|
1028
|
+
async function bridgeRunLog({ event, context, runId, generation }) {
|
|
1029
|
+
if (!context.runLog || !generation) {
|
|
1030
|
+
return { type: 'run-log-result', message: 'the host does not own this run log' };
|
|
1031
|
+
}
|
|
1032
|
+
const step = event.payload;
|
|
1033
|
+
if (!isEngineStep(step)) {
|
|
1034
|
+
return { type: 'run-log-result', message: 'the worker sent an invalid run-log step' };
|
|
1035
|
+
}
|
|
1036
|
+
try {
|
|
1037
|
+
await context.runLog.append(runId ?? '', generation, step);
|
|
1038
|
+
return { type: 'run-log-result' };
|
|
1039
|
+
}
|
|
1040
|
+
catch (err) {
|
|
1041
|
+
return { type: 'run-log-result', message: errorMessage(err) };
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
function isEngineStep(value) {
|
|
1045
|
+
return (isRecord(value) &&
|
|
1046
|
+
typeof value.seq === 'number' &&
|
|
1047
|
+
Number.isSafeInteger(value.seq) &&
|
|
1048
|
+
value.seq >= 0 &&
|
|
1049
|
+
typeof value.expectedLength === 'number' &&
|
|
1050
|
+
Number.isSafeInteger(value.expectedLength) &&
|
|
1051
|
+
value.expectedLength >= 0 &&
|
|
1052
|
+
Array.isArray(value.records));
|
|
1053
|
+
}
|
|
1054
|
+
function isDigestKey(value) {
|
|
1055
|
+
return value instanceof Uint8Array && value.byteLength === 32;
|
|
1056
|
+
}
|
|
1057
|
+
function releaseLateHostLease(pending, runLog, runId) {
|
|
1058
|
+
void pending
|
|
1059
|
+
.then(async (lease) => {
|
|
1060
|
+
if (!lease || typeof lease.generation !== 'string' || !lease.generation) {
|
|
1061
|
+
throw new Error('host returned an invalid generation for an aborted run-log begin');
|
|
1062
|
+
}
|
|
1063
|
+
await runLog.release(runId, lease.generation);
|
|
1064
|
+
})
|
|
1065
|
+
.catch((err) => hlog('aborted run-log begin cleanup failed', {
|
|
1066
|
+
runId,
|
|
1067
|
+
message: errorMessage(err)
|
|
1068
|
+
}));
|
|
1069
|
+
}
|
|
1070
|
+
function validateHostRunLogLease(lease, runId) {
|
|
1071
|
+
if (typeof lease.generation !== 'string' || !lease.generation || !isDigestKey(lease.digestKey)) {
|
|
1072
|
+
throw new Error('host returned an invalid run-log lease');
|
|
1073
|
+
}
|
|
1074
|
+
if (lease.boot) {
|
|
1075
|
+
validateEngineBoot(lease.boot);
|
|
1076
|
+
}
|
|
1077
|
+
const metadata = lease.boot?.metadata;
|
|
1078
|
+
if (metadata && metadata.runId !== runId) {
|
|
1079
|
+
throw new Error('host returned a run-log boot for a different run');
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
function approvalCall(event) {
|
|
1083
|
+
const identity = isRecord(event.payload) ? event.payload : {};
|
|
1084
|
+
const approval = {
|
|
1085
|
+
name: event.name ?? '',
|
|
1086
|
+
arguments: isRecord(event.arguments) ? event.arguments : {},
|
|
1087
|
+
resource: event.resource ?? null,
|
|
1088
|
+
effect: event.effect === 'read' ? 'read' : 'write',
|
|
1089
|
+
intent: event.intent || null,
|
|
1090
|
+
display: isToolCallDisplay(event.display) ? event.display : null
|
|
1091
|
+
};
|
|
1092
|
+
if (typeof identity.callId === 'string') {
|
|
1093
|
+
approval.callId = identity.callId;
|
|
1094
|
+
}
|
|
1095
|
+
if (typeof identity.round === 'number') {
|
|
1096
|
+
approval.round = identity.round;
|
|
1097
|
+
}
|
|
1098
|
+
return approval;
|
|
1099
|
+
}
|
|
1100
|
+
async function acquireHostRunLogLease(runLog, runId, signal) {
|
|
1101
|
+
if (!runId) {
|
|
1102
|
+
throw new Error('host-owned run log requires a run id');
|
|
1103
|
+
}
|
|
1104
|
+
const pending = runLog.begin(runId);
|
|
1105
|
+
try {
|
|
1106
|
+
return await awaitWithAbort(pending, signal);
|
|
1107
|
+
}
|
|
1108
|
+
catch (err) {
|
|
1109
|
+
if (!signal?.aborted) {
|
|
1110
|
+
throw err;
|
|
1111
|
+
}
|
|
1112
|
+
releaseLateHostLease(pending, runLog, runId);
|
|
1113
|
+
return null;
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
function awaitWithAbort(promise, signal) {
|
|
1117
|
+
if (!signal)
|
|
1118
|
+
return promise;
|
|
1119
|
+
if (signal.aborted) {
|
|
1120
|
+
return Promise.reject(new Error('operation aborted'));
|
|
1121
|
+
}
|
|
1122
|
+
return new Promise((resolve, reject) => {
|
|
1123
|
+
let settled = false;
|
|
1124
|
+
const cleanup = () => signal.removeEventListener?.('abort', onAbort);
|
|
1125
|
+
const onAbort = () => {
|
|
1126
|
+
if (settled)
|
|
1127
|
+
return;
|
|
1128
|
+
settled = true;
|
|
1129
|
+
cleanup();
|
|
1130
|
+
reject(new Error('operation aborted'));
|
|
1131
|
+
};
|
|
1132
|
+
signal.addEventListener?.('abort', onAbort, { once: true });
|
|
1133
|
+
promise.then((value) => {
|
|
1134
|
+
if (settled)
|
|
1135
|
+
return;
|
|
1136
|
+
settled = true;
|
|
1137
|
+
cleanup();
|
|
1138
|
+
resolve(value);
|
|
1139
|
+
}, (error) => {
|
|
1140
|
+
if (settled)
|
|
1141
|
+
return;
|
|
1142
|
+
settled = true;
|
|
1143
|
+
cleanup();
|
|
1144
|
+
reject(error);
|
|
1145
|
+
});
|
|
1146
|
+
});
|
|
1147
|
+
}
|
|
842
1148
|
async function bridgeRag(event, context) {
|
|
843
1149
|
if (!context.ragSearch) {
|
|
844
1150
|
return {
|
|
@@ -13,7 +13,9 @@ import type { ManagedSkill, SkillFileContent } from './tools/skills/overlay-crud
|
|
|
13
13
|
import type { DriveOpFn, GrantedDrive } from './tools/fs/remote.ts';
|
|
14
14
|
import type { ResolvedSkillCatalogEntry } from './tools/skills/catalog.ts';
|
|
15
15
|
import type { InstallStep, SkillSetup } from './tools/skills/manifest.ts';
|
|
16
|
-
|
|
16
|
+
import type { EngineBoot, EngineStep, HostRunLog, HostRunLogLease, RecoveryResolution, RunRecord } from './run-log-protocol.ts';
|
|
17
|
+
export type { InstallStep, ListModelsOptions, ModelInfo, ResolvedSkillCatalogEntry, ResourceDescriptor, RunRecord, SkillSetup, ToolCatalogEntry };
|
|
18
|
+
export type { HostRunLog, HostRunLogLease };
|
|
17
19
|
export type ApprovalCall = Parameters<ApproveFn>[0];
|
|
18
20
|
export interface ChatMessage {
|
|
19
21
|
role: 'system' | 'user' | 'assistant' | 'tool';
|
|
@@ -43,6 +45,9 @@ export interface AgentKnobs {
|
|
|
43
45
|
sandboxMode?: boolean | null;
|
|
44
46
|
}
|
|
45
47
|
export interface CompletionContext {
|
|
48
|
+
runId?: string;
|
|
49
|
+
resume?: boolean;
|
|
50
|
+
recovery?: RecoveryResolution[];
|
|
46
51
|
model: string;
|
|
47
52
|
agent: AgentKnobs;
|
|
48
53
|
messages: ChatMessage[];
|
|
@@ -62,6 +67,11 @@ export interface CompletionContext {
|
|
|
62
67
|
ragSearch?: RagSearchFn;
|
|
63
68
|
progress?: ProgressFn;
|
|
64
69
|
askUser?: AskUserFn;
|
|
70
|
+
runLog?: HostRunLog;
|
|
71
|
+
boot?: EngineBoot;
|
|
72
|
+
onStep?: (step: EngineStep) => Promise<void>;
|
|
73
|
+
hostAppendTimeoutMs?: number;
|
|
74
|
+
requestDigestKey?: Uint8Array;
|
|
65
75
|
signal?: {
|
|
66
76
|
aborted?: boolean;
|
|
67
77
|
addEventListener?: (type: 'abort', fn: () => void, opts?: {
|
|
@@ -70,6 +80,10 @@ export interface CompletionContext {
|
|
|
70
80
|
removeEventListener?: (type: 'abort', fn: () => void) => void;
|
|
71
81
|
};
|
|
72
82
|
}
|
|
83
|
+
export type ResumeCompletionContext = Omit<Partial<CompletionContext>, 'runId' | 'resume'> & {
|
|
84
|
+
runId: string;
|
|
85
|
+
resume: true;
|
|
86
|
+
};
|
|
73
87
|
export interface InvokeContext {
|
|
74
88
|
capability: string;
|
|
75
89
|
args: Record<string, unknown>;
|
|
@@ -172,6 +186,9 @@ export interface HarnessInfo {
|
|
|
172
186
|
supportsKvCacheDeletion?: boolean;
|
|
173
187
|
}
|
|
174
188
|
export interface CapabilityInfo {
|
|
189
|
+
completionRecovery?: boolean;
|
|
190
|
+
hostRunLog?: boolean;
|
|
191
|
+
hostRunLogVersion?: number;
|
|
175
192
|
capabilityProfile: HarnessCapabilityProfile;
|
|
176
193
|
recommendedModelName: string;
|
|
177
194
|
memoryBudget?: MemoryBudget;
|
|
@@ -196,7 +213,7 @@ export interface InfraModel {
|
|
|
196
213
|
addon: string;
|
|
197
214
|
}
|
|
198
215
|
export interface HarnessContract {
|
|
199
|
-
completion(context: CompletionContext): AsyncIterable<HarnessEvent>;
|
|
216
|
+
completion(context: CompletionContext | ResumeCompletionContext): AsyncIterable<HarnessEvent>;
|
|
200
217
|
invoke?(context: InvokeContext): AsyncIterable<HarnessEvent>;
|
|
201
218
|
download?(context: DownloadContext): AsyncIterable<HarnessEvent>;
|
|
202
219
|
describe?(): Promise<HarnessInfo | null> | HarnessInfo;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type SnapshotFrom } from 'xstate';
|
|
2
|
+
type Request = 'SUSPEND' | 'RESUME' | 'WAKEUP';
|
|
3
|
+
export interface LifecycleEvent {
|
|
4
|
+
type: 'PRESUSPEND' | 'CLOSE' | Request;
|
|
5
|
+
}
|
|
6
|
+
export interface LifecycleWork {
|
|
7
|
+
suspend(): Promise<void>;
|
|
8
|
+
resume(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
interface LifecycleContext {
|
|
11
|
+
pending: Request | null;
|
|
12
|
+
failureCount: number;
|
|
13
|
+
failureMessage: string | null;
|
|
14
|
+
}
|
|
15
|
+
export declare const harnessLifecycle: import("xstate").StateMachine<LifecycleContext, LifecycleEvent, {
|
|
16
|
+
[x: string]: import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<void, import("xstate").NonReducibleUnknown, import("xstate").EventObject>> | undefined;
|
|
17
|
+
}, {
|
|
18
|
+
src: "resume";
|
|
19
|
+
logic: import("xstate").PromiseActorLogic<void, import("xstate").NonReducibleUnknown, import("xstate").EventObject>;
|
|
20
|
+
id: string | undefined;
|
|
21
|
+
} | {
|
|
22
|
+
src: "suspend";
|
|
23
|
+
logic: import("xstate").PromiseActorLogic<void, import("xstate").NonReducibleUnknown, import("xstate").EventObject>;
|
|
24
|
+
id: string | undefined;
|
|
25
|
+
}, {
|
|
26
|
+
type: "clear";
|
|
27
|
+
params: import("xstate").NonReducibleUnknown;
|
|
28
|
+
} | {
|
|
29
|
+
type: "hold";
|
|
30
|
+
params: import("xstate").NonReducibleUnknown;
|
|
31
|
+
} | {
|
|
32
|
+
type: "recordError";
|
|
33
|
+
params: import("xstate").NonReducibleUnknown;
|
|
34
|
+
} | {
|
|
35
|
+
type: "report";
|
|
36
|
+
params: unknown;
|
|
37
|
+
}, {
|
|
38
|
+
type: "resumeHeld";
|
|
39
|
+
params: unknown;
|
|
40
|
+
} | {
|
|
41
|
+
type: "suspendHeld";
|
|
42
|
+
params: unknown;
|
|
43
|
+
} | {
|
|
44
|
+
type: "wakeupHeld";
|
|
45
|
+
params: unknown;
|
|
46
|
+
}, never, "presuspended" | "resuming" | "running" | "suspended" | "suspending" | "waking", string, import("xstate").NonReducibleUnknown, import("xstate").NonReducibleUnknown, import("xstate").EventObject, import("xstate").MetaObject, {
|
|
47
|
+
id: "harness";
|
|
48
|
+
states: {
|
|
49
|
+
readonly running: {};
|
|
50
|
+
readonly presuspended: {};
|
|
51
|
+
readonly suspending: {};
|
|
52
|
+
readonly suspended: {};
|
|
53
|
+
readonly resuming: {};
|
|
54
|
+
readonly waking: {};
|
|
55
|
+
};
|
|
56
|
+
}, import("xstate").MetaObject>;
|
|
57
|
+
export interface HarnessLifecycle {
|
|
58
|
+
readonly suspended: boolean;
|
|
59
|
+
readonly state: SnapshotFrom<typeof harnessLifecycle>['value'];
|
|
60
|
+
send(type: LifecycleEvent['type']): Promise<void>;
|
|
61
|
+
settled(): Promise<SnapshotFrom<typeof harnessLifecycle>>;
|
|
62
|
+
cancelPending(): void;
|
|
63
|
+
stop(): void;
|
|
64
|
+
}
|
|
65
|
+
export declare function createHarnessLifecycle(work: LifecycleWork): HarnessLifecycle;
|
|
66
|
+
export {};
|