@qvac/harness 0.5.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.
@@ -191,6 +191,18 @@ export function serveHarness(stream, harness) {
191
191
  await harness.warmModel({ model, agent: agent ?? {} });
192
192
  return { ok: true };
193
193
  },
194
+ loadModel: async ({ model, agent }) => {
195
+ if (!harness.loadModel) {
196
+ throw new Error('harness does not support loadModel');
197
+ }
198
+ return harness.loadModel({ model, agent: agent ?? {} });
199
+ },
200
+ unloadModel: async ({ model }) => {
201
+ if (!harness.unloadModel) {
202
+ throw new Error('harness does not support unloadModel');
203
+ }
204
+ return harness.unloadModel({ model });
205
+ },
194
206
  modelEvents: () => modelEvents(harness),
195
207
  completion: completion(harness)
196
208
  });
@@ -721,6 +721,21 @@ export function registerHarnessTypes(ns) {
721
721
  name: 'set-model-idle-timeout-request',
722
722
  fields: [{ name: 'ms', type: 'uint', required: true }]
723
723
  });
724
+ ns.register({
725
+ name: 'load-model-response',
726
+ fields: [
727
+ { name: 'loaded', type: 'bool', required: true },
728
+ { name: 'reason', type: 'string' }
729
+ ]
730
+ });
731
+ ns.register({
732
+ name: 'unload-model-request',
733
+ fields: [{ name: 'model', type: 'string', required: true }]
734
+ });
735
+ ns.register({
736
+ name: 'unload-model-response',
737
+ fields: [{ name: 'unloaded', type: 'bool', required: true }]
738
+ });
724
739
  }
725
740
  export function registerHarnessApi(api) {
726
741
  api.register({
@@ -878,4 +893,14 @@ export function registerHarnessApi(api) {
878
893
  request: { name: '@harness/set-model-idle-timeout-request', stream: false },
879
894
  response: { name: '@harness/ok-response', stream: false }
880
895
  });
896
+ api.register({
897
+ name: 'load-model',
898
+ request: { name: '@harness/warm-model-request', stream: false },
899
+ response: { name: '@harness/load-model-response', stream: false }
900
+ });
901
+ api.register({
902
+ name: 'unload-model',
903
+ request: { name: '@harness/unload-model-request', stream: false },
904
+ response: { name: '@harness/unload-model-response', stream: false }
905
+ });
881
906
  }
@@ -133,4 +133,10 @@ export function bindApi(rpc, api) {
133
133
  if (api.setModelIdleTimeout) {
134
134
  rpc.onSetModelIdleTimeout((req) => api.setModelIdleTimeout(req));
135
135
  }
136
+ if (api.loadModel) {
137
+ rpc.onLoadModel((req) => api.loadModel(req));
138
+ }
139
+ if (api.unloadModel) {
140
+ rpc.onUnloadModel((req) => api.unloadModel(req));
141
+ }
136
142
  }
@@ -41,5 +41,7 @@ export function harnessClient(rpc) {
41
41
  detectLanguage: (input) => rpc.detectLanguage(input),
42
42
  previewModelSource: (input) => rpc.previewModelSource(input),
43
43
  setModelIdleTimeout: (input) => rpc.setModelIdleTimeout(input),
44
+ loadModel: (input) => rpc.loadModel(input),
45
+ unloadModel: (input) => rpc.unloadModel(input),
44
46
  };
45
47
  }
@@ -403,6 +403,32 @@
403
403
  "stream": false
404
404
  },
405
405
  "version": 1
406
+ },
407
+ {
408
+ "id": 31,
409
+ "name": "@harness/load-model",
410
+ "request": {
411
+ "name": "@harness/warm-model-request",
412
+ "stream": false
413
+ },
414
+ "response": {
415
+ "name": "@harness/load-model-response",
416
+ "stream": false
417
+ },
418
+ "version": 1
419
+ },
420
+ {
421
+ "id": 32,
422
+ "name": "@harness/unload-model",
423
+ "request": {
424
+ "name": "@harness/unload-model-request",
425
+ "stream": false
426
+ },
427
+ "response": {
428
+ "name": "@harness/unload-model-response",
429
+ "stream": false
430
+ },
431
+ "version": 1
406
432
  }
407
433
  ]
408
434
  }
@@ -67,7 +67,11 @@ const methods = new Map([
67
67
  ['@harness/preview-model-source', 29],
68
68
  [29, '@harness/preview-model-source'],
69
69
  ['@harness/set-model-idle-timeout', 30],
70
- [30, '@harness/set-model-idle-timeout']
70
+ [30, '@harness/set-model-idle-timeout'],
71
+ ['@harness/load-model', 31],
72
+ [31, '@harness/load-model'],
73
+ ['@harness/unload-model', 32],
74
+ [32, '@harness/unload-model']
71
75
  ])
