pi-goosedump 0.3.5 → 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.
- package/README.md +1 -1
- package/index.ts +282 -95
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ Opens an interactive session browser.
|
|
|
47
47
|
### Compaction
|
|
48
48
|
|
|
49
49
|
pi-goosedump hooks Pi's `/compact` and auto-compaction flow. It uses
|
|
50
|
-
`goosedump compact pi
|
|
50
|
+
`goosedump compact pi:<session>` with Pi's compaction range (`--from`,
|
|
51
51
|
`--until`, and `--scope`) so the generated summary matches the entries Pi is
|
|
52
52
|
about to replace.
|
|
53
53
|
|
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,
|
|
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 {
|
|
@@ -43,6 +44,62 @@ interface GoosedumpContextResult {
|
|
|
43
44
|
totalPages: number;
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
interface ListJson {
|
|
48
|
+
sessions: { id: string; path?: string | null }[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface ToolCallJson {
|
|
52
|
+
name: string;
|
|
53
|
+
arguments: unknown;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface ShowMessageJson {
|
|
57
|
+
entryId: string;
|
|
58
|
+
kind: 'text' | 'assistant' | 'toolResult' | 'bash';
|
|
59
|
+
role?: string;
|
|
60
|
+
text?: string;
|
|
61
|
+
thinking?: string[];
|
|
62
|
+
toolCalls?: ToolCallJson[];
|
|
63
|
+
toolName?: string;
|
|
64
|
+
content?: string;
|
|
65
|
+
isError?: boolean;
|
|
66
|
+
command?: string;
|
|
67
|
+
output?: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
interface ShowJson {
|
|
71
|
+
messages: ShowMessageJson[];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface HitJson {
|
|
75
|
+
entryId: string;
|
|
76
|
+
role: string;
|
|
77
|
+
score: number;
|
|
78
|
+
text: string;
|
|
79
|
+
files: string[];
|
|
80
|
+
terms: string[];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
interface SearchJson {
|
|
84
|
+
page: number;
|
|
85
|
+
totalPages: number;
|
|
86
|
+
total: number;
|
|
87
|
+
hits: HitJson[];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
interface GrepJson {
|
|
91
|
+
hits: HitJson[];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface CompactJson {
|
|
95
|
+
goals: string[];
|
|
96
|
+
files: { modified: string[]; created: string[]; read: string[] };
|
|
97
|
+
commits: string[];
|
|
98
|
+
outstanding: string[];
|
|
99
|
+
preferences: string[];
|
|
100
|
+
brief: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
46
103
|
function resolveGoosedumpBinary(): string {
|
|
47
104
|
try {
|
|
48
105
|
return require.resolve('@jarkkojs/goosedump/bin/goosedump.js');
|
|
@@ -92,66 +149,76 @@ function hasMinimumVersion(version: string, minimum: readonly [number, number, n
|
|
|
92
149
|
return true;
|
|
93
150
|
}
|
|
94
151
|
|
|
95
|
-
function
|
|
96
|
-
|
|
97
|
-
|
|
152
|
+
function clip(value: string, max: number): string {
|
|
153
|
+
return value.length > max ? `${value.slice(0, max)}...` : value;
|
|
154
|
+
}
|
|
98
155
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
156
|
+
function summarizeToolArgs(args: unknown): string {
|
|
157
|
+
if (args && typeof args === 'object' && !Array.isArray(args)) {
|
|
158
|
+
const obj = args as Record<string, unknown>;
|
|
159
|
+
for (const key of ['path', 'file_path', 'filePath', 'file']) {
|
|
160
|
+
if (typeof obj[key] === 'string') return `path=${obj[key] as string}`;
|
|
161
|
+
}
|
|
162
|
+
for (const key of ['command', 'query', 'pattern', 'description']) {
|
|
163
|
+
if (typeof obj[key] === 'string') return `${key}=${clip(obj[key] as string, 160)}`;
|
|
104
164
|
}
|
|
165
|
+
const keys = Object.keys(obj);
|
|
166
|
+
return keys.length === 0 ? '' : keys.sort().join(', ');
|
|
105
167
|
}
|
|
106
|
-
|
|
107
|
-
return
|
|
168
|
+
if (typeof args === 'string') return clip(args, 160);
|
|
169
|
+
if (args == null) return '';
|
|
170
|
+
return clip(JSON.stringify(args), 160);
|
|
108
171
|
}
|
|
109
172
|
|
|
110
|
-
function
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
173
|
+
function showMessageRole(m: ShowMessageJson): string {
|
|
174
|
+
switch (m.kind) {
|
|
175
|
+
case 'assistant':
|
|
176
|
+
return 'assistant';
|
|
177
|
+
case 'toolResult':
|
|
178
|
+
return `tool/${m.toolName ?? ''}${m.isError ? ' ⚠' : ''}`;
|
|
179
|
+
case 'bash':
|
|
180
|
+
return 'bash';
|
|
181
|
+
default:
|
|
182
|
+
return m.role && m.role.length > 0 ? m.role : 'unknown';
|
|
183
|
+
}
|
|
184
|
+
}
|
|
118
185
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
186
|
+
function showMessageContent(m: ShowMessageJson): string {
|
|
187
|
+
switch (m.kind) {
|
|
188
|
+
case 'assistant': {
|
|
189
|
+
const parts: string[] = [];
|
|
190
|
+
if (m.thinking && m.thinking.length > 0) parts.push(m.thinking.join('\n'));
|
|
191
|
+
if (m.text) parts.push(m.text);
|
|
192
|
+
if (m.toolCalls && m.toolCalls.length > 0) {
|
|
193
|
+
parts.push(
|
|
194
|
+
m.toolCalls
|
|
195
|
+
.map((tc) => {
|
|
196
|
+
const summary = summarizeToolArgs(tc.arguments);
|
|
197
|
+
return summary ? `${tc.name}(${summary})` : tc.name;
|
|
198
|
+
})
|
|
199
|
+
.join('\n'),
|
|
200
|
+
);
|
|
124
201
|
}
|
|
125
|
-
|
|
126
|
-
id: entryMatch[1],
|
|
127
|
-
role: entryMatch[2],
|
|
128
|
-
content: '',
|
|
129
|
-
};
|
|
130
|
-
contentLines = [];
|
|
131
|
-
continue;
|
|
202
|
+
return parts.join('\n');
|
|
132
203
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const scoreVal = parseFloat(content.slice(7));
|
|
140
|
-
if (!isNaN(scoreVal)) currentMsg.score = scoreVal;
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
if (/^\.\.\.\(\d+ lines (?:above|below)\)$/.test(content)) continue;
|
|
144
|
-
contentLines.push(content);
|
|
145
|
-
}
|
|
204
|
+
case 'toolResult':
|
|
205
|
+
return m.content ?? '';
|
|
206
|
+
case 'bash': {
|
|
207
|
+
const cmd = m.command ? `$ ${m.command}` : '';
|
|
208
|
+
if (cmd && m.output) return `${cmd}\n${m.output}`;
|
|
209
|
+
return cmd || (m.output ?? '');
|
|
146
210
|
}
|
|
211
|
+
default:
|
|
212
|
+
return m.text ?? '';
|
|
147
213
|
}
|
|
214
|
+
}
|
|
148
215
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
216
|
+
function showMessage(m: ShowMessageJson): GoosedumpMessage {
|
|
217
|
+
return { id: m.entryId, role: showMessageRole(m), content: showMessageContent(m) };
|
|
218
|
+
}
|
|
153
219
|
|
|
154
|
-
|
|
220
|
+
function hitMessage(h: HitJson): GoosedumpMessage {
|
|
221
|
+
return { id: h.entryId, role: h.role, content: h.text, score: h.score };
|
|
155
222
|
}
|
|
156
223
|
|
|
157
224
|
function formatMessagesCompact(messages: GoosedumpMessage[]): string {
|
|
@@ -172,21 +239,12 @@ function runGoosedump(args: string[]): string {
|
|
|
172
239
|
});
|
|
173
240
|
}
|
|
174
241
|
|
|
175
|
-
function parsePageInfo(output: string, fallbackPage: number): { page: number; totalPages: number } {
|
|
176
|
-
const match = output.match(/\(page\s+(\d+)\s+of\s+(\d+)\):/i);
|
|
177
|
-
if (!match) {
|
|
178
|
-
return { page: fallbackPage, totalPages: 1 };
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return {
|
|
182
|
-
page: Number(match[1]),
|
|
183
|
-
totalPages: Number(match[2]),
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
|
|
187
242
|
function goosedumpList(): GoosedumpListing[] {
|
|
188
|
-
const
|
|
189
|
-
return
|
|
243
|
+
const json = JSON.parse(runGoosedump(['list', 'pi:*'])) as ListJson;
|
|
244
|
+
return (json.sessions ?? []).map((session) => ({
|
|
245
|
+
id: session.id,
|
|
246
|
+
path: session.path ?? null,
|
|
247
|
+
}));
|
|
190
248
|
}
|
|
191
249
|
|
|
192
250
|
function goosedumpContext(
|
|
@@ -194,7 +252,6 @@ function goosedumpContext(
|
|
|
194
252
|
options: {
|
|
195
253
|
scope?: string;
|
|
196
254
|
grep?: string;
|
|
197
|
-
compact?: boolean;
|
|
198
255
|
ids?: string;
|
|
199
256
|
rank?: boolean;
|
|
200
257
|
page?: number;
|
|
@@ -202,33 +259,35 @@ function goosedumpContext(
|
|
|
202
259
|
): GoosedumpContextResult {
|
|
203
260
|
const scope = options.scope ?? 'lineage';
|
|
204
261
|
const hasQuery = typeof options.grep === 'string';
|
|
262
|
+
const isSearch = hasQuery && options.rank !== false;
|
|
263
|
+
const target = `pi:${contextId}`;
|
|
205
264
|
const args = hasQuery
|
|
206
|
-
?
|
|
207
|
-
? ['
|
|
208
|
-
: ['
|
|
209
|
-
: ['show',
|
|
265
|
+
? isSearch
|
|
266
|
+
? ['search', target, options.grep ?? '']
|
|
267
|
+
: ['grep', target, options.grep ?? '']
|
|
268
|
+
: ['show', target];
|
|
210
269
|
|
|
211
|
-
if (options.compact) {
|
|
212
|
-
args.push('--clip');
|
|
213
|
-
}
|
|
214
270
|
if (options.ids) {
|
|
215
271
|
args.push('--ids', options.ids);
|
|
216
272
|
}
|
|
217
|
-
if (
|
|
273
|
+
if (isSearch && options.page) {
|
|
218
274
|
args.push('--page', String(options.page));
|
|
219
275
|
}
|
|
220
276
|
args.push('--scope', scope);
|
|
221
277
|
|
|
222
278
|
const output = runGoosedump(args);
|
|
223
|
-
const messages = parseMessages(output);
|
|
224
|
-
const pageInfo = parsePageInfo(output, options.page ?? 1);
|
|
225
279
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
page
|
|
230
|
-
totalPages
|
|
231
|
-
|
|
280
|
+
if (hasQuery) {
|
|
281
|
+
const json = JSON.parse(output) as SearchJson | GrepJson;
|
|
282
|
+
const messages = (json.hits ?? []).map(hitMessage);
|
|
283
|
+
const page = isSearch ? ((json as SearchJson).page ?? options.page ?? 1) : 1;
|
|
284
|
+
const totalPages = isSearch ? ((json as SearchJson).totalPages ?? 1) : 1;
|
|
285
|
+
return { messages, totalCount: messages.length, page, totalPages };
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const json = JSON.parse(output) as ShowJson;
|
|
289
|
+
const messages = (json.messages ?? []).map(showMessage);
|
|
290
|
+
return { messages, totalCount: messages.length, page: options.page ?? 1, totalPages: 1 };
|
|
232
291
|
}
|
|
233
292
|
|
|
234
293
|
function goosedumpExpand(
|
|
@@ -238,16 +297,38 @@ function goosedumpExpand(
|
|
|
238
297
|
): GoosedumpMessage[] {
|
|
239
298
|
if (entryIds.length === 0) return [];
|
|
240
299
|
|
|
241
|
-
const
|
|
242
|
-
'show',
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
300
|
+
const json = JSON.parse(
|
|
301
|
+
runGoosedump(['show', `pi:${contextId}`, '--ids', entryIds.join(','), '--scope', scope]),
|
|
302
|
+
) as ShowJson;
|
|
303
|
+
return (json.messages ?? []).map(showMessage);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function capList(items: string[], limit: number): string {
|
|
307
|
+
const shown = items.slice(0, limit).join(', ');
|
|
308
|
+
return items.length > limit ? `${shown} (+${items.length - limit} more)` : shown;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function bulletSection(title: string, items: string[]): string | null {
|
|
312
|
+
if (items.length === 0) return null;
|
|
313
|
+
return `[${title}]\n${items.map((item) => `- ${item}`).join('\n')}`;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function renderCompactSummary(c: CompactJson): string {
|
|
317
|
+
const fileLines: string[] = [];
|
|
318
|
+
if (c.files.modified.length > 0) fileLines.push(`Modified: ${capList(c.files.modified, 10)}`);
|
|
319
|
+
if (c.files.created.length > 0) fileLines.push(`Created: ${capList(c.files.created, 10)}`);
|
|
320
|
+
if (c.files.read.length > 0) fileLines.push(`Read: ${capList(c.files.read, 10)}`);
|
|
321
|
+
|
|
322
|
+
const parts = [
|
|
323
|
+
bulletSection('Session Goal', c.goals),
|
|
324
|
+
bulletSection('Files And Changes', fileLines),
|
|
325
|
+
bulletSection('Commits', c.commits),
|
|
326
|
+
bulletSection('Outstanding Context', c.outstanding),
|
|
327
|
+
bulletSection('User Preferences', c.preferences),
|
|
328
|
+
c.brief.trim() ? c.brief : null,
|
|
329
|
+
].filter((part): part is string => part !== null);
|
|
330
|
+
|
|
331
|
+
return parts.join('\n\n---\n\n');
|
|
251
332
|
}
|
|
252
333
|
|
|
253
334
|
function goosedumpCompact(
|
|
@@ -260,7 +341,7 @@ function goosedumpCompact(
|
|
|
260
341
|
},
|
|
261
342
|
): string {
|
|
262
343
|
const scope = options.scope ?? 'lineage';
|
|
263
|
-
const args = ['compact',
|
|
344
|
+
const args = ['compact', `pi:${contextId}`, '--scope', scope];
|
|
264
345
|
|
|
265
346
|
if (options.ids && options.ids.length > 0) {
|
|
266
347
|
args.push('--ids', options.ids.join(','));
|
|
@@ -269,7 +350,8 @@ function goosedumpCompact(
|
|
|
269
350
|
if (options.until) args.push('--until', options.until);
|
|
270
351
|
}
|
|
271
352
|
|
|
272
|
-
|
|
353
|
+
const json = JSON.parse(runGoosedump(args)) as CompactJson;
|
|
354
|
+
return renderCompactSummary(json);
|
|
273
355
|
}
|
|
274
356
|
|
|
275
357
|
export interface GoosedumpIntegrationOptions {
|
|
@@ -666,7 +748,6 @@ export function createGoosedumpIntegration(
|
|
|
666
748
|
const result = goosedumpContext(contextId, {
|
|
667
749
|
scope: params.scope ?? 'lineage',
|
|
668
750
|
grep: params.query,
|
|
669
|
-
compact: params.compact ?? true,
|
|
670
751
|
rank: true,
|
|
671
752
|
page: params.page ?? 1,
|
|
672
753
|
});
|
|
@@ -748,7 +829,6 @@ export function createGoosedumpIntegration(
|
|
|
748
829
|
|
|
749
830
|
const result = goosedumpContext(contextId, {
|
|
750
831
|
scope: params.scope ?? 'lineage',
|
|
751
|
-
compact: false,
|
|
752
832
|
});
|
|
753
833
|
|
|
754
834
|
if (result.messages.length === 0) {
|
|
@@ -865,9 +945,17 @@ export function createGoosedumpIntegration(
|
|
|
865
945
|
return;
|
|
866
946
|
}
|
|
867
947
|
|
|
948
|
+
let resumePath: string | null | undefined;
|
|
949
|
+
|
|
868
950
|
await ctx.ui.custom<void>(
|
|
869
951
|
(tui, theme, _kb, done) => {
|
|
870
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;
|
|
871
959
|
|
|
872
960
|
return {
|
|
873
961
|
render(width: number): string[] {
|
|
@@ -881,6 +969,39 @@ export function createGoosedumpIntegration(
|
|
|
881
969
|
|
|
882
970
|
const lines: string[] = [];
|
|
883
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
|
+
|
|
884
1005
|
// Top border
|
|
885
1006
|
const title = accent(' Goosedump Sessions ');
|
|
886
1007
|
const topFill = borderFg(
|
|
@@ -913,7 +1034,13 @@ export function createGoosedumpIntegration(
|
|
|
913
1034
|
|
|
914
1035
|
// Footer
|
|
915
1036
|
lines.push(makeRow('', innerW, border));
|
|
916
|
-
lines.push(
|
|
1037
|
+
lines.push(
|
|
1038
|
+
makeRow(
|
|
1039
|
+
dim('↑↓ navigate enter compact shift+enter resume esc close'),
|
|
1040
|
+
innerW,
|
|
1041
|
+
border,
|
|
1042
|
+
),
|
|
1043
|
+
);
|
|
917
1044
|
|
|
918
1045
|
// Bottom border
|
|
919
1046
|
lines.push(`${borderFg('╰')}${borderFg('─'.repeat(width - 2))}${borderFg('╯')}`);
|
|
@@ -922,6 +1049,35 @@ export function createGoosedumpIntegration(
|
|
|
922
1049
|
},
|
|
923
1050
|
|
|
924
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
|
+
|
|
925
1081
|
if (matchesKey(data, Key.escape) || matchesKey(data, Key.ctrl('c'))) {
|
|
926
1082
|
done(undefined);
|
|
927
1083
|
return;
|
|
@@ -938,6 +1094,31 @@ export function createGoosedumpIntegration(
|
|
|
938
1094
|
tui.requestRender();
|
|
939
1095
|
return;
|
|
940
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
|
+
}
|
|
941
1122
|
},
|
|
942
1123
|
|
|
943
1124
|
invalidate(): void {},
|
|
@@ -958,6 +1139,12 @@ export function createGoosedumpIntegration(
|
|
|
958
1139
|
},
|
|
959
1140
|
},
|
|
960
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
|
+
}
|
|
961
1148
|
} catch (err) {
|
|
962
1149
|
const message = err instanceof Error ? err.message : String(err);
|
|
963
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.
|
|
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.
|
|
32
|
+
"@jarkkojs/goosedump": "^0.5.0",
|
|
33
33
|
"@sinclair/typebox": "^0.34.49"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|