@qvac/harness 0.1.2 → 0.2.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.
Files changed (38) hide show
  1. package/dist/harness.bundle +827 -6748
  2. package/dist/prebuilds-manifest.json +0 -7
  3. package/dist-lib/index.d.ts +1 -0
  4. package/dist-lib/index.js +21 -4
  5. package/dist-lib/lib/audio-transcode-bare.js +20 -20
  6. package/dist-lib/lib/capabilities/completion.d.ts +6 -0
  7. package/dist-lib/lib/capabilities/completion.js +48 -15
  8. package/dist-lib/lib/capabilities/download.d.ts +2 -0
  9. package/dist-lib/lib/capabilities/download.js +12 -3
  10. package/dist-lib/lib/capabilities/kv-cache.d.ts +1 -0
  11. package/dist-lib/lib/capabilities/kv-cache.js +7 -1
  12. package/dist-lib/lib/capabilities/tool-prompt-log.d.ts +23 -0
  13. package/dist-lib/lib/capabilities/tool-prompt-log.js +62 -0
  14. package/dist-lib/lib/capabilities/tool-selection.d.ts +2 -1
  15. package/dist-lib/lib/capabilities/tool-selection.js +2 -2
  16. package/dist-lib/lib/connect.d.ts +2 -0
  17. package/dist-lib/lib/connect.js +7 -1
  18. package/dist-lib/lib/contract-types.d.ts +1 -0
  19. package/dist-lib/lib/models/model-pool.d.ts +1 -1
  20. package/dist-lib/lib/sdk-loader.d.ts +1 -1
  21. package/dist-lib/lib/sdk-loader.js +1 -1
  22. package/dist-lib/lib/serve.js +2 -0
  23. package/dist-lib/lib/tools/exec.js +60 -8
  24. package/dist-lib/lib/tools/generate-image.d.ts +2 -1
  25. package/dist-lib/lib/tools/generate-image.js +2 -1
  26. package/dist-lib/lib/tools/skill.js +16 -0
  27. package/dist-lib/lib/wire.d.ts +1 -0
  28. package/dist-lib/lib/wire.js +6 -2
  29. package/dist-lib/schema/harness.js +12 -2
  30. package/dist-lib/spec/bind.js +3 -0
  31. package/dist-lib/spec/calls.js +1 -0
  32. package/dist-lib/spec/hrpc/hrpc.json +13 -0
  33. package/dist-lib/spec/hrpc/index.js +15 -3
  34. package/dist-lib/spec/hrpc/messages.js +35 -5
  35. package/dist-lib/spec/hyperschema/index.js +35 -5
  36. package/dist-lib/spec/hyperschema/schema.json +23 -0
  37. package/dist-lib/spec/hyperschema/types.d.ts +7 -1
  38. package/package.json +20 -12
@@ -59,16 +59,19 @@ function resolveExecution(adapters, fallback, args, ctx) {
59
59
  }
60
60
  return fallback.resolve(args, ctx);
61
61
  }
62
+ function isPresent(value) {
63
+ return value !== undefined && value !== null;
64
+ }
62
65
  function checkFileArgs(args, python) {
66
+ if (!python && (isPresent(args.inputs) || isPresent(args.outputs))) {
67
+ return 'inputs and outputs require language "python" with Pyodide enabled';
68
+ }
63
69
  const inputs = parseInputs(args.inputs);
64
70
  if (inputs && 'error' in inputs)
65
71
  return inputs.error;
66
72
  const outputs = parseOutputs(args.outputs);
67
73
  if (outputs && 'error' in outputs)
68
74
  return outputs.error;
69
- if ((inputs || outputs) && !python) {
70
- return 'inputs and outputs require language "python" with Pyodide enabled';
71
- }
72
75
  if (!python)
73
76
  return null;
74
77
  const workdir = parseWorkdir(args.workdir);
@@ -150,6 +153,12 @@ export function resolveScriptRun(rawArgs, skillsDir) {
150
153
  trusted: false
151
154
  };
152
155
  }
156
+ if (!script.startsWith('scripts/') || !script.endsWith('.py')) {
157
+ return {
158
+ error: 'script takes a scripts/*.py path bundled with a skill, not a command line — ' +
159
+ `run a shell command by passing it in \`command\` instead. Got: ${String(rawArgs.script)}`
160
+ };
161
+ }
153
162
  const skill = typeof rawArgs.skill === 'string' ? unquoteArg(rawArgs.skill) : '';
