pi-goosedump 0.4.0 → 0.5.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.ts +115 -4
  2. package/package.json +2 -2
package/index.ts CHANGED
@@ -23,10 +23,11 @@ import { Type } from '@sinclair/typebox';
23
23
 
24
24
  const require = createRequire(import.meta.url);
25
25
 
26
- const GOOSEDUMP_VERSION = [0, 4, 2] as const;
26
+ const GOOSEDUMP_VERSION = [0, 5, 0] as const;
27
27
 
28
28
  interface GoosedumpListing {
29
29
  id: string;
30
+ path: string | null;
30
31
  }
31
32
 
32
33
  interface GoosedumpMessage {
@@ -44,7 +45,7 @@ interface GoosedumpContextResult {
44
45
  }
45
46
 
46
47
  interface ListJson {
47
- sessions: { id: string }[];
48
+ sessions: { id: string; path?: string | null }[];
48
49
  }
49
50
 
50
51
  interface ToolCallJson {
@@ -240,7 +241,10 @@ function runGoosedump(args: string[]): string {
240
241
 
241
242
  function goosedumpList(): GoosedumpListing[] {
242
243
  const json = JSON.parse(runGoosedump(['list', 'pi:*'])) as ListJson;
243
- return (json.sessions ?? []).map((session) => ({ id: session.id }));
244
+ return (json.sessions ?? []).map((session) => ({
245
+ id: session.id,
246
+ path: session.path ?? null,
247
+ }));
244
248
  }
245
249
 
246
250
  function goosedumpContext(
@@ -941,9 +945,17 @@ export function createGoosedumpIntegration(
941
945
  return;
942
946
  }
943
947
 
948
+ let resumePath: string | null | undefined;
949
+
944
950
  await ctx.ui.custom<void>(
945
951
  (tui, theme, _kb, done) => {
946
952
  let selectedIndex = 0;
953
+ let mode: 'list' | 'compact' = 'list';
954
+ let compactLines: string[] = [];
955
+ let compactScroll = 0;
956
+ let compactTitle = '';
957
+
958
+ const COMPACT_VIEWPORT = 20;
947
959
 
948
960
  return {
949
961
  render(width: number): string[] {
@@ -957,6 +969,39 @@ export function createGoosedumpIntegration(
957
969
 
958
970
  const lines: string[] = [];
959
971
 
972
+ if (mode === 'compact') {
973
+ const title = accent(` Compact: ${truncateToWidth(compactTitle, 40)} `);
974
+ const topFill = borderFg(
975
+ '─'.repeat(Math.max(0, width - 4 - visibleWidth(title))),
976
+ );
977
+ lines.push(`${borderFg('╭─')}${title}${topFill}${borderFg('─╮')}`);
978
+
979
+ const total = compactLines.length;
980
+ const maxScroll = Math.max(0, total - COMPACT_VIEWPORT);
981
+ if (compactScroll > maxScroll) compactScroll = maxScroll;
982
+ const window = compactLines.slice(
983
+ compactScroll,
984
+ compactScroll + COMPACT_VIEWPORT,
985
+ );
986
+ for (const row of window) {
987
+ lines.push(makeRow(text(truncateToWidth(row, innerW)), innerW, border));
988
+ }
989
+ for (let i = window.length; i < COMPACT_VIEWPORT; i++) {
990
+ lines.push(makeRow('', innerW, border));
991
+ }
992
+
993
+ const position =
994
+ total > COMPACT_VIEWPORT
995
+ ? `${compactScroll + 1}-${Math.min(compactScroll + COMPACT_VIEWPORT, total)} of ${total}`
996
+ : `${total} line${total === 1 ? '' : 's'}`;
997
+ lines.push(makeRow('', innerW, border));
998
+ lines.push(makeRow(dim(`↑↓ scroll esc back (${position})`), innerW, border));
999
+ lines.push(
1000
+ `${borderFg('╰')}${borderFg('─'.repeat(width - 2))}${borderFg('╯')}`,
1001
+ );
1002
+ return lines;
1003
+ }
1004
+
960
1005
  // Top border
961
1006
  const title = accent(' Goosedump Sessions ');
962
1007
  const topFill = borderFg(
@@ -989,7 +1034,13 @@ export function createGoosedumpIntegration(
989
1034
 
990
1035
  // Footer
991
1036
  lines.push(makeRow('', innerW, border));
992
- lines.push(makeRow(dim('↑↓ navigate esc close'), innerW, border));
1037
+ lines.push(
1038
+ makeRow(
1039
+ dim('↑↓ navigate enter compact shift+enter resume esc close'),
1040
+ innerW,
1041
+ border,
1042
+ ),
1043
+ );
993
1044
 
994
1045
  // Bottom border
995
1046
  lines.push(`${borderFg('╰')}${borderFg('─'.repeat(width - 2))}${borderFg('╯')}`);
@@ -998,6 +1049,35 @@ export function createGoosedumpIntegration(
998
1049
  },
999
1050
 
1000
1051
  handleInput(data: string): void {
1052
+ if (mode === 'compact') {
1053
+ if (matchesKey(data, Key.escape) || matchesKey(data, Key.ctrl('c'))) {
1054
+ mode = 'list';
1055
+ tui.requestRender();
1056
+ return;
1057
+ }
1058
+ if (matchesKey(data, Key.up)) {
1059
+ compactScroll = Math.max(0, compactScroll - 1);
1060
+ tui.requestRender();
1061
+ return;
1062
+ }
1063
+ if (matchesKey(data, Key.down)) {
1064
+ compactScroll += 1;
1065
+ tui.requestRender();
1066
+ return;
1067
+ }
1068
+ if (matchesKey(data, Key.pageUp)) {
1069
+ compactScroll = Math.max(0, compactScroll - COMPACT_VIEWPORT);
1070
+ tui.requestRender();
1071
+ return;
1072
+ }
1073
+ if (matchesKey(data, Key.pageDown)) {
1074
+ compactScroll += COMPACT_VIEWPORT;
1075
+ tui.requestRender();
1076
+ return;
1077
+ }
1078
+ return;
1079
+ }
1080
+
1001
1081
  if (matchesKey(data, Key.escape) || matchesKey(data, Key.ctrl('c'))) {
1002
1082
  done(undefined);
1003
1083
  return;
@@ -1014,6 +1094,31 @@ export function createGoosedumpIntegration(
1014
1094
  tui.requestRender();
1015
1095
  return;
1016
1096
  }
1097
+
1098
+ if (matchesKey(data, Key.shift(Key.enter))) {
1099
+ resumePath = listings[selectedIndex]?.path;
1100
+ done(undefined);
1101
+ return;
1102
+ }
1103
+
1104
+ if (matchesKey(data, Key.enter) || matchesKey(data, Key.return)) {
1105
+ const listing = listings[selectedIndex];
1106
+ if (!listing) return;
1107
+ compactTitle = listing.id;
1108
+ compactScroll = 0;
1109
+ try {
1110
+ const summary = goosedumpCompact(listing.id, { scope: 'lineage' }).trim();
1111
+ compactLines = summary
1112
+ ? summary.split('\n')
1113
+ : ['No compact summary available for this session.'];
1114
+ } catch (err) {
1115
+ const msg = err instanceof Error ? err.message : String(err);
1116
+ compactLines = [`Failed to compact session: ${msg}`];
1117
+ }
1118
+ mode = 'compact';
1119
+ tui.requestRender();
1120
+ return;
1121
+ }
1017
1122
  },
1018
1123
 
1019
1124
  invalidate(): void {},
@@ -1034,6 +1139,12 @@ export function createGoosedumpIntegration(
1034
1139
  },
1035
1140
  },
1036
1141
  );
1142
+
1143
+ if (resumePath) {
1144
+ await ctx.switchSession(resumePath);
1145
+ } else if (resumePath === null) {
1146
+ ctx.ui.notify('Cannot resume: session file path is unavailable.', 'error');
1147
+ }
1037
1148
  } catch (err) {
1038
1149
  const message = err instanceof Error ? err.message : String(err);
1039
1150
  ctx.ui.notify(`goosedump error: ${message}`, 'error');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-goosedump",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Coding agent context data browser plugin for pi",
5
5
  "keywords": [
6
6
  "goosedump",
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@earendil-works/pi-tui": "^0.78.0",
32
- "@jarkkojs/goosedump": "^0.4.2",
32
+ "@jarkkojs/goosedump": "^0.5.0",
33
33
  "@sinclair/typebox": "^0.34.49"
34
34
  },
35
35
  "devDependencies": {