create-quorum-router 0.1.5 → 0.1.8

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.
@@ -0,0 +1,150 @@
1
+ import { readRouterEnv } from "./env.ts";
2
+ import type { CostAwareTrace, ModelInventoryEntry } from "./schema.ts";
3
+
4
+ export type CostExclusion = {
5
+ model_id: string;
6
+ estimated_cost_usd?: number;
7
+ reason: "missing_estimate" | "budget_exceeded";
8
+ };
9
+
10
+ export type CostAwareSelection =
11
+ | CostAwareTrace
12
+ | {
13
+ enabled: false;
14
+ selected_model_ids: string[];
15
+ excluded: CostExclusion[];
16
+ };
17
+
18
+ export type CostAwareConfig = {
19
+ maxBudgetUsd: number;
20
+ estimates: Map<string, number>;
21
+ };
22
+
23
+ function normalizedModelId(value: string): string {
24
+ return value.trim().toLowerCase();
25
+ }
26
+
27
+ function parsePositiveBudget(raw: string): number {
28
+ const value = Number(raw);
29
+ if (!Number.isFinite(value) || value <= 0) {
30
+ throw new Error(
31
+ "QuorumRouter blocked: QUORUM_ROUTER_MAX_BUDGET_USD must be a finite number > 0",
32
+ );
33
+ }
34
+ return value;
35
+ }
36
+
37
+ function parseEstimates(raw: string): Map<string, number> {
38
+ let parsed: unknown;
39
+ try {
40
+ parsed = JSON.parse(raw);
41
+ } catch {
42
+ throw new Error(
43
+ "QuorumRouter blocked: QUORUM_ROUTER_ESTIMATED_COSTS_JSON must be valid JSON",
44
+ );
45
+ }
46
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
47
+ throw new Error(
48
+ "QuorumRouter blocked: QUORUM_ROUTER_ESTIMATED_COSTS_JSON must be a model-id to USD object",
49
+ );
50
+ }
51
+
52
+ const estimates = new Map<string, number>();
53
+ for (const [rawModelId, rawCost] of Object.entries(parsed)) {
54
+ const modelId = normalizedModelId(rawModelId);
55
+ if (
56
+ !modelId || typeof rawCost !== "number" || !Number.isFinite(rawCost) ||
57
+ rawCost < 0
58
+ ) {
59
+ throw new Error(
60
+ "QuorumRouter blocked: every cost estimate must use a non-empty model id and a finite USD number >= 0",
61
+ );
62
+ }
63
+ if (estimates.has(modelId)) {
64
+ throw new Error(
65
+ `QuorumRouter blocked: duplicate normalized cost estimate for ${modelId}`,
66
+ );
67
+ }
68
+ estimates.set(modelId, rawCost);
69
+ }
70
+ if (estimates.size === 0) {
71
+ throw new Error(
72
+ "QuorumRouter blocked: QUORUM_ROUTER_ESTIMATED_COSTS_JSON must contain at least one estimate",
73
+ );
74
+ }
75
+ return estimates;
76
+ }
77
+
78
+ export function readCostAwareConfig(): CostAwareConfig | undefined {
79
+ const rawBudget = readRouterEnv("QUORUM_ROUTER_MAX_BUDGET_USD");
80
+ const rawEstimates = readRouterEnv("QUORUM_ROUTER_ESTIMATED_COSTS_JSON");
81
+ if (rawBudget === undefined && rawEstimates === undefined) return undefined;
82
+ if (rawBudget === undefined || rawEstimates === undefined) {
83
+ throw new Error(
84
+ "QuorumRouter blocked: cost-aware routing requires both QUORUM_ROUTER_MAX_BUDGET_USD and QUORUM_ROUTER_ESTIMATED_COSTS_JSON",
85
+ );
86
+ }
87
+ return {
88
+ maxBudgetUsd: parsePositiveBudget(rawBudget),
89
+ estimates: parseEstimates(rawEstimates),
90
+ };
91
+ }
92
+
93
+ export function selectCandidatesWithinBudget(
94
+ candidates: ModelInventoryEntry[],
95
+ config = readCostAwareConfig(),
96
+ ): { candidates: ModelInventoryEntry[]; cost: CostAwareSelection } {
97
+ if (!config) {
98
+ return {
99
+ candidates,
100
+ cost: {
101
+ enabled: false,
102
+ selected_model_ids: candidates.map((candidate) => candidate.model_id),
103
+ excluded: [],
104
+ },
105
+ };
106
+ }
107
+
108
+ const selected: ModelInventoryEntry[] = [];
109
+ const excluded: CostExclusion[] = [];
110
+ let estimatedTotalUsd = 0;
111
+ for (const candidate of candidates) {
112
+ const estimate = config.estimates.get(
113
+ normalizedModelId(candidate.model_id),
114
+ );
115
+ if (estimate === undefined) {
116
+ excluded.push({
117
+ model_id: candidate.model_id,
118
+ reason: "missing_estimate",
119
+ });
120
+ continue;
121
+ }
122
+ if (estimatedTotalUsd + estimate > config.maxBudgetUsd) {
123
+ excluded.push({
124
+ model_id: candidate.model_id,
125
+ estimated_cost_usd: estimate,
126
+ reason: "budget_exceeded",
127
+ });
128
+ continue;
129
+ }
130
+ selected.push(candidate);
131
+ estimatedTotalUsd += estimate;
132
+ }
133
+
134
+ if (selected.length === 0) {
135
+ throw new Error(
136
+ "QuorumRouter blocked: cost-aware routing selected no candidates within the configured budget",
137
+ );
138
+ }
139
+ return {
140
+ candidates: selected,
141
+ cost: {
142
+ enabled: true,
143
+ pricing_source: "configured_estimate_not_live_billing",
144
+ max_budget_usd: config.maxBudgetUsd,
145
+ estimated_total_usd: estimatedTotalUsd,
146
+ selected_model_ids: selected.map((candidate) => candidate.model_id),
147
+ excluded,
148
+ },
149
+ };
150
+ }
@@ -9,6 +9,7 @@ export type ProviderSpec = {
9
9
  source: "wrapper" | "oauth_session" | "local_cli" | "env_fallback";
10
10
  command?: string;
11
11
  args_template?: string[];
12
+ prompt_transport?: "stdin" | "file";
12
13
  list_models_args?: string[];
13
14
  list_blocked_reason?: string;
14
15
  notes: string[];
@@ -145,8 +146,9 @@ export const LOCAL_PROVIDER_SPECS: ProviderSpec[] = [
145
146
  "__CWD__",
146
147
  "--output-last-message",
147
148
  "__OUT__",
148
- "__PROMPT__",
149
+ "-",
149
150
  ],
151
+ prompt_transport: "stdin",
150
152
  list_blocked_reason:
151
153
  "codex models is tty/stdin dependent in this environment; model catalog listing is unavailable from non-interactive Deno.",
152
154
  notes: [
@@ -160,7 +162,8 @@ export const LOCAL_PROVIDER_SPECS: ProviderSpec[] = [
160
162
  auth_mode: "oauth",
161
163
  source: "oauth_session",
162
164
  command: "claude",
163
- args_template: ["-p", "__PROMPT__"],
165
+ args_template: ["-p"],
166
+ prompt_transport: "stdin",
164
167
  list_blocked_reason:
165
168
  "Claude Code model listing is blocked by organization policy / disabled subscription access in this environment.",
166
169
  notes: [
@@ -174,7 +177,8 @@ export const LOCAL_PROVIDER_SPECS: ProviderSpec[] = [
174
177
  auth_mode: "oauth",
175
178
  source: "oauth_session",
176
179
  command: "gemini",
177
- args_template: ["-p", "__PROMPT__"],
180
+ args_template: ["-p", ""],
181
+ prompt_transport: "stdin",
178
182
  list_blocked_reason:
179
183
  "Gemini CLI list/invoke paths require a trusted directory in non-interactive runs unless the user opts into the trust setting.",
180
184
  notes: [
@@ -189,14 +193,15 @@ export const LOCAL_PROVIDER_SPECS: ProviderSpec[] = [
189
193
  source: "oauth_session",
190
194
  command: "grok",
191
195
  args_template: [
192
- "-p",
193
- "__PROMPT__",
196
+ "--prompt-file",
197
+ "__PROMPT_FILE__",
194
198
  "--output-format",
195
199
  "plain",
196
200
  "--permission-mode",
197
201
  "plan",
198
202
  "--disable-web-search",
199
203
  ],
204
+ prompt_transport: "file",
200
205
  list_models_args: ["models"],
201
206
  notes: [
202
207
  "Uses existing Grok CLI session; `grok models` is safe list-only discovery.",
@@ -209,7 +214,8 @@ export const LOCAL_PROVIDER_SPECS: ProviderSpec[] = [
209
214
  auth_mode: "session",
210
215
  source: "local_cli",
211
216
  command: "devin",
212
- args_template: ["-p", "__PROMPT__"],
217
+ args_template: ["-p", "--prompt-file", "__PROMPT_FILE__"],
218
+ prompt_transport: "file",
213
219
  list_blocked_reason:
214
220
  "Devin CLI does not expose a models subcommand in this environment.",
215
221
  notes: ["Uses existing Devin CLI session."],
@@ -221,7 +227,8 @@ export const LOCAL_PROVIDER_SPECS: ProviderSpec[] = [
221
227
  auth_mode: "session",
222
228
  source: "local_cli",
223
229
  command: "qwen",
224
- args_template: ["-p", "__PROMPT__"],
230
+ args_template: ["-p", ""],
231
+ prompt_transport: "stdin",
225
232
  list_blocked_reason:
226
233
  "Qwen CLI model listing path is stdin/API-key dependent in this environment.",
227
234
  notes: ["Uses existing local Qwen CLI session."],
@@ -1,3 +1,75 @@
1
+ import { z } from "zod";
2
+
3
+ export const SupabaseAuditModeSchema = z.enum([
4
+ "disabled",
5
+ "optional",
6
+ "required",
7
+ ]);
8
+
9
+ export type SupabaseAuditMode = z.infer<typeof SupabaseAuditModeSchema>;
10
+
11
+ export const SupabaseFeatureConfigSchema = z.object({
12
+ audit: z.object({
13
+ mode: SupabaseAuditModeSchema,
14
+ }).strict(),
15
+ }).strict();
16
+
17
+ export type SupabaseFeatureConfig = z.infer<
18
+ typeof SupabaseFeatureConfigSchema
19
+ >;
20
+
21
+ export const SelectiveFeatureConfigSchema = z.object({
22
+ supabase: SupabaseFeatureConfigSchema.optional(),
23
+ }).strict();
24
+
25
+ const SECRET_CONFIG_KEY =
26
+ /^(?:quorum_router_)?supabase_(?:url|anon_key|publishable_key|session_jwt|access_token|service_role_key|admin_key)$/i;
27
+
28
+ function normalizedConfigKey(key: string): string {
29
+ return key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/[^a-z0-9]+/gi, "_")
30
+ .toLowerCase();
31
+ }
32
+
33
+ function findSupabaseCredentialPath(
34
+ value: unknown,
35
+ path: Array<string | number> = [],
36
+ ): Array<string | number> | undefined {
37
+ if (Array.isArray(value)) {
38
+ for (let index = 0; index < value.length; index += 1) {
39
+ const found = findSupabaseCredentialPath(value[index], [...path, index]);
40
+ if (found) return found;
41
+ }
42
+ return undefined;
43
+ }
44
+ if (!value || typeof value !== "object") return undefined;
45
+ for (const [key, nested] of Object.entries(value)) {
46
+ const normalized = normalizedConfigKey(key);
47
+ if (
48
+ SECRET_CONFIG_KEY.test(normalized) ||
49
+ (/supabase/.test(normalized) &&
50
+ /(secret|token|key|credential|password|url)/.test(normalized))
51
+ ) {
52
+ return [...path, key];
53
+ }
54
+ const found = findSupabaseCredentialPath(nested, [...path, key]);
55
+ if (found) return found;
56
+ }
57
+ return undefined;
58
+ }
59
+
60
+ export const GeneratedRouterConfigSchema = z.object({
61
+ features: SelectiveFeatureConfigSchema.optional(),
62
+ }).passthrough().superRefine((value, context) => {
63
+ const path = findSupabaseCredentialPath(value);
64
+ if (path) {
65
+ context.addIssue({
66
+ code: z.ZodIssueCode.custom,
67
+ path,
68
+ message: "Supabase runtime credentials belong in the environment only",
69
+ });
70
+ }
71
+ });
72
+
1
73
  export type AuthMode = "auto" | "wrapper" | "oauth" | "session" | "env";
2
74
  export type InventorySource =
3
75
  | "wrapper"
@@ -21,6 +93,7 @@ export type ModelInventoryEntry = {
21
93
  notes: string[];
22
94
  command?: string;
23
95
  args_template?: string[];
96
+ prompt_transport?: "stdin" | "file";
24
97
  invocation_model?: string;
25
98
  };
26
99
 
@@ -82,6 +155,19 @@ export type PromptContextTrace = {
82
155
  context_fetch_error?: string;
83
156
  };
84
157
 
158
+ export type CostAwareTrace = {
159
+ enabled: boolean;
160
+ pricing_source: "configured_estimate_not_live_billing";
161
+ max_budget_usd?: number;
162
+ estimated_total_usd?: number;
163
+ selected_model_ids: string[];
164
+ excluded: Array<{
165
+ model_id: string;
166
+ estimated_cost_usd?: number;
167
+ reason: "missing_estimate" | "budget_exceeded";
168
+ }>;
169
+ };
170
+
85
171
  export type DogfoodTrace = {
86
172
  run_id: string;
87
173
  timestamp: string;
@@ -99,6 +185,7 @@ export type DogfoodTrace = {
99
185
  prompt_hash?: string;
100
186
  prompt_summary?: string;
101
187
  prompt_context?: PromptContextTrace;
188
+ cost_aware?: CostAwareTrace;
102
189
  response_summary?: string;
103
190
  schema_valid: boolean;
104
191
  redaction_ok: boolean;