@runtypelabs/cli 2.59.0 → 2.59.2

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-0-T9NWjH.js +3899 -0
  2. package/dist/chunk-0x7UKC1U.js +17 -0
  3. package/dist/chunk-2ySxXtcg.js +418 -0
  4. package/dist/chunk-3An_BRHv.js +501 -0
  5. package/dist/chunk-6uTxgdiY.js +16218 -0
  6. package/dist/chunk-87nRnNRG.js +1363 -0
  7. package/dist/chunk-B3wo8uRx.js +322 -0
  8. package/dist/chunk-BGp3ZdBy.js +560 -0
  9. package/dist/chunk-BJQv9Elp.js +107 -0
  10. package/dist/chunk-BOpO6xE-.js +6053 -0
  11. package/dist/chunk-BQXXCL8B.js +102 -0
  12. package/dist/chunk-BV-8isOd.js +34 -0
  13. package/dist/chunk-BVMhjGVe.js +826 -0
  14. package/dist/chunk-BW2fg46T.js +141 -0
  15. package/dist/chunk-BWJdY5Ag.js +36 -0
  16. package/dist/chunk-BYJOrLhh.js +302 -0
  17. package/dist/chunk-BYab8EVL.js +127 -0
  18. package/dist/chunk-BfEKvp7h.js +82 -0
  19. package/dist/chunk-BhgLSfH6.js +1123 -0
  20. package/dist/chunk-BirUxTtH.js +296 -0
  21. package/dist/chunk-BmB6UVZ9.js +1559 -0
  22. package/dist/chunk-BnWhIqW1.js +109 -0
  23. package/dist/chunk-Bpfnfk0t.js +123 -0
  24. package/dist/chunk-BrhgdnM3.js +108 -0
  25. package/dist/chunk-Bt0XAgX5.js +327 -0
  26. package/dist/chunk-Bu0FJr6S.js +84 -0
  27. package/dist/chunk-BvEoKpN3.js +255 -0
  28. package/dist/chunk-BxNJgYbE.js +28 -0
  29. package/dist/chunk-C1OFhd7F.js +6131 -0
  30. package/dist/chunk-C7e7WwbU.js +331 -0
  31. package/dist/chunk-CDTYP6bN.js +558 -0
  32. package/dist/chunk-CGDQoqDC.js +24 -0
  33. package/dist/chunk-CJraEBVd.js +127 -0
  34. package/dist/chunk-CQrNhOtv.js +40 -0
  35. package/dist/chunk-CW6AzBH6.js +128 -0
  36. package/dist/chunk-CXgL4w-9.js +317 -0
  37. package/dist/chunk-CZrqoPyf.js +233 -0
  38. package/dist/chunk-CcFCyqbB.js +83 -0
  39. package/dist/chunk-CdaIvO-y.js +485 -0
  40. package/dist/chunk-CehSXtgK.js +624 -0
  41. package/dist/chunk-Ciqkop65.js +218 -0
  42. package/dist/chunk-CoAWdSiE.js +43 -0
  43. package/dist/chunk-Crb4y7t4.js +830 -0
  44. package/dist/chunk-CrlqIfmb.js +337 -0
  45. package/dist/chunk-Cs4pwCQ-.js +324 -0
  46. package/dist/chunk-CwM_9y01.js +519 -0
  47. package/dist/chunk-CyRbIJg8.js +440 -0
  48. package/dist/chunk-D0OHsyMy.js +212 -0
  49. package/dist/chunk-D3y2bURs.js +1347 -0
  50. package/dist/chunk-D4_mJk03.js +2338 -0
  51. package/dist/chunk-D6C8rned.js +578 -0
  52. package/dist/chunk-D9ZbUnks.js +11 -0
  53. package/dist/chunk-DEPmLshX.js +834 -0
  54. package/dist/chunk-DFj1UPB2.js +330 -0
  55. package/dist/chunk-DGdFdZVf.js +197 -0
  56. package/dist/chunk-DGv7X9S_.js +63 -0
  57. package/dist/chunk-DJQ47WYZ.js +664 -0
  58. package/dist/chunk-DJw3O61j.js +1974 -0
  59. package/dist/chunk-DK4FbWVK.js +100 -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 -73764
  84. package/package.json +6 -6
