@qvac/harness 0.8.8 → 0.8.10
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 +80 -1
- package/dist-lib/index.d.ts +1 -1
- package/dist-lib/index.js +51 -50
- package/dist-lib/lib/audio-transcode-bare.js +2 -2
- package/dist-lib/lib/capabilities/completion.d.ts +1 -2
- package/dist-lib/lib/capabilities/completion.js +29 -25
- package/dist-lib/lib/capabilities/tool-prompt-log.js +3 -3
- package/dist-lib/lib/capabilities/voice.js +7 -6
- package/dist-lib/lib/connect.js +18 -17
- package/dist-lib/lib/errors.d.ts +266 -0
- package/dist-lib/lib/errors.js +189 -0
- package/dist-lib/lib/helpers/load-stall.d.ts +1 -1
- package/dist-lib/lib/helpers/load-stall.js +2 -2
- package/dist-lib/lib/helpers/race-abort.d.ts +2 -1
- package/dist-lib/lib/helpers/race-abort.js +3 -4
- package/dist-lib/lib/hooks/built-in/arg-repair.js +2 -2
- package/dist-lib/lib/hooks/pipeline.js +4 -4
- package/dist-lib/lib/hooks/run.js +2 -2
- package/dist-lib/lib/log.d.ts +26 -2
- package/dist-lib/lib/log.js +66 -16
- package/dist-lib/lib/models/model-pool.js +11 -6
- package/dist-lib/lib/models/model-source.js +3 -2
- package/dist-lib/lib/no-redirect-fetch-bare.js +2 -1
- package/dist-lib/lib/no-redirect-fetch-impl.js +2 -1
- package/dist-lib/lib/office/extract.js +4 -3
- package/dist-lib/lib/office/index.js +2 -1
- package/dist-lib/lib/resolution-detector.js +3 -3
- package/dist-lib/lib/rpc-session.js +2 -1
- package/dist-lib/lib/sdk-loader.js +2 -2
- package/dist-lib/lib/serve.js +33 -29
- package/dist-lib/lib/spawn.d.ts +2 -4
- package/dist-lib/lib/spawn.js +14 -7
- package/dist-lib/lib/tools/edit-image.js +2 -1
- package/dist-lib/lib/tools/exec/adapters/python/attachments.js +8 -8
- package/dist-lib/lib/tools/exec/adapters/python/guarded-fetch.js +7 -6
- package/dist-lib/lib/tools/exec/adapters/python/interrupt-timer.js +2 -2
- package/dist-lib/lib/tools/exec/adapters/python/memfs.js +2 -2
- package/dist-lib/lib/tools/exec/adapters/python/pyodide.js +8 -8
- package/dist-lib/lib/tools/exec/adapters/python/run-session.js +11 -7
- package/dist-lib/lib/tools/exec/adapters/python/wheels.js +5 -5
- package/dist-lib/lib/tools/exec/adapters/python/worker/active.js +2 -2
- package/dist-lib/lib/tools/exec/adapters/python/worker/client.js +9 -8
- package/dist-lib/lib/tools/exec/adapters/python/worker/protocol.d.ts +2 -0
- package/dist-lib/lib/tools/exec/adapters/python/worker/serve.js +4 -4
- package/dist-lib/lib/tools/exec/adapters/python/worker/spawn.d.ts +2 -1
- package/dist-lib/lib/tools/exec/adapters/python/worker/spawn.js +2 -1
- package/dist-lib/lib/tools/exec/obsidian/note-name.js +2 -1
- package/dist-lib/lib/tools/exec/obsidian/safe-path.js +5 -4
- package/dist-lib/lib/tools/exec/obsidian/vault-create.js +3 -2
- package/dist-lib/lib/tools/exec/obsidian/vault-fs.js +2 -2
- package/dist-lib/lib/tools/exec/obsidian/vault-paths.js +3 -2
- package/dist-lib/lib/tools/exec/obsidian/vault-read.js +6 -5
- package/dist-lib/lib/tools/exec/obsidian/vault-write.js +13 -12
- package/dist-lib/lib/tools/exec/runner.js +2 -1
- package/dist-lib/lib/tools/files/edit-file.d.ts +3 -0
- package/dist-lib/lib/tools/files/edit-file.js +73 -0
- package/dist-lib/lib/tools/files/glob.d.ts +3 -0
- package/dist-lib/lib/tools/files/glob.js +63 -0
- package/dist-lib/lib/tools/files/grep.d.ts +3 -0
- package/dist-lib/lib/tools/files/grep.js +114 -0
- package/dist-lib/lib/tools/files/index.d.ts +3 -0
- package/dist-lib/lib/tools/files/index.js +23 -0
- package/dist-lib/lib/tools/files/list-dir.d.ts +5 -0
- package/dist-lib/lib/tools/files/list-dir.js +130 -0
- package/dist-lib/lib/tools/files/make-dir.d.ts +3 -0
- package/dist-lib/lib/tools/files/make-dir.js +47 -0
- package/dist-lib/lib/tools/files/read-file.d.ts +3 -0
- package/dist-lib/lib/tools/files/read-file.js +103 -0
- package/dist-lib/lib/tools/files/transfer.d.ts +4 -0
- package/dist-lib/lib/tools/files/transfer.js +82 -0
- package/dist-lib/lib/tools/files/trash-file.d.ts +4 -0
- package/dist-lib/lib/tools/files/trash-file.js +61 -0
- package/dist-lib/lib/tools/files/write-file.d.ts +3 -0
- package/dist-lib/lib/tools/files/write-file.js +55 -0
- package/dist-lib/lib/tools/fs/document-text.d.ts +2 -0
- package/dist-lib/lib/tools/fs/document-text.js +38 -0
- package/dist-lib/lib/tools/fs/edit-match.d.ts +11 -0
- package/dist-lib/lib/tools/fs/edit-match.js +85 -0
- package/dist-lib/lib/tools/fs/remote.d.ts +2 -1
- package/dist-lib/lib/tools/fs/remote.js +4 -4
- package/dist-lib/lib/tools/fs/scope.d.ts +1 -1
- package/dist-lib/lib/tools/fs/scope.js +3 -2
- package/dist-lib/lib/tools/fs/targets.d.ts +10 -0
- package/dist-lib/lib/tools/fs/targets.js +32 -0
- package/dist-lib/lib/tools/fs/tool-path.d.ts +24 -0
- package/dist-lib/lib/tools/fs/tool-path.js +58 -0
- package/dist-lib/lib/tools/fs/walk.js +3 -3
- package/dist-lib/lib/tools/generate-image.d.ts +2 -2
- package/dist-lib/lib/tools/generate-image.js +5 -6
- package/dist-lib/lib/tools/office.js +2 -1
- package/dist-lib/lib/tools/skill.js +2 -1
- package/dist-lib/lib/tools/skills/bundled-dir.js +4 -4
- package/dist-lib/lib/tools/skills/catalog.js +2 -2
- package/dist-lib/lib/tools/skills/credential-health.js +3 -3
- package/dist-lib/lib/tools/skills/mention.js +7 -2
- package/dist-lib/lib/tools/skills/overlay-crud.js +3 -2
- package/dist-lib/lib/tools/translate.d.ts +2 -2
- package/dist-lib/lib/tools/translate.js +5 -6
- package/dist-lib/lib/tools/weather-lookup/geocode.js +5 -4
- package/dist-lib/lib/web-search/engines/bing.js +2 -1
- package/dist-lib/lib/web-search/engines/google.js +2 -1
- package/dist-lib/lib/web-search/fetch-html.d.ts +5 -5
- package/dist-lib/lib/web-search/fetch-html.js +12 -15
- package/package.json +67 -25
- package/worker/harness-sidecar.mjs +12 -13
- package/dist-lib/lib/tools/create-documents.d.ts +0 -3
- package/dist-lib/lib/tools/create-documents.js +0 -95
- package/dist-lib/lib/tools/edit-documents.d.ts +0 -3
- package/dist-lib/lib/tools/edit-documents.js +0 -132
- package/dist-lib/lib/tools/file-glob.d.ts +0 -14
- package/dist-lib/lib/tools/file-glob.js +0 -118
- package/dist-lib/lib/tools/grep.d.ts +0 -5
- package/dist-lib/lib/tools/grep.js +0 -184
- package/dist-lib/lib/tools/read-files.d.ts +0 -5
- package/dist-lib/lib/tools/read-files.js +0 -157
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { QvacErrorBase } from '@qvac/error';
|
|
2
|
+
export declare const CONTEXT_OVERFLOW_MESSAGE = "This message is too large for the model context window.";
|
|
3
|
+
export declare const IMAGE_LOAD_STALL_ERROR = "image model download stalled";
|
|
4
|
+
export declare const TRANSLATION_LOAD_STALL_ERROR = "translation model download stalled";
|
|
5
|
+
export declare const NO_STORAGE_ROOT = "cannot fence the app storage root: the SDK home is unknown";
|
|
6
|
+
declare const HARNESS_ERRORS: {
|
|
7
|
+
readonly ABORTED: {
|
|
8
|
+
readonly code: 102001;
|
|
9
|
+
readonly message: () => string;
|
|
10
|
+
};
|
|
11
|
+
readonly HARNESS_CLOSING: {
|
|
12
|
+
readonly code: 102002;
|
|
13
|
+
readonly message: () => string;
|
|
14
|
+
};
|
|
15
|
+
readonly HARNESS_SUSPENDED: {
|
|
16
|
+
readonly code: 102003;
|
|
17
|
+
readonly message: () => string;
|
|
18
|
+
};
|
|
19
|
+
readonly HARNESS_EXITED_BEFORE_READY: {
|
|
20
|
+
readonly code: 102004;
|
|
21
|
+
readonly message: (exitCode: number | null) => string;
|
|
22
|
+
};
|
|
23
|
+
readonly CAPABILITY_UNSUPPORTED: {
|
|
24
|
+
readonly code: 102005;
|
|
25
|
+
readonly message: (what: string) => string;
|
|
26
|
+
};
|
|
27
|
+
readonly UNKNOWN_CAPABILITY: {
|
|
28
|
+
readonly code: 102006;
|
|
29
|
+
readonly message: (capability: string) => string;
|
|
30
|
+
};
|
|
31
|
+
readonly CLIENT_GONE: {
|
|
32
|
+
readonly code: 102007;
|
|
33
|
+
readonly message: () => string;
|
|
34
|
+
};
|
|
35
|
+
readonly RPC_STREAM_DESTROYED: {
|
|
36
|
+
readonly code: 102008;
|
|
37
|
+
readonly message: () => string;
|
|
38
|
+
};
|
|
39
|
+
readonly EMBED_ABORTED: {
|
|
40
|
+
readonly code: 102009;
|
|
41
|
+
readonly message: () => string;
|
|
42
|
+
};
|
|
43
|
+
readonly NO_SKILLS_OVERLAY: {
|
|
44
|
+
readonly code: 102010;
|
|
45
|
+
readonly message: () => string;
|
|
46
|
+
};
|
|
47
|
+
readonly CHAT_MODEL_BUSY: {
|
|
48
|
+
readonly code: 102101;
|
|
49
|
+
readonly message: (output: string) => string;
|
|
50
|
+
};
|
|
51
|
+
readonly MODEL_NOT_RESIDENT: {
|
|
52
|
+
readonly code: 102102;
|
|
53
|
+
readonly message: (model: string) => string;
|
|
54
|
+
};
|
|
55
|
+
readonly AUDIOGEN_MODEL_NOT_FOUND: {
|
|
56
|
+
readonly code: 102103;
|
|
57
|
+
readonly message: (model: string) => string;
|
|
58
|
+
};
|
|
59
|
+
readonly MODEL_NOT_IN_REGISTRY: {
|
|
60
|
+
readonly code: 102104;
|
|
61
|
+
readonly message: (model: string, addon: string) => string;
|
|
62
|
+
};
|
|
63
|
+
readonly MODEL_LOAD_CLOCK_SKEW: {
|
|
64
|
+
readonly code: 102105;
|
|
65
|
+
readonly message: (model: string) => string;
|
|
66
|
+
};
|
|
67
|
+
readonly IMAGE_LOAD_STALLED: {
|
|
68
|
+
readonly code: 102106;
|
|
69
|
+
readonly message: () => string;
|
|
70
|
+
};
|
|
71
|
+
readonly TRANSLATION_LOAD_STALLED: {
|
|
72
|
+
readonly code: 102107;
|
|
73
|
+
readonly message: () => string;
|
|
74
|
+
};
|
|
75
|
+
readonly CONTEXT_WINDOW_EXCEEDED: {
|
|
76
|
+
readonly code: 102201;
|
|
77
|
+
readonly message: () => string;
|
|
78
|
+
};
|
|
79
|
+
readonly TTS_NO_AUDIO: {
|
|
80
|
+
readonly code: 102202;
|
|
81
|
+
readonly message: () => string;
|
|
82
|
+
};
|
|
83
|
+
readonly TTS_INCOMPLETE: {
|
|
84
|
+
readonly code: 102203;
|
|
85
|
+
readonly message: () => string;
|
|
86
|
+
};
|
|
87
|
+
readonly FETCH_TIMED_OUT: {
|
|
88
|
+
readonly code: 102301;
|
|
89
|
+
readonly message: (ms: number) => string;
|
|
90
|
+
};
|
|
91
|
+
readonly FETCH_CANCELLED: {
|
|
92
|
+
readonly code: 102302;
|
|
93
|
+
readonly message: () => string;
|
|
94
|
+
};
|
|
95
|
+
readonly RESPONSE_NOT_JSON: {
|
|
96
|
+
readonly code: 102303;
|
|
97
|
+
readonly message: (chars: number, detail: string) => string;
|
|
98
|
+
};
|
|
99
|
+
readonly HTTP_STATUS: {
|
|
100
|
+
readonly code: 102304;
|
|
101
|
+
readonly message: (status: number) => string;
|
|
102
|
+
};
|
|
103
|
+
readonly SEARCH_CAPTCHA: {
|
|
104
|
+
readonly code: 102305;
|
|
105
|
+
readonly message: (engine: string) => string;
|
|
106
|
+
};
|
|
107
|
+
readonly RESPONSE_TOO_LARGE: {
|
|
108
|
+
readonly code: 102306;
|
|
109
|
+
readonly message: (maxBytes: number) => string;
|
|
110
|
+
};
|
|
111
|
+
readonly UNSUPPORTED_HTTP_METHOD: {
|
|
112
|
+
readonly code: 102307;
|
|
113
|
+
readonly message: (method: string) => string;
|
|
114
|
+
};
|
|
115
|
+
readonly GEOCODER_HTTP_STATUS: {
|
|
116
|
+
readonly code: 102308;
|
|
117
|
+
readonly message: (status: number) => string;
|
|
118
|
+
};
|
|
119
|
+
readonly EGRESS_BLOCKED: {
|
|
120
|
+
readonly code: 102309;
|
|
121
|
+
readonly message: (reason: string) => string;
|
|
122
|
+
};
|
|
123
|
+
readonly OFFICE_UNSUPPORTED_DOCUMENT: {
|
|
124
|
+
readonly code: 102401;
|
|
125
|
+
readonly message: (fileName: string) => string;
|
|
126
|
+
};
|
|
127
|
+
readonly OFFICE_TOO_LARGE: {
|
|
128
|
+
readonly code: 102402;
|
|
129
|
+
readonly message: (bytes: number, limit: number) => string;
|
|
130
|
+
};
|
|
131
|
+
readonly OFFICE_EXTRACTION_ABORTED: {
|
|
132
|
+
readonly code: 102403;
|
|
133
|
+
readonly message: (fileName: string) => string;
|
|
134
|
+
};
|
|
135
|
+
readonly OFFICE_EXTRACTION_FAILED: {
|
|
136
|
+
readonly code: 102404;
|
|
137
|
+
readonly message: (fileName: string, detail: string) => string;
|
|
138
|
+
};
|
|
139
|
+
readonly OFFICE_OP_UNAVAILABLE: {
|
|
140
|
+
readonly code: 102405;
|
|
141
|
+
readonly message: (op: string) => string;
|
|
142
|
+
};
|
|
143
|
+
readonly COMMAND_TIMED_OUT: {
|
|
144
|
+
readonly code: 102501;
|
|
145
|
+
readonly message: (ms: number) => string;
|
|
146
|
+
};
|
|
147
|
+
readonly PACKAGE_INSTALL_TIMED_OUT: {
|
|
148
|
+
readonly code: 102502;
|
|
149
|
+
readonly message: (ms: number) => string;
|
|
150
|
+
};
|
|
151
|
+
readonly PYTHON_WORKER_FAILED: {
|
|
152
|
+
readonly code: 102503;
|
|
153
|
+
readonly message: (detail: string) => string;
|
|
154
|
+
};
|
|
155
|
+
readonly PYTHON_WORKER_EXITED: {
|
|
156
|
+
readonly code: 102504;
|
|
157
|
+
readonly message: (exitCode: number) => string;
|
|
158
|
+
};
|
|
159
|
+
readonly ATTACHMENT_STAGING_TIMED_OUT: {
|
|
160
|
+
readonly code: 102505;
|
|
161
|
+
readonly message: (ms: number) => string;
|
|
162
|
+
};
|
|
163
|
+
readonly FETCH_REFUSED: {
|
|
164
|
+
readonly code: 102506;
|
|
165
|
+
readonly message: (reason: string) => string;
|
|
166
|
+
};
|
|
167
|
+
readonly OBSIDIAN_NOTE_NAME_IS_PATH: {
|
|
168
|
+
readonly code: 102601;
|
|
169
|
+
readonly message: () => string;
|
|
170
|
+
};
|
|
171
|
+
readonly OBSIDIAN_NOTE_NOT_FOUND: {
|
|
172
|
+
readonly code: 102602;
|
|
173
|
+
readonly message: (args: readonly string[]) => string;
|
|
174
|
+
};
|
|
175
|
+
readonly OBSIDIAN_MISSING_ARGUMENT: {
|
|
176
|
+
readonly code: 102603;
|
|
177
|
+
readonly message: (names: string) => string;
|
|
178
|
+
};
|
|
179
|
+
readonly OBSIDIAN_NO_PROPERTIES: {
|
|
180
|
+
readonly code: 102604;
|
|
181
|
+
readonly message: () => string;
|
|
182
|
+
};
|
|
183
|
+
readonly OBSIDIAN_NOTE_EXISTS: {
|
|
184
|
+
readonly code: 102605;
|
|
185
|
+
readonly message: (name: string, folder: string) => string;
|
|
186
|
+
};
|
|
187
|
+
readonly OBSIDIAN_ACTION_UNSUPPORTED: {
|
|
188
|
+
readonly code: 102606;
|
|
189
|
+
readonly message: (action: string) => string;
|
|
190
|
+
};
|
|
191
|
+
readonly OBSIDIAN_NOTE_CHANGED: {
|
|
192
|
+
readonly code: 102607;
|
|
193
|
+
readonly message: (why: string, file: string) => string;
|
|
194
|
+
};
|
|
195
|
+
readonly OBSIDIAN_PATH_CROSSES_SYMLINK: {
|
|
196
|
+
readonly code: 102608;
|
|
197
|
+
readonly message: (target: string) => string;
|
|
198
|
+
};
|
|
199
|
+
readonly OBSIDIAN_PATH_ESCAPES_VAULT: {
|
|
200
|
+
readonly code: 102609;
|
|
201
|
+
readonly message: (rel: string) => string;
|
|
202
|
+
};
|
|
203
|
+
readonly OBSIDIAN_DESTINATION_EXISTS: {
|
|
204
|
+
readonly code: 102610;
|
|
205
|
+
readonly message: (filePath: string) => string;
|
|
206
|
+
};
|
|
207
|
+
readonly SKILL_FILE_NOT_FOUND: {
|
|
208
|
+
readonly code: 102701;
|
|
209
|
+
readonly message: (name: string, file: string) => string;
|
|
210
|
+
};
|
|
211
|
+
readonly INVALID_SKILL_NAME: {
|
|
212
|
+
readonly code: 102702;
|
|
213
|
+
readonly message: (name: string) => string;
|
|
214
|
+
};
|
|
215
|
+
readonly SKILL_NOT_FOUND: {
|
|
216
|
+
readonly code: 102703;
|
|
217
|
+
readonly message: (name: string) => string;
|
|
218
|
+
};
|
|
219
|
+
readonly BUNDLED_SKILLS_INVALID: {
|
|
220
|
+
readonly code: 102704;
|
|
221
|
+
readonly message: (staging: string) => string;
|
|
222
|
+
};
|
|
223
|
+
readonly BUNDLED_SKILLS_TAMPERED: {
|
|
224
|
+
readonly code: 102705;
|
|
225
|
+
readonly message: (dir: string) => string;
|
|
226
|
+
};
|
|
227
|
+
readonly BUNDLED_SKILLS_OCCUPIED: {
|
|
228
|
+
readonly code: 102706;
|
|
229
|
+
readonly message: (dir: string, why: string) => string;
|
|
230
|
+
};
|
|
231
|
+
readonly DRIVE_TIMED_OUT: {
|
|
232
|
+
readonly code: 102707;
|
|
233
|
+
readonly message: (op: string) => string;
|
|
234
|
+
};
|
|
235
|
+
readonly DRIVE_READ_TRUNCATED: {
|
|
236
|
+
readonly code: 102708;
|
|
237
|
+
readonly message: (maxBytes: number, key: string) => string;
|
|
238
|
+
};
|
|
239
|
+
readonly NO_STORAGE_ROOT: {
|
|
240
|
+
readonly code: 102709;
|
|
241
|
+
readonly message: () => string;
|
|
242
|
+
};
|
|
243
|
+
readonly SLM_TRANSLATION_UNAVAILABLE: {
|
|
244
|
+
readonly code: 102710;
|
|
245
|
+
readonly message: () => string;
|
|
246
|
+
};
|
|
247
|
+
readonly PDF_TEXT_UNAVAILABLE: {
|
|
248
|
+
readonly code: 102711;
|
|
249
|
+
readonly message: () => string;
|
|
250
|
+
};
|
|
251
|
+
};
|
|
252
|
+
type Errors = typeof HARNESS_ERRORS;
|
|
253
|
+
export type HarnessErrorName = keyof Errors;
|
|
254
|
+
type Adds<K extends HarnessErrorName> = Parameters<Errors[K]['message']>;
|
|
255
|
+
interface HarnessErrorOptions {
|
|
256
|
+
readonly cause?: unknown;
|
|
257
|
+
}
|
|
258
|
+
type HarnessErrorArgs<K extends HarnessErrorName> = [
|
|
259
|
+
] extends Adds<K> ? [adds?: Adds<K>, opts?: HarnessErrorOptions] : [adds: Adds<K>, opts?: HarnessErrorOptions];
|
|
260
|
+
export declare class HarnessError<K extends HarnessErrorName = HarnessErrorName> extends QvacErrorBase {
|
|
261
|
+
constructor(name: K, ...[adds, opts]: HarnessErrorArgs<K>);
|
|
262
|
+
}
|
|
263
|
+
export declare function harnessErrorCode(name: HarnessErrorName): number;
|
|
264
|
+
export declare function harnessErrorCodes(): ReadonlyArray<number>;
|
|
265
|
+
export declare function isHarnessError(err: unknown, name: HarnessErrorName): boolean;
|
|
266
|
+
export {};
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { QvacErrorBase, addCodes } from '@qvac/error';
|
|
2
|
+
import { isRecord } from './guards.js';
|
|
3
|
+
export const CONTEXT_OVERFLOW_MESSAGE = 'This message is too large for the model context window.';
|
|
4
|
+
export const IMAGE_LOAD_STALL_ERROR = 'image model download stalled';
|
|
5
|
+
export const TRANSLATION_LOAD_STALL_ERROR = 'translation model download stalled';
|
|
6
|
+
export const NO_STORAGE_ROOT = 'cannot fence the app storage root: the SDK home is unknown';
|
|
7
|
+
const HARNESS_ERRORS = {
|
|
8
|
+
ABORTED: { code: 102001, message: () => 'aborted' },
|
|
9
|
+
HARNESS_CLOSING: { code: 102002, message: () => 'harness is closing' },
|
|
10
|
+
HARNESS_SUSPENDED: { code: 102003, message: () => 'harness is suspended' },
|
|
11
|
+
HARNESS_EXITED_BEFORE_READY: {
|
|
12
|
+
code: 102004,
|
|
13
|
+
message: (exitCode) => `harness exited (${exitCode}) before ready`
|
|
14
|
+
},
|
|
15
|
+
CAPABILITY_UNSUPPORTED: {
|
|
16
|
+
code: 102005,
|
|
17
|
+
message: (what) => `harness does not support ${what}`
|
|
18
|
+
},
|
|
19
|
+
UNKNOWN_CAPABILITY: {
|
|
20
|
+
code: 102006,
|
|
21
|
+
message: (capability) => `unknown capability: ${capability}`
|
|
22
|
+
},
|
|
23
|
+
CLIENT_GONE: { code: 102007, message: () => 'client gone' },
|
|
24
|
+
RPC_STREAM_DESTROYED: { code: 102008, message: () => 'rpc stream destroyed' },
|
|
25
|
+
EMBED_ABORTED: { code: 102009, message: () => 'embed aborted' },
|
|
26
|
+
NO_SKILLS_OVERLAY: { code: 102010, message: () => 'no writable skills overlay is configured' },
|
|
27
|
+
CHAT_MODEL_BUSY: {
|
|
28
|
+
code: 102101,
|
|
29
|
+
message: (output) => `the chat model is busy; try the ${output} again once the current reply finishes`
|
|
30
|
+
},
|
|
31
|
+
MODEL_NOT_RESIDENT: {
|
|
32
|
+
code: 102102,
|
|
33
|
+
message: (model) => `${model} loads for each generation and is not kept in memory`
|
|
34
|
+
},
|
|
35
|
+
AUDIOGEN_MODEL_NOT_FOUND: {
|
|
36
|
+
code: 102103,
|
|
37
|
+
message: (model) => `audiogen model not found: ${model}`
|
|
38
|
+
},
|
|
39
|
+
MODEL_NOT_IN_REGISTRY: {
|
|
40
|
+
code: 102104,
|
|
41
|
+
message: (model, addon) => `model not found in registry: ${model} (addon=${addon})`
|
|
42
|
+
},
|
|
43
|
+
MODEL_LOAD_CLOCK_SKEW: {
|
|
44
|
+
code: 102105,
|
|
45
|
+
message: (model) => `model load abandoned: system clock moved backward mid-load: ${model}`
|
|
46
|
+
},
|
|
47
|
+
IMAGE_LOAD_STALLED: { code: 102106, message: () => IMAGE_LOAD_STALL_ERROR },
|
|
48
|
+
TRANSLATION_LOAD_STALLED: { code: 102107, message: () => TRANSLATION_LOAD_STALL_ERROR },
|
|
49
|
+
CONTEXT_WINDOW_EXCEEDED: { code: 102201, message: () => CONTEXT_OVERFLOW_MESSAGE },
|
|
50
|
+
TTS_NO_AUDIO: { code: 102202, message: () => 'Text-to-speech returned no audio.' },
|
|
51
|
+
TTS_INCOMPLETE: { code: 102203, message: () => 'tts synthesis did not complete' },
|
|
52
|
+
FETCH_TIMED_OUT: { code: 102301, message: (ms) => `Request timed out after ${ms}ms` },
|
|
53
|
+
FETCH_CANCELLED: { code: 102302, message: () => 'Request cancelled' },
|
|
54
|
+
RESPONSE_NOT_JSON: {
|
|
55
|
+
code: 102303,
|
|
56
|
+
message: (chars, detail) => `Response was not valid JSON (${chars} chars): ${detail}`
|
|
57
|
+
},
|
|
58
|
+
HTTP_STATUS: { code: 102304, message: (status) => `HTTP ${status}` },
|
|
59
|
+
SEARCH_CAPTCHA: { code: 102305, message: (engine) => `${engine} CAPTCHA detected` },
|
|
60
|
+
RESPONSE_TOO_LARGE: {
|
|
61
|
+
code: 102306,
|
|
62
|
+
message: (maxBytes) => `response exceeded ${maxBytes} bytes`
|
|
63
|
+
},
|
|
64
|
+
UNSUPPORTED_HTTP_METHOD: {
|
|
65
|
+
code: 102307,
|
|
66
|
+
message: (method) => `unsupported HTTP method: ${method}`
|
|
67
|
+
},
|
|
68
|
+
GEOCODER_HTTP_STATUS: {
|
|
69
|
+
code: 102308,
|
|
70
|
+
message: (status) => `geocoder answered HTTP ${status}`
|
|
71
|
+
},
|
|
72
|
+
EGRESS_BLOCKED: { code: 102309, message: (reason) => reason },
|
|
73
|
+
OFFICE_UNSUPPORTED_DOCUMENT: {
|
|
74
|
+
code: 102401,
|
|
75
|
+
message: (fileName) => `Unsupported Office document: ${fileName}`
|
|
76
|
+
},
|
|
77
|
+
OFFICE_TOO_LARGE: {
|
|
78
|
+
code: 102402,
|
|
79
|
+
message: (bytes, limit) => `document is too large to extract: ${bytes} bytes, limit ${limit}`
|
|
80
|
+
},
|
|
81
|
+
OFFICE_EXTRACTION_ABORTED: {
|
|
82
|
+
code: 102403,
|
|
83
|
+
message: (fileName) => `${fileName}: extraction aborted`
|
|
84
|
+
},
|
|
85
|
+
OFFICE_EXTRACTION_FAILED: {
|
|
86
|
+
code: 102404,
|
|
87
|
+
message: (fileName, detail) => `${fileName}: ${detail}`
|
|
88
|
+
},
|
|
89
|
+
OFFICE_OP_UNAVAILABLE: {
|
|
90
|
+
code: 102405,
|
|
91
|
+
message: (op) => `${op} is not available on this file`
|
|
92
|
+
},
|
|
93
|
+
COMMAND_TIMED_OUT: { code: 102501, message: (ms) => `Command timed out after ${ms}ms` },
|
|
94
|
+
PACKAGE_INSTALL_TIMED_OUT: {
|
|
95
|
+
code: 102502,
|
|
96
|
+
message: (ms) => `package install timed out after ${ms}ms`
|
|
97
|
+
},
|
|
98
|
+
PYTHON_WORKER_FAILED: { code: 102503, message: (detail) => `python worker: ${detail}` },
|
|
99
|
+
PYTHON_WORKER_EXITED: {
|
|
100
|
+
code: 102504,
|
|
101
|
+
message: (exitCode) => `python worker exited with code ${exitCode}`
|
|
102
|
+
},
|
|
103
|
+
ATTACHMENT_STAGING_TIMED_OUT: {
|
|
104
|
+
code: 102505,
|
|
105
|
+
message: (ms) => `staging attachments timed out after ${ms}ms`
|
|
106
|
+
},
|
|
107
|
+
FETCH_REFUSED: { code: 102506, message: (reason) => `fetch refused: ${reason}` },
|
|
108
|
+
OBSIDIAN_NOTE_NAME_IS_PATH: {
|
|
109
|
+
code: 102601,
|
|
110
|
+
message: () => 'name= must be a note name, not a path.'
|
|
111
|
+
},
|
|
112
|
+
OBSIDIAN_NOTE_NOT_FOUND: {
|
|
113
|
+
code: 102602,
|
|
114
|
+
message: (args) => `Note not found. Args: ${args.join(', ')}`
|
|
115
|
+
},
|
|
116
|
+
OBSIDIAN_MISSING_ARGUMENT: {
|
|
117
|
+
code: 102603,
|
|
118
|
+
message: (names) => `Missing required argument: ${names}`
|
|
119
|
+
},
|
|
120
|
+
OBSIDIAN_NO_PROPERTIES: { code: 102604, message: () => 'No property key=value pairs provided.' },
|
|
121
|
+
OBSIDIAN_NOTE_EXISTS: {
|
|
122
|
+
code: 102605,
|
|
123
|
+
message: (name, folder) => `Note "${name}" already exists at ${folder}`
|
|
124
|
+
},
|
|
125
|
+
OBSIDIAN_ACTION_UNSUPPORTED: {
|
|
126
|
+
code: 102606,
|
|
127
|
+
message: (action) => `Action "${action}" is not supported in vault file mode. ` +
|
|
128
|
+
`This action requires the Obsidian CLI connected to the running app.`
|
|
129
|
+
},
|
|
130
|
+
OBSIDIAN_NOTE_CHANGED: {
|
|
131
|
+
code: 102607,
|
|
132
|
+
message: (why, file) => `Note changed on disk during update (${why}): ${file}`
|
|
133
|
+
},
|
|
134
|
+
OBSIDIAN_PATH_CROSSES_SYMLINK: {
|
|
135
|
+
code: 102608,
|
|
136
|
+
message: (target) => `Path "${target}" crosses a symlink inside the vault.`
|
|
137
|
+
},
|
|
138
|
+
OBSIDIAN_PATH_ESCAPES_VAULT: {
|
|
139
|
+
code: 102609,
|
|
140
|
+
message: (rel) => `Path "${rel}" escapes the vault root.`
|
|
141
|
+
},
|
|
142
|
+
OBSIDIAN_DESTINATION_EXISTS: {
|
|
143
|
+
code: 102610,
|
|
144
|
+
message: (filePath) => `Destination already exists: ${filePath}`
|
|
145
|
+
},
|
|
146
|
+
SKILL_FILE_NOT_FOUND: {
|
|
147
|
+
code: 102701,
|
|
148
|
+
message: (name, file) => `ENOENT: ${name}/${file}`
|
|
149
|
+
},
|
|
150
|
+
INVALID_SKILL_NAME: { code: 102702, message: (name) => `invalid skill name: ${name}` },
|
|
151
|
+
SKILL_NOT_FOUND: { code: 102703, message: (name) => `skill not found: ${name}` },
|
|
152
|
+
BUNDLED_SKILLS_INVALID: {
|
|
153
|
+
code: 102704,
|
|
154
|
+
message: (staging) => `bundled skills staging dir ${staging} failed validation`
|
|
155
|
+
},
|
|
156
|
+
BUNDLED_SKILLS_TAMPERED: {
|
|
157
|
+
code: 102705,
|
|
158
|
+
message: (dir) => `bundled skills dir ${dir} failed validation after a rewrite — ` +
|
|
159
|
+
'another process is tampering with it; remove it and restart'
|
|
160
|
+
},
|
|
161
|
+
BUNDLED_SKILLS_OCCUPIED: {
|
|
162
|
+
code: 102706,
|
|
163
|
+
message: (dir, why) => `bundled skills dir ${dir} could not be read or replaced${why} — remove it and restart`
|
|
164
|
+
},
|
|
165
|
+
DRIVE_TIMED_OUT: { code: 102707, message: (op) => `drive ${op} timed out` },
|
|
166
|
+
DRIVE_READ_TRUNCATED: {
|
|
167
|
+
code: 102708,
|
|
168
|
+
message: (maxBytes, key) => `read stopped at ${maxBytes} bytes: ${key}`
|
|
169
|
+
},
|
|
170
|
+
NO_STORAGE_ROOT: { code: 102709, message: () => NO_STORAGE_ROOT },
|
|
171
|
+
SLM_TRANSLATION_UNAVAILABLE: { code: 102710, message: () => 'slm translation is unavailable' },
|
|
172
|
+
PDF_TEXT_UNAVAILABLE: { code: 102711, message: () => 'PDF text is not available on this device' }
|
|
173
|
+
};
|
|
174
|
+
addCodes(Object.fromEntries(Object.entries(HARNESS_ERRORS).map(([name, { code, message }]) => [code, { name, message }])), { name: '@qvac/harness', version: `${Object.keys(HARNESS_ERRORS).length}.0.0` });
|
|
175
|
+
export class HarnessError extends QvacErrorBase {
|
|
176
|
+
constructor(name, ...[adds, opts]) {
|
|
177
|
+
const cause = opts?.cause instanceof Error ? opts.cause : undefined;
|
|
178
|
+
super({ code: HARNESS_ERRORS[name].code, adds: adds ?? [], cause });
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
export function harnessErrorCode(name) {
|
|
182
|
+
return HARNESS_ERRORS[name].code;
|
|
183
|
+
}
|
|
184
|
+
export function harnessErrorCodes() {
|
|
185
|
+
return Object.values(HARNESS_ERRORS).map(({ code }) => code);
|
|
186
|
+
}
|
|
187
|
+
export function isHarnessError(err, name) {
|
|
188
|
+
return isRecord(err) && String(err.code) === String(HARNESS_ERRORS[name].code);
|
|
189
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function createLoadStall(ms,
|
|
1
|
+
export function createLoadStall(ms, stalled) {
|
|
2
2
|
let timer = null;
|
|
3
3
|
let rejectStall = null;
|
|
4
4
|
const promise = new Promise((_, reject) => {
|
|
@@ -9,7 +9,7 @@ export function createLoadStall(ms, message) {
|
|
|
9
9
|
clearTimeout(timer);
|
|
10
10
|
}
|
|
11
11
|
timer = setTimeout(() => {
|
|
12
|
-
rejectStall?.(
|
|
12
|
+
rejectStall?.(stalled());
|
|
13
13
|
}, ms);
|
|
14
14
|
};
|
|
15
15
|
arm();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AbortSignal as BareAbortSignal } from 'bare-abort-controller';
|
|
2
|
-
|
|
2
|
+
import { HarnessError } from '../errors.ts';
|
|
3
|
+
export declare class AbortedError extends HarnessError<'ABORTED'> {
|
|
3
4
|
constructor();
|
|
4
5
|
}
|
|
5
6
|
export declare function raceAbort<T>(promise: Promise<T>, signal?: BareAbortSignal): Promise<T>;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import { HarnessError } from '../errors.js';
|
|
2
|
+
export class AbortedError extends HarnessError {
|
|
2
3
|
constructor() {
|
|
3
|
-
super('
|
|
4
|
-
this.name = 'AbortedError';
|
|
5
|
-
Error.captureStackTrace?.(this, AbortedError);
|
|
4
|
+
super('ABORTED');
|
|
6
5
|
}
|
|
7
6
|
}
|
|
8
7
|
export function raceAbort(promise, signal) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsonrepair } from 'jsonrepair';
|
|
2
2
|
import { isRecord } from '../../guards.js';
|
|
3
|
-
import {
|
|
3
|
+
import { log } from '../../log.js';
|
|
4
4
|
import { escapeLiteralDollars } from '../../tools/exec/scope.js';
|
|
5
5
|
const STRUCTURED_TYPES = new Set(['object', 'array']);
|
|
6
6
|
export class ArgRepairHook {
|
|
@@ -20,7 +20,7 @@ export class ArgRepairHook {
|
|
|
20
20
|
}
|
|
21
21
|
const parsed = parseStructured(value, types);
|
|
22
22
|
if (parsed === null) {
|
|
23
|
-
|
|
23
|
+
log.debug('arg repair declined', { tool: ctx.toolName, param: key, length: value.length });
|
|
24
24
|
continue;
|
|
25
25
|
}
|
|
26
26
|
args = { ...args, [key]: parsed };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { log } from '../log.js';
|
|
2
2
|
import { normalizeToolExecutionOutcome } from '../helpers/run-outcome.js';
|
|
3
3
|
import { harnessHooks } from './registry.js';
|
|
4
4
|
import { runHooks } from './run.js';
|
|
@@ -10,19 +10,19 @@ export class HookPipeline {
|
|
|
10
10
|
async onRunStart(payload) {
|
|
11
11
|
const folded = await runHooks(this._behaviorHooks, { phase: 'runStart', ...payload });
|
|
12
12
|
if ('guidance' in folded) {
|
|
13
|
-
|
|
13
|
+
log.warn('run hook failed', { stage: 'runStart', error: folded.error });
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
async onRunEnd(payload) {
|
|
17
17
|
const folded = await runHooks(this._behaviorHooks, { phase: 'runEnd', ...payload });
|
|
18
18
|
if ('guidance' in folded) {
|
|
19
|
-
|
|
19
|
+
log.warn('run hook failed', { stage: 'runEnd', error: folded.error });
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
async runPreToolFold(payload) {
|
|
23
23
|
const folded = await runHooks(this._behaviorHooks, { phase: 'preToolCall', ...payload });
|
|
24
24
|
if ('guidance' in folded) {
|
|
25
|
-
|
|
25
|
+
log.info('tool rejected: pre-hook refused the call', { tool: payload.toolName });
|
|
26
26
|
return { ok: false, rejection: folded };
|
|
27
27
|
}
|
|
28
28
|
return { ok: true, args: folded.args };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { errorMessage, isRecord } from '../guards.js';
|
|
2
|
-
import {
|
|
2
|
+
import { log } from '../log.js';
|
|
3
3
|
function cloneJson(value) {
|
|
4
4
|
try {
|
|
5
5
|
const text = JSON.stringify(value);
|
|
@@ -55,7 +55,7 @@ function merge(current, returned) {
|
|
|
55
55
|
}
|
|
56
56
|
function rejectionOf(current, err) {
|
|
57
57
|
const message = errorMessage(err);
|
|
58
|
-
|
|
58
|
+
log.warn('hook failed', { stage: current.phase, error: message });
|
|
59
59
|
if (current.phase === 'postToolCall') {
|
|
60
60
|
return {
|
|
61
61
|
error: `tool executed; output withheld: post-hook failed: ${message}. Do not retry this call.`,
|
package/dist-lib/lib/log.d.ts
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
|
+
import { type LogLevel } from '@qvac/logging';
|
|
2
|
+
export type { LogLevel };
|
|
3
|
+
export type LineLevel = Exclude<LogLevel, 'off'>;
|
|
4
|
+
type Write = (message: string, data?: Record<string, unknown>) => void;
|
|
5
|
+
type Sink = (line: string, level: LineLevel) => void;
|
|
6
|
+
export interface HarnessLog {
|
|
7
|
+
readonly error: Write;
|
|
8
|
+
readonly warn: Write;
|
|
9
|
+
readonly info: Write;
|
|
10
|
+
readonly debug: Write;
|
|
11
|
+
}
|
|
12
|
+
export interface HostLogger {
|
|
13
|
+
info(...args: unknown[]): void;
|
|
14
|
+
warn(...args: unknown[]): void;
|
|
15
|
+
error?(...args: unknown[]): void;
|
|
16
|
+
debug?(...args: unknown[]): void;
|
|
17
|
+
getLevel?(): string;
|
|
18
|
+
}
|
|
19
|
+
export declare const log: HarnessLog;
|
|
1
20
|
export declare function setHarnessLog(on: boolean): void;
|
|
2
|
-
export declare function
|
|
3
|
-
export declare function
|
|
21
|
+
export declare function setHarnessLogLevel(level: LogLevel): void;
|
|
22
|
+
export declare function followHostLevel(level: unknown): void;
|
|
23
|
+
export declare function logToHost(next: HostLogger | null): void;
|
|
24
|
+
export declare function harnessLogLevel(): LogLevel;
|
|
25
|
+
export declare function isLogLevel(value: unknown): value is LogLevel;
|
|
26
|
+
export declare function logEnabled(level: LineLevel): boolean;
|
|
27
|
+
export declare function setHarnessLogSink(next: Sink | null): void;
|
|
4
28
|
export declare function hlog(message: string, data?: Record<string, unknown>): void;
|
|
5
29
|
export declare function hdiag(message: string, data?: Record<string, unknown>): void;
|