@insforge/cli 0.1.49 → 0.1.50

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.
package/dist/index.js CHANGED
@@ -5,7 +5,166 @@ import { readFileSync as readFileSync7 } from "fs";
5
5
  import { join as join9, dirname } from "path";
6
6
  import { fileURLToPath } from "url";
7
7
  import { Command } from "commander";
8
- import * as clack15 from "@clack/prompts";
8
+ import * as clack11 from "@clack/prompts";
9
+
10
+ // src/lib/prompts.ts
11
+ import * as readline from "readline";
12
+ import * as clack from "@clack/prompts";
13
+ var isInteractive = !!(process.stdin.isTTY && process.stdout.isTTY);
14
+ var LineReader = class {
15
+ constructor(input, output) {
16
+ this.output = output;
17
+ this.rl = readline.createInterface({ input });
18
+ this.rl.on("line", (line) => {
19
+ if (this.waiter) {
20
+ const w = this.waiter;
21
+ this.waiter = null;
22
+ w(line);
23
+ } else {
24
+ this.queue.push(line);
25
+ }
26
+ });
27
+ this.rl.on("close", () => {
28
+ this.closed = true;
29
+ if (this.waiter) {
30
+ const w = this.waiter;
31
+ this.waiter = null;
32
+ w(null);
33
+ }
34
+ });
35
+ }
36
+ queue = [];
37
+ waiter = null;
38
+ closed = false;
39
+ rl;
40
+ async readLine(prompt) {
41
+ this.output.write(prompt);
42
+ if (this.queue.length > 0) return this.queue.shift();
43
+ if (this.closed) return null;
44
+ return new Promise((resolve4) => {
45
+ this.waiter = resolve4;
46
+ });
47
+ }
48
+ close() {
49
+ this.rl.close();
50
+ }
51
+ };
52
+ var sharedReader = null;
53
+ function getReader() {
54
+ if (!sharedReader) {
55
+ sharedReader = new LineReader(process.stdin, process.stdout);
56
+ }
57
+ return sharedReader;
58
+ }
59
+ var CANCEL = /* @__PURE__ */ Symbol("prompt.cancel");
60
+ function isCancel2(v) {
61
+ return v === CANCEL || clack.isCancel(v);
62
+ }
63
+ async function text2(opts) {
64
+ if (isInteractive) {
65
+ const result = await clack.text({
66
+ message: opts.message,
67
+ initialValue: opts.initialValue,
68
+ placeholder: opts.placeholder,
69
+ validate: opts.validate
70
+ });
71
+ if (clack.isCancel(result)) return CANCEL;
72
+ return result;
73
+ }
74
+ return nonTtyText(opts);
75
+ }
76
+ async function select2(opts) {
77
+ if (isInteractive) {
78
+ const result = await clack.select({
79
+ message: opts.message,
80
+ options: opts.options,
81
+ initialValue: opts.initialValue
82
+ });
83
+ if (clack.isCancel(result)) return CANCEL;
84
+ return result;
85
+ }
86
+ return nonTtySelect(opts);
87
+ }
88
+ async function confirm2(opts) {
89
+ if (isInteractive) {
90
+ const result = await clack.confirm({
91
+ message: opts.message,
92
+ initialValue: opts.initialValue
93
+ });
94
+ if (clack.isCancel(result)) return CANCEL;
95
+ return result;
96
+ }
97
+ return nonTtyConfirm(opts);
98
+ }
99
+ async function password2(opts) {
100
+ if (isInteractive) {
101
+ const result = await clack.password({ message: opts.message });
102
+ if (clack.isCancel(result)) return CANCEL;
103
+ return result;
104
+ }
105
+ return nonTtyText({ message: opts.message, trim: false });
106
+ }
107
+ async function nonTtyText(opts, io = {}) {
108
+ const reader = io.reader ?? getReader();
109
+ const stderr = io.stderr ?? process.stderr;
110
+ const shouldTrim = opts.trim ?? true;
111
+ const defaultHint = opts.initialValue ? ` [${opts.initialValue}]` : "";
112
+ for (; ; ) {
113
+ const raw = await reader.readLine(`? ${opts.message}${defaultHint} `);
114
+ if (raw === null) return CANCEL;
115
+ const normalized = shouldTrim ? raw.trim() : raw;
116
+ const value = normalized === "" ? opts.initialValue ?? "" : normalized;
117
+ if (opts.validate) {
118
+ const err = opts.validate(value);
119
+ if (err) {
120
+ stderr.write(` ${err}
121
+ `);
122
+ continue;
123
+ }
124
+ }
125
+ return value;
126
+ }
127
+ }
128
+ async function nonTtySelect(opts, io = {}) {
129
+ if (opts.options.length === 0) {
130
+ throw new Error(`No options available for prompt "${opts.message}".`);
131
+ }
132
+ const reader = io.reader ?? getReader();
133
+ const stdout = io.stdout ?? process.stdout;
134
+ const stderr = io.stderr ?? process.stderr;
135
+ stdout.write(`? ${opts.message}
136
+ `);
137
+ opts.options.forEach((o, i) => {
138
+ const hint = o.hint ? ` \u2014 ${o.hint}` : "";
139
+ stdout.write(` ${i + 1}) ${o.label}${hint}
140
+ `);
141
+ });
142
+ for (; ; ) {
143
+ const raw = await reader.readLine(`Enter number [1-${opts.options.length}]: `);
144
+ if (raw === null) return CANCEL;
145
+ const n = Number.parseInt(raw.trim(), 10);
146
+ if (Number.isInteger(n) && n >= 1 && n <= opts.options.length) {
147
+ return opts.options[n - 1].value;
148
+ }
149
+ stderr.write(` Please enter a number between 1 and ${opts.options.length}.
150
+ `);
151
+ }
152
+ }
153
+ async function nonTtyConfirm(opts, io = {}) {
154
+ const reader = io.reader ?? getReader();
155
+ const stderr = io.stderr ?? process.stderr;
156
+ const defaultHint = opts.initialValue === true ? " [Y/n]" : opts.initialValue === false ? " [y/N]" : " [y/n]";
157
+ for (; ; ) {
158
+ const raw = await reader.readLine(`? ${opts.message}${defaultHint} `);
159
+ if (raw === null) return CANCEL;
160
+ const answer = raw.trim().toLowerCase();
161
+ if (answer === "" && opts.initialValue !== void 0) return opts.initialValue;
162
+ if (answer === "y" || answer === "yes") return true;
163
+ if (answer === "n" || answer === "no") return false;
164
+ stderr.write(` Please answer y or n.
165
+ `);
166
+ }
167
+ }
9
168
 
