@kud/gh-ink 0.70.0 → 0.72.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.
package/dist/index.d.ts CHANGED
@@ -468,6 +468,16 @@ interface InboxExtension {
468
468
  drills?: AnyItem["kind"][];
469
469
  body: (onExit: () => void, target?: ExtensionTarget) => ReactNode;
470
470
  commands?: (target: ExtensionTarget) => Command[];
471
+ resolve?: (input: string) => (() => Promise<AnyItem>) | null;
472
+ }
473
+ /**
474
+ * How a `resolve` thunk says "nothing by that name": the launcher draws its
475
+ * message muted, the way it draws a query that matched nothing, and keeps the
476
+ * input open. Any other rejection is a failure and is drawn in the error tone —
477
+ * the difference a reader needs between "you typed it wrong" and "try again".
478
+ */
479
+ declare class LookupMiss extends Error {
480
+ constructor(message: string);
471
481
  }
472
482
 
473
483
  /**
@@ -909,4 +919,4 @@ declare const matchesFilter: (repo: string, filter: RepoFilter) => boolean;
909
919
  */
910
920
  declare const parsePatterns: (value: string) => string[];
911
921
 
912
- export { type Action, type ActionGroup, ActionMenu, App, COLS, type ChromeHints, type ChromeSpec, type ChromeState, CiStatusLine, type CiStatusState, type Command, CommentsPanel, type CommentsPanelProps, type DetailContext, type ExplainSection, type ExtensionTarget, HealthPanel, type HealthPanelProps, type InboxBudget, type InboxExtension, type JiraAvailableTransition, type JiraTransition, type JiraTransitionsFor, type LiveLabel, MIN_SIDEBAR_COLS, type MenuGap, type MenuRow, PrRow, type PrRowProps, type Rails, type RepoFilter, type RowAnnouncement, type RowMotion, SIDEBAR_COLS, type SettledResult, SidePanel, type Sidebar, type SidebarRow, type StatusStrip, StatusStripLine, type StripItem, type StripState, type StripStatusState, type TrailingColumns, type TrailingShed, ageLabel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, isMenuGap, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, menuRowsOf, menuTone, moveCursor, numberColumnsOf, openInTab, parsePatterns, railCapacity, railHeights, railRowsOf, railWidth, railsOf, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sectionShedOf, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, trailingColumnsOf, truncate, useActionMenu, useChrome, windowCount, withHeaders, withoutItem, workCount, writeCache };
922
+ export { type Action, type ActionGroup, ActionMenu, App, COLS, type ChromeHints, type ChromeSpec, type ChromeState, CiStatusLine, type CiStatusState, type Command, CommentsPanel, type CommentsPanelProps, type DetailContext, type ExplainSection, type ExtensionTarget, HealthPanel, type HealthPanelProps, type InboxBudget, type InboxExtension, type JiraAvailableTransition, type JiraTransition, type JiraTransitionsFor, type LiveLabel, LookupMiss, MIN_SIDEBAR_COLS, type MenuGap, type MenuRow, PrRow, type PrRowProps, type Rails, type RepoFilter, type RowAnnouncement, type RowMotion, SIDEBAR_COLS, type SettledResult, SidePanel, type Sidebar, type SidebarRow, type StatusStrip, StatusStripLine, type StripItem, type StripState, type StripStatusState, type TrailingColumns, type TrailingShed, ageLabel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, isMenuGap, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, menuRowsOf, menuTone, moveCursor, numberColumnsOf, openInTab, parsePatterns, railCapacity, railHeights, railRowsOf, railWidth, railsOf, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sectionShedOf, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, trailingColumnsOf, truncate, useActionMenu, useChrome, windowCount, withHeaders, withoutItem, workCount, writeCache };
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import React2, { createContext, useState, useRef, useContext, useEffect, useCallback, useMemo } from 'react';
2
2
  import { useWindowSize, useInput, Text, Box } from 'ink';
3
3
  import { colors, ScrollView, TextInput, Pill, getIconMode, FooterHints, useAppKeys, LoadingScreen, StatusMessage, useFilterMode, useListCursor, CommandPalette, Tabs, ProgressBar, pillWidth } from '@kud/ink-ui';
