@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/mcp/index.js
CHANGED
|
@@ -4,16 +4,63 @@
|
|
|
4
4
|
// src/mcp.ts
|
|
5
5
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6
6
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
|
-
import { z as
|
|
7
|
+
import { z as z3 } from "zod";
|
|
8
8
|
|
|
9
9
|
// src/domain.ts
|
|
10
|
+
import { z as z2 } from "zod";
|
|
11
|
+
|
|
12
|
+
// src/model-policy-schema.ts
|
|
10
13
|
import { z } from "zod";
|
|
11
|
-
var
|
|
12
|
-
var
|
|
13
|
-
var
|
|
14
|
-
var
|
|
15
|
-
var
|
|
16
|
-
|
|
14
|
+
var policyModelIdSchema = z.string().min(1).max(300).regex(/^[^\u0000-\u001f\u007f]+$/);
|
|
15
|
+
var modelPolicyRoleSchema = z.enum(["subagent", "fast", "planning", "review", "summary", "compaction", "weak", "editor"]);
|
|
16
|
+
var boundedModelList = z.array(policyModelIdSchema).max(500);
|
|
17
|
+
var aliasSchema = z.string().regex(/^[A-Za-z0-9._/-]{1,120}$/).refine((v) => !["__proto__", "prototype", "constructor"].includes(v));
|
|
18
|
+
var boundedModelMap = z.record(aliasSchema, policyModelIdSchema).superRefine((value, ctx) => {
|
|
19
|
+
if (Object.keys(value).length > 200)
|
|
20
|
+
ctx.addIssue({ code: "custom", message: "Model policy maps may contain at most 200 entries." });
|
|
21
|
+
});
|
|
22
|
+
var fallbacksSchema = z.record(policyModelIdSchema, z.array(policyModelIdSchema).max(20)).superRefine((value, ctx) => {
|
|
23
|
+
if (Object.keys(value).length > 200)
|
|
24
|
+
ctx.addIssue({ code: "custom", message: "Model policy fallback maps may contain at most 200 entries." });
|
|
25
|
+
});
|
|
26
|
+
var modelPolicySchema = z.object({
|
|
27
|
+
version: z.literal(1).default(1),
|
|
28
|
+
roles: z.object({
|
|
29
|
+
subagent: policyModelIdSchema.optional(),
|
|
30
|
+
fast: policyModelIdSchema.optional(),
|
|
31
|
+
planning: policyModelIdSchema.optional(),
|
|
32
|
+
review: policyModelIdSchema.optional(),
|
|
33
|
+
summary: policyModelIdSchema.optional(),
|
|
34
|
+
compaction: policyModelIdSchema.optional(),
|
|
35
|
+
weak: policyModelIdSchema.optional(),
|
|
36
|
+
editor: policyModelIdSchema.optional()
|
|
37
|
+
}).strict().optional(),
|
|
38
|
+
allowedModels: boundedModelList.optional(),
|
|
39
|
+
aliases: boundedModelMap.optional(),
|
|
40
|
+
fallbacks: fallbacksSchema.optional()
|
|
41
|
+
}).strict();
|
|
42
|
+
var routingDecisionSchema = z.enum(["allow", "alias", "reject", "fallback"]);
|
|
43
|
+
var routingEventRoleSchema = z.enum(["main", ...modelPolicyRoleSchema.options]);
|
|
44
|
+
var routingEventSchema = z.object({
|
|
45
|
+
at: z.string().datetime({ offset: true }),
|
|
46
|
+
requestId: z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/),
|
|
47
|
+
requestedModel: policyModelIdSchema,
|
|
48
|
+
resolvedModel: policyModelIdSchema.optional(),
|
|
49
|
+
reportedModel: policyModelIdSchema.optional(),
|
|
50
|
+
decision: routingDecisionSchema,
|
|
51
|
+
role: routingEventRoleSchema.optional(),
|
|
52
|
+
reason: z.string().regex(/^[a-z][a-z0-9_]{0,63}$/).optional(),
|
|
53
|
+
upstreamStatus: z.number().int().min(100).max(599).optional()
|
|
54
|
+
}).strict();
|
|
55
|
+
var routingEventsSchema = z.array(routingEventSchema).max(1000);
|
|
56
|
+
|
|
57
|
+
// src/domain.ts
|
|
58
|
+
var VERSION = "0.1.3";
|
|
59
|
+
var harnessSchema = z2.enum(["claude", "codex", "grok", "opencode", "opencode2", "pi", "omp", "dsh", "cline", "hermes", "prime-agent", "gemini", "aider", "kilo"]);
|
|
60
|
+
var protocolSchema = z2.enum(["anthropic-messages", "openai-responses", "openai-chat", "gemini-generate-content"]);
|
|
61
|
+
var idSchema = z2.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,79}$/);
|
|
62
|
+
var label = z2.string().min(1).max(200);
|
|
63
|
+
var envRef = z2.string().regex(/^SWITCHER_PROVIDER_[A-Z0-9_]+$/);
|
|
17
64
|
function endpoint(value) {
|
|
18
65
|
let url;
|
|
19
66
|
try {
|
|
@@ -26,74 +73,79 @@ function endpoint(value) {
|
|
|
26
73
|
throw new Fault(400, "invalid_url", "URL must use HTTPS, contain no credentials/query/fragment, or use HTTP on loopback.");
|
|
27
74
|
return url.href.replace(/\/+$/, "");
|
|
28
75
|
}
|
|
29
|
-
var urlSchema =
|
|
76
|
+
var urlSchema = z2.string().max(2000).superRefine((v, ctx) => {
|
|
30
77
|
try {
|
|
31
78
|
endpoint(v);
|
|
32
79
|
} catch {
|
|
33
80
|
ctx.addIssue({ code: "custom", message: "Invalid endpoint URL" });
|
|
34
81
|
}
|
|
35
82
|
}).transform(endpoint);
|
|
36
|
-
var modelSchema =
|
|
37
|
-
id:
|
|
83
|
+
var modelSchema = z2.object({
|
|
84
|
+
id: z2.string().min(1).max(300),
|
|
38
85
|
name: label,
|
|
39
|
-
description:
|
|
40
|
-
available:
|
|
41
|
-
contextWindow:
|
|
42
|
-
maxOutputTokens:
|
|
43
|
-
inputModalities:
|
|
44
|
-
outputModalities:
|
|
45
|
-
supportedParameters:
|
|
46
|
-
supportedGenerationMethods:
|
|
86
|
+
description: z2.string().max(8000).optional(),
|
|
87
|
+
available: z2.boolean().optional(),
|
|
88
|
+
contextWindow: z2.number().int().positive().optional(),
|
|
89
|
+
maxOutputTokens: z2.number().int().positive().optional(),
|
|
90
|
+
inputModalities: z2.array(z2.string().max(50)).max(20).optional(),
|
|
91
|
+
outputModalities: z2.array(z2.string().max(50)).max(20).optional(),
|
|
92
|
+
supportedParameters: z2.array(z2.string().max(100)).max(100).optional(),
|
|
93
|
+
supportedGenerationMethods: z2.array(z2.string().min(1).max(100)).max(100).optional()
|
|
47
94
|
}).strict();
|
|
48
|
-
var providerInputSchema =
|
|
95
|
+
var providerInputSchema = z2.object({
|
|
49
96
|
id: idSchema,
|
|
50
97
|
name: label,
|
|
51
98
|
baseUrl: urlSchema,
|
|
52
99
|
protocol: protocolSchema,
|
|
53
100
|
credentialEnv: envRef.optional(),
|
|
54
|
-
authStyle:
|
|
101
|
+
authStyle: z2.enum(["bearer", "x-api-key", "api-key"]).default("bearer"),
|
|
55
102
|
catalogBaseUrl: urlSchema.optional(),
|
|
56
|
-
catalogFormat:
|
|
57
|
-
catalogAuthStyle:
|
|
103
|
+
catalogFormat: z2.enum(["openai", "ollama", "mistral", "together", "fireworks", "dashscope", "gemini", "none"]).optional(),
|
|
104
|
+
catalogAuthStyle: z2.enum(["bearer", "x-api-key", "api-key", "none"]).optional(),
|
|
58
105
|
catalogCredentialEnv: envRef.optional(),
|
|
59
|
-
catalogAccountId:
|
|
60
|
-
modelsPath:
|
|
61
|
-
manualModels:
|
|
106
|
+
catalogAccountId: z2.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/).optional(),
|
|
107
|
+
modelsPath: z2.string().regex(/^[a-zA-Z0-9_/-]+$/).max(200).default("models"),
|
|
108
|
+
manualModels: z2.array(modelSchema).max(1e4).default([])
|
|
62
109
|
}).strict().refine((p) => !p.modelsPath.split("/").includes("..") && !p.modelsPath.startsWith("/"), "modelsPath must be relative");
|
|
63
|
-
var providerPresetSchema =
|
|
110
|
+
var providerPresetSchema = z2.object({
|
|
64
111
|
id: idSchema,
|
|
65
112
|
name: label,
|
|
66
113
|
credentialEnv: envRef.optional(),
|
|
67
|
-
credentialAliases:
|
|
68
|
-
protocols:
|
|
114
|
+
credentialAliases: z2.array(z2.string().regex(/^[A-Z][A-Z0-9_]+$/)),
|
|
115
|
+
protocols: z2.array(z2.object({
|
|
69
116
|
protocol: protocolSchema,
|
|
70
117
|
baseUrl: urlSchema.optional(),
|
|
71
|
-
authStyle:
|
|
118
|
+
authStyle: z2.enum(["bearer", "x-api-key", "api-key"]),
|
|
72
119
|
catalogBaseUrl: urlSchema.optional(),
|
|
73
|
-
catalogFormat:
|
|
74
|
-
catalogAuthStyle:
|
|
75
|
-
modelsPath:
|
|
76
|
-
notes:
|
|
120
|
+
catalogFormat: z2.enum(["openai", "ollama", "mistral", "together", "fireworks", "dashscope", "gemini", "none"]),
|
|
121
|
+
catalogAuthStyle: z2.enum(["bearer", "x-api-key", "api-key", "none"]).optional(),
|
|
122
|
+
modelsPath: z2.string(),
|
|
123
|
+
notes: z2.array(z2.string())
|
|
77
124
|
}).strict()).min(1),
|
|
78
|
-
sources:
|
|
79
|
-
verification:
|
|
125
|
+
sources: z2.array(z2.string().url()),
|
|
126
|
+
verification: z2.literal("documented")
|
|
80
127
|
}).strict();
|
|
81
|
-
var profileInputSchema =
|
|
128
|
+
var profileInputSchema = z2.object({
|
|
82
129
|
id: idSchema,
|
|
83
130
|
name: label,
|
|
84
131
|
providerId: idSchema,
|
|
85
132
|
harness: harnessSchema,
|
|
86
|
-
model:
|
|
133
|
+
model: z2.string().min(1).max(300),
|
|
134
|
+
modelPolicy: modelPolicySchema.optional()
|
|
87
135
|
}).strict();
|
|
88
|
-
var runInputSchema =
|
|
136
|
+
var runInputSchema = z2.object({
|
|
137
|
+
modelPolicyVersion: z2.literal(1),
|
|
89
138
|
profileId: idSchema,
|
|
90
139
|
harness: harnessSchema,
|
|
91
|
-
model:
|
|
92
|
-
|
|
140
|
+
model: z2.string().min(1).max(300),
|
|
141
|
+
modelPolicy: modelPolicySchema.optional(),
|
|
142
|
+
planToken: z2.string().regex(/^[a-f0-9]{64}$/)
|
|
93
143
|
}).strict();
|
|
94
|
-
var runUpdateSchema =
|
|
95
|
-
status:
|
|
96
|
-
exitCode:
|
|
144
|
+
var runUpdateSchema = z2.object({
|
|
145
|
+
status: z2.enum(["exited", "failed", "interrupted"]),
|
|
146
|
+
exitCode: z2.number().int().min(0).max(255),
|
|
147
|
+
routingEvents: routingEventsSchema.optional(),
|
|
148
|
+
routingEventsDropped: z2.number().int().min(0).max(1e6).optional()
|
|
97
149
|
}).strict();
|
|
98
150
|
|
|
99
151
|
class Fault extends Error {
|
|
@@ -369,7 +421,7 @@ class SwitcherClient {
|
|
|
369
421
|
return this.request("GET", `/v1/runs/${encodeURIComponent(id)}`);
|
|
370
422
|
}
|
|
371
423
|
createRun(input, idempotencyKey) {
|
|
372
|
-
return this.request("POST", "/v1/runs", input, { idempotencyKey });
|
|
424
|
+
return this.request("POST", "/v1/runs", { ...input, modelPolicyVersion: 1 }, { idempotencyKey });
|
|
373
425
|
}
|
|
374
426
|
finishRun(id, version, input, idempotencyKey) {
|
|
375
427
|
return this.request("PATCH", `/v1/runs/${encodeURIComponent(id)}`, input, { version, idempotencyKey });
|
|
@@ -384,7 +436,7 @@ function clientFromEnv(env = process.env) {
|
|
|
384
436
|
|
|
385
437
|
// src/mcp.ts
|
|
386
438
|
var server = new McpServer({ name: "switcher", version: VERSION });
|
|
387
|
-
var page = { limit:
|
|
439
|
+
var page = { limit: z3.number().int().min(1).max(1000).optional(), offset: z3.number().int().nonnegative().optional(), search: z3.string().optional() };
|
|
388
440
|
function tool(name, description, schema, run) {
|
|
389
441
|
server.tool(name, description, schema, async (input) => {
|
|
390
442
|
try {
|
|
@@ -395,23 +447,23 @@ function tool(name, description, schema, run) {
|
|
|
395
447
|
});
|
|
396
448
|
}
|
|
397
449
|
tool("providers_list", "List provider profiles.", page, (p) => clientFromEnv().listProviders(p));
|
|
398
|
-
tool("providers_get", "Get a provider.", { id:
|
|
450
|
+
tool("providers_get", "Get a provider.", { id: z3.string() }, (p) => clientFromEnv().getProvider(p.id));
|
|
399
451
|
tool("providers_create", "Create a provider using credential environment references only.", providerInputSchema.innerType().shape, (p) => clientFromEnv().createProvider(p));
|
|
400
|
-
tool("providers_update", "Replace a provider at its current version.", { provider: providerInputSchema, version:
|
|
401
|
-
tool("providers_delete", "Delete an unreferenced provider.", { id:
|
|
402
|
-
tool("models_list", "List catalog with capability information.", { id:
|
|
452
|
+
tool("providers_update", "Replace a provider at its current version.", { provider: providerInputSchema, version: z3.number().int() }, (p) => clientFromEnv().updateProvider(p.provider, p.version));
|
|
453
|
+
tool("providers_delete", "Delete an unreferenced provider.", { id: z3.string(), version: z3.number().int() }, (p) => clientFromEnv().deleteProvider(p.id, p.version));
|
|
454
|
+
tool("models_list", "List catalog with capability information.", { id: z3.string(), ...page }, (p) => {
|
|
403
455
|
const { id, ...rest } = p;
|
|
404
456
|
return clientFromEnv().listModels(id, rest);
|
|
405
457
|
});
|
|
406
|
-
tool("models_refresh", "Discover provider models.", { id:
|
|
458
|
+
tool("models_refresh", "Discover provider models.", { id: z3.string() }, (p) => clientFromEnv().refreshModels(p.id));
|
|
407
459
|
tool("profiles_list", "List harness launch profiles.", page, (p) => clientFromEnv().listProfiles(p));
|
|
408
|
-
tool("profiles_get", "Get a harness profile.", { id:
|
|
460
|
+
tool("profiles_get", "Get a harness profile.", { id: z3.string() }, (p) => clientFromEnv().getProfile(p.id));
|
|
409
461
|
tool("profiles_create", "Create a harness launch profile.", profileInputSchema.shape, (p) => clientFromEnv().createProfile(p));
|
|
410
|
-
tool("profiles_update", "Replace a harness profile at its version.", { profile: profileInputSchema, version:
|
|
411
|
-
tool("profiles_delete", "Delete a profile without run history.", { id:
|
|
412
|
-
tool("launch_plan", "Validate a local launch plan; does not execute a remote process.", { profileId:
|
|
462
|
+
tool("profiles_update", "Replace a harness profile at its version.", { profile: profileInputSchema, version: z3.number().int() }, (p) => clientFromEnv().updateProfile(p.profile, p.version));
|
|
463
|
+
tool("profiles_delete", "Delete a profile without run history.", { id: z3.string(), version: z3.number().int() }, (p) => clientFromEnv().deleteProfile(p.id, p.version));
|
|
464
|
+
tool("launch_plan", "Validate a local launch plan; does not execute a remote process.", { profileId: z3.string() }, (p) => clientFromEnv().launchPlan(p.profileId));
|
|
413
465
|
tool("runs_list", "List launch metadata.", page, (p) => clientFromEnv().listRuns(p));
|
|
414
|
-
tool("runs_get", "Get launch metadata.", { id:
|
|
466
|
+
tool("runs_get", "Get launch metadata.", { id: z3.string() }, (p) => clientFromEnv().getRun(p.id));
|
|
415
467
|
if (process.argv.includes("--version"))
|
|
416
468
|
console.log(VERSION);
|
|
417
469
|
else if (process.argv.includes("--help"))
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Model references are opaque provider IDs, never prompts or credentials. */
|
|
3
|
+
export declare const policyModelIdSchema: z.ZodString;
|
|
4
|
+
export declare const modelPolicyRoleSchema: z.ZodEnum<["subagent", "fast", "planning", "review", "summary", "compaction", "weak", "editor"]>;
|
|
5
|
+
export type ModelPolicyRole = z.infer<typeof modelPolicyRoleSchema>;
|
|
6
|
+
export declare const modelPolicySchema: z.ZodObject<{
|
|
7
|
+
version: z.ZodDefault<z.ZodLiteral<1>>;
|
|
8
|
+
roles: z.ZodOptional<z.ZodObject<{
|
|
9
|
+
subagent: z.ZodOptional<z.ZodString>;
|
|
10
|
+
fast: z.ZodOptional<z.ZodString>;
|
|
11
|
+
planning: z.ZodOptional<z.ZodString>;
|
|
12
|
+
review: z.ZodOptional<z.ZodString>;
|
|
13
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
14
|
+
compaction: z.ZodOptional<z.ZodString>;
|
|
15
|
+
weak: z.ZodOptional<z.ZodString>;
|
|
16
|
+
editor: z.ZodOptional<z.ZodString>;
|
|
17
|
+
}, "strict", z.ZodTypeAny, {
|
|
18
|
+
subagent?: string | undefined;
|
|
19
|
+
fast?: string | undefined;
|
|
20
|
+
planning?: string | undefined;
|
|
21
|
+
review?: string | undefined;
|
|
22
|
+
summary?: string | undefined;
|
|
23
|
+
compaction?: string | undefined;
|
|
24
|
+
weak?: string | undefined;
|
|
25
|
+
editor?: string | undefined;
|
|
26
|
+
}, {
|
|
27
|
+
subagent?: string | undefined;
|
|
28
|
+
fast?: string | undefined;
|
|
29
|
+
planning?: string | undefined;
|
|
30
|
+
review?: string | undefined;
|
|
31
|
+
summary?: string | undefined;
|
|
32
|
+
compaction?: string | undefined;
|
|
33
|
+
weak?: string | undefined;
|
|
34
|
+
editor?: string | undefined;
|
|
35
|
+
}>>;
|
|
36
|
+
allowedModels: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
37
|
+
aliases: z.ZodOptional<z.ZodEffects<z.ZodRecord<z.ZodEffects<z.ZodString, string, string>, z.ZodString>, Record<string, string>, Record<string, string>>>;
|
|
38
|
+
fallbacks: z.ZodOptional<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>, Record<string, string[]>, Record<string, string[]>>>;
|
|
39
|
+
}, "strict", z.ZodTypeAny, {
|
|
40
|
+
version: 1;
|
|
41
|
+
roles?: {
|
|
42
|
+
subagent?: string | undefined;
|
|
43
|
+
fast?: string | undefined;
|
|
44
|
+
planning?: string | undefined;
|
|
45
|
+
review?: string | undefined;
|
|
46
|
+
summary?: string | undefined;
|
|
47
|
+
compaction?: string | undefined;
|
|
48
|
+
weak?: string | undefined;
|
|
49
|
+
editor?: string | undefined;
|
|
50
|
+
} | undefined;
|
|
51
|
+
allowedModels?: string[] | undefined;
|
|
52
|
+
aliases?: Record<string, string> | undefined;
|
|
53
|
+
fallbacks?: Record<string, string[]> | undefined;
|
|
54
|
+
}, {
|
|
55
|
+
version?: 1 | undefined;
|
|
56
|
+
roles?: {
|
|
57
|
+
subagent?: string | undefined;
|
|
58
|
+
fast?: string | undefined;
|
|
59
|
+
planning?: string | undefined;
|
|
60
|
+
review?: string | undefined;
|
|
61
|
+
summary?: string | undefined;
|
|
62
|
+
compaction?: string | undefined;
|
|
63
|
+
weak?: string | undefined;
|
|
64
|
+
editor?: string | undefined;
|
|
65
|
+
} | undefined;
|
|
66
|
+
allowedModels?: string[] | undefined;
|
|
67
|
+
aliases?: Record<string, string> | undefined;
|
|
68
|
+
fallbacks?: Record<string, string[]> | undefined;
|
|
69
|
+
}>;
|
|
70
|
+
export type ModelPolicy = z.infer<typeof modelPolicySchema>;
|
|
71
|
+
export declare const routingDecisionSchema: z.ZodEnum<["allow", "alias", "reject", "fallback"]>;
|
|
72
|
+
export declare const routingEventRoleSchema: z.ZodEnum<["main", "subagent", "fast", "planning", "review", "summary", "compaction", "weak", "editor"]>;
|
|
73
|
+
export declare const routingEventSchema: z.ZodObject<{
|
|
74
|
+
at: z.ZodString;
|
|
75
|
+
requestId: z.ZodString;
|
|
76
|
+
requestedModel: z.ZodString;
|
|
77
|
+
resolvedModel: z.ZodOptional<z.ZodString>;
|
|
78
|
+
reportedModel: z.ZodOptional<z.ZodString>;
|
|
79
|
+
decision: z.ZodEnum<["allow", "alias", "reject", "fallback"]>;
|
|
80
|
+
role: z.ZodOptional<z.ZodEnum<["main", "subagent", "fast", "planning", "review", "summary", "compaction", "weak", "editor"]>>;
|
|
81
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
82
|
+
upstreamStatus: z.ZodOptional<z.ZodNumber>;
|
|
83
|
+
}, "strict", z.ZodTypeAny, {
|
|
84
|
+
at: string;
|
|
85
|
+
requestId: string;
|
|
86
|
+
requestedModel: string;
|
|
87
|
+
decision: "allow" | "alias" | "reject" | "fallback";
|
|
88
|
+
resolvedModel?: string | undefined;
|
|
89
|
+
reportedModel?: string | undefined;
|
|
90
|
+
role?: "main" | "subagent" | "fast" | "planning" | "review" | "summary" | "compaction" | "weak" | "editor" | undefined;
|
|
91
|
+
reason?: string | undefined;
|
|
92
|
+
upstreamStatus?: number | undefined;
|
|
93
|
+
}, {
|
|
94
|
+
at: string;
|
|
95
|
+
requestId: string;
|
|
96
|
+
requestedModel: string;
|
|
97
|
+
decision: "allow" | "alias" | "reject" | "fallback";
|
|
98
|
+
resolvedModel?: string | undefined;
|
|
99
|
+
reportedModel?: string | undefined;
|
|
100
|
+
role?: "main" | "subagent" | "fast" | "planning" | "review" | "summary" | "compaction" | "weak" | "editor" | undefined;
|
|
101
|
+
reason?: string | undefined;
|
|
102
|
+
upstreamStatus?: number | undefined;
|
|
103
|
+
}>;
|
|
104
|
+
export type RoutingEvent = z.infer<typeof routingEventSchema>;
|
|
105
|
+
export declare const routingEventsSchema: z.ZodArray<z.ZodObject<{
|
|
106
|
+
at: z.ZodString;
|
|
107
|
+
requestId: z.ZodString;
|
|
108
|
+
requestedModel: z.ZodString;
|
|
109
|
+
resolvedModel: z.ZodOptional<z.ZodString>;
|
|
110
|
+
reportedModel: z.ZodOptional<z.ZodString>;
|
|
111
|
+
decision: z.ZodEnum<["allow", "alias", "reject", "fallback"]>;
|
|
112
|
+
role: z.ZodOptional<z.ZodEnum<["main", "subagent", "fast", "planning", "review", "summary", "compaction", "weak", "editor"]>>;
|
|
113
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
114
|
+
upstreamStatus: z.ZodOptional<z.ZodNumber>;
|
|
115
|
+
}, "strict", z.ZodTypeAny, {
|
|
116
|
+
at: string;
|
|
117
|
+
requestId: string;
|
|
118
|
+
requestedModel: string;
|
|
119
|
+
decision: "allow" | "alias" | "reject" | "fallback";
|
|
120
|
+
resolvedModel?: string | undefined;
|
|
121
|
+
reportedModel?: string | undefined;
|
|
122
|
+
role?: "main" | "subagent" | "fast" | "planning" | "review" | "summary" | "compaction" | "weak" | "editor" | undefined;
|
|
123
|
+
reason?: string | undefined;
|
|
124
|
+
upstreamStatus?: number | undefined;
|
|
125
|
+
}, {
|
|
126
|
+
at: string;
|
|
127
|
+
requestId: string;
|
|
128
|
+
requestedModel: string;
|
|
129
|
+
decision: "allow" | "alias" | "reject" | "fallback";
|
|
130
|
+
resolvedModel?: string | undefined;
|
|
131
|
+
reportedModel?: string | undefined;
|
|
132
|
+
role?: "main" | "subagent" | "fast" | "planning" | "review" | "summary" | "compaction" | "weak" | "editor" | undefined;
|
|
133
|
+
reason?: string | undefined;
|
|
134
|
+
upstreamStatus?: number | undefined;
|
|
135
|
+
}>, "many">;
|
|
136
|
+
/** Stable object-key order; ordered fallback arrays retain their precedence. */
|
|
137
|
+
export declare function canonicalPolicyJSON(value: unknown): string;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type Model } from "./domain";
|
|
2
|
+
export declare const MODEL_POLICY_VERSION: 1;
|
|
3
|
+
export type ModelRole = "subagent" | "fast" | "planning" | "review" | "summary" | "compaction" | "weak" | "editor";
|
|
4
|
+
export type ModelPolicy = {
|
|
5
|
+
version?: 1;
|
|
6
|
+
roles?: Partial<Record<ModelRole, string>>;
|
|
7
|
+
allowedModels?: string[];
|
|
8
|
+
aliases?: Record<string, string>;
|
|
9
|
+
fallbacks?: Record<string, string[]>;
|
|
10
|
+
};
|
|
11
|
+
export type CompiledModelPolicy = {
|
|
12
|
+
version: 1;
|
|
13
|
+
model: string;
|
|
14
|
+
roles: Record<ModelRole, string>;
|
|
15
|
+
allowedModels: string[];
|
|
16
|
+
aliases: Record<string, string>;
|
|
17
|
+
fallbacks: Record<string, string[]>;
|
|
18
|
+
digest: string;
|
|
19
|
+
};
|
|
20
|
+
export type ModelGuidanceContext = {
|
|
21
|
+
harness: string;
|
|
22
|
+
providerId?: string;
|
|
23
|
+
baseUrl?: string;
|
|
24
|
+
model: string;
|
|
25
|
+
compiled: CompiledModelPolicy;
|
|
26
|
+
catalogPath?: string;
|
|
27
|
+
};
|
|
28
|
+
export declare function compileModelPolicy(model: string, catalog: readonly Model[], policy?: ModelPolicy): CompiledModelPolicy;
|
|
29
|
+
export declare function resolvePolicyModel(compiled: CompiledModelPolicy, requested: string): string;
|
|
30
|
+
export declare function renderModelGuidance(context: ModelGuidanceContext): string;
|
|
31
|
+
export declare function injectModelGuidance(protocol: "anthropic-messages" | "openai-chat" | "openai-responses" | "gemini-generate-content", body: unknown, guidance: string, operation?: string): unknown;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Pure compilation of the documented native model-policy surfaces.
|
|
2
|
+
*
|
|
3
|
+
* This module deliberately does not launch processes, read configuration, or
|
|
4
|
+
* infer provider aliases. Callers provide the exact model IDs they have
|
|
5
|
+
* already selected and may then serialize the returned env/config values.
|
|
6
|
+
*/
|
|
7
|
+
export declare const nativeRoles: readonly ["main", "subagent", "fast", "planning", "review", "summary", "compaction", "weak", "editor"];
|
|
8
|
+
export type NativeRole = typeof nativeRoles[number];
|
|
9
|
+
export type NativePolicyHarness = "claude" | "codex" | "grok" | "opencode" | "opencode2" | "omp" | "hermes" | "aider" | "kilo" | "gemini" | "cline" | "dsh" | "pi" | "prime-agent";
|
|
10
|
+
export type NativeModelPolicyInput = {
|
|
11
|
+
harness: NativePolicyHarness;
|
|
12
|
+
mainModel: string;
|
|
13
|
+
roles?: Partial<Record<NativeRole, string>>;
|
|
14
|
+
version?: string;
|
|
15
|
+
};
|
|
16
|
+
export type NativeModelPolicy = {
|
|
17
|
+
harness: NativePolicyHarness;
|
|
18
|
+
env: Record<string, string>;
|
|
19
|
+
config: Record<string, unknown>;
|
|
20
|
+
unsupportedRoles: NativeRole[];
|
|
21
|
+
};
|
|
22
|
+
/** Compile exact role assignments into native settings/env without inventing knobs. */
|
|
23
|
+
export declare function compileNativeModelPolicy(input: NativeModelPolicyInput): NativeModelPolicy;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ModelPolicy } from "./model-policy-schema";
|
|
2
|
+
type Dict = Record<string, unknown>;
|
|
3
|
+
export type OpenCodeRole = "main" | "subagent" | "planning" | "summary" | "compaction";
|
|
4
|
+
export type OpenCodeCompiledRoles = Partial<Record<OpenCodeRole, string>>;
|
|
5
|
+
export type PreservedOpenCodeAgent = Dict & {
|
|
6
|
+
name: string;
|
|
7
|
+
};
|
|
8
|
+
export type OpenCodeModelPolicyInput = {
|
|
9
|
+
providerId: string;
|
|
10
|
+
mainModel: string;
|
|
11
|
+
roles?: OpenCodeCompiledRoles | ModelPolicy["roles"];
|
|
12
|
+
preservedAgents?: PreservedOpenCodeAgent[];
|
|
13
|
+
/** OpenCode 2's native `agents` table or legacy OpenCode's `agent` table. */
|
|
14
|
+
format?: "v2" | "legacy";
|
|
15
|
+
};
|
|
16
|
+
export type OpenCodeModelPolicyResult = {
|
|
17
|
+
model: string;
|
|
18
|
+
agents: PreservedOpenCodeAgent[];
|
|
19
|
+
/** Only native OpenCode fields are emitted. */
|
|
20
|
+
config: {
|
|
21
|
+
model: string;
|
|
22
|
+
agents?: Record<string, Dict>;
|
|
23
|
+
agent?: Record<string, Dict>;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Merge Switcher routing into native OpenCode agent declarations. Prompts,
|
|
28
|
+
* permissions, modes and other native fields are copied without alteration.
|
|
29
|
+
*/
|
|
30
|
+
export declare function compileOpenCodeModelPolicy(input: OpenCodeModelPolicyInput): OpenCodeModelPolicyResult;
|
|
31
|
+
/** Match OpenCode's explicit agent selection without interpreting prompt values as flags. */
|
|
32
|
+
export declare function openCodeInvocationModel(args: readonly string[], policy: OpenCodeModelPolicyResult, defaultAgent?: string): string;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PreparedLaunch } from "./harness-types";
|
|
2
|
+
/** Execute the verified native launch after Ori finishes its OpenRouter setup.
|
|
3
|
+
* Credentials are remapped from process environment, never written into the shim. */
|
|
4
|
+
export declare function prepareOriModelPolicy(target: "codex" | "grok", prepared: Pick<PreparedLaunch, "executable" | "args" | "env">): {
|
|
5
|
+
name: "codex" | "grok";
|
|
6
|
+
env: Record<string, string>;
|
|
7
|
+
script: string;
|
|
8
|
+
};
|