@qvac/harness 0.4.0 → 0.6.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 +740 -141
- package/README.md +75 -7
- package/dist/harness.bundle +72 -50
- package/dist-lib/index.d.ts +49 -39
- package/dist-lib/index.js +448 -161
- 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 +13 -32
- package/dist-lib/lib/connect.js +170 -112
- package/dist-lib/lib/context-window.js +25 -21
- package/dist-lib/lib/contract-types.d.ts +35 -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 +15 -20
- package/dist-lib/lib/models/model-catalog.js +66 -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 +48 -10
- package/dist-lib/lib/models/model-pool.js +106 -45
- 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 +122 -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 +39 -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 +9 -0
- package/dist-lib/spec/calls.js +3 -0
- package/dist-lib/spec/hrpc/hrpc.json +39 -0
- package/dist-lib/spec/hrpc/index.js +39 -3
- package/dist-lib/spec/hrpc/messages.js +105 -8
- package/dist-lib/spec/hyperschema/index.js +105 -8
- package/dist-lib/spec/hyperschema/schema.json +77 -1
- package/dist-lib/spec/hyperschema/types.d.ts +25 -1
- package/package.json +14 -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
|
@@ -4,12 +4,12 @@ import { type DiffusionRuntime } from './generate-image.ts';
|
|
|
4
4
|
interface Rgba {
|
|
5
5
|
width: number;
|
|
6
6
|
height: number;
|
|
7
|
-
data:
|
|
7
|
+
data: Uint8Array;
|
|
8
8
|
frames?: Rgba[];
|
|
9
9
|
}
|
|
10
10
|
interface Media {
|
|
11
11
|
image: {
|
|
12
|
-
decode(input:
|
|
12
|
+
decode(input: Uint8Array, opts?: {
|
|
13
13
|
maxFrames?: number;
|
|
14
14
|
}): Promise<Rgba>;
|
|
15
15
|
encode(rgba: Rgba, opts: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import b4a from 'b4a';
|
|
1
2
|
import fs from 'fs';
|
|
2
3
|
import path from 'path';
|
|
3
4
|
import { AbortedError } from '../helpers/race-abort.js';
|
|
@@ -11,13 +12,14 @@ async function turnSources(turnImages) {
|
|
|
11
12
|
const sources = [];
|
|
12
13
|
for (const image of turnImages) {
|
|
13
14
|
const bytes = await fs.promises.readFile(image.path).catch(toNull);
|
|
14
|
-
if (!bytes)
|
|
15
|
+
if (!bytes) {
|
|
15
16
|
return { error: `could not read attached image ${path.basename(image.path)}` };
|
|
17
|
+
}
|
|
16
18
|
sources.push({ bytes, fileName: path.basename(image.path) });
|
|
17
19
|
}
|
|
18
20
|
return sources;
|
|
19
21
|
}
|
|
20
|
-
async function resolveSources(fetchAttachment, ids, turnImages, signal) {
|
|
22
|
+
async function resolveSources(fetchAttachment, { ids, turnImages, signal }) {
|
|
21
23
|
if (!ids.length) {
|
|
22
24
|
if (turnImages.length) {
|
|
23
25
|
const sources = await turnSources(turnImages);
|
|
@@ -33,13 +35,16 @@ async function resolveSources(fetchAttachment, ids, turnImages, signal) {
|
|
|
33
35
|
const missing = [];
|
|
34
36
|
for (const id of ids) {
|
|
35
37
|
const found = await fetchAttachment({ attachmentId: id, signal });
|
|
36
|
-
if (found && 'bytes' in found && found.bytes)
|
|
38
|
+
if (found && 'bytes' in found && found.bytes) {
|
|
37
39
|
sources.push(found);
|
|
38
|
-
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
39
42
|
missing.push(id);
|
|
43
|
+
}
|
|
40
44
|
}
|
|
41
|
-
if (!missing.length)
|
|
45
|
+
if (!missing.length) {
|
|
42
46
|
return { sources };
|
|
47
|
+
}
|
|
43
48
|
if (sources.length) {
|
|
44
49
|
return {
|
|
45
50
|
sources,
|
|
@@ -48,8 +53,9 @@ async function resolveSources(fetchAttachment, ids, turnImages, signal) {
|
|
|
48
53
|
}
|
|
49
54
|
if (turnImages.length) {
|
|
50
55
|
const fallback = await turnSources(turnImages);
|
|
51
|
-
if ('error' in fallback)
|
|
56
|
+
if ('error' in fallback) {
|
|
52
57
|
return fallback;
|
|
58
|
+
}
|
|
53
59
|
return {
|
|
54
60
|
sources: fallback,
|
|
55
61
|
note: `ignored unknown attachment id(s) ${missing.join(', ')} — edited the image(s) from the user's latest message`
|
|
@@ -62,7 +68,7 @@ async function resolveSources(fetchAttachment, ids, turnImages, signal) {
|
|
|
62
68
|
}
|
|
63
69
|
async function defaultLoadMedia() {
|
|
64
70
|
try {
|
|
65
|
-
return
|
|
71
|
+
return await import('bare-media');
|
|
66
72
|
}
|
|
67
73
|
catch {
|
|
68
74
|
return null;
|
|
@@ -129,8 +135,9 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
|
|
|
129
135
|
}),
|
|
130
136
|
execute: async (args, ctx) => {
|
|
131
137
|
const common = parseCommonArgs(args, cap.maxSteps);
|
|
132
|
-
if ('error' in common)
|
|
138
|
+
if ('error' in common) {
|
|
133
139
|
return common;
|
|
140
|
+
}
|
|
134
141
|
let strength = DEFAULT_STRENGTH;
|
|
135
142
|
if (args.strength !== undefined && args.strength !== null) {
|
|
136
143
|
strength = Number(args.strength);
|
|
@@ -144,15 +151,17 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
|
|
|
144
151
|
const attachmentIds = [];
|
|
145
152
|
if (Array.isArray(args.attachment_ids)) {
|
|
146
153
|
for (const id of args.attachment_ids) {
|
|
147
|
-
if (typeof id === 'string' && id)
|
|
154
|
+
if (typeof id === 'string' && id) {
|
|
148
155
|
attachmentIds.push(id);
|
|
156
|
+
}
|
|
149
157
|
}
|
|
150
158
|
}
|
|
151
159
|
if (attachmentId && attachmentIds.length) {
|
|
152
160
|
return { error: 'pass attachment_id or attachment_ids, not both' };
|
|
153
161
|
}
|
|
154
|
-
if (attachmentId)
|
|
162
|
+
if (attachmentId) {
|
|
155
163
|
attachmentIds.push(attachmentId);
|
|
164
|
+
}
|
|
156
165
|
if (!ctx?.attach || !ctx.fetchAttachment) {
|
|
157
166
|
return { error: 'this device cannot edit chat images' };
|
|
158
167
|
}
|
|
@@ -161,16 +170,24 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
|
|
|
161
170
|
if (!attachmentIds.length && turnImages.length > 1 && !inContext) {
|
|
162
171
|
return { error: MULTI_SOURCE_UNSUPPORTED };
|
|
163
172
|
}
|
|
164
|
-
const resolved = await resolveSources(ctx.fetchAttachment,
|
|
165
|
-
|
|
173
|
+
const resolved = await resolveSources(ctx.fetchAttachment, {
|
|
174
|
+
ids: attachmentIds,
|
|
175
|
+
turnImages,
|
|
176
|
+
signal: ctx.signal
|
|
177
|
+
});
|
|
178
|
+
if (ctx.signal?.aborted) {
|
|
166
179
|
return { error: 'image generation canceled' };
|
|
167
|
-
|
|
180
|
+
}
|
|
181
|
+
if ('error' in resolved) {
|
|
168
182
|
return resolved;
|
|
183
|
+
}
|
|
169
184
|
const { sources, note } = resolved;
|
|
170
|
-
if (sources.length > 1 && !inContext)
|
|
185
|
+
if (sources.length > 1 && !inContext) {
|
|
171
186
|
return { error: MULTI_SOURCE_UNSUPPORTED };
|
|
172
|
-
|
|
187
|
+
}
|
|
188
|
+
if (!runtime.acquire()) {
|
|
173
189
|
return { error: BUSY_ERROR, code: 'busy' };
|
|
190
|
+
}
|
|
174
191
|
const report = ctx.progress;
|
|
175
192
|
const onTick = report && generationPercentTick((percentage) => report({ percentage }), sources.length);
|
|
176
193
|
try {
|
|
@@ -186,7 +203,7 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
|
|
|
186
203
|
for (const source of sources) {
|
|
187
204
|
let decoded;
|
|
188
205
|
try {
|
|
189
|
-
decoded = await media.image.decode(
|
|
206
|
+
decoded = await media.image.decode(b4a.from(source.bytes), { maxFrames: 1 });
|
|
190
207
|
}
|
|
191
208
|
catch {
|
|
192
209
|
return { error: `could not decode ${source.fileName} as an image` };
|
|
@@ -198,7 +215,7 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
|
|
|
198
215
|
const fitted = frame.width === fitWidth && frame.height === fitHeight
|
|
199
216
|
? frame
|
|
200
217
|
: await resample(frame, fitWidth, fitHeight);
|
|
201
|
-
inits.push(
|
|
218
|
+
inits.push(b4a.from(await media.image.encode(fitted, { mimetype: 'image/png' })));
|
|
202
219
|
if (!width) {
|
|
203
220
|
width = fitWidth;
|
|
204
221
|
height = fitHeight;
|
|
@@ -207,24 +224,30 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
|
|
|
207
224
|
const sdk = await runtime.loadSdk();
|
|
208
225
|
const { modelId } = await runtime.ensureLoaded(sdk, ctx.signal, ctx.image?.modelChoice);
|
|
209
226
|
const fusion = inits.length > 1;
|
|
210
|
-
const image = await runDiffusion(sdk,
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
+
const image = await runDiffusion(sdk, {
|
|
228
|
+
modelId,
|
|
229
|
+
params: {
|
|
230
|
+
prompt: common.prompt,
|
|
231
|
+
width,
|
|
232
|
+
height,
|
|
233
|
+
steps: effectiveSteps(common.steps, ctx.image?.steps, stepsCap),
|
|
234
|
+
seed: common.seed,
|
|
235
|
+
negative_prompt: common.negativePrompt,
|
|
236
|
+
...(inContext
|
|
237
|
+
? {
|
|
238
|
+
init_images: inits,
|
|
239
|
+
auto_resize_ref_image: true,
|
|
240
|
+
guidance: FLUX2_GUIDANCE,
|
|
241
|
+
cfg_scale: FLUX2_CFG_SCALE
|
|
242
|
+
}
|
|
243
|
+
: { init_image: inits[0], strength })
|
|
244
|
+
},
|
|
245
|
+
signal: ctx.signal,
|
|
246
|
+
onTick
|
|
247
|
+
});
|
|
248
|
+
if (!(image instanceof Uint8Array)) {
|
|
227
249
|
return image;
|
|
250
|
+
}
|
|
228
251
|
const record = await ctx.attach({
|
|
229
252
|
fileName: `edited-${Date.now()}.png`,
|
|
230
253
|
mimeType: 'image/png',
|
|
@@ -244,7 +267,7 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
|
|
|
244
267
|
...(sources.length === 1 && sources[0].id
|
|
245
268
|
? { sourceAttachmentId: sources[0].id }
|
|
246
269
|
: { sourceFileNames: sources.map((source) => source.fileName) }),
|
|
247
|
-
|
|
270
|
+
note: notes.length ? notes.join('; ') : undefined,
|
|
248
271
|
fileName: record.fileName,
|
|
249
272
|
byteLength: record.byteLength,
|
|
250
273
|
width,
|
|
@@ -252,8 +275,9 @@ export function createEditImageTool(runtime, { loadMedia = defaultLoadMedia, res
|
|
|
252
275
|
};
|
|
253
276
|
}
|
|
254
277
|
catch (err) {
|
|
255
|
-
if (err instanceof AbortedError)
|
|
278
|
+
if (err instanceof AbortedError) {
|
|
256
279
|
return { error: 'image generation canceled' };
|
|
280
|
+
}
|
|
257
281
|
if (err instanceof Error && err.message === IMAGE_LOAD_STALL_ERROR) {
|
|
258
282
|
return { error: IMAGE_LOAD_STALL_ERROR };
|
|
259
283
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import type { AbortSignal as BareAbortSignal } from 'bare-abort-controller';
|
|
2
2
|
import type { AttachFn, FetchAttachmentFn, RunBudget, ToolDecision } from '../../../capabilities/completion.ts';
|
|
3
3
|
import type { ExecResult } from '../runner.ts';
|
|
4
|
-
export
|
|
4
|
+
export interface ExecutionOptions {
|
|
5
5
|
readonly cwd?: string;
|
|
6
6
|
readonly env?: Readonly<Record<string, string>>;
|
|
7
7
|
readonly timeoutMs?: number;
|
|
8
8
|
readonly maxOutputChars?: number;
|
|
9
9
|
readonly signal?: BareAbortSignal;
|
|
10
|
-
}
|
|
11
|
-
export
|
|
10
|
+
}
|
|
11
|
+
export interface ExecutionContext {
|
|
12
12
|
readonly attach?: AttachFn;
|
|
13
13
|
readonly fetchAttachment?: FetchAttachmentFn;
|
|
14
14
|
readonly turnImages?: readonly {
|
|
@@ -19,13 +19,13 @@ export type ExecutionContext = {
|
|
|
19
19
|
readonly toolNames?: readonly string[];
|
|
20
20
|
readonly approval?: ToolDecision;
|
|
21
21
|
readonly confirmConnect?: (host: string) => Promise<boolean>;
|
|
22
|
-
}
|
|
23
|
-
export
|
|
22
|
+
}
|
|
23
|
+
export interface ExecutionPlan {
|
|
24
24
|
run(options: ExecutionOptions): Promise<ExecResult> | ExecResult;
|
|
25
|
-
}
|
|
26
|
-
export
|
|
25
|
+
}
|
|
26
|
+
export interface ExecutionAdapter {
|
|
27
27
|
resolve(args: Record<string, unknown>, ctx?: ExecutionContext): ExecutionPlan | null;
|
|
28
|
-
}
|
|
29
|
-
export
|
|
28
|
+
}
|
|
29
|
+
export interface FallbackExecutionAdapter {
|
|
30
30
|
resolve(args: Record<string, unknown>, ctx?: ExecutionContext): ExecutionPlan;
|
|
31
|
-
}
|
|
31
|
+
}
|
|
@@ -1,26 +1,32 @@
|
|
|
1
1
|
import type { AbortSignal as BareAbortSignal } from 'bare-abort-controller';
|
|
2
2
|
import type { AttachFn, FetchAttachmentFn, RunBudget } from '../../../../capabilities/completion.ts';
|
|
3
3
|
import type { ExecAttachment, RejectedOutput } from '../../runner.ts';
|
|
4
|
-
|
|
4
|
+
import { type ExecError } from './output-policy.ts';
|
|
5
|
+
export interface ExecInput {
|
|
5
6
|
readonly attachmentId?: string;
|
|
6
7
|
readonly path: string;
|
|
7
|
-
}
|
|
8
|
-
export
|
|
8
|
+
}
|
|
9
|
+
export interface StagedInput {
|
|
9
10
|
readonly path: string;
|
|
10
11
|
readonly bytes: Uint8Array;
|
|
11
|
-
}
|
|
12
|
-
export
|
|
12
|
+
}
|
|
13
|
+
export interface StageInputsOptions {
|
|
13
14
|
turnImages?: readonly {
|
|
14
15
|
path: string;
|
|
15
16
|
}[];
|
|
16
17
|
signal?: BareAbortSignal;
|
|
17
|
-
}
|
|
18
|
+
}
|
|
19
|
+
export interface StagedInputs {
|
|
18
20
|
files: readonly StagedInput[];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
}
|
|
22
|
+
export declare function stageInputs(fetchAttachment: FetchAttachmentFn, inputs: readonly ExecInput[], opts?: StageInputsOptions): Promise<StagedInputs | ExecError>;
|
|
23
|
+
export interface AttachOutputsOptions {
|
|
24
|
+
readonly declared: readonly string[];
|
|
25
|
+
readonly runBudget?: RunBudget | undefined;
|
|
26
|
+
}
|
|
27
|
+
export interface AttachedOutputs {
|
|
23
28
|
attachments: readonly ExecAttachment[];
|
|
24
29
|
missingOutputs: readonly string[];
|
|
25
30
|
rejectedOutputs: readonly RejectedOutput[];
|
|
26
|
-
}
|
|
31
|
+
}
|
|
32
|
+
export declare function attachOutputs(attach: AttachFn, files: ReadonlyMap<string, Uint8Array>, { declared, runBudget }: AttachOutputsOptions): Promise<AttachedOutputs>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { errorMessage } from '../../../../guards.js';
|
|
3
4
|
import { hlog } from '../../../../log.js';
|
|
4
5
|
import { checkOutputBytes, MAX_INPUT_TOTAL_BYTES, RUN_OUTPUT_BUDGET_BYTES } from './output-policy.js';
|
|
5
6
|
const STAGE_TIMEOUT_MS = 60_000;
|
|
@@ -15,8 +16,9 @@ function bounded(work, ms, message) {
|
|
|
15
16
|
timer = setTimeout(() => reject(new Error(message)), ms);
|
|
16
17
|
});
|
|
17
18
|
return Promise.race([work, bound]).finally(() => {
|
|
18
|
-
if (timer)
|
|
19
|
+
if (timer) {
|
|
19
20
|
clearTimeout(timer);
|
|
21
|
+
}
|
|
20
22
|
});
|
|
21
23
|
}
|
|
22
24
|
function hasBytes(record) {
|
|
@@ -25,12 +27,13 @@ function hasBytes(record) {
|
|
|
25
27
|
function byteLengthOf(record) {
|
|
26
28
|
return hasBytes(record) ? record.bytes.byteLength : record.byteLength;
|
|
27
29
|
}
|
|
28
|
-
async function uploadedBytes(fetchAttachment,
|
|
30
|
+
async function uploadedBytes(fetchAttachment, index, { turnImages, signal }) {
|
|
29
31
|
const image = turnImages[index];
|
|
30
32
|
if (image) {
|
|
31
33
|
const bytes = await fs.promises.readFile(image.path).catch(toNull);
|
|
32
|
-
if (!bytes)
|
|
34
|
+
if (!bytes) {
|
|
33
35
|
return { error: `could not read attached image ${path.basename(image.path)}` };
|
|
36
|
+
}
|
|
34
37
|
return bytes;
|
|
35
38
|
}
|
|
36
39
|
if (turnImages.length) {
|
|
@@ -38,13 +41,32 @@ async function uploadedBytes(fetchAttachment, turnImages, index, signal) {
|
|
|
38
41
|
error: `the user's latest message has only ${turnImages.length} image(s) — one id-less input per uploaded image`
|
|
39
42
|
};
|
|
40
43
|
}
|
|
41
|
-
if (index > 0)
|
|
44
|
+
if (index > 0) {
|
|
42
45
|
return { error: NO_UPLOAD_ERROR };
|
|
46
|
+
}
|
|
43
47
|
const latest = await fetchAttachment({ signal });
|
|
44
|
-
if (!latest || !hasBytes(latest))
|
|
48
|
+
if (!latest || !hasBytes(latest)) {
|
|
45
49
|
return { error: NO_UPLOAD_ERROR };
|
|
50
|
+
}
|
|
46
51
|
return latest.bytes;
|
|
47
52
|
}
|
|
53
|
+
async function probeUpload(fetchAttachment, input, { index, turnImages, signal, deadline }) {
|
|
54
|
+
if (DOCUMENT_INPUT.test(input.path)) {
|
|
55
|
+
return { error: NO_DOCUMENT_ERROR };
|
|
56
|
+
}
|
|
57
|
+
const bytes = await bounded(uploadedBytes(fetchAttachment, index, { turnImages, signal }), deadline - Date.now(), STAGE_TIMEOUT_MESSAGE);
|
|
58
|
+
if ('error' in bytes) {
|
|
59
|
+
return bytes;
|
|
60
|
+
}
|
|
61
|
+
return { size: bytes.byteLength, bytes };
|
|
62
|
+
}
|
|
63
|
+
async function probeAttachment(fetchAttachment, id, { signal, deadline }) {
|
|
64
|
+
const head = await bounded(fetchAttachment({ attachmentId: id, meta: true, signal }), deadline - Date.now(), STAGE_TIMEOUT_MESSAGE);
|
|
65
|
+
if (!head) {
|
|
66
|
+
return { error: `attachment ${id} not found in this chat` };
|
|
67
|
+
}
|
|
68
|
+
return { size: byteLengthOf(head), bytes: hasBytes(head) ? head.bytes : null };
|
|
69
|
+
}
|
|
48
70
|
export async function stageInputs(fetchAttachment, inputs, opts = {}) {
|
|
49
71
|
const { turnImages = [], signal } = opts;
|
|
50
72
|
const files = inputs.map(() => null);
|
|
@@ -52,32 +74,21 @@ export async function stageInputs(fetchAttachment, inputs, opts = {}) {
|
|
|
52
74
|
const deadline = Date.now() + STAGE_TIMEOUT_MS;
|
|
53
75
|
let total = 0;
|
|
54
76
|
let uploads = 0;
|
|
55
|
-
for (
|
|
56
|
-
const input = inputs[i];
|
|
77
|
+
for (const [i, input] of inputs.entries()) {
|
|
57
78
|
const id = input.attachmentId;
|
|
58
79
|
try {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
cap: MAX_INPUT_TOTAL_BYTES,
|
|
70
|
-
count: inputs.length
|
|
71
|
-
});
|
|
72
|
-
return { error: OVER_BUDGET_ERROR };
|
|
73
|
-
}
|
|
74
|
-
files[i] = { path: input.path, bytes };
|
|
75
|
-
continue;
|
|
80
|
+
const probe = id === undefined
|
|
81
|
+
? await probeUpload(fetchAttachment, input, {
|
|
82
|
+
index: uploads++,
|
|
83
|
+
turnImages,
|
|
84
|
+
signal,
|
|
85
|
+
deadline
|
|
86
|
+
})
|
|
87
|
+
: await probeAttachment(fetchAttachment, id, { signal, deadline });
|
|
88
|
+
if ('error' in probe) {
|
|
89
|
+
return probe;
|
|
76
90
|
}
|
|
77
|
-
|
|
78
|
-
if (!head)
|
|
79
|
-
return { error: `attachment ${id} not found in this chat` };
|
|
80
|
-
total += byteLengthOf(head);
|
|
91
|
+
total += probe.size;
|
|
81
92
|
if (total > MAX_INPUT_TOTAL_BYTES) {
|
|
82
93
|
hlog('python: input attachments over budget; skipping blob download', {
|
|
83
94
|
total,
|
|
@@ -86,32 +97,33 @@ export async function stageInputs(fetchAttachment, inputs, opts = {}) {
|
|
|
86
97
|
});
|
|
87
98
|
return { error: OVER_BUDGET_ERROR };
|
|
88
99
|
}
|
|
89
|
-
if (
|
|
90
|
-
files[i] = { path: input.path, bytes:
|
|
91
|
-
|
|
92
|
-
|
|
100
|
+
if (probe.bytes !== null) {
|
|
101
|
+
files[i] = { path: input.path, bytes: probe.bytes };
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
pending.push({ index: i, input });
|
|
105
|
+
}
|
|
93
106
|
}
|
|
94
107
|
catch (error) {
|
|
95
|
-
return { error:
|
|
108
|
+
return { error: errorMessage(error) };
|
|
96
109
|
}
|
|
97
110
|
}
|
|
98
|
-
for (const
|
|
99
|
-
const input = inputs[i];
|
|
111
|
+
for (const { index, input } of pending) {
|
|
100
112
|
const id = input.attachmentId;
|
|
101
113
|
try {
|
|
102
114
|
const fetched = await bounded(fetchAttachment({ attachmentId: id, signal }), deadline - Date.now(), STAGE_TIMEOUT_MESSAGE);
|
|
103
115
|
if (!fetched || !hasBytes(fetched)) {
|
|
104
116
|
return { error: `attachment ${id} not found in this chat` };
|
|
105
117
|
}
|
|
106
|
-
files[
|
|
118
|
+
files[index] = { path: input.path, bytes: fetched.bytes };
|
|
107
119
|
}
|
|
108
120
|
catch (error) {
|
|
109
|
-
return { error:
|
|
121
|
+
return { error: errorMessage(error) };
|
|
110
122
|
}
|
|
111
123
|
}
|
|
112
|
-
return { files: files };
|
|
124
|
+
return { files: files.filter((file) => file !== null) };
|
|
113
125
|
}
|
|
114
|
-
export async function attachOutputs(attach, files, declared, runBudget) {
|
|
126
|
+
export async function attachOutputs(attach, files, { declared, runBudget }) {
|
|
115
127
|
const attachments = [];
|
|
116
128
|
const missingOutputs = [];
|
|
117
129
|
const rejectedOutputs = [];
|
|
@@ -145,8 +157,9 @@ export async function attachOutputs(attach, files, declared, runBudget) {
|
|
|
145
157
|
continue;
|
|
146
158
|
}
|
|
147
159
|
total += bytes.byteLength;
|
|
148
|
-
if (runBudget)
|
|
160
|
+
if (runBudget) {
|
|
149
161
|
runBudget.outputBytesUsed += bytes.byteLength;
|
|
162
|
+
}
|
|
150
163
|
attachments.push({
|
|
151
164
|
attachmentId: record.id,
|
|
152
165
|
fileName: record.fileName,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
interface SourceHalves {
|
|
2
2
|
code: string;
|
|
3
3
|
text: string;
|
|
4
|
-
}
|
|
4
|
+
}
|
|
5
5
|
export declare function splitPythonSource(source: string): SourceHalves | null;
|
|
6
6
|
export declare function pythonCreateEffect(args: Record<string, unknown>): 'read' | 'write';
|
|
7
7
|
export {};
|