4
- import { isPassCheck, isFailCheck, isInconclusiveCheck, resolveThread, unresolveThread, replyToThread, rerunFailedRun, mergePr, reRequestReviewer } from '@kud/gh';
4
+ import { isPassCheck, isFailCheck, isInconclusiveCheck, resolveThread, unresolveThread, replyToThread, rerunFailedRun, mergePr, reRequestReviewer, parseRef, formatRef, fetchItemNode } from '@kud/gh';
5
5
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
6
- import { PIN_MARK, sizeOf, sizePartsOf, depthOf, impliedLabels, labelPriority, checkoutDirs, profileOf, inboxConfig, relativeTime, filterBySearch, filterByRepos, filterByOrigin } from '@kud/gh-workflow';
6
+ import { PIN_MARK, sizeOf, sizePartsOf, depthOf, impliedLabels, labelPriority, checkoutDirs, profileOf, inboxConfig, relativeTime, filterBySearch, filterByRepos, filterByOrigin, refCandidates, resolveRef } from '@kud/gh-workflow';
7
7
  export { NEEDS_YOU_SECTION, PIN_MARK, bandOf, checkoutDirs, configureInbox, filterByOrigin, filterByRepos, filterBySearch, impliedLabels, inboxConfig, insertRepoHeaders, labelPriority, layoutGHItems, profileOf, relativeTime, repoPriority, resetInboxConfig, sortByRecency, sortItems, whoseMove } from '@kud/gh-workflow';
8
8
  import { $ } from 'zx';
9
9
  import { spawn } from 'child_process';
@@ -1194,6 +1194,189 @@ var useChrome = (spec) => {
1194
1194
  }, [setChrome, scope, hintsKey]);
1195
1195
  return chrome !== null;
1196
1196
  };
