@runtypelabs/cli 2.59.1 → 2.59.4

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 (84) hide show
  1. package/dist/chunk-0x7UKC1U.js +17 -0
  2. package/dist/chunk-2ySxXtcg.js +418 -0
  3. package/dist/chunk-3An_BRHv.js +501 -0
  4. package/dist/chunk-6uTxgdiY.js +16218 -0
  5. package/dist/chunk-87nRnNRG.js +1363 -0
  6. package/dist/chunk-B3wo8uRx.js +322 -0
  7. package/dist/chunk-BGp3ZdBy.js +560 -0
  8. package/dist/chunk-BJQv9Elp.js +107 -0
  9. package/dist/chunk-BOpO6xE-.js +6053 -0
  10. package/dist/chunk-BQXXCL8B.js +102 -0
  11. package/dist/chunk-BV-8isOd.js +34 -0
  12. package/dist/chunk-BVMhjGVe.js +826 -0
  13. package/dist/chunk-BW2fg46T.js +141 -0
  14. package/dist/chunk-BWJdY5Ag.js +36 -0
  15. package/dist/chunk-BYJOrLhh.js +302 -0
  16. package/dist/chunk-BYab8EVL.js +127 -0
  17. package/dist/chunk-BfEKvp7h.js +82 -0
  18. package/dist/chunk-BhgLSfH6.js +1123 -0
  19. package/dist/chunk-BirUxTtH.js +296 -0
  20. package/dist/chunk-BmB6UVZ9.js +1559 -0
  21. package/dist/chunk-BnWhIqW1.js +109 -0
  22. package/dist/chunk-Bpfnfk0t.js +123 -0
  23. package/dist/chunk-BrhgdnM3.js +108 -0
  24. package/dist/chunk-Bt0XAgX5.js +327 -0
  25. package/dist/chunk-Bu0FJr6S.js +84 -0
  26. package/dist/chunk-BvEoKpN3.js +255 -0
  27. package/dist/chunk-BxNJgYbE.js +28 -0
  28. package/dist/chunk-C1OFhd7F.js +6131 -0
  29. package/dist/chunk-C7e7WwbU.js +331 -0
  30. package/dist/chunk-CDTYP6bN.js +558 -0
  31. package/dist/chunk-CGDQoqDC.js +24 -0
  32. package/dist/chunk-CJraEBVd.js +127 -0
  33. package/dist/chunk-CQrNhOtv.js +40 -0
  34. package/dist/chunk-CW6AzBH6.js +128 -0
  35. package/dist/chunk-CXgL4w-9.js +317 -0
  36. package/dist/chunk-CZrqoPyf.js +233 -0
  37. package/dist/chunk-CcFCyqbB.js +83 -0
  38. package/dist/chunk-CdaIvO-y.js +485 -0
  39. package/dist/chunk-CehSXtgK.js +624 -0
  40. package/dist/chunk-Ciqkop65.js +218 -0
  41. package/dist/chunk-CoAWdSiE.js +43 -0
  42. package/dist/chunk-Crb4y7t4.js +830 -0
  43. package/dist/chunk-CrlqIfmb.js +337 -0
  44. package/dist/chunk-Cs4pwCQ-.js +324 -0
  45. package/dist/chunk-CwM_9y01.js +519 -0
  46. package/dist/chunk-CyRbIJg8.js +440 -0
  47. package/dist/chunk-D0OHsyMy.js +212 -0
  48. package/dist/chunk-D3y2bURs.js +1347 -0
  49. package/dist/chunk-D4_mJk03.js +2338 -0
  50. package/dist/chunk-D6C8rned.js +578 -0
  51. package/dist/chunk-D9ZbUnks.js +11 -0
  52. package/dist/chunk-DEPmLshX.js +834 -0
  53. package/dist/chunk-DFj1UPB2.js +330 -0
  54. package/dist/chunk-DGdFdZVf.js +197 -0
  55. package/dist/chunk-DGv7X9S_.js +63 -0
  56. package/dist/chunk-DJQ47WYZ.js +664 -0
  57. package/dist/chunk-DJw3O61j.js +1974 -0
  58. package/dist/chunk-DK4FbWVK.js +100 -0
  59. package/dist/chunk-DPuofXMp.js +3907 -0
  60. package/dist/chunk-DSRYhUus.js +993 -0
  61. package/dist/chunk-DajZ9Eg4.js +299 -0
  62. package/dist/chunk-Df4dunvU.js +195 -0
  63. package/dist/chunk-DjNTPhfO.js +481 -0
  64. package/dist/chunk-Dn8eaJuu.js +1042 -0
  65. package/dist/chunk-DwDWqSxM.js +637 -0
  66. package/dist/chunk-Dz7cEtxl.js +84 -0
  67. package/dist/chunk-E_0bgjrS.js +359 -0
  68. package/dist/chunk-KPYN2vUp.js +776 -0
  69. package/dist/chunk-KcqPQJBi.js +86 -0
  70. package/dist/chunk-N9H0JnoG.js +349 -0
  71. package/dist/chunk-NONFcXkn.js +728 -0
  72. package/dist/chunk-PrFjcpmH.js +256 -0
  73. package/dist/chunk-QSfNYiw9.js +11 -0
  74. package/dist/chunk-R265bzj9.js +226 -0
  75. package/dist/chunk-X9V_r6jM.js +166 -0
  76. package/dist/chunk-ZBtPUtyA.js +55 -0
  77. package/dist/chunk-ZCTfmOs7.js +4939 -0
  78. package/dist/chunk-h6oavj0t.js +97 -0
  79. package/dist/chunk-i7DwkvvD.js +42 -0
  80. package/dist/chunk-mG-4eZ6S.js +203 -0
  81. package/dist/chunk-o0ygUbCf.js +313 -0
  82. package/dist/chunk-ucu5lrDZ.js +5715 -0
  83. package/dist/index.js +11367 -73789
  84. package/package.json +5 -5
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env node
2
+ import { b as CredentialStore, c as loadEffectiveContext } from "./index.js";
3
+ import { o as getClerkPublishableKey, s as getDashboardUrl, t as ApiKeyManager } from "./chunk-BW2fg46T.js";
4
+ import open from "open";
5
+ import crypto from "crypto";
6
+ // src/auth/oauth-manager.ts
7
+ var OAuthManager = class {
8
+ clerkPublishableKey;
9
+ dashboardUrl;
10
+ constructor(config) {
11
+ this.clerkPublishableKey = config.clerkPublishableKey;
12
+ this.dashboardUrl = config.dashboardUrl;
13
+ }
14
+ /** `orgId` preselects that organization on the dashboard's account picker; the user can still choose another. */
15
+ async authenticate(mode, options = {}) {
16
+ const state = crypto.randomBytes(32).toString("base64url");
17
+ const codeVerifier = crypto.randomBytes(32).toString("base64url");
18
+ const codeChallenge = crypto.createHash("sha256").update(codeVerifier).digest("base64url");
19
+ const { CallbackServer } = await import("./chunk-C7e7WwbU.js");
20
+ const callbackServer = new CallbackServer();
21
+ callbackServer.setExpectedState(state);
22
+ const requestedPort = await this.findAvailablePort();
23
+ const { actualPort, codePromise } = await callbackServer.start(requestedPort);
24
+ const redirectUri = `http://127.0.0.1:${actualPort}/callback`;
25
+ const authUrl = new URL(`${this.dashboardUrl.replace(/\/$/, "")}/${mode}`);
26
+ authUrl.searchParams.set("redirect_uri", redirectUri);
27
+ authUrl.searchParams.set("cli", "true");
28
+ authUrl.searchParams.set("state", state);
29
+ authUrl.searchParams.set("code_challenge", codeChallenge);
30
+ authUrl.searchParams.set("code_challenge_method", "S256");
31
+ authUrl.searchParams.set("publishable_key", this.clerkPublishableKey);
32
+ if (options.orgId) authUrl.searchParams.set("org", options.orgId);
33
+ console.log("🌐 Opening browser for authentication...");
34
+ console.log(`If the browser doesn't open, visit: ${authUrl}`);
35
+ try {
36
+ console.log("⏳ Waiting for authentication...");
37
+ const [code] = await Promise.all([codePromise, open(authUrl.toString()).catch(() => {
38
+ console.log("Failed to open browser automatically. Please visit the URL above.");
39
+ })]);
40
+ return await this.exchangeCodeForSession(code, codeVerifier, redirectUri);
41
+ } finally {
42
+ callbackServer.stop();
43
+ }
44
+ }
45
+ async findAvailablePort() {
46
+ return 8765;
47
+ }
48
+ async exchangeCodeForSession(code, codeVerifier, redirectUri) {
49
+ return code;
50
+ }
51
+ };
52
+ // src/auth/login-flow.ts
53
+ var InvalidApiKeyError = class extends Error {
54
+ constructor() {
55
+ super("Invalid API key");
56
+ this.name = "InvalidApiKeyError";
57
+ }
58
+ };
59
+ async function storeLogin(credentials) {
60
+ const context = await loadEffectiveContext(credentials.apiUrl);
61
+ const store = new CredentialStore();
62
+ const account = await store.saveCredentials(credentials);
63
+ const isDefault = (await store.getDefaultAccount())?.id === account.id;
64
+ return {
65
+ ...credentials,
66
+ account,
67
+ isDefault,
68
+ ...context.requestedOrgId ? { requestedOrgId: context.requestedOrgId } : {}
69
+ };
70
+ }
71
+ /** Browser (Clerk) login: mint an org-owned CLI key for the organization the user authorizes. */
72
+ async function browserLogin(options = {}) {
73
+ const context = await loadEffectiveContext(options.apiUrl);
74
+ const oauth = new OAuthManager({
75
+ clerkPublishableKey: getClerkPublishableKey(),
76
+ dashboardUrl: options.dashboardUrl || getDashboardUrl()
77
+ });
78
+ options.onProgress?.("Waiting for browser authentication...");
79
+ const sessionToken = await oauth.authenticate("sign-in", { orgId: context.requestedOrgId });
80
+ options.onProgress?.("Creating API key...");
81
+ const { key, userId, orgId } = await new ApiKeyManager().exchangeSessionForApiKey(sessionToken, context.apiUrl);
82
+ options.onProgress?.("Storing credentials securely...");
83
+ return storeLogin({
84
+ apiKey: key,
85
+ userId,
86
+ orgId,
87
+ apiUrl: context.apiUrl
88
+ });
89
+ }
90
+ /** Store an existing API key as a login for whichever organization owns it. */
91
+ async function apiKeyLogin(apiKey, options = {}) {
92
+ const context = await loadEffectiveContext(options.apiUrl);
93
+ const manager = new ApiKeyManager();
94
+ if (!await manager.validateApiKey(apiKey, context.apiUrl)) throw new InvalidApiKeyError();
95
+ const user = await manager.getCurrentUser(apiKey, context.apiUrl);
96
+ return storeLogin({
97
+ apiKey,
98
+ userId: user.userId,
99
+ orgId: user.orgId ?? void 0,
100
+ apiUrl: context.apiUrl
101
+ });
102
+ }
103
+ /** Non-null when the user authorized a different organization than the one this directory targets. */
104
+ function orgMismatchWarning(login) {
105
+ if (!login.requestedOrgId || login.requestedOrgId === login.orgId) return null;
106
+ return `Logged in to ${login.orgId ?? "a personal account"}, but this invocation targets ${login.requestedOrgId}. Commands here will keep asking for a login to ${login.requestedOrgId}; run "runtype login" again and pick that organization, or update the link with "runtype link ${login.orgId ?? ""}".`;
107
+ }
108
+ export { browserLogin as n, orgMismatchWarning as r, apiKeyLogin as t };
109
+
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env node
2
+ import "./chunk-QSfNYiw9.js";
3
+ // ../shared/dist/chunk-BIfgel88.mjs
4
+ const DEFAULT_GENERIC_OPENAI_API_FORMAT = "chat-completions";
5
+ /** Provider defaults shared by every execution engine and deploy guidance. */
6
+ const DEFAULT_BEDROCK_REGION = "us-east-1";
7
+ const DEFAULT_VERTEX_LOCATION = "us-central1";
8
+ /**
9
+ * Ordered array of provider specs. First-match-wins on `matches` predicate.
10
+ * Explicit-prefix providers (vertex-*, vercel/*, cloudflare/*, etc.) come before
11
+ * base providers (anthropic, openai, google, …) for the same reason PROVIDER_REGISTRY
12
+ * in prompt-executor.ts declares them first.
13
+ */
14
+ const PROVIDER_SECRET_SPECS = [
15
+ {
16
+ providerId: "mock",
17
+ matches: (m) => m.startsWith("mock/"),
18
+ secretNames: []
19
+ },
20
+ {
21
+ providerId: "google-vertex-anthropic",
22
+ matches: (m) => m.startsWith("vertex-anthropic/"),
23
+ secretNames: ["GOOGLE_VERTEX_PROJECT", "GOOGLE_VERTEX_CREDENTIALS"],
24
+ optionalSettings: [{
25
+ name: "GOOGLE_VERTEX_LOCATION",
26
+ defaultValue: DEFAULT_VERTEX_LOCATION
27
+ }]
28
+ },
29
+ {
30
+ providerId: "google-vertex",
31
+ matches: (m) => m.startsWith("vertex/"),
32
+ secretNames: ["GOOGLE_VERTEX_PROJECT", "GOOGLE_VERTEX_CREDENTIALS"],
33
+ optionalSettings: [{
34
+ name: "GOOGLE_VERTEX_LOCATION",
35
+ defaultValue: DEFAULT_VERTEX_LOCATION
36
+ }]
37
+ },
38
+ {
39
+ providerId: "vercel-gateway",
40
+ matches: (m) => m.startsWith("vercel/") || m.startsWith("vercel."),
41
+ secretNames: ["VERCEL_AI_GATEWAY_API_KEY"]
42
+ },
43
+ {
44
+ providerId: "cloudflare-gateway",
45
+ matches: (m) => m.startsWith("cloudflare/") || m.startsWith("cloudflare:"),
46
+ secretNames: ["CF_ACCOUNT_ID", "CF_AI_GATEWAY_ID"]
47
+ },
48
+ {
49
+ providerId: "bedrock",
50
+ matches: (m) => m.startsWith("bedrock/"),
51
+ secretNames: ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"],
52
+ optionalSettings: [{
53
+ name: "AWS_REGION",
54
+ defaultValue: DEFAULT_BEDROCK_REGION
55
+ }]
56
+ },
57
+ {
58
+ providerId: "tinfoil",
59
+ matches: (m) => m.startsWith("tinfoil/") || m.startsWith("tinfoil:"),
60
+ secretNames: ["TINFOIL_API_KEY"]
61
+ },
62
+ {
63
+ providerId: "generic-openai",
64
+ matches: (m) => m.startsWith("generic-openai/") || m.startsWith("generic-openai:"),
65
+ secretNames: ["GENERIC_OPENAI_API_KEY", "GENERIC_OPENAI_BASE_URL"],
66
+ optionalSettings: [{
67
+ name: "GENERIC_OPENAI_API_FORMAT",
68
+ defaultValue: DEFAULT_GENERIC_OPENAI_API_FORMAT
69
+ }]
70
+ },
71
+ {
72
+ providerId: "workers-ai",
73
+ matches: (m) => m.startsWith("@cf/") || m.startsWith("workers-ai/"),
74
+ secretNames: []
75
+ },
76
+ {
77
+ providerId: "anthropic",
78
+ matches: (m) => m.startsWith("anthropic/") || m.startsWith("claude-") || m.includes("/claude-"),
79
+ secretNames: ["ANTHROPIC_API_KEY"]
80
+ },
81
+ {
82
+ providerId: "openai",
83
+ matches: (m) => m.startsWith("openai/") || m.startsWith("gpt-") || m.startsWith("o1-") || m.startsWith("o3-") || m.startsWith("o4-") || m.includes("/gpt-"),
84
+ secretNames: ["OPENAI_API_KEY"]
85
+ },
86
+ {
87
+ providerId: "google",
88
+ matches: (m) => m.startsWith("google/") || m.startsWith("gemini-") || m.includes("/gemini-"),
89
+ secretNames: ["GOOGLE_API_KEY"]
90
+ },
91
+ {
92
+ providerId: "mixlayer",
93
+ matches: (m) => m.startsWith("mixlayer/") || m.startsWith("modelsocket/") || m.startsWith("qwen/") || m.startsWith("z-ai/") || m.startsWith("kimi-") || m.includes("/kimi-") || /(?:^|\/)qwen3[.-]5-\d+b(?:-a\d+b)?$/i.test(m),
94
+ secretNames: ["MIXLAYER_API_KEY"]
95
+ },
96
+ {
97
+ providerId: "xai",
98
+ matches: (m) => m.startsWith("grok-") || m.startsWith("xai/"),
99
+ secretNames: ["XAI_API_KEY"]
100
+ }
101
+ ];
102
+ /**
103
+ * Returns the required secret names for the given model id using first-match-wins order.
104
+ * Returns an empty array for models that use platform bindings (Workers AI) or for
105
+ * unrecognized model strings.
106
+ */
107
+ function resolveModelSecretNames(model) {
108
+ const lower = model.toLowerCase();
109
+ for (const spec of PROVIDER_SECRET_SPECS) if (spec.matches(lower)) return [...spec.secretNames];
110
+ return [];
111
+ }
112
+ /**
113
+ * Returns optional deployment settings for the model's provider. These are
114
+ * guidance only: runtime key validation must continue to use
115
+ * `resolveModelSecretNames`, which contains required credentials exclusively.
116
+ */
117
+ function resolveModelOptionalSettings(model) {
118
+ const lower = model.toLowerCase();
119
+ for (const spec of PROVIDER_SECRET_SPECS) if (spec.matches(lower)) return [...spec.optionalSettings ?? []];
120
+ return [];
121
+ }
122
+ export { resolveModelSecretNames as n, resolveModelOptionalSettings as t };
123
+
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ import chalk from "chalk";
3
+ import readline from "readline";
4
+ // src/lib/select-prompt.ts
5
+ function canUseArrowKeySelect() {
6
+ return process.stdin.isTTY === true && process.stdout.isTTY === true && typeof process.stdin.setRawMode === "function";
7
+ }
8
+ function clearRenderedLines(output, lineCount) {
9
+ for (let index = 0; index < lineCount; index += 1) {
10
+ readline.clearLine(output, 0);
11
+ readline.cursorTo(output, 0);
12
+ if (index < lineCount - 1) readline.moveCursor(output, 0, -1);
13
+ }
14
+ }
15
+ function formatChoice(choice, index, selectedIndex) {
16
+ return ` ${index === selectedIndex ? chalk.cyan("›") : " "} ${index === selectedIndex ? chalk.cyan(`${index + 1})`) : chalk.gray(`${index + 1})`)} ${index === selectedIndex ? chalk.bold(choice.label) : choice.label}${choice.description ? chalk.gray(` - ${choice.description}`) : ""}`;
17
+ }
18
+ async function promptNumericSelect(choices, promptLabel) {
19
+ choices.forEach((choice, index) => {
20
+ const description = choice.description ? chalk.gray(` - ${choice.description}`) : "";
21
+ console.log(` ${chalk.green(`${index + 1})`)} ${choice.label}${description}`);
22
+ });
23
+ const rl = readline.createInterface({
24
+ input: process.stdin,
25
+ output: process.stdout,
26
+ terminal: true
27
+ });
28
+ return new Promise((resolve) => {
29
+ const ask = () => {
30
+ rl.question(chalk.cyan(`\n${promptLabel} (1-${choices.length}): `), (answer) => {
31
+ const value = parseInt(answer.trim(), 10);
32
+ if (value >= 1 && value <= choices.length) {
33
+ rl.close();
34
+ resolve(choices[value - 1].value);
35
+ return;
36
+ }
37
+ console.log(chalk.red(`Please enter a number between 1 and ${choices.length}.`));
38
+ ask();
39
+ });
40
+ };
41
+ ask();
42
+ });
43
+ }
44
+ async function promptSelect(message, choices, options) {
45
+ if (message) console.log(chalk.cyan(`\n${message}`));
46
+ if (!canUseArrowKeySelect()) return promptNumericSelect(choices, options?.promptLabel ?? "Select");
47
+ const input = process.stdin;
48
+ const output = process.stdout;
49
+ const promptLabel = options?.promptLabel ?? "Select";
50
+ const shortcutRange = choices.length === 1 ? "1" : `1-${choices.length}`;
51
+ const instructions = chalk.gray(`Use ${chalk.cyan("↑/↓")} to move, ${chalk.cyan("Enter")} to select, or press ${shortcutRange}.`);
52
+ const previousRawMode = input.isRaw === true;
53
+ let selectedIndex = 0;
54
+ let renderedLineCount = 0;
55
+ return new Promise((resolve) => {
56
+ const renderMenu = () => {
57
+ if (renderedLineCount > 0) clearRenderedLines(output, renderedLineCount);
58
+ const lines = [
59
+ ...choices.map((choice, index) => formatChoice(choice, index, selectedIndex)),
60
+ "",
61
+ `${promptLabel}: ${instructions}`
62
+ ];
63
+ output.write(`${lines.join("\n")}`);
64
+ renderedLineCount = lines.length;
65
+ };
66
+ const cleanup = () => {
67
+ input.off("keypress", onKeypress);
68
+ if (typeof input.setRawMode === "function") input.setRawMode(previousRawMode);
69
+ output.write("\n");
70
+ };
71
+ const finish = (value) => {
72
+ cleanup();
73
+ resolve(value);
74
+ };
75
+ const onKeypress = (_, key) => {
76
+ if (key.ctrl && key.name === "c") {
77
+ cleanup();
78
+ process.kill(process.pid, "SIGINT");
79
+ return;
80
+ }
81
+ if (key.name === "up" || key.name === "k") {
82
+ selectedIndex = (selectedIndex - 1 + choices.length) % choices.length;
83
+ renderMenu();
84
+ return;
85
+ }
86
+ if (key.name === "down" || key.name === "j") {
87
+ selectedIndex = (selectedIndex + 1) % choices.length;
88
+ renderMenu();
89
+ return;
90
+ }
91
+ if (key.name === "return" || key.name === "enter") {
92
+ finish(choices[selectedIndex].value);
93
+ return;
94
+ }
95
+ if (/^[1-9]$/.test(key.sequence ?? "")) {
96
+ const numericIndex = Number(key.sequence) - 1;
97
+ if (numericIndex >= 0 && numericIndex < choices.length) finish(choices[numericIndex].value);
98
+ }
99
+ };
100
+ readline.emitKeypressEvents(input);
101
+ input.on("keypress", onKeypress);
102
+ input.resume();
103
+ input.setRawMode?.(true);
104
+ renderMenu();
105
+ });
106
+ }
107
+ export { promptSelect as t };
108
+
@@ -0,0 +1,327 @@
1
+ #!/usr/bin/env node
2
+ import { C as unknown, S as union, a as _null, b as string, c as boolean, f as literal, h as object, i as _enum, m as number, o as any, s as array, u as discriminatedUnion, v as record, y as strictObject } from "./chunk-BOpO6xE-.js";
3
+ // ../shared/dist/chunk-DH-C5yxa.mjs
4
+ /** The person a turn runs as: exposed to tools as `_endUser.*`, shards memory, and satisfies `end-user-isolated`. */
5
+ const hostEndUserIdentitySchema = object({
6
+ id: string().min(1),
7
+ email: string().optional()
8
+ }).passthrough().describe("The end user (the person) the turn runs as. Exposed to tools as _endUser.*, drives memory-profile sharding, and satisfies an end-user-isolated tenancyStrategy. Distinct from _user (the Builder User).");
9
+ /** The product tenant (under the Builder Org) the turn runs within, exposed as `_tenant.*`. */
10
+ const hostTenantIdentitySchema = object({ id: string().min(1) }).passthrough().describe("The product tenant (a customer of your product, under your Builder Org) the turn runs within. Exposed to tools as _tenant.*.");
11
+ /** Suite-level default identity an eval case inherits when it does not carry its own. */
12
+ const evalIdentityDefaultsSchema = object({
13
+ endUser: hostEndUserIdentitySchema.optional(),
14
+ tenant: hostTenantIdentitySchema.optional()
15
+ }).strict().describe("Default identity every case in the suite runs as unless the case sets its own endUser/tenant. No credentials or identity proofs: the identity is asserted by the suite author.");
16
+ const tokenCountSchema = number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
17
+ const judgeParseErrorSchema = _enum([
18
+ "empty_completion",
19
+ "invalid_json",
20
+ "invalid_contract",
21
+ "missing_access_assessment",
22
+ "invalid_access_assessment",
23
+ "output_truncated"
24
+ ]);
25
+ const judgeFinishReasonSchema = _enum([
26
+ "stop",
27
+ "length",
28
+ "content-filter",
29
+ "tool-calls",
30
+ "error",
31
+ "other",
32
+ "unknown"
33
+ ]);
34
+ /** Bounded metadata only: never persist judge prompts, response text, or provider error messages here. */
35
+ const judgeAttemptDiagnosticSchema = strictObject({
36
+ attempt: union([literal(1), literal(2)]),
37
+ requestedModel: string().max(160),
38
+ resolvedModel: string().max(160).optional(),
39
+ provider: string().max(64).optional(),
40
+ durationMs: tokenCountSchema,
41
+ status: _enum([
42
+ "valid",
43
+ "invalid_response",
44
+ "model_error"
45
+ ]),
46
+ parseError: judgeParseErrorSchema.optional(),
47
+ modelError: _enum(["empty_completion", "model_call_error"]).optional(),
48
+ finishReason: judgeFinishReasonSchema.optional(),
49
+ responseChars: tokenCountSchema.optional(),
50
+ usageObserved: boolean(),
51
+ promptTokens: tokenCountSchema.optional(),
52
+ completionTokens: tokenCountSchema.optional(),
53
+ reasoningTokens: tokenCountSchema.optional(),
54
+ cacheReadTokens: tokenCountSchema.optional(),
55
+ cacheWriteTokens: tokenCountSchema.optional()
56
+ });
57
+ const judgeDiagnosticsSchema = strictObject({
58
+ attempts: array(judgeAttemptDiagnosticSchema).max(2),
59
+ flowFailure: _enum([
60
+ "deadline_exhausted",
61
+ "execution_failed",
62
+ "invalid_response"
63
+ ]).optional()
64
+ }).refine((diagnostics) => diagnostics.attempts.length > 0 || diagnostics.flowFailure !== void 0, { message: "Judge diagnostics require an attempt or an explicit custom flow failure." });
65
+ const BUILT_IN_GRADER_IDS = [
66
+ "answersQuestion",
67
+ "matchesExpected",
68
+ "followsInstructions",
69
+ "grounded",
70
+ "rightTone",
71
+ "safeToSend",
72
+ "staysOnTask",
73
+ "sameLanguage",
74
+ "refusesWhenItShould",
75
+ "noPersonalData"
76
+ ];
77
+ /**
78
+ * Per-grader severity. A `gate` miss always fails the case; a `soft` miss is
79
+ * tracked-but-not-failing unless the run is `--strict`. Absent ⇒ `gate` (the
80
+ * historical, every-grader-is-a-hard-gate behavior). Severity rides on EVERY
81
+ * grader — check and AI alike — so it is spread into each member below.
82
+ */
83
+ const graderSeveritySchema = _enum(["gate", "soft"]);
84
+ /**
85
+ * Shared severity field, spread into each grader member to preserve kind-based discriminated union narrowing.
86
+ * An intersection at the union level would lose that narrowing.
87
+ * Optional and absent-by-default keeps the wire shape/content-hash unchanged for un-annotated graders.
88
+ */
89
+ const severityFields = { severity: graderSeveritySchema.optional() };
90
+ const checkGraderSchema = discriminatedUnion("kind", [
91
+ object({
92
+ kind: literal("contains"),
93
+ value: string(),
94
+ caseSensitive: boolean().optional(),
95
+ ...severityFields
96
+ }),
97
+ object({
98
+ kind: literal("not_contains"),
99
+ value: string(),
100
+ caseSensitive: boolean().optional(),
101
+ ...severityFields
102
+ }),
103
+ object({
104
+ kind: literal("matches_expected"),
105
+ ...severityFields
106
+ }),
107
+ object({
108
+ kind: literal("regex"),
109
+ pattern: string(),
110
+ flags: string().optional(),
111
+ ...severityFields
112
+ }),
113
+ object({
114
+ kind: literal("valid_json"),
115
+ ...severityFields
116
+ }),
117
+ object({
118
+ kind: literal("json_field"),
119
+ path: string(),
120
+ equals: unknown().optional(),
121
+ exists: boolean().optional(),
122
+ ...severityFields
123
+ }),
124
+ object({
125
+ kind: literal("length"),
126
+ minChars: number().int().nonnegative().optional(),
127
+ maxChars: number().int().nonnegative().optional(),
128
+ ...severityFields
129
+ }),
130
+ object({
131
+ kind: literal("latency"),
132
+ maxMs: number().int().positive(),
133
+ ...severityFields
134
+ }),
135
+ object({
136
+ kind: literal("no_error"),
137
+ ...severityFields
138
+ }),
139
+ object({
140
+ kind: literal("called_tool"),
141
+ name: string().min(1),
142
+ input: unknown().optional(),
143
+ output: unknown().optional(),
144
+ isError: boolean().optional(),
145
+ times: number().int().positive().optional(),
146
+ ...severityFields
147
+ }),
148
+ object({
149
+ kind: literal("not_called_tool"),
150
+ name: string().min(1),
151
+ ...severityFields
152
+ }),
153
+ object({
154
+ kind: literal("used_no_tools"),
155
+ ...severityFields
156
+ }),
157
+ object({
158
+ kind: literal("max_tool_calls"),
159
+ max: number().int().nonnegative(),
160
+ ...severityFields
161
+ }),
162
+ object({
163
+ kind: literal("tool_order"),
164
+ tools: array(string()).min(1),
165
+ ...severityFields
166
+ }),
167
+ object({
168
+ kind: literal("ran_step"),
169
+ name: string().min(1),
170
+ ...severityFields
171
+ }),
172
+ object({
173
+ kind: literal("step_order"),
174
+ steps: array(string()).min(1),
175
+ ...severityFields
176
+ }),
177
+ object({
178
+ kind: literal("completed"),
179
+ ...severityFields
180
+ }),
181
+ object({
182
+ kind: literal("cost"),
183
+ maxUsd: number().positive(),
184
+ ...severityFields
185
+ })
186
+ ]);
187
+ const aiGraderSchema = object({
188
+ kind: literal("ai"),
189
+ preset: _enum(BUILT_IN_GRADER_IDS).optional(),
190
+ /** Plain language: "what does a good answer look like?" */
191
+ criteria: string().min(1),
192
+ /** Reference-guided when the case has `expected`. */
193
+ useExpected: boolean().default(false),
194
+ /** Defaults to the Runtype Eval Judge flow's model pair (`EVAL_JUDGE_MODEL` with a cross-provider fallback) at execution time. Ignored when `judgeFlowId` is set (the flow's own steps pin their models). */
195
+ model: string().optional(),
196
+ /**
197
+ * Custom judge flow: the escape hatch when the platform judge prompt isn't enough.
198
+ * The referenced flow runs through the normal pipeline, receiving the four EvalJudgeVariables as inputs.
199
+ * Its output must match the same verdict JSON contract the platform judge returns.
200
+ * A missing/failed/malformed judge resolves to insufficient_evidence with a visible error; it never decides cases.
201
+ */
202
+ judgeFlowId: string().min(1).optional(),
203
+ /** Pass cutoff for the 1-5 scale. */
204
+ threshold: number().min(1).max(5).optional(),
205
+ /**
206
+ * The platform judge-prompt version that produced this grader's most recent outcome.
207
+ * Stamped by grader-executor.ts at grade time; not settable by callers.
208
+ * Any caller-supplied value is overwritten before scoring, or stripped for judgeFlowId graders.
209
+ */
210
+ judgePromptVersion: number().int().positive().optional(),
211
+ ...severityFields
212
+ });
213
+ const judgeVerdictSchema = _enum([
214
+ "pass",
215
+ "fail",
216
+ "insufficient_evidence"
217
+ ]);
218
+ _enum(["agree", "disagree"]);
219
+ const judgeEvidenceSchema = object({
220
+ kind: _enum(["message", "tool_call"]),
221
+ /**
222
+ * Position in the transcript the judge was shown: an index into
223
+ * `GradingTrace.steps` for `kind: 'message'`, or `GradingTrace.toolCalls`
224
+ * for `kind: 'tool_call'` — the same ordering the transcript renderer
225
+ * numbered when building the judge prompt.
226
+ */
227
+ index: number().int().nonnegative()
228
+ });
229
+ const graderConfigSchema = union([checkGraderSchema, aiGraderSchema]);
230
+ /** The executed grader snapshot carries server metadata that authored grader config deliberately omits. */
231
+ const evalGraderSnapshotSchema = graderConfigSchema.and(object({ judgeDiagnostics: judgeDiagnosticsSchema.optional() }));
232
+ array(graderConfigSchema);
233
+ const caseExpectedSchema = object({
234
+ text: string().optional(),
235
+ json: unknown().optional(),
236
+ facts: array(string()).optional()
237
+ });
238
+ _enum([
239
+ "manual",
240
+ "saved_from_run",
241
+ "generated",
242
+ "imported",
243
+ "fpo",
244
+ "ensure"
245
+ ]);
246
+ /**
247
+ * Where a saved_from_run case was forked from.
248
+ * Exactly one of sourceExecutionId / sourceConversationId identifies the origin trace.
249
+ * forkMessageIndex is the count of frozen history messages kept before the graded next step.
250
+ * The fork slices history at [0, forkMessageIndex).
251
+ */
252
+ const caseCheckpointSchema = object({
253
+ /** Execution id the case was captured from (`from-execution`). */
254
+ sourceExecutionId: string().optional(),
255
+ /** Conversation id the case was captured from (`from-conversation`). */
256
+ sourceConversationId: string().optional(),
257
+ /**
258
+ * Number of leading history messages kept before the fork point — the
259
+ * length of the frozen `input.messages` prefix the target is seeded with.
260
+ */
261
+ forkMessageIndex: number().int().nonnegative()
262
+ }).strict();
263
+ /**
264
+ * A REQUIRED 'any JSON value' field, unlike a bare z.unknown()/z.any().
265
+ * Zod's isOptional() returns true for unknown()/any(), which silently made this field optional in the OpenAPI spec/SDKs.
266
+ * A union of concrete JSON-value types has isOptional() = false, so the field correctly lands in 'required'.
267
+ * Also TS-compatible: z.custom() would throw UnknownZodTypeError in this repo's OpenAPI generator.
268
+ */
269
+ const requiredJsonValueSchema = union([
270
+ _null(),
271
+ boolean(),
272
+ number(),
273
+ string(),
274
+ array(any()),
275
+ record(string(), any())
276
+ ]);
277
+ /**
278
+ * One recorded tool result captured from a run, matched to a replayed call by toolName.
279
+ * output is the finalized tool result (scrubbed + possibly truncated at capture).
280
+ * sourceToolExecutionId is the tool_executions row it came from, for audit.
281
+ * Editing output turns any recorded case into a counterfactual for free.
282
+ */
283
+ const toolMockSchema = object({
284
+ toolName: string().min(1),
285
+ input: unknown().optional(),
286
+ output: requiredJsonValueSchema,
287
+ /**
288
+ * True when the recorded call FAILED — `output` is then the error payload,
289
+ * and a replay must serve it as a failure, not a success. Captured now so
290
+ * the bit survives even after the source `tool_executions` rows age out.
291
+ */
292
+ isError: boolean().optional(),
293
+ /** The `tool_executions.id` this mock was captured from, when persisted. */
294
+ sourceToolExecutionId: string().optional(),
295
+ /** True when `output` was capped at `MAX_TOOL_MOCK_OUTPUT_CHARS` on capture. */
296
+ truncated: boolean().optional()
297
+ }).strict();
298
+ _enum([
299
+ "definition",
300
+ "trace",
301
+ "feedback",
302
+ "coverage_gap"
303
+ ]);
304
+ _enum([
305
+ "proposed",
306
+ "accepted",
307
+ "edited_accepted",
308
+ "rejected"
309
+ ]);
310
+ object({
311
+ name: string().min(1),
312
+ input: object({
313
+ variables: record(string(), unknown()).optional(),
314
+ messages: array(object({
315
+ role: string().min(1),
316
+ content: string()
317
+ }).passthrough()).optional(),
318
+ checkpoint: caseCheckpointSchema.optional(),
319
+ toolMocks: array(toolMockSchema).optional(),
320
+ endUser: hostEndUserIdentitySchema.optional(),
321
+ tenant: hostTenantIdentitySchema.optional()
322
+ }).strict(),
323
+ expected: caseExpectedSchema.optional(),
324
+ notes: string().optional()
325
+ }).strict();
326
+ export { graderConfigSchema as a, hostTenantIdentitySchema as c, toolMockSchema as d, evalIdentityDefaultsSchema as i, judgeEvidenceSchema as l, caseExpectedSchema as n, graderSeveritySchema as o, evalGraderSnapshotSchema as r, hostEndUserIdentitySchema as s, caseCheckpointSchema as t, judgeVerdictSchema as u };
327
+