@runcofactor/cli 0.10.0

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 (150) hide show
  1. package/README.md +125 -0
  2. package/dist/api-catalog-GFGCLVS4.js +401 -0
  3. package/dist/api-catalog-GFGCLVS4.js.map +1 -0
  4. package/dist/attachment-SJC7D7FY.js +276 -0
  5. package/dist/attachment-SJC7D7FY.js.map +1 -0
  6. package/dist/auth-EN6NQCJY.js +31 -0
  7. package/dist/auth-EN6NQCJY.js.map +1 -0
  8. package/dist/bin.js +7 -0
  9. package/dist/bin.js.map +1 -0
  10. package/dist/chunk-3CZU7XCS.js +272 -0
  11. package/dist/chunk-3CZU7XCS.js.map +1 -0
  12. package/dist/chunk-4NRDONSC.js +1048 -0
  13. package/dist/chunk-4NRDONSC.js.map +1 -0
  14. package/dist/chunk-4PNOV7OV.js +51980 -0
  15. package/dist/chunk-4PNOV7OV.js.map +1 -0
  16. package/dist/chunk-52IO7ACJ.js +2941 -0
  17. package/dist/chunk-52IO7ACJ.js.map +1 -0
  18. package/dist/chunk-6LEZCKKV.js +663 -0
  19. package/dist/chunk-6LEZCKKV.js.map +1 -0
  20. package/dist/chunk-A4OFTUVV.js +170 -0
  21. package/dist/chunk-A4OFTUVV.js.map +1 -0
  22. package/dist/chunk-B2VISN2V.js +2459 -0
  23. package/dist/chunk-B2VISN2V.js.map +1 -0
  24. package/dist/chunk-CLAWT7BJ.js +271 -0
  25. package/dist/chunk-CLAWT7BJ.js.map +1 -0
  26. package/dist/chunk-GKY2KXO5.js +281 -0
  27. package/dist/chunk-GKY2KXO5.js.map +1 -0
  28. package/dist/chunk-I4QLI3JO.js +413 -0
  29. package/dist/chunk-I4QLI3JO.js.map +1 -0
  30. package/dist/chunk-IMPZAX6L.js +180 -0
  31. package/dist/chunk-IMPZAX6L.js.map +1 -0
  32. package/dist/chunk-J6SH7GQT.js +241 -0
  33. package/dist/chunk-J6SH7GQT.js.map +1 -0
  34. package/dist/chunk-JDBCZ3Z2.js +298 -0
  35. package/dist/chunk-JDBCZ3Z2.js.map +1 -0
  36. package/dist/chunk-JICSYFRJ.js +46 -0
  37. package/dist/chunk-JICSYFRJ.js.map +1 -0
  38. package/dist/chunk-JWHYXEA2.js +32 -0
  39. package/dist/chunk-JWHYXEA2.js.map +1 -0
  40. package/dist/chunk-N7HFALX3.js +88 -0
  41. package/dist/chunk-N7HFALX3.js.map +1 -0
  42. package/dist/chunk-Q4BO4Z5V.js +178 -0
  43. package/dist/chunk-Q4BO4Z5V.js.map +1 -0
  44. package/dist/chunk-QFDOWABX.js +195 -0
  45. package/dist/chunk-QFDOWABX.js.map +1 -0
  46. package/dist/chunk-SJJW77WN.js +605 -0
  47. package/dist/chunk-SJJW77WN.js.map +1 -0
  48. package/dist/chunk-VKVL7WBN.js +50 -0
  49. package/dist/chunk-VKVL7WBN.js.map +1 -0
  50. package/dist/chunk-WOHL4FTB.js +353 -0
  51. package/dist/chunk-WOHL4FTB.js.map +1 -0
  52. package/dist/chunk-XQXVG7RA.js +426 -0
  53. package/dist/chunk-XQXVG7RA.js.map +1 -0
  54. package/dist/chunk-ZD3KHESI.js +94 -0
  55. package/dist/chunk-ZD3KHESI.js.map +1 -0
  56. package/dist/credential-COLTBV6D.js +450 -0
  57. package/dist/credential-COLTBV6D.js.map +1 -0
  58. package/dist/credential-template-EEPYFG7R.js +291 -0
  59. package/dist/credential-template-EEPYFG7R.js.map +1 -0
  60. package/dist/debug-workflow-KOVH5GOP.js +259 -0
  61. package/dist/debug-workflow-KOVH5GOP.js.map +1 -0
  62. package/dist/dist-44PZR7BQ.js +423 -0
  63. package/dist/dist-44PZR7BQ.js.map +1 -0
  64. package/dist/docs-3SSORHB5.js +366 -0
  65. package/dist/docs-3SSORHB5.js.map +1 -0
  66. package/dist/doctor-OTSIWV6G.js +132 -0
  67. package/dist/doctor-OTSIWV6G.js.map +1 -0
  68. package/dist/feature-flag-T2LRZME3.js +283 -0
  69. package/dist/feature-flag-T2LRZME3.js.map +1 -0
  70. package/dist/file-type-S3UUBVCT.js +4205 -0
  71. package/dist/file-type-S3UUBVCT.js.map +1 -0
  72. package/dist/index.d.ts +3 -0
  73. package/dist/index.js +982 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/init-TGWRECT2.js +208 -0
  76. package/dist/init-TGWRECT2.js.map +1 -0
  77. package/dist/install-DXSNWZKO.js +295 -0
  78. package/dist/install-DXSNWZKO.js.map +1 -0
  79. package/dist/issues-XIZOPX6T.js +564 -0
  80. package/dist/issues-XIZOPX6T.js.map +1 -0
  81. package/dist/knobs-NBINZIUB.js +295 -0
  82. package/dist/knobs-NBINZIUB.js.map +1 -0
  83. package/dist/list-3TDHK637.js +59 -0
  84. package/dist/list-3TDHK637.js.map +1 -0
  85. package/dist/local-HICVD6PU.js +100 -0
  86. package/dist/local-HICVD6PU.js.map +1 -0
  87. package/dist/login-UOIUXVUK.js +315 -0
  88. package/dist/login-UOIUXVUK.js.map +1 -0
  89. package/dist/mcp-54IJEOUA.js +1956 -0
  90. package/dist/mcp-54IJEOUA.js.map +1 -0
  91. package/dist/pdf-extract-ABWV3L5X.js +13 -0
  92. package/dist/pdf-extract-ABWV3L5X.js.map +1 -0
  93. package/dist/pdfjs-DQ2YA5S3.js +41561 -0
  94. package/dist/pdfjs-DQ2YA5S3.js.map +1 -0
  95. package/dist/property-UXLOLPTD.js +701 -0
  96. package/dist/property-UXLOLPTD.js.map +1 -0
  97. package/dist/property-skill-guide.md +189 -0
  98. package/dist/psql-BYUUNLGG.js +115 -0
  99. package/dist/psql-BYUUNLGG.js.map +1 -0
  100. package/dist/record-4TR2UIIS.js +233 -0
  101. package/dist/record-4TR2UIIS.js.map +1 -0
  102. package/dist/redis-35VBUYW7.js +116 -0
  103. package/dist/redis-35VBUYW7.js.map +1 -0
  104. package/dist/release-OOLTUBUT.js +354 -0
  105. package/dist/release-OOLTUBUT.js.map +1 -0
  106. package/dist/sandbox-XGSUU6G7.js +2046 -0
  107. package/dist/sandbox-XGSUU6G7.js.map +1 -0
  108. package/dist/scenarios-GWLJEGHA.js +280 -0
  109. package/dist/scenarios-GWLJEGHA.js.map +1 -0
  110. package/dist/session-MYFNZPRP.js +2414 -0
  111. package/dist/session-MYFNZPRP.js.map +1 -0
  112. package/dist/skill-KM34LDMO.js +1839 -0
  113. package/dist/skill-KM34LDMO.js.map +1 -0
  114. package/dist/skills/debug-run/SKILL.md +262 -0
  115. package/dist/skills/debug-run/history/1.0.0.md +244 -0
  116. package/dist/skills/debug-run/history/1.0.1.md +245 -0
  117. package/dist/skills/debug-run/history/1.0.2.md +254 -0
  118. package/dist/skills/debug-run/history/1.1.0.md +262 -0
  119. package/dist/skills/debug-run/version.json +3 -0
  120. package/dist/spec-RA3CFEKG.js +951 -0
  121. package/dist/spec-RA3CFEKG.js.map +1 -0
  122. package/dist/src-LB4HBTJQ.js +1516 -0
  123. package/dist/src-LB4HBTJQ.js.map +1 -0
  124. package/dist/src-N3TPKGTY.js +244 -0
  125. package/dist/src-N3TPKGTY.js.map +1 -0
  126. package/dist/src-UVDX5UP6.js +17 -0
  127. package/dist/src-UVDX5UP6.js.map +1 -0
  128. package/dist/start-PSEQSQA3.js +151 -0
  129. package/dist/start-PSEQSQA3.js.map +1 -0
  130. package/dist/tag-YY6YAABQ.js +22 -0
  131. package/dist/tag-YY6YAABQ.js.map +1 -0
  132. package/dist/task-IQC3YR5K.js +922 -0
  133. package/dist/task-IQC3YR5K.js.map +1 -0
  134. package/dist/test-suite-DZNJFXDW.js +394 -0
  135. package/dist/test-suite-DZNJFXDW.js.map +1 -0
  136. package/dist/trace-HXIW7U2D.js +14 -0
  137. package/dist/trace-HXIW7U2D.js.map +1 -0
  138. package/dist/triage-ORG45R5W.js +16 -0
  139. package/dist/triage-ORG45R5W.js.map +1 -0
  140. package/dist/upgrade-L2VYMP2V.js +61 -0
  141. package/dist/upgrade-L2VYMP2V.js.map +1 -0
  142. package/dist/workflow-XYFH5LTP.js +3708 -0
  143. package/dist/workflow-XYFH5LTP.js.map +1 -0
  144. package/dist/workflow-cache-NQJQFWMV.js +253 -0
  145. package/dist/workflow-cache-NQJQFWMV.js.map +1 -0
  146. package/dist/workflow-debug-BGD4UIXU.js +927 -0
  147. package/dist/workflow-debug-BGD4UIXU.js.map +1 -0
  148. package/dist/workflow-proposals-MTUDX46O.js +382 -0
  149. package/dist/workflow-proposals-MTUDX46O.js.map +1 -0
  150. package/package.json +61 -0