1197
+ var LookupMiss = class extends Error {
1198
+ constructor(message) {
1199
+ super(message);
1200
+ this.name = "LookupMiss";
1201
+ }
1202
+ };
1203
+ var isGH = (item) => item.kind === "pr" || item.kind === "issue";
1204
+ var listedAt = (sections, repo, number) => {
1205
+ const want = repo.toLowerCase();
1206
+ for (const section of sections)
1207
+ for (const item of section.items)
1208
+ if (isGH(item) && item.number === number && item.repo.toLowerCase() === want)
1209
+ return item;
1210
+ return void 0;
1211
+ };
1212
+ var listedCopy = (sections, item) => {
1213
+ if (isGH(item)) return listedAt(sections, item.repo, item.number);
1214
+ const url = "url" in item ? item.url : void 0;
1215
+ if (!url) return void 0;
1216
+ for (const section of sections)
1217
+ for (const row of section.items)
1218
+ if (row.kind === item.kind && "url" in row && row.url === url) return row;
1219
+ return void 0;
1220
+ };
1221
+ var settle = (sections, item) => listedCopy(sections, item) ?? (isGH(item) ? { ...item, notInInbox: true } : item);
1222
+ var githubClaim = (query, { activeRepo, repos, sections }) => {
1223
+ const ref = parseRef(query);
1224
+ if (!ref) return null;
1225
+ const near = ref.repo ? listedAt(sections, ref.repo, ref.number) : activeRepo ? listedAt(sections, activeRepo, ref.number) : void 0;
1226
+ const label = near ? `${near.repo}#${near.number}` : formatRef(ref);
1227
+ const repo = ref.repo ?? refCandidates(activeRepo, repos)[0];
1228
+ const text = query.trim();
1229
+ const browserUrl = near?.url ?? (/^https?:/i.test(text) ? text : repo ? `https://github.com/${repo}/issues/${ref.number}` : void 0);
1230
+ return {
1231
+ label,
1232
+ browser: browserUrl ? {
1233
+ label: near || !repo ? label : `${repo}#${ref.number}`,
1234
+ url: browserUrl
1235
+ } : void 0,
1236
+ fetch: async () => {
1237
+ if (near) return near;
1238
+ const item = await resolveRef(text, {
1239
+ fetchNode: (r, n) => fetchItemNode(r, n),
1240
+ activeRepo,
1241
+ repos
1242
+ });
1243
+ if (!item) throw new LookupMiss(`nothing matches "${label}"`);
1244
+ return item;
1245
+ }
1246
+ };
1247
+ };
1248
+ var claimFor = (query, context, extensions = []) => {
1249
+ if (!query.trim()) return null;
1250
+ const github = githubClaim(query, context);
1251
+ if (github) return github;
1252
+ for (const ext of extensions) {
1253
+ const fetch = ext.resolve?.(query);
1254
+ if (fetch) return { label: query.trim(), fetch };
1255
+ }
1256
+ return null;
1257
+ };
1258
+ var reasonOf = (error) => {
1259
+ const e = error;
1260
+ const text = typeof e?.stderr === "string" && e.stderr.trim() || typeof e?.message === "string" && e.message || String(error);
1261
+ const line = text.split("\n").find((l) => l.trim()) ?? text;
1262
+ return line.replace(/^gh:\s*/, "").trim();
1263
+ };
1264
+ var useLauncherLookup = (palette, open) => {
1265
+ const [lookup, setLookup] = useState(null);
1266
+ const seq = useRef(0);
1267
+ const latest = useRef({ palette, open });
1268
+ latest.current = { palette, open };
1269
+ const start = (query, claim) => {
1270
+ const id = ++seq.current;
1271
+ const live = () => id === seq.current && latest.current.palette === query;
1272
+ setLookup({ query, phase: "loading", label: claim.label });
1273
+ claim.fetch().then(
1274
+ (item) => {
1275
+ if (!live()) return;
1276
+ setLookup(null);
1277
+ if (!latest.current.open(item))
1278
+ setLookup({
1279
+ query,
1280
+ phase: "failed",
1281
+ label: claim.label,
1282
+ message: `nothing here can open ${claim.label}`
1283
+ });
1284
+ },
1285
+ (error) => {
1286
+ if (!live()) return;
1287
+ setLookup(
1288
+ error instanceof LookupMiss ? {
1289
+ query,
1290
+ phase: "missed",
1291
+ label: claim.label,
1292
+ message: error.message
1293
+ } : {
1294
+ query,
1295
+ phase: "failed",
1296
+ label: claim.label,
1297
+ message: reasonOf(error)
1298
+ }
1299
+ );
1300
+ }
1301
+ );
1302
+ };
1303
+ const reset = () => {
1304
+ seq.current++;
1305
+ setLookup(null);
1306
+ };
1307
+ return {
1308
+ lookup: lookup && lookup.query === palette ? lookup : null,
1309
+ start,
1310
+ reset
1311
+ };
1312
+ };
1313
+ var lookupRows = (claim, lookup, query, start, openUrl) => {
1314
+ const ref = (s) => /* @__PURE__ */ jsx(Text3, { color: colors.accent, children: s });
1315
+ if (lookup?.phase === "loading")
1316
+ return {
1317
+ exclusive: true,
1318
+ rows: [
1319
+ {
1320
+ id: "launcher:lookup",
1321
+ title: `Looking up ${claim.label}\u2026`,
1322
+ label: /* @__PURE__ */ jsxs(Text3, { dimColor: true, children: [
1323
+ "Looking up ",
1324
+ ref(claim.label),
1325
+ "\u2026"
1326
+ ] }),
1327
+ run: () => {
1328
+ },
1329
+ keepOpen: true
1330
+ }
1331
+ ]
1332
+ };
1333
+ if (lookup?.phase === "missed")
1334
+ return { exclusive: true, rows: [], message: lookup.message };
1335
+ if (lookup?.phase === "failed")
1336
+ return {
1337
+ exclusive: true,
1338
+ rows: [
1339
+ {
1340
+ id: "launcher:retry",
1341
+ title: `Couldn't look up ${claim.label}: ${lookup.message}`,
1342
+ label: /* @__PURE__ */ jsxs(Text3, { color: colors.error, children: [
1343
+ "\u2717 couldn't look up ",
1344
+ claim.label,
1345
+ " \xB7 ",
1346
+ lookup.message
1347
+ ] }),
1348
+ run: () => start(query, claim),
1349
+ keepOpen: true
1350
+ }
1351
+ ]
1352
+ };
1353
+ const rows = [
1354
+ {
1355
+ id: "launcher:open",
1356
+ title: `\u21B5 opens ${claim.label}`,
1357
+ label: /* @__PURE__ */ jsxs(Text3, { children: [
1358
+ "\u21B5 opens ",
1359
+ ref(claim.label)
1360
+ ] }),
1361
+ run: () => start(query, claim),
1362
+ keepOpen: true
1363
+ }
1364
+ ];
1365
+ const browser = claim.browser;
1366
+ if (browser)
1367
+ rows.push({
1368
+ id: "launcher:browser",
1369
+ title: `Open ${browser.label} in browser`,
1370
+ label: /* @__PURE__ */ jsxs(Text3, { children: [
1371
+ "Open ",
1372
+ ref(browser.label),
1373
+ " ",
1374
+ /* @__PURE__ */ jsx(Text3, { color: colors.info, children: "in browser" })
1375
+ ] }),
1376
+ run: () => openUrl(browser.url, browser.label)
1377
+ });
1378
+ return { exclusive: false, rows };
1379
+ };
1197
1380
 
