pi-goosedump 0.9.2 → 0.9.3

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.ts +59 -42
  2. package/package.json +2 -2
package/index.ts CHANGED
@@ -80,6 +80,9 @@ const DEFAULT_GOOSEDUMP_SETTINGS: GoosedumpSettings = {
80
80
  turnsBeforeCompact: 0,
81
81
  };
82
82
 
83
+ const TURNS_BEFORE_COMPACT_MIN = 0;
84
+ const TURNS_BEFORE_COMPACT_MAX = 255;
85
+
83
86
  function piAgentDir(): string {
84
87
  return process.env.PI_CODING_AGENT_DIR ?? join(homedir(), '.pi', 'agent');
85
88
  }
@@ -113,7 +116,12 @@ function readGoosedumpSettingsFrom(path: string): Partial<GoosedumpSettings> {
113
116
 
114
117
  const settings: Partial<GoosedumpSettings> = {};
115
118
  const value = raw.turnsBeforeCompact;
116
- if (typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 && value <= 255) {
119
+ if (
120
+ typeof value === 'number' &&
121
+ Number.isSafeInteger(value) &&
122
+ value >= TURNS_BEFORE_COMPACT_MIN &&
123
+ value <= TURNS_BEFORE_COMPACT_MAX
124
+ ) {
117
125
  settings.turnsBeforeCompact = value;
118
126
  }
119
127
  return settings;
@@ -248,6 +256,13 @@ function missingSessionId(tool: string, provider = 'pi'): AgentToolResult<void>
248
256
  return textResult(`session is required for ${tool} when no current session is available`);
249
257
  }
250
258
 
259
+ const GOOSEDUMP_UNAVAILABLE_MESSAGE =
260
+ 'goosedump is not available. Install with: npm install @jarkkojs/goosedump';
261
+
262
+ function goosedumpUnavailableResult(): AgentToolResult<void> {
263
+ return textResult(GOOSEDUMP_UNAVAILABLE_MESSAGE);
264
+ }
265
+
251
266
  function runGoosedump(args: string[]): string {
252
267
  try {
253
268
  return execFileSync('node', [resolveGoosedumpBinary(), ...args], {
@@ -552,20 +567,28 @@ function isControlChar(char: string): boolean {
552
567
  class NumberInputSubmenu implements Component {
553
568
  private readonly input = new Input();
554
569
  private readonly hint: (text: string) => string;
555
- private readonly onSubmitValue: (value: string) => void;
570
+ private readonly onSubmitValue: (value: number) => void;
556
571
  private readonly onCancelEdit: () => void;
572
+ private readonly onInvalidValue: (message: string) => void;
557
573
  private readonly title: string;
574
+ private readonly currentValue: number;
575
+ private readonly min: number;
576
+ private readonly max: number;
558
577
 
559
578
  constructor(
560
579
  title: string,
561
- initialValue: string,
562
- onSubmit: (value: string) => void,
580
+ currentValue: number,
581
+ onSubmit: (value: number) => void,
563
582
  onCancel: () => void,
583
+ options?: { min?: number; max?: number; onInvalid?: (message: string) => void },
564
584
  ) {
565
585
  this.title = title;
586
+ this.currentValue = currentValue;
566
587
  this.onSubmitValue = onSubmit;
567
588
  this.onCancelEdit = onCancel;
568
- this.input.setValue(initialValue);
589
+ this.onInvalidValue = options?.onInvalid ?? (() => {});
590
+ this.min = options?.min ?? 0;
591
+ this.max = options?.max ?? 255;
569
592
  this.hint = getSettingsListTheme().hint;
570
593
  }
571
594
 
@@ -573,8 +596,16 @@ class NumberInputSubmenu implements Component {
573
596
  const kb = getKeybindings();
574
597
  if (kb.matches(data, 'tui.select.confirm') || data === '\n') {
575
598
  const digits = this.input.getValue().replace(/\D/g, '');
599
+ if (digits === '') {
600
+ this.onCancelEdit();
601
+ return;
602
+ }
576
603
  const parsed = Number(digits);
577
- this.onSubmitValue(digits !== '' && Number.isSafeInteger(parsed) ? String(parsed) : '0');
604
+ if (!Number.isSafeInteger(parsed) || parsed < this.min || parsed > this.max) {
605
+ this.onInvalidValue(`Enter a whole number between ${this.min} and ${this.max}`);
606
+ return;
607
+ }
608
+ this.onSubmitValue(parsed);
578
609
  return;
579
610
  }
580
611
  if (kb.matches(data, 'tui.select.cancel')) {
@@ -593,7 +624,7 @@ class NumberInputSubmenu implements Component {
593
624
 
594
625
  render(width: number): string[] {
595
626
  return [
596
- this.hint(` ${this.title}`),
627
+ this.hint(` ${this.title} · current ${this.currentValue} · ${this.min}-${this.max}`),
597
628
  '',
598
629
  ...this.input.render(width),
599
630
  '',
@@ -637,9 +668,14 @@ async function runSettingsEditor(ctx: ExtensionContext): Promise<void> {
637
668
  submenu: (currentValue, subDone) =>
638
669
  new NumberInputSubmenu(
639
670
  settingLabel(scope, 'turnsBeforeCompact'),
640
- currentValue,
641
- (value) => subDone(value),
671
+ Number(currentValue),
672
+ (value) => subDone(String(value)),
642
673
  () => subDone(),
674
+ {
675
+ min: TURNS_BEFORE_COMPACT_MIN,
676
+ max: TURNS_BEFORE_COMPACT_MAX,
677
+ onInvalid: (message) => ctx.ui.notify(message, 'error'),
678
+ },
643
679
  ),
644
680
  }));
645
681
  }
@@ -652,7 +688,12 @@ async function runSettingsEditor(ctx: ExtensionContext): Promise<void> {
652
688
  (id, newValue) => {
653
689
  const [scope, key] = id.split(':') as [SettingsScope, GoosedumpSettingKey];
654
690
  const parsed = Number(newValue);
655
- if (!Number.isSafeInteger(parsed) || parsed < 0 || parsed > 255) return;
691
+ if (
692
+ !Number.isSafeInteger(parsed) ||
693
+ parsed < TURNS_BEFORE_COMPACT_MIN ||
694
+ parsed > TURNS_BEFORE_COMPACT_MAX
695
+ )
696
+ return;
656
697
  writeScopedGoosedumpSetting(location, scope, key, parsed);
657
698
  settingsList.updateValue(id, newValue);
658
699
  ctx.ui.notify(`${settingLabel(scope, key)} = ${formatCompactSetting(parsed)}`, 'info');
@@ -1091,11 +1132,7 @@ export function createGoosedumpIntegration(
1091
1132
  ),
1092
1133
  }),
1093
1134
  async execute(_id, params, _signal, _onUpdate, ctx): Promise<AgentToolResult<void>> {
1094
- if (!goosedumpAvailable) {
1095
- return textResult(
1096
- 'goosedump is not available. Install with: npm install @jarkkojs/goosedump',
1097
- );
1098
- }
1135
+ if (!goosedumpAvailable) return goosedumpUnavailableResult();
1099
1136
 
1100
1137
  try {
1101
1138
  const provider = params.provider ?? 'pi';
@@ -1172,11 +1209,7 @@ export function createGoosedumpIntegration(
1172
1209
  ),
1173
1210
  }),
1174
1211
  async execute(_id, params, _signal, _onUpdate, ctx): Promise<AgentToolResult<void>> {
1175
- if (!goosedumpAvailable) {
1176
- return textResult(
1177
- 'goosedump is not available. Install with: npm install @jarkkojs/goosedump',
1178
- );
1179
- }
1212
+ if (!goosedumpAvailable) return goosedumpUnavailableResult();
1180
1213
 
1181
1214
  try {
1182
1215
  const provider = params.provider ?? 'pi';
@@ -1247,11 +1280,7 @@ export function createGoosedumpIntegration(
1247
1280
  ),
1248
1281
  }),
1249
1282
  async execute(_id, params, _signal, _onUpdate, ctx): Promise<AgentToolResult<void>> {
1250
- if (!goosedumpAvailable) {
1251
- return textResult(
1252
- 'goosedump is not available. Install with: npm install @jarkkojs/goosedump',
1253
- );
1254
- }
1283
+ if (!goosedumpAvailable) return goosedumpUnavailableResult();
1255
1284
 
1256
1285
  try {
1257
1286
  const provider = params.provider ?? 'pi';
@@ -1298,11 +1327,7 @@ export function createGoosedumpIntegration(
1298
1327
  ),
1299
1328
  }),
1300
1329
  async execute(_id, params, _signal, _onUpdate, ctx): Promise<AgentToolResult<void>> {
1301
- if (!goosedumpAvailable) {
1302
- return textResult(
1303
- 'goosedump is not available. Install with: npm install @jarkkojs/goosedump',
1304
- );
1305
- }
1330
+ if (!goosedumpAvailable) return goosedumpUnavailableResult();
1306
1331
 
1307
1332
  const keep = params.keep ?? null;
1308
1333
  requestCompaction(ctx, keep);
@@ -1390,15 +1415,13 @@ export function createGoosedumpIntegration(
1390
1415
  description: 'Edit goosedump compaction settings',
1391
1416
  handler: async (_args, ctx) => {
1392
1417
  if (!goosedumpAvailable) {
1393
- ctx.ui.notify(
1394
- 'goosedump is not available. Install with: npm install @jarkkojs/goosedump',
1395
- 'error',
1396
- );
1418
+ ctx.ui.notify(GOOSEDUMP_UNAVAILABLE_MESSAGE, 'error');
1397
1419
  return;
1398
1420
  }
1399
1421
 
1400
1422
  try {
1401
1423
  await runSettingsEditor(ctx);
1424
+ reloadCompactSettings(ctx.cwd);
1402
1425
  updateStatus(ctx);
1403
1426
  } catch (err) {
1404
1427
  const message = err instanceof Error ? err.message : String(err);
@@ -1411,10 +1434,7 @@ export function createGoosedumpIntegration(
1411
1434
  description: 'Compact now with goosedump; optionally keep the last N user turns',
1412
1435
  handler: async (args, ctx) => {
1413
1436
  if (!goosedumpAvailable) {
1414
- ctx.ui.notify(
1415
- 'goosedump is not available. Install with: npm install @jarkkojs/goosedump',
1416
- 'error',
1417
- );
1437
+ ctx.ui.notify(GOOSEDUMP_UNAVAILABLE_MESSAGE, 'error');
1418
1438
  return;
1419
1439
  }
1420
1440
 
@@ -1439,10 +1459,7 @@ export function createGoosedumpIntegration(
1439
1459
  description: 'Search the current session history',
1440
1460
  handler: async (args, ctx) => {
1441
1461
  if (!goosedumpAvailable) {
1442
- ctx.ui.notify(
1443
- 'goosedump is not available. Install with: npm install @jarkkojs/goosedump',
1444
- 'error',
1445
- );
1462
+ ctx.ui.notify(GOOSEDUMP_UNAVAILABLE_MESSAGE, 'error');
1446
1463
  return;
1447
1464
  }
1448
1465
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-goosedump",
3
- "version": "0.9.2",
3
+ "version": "0.9.3",
4
4
  "description": "Pi extension for goosedump-backed session-history search, entry expansion, and compaction",
5
5
  "keywords": [
6
6
  "compaction",
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@earendil-works/pi-tui": "^0.78.0",
34
- "@jarkkojs/goosedump": "^0.9.3",
34
+ "@jarkkojs/goosedump": "^0.9.4",
35
35
  "@sinclair/typebox": "^0.34.49"
36
36
  },
37
37
  "devDependencies": {