154
163
  if (!skill)
155
164
  return { error: 'script runs need the owning skill name in `skill`' };
@@ -158,11 +167,6 @@ export function resolveScriptRun(rawArgs, skillsDir) {
158
167
  if (String(rawArgs.command ?? '').trim()) {
159
168
  return { error: 'pass either command or script, never both' };
160
169
  }
161
- if (!script.startsWith('scripts/') || !script.endsWith('.py')) {
162
- return {
163
- error: `script must be a scripts/*.py path from the skill instructions, got: ${script}`
164
- };
165
- }
166
170
  const segments = [...skill.split('/'), ...script.split('/')];
167
171
  if (segments.some((segment) => segment === '' || segment === '..' || segment.includes('\\'))) {
168
172
  return { error: `script not found in skill ${skill}: ${script}` };
@@ -294,6 +298,54 @@ export function createExecTool({ spawn, killProcess, loadPyodide, disablePyodide
294
298
  },
295
299
  required: []
296
300
  },
301
+ prompt: {
302
+ description: "Run one program on the user's device: a shell command, or Python source in `command` with " +
303
+ 'language="python". Chaining, pipes, redirection and shell expansion are rejected. ' +
304
+ 'Returns stdout, stderr, exit code. Run a script ' +
305
+ 'bundled with a loaded skill via `skill`+`script`+`scriptArgs`, never as retyped source.',
306
+ parameters: {
307
+ type: 'object',
308
+ properties: {
309
+ command: {
310
+ type: 'string',
311
+ description: 'Shell command, or bare Python source when language="python".'
312
+ },
313
+ language: {
314
+ type: 'string',
315
+ enum: ['shell', 'python'],
316
+ description: '"python" runs `command` as Python; default shell.'
317
+ },
318
+ packages: { type: 'array', description: 'python only: PyPI packages to install.' },
319
+ inputs: {
320
+ type: 'array',
321
+ description: 'python only: attachments to stage as {attachmentId, path}, path a bare file name; ' +
322
+ 'omit attachmentId for the latest attached image.'
323
+ },
324
+ outputs: {
325
+ type: 'array',
326
+ description: 'Only with language "python": bare file names the code writes; attached on success.'
327
+ },
328
+ workdir: { type: 'string' },
329
+ timeoutMs: { type: 'number', description: 'default 120000, max 600000.' },
330
+ maxOutputChars: {
331
+ type: 'number',
332
+ description: 'stdout/stderr cap (default 8192, max 65536); raise for long content.'
333
+ },
334
+ script: {
335
+ type: 'string',
336
+ description: 'Run a python script bundled with a loaded skill instead of passing source: a scripts/*.py ' +
337
+ 'path exactly as the skill instructions name it (e.g. "scripts/extract_text.py"). Requires ' +
338
+ '`skill`; leave `command` unset. Never a command line — shell commands go in `command`.'
339
+ },
340
+ skill: {
341
+ type: 'string',
342
+ description: 'With script: the name of the skill that bundles it (e.g. "pdf").'
343
+ },
344
+ scriptArgs: { type: 'array', description: 'With script: string arguments in order.' }
345
+ },
346
+ required: []
347
+ }
348
+ },
297
349
  autoApprove: false,
298
350
  effect(args, ctx) {
299
351
  if (typeof args.script === 'string' && args.script.trim() && !args.script.includes('\n')) {
@@ -67,6 +67,7 @@ export declare const IMAGE_LOAD_STALL_MS: number;
67
67
  export interface DiffusionRuntimeOptions extends ImageModelSet {
68
68
  loadSdk: () => Promise<DiffusionSdk>;
69
69
  onProgress?: (model: string, progress: Record<string, unknown>) => void;
70
+ onLoaded?: (model: string) => void;
70
71
  onBeforeLoad?: (signal?: BareAbortSignal) => Promise<void>;
71
72
  loads?: LoadTracker;
72
73
  stallMs?: number;
@@ -86,7 +87,7 @@ export interface DiffusionRuntime {
86
87
  }
87
88
  export declare function generationPercentTick(onPercent: (percentage: number) => void, encodePhases?: number): (tick: DiffusionTick) => void;
88
89
  export declare const IMAGE_LOAD_STALL_ERROR = "image model download stalled";
89
- export declare function createDiffusionRuntime({ loadSdk, onProgress, onBeforeLoad, loads, stallMs, ...base }: DiffusionRuntimeOptions): DiffusionRuntime;
90
+ export declare function createDiffusionRuntime({ loadSdk, onProgress, onLoaded, onBeforeLoad, loads, stallMs, ...base }: DiffusionRuntimeOptions): DiffusionRuntime;
90
91
  export declare const BUSY_ERROR = "an image generation is already running; try again when it finishes";
91
92
  export declare function runDiffusion(sdk: DiffusionSdk, modelId: string, params: DiffusionParams, signal?: BareAbortSignal, onTick?: (tick: DiffusionTick) => void): Promise<Uint8Array | {
92
93
  error: string;
@@ -60,7 +60,7 @@ function createLoadStall(ms) {
60
60
  promise
61
61
  };
62
62
  }
63
- export function createDiffusionRuntime({ loadSdk, onProgress, onBeforeLoad, loads = createLoadTracker(), stallMs = IMAGE_LOAD_STALL_MS, ...base }) {
63
+ export function createDiffusionRuntime({ loadSdk, onProgress, onLoaded, onBeforeLoad, loads = createLoadTracker(), stallMs = IMAGE_LOAD_STALL_MS, ...base }) {
64
64
  let loading = null;
65
65
  let residentFingerprint = null;
66
66
  let busy = false;
@@ -128,6 +128,7 @@ export function createDiffusionRuntime({ loadSdk, onProgress, onBeforeLoad, load
128
128
  });
129
129
  try {
130
130
  const modelId = await Promise.race([loads.track(pending), stall.promise]);
131
+ onLoaded?.(diffusionProgressName(set));
131
132
  return { modelId, prediction: set.prediction };
132
133
  }
133
134
  catch (err) {
@@ -87,6 +87,22 @@ export function createSkillTool({ skillsDir, overlayDir = resolveSkillsOverlayDi
87
87
  },
88
88
  required: ['name']
89
89
  },
90
+ prompt: {
91
+ description: "Load a named skill's instructions FIRST, before any other tool, when a listed skill covers " +
92
+ 'what you are about to do — and again with `file` for any file they reference.',
93
+ parameters: {
94
+ type: 'object',
95
+ properties: {
96
+ name: { type: 'string' },
97
+ file: {
98
+ type: 'string',
99
+ description: "A file inside the skill, exactly as named there (e.g. 'references/edit.md'). " +
100
+ 'Omit for the main instructions.'
101
+ }
102
+ },
103
+ required: ['name']
104
+ }
105
+ },
90
106
  effect: () => 'read',
91
107
  autoApprove: true,
92
108
  async execute(args, ctx) {
@@ -35,6 +35,7 @@ export interface WireEvent {
35
35
  }
36
36
  export interface WireDownloadEvent {
37
37
  type: string;
38
+ downloaded?: boolean | null;
38
39
  progress?: unknown;
39
40
  assetId?: string | null;
40
41
  message?: string | null;
@@ -88,7 +88,11 @@ export function toDownloadWire(event) {
88
88
  return { type, progress };
89
89
  }
90
90
  case 'complete':
91
- return { type: 'complete', assetId: event.assetId };
91
+ return {
92
+ type: 'complete',
93
+ assetId: event.assetId,
94
+ downloaded: typeof event.downloaded === 'boolean' ? event.downloaded : undefined
95
+ };
92
96
  case 'error':
93
97
  return { type: 'error', message: event.message };
94
98
  case 'aborted':
@@ -102,7 +106,7 @@ export function fromDownloadWire(event) {
102
106
  case 'progress':
103
107
  return { type: 'progress', ...(event.progress ?? {}) };
104
108
  case 'complete':
105
- return { type: 'complete', assetId: event.assetId ?? '' };
109
+ return { type: 'complete', assetId: event.assetId ?? '', downloaded: event.downloaded };
106
110
  case 'error':
107
111
  return { type: 'error', message: event.message ?? 'download error' };
108
112
  case 'aborted':
@@ -167,7 +167,7 @@ export function registerHarnessTypes(ns) {
167
167
  });
168
168
  ns.register({
169
169
  name: 'model-event-status',
170
- enum: ['loading', 'downloading', 'ready', 'error', 'unloading', 'unloaded'],
170
+ enum: ['loading', 'downloading', 'ready', 'error', 'unloading', 'unloaded', 'downloaded'],
171
171
  strings: true
172
172
  });
173
173
  ns.register({
@@ -209,7 +209,8 @@ export function registerHarnessTypes(ns) {
209
209
  { name: 'type', type: '@harness/download-event-type', required: true },
210
210
  { name: 'progress', type: 'json' },
211
211
  { name: 'assetId', type: 'string' },
212
- { name: 'message', type: 'string' }
212
+ { name: 'message', type: 'string' },
213
+ { name: 'downloaded', type: 'bool', useDefault: false }
213
214
  ]
214
215
  });
215
216
  ns.register({
@@ -605,6 +606,10 @@ export function registerHarnessTypes(ns) {
605
606
  name: 'delete-skill-response',
606
607
  fields: [{ name: 'removed', type: 'bool', required: true }]
607
608
  });
609
+ ns.register({
610
+ name: 'kv-cache-delete-request',
611
+ fields: [{ name: 'kvCacheKey', type: 'string', required: true }]
612
+ });
608
613
  }
609
614
  export function registerHarnessApi(api) {
610
615
  api.register({
@@ -742,4 +747,9 @@ export function registerHarnessApi(api) {
742
747
  request: { name: '@harness/skill-name-request', stream: false },
743
748
  response: { name: '@harness/delete-skill-response', stream: false }
744
749
  });
750
+ api.register({
751
+ name: 'delete-kv-cache',
752
+ request: { name: '@harness/kv-cache-delete-request', stream: false },
753
+ response: { name: '@harness/kv-cache-deletion-response', stream: false }
754
+ });
745
755
  }
@@ -121,4 +121,7 @@ export function bindApi(rpc, api) {
121
121
  if (api.deleteOverlaySkill) {
122
122
  rpc.onDeleteOverlaySkill((req) => api.deleteOverlaySkill(req));
123
123
  }
124
+ if (api.deleteKvCache) {
125
+ rpc.onDeleteKvCache((req) => api.deleteKvCache(req));
126
+ }
124
127
  }
@@ -37,5 +37,6 @@ export function harnessClient(rpc) {
37
37
  writeSkillFile: (input) => rpc.writeSkillFile(input),
38
38
  copySkillForEdit: (input) => rpc.copySkillForEdit(input),
39
39
  deleteOverlaySkill: (input) => rpc.deleteOverlaySkill(input),
40
+ deleteKvCache: (input) => rpc.deleteKvCache(input),
40
41
  };
41
42
  }
@@ -351,6 +351,19 @@
351
351
  "stream": false
352
352
  },
353
353
  "version": 1
354
+ },
355
+ {
356
+ "id": 27,
357
+ "name": "@harness/delete-kv-cache",
358
+ "request": {
359
+ "name": "@harness/kv-cache-delete-request",
360
+ "stream": false
361
+ },
362
+ "response": {
363
+ "name": "@harness/kv-cache-deletion-response",
364
+ "stream": false
365
+ },
366
+ "version": 1
354
367
  }
355
368
  ]
356
369
  }
@@ -59,7 +59,9 @@ const methods = new Map([
59
59
  ['@harness/copy-skill-for-edit', 25],
60
60
  [25, '@harness/copy-skill-for-edit'],
61
61
  ['@harness/delete-overlay-skill', 26],
62
- [26, '@harness/delete-overlay-skill']
62
+ [26, '@harness/delete-overlay-skill'],
63
+ ['@harness/delete-kv-cache', 27],
64
+ [27, '@harness/delete-kv-cache']
63
65
  ])
64
66
 
65
67
  class HRPC {
@@ -93,7 +95,8 @@ class HRPC {
93
95
  ['@harness/read-skill-file', getEncoding('@harness/skill-name-request')],
94
96
  ['@harness/write-skill-file', getEncoding('@harness/write-skill-request')],
95
97
  ['@harness/copy-skill-for-edit', getEncoding('@harness/skill-name-request')],
96
- ['@harness/delete-overlay-skill', getEncoding('@harness/skill-name-request')]
98
+ ['@harness/delete-overlay-skill', getEncoding('@harness/skill-name-request')],
99
+ ['@harness/delete-kv-cache', getEncoding('@harness/kv-cache-delete-request')]
97
100
  ])
98
101
  this._responseEncodings = new Map([
99
102
  ['@harness/completion', getEncoding('@harness/completion-event')],
@@ -122,7 +125,8 @@ class HRPC {
122
125
  ['@harness/read-skill-file', getEncoding('@harness/skill-file-response')],
123
126
  ['@harness/write-skill-file', getEncoding('@harness/ok-response')],
124
127
  ['@harness/copy-skill-for-edit', getEncoding('@harness/copy-skill-response')],
125
- ['@harness/delete-overlay-skill', getEncoding('@harness/delete-skill-response')]
128
+ ['@harness/delete-overlay-skill', getEncoding('@harness/delete-skill-response')],
129
+ ['@harness/delete-kv-cache', getEncoding('@harness/kv-cache-deletion-response')]
126
130
  ])
127
131
  this._rpc = new RPC(stream, async (req) => {
128
132
  const command = methods.get(req.command)
@@ -328,6 +332,10 @@ class HRPC {
328
332
  return this._call('@harness/delete-overlay-skill', args)
329
333
  }
330
334
 
335
+ async deleteKvCache(args) {
336
+ return this._call('@harness/delete-kv-cache', args)
337
+ }
338
+
331
339
  onCompletion(responseFn) {
332
340
  this._handlers['@harness/completion'] = responseFn
333
341
  }
@@ -436,6 +444,10 @@ class HRPC {
436
444
  this._handlers['@harness/delete-overlay-skill'] = responseFn
437
445
  }
438
446
 
447
+ onDeleteKvCache(responseFn) {
448
+ this._handlers['@harness/delete-kv-cache'] = responseFn
449
+ }
450
+
439
451
  _requestIsStream(command) {
440
452
  return [
441
453
  '@harness/completion',
@@ -878,13 +878,14 @@ const encoding14_enum = {
878
878
  ready: 'ready',
879
879
  error: 'error',
880
880
  unloading: 'unloading',
881
- unloaded: 'unloaded'
881
+ unloaded: 'unloaded',
882
+ downloaded: 'downloaded'
882
883
  }
883
884
 
884
885
  // @harness/model-event-status enum
885
886
  const encoding14 = {
886
887
  preencode (state, m) {
887
- state.end++ // max enum is 6 so always one byte
888
+ state.end++ // max enum is 7 so always one byte
888
889
  },
889
890
  encode (state, m) {
890
891
  switch (m) {
@@ -906,6 +907,9 @@ const encoding14 = {
906
907
  case 'unloaded':
907
908
  c.uint.encode(state, 6)
908
909
  break
910
+ case 'downloaded':
911
+ c.uint.encode(state, 7)
912
+ break
909
913
  default:
910
914
  throw new Error('Unknown enum')
911
915
  }
@@ -924,6 +928,8 @@ const encoding14 = {
924
928
  return 'unloading'
925
929
  case 6:
926
930
  return 'unloaded'
931
+ case 7:
932
+ return 'downloaded'
927
933
  default: return null
928
934
  }
929
935
  }
@@ -1080,14 +1086,18 @@ const encoding18 = {
1080
1086
  const encoding19 = {
1081
1087
  preencode(state, m) {
1082
1088
  encoding18.preencode(state, m.type)
1083
- state.end++ // max flag is 4 so always one byte
1089
+ state.end++ // max flag is 8 so always one byte
1084
1090
 
1085
1091
  if (m.progress) c.json.preencode(state, m.progress)
1086
1092
  if (m.assetId) c.string.preencode(state, m.assetId)
1087
1093
  if (m.message) c.string.preencode(state, m.message)
1088
1094
  },
1089
1095
  encode(state, m) {
1090
- const flags = (m.progress ? 1 : 0) | (m.assetId ? 2 : 0) | (m.message ? 4 : 0)
1096
+ const flags =
1097
+ (m.progress ? 1 : 0) |
1098
+ (m.assetId ? 2 : 0) |
1099
+ (m.message ? 4 : 0) |
1100
+ ((version >= 7 && m.downloaded) ? 8 : 0)
1091
1101
 
1092
1102
  encoding18.encode(state, m.type)
1093
1103
  c.uint.encode(state, flags)
@@ -1104,7 +1114,8 @@ const encoding19 = {
1104
1114
  type: r0,
1105
1115
  progress: (flags & 1) !== 0 ? c.json.decode(state) : null,
1106
1116
  assetId: (flags & 2) !== 0 ? c.string.decode(state) : null,
1107
- message: (flags & 4) !== 0 ? c.string.decode(state) : null
1117
+ message: (flags & 4) !== 0 ? c.string.decode(state) : null,
1118
+ downloaded: (version >= 7 && (flags & 8) !== 0)
1108
1119
  }
1109
1120
  }
1110
1121
  }
@@ -2862,6 +2873,23 @@ const encoding76 = {
2862
2873
  }
2863
2874
  }
2864
2875
 
2876
+ // @harness/kv-cache-delete-request
2877
+ const encoding77 = {
2878
+ preencode(state, m) {
2879
+ c.string.preencode(state, m.kvCacheKey)
2880
+ },
2881
+ encode(state, m) {
2882
+ c.string.encode(state, m.kvCacheKey)
2883
+ },
2884
+ decode(state) {
2885
+ const r0 = c.string.decode(state)
2886
+
2887
+ return {
2888
+ kvCacheKey: r0
2889
+ }
2890
+ }
2891
+ }
2892
+
2865
2893
  // @harness/completion-frame.grantedDrives, deferred due to recusive use
2866
2894
  const encoding11_23 = c.array(c.frame(encoding60))
2867
2895
  // @harness/skill.setupV2, deferred due to recusive use
@@ -3074,6 +3102,8 @@ function getEncoding(name) {
3074
3102
  return encoding75
3075
3103
  case '@harness/delete-skill-response':
3076
3104
  return encoding76
3105
+ case '@harness/kv-cache-delete-request':
3106
+ return encoding77
3077
3107
  default:
3078
3108
  throw new Error('Encoder not found ' + name)
3079
3109
  }
@@ -878,13 +878,14 @@ const encoding14_enum = {
878
878
  ready: 'ready',
879
879
  error: 'error',
880
880
  unloading: 'unloading',
881
- unloaded: 'unloaded'
881
+ unloaded: 'unloaded',
882
+ downloaded: 'downloaded'
882
883
  }
883
884
 
884
885
  // @harness/model-event-status enum
885
886
  const encoding14 = {
886
887
  preencode (state, m) {
887
- state.end++ // max enum is 6 so always one byte
888
+ state.end++ // max enum is 7 so always one byte
888
889
  },
889
890
  encode (state, m) {
890
891
  switch (m) {
@@ -906,6 +907,9 @@ const encoding14 = {
906
907
  case 'unloaded':
907
908
  c.uint.encode(state, 6)
908
909
  break
910
+ case 'downloaded':
911
+ c.uint.encode(state, 7)
912
+ break
909
913
  default:
910
914
  throw new Error('Unknown enum')
911
915
  }
@@ -924,6 +928,8 @@ const encoding14 = {
924
928
  return 'unloading'
925
929
  case 6:
926
930
  return 'unloaded'
931
+ case 7:
932
+ return 'downloaded'
927
933
  default: return null
928
934
  }
929
935
  }
@@ -1080,14 +1086,18 @@ const encoding18 = {
1080
1086
  const encoding19 = {
1081
1087
  preencode(state, m) {
1082
1088
  encoding18.preencode(state, m.type)
1083
- state.end++ // max flag is 4 so always one byte
1089
+ state.end++ // max flag is 8 so always one byte
1084
1090
 
1085
1091
  if (m.progress) c.json.preencode(state, m.progress)
1086
1092
  if (m.assetId) c.string.preencode(state, m.assetId)
1087
1093
  if (m.message) c.string.preencode(state, m.message)
1088
1094
  },
1089
1095
  encode(state, m) {
1090
- const flags = (m.progress ? 1 : 0) | (m.assetId ? 2 : 0) | (m.message ? 4 : 0)
1096
+ const flags =
1097
+ (m.progress ? 1 : 0) |
1098
+ (m.assetId ? 2 : 0) |
1099
+ (m.message ? 4 : 0) |
1100
+ ((version >= 7 && m.downloaded) ? 8 : 0)
1091
1101
 
1092
1102
  encoding18.encode(state, m.type)
1093
1103
  c.uint.encode(state, flags)
@@ -1104,7 +1114,8 @@ const encoding19 = {
1104
1114
  type: r0,
1105
1115
  progress: (flags & 1) !== 0 ? c.json.decode(state) : null,
1106
1116
  assetId: (flags & 2) !== 0 ? c.string.decode(state) : null,
1107
- message: (flags & 4) !== 0 ? c.string.decode(state) : null
1117
+ message: (flags & 4) !== 0 ? c.string.decode(state) : null,
1118
+ downloaded: (version >= 7 && (flags & 8) !== 0)
1108
1119
  }
1109
1120
  }
1110
1121
  }
@@ -2862,6 +2873,23 @@ const encoding76 = {
2862
2873
  }
2863
2874
  }
2864
2875
 
2876
+ // @harness/kv-cache-delete-request
2877
+ const encoding77 = {
2878
+ preencode(state, m) {
2879
+ c.string.preencode(state, m.kvCacheKey)
2880
+ },
2881
+ encode(state, m) {
2882
+ c.string.encode(state, m.kvCacheKey)
2883
+ },
2884
+ decode(state) {
2885
+ const r0 = c.string.decode(state)
2886
+
2887
+ return {
2888
+ kvCacheKey: r0
2889
+ }
2890
+ }
2891
+ }
2892
+
2865
2893
  // @harness/completion-frame.grantedDrives, deferred due to recusive use
2866
2894
  const encoding11_23 = c.array(c.frame(encoding60))
2867
2895
  // @harness/skill.setupV2, deferred due to recusive use
@@ -3074,6 +3102,8 @@ function getEncoding(name) {
3074
3102
  return encoding75
3075
3103
  case '@harness/delete-skill-response':
3076
3104
  return encoding76
3105
+ case '@harness/kv-cache-delete-request':
3106
+ return encoding77
3077
3107
  default:
3078
3108
  throw new Error('Encoder not found ' + name)
3079
3109
  }
@@ -698,6 +698,10 @@
698
698
  {
699
699
  "key": "unloaded",
700
700
  "version": 1
701
+ },
702
+ {
703
+ "key": "downloaded",
704
+ "version": 7
701
705
  }
702
706
  ],
703
707
  "strings": true
@@ -846,6 +850,11 @@
846
850
  "name": "message",
847
851
  "type": "string",
848
852
  "version": 1
853
+ },
854
+ {
855
+ "name": "downloaded",
856
+ "type": "bool",
857
+ "version": 7
849
858
  }
850
859
  ]
851
860
  },
@@ -2285,6 +2294,20 @@
2285
2294
  "version": 6
2286
2295
  }
2287
2296
  ]
2297
+ },
2298
+ {
2299
+ "name": "kv-cache-delete-request",
2300
+ "namespace": "harness",
2301
+ "compact": false,
2302
+ "flagsPosition": -1,
2303
+ "fields": [
2304
+ {
2305
+ "name": "kvCacheKey",
2306
+ "required": true,
2307
+ "type": "string",
2308
+ "version": 7
2309
+ }
2310
+ ]
2288
2311
  }
2289
2312
  ]
2290
2313
  }
@@ -121,7 +121,7 @@ export interface HarnessCompletionEvent {
121
121
  rawCall?: string | null
122
122
  }
123
123
 
124
- export type HarnessModelEventStatus = "loading" | "downloading" | "ready" | "error" | "unloading" | "unloaded"
124
+ export type HarnessModelEventStatus = "loading" | "downloading" | "ready" | "error" | "unloading" | "unloaded" | "downloaded"
125
125
 
126
126
  export interface HarnessLoadedModel {
127
127
  model: string
@@ -152,6 +152,7 @@ export interface HarnessDownloadEvent {
152
152
  progress?: unknown | null
153
153
  assetId?: string | null
154
154
  message?: string | null
155
+ downloaded?: boolean
155
156
  }
156
157
 
157
158
  export interface HarnessEmbedRequest {
@@ -473,6 +474,10 @@ export interface HarnessDeleteSkillResponse {
473
474
  removed?: boolean
474
475
  }
475
476
 
477
+ export interface HarnessKvCacheDeleteRequest {
478
+ kvCacheKey: string
479
+ }
480
+
476
481
  export interface SchemaTypes {
477
482
  "@harness/empty": HarnessEmpty
478
483
  "@harness/ok-response": HarnessOkResponse
@@ -551,4 +556,5 @@ export interface SchemaTypes {
551
556
  "@harness/write-skill-request": HarnessWriteSkillRequest
552
557
  "@harness/copy-skill-response": HarnessCopySkillResponse
553
558
  "@harness/delete-skill-response": HarnessDeleteSkillResponse
559
+ "@harness/kv-cache-delete-request": HarnessKvCacheDeleteRequest
554
560
  }