@hasna/switcher 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/cli/index.js +2634 -615
- package/dist/cli.d.ts +2 -0
- package/dist/codex-model-policy.d.ts +65 -0
- package/dist/direct-launch.d.ts +2 -2
- package/dist/domain.d.ts +259 -2
- package/dist/gemini-model-policy.d.ts +56 -0
- package/dist/generated/api.d.ts +192 -0
- package/dist/harness-types.d.ts +9 -0
- package/dist/hermes-model-policy.d.ts +30 -0
- package/dist/index.js +93 -42
- package/dist/inference-gateway.d.ts +24 -0
- package/dist/launcher.d.ts +8 -3
- package/dist/mcp/index.js +107 -55
- package/dist/model-policy-schema.d.ts +137 -0
- package/dist/model-policy.d.ts +31 -0
- package/dist/native-model-policy.d.ts +23 -0
- package/dist/opencode-model-policy.d.ts +33 -0
- package/dist/ori-model-policy.d.ts +8 -0
- package/dist/sdk.d.ts +238 -5
- package/dist/sdk.js +93 -42
- package/dist/serve/index.js +1044 -88
- package/docs/MODEL-POLICY.md +82 -0
- package/openapi.json +836 -1
- package/package.json +3 -2
package/dist/generated/api.d.ts
CHANGED
|
@@ -345,6 +345,30 @@ export interface components {
|
|
|
345
345
|
/** @enum {string} */
|
|
346
346
|
harness: "claude" | "codex" | "grok" | "opencode" | "opencode2" | "pi" | "omp" | "dsh" | "cline" | "hermes" | "prime-agent" | "gemini" | "aider" | "kilo";
|
|
347
347
|
model: string;
|
|
348
|
+
modelPolicy?: {
|
|
349
|
+
/**
|
|
350
|
+
* @default 1
|
|
351
|
+
* @enum {number}
|
|
352
|
+
*/
|
|
353
|
+
version: 1;
|
|
354
|
+
roles?: {
|
|
355
|
+
subagent?: string;
|
|
356
|
+
fast?: string;
|
|
357
|
+
planning?: string;
|
|
358
|
+
review?: string;
|
|
359
|
+
summary?: string;
|
|
360
|
+
compaction?: string;
|
|
361
|
+
weak?: string;
|
|
362
|
+
editor?: string;
|
|
363
|
+
};
|
|
364
|
+
allowedModels?: string[];
|
|
365
|
+
aliases?: {
|
|
366
|
+
[key: string]: string;
|
|
367
|
+
};
|
|
368
|
+
fallbacks?: {
|
|
369
|
+
[key: string]: string[];
|
|
370
|
+
};
|
|
371
|
+
};
|
|
348
372
|
};
|
|
349
373
|
Profile: {
|
|
350
374
|
id: string;
|
|
@@ -353,6 +377,30 @@ export interface components {
|
|
|
353
377
|
/** @enum {string} */
|
|
354
378
|
harness: "claude" | "codex" | "grok" | "opencode" | "opencode2" | "pi" | "omp" | "dsh" | "cline" | "hermes" | "prime-agent" | "gemini" | "aider" | "kilo";
|
|
355
379
|
model: string;
|
|
380
|
+
modelPolicy?: {
|
|
381
|
+
/**
|
|
382
|
+
* @default 1
|
|
383
|
+
* @enum {number}
|
|
384
|
+
*/
|
|
385
|
+
version: 1;
|
|
386
|
+
roles?: {
|
|
387
|
+
subagent?: string;
|
|
388
|
+
fast?: string;
|
|
389
|
+
planning?: string;
|
|
390
|
+
review?: string;
|
|
391
|
+
summary?: string;
|
|
392
|
+
compaction?: string;
|
|
393
|
+
weak?: string;
|
|
394
|
+
editor?: string;
|
|
395
|
+
};
|
|
396
|
+
allowedModels?: string[];
|
|
397
|
+
aliases?: {
|
|
398
|
+
[key: string]: string;
|
|
399
|
+
};
|
|
400
|
+
fallbacks?: {
|
|
401
|
+
[key: string]: string[];
|
|
402
|
+
};
|
|
403
|
+
};
|
|
356
404
|
version: number;
|
|
357
405
|
updatedAt: string;
|
|
358
406
|
};
|
|
@@ -368,6 +416,44 @@ export interface components {
|
|
|
368
416
|
supportedParameters?: string[];
|
|
369
417
|
supportedGenerationMethods?: string[];
|
|
370
418
|
};
|
|
419
|
+
ModelPolicy: {
|
|
420
|
+
/**
|
|
421
|
+
* @default 1
|
|
422
|
+
* @enum {number}
|
|
423
|
+
*/
|
|
424
|
+
version: 1;
|
|
425
|
+
roles?: {
|
|
426
|
+
subagent?: string;
|
|
427
|
+
fast?: string;
|
|
428
|
+
planning?: string;
|
|
429
|
+
review?: string;
|
|
430
|
+
summary?: string;
|
|
431
|
+
compaction?: string;
|
|
432
|
+
weak?: string;
|
|
433
|
+
editor?: string;
|
|
434
|
+
};
|
|
435
|
+
allowedModels?: string[];
|
|
436
|
+
aliases?: {
|
|
437
|
+
[key: string]: string;
|
|
438
|
+
};
|
|
439
|
+
fallbacks?: {
|
|
440
|
+
[key: string]: string[];
|
|
441
|
+
};
|
|
442
|
+
};
|
|
443
|
+
RoutingEvent: {
|
|
444
|
+
/** Format: date-time */
|
|
445
|
+
at: string;
|
|
446
|
+
requestId: string;
|
|
447
|
+
requestedModel: string;
|
|
448
|
+
resolvedModel?: string;
|
|
449
|
+
reportedModel?: string;
|
|
450
|
+
/** @enum {string} */
|
|
451
|
+
decision: "allow" | "alias" | "reject" | "fallback";
|
|
452
|
+
/** @enum {string} */
|
|
453
|
+
role?: "main" | "subagent" | "fast" | "planning" | "review" | "summary" | "compaction" | "weak" | "editor";
|
|
454
|
+
reason?: string;
|
|
455
|
+
upstreamStatus?: number;
|
|
456
|
+
};
|
|
371
457
|
ModelPage: {
|
|
372
458
|
data: {
|
|
373
459
|
id: string;
|
|
@@ -451,6 +537,30 @@ export interface components {
|
|
|
451
537
|
/** @enum {string} */
|
|
452
538
|
harness: "claude" | "codex" | "grok" | "opencode" | "opencode2" | "pi" | "omp" | "dsh" | "cline" | "hermes" | "prime-agent" | "gemini" | "aider" | "kilo";
|
|
453
539
|
model: string;
|
|
540
|
+
modelPolicy?: {
|
|
541
|
+
/**
|
|
542
|
+
* @default 1
|
|
543
|
+
* @enum {number}
|
|
544
|
+
*/
|
|
545
|
+
version: 1;
|
|
546
|
+
roles?: {
|
|
547
|
+
subagent?: string;
|
|
548
|
+
fast?: string;
|
|
549
|
+
planning?: string;
|
|
550
|
+
review?: string;
|
|
551
|
+
summary?: string;
|
|
552
|
+
compaction?: string;
|
|
553
|
+
weak?: string;
|
|
554
|
+
editor?: string;
|
|
555
|
+
};
|
|
556
|
+
allowedModels?: string[];
|
|
557
|
+
aliases?: {
|
|
558
|
+
[key: string]: string;
|
|
559
|
+
};
|
|
560
|
+
fallbacks?: {
|
|
561
|
+
[key: string]: string[];
|
|
562
|
+
};
|
|
563
|
+
};
|
|
454
564
|
version: number;
|
|
455
565
|
updatedAt: string;
|
|
456
566
|
};
|
|
@@ -475,22 +585,89 @@ export interface components {
|
|
|
475
585
|
warnings: string[];
|
|
476
586
|
};
|
|
477
587
|
RunInput: {
|
|
588
|
+
/** @enum {number} */
|
|
589
|
+
modelPolicyVersion: 1;
|
|
478
590
|
profileId: string;
|
|
479
591
|
/** @enum {string} */
|
|
480
592
|
harness: "claude" | "codex" | "grok" | "opencode" | "opencode2" | "pi" | "omp" | "dsh" | "cline" | "hermes" | "prime-agent" | "gemini" | "aider" | "kilo";
|
|
481
593
|
model: string;
|
|
594
|
+
modelPolicy?: {
|
|
595
|
+
/**
|
|
596
|
+
* @default 1
|
|
597
|
+
* @enum {number}
|
|
598
|
+
*/
|
|
599
|
+
version: 1;
|
|
600
|
+
roles?: {
|
|
601
|
+
subagent?: string;
|
|
602
|
+
fast?: string;
|
|
603
|
+
planning?: string;
|
|
604
|
+
review?: string;
|
|
605
|
+
summary?: string;
|
|
606
|
+
compaction?: string;
|
|
607
|
+
weak?: string;
|
|
608
|
+
editor?: string;
|
|
609
|
+
};
|
|
610
|
+
allowedModels?: string[];
|
|
611
|
+
aliases?: {
|
|
612
|
+
[key: string]: string;
|
|
613
|
+
};
|
|
614
|
+
fallbacks?: {
|
|
615
|
+
[key: string]: string[];
|
|
616
|
+
};
|
|
617
|
+
};
|
|
482
618
|
planToken: string;
|
|
483
619
|
};
|
|
484
620
|
RunUpdate: {
|
|
485
621
|
/** @enum {string} */
|
|
486
622
|
status: "exited" | "failed" | "interrupted";
|
|
487
623
|
exitCode: number;
|
|
624
|
+
routingEvents?: {
|
|
625
|
+
/** Format: date-time */
|
|
626
|
+
at: string;
|
|
627
|
+
requestId: string;
|
|
628
|
+
requestedModel: string;
|
|
629
|
+
resolvedModel?: string;
|
|
630
|
+
reportedModel?: string;
|
|
631
|
+
/** @enum {string} */
|
|
632
|
+
decision: "allow" | "alias" | "reject" | "fallback";
|
|
633
|
+
/** @enum {string} */
|
|
634
|
+
role?: "main" | "subagent" | "fast" | "planning" | "review" | "summary" | "compaction" | "weak" | "editor";
|
|
635
|
+
reason?: string;
|
|
636
|
+
upstreamStatus?: number;
|
|
637
|
+
}[];
|
|
638
|
+
routingEventsDropped?: number;
|
|
488
639
|
};
|
|
489
640
|
Run: {
|
|
641
|
+
/** @enum {number} */
|
|
642
|
+
modelPolicyVersion?: 1;
|
|
490
643
|
profileId: string;
|
|
491
644
|
/** @enum {string} */
|
|
492
645
|
harness: "claude" | "codex" | "grok" | "opencode" | "opencode2" | "pi" | "omp" | "dsh" | "cline" | "hermes" | "prime-agent" | "gemini" | "aider" | "kilo";
|
|
493
646
|
model: string;
|
|
647
|
+
modelPolicy?: {
|
|
648
|
+
/**
|
|
649
|
+
* @default 1
|
|
650
|
+
* @enum {number}
|
|
651
|
+
*/
|
|
652
|
+
version: 1;
|
|
653
|
+
roles?: {
|
|
654
|
+
subagent?: string;
|
|
655
|
+
fast?: string;
|
|
656
|
+
planning?: string;
|
|
657
|
+
review?: string;
|
|
658
|
+
summary?: string;
|
|
659
|
+
compaction?: string;
|
|
660
|
+
weak?: string;
|
|
661
|
+
editor?: string;
|
|
662
|
+
};
|
|
663
|
+
allowedModels?: string[];
|
|
664
|
+
aliases?: {
|
|
665
|
+
[key: string]: string;
|
|
666
|
+
};
|
|
667
|
+
fallbacks?: {
|
|
668
|
+
[key: string]: string[];
|
|
669
|
+
};
|
|
670
|
+
};
|
|
494
671
|
planToken: string;
|
|
495
672
|
version: number;
|
|
496
673
|
updatedAt: string;
|
|
@@ -503,6 +680,21 @@ export interface components {
|
|
|
503
680
|
startedAt: string;
|
|
504
681
|
endedAt?: string;
|
|
505
682
|
exitCode?: number;
|
|
683
|
+
routingEvents?: {
|
|
684
|
+
/** Format: date-time */
|
|
685
|
+
at: string;
|
|
686
|
+
requestId: string;
|
|
687
|
+
requestedModel: string;
|
|
688
|
+
resolvedModel?: string;
|
|
689
|
+
reportedModel?: string;
|
|
690
|
+
/** @enum {string} */
|
|
691
|
+
decision: "allow" | "alias" | "reject" | "fallback";
|
|
692
|
+
/** @enum {string} */
|
|
693
|
+
role?: "main" | "subagent" | "fast" | "planning" | "review" | "summary" | "compaction" | "weak" | "editor";
|
|
694
|
+
reason?: string;
|
|
695
|
+
upstreamStatus?: number;
|
|
696
|
+
}[];
|
|
697
|
+
routingEventsDropped?: number;
|
|
506
698
|
};
|
|
507
699
|
Health: {
|
|
508
700
|
/** @enum {string} */
|
package/dist/harness-types.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { Model, Provider, Profile } from "./domain";
|
|
2
|
+
import type { CompiledModelPolicy, ModelPolicy } from "./model-policy";
|
|
3
|
+
import type { NativeModelPolicy } from "./native-model-policy";
|
|
4
|
+
import type { RoutingEvent } from "./inference-gateway";
|
|
2
5
|
export type HarnessId = Profile["harness"];
|
|
3
6
|
export type HarnessLaunchInput = {
|
|
4
7
|
harness: HarnessId;
|
|
@@ -14,6 +17,12 @@ export type HarnessLaunchInput = {
|
|
|
14
17
|
cwd: string;
|
|
15
18
|
version?: string;
|
|
16
19
|
sessionDir?: string;
|
|
20
|
+
providerId?: string;
|
|
21
|
+
providerBaseUrl?: string;
|
|
22
|
+
modelPolicy?: ModelPolicy;
|
|
23
|
+
compiledPolicy?: CompiledModelPolicy;
|
|
24
|
+
nativePolicy?: NativeModelPolicy;
|
|
25
|
+
onRoutingEvent?: (event: RoutingEvent) => void;
|
|
17
26
|
};
|
|
18
27
|
export type PreparedLaunch = {
|
|
19
28
|
executable: string;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type HermesModelRoles = {
|
|
2
|
+
subagent?: string;
|
|
3
|
+
fast?: string;
|
|
4
|
+
planning?: string;
|
|
5
|
+
review?: string;
|
|
6
|
+
summary?: string;
|
|
7
|
+
compaction?: string;
|
|
8
|
+
weak?: string;
|
|
9
|
+
editor?: string;
|
|
10
|
+
};
|
|
11
|
+
export type HermesModelPolicyFragment = {
|
|
12
|
+
auxiliary: Record<string, {
|
|
13
|
+
api_mode: string;
|
|
14
|
+
provider: "custom";
|
|
15
|
+
model: string;
|
|
16
|
+
base_url: string;
|
|
17
|
+
api_key_env: "SWITCHER_HERMES_AUX_API_KEY";
|
|
18
|
+
fallback_chain: [];
|
|
19
|
+
}>;
|
|
20
|
+
delegation: {
|
|
21
|
+
model: string;
|
|
22
|
+
provider: "custom";
|
|
23
|
+
base_url: string;
|
|
24
|
+
};
|
|
25
|
+
env: {
|
|
26
|
+
apiKeyEnv: "SWITCHER_HERMES_AUX_API_KEY";
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
/** Compile verified Hermes auxiliary config fields without serializing credentials. */
|
|
30
|
+
export declare function compileHermesModelPolicy(currentModel: string, roles: HermesModelRoles, baseUrl: string, apiMode?: string): HermesModelPolicyFragment;
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,56 @@
|
|
|
1
1
|
// src/domain.ts
|
|
2
|
+
import { z as z2 } from "zod";
|
|
3
|
+
|
|
4
|
+
// src/model-policy-schema.ts
|
|
2
5
|
import { z } from "zod";
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
6
|
+
var policyModelIdSchema = z.string().min(1).max(300).regex(/^[^\u0000-\u001f\u007f]+$/);
|
|
7
|
+
var modelPolicyRoleSchema = z.enum(["subagent", "fast", "planning", "review", "summary", "compaction", "weak", "editor"]);
|
|
8
|
+
var boundedModelList = z.array(policyModelIdSchema).max(500);
|
|
9
|
+
var aliasSchema = z.string().regex(/^[A-Za-z0-9._/-]{1,120}$/).refine((v) => !["__proto__", "prototype", "constructor"].includes(v));
|
|
10
|
+
var boundedModelMap = z.record(aliasSchema, policyModelIdSchema).superRefine((value, ctx) => {
|
|
11
|
+
if (Object.keys(value).length > 200)
|
|
12
|
+
ctx.addIssue({ code: "custom", message: "Model policy maps may contain at most 200 entries." });
|
|
13
|
+
});
|
|
14
|
+
var fallbacksSchema = z.record(policyModelIdSchema, z.array(policyModelIdSchema).max(20)).superRefine((value, ctx) => {
|
|
15
|
+
if (Object.keys(value).length > 200)
|
|
16
|
+
ctx.addIssue({ code: "custom", message: "Model policy fallback maps may contain at most 200 entries." });
|
|
17
|
+
});
|
|
18
|
+
var modelPolicySchema = z.object({
|
|
19
|
+
version: z.literal(1).default(1),
|
|
20
|
+
roles: z.object({
|
|
21
|
+
subagent: policyModelIdSchema.optional(),
|
|
22
|
+
fast: policyModelIdSchema.optional(),
|
|
23
|
+
planning: policyModelIdSchema.optional(),
|
|
24
|
+
review: policyModelIdSchema.optional(),
|
|
25
|
+
summary: policyModelIdSchema.optional(),
|
|
26
|
+
compaction: policyModelIdSchema.optional(),
|
|
27
|
+
weak: policyModelIdSchema.optional(),
|
|
28
|
+
editor: policyModelIdSchema.optional()
|
|
29
|
+
}).strict().optional(),
|
|
30
|
+
allowedModels: boundedModelList.optional(),
|
|
31
|
+
aliases: boundedModelMap.optional(),
|
|
32
|
+
fallbacks: fallbacksSchema.optional()
|
|
33
|
+
}).strict();
|
|
34
|
+
var routingDecisionSchema = z.enum(["allow", "alias", "reject", "fallback"]);
|
|
35
|
+
var routingEventRoleSchema = z.enum(["main", ...modelPolicyRoleSchema.options]);
|
|
36
|
+
var routingEventSchema = z.object({
|
|
37
|
+
at: z.string().datetime({ offset: true }),
|
|
38
|
+
requestId: z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/),
|
|
39
|
+
requestedModel: policyModelIdSchema,
|
|
40
|
+
resolvedModel: policyModelIdSchema.optional(),
|
|
41
|
+
reportedModel: policyModelIdSchema.optional(),
|
|
42
|
+
decision: routingDecisionSchema,
|
|
43
|
+
role: routingEventRoleSchema.optional(),
|
|
44
|
+
reason: z.string().regex(/^[a-z][a-z0-9_]{0,63}$/).optional(),
|
|
45
|
+
upstreamStatus: z.number().int().min(100).max(599).optional()
|
|
46
|
+
}).strict();
|
|
47
|
+
var routingEventsSchema = z.array(routingEventSchema).max(1000);
|
|
48
|
+
// src/domain.ts
|
|
49
|
+
var harnessSchema = z2.enum(["claude", "codex", "grok", "opencode", "opencode2", "pi", "omp", "dsh", "cline", "hermes", "prime-agent", "gemini", "aider", "kilo"]);
|
|
50
|
+
var protocolSchema = z2.enum(["anthropic-messages", "openai-responses", "openai-chat", "gemini-generate-content"]);
|
|
51
|
+
var idSchema = z2.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,79}$/);
|
|
52
|
+
var label = z2.string().min(1).max(200);
|
|
53
|
+
var envRef = z2.string().regex(/^SWITCHER_PROVIDER_[A-Z0-9_]+$/);
|
|
8
54
|
function endpoint(value) {
|
|
9
55
|
let url;
|
|
10
56
|
try {
|
|
@@ -17,74 +63,79 @@ function endpoint(value) {
|
|
|
17
63
|
throw new Fault(400, "invalid_url", "URL must use HTTPS, contain no credentials/query/fragment, or use HTTP on loopback.");
|
|
18
64
|
return url.href.replace(/\/+$/, "");
|
|
19
65
|
}
|
|
20
|
-
var urlSchema =
|
|
66
|
+
var urlSchema = z2.string().max(2000).superRefine((v, ctx) => {
|
|
21
67
|
try {
|
|
22
68
|
endpoint(v);
|
|
23
69
|
} catch {
|
|
24
70
|
ctx.addIssue({ code: "custom", message: "Invalid endpoint URL" });
|
|
25
71
|
}
|
|
26
72
|
}).transform(endpoint);
|
|
27
|
-
var modelSchema =
|
|
28
|
-
id:
|
|
73
|
+
var modelSchema = z2.object({
|
|
74
|
+
id: z2.string().min(1).max(300),
|
|
29
75
|
name: label,
|
|
30
|
-
description:
|
|
31
|
-
available:
|
|
32
|
-
contextWindow:
|
|
33
|
-
maxOutputTokens:
|
|
34
|
-
inputModalities:
|
|
35
|
-
outputModalities:
|
|
36
|
-
supportedParameters:
|
|
37
|
-
supportedGenerationMethods:
|
|
76
|
+
description: z2.string().max(8000).optional(),
|
|
77
|
+
available: z2.boolean().optional(),
|
|
78
|
+
contextWindow: z2.number().int().positive().optional(),
|
|
79
|
+
maxOutputTokens: z2.number().int().positive().optional(),
|
|
80
|
+
inputModalities: z2.array(z2.string().max(50)).max(20).optional(),
|
|
81
|
+
outputModalities: z2.array(z2.string().max(50)).max(20).optional(),
|
|
82
|
+
supportedParameters: z2.array(z2.string().max(100)).max(100).optional(),
|
|
83
|
+
supportedGenerationMethods: z2.array(z2.string().min(1).max(100)).max(100).optional()
|
|
38
84
|
}).strict();
|
|
39
|
-
var providerInputSchema =
|
|
85
|
+
var providerInputSchema = z2.object({
|
|
40
86
|
id: idSchema,
|
|
41
87
|
name: label,
|
|
42
88
|
baseUrl: urlSchema,
|
|
43
89
|
protocol: protocolSchema,
|
|
44
90
|
credentialEnv: envRef.optional(),
|
|
45
|
-
authStyle:
|
|
91
|
+
authStyle: z2.enum(["bearer", "x-api-key", "api-key"]).default("bearer"),
|
|
46
92
|
catalogBaseUrl: urlSchema.optional(),
|
|
47
|
-
catalogFormat:
|
|
48
|
-
catalogAuthStyle:
|
|
93
|
+
catalogFormat: z2.enum(["openai", "ollama", "mistral", "together", "fireworks", "dashscope", "gemini", "none"]).optional(),
|
|
94
|
+
catalogAuthStyle: z2.enum(["bearer", "x-api-key", "api-key", "none"]).optional(),
|
|
49
95
|
catalogCredentialEnv: envRef.optional(),
|
|
50
|
-
catalogAccountId:
|
|
51
|
-
modelsPath:
|
|
52
|
-
manualModels:
|
|
96
|
+
catalogAccountId: z2.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/).optional(),
|
|
97
|
+
modelsPath: z2.string().regex(/^[a-zA-Z0-9_/-]+$/).max(200).default("models"),
|
|
98
|
+
manualModels: z2.array(modelSchema).max(1e4).default([])
|
|
53
99
|
}).strict().refine((p) => !p.modelsPath.split("/").includes("..") && !p.modelsPath.startsWith("/"), "modelsPath must be relative");
|
|
54
|
-
var providerPresetSchema =
|
|
100
|
+
var providerPresetSchema = z2.object({
|
|
55
101
|
id: idSchema,
|
|
56
102
|
name: label,
|
|
57
103
|
credentialEnv: envRef.optional(),
|
|
58
|
-
credentialAliases:
|
|
59
|
-
protocols:
|
|
104
|
+
credentialAliases: z2.array(z2.string().regex(/^[A-Z][A-Z0-9_]+$/)),
|
|
105
|
+
protocols: z2.array(z2.object({
|
|
60
106
|
protocol: protocolSchema,
|
|
61
107
|
baseUrl: urlSchema.optional(),
|
|
62
|
-
authStyle:
|
|
108
|
+
authStyle: z2.enum(["bearer", "x-api-key", "api-key"]),
|
|
63
109
|
catalogBaseUrl: urlSchema.optional(),
|
|
64
|
-
catalogFormat:
|
|
65
|
-
catalogAuthStyle:
|
|
66
|
-
modelsPath:
|
|
67
|
-
notes:
|
|
110
|
+
catalogFormat: z2.enum(["openai", "ollama", "mistral", "together", "fireworks", "dashscope", "gemini", "none"]),
|
|
111
|
+
catalogAuthStyle: z2.enum(["bearer", "x-api-key", "api-key", "none"]).optional(),
|
|
112
|
+
modelsPath: z2.string(),
|
|
113
|
+
notes: z2.array(z2.string())
|
|
68
114
|
}).strict()).min(1),
|
|
69
|
-
sources:
|
|
70
|
-
verification:
|
|
115
|
+
sources: z2.array(z2.string().url()),
|
|
116
|
+
verification: z2.literal("documented")
|
|
71
117
|
}).strict();
|
|
72
|
-
var profileInputSchema =
|
|
118
|
+
var profileInputSchema = z2.object({
|
|
73
119
|
id: idSchema,
|
|
74
120
|
name: label,
|
|
75
121
|
providerId: idSchema,
|
|
76
122
|
harness: harnessSchema,
|
|
77
|
-
model:
|
|
123
|
+
model: z2.string().min(1).max(300),
|
|
124
|
+
modelPolicy: modelPolicySchema.optional()
|
|
78
125
|
}).strict();
|
|
79
|
-
var runInputSchema =
|
|
126
|
+
var runInputSchema = z2.object({
|
|
127
|
+
modelPolicyVersion: z2.literal(1),
|
|
80
128
|
profileId: idSchema,
|
|
81
129
|
harness: harnessSchema,
|
|
82
|
-
model:
|
|
83
|
-
|
|
130
|
+
model: z2.string().min(1).max(300),
|
|
131
|
+
modelPolicy: modelPolicySchema.optional(),
|
|
132
|
+
planToken: z2.string().regex(/^[a-f0-9]{64}$/)
|
|
84
133
|
}).strict();
|
|
85
|
-
var runUpdateSchema =
|
|
86
|
-
status:
|
|
87
|
-
exitCode:
|
|
134
|
+
var runUpdateSchema = z2.object({
|
|
135
|
+
status: z2.enum(["exited", "failed", "interrupted"]),
|
|
136
|
+
exitCode: z2.number().int().min(0).max(255),
|
|
137
|
+
routingEvents: routingEventsSchema.optional(),
|
|
138
|
+
routingEventsDropped: z2.number().int().min(0).max(1e6).optional()
|
|
88
139
|
}).strict();
|
|
89
140
|
|
|
90
141
|
class Fault extends Error {
|
|
@@ -410,7 +461,7 @@ class SwitcherClient {
|
|
|
410
461
|
return this.request("GET", `/v1/runs/${encodeURIComponent(id)}`);
|
|
411
462
|
}
|
|
412
463
|
createRun(input, idempotencyKey) {
|
|
413
|
-
return this.request("POST", "/v1/runs", input, { idempotencyKey });
|
|
464
|
+
return this.request("POST", "/v1/runs", { ...input, modelPolicyVersion: 1 }, { idempotencyKey });
|
|
414
465
|
}
|
|
415
466
|
finishRun(id, version, input, idempotencyKey) {
|
|
416
467
|
return this.request("PATCH", `/v1/runs/${encodeURIComponent(id)}`, input, { version, idempotencyKey });
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { HarnessLaunchInput } from "./harness-types";
|
|
2
|
+
import { type CompiledModelPolicy } from "./model-policy";
|
|
3
|
+
export type RoutingEvent = {
|
|
4
|
+
at: string;
|
|
5
|
+
requestId: string;
|
|
6
|
+
requestedModel: string;
|
|
7
|
+
resolvedModel?: string;
|
|
8
|
+
reportedModel?: string;
|
|
9
|
+
decision: "allow" | "alias" | "reject" | "fallback";
|
|
10
|
+
reason?: string;
|
|
11
|
+
upstreamStatus?: number;
|
|
12
|
+
};
|
|
13
|
+
type GatewayInput = HarnessLaunchInput & {
|
|
14
|
+
compiledPolicy: CompiledModelPolicy;
|
|
15
|
+
catalogPath: string;
|
|
16
|
+
onRoutingEvent?: (event: RoutingEvent) => void;
|
|
17
|
+
};
|
|
18
|
+
/** A per-launch credential boundary: the native client never receives the provider key. */
|
|
19
|
+
export declare function createInferenceGateway(input: GatewayInput): {
|
|
20
|
+
baseUrl: string;
|
|
21
|
+
token: string;
|
|
22
|
+
cleanup: () => Promise<void>;
|
|
23
|
+
};
|
|
24
|
+
export {};
|
package/dist/launcher.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { PreparedLaunch } from "./harness-types";
|
|
1
2
|
import { SwitcherClient } from "./sdk";
|
|
2
3
|
import { type LaunchPlan, type ProviderInput } from "./domain";
|
|
3
|
-
import { type OriContract
|
|
4
|
+
import { type OriContract } from "./ori-backend";
|
|
5
|
+
import type { RoutingEvent } from "./inference-gateway";
|
|
4
6
|
export { childEnvironment } from "./harness-environment";
|
|
5
7
|
export type LaunchBackend = "direct" | "ori";
|
|
6
8
|
export type LaunchOptions = {
|
|
@@ -18,6 +20,7 @@ export type LaunchOptions = {
|
|
|
18
20
|
type OriPreparationOptions = Pick<LaunchOptions, "oriExecutable" | "args" | "resolveCredential" | "credentialEnv"> & {
|
|
19
21
|
stateDir?: string;
|
|
20
22
|
cwd?: string;
|
|
23
|
+
onRoutingEvent?: (event: RoutingEvent) => void;
|
|
21
24
|
};
|
|
22
25
|
type OriSupportedHarness = Exclude<LaunchPlan["profile"]["harness"], "omp" | "cline" | "hermes" | "prime-agent" | "gemini" | "aider" | "opencode" | "kilo">;
|
|
23
26
|
export declare function validateOriForPlan(plan: LaunchPlan, options?: Pick<OriPreparationOptions, "oriExecutable" | "args" | "credentialEnv" | "cwd">): Promise<{
|
|
@@ -38,8 +41,10 @@ declare function buildOriRequest(plan: LaunchPlan, target: OriSupportedHarness,
|
|
|
38
41
|
};
|
|
39
42
|
readonly args: string[];
|
|
40
43
|
};
|
|
41
|
-
export declare function prepareOriForPlan(plan: LaunchPlan, options
|
|
44
|
+
export declare function prepareOriForPlan(plan: LaunchPlan, options: OriPreparationOptions & {
|
|
45
|
+
stateDir: string;
|
|
46
|
+
}): Promise<{
|
|
42
47
|
contract: OriContract;
|
|
43
|
-
prepared:
|
|
48
|
+
prepared: PreparedLaunch;
|
|
44
49
|
}>;
|
|
45
50
|
export declare function launch(client: SwitcherClient, profileId: string, options?: LaunchOptions): Promise<number>;
|