@qvac/harness 0.4.0 → 0.5.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 +689 -141
- package/README.md +29 -7
- package/dist/harness.bundle +71 -50
- package/dist-lib/index.d.ts +36 -39
- package/dist-lib/index.js +279 -114
- package/dist-lib/lib/audio-transcode-bare.d.ts +2 -2
- package/dist-lib/lib/audio-transcode-bare.js +28 -18
- package/dist-lib/lib/audio-transcode-node.d.ts +2 -2
- package/dist-lib/lib/capabilities/audio-resample.d.ts +7 -6
- package/dist-lib/lib/capabilities/audio-resample.js +30 -18
- package/dist-lib/lib/capabilities/completion.d.ts +20 -19
- package/dist-lib/lib/capabilities/completion.js +193 -132
- package/dist-lib/lib/capabilities/download.d.ts +6 -6
- package/dist-lib/lib/capabilities/download.js +15 -8
- package/dist-lib/lib/capabilities/embed.js +2 -1
- package/dist-lib/lib/capabilities/enhance.d.ts +6 -1
- package/dist-lib/lib/capabilities/enhance.js +7 -4
- package/dist-lib/lib/capabilities/invoke.js +7 -4
- package/dist-lib/lib/capabilities/kv-cache.js +2 -1
- package/dist-lib/lib/capabilities/preview-model-source.d.ts +9 -7
- package/dist-lib/lib/capabilities/preview-model-source.js +80 -28
- package/dist-lib/lib/capabilities/speech-text.js +5 -4
- package/dist-lib/lib/capabilities/tool-selection.js +10 -9
- package/dist-lib/lib/capabilities/tool-turns.js +30 -16
- package/dist-lib/lib/capabilities/usage-breakdown.js +2 -1
- package/dist-lib/lib/capabilities/voice.d.ts +5 -1
- package/dist-lib/lib/capabilities/voice.js +22 -12
- package/dist-lib/lib/connect.d.ts +11 -32
- package/dist-lib/lib/connect.js +152 -112
- package/dist-lib/lib/context-window.js +25 -21
- package/dist-lib/lib/contract-types.d.ts +22 -15
- package/dist-lib/lib/diagram-repair.d.ts +4 -4
- package/dist-lib/lib/diagram-repair.js +6 -3
- package/dist-lib/lib/docx/index.d.ts +3 -2
- package/dist-lib/lib/{error-fields.d.ts → guards.d.ts} +1 -0
- package/dist-lib/lib/{error-fields.js → guards.js} +3 -0
- package/dist-lib/lib/hardware/capability-probe.js +20 -10
- package/dist-lib/lib/hardware/gpu-classify.js +6 -3
- package/dist-lib/lib/hardware/gpu-probe-addon.js +8 -4
- package/dist-lib/lib/hardware/gpu-probe.js +4 -2
- package/dist-lib/lib/hardware/gpu-stats.native.cjs +8 -9
- package/dist-lib/lib/hardware/parsers.js +8 -4
- package/dist-lib/lib/helpers/buffer-burst.js +4 -2
- package/dist-lib/lib/helpers/control-tokens.js +4 -2
- package/dist-lib/lib/helpers/join-guard.d.ts +2 -2
- package/dist-lib/lib/helpers/join-guard.js +4 -2
- package/dist-lib/lib/helpers/load-stall.js +4 -2
- package/dist-lib/lib/helpers/markup-stream-filter.d.ts +2 -2
- package/dist-lib/lib/helpers/markup-stream-filter.js +6 -3
- package/dist-lib/lib/helpers/race-abort.js +2 -1
- package/dist-lib/lib/helpers/race-timeout.d.ts +5 -0
- package/dist-lib/lib/helpers/race-timeout.js +14 -0
- package/dist-lib/lib/helpers/run-outcome.d.ts +6 -8
- package/dist-lib/lib/helpers/run-outcome.js +36 -20
- package/dist-lib/lib/helpers/spawn-path.js +6 -3
- package/dist-lib/lib/helpers/text-coalescer.js +6 -3
- package/dist-lib/lib/helpers/thinking.js +38 -45
- package/dist-lib/lib/helpers/tool-call-markup.d.ts +9 -7
- package/dist-lib/lib/helpers/tool-call-markup.js +36 -20
- package/dist-lib/lib/helpers/tool-intent.d.ts +3 -2
- package/dist-lib/lib/helpers/tool-intent.js +4 -2
- package/dist-lib/lib/helpers/tool-label.js +18 -9
- package/dist-lib/lib/hooks/built-in/arg-repair.js +23 -13
- package/dist-lib/lib/hooks/built-in/egress.js +2 -1
- package/dist-lib/lib/hooks/built-in/skill-catalog.js +2 -1
- package/dist-lib/lib/hooks/pipeline.d.ts +5 -4
- package/dist-lib/lib/hooks/pipeline.js +6 -3
- package/dist-lib/lib/hooks/run.js +12 -8
- package/dist-lib/lib/model-download-progress.js +10 -8
- package/dist-lib/lib/models/context.d.ts +1 -1
- package/dist-lib/lib/models/context.js +5 -1
- package/dist-lib/lib/models/custom-model-cache.d.ts +10 -1
- package/dist-lib/lib/models/custom-model-cache.js +43 -15
- package/dist-lib/lib/models/gguf-header.d.ts +3 -2
- package/dist-lib/lib/models/gguf-header.js +44 -22
- package/dist-lib/lib/models/idle-unload.d.ts +14 -0
- package/dist-lib/lib/models/idle-unload.js +51 -0
- package/dist-lib/lib/models/kv-cache.d.ts +3 -2
- package/dist-lib/lib/models/kv-cache.js +4 -3
- package/dist-lib/lib/models/llm-presets.d.ts +2 -2
- package/dist-lib/lib/models/llm-presets.js +4 -2
- package/dist-lib/lib/models/model-catalog-constants.js +3 -2
- package/dist-lib/lib/models/model-catalog.d.ts +13 -20
- package/dist-lib/lib/models/model-catalog.js +59 -31
- package/dist-lib/lib/models/model-delete.js +18 -8
- package/dist-lib/lib/models/model-handle.js +2 -1
- package/dist-lib/lib/models/model-list.d.ts +8 -3
- package/dist-lib/lib/models/model-list.js +11 -6
- package/dist-lib/lib/models/model-pool.d.ts +44 -10
- package/dist-lib/lib/models/model-pool.js +47 -42
- package/dist-lib/lib/models/model-source.js +10 -5
- package/dist-lib/lib/models/music-catalog.d.ts +2 -2
- package/dist-lib/lib/models/nmt-catalog.d.ts +4 -3
- package/dist-lib/lib/models/nmt-catalog.js +10 -5
- package/dist-lib/lib/models/opencl-cache.d.ts +6 -1
- package/dist-lib/lib/models/opencl-cache.js +5 -3
- package/dist-lib/lib/models/sdk-faults.d.ts +11 -8
- package/dist-lib/lib/models/sdk-faults.js +9 -6
- package/dist-lib/lib/models/shards.d.ts +11 -0
- package/dist-lib/lib/models/shards.js +15 -0
- package/dist-lib/lib/models/tool-dialect.js +10 -5
- package/dist-lib/lib/no-redirect-fetch-bare.d.ts +3 -3
- package/dist-lib/lib/no-redirect-fetch-bare.js +1 -1
- package/dist-lib/lib/no-redirect-fetch-impl.js +6 -3
- package/dist-lib/lib/no-redirect-fetch-node.d.ts +1 -1
- package/dist-lib/lib/no-redirect-fetch-node.js +9 -9
- package/dist-lib/lib/office/index.d.ts +3 -2
- package/dist-lib/lib/office/python.d.ts +3 -2
- package/dist-lib/lib/office/python.js +2 -1
- package/dist-lib/lib/prompt.d.ts +5 -4
- package/dist-lib/lib/prompt.js +8 -4
- package/dist-lib/lib/queue.js +10 -5
- package/dist-lib/lib/resolution-detector.js +21 -11
- package/dist-lib/lib/rpc-session.js +2 -1
- package/dist-lib/lib/sdk-loader.js +2 -1
- package/dist-lib/lib/sdk-storage.js +4 -2
- package/dist-lib/lib/serve.js +110 -66
- package/dist-lib/lib/spawn.js +7 -4
- package/dist-lib/lib/tmp-path.d.ts +7 -6
- package/dist-lib/lib/tool-call-display.d.ts +2 -2
- package/dist-lib/lib/tools/create-documents.js +18 -10
- package/dist-lib/lib/tools/edit-documents.js +23 -13
- package/dist-lib/lib/tools/edit-image.d.ts +2 -2
- package/dist-lib/lib/tools/edit-image.js +60 -36
- package/dist-lib/lib/tools/exec/adapters/adapter.d.ts +10 -10
- package/dist-lib/lib/tools/exec/adapters/python/attachments.d.ts +17 -11
- package/dist-lib/lib/tools/exec/adapters/python/attachments.js +53 -40
- package/dist-lib/lib/tools/exec/adapters/python/create-effect.d.ts +2 -2
- package/dist-lib/lib/tools/exec/adapters/python/create-effect.js +60 -32
- package/dist-lib/lib/tools/exec/adapters/python/guarded-fetch.d.ts +33 -22
- package/dist-lib/lib/tools/exec/adapters/python/guarded-fetch.js +58 -29
- package/dist-lib/lib/tools/exec/adapters/python/interrupt-timer.d.ts +2 -2
- package/dist-lib/lib/tools/exec/adapters/python/loader.js +23 -12
- package/dist-lib/lib/tools/exec/adapters/python/memfs.d.ts +13 -11
- package/dist-lib/lib/tools/exec/adapters/python/memfs.js +10 -5
- package/dist-lib/lib/tools/exec/adapters/python/net-shim.js +3 -1
- package/dist-lib/lib/tools/exec/adapters/python/output-policy.d.ts +6 -4
- package/dist-lib/lib/tools/exec/adapters/python/output-policy.js +20 -10
- package/dist-lib/lib/tools/exec/adapters/python/pyodide.d.ts +2 -2
- package/dist-lib/lib/tools/exec/adapters/python/pyodide.js +14 -7
- package/dist-lib/lib/tools/exec/adapters/python/python-adapter.d.ts +41 -34
- package/dist-lib/lib/tools/exec/adapters/python/python-adapter.js +316 -166
- package/dist-lib/lib/tools/exec/adapters/python/run-session.d.ts +9 -8
- package/dist-lib/lib/tools/exec/adapters/python/run-session.js +56 -28
- package/dist-lib/lib/tools/exec/adapters/python/wheels.d.ts +8 -10
- package/dist-lib/lib/tools/exec/adapters/python/wheels.js +22 -11
- package/dist-lib/lib/tools/exec/adapters/python/worker/client.d.ts +3 -2
- package/dist-lib/lib/tools/exec/adapters/python/worker/client.js +41 -26
- package/dist-lib/lib/tools/exec/adapters/python/worker/entry.js +27 -18
- package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.d.ts +2 -2
- package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.js +14 -13
- package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.d.ts +4 -4
- package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.js +10 -5
- package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.d.ts +4 -4
- package/dist-lib/lib/tools/exec/adapters/shell/shell-adapter.js +2 -1
- package/dist-lib/lib/tools/exec/obsidian/cli-process.d.ts +6 -1
- package/dist-lib/lib/tools/exec/obsidian/cli-process.js +8 -5
- package/dist-lib/lib/tools/exec/obsidian/cli.d.ts +6 -6
- package/dist-lib/lib/tools/exec/obsidian/cli.js +4 -4
- package/dist-lib/lib/tools/exec/obsidian/command.d.ts +3 -2
- package/dist-lib/lib/tools/exec/obsidian/command.js +6 -3
- package/dist-lib/lib/tools/exec/obsidian/output.js +2 -1
- package/dist-lib/lib/tools/exec/obsidian/route.d.ts +4 -6
- package/dist-lib/lib/tools/exec/obsidian/route.js +17 -11
- package/dist-lib/lib/tools/exec/obsidian/safe-path.js +2 -1
- package/dist-lib/lib/tools/exec/obsidian/vault-create.js +15 -7
- package/dist-lib/lib/tools/exec/obsidian/vault-paths.d.ts +2 -2
- package/dist-lib/lib/tools/exec/obsidian/vault-paths.js +20 -10
- package/dist-lib/lib/tools/exec/obsidian/vault-read.js +20 -13
- package/dist-lib/lib/tools/exec/obsidian/vault-write.js +24 -12
- package/dist-lib/lib/tools/exec/runner.d.ts +14 -14
- package/dist-lib/lib/tools/exec/runner.js +5 -3
- package/dist-lib/lib/tools/exec/scope.js +52 -28
- package/dist-lib/lib/tools/exec/shell-argv.js +31 -18
- package/dist-lib/lib/tools/exec/shell-guidance.d.ts +6 -1
- package/dist-lib/lib/tools/exec/shell-guidance.js +35 -20
- package/dist-lib/lib/tools/exec/video-tools.js +2 -2
- package/dist-lib/lib/tools/exec.d.ts +6 -8
- package/dist-lib/lib/tools/exec.js +113 -54
- package/dist-lib/lib/tools/file-glob.d.ts +4 -5
- package/dist-lib/lib/tools/file-glob.js +16 -11
- package/dist-lib/lib/tools/fs/glob.js +13 -18
- package/dist-lib/lib/tools/fs/remote-protocol.d.ts +10 -10
- package/dist-lib/lib/tools/fs/remote.d.ts +3 -2
- package/dist-lib/lib/tools/fs/remote.js +13 -7
- package/dist-lib/lib/tools/fs/scope.d.ts +8 -3
- package/dist-lib/lib/tools/fs/scope.js +20 -12
- package/dist-lib/lib/tools/fs/walk.js +6 -3
- package/dist-lib/lib/tools/fs/write.d.ts +3 -2
- package/dist-lib/lib/tools/generate-image.d.ts +11 -9
- package/dist-lib/lib/tools/generate-image.js +73 -37
- package/dist-lib/lib/tools/generate-music.d.ts +22 -11
- package/dist-lib/lib/tools/generate-music.js +79 -48
- package/dist-lib/lib/tools/grep.js +66 -41
- package/dist-lib/lib/tools/http-request/encode-fields.js +18 -9
- package/dist-lib/lib/tools/http-request/{utils.js → request.js} +20 -11
- package/dist-lib/lib/tools/http-request/truncate-response.js +57 -46
- package/dist-lib/lib/tools/http-request.d.ts +1 -1
- package/dist-lib/lib/tools/http-request.js +33 -18
- package/dist-lib/lib/tools/mcp/protocol.d.ts +53 -0
- package/dist-lib/lib/tools/mcp/{utils.js → protocol.js} +45 -23
- package/dist-lib/lib/tools/mcp-call.d.ts +1 -1
- package/dist-lib/lib/tools/mcp-call.js +37 -16
- package/dist-lib/lib/tools/operations/builders.js +10 -6
- package/dist-lib/lib/tools/operations/compile.js +20 -10
- package/dist-lib/lib/tools/operations/decoders.js +12 -6
- package/dist-lib/lib/tools/operations/gmail-message.js +3 -2
- package/dist-lib/lib/tools/outbound-guard.d.ts +4 -3
- package/dist-lib/lib/tools/outbound-guard.js +14 -8
- package/dist-lib/lib/tools/private-ip.js +8 -7
- package/dist-lib/lib/tools/rag-search.js +14 -7
- package/dist-lib/lib/tools/read-files.js +23 -20
- package/dist-lib/lib/tools/skill.js +19 -10
- package/dist-lib/lib/tools/skills/auth-resolver.d.ts +11 -18
- package/dist-lib/lib/tools/skills/auth-resolver.js +30 -18
- package/dist-lib/lib/tools/skills/bin-check.d.ts +3 -2
- package/dist-lib/lib/tools/skills/bin-check.js +10 -3
- package/dist-lib/lib/tools/skills/bundled-dir.js +20 -10
- package/dist-lib/lib/tools/skills/bundled-hash.d.ts +3 -2
- package/dist-lib/lib/tools/skills/bundled-hash.js +6 -1
- package/dist-lib/lib/tools/skills/catalog.d.ts +3 -2
- package/dist-lib/lib/tools/skills/catalog.js +33 -28
- package/dist-lib/lib/tools/skills/cli-argv.d.ts +3 -2
- package/dist-lib/lib/tools/skills/cli-argv.js +55 -52
- package/dist-lib/lib/tools/skills/cli-schema-check.js +21 -10
- package/dist-lib/lib/tools/skills/cli-schema-load.js +28 -20
- package/dist-lib/lib/tools/skills/cli-schema-types.d.ts +6 -6
- package/dist-lib/lib/tools/skills/cli-schema.js +2 -1
- package/dist-lib/lib/tools/skills/credential-check.d.ts +6 -3
- package/dist-lib/lib/tools/skills/credential-check.js +24 -12
- package/dist-lib/lib/tools/skills/credential-grants.js +1 -6
- package/dist-lib/lib/tools/skills/credential-health.d.ts +5 -1
- package/dist-lib/lib/tools/skills/credential-health.js +5 -3
- package/dist-lib/lib/tools/skills/frontmatter-parser.js +10 -5
- package/dist-lib/lib/tools/skills/manifest-parse.js +84 -64
- package/dist-lib/lib/tools/skills/mention.js +7 -6
- package/dist-lib/lib/tools/skills/obsidian-readiness.d.ts +2 -2
- package/dist-lib/lib/tools/skills/obsidian-readiness.js +11 -3
- package/dist-lib/lib/tools/skills/overlay-crud.d.ts +6 -4
- package/dist-lib/lib/tools/skills/overlay-crud.js +12 -6
- package/dist-lib/lib/tools/skills/overlay-dir.js +4 -2
- package/dist-lib/lib/tools/skills/overlay-watch.d.ts +3 -2
- package/dist-lib/lib/tools/skills/overlay-watch.js +8 -4
- package/dist-lib/lib/tools/skills/setup-routes.js +1 -3
- package/dist-lib/lib/tools/skills/skill-settings.js +4 -1
- package/dist-lib/lib/tools/skills/skill-state.d.ts +6 -11
- package/dist-lib/lib/tools/skills/skill-state.js +48 -29
- package/dist-lib/lib/tools/skills/tool-grants.js +6 -3
- package/dist-lib/lib/tools/toolsets.js +2 -1
- package/dist-lib/lib/tools/translate.d.ts +4 -5
- package/dist-lib/lib/tools/translate.js +31 -14
- package/dist-lib/lib/tools/url-guard.js +2 -1
- package/dist-lib/lib/tools/weather-lookup/place.js +8 -4
- package/dist-lib/lib/tools/weather-lookup/report.d.ts +7 -1
- package/dist-lib/lib/tools/weather-lookup/report.js +46 -9
- package/dist-lib/lib/tools/weather-lookup.js +18 -12
- package/dist-lib/lib/tools/web-fetch.js +47 -24
- package/dist-lib/lib/tools/web-search.js +8 -3
- package/dist-lib/lib/validating-lookup.d.ts +4 -4
- package/dist-lib/lib/wav-encode.d.ts +1 -1
- package/dist-lib/lib/wav-encode.js +11 -10
- package/dist-lib/lib/web-fetch/embedded-state.js +24 -12
- package/dist-lib/lib/web-fetch/extract.js +4 -2
- package/dist-lib/lib/web-fetch/images.js +8 -4
- package/dist-lib/lib/web-fetch/video.d.ts +2 -2
- package/dist-lib/lib/web-fetch/video.js +8 -4
- package/dist-lib/lib/web-search/engine-registry.d.ts +2 -2
- package/dist-lib/lib/web-search/engines/aol.js +1 -1
- package/dist-lib/lib/web-search/engines/bing.js +1 -1
- package/dist-lib/lib/web-search/engines/brave.js +4 -1
- package/dist-lib/lib/web-search/engines/duckduckgo.js +3 -2
- package/dist-lib/lib/web-search/engines/google.js +7 -3
- package/dist-lib/lib/web-search/engines/wikipedia.js +5 -4
- package/dist-lib/lib/web-search/engines/yahoo.js +1 -1
- package/dist-lib/lib/web-search/fetch-html.d.ts +5 -4
- package/dist-lib/lib/web-search/fetch-html.js +13 -7
- package/dist-lib/lib/web-search/orchestrator.d.ts +9 -5
- package/dist-lib/lib/web-search/orchestrator.js +3 -3
- package/dist-lib/lib/wire.d.ts +3 -2
- package/dist-lib/lib/wire.js +23 -15
- package/dist-lib/schema/baseline.js +10 -5
- package/dist-lib/schema/build.js +2 -1
- package/dist-lib/schema/harness.d.ts +15 -2
- package/dist-lib/schema/harness.js +14 -2
- package/dist-lib/schema/release-tags.d.ts +3 -2
- package/dist-lib/schema/release-tags.js +6 -3
- package/dist-lib/spec/bind.js +3 -0
- package/dist-lib/spec/calls.js +1 -0
- package/dist-lib/spec/hrpc/hrpc.json +13 -0
- package/dist-lib/spec/hrpc/index.js +15 -3
- package/dist-lib/spec/hrpc/messages.js +39 -8
- package/dist-lib/spec/hyperschema/index.js +39 -8
- package/dist-lib/spec/hyperschema/schema.json +30 -1
- package/dist-lib/spec/hyperschema/types.d.ts +9 -1
- package/package.json +13 -14
- package/worker/harness-sidecar.mjs +15 -22
- package/worker/stow-entry.mjs +7 -4
- package/dist-lib/lib/tools/mcp/utils.d.ts +0 -47
- /package/dist-lib/lib/tools/http-request/{utils.d.ts → request.d.ts} +0 -0
package/dist-lib/lib/connect.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import EventEmitter from 'events';
|
|
2
2
|
import fs from 'fs';
|
|
3
|
+
import { z } from 'zod';
|
|
3
4
|
import { settleOnClose } from './rpc-session.js';
|
|
4
5
|
import { harnessClient } from '../spec/calls.js';
|
|
5
6
|
import HRPC from '../spec/hrpc/index.js';
|
|
@@ -7,7 +8,7 @@ import { unsupportedKvCacheDeletion } from './capabilities/kv-cache.js';
|
|
|
7
8
|
import { readModelSourcePreview } from './capabilities/preview-model-source.js';
|
|
8
9
|
import { hlog } from './log.js';
|
|
9
10
|
import { assertEmbedDevice } from './models/embed-config.js';
|
|
10
|
-
import { errorCode, errorMessage } from './
|
|
11
|
+
import { errorCode, errorMessage, isRecord } from './guards.js';
|
|
11
12
|
import { pushQueue } from './queue.js';
|
|
12
13
|
import { stageFile, sweepStaging } from './staging.js';
|
|
13
14
|
import { readInstall, readSetup } from './tools/skills/manifest-parse.js';
|
|
@@ -19,9 +20,10 @@ export function connectHarness(transport) {
|
|
|
19
20
|
return new RemoteHarness(transport);
|
|
20
21
|
}
|
|
21
22
|
export function readEmbeddingDeviceResponse(response) {
|
|
22
|
-
const device =
|
|
23
|
-
if (typeof device !== 'string')
|
|
23
|
+
const device = isRecord(response) ? response.device : undefined;
|
|
24
|
+
if (typeof device !== 'string') {
|
|
24
25
|
throw new Error('invalid embedding device response');
|
|
26
|
+
}
|
|
25
27
|
assertEmbedDevice(device);
|
|
26
28
|
return device;
|
|
27
29
|
}
|
|
@@ -36,8 +38,9 @@ export class RemoteHarness extends EventEmitter {
|
|
|
36
38
|
this._transport = transport;
|
|
37
39
|
}
|
|
38
40
|
_ensure() {
|
|
39
|
-
if (this._closed)
|
|
41
|
+
if (this._closed) {
|
|
40
42
|
return Promise.reject(died('harness closed'));
|
|
43
|
+
}
|
|
41
44
|
if (this._session) {
|
|
42
45
|
return this._session.dead
|
|
43
46
|
? Promise.reject(died('harness is dead'))
|
|
@@ -72,8 +75,9 @@ export class RemoteHarness extends EventEmitter {
|
|
|
72
75
|
});
|
|
73
76
|
stream.on('close', () => {
|
|
74
77
|
session.dead = true;
|
|
75
|
-
if (this._closed)
|
|
78
|
+
if (this._closed) {
|
|
76
79
|
return;
|
|
80
|
+
}
|
|
77
81
|
this.emit('status', streamError ? { state: 'died', ...errorDetails(streamError) } : { state: 'died' });
|
|
78
82
|
});
|
|
79
83
|
this._session = session;
|
|
@@ -138,8 +142,9 @@ export class RemoteHarness extends EventEmitter {
|
|
|
138
142
|
let closed = false;
|
|
139
143
|
let received = 0;
|
|
140
144
|
const reclaim = () => {
|
|
141
|
-
|
|
142
|
-
void fs.promises.unlink(
|
|
145
|
+
for (const file of staged.splice(0).reverse()) {
|
|
146
|
+
void fs.promises.unlink(file).catch(noop);
|
|
147
|
+
}
|
|
143
148
|
};
|
|
144
149
|
const onAbort = () => duplex?.destroy();
|
|
145
150
|
try {
|
|
@@ -157,18 +162,19 @@ export class RemoteHarness extends EventEmitter {
|
|
|
157
162
|
if (event.type !== 'content' && event.type !== 'thinking') {
|
|
158
163
|
hlog('client frame', { type: event.type, n: received });
|
|
159
164
|
}
|
|
160
|
-
if (event.type === 'done')
|
|
165
|
+
if (event.type === 'done') {
|
|
161
166
|
break;
|
|
167
|
+
}
|
|
162
168
|
if (event.type === 'approval-ask') {
|
|
163
169
|
const callId = event.callId;
|
|
164
170
|
void Promise.resolve()
|
|
165
171
|
.then(() => context.approve?.({
|
|
166
172
|
name: event.name ?? '',
|
|
167
|
-
arguments: (event.arguments
|
|
173
|
+
arguments: isRecord(event.arguments) ? event.arguments : {},
|
|
168
174
|
resource: event.resource ?? null,
|
|
169
175
|
effect: event.effect === 'read' ? 'read' : 'write',
|
|
170
176
|
intent: event.intent || null,
|
|
171
|
-
display: event.display
|
|
177
|
+
display: isToolCallDisplay(event.display) ? event.display : null
|
|
172
178
|
}))
|
|
173
179
|
.then((approved) => {
|
|
174
180
|
if (!closed) {
|
|
@@ -186,8 +192,9 @@ export class RemoteHarness extends EventEmitter {
|
|
|
186
192
|
const callId = event.callId;
|
|
187
193
|
void bridgeAttach(event, context.attach)
|
|
188
194
|
.then((frame) => {
|
|
189
|
-
if (!closed)
|
|
195
|
+
if (!closed) {
|
|
190
196
|
duplex.write({ ...frame, callId });
|
|
197
|
+
}
|
|
191
198
|
}, (err) => {
|
|
192
199
|
if (!closed) {
|
|
193
200
|
duplex.write({
|
|
@@ -204,12 +211,14 @@ export class RemoteHarness extends EventEmitter {
|
|
|
204
211
|
const callId = event.callId;
|
|
205
212
|
void bridgeFetch(event, context, staged)
|
|
206
213
|
.then((frame) => {
|
|
207
|
-
if (closed)
|
|
214
|
+
if (closed) {
|
|
208
215
|
return reclaim();
|
|
216
|
+
}
|
|
209
217
|
duplex.write({ ...frame, callId });
|
|
210
218
|
}, (err) => {
|
|
211
|
-
if (closed)
|
|
219
|
+
if (closed) {
|
|
212
220
|
return reclaim();
|
|
221
|
+
}
|
|
213
222
|
duplex.write({ type: 'fetch-result', callId, message: errorMessage(err) });
|
|
214
223
|
})
|
|
215
224
|
.catch((err) => hlog('fetch reply failed', { callId, message: errorMessage(err) }));
|
|
@@ -219,11 +228,13 @@ export class RemoteHarness extends EventEmitter {
|
|
|
219
228
|
const callId = event.callId;
|
|
220
229
|
void bridgeDrive(event, context)
|
|
221
230
|
.then((frame) => {
|
|
222
|
-
if (!closed)
|
|
231
|
+
if (!closed) {
|
|
223
232
|
return duplex.write({ ...frame, callId });
|
|
233
|
+
}
|
|
224
234
|
const stagedPath = frame.payload?.path;
|
|
225
|
-
if (stagedPath)
|
|
235
|
+
if (stagedPath) {
|
|
226
236
|
void fs.promises.unlink(stagedPath).catch(noop);
|
|
237
|
+
}
|
|
227
238
|
}, (err) => {
|
|
228
239
|
if (!closed) {
|
|
229
240
|
duplex.write({
|
|
@@ -240,8 +251,9 @@ export class RemoteHarness extends EventEmitter {
|
|
|
240
251
|
const callId = event.callId;
|
|
241
252
|
void bridgeRag(event, context)
|
|
242
253
|
.then((frame) => {
|
|
243
|
-
if (!closed)
|
|
254
|
+
if (!closed) {
|
|
244
255
|
duplex.write({ ...frame, callId });
|
|
256
|
+
}
|
|
245
257
|
}, (err) => {
|
|
246
258
|
if (!closed) {
|
|
247
259
|
duplex.write({
|
|
@@ -255,39 +267,14 @@ export class RemoteHarness extends EventEmitter {
|
|
|
255
267
|
continue;
|
|
256
268
|
}
|
|
257
269
|
if (event.type === 'question-ask') {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
callId,
|
|
265
|
-
message: 'the host cannot ask questions'
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
continue;
|
|
269
|
-
}
|
|
270
|
-
void Promise.resolve()
|
|
271
|
-
.then(() => askUser({
|
|
272
|
-
question: event.question ?? '',
|
|
273
|
-
...(Array.isArray(event.options)
|
|
274
|
-
? { options: event.options.map(String) }
|
|
275
|
-
: {})
|
|
276
|
-
}))
|
|
277
|
-
.then((answer) => {
|
|
278
|
-
if (!closed) {
|
|
279
|
-
duplex.write({ type: 'question-result', callId, answer: answer ?? '' });
|
|
280
|
-
}
|
|
281
|
-
}, (err) => {
|
|
282
|
-
if (!closed) {
|
|
283
|
-
duplex.write({
|
|
284
|
-
type: 'question-result',
|
|
285
|
-
callId,
|
|
286
|
-
message: errorMessage(err)
|
|
287
|
-
});
|
|
270
|
+
answerQuestion(event, {
|
|
271
|
+
askUser: context.askUser,
|
|
272
|
+
reply: (frame) => {
|
|
273
|
+
if (!closed) {
|
|
274
|
+
duplex.write(frame);
|
|
275
|
+
}
|
|
288
276
|
}
|
|
289
|
-
})
|
|
290
|
-
.catch((err) => hlog('question reply failed', { callId, message: errorMessage(err) }));
|
|
277
|
+
});
|
|
291
278
|
continue;
|
|
292
279
|
}
|
|
293
280
|
if (event.type === 'progress') {
|
|
@@ -295,19 +282,21 @@ export class RemoteHarness extends EventEmitter {
|
|
|
295
282
|
continue;
|
|
296
283
|
}
|
|
297
284
|
const wire = fromWire(event);
|
|
298
|
-
if (wire.type === 'aborted')
|
|
285
|
+
if (wire.type === 'aborted') {
|
|
299
286
|
emittedAborted = true;
|
|
287
|
+
}
|
|
300
288
|
yield wire;
|
|
301
289
|
}
|
|
302
290
|
hlog('client wire ended', { received });
|
|
303
291
|
}
|
|
304
292
|
catch (err) {
|
|
305
293
|
if (context.signal?.aborted) {
|
|
306
|
-
if (!emittedAborted)
|
|
294
|
+
if (!emittedAborted) {
|
|
307
295
|
yield { type: 'aborted' };
|
|
296
|
+
}
|
|
308
297
|
return;
|
|
309
298
|
}
|
|
310
|
-
throw died(`harness died mid-run: ${err
|
|
299
|
+
throw died(`harness died mid-run: ${errorMessage(err)}`);
|
|
311
300
|
}
|
|
312
301
|
finally {
|
|
313
302
|
hlog('client run end', { received, aborted: Boolean(context.signal?.aborted) });
|
|
@@ -316,8 +305,9 @@ export class RemoteHarness extends EventEmitter {
|
|
|
316
305
|
closed = true;
|
|
317
306
|
reclaim();
|
|
318
307
|
}
|
|
319
|
-
if (context.signal?.aborted && !emittedAborted)
|
|
308
|
+
if (context.signal?.aborted && !emittedAborted) {
|
|
320
309
|
yield { type: 'aborted' };
|
|
310
|
+
}
|
|
321
311
|
}
|
|
322
312
|
async *download(context) {
|
|
323
313
|
const { client } = await this._ensure();
|
|
@@ -338,25 +328,28 @@ export class RemoteHarness extends EventEmitter {
|
|
|
338
328
|
context.signal?.addEventListener?.('abort', onAbort, { once: true });
|
|
339
329
|
for await (const event of downloadFrames(stream)) {
|
|
340
330
|
const wire = fromDownloadWire(event);
|
|
341
|
-
if (wire.type === 'aborted')
|
|
331
|
+
if (wire.type === 'aborted') {
|
|
342
332
|
emittedAborted = true;
|
|
333
|
+
}
|
|
343
334
|
yield wire;
|
|
344
335
|
}
|
|
345
336
|
}
|
|
346
337
|
catch (err) {
|
|
347
338
|
if (context.signal?.aborted) {
|
|
348
|
-
if (!emittedAborted)
|
|
339
|
+
if (!emittedAborted) {
|
|
349
340
|
yield { type: 'aborted' };
|
|
341
|
+
}
|
|
350
342
|
return;
|
|
351
343
|
}
|
|
352
|
-
throw died(`harness died mid-download: ${err
|
|
344
|
+
throw died(`harness died mid-download: ${errorMessage(err)}`);
|
|
353
345
|
}
|
|
354
346
|
finally {
|
|
355
347
|
context.signal?.removeEventListener?.('abort', onAbort);
|
|
356
348
|
stream?.destroy();
|
|
357
349
|
}
|
|
358
|
-
if (context.signal?.aborted && !emittedAborted)
|
|
350
|
+
if (context.signal?.aborted && !emittedAborted) {
|
|
359
351
|
yield { type: 'aborted' };
|
|
352
|
+
}
|
|
360
353
|
}
|
|
361
354
|
async embed(context) {
|
|
362
355
|
const { client } = await this._ensure();
|
|
@@ -390,8 +383,9 @@ export class RemoteHarness extends EventEmitter {
|
|
|
390
383
|
const duplex = client.speakStream();
|
|
391
384
|
const pump = (async () => {
|
|
392
385
|
try {
|
|
393
|
-
for await (const fragment of context.text)
|
|
386
|
+
for await (const fragment of context.text) {
|
|
394
387
|
duplex.write({ text: fragment });
|
|
388
|
+
}
|
|
395
389
|
duplex.end();
|
|
396
390
|
}
|
|
397
391
|
catch {
|
|
@@ -400,12 +394,11 @@ export class RemoteHarness extends EventEmitter {
|
|
|
400
394
|
})();
|
|
401
395
|
try {
|
|
402
396
|
for await (const frame of frames(duplex)) {
|
|
403
|
-
|
|
404
|
-
yield { audio: chunk.audio, sampleRate: chunk.sampleRate };
|
|
397
|
+
yield { audio: frame.audio, sampleRate: frame.sampleRate };
|
|
405
398
|
}
|
|
406
399
|
}
|
|
407
400
|
finally {
|
|
408
|
-
await pump.catch(
|
|
401
|
+
await pump.catch(noop);
|
|
409
402
|
}
|
|
410
403
|
}
|
|
411
404
|
async getEmbeddingDevice() {
|
|
@@ -424,6 +417,10 @@ export class RemoteHarness extends EventEmitter {
|
|
|
424
417
|
const { client } = await this._ensure();
|
|
425
418
|
await client.setSkillSettings({ entries });
|
|
426
419
|
}
|
|
420
|
+
async setModelIdleTimeout(ms) {
|
|
421
|
+
const { client } = await this._ensure();
|
|
422
|
+
await client.setModelIdleTimeout({ ms });
|
|
423
|
+
}
|
|
427
424
|
async listManagedSkills() {
|
|
428
425
|
const { client } = await this._ensure();
|
|
429
426
|
const response = await client.listManagedSkills({});
|
|
@@ -491,7 +488,7 @@ export class RemoteHarness extends EventEmitter {
|
|
|
491
488
|
binary.bin,
|
|
492
489
|
{
|
|
493
490
|
min: minVersion,
|
|
494
|
-
|
|
491
|
+
command: binary.command || undefined
|
|
495
492
|
}
|
|
496
493
|
]
|
|
497
494
|
]
|
|
@@ -505,22 +502,20 @@ export class RemoteHarness extends EventEmitter {
|
|
|
505
502
|
allowList: skill.allowList ?? [],
|
|
506
503
|
platform: skill.platforms ?? [],
|
|
507
504
|
status: parseSkillState(skill.status),
|
|
508
|
-
|
|
505
|
+
requires: skill.requirements
|
|
509
506
|
? {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
...(Object.keys(binMinVersions).length > 0 ? { binMinVersions } : {})
|
|
516
|
-
}
|
|
507
|
+
bins: binaries.map((binary) => binary.bin),
|
|
508
|
+
credentials: skill.requirements.credentials?.length
|
|
509
|
+
? skill.requirements.credentials
|
|
510
|
+
: undefined,
|
|
511
|
+
binMinVersions: Object.keys(binMinVersions).length > 0 ? binMinVersions : undefined
|
|
517
512
|
}
|
|
518
|
-
:
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
513
|
+
: undefined,
|
|
514
|
+
install,
|
|
515
|
+
setup,
|
|
516
|
+
stub: skill.stub === true ? true : undefined,
|
|
517
|
+
minCapabilityProfile: skill.minCapabilityProfile || undefined,
|
|
518
|
+
emoji: skill.emoji || undefined
|
|
524
519
|
};
|
|
525
520
|
});
|
|
526
521
|
}
|
|
@@ -542,24 +537,25 @@ export class RemoteHarness extends EventEmitter {
|
|
|
542
537
|
const { client } = await this._ensure();
|
|
543
538
|
await abortable(client.warmModel({
|
|
544
539
|
model: context.model,
|
|
545
|
-
|
|
540
|
+
agent: context.agent ? knobs(context.agent) : undefined
|
|
546
541
|
}), context.signal);
|
|
547
542
|
}
|
|
548
543
|
async list(options = {}) {
|
|
549
544
|
const { client } = await this._ensure();
|
|
550
|
-
const response =
|
|
545
|
+
const response = await client.listModels({
|
|
551
546
|
type: options.type,
|
|
552
547
|
cachedOnly: options.cachedOnly,
|
|
553
548
|
fullRegistry: options.fullRegistry
|
|
554
|
-
})
|
|
555
|
-
return (response.models ?? []).map(({ actualSize, ...row }) => ({
|
|
549
|
+
});
|
|
550
|
+
return (response.models ?? []).map(({ actualSize, label, ...row }) => ({
|
|
556
551
|
...row,
|
|
557
|
-
|
|
552
|
+
actualSize: actualSize || undefined,
|
|
553
|
+
label: label || undefined
|
|
558
554
|
}));
|
|
559
555
|
}
|
|
560
556
|
async deleteModel(name) {
|
|
561
557
|
const { client } = await this._ensure();
|
|
562
|
-
const response =
|
|
558
|
+
const response = await client.deleteModel({ name });
|
|
563
559
|
return { name: response.name, removed: response.removed, freedBytes: response.freedBytes };
|
|
564
560
|
}
|
|
565
561
|
async clearKvCache() {
|
|
@@ -572,11 +568,13 @@ export class RemoteHarness extends EventEmitter {
|
|
|
572
568
|
try {
|
|
573
569
|
const { client } = await this._ensure();
|
|
574
570
|
const info = await client.describe({});
|
|
575
|
-
if (info.supportsKvCacheDeletion !== true)
|
|
571
|
+
if (info.supportsKvCacheDeletion !== true) {
|
|
576
572
|
return unsupportedKvCacheDeletion();
|
|
573
|
+
}
|
|
577
574
|
const response = await call(client);
|
|
578
|
-
if (response.status === 'success')
|
|
575
|
+
if (response.status === 'success') {
|
|
579
576
|
return { status: 'success' };
|
|
577
|
+
}
|
|
580
578
|
if (response.status === 'failure') {
|
|
581
579
|
return { status: 'failure', error: response.error ?? 'Harness cache deletion failed' };
|
|
582
580
|
}
|
|
@@ -585,13 +583,13 @@ export class RemoteHarness extends EventEmitter {
|
|
|
585
583
|
catch (error) {
|
|
586
584
|
return {
|
|
587
585
|
status: 'failure',
|
|
588
|
-
error:
|
|
586
|
+
error: errorMessage(error)
|
|
589
587
|
};
|
|
590
588
|
}
|
|
591
589
|
}
|
|
592
590
|
async infraModels(profile) {
|
|
593
591
|
const { client } = await this._ensure();
|
|
594
|
-
const response =
|
|
592
|
+
const response = await client.infraModels({ profile });
|
|
595
593
|
return response.models ?? [];
|
|
596
594
|
}
|
|
597
595
|
async capability() {
|
|
@@ -601,16 +599,14 @@ export class RemoteHarness extends EventEmitter {
|
|
|
601
599
|
return {
|
|
602
600
|
capabilityProfile: response.capabilityProfile,
|
|
603
601
|
recommendedModelName: response.recommendedModelName,
|
|
604
|
-
|
|
602
|
+
memoryBudget: memoryBudget
|
|
605
603
|
? {
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
...(memoryBudget.gpuClass ? { gpuClass: memoryBudget.gpuClass } : {})
|
|
611
|
-
}
|
|
604
|
+
totalBytes: memoryBudget.totalBytes,
|
|
605
|
+
availableBytes: memoryBudget.availableBytes,
|
|
606
|
+
source: memoryBudget.source,
|
|
607
|
+
gpuClass: memoryBudget.gpuClass || undefined
|
|
612
608
|
}
|
|
613
|
-
:
|
|
609
|
+
: undefined
|
|
614
610
|
};
|
|
615
611
|
}
|
|
616
612
|
close() {
|
|
@@ -620,8 +616,9 @@ export class RemoteHarness extends EventEmitter {
|
|
|
620
616
|
async describe() {
|
|
621
617
|
const { client } = await this._ensure();
|
|
622
618
|
const describe = client.describe;
|
|
623
|
-
if (!describe)
|
|
619
|
+
if (!describe) {
|
|
624
620
|
return null;
|
|
621
|
+
}
|
|
625
622
|
const info = await describe.call(client, {});
|
|
626
623
|
return {
|
|
627
624
|
toolNames: info?.toolNames ?? [],
|
|
@@ -632,12 +629,14 @@ export class RemoteHarness extends EventEmitter {
|
|
|
632
629
|
}
|
|
633
630
|
async fetchDiagnostics() {
|
|
634
631
|
const session = this._session;
|
|
635
|
-
if (!session || session.dead)
|
|
632
|
+
if (!session || session.dead) {
|
|
636
633
|
return null;
|
|
634
|
+
}
|
|
637
635
|
const client = session.client;
|
|
638
636
|
const diagnostics = client.diagnostics;
|
|
639
|
-
if (!diagnostics)
|
|
637
|
+
if (!diagnostics) {
|
|
640
638
|
return null;
|
|
639
|
+
}
|
|
641
640
|
const snapshot = await diagnostics.call(client, {});
|
|
642
641
|
const device = snapshot?.device;
|
|
643
642
|
return {
|
|
@@ -646,7 +645,7 @@ export class RemoteHarness extends EventEmitter {
|
|
|
646
645
|
sdkLoaded: snapshot?.sdkLoaded ?? false,
|
|
647
646
|
toolNames: snapshot?.toolNames ?? [],
|
|
648
647
|
skills: snapshot?.skills ?? [],
|
|
649
|
-
|
|
648
|
+
device: device || undefined
|
|
650
649
|
};
|
|
651
650
|
}
|
|
652
651
|
}
|
|
@@ -656,10 +655,11 @@ function parseSkillState(value) {
|
|
|
656
655
|
function errorDetails(err) {
|
|
657
656
|
return { error: errorMessage(err), code: errorCode(err) };
|
|
658
657
|
}
|
|
658
|
+
function isToolCallDisplay(value) {
|
|
659
|
+
return isRecord(value) && typeof value.label === 'string';
|
|
660
|
+
}
|
|
659
661
|
function died(message) {
|
|
660
|
-
|
|
661
|
-
err.code = HARNESS_DIED;
|
|
662
|
-
return err;
|
|
662
|
+
return Object.assign(new Error(message), { code: HARNESS_DIED });
|
|
663
663
|
}
|
|
664
664
|
const noop = () => { };
|
|
665
665
|
function abortable(promise, signal) {
|
|
@@ -700,8 +700,9 @@ function knobs(agent) {
|
|
|
700
700
|
}
|
|
701
701
|
async function bridgeAttach(event, attach) {
|
|
702
702
|
try {
|
|
703
|
-
if (!attach)
|
|
703
|
+
if (!attach) {
|
|
704
704
|
return { type: 'attach-result', message: 'the host cannot persist attachments' };
|
|
705
|
+
}
|
|
705
706
|
const bytes = await fs.promises.readFile(event.path ?? '');
|
|
706
707
|
const record = await attach({
|
|
707
708
|
fileName: event.fileName ?? '',
|
|
@@ -720,11 +721,12 @@ async function bridgeAttach(event, attach) {
|
|
|
720
721
|
};
|
|
721
722
|
}
|
|
722
723
|
catch (err) {
|
|
723
|
-
return { type: 'attach-result', message: err
|
|
724
|
+
return { type: 'attach-result', message: errorMessage(err) };
|
|
724
725
|
}
|
|
725
726
|
finally {
|
|
726
|
-
if (event.path)
|
|
727
|
+
if (event.path) {
|
|
727
728
|
void fs.promises.unlink(event.path).catch(noop);
|
|
729
|
+
}
|
|
728
730
|
}
|
|
729
731
|
}
|
|
730
732
|
async function bridgeFetch(event, context, staged) {
|
|
@@ -735,11 +737,12 @@ async function bridgeFetch(event, context, staged) {
|
|
|
735
737
|
const metaOnly = event.meta === true;
|
|
736
738
|
const found = await context.fetchAttachment({
|
|
737
739
|
attachmentId: event.attachmentId ?? undefined,
|
|
738
|
-
|
|
740
|
+
meta: metaOnly ? true : undefined,
|
|
739
741
|
signal: context.signal
|
|
740
742
|
});
|
|
741
|
-
if (!found)
|
|
743
|
+
if (!found) {
|
|
742
744
|
return { type: 'fetch-result' };
|
|
745
|
+
}
|
|
743
746
|
const size = 'bytes' in found && found.bytes !== null ? found.bytes.byteLength : found.byteLength;
|
|
744
747
|
if (metaOnly) {
|
|
745
748
|
return {
|
|
@@ -766,20 +769,55 @@ async function bridgeFetch(event, context, staged) {
|
|
|
766
769
|
};
|
|
767
770
|
}
|
|
768
771
|
catch (err) {
|
|
769
|
-
return { type: 'fetch-result', message: err
|
|
772
|
+
return { type: 'fetch-result', message: errorMessage(err) };
|
|
770
773
|
}
|
|
771
774
|
}
|
|
775
|
+
const DriveRequestSchema = z.discriminatedUnion('op', [
|
|
776
|
+
z.looseObject({ op: z.literal('entry'), driveKey: z.string(), key: z.string() }),
|
|
777
|
+
z.looseObject({ op: z.literal('get'), driveKey: z.string(), key: z.string() }),
|
|
778
|
+
z.looseObject({ op: z.literal('read'), driveKey: z.string(), key: z.string() }),
|
|
779
|
+
z.looseObject({
|
|
780
|
+
op: z.literal('list'),
|
|
781
|
+
driveKey: z.string(),
|
|
782
|
+
folder: z.string(),
|
|
783
|
+
skip: z.array(z.string()),
|
|
784
|
+
limit: z.number(),
|
|
785
|
+
cursor: z.string().nullable()
|
|
786
|
+
}),
|
|
787
|
+
z.looseObject({
|
|
788
|
+
op: z.literal('write'),
|
|
789
|
+
driveKey: z.string(),
|
|
790
|
+
key: z.string(),
|
|
791
|
+
path: z.string(),
|
|
792
|
+
executable: z.boolean().optional()
|
|
793
|
+
})
|
|
794
|
+
]);
|
|
772
795
|
async function bridgeDrive(event, context) {
|
|
773
|
-
if (!context.driveOp)
|
|
796
|
+
if (!context.driveOp) {
|
|
774
797
|
return { type: 'drive-result', message: 'the host cannot proxy drives' };
|
|
798
|
+
}
|
|
775
799
|
try {
|
|
776
|
-
const payload = await context.driveOp(event.payload);
|
|
800
|
+
const payload = await context.driveOp(DriveRequestSchema.parse(event.payload));
|
|
777
801
|
return { type: 'drive-result', payload };
|
|
778
802
|
}
|
|
779
803
|
catch (err) {
|
|
780
|
-
return { type: 'drive-result', message:
|
|
804
|
+
return { type: 'drive-result', message: errorMessage(err) };
|
|
781
805
|
}
|
|
782
806
|
}
|
|
807
|
+
function answerQuestion(event, { askUser, reply }) {
|
|
808
|
+
const callId = event.callId;
|
|
809
|
+
if (!askUser) {
|
|
810
|
+
reply({ type: 'question-result', callId, message: 'the host cannot ask questions' });
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
void Promise.resolve()
|
|
814
|
+
.then(() => askUser({
|
|
815
|
+
question: event.question ?? '',
|
|
816
|
+
options: Array.isArray(event.options) ? event.options.map(String) : undefined
|
|
817
|
+
}))
|
|
818
|
+
.then((answer) => reply({ type: 'question-result', callId, answer: answer ?? '' }), (err) => reply({ type: 'question-result', callId, message: errorMessage(err) }))
|
|
819
|
+
.catch((err) => hlog('question reply failed', { callId, message: errorMessage(err) }));
|
|
820
|
+
}
|
|
783
821
|
async function bridgeRag(event, context) {
|
|
784
822
|
if (!context.ragSearch) {
|
|
785
823
|
return {
|
|
@@ -795,7 +833,7 @@ async function bridgeRag(event, context) {
|
|
|
795
833
|
return { type: 'rag-result', result };
|
|
796
834
|
}
|
|
797
835
|
catch (err) {
|
|
798
|
-
return { type: 'rag-result', message:
|
|
836
|
+
return { type: 'rag-result', message: errorMessage(err) };
|
|
799
837
|
}
|
|
800
838
|
}
|
|
801
839
|
async function* frames(stream) {
|
|
@@ -816,8 +854,9 @@ async function* frames(stream) {
|
|
|
816
854
|
queue.end();
|
|
817
855
|
});
|
|
818
856
|
yield* queue;
|
|
819
|
-
if (error)
|
|
857
|
+
if (error) {
|
|
820
858
|
throw error;
|
|
859
|
+
}
|
|
821
860
|
}
|
|
822
861
|
async function* downloadFrames(stream) {
|
|
823
862
|
const queue = pushQueue();
|
|
@@ -830,6 +869,7 @@ async function* downloadFrames(stream) {
|
|
|
830
869
|
queue.end();
|
|
831
870
|
});
|
|
832
871
|
yield* queue;
|
|
833
|
-
if (error)
|
|
872
|
+
if (error) {
|
|
834
873
|
throw error;
|
|
874
|
+
}
|
|
835
875
|
}
|