package/dist/index.js ADDED
@@ -0,0 +1,982 @@
1
+ import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
+ import {
3
+ runRemoteTest
4
+ } from "./chunk-GKY2KXO5.js";
5
+ import {
6
+ runLogin
7
+ } from "./chunk-QFDOWABX.js";
8
+ import {
9
+ checkForUpdate
10
+ } from "./chunk-N7HFALX3.js";
11
+ import {
12
+ installConsoleBranding,
13
+ version
14
+ } from "./chunk-JICSYFRJ.js";
15
+ import "./chunk-CLAWT7BJ.js";
16
+ import "./chunk-WOHL4FTB.js";
17
+ import "./chunk-SJJW77WN.js";
18
+ import {
19
+ fetchOrExit,
20
+ isSuperadminToken
21
+ } from "./chunk-3CZU7XCS.js";
22
+ import {
23
+ envToProfile,
24
+ getArgValue,
25
+ hasFlag,
26
+ readAllStoredTokens,
27
+ readStoredAuth,
28
+ resolveConfig,
29
+ resolveOptionalConfig
30
+ } from "./chunk-A4OFTUVV.js";
31
+ import "./chunk-JWHYXEA2.js";
32
+ import "./chunk-VKVL7WBN.js";
33
+
34
+ // src/index.ts
35
+ import process4 from "process";
36
+ import { pathToFileURL } from "url";
37
+
38
+ // src/orgs.ts
39
+ import process from "process";
40
+ async function runOrgs(argv) {
41
+ const { apiUrl, token } = await resolveConfig(argv);
42
+ const env = getArgValue(argv, "--env");
43
+ const auth = await readStoredAuth(env ? envToProfile(env) : void 0);
44
+ const showAll = hasFlag(argv, "--all");
45
+ if (showAll) {
46
+ const res2 = await fetch(`${apiUrl}/superadmin/organizations`, {
47
+ headers: { Authorization: `Bearer ${token}` }
48
+ });
49
+ if (!res2.ok) {
50
+ if (res2.status === 403) {
51
+ console.error("Superadmin access required for --all");
52
+ } else {
53
+ console.error("Failed to fetch organizations. You may need to re-login: canary login");
54
+ }
55
+ process.exit(1);
56
+ }
57
+ const data2 = await res2.json();
58
+ if (!data2.ok || !data2.organizations) {
59
+ console.error("Failed to fetch organizations:", data2.error ?? "Unknown error");
60
+ process.exit(1);
61
+ }
62
+ console.log("All Organizations:\n");
63
+ for (const org of data2.organizations) {
64
+ const members = org.memberCount !== void 0 && org.memberCount !== null ? ` (${org.memberCount} members)` : "";
65
+ console.log(` ${org.name}${members} [${org.id}]`);
66
+ }
67
+ console.log(`
68
+ Total: ${data2.organizations.length} organizations`);
69
+ return;
70
+ }
71
+ const res = await fetch(`${apiUrl}/cli-login/orgs`, {
72
+ headers: { Authorization: `Bearer ${token}` }
73
+ });
74
+ if (!res.ok) {
75
+ console.error("Failed to fetch organizations. You may need to re-login: canary login");
76
+ process.exit(1);
77
+ }
78
+ const data = await res.json();
79
+ if (!data.ok || !data.organizations) {
80
+ console.error("Failed to fetch organizations:", data.error ?? "Unknown error");
81
+ process.exit(1);
82
+ }
83
+ const currentOrgId = auth?.orgId ?? data.currentOrgId;
84
+ console.log("Organizations:\n");
85
+ for (const org of data.organizations) {
86
+ const marker = org.id === currentOrgId ? " *" : "";
87
+ console.log(` ${org.name} (${org.role}) [${org.id}]${marker}`);
88
+ }
89
+ console.log("\n* = current organization");
90
+ console.log("To switch: canary login --org <name>");
91
+ }
92
+
93
+ // src/debug-session.ts
94
+ import fs from "fs/promises";
95
+ import os from "os";
96
+ import path from "path";
97
+ import process2 from "process";
98
+ async function writeDebugSession(loginUrl, expiresAt, apiUrl) {
99
+ const dir = path.join(os.homedir(), ".config", "canary-cli");
100
+ const filePath = path.join(dir, "debug-session.json");
101
+ await fs.mkdir(dir, { recursive: true, mode: 448 });
102
+ await fs.writeFile(
103
+ filePath,
104
+ JSON.stringify({ loginUrl, expiresAt, apiUrl, createdAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
105
+ { encoding: "utf8", mode: 384 }
106
+ );
107
+ return filePath;
108
+ }
109
+ async function runDebugSession(argv) {
110
+ const { apiUrl, token } = await resolveConfig(argv);
111
+ const jsonOutput = hasFlag(argv, "--json");
112
+ try {
113
+ const res = await fetchOrExit(`${apiUrl}/auth/debug-session/create`, {
114
+ method: "POST",
115
+ headers: {
116
+ Authorization: `Bearer ${token}`,
117
+ "Content-Type": "application/json"
118
+ },
119
+ token
120
+ });
121
+ if (!res.ok) {
122
+ const text = await res.text();
123
+ if (res.status === 403) {
124
+ console.error("Error: Forbidden. Debug session creation requires superadmin access.");
125
+ process2.exit(1);
126
+ }
127
+ if (res.status === 404) {
128
+ console.error(
129
+ "Error: Endpoint not found. The debug-session feature may not be deployed to this environment."
130
+ );
131
+ process2.exit(1);
132
+ }
133
+ try {
134
+ const errorJson = JSON.parse(text);
135
+ console.error(`Error: ${errorJson.message ?? errorJson.error ?? text}`);
136
+ } catch {
137
+ console.error(`Error (${res.status}): ${text || res.statusText}`);
138
+ }
139
+ process2.exit(1);
140
+ }
141
+ const json = await res.json();
142
+ if (!json.ok || !json.loginUrl) {
143
+ console.error(`Error: ${json.message ?? json.error ?? "Failed to create debug session"}`);
144
+ process2.exit(1);
145
+ }
146
+ const filePath = await writeDebugSession(json.loginUrl, json.expiresAt ?? "", apiUrl);
147
+ if (jsonOutput) {
148
+ console.log(
149
+ JSON.stringify(
150
+ {
151
+ loginUrl: json.loginUrl,
152
+ expiresAt: json.expiresAt,
153
+ sessionFile: filePath
154
+ },
155
+ null,
156
+ 2
157
+ )
158
+ );
159
+ } else {
160
+ console.log("Debug session created successfully.");
161
+ console.log("");
162
+ console.log(`Login URL: ${json.loginUrl}`);
163
+ console.log(`Expires: ${json.expiresAt}`);
164
+ console.log(`Session saved to: ${filePath}`);
165
+ console.log("");
166
+ console.log("Use this URL with Playwright to authenticate as the debug agent.");
167
+ console.log("The token is single-use and expires in 5 minutes.");
168
+ }
169
+ } catch (err) {
170
+ console.error(`Failed to create debug session: ${err}`);
171
+ process2.exit(1);
172
+ }
173
+ }
174
+
175
+ // src/user-event-tracking.ts
176
+ import process3 from "process";
177
+
178
+ // ../sdk/src/errors.ts
179
+ var SdkError = class extends Error {
180
+ status;
181
+ body;
182
+ constructor(message, status, body) {
183
+ super(message);
184
+ this.name = "SdkError";
185
+ this.status = status;
186
+ this.body = body;
187
+ }
188
+ };
189
+ var AuthError = class extends SdkError {
190
+ constructor(message, status, body) {
191
+ super(message, status, body);
192
+ this.name = "AuthError";
193
+ }
194
+ };
195
+ var ValidationError = class extends SdkError {
196
+ constructor(message, status, body) {
197
+ super(message, status, body);
198
+ this.name = "ValidationError";
199
+ }
200
+ };
201
+ function errorFromResponse(status, body) {
202
+ const message = body?.error ?? `Request failed with status ${status}`;
203
+ if (status === 401 || status === 403) return new AuthError(message, status, body);
204
+ if (status === 400 || status === 422) return new ValidationError(message, status, body);
205
+ return new SdkError(message, status, body);
206
+ }
207
+
208
+ // ../sdk/src/client.ts
209
+ function interpolate(path2, params) {
210
+ if (!params) return path2;
211
+ return path2.replace(/:([A-Za-z0-9_]+)/g, (_, k) => {
212
+ const v = params[k];
213
+ if (v === void 0) throw new Error(`Missing path param :${k} for ${path2}`);
214
+ return encodeURIComponent(String(v));
215
+ });
216
+ }
217
+ function buildQuery(q) {
218
+ if (!q) return "";
219
+ const usp = new URLSearchParams();
220
+ for (const [k, v] of Object.entries(q)) {
221
+ if (v === void 0 || v === null) continue;
222
+ usp.set(k, String(v));
223
+ }
224
+ const s = usp.toString();
225
+ return s ? `?${s}` : "";
226
+ }
227
+ function createClient(cfg) {
228
+ let token = cfg.token;
229
+ const fetchImpl = cfg.fetch ?? fetch;
230
+ async function resolveToken() {
231
+ if (typeof token === "function") return token();
232
+ return token;
233
+ }
234
+ async function request(method, path2, opts = {}) {
235
+ const url = cfg.baseUrl.replace(/\/$/, "") + interpolate(path2, opts.params) + buildQuery(opts.query);
236
+ const headers = {
237
+ accept: "application/json",
238
+ ...cfg.headers,
239
+ ...opts.headers
240
+ };
241
+ const resolvedToken = await resolveToken();
242
+ if (resolvedToken && !headers.authorization) {
243
+ headers.authorization = `Bearer ${resolvedToken}`;
244
+ }
245
+ if (opts.body !== void 0 && !headers["content-type"]) {
246
+ headers["content-type"] = "application/json";
247
+ }
248
+ const res = await fetchImpl(url, {
249
+ method,
250
+ headers,
251
+ body: opts.body === void 0 ? void 0 : JSON.stringify(opts.body),
252
+ signal: opts.signal
253
+ });
254
+ const text = await res.text();
255
+ let parsed;
256
+ if (text.length > 0) {
257
+ try {
258
+ parsed = JSON.parse(text);
259
+ } catch {
260
+ parsed = text;
261
+ }
262
+ }
263
+ if (!res.ok) {
264
+ const body = parsed && typeof parsed === "object" ? parsed : void 0;
265
+ throw errorFromResponse(res.status, body);
266
+ }
267
+ return parsed;
268
+ }
269
+ return {
270
+ get baseUrl() {
271
+ return cfg.baseUrl;
272
+ },
273
+ request,
274
+ setToken(next) {
275
+ token = next;
276
+ }
277
+ };
278
+ }
279
+
280
+ // ../sdk/src/user-events.ts
281
+ async function recordUserEvent(client, input) {
282
+ await client.request("POST", "/events", {
283
+ body: input
284
+ });
285
+ }
286
+
287
+ // ../user-events/src/recorder.ts
288
+ function createUserEventRecorder(opts) {
289
+ const safeRecord = async (eventType, metadata) => {
290
+ try {
291
+ await recordUserEvent(opts.client, {
292
+ eventType,
293
+ origin: opts.origin,
294
+ metadata
295
+ });
296
+ } catch (error) {
297
+ opts.onError?.(error);
298
+ }
299
+ };
300
+ return {
301
+ record: safeRecord,
302
+ recordCommandStarted(metadata) {
303
+ return safeRecord("command.started", metadata);
304
+ },
305
+ recordCommandCompleted(metadata) {
306
+ return safeRecord("command.completed", metadata);
307
+ },
308
+ recordCommandFailed(metadata) {
309
+ return safeRecord("command.failed", metadata);
310
+ },
311
+ recordCommandInstrumentationFailed(metadata) {
312
+ return safeRecord("command.instrumentation-failed", metadata);
313
+ }
314
+ };
315
+ }
316
+
317
+ // src/user-event-tracking.ts
318
+ var SUBCOMMAND_COMMANDS = /* @__PURE__ */ new Set([
319
+ "api-catalog",
320
+ "attachment",
321
+ "attachments",
322
+ "auth",
323
+ "credential",
324
+ "credential-template",
325
+ "credential-templates",
326
+ "docs",
327
+ "feature-flag",
328
+ "issues",
329
+ "knobs",
330
+ "local",
331
+ "property",
332
+ "release",
333
+ "sandbox",
334
+ "session",
335
+ "tag",
336
+ "tags",
337
+ "task",
338
+ "test-suite",
339
+ "workflow"
340
+ ]);
341
+ var UNTRACKED_COMMANDS = /* @__PURE__ */ new Set(["help", "upgrade", "version"]);
342
+ var ProcessExitSignal = class extends Error {
343
+ exitCode;
344
+ constructor(exitCode) {
345
+ super(`Process exited with code ${exitCode}`);
346
+ this.name = "ProcessExitSignal";
347
+ this.exitCode = exitCode;
348
+ }
349
+ };
350
+ function shouldTrack(argv) {
351
+ const command = argv[0];
352
+ if (!command || UNTRACKED_COMMANDS.has(command)) return false;
353
+ if (argv.includes("--help") || argv.includes("-h")) return false;
354
+ return true;
355
+ }
356
+ function getSubcommand(argv) {
357
+ const command = argv[0];
358
+ if (!command || !SUBCOMMAND_COMMANDS.has(command)) return void 0;
359
+ const candidate = argv[1];
360
+ if (!candidate || candidate.startsWith("-")) return void 0;
361
+ return candidate;
362
+ }
363
+ function getApiHost(apiUrl) {
364
+ try {
365
+ return new URL(apiUrl).host;
366
+ } catch {
367
+ return void 0;
368
+ }
369
+ }
370
+ function getArgNames(argv) {
371
+ return argv.filter((arg) => arg.startsWith("-"));
372
+ }
373
+ function buildBaseMetadata(argv, cliVersion, apiUrl) {
374
+ const topLevelCommand = argv[0] ?? "unknown";
375
+ const subcommand = getSubcommand(argv);
376
+ return {
377
+ commandPath: subcommand ? `${topLevelCommand} ${subcommand}` : topLevelCommand,
378
+ topLevelCommand,
379
+ subcommand,
380
+ cliVersion,
381
+ apiHost: getApiHost(apiUrl),
382
+ isInteractive: Boolean(process3.stdin.isTTY && process3.stdout.isTTY),
383
+ args: getArgNames(argv)
384
+ };
385
+ }
386
+ function errorMetadata(error) {
387
+ return {
388
+ errorKind: error instanceof Error ? error.name : typeof error,
389
+ errorName: error instanceof Error ? error.name : void 0,
390
+ errorMessage: error instanceof Error ? error.message : String(error)
391
+ };
392
+ }
393
+ async function createCliUserEventRecorder(argv, cliVersion) {
394
+ if (!shouldTrack(argv)) return null;
395
+ const config = await resolveOptionalConfig(argv);
396
+ if (!config) return null;
397
+ const client = createClient({
398
+ baseUrl: config.apiUrl,
399
+ token: config.token
400
+ });
401
+ return {
402
+ recorder: createUserEventRecorder({
403
+ client,
404
+ origin: "cli",
405
+ onError: (error) => {
406
+ const message = error instanceof Error ? error.message : String(error);
407
+ process3.stderr.write(`[canary] user event tracking skipped: ${message}
408
+ `);
409
+ }
410
+ }),
411
+ metadata: buildBaseMetadata(argv, cliVersion, config.apiUrl)
412
+ };
413
+ }
414
+ async function recordCliInstrumentationFailure(argv, cliVersion, stage, error) {
415
+ if (!shouldTrack(argv)) return;
416
+ try {
417
+ const config = await resolveOptionalConfig(argv);
418
+ if (!config) return;
419
+ const client = createClient({
420
+ baseUrl: config.apiUrl,
421
+ token: config.token
422
+ });
423
+ const recorder = createUserEventRecorder({
424
+ client,
425
+ origin: "cli"
426
+ });
427
+ await recorder.recordCommandInstrumentationFailed({
428
+ ...buildBaseMetadata(argv, cliVersion, config.apiUrl),
429
+ stage,
430
+ ...errorMetadata(error),
431
+ reportToSentry: true,
432
+ sentryFingerprint: ["canary-cli", "instrumentation-failed", stage]
433
+ });
434
+ } catch {
435
+ }
436
+ }
437
+
438
+ // src/index.ts
439
+ var loadMcp = () => import("./mcp-54IJEOUA.js").then((m) => m.runMcp);
440
+ var loadDebugWorkflow = () => import("./debug-workflow-KOVH5GOP.js").then((m) => m.runDebugWorkflow);
441
+ var loadRecord = () => import("./record-4TR2UIIS.js").then((m) => m.runRecord);
442
+ var loadSession = () => import("./session-MYFNZPRP.js").then((m) => m.runSession);
443
+ var loadLocal = () => import("./local-HICVD6PU.js").then((m) => m.runLocal);
444
+ function printVersion() {
445
+ console.log(`canary v${version}`);
446
+ }
447
+ function printHelp({ isSuperadmin }) {
448
+ const lines = [
449
+ `canary v${version}: Testing and QA CLI`,
450
+ "",
451
+ "Usage:",
452
+ " canary test-suite <sub-command> Run and query test suite results",
453
+ " canary mcp Start MCP server (stdio)",
454
+ " canary install [--target <id>] Install MCP server into Claude, Cursor, etc.",
455
+ " canary login [--org <name>] [--app-url https://app.trycanary.ai] [--no-open]",
456
+ " canary orgs List organizations",
457
+ " canary debug <workflowId> [options] Debug workflow in local headed browser",
458
+ " canary record [options] Record browser interactions",
459
+ " canary local <sub-command> Set up and manage local testing",
460
+ " canary session <sub-command> Manage local browser sessions",
461
+ " canary issues <sub-command> Search and view issues",
462
+ " canary credential <sub-command> List, create, update, and test credentials",
463
+ " canary credential-template <sub-command> Manage per-application credential templates",
464
+ " canary workflow <sub-command> Inspect workflow definitions",
465
+ " canary spec <sub-command> Author workflows from .canary.md spec files",
466
+ " canary api-catalog <sub-command> Manage API catalog sources and endpoints",
467
+ " canary skill <name> Install an AI agent skill template"
468
+ ];
469
+ lines.push(" canary release <sub-command> Release QA gate (CI/CD)");
470
+ lines.push(
471
+ " canary application <sub-command> List and create applications, view linked repos (alias: property)",
472
+ " canary task <sub-command> Manage agent tasks (requires feature flag)",
473
+ " canary sandbox <sub-command> Manage sandbox templates and instances",
474
+ " canary attachment <sub-command> List, upload, and manage attachments",
475
+ " canary tag <sub-command> List, create, and assign tags",
476
+ " canary triage <sub-command> Read AI triage results for a test suite execution"
477
+ );
478
+ if (isSuperadmin) {
479
+ lines.push(
480
+ " canary debug-session [--env dev|local] [--json] Create browser debug session",
481
+ " canary psql <query> [--json] Execute read-only SQL",
482
+ " canary redis <command> [--json] Execute read-only Redis commands",
483
+ " canary docs <sub-command> Manage documentation pages",
484
+ " canary feature-flag <sub-command> Manage feature flags",
485
+ " canary knobs <sub-command> Manage knobs (global config)"
486
+ );
487
+ }
488
+ lines.push(
489
+ " canary auth doctor [--env <env>] Diagnose auth / corporate-proxy issues",
490
+ " canary upgrade Upgrade CLI to latest version",
491
+ " canary version Show version",
492
+ " canary help",
493
+ "",
494
+ "Test suite sub-commands:",
495
+ " run [options] Trigger a test suite and stream results",
496
+ " list [options] List recent test suites",
497
+ " get <id> [options] Show suite detail with runs",
498
+ " diagnostics <workflowId> <runId> Get failure diagnostic",
499
+ " steps <workflowId> <runId> Get workflow run steps",
500
+ "",
501
+ "Test suite run options:",
502
+ " --token <key> API key (or set CANARY_API_TOKEN)",
503
+ " --api-url <url> API URL (default: https://api.trycanary.ai)",
504
+ " --application <name|id> Target a specific application (alias: --property)",
505
+ " --environment <name|id> Target a specific environment",
506
+ " --tag <tag> Filter workflows by tag",
507
+ " --name-pattern <pat> Filter workflows by name pattern",
508
+ " --verbose, -v Show all events",
509
+ "",
510
+ "Login options:",
511
+ " --org <name> Select organization by name or ID (for multi-org users)",
512
+ "",
513
+ "Login environments:",
514
+ " Production: canary login",
515
+ " Dev: canary login --app-url https://app.dev.trycanary.ai --api-url https://api.dev.trycanary.ai",
516
+ " Local: canary login --app-url http://localhost:5173 --api-url http://localhost:3000",
517
+ "",
518
+ " Or set CANARY_API_URL env var for non-production environments:",
519
+ " export CANARY_API_URL=http://localhost:3000"
520
+ );
521
+ lines.push(
522
+ "",
523
+ "Debug options:",
524
+ " --to-step <N> Stop after step N (1-based, default: all)",
525
+ " --env <env> Environment (local, dev, prod)",
526
+ " --verbose, -v Show all SSE events",
527
+ "",
528
+ "Issues sub-commands:",
529
+ " list [options] List and search issues",
530
+ " get <issueId> [options] Get issue detail with diagnostics",
531
+ "",
532
+ "Issues options:",
533
+ " --search <query> Full-text search",
534
+ " --severity <level> Filter: low, medium, high, unknown",
535
+ " --status <statuses> Filter: open, closed, not_a_bug (comma-separated)",
536
+ " --application-id <uuid> Filter by application (alias: --property-id)",
537
+ " --page <n> Page number (default: 1)",
538
+ " --page-size <n> Page size (default: 25)",
539
+ " --json Output raw JSON",
540
+ " --format markdown Output as markdown",
541
+ "",
542
+ "Release sub-commands:",
543
+ " trigger --application-id <uuid> Trigger a Release QA run (alias: --property-id)",
544
+ " status <run-id> [--json] Check run status",
545
+ " run --application-id <uuid> [--timeout N] Trigger and poll until complete",
546
+ "",
547
+ "Record options:",
548
+ " --credential <id> Credential ID (skip interactive selection)",
549
+ " --url <startUrl> URL to navigate to after launch",
550
+ " --output <dir> Local output directory (default: temp dir)",
551
+ " --env <env> Environment (local, dev, prod)",
552
+ " --no-upload Save locally only, skip API upload",
553
+ ""
554
+ );
555
+ if (isSuperadmin) {
556
+ lines.push(
557
+ "",
558
+ "PSQL options:",
559
+ " --json Output results as JSON",
560
+ " --query <sql> SQL query (alternative to positional)",
561
+ "",
562
+ "Redis options:",
563
+ " --json Output results as JSON",
564
+ "",
565
+ "Feature flag sub-commands:",
566
+ " list List all flags",
567
+ " create <name> [--description <text>] Create a flag",
568
+ " delete <name> Delete a flag and its gates",
569
+ " enable <name> --org <orgId> Enable for an org",
570
+ " disable <name> --org <orgId> Disable for an org",
571
+ " lifecycle <name> --stage <stage> [--final-value true|false]",
572
+ " Set lifecycle metadata",
573
+ "",
574
+ "Knobs sub-commands:",
575
+ " list List all knobs",
576
+ " get <key> Get a knob value",
577
+ " set <key> <value> --type <type> Set a knob value",
578
+ " delete <key> Delete a knob",
579
+ " toggle <key> Toggle a boolean knob",
580
+ " lifecycle <key> --stage <stage> [--final-value <value>]",
581
+ " Set lifecycle metadata"
582
+ );
583
+ }
584
+ lines.push("", "Flags:", " -h, --help Show help", " -V, --version Show version");
585
+ console.log(lines.join("\n"));
586
+ }
587
+ function printTestHelp() {
588
+ console.log(
589
+ [
590
+ `canary v${version}: Test command`,
591
+ "",
592
+ "\x1B[33m\u26A0 `canary test` is deprecated. Use `canary test-suite run` instead.\x1B[0m",
593
+ "",
594
+ "Usage:",
595
+ " canary test-suite run [options] Trigger a test suite and stream results",
596
+ " canary test-suite list List recent test suites",
597
+ " canary test-suite get <id> Show suite detail with runs",
598
+ "",
599
+ "Run options:",
600
+ " --token <key> API key (or set CANARY_API_TOKEN)",
601
+ " --api-url <url> API URL (default: https://api.trycanary.ai)",
602
+ " --application <name|id> Target a specific application (alias: --property)",
603
+ " --environment <name|id> Target a specific environment",
604
+ " --tag <tag> Filter workflows by tag",
605
+ " --name-pattern <pat> Filter workflows by name pattern",
606
+ " --verbose, -v Show all events",
607
+ "",
608
+ "Examples:",
609
+ " canary test-suite run Run all workflow tests",
610
+ " canary test-suite run --tag smoke Run smoke-tagged workflows",
611
+ ' canary test-suite run --property "My App" --environment staging'
612
+ ].join("\n")
613
+ );
614
+ }
615
+ var COMMANDS_WITH_UPDATE_CHECK = /* @__PURE__ */ new Set([
616
+ "test",
617
+ "login",
618
+ "orgs",
619
+ "issues",
620
+ "release",
621
+ "debug",
622
+ "record",
623
+ "session",
624
+ "local",
625
+ "workflow",
626
+ "credential",
627
+ "task",
628
+ "test-suite",
629
+ "skill",
630
+ "skills",
631
+ "sandbox",
632
+ "attachment",
633
+ "attachments",
634
+ "tag",
635
+ "tags",
636
+ "api-catalog"
637
+ ]);
638
+ var COMMANDS_WITH_HELP = /* @__PURE__ */ new Set([
639
+ "test",
640
+ "install",
641
+ "session",
642
+ "local",
643
+ "issues",
644
+ "credential",
645
+ "workflow",
646
+ "release",
647
+ "skill",
648
+ "skills",
649
+ "task",
650
+ "test-suite",
651
+ "sandbox",
652
+ "attachment",
653
+ "attachments",
654
+ "tag",
655
+ "tags",
656
+ "api-catalog"
657
+ ]);
658
+ async function resolveIsSuperadmin() {
659
+ const envToken = process4.env.CANARY_API_TOKEN;
660
+ if (envToken) return isSuperadminToken(envToken);
661
+ const tokens = await readAllStoredTokens();
662
+ return tokens.some((t) => isSuperadminToken(t));
663
+ }
664
+ function normalizeExitCode(value) {
665
+ if (typeof value === "number") return value;
666
+ if (typeof value === "string") {
667
+ const parsed = Number(value);
668
+ return Number.isFinite(parsed) ? parsed : 1;
669
+ }
670
+ return 0;
671
+ }
672
+ async function executeCommand(command, rest) {
673
+ if (command === "upgrade") {
674
+ const { runUpgrade } = await import("./upgrade-L2VYMP2V.js");
675
+ await runUpgrade();
676
+ return;
677
+ }
678
+ if (command === "test") {
679
+ if (rest.includes("--help") || rest.includes("-h")) {
680
+ printTestHelp();
681
+ return;
682
+ }
683
+ if (rest.includes("--remote")) {
684
+ console.warn(
685
+ "\x1B[33m\u26A0 `canary test --remote` is deprecated and will be removed in a future release.\x1B[0m"
686
+ );
687
+ console.warn(" Use `canary test-suite run` instead.\n");
688
+ const remoteArgs = rest.filter((arg) => arg !== "--remote");
689
+ await runRemoteTest(remoteArgs);
690
+ return;
691
+ }
692
+ console.error(
693
+ '`canary test` (local Playwright runner) has been removed.\nUse `canary test-suite run` for remote workflow tests.\n\nExamples:\n canary test-suite run\n canary test-suite run --tag smoke\n canary test-suite run --property "My App" --environment staging'
694
+ );
695
+ process4.exit(1);
696
+ }
697
+ if (command === "mcp") {
698
+ const runMcp = await loadMcp();
699
+ await runMcp(rest);
700
+ return;
701
+ }
702
+ if (command === "install") {
703
+ const { runInstall } = await import("./install-DXSNWZKO.js");
704
+ await runInstall(rest);
705
+ return;
706
+ }
707
+ if (command === "login") {
708
+ await runLogin(rest);
709
+ return;
710
+ }
711
+ if (command === "orgs") {
712
+ await runOrgs(rest);
713
+ return;
714
+ }
715
+ if (command === "debug") {
716
+ const runDebugWorkflow = await loadDebugWorkflow();
717
+ await runDebugWorkflow(rest);
718
+ return;
719
+ }
720
+ if (command === "record") {
721
+ const runRecord = await loadRecord();
722
+ await runRecord(rest);
723
+ return;
724
+ }
725
+ if (command === "session") {
726
+ const runSession = await loadSession();
727
+ await runSession(rest);
728
+ return;
729
+ }
730
+ if (command === "local") {
731
+ const runLocal = await loadLocal();
732
+ await runLocal(rest);
733
+ return;
734
+ }
735
+ if (command === "debug-session") {
736
+ await runDebugSession(rest);
737
+ return;
738
+ }
739
+ if (command === "psql") {
740
+ const { runPsql } = await import("./psql-BYUUNLGG.js");
741
+ await runPsql(rest);
742
+ return;
743
+ }
744
+ if (command === "redis") {
745
+ const { runRedis } = await import("./redis-35VBUYW7.js");
746
+ await runRedis(rest);
747
+ return;
748
+ }
749
+ if (command === "release") {
750
+ const { runRelease } = await import("./release-OOLTUBUT.js");
751
+ await runRelease(rest);
752
+ return;
753
+ }
754
+ if (command === "docs") {
755
+ const { runDocs } = await import("./docs-3SSORHB5.js");
756
+ await runDocs(rest);
757
+ return;
758
+ }
759
+ if (command === "feature-flag") {
760
+ const { runFeatureFlag } = await import("./feature-flag-T2LRZME3.js");
761
+ await runFeatureFlag(rest);
762
+ return;
763
+ }
764
+ if (command === "scenarios" || command === "scenario") {
765
+ const { runScenarios } = await import("./scenarios-GWLJEGHA.js");
766
+ await runScenarios(rest);
767
+ return;
768
+ }
769
+ if (command === "knobs") {
770
+ const { runKnobs } = await import("./knobs-NBINZIUB.js");
771
+ await runKnobs(rest);
772
+ return;
773
+ }
774
+ if (command === "issues") {
775
+ const { runIssues } = await import("./issues-XIZOPX6T.js");
776
+ await runIssues(rest);
777
+ return;
778
+ }
779
+ if (command === "credential") {
780
+ const { runCredential } = await import("./credential-COLTBV6D.js");
781
+ await runCredential(rest);
782
+ return;
783
+ }
784
+ if (command === "credential-template" || command === "credential-templates") {
785
+ const { runCredentialTemplate } = await import("./credential-template-EEPYFG7R.js");
786
+ await runCredentialTemplate(rest);
787
+ return;
788
+ }
789
+ if (command === "workflow") {
790
+ const { runWorkflow } = await import("./workflow-XYFH5LTP.js");
791
+ await runWorkflow(rest);
792
+ return;
793
+ }
794
+ if (command === "spec") {
795
+ const { resolveConfig: resolveConfig2 } = await import("./auth-EN6NQCJY.js");
796
+ const { handleSpec } = await import("./spec-RA3CFEKG.js");
797
+ const wantsAuth = rest[0] === "compile" || rest[0] === "pull" || rest[0] === "diff";
798
+ if (wantsAuth) {
799
+ const { apiUrl, token } = await resolveConfig2(rest);
800
+ await handleSpec(rest, apiUrl, token);
801
+ } else {
802
+ await handleSpec(rest, "", "");
803
+ }
804
+ return;
805
+ }
806
+ if (command === "api-catalog") {
807
+ const { resolveConfig: resolveConfig2 } = await import("./auth-EN6NQCJY.js");
808
+ const { runApiCatalog } = await import("./api-catalog-GFGCLVS4.js");
809
+ const { apiUrl, token } = await resolveConfig2(rest);
810
+ await runApiCatalog(rest, apiUrl, token);
811
+ return;
812
+ }
813
+ if (command === "skill" || command === "skills") {
814
+ const { runSkill } = await import("./skill-KM34LDMO.js");
815
+ await runSkill(rest);
816
+ return;
817
+ }
818
+ if (command === "task") {
819
+ const { runTask } = await import("./task-IQC3YR5K.js");
820
+ await runTask(rest);
821
+ return;
822
+ }
823
+ if (command === "test-suite") {
824
+ const { runTestSuite } = await import("./test-suite-DZNJFXDW.js");
825
+ await runTestSuite(rest);
826
+ return;
827
+ }
828
+ if (command === "triage") {
829
+ const { runTriage } = await import("./triage-ORG45R5W.js");
830
+ await runTriage(rest);
831
+ return;
832
+ }
833
+ if (command === "application" || command === "applications" || command === "property" || command === "properties") {
834
+ const { runProperty } = await import("./property-UXLOLPTD.js");
835
+ await runProperty(rest);
836
+ return;
837
+ }
838
+ if (command === "sandbox") {
839
+ const { runSandbox } = await import("./sandbox-XGSUU6G7.js");
840
+ await runSandbox(rest);
841
+ return;
842
+ }
843
+ if (command === "attachment" || command === "attachments") {
844
+ const { runAttachment } = await import("./attachment-SJC7D7FY.js");
845
+ await runAttachment(rest);
846
+ return;
847
+ }
848
+ if (command === "tag" || command === "tags") {
849
+ const { runTag } = await import("./tag-YY6YAABQ.js");
850
+ await runTag(rest);
851
+ return;
852
+ }
853
+ if (command === "trace") {
854
+ const { runTrace } = await import("./trace-HXIW7U2D.js");
855
+ await runTrace(rest);
856
+ return;
857
+ }
858
+ if (command === "auth") {
859
+ const sub = rest[0];
860
+ if (sub === "doctor") {
861
+ const { runAuthDoctor } = await import("./doctor-OTSIWV6G.js");
862
+ await runAuthDoctor(rest.slice(1));
863
+ return;
864
+ }
865
+ console.error("Usage: canary auth doctor [--env <env>]");
866
+ process4.exit(1);
867
+ }
868
+ console.log(`Unknown command "${command}".`);
869
+ printHelp({ isSuperadmin: await resolveIsSuperadmin() });
870
+ process4.exit(1);
871
+ }
872
+ async function main(argv) {
873
+ const wantsMachineOutput = argv.includes("--json") || argv.includes("--format");
874
+ if (argv[0] !== "mcp" && !wantsMachineOutput) {
875
+ installConsoleBranding();
876
+ }
877
+ if (argv.includes("--version") || argv.includes("-V")) {
878
+ printVersion();
879
+ return;
880
+ }
881
+ const [command, ...rest] = argv;
882
+ const hasHelpFlag = argv.includes("--help") || argv.includes("-h");
883
+ if (hasHelpFlag && (!command || !COMMANDS_WITH_HELP.has(command))) {
884
+ printHelp({ isSuperadmin: await resolveIsSuperadmin() });
885
+ return;
886
+ }
887
+ if (!command || command === "help") {
888
+ printHelp({ isSuperadmin: await resolveIsSuperadmin() });
889
+ return;
890
+ }
891
+ if (command === "version") {
892
+ printVersion();
893
+ return;
894
+ }
895
+ if (command && COMMANDS_WITH_UPDATE_CHECK.has(command)) {
896
+ await checkForUpdate(version);
897
+ }
898
+ let tracking = null;
899
+ try {
900
+ tracking = await createCliUserEventRecorder(argv, version);
901
+ } catch (error) {
902
+ await recordCliInstrumentationFailure(argv, version, "recorder-init", error);
903
+ }
904
+ const startedAt = Date.now();
905
+ const originalExit = process4.exit.bind(process4);
906
+ let finalExitCode = 0;
907
+ if (tracking) {
908
+ await tracking.recorder.recordCommandStarted(tracking.metadata);
909
+ }
910
+ process4.exit = ((code) => {
911
+ throw new ProcessExitSignal(code ?? normalizeExitCode(process4.exitCode));
912
+ });
913
+ try {
914
+ await executeCommand(command, rest);
915
+ finalExitCode = normalizeExitCode(process4.exitCode);
916
+ if (tracking) {
917
+ const metadata = {
918
+ ...tracking.metadata,
919
+ durationMs: Date.now() - startedAt,
920
+ exitCode: finalExitCode
921
+ };
922
+ if (finalExitCode === 0) {
923
+ await tracking.recorder.recordCommandCompleted(metadata);
924
+ } else {
925
+ await tracking.recorder.recordCommandFailed({
926
+ ...metadata,
927
+ errorKind: "exit-code"
928
+ });
929
+ }
930
+ }
931
+ } catch (error) {
932
+ if (error instanceof ProcessExitSignal) {
933
+ finalExitCode = error.exitCode;
934
+ if (tracking) {
935
+ const metadata = {
936
+ ...tracking.metadata,
937
+ durationMs: Date.now() - startedAt,
938
+ exitCode: finalExitCode
939
+ };
940
+ if (finalExitCode === 0) {
941
+ await tracking.recorder.recordCommandCompleted(metadata);
942
+ } else {
943
+ await tracking.recorder.recordCommandFailed({
944
+ ...metadata,
945
+ errorKind: "process-exit"
946
+ });
947
+ }
948
+ }
949
+ } else {
950
+ finalExitCode = normalizeExitCode(process4.exitCode) || 1;
951
+ if (tracking) {
952
+ await tracking.recorder.recordCommandFailed({
953
+ ...tracking.metadata,
954
+ durationMs: Date.now() - startedAt,
955
+ exitCode: finalExitCode,
956
+ errorKind: error instanceof Error ? error.name : typeof error,
957
+ errorName: error instanceof Error ? error.name : void 0,
958
+ errorMessage: error instanceof Error ? error.message : String(error),
959
+ reportToSentry: true,
960
+ sentryFingerprint: [
961
+ "canary-cli",
962
+ tracking.metadata.commandPath,
963
+ error instanceof Error ? error.name : typeof error
964
+ ]
965
+ });
966
+ }
967
+ throw error;
968
+ }
969
+ } finally {
970
+ process4.exit = originalExit;
971
+ }
972
+ if (finalExitCode !== 0) {
973
+ originalExit(finalExitCode);
974
+ }
975
+ }
976
+ if (import.meta.url === pathToFileURL(process4.argv[1]).href) {
977
+ void main(process4.argv.slice(2));
978
+ }
979
+ export {
980
+ main
981
+ };
982
+ //# sourceMappingURL=index.js.map