@antseed/cli 0.1.189 → 0.1.191

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 (42) hide show
  1. package/dist/cli/commands/seller/start.d.ts.map +1 -1
  2. package/dist/cli/commands/seller/start.js +2 -1
  3. package/dist/cli/commands/seller/start.js.map +1 -1
  4. package/dist/config/service-metadata.test.js +1 -1
  5. package/dist/config/service-metadata.test.js.map +1 -1
  6. package/dist/gateway/routing-through-gateway.test.d.ts +2 -0
  7. package/dist/gateway/routing-through-gateway.test.d.ts.map +1 -0
  8. package/dist/gateway/routing-through-gateway.test.js +177 -0
  9. package/dist/gateway/routing-through-gateway.test.js.map +1 -0
  10. package/dist/plugins/registry.d.ts.map +1 -1
  11. package/dist/plugins/registry.js +9 -3
  12. package/dist/plugins/registry.js.map +1 -1
  13. package/dist/proxy/buyer-proxy.d.ts +8 -2
  14. package/dist/proxy/buyer-proxy.d.ts.map +1 -1
  15. package/dist/proxy/buyer-proxy.js +37 -8
  16. package/dist/proxy/buyer-proxy.js.map +1 -1
  17. package/dist/proxy/buyer-proxy.test.js +51 -41
  18. package/dist/proxy/buyer-proxy.test.js.map +1 -1
  19. package/dist/proxy/conversation-store.test.js +2 -2
  20. package/dist/proxy/conversation-store.test.js.map +1 -1
  21. package/dist/proxy/gateway-policy.test.js +3 -3
  22. package/dist/proxy/gateway-policy.test.js.map +1 -1
  23. package/dist/proxy/network-models.d.ts +6 -0
  24. package/dist/proxy/network-models.d.ts.map +1 -1
  25. package/dist/proxy/network-models.js.map +1 -1
  26. package/dist/proxy/request-utils.d.ts +10 -10
  27. package/dist/proxy/request-utils.d.ts.map +1 -1
  28. package/dist/proxy/request-utils.js +8 -30
  29. package/dist/proxy/request-utils.js.map +1 -1
  30. package/dist/proxy/router-execution.d.ts +3 -3
  31. package/dist/proxy/router-execution.d.ts.map +1 -1
  32. package/dist/proxy/router-execution.js +9 -7
  33. package/dist/proxy/router-execution.js.map +1 -1
  34. package/dist/proxy/router-execution.test.js +6 -6
  35. package/dist/proxy/router-execution.test.js.map +1 -1
  36. package/dist/proxy/routing-services.d.ts +17 -6
  37. package/dist/proxy/routing-services.d.ts.map +1 -1
  38. package/dist/proxy/routing-services.js +31 -23
  39. package/dist/proxy/routing-services.js.map +1 -1
  40. package/dist/proxy/routing-services.test.js +4 -4
  41. package/dist/proxy/routing-services.test.js.map +1 -1
  42. package/package.json +9 -9
@@ -21,15 +21,15 @@ function makePeer(seed, providers) {
21
21
  providers,
22
22
  };
23
23
  }