10
169
  // src/lib/config.ts
11
170
  import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
@@ -87,7 +246,7 @@ function getAccessToken() {
87
246
  }
88
247
 
89
248
  // src/commands/login.ts
90
- import * as clack3 from "@clack/prompts";
249
+ import * as clack4 from "@clack/prompts";
91
250
 
92
251
  // src/lib/errors.ts
93
252
  var CLIError = class extends Error {
@@ -179,7 +338,8 @@ function getRootOpts(cmd) {
179
338
  import { createServer } from "http";
180
339
  import { randomBytes, createHash } from "crypto";
181
340
  import { URL as URL2 } from "url";
182
- import * as clack from "@clack/prompts";
341
+ import * as clack2 from "@clack/prompts";
342
+ import pc from "picocolors";
183
343
  var DEFAULT_CLIENT_ID = "clf_NK8cMUs41gm8ZcfdtSguVw";
184
344
  var OAUTH_SCOPES = "user:read organizations:read projects:read projects:write";
185
345
  function generatePKCE() {
@@ -315,25 +475,35 @@ async function performOAuthLogin(apiUrl) {
315
475
  state,
316
476
  scopes: OAUTH_SCOPES
317
477
  });
318
- clack.log.info("Opening browser for authentication...");
319
- clack.log.info(`If browser doesn't open, visit:
478
+ if (isInteractive) {
479
+ clack2.log.info("Opening browser for authentication...");
480
+ clack2.log.info(`If browser doesn't open, visit:
320
481
  ${authUrl}`);
482
+ } else {
483
+ process.stderr.write(`
484
+ To sign in, open this URL in your browser:
485
+
486
+ ${pc.cyan(pc.underline(authUrl))}
487
+
488
+ `);
489
+ }
321
490
  try {
322
491
  const open = (await import("open")).default;
323
492
  await open(authUrl);
324
493
  } catch {
325
- clack.log.warn("Could not open browser. Please visit the URL above.");
494
+ if (isInteractive) clack2.log.warn("Could not open browser. Please visit the URL above.");
326
495
  }
327
- const s = clack.spinner();
328
- s.start("Waiting for authentication...");
496
+ const s = isInteractive ? clack2.spinner() : null;
497
+ s?.start("Waiting for authentication...");
498
+ if (!isInteractive) process.stderr.write("Waiting for authentication...\n");
329
499
  try {
330
500
  const callbackResult = await result;
331
501
  close();
332
502
  if (callbackResult.state !== state) {
333
- s.stop("Authentication failed");
503
+ s?.stop("Authentication failed");
334
504
  throw new Error("State mismatch. Possible CSRF attack.");
335
505
  }
336
- s.message("Exchanging authorization code...");
506
+ s?.message("Exchanging authorization code...");
337
507
  const tokens = await exchangeCodeForTokens({
338
508
  platformUrl,
339
509
  code: callbackResult.code,
@@ -351,20 +521,24 @@ ${authUrl}`);
351
521
  const profile = await getProfile(apiUrl);
352
522
  creds.user = profile;
353
523
  saveCredentials(creds);
354
- s.stop(`Authenticated as ${profile.email}`);
524
+ s?.stop(`Authenticated as ${profile.email}`);
525
+ if (!isInteractive) process.stderr.write(`Authenticated as ${profile.email}
526
+ `);
355
527
  } catch {
356
- s.stop("Authenticated successfully");
528
+ s?.stop("Authenticated successfully");
529
+ if (!isInteractive) process.stderr.write("Authenticated successfully\n");
357
530
  }
358
531
  return creds;
359
532
  } catch (err) {
360
533
  close();
361
- s.stop("Authentication failed");
534
+ s?.stop("Authentication failed");
535
+ if (!isInteractive) process.stderr.write("Authentication failed\n");
362
536
  throw err;
363
537
  }
