@canaryai/cli 0.2.3 → 0.2.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 (57) hide show
  1. package/dist/bin.js +1 -0
  2. package/dist/bin.js.map +1 -1
  3. package/dist/{chunk-DXJNFJ3A.js → chunk-6WWHXWCS.js} +3 -2
  4. package/dist/{chunk-DXJNFJ3A.js.map → chunk-6WWHXWCS.js.map} +1 -1
  5. package/dist/{chunk-HOYYXZPV.js → chunk-DXIAHB72.js} +3 -2
  6. package/dist/{chunk-HOYYXZPV.js.map → chunk-DXIAHB72.js.map} +1 -1
  7. package/dist/chunk-FIQBGAKW.js +373 -0
  8. package/dist/chunk-FIQBGAKW.js.map +1 -0
  9. package/dist/{chunk-JMI7WWPF.js → chunk-ILEPYWZX.js} +3 -2
  10. package/dist/{chunk-JMI7WWPF.js.map → chunk-ILEPYWZX.js.map} +1 -1
  11. package/dist/{chunk-7R4YFGP6.js → chunk-PWWQGYFG.js} +3 -1
  12. package/dist/{chunk-7R4YFGP6.js.map → chunk-PWWQGYFG.js.map} +1 -1
  13. package/dist/chunk-VLFUCAPZ.js +12 -0
  14. package/dist/{debug-workflow-PMLMWKWI.js → debug-workflow-PT3OUR3V.js} +5 -5
  15. package/dist/docs-GCYDTEOY.js +270 -0
  16. package/dist/docs-GCYDTEOY.js.map +1 -0
  17. package/dist/{feature-flag-D3QTHGL6.js → feature-flag-S5B5GLPP.js} +77 -33
  18. package/dist/feature-flag-S5B5GLPP.js.map +1 -0
  19. package/dist/index.js +26 -12
  20. package/dist/index.js.map +1 -1
  21. package/dist/{issues-6MHRFKTU.js → issues-4ZEDHPLW.js} +5 -4
  22. package/dist/{issues-6MHRFKTU.js.map → issues-4ZEDHPLW.js.map} +1 -1
  23. package/dist/{knobs-ED6LXBVM.js → knobs-RKUVK3HC.js} +5 -4
  24. package/dist/{knobs-ED6LXBVM.js.map → knobs-RKUVK3HC.js.map} +1 -1
  25. package/dist/{local-browser-YSE3XCUW.js → local-browser-J6WGFLVD.js} +5 -5
  26. package/dist/mcp-HGYBMDYZ.js +687 -0
  27. package/dist/mcp-HGYBMDYZ.js.map +1 -0
  28. package/dist/{psql-U5LF6ELS.js → psql-WVIHMC6A.js} +4 -3
  29. package/dist/{psql-U5LF6ELS.js.map → psql-WVIHMC6A.js.map} +1 -1
  30. package/dist/record-X4SVNYP3.js +334 -0
  31. package/dist/record-X4SVNYP3.js.map +1 -0
  32. package/dist/{redis-PBQZGU6T.js → redis-RGHECKV5.js} +4 -3
  33. package/dist/{redis-PBQZGU6T.js.map → redis-RGHECKV5.js.map} +1 -1
  34. package/dist/{release-QBSP474D.js → release-ZOD4Y2BF.js} +4 -3
  35. package/dist/{release-QBSP474D.js.map → release-ZOD4Y2BF.js.map} +1 -1
  36. package/dist/runner/preload.js +3 -2
  37. package/dist/runner/preload.js.map +1 -1
  38. package/dist/test.js +3 -2
  39. package/dist/test.js.map +1 -1
  40. package/package.json +2 -2
  41. package/dist/chunk-OE6O7H45.js +0 -92
  42. package/dist/chunk-OE6O7H45.js.map +0 -1
  43. package/dist/chunk-PLDDJCW6.js +0 -49
  44. package/dist/chunk-ZTWHPIXU.js +0 -42798
  45. package/dist/chunk-ZTWHPIXU.js.map +0 -1
  46. package/dist/dist-6NXLJYRZ.js +0 -335
  47. package/dist/dist-6NXLJYRZ.js.map +0 -1
  48. package/dist/feature-flag-D3QTHGL6.js.map +0 -1
  49. package/dist/mcp-LKHFYMA6.js +0 -385
  50. package/dist/mcp-LKHFYMA6.js.map +0 -1
  51. package/dist/pdf-extract-YIDRKYUD.js +0 -12
  52. package/dist/pdf-extract-YIDRKYUD.js.map +0 -1
  53. package/dist/pdfjs-44AOKLEM.js +0 -35242
  54. package/dist/pdfjs-44AOKLEM.js.map +0 -1
  55. /package/dist/{chunk-PLDDJCW6.js.map → chunk-VLFUCAPZ.js.map} +0 -0
  56. /package/dist/{debug-workflow-PMLMWKWI.js.map → debug-workflow-PT3OUR3V.js.map} +0 -0
  57. /package/dist/{local-browser-YSE3XCUW.js.map → local-browser-J6WGFLVD.js.map} +0 -0