24
- test('the buyer switches between a model and a model-routing service without replacing the plugin', async () => {
24
+ test('the buyer switches between a model and a routing service without replacing the plugin', async () => {
25
25
  const inferencePeer = makeRankedRoutingFixture().peers[0];
26
26
  const routingPeer = makePeer('d', ['alpha']);
27
27
  routingPeer.metadata = {
28
28
  peerId: routingPeer.peerId, version: 12, timestamp: Date.now(), signature: '', region: 'test',
29
29
  providers: [{ provider: 'alpha', services: ['alpha-route'], maxConcurrency: 1, currentLoad: 0,
30
30
  defaultPricing: { inputUsdPerMillion: 0, outputUsdPerMillion: 0 },
31
- serviceApiProtocols: { 'alpha-route': ['model-routing'] },
32
- serviceUnitBillingModels: { 'alpha-route': { 'model-routing': {
31
+ serviceApiProtocols: { 'alpha-route': ['irp-suggest'] },
32
+ serviceUnitBillingModels: { 'alpha-route': { 'irp-suggest': {
33
33
  version: 1, components: [{ unit: 'completed_requests', priceUsd: 0.001 }],
34
34
  } } },
35
35
  }],
@@ -73,8 +73,18 @@ test('the buyer switches between a model and a model-routing service without rep
73
73
  assert.equal((await setModel()).statusCode, 200);
74
74
  assert.equal((await infer()).statusCode, 200);
75
75
  assert.equal(requests.length, 1);
76
- const selection = { kind: 'router', service: { peerId: routingPeer.peerId, provider: 'alpha', serviceId: 'alpha-route' }, costQualityTradeoff: 1 };
76
+ const selection = { kind: 'router', service: { peerId: routingPeer.peerId, provider: 'alpha', serviceId: 'alpha-route' }, options: { cost_quality_tradeoff: 1 } };
77
+ // Options are checked against the router's advertised protocol (irp-suggest) when it is saved.
78
+ for (const options of [{ cost_quality_tradeoff: 11 }, { cost_quality_tradeoff: 2.5 }, { tier: 'fast' }]) {
79
+ const refused = await invokeProxy(proxy, makeProxyRequest({ path: '/_antseed/route', body: routeBody({ ...selection, options }) }));
80
+ assert.equal(refused.statusCode, 400, refused.body);
81
+ }
77
82
  assert.equal((await invokeProxy(proxy, makeProxyRequest({ path: '/_antseed/route', body: routeBody(selection) }))).statusCode, 200);
83
+ // ...and per request, before any ranking is bought.
84
+ const badRequest = await invokeProxy(proxy, makeProxyRequest({ body: { model: 'antseed', messages: [{ role: 'user', content: 'Hello' }], routing: { cost_quality_tradeoff: 11 } } }));
85
+ assert.equal(badRequest.statusCode, 400, badRequest.body);
86
+ assert.equal(JSON.parse(badRequest.body).error.code, 'invalid_routing');
87
+ assert.equal(requests.length, 1);
78
88
  const routed = await infer();
79
89
  assert.equal(routed.statusCode, 200, routed.body);
80
90
  assert.deepEqual(requests.map(request => request.path.split('?')[0]), ['/v1/chat/completions', '/v1/routing/models', '/v1/routing/rank', '/v1/chat/completions']);
@@ -138,7 +148,7 @@ test('the buyer and chat router selections pass their cost/quality tradeoff to t
138
148
  routingPeer.metadata = { peerId: routingPeer.peerId, version: 12, region: 'test', timestamp: Date.now(), signature: '',
139
149
  providers: [{ provider: 'alternative', services: ['route'], maxConcurrency: 1, currentLoad: 0,
140
150
  defaultPricing: { inputUsdPerMillion: 0, outputUsdPerMillion: 0 },
141
- serviceApiProtocols: { route: ['model-routing'] },
151
+ serviceApiProtocols: { route: ['irp-suggest'] },
142
152
  }] };
143
153
  const contexts = [];
144
154
  const client = {
@@ -166,31 +176,31 @@ test('the buyer and chat router selections pass their cost/quality tradeoff to t
166
176
  };
167
177
  const target = { peerId: routingPeer.peerId, provider: 'alternative', serviceId: 'route' };
168
178
  const select = (costQualityTradeoff) => invokeProxy(proxy, makeProxyRequest({ path: '/_antseed/route',
169
- body: routeBody({ kind: 'router', service: target, ...(costQualityTradeoff !== undefined ? { costQualityTradeoff } : {}) }) }));
179
+ body: routeBody({ kind: 'router', service: target, ...(costQualityTradeoff !== undefined ? { options: { cost_quality_tradeoff: costQualityTradeoff } } : {}) }) }));
170
180
  const chosen = await select(0);
171
181
  assert.equal(chosen.statusCode, 200, chosen.body);
172
182
  const response = await invokeProxy(proxy, makeProxyRequest({ body: { model: 'antseed', messages: [{ role: 'user', content: 'Hello' }] } }));
173
183
  assert.equal(response.statusCode, 200, response.body);
174
184
  assert.equal(contexts.length, 1);
175
185
  assert.equal(inferenceCalls, 1);
176
- assert.equal(contexts[0].costQualityTradeoff, 0);
186
+ assert.equal(contexts[0].options?.cost_quality_tradeoff, 0);
177
187
  assert.deepEqual(contexts[0].routingService, target);
178
188
  assert.equal((await invokeProxy(proxy, makeProxyRequest({ path: '/_antseed/route', body: routeBody({ kind: 'router', service: target }) }))).statusCode, 200);
179
189
  store.touch({ tool: 'vpr', sessionKey: 'client-chat' });
180
190
  const selectChat = (costQualityTradeoff) => invokeProxy(proxy, makeProxyRequest({
181
- path: '/_antseed/conversations/update', body: { id: 'vpr:client-chat', routingSelection: { kind: 'router', service: target, costQualityTradeoff } },
191
+ path: '/_antseed/conversations/update', body: { id: 'vpr:client-chat', routingSelection: { kind: 'router', service: target, options: { cost_quality_tradeoff: costQualityTradeoff } } },
182
192
  }));
183
193
  assert.equal((await selectChat(10)).statusCode, 200);
184
194
  const chatResponse = await invokeProxy(proxy, makeProxyRequest({ headers: { 'x-vpr-session-id': 'client-chat' },
185
195
  body: { model: 'antseed', messages: [{ role: 'user', content: 'Hello' }] },
186
196
  }));
187
197
  assert.equal(chatResponse.statusCode, 200, chatResponse.body);
188
- assert.equal(contexts[1].costQualityTradeoff, 10);
198
+ assert.equal(contexts[1].options?.cost_quality_tradeoff, 10);
189
199
  assert.deepEqual(contexts[1].routingService, target);
190
200
  assert.equal((await select()).statusCode, 200);
191
201
  const defaultResponse = await invokeProxy(proxy, makeProxyRequest({ body: { model: 'antseed', messages: [{ role: 'user', content: 'Hello' }] } }));
192
202
  assert.equal(defaultResponse.statusCode, 200, defaultResponse.body);
193
- assert.equal(contexts[2].costQualityTradeoff, undefined);
203
+ assert.equal(contexts[2].options?.cost_quality_tradeoff, undefined);
194
204
  assert.equal(contexts.length, 3);
195
205
  assert.equal(inferenceCalls, 3);
196
206
  });
@@ -279,7 +289,7 @@ function setRouter(proxy, selection) {
279
289
  proxy._defaultRoutedModel = null;
280
290
  proxy._defaultRouter = selection;
281
291
  }
282
- /** `POST /_antseed/route` body: `{ model }` for a model, `{ router: { service, costQualityTradeoff } }` for a router. */
292
+ /** `POST /_antseed/route` body: `{ model }` for a model, `{ router: { service, options } }` for a router. */
283
293
  function routeBody(selection) {
284
294
  if (selection.kind === 'model')
285
295
  return { model: selection.model ?? '' };
@@ -287,7 +297,7 @@ function routeBody(selection) {
287
297
  return { router };
288
298
  }
289
299
  function chatRouterSelection(peer, costQualityTradeoff) {
290
- return { kind: 'router', service: { peerId: peer.repeat(40), provider: 'alpha', serviceId: 'alpha-route' }, costQualityTradeoff };
300
+ return { kind: 'router', service: { peerId: peer.repeat(40), provider: 'alpha', serviceId: 'alpha-route' }, options: { cost_quality_tradeoff: costQualityTradeoff } };
291
301
  }
292
302
  async function makeConversationRoutingFixture(context) {
293
303
  const fixture = makeRankedRoutingFixture([]);
@@ -320,18 +330,18 @@ test('chats keep independent routing-service targets and tradeoffs while unconfi
320
330
  assert.equal((await update('chat-b', second)).statusCode, 200);
321
331
  for (const session of ['chat-a', 'chat-b', 'chat-c'])
322
332
  assert.equal((await request(session)).statusCode, 200);
323
- assert.deepEqual(captured.map(entry => [entry.routingService, entry.costQualityTradeoff]), [first, second, chatRouterSelection('c', 5)].map(selection => [selection.service, selection.costQualityTradeoff]));
333
+ assert.deepEqual(captured.map(entry => [entry.routingService, entry.options?.cost_quality_tradeoff]), [first, second, chatRouterSelection('c', 5)].map(selection => [selection.service, selection.options?.cost_quality_tradeoff]));
324
334
  setRouter(proxy, chatRouterSelection('f', 3));
325
335
  for (const session of ['chat-a', 'chat-b', 'chat-c'])
326
336
  assert.equal((await request(session)).statusCode, 200);
327
- assert.deepEqual(captured.slice(3).map(entry => [entry.routingService, entry.costQualityTradeoff]), [first, second, chatRouterSelection('f', 3)].map(selection => [selection.service, selection.costQualityTradeoff]));
337
+ assert.deepEqual(captured.slice(3).map(entry => [entry.routingService, entry.options?.cost_quality_tradeoff]), [first, second, chatRouterSelection('f', 3)].map(selection => [selection.service, selection.options?.cost_quality_tradeoff]));
328
338
  assert.equal(store.get('vpr:chat-c')?.routingSelection, null);
329
339
  const get = await invokeProxy(proxy, makeProxyRequest({ path: '/_antseed/conversations/vpr%3Achat-a', method: 'GET' }));
330
340
  assert.deepEqual(JSON.parse(get.body).conversation.routingSelection, first);
331
341
  assert.equal((await update('chat-a', null)).statusCode, 200);
332
342
  assert.equal((await request('chat-a')).statusCode, 200);
333
343
  assert.deepEqual(captured.at(-1).routingService, chatRouterSelection('f', 3).service);
334
- assert.equal(captured.at(-1).costQualityTradeoff, 3);
344
+ assert.equal(captured.at(-1).options?.cost_quality_tradeoff, 3);
335
345
  });
336
346
  test('chat routing overrides beat the buyer model default, inherit into children, and yield to explicit model pins', async (context) => {
337
347
  const { proxy, peers, calls, captured, update, request, store } = await makeConversationRoutingFixture(context);
@@ -362,7 +372,7 @@ test('chat routing updates reject malformed selections without partially changin
362
372
  assert.equal((await update('chat-a', selection)).statusCode, 200);
363
373
  for (const invalid of [[], { kind: 'model', model: 'model-a' }, { kind: 'router' },
364
374
  { ...selection, service: { ...selection.service, peerId: 'invalid' } },
365
- { ...selection, costQualityTradeoff: 11 }, { ...selection, costQualityTradeoff: 2.5 }, { ...selection, preferences: { tradeoff: '9' } }]) {
375
+ { ...selection, options: { cost_quality_tradeoff: {} } }, { ...selection, options: [] }, { ...selection, costQualityTradeoff: 5 }, { ...selection, preferences: { tradeoff: '9' } }]) {
366
376
  assert.equal((await update('chat-a', invalid)).statusCode, 400);
367
377
  assert.deepEqual(store.get('vpr:chat-a')?.routingSelection, selection);
368
378
  }
@@ -382,7 +392,7 @@ test('persisted chat overrides route after reload and fail closed when the route
382
392
  await store.flush();
383
393
  proxy._conversations = new ConversationStore(directory);
384
394
  assert.equal((await request('chat-a')).statusCode, 200);
385
- assert.equal(captured[0].costQualityTradeoff, selection.costQualityTradeoff);
395
+ assert.equal(captured[0].options?.cost_quality_tradeoff, selection.options?.cost_quality_tradeoff);
386
396
  client.listModels = listModelsWith(['model-z']);
387
397
  proxy._routingModels.invalidate(selection.service);
388
398
  assert.equal((await request('chat-a')).statusCode, 422);
@@ -421,15 +431,15 @@ test('chat and buyer selection changes leave in-flight requests using their orig
421
431
  for (const response of await Promise.all([first, second, inherited]))
422
432
  assert.equal(response.statusCode, 200);
423
433
  });
424
- /** A peer advertising one `model-routing` service, `alpha-route`. */
434
+ /** A peer advertising one `irp-suggest` routing service, `alpha-route`. */
425
435
  function makeRoutingPeer(seed) {
426
436
  const peer = makePeer(seed, ['alpha']);
427
437
  peer.metadata = {
428
438
  peerId: peer.peerId, version: 12, timestamp: Date.now(), signature: '', region: 'test',
429
439
  providers: [{ provider: 'alpha', services: ['alpha-route'], maxConcurrency: 1, currentLoad: 0,
430
440
  defaultPricing: { inputUsdPerMillion: 0, outputUsdPerMillion: 0 },
431
- serviceApiProtocols: { 'alpha-route': ['model-routing'] },
432
- serviceUnitBillingModels: { 'alpha-route': { 'model-routing': {
441
+ serviceApiProtocols: { 'alpha-route': ['irp-suggest'] },
442
+ serviceUnitBillingModels: { 'alpha-route': { 'irp-suggest': {
433
443
  version: 1, components: [{ unit: 'completed_requests', priceUsd: 0.001 }],
434
444
  } } },
435
445
  }],
@@ -457,7 +467,7 @@ test('a routing service pinned as the model ranks and serves the request without
457
467
  assert.equal(response.statusCode, 200, response.body);
458
468
  assert.equal(calls.routing, 1);
459
469
  assert.deepEqual(captured[0].routingService, target);
460
- assert.equal(captured[0].costQualityTradeoff, undefined);
470
+ assert.equal(captured[0].options?.cost_quality_tradeoff, undefined);
461
471
  assert.equal(calls.requests.length, 1);
462
472
  assert.equal(calls.requests[0].peer.peerId, peers[0].peerId);
463
473
  assert.equal(JSON.parse(Buffer.from(calls.requests[0].request.body).toString()).model, 'model-a');
@@ -468,7 +478,7 @@ test('the body routing object sets the tradeoff for a pinned router and never re
468
478
  model, messages: [{ role: 'user', content: 'Hello' }], routing: { cost_quality_tradeoff: 7 },
469
479
  } }));
470
480
  assert.equal(response.statusCode, 200, response.body);
471
- assert.equal(captured[0].costQualityTradeoff, 7);
481
+ assert.equal(captured[0].options?.cost_quality_tradeoff, 7);
472
482
  const sent = JSON.parse(Buffer.from(calls.requests[0].request.body).toString());
473
483
  assert.equal('routing' in sent, false);
474
484
  const direct = await invokeProxy(proxy, makeProxyRequest({ body: {
@@ -482,28 +492,28 @@ test('the body routing object sets the tradeoff for a pinned router and never re
482
492
  });
483
493
  test('the body routing tradeoff overrides the buyer default router tradeoff', async () => {
484
494
  const { proxy, captured } = makePinnedRouterFixture();
485
- setRouter(proxy, { kind: 'router', service: { peerId: 'd'.repeat(40), provider: 'alpha', serviceId: 'alpha-route' }, costQualityTradeoff: 1 });
495
+ setRouter(proxy, { kind: 'router', service: { peerId: 'd'.repeat(40), provider: 'alpha', serviceId: 'alpha-route' }, options: { cost_quality_tradeoff: 1 } });
486
496
  const response = await invokeProxy(proxy, makeProxyRequest({ body: {
487
497
  model: 'antseed', messages: [{ role: 'user', content: 'Hello' }], routing: { cost_quality_tradeoff: 9 },
488
498
  } }));
489
499
  assert.equal(response.statusCode, 200, response.body);
490
- assert.equal(captured[0].costQualityTradeoff, 9);
500
+ assert.equal(captured[0].options?.cost_quality_tradeoff, 9);
491
501
  });
492
502
  test('a pinned router without a routing object uses the saved settings for that router only', async () => {
493
503
  const { proxy, peers, captured, target, model } = makePinnedRouterFixture();
494
- setRouter(proxy, { kind: 'router', service: target, costQualityTradeoff: 3, allowedModels: [{ provider: 'openai', serviceId: 'model-b' }] });
504
+ setRouter(proxy, { kind: 'router', service: target, options: { cost_quality_tradeoff: 3 }, allowedModels: [{ provider: 'openai', serviceId: 'model-b' }] });
495
505
  const saved = await invokeProxy(proxy, makeProxyRequest({ body: { model, messages: [{ role: 'user', content: 'Hello' }] } }));
496
506
  assert.equal(saved.statusCode, 200, saved.body);
497
- assert.equal(captured[0].costQualityTradeoff, 3);
507
+ assert.equal(captured[0].options?.cost_quality_tradeoff, 3);
498
508
  assert.deepEqual([...new Set(captured[0].candidates.map((candidate) => candidate.serviceId))], ['model-b']);
499
509
  const overridden = await invokeProxy(proxy, makeProxyRequest({ body: { model, messages: [{ role: 'user', content: 'Hello' }], routing: { cost_quality_tradeoff: 9 } } }));
500
510
  assert.equal(overridden.statusCode, 200, overridden.body);
501
- assert.equal(captured[1].costQualityTradeoff, 9);
511
+ assert.equal(captured[1].options?.cost_quality_tradeoff, 9);
502
512
  assert.deepEqual([...new Set(captured[1].candidates.map((candidate) => candidate.serviceId))], ['model-b']);
503
- setRouter(proxy, { kind: 'router', service: { ...target, peerId: 'e'.repeat(40) }, costQualityTradeoff: 3, allowedModels: [{ provider: 'openai', serviceId: 'model-b' }] });
513
+ setRouter(proxy, { kind: 'router', service: { ...target, peerId: 'e'.repeat(40) }, options: { cost_quality_tradeoff: 3 }, allowedModels: [{ provider: 'openai', serviceId: 'model-b' }] });
504
514
  const other = await invokeProxy(proxy, makeProxyRequest({ body: { model, messages: [{ role: 'user', content: 'Hello' }] } }));
505
515
  assert.equal(other.statusCode, 200, other.body);
506
- assert.equal(captured[2].costQualityTradeoff, undefined);
516
+ assert.equal(captured[2].options?.cost_quality_tradeoff, undefined);
507
517
  assert.ok(captured[2].candidates.some((candidate) => candidate.serviceId === 'model-a'));
508
518
  assert.ok(peers.length > 0);
509
519
  });
@@ -514,7 +524,7 @@ test('a router pinned as the default route serves the antseed alias through that
514
524
  assert.equal(response.statusCode, 200, response.body);
515
525
  assert.equal(calls.routing, 1);
516
526
  assert.deepEqual(captured[0].routingService, target);
517
- assert.equal(captured[0].costQualityTradeoff, 6);
527
+ assert.equal(captured[0].options?.cost_quality_tradeoff, 6);
518
528
  assert.equal(calls.requests[0].peer.peerId, peers[0].peerId);
519
529
  assert.equal(JSON.parse(Buffer.from(calls.requests[0].request.body).toString()).model, 'model-a');
520
530
  });
@@ -569,7 +579,7 @@ test('a chat\'s own router wins over a router pinned as the default route', asyn
569
579
  assert.equal(chatTurn.statusCode, 200, chatTurn.body);
570
580
  const plain = await turn();
571
581
  assert.equal(plain.statusCode, 200, plain.body);
572
- assert.deepEqual(captured.map((entry) => [entry.routingService.peerId, entry.costQualityTradeoff]), [[chatRouter.peerId, 9], [routingPeer.peerId, undefined]]);
582
+ assert.deepEqual(captured.map((entry) => [entry.routingService.peerId, entry.options?.cost_quality_tradeoff]), [[chatRouter.peerId, 9], [routingPeer.peerId, undefined]]);
573
583
  assert.equal(calls.routing, 2);
574
584
  });
575
585
  test('an automatic chat route never turns a seller into a router pin', async (context) => {
@@ -675,28 +685,28 @@ test('a pinned service that is not the peer\'s routing service is a normal selle
675
685
  assert.equal(calls.routing, 0);
676
686
  assert.equal(calls.requests[0].peer.peerId, peers[1].peerId);
677
687
  });
678
- test('routing selection carries the tradeoff, rejects invalid values and preserves model mode', async () => {
688
+ test('routing selection carries router options, rejects malformed ones and preserves model mode', async () => {
679
689
  const { proxy, calls } = makeRankedRoutingFixture([200, 200, 200, 200]);
680
690
  const client = proxy._modelRoutingClient;
681
691
  const captured = [];
682
692
  const select = client.selectRoute;
683
693
  client.selectRoute = (request, peers, context) => {
684
- captured.push({ tradeoff: context.costQualityTradeoff, target: context.routingService });
694
+ captured.push({ tradeoff: context.options?.cost_quality_tradeoff, target: context.routingService });
685
695
  return select(request, peers, context);
686
696
  };
687
697
  proxy._mergeStateFile = async () => { };
688
698
  setDefaultModel(proxy, 'stale-model');
689
699
  const service = { peerId: 'd'.repeat(40), provider: 'alpha', serviceId: 'alpha-route' };
690
- const selected = await invokeProxy(proxy, makeProxyRequest({ path: '/_antseed/route', body: routeBody({ kind: 'router', service, costQualityTradeoff: 9 }) }));
700
+ const selected = await invokeProxy(proxy, makeProxyRequest({ path: '/_antseed/route', body: routeBody({ kind: 'router', service, options: { cost_quality_tradeoff: 9 } }) }));
691
701
  assert.equal(selected.statusCode, 200, selected.body);
692
702
  const first = await invokeProxy(proxy, makeProxyRequest({ body: { model: 'antseed', messages: [{ role: 'user', content: 'Hello' }] } }));
693
703
  assert.equal(first.statusCode, 200, first.body);
694
704
  assert.deepEqual(captured[0], { tradeoff: 9, target: service });
695
- const updated = await invokeProxy(proxy, makeProxyRequest({ path: '/_antseed/route', body: routeBody({ kind: 'router', service, costQualityTradeoff: 1 }) }));
705
+ const updated = await invokeProxy(proxy, makeProxyRequest({ path: '/_antseed/route', body: routeBody({ kind: 'router', service, options: { cost_quality_tradeoff: 1 } }) }));
696
706
  assert.equal(updated.statusCode, 200, updated.body);
697
707
  await invokeProxy(proxy, makeProxyRequest({ body: { model: 'antseed', messages: [{ role: 'user', content: 'Hello' }] } }));
698
708
  assert.equal(captured[1].tradeoff, 1);
699
- for (const selection of [{ kind: 'router', service, costQualityTradeoff: -1 }, { kind: 'router', service, costQualityTradeoff: '5' }, { kind: 'router', service, preferences: { tradeoff: '9' } }]) {
709
+ for (const selection of [{ kind: 'router', service, options: { cost_quality_tradeoff: null } }, { kind: 'router', service, options: 'cheap' }, { kind: 'router', service, preferences: { tradeoff: '9' } }]) {
700
710
  const invalid = await invokeProxy(proxy, makeProxyRequest({ path: '/_antseed/route', body: routeBody(selection) }));
701
711
  assert.equal(invalid.statusCode, 400, invalid.body);
702
712
  }
@@ -772,7 +782,7 @@ test('explicit routing-service target and tradeoff survive the local state-file
772
782
  const client = proxy._modelRoutingClient;
773
783
  const stateFile = join(directory, 'buyer.state.json');
774
784
  proxy._stateFile = stateFile;
775
- const selection = { kind: 'router', service: { peerId: 'c'.repeat(40), provider: 'alpha', serviceId: 'alpha-route' }, costQualityTradeoff: 9 };
785
+ const selection = { kind: 'router', service: { peerId: 'c'.repeat(40), provider: 'alpha', serviceId: 'alpha-route' }, options: { cost_quality_tradeoff: 9 } };
776
786
  const response = await invokeProxy(proxy, makeProxyRequest({ path: '/_antseed/route', body: routeBody(selection) }));
777
787
  assert.equal(response.statusCode, 200, response.body);
778
788
  assert.deepEqual(JSON.parse(await readFile(stateFile, 'utf8')).defaultRouter, routeBody(selection).router);
@@ -809,7 +819,7 @@ test('config reload updates eligibility policy without replacing the active rout
809
819
  proxy._configPath = path;
810
820
  proxy._mergeStateFile = async () => { assert.fail('Config reload must not persist selection'); };
811
821
  const service = { peerId: 'c'.repeat(40), provider: 'alpha', serviceId: 'alpha-route' };
812
- const activeSelection = { kind: 'router', service, costQualityTradeoff: 5 };
822
+ const activeSelection = { kind: 'router', service, options: { cost_quality_tradeoff: 5 } };
813
823
  setRouter(proxy, activeSelection);
814
824
  for (const maxInputUsdPerMillion of [15, 25]) {
815
825
  const routingPreferences = { ...priceAndTrustPreferences, maxInputUsdPerMillion };
@@ -905,7 +915,7 @@ test('changing model selection affects the next request without cancelling the c
905
915
  assert.equal(next.statusCode, 200);
906
916
  assert.equal(JSON.parse(Buffer.from(calls.requests[1].request.body).toString()).model, 'model-b');
907
917
  });
908
- test('client disconnect still cancels a pending model-routing decision', { timeout: 5_000 }, async () => {
918
+ test('client disconnect still cancels a pending routing decision', { timeout: 5_000 }, async () => {
909
919
  const { proxy, calls } = makeRankedRoutingFixture([200]);
910
920
  const client = proxy._modelRoutingClient;
911
921
  let started;
@@ -1301,7 +1311,7 @@ test('ordinary requests keep attributing spend after the conversation already ex
1301
1311
  assert.equal(conversation.requestCount, 2);
1302
1312
  assert.equal(conversation.inputTokens, '8');
1303
1313
  });
1304
- test('model and model-routing requests use the same duplicate tracking guard', () => {
1314
+ test('model and routing requests use the same duplicate tracking guard', () => {
1305
1315
  const proxy = makeBuyerProxyWithPeers([]);
1306
1316
  for (const purpose of [undefined, 'routing']) {
1307
1317
  const requestId = randomUUID();
@@ -4136,7 +4146,7 @@ test('route control endpoint sets, persists, and returns the default routed mode
4136
4146
  assert.equal(automaticPersisted['defaultRoutedModel'], 'gpt-4o');
4137
4147
  const invalid = await invokeProxy(proxy, makeProxyRequest({ path: '/_antseed/route', body: { model: 'not-a-peer@gpt-4o' } }));
4138
4148
  assert.equal(invalid.statusCode, 400);
4139
- const router = { service: { peerId: validPeerId, provider: 'alpha', serviceId: 'alpha-route' }, costQualityTradeoff: 5 };
4149
+ const router = { service: { peerId: validPeerId, provider: 'alpha', serviceId: 'alpha-route' }, options: { cost_quality_tradeoff: 5 } };
4140
4150
  const routed = await invokeProxy(proxy, makeProxyRequest({ path: '/_antseed/route', body: { router } }));
4141
4151
  assert.deepEqual(JSON.parse(routed.body), { ok: true, model: null, router });
4142
4152
  const routedPersisted = JSON.parse(await readFile(join(dir, 'buyer.state.json'), 'utf-8'));