364
538
  }
365
539
 
366
540
  // src/lib/credentials.ts
367
- import * as clack2 from "@clack/prompts";
541
+ import * as clack3 from "@clack/prompts";
368
542
  async function requireAuth(apiUrl, allowOssBypass = true) {
369
543
  const projConfig = getProjectConfig();
370
544
  if (allowOssBypass && projConfig?.project_id === FAKE_PROJECT_ID) {
@@ -382,16 +556,16 @@ async function requireAuth(apiUrl, allowOssBypass = true) {
382
556
  }
383
557
  const creds = getCredentials();
384
558
  if (creds && creds.access_token) return creds;
385
- clack2.log.info("You need to log in to continue.");
559
+ clack3.log.info("You need to log in to continue.");
386
560
  for (; ; ) {
387
561
  try {
388
562
  return await performOAuthLogin(apiUrl);
389
563
  } catch (err) {
390
564
  if (!process.stdout.isTTY) throw err;
391
565
  const msg = err instanceof Error ? err.message : "Unknown error";
392
- clack2.log.error(`Login failed: ${msg}`);
393
- const retry = await clack2.confirm({ message: "Would you like to try again?" });
394
- if (clack2.isCancel(retry) || !retry) {
566
+ clack3.log.error(`Login failed: ${msg}`);
567
+ const retry = await confirm2({ message: "Would you like to try again?" });
568
+ if (isCancel2(retry) || !retry) {
395
569
  throw new AuthError("Authentication required. Run `npx @insforge/cli login` to authenticate.");
396
570
  }
397
571
  }
@@ -421,7 +595,7 @@ async function refreshAccessToken(apiUrl) {
421
595
  return data.access_token;
422
596
  } catch {
423
597
  if (process.stdout.isTTY) {
424
- clack2.log.warn("Session expired. Please log in again.");
598
+ clack3.log.warn("Session expired. Please log in again.");
425
599
  const newCreds = await performOAuthLogin(apiUrl);
426
600
  return newCreds.access_token;
427
601
  }
@@ -477,12 +651,12 @@ async function platformFetch(path5, options = {}, apiUrl) {
477
651
  }
478
652
  return res;
479
653
  }
480
- async function login(email, password2, apiUrl) {
654
+ async function login(email, password3, apiUrl) {
481
655
  const baseUrl = getPlatformApiUrl(apiUrl);
482
656
  const res = await fetch(`${baseUrl}/auth/v1/login`, {
483
657
  method: "POST",
484
658
  headers: { "Content-Type": "application/json" },
485
- body: JSON.stringify({ email, password: password2 })
659
+ body: JSON.stringify({ email, password: password3 })
486
660
  });
487
661
  if (!res.ok) {
488
662
  const err = await res.json().catch(() => ({}));
@@ -618,30 +792,30 @@ function registerLoginCommand(program2) {
618
792
  }
619
793
  async function loginWithEmail(json, apiUrl) {
620
794
  if (!json) {
621
- clack3.intro("InsForge CLI");
795
+ clack4.intro("InsForge CLI");
622
796
  }
623
- const email = json ? process.env.INSFORGE_EMAIL : await clack3.text({
797
+ const email = json ? process.env.INSFORGE_EMAIL : await text2({
624
798
  message: "Email:",
625
799
  validate: (v) => v.includes("@") ? void 0 : "Please enter a valid email"
626
800
  });
627
- if (clack3.isCancel(email)) {
628
- clack3.cancel("Login cancelled.");
801
+ if (isCancel2(email)) {
802
+ clack4.cancel("Login cancelled.");
629
803
  throw new Error("cancelled");
630
804
  }
631
- const password2 = json ? process.env.INSFORGE_PASSWORD : await clack3.password({
805
+ const password3 = json ? process.env.INSFORGE_PASSWORD : await password2({
632
806
  message: "Password:"
633
807
  });
634
- if (clack3.isCancel(password2)) {
635
- clack3.cancel("Login cancelled.");
808
+ if (isCancel2(password3)) {
809
+ clack4.cancel("Login cancelled.");
636
810
  throw new Error("cancelled");
637
811
  }
638
- if (!email || !password2) {
812
+ if (!email || !password3) {
639
813
  throw new Error("Email and password are required. Set INSFORGE_EMAIL and INSFORGE_PASSWORD environment variables for non-interactive mode.");
640
814
  }
641
815
  if (!json) {
642
- const s = clack3.spinner();
816
+ const s = clack4.spinner();
643
817
  s.start("Authenticating...");
644
- const result = await login(email, password2, apiUrl);
818
+ const result = await login(email, password3, apiUrl);
645
819
  const creds = {
646
820
  access_token: result.token,
647
821
  refresh_token: result._refreshToken ?? "",
@@ -649,9 +823,9 @@ async function loginWithEmail(json, apiUrl) {
649
823
  };
650
824
  saveCredentials(creds);
651
825
  s.stop(`Authenticated as ${result.user.email}`);
652
- clack3.outro("Done");
826
+ clack4.outro("Done");
653
827
  } else {
654
- const result = await login(email, password2, apiUrl);
828
+ const result = await login(email, password3, apiUrl);
655
829
  const creds = {
656
830
  access_token: result.token,
657
831
  refresh_token: result._refreshToken ?? "",
@@ -663,11 +837,11 @@ async function loginWithEmail(json, apiUrl) {
663
837
  }
664
838
  async function loginWithOAuth(json, apiUrl) {
665
839
  if (!json) {
666
- clack3.intro("InsForge CLI");
840
+ clack4.intro("InsForge CLI");
667
841
  }
668
842
  const creds = await performOAuthLogin(apiUrl);
669
843
  if (!json) {
670
- clack3.outro("Done");
844
+ clack4.outro("Done");
671
845
  } else {
672
846
  console.log(JSON.stringify({ success: true, user: creds.user }));
673
847
  }
@@ -762,7 +936,6 @@ function registerOrgsCommands(orgsCmd2) {
762
936
  }
763
937
 
764
938
  // src/commands/projects/list.ts
765
- import * as clack4 from "@clack/prompts";
766
939
  function registerProjectsCommands(projectsCmd2) {
767
940
  projectsCmd2.command("list").description("List all projects in an organization").option("--org-id <id>", "Organization ID (uses default if not specified)").action(async (opts, cmd) => {
768
941
  const { json, apiUrl } = getRootOpts(cmd);
@@ -777,14 +950,14 @@ function registerProjectsCommands(projectsCmd2) {
777
950
  if (orgs.length === 1) {
778
951
  orgId = orgs[0].id;
779
952
  } else if (!json) {
780
- const selected = await clack4.select({
953
+ const selected = await select2({
781
954
  message: "Select an organization:",
782
955
  options: orgs.map((o) => ({
783
956
  value: o.id,
784
957
  label: o.name
785
958
  }))
786
959
  });
787
- if (clack4.isCancel(selected)) {
960
+ if (isCancel2(selected)) {
788
961
  process.exit(0);
789
962
  }
790
963
  orgId = selected;
@@ -817,7 +990,7 @@ import { promisify as promisify3 } from "util";
817
990
  import * as fs4 from "fs/promises";
818
991
  import * as path4 from "path";
819
992
  import * as clack8 from "@clack/prompts";
820
- import pc from "picocolors";
993
+ import pc2 from "picocolors";
821
994
 
822
995
  // src/lib/skills.ts
823
996
  import { exec } from "child_process";
@@ -1383,14 +1556,14 @@ function registerCreateCommand(program2) {
1383
1556
  if (json) {
1384
1557
  throw new CLIError("Multiple organizations found. Specify --org-id.");
1385
1558
  }
1386
- const selected = await clack7.select({
1559
+ const selected = await select2({
1387
1560
  message: "Select an organization:",
1388
1561
  options: orgs.map((o) => ({
1389
1562
  value: o.id,
1390
1563
  label: o.name
1391
1564
  }))
1392
1565
  });
1393
- if (clack7.isCancel(selected)) process.exit(0);
1566
+ if (isCancel2(selected)) process.exit(0);
1394
1567
  orgId = selected;
1395
1568
  }
1396
1569
  }
@@ -1401,12 +1574,12 @@ function registerCreateCommand(program2) {
1401
1574
  if (!projectName) {
1402
1575
  if (json) throw new CLIError("--name is required in JSON mode.");
1403
1576
  const defaultName = getDefaultProjectName();
1404
- const name = await clack7.text({
1577
+ const name = await text2({
1405
1578
  message: "Project name:",
1406
1579
  ...defaultName ? { initialValue: defaultName } : {},
1407
1580
  validate: (v) => v.length >= 2 ? void 0 : "Name must be at least 2 characters"
1408
1581
  });
1409
- if (clack7.isCancel(name)) process.exit(0);
1582
+ if (isCancel2(name)) process.exit(0);
1410
1583
  projectName = name;
1411
1584
  }
1412
1585
  projectName = path3.basename(projectName).replace(/[^a-zA-Z0-9._-]/g, "-").replace(/\.+/g, ".");
@@ -1422,21 +1595,21 @@ function registerCreateCommand(program2) {
1422
1595
  if (json) {
1423
1596
  template = "empty";
1424
1597
  } else {
1425
- const approach = await clack7.select({
1598
+ const approach = await select2({
1426
1599
  message: "How would you like to start?",
1427
1600
  options: [
1428
1601
  { value: "blank", label: "Blank project", hint: "Start from scratch with .env.local ready" },
1429
1602
  { value: "template", label: "Start from a template", hint: "Pre-built starter apps" }
1430
1603
  ]
1431
1604
  });
1432
- if (clack7.isCancel(approach)) process.exit(0);
1605
+ if (isCancel2(approach)) process.exit(0);
1433
1606
  captureEvent(orgId, "create_approach_selected", {
1434
1607
  approach
1435
1608
  });
1436
1609
  if (approach === "blank") {
1437
1610
  template = "empty";
1438
1611
  } else {
1439
- const selected = await clack7.select({
1612
+ const selected = await select2({
1440
1613
  message: "Choose a starter template:",
1441
1614
  options: [
1442
1615
  { value: "react", label: "Web app template with React" },
@@ -1447,7 +1620,7 @@ function registerCreateCommand(program2) {
1447
1620
  { value: "todo", label: "Todo app with Next.js" }
1448
1621
  ]
1449
1622
  });
1450
- if (clack7.isCancel(selected)) process.exit(0);
1623
+ if (isCancel2(selected)) process.exit(0);
1451
1624
  template = selected;
1452
1625
  }
1453
1626
  }
@@ -1463,7 +1636,7 @@ function registerCreateCommand(program2) {
1463
1636
  if (hasTemplate) {
1464
1637
  dirName = projectName;
1465
1638
  if (!json) {
1466
- const inputDir = await clack7.text({
1639
+ const inputDir = await text2({
1467
1640
  message: "Directory name:",
1468
1641
  initialValue: projectName,
1469
1642
  validate: (v) => {
@@ -1473,7 +1646,7 @@ function registerCreateCommand(program2) {
1473
1646
  return void 0;
1474
1647
  }
1475
1648
  });
1476
- if (clack7.isCancel(inputDir)) process.exit(0);
1649
+ if (isCancel2(inputDir)) process.exit(0);
1477
1650
  dirName = path3.basename(inputDir).replace(/[^a-zA-Z0-9._-]/g, "-");
1478
1651
  }
1479
1652
  if (!dirName || dirName === "." || dirName === "..") {
@@ -1561,10 +1734,10 @@ function registerCreateCommand(program2) {
1561
1734
  }
1562
1735
  let liveUrl = null;
1563
1736
  if (templateDownloaded && !json) {
1564
- const shouldDeploy = await clack7.confirm({
1737
+ const shouldDeploy = await confirm2({
1565
1738
  message: "Would you like to deploy now?"
1566
1739
  });
1567
- if (!clack7.isCancel(shouldDeploy) && shouldDeploy) {
1740
+ if (!isCancel2(shouldDeploy) && shouldDeploy) {
1568
1741
  try {
1569
1742
  const envVars = await readEnvFile(process.cwd());
1570
1743
  const startBody = {};
@@ -1826,14 +1999,14 @@ function registerProjectLinkCommand(program2) {
1826
1999
  if (json) {
1827
2000
  throw new CLIError("Multiple organizations found. Specify --org-id.");
1828
2001
  }
1829
- const selected = await clack8.select({
2002
+ const selected = await select2({
1830
2003
  message: "Select an organization:",
1831
2004
  options: orgs.map((o) => ({
1832
2005
  value: o.id,
1833
2006
  label: o.name
1834
2007
  }))
1835
2008
  });
1836
- if (clack8.isCancel(selected)) process.exit(0);
2009
+ if (isCancel2(selected)) process.exit(0);
1837
2010
  orgId = selected;
1838
2011
  }
1839
2012
  }
@@ -1848,14 +2021,14 @@ function registerProjectLinkCommand(program2) {
1848
2021
  if (json) {
1849
2022
  throw new CLIError("Specify --project-id in JSON mode.");
1850
2023
  }
1851
- const selected = await clack8.select({
2024
+ const selected = await select2({
1852
2025
  message: "Select a project to link:",
1853
2026
  options: projects.map((p) => ({
1854
2027
  value: p.id,
1855
2028
  label: `${p.name} (${p.region}, ${p.status})`
1856
2029
  }))
1857
2030
  });
1858
- if (clack8.isCancel(selected)) process.exit(0);
2031
+ if (isCancel2(selected)) process.exit(0);
1859
2032
  projectId = selected;
1860
2033
  }
1861
2034
  let project;
@@ -1906,7 +2079,7 @@ function registerProjectLinkCommand(program2) {
1906
2079
  }
1907
2080
  let dirName = project.name;
1908
2081
  if (!json) {
1909
- const inputDir = await clack8.text({
2082
+ const inputDir = await text2({
1910
2083
  message: "Directory name:",
1911
2084
  initialValue: project.name,
1912
2085
  validate: (v) => {
@@ -1916,7 +2089,7 @@ function registerProjectLinkCommand(program2) {
1916
2089
  return void 0;
1917
2090
  }
1918
2091
  });
1919
- if (clack8.isCancel(inputDir)) process.exit(0);
2092
+ if (isCancel2(inputDir)) process.exit(0);
1920
2093
  dirName = path4.basename(inputDir).replace(/[^a-zA-Z0-9._-]/g, "-");
1921
2094
  }
1922
2095
  if (!dirName || dirName === "." || dirName === "..") {
@@ -1954,12 +2127,12 @@ function registerProjectLinkCommand(program2) {
1954
2127
  await reportCliUsage("cli.link", true, 6, projectConfig);
1955
2128
  if (!json) {
1956
2129
  const dashboardUrl = `${getFrontendUrl()}/dashboard/project/${project.id}`;
1957
- clack8.log.step(`Dashboard: ${pc.underline(dashboardUrl)}`);
2130
+ clack8.log.step(`Dashboard: ${pc2.underline(dashboardUrl)}`);
1958
2131
  if (templateDownloaded) {
1959
- const runCommand = `${pc.cyan("cd")} ${pc.green(dirName)} ${pc.dim("&&")} ${pc.cyan("npm run dev")}`;
2132
+ const runCommand = `${pc2.cyan("cd")} ${pc2.green(dirName)} ${pc2.dim("&&")} ${pc2.cyan("npm run dev")}`;
1960
2133
  const steps = [
1961
- `${pc.bold("1.")} ${runCommand}`,
1962
- `${pc.bold("2.")} Open ${pc.cyan("Claude Code")} or ${pc.cyan("Cursor")} and prompt your agent to add more features`
2134
+ `${pc2.bold("1.")} ${runCommand}`,
2135
+ `${pc2.bold("2.")} Open ${pc2.cyan("Claude Code")} or ${pc2.cyan("Cursor")} and prompt your agent to add more features`
1963
2136
  ];
1964
2137
  clack8.note(steps.join("\n"), "What's next");
1965
2138
  } else {
@@ -2590,8 +2763,8 @@ function registerFunctionsInvokeCommand(functionsCmd2) {
2590
2763
  console.log(JSON.stringify(data, null, 2));
2591
2764
  }
2592
2765
  } else {
2593
- const text4 = await res.text();
2594
- console.log(text4);
2766
+ const text3 = await res.text();
2767
+ console.log(text3);
2595
2768
  }
2596
2769
  if (status >= 400) {
2597
2770
  throw new CLIError(`HTTP ${status}`, 1, "HTTP_ERROR");
@@ -2634,10 +2807,10 @@ function registerFunctionsDeleteCommand(functionsCmd2) {
2634
2807
  try {
2635
2808
  await requireAuth();
2636
2809
  if (!yes && !json) {
2637
- const confirmed = await clack9.confirm({
2810
+ const confirmed = await confirm2({
2638
2811
  message: `Delete function "${slug}"? This cannot be undone.`
2639
2812
  });
2640
- if (clack9.isCancel(confirmed) || !confirmed) {
2813
+ if (isCancel2(confirmed) || !confirmed) {
2641
2814
  clack9.log.info("Cancelled.");
2642
2815
  return;
2643
2816
  }
@@ -2796,17 +2969,16 @@ function registerStorageCreateBucketCommand(storageCmd2) {
2796
2969
  }
2797
2970
 
2798
2971
  // src/commands/storage/delete-bucket.ts
2799
- import * as clack10 from "@clack/prompts";
2800
2972
  function registerStorageDeleteBucketCommand(storageCmd2) {
2801
2973
  storageCmd2.command("delete-bucket <name>").description("Delete a storage bucket and all its objects").action(async (name, _opts, cmd) => {
2802
2974
  const { json, yes } = getRootOpts(cmd);
2803
2975
  try {
2804
2976
  await requireAuth();
2805
2977
  if (!yes && !json) {
2806
- const confirm8 = await clack10.confirm({
2978
+ const confirm3 = await confirm2({
2807
2979
  message: `Delete bucket "${name}" and all its objects? This cannot be undone.`
2808
2980
  });
2809
- if (!confirm8 || clack10.isCancel(confirm8)) {
2981
+ if (isCancel2(confirm3) || !confirm3) {
2810
2982
  process.exit(0);
2811
2983
  }
2812
2984
  }
@@ -3061,7 +3233,6 @@ function registerDeploymentsStatusCommand(deploymentsCmd2) {
3061
3233
  }
3062
3234
 
3063
3235
  // src/commands/deployments/cancel.ts
3064
- import * as clack11 from "@clack/prompts";
3065
3236
  function registerDeploymentsCancelCommand(deploymentsCmd2) {
3066
3237
  deploymentsCmd2.command("cancel <id>").description("Cancel a deployment").action(async (id, _opts, cmd) => {
3067
3238
  const { json, yes } = getRootOpts(cmd);
@@ -3069,10 +3240,10 @@ function registerDeploymentsCancelCommand(deploymentsCmd2) {
3069
3240
  await requireAuth();
3070
3241
  if (!getProjectConfig()) throw new ProjectNotLinkedError();
3071
3242
  if (!yes && !json) {
3072
- const confirmed = await clack11.confirm({
3243
+ const confirmed = await confirm2({
3073
3244
  message: `Cancel deployment ${id}?`
3074
3245
  });
3075
- if (clack11.isCancel(confirmed) || !confirmed) process.exit(0);
3246
+ if (isCancel2(confirmed) || !confirmed) process.exit(0);
3076
3247
  }
3077
3248
  const res = await ossFetch(`/api/deployments/${id}/cancel`, { method: "POST" });
3078
3249
  const result = await res.json();
@@ -3352,17 +3523,16 @@ function registerSecretsUpdateCommand(secretsCmd2) {
3352
3523
  }
3353
3524
 
3354
3525
  // src/commands/secrets/delete.ts
3355
- import * as clack12 from "@clack/prompts";
3356
3526
  function registerSecretsDeleteCommand(secretsCmd2) {
3357
3527
  secretsCmd2.command("delete <key>").description("Delete a secret").action(async (key, _opts, cmd) => {
3358
3528
  const { json, yes } = getRootOpts(cmd);
3359
3529
  try {
3360
3530
  await requireAuth();
3361
3531
  if (!yes && !json) {
3362
- const confirm8 = await clack12.confirm({
3532
+ const confirm3 = await confirm2({
3363
3533
  message: `Delete secret "${key}"? This cannot be undone.`
3364
3534
  });
3365
- if (!confirm8 || clack12.isCancel(confirm8)) {
3535
+ if (isCancel2(confirm3) || !confirm3) {
3366
3536
  process.exit(0);
3367
3537
  }
3368
3538
  }
@@ -3538,17 +3708,16 @@ function registerSchedulesUpdateCommand(schedulesCmd2) {
3538
3708
  }
3539
3709
 
3540
3710
  // src/commands/schedules/delete.ts
3541
- import * as clack13 from "@clack/prompts";
3542
3711
  function registerSchedulesDeleteCommand(schedulesCmd2) {
3543
3712
  schedulesCmd2.command("delete <id>").description("Delete a schedule").action(async (id, _opts, cmd) => {
3544
3713
  const { json, yes } = getRootOpts(cmd);
3545
3714
  try {
3546
3715
  await requireAuth();
3547
3716
  if (!yes && !json) {
3548
- const confirm8 = await clack13.confirm({
3717
+ const confirm3 = await confirm2({
3549
3718
  message: `Delete schedule "${id}"? This cannot be undone.`
3550
3719
  });
3551
- if (!confirm8 || clack13.isCancel(confirm8)) {
3720
+ if (isCancel2(confirm3) || !confirm3) {
3552
3721
  process.exit(0);
3553
3722
  }
3554
3723
  }
@@ -4179,7 +4348,7 @@ function formatSize2(gb) {
4179
4348
 
4180
4349
  // src/commands/diagnose/index.ts
4181
4350
  import * as os from "os";
4182
- import * as clack14 from "@clack/prompts";
4351
+ import * as clack10 from "@clack/prompts";
4183
4352
 
4184
4353
  // src/commands/diagnose/metrics.ts
4185
4354
  var METRIC_LABELS = {
@@ -4716,10 +4885,10 @@ function registerDiagnoseCommands(diagnoseCmd2) {
4716
4885
  if (question.length === 0 || question.length > 2e3) {
4717
4886
  throw new CLIError("Question must be between 1 and 2000 characters.");
4718
4887
  }
4719
- const s = !json ? clack14.spinner() : null;
4888
+ const s = !json ? clack10.spinner() : null;
4720
4889
  s?.start("Collecting diagnostic data...");
4721
4890
  const data2 = await collectDiagnosticData(projectId, ossMode, apiUrl);
4722
- const cliVersion = "0.1.49";
4891
+ const cliVersion = "0.1.50";
4723
4892
  s?.stop("Data collected");
4724
4893
  if (!json) {
4725
4894
  console.log(`
@@ -4835,7 +5004,7 @@ function registerDiagnoseCommands(diagnoseCmd2) {
4835
5004
  outputJson({ sessionId, events: jsonEvents });
4836
5005
  }
4837
5006
  if (!json && sessionId) {
4838
- const ratingChoice = await clack14.select({
5007
+ const ratingChoice = await select2({
4839
5008
  message: "Was this analysis helpful?",
4840
5009
  options: [
4841
5010
  { value: "skip", label: "Skip", hint: "no rating" },
@@ -4844,7 +5013,7 @@ function registerDiagnoseCommands(diagnoseCmd2) {
4844
5013
  { value: "incorrect", label: "Incorrect", hint: "diagnosis was wrong or misleading" }
4845
5014
  ]
4846
5015
  });
4847
- if (!clack14.isCancel(ratingChoice) && ratingChoice !== "skip") {
5016
+ if (!isCancel2(ratingChoice) && ratingChoice !== "skip") {
4848
5017
  try {
4849
5018
  await rateDiagnosticSession(
4850
5019
  sessionId,
@@ -4852,9 +5021,9 @@ function registerDiagnoseCommands(diagnoseCmd2) {
4852
5021
  void 0,
4853
5022
  apiUrl
4854
5023
  );
4855
- clack14.log.success("Thanks for your feedback!");
5024
+ clack10.log.success("Thanks for your feedback!");
4856
5025
  } catch {
4857
- clack14.log.warn("Failed to submit rating.");
5026
+ clack10.log.warn("Failed to submit rating.");
4858
5027
  }
4859
5028
  }
4860
5029
  }
@@ -5049,7 +5218,7 @@ async function showInteractiveMenu() {
5049
5218
  } catch {
5050
5219
  }
5051
5220
  console.log(INSFORGE_LOGO);
5052
- clack15.intro(`InsForge CLI v${pkg.version}`);
5221
+ clack11.intro(`InsForge CLI v${pkg.version}`);
5053
5222
  const options = [];
5054
5223
  if (!isLoggedIn) {
5055
5224
  options.push({ value: "login", label: "Log in to InsForge" });
@@ -5065,12 +5234,12 @@ async function showInteractiveMenu() {
5065
5234
  { value: "docs", label: "View documentation" },
5066
5235
  { value: "help", label: "Show all commands" }
5067
5236
  );
5068
- const action = await clack15.select({
5237
+ const action = await select2({
5069
5238
  message: "What would you like to do?",
5070
5239
  options
5071
5240
  });
5072
- if (clack15.isCancel(action)) {
5073
- clack15.cancel("Bye!");
5241
+ if (isCancel2(action)) {
5242
+ clack11.cancel("Bye!");
5074
5243
  process.exit(0);
5075
5244
  }
5076
5245
  switch (action) {