@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
package/README.md
CHANGED
|
@@ -308,6 +308,16 @@ bun run build:schema # regenerates spec/ (wire-compat rewind once v* tags exist
|
|
|
308
308
|
bun run build:bundle # stows the sidecar entry into dist/, to prove it still stows
|
|
309
309
|
```
|
|
310
310
|
|
|
311
|
+
## Engine layout
|
|
312
|
+
|
|
313
|
+
`lib/machine/` contains `completion/**`, `engine.ts`, `errors.ts`, `index.ts`, `replay-output.ts`,
|
|
314
|
+
`stable-stringify.ts`, and `guards.ts`. The run-log layer is in `lib/run-log/`:
|
|
315
|
+
`protocol.ts`, `protocol-types.ts`, `history-codec.ts`, `run-journal.ts`,
|
|
316
|
+
`persisted-actor.ts`, `replay.ts`, and `patch.ts`.
|
|
317
|
+
|
|
318
|
+
The completion graph has 24 states and 61 transitions. Reproduce these
|
|
319
|
+
counts with `examples/bench/graph-metrics.ts`.
|
|
320
|
+
|
|
311
321
|
The schema baseline rewinds `spec/` against this repo's `v*` release tags and
|
|
312
322
|
skips loudly while none exist. Dependency `overrides` pin the resolutions the
|
|
313
323
|
engine is validated against — keep them aligned with direct specs, npm refuses
|
|
@@ -316,3 +326,217 @@ a mismatch on publish.
|
|
|
316
326
|
## License
|
|
317
327
|
|
|
318
328
|
See [LICENSE](./LICENSE.md).
|
|
329
|
+
|
|
330
|
+
## Resuming a completion
|
|
331
|
+
|
|
332
|
+
The harness emits resumable steps to a host-owned log. Direct `Harness.completion()` runs without
|
|
333
|
+
that host log work normally, but cannot recover after process death. For remote runs, pass a
|
|
334
|
+
`HostRunLog` to `connectHarness(...).completion()` and reuse the same `runId` when reconnecting.
|
|
335
|
+
The peer must advertise `hostRunLogVersion: 1`.
|
|
336
|
+
|
|
337
|
+
```ts
|
|
338
|
+
const request = { runId: 'draft-42', model, messages, agent, runLog }
|
|
339
|
+
for await (const event of remote.completion(request)) {
|
|
340
|
+
// Save the run ID and render completion events.
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// begin() returns the saved boot for this run. connectHarness resumes from it and sends the
|
|
344
|
+
// same request identity; supply current callbacks, tool configs, and filesystem grants again.
|
|
345
|
+
for await (const event of remote.completion({ runId: 'draft-42', resume: true, runLog, approve })) {
|
|
346
|
+
// Handle run-resumed, round-reset, content, tool activity, and paused.
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
`HostRunLog.begin(runId)` acquires one exclusive generation and returns its compact boot, if the
|
|
351
|
+
run already exists, plus a 32-byte `digestKey`. Each `append(runId, generation, step)` must durably
|
|
352
|
+
commit the whole `EngineStep`—its `seq`, expected logical record length, and records—in one
|
|
353
|
+
transaction. The client waits for that commit before continuing. `release(runId, generation)` fences
|
|
354
|
+
late appends from the ended connection. A host may export its authenticated records for inspection;
|
|
355
|
+
the harness does not fetch storage or decrypt a host's log itself.
|
|
356
|
+
|
|
357
|
+
`hostAppendTimeoutMs` (default 5000) bounds that wait; it applies in full even to a resume issued
|
|
358
|
+
after the run's own deadline has passed. A spawned host raises it via the `runLog` start payload
|
|
359
|
+
when its appends (e.g. a large first append on resume) can take longer than the default.
|
|
360
|
+
|
|
361
|
+
Cancellation, iterator disposal, suspension, shutdown, and remote disconnect pause a run. A
|
|
362
|
+
`paused` event ends that stream without making the run terminal. Resume retains completed tool
|
|
363
|
+
results; time spent paused does not count against the run's deadline. A `round-reset` event identifies
|
|
364
|
+
the unfinished round. Ordinary resets carry no `replacedTypes`; only the terminal replay reset
|
|
365
|
+
(when resuming) lists the output kinds to replace. Both replace content and thinking. Text and
|
|
366
|
+
tool events carry run/round identities; tool events also carry their call identity. Completed runs
|
|
367
|
+
replay their final answer and metrics without loading a model.
|
|
368
|
+
|
|
369
|
+
An unfinished write produces `recovery-required` with an `operation` containing its ID, name,
|
|
370
|
+
resolved arguments, and effect. A write that the pause stopped before it started runs again. Reconcile the external result, then supply exactly that operation's
|
|
371
|
+
resolution on resume:
|
|
372
|
+
|
|
373
|
+
```ts
|
|
374
|
+
remote.completion({
|
|
375
|
+
runId: 'draft-42',
|
|
376
|
+
resume: true,
|
|
377
|
+
model,
|
|
378
|
+
messages,
|
|
379
|
+
agent,
|
|
380
|
+
recovery: [{ operationId: operation.id, decision: 'result', result: confirmedResult }],
|
|
381
|
+
runLog,
|
|
382
|
+
approve
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
// If re-execution is appropriate, explicitly authorize it instead:
|
|
386
|
+
// recovery: [{ operationId: operation.id, decision: 'retry' }]
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
A retry can repeat an external effect. Receipts prevent replay of completed operations; they do
|
|
390
|
+
not provide transactions or exactly-once effects in external systems. Missing runtime callbacks or
|
|
391
|
+
a model that cannot load leave the run paused with a recovery reason. For these runtime/read
|
|
392
|
+
reasons, restore the dependencies and resume without a `recovery` resolution. A tool that is gone
|
|
393
|
+
or whose schema changed since the pause ends the run with an error, because no resolution can
|
|
394
|
+
bring the old tool back. Stale resolutions and attempts to change the original conversation or
|
|
395
|
+
model are rejected.
|
|
396
|
+
|
|
397
|
+
A round can pause with one call's arguments redacted, whether or not a sibling call in the same
|
|
398
|
+
round already landed or was already dispatched. Resuming refuses with `PENDING_ARGS_REDACTED`
|
|
399
|
+
instead of replaying the redacted call. Its `recoveryOperationIds` lists every call the round still
|
|
400
|
+
needs settled before it can proceed: a dispatched write not yet resolved (redacted or not), or a
|
|
401
|
+
call whose real arguments exist only in the redacted snapshot, whether dispatched as a read or
|
|
402
|
+
never dispatched at all. A plain call that was never redacted and never dispatched is not listed;
|
|
403
|
+
it simply runs when the round resumes. Settle any listed operation with `decision: 'result'` and
|
|
404
|
+
the known outcome. `decision: 'skip'` is also available when the host knows a redacted operation
|
|
405
|
+
did not land, or for a read; it records a readable placeholder body,
|
|
406
|
+
`{ skipped: true, reason: 'not executed; arguments unavailable after resume' }`, never the literal
|
|
407
|
+
`undefined`. For a dispatched redacted write, `skip` asserts the call never landed; if the host
|
|
408
|
+
skips a write that did land, the model sees "not executed" and may issue it again. It remains
|
|
409
|
+
refused for a dispatched write whose arguments are available. The `retry` decision re-dispatches a
|
|
410
|
+
call still pending; it is refused once that call already has a settled result, for a call never
|
|
411
|
+
dispatched at all, and for a dispatched call whose arguments were redacted, which re-raises
|
|
412
|
+
`PENDING_ARGS_REDACTED` instead of retrying blind. Settling every listed operation finishes the
|
|
413
|
+
round; the landed write is never repeated, though a redacted read may run again. When no operation
|
|
414
|
+
can be reconciled this way, the error's `forkAt` gives the last log length that never held redacted
|
|
415
|
+
arguments as real ones, and `forkSafe` says whether forking there is actually safe: `false` means a
|
|
416
|
+
write whose intent starts at or after `forkAt` has an unknown outcome — its result already landed, or it was dispatched
|
|
417
|
+
and never resolved — so a fork could repeat it and the host should resolve `recoveryOperationIds`
|
|
418
|
+
instead. `forkRun(sourceCore, targetCore, { at: forkAt, runId })` copies the log up to that point
|
|
419
|
+
under a new `runId`, and the round reruns from there.
|
|
420
|
+
|
|
421
|
+
Tool definitions are checked again on resume, including their function source. A tool whose
|
|
422
|
+
behavior depends on values captured in a closure must supply and update `policyVersion` when
|
|
423
|
+
those values change; function source cannot reveal them. The `exec` and `http_request` factories
|
|
424
|
+
accept this value as an option; `exec` also fingerprints its static path and Python settings.
|
|
425
|
+
|
|
426
|
+
Tool configuration values are not stored in the log; a digest verifies that the caller supplies
|
|
427
|
+
the same configuration on resume. Credentials embedded in those values must currently remain
|
|
428
|
+
unchanged. Credentials managed through `setCredentials()` or runtime callbacks can be refreshed
|
|
429
|
+
without changing the request.
|
|
430
|
+
|
|
431
|
+
For host-owned logs, resume uses the boot returned by `begin()` and does not require the peer's
|
|
432
|
+
local `completionRecovery` capability. A transport `done` frame only means the stream ended; it
|
|
433
|
+
does not mean the run succeeded. Run-log and machine versions must match. XState restore accepts
|
|
434
|
+
older stable patches in the installed minor; future patches, other minors, and prereleases are
|
|
435
|
+
rejected. The first checkpoint and child actor snapshots are trusted inputs; diagnostic replay does
|
|
436
|
+
not verify actor effects or the initial context.
|
|
437
|
+
|
|
438
|
+
`connectHarness(transport, { runLogReleaseTimeoutMs })` bounds host lease cleanup to 5 seconds
|
|
439
|
+
by default. A rejected, throwing, or timed-out release is logged without replacing the completion
|
|
440
|
+
outcome. The host must keep generation fencing active until release actually settles; a cleanup
|
|
441
|
+
timeout does not authorize another writer.
|
|
442
|
+
|
|
443
|
+
Each run's metadata contains a JSON-only definition of the machine, including state hierarchy,
|
|
444
|
+
initial states, tags, invoked actors, and named transition guards/actions. Checkpoints and deltas
|
|
445
|
+
also carry the exact event, source/target state IDs, fired guard names, and action names observed in
|
|
446
|
+
XState's transition trace. The inspector displays these recorded traces and can replay state/context
|
|
447
|
+
at the same machine and XState versions; event-triggered guard/action traces are re-evaluated and
|
|
448
|
+
must match the recorded trace exactly, or replay reports a divergence. Eventless traces (no
|
|
449
|
+
triggering event, e.g. `always` transitions) are not replay-verified; the inspector marks each such
|
|
450
|
+
line `[eventless; not replay-verified]`. A version mismatch, legacy log, or prefix selection skips
|
|
451
|
+
replay and leaves the stored snapshot and trace authoritative. The checked-in [completion
|
|
452
|
+
graph](./docs/statecharts/completion-machine.mmd) is generated from the same machine definition and
|
|
453
|
+
CI rejects a stale artifact.
|
|
454
|
+
|
|
455
|
+
Export records from the host, then inspect a selected logical record or physical core length:
|
|
456
|
+
|
|
457
|
+
```sh
|
|
458
|
+
bare examples/run-log/inspect.ts <records.json> --context <recordIndex>
|
|
459
|
+
bare examples/run-log/view.ts <records.json> report.html --limit <recordIndex>
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
Logical record index, engine step sequence, and physical storage length are different positions;
|
|
463
|
+
host exports can include the mapping. The CLI reads exported records only. The host remains
|
|
464
|
+
responsible for remote lookup, authentication, decryption, and sharing access.
|
|
465
|
+
|
|
466
|
+
`@qvac/harness/run-log-inspect` is the library behind that CLI: `inspectRun(core, opts)` yields the
|
|
467
|
+
same lines the `inspect.ts` example prints, and `renderRunLogHtml(core, opts)` renders the HTML
|
|
468
|
+
report `view.ts` writes. A host imports either directly instead of shelling out to the examples,
|
|
469
|
+
passing a `MachineLog` adapter or an envelope whose `records()` method returns an async iterable
|
|
470
|
+
of `{ recordIndex, stepSeq, physicalLength, record }` entries. A raw records array or parsed JSON
|
|
471
|
+
envelope must first be adapted; the CLI's `recordsCore` helper shows this conversion. Options are
|
|
472
|
+
`recordLimit` (an exclusive logical index), `contextRecord`, `physicalLength`, and
|
|
473
|
+
`contextPhysicalLength`.
|
|
474
|
+
|
|
475
|
+
The completion machine is internal: its state names are part of the run-log format, not the API.
|
|
476
|
+
Hook consumers observe `runPause` and `runResume` for a run that can resume. A run with no run-log
|
|
477
|
+
store cannot resume, so a pause ends it and `runEnd` reports `aborted` (the caller aborted) or
|
|
478
|
+
`abandoned` (the consumer stopped iterating).
|
|
479
|
+
|
|
480
|
+
## Tool-call markup grammar
|
|
481
|
+
|
|
482
|
+
A tool-call block opens with `<function`, up to 64 ASCII whitespace characters, `=`, up to 64
|
|
483
|
+
more ASCII whitespace characters, a name, up to 64 ASCII whitespace characters, and `>`. Tags are
|
|
484
|
+
case-insensitive, except in the legacy nested reading below. An executable name is 1–64
|
|
485
|
+
non-whitespace characters other than `<` or `>`; persistence also recognizes longer names so an
|
|
486
|
+
oversized call cannot bypass redaction. A parameter uses the same form with `parameter` in place
|
|
487
|
+
of `function`, and ends at the first case-insensitive
|
|
488
|
+
`</parameter>`. A function block ends at the first case-insensitive `</function>`. Anything after
|
|
489
|
+
that closer is prose and cannot extend the call, including more parameters or closers.
|
|
490
|
+
|
|
491
|
+
Text that does not form a complete opener and closed block is prose. In particular, empty names,
|
|
492
|
+
overlong executable names, bare parameter tags, and function-tag examples without a matching
|
|
493
|
+
closer are neither executed nor hidden from the displayed answer. Stray function closers, including
|
|
494
|
+
`</FUNCTION>`, also stay visible. A function opener inside a function block or a parameter opener
|
|
495
|
+
inside a parameter value makes that block ambiguous, and persistence redacts it conservatively.
|
|
496
|
+
A block with a nested function opener keeps the legacy recovery reading: the first lowercase
|
|
497
|
+
`<function=` with no whitespace before `=` names the call. The text between `=` and `>` is limited
|
|
498
|
+
to 64 characters before the name is trimmed. It runs with complete lowercase
|
|
499
|
+
parameters up to the first lowercase `</function>` within that block. That reading ignores other
|
|
500
|
+
function openers, so `<function=a><function=login>…` runs `a`,
|
|
501
|
+
`<FUNCTION=a><function=login>…` and `<function =a><function=login>…` run `login`, and
|
|
502
|
+
`<FUNCTION=a><FUNCTION=login>…` runs nothing. Likewise,
|
|
503
|
+
`<function=x><function= login ><parameter=path>p</parameter></function>` runs `x` with `path: "p"`
|
|
504
|
+
when `x` is a known tool. An unclosed parameter, such as `<parameter=key>S</function>`, contributes
|
|
505
|
+
no argument and does not itself make the function block ambiguous. Persistence still redacts its
|
|
506
|
+
value when the name is a credential field or a registered sensitive parameter, including in prose.
|
|
507
|
+
|
|
508
|
+
## Run-log data and privacy
|
|
509
|
+
|
|
510
|
+
The harness redacts structured values before it sends a durable step to the host. String or object
|
|
511
|
+
values under exact credential field names are redacted. Numeric values under known credential
|
|
512
|
+
names are also redacted; generic `token` counts and `secret` flags are preserved. Registered tool
|
|
513
|
+
parameters marked `sensitive: true` are redacted regardless of name or value type. Known names include `db_password`, `GITHUB_TOKEN`,
|
|
514
|
+
`openai_api_key`, `client_password`, and `client_passphrase` (case, underscores, and hyphens
|
|
515
|
+
are normalized).
|
|
516
|
+
Name-based redaction is best effort: provider key names such as `ANTHROPIC_API_KEY`, `GH_TOKEN`,
|
|
517
|
+
and `PGPASSWORD` are not covered, and a bare `token` argument (e.g. a pagination cursor) is
|
|
518
|
+
redacted and lost on resume just like a real secret. The durable way to mark a value as a secret,
|
|
519
|
+
regardless of its name, is the schema's `sensitive: true` annotation.
|
|
520
|
+
Encoded assistant tool calls are redacted when history crosses persistence. Within one live process,
|
|
521
|
+
a model's next request still sees its own prior call's real arguments, because that history lives
|
|
522
|
+
only in the actor's memory. A **resumed** run has no such memory: its context is rebuilt from the
|
|
523
|
+
persisted (redacted) log, so the model's first request after resume sees `[redacted]` for any tool
|
|
524
|
+
call it made before the run was interrupted, not the original argument; that argument cannot be
|
|
525
|
+
recovered. The model sees that prior call as well-formed markup with the literal `"[redacted]"`
|
|
526
|
+
value, not an error; a model that re-issues such a call runs it with that literal placeholder.
|
|
527
|
+
A persisted `raw` or `rawCall` of 4,096 characters or more is rebuilt from its (redacted) arguments
|
|
528
|
+
even when nothing is sensitive, so it may differ byte-for-byte from the live call's `rawCall`.
|
|
529
|
+
Shorter unchanged text stays identical to the original.
|
|
530
|
+
Other arbitrary strings, tool results, and prose are preserved. Persisted machine
|
|
531
|
+
history can reference matching original request messages by index and materializes to the same
|
|
532
|
+
messages on resume and inspection — this applies to the caller-supplied conversation the run
|
|
533
|
+
started from, which is never redacted, not to arguments the model generated mid-run. Hosts must
|
|
534
|
+
treat free text and results as confidential and
|
|
535
|
+
protect their log with encryption and access control. The host's `digestKey` verifies request
|
|
536
|
+
identity and never enters a run record.
|
|
537
|
+
|
|
538
|
+
A pending tool call whose arguments were redacted cannot be executed on resume and is rejected.
|
|
539
|
+
A literal `[redacted]` supplied by the user is not enough to trigger that check. Tool configuration
|
|
540
|
+
values are not stored in the run log; a keyed digest verifies that the caller supplies the same
|
|
541
|
+
configuration on resume. Credentials managed through `setCredentials()` or runtime callbacks can
|
|
542
|
+
be refreshed without changing the request identity.
|
package/dist-lib/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AbortSignal as BareAbortSignal } from 'bare-abort-controller';
|
|
2
2
|
import ReadyResource from 'ready-resource';
|
|
3
|
+
import type { EngineBoot, EngineStep, RecoveryResolution } from './lib/machine/index.ts';
|
|
3
4
|
import { type Agent, type ApproveFn, type AskUserFn, type AttachFn, type CompletionEvent, type FetchAttachmentFn, type Message, type ProgressFn, type RagSearchFn, type ResponseFormat, type ToolDefinition, type ToolExecuteContext } from './lib/capabilities/completion.ts';
|
|
4
5
|
import { type DetectLanguageContext, type DetectedLanguage } from './lib/capabilities/detect-language.ts';
|
|
5
6
|
import { type Capability } from './lib/capabilities/invoke.ts';
|
|
@@ -40,6 +41,7 @@ export * from './lib/models/model-catalog.ts';
|
|
|
40
41
|
export * from './lib/models/model-list.ts';
|
|
41
42
|
export type { ModelTaskType } from './lib/models/model-task.ts';
|
|
42
43
|
export type { DeleteModelResult, DeleteModelSummary } from './lib/models/model-delete.ts';
|
|
44
|
+
export type { RecoveryResolution, RecoveryOperation } from './lib/machine/index.ts';
|
|
43
45
|
export { harnessChild, spawnHarness, type HarnessChildOptions, type SpawnHarnessOptions } from './lib/spawn.ts';
|
|
44
46
|
export { settingsDimension, settingsSteps } from './lib/tools/generate-image.ts';
|
|
45
47
|
export * from './lib/tools/skills/catalog.ts';
|
|
@@ -52,6 +54,7 @@ export { readSetup as normalizeSkillSetup } from './lib/tools/skills/manifest-pa
|
|
|
52
54
|
export type { CredentialRecord, CredentialStoreValue } from './lib/tools/skills/auth-resolver.ts';
|
|
53
55
|
export { isAvailableState, SKILL_STATE, type SkillState } from './lib/tools/skills/skill-state.ts';
|
|
54
56
|
export { connectHarness, HARNESS_DIED, RemoteHarness } from './lib/connect.ts';
|
|
57
|
+
export type { ConnectOptions, HostRunLog, HostRunLogLease } from './lib/connect.ts';
|
|
55
58
|
export type { KvCacheDeletionResult } from './lib/capabilities/kv-cache.ts';
|
|
56
59
|
export type { AgentKnobs, ApprovalCall, ChatMessage, CredentialEntry, DownloadContext, HarnessContract, HarnessDiagnostics, HarnessEvent, HarnessInfo, HarnessStatus, InfraModel, ModelState, SkillsOptions, SkillWriteResult } from './lib/contract-types.ts';
|
|
57
60
|
import type { HarnessInfo } from './lib/contract-types.ts';
|
|
@@ -96,6 +99,9 @@ export interface HarnessOptions {
|
|
|
96
99
|
completionModelCap?: number;
|
|
97
100
|
}
|
|
98
101
|
export interface CompletionContext {
|
|
102
|
+
runId?: string;
|
|
103
|
+
resume?: boolean;
|
|
104
|
+
recovery?: RecoveryResolution[];
|
|
99
105
|
model: string;
|
|
100
106
|
agent?: Agent;
|
|
101
107
|
messages: Message[];
|
|
@@ -115,8 +121,16 @@ export interface CompletionContext {
|
|
|
115
121
|
ragSearch?: RagSearchFn;
|
|
116
122
|
progress?: ProgressFn;
|
|
117
123
|
askUser?: AskUserFn;
|
|
124
|
+
boot?: EngineBoot;
|
|
125
|
+
onStep?: (step: EngineStep) => Promise<void>;
|
|
126
|
+
hostAppendTimeoutMs?: number;
|
|
127
|
+
requestDigestKey?: Uint8Array;
|
|
118
128
|
signal?: BareAbortSignal;
|
|
119
129
|
}
|
|
130
|
+
export type ResumeCompletionContext = Omit<Partial<CompletionContext>, 'runId' | 'resume'> & {
|
|
131
|
+
runId: string;
|
|
132
|
+
resume: true;
|
|
133
|
+
};
|
|
120
134
|
export interface InvokeContext {
|
|
121
135
|
capability: Capability;
|
|
122
136
|
args: Record<string, unknown>;
|
|
@@ -145,6 +159,7 @@ export declare class Harness extends ReadyResource {
|
|
|
145
159
|
private _models;
|
|
146
160
|
private _embedModels;
|
|
147
161
|
private readonly _retiredEmbedModels;
|
|
162
|
+
private readonly _faultedEmbedKeys;
|
|
148
163
|
private _embedLane;
|
|
149
164
|
private _embedFaults;
|
|
150
165
|
private readonly _embedGpuLayers?;
|
|
@@ -153,7 +168,20 @@ export declare class Harness extends ReadyResource {
|
|
|
153
168
|
private _ttsModels;
|
|
154
169
|
private _transcriptionModels;
|
|
155
170
|
private _voiceLane;
|
|
156
|
-
private
|
|
171
|
+
private readonly _lifecycle;
|
|
172
|
+
private readonly _detachedRuns;
|
|
173
|
+
private readonly _effectDrainWaiters;
|
|
174
|
+
private _activeWork;
|
|
175
|
+
private readonly _workDrainWaiters;
|
|
176
|
+
private _runtimeDraining;
|
|
177
|
+
private _runtimeUnloadFailed;
|
|
178
|
+
private _poolUnloadFailed;
|
|
179
|
+
private _poolCleanupFailed;
|
|
180
|
+
private readonly _failedModelUnloads;
|
|
181
|
+
private _sdkClosed;
|
|
182
|
+
private _runtimesReleased;
|
|
183
|
+
private _closeRetryNeeded;
|
|
184
|
+
private _closeRequested;
|
|
157
185
|
private _skillsDir?;
|
|
158
186
|
private readonly _modelsDir?;
|
|
159
187
|
private _overlayWatcher;
|
|
@@ -178,6 +206,7 @@ export declare class Harness extends ReadyResource {
|
|
|
178
206
|
private _musicSdk;
|
|
179
207
|
private _translationSdk;
|
|
180
208
|
private _musicRuntime;
|
|
209
|
+
private readonly _completionRuns;
|
|
181
210
|
private _translationRuntime;
|
|
182
211
|
private _capabilityTools;
|
|
183
212
|
private _capability;
|
|
@@ -228,26 +257,46 @@ export declare class Harness extends ReadyResource {
|
|
|
228
257
|
private _loadMusicSdk;
|
|
229
258
|
private _deviceConfig;
|
|
230
259
|
private _createPool;
|
|
260
|
+
private _loadModelLifecycleSdk;
|
|
231
261
|
private _createEmbedPool;
|
|
232
262
|
private _createTtsPool;
|
|
233
263
|
private _createTranscriptionPool;
|
|
264
|
+
private _recordModelUnloadFailure;
|
|
234
265
|
private _notifyModel;
|
|
235
266
|
private _collectRetiredEmbedPool;
|
|
236
267
|
private _releaseEmbedResource;
|
|
268
|
+
private _releaseEmbedResourceBeforeWork;
|
|
269
|
+
private _markEmbedFault;
|
|
237
270
|
private _releaseEmbedResourceAfter;
|
|
238
271
|
private _destroyEmbedPools;
|
|
239
272
|
private _enqueueEmbedControl;
|
|
273
|
+
private _runLifecycle;
|
|
274
|
+
private _abortCompletions;
|
|
275
|
+
private _assertNotClosing;
|
|
276
|
+
private _enterWork;
|
|
277
|
+
private _waitForWorkDrain;
|
|
278
|
+
private _effectsSettled;
|
|
279
|
+
private _notifyEffectDrain;
|
|
280
|
+
private _waitForEffectDrain;
|
|
281
|
+
private _trackDetachedRun;
|
|
282
|
+
private _closeCompletions;
|
|
240
283
|
getEmbeddingDevice(): EmbedDevice;
|
|
241
284
|
setEmbeddingDevice(device: EmbedDevice): Promise<void>;
|
|
242
285
|
private _setEmbeddingDevice;
|
|
243
286
|
presuspend(): Promise<void>;
|
|
244
287
|
suspend(): Promise<void>;
|
|
288
|
+
private _suspendRuntimes;
|
|
245
289
|
private _sdkLifecycle;
|
|
246
290
|
private _releaseRuntimes;
|
|
247
291
|
private _unloadIdleModels;
|
|
248
292
|
resume(): Promise<void>;
|
|
293
|
+
private _resumeRuntimes;
|
|
249
294
|
wakeup(): Promise<void>;
|
|
295
|
+
ready(): Promise<void>;
|
|
250
296
|
_close(): Promise<void>;
|
|
297
|
+
close(): Promise<void>;
|
|
298
|
+
private _closeWhileOpening;
|
|
299
|
+
private _finishClose;
|
|
251
300
|
download(args: DownloadArgs): DownloadEventStream;
|
|
252
301
|
embed(context: EmbedContext): Promise<number[][]>;
|
|
253
302
|
private _embed;
|
|
@@ -278,10 +327,13 @@ export declare class Harness extends ReadyResource {
|
|
|
278
327
|
private _yieldPins;
|
|
279
328
|
private _residency;
|
|
280
329
|
private _completionLoadOptions;
|
|
330
|
+
private _acquireModelLease;
|
|
281
331
|
invoke(context: InvokeContext): AsyncGenerator<CompletionEvent>;
|
|
282
332
|
private _invoke;
|
|
283
|
-
completion(context: CompletionContext): AsyncGenerator<CompletionEvent>;
|
|
284
|
-
private
|
|
333
|
+
completion(context: CompletionContext | ResumeCompletionContext): AsyncGenerator<CompletionEvent>;
|
|
334
|
+
private _runCompletion;
|
|
335
|
+
private _completionFailed;
|
|
336
|
+
private _completionRuntime;
|
|
285
337
|
private _residentEnhancer;
|
|
286
338
|
private _makeRoomForCompletion;
|
|
287
339
|
private _evictWedgedModel;
|