@signalridge/pi-welcome 1.3.10 → 1.3.11

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/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.3.11
4
+ ### Patch Changes
5
+
6
+ - 3096585: Render Welcome key hints from the host's live bindings, report the inline snippet picker as a native blocking question, and cancel history search below five terminal rows without accepting hidden results or changing the draft.
7
+
3
8
  ## 1.3.10
4
9
  ### Patch Changes
5
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signalridge/pi-welcome",
3
- "version": "1.3.10",
3
+ "version": "1.3.11",
4
4
  "description": "Startup resource and repository summary card for Pi.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/index.ts CHANGED
@@ -27,6 +27,7 @@ import {
27
27
  type ExtensionAPI,
28
28
  type ExtensionContext,
29
29
  getAgentDir,
30
+ type KeybindingHints,
30
31
  keyText,
31
32
  loadProjectContextFiles,
32
33
  SettingsManager,
@@ -75,7 +76,7 @@ const MAX_NAMES = 8;
75
76
  interface WelcomeData {
76
77
  rows: [string, string][];
77
78
  /**
78
- * Key hints, most useful first. Kept as separate items rather than one joined
79
+ * Legacy key hints (new entries store only facts). Kept as separate items rather than one joined
79
80
  * string so a narrow card can drop the trailing ones instead of wrapping a
80
81
  * separator onto a line of its own. Optional because an entry written before
81
82
  * this field existed replays without any.
@@ -173,28 +174,25 @@ function capitalizeKey(key: string): string {
173
174
  /**
174
175
  * The key hints Pi's own header would have shown, as plain text.
175
176
  *
176
- * Read from the live keybindings rather than hard-coded, so a rebound key is
177
- * still described correctly. Deliberately not built with pi's `keyHint()`: that
178
- * colors through pi's own theme singleton, while this card renders with the
179
- * theme handed to its entry renderer, and the two would disagree after a theme
180
- * change. The whole line is dimmed by the renderer instead of highlighting
181
- * individual keys.
177
+ * Renderers pass the host-injected formatter so remapped and unbound keys
178
+ * reflect the host, even when the extension resolves a separate SDK copy.
179
+ * The no-argument form remains available for existing callers. Use plain
180
+ * `keyText`, not styled `keyHint`, so the card's supplied theme owns styling.
182
181
  */
183
- export function collectHints(): string[] {
182
+ export function collectHints(hints: Pick<KeybindingHints, "keyText"> = { keyText }): string[] {
184
183
  try {
185
184
  // Ordered most useful first: a narrow card keeps the head of this list.
186
185
  return [
187
- [capitalizeKey(keyText("app.interrupt")), "interrupt"],
186
+ [capitalizeKey(hints.keyText("app.interrupt")), "interrupt"],
188
187
  ["/", "commands"],
189
188
  ["!", "bash"],
190
- [capitalizeKey(keyText("app.clear")), "clear"],
191
- [capitalizeKey(keyText("app.tools.expand")), "expand tools"],
189
+ [capitalizeKey(hints.keyText("app.clear")), "clear"],
190
+ [capitalizeKey(hints.keyText("app.tools.expand")), "expand tools"],
192
191
  ]
193
192
  .filter(([key]) => key && key.length > 0)
194
193
  .map(([key, description]) => `${key} ${description}`);
195
194
  } catch {
196
- // Keybindings are a TUI singleton; if it is not up yet, a card without a
197
- // hint line is better than no card.
195
+ // If the formatter is unavailable, omit hints rather than invent bindings.
198
196
  return [];
199
197
  }
200
198
  }
@@ -331,8 +329,7 @@ function collect(pi: ExtensionAPI, ctx: ExtensionContext): WelcomeData {
331
329
  }
332
330
  }
333
331
 
334
- const hints = collectHints();
335
- return hints.length > 0 ? { rows, hints } : { rows };
332
+ return { rows }; // Keybindings are live presentation, not persisted workspace facts.
336
333
  }
337
334
 
338
335
  // ─── Card Component ────────────────────────────────────────────────────────────
@@ -390,6 +387,7 @@ export class WelcomeCard implements Component {
390
387
  constructor(
391
388
  data: WelcomeData,
392
389
  private readonly theme: Theme,
390
+ private readonly keybindings?: Pick<KeybindingHints, "keyText">,
393
391
  ) {
394
392
  this.rows = data.rows.map(([label, value]) => [sanitizeCardText(label), sanitizeCardText(value)]);
395
393
  // The entry is replayed from a session file on disk, which an older build
@@ -408,10 +406,10 @@ export class WelcomeCard implements Component {
408
406
  return text + " ".repeat(safeWidth - renderedWidth);
409
407
  }
410
408
 
411
- private renderCompact(width: number): string[] {
409
+ private renderCompact(width: number, hints: readonly string[]): string[] {
412
410
  const t = this.theme;
413
411
  const lines = [
414
- t.fg("muted", this.hints.length > 0 ? (this.hints[0] ?? "ready") : "ready"),
412
+ t.fg("muted", hints.length > 0 ? (hints[0] ?? "ready") : "ready"),
415
413
  ...this.rows.map(([label, value]) =>
416
414
  label === GAP[0] && value === GAP[1] ? "" : `${t.fg("dim", `${label}:`)} ${t.fg("text", value)}`,
417
415
  ),
@@ -421,7 +419,8 @@ export class WelcomeCard implements Component {
421
419
 
422
420
  render(width: number): string[] {
423
421
  const safeWidth = Math.max(1, width);
424
- if (safeWidth < MIN_WIDTH) return this.renderCompact(safeWidth);
422
+ const hints = this.keybindings ? collectHints(this.keybindings).map(sanitizeCardText) : this.hints;
423
+ if (safeWidth < MIN_WIDTH) return this.renderCompact(safeWidth, hints);
425
424
 
426
425
  const t = this.theme;
427
426
  const border = (text: string) => t.fg("borderAccent", text);
@@ -442,7 +441,7 @@ export class WelcomeCard implements Component {
442
441
  blank(),
443
442
  );
444
443
 
445
- const hintLine = fitHints(this.hints, Math.max(1, inner - PAD * 2));
444
+ const hintLine = fitHints(hints, Math.max(1, inner - PAD * 2));
446
445
  if (hintLine) {
447
446
  // The whole line is dimmed rather than highlighting each key: this is
448
447
  // orientation, not a control the user is meant to look at.
@@ -498,10 +497,12 @@ function withLiveInventory(data: WelcomeData, pi: ExtensionAPI, ctx: ExtensionCo
498
497
 
499
498
  export default function (pi: ExtensionAPI) {
500
499
  let currentContext: ExtensionContext | undefined;
501
- pi.registerEntryRenderer<WelcomeData>(ENTRY_TYPE, (entry, _options, theme) => {
500
+ pi.registerEntryRenderer<WelcomeData>(ENTRY_TYPE, (entry, options, theme) => {
502
501
  const data = entry.data;
503
502
  if (!data?.rows?.length) return undefined;
504
- return new WelcomeCard(currentContext ? withLiveInventory(data, pi, currentContext) : data, theme);
503
+ const live = currentContext ? withLiveInventory(data, pi, currentContext) : data;
504
+ // Ignore legacy persisted hints on replay; never rewrite the stored entry.
505
+ return new WelcomeCard(live, theme, options);
505
506
  });
506
507
 
507
508
  pi.on("session_start", async (_event, ctx) => {