1198
1381
  // src/inbox/cache.ts
1199
1382
  var cacheTtlMs = () => inboxConfig().cacheTtlMs;
@@ -2011,7 +2194,7 @@ var ROW_MAX_COLS = 140;
2011
2194
  var OVERLAY_BG = "#22222e";
2012
2195
  var SELECTION_BG = "#16161f";
2013
2196
  var selectionBackground = (active, backdropped) => active && !backdropped ? SELECTION_BG : void 0;
2014
- var TICKET_KEY_COLOUR = "#C792EA";
2197
+ var TICKET_KEY_COLOUR = "#FFCB6B";
2015
2198
  var taskKeyStyle = () => ({
2016
2199
  color: TICKET_KEY_COLOUR,
2017
2200
  bold: true
@@ -2970,9 +3153,9 @@ var HelpModal = ({
2970
3153
  ["u", "unsubscribe from this item"],
2971
3154
  ["x", "remove yourself as reviewer"],
2972
3155
  ...hasJira ? [
2973
- ["t", "Jira: move / open ticket"],
2974
- ["\u2303K", "launch \xB7 jump to a ticket by key"]
3156
+ ["t", "Jira: move / open ticket"]
2975
3157
  ] : [],
3158
+ ["\u2303K", "launch \xB7 open a ticket or PR by name"],
2976
3159
  ["/", "search"],
2977
3160
  ["f", "filter by repo"],
2978
3161
  ["r", "refresh"],
@@ -3861,9 +4044,10 @@ var BrowseScreen = ({
3861
4044
  ["\u2190\u2192", "tab"],
3862
4045
  ["\u21B5/d", "open"],
3863
4046
  ["m", "actions"],
3864
- // Only where Jira is configured: without it the launcher can only say
3865
- // so, and a footer key that opens an apology is a broken feature.
3866
- ...jiraBase ? [["\u2303K", "launch"]] : [],
4047
+ // Always, now that the launcher opens a pasted PR or issue too. It was
4048
+ // shown only where Jira was configured, when a ticket key was all it
4049
+ // could take and without one it could only apologise.
4050
+ ["\u2303K", "launch"],
3867
4051
  // Advertised only where it does something, and named for what it
3868
4052
  // shows rather than for the furniture: nobody wants "a sidebar".
3869
4053
  ...showRail ? [["\u21E5", railTitle]] : hasRail ? [["i", railTitle]] : [],
@@ -3877,10 +4061,16 @@ var BrowseScreen = ({
3877
4061
  typing: searchInput,
3878
4062
  nerd: getIconMode() === "nerd"
3879
4063
  });
4064
+ const launcherLookup = useLauncherLookup(palette, (item) => {
4065
+ if (!openDrillView(settle(localSections, item))) return false;
4066
+ setPalette(null);
4067
+ return true;
4068
+ });
3880
4069
  const launcher = useMemo(() => {
3881
4070
  const run = /* @__PURE__ */ new Map();
4071
+ const keepOpen = /* @__PURE__ */ new Set();
3882
4072
  if (palette === null)
3883
- return { items: [], run, message: void 0 };
4073
+ return { items: [], run, keepOpen, message: void 0 };
3884
4074
  const query = palette.trim();
3885
4075
  const ticketKey = jiraKeyRe ? query.toUpperCase().match(jiraKeyRe)?.[0] : void 0;
3886
4076
  const commands = [];
@@ -3891,6 +4081,31 @@ var BrowseScreen = ({
3891
4081
  /* @__PURE__ */ jsx(Text3, { color: colors.info, children: where })
3892
4082
  ] });
3893
4083
  const labels = /* @__PURE__ */ new Map();
4084
+ const claim = claimFor(
4085
+ query,
4086
+ {
4087
+ activeRepo: activeItem?.kind === "pr" || activeItem?.kind === "issue" ? activeItem.repo : void 0,
4088
+ repos: reposInSections(localSections),
4089
+ sections: localSections
4090
+ },
4091
+ extensions
4092
+ );
4093
+ const claimed = claim ? lookupRows(
4094
+ claim,
4095
+ launcherLookup.lookup,
4096
+ palette,
4097
+ launcherLookup.start,
4098
+ (url, label) => {
4099
+ quietly`open ${url}`.catch(() => {
4100
+ });
4101
+ showFlash(`\u2197 Opened ${label} in browser`);
4102
+ }
4103
+ ) : void 0;
4104
+ for (const row of claimed?.rows ?? []) {
4105
+ commands.push({ id: row.id, title: row.title, run: row.run });
4106
+ labels.set(row.id, row.label);
4107
+ if (row.keepOpen) keepOpen.add(row.id);
4108
+ }
3894
4109
  if (ticketKey && jiraBase) {
3895
4110
  const row = {
3896
4111
  kind: "task",
@@ -3926,16 +4141,26 @@ var BrowseScreen = ({
3926
4141
  commands.push({ ...command, id: `${ext.id}:${command.id}` });
3927
4142
  }
3928
4143
  }
4144
+ if (claimed?.exclusive) commands.splice(claimed.rows.length);
3929
4145
  for (const command of commands) run.set(command.id, command.run);
3930
- const message = !jiraBase ? `Jira not configured${jiraSetupHint ? ` \xB7 ${jiraSetupHint}` : ""}` : query && !ticketKey ? `no ticket matches "${query}"` : void 0;
4146
+ const message = claimed ? claimed.message : !jiraBase ? `Jira not configured${jiraSetupHint ? ` \xB7 ${jiraSetupHint}` : ""}` : query && !ticketKey ? `nothing matches "${query}"` : void 0;
3931
4147
  const items = commands.map((command) => ({
3932
4148
  id: command.id,
3933
4149
  title: command.title,
3934
4150
  group: command.group,
3935
4151
  label: labels.get(command.id)
3936
4152
  }));
3937
- return { items, run, message };
3938
- }, [palette, activeItem, extensions, jiraBase, jiraKeyRe, jiraSetupHint]);
4153
+ return { items, run, keepOpen, message };
4154
+ }, [
4155
+ palette,
4156
+ activeItem,
4157
+ extensions,
4158
+ jiraBase,
4159
+ jiraKeyRe,
4160
+ jiraSetupHint,
4161
+ localSections,
4162
+ launcherLookup.lookup
4163
+ ]);
3939
4164
  const chrome = useContext(InboxChromeContext);
3940
4165
  const overlayOpen = overlayBody != null;
3941
4166
  const overlay = palette !== null ? /* @__PURE__ */ jsx(
@@ -3943,15 +4168,18 @@ var BrowseScreen = ({
3943
4168
  {
3944
4169
  items: launcher.items,
3945
4170
  query: palette,
3946
- onQueryChange: setPalette,
4171
+ onQueryChange: (query) => {
4172
+ launcherLookup.reset();
4173
+ setPalette(query);
4174
+ },
3947
4175
  onSelect: (id) => {
3948
4176
  const run = launcher.run.get(id);
3949
- setPalette(null);
4177
+ if (!launcher.keepOpen.has(id)) setPalette(null);
3950
4178
  void run?.();
3951
4179
  },
3952
4180
  onClose: () => setPalette(null),
3953
4181
  message: launcher.message,
3954
- placeholder: "ticket key\u2026",
4182
+ placeholder: "ticket, PR, owner/repo#N or URL\u2026",
3955
4183
  width: Math.min(60, Math.max(30, listCols - 2)),
3956
4184
  maxRows: Math.max(3, listHeight - 6),
3957
4185
  hints: [
@@ -4054,7 +4282,8 @@ var BrowseScreen = ({
4054
4282
  s.id,
4055
4283
  pulseSettled ? PULSE_SETTLED_FRAME : sparkFrame
4056
4284
  ),
4057
- markerColor: colors.accent
4285
+ markerColor: colors.accent,
4286
+ group: s.group
4058
4287
  }))
4059
4288
  }
4060
4289
  ) }),
@@ -4727,4 +4956,4 @@ var matchesFilter = (repo, filter) => {
4727
4956
  };
4728
4957
  var parsePatterns = (value) => value.split(",").map((p) => p.trim()).filter(Boolean);
4729
4958
 
4730
- export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, MIN_SIDEBAR_COLS, PrRow, SIDEBAR_COLS, SidePanel, StatusStripLine, ageLabel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, isMenuGap, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, menuRowsOf, menuTone, moveCursor, numberColumnsOf, openInTab, parsePatterns, railCapacity, railHeights, railRowsOf, railWidth, railsOf, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sectionShedOf, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, trailingColumnsOf, truncate, useActionMenu, useChrome, windowCount, withHeaders, withoutItem, workCount, writeCache };
4959
+ export { ActionMenu, App, COLS, CiStatusLine, CommentsPanel, HealthPanel, LookupMiss, MIN_SIDEBAR_COLS, PrRow, SIDEBAR_COLS, SidePanel, StatusStripLine, ageLabel, budgetNotice, buildActions, buildCheckoutCmd, clipboard, counts, drillCmd, explainGhAction, explainItem, fitCount, gapsAbove, healthColor, healthDisplay, healthGlyph, healthLegend, isMenuGap, itermRun, jumpToRepo, jumpToRepoPane, matchesFilter, maxViewStart, menuRowsOf, menuTone, moveCursor, numberColumnsOf, openInTab, parsePatterns, railCapacity, railHeights, railRowsOf, railWidth, railsOf, readCache, renderMarkdown, reposInSections, resolveRepoPath, runHere, runInPane, runInPaneHorizontal, sameCiStatusState, sectionShedOf, signatureOf, stripGlyph, stripLayout, stripSignature, toCiStatusState, trailingColumnsOf, truncate, useActionMenu, useChrome, windowCount, withHeaders, withoutItem, workCount, writeCache };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kud/gh-ink",
3
- "version": "0.70.0",
3
+ "version": "0.72.0",
4
4
  "description": "Ink components for rendering GitHub PR review comments and health — controlled, presentation-only, built on @kud/ink-ui and fed by @kud/gh.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -49,12 +49,12 @@
49
49
  "react": ">=19"
50
50
  },
51
51
  "dependencies": {
52
- "@kud/gh": "0.20.0",
53
- "@kud/gh-workflow": "0.14.1",
52
+ "@kud/gh": "0.21.0",
53
+ "@kud/gh-workflow": "0.16.0",
54
54
  "zx": "8.8.5"
55
55
  },
56
56
  "devDependencies": {
57
- "@kud/ink-ui": "0.34.0",
57
+ "@kud/ink-ui": "0.35.0",
58
58
  "@types/node": "22.20.1",
59
59
  "@types/react": "19.2.17",
60
60
  "ink": "7.1.0",