@@ -0,0 +1,270 @@
1
+ import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
2
+ import {
3
+ apiRequest,
4
+ fetchList
5
+ } from "./chunk-6WWHXWCS.js";
6
+ import {
7
+ getArgValue,
8
+ hasFlag,
9
+ resolveConfig
10
+ } from "./chunk-PWWQGYFG.js";
11
+ import "./chunk-VLFUCAPZ.js";
12
+
13
+ // src/docs.ts
14
+ import { readFile, writeFile, mkdir } from "fs/promises";
15
+ import path from "path";
16
+ import process from "process";
17
+ var DEFAULT_PULL_DIR = "/tmp/canary-docs";
18
+ async function handleList(argv, apiUrl, token) {
19
+ const jsonOutput = hasFlag(argv, "--json");
20
+ const pages = await fetchList(apiUrl, token, "/public/docs/pages", "pages");
21
+ if (jsonOutput) {
22
+ console.log(JSON.stringify(pages, null, 2));
23
+ return;
24
+ }
25
+ if (pages.length === 0) {
26
+ console.log("No documentation pages found.");
27
+ return;
28
+ }
29
+ for (const page of pages) {
30
+ const date = new Date(page.updatedAt).toISOString().slice(0, 10);
31
+ const by = page.publishedBy ? ` (${page.publishedBy})` : "";
32
+ console.log(` ${page.slug} ${page.title} [${date}${by}]`);
33
+ }
34
+ }
35
+ async function handleGet(argv, apiUrl, token) {
36
+ const slug = argv[0];
37
+ if (!slug || slug.startsWith("--")) {
38
+ console.error("Error: Missing slug.");
39
+ console.error("Usage: canary docs get <slug>");
40
+ process.exit(1);
41
+ }
42
+ const res = await fetch(`${apiUrl}/public/docs/pages/raw?slug=${encodeURIComponent(slug)}`, {
43
+ headers: { Authorization: `Bearer ${token}` }
44
+ });
45
+ if (res.status === 404) {
46
+ console.error(`Error: Page not found: ${slug}`);
47
+ process.exit(1);
48
+ }
49
+ if (!res.ok) {
50
+ console.error(`Error: ${res.statusText}`);
51
+ process.exit(1);
52
+ }
53
+ const content = await res.text();
54
+ console.log(content);
55
+ }
56
+ async function handlePull(argv, apiUrl, token) {
57
+ const slug = argv[0];
58
+ if (!slug || slug.startsWith("--")) {
59
+ console.error("Error: Missing slug.");
60
+ console.error("Usage: canary docs pull <slug> [--output <path>]");
61
+ process.exit(1);
62
+ }
63
+ const outputPath = getArgValue(argv, "--output") ?? path.join(DEFAULT_PULL_DIR, `${slug}.md`);
64
+ const res = await fetch(`${apiUrl}/public/docs/pages/raw?slug=${encodeURIComponent(slug)}`, {
65
+ headers: { Authorization: `Bearer ${token}` }
66
+ });
67
+ if (res.status === 404) {
68
+ console.error(`Error: Page not found: ${slug}`);
69
+ process.exit(1);
70
+ }
71
+ if (!res.ok) {
72
+ console.error(`Error: ${res.statusText}`);
73
+ process.exit(1);
74
+ }
75
+ const content = await res.text();
76
+ await mkdir(path.dirname(outputPath), { recursive: true });
77
+ await writeFile(outputPath, content, "utf8");
78
+ console.log(`Pulled ${slug} \u2192 ${outputPath}`);
79
+ }
80
+ async function handlePush(argv, apiUrl, token) {
81
+ const slug = argv[0];
82
+ if (!slug || slug.startsWith("--")) {
83
+ console.error("Error: Missing slug.");
84
+ console.error("Usage: canary docs push <slug> --file <path> [--message <text>]");
85
+ process.exit(1);
86
+ }
87
+ const filePath = getArgValue(argv, "--file");
88
+ if (!filePath) {
89
+ console.error("Error: Missing --file <path>.");
90
+ process.exit(1);
91
+ }
92
+ const message = getArgValue(argv, "--message") ?? void 0;
93
+ const createdBy = getArgValue(argv, "--created-by") ?? void 0;
94
+ let content;
95
+ try {
96
+ content = await readFile(filePath, "utf8");
97
+ } catch {
98
+ console.error(`Error: Could not read file: ${filePath}`);
99
+ process.exit(1);
100
+ }
101
+ const result = await apiRequest(
102
+ apiUrl,
103
+ token,
104
+ "PUT",
105
+ `/superadmin/docs/pages?slug=${encodeURIComponent(slug)}`,
106
+ { content, message, createdBy }
107
+ );
108
+ if (!result.ok) {
109
+ console.error(`Error: ${result.error}`);
110
+ process.exit(1);
111
+ }
112
+ console.log(`Published new version of ${slug}`);
113
+ }
114
+ async function handleHistory(argv, apiUrl, token) {
115
+ const slug = argv[0];
116
+ if (!slug || slug.startsWith("--")) {
117
+ console.error("Error: Missing slug.");
118
+ console.error("Usage: canary docs history <slug>");
119
+ process.exit(1);
120
+ }
121
+ const jsonOutput = hasFlag(argv, "--json");
122
+ const res = await fetch(
123
+ `${apiUrl}/public/docs/pages/versions?slug=${encodeURIComponent(slug)}`,
124
+ { headers: { Authorization: `Bearer ${token}` } }
125
+ );
126
+ if (!res.ok) {
127
+ const body2 = await res.json().catch(() => ({ error: res.statusText }));
128
+ console.error(`Error: ${body2.error ?? res.statusText}`);
129
+ process.exit(1);
130
+ }
131
+ const body = await res.json();
132
+ const versions = body.data?.versions ?? [];
133
+ if (jsonOutput) {
134
+ console.log(JSON.stringify(versions, null, 2));
135
+ return;
136
+ }
137
+ if (versions.length === 0) {
138
+ console.log(`No versions found for ${slug}.`);
139
+ return;
140
+ }
141
+ for (const v of versions) {
142
+ const date = new Date(v.createdAt).toISOString().slice(0, 19).replace("T", " ");
143
+ const msg = v.message ? ` \u2014 ${v.message}` : "";
144
+ console.log(` v${v.version} ${date} ${v.createdBy}${msg}`);
145
+ }
146
+ }
147
+ async function handleCreate(argv, apiUrl, token) {
148
+ const slug = argv[0];
149
+ if (!slug || slug.startsWith("--")) {
150
+ console.error("Error: Missing slug.");
151
+ console.error("Usage: canary docs create <slug> --file <path> --title <text>");
152
+ process.exit(1);
153
+ }
154
+ const filePath = getArgValue(argv, "--file");
155
+ const title = getArgValue(argv, "--title");
156
+ if (!filePath) {
157
+ console.error("Error: Missing --file <path>.");
158
+ process.exit(1);
159
+ }
160
+ if (!title) {
161
+ console.error("Error: Missing --title <text>.");
162
+ process.exit(1);
163
+ }
164
+ const description = getArgValue(argv, "--description") ?? void 0;
165
+ const message = getArgValue(argv, "--message") ?? void 0;
166
+ let content;
167
+ try {
168
+ content = await readFile(filePath, "utf8");
169
+ } catch {
170
+ console.error(`Error: Could not read file: ${filePath}`);
171
+ process.exit(1);
172
+ }
173
+ const result = await apiRequest(apiUrl, token, "POST", "/superadmin/docs/pages", {
174
+ slug,
175
+ title,
176
+ description,
177
+ content,
178
+ message
179
+ });
180
+ if (!result.ok) {
181
+ console.error(`Error: ${result.error}`);
182
+ process.exit(1);
183
+ }
184
+ console.log(`Created page: ${slug}`);
185
+ }
186
+ async function handleDelete(argv, apiUrl, token) {
187
+ const slug = argv[0];
188
+ if (!slug || slug.startsWith("--")) {
189
+ console.error("Error: Missing slug.");
190
+ console.error("Usage: canary docs delete <slug>");
191
+ process.exit(1);
192
+ }
193
+ const result = await apiRequest(
194
+ apiUrl,
195
+ token,
196
+ "DELETE",
197
+ `/superadmin/docs/pages?slug=${encodeURIComponent(slug)}`
198
+ );
199
+ if (!result.ok) {
200
+ console.error(`Error: ${result.error}`);
201
+ process.exit(1);
202
+ }
203
+ console.log(`Deleted page: ${slug}`);
204
+ }
205
+ function printDocsHelp() {
206
+ console.log(
207
+ [
208
+ "Usage: canary docs <sub-command> [options]",
209
+ "",
210
+ "Sub-commands:",
211
+ " list List all doc pages",
212
+ " get <slug> Print content to stdout",
213
+ " pull <slug> [--output <path>] Download to local file",
214
+ " push <slug> --file <path> [--message] Publish new version",
215
+ " history <slug> Show version history",
216
+ " create <slug> --file <path> --title ... Create new page",
217
+ " delete <slug> Soft-delete a page",
218
+ "",
219
+ "Options:",
220
+ " --file <path> Path to markdown file",
221
+ " --title <text> Page title (create only)",
222
+ " --description <text> Page description (create only)",
223
+ " --message <text> Version commit message",
224
+ " --output <path> Output path for pull (default: /tmp/canary-docs/<slug>.md)",
225
+ " --json Output as JSON (list, history)",
226
+ " --env <env> Target environment (prod, dev)",
227
+ " --api-url <url> API URL override",
228
+ " --token <key> API token override"
229
+ ].join("\n")
230
+ );
231
+ }
232
+ async function runDocs(argv) {
233
+ const [subCommand, ...rest] = argv;
234
+ if (!subCommand || subCommand === "help" || hasFlag(argv, "--help", "-h")) {
235
+ printDocsHelp();
236
+ return;
237
+ }
238
+ const { apiUrl, token } = await resolveConfig(argv);
239
+ switch (subCommand) {
240
+ case "list":
241
+ await handleList(rest, apiUrl, token);
242
+ break;
243
+ case "get":
244
+ await handleGet(rest, apiUrl, token);
245
+ break;
246
+ case "pull":
247
+ await handlePull(rest, apiUrl, token);
248
+ break;
249
+ case "push":
250
+ await handlePush(rest, apiUrl, token);
251
+ break;
252
+ case "history":
253
+ await handleHistory(rest, apiUrl, token);
254
+ break;
255
+ case "create":
256
+ await handleCreate(rest, apiUrl, token);
257
+ break;
258
+ case "delete":
259
+ await handleDelete(rest, apiUrl, token);
260
+ break;
261
+ default:
262
+ console.error(`Unknown sub-command: ${subCommand}`);
263
+ printDocsHelp();
264
+ process.exit(1);
265
+ }
266
+ }
267
+ export {
268
+ runDocs
269
+ };
270
+ //# sourceMappingURL=docs-GCYDTEOY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/docs.ts"],"sourcesContent":["/**\n * CLI Documentation Management\n *\n * Allows agents and superadmins to list, pull, edit, and push documentation pages.\n */\n\nimport { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { resolveConfig, getArgValue, hasFlag } from \"./auth.js\";\nimport { apiRequest, fetchList } from \"./cli-helpers.js\";\n\ntype DocsPageListItem = {\n slug: string;\n title: string;\n description: string | null;\n updatedAt: string;\n publishedBy: string | null;\n};\n\ntype DocsPageContent = {\n slug: string;\n path: string;\n title: string;\n description: string | null;\n content: string;\n checksum: string;\n updatedAt: string;\n publishedBy: string | null;\n};\n\ntype DocsVersionItem = {\n version: number;\n title: string;\n checksum: string;\n message: string | null;\n createdBy: string;\n createdAt: string;\n};\n\ntype DocsApiResponse = {\n ok: boolean;\n error?: string;\n data?: {\n slug?: string;\n title?: string;\n pages?: DocsPageListItem[];\n content?: string;\n versions?: DocsVersionItem[];\n };\n};\n\nconst DEFAULT_PULL_DIR = \"/tmp/canary-docs\";\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, \"--json\");\n const pages = await fetchList<DocsPageListItem>(apiUrl, token, \"/public/docs/pages\", \"pages\");\n\n if (jsonOutput) {\n console.log(JSON.stringify(pages, null, 2));\n return;\n }\n\n if (pages.length === 0) {\n console.log(\"No documentation pages found.\");\n return;\n }\n\n for (const page of pages) {\n const date = new Date(page.updatedAt).toISOString().slice(0, 10);\n const by = page.publishedBy ? ` (${page.publishedBy})` : \"\";\n console.log(` ${page.slug} ${page.title} [${date}${by}]`);\n }\n}\n\nasync function handleGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const slug = argv[0];\n if (!slug || slug.startsWith(\"--\")) {\n console.error(\"Error: Missing slug.\");\n console.error(\"Usage: canary docs get <slug>\");\n process.exit(1);\n }\n\n const res = await fetch(`${apiUrl}/public/docs/pages/raw?slug=${encodeURIComponent(slug)}`, {\n headers: { Authorization: `Bearer ${token}` },\n });\n\n if (res.status === 404) {\n console.error(`Error: Page not found: ${slug}`);\n process.exit(1);\n }\n\n if (!res.ok) {\n console.error(`Error: ${res.statusText}`);\n process.exit(1);\n }\n\n const content = await res.text();\n console.log(content);\n}\n\nasync function handlePull(argv: string[], apiUrl: string, token: string): Promise<void> {\n const slug = argv[0];\n if (!slug || slug.startsWith(\"--\")) {\n console.error(\"Error: Missing slug.\");\n console.error(\"Usage: canary docs pull <slug> [--output <path>]\");\n process.exit(1);\n }\n\n const outputPath = getArgValue(argv, \"--output\") ?? path.join(DEFAULT_PULL_DIR, `${slug}.md`);\n\n const res = await fetch(`${apiUrl}/public/docs/pages/raw?slug=${encodeURIComponent(slug)}`, {\n headers: { Authorization: `Bearer ${token}` },\n });\n\n if (res.status === 404) {\n console.error(`Error: Page not found: ${slug}`);\n process.exit(1);\n }\n\n if (!res.ok) {\n console.error(`Error: ${res.statusText}`);\n process.exit(1);\n }\n\n const content = await res.text();\n await mkdir(path.dirname(outputPath), { recursive: true });\n await writeFile(outputPath, content, \"utf8\");\n console.log(`Pulled ${slug} → ${outputPath}`);\n}\n\nasync function handlePush(argv: string[], apiUrl: string, token: string): Promise<void> {\n const slug = argv[0];\n if (!slug || slug.startsWith(\"--\")) {\n console.error(\"Error: Missing slug.\");\n console.error(\"Usage: canary docs push <slug> --file <path> [--message <text>]\");\n process.exit(1);\n }\n\n const filePath = getArgValue(argv, \"--file\");\n if (!filePath) {\n console.error(\"Error: Missing --file <path>.\");\n process.exit(1);\n }\n\n const message = getArgValue(argv, \"--message\") ?? undefined;\n const createdBy = getArgValue(argv, \"--created-by\") ?? undefined;\n\n let content: string;\n try {\n content = await readFile(filePath, \"utf8\");\n } catch {\n console.error(`Error: Could not read file: ${filePath}`);\n process.exit(1);\n }\n\n const result = await apiRequest<DocsApiResponse>(\n apiUrl,\n token,\n \"PUT\",\n `/superadmin/docs/pages?slug=${encodeURIComponent(slug)}`,\n { content, message, createdBy }\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Published new version of ${slug}`);\n}\n\nasync function handleHistory(argv: string[], apiUrl: string, token: string): Promise<void> {\n const slug = argv[0];\n if (!slug || slug.startsWith(\"--\")) {\n console.error(\"Error: Missing slug.\");\n console.error(\"Usage: canary docs history <slug>\");\n process.exit(1);\n }\n\n const jsonOutput = hasFlag(argv, \"--json\");\n\n const res = await fetch(\n `${apiUrl}/public/docs/pages/versions?slug=${encodeURIComponent(slug)}`,\n { headers: { Authorization: `Bearer ${token}` } }\n );\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({ error: res.statusText }));\n console.error(`Error: ${(body as { error?: string }).error ?? res.statusText}`);\n process.exit(1);\n }\n\n const body = (await res.json()) as DocsApiResponse;\n const versions = body.data?.versions ?? [];\n\n if (jsonOutput) {\n console.log(JSON.stringify(versions, null, 2));\n return;\n }\n\n if (versions.length === 0) {\n console.log(`No versions found for ${slug}.`);\n return;\n }\n\n for (const v of versions) {\n const date = new Date(v.createdAt).toISOString().slice(0, 19).replace(\"T\", \" \");\n const msg = v.message ? ` — ${v.message}` : \"\";\n console.log(` v${v.version} ${date} ${v.createdBy}${msg}`);\n }\n}\n\nasync function handleCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const slug = argv[0];\n if (!slug || slug.startsWith(\"--\")) {\n console.error(\"Error: Missing slug.\");\n console.error(\"Usage: canary docs create <slug> --file <path> --title <text>\");\n process.exit(1);\n }\n\n const filePath = getArgValue(argv, \"--file\");\n const title = getArgValue(argv, \"--title\");\n\n if (!filePath) {\n console.error(\"Error: Missing --file <path>.\");\n process.exit(1);\n }\n if (!title) {\n console.error(\"Error: Missing --title <text>.\");\n process.exit(1);\n }\n\n const description = getArgValue(argv, \"--description\") ?? undefined;\n const message = getArgValue(argv, \"--message\") ?? undefined;\n\n let content: string;\n try {\n content = await readFile(filePath, \"utf8\");\n } catch {\n console.error(`Error: Could not read file: ${filePath}`);\n process.exit(1);\n }\n\n const result = await apiRequest<DocsApiResponse>(apiUrl, token, \"POST\", \"/superadmin/docs/pages\", {\n slug,\n title,\n description,\n content,\n message,\n });\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Created page: ${slug}`);\n}\n\nasync function handleDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const slug = argv[0];\n if (!slug || slug.startsWith(\"--\")) {\n console.error(\"Error: Missing slug.\");\n console.error(\"Usage: canary docs delete <slug>\");\n process.exit(1);\n }\n\n const result = await apiRequest<DocsApiResponse>(\n apiUrl,\n token,\n \"DELETE\",\n `/superadmin/docs/pages?slug=${encodeURIComponent(slug)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Deleted page: ${slug}`);\n}\n\nfunction printDocsHelp(): void {\n console.log(\n [\n \"Usage: canary docs <sub-command> [options]\",\n \"\",\n \"Sub-commands:\",\n \" list List all doc pages\",\n \" get <slug> Print content to stdout\",\n \" pull <slug> [--output <path>] Download to local file\",\n \" push <slug> --file <path> [--message] Publish new version\",\n \" history <slug> Show version history\",\n \" create <slug> --file <path> --title ... Create new page\",\n \" delete <slug> Soft-delete a page\",\n \"\",\n \"Options:\",\n \" --file <path> Path to markdown file\",\n \" --title <text> Page title (create only)\",\n \" --description <text> Page description (create only)\",\n \" --message <text> Version commit message\",\n \" --output <path> Output path for pull (default: /tmp/canary-docs/<slug>.md)\",\n \" --json Output as JSON (list, history)\",\n \" --env <env> Target environment (prod, dev)\",\n \" --api-url <url> API URL override\",\n \" --token <key> API token override\",\n ].join(\"\\n\")\n );\n}\n\nexport async function runDocs(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === \"help\" || hasFlag(argv, \"--help\", \"-h\")) {\n printDocsHelp();\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n switch (subCommand) {\n case \"list\":\n await handleList(rest, apiUrl, token);\n break;\n case \"get\":\n await handleGet(rest, apiUrl, token);\n break;\n case \"pull\":\n await handlePull(rest, apiUrl, token);\n break;\n case \"push\":\n await handlePush(rest, apiUrl, token);\n break;\n case \"history\":\n await handleHistory(rest, apiUrl, token);\n break;\n case \"create\":\n await handleCreate(rest, apiUrl, token);\n break;\n case \"delete\":\n await handleDelete(rest, apiUrl, token);\n break;\n default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printDocsHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":["body"]}
@@ -1,15 +1,16 @@
1
+ import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
1
2
  import {
2
3
  apiRequest,
3
4
  fetchList,
4
5
  parseLifecycleStage,
5
6
  toLifecycleLabel
6
- } from "./chunk-DXJNFJ3A.js";
7
+ } from "./chunk-6WWHXWCS.js";
7
8
  import {
8
9
  getArgValue,
9
10
  hasFlag,
10
11
  resolveConfig
11
- } from "./chunk-7R4YFGP6.js";
12
- import "./chunk-PLDDJCW6.js";
12
+ } from "./chunk-PWWQGYFG.js";
13
+ import "./chunk-VLFUCAPZ.js";
13
14
 