@@ -0,0 +1,233 @@
1
+ #!/usr/bin/env node
2
+ import { _ as isProductEventName, a as PRODUCT_EVENT_DEFAULT_NEXT_POLL_MS, i as PRODUCT_EVENT_CURSOR_PATTERN, o as PRODUCT_EVENT_MAX_WAIT_MS, s as PRODUCT_EVENT_NAMES } from "./chunk-ucu5lrDZ.js";
3
+ import { i as getApiUrl, r as createCliClient } from "./chunk-BW2fg46T.js";
4
+ import { n as ensureAuth } from "./chunk-CJraEBVd.js";
5
+ import { Command } from "commander";
6
+ import chalk from "chalk";
7
+ import { RuntypeApiError } from "@runtypelabs/sdk";
8
+ // src/commands/events.ts
9
+ const LONG_POLL_WAIT_MS = PRODUCT_EVENT_MAX_WAIT_MS;
10
+ const BASE_DELAY_MS = 1e3;
11
+ const MAX_DELAY_MS = 3e4;
12
+ const MAX_ATTEMPTS = 10;
13
+ const MAX_NEXT_POLL_MS = 6e4;
14
+ const MAX_VALUE_CHARS = 120;
15
+ var FatalWatchError = class extends Error {};
16
+ function abortableSleep(ms, signal) {
17
+ return new Promise((resolve) => {
18
+ if (signal.aborted) return resolve();
19
+ const timer = setTimeout(() => {
20
+ signal.removeEventListener("abort", onAbort);
21
+ resolve();
22
+ }, ms);
23
+ const onAbort = () => {
24
+ clearTimeout(timer);
25
+ resolve();
26
+ };
27
+ signal.addEventListener("abort", onAbort, { once: true });
28
+ });
29
+ }
30
+ const defaultIo = {
31
+ stdout: (line) => process.stdout.write(`${line}\n`),
32
+ stderr: (line) => process.stderr.write(`${line}\n`),
33
+ sleep: abortableSleep
34
+ };
35
+ /** Parse `--since`: `now` (or omitted) starts at the head; otherwise a decimal cursor. */
36
+ function parseSince(value) {
37
+ if (value === void 0 || value === "now") return void 0;
38
+ if (!PRODUCT_EVENT_CURSOR_PATTERN.test(value)) throw new Error(`Invalid --since value "${value}": expected "now" or a decimal cursor`);
39
+ return value;
40
+ }
41
+ /** Reject an unknown `--name` locally instead of round-tripping to the API's 400. */
42
+ function parseEventName(value) {
43
+ if (value === void 0 || isProductEventName(value)) return value;
44
+ throw new Error(`Unknown event type "${value}". Known types: ${PRODUCT_EVENT_NAMES.join(", ")}`);
45
+ }
46
+ /** `--request` filters only this event, and a key with no event scope may read it only by name. */
47
+ const API_KEY_REQUEST_DECIDED_EVENT = "runtype.api_key_request.decided";
48
+ /** Query string for one GET /events call; `after` omitted asks the API for the head cursor. */
49
+ function buildEventsQuery(options, after) {
50
+ const params = new URLSearchParams();
51
+ const entries = [
52
+ ["name", options.name ?? (options.request ? API_KEY_REQUEST_DECIDED_EVENT : void 0)],
53
+ ["agentId", options.agent],
54
+ ["flowId", options.flow],
55
+ ["productId", options.product],
56
+ ["surfaceId", options.surface],
57
+ ["scheduleId", options.schedule],
58
+ ["suiteId", options.suite],
59
+ ["simulationId", options.simulation],
60
+ ["taskId", options.task],
61
+ ["requestId", options.request],
62
+ ["key", options.key],
63
+ ["onlyRegressions", options.onlyRegressions ? "true" : void 0],
64
+ ["after", after],
65
+ ["waitMs", after === void 0 ? void 0 : String(LONG_POLL_WAIT_MS)]
66
+ ];
67
+ for (const [key, value] of entries) if (value !== void 0) params.set(key, value);
68
+ return params.toString();
69
+ }
70
+ function formatTime(ts) {
71
+ const d = new Date(ts);
72
+ if (Number.isNaN(d.getTime())) return ts;
73
+ return `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}:${String(d.getSeconds()).padStart(2, "0")}.${String(d.getMilliseconds()).padStart(3, "0")}`;
74
+ }
75
+ function formatValue(value) {
76
+ const singleLine = (typeof value === "string" ? value : JSON.stringify(value)).replace(/\s+/g, " ");
77
+ return singleLine.length > MAX_VALUE_CHARS ? `${singleLine.slice(0, 117)}...` : singleLine;
78
+ }
79
+ /** One human-readable line per event: local time, name, data fields, cursor. */
80
+ function formatEventLine(event, useColor) {
81
+ const paint = (fn, s) => useColor ? fn(s) : s;
82
+ const fields = Object.entries(event.data ?? {}).filter(([, v]) => v !== void 0 && v !== null).map(([k, v]) => `${k}=${formatValue(v)}`).join(" ");
83
+ const time = paint(chalk.gray, formatTime(event.timestamp));
84
+ const name = paint(event.name.endsWith("failed") ? chalk.red : chalk.cyan, event.name);
85
+ const cursor = paint(chalk.gray, `#${event.cursor}`);
86
+ return `${time} ${name}${fields ? ` ${fields}` : ""} ${cursor}`;
87
+ }
88
+ function isFatalApiError(error) {
89
+ if (!(error instanceof RuntypeApiError)) return false;
90
+ const status = error.statusCode;
91
+ return status >= 400 && status < 500 && status !== 408 && status !== 429;
92
+ }
93
+ async function pollOnce(client, options, after, signal) {
94
+ const body = await (await client.requestStream(`/events?${buildEventsQuery(options, after)}`, {
95
+ method: "GET",
96
+ headers: { Accept: "application/json" },
97
+ signal
98
+ })).json();
99
+ if (!body || !Array.isArray(body.events)) throw new FatalWatchError("Unexpected response from GET /events: missing \"events\" array");
100
+ return {
101
+ events: body.events,
102
+ cursor: body.cursor ?? null,
103
+ truncated: body.truncated === true,
104
+ hasMore: body.hasMore === true,
105
+ nextPollMs: typeof body.nextPollMs === "number" ? body.nextPollMs : PRODUCT_EVENT_DEFAULT_NEXT_POLL_MS
106
+ };
107
+ }
108
+ /**
109
+ * Long-poll GET /events until aborted, printing each event as it arrives.
110
+ * With `json`, stdout carries exactly one ProductEventOccurrence per line; diagnostics go to stderr.
111
+ */
112
+ async function watchEvents(client, options, signal, io = defaultIo) {
113
+ const useColor = options.color && !options.json;
114
+ const warn = (msg) => io.stderr(useColor ? chalk.yellow(msg) : msg);
115
+ const fail = (msg) => io.stderr(useColor ? chalk.red(msg) : msg);
116
+ const note = (msg) => io.stderr(useColor ? chalk.gray(msg) : msg);
117
+ let after = parseSince(options.since);
118
+ let attempt = 0;
119
+ while (!signal.aborted) {
120
+ const longPoll = after !== void 0;
121
+ let result;
122
+ try {
123
+ result = await pollOnce(client, options, after, signal);
124
+ attempt = 0;
125
+ } catch (error) {
126
+ if (signal.aborted) return "aborted";
127
+ const message = error instanceof Error ? error.message : String(error);
128
+ if (error instanceof FatalWatchError || isFatalApiError(error)) {
129
+ fail(`Failed to poll events: ${message}`);
130
+ return "failed";
131
+ }
132
+ attempt++;
133
+ fail(`Connection error: ${message}`);
134
+ if (attempt >= MAX_ATTEMPTS) {
135
+ fail(`Max reconnect attempts (${MAX_ATTEMPTS}) reached. Exiting.`);
136
+ return "failed";
137
+ }
138
+ const delay = Math.min(BASE_DELAY_MS * Math.pow(2, attempt - 1), MAX_DELAY_MS);
139
+ note(`Retrying in ${delay / 1e3}s (attempt ${attempt}/${MAX_ATTEMPTS})...`);
140
+ await io.sleep(delay, signal);
141
+ continue;
142
+ }
143
+ if (result.truncated) warn("[warn] Some events were skipped: the cursor was older than the 7-day retention window");
144
+ for (const event of result.events) io.stdout(options.json ? JSON.stringify(event) : formatEventLine(event, useColor));
145
+ const lastCursor = result.events.at(-1)?.cursor;
146
+ after = result.cursor ?? lastCursor ?? after ?? "0";
147
+ if (options.once && result.events.length > 0) {
148
+ note(`Resume with --since ${after}`);
149
+ return "once";
150
+ }
151
+ if (result.hasMore || !longPoll) continue;
152
+ const wait = Math.min(Math.max(result.nextPollMs, 0), MAX_NEXT_POLL_MS);
153
+ if (wait > 0) await io.sleep(wait, signal);
154
+ }
155
+ return "aborted";
156
+ }
157
+ async function runWatch(options) {
158
+ try {
159
+ parseSince(options.since);
160
+ parseEventName(options.name);
161
+ } catch (error) {
162
+ process.stderr.write(`${chalk.red(error.message)}\n`);
163
+ process.exitCode = 1;
164
+ return;
165
+ }
166
+ const apiKey = await ensureAuth();
167
+ if (!apiKey) return;
168
+ const apiUrl = getApiUrl();
169
+ const client = createCliClient(apiKey, apiUrl);
170
+ const useColor = options.color && !options.json;
171
+ const banner = `Watching ${options.name ?? "all event types"} on ${apiUrl} from ${options.since && options.since !== "now" ? `after cursor ${options.since}` : "now"}...`;
172
+ process.stderr.write(`${useColor ? chalk.gray(banner) : banner}\n`);
173
+ const controller = new AbortController();
174
+ const shutdown = () => {
175
+ if (controller.signal.aborted) return;
176
+ process.stderr.write(`${useColor ? chalk.gray("\nDisconnecting...") : "\nDisconnecting..."}\n`);
177
+ controller.abort();
178
+ };
179
+ process.on("SIGINT", shutdown);
180
+ process.on("SIGTERM", shutdown);
181
+ try {
182
+ if (await watchEvents(client, options, controller.signal) === "failed") process.exitCode = 1;
183
+ } finally {
184
+ process.removeListener("SIGINT", shutdown);
185
+ process.removeListener("SIGTERM", shutdown);
186
+ }
187
+ }
188
+ function filterNames(descriptor) {
189
+ const properties = descriptor.inputSchema?.properties;
190
+ return properties && typeof properties === "object" ? Object.keys(properties) : [];
191
+ }
192
+ async function runTypes(options) {
193
+ const apiKey = await ensureAuth();
194
+ if (!apiKey) return;
195
+ const client = createCliClient(apiKey);
196
+ let events;
197
+ try {
198
+ events = (await client.get("/events/types")).events ?? [];
199
+ } catch (error) {
200
+ const message = error instanceof Error ? error.message : String(error);
201
+ process.stderr.write(`${chalk.red(`Failed to list event types: ${message}`)}\n`);
202
+ process.exitCode = 1;
203
+ return;
204
+ }
205
+ if (options.json) {
206
+ console.log(JSON.stringify({ events }, null, 2));
207
+ return;
208
+ }
209
+ if (events.length === 0) {
210
+ console.log(chalk.gray("No event types available"));
211
+ return;
212
+ }
213
+ const width = Math.max(...events.map((e) => e.name.length));
214
+ console.log(chalk.cyan("Event types:"));
215
+ for (const event of events) {
216
+ const name = event.name.padEnd(width);
217
+ console.log(` ${options.color ? chalk.green(name) : name} ${event.description}`);
218
+ const filters = filterNames(event);
219
+ if (filters.length > 0) {
220
+ const line = ` ${" ".repeat(width)} filters: ${filters.join(", ")}`;
221
+ console.log(options.color ? chalk.dim(line) : line);
222
+ }
223
+ }
224
+ }
225
+ const eventsCommand = new Command("events").description("Watch product events (failed executions, approvals, eval results, ...)");
226
+ eventsCommand.command("types").description("List the product event types you can watch").option("--json", "Output as JSON").option("--no-color", "Disable color output").action(async (options) => {
227
+ await runTypes(options);
228
+ });
229
+ eventsCommand.command("watch").description("Long-poll product events and print one line per event").option("--name <name>", "Event type to watch (default: every type; see `runtype events types`)").option("--agent <id>", "Filter by agent ID").option("--flow <id>", "Filter by flow ID").option("--product <id>", "Filter by product ID").option("--surface <id>", "Filter by surface ID").option("--schedule <id>", "Filter by schedule ID").option("--suite <id>", "Filter by eval suite ID").option("--simulation <id>", "Filter by simulation ID").option("--task <id>", "Filter by delegated task ID").option("--request <id>", "Filter by API key request ID").option("--key <key>", "Signal events: only this signal key, such as tool_error").option("--only-regressions", "Eval runs: only those whose pass rate dropped").option("--since <cursor>", "Start after this cursor, or \"now\" (default)").option("--json", "Output NDJSON: one event object per line on stdout").option("--once", "Exit after the first poll that returns events").option("--no-color", "Disable color output").action(async (options) => {
230
+ await runWatch(options);
231
+ });
232
+ export { eventsCommand };
233
+
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+ import chalk from "chalk";
3
+ import { RuntypeApiError } from "@runtypelabs/sdk";
4
+ // src/lib/output.ts
5
+ /**
6
+ * Print data as formatted JSON.
7
+ */
8
+ function printJson(data) {
9
+ console.log(JSON.stringify(data, null, 2));
10
+ }
11
+ /** The structured `details` list of an API error envelope, for `--json` error output. */
12
+ function apiErrorDetails(error) {
13
+ if (!(error instanceof RuntypeApiError)) return void 0;
14
+ const data = error.data;
15
+ if (typeof data !== "object" || data === null || !("details" in data)) return void 0;
16
+ return Array.isArray(data.details) && data.details.length > 0 ? data.details : void 0;
17
+ }
18
+ /**
19
+ * Print a list of items with id + name, plus optional extra fields.
20
+ */
21
+ function printList(items, options) {
22
+ console.log(chalk.cyan(`${options.title}:`));
23
+ if (items.length === 0) {
24
+ console.log(chalk.gray(` ${options.emptyMessage || "None found"}`));
25
+ return;
26
+ }
27
+ for (const item of items) {
28
+ const parts = [];
29
+ for (const col of options.columns) {
30
+ const value = item[col.key];
31
+ if (value === void 0 || value === null) continue;
32
+ const str = String(value);
33
+ const colorFn = col.color ? chalk[col.color] : (s) => s;
34
+ if (col.label) parts.push(`${col.label}: ${colorFn(str)}`);
35
+ else parts.push(colorFn(str));
36
+ }
37
+ console.log(` ${parts.join(" - ")}`);
38
+ }
39
+ if (options.total !== void 0) console.log(chalk.dim(`\n Total: ${options.total}`));
40
+ }
41
+ /**
42
+ * Print a single item's details as key-value pairs.
43
+ */
44
+ function printDetail(title, fields) {
45
+ console.log(chalk.cyan(`${title}:`));
46
+ for (const field of fields) {
47
+ if (field.value === void 0 || field.value === null) continue;
48
+ const str = typeof field.value === "object" ? JSON.stringify(field.value) : String(field.value);
49
+ console.log(` ${chalk.gray(field.label + ":")} ${str}`);
50
+ }
51
+ }
52
+ /**
53
+ * Extract total count from a paginated response.
54
+ */
55
+ function getTotalCount(pagination) {
56
+ return pagination?.totalCount ?? pagination?.total ?? void 0;
57
+ }
58
+ /**
59
+ * Build query params for a paginated list request from the standard `--limit`/`--cursor`
60
+ * flags, merging in any command-specific filters. Undefined values are omitted.
61
+ */
62
+ function buildListParams(options, extra) {
63
+ const params = {};
64
+ if (options.limit) params.limit = options.limit;
65
+ if (options.cursor) params.cursor = options.cursor;
66
+ if (extra) {
67
+ for (const [key, value] of Object.entries(extra)) if (value !== void 0) params[key] = value;
68
+ }
69
+ return params;
70
+ }
71
+ /**
72
+ * Print a hint showing how to fetch the next page via `--cursor`, when more results exist.
73
+ * Normalizes over the `nextCursor`/`cursor` and `hasMore`/`hasNextPage` field variants.
74
+ * `commandPath` is the invocation prefix to suggest, e.g. `runtype flows list`.
75
+ */
76
+ function printNextCursorHint(commandPath, pagination) {
77
+ const hasMore = pagination?.hasMore ?? pagination?.hasNextPage ?? false;
78
+ const nextCursor = pagination?.nextCursor !== void 0 ? pagination.nextCursor : pagination?.cursor ?? null;
79
+ if (!hasMore || !nextCursor) return;
80
+ console.log(chalk.yellow("\n More results available — fetch the next page with:") + chalk.dim(`\n ${commandPath} --cursor ${nextCursor}`));
81
+ }
82
+ export { printJson as a, printDetail as i, buildListParams as n, printList as o, getTotalCount as r, printNextCursorHint as s, apiErrorDetails as t };
83
+