72
76
 
73
77
  class HRPC {
@@ -105,7 +109,9 @@ class HRPC {
105
109
  ['@harness/delete-kv-cache', getEncoding('@harness/kv-cache-delete-request')],
106
110
  ['@harness/detect-language', getEncoding('@harness/detect-language-request')],
107
111
  ['@harness/preview-model-source', getEncoding('@harness/preview-model-source-request')],
108
- ['@harness/set-model-idle-timeout', getEncoding('@harness/set-model-idle-timeout-request')]
112
+ ['@harness/set-model-idle-timeout', getEncoding('@harness/set-model-idle-timeout-request')],
113
+ ['@harness/load-model', getEncoding('@harness/warm-model-request')],
114
+ ['@harness/unload-model', getEncoding('@harness/unload-model-request')]
109
115
  ])
110
116
  this._responseEncodings = new Map([
111
117
  ['@harness/completion', getEncoding('@harness/completion-event')],
@@ -138,7 +144,9 @@ class HRPC {
138
144
  ['@harness/delete-kv-cache', getEncoding('@harness/kv-cache-deletion-response')],
139
145
  ['@harness/detect-language', getEncoding('@harness/detect-language-response')],
140
146
  ['@harness/preview-model-source', getEncoding('@harness/preview-model-source-response')],
141
- ['@harness/set-model-idle-timeout', getEncoding('@harness/ok-response')]
147
+ ['@harness/set-model-idle-timeout', getEncoding('@harness/ok-response')],
148
+ ['@harness/load-model', getEncoding('@harness/load-model-response')],
149
+ ['@harness/unload-model', getEncoding('@harness/unload-model-response')]
142
150
  ])
143
151
  this._rpc = new RPC(stream, async (req) => {
144
152
  const command = methods.get(req.command)
@@ -360,6 +368,14 @@ class HRPC {
360
368
  return this._call('@harness/set-model-idle-timeout', args)
361
369
  }
362
370
 
371
+ async loadModel(args) {
372
+ return this._call('@harness/load-model', args)
373
+ }
374
+
375
+ async unloadModel(args) {
376
+ return this._call('@harness/unload-model', args)
377
+ }
378
+
363
379
  onCompletion(responseFn) {
364
380
  this._handlers['@harness/completion'] = responseFn
365
381
  }
@@ -484,6 +500,14 @@ class HRPC {
484
500
  this._handlers['@harness/set-model-idle-timeout'] = responseFn
485
501
  }
486
502
 
503
+ onLoadModel(responseFn) {
504
+ this._handlers['@harness/load-model'] = responseFn
505
+ }
506
+
507
+ onUnloadModel(responseFn) {
508
+ this._handlers['@harness/unload-model'] = responseFn
509
+ }
510
+
487
511
  _requestIsStream(command) {
488
512
  return [
489
513
  '@harness/completion',
@@ -1,12 +1,12 @@
1
1
  // This file is autogenerated by the hyperschema compiler
2
- // Schema Version: 15
2
+ // Schema Version: 16
3
3
  /* eslint-disable camelcase */
4
4
  /* eslint-disable quotes */
5
5
  /* eslint-disable space-before-function-paren */
6
6
 
7
7
  import { c } from 'hyperschema/runtime'
8
8
 
9
- const VERSION = 15
9
+ const VERSION = 16
10
10
 
11
11
  // eslint-disable-next-line no-unused-vars
12
12
  let version = VERSION
@@ -3365,6 +3365,66 @@ const encoding88 = {
3365
3365
  }
3366
3366
  }
3367
3367
 
3368
+ // @harness/load-model-response
3369
+ const encoding89 = {
3370
+ preencode(state, m) {
3371
+ state.end++ // max flag is 2 so always one byte
3372
+
3373
+ if (version >= 16 && m.reason) c.string.preencode(state, m.reason)
3374
+ },
3375
+ encode(state, m) {
3376
+ const flags = ((version >= 16 && m.loaded) ? 1 : 0) | ((version >= 16 && m.reason) ? 2 : 0)
3377
+
3378
+ c.uint.encode(state, flags)
3379
+
3380
+ if (version >= 16 && m.reason) c.string.encode(state, m.reason)
3381
+ },
3382
+ decode(state) {
3383
+ const flags = c.uint.decode(state)
3384
+
3385
+ return {
3386
+ loaded: (version >= 16 && (flags & 1) !== 0),
3387
+ reason: (version >= 16 && (flags & 2) !== 0) ? c.string.decode(state) : null
3388
+ }
3389
+ }
3390
+ }
3391
+
3392
+ // @harness/unload-model-request
3393
+ const encoding90 = {
3394
+ preencode(state, m) {
3395
+ c.string.preencode(state, m.model)
3396
+ },
3397
+ encode(state, m) {
3398
+ c.string.encode(state, m.model)
3399
+ },
3400
+ decode(state) {
3401
+ const r0 = c.string.decode(state)
3402
+
3403
+ return {
3404
+ model: r0
3405
+ }
3406
+ }
3407
+ }
3408
+
3409
+ // @harness/unload-model-response
3410
+ const encoding91 = {
3411
+ preencode(state, m) {
3412
+ state.end++ // max flag is 1 so always one byte
3413
+ },
3414
+ encode(state, m) {
3415
+ const flags = (version >= 16 && m.unloaded) ? 1 : 0
3416
+
3417
+ c.uint.encode(state, flags)
3418
+ },
3419
+ decode(state) {
3420
+ const flags = c.uint.decode(state)
3421
+
3422
+ return {
3423
+ unloaded: (version >= 16 && (flags & 1) !== 0)
3424
+ }
3425
+ }
3426
+ }
3427
+
3368
3428
  // @harness/completion-frame.grantedDrives, deferred due to recusive use
3369
3429
  const encoding11_23 = c.array(c.frame(encoding60))
3370
3430
  // @harness/skill.setupV2, deferred due to recusive use
@@ -3605,6 +3665,12 @@ function getEncoding(name) {
3605
3665
  return encoding87
3606
3666
  case '@harness/set-model-idle-timeout-request':
3607
3667
  return encoding88
3668
+ case '@harness/load-model-response':
3669
+ return encoding89
3670
+ case '@harness/unload-model-request':
3671
+ return encoding90
3672
+ case '@harness/unload-model-response':
3673
+ return encoding91
3608
3674
  default:
3609
3675
  throw new Error('Encoder not found ' + name)
3610
3676
  }
@@ -1,12 +1,12 @@
1
1
  // This file is autogenerated by the hyperschema compiler
2
- // Schema Version: 15
2
+ // Schema Version: 16
3
3
  /* eslint-disable camelcase */
4
4
  /* eslint-disable quotes */
5
5
  /* eslint-disable space-before-function-paren */
6
6
 
7
7
  import { c } from 'hyperschema/runtime'
8
8
 
9
- const VERSION = 15
9
+ const VERSION = 16
10
10
 
11
11
  // eslint-disable-next-line no-unused-vars
12
12
  let version = VERSION
@@ -3365,6 +3365,66 @@ const encoding88 = {
3365
3365
  }
3366
3366
  }
3367
3367
 
3368
+ // @harness/load-model-response
3369
+ const encoding89 = {
3370
+ preencode(state, m) {
3371
+ state.end++ // max flag is 2 so always one byte
3372
+
3373
+ if (version >= 16 && m.reason) c.string.preencode(state, m.reason)
3374
+ },
3375
+ encode(state, m) {
3376
+ const flags = ((version >= 16 && m.loaded) ? 1 : 0) | ((version >= 16 && m.reason) ? 2 : 0)
3377
+
3378
+ c.uint.encode(state, flags)
3379
+
3380
+ if (version >= 16 && m.reason) c.string.encode(state, m.reason)
3381
+ },
3382
+ decode(state) {
3383
+ const flags = c.uint.decode(state)
3384
+
3385
+ return {
3386
+ loaded: (version >= 16 && (flags & 1) !== 0),
3387
+ reason: (version >= 16 && (flags & 2) !== 0) ? c.string.decode(state) : null
3388
+ }
3389
+ }
3390
+ }
3391
+
3392
+ // @harness/unload-model-request
3393
+ const encoding90 = {
3394
+ preencode(state, m) {
3395
+ c.string.preencode(state, m.model)
3396
+ },
3397
+ encode(state, m) {
3398
+ c.string.encode(state, m.model)
3399
+ },
3400
+ decode(state) {
3401
+ const r0 = c.string.decode(state)
3402
+
3403
+ return {
3404
+ model: r0
3405
+ }
3406
+ }
3407
+ }
3408
+
3409
+ // @harness/unload-model-response
3410
+ const encoding91 = {
3411
+ preencode(state, m) {
3412
+ state.end++ // max flag is 1 so always one byte
3413
+ },
3414
+ encode(state, m) {
3415
+ const flags = (version >= 16 && m.unloaded) ? 1 : 0
3416
+
3417
+ c.uint.encode(state, flags)
3418
+ },
3419
+ decode(state) {
3420
+ const flags = c.uint.decode(state)
3421
+
3422
+ return {
3423
+ unloaded: (version >= 16 && (flags & 1) !== 0)
3424
+ }
3425
+ }
3426
+ }
3427
+
3368
3428
  // @harness/completion-frame.grantedDrives, deferred due to recusive use
3369
3429
  const encoding11_23 = c.array(c.frame(encoding60))
3370
3430
  // @harness/skill.setupV2, deferred due to recusive use
@@ -3605,6 +3665,12 @@ function getEncoding(name) {
3605
3665
  return encoding87
3606
3666
  case '@harness/set-model-idle-timeout-request':
3607
3667
  return encoding88
3668
+ case '@harness/load-model-response':
3669
+ return encoding89
3670
+ case '@harness/unload-model-request':
3671
+ return encoding90
3672
+ case '@harness/unload-model-response':
3673
+ return encoding91
3608
3674
  default:
3609
3675
  throw new Error('Encoder not found ' + name)
3610
3676
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": 15,
2
+ "version": 16,
3
3
  "schema": [
4
4
  {
5
5
  "name": "empty",
@@ -2717,6 +2717,53 @@
2717
2717
  "version": 15
2718
2718
  }
2719
2719
  ]
2720
+ },
2721
+ {
2722
+ "name": "load-model-response",
2723
+ "namespace": "harness",
2724
+ "compact": false,
2725
+ "flagsPosition": 0,
2726
+ "fields": [
2727
+ {
2728
+ "name": "loaded",
2729
+ "required": false,
2730
+ "type": "bool",
2731
+ "version": 16
2732
+ },
2733
+ {
2734
+ "name": "reason",
2735
+ "type": "string",
2736
+ "version": 16
2737
+ }
2738
+ ]
2739
+ },
2740
+ {
2741
+ "name": "unload-model-request",
2742
+ "namespace": "harness",
2743
+ "compact": false,
2744
+ "flagsPosition": -1,
2745
+ "fields": [
2746
+ {
2747
+ "name": "model",
2748
+ "required": true,
2749
+ "type": "string",
2750
+ "version": 16
2751
+ }
2752
+ ]
2753
+ },
2754
+ {
2755
+ "name": "unload-model-response",
2756
+ "namespace": "harness",
2757
+ "compact": false,
2758
+ "flagsPosition": 0,
2759
+ "fields": [
2760
+ {
2761
+ "name": "unloaded",
2762
+ "required": false,
2763
+ "type": "bool",
2764
+ "version": 16
2765
+ }
2766
+ ]
2720
2767
  }
2721
2768
  ]
2722
2769
  }
@@ -1,5 +1,5 @@
1
1
  // This file is autogenerated by hyperschema-ts
2
- // Schema version: 15
2
+ // Schema version: 16
3
3
  // Do not edit manually.
4
4
 
5
5
  export interface HarnessEmpty {
@@ -568,6 +568,19 @@ export interface HarnessSetModelIdleTimeoutRequest {
568
568
  ms: number
569
569
  }
570
570
 
571
+ export interface HarnessLoadModelResponse {
572
+ loaded?: boolean
573
+ reason?: string | null
574
+ }
575
+
576
+ export interface HarnessUnloadModelRequest {
577
+ model: string
578
+ }
579
+
580
+ export interface HarnessUnloadModelResponse {
581
+ unloaded?: boolean
582
+ }
583
+
571
584
  export interface SchemaTypes {
572
585
  "@harness/empty": HarnessEmpty
573
586
  "@harness/ok-response": HarnessOkResponse
@@ -658,4 +671,7 @@ export interface SchemaTypes {
658
671
  "@harness/model-source-file": HarnessModelSourceFile
659
672
  "@harness/preview-model-source-response": HarnessPreviewModelSourceResponse
660
673
  "@harness/set-model-idle-timeout-request": HarnessSetModelIdleTimeoutRequest
674
+ "@harness/load-model-response": HarnessLoadModelResponse
675
+ "@harness/unload-model-request": HarnessUnloadModelRequest
676
+ "@harness/unload-model-response": HarnessUnloadModelResponse
661
677
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qvac/harness",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
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": {
@@ -606,6 +606,7 @@
606
606
  "build:bundle": "node scripts/build-bundle.mjs",
607
607
  "skill-eval": "bare examples/skill-eval/run.ts",
608
608
  "translate-eval": "bare examples/translate-eval/run.ts",
609
+ "model-residency": "bare examples/model-residency/run.ts",
609
610
  "prepack": "node scripts/vendor-python-wheels.mjs && node scripts/build-lib.mjs && node scripts/build-bundle.mjs --minify",
610
611
  "vendor:wheels": "node scripts/vendor-python-wheels.mjs",
611
612
  "build:lib": "node scripts/build-lib.mjs",