@islamihab/kds 0.11.0 → 0.12.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 (2) hide show
  1. package/index.js +138 -56
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -14623,7 +14623,7 @@ import { join } from "path";
14623
14623
  // package.json
14624
14624
  var package_default = {
14625
14625
  name: "cli",
14626
- version: "0.11.0",
14626
+ version: "0.12.0",
14627
14627
  private: true,
14628
14628
  type: "module",
14629
14629
  bin: {
@@ -15196,9 +15196,20 @@ var components = componentsGeneric();
15196
15196
 
15197
15197
  // ../../packages/backend/convex/constants.ts
15198
15198
  var KDS_DEVICE_AUTH_CLIENT_ID = "kds-cli";
15199
- var PAGE_MODES = ["themed", "raw"];
15199
+ var PAGE_STYLES = {
15200
+ basic: {
15201
+ description: "a report in the house theme with a light/dark toggle and the credit line, where you write only what goes inside the page"
15202
+ },
15203
+ mockup: {
15204
+ description: "an interactive prototype where the fragment is the screen of a phone, its own <style> and <script> tags do the rest, it fills the display on a real phone, and its manifest and apple-touch-icon install it under its own name and icon"
15205
+ },
15206
+ unthemed: {
15207
+ description: "a blank document where the fragment is served as written with nothing added, so its own <style> and <script> tags decide everything"
15208
+ }
15209
+ };
15200
15210
  var PAGE_VISIBILITIES = ["public", "private"];
15201
15211
  var MAX_PAGE_HTML_BYTES = 4000000;
15212
+ var MAX_PAGE_VERSIONS = 20;
15202
15213
  var ISSUE_STATUSES = [
15203
15214
  "backlog",
15204
15215
  "todo",
@@ -17346,6 +17357,7 @@ var localDateString = (timestamp) => {
17346
17357
  return `${date5.getFullYear()}-${month}-${day}`;
17347
17358
  };
17348
17359
  var localToday = () => localDateString(Date.now());
17360
+ var describeChoices = (choices, separator = "; ") => Object.entries(choices).map(([key, { description }]) => `${key}: ${description}`).join(separator);
17349
17361
 
17350
17362
  // src/lib/zod.ts
17351
17363
  var configSchema = exports_external.object({ sessionToken: exports_external.string().optional(), convexUrl: exports_external.url(), convexSiteUrl: exports_external.url() });
@@ -24120,6 +24132,10 @@ var issueActivityLine = (detail) => {
24120
24132
  case "attachment_added":
24121
24133
  case "attachment_removed":
24122
24134
  return `${label}: ${detail.name}`;
24135
+ case "page_linked":
24136
+ case "page_unlinked":
24137
+ case "page_updated":
24138
+ return `${label}: ${detail.title}`;
24123
24139
  case "child_added":
24124
24140
  case "child_removed":
24125
24141
  return `${label}: ${detail.identifier}`;
@@ -24413,15 +24429,6 @@ var repoProject = async (client3) => {
24413
24429
  throw new Error(`No project is connected to ${repo}. Connect one on the project in the dashboard.`);
24414
24430
  return project;
24415
24431
  };
24416
- var resolveMilestone = async (client3, projectId, name) => {
24417
- const milestone = await client3.query(api2.milestones.find, { projectId, name });
24418
- if (!milestone) {
24419
- const milestones = await client3.query(api2.milestones.listByProject, { projectId, today: localToday() });
24420
- const names = milestones.map((candidate) => candidate.name).join(", ");
24421
- throw new Error(names ? `No milestone named "${name}". The project has: ${names}.` : "The project has no milestones.");
24422
- }
24423
- return milestone;
24424
- };
24425
24432
 
24426
24433
  // src/commands/clients/charges/list.ts
24427
24434
  var monthName = (month) => new Date(Date.UTC(2000, month - 1)).toLocaleString("en-US", { month: "short", timeZone: "UTC" });
@@ -24691,9 +24698,10 @@ var create2 = command({
24691
24698
  name: "create",
24692
24699
  description: "Record a cost and print its id",
24693
24700
  longDescription: `One record per real-world bill, never one per project. A cost links to any number
24694
- of projects, each carrying the full amount; no links at all is overhead. Billable
24695
- costs pass through onto a client's invoices, so their projects must all belong to
24696
- the same client.`,
24701
+ of projects, each carrying the full amount; until a client's project carries it, it
24702
+ is overhead. Billable
24703
+ costs pass through onto the invoices of whichever client their projects belong to,
24704
+ so the links cannot span two clients; with no links, billable waits for one.`,
24697
24705
  positionals: {
24698
24706
  name: exports_external.string().describe('What the bill is for, e.g. "Figma seats"')
24699
24707
  },
@@ -24750,9 +24758,10 @@ var costKindLabel = (cost) => {
24750
24758
  return cost.endDate === undefined ? cost.kind : `${cost.kind} \u2192 ${cost.endDate}`;
24751
24759
  };
24752
24760
  var costProjectsLabel = (cost) => {
24753
- if (cost.overhead)
24754
- return "overhead";
24755
- return cost.projects.length === 0 ? "(deleted project)" : cost.projects.map((project) => project.name).join(", ");
24761
+ const names = cost.projects.map((project) => project.name).join(", ");
24762
+ if (!cost.overhead)
24763
+ return names;
24764
+ return names === "" ? "overhead" : `overhead (${names})`;
24756
24765
  };
24757
24766
 
24758
24767
  // src/commands/costs/get.ts
@@ -24800,7 +24809,7 @@ after an edit. A yearly cost lands whole in its renewal month, never amortized.`
24800
24809
  month: exports_external.string().optional().describe("Derive one month's costs (YYYY-MM)").meta({ short: "m" }),
24801
24810
  kind: exports_external.enum(COST_KINDS).optional().describe("Only one_off, monthly, or yearly").meta({ short: "k" }),
24802
24811
  project: exports_external.string().optional().describe("Only costs linked to this project (id, URL, or repo)").meta({ short: "p" }),
24803
- overhead: exports_external.boolean().default(false).describe("Only costs with no project links"),
24812
+ overhead: exports_external.boolean().default(false).describe("Only costs no client's project carries"),
24804
24813
  billable: exports_external.boolean().optional().describe("Only billable costs, or --no-billable").meta({ negatable: true }),
24805
24814
  limit: exports_external.coerce.number().int().positive().default(50).describe("Most costs to print"),
24806
24815
  json: exports_external.boolean().default(false).describe("Print as JSON")
@@ -24908,7 +24917,7 @@ var costs = group({
24908
24917
  description: "Manage costs",
24909
24918
  longDescription: `A cost is money the studio spends, recorded once per real-world bill. It links to any
24910
24919
  number of projects \u2014 each carrying the full amount, so per-project figures never sum
24911
- to the studio total \u2014 and no links at all is overhead. Occurrences are always derived
24920
+ to the studio total. A cost no client's project carries is overhead. Occurrences are always derived
24912
24921
  from the record, so \`costs list --month\` answers for any month, past or future.`,
24913
24922
  commands: [create2, list3, get2, update3, end, remove2]
24914
24923
  });
@@ -25739,7 +25748,7 @@ var printTasks = (tasks) => {
25739
25748
  };
25740
25749
 
25741
25750
  // src/commands/issues/get.ts
25742
- var printIssue = ({ relations, attachments, tasks, feed, milestone, ...issue3 }) => {
25751
+ var printIssue = ({ relations, attachments, pages, tasks, feed, milestone, ...issue3 }) => {
25743
25752
  const project = issue3.project;
25744
25753
  console.log(`${issue3.identifier} ${issue3.title}`);
25745
25754
  console.log(`Status: ${issue3.status} \xB7 Priority: ${issue3.priority} \xB7 Disposition: ${issue3.disposition}`);
@@ -25778,6 +25787,12 @@ var printIssue = ({ relations, attachments, tasks, feed, milestone, ...issue3 })
25778
25787
  console.log(` ${attachment.name} \u2014 ${attachment.url ?? "unavailable"}`);
25779
25788
  }
25780
25789
  }
25790
+ if (pages.length > 0) {
25791
+ console.log("Pages:");
25792
+ for (const page of pages) {
25793
+ console.log(` ${page.title} (${page.style}, ${page.visibility}) \u2014 ${page.url}`);
25794
+ }
25795
+ }
25781
25796
  printTasks(tasks);
25782
25797
  if (issue3.descriptionMarkdown)
25783
25798
  console.log(`
@@ -25819,10 +25834,11 @@ var get4 = command({
25819
25834
  throw new Error(`No issues match ${missing.join(", ")}.`);
25820
25835
  const details = found.flatMap((detail) => detail ? [detail] : []);
25821
25836
  if (json2) {
25822
- const objects = details.map(({ relations, attachments, tasks, feed, milestone: _, ...issue3 }) => ({
25837
+ const objects = details.map(({ relations, attachments, pages, tasks, feed, milestone: _, ...issue3 }) => ({
25823
25838
  ...issue3,
25824
25839
  relations,
25825
25840
  attachments,
25841
+ pages,
25826
25842
  tasks,
25827
25843
  feed
25828
25844
  }));
@@ -25911,7 +25927,50 @@ var labels = group({
25911
25927
  commands: [create5, list6, update5, remove4]
25912
25928
  });
25913
25929
 
25930
+ // src/commands/issues/link-pr.ts
25931
+ var linkPr = command({
25932
+ name: "link-pr",
25933
+ description: "Link a pull request to an issue by hand",
25934
+ longDescription: `For a pull request the webhook cannot match on its own: work that started before
25935
+ its issue existed, so the branch never carried the identifier, or a second issue the
25936
+ same pull request lands. From here reviews and the merge move the issue as usual.
25937
+ --claim applies what opening the pull request would have: unstarted work moves to
25938
+ in_progress; any other status is kept.`,
25939
+ positionals: {
25940
+ id: exports_external.string().describe("Issue identifier, number, or URL"),
25941
+ url: exports_external.string().describe("Pull request URL")
25942
+ },
25943
+ options: {
25944
+ claim: exports_external.boolean().default(false).describe("Move backlog or todo work to in_progress along with the link")
25945
+ },
25946
+ run: async ({ positionals: { id, url: url2 }, options: { claim: claim2 } }) => {
25947
+ const client3 = await backendClient();
25948
+ const { identifier, linked, status: status3 } = await client3.mutation(api2.issues.linkPr, {
25949
+ id: readIssueRef(id),
25950
+ prUrl: url2,
25951
+ ...claim2 ? { claim: claim2 } : {}
25952
+ });
25953
+ console.log(`${linked ? "Linked" : "Already linked"} ${url2} to ${identifier}: ${status3}`);
25954
+ }
25955
+ });
25956
+
25914
25957
  // src/commands/issues/list.ts
25958
+ var resolveScope = async (client3, { project, here, milestone }) => {
25959
+ if (milestone) {
25960
+ if (!project && !here)
25961
+ throw new Error("A milestone filter needs --project or --here.");
25962
+ const ref = project ? readProjectRef(project) : await currentRepoKey();
25963
+ if (!ref)
25964
+ throw new Error("No repository here: not a git checkout with an origin remote.");
25965
+ const resolved = await client3.query(api2.milestones.resolve, { project: ref, name: milestone });
25966
+ return { projectId: resolved.projectId, milestoneId: resolved._id };
25967
+ }
25968
+ if (project)
25969
+ return { projectId: (await resolveProject(client3, project))._id };
25970
+ if (here)
25971
+ return { projectId: (await repoProject(client3))._id };
25972
+ return;
25973
+ };
25915
25974
  var list7 = command({
25916
25975
  name: "list",
25917
25976
  description: "List open issues, most recently updated first",
@@ -25932,10 +25991,7 @@ var list7 = command({
25932
25991
  if (options.project && options.here)
25933
25992
  throw new Error("Pass --project or --here, not both.");
25934
25993
  const client3 = await backendClient();
25935
- const project = options.project ? await resolveProject(client3, options.project) : options.here ? await repoProject(client3) : undefined;
25936
- if (options.milestone && !project)
25937
- throw new Error("A milestone filter needs --project or --here.");
25938
- const milestone = project && options.milestone ? await resolveMilestone(client3, project._id, options.milestone) : undefined;
25994
+ const scope = await resolveScope(client3, options);
25939
25995
  const result = await client3.query(api2.issueViews.query, {
25940
25996
  source: {
25941
25997
  type: "custom",
@@ -25949,8 +26005,8 @@ var list7 = command({
25949
26005
  statuses: options.status ? [options.status] : options.all ? undefined : ISSUE_STATUSES.filter(issueIsOpen),
25950
26006
  priorities: options.priority ? [options.priority] : undefined,
25951
26007
  dispositions: options.disposition ? [options.disposition] : undefined,
25952
- projectIds: project ? [project._id] : undefined,
25953
- milestoneIds: milestone ? [milestone._id] : undefined,
26008
+ projectIds: scope ? [scope.projectId] : undefined,
26009
+ milestoneIds: scope?.milestoneId ? [scope.milestoneId] : undefined,
25954
26010
  dueDate: options.due
25955
26011
  }
25956
26012
  }
@@ -26360,11 +26416,11 @@ todo, in_progress, ready_for_review, in_review, changes_requested, approved, don
26360
26416
  canceled), priority, and disposition (who acts next). The workflow commands \u2014 start,
26361
26417
  submit, start-review, submit-review \u2014 and the linked pull request move the status;
26362
26418
  each refuses an issue outside its own status, and \`set -s\` is for corrections.
26363
- The repo link is never set by hand: work on a branch whose name contains the issue
26364
- identifier and the branch, pull request, and status track automatically \u2014 a change
26365
- request moves the issue to changes_requested, an approval to approved (one
26366
- outstanding change request outweighs any number of approvals), and a merge lands
26367
- it as done.`,
26419
+ Work on a branch whose name contains the issue identifier and the branch, pull
26420
+ request, and status track automatically \u2014 a change request moves the issue to
26421
+ changes_requested, an approval to approved (one outstanding change request outweighs
26422
+ any number of approvals), and a merge lands it as done. link-pr covers the pull
26423
+ request the branch name does not point at; from there the same tracking applies.`,
26368
26424
  commands: [
26369
26425
  create4,
26370
26426
  list7,
@@ -26378,6 +26434,7 @@ it as done.`,
26378
26434
  startReview,
26379
26435
  submitReview,
26380
26436
  markAddressed,
26437
+ linkPr,
26381
26438
  tasks,
26382
26439
  relate,
26383
26440
  unrelate,
@@ -26386,6 +26443,9 @@ it as done.`,
26386
26443
  ]
26387
26444
  });
26388
26445
 
26446
+ // ../../packages/backend/convex/lib/object.ts
26447
+ var keys = (object2) => Object.keys(object2);
26448
+
26389
26449
  // src/lib/group.ts
26390
26450
  import { basename as basename2 } from "path";
26391
26451
  var git = async (...args) => {
@@ -26413,20 +26473,21 @@ var create6 = command({
26413
26473
  options: {
26414
26474
  title: exports_external.string().describe("Page title").meta({ short: "t" }),
26415
26475
  group: exports_external.string().nullable().optional().describe("Group to list the page under (default: the current repo)").meta({ short: "g", negatable: true }),
26416
- raw: exports_external.boolean().default(false).describe("Serve a full document verbatim (may run JS)"),
26417
- private: exports_external.boolean().default(false).describe("Require the publishing account to view the page")
26476
+ style: exports_external.enum(keys(PAGE_STYLES)).default("basic").describe(`Style to render in \u2014 ${describeChoices(PAGE_STYLES)}`),
26477
+ private: exports_external.boolean().default(false).describe("Require the publishing account to view the page"),
26478
+ issue: exports_external.string().optional().describe("Link the page to an issue (KAI-N, number, or URL)")
26418
26479
  },
26419
- run: async ({ positionals: { file: file2 }, options: { title, group: group2, raw, private: isPrivate } }) => {
26480
+ run: async ({ positionals: { file: file2 }, options: { title, group: group2, style, private: isPrivate, issue: issue3 } }) => {
26420
26481
  const newGroup = await groupForCreate(group2);
26421
26482
  const html = await readBody(file2);
26422
- const mode = raw ? "raw" : "themed";
26423
26483
  const visibility = isPrivate ? "private" : "public";
26424
26484
  const { url: url2 } = await (await backendClient()).action(api2.pages.create, {
26425
26485
  title,
26426
26486
  group: newGroup,
26427
26487
  html,
26428
- mode,
26429
- visibility
26488
+ style,
26489
+ visibility,
26490
+ issue: issue3 === undefined ? undefined : readIssueRef(issue3)
26430
26491
  });
26431
26492
  console.log(url2);
26432
26493
  }
@@ -26470,12 +26531,12 @@ var list8 = command({
26470
26531
  if (pages.length === 0)
26471
26532
  return console.log(group2 === undefined ? "No pages yet." : "No pages in that group.");
26472
26533
  printTable([
26473
- ["TITLE", "GROUP", "ACCESS", "MODE", "SIZE", "VERSIONS", "CREATED", "URL"],
26534
+ ["TITLE", "GROUP", "ACCESS", "STYLE", "SIZE", "VERSIONS", "CREATED", "URL"],
26474
26535
  ...pages.map((page) => [
26475
26536
  page.title,
26476
26537
  page.group ?? "-",
26477
26538
  page.visibility,
26478
- page.mode,
26539
+ page.style,
26479
26540
  formatBytes(page.size),
26480
26541
  page.versions === 0 ? "-" : String(page.versions),
26481
26542
  new Date(page.createdAt).toISOString().slice(0, 10),
@@ -26498,6 +26559,14 @@ var remove6 = command({
26498
26559
  }
26499
26560
  });
26500
26561
 
26562
+ // src/lib/pages.ts
26563
+ var warnPruned = (pruned) => {
26564
+ if (pruned.length === 0)
26565
+ return;
26566
+ const versions2 = pruned.length === 1 ? `version ${pruned[0]}` : `versions ${pruned.join(", ")}`;
26567
+ console.error(`Pruned ${versions2}; the history keeps the newest ${MAX_PAGE_VERSIONS}.`);
26568
+ };
26569
+
26501
26570
  // src/commands/pages/revert.ts
26502
26571
  var revert = command({
26503
26572
  name: "revert",
@@ -26507,7 +26576,8 @@ var revert = command({
26507
26576
  version: exports_external.coerce.number().int().positive().describe("Version number from `kds pages versions`")
26508
26577
  },
26509
26578
  run: async ({ positionals: { id, version: version4 } }) => {
26510
- const { url: url2 } = await (await backendClient()).mutation(api2.pages.revert, { id: readPageId(id), version: version4 });
26579
+ const { url: url2, pruned } = await (await backendClient()).mutation(api2.pages.revert, { id: readPageId(id), version: version4 });
26580
+ warnPruned(pruned);
26511
26581
  console.log(url2);
26512
26582
  }
26513
26583
  });
@@ -26515,7 +26585,7 @@ var revert = command({
26515
26585
  // src/commands/pages/update.ts
26516
26586
  var update7 = command({
26517
26587
  name: "update",
26518
- description: "Replace a page's HTML, title, group, mode, or visibility",
26588
+ description: "Replace a page's HTML, title, group, style, or visibility",
26519
26589
  positionals: {
26520
26590
  id: exports_external.string().describe("Page id or URL"),
26521
26591
  file: exports_external.string().optional().describe("HTML file, or - for stdin")
@@ -26523,21 +26593,24 @@ var update7 = command({
26523
26593
  options: {
26524
26594
  title: exports_external.string().optional().describe("New page title").meta({ short: "t" }),
26525
26595
  group: exports_external.string().nullable().optional().describe("Move the page to this group, or --no-group to remove it from one").meta({ short: "g", negatable: true }),
26526
- mode: exports_external.enum(PAGE_MODES).optional().describe("New serving mode"),
26527
- visibility: exports_external.enum(PAGE_VISIBILITIES).optional().describe("Who can view the page")
26596
+ style: exports_external.enum(keys(PAGE_STYLES)).optional().describe(`New style \u2014 ${describeChoices(PAGE_STYLES)}`),
26597
+ visibility: exports_external.enum(PAGE_VISIBILITIES).optional().describe("Who can view the page"),
26598
+ issue: exports_external.string().nullable().optional().describe("Link the page to an issue (KAI-N, number, or URL), or --no-issue to unlink it").meta({ negatable: true })
26528
26599
  },
26529
- run: async ({ positionals: { id, file: file2 }, options: { title, group: group2, mode, visibility } }) => {
26530
- if (!file2 && title === undefined && group2 === undefined && mode === undefined && visibility === undefined)
26531
- throw new Error("Nothing to update. Pass a file, --title, --group, --no-group, --mode, or --visibility.");
26600
+ run: async ({ positionals: { id, file: file2 }, options: { title, group: group2, style, visibility, issue: issue3 } }) => {
26601
+ if (!file2 && title === undefined && group2 === undefined && style === undefined && visibility === undefined && issue3 === undefined)
26602
+ throw new Error("Nothing to update. Pass a file, --title, --group, --no-group, --style, --visibility, --issue, or --no-issue.");
26532
26603
  const html = file2 ? await readBody(file2) : undefined;
26533
- const { url: url2 } = await (await backendClient()).action(api2.pages.update, {
26604
+ const { url: url2, pruned } = await (await backendClient()).action(api2.pages.update, {
26534
26605
  id: readPageId(id),
26535
26606
  html,
26536
26607
  title,
26537
26608
  group: group2,
26538
- mode,
26539
- visibility
26609
+ style,
26610
+ visibility,
26611
+ issue: typeof issue3 === "string" ? readIssueRef(issue3) : issue3
26540
26612
  });
26613
+ warnPruned(pruned);
26541
26614
  console.log(url2);
26542
26615
  }
26543
26616
  });
@@ -26559,10 +26632,10 @@ var versions2 = command({
26559
26632
  if (archived.length === 0)
26560
26633
  return console.log("No previous versions.");
26561
26634
  printTable([
26562
- ["VERSION", "MODE", "SIZE", "ARCHIVED"],
26635
+ ["VERSION", "STYLE", "SIZE", "ARCHIVED"],
26563
26636
  ...archived.map((version4) => [
26564
26637
  String(version4.version),
26565
- version4.mode,
26638
+ version4.style,
26566
26639
  formatBytes(version4.size),
26567
26640
  new Date(version4.archivedAt).toISOString().slice(0, 10)
26568
26641
  ])
@@ -26574,10 +26647,10 @@ var versions2 = command({
26574
26647
  var pages = group({
26575
26648
  name: "pages",
26576
26649
  description: "Publish HTML documents to the web",
26577
- longDescription: `Themed pages (the default) render inside the site chrome under a strict CSP: only
26578
- the site theme's styles apply \u2014 inline style attributes and author scripts are
26579
- dropped. A self-contained document with its own CSS or JS needs raw mode, which
26580
- serves it verbatim. A page keeps its URL across updates and reverts.`,
26650
+ longDescription: `A page is an HTML fragment rendered in one of the site's styles:
26651
+ ${describeChoices(PAGE_STYLES, `
26652
+ `)}
26653
+ Basic is the default. A page keeps its URL across updates and reverts.`,
26581
26654
  commands: [create6, list8, get5, update7, versions2, revert, remove6]
26582
26655
  });
26583
26656
 
@@ -27198,6 +27271,7 @@ var rootCommand = group({
27198
27271
 
27199
27272
  // src/lib/errors.ts
27200
27273
  var errorMessage = (error51) => error51 instanceof ConvexError && typeof error51.data === "string" ? error51.data : error51.message;
27274
+ var isRedactedServerError = (error51) => error51 instanceof Error && !(error51 instanceof ConvexError) && /^\[Request ID: \w+\] Server Error$/.test(error51.message);
27201
27275
 
27202
27276
  // src/lib/update-check.ts
27203
27277
  var latestVersion = async () => {
@@ -27228,6 +27302,12 @@ var maybeNotifyUpdate = async () => {
27228
27302
  if (latest && Bun.semver.order(latest, CLI_VERSION) === 1)
27229
27303
  console.error(`kds v${latest} available (you have v${CLI_VERSION}) \u2014 run 'kds upgrade'`);
27230
27304
  };
27305
+ var staleCliHint = async (current = CLI_VERSION) => {
27306
+ const latest = env.KDS_NO_UPDATE_CHECK ? undefined : await latestVersion().catch(() => {
27307
+ return;
27308
+ });
27309
+ return latest && Bun.semver.order(latest, current) === 1 ? `kds v${current} is behind v${latest}, so the server likely refused a request this version still sends \u2014 run 'kds upgrade' and retry.` : "The server gave no details. If kds was installed a while ago, try 'kds upgrade'; otherwise report the request id.";
27310
+ };
27231
27311
 
27232
27312
  // src/index.ts
27233
27313
  var args = Bun.argv.slice(2);
@@ -27237,6 +27317,8 @@ try {
27237
27317
  await maybeNotifyUpdate();
27238
27318
  } catch (error51) {
27239
27319
  console.error(errorMessage(error51));
27320
+ if (isRedactedServerError(error51))
27321
+ console.error(await staleCliHint());
27240
27322
  process.exitCode = 1;
27241
27323
  } finally {
27242
27324
  closePrompts();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@islamihab/kds",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Command-line client for Kai Dev Studio",
5
5
  "license": "MIT",
6
6
  "publishConfig": {