@qvac/harness 0.3.1 → 0.3.3
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 +79 -1
- package/dist/harness.bundle +359 -175
- package/dist/prebuilds-manifest.json +8 -0
- package/dist-lib/lib/capabilities/completion.d.ts +2 -1
- package/dist-lib/lib/capabilities/completion.js +5 -6
- package/dist-lib/lib/tools/exec/adapters/adapter.d.ts +3 -1
- package/dist-lib/lib/tools/exec/adapters/python/guarded-fetch.d.ts +5 -0
- package/dist-lib/lib/tools/exec/adapters/python/guarded-fetch.js +28 -2
- package/dist-lib/lib/tools/exec/adapters/python/interrupt-timer.d.ts +5 -0
- package/dist-lib/lib/tools/exec/adapters/python/interrupt-timer.js +29 -0
- package/dist-lib/lib/tools/exec/adapters/python/named-hosts.d.ts +2 -0
- package/dist-lib/lib/tools/exec/adapters/python/named-hosts.js +15 -0
- package/dist-lib/lib/tools/exec/adapters/python/pyodide.d.ts +3 -1
- package/dist-lib/lib/tools/exec/adapters/python/pyodide.js +41 -7
- package/dist-lib/lib/tools/exec/adapters/python/python-adapter.js +9 -3
- package/dist-lib/lib/tools/exec/adapters/python/run-session.d.ts +2 -0
- package/dist-lib/lib/tools/exec/adapters/python/run-session.js +19 -11
- package/dist-lib/lib/tools/exec/adapters/python/worker/client.d.ts +2 -1
- package/dist-lib/lib/tools/exec/adapters/python/worker/client.js +16 -3
- package/dist-lib/lib/tools/exec/adapters/python/worker/entry.js +15 -2
- package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.d.ts +6 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.js +6 -2
- package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-bare.d.ts +1 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-bare.js +8 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.d.ts +1 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/spawn-node.js +8 -0
- package/dist-lib/lib/tools/exec.js +36 -3
- package/package.json +16 -7
- package/dist-lib/lib/capabilities/vision-history.d.ts +0 -3
- package/dist-lib/lib/capabilities/vision-history.js +0 -21
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import Channel from 'bare-channel';
|
|
2
2
|
import safetyCatch from 'safety-catch';
|
|
3
|
+
export function spawnInlineThread(source, data) {
|
|
4
|
+
const Thread = Bare.Thread;
|
|
5
|
+
const thread = new Thread('inline-thread.js', {
|
|
6
|
+
data,
|
|
7
|
+
source: `const data = Bare.Thread.self.data\n${source}`
|
|
8
|
+
});
|
|
9
|
+
return () => thread.join();
|
|
10
|
+
}
|
|
3
11
|
export function spawnPythonWorker(entry, data) {
|
|
4
12
|
const channel = new Channel();
|
|
5
13
|
const thread = new Bare.Thread(entry, { data: { handle: channel.handle, ...data } });
|
|
@@ -43,3 +43,11 @@ export function spawnPythonWorker(entry, data) {
|
|
|
43
43
|
unref: () => worker.unref()
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
|
+
export function spawnInlineThread(source, data) {
|
|
47
|
+
const worker = new Worker(`const data = require('worker_threads').workerData\n${source}`, {
|
|
48
|
+
eval: true,
|
|
49
|
+
workerData: data
|
|
50
|
+
});
|
|
51
|
+
worker.unref();
|
|
52
|
+
return () => { };
|
|
53
|
+
}
|
|
@@ -4,6 +4,7 @@ import { AbortedError } from '../helpers/race-abort.js';
|
|
|
4
4
|
import { spawnEnv } from '../helpers/spawn-path.js';
|
|
5
5
|
import { checkPdfBuildSource, checkBareLengthArgs, checkPptxBuildSource, checkPythonSource, checkUnstagedRead, createPythonAdapter, isPythonLanguage, parseInputs, parseOutputs, parsePackages, parseWorkdir, pinned, runsThroughPyodide, unwrapPythonSource } from './exec/adapters/python/python-adapter.js';
|
|
6
6
|
import { pythonCreateEffect } from './exec/adapters/python/create-effect.js';
|
|
7
|
+
import { namedHosts } from './exec/adapters/python/named-hosts.js';
|
|
7
8
|
import { pythonReachesNetwork } from './exec/adapters/python/net-shim.js';
|
|
8
9
|
import { createShellAdapter } from './exec/adapters/shell/shell-adapter.js';
|
|
9
10
|
import { routeObsidianCommand } from './exec/obsidian/route.js';
|
|
@@ -82,6 +83,34 @@ function checkFileArgs(args, python) {
|
|
|
82
83
|
function truncateLabel(text) {
|
|
83
84
|
return text.length > 120 ? `${text.slice(0, 120)}…` : text;
|
|
84
85
|
}
|
|
86
|
+
const CONNECT_ANSWER_MS = 60_000;
|
|
87
|
+
function connectAsker(askUser) {
|
|
88
|
+
return async (host) => {
|
|
89
|
+
let timer;
|
|
90
|
+
const late = new Promise((resolve) => {
|
|
91
|
+
timer = setTimeout(() => resolve(null), CONNECT_ANSWER_MS);
|
|
92
|
+
});
|
|
93
|
+
try {
|
|
94
|
+
const answer = await Promise.race([
|
|
95
|
+
askUser({
|
|
96
|
+
question: `This Python run wants to connect to ${host}, which its approved code does not name. Allow it for this run?`,
|
|
97
|
+
options: ['Allow', 'Deny']
|
|
98
|
+
}),
|
|
99
|
+
late
|
|
100
|
+
]);
|
|
101
|
+
return /^allow/i.test((answer ?? '').trim());
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
clearTimeout(timer);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function networkPrefix(source) {
|
|
109
|
+
const hosts = namedHosts(source);
|
|
110
|
+
if (hosts.length === 0)
|
|
111
|
+
return ' · network: no host named in the code';
|
|
112
|
+
return ` · network: ${hosts.join(', ')}`;
|
|
113
|
+
}
|
|
85
114
|
function packageSuffix(args) {
|
|
86
115
|
if (!Array.isArray(args.packages) || args.packages.length === 0)
|
|
87
116
|
return '';
|
|
@@ -428,7 +457,7 @@ export function createExecTool({ spawn, killProcess, loadPyodide, disablePyodide
|
|
|
428
457
|
return PACKAGES_NEED_PYTHON_ERROR;
|
|
429
458
|
return checkFileArgs(rawArgs, python);
|
|
430
459
|
},
|
|
431
|
-
resource(rawArgs) {
|
|
460
|
+
resource(rawArgs, ctx) {
|
|
432
461
|
const args = withInferredLanguage(rawArgs, disablePyodide);
|
|
433
462
|
const script = typeof args.script === 'string' ? args.script : '';
|
|
434
463
|
if (script.trim() && !script.includes('\n')) {
|
|
@@ -438,8 +467,10 @@ export function createExecTool({ spawn, killProcess, loadPyodide, disablePyodide
|
|
|
438
467
|
if (!command)
|
|
439
468
|
return null;
|
|
440
469
|
const workdir = typeof args.workdir === 'string' && args.workdir.trim() ? args.workdir.trim() : null;
|
|
470
|
+
const source = unwrapPythonSource(command) ?? command;
|
|
471
|
+
const online = pythonNetwork && ctx?.sandboxMode !== true;
|
|
441
472
|
const body = runsThroughPyodide(args.language, disablePyodide)
|
|
442
|
-
? `python${packageSuffix(args)}${fileSuffix(args)}: ${
|
|
473
|
+
? `python${online ? networkPrefix(source) : ''}${packageSuffix(args)}${fileSuffix(args)}: ${source.slice(0, 120)}`
|
|
443
474
|
: command;
|
|
444
475
|
return {
|
|
445
476
|
kind: 'command',
|
|
@@ -515,7 +546,9 @@ export function createExecTool({ spawn, killProcess, loadPyodide, disablePyodide
|
|
|
515
546
|
turnImages: ctx?.turnImages,
|
|
516
547
|
runBudget: ctx?.runBudget,
|
|
517
548
|
sandboxMode: ctx?.sandboxMode,
|
|
518
|
-
toolNames: ctx?.toolNames
|
|
549
|
+
toolNames: ctx?.toolNames,
|
|
550
|
+
approval: ctx?.approval,
|
|
551
|
+
confirmConnect: ctx?.askUser ? connectAsker(ctx.askUser) : undefined
|
|
519
552
|
});
|
|
520
553
|
return await execution.run({
|
|
521
554
|
cwd,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qvac/harness",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "An AI harness implementing generate(context) via @qvac/sdk. Knows nothing about workbench, hyperdb, or chunks — just inference in, events out.",
|
|
6
6
|
"exports": {
|
|
@@ -220,6 +220,10 @@
|
|
|
220
220
|
"types": "./dist-lib/lib/tools/exec/adapters/python/guarded-fetch.d.ts",
|
|
221
221
|
"default": "./dist-lib/lib/tools/exec/adapters/python/guarded-fetch.js"
|
|
222
222
|
},
|
|
223
|
+
"./lib/tools/exec/adapters/python/interrupt-timer.ts": {
|
|
224
|
+
"types": "./dist-lib/lib/tools/exec/adapters/python/interrupt-timer.d.ts",
|
|
225
|
+
"default": "./dist-lib/lib/tools/exec/adapters/python/interrupt-timer.js"
|
|
226
|
+
},
|
|
223
227
|
"./lib/tools/exec/adapters/python/loader.ts": {
|
|
224
228
|
"types": "./dist-lib/lib/tools/exec/adapters/python/loader.d.ts",
|
|
225
229
|
"default": "./dist-lib/lib/tools/exec/adapters/python/loader.js"
|
|
@@ -232,6 +236,10 @@
|
|
|
232
236
|
"types": "./dist-lib/lib/tools/exec/adapters/python/module-distributions.d.ts",
|
|
233
237
|
"default": "./dist-lib/lib/tools/exec/adapters/python/module-distributions.js"
|
|
234
238
|
},
|
|
239
|
+
"./lib/tools/exec/adapters/python/named-hosts.ts": {
|
|
240
|
+
"types": "./dist-lib/lib/tools/exec/adapters/python/named-hosts.d.ts",
|
|
241
|
+
"default": "./dist-lib/lib/tools/exec/adapters/python/named-hosts.js"
|
|
242
|
+
},
|
|
235
243
|
"./lib/tools/exec/adapters/python/net-shim.ts": {
|
|
236
244
|
"types": "./dist-lib/lib/tools/exec/adapters/python/net-shim.d.ts",
|
|
237
245
|
"default": "./dist-lib/lib/tools/exec/adapters/python/net-shim.js"
|
|
@@ -686,10 +694,10 @@
|
|
|
686
694
|
}
|
|
687
695
|
},
|
|
688
696
|
"dependencies": {
|
|
689
|
-
"@qvac/inference": "0.
|
|
697
|
+
"@qvac/inference": "0.20.0",
|
|
690
698
|
"@qvac/langdetect-text": "0.1.2",
|
|
691
|
-
"@qvac/sdk": "0.
|
|
692
|
-
"@qvac/skills": "0.1.
|
|
699
|
+
"@qvac/sdk": "0.20.0",
|
|
700
|
+
"@qvac/skills": "0.1.9",
|
|
693
701
|
"asenion": "^0.1.0",
|
|
694
702
|
"b4a": "^1.8.1",
|
|
695
703
|
"bare-abort-controller": "^1.1.2",
|
|
@@ -748,7 +756,9 @@
|
|
|
748
756
|
"corestore": "^7.11.0",
|
|
749
757
|
"holepunch-types": "^0.2.1",
|
|
750
758
|
"hyperdrive": "^13.3.3",
|
|
759
|
+
"jsdom": "~30.0.1",
|
|
751
760
|
"lunte": "^1.8.3",
|
|
761
|
+
"mermaid": "~11.16.1",
|
|
752
762
|
"prettier": "^3.6.2",
|
|
753
763
|
"prettier-config-holepunch": "^2.0.0",
|
|
754
764
|
"prettytap": "^0.2.0",
|
|
@@ -761,8 +771,8 @@
|
|
|
761
771
|
"localwatch@1.4.3": "patches/localwatch@1.4.3.patch",
|
|
762
772
|
"hypercore-blob-server@1.15.0": "patches/hypercore-blob-server@1.15.0.patch",
|
|
763
773
|
"bare-stow@0.1.5": "patches/bare-stow@0.1.5.patch",
|
|
764
|
-
"@
|
|
765
|
-
"
|
|
774
|
+
"brittle@4.1.0": "patches/brittle@4.1.0.patch",
|
|
775
|
+
"@qvac/inference@0.20.0": "patches/@qvac%2Finference@0.20.0.patch"
|
|
766
776
|
},
|
|
767
777
|
"repository": {
|
|
768
778
|
"type": "git",
|
|
@@ -775,7 +785,6 @@
|
|
|
775
785
|
},
|
|
776
786
|
"homepage": "https://github.com/tetherto/qvac-harness",
|
|
777
787
|
"overrides": {
|
|
778
|
-
"@qvac/asr-ggml": "0.4.2",
|
|
779
788
|
"bare-runtime": "^1.30.0",
|
|
780
789
|
"bare-module": "6.4.0",
|
|
781
790
|
"bare-process": "4.4.1",
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
const CACHE_VERSION = 'vision-history-v1';
|
|
2
|
-
export function projectVisionHistory(history) {
|
|
3
|
-
return history.flatMap((message) => {
|
|
4
|
-
const attachments = message.attachments;
|
|
5
|
-
if (message.role !== 'user' || !attachments || attachments.length < 2)
|
|
6
|
-
return [message];
|
|
7
|
-
return attachments.map((attachment, index) => ({
|
|
8
|
-
...message,
|
|
9
|
-
content: index === attachments.length - 1 ? message.content : '\n',
|
|
10
|
-
attachments: [attachment]
|
|
11
|
-
}));
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
export function visionHistoryCacheKey(cacheKey, history) {
|
|
15
|
-
if (!cacheKey || !history.some(hasMultipleImages))
|
|
16
|
-
return cacheKey;
|
|
17
|
-
return `${cacheKey}-${CACHE_VERSION}`;
|
|
18
|
-
}
|
|
19
|
-
function hasMultipleImages(message) {
|
|
20
|
-
return message.role === 'user' && (message.attachments?.length ?? 0) > 1;
|
|
21
|
-
}
|