14
15
  // src/feature-flag.ts
15
16
  import process from "process";
@@ -29,9 +30,10 @@ async function handleList(argv, apiUrl, token) {
29
30
  }
30
31
  for (const flag of flags) {
31
32
  const orgCount = flag.organizations?.length ?? 0;
33
+ const userCount = flag.users?.length ?? 0;
32
34
  const lifecycle = `lifecycle=${toLifecycleLabel(flag.lifecycleStage)}`;
33
35
  const finalValue = flag.lifecycleStage === "active" ? "" : ` final=${flag.finalValue === true ? "true" : "false"}`;
34
- console.log(` ${flag.name} ${flag.description ?? ""} (${lifecycle}${finalValue}) [orgs=${orgCount}]`);
36
+ console.log(` ${flag.name} ${flag.description ?? ""} (${lifecycle}${finalValue}) [orgs=${orgCount}, users=${userCount}]`);
35
37
  }
36
38
  }
37
39
  async function handleCreate(argv, apiUrl, token) {
@@ -74,52 +76,90 @@ async function handleDelete(argv, apiUrl, token) {
74
76
  async function handleEnable(argv, apiUrl, token) {
75
77
  const name = argv[0];
76
78
  const orgId = getArgValue(argv, "--org");
79
+ const userId = getArgValue(argv, "--user");
77
80
  if (!name || name.startsWith("--")) {
78
81
  console.error("Error: Missing flag name.");
79
- console.error("Usage: canary feature-flag enable <name> --org <orgId>");
82
+ console.error("Usage: canary feature-flag enable <name> (--org <orgId> | --user <userId>)");
80
83
  process.exit(1);
81
84
  }
82
- if (!orgId) {
83
- console.error("Error: Missing --org <orgId>.");
84
- console.error("Usage: canary feature-flag enable <name> --org <orgId>");
85
+ if (orgId && userId) {
86
+ console.error("Error: Provide either --org or --user, not both.");
85
87
  process.exit(1);
86
88
  }
87
- const result = await apiRequest(
88
- apiUrl,
89
- token,
90
- "POST",
91
- `/superadmin/feature-flags/${encodeURIComponent(name)}/organizations/${encodeURIComponent(orgId)}`
92
- );
93
- if (!result.ok) {
94
- console.error(`Error: ${result.error}`);
89
+ if (!orgId && !userId) {
90
+ console.error("Error: Provide either --org <orgId> or --user <userId>.");
91
+ console.error("Usage: canary feature-flag enable <name> (--org <orgId> | --user <userId>)");
95
92
  process.exit(1);
96
93
  }
97
- console.log(`Enabled ${name} for org ${orgId}`);
94
+ if (orgId) {
95
+ const result = await apiRequest(
96
+ apiUrl,
97
+ token,
98
+ "POST",
99
+ `/superadmin/feature-flags/${encodeURIComponent(name)}/organizations/${encodeURIComponent(orgId)}`
100
+ );
101
+ if (!result.ok) {
102
+ console.error(`Error: ${result.error}`);
103
+ process.exit(1);
104
+ }
105
+ console.log(`Enabled ${name} for org ${orgId}`);
106
+ } else {
107
+ const result = await apiRequest(
108
+ apiUrl,
109
+ token,
110
+ "POST",
111
+ `/superadmin/feature-flags/${encodeURIComponent(name)}/users/${encodeURIComponent(userId)}`
112
+ );
113
+ if (!result.ok) {
114
+ console.error(`Error: ${result.error}`);
115
+ process.exit(1);
116
+ }
117
+ console.log(`Enabled ${name} for user ${userId}`);
118
+ }
98
119
  }
99
120
  async function handleDisable(argv, apiUrl, token) {
100
121
  const name = argv[0];
101
122
  const orgId = getArgValue(argv, "--org");
123
+ const userId = getArgValue(argv, "--user");
102
124
  if (!name || name.startsWith("--")) {
103
125
  console.error("Error: Missing flag name.");
104
- console.error("Usage: canary feature-flag disable <name> --org <orgId>");
126
+ console.error("Usage: canary feature-flag disable <name> (--org <orgId> | --user <userId>)");
105
127
  process.exit(1);
106
128
  }
107
- if (!orgId) {
108
- console.error("Error: Missing --org <orgId>.");
109
- console.error("Usage: canary feature-flag disable <name> --org <orgId>");
129
+ if (orgId && userId) {
130
+ console.error("Error: Provide either --org or --user, not both.");
110
131
  process.exit(1);
111
132
  }
112
- const result = await apiRequest(
113
- apiUrl,
114
- token,
115
- "DELETE",
116
- `/superadmin/feature-flags/${encodeURIComponent(name)}/organizations/${encodeURIComponent(orgId)}`
117
- );
118
- if (!result.ok) {
119
- console.error(`Error: ${result.error}`);
133
+ if (!orgId && !userId) {
134
+ console.error("Error: Provide either --org <orgId> or --user <userId>.");
135
+ console.error("Usage: canary feature-flag disable <name> (--org <orgId> | --user <userId>)");
120
136
  process.exit(1);
121
137
  }
122
- console.log(`Disabled ${name} for org ${orgId}`);
138
+ if (orgId) {
139
+ const result = await apiRequest(
140
+ apiUrl,
141
+ token,
142
+ "DELETE",
143
+ `/superadmin/feature-flags/${encodeURIComponent(name)}/organizations/${encodeURIComponent(orgId)}`
144
+ );
145
+ if (!result.ok) {
146
+ console.error(`Error: ${result.error}`);
147
+ process.exit(1);
148
+ }
149
+ console.log(`Disabled ${name} for org ${orgId}`);
150
+ } else {
151
+ const result = await apiRequest(
152
+ apiUrl,
153
+ token,
154
+ "DELETE",
155
+ `/superadmin/feature-flags/${encodeURIComponent(name)}/users/${encodeURIComponent(userId)}`
156
+ );
157
+ if (!result.ok) {
158
+ console.error(`Error: ${result.error}`);
159
+ process.exit(1);
160
+ }
161
+ console.log(`Disabled ${name} for user ${userId}`);
162
+ }
123
163
  }
124
164
  async function handleLifecycle(argv, apiUrl, token) {
125
165
  const name = argv[0];
@@ -180,14 +220,18 @@ function printFeatureFlagHelp() {
180
220
  " list List all feature flags",
181
221
  " create <name> [--description <text>] Create a new flag",
182
222
  " delete <name> Delete a flag and all its gates",
183
- " enable <name> --org <orgId> Enable a flag for an organization",
184
- " disable <name> --org <orgId> Disable a flag for an organization",
223
+ " enable <name> (--org <orgId> | --user <userId>)",
224
+ " Enable a flag for an org or user",
225
+ " disable <name> (--org <orgId> | --user <userId>)",
226
+ " Disable a flag for an org or user",
185
227
  " lifecycle <name> --stage <stage> [--final-value true|false]",
186
228
  " Mark lifecycle + final value",
187
229
  "",
188
230
  "Stages: active, deprecated, ready_for_cleanup",
189
231
  "",
190
232
  "Options:",
233
+ " --org <orgId> Target organization",
234
+ " --user <userId> Target user",
191
235
  " --final-value <true|false> Final value for deprecated/ready_for_cleanup",
192
236
  " --clear-final-value Clear final value (only valid with --stage active)",
193
237
  " --env <env> Target environment (prod, dev, local)",
@@ -232,4 +276,4 @@ async function runFeatureFlag(argv) {
232
276
  export {
233
277
  runFeatureFlag
234
278
  };
235
- //# sourceMappingURL=feature-flag-D3QTHGL6.js.map
279
+ //# sourceMappingURL=feature-flag-S5B5GLPP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/feature-flag.ts"],"sourcesContent":["/**\n * CLI Feature Flag Management\n *\n * Allows superadmins to manage feature flags via the CLI.\n */\n\nimport process from \"node:process\";\nimport { resolveConfig, getArgValue, hasFlag } from \"./auth.js\";\nimport {\n type LifecycleStage,\n toLifecycleLabel,\n parseLifecycleStage,\n apiRequest,\n fetchList,\n} from \"./cli-helpers.js\";\n\ntype FeatureFlag = {\n id: string;\n name: string;\n description: string | null;\n lifecycleStage: LifecycleStage;\n finalValue: boolean | null;\n createdAt: string;\n organizations?: Array<{\n gateId: string;\n orgId: string;\n orgName: string;\n createdAt: string;\n }>;\n users?: Array<{\n gateId: string;\n userId: string;\n userEmail: string | null;\n createdAt: string;\n }>;\n};\n\ntype FlagApiResponse = {\n ok: boolean;\n error?: string;\n flag?: FeatureFlag;\n};\n\nfunction fetchFlags(apiUrl: string, token: string): Promise<FeatureFlag[]> {\n return fetchList<FeatureFlag>(apiUrl, token, \"/superadmin/feature-flags\", \"flags\");\n}\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const jsonOutput = hasFlag(argv, \"--json\");\n const flags = await fetchFlags(apiUrl, token);\n\n if (jsonOutput) {\n console.log(JSON.stringify(flags, null, 2));\n return;\n }\n\n if (flags.length === 0) {\n console.log(\"No feature flags found.\");\n return;\n }\n\n for (const flag of flags) {\n const orgCount = flag.organizations?.length ?? 0;\n const userCount = flag.users?.length ?? 0;\n const lifecycle = `lifecycle=${toLifecycleLabel(flag.lifecycleStage)}`;\n const finalValue =\n flag.lifecycleStage === \"active\" ? \"\" : ` final=${flag.finalValue === true ? \"true\" : \"false\"}`;\n console.log(` ${flag.name} ${flag.description ?? \"\"} (${lifecycle}${finalValue}) [orgs=${orgCount}, users=${userCount}]`);\n }\n}\n\nasync function handleCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag create <name> [--description <text>]\");\n process.exit(1);\n }\n\n const description = getArgValue(argv, \"--description\") ?? null;\n const result = await apiRequest<FlagApiResponse>(apiUrl, token, \"POST\", \"/superadmin/feature-flags\", {\n name,\n description,\n });\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Created feature flag: ${name}`);\n}\n\nasync function handleDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag delete <name>\");\n process.exit(1);\n }\n\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"DELETE\", `/superadmin/feature-flags/${encodeURIComponent(name)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Deleted feature flag: ${name}`);\n}\n\nasync function handleEnable(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n const orgId = getArgValue(argv, \"--org\");\n const userId = getArgValue(argv, \"--user\");\n\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag enable <name> (--org <orgId> | --user <userId>)\");\n process.exit(1);\n }\n\n if (orgId && userId) {\n console.error(\"Error: Provide either --org or --user, not both.\");\n process.exit(1);\n }\n\n if (!orgId && !userId) {\n console.error(\"Error: Provide either --org <orgId> or --user <userId>.\");\n console.error(\"Usage: canary feature-flag enable <name> (--org <orgId> | --user <userId>)\");\n process.exit(1);\n }\n\n if (orgId) {\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"POST\",\n `/superadmin/feature-flags/${encodeURIComponent(name)}/organizations/${encodeURIComponent(orgId)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Enabled ${name} for org ${orgId}`);\n } else {\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"POST\",\n `/superadmin/feature-flags/${encodeURIComponent(name)}/users/${encodeURIComponent(userId!)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Enabled ${name} for user ${userId}`);\n }\n}\n\nasync function handleDisable(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n const orgId = getArgValue(argv, \"--org\");\n const userId = getArgValue(argv, \"--user\");\n\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag disable <name> (--org <orgId> | --user <userId>)\");\n process.exit(1);\n }\n\n if (orgId && userId) {\n console.error(\"Error: Provide either --org or --user, not both.\");\n process.exit(1);\n }\n\n if (!orgId && !userId) {\n console.error(\"Error: Provide either --org <orgId> or --user <userId>.\");\n console.error(\"Usage: canary feature-flag disable <name> (--org <orgId> | --user <userId>)\");\n process.exit(1);\n }\n\n if (orgId) {\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"DELETE\",\n `/superadmin/feature-flags/${encodeURIComponent(name)}/organizations/${encodeURIComponent(orgId)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Disabled ${name} for org ${orgId}`);\n } else {\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"DELETE\",\n `/superadmin/feature-flags/${encodeURIComponent(name)}/users/${encodeURIComponent(userId!)}`\n );\n\n if (!result.ok) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n console.log(`Disabled ${name} for user ${userId}`);\n }\n}\n\nasync function handleLifecycle(argv: string[], apiUrl: string, token: string): Promise<void> {\n const name = argv[0];\n\n if (!name || name.startsWith(\"--\")) {\n console.error(\"Error: Missing flag name.\");\n console.error(\"Usage: canary feature-flag lifecycle <name> --stage <active|deprecated|ready_for_cleanup> [--final-value true|false]\");\n process.exit(1);\n }\n\n const stage = parseLifecycleStage(argv);\n const rawFinalValue = getArgValue(argv, \"--final-value\");\n const clearFinalValue = hasFlag(argv, \"--clear-final-value\");\n\n if (rawFinalValue !== undefined && clearFinalValue) {\n console.error(\"Error: use either --final-value or --clear-final-value, not both.\");\n process.exit(1);\n }\n\n let finalValue: boolean | undefined = undefined;\n\n if (stage === \"active\") {\n if (rawFinalValue !== undefined) {\n console.error(\"Error: active stage does not accept --final-value.\");\n process.exit(1);\n }\n finalValue = undefined;\n } else {\n if (clearFinalValue) {\n console.error(\"Error: --clear-final-value can only be used with --stage active.\");\n process.exit(1);\n }\n if (!rawFinalValue) {\n console.error(\"Error: --final-value true|false is required for deprecated or ready_for_cleanup.\");\n process.exit(1);\n }\n if (rawFinalValue !== \"true\" && rawFinalValue !== \"false\") {\n console.error(\"Error: --final-value must be true or false.\");\n process.exit(1);\n }\n finalValue = rawFinalValue === \"true\";\n }\n\n const result = await apiRequest<FlagApiResponse>(\n apiUrl, token, \"POST\",\n `/superadmin/feature-flags/${encodeURIComponent(name)}/lifecycle`,\n { stage, finalValue }\n );\n\n if (!result.ok || !result.flag) {\n console.error(`Error: ${result.error ?? \"Failed to update lifecycle\"}`);\n process.exit(1);\n }\n\n const final =\n result.flag.lifecycleStage === \"active\"\n ? \"(none)\"\n : result.flag.finalValue === true\n ? \"true\"\n : \"false\";\n console.log(`Updated lifecycle for ${name}: stage=${toLifecycleLabel(result.flag.lifecycleStage)}, final=${final}`);\n}\n\nfunction printFeatureFlagHelp(): void {\n console.log(\n [\n \"Usage: canary feature-flag <sub-command> [options]\",\n \"\",\n \"Sub-commands:\",\n \" list List all feature flags\",\n \" create <name> [--description <text>] Create a new flag\",\n \" delete <name> Delete a flag and all its gates\",\n \" enable <name> (--org <orgId> | --user <userId>)\",\n \" Enable a flag for an org or user\",\n \" disable <name> (--org <orgId> | --user <userId>)\",\n \" Disable a flag for an org or user\",\n \" lifecycle <name> --stage <stage> [--final-value true|false]\",\n \" Mark lifecycle + final value\",\n \"\",\n \"Stages: active, deprecated, ready_for_cleanup\",\n \"\",\n \"Options:\",\n \" --org <orgId> Target organization\",\n \" --user <userId> Target user\",\n \" --final-value <true|false> Final value for deprecated/ready_for_cleanup\",\n \" --clear-final-value Clear final value (only valid with --stage active)\",\n \" --env <env> Target environment (prod, dev, local)\",\n \" --json Output as JSON (list only)\",\n \" --api-url <url> API URL override (takes precedence over --env)\",\n \" --token <key> API token override\",\n ].join(\"\\n\")\n );\n}\n\nexport async function runFeatureFlag(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === \"help\" || hasFlag(argv, \"--help\", \"-h\")) {\n printFeatureFlagHelp();\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n switch (subCommand) {\n case \"list\":\n await handleList(rest, apiUrl, token);\n break;\n case \"create\":\n await handleCreate(rest, apiUrl, token);\n break;\n case \"delete\":\n await handleDelete(rest, apiUrl, token);\n break;\n case \"enable\":\n await handleEnable(rest, apiUrl, token);\n break;\n case \"disable\":\n await handleDisable(rest, apiUrl, token);\n break;\n case \"lifecycle\":\n await handleLifecycle(rest, apiUrl, token);\n break;\n default:\n console.error(`Unknown sub-command: ${subCommand}`);\n printFeatureFlagHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.js CHANGED
@@ -1,10 +1,11 @@
1
+ import { createRequire as __cr } from "module"; const require = __cr(import.meta.url);
1
2
  import {
2
3
  connectTunnel,
3
4
  createLocalRun,
4
5
  createTunnel,
5
6
  runLocalTest,
6
7
  runTunnel
7
- } from "./chunk-HOYYXZPV.js";
8
+ } from "./chunk-DXIAHB72.js";
8
9
  import {
9
10
  ENV_URLS,
10
11
  envToProfile,
@@ -15,10 +16,10 @@ import {
15
16
  readStoredToken,
16
17
  resolveConfig,
17
18
  saveAuth
18
- } from "./chunk-7R4YFGP6.js";
19
+ } from "./chunk-PWWQGYFG.js";
19
20
  import {
20
21
  __require
21
- } from "./chunk-PLDDJCW6.js";
22
+ } from "./chunk-VLFUCAPZ.js";
22
23
 
23
24
  // src/index.ts
24
25
  import { spawnSync as spawnSync2 } from "child_process";
@@ -909,9 +910,10 @@ function isSuperadminToken(token) {
909
910
  // src/index.ts
910
911
  var require2 = createRequire2(import.meta.url);
911
912
  var pkg = require2("../package.json");
912
- var loadMcp = () => import("./mcp-LKHFYMA6.js").then((m) => m.runMcp);
913
- var loadLocalBrowser = () => import("./local-browser-YSE3XCUW.js").then((m) => m.runLocalBrowser);
914
- var loadDebugWorkflow = () => import("./debug-workflow-PMLMWKWI.js").then((m) => m.runDebugWorkflow);
913
+ var loadMcp = () => import("./mcp-HGYBMDYZ.js").then((m) => m.runMcp);
914
+ var loadLocalBrowser = () => import("./local-browser-J6WGFLVD.js").then((m) => m.runLocalBrowser);
915
+ var loadDebugWorkflow = () => import("./debug-workflow-PT3OUR3V.js").then((m) => m.runDebugWorkflow);
916
+ var loadRecord = () => import("./record-X4SVNYP3.js").then((m) => m.runRecord);
915
917
  var canary = { run };
916
918
  var baseDir = typeof __dirname !== "undefined" ? __dirname : path4.dirname(fileURLToPath2(import.meta.url));
917
919
  var preloadPath = path4.join(baseDir, "runner", "preload.js");
@@ -955,6 +957,7 @@ function printHelp({ isSuperadmin }) {
955
957
  " canary login [--org <name>] [--app-url https://app.trycanary.ai] [--no-open]",
956
958
  " canary orgs List organizations",
957
959
  " canary debug <workflowId> [options] Debug workflow in local headed browser",
960
+ " canary record [options] Record browser interactions",
958
961
  " canary issues <sub-command> Search and view issues"
959
962
  ];
960
963
  lines.push(
@@ -965,6 +968,7 @@ function printHelp({ isSuperadmin }) {
965
968
  " canary debug-session [--env dev|local] [--json] Create browser debug session",
966
969
  " canary psql <query> [--json] Execute read-only SQL",
967
970
  " canary redis <command> [--json] Execute read-only Redis commands",
971
+ " canary docs <sub-command> Manage documentation pages",
968
972
  " canary feature-flag <sub-command> Manage feature flags",
969
973
  " canary knobs <sub-command> Manage knobs (global config)"
970
974
  );
@@ -1169,37 +1173,47 @@ async function main(argv) {
1169
1173
  await runDebugWorkflow(rest);
1170
1174
  return;
1171
1175
  }
1176
+ if (command === "record") {
1177
+ const runRecord = await loadRecord();
1178
+ await runRecord(rest);
1179
+ return;
1180
+ }
1172
1181
  if (command === "debug-session") {
1173
1182
  await runDebugSession(rest);
1174
1183
  return;
1175
1184
  }
1176
1185
  if (command === "psql") {
1177
- const { runPsql } = await import("./psql-U5LF6ELS.js");
1186
+ const { runPsql } = await import("./psql-WVIHMC6A.js");
1178
1187
  await runPsql(rest);
1179
1188
  return;
1180
1189
  }
1181
1190
  if (command === "redis") {
1182
- const { runRedis } = await import("./redis-PBQZGU6T.js");
1191
+ const { runRedis } = await import("./redis-RGHECKV5.js");
1183
1192
  await runRedis(rest);
1184
1193
  return;
1185
1194
  }
1186
1195
  if (command === "release") {
1187
- const { runRelease } = await import("./release-QBSP474D.js");
1196
+ const { runRelease } = await import("./release-ZOD4Y2BF.js");
1188
1197
  await runRelease(rest);
1189
1198
  return;
1190
1199
  }
1200
+ if (command === "docs") {
1201
+ const { runDocs } = await import("./docs-GCYDTEOY.js");
1202
+ await runDocs(rest);
1203
+ return;
1204
+ }
1191
1205
  if (command === "feature-flag") {
1192
- const { runFeatureFlag } = await import("./feature-flag-D3QTHGL6.js");
1206
+ const { runFeatureFlag } = await import("./feature-flag-S5B5GLPP.js");
1193
1207
  await runFeatureFlag(rest);
1194
1208
  return;
1195
1209
  }
1196
1210
  if (command === "knobs") {
1197
- const { runKnobs } = await import("./knobs-ED6LXBVM.js");
1211
+ const { runKnobs } = await import("./knobs-RKUVK3HC.js");
1198
1212
  await runKnobs(rest);
1199
1213
  return;
1200
1214
  }
1201
1215
  if (command === "issues") {
1202
- const { runIssues } = await import("./issues-6MHRFKTU.js");
1216
+ const { runIssues } = await import("./issues-4ZEDHPLW.js");
1203
1217
  await runIssues(rest);
1204
1218
  return;
1205
1219
  }