pi-goosedump 0.10.5 → 0.10.6
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/index.ts +172 -43
- package/package.json +2 -2
package/index.ts
CHANGED
|
@@ -50,6 +50,9 @@ import {
|
|
|
50
50
|
import { Type } from '@sinclair/typebox';
|
|
51
51
|
|
|
52
52
|
const require = createRequire(import.meta.url);
|
|
53
|
+
const BRANCH_SUMMARY_PREFIX =
|
|
54
|
+
'The following is a summary of a branch that this conversation came back from:\n\n<summary>\n';
|
|
55
|
+
const BRANCH_SUMMARY_SUFFIX = '</summary>';
|
|
53
56
|
|
|
54
57
|
// One rendered message after normalizing a context into pi's native JSONL.
|
|
55
58
|
interface GoosedumpMessage {
|
|
@@ -91,6 +94,7 @@ interface PiEntryJson {
|
|
|
91
94
|
type?: string;
|
|
92
95
|
id?: string;
|
|
93
96
|
message?: { role?: string; content?: PiPartJson[] | string };
|
|
97
|
+
content?: PiPartJson[] | string;
|
|
94
98
|
summary?: string;
|
|
95
99
|
}
|
|
96
100
|
|
|
@@ -108,6 +112,15 @@ const DEFAULT_GOOSEDUMP_SETTINGS: GoosedumpSettings = {
|
|
|
108
112
|
const TURNS_BEFORE_COMPACT_MIN = 0;
|
|
109
113
|
const TURNS_BEFORE_COMPACT_MAX = 255;
|
|
110
114
|
|
|
115
|
+
function isTurnsBeforeCompact(value: unknown): value is number {
|
|
116
|
+
return (
|
|
117
|
+
typeof value === 'number' &&
|
|
118
|
+
Number.isSafeInteger(value) &&
|
|
119
|
+
value >= TURNS_BEFORE_COMPACT_MIN &&
|
|
120
|
+
value <= TURNS_BEFORE_COMPACT_MAX
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
111
124
|
function piAgentDir(): string {
|
|
112
125
|
return process.env.PI_CODING_AGENT_DIR ?? join(homedir(), '.pi', 'agent');
|
|
113
126
|
}
|
|
@@ -138,7 +151,13 @@ function readJsonObject(path: string): Record<string, unknown> {
|
|
|
138
151
|
function readJsonObjectStrict(path: string): Record<string, unknown> {
|
|
139
152
|
if (!existsSync(path)) return {};
|
|
140
153
|
|
|
141
|
-
|
|
154
|
+
let parsed: unknown;
|
|
155
|
+
try {
|
|
156
|
+
parsed = JSON.parse(readFileSync(path, 'utf8')) as unknown;
|
|
157
|
+
} catch (error) {
|
|
158
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
159
|
+
throw new Error(`${path}: ${message}`);
|
|
160
|
+
}
|
|
142
161
|
if (!isRecord(parsed)) throw new Error(`${path} must contain a JSON object`);
|
|
143
162
|
return parsed;
|
|
144
163
|
}
|
|
@@ -165,17 +184,26 @@ function readGoosedumpSettingsFrom(path: string): Partial<GoosedumpSettings> {
|
|
|
165
184
|
|
|
166
185
|
const settings: Partial<GoosedumpSettings> = {};
|
|
167
186
|
const value = raw.turnsBeforeCompact;
|
|
168
|
-
if (
|
|
169
|
-
typeof value === 'number' &&
|
|
170
|
-
Number.isSafeInteger(value) &&
|
|
171
|
-
value >= TURNS_BEFORE_COMPACT_MIN &&
|
|
172
|
-
value <= TURNS_BEFORE_COMPACT_MAX
|
|
173
|
-
) {
|
|
174
|
-
settings.turnsBeforeCompact = value;
|
|
175
|
-
}
|
|
187
|
+
if (isTurnsBeforeCompact(value)) settings.turnsBeforeCompact = value;
|
|
176
188
|
return settings;
|
|
177
189
|
}
|
|
178
190
|
|
|
191
|
+
function validateGoosedumpSettings(path: string): void {
|
|
192
|
+
const root = readJsonObjectStrict(path);
|
|
193
|
+
if (root.goosedump === undefined) return;
|
|
194
|
+
if (!isRecord(root.goosedump)) {
|
|
195
|
+
throw new Error(`${path}: goosedump must be a JSON object`);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const value = root.goosedump.turnsBeforeCompact;
|
|
199
|
+
if (value !== undefined && !isTurnsBeforeCompact(value)) {
|
|
200
|
+
throw new Error(
|
|
201
|
+
`${path}: goosedump.turnsBeforeCompact must be an integer from ` +
|
|
202
|
+
`${TURNS_BEFORE_COMPACT_MIN} to ${TURNS_BEFORE_COMPACT_MAX}`,
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
179
207
|
function resolveGoosedumpSettings(cwd: string): GoosedumpSettings {
|
|
180
208
|
return {
|
|
181
209
|
...DEFAULT_GOOSEDUMP_SETTINGS,
|
|
@@ -187,7 +215,7 @@ function resolveGoosedumpSettings(cwd: string): GoosedumpSettings {
|
|
|
187
215
|
function notifyInvalidSettings(ctx: ExtensionContext): void {
|
|
188
216
|
for (const path of [globalSettingsPath(), projectSettingsPath(ctx.cwd)]) {
|
|
189
217
|
try {
|
|
190
|
-
|
|
218
|
+
validateGoosedumpSettings(path);
|
|
191
219
|
} catch (error) {
|
|
192
220
|
const message = error instanceof Error ? error.message : String(error);
|
|
193
221
|
if (ctx.hasUI) ctx.ui.notify(`goosedump settings error: ${message}`, 'error');
|
|
@@ -202,14 +230,7 @@ function readScopedGoosedumpSettings(cwd: string, scope: SettingsScope): Goosedu
|
|
|
202
230
|
|
|
203
231
|
const settings: Partial<GoosedumpSettings> = {};
|
|
204
232
|
const value = raw.turnsBeforeCompact;
|
|
205
|
-
if (
|
|
206
|
-
typeof value === 'number' &&
|
|
207
|
-
Number.isSafeInteger(value) &&
|
|
208
|
-
value >= TURNS_BEFORE_COMPACT_MIN &&
|
|
209
|
-
value <= TURNS_BEFORE_COMPACT_MAX
|
|
210
|
-
) {
|
|
211
|
-
settings.turnsBeforeCompact = value;
|
|
212
|
-
}
|
|
233
|
+
if (isTurnsBeforeCompact(value)) settings.turnsBeforeCompact = value;
|
|
213
234
|
return { ...DEFAULT_GOOSEDUMP_SETTINGS, ...settings };
|
|
214
235
|
}
|
|
215
236
|
|
|
@@ -296,11 +317,10 @@ function flattenPiContent(content: PiPartJson[] | string | undefined): string {
|
|
|
296
317
|
return content.map(flattenPiPart).filter(Boolean).join('\n');
|
|
297
318
|
}
|
|
298
319
|
|
|
299
|
-
// goosedump
|
|
300
|
-
// Passing `--as-provider pi` normalizes every provider's output to
|
|
301
|
-
//
|
|
302
|
-
|
|
303
|
-
function parsePiMessages(output: string): GoosedumpMessage[] {
|
|
320
|
+
// goosedump renders `show`/`grep`/`search` in a provider's native format.
|
|
321
|
+
// Passing `--as-provider pi` normalizes every provider's output to Pi JSONL, so
|
|
322
|
+
// one parser covers all sources, including Pi-native context entries.
|
|
323
|
+
export function parsePiMessages(output: string): GoosedumpMessage[] {
|
|
304
324
|
const messages: GoosedumpMessage[] = [];
|
|
305
325
|
for (const line of output.split('\n')) {
|
|
306
326
|
if (!line) continue;
|
|
@@ -310,9 +330,22 @@ function parsePiMessages(output: string): GoosedumpMessage[] {
|
|
|
310
330
|
} catch {
|
|
311
331
|
continue;
|
|
312
332
|
}
|
|
313
|
-
if (entry.type
|
|
314
|
-
|
|
315
|
-
|
|
333
|
+
if (entry.type === 'message' && entry.message) {
|
|
334
|
+
const content = flattenPiContent(entry.message.content);
|
|
335
|
+
messages.push({ id: entry.id ?? '', role: entry.message.role ?? 'unknown', content });
|
|
336
|
+
} else if (entry.type === 'custom_message') {
|
|
337
|
+
messages.push({
|
|
338
|
+
id: entry.id ?? '',
|
|
339
|
+
role: 'user',
|
|
340
|
+
content: flattenPiContent(entry.content),
|
|
341
|
+
});
|
|
342
|
+
} else if (entry.type === 'branch_summary') {
|
|
343
|
+
messages.push({
|
|
344
|
+
id: entry.id ?? '',
|
|
345
|
+
role: 'user',
|
|
346
|
+
content: `${BRANCH_SUMMARY_PREFIX}${entry.summary ?? ''}${BRANCH_SUMMARY_SUFFIX}`,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
316
349
|
}
|
|
317
350
|
return messages;
|
|
318
351
|
}
|
|
@@ -620,11 +653,19 @@ function isCompactionEntry(entry: SessionEntry): entry is CompactionEntry {
|
|
|
620
653
|
|
|
621
654
|
function isMessageEntry(entry: SessionEntry): entry is SessionEntry & {
|
|
622
655
|
type: 'message';
|
|
623
|
-
message: { role?: string };
|
|
656
|
+
message: { role?: string; stopReason?: string };
|
|
624
657
|
} {
|
|
625
658
|
return entry.type === 'message';
|
|
626
659
|
}
|
|
627
660
|
|
|
661
|
+
function isCompletedAssistant(message: { role?: string; stopReason?: string }): boolean {
|
|
662
|
+
return (
|
|
663
|
+
message.role === 'assistant' &&
|
|
664
|
+
message.stopReason !== 'error' &&
|
|
665
|
+
message.stopReason !== 'aborted'
|
|
666
|
+
);
|
|
667
|
+
}
|
|
668
|
+
|
|
628
669
|
// Entry types that sessionEntryToContextMessages turns into context messages;
|
|
629
670
|
// only these count toward "is there anything to summarize".
|
|
630
671
|
const SUMMARIZABLE_ENTRY_TYPES = new Set(['message', 'custom_message', 'branch_summary']);
|
|
@@ -641,6 +682,38 @@ function piKeepRecentTokens(cwd: string): number {
|
|
|
641
682
|
return DEFAULT_COMPACTION_SETTINGS.keepRecentTokens;
|
|
642
683
|
}
|
|
643
684
|
|
|
685
|
+
function piCompactionEnabled(cwd: string): boolean {
|
|
686
|
+
for (const path of [projectSettingsPath(cwd), globalSettingsPath()]) {
|
|
687
|
+
const compaction = readJsonObject(path).compaction;
|
|
688
|
+
if (isRecord(compaction) && typeof compaction.enabled === 'boolean') {
|
|
689
|
+
return compaction.enabled;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
return DEFAULT_COMPACTION_SETTINGS.enabled;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
function piReserveTokens(cwd: string): number {
|
|
696
|
+
for (const path of [projectSettingsPath(cwd), globalSettingsPath()]) {
|
|
697
|
+
const compaction = readJsonObject(path).compaction;
|
|
698
|
+
if (isRecord(compaction) && typeof compaction.reserveTokens === 'number') {
|
|
699
|
+
return compaction.reserveTokens;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
return DEFAULT_COMPACTION_SETTINGS.reserveTokens;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
const SUMMARY_TOKEN_BUDGET_RATIO = 0.8;
|
|
706
|
+
const OMITTED_SUMMARY_CONTEXT = '\n\n[Earlier compaction context omitted]\n\n';
|
|
707
|
+
|
|
708
|
+
function piAutoCompactionPending(ctx: ExtensionContext): boolean {
|
|
709
|
+
const usage = ctx.getContextUsage();
|
|
710
|
+
if (!usage || usage.tokens === null) return false;
|
|
711
|
+
|
|
712
|
+
return (
|
|
713
|
+
piCompactionEnabled(ctx.cwd) && usage.tokens > usage.contextWindow - piReserveTokens(ctx.cwd)
|
|
714
|
+
);
|
|
715
|
+
}
|
|
716
|
+
|
|
644
717
|
// Predict whether ctx.compact() would throw "Nothing to compact" or "Already
|
|
645
718
|
// compacted": mirrors prepareCompaction's guards over the active lineage so
|
|
646
719
|
// plugin-triggered compaction can skip the call instead of surfacing pi's
|
|
@@ -704,7 +777,7 @@ function completedTurnsSinceCompaction(branchEntries: SessionEntry[]): number {
|
|
|
704
777
|
let completed = 0;
|
|
705
778
|
for (let i = start; i < branchEntries.length; i += 1) {
|
|
706
779
|
const entry = branchEntries[i];
|
|
707
|
-
if (isMessageEntry(entry) && entry.message
|
|
780
|
+
if (isMessageEntry(entry) && isCompletedAssistant(entry.message)) completed += 1;
|
|
708
781
|
}
|
|
709
782
|
return completed;
|
|
710
783
|
}
|
|
@@ -763,12 +836,59 @@ function buildCompactRange(
|
|
|
763
836
|
: { scope: 'lineage', until: firstKeptEntryId };
|
|
764
837
|
}
|
|
765
838
|
|
|
839
|
+
function utf8Prefix(text: string, maxBytes: number): string {
|
|
840
|
+
const prefix: string[] = [];
|
|
841
|
+
let bytes = 0;
|
|
842
|
+
for (const char of text) {
|
|
843
|
+
const charBytes = Buffer.byteLength(char);
|
|
844
|
+
if (bytes + charBytes > maxBytes) break;
|
|
845
|
+
prefix.push(char);
|
|
846
|
+
bytes += charBytes;
|
|
847
|
+
}
|
|
848
|
+
return prefix.join('');
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
function utf8Suffix(text: string, maxBytes: number): string {
|
|
852
|
+
const suffix: string[] = [];
|
|
853
|
+
let bytes = 0;
|
|
854
|
+
for (const char of Array.from(text).reverse()) {
|
|
855
|
+
const charBytes = Buffer.byteLength(char);
|
|
856
|
+
if (bytes + charBytes > maxBytes) break;
|
|
857
|
+
suffix.push(char);
|
|
858
|
+
bytes += charBytes;
|
|
859
|
+
}
|
|
860
|
+
return suffix.reverse().join('');
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
function truncateSummary(summary: string, maxBytes: number): string {
|
|
864
|
+
const text = summary.trim();
|
|
865
|
+
if (Buffer.byteLength(text) <= maxBytes) return text;
|
|
866
|
+
|
|
867
|
+
const markerBytes = Buffer.byteLength(OMITTED_SUMMARY_CONTEXT);
|
|
868
|
+
if (maxBytes <= markerBytes) return utf8Prefix(text, maxBytes);
|
|
869
|
+
|
|
870
|
+
const retainedBytes = maxBytes - markerBytes;
|
|
871
|
+
const headBytes = Math.ceil(retainedBytes / 2);
|
|
872
|
+
const tailBytes = Math.floor(retainedBytes / 2);
|
|
873
|
+
return `${utf8Prefix(text, headBytes)}${OMITTED_SUMMARY_CONTEXT}${utf8Suffix(text, tailBytes)}`;
|
|
874
|
+
}
|
|
875
|
+
|
|
766
876
|
function mergeCompactionSummary(
|
|
767
877
|
previousSummary: string | undefined,
|
|
768
878
|
generatedSummary: string,
|
|
879
|
+
reserveTokens: number,
|
|
769
880
|
): string {
|
|
881
|
+
// A token always represents at least one UTF-8 byte. Capping bytes is
|
|
882
|
+
// conservative, but unlike a chars/token estimate it cannot undercount text.
|
|
883
|
+
const maxBytes = Math.max(1, Math.floor(reserveTokens * SUMMARY_TOKEN_BUDGET_RATIO));
|
|
884
|
+
const generated = truncateSummary(generatedSummary, maxBytes);
|
|
770
885
|
const previous = previousSummary?.trim();
|
|
771
|
-
|
|
886
|
+
const separator = '\n\n';
|
|
887
|
+
const generatedBytes = Buffer.byteLength(generated);
|
|
888
|
+
if (!previous || generatedBytes + Buffer.byteLength(separator) >= maxBytes) return generated;
|
|
889
|
+
|
|
890
|
+
const previousBytes = maxBytes - generatedBytes - Buffer.byteLength(separator);
|
|
891
|
+
return `${truncateSummary(previous, previousBytes)}${separator}${generated}`;
|
|
772
892
|
}
|
|
773
893
|
|
|
774
894
|
async function buildGoosedumpCompaction(
|
|
@@ -780,6 +900,7 @@ async function buildGoosedumpCompaction(
|
|
|
780
900
|
fileOps: unknown;
|
|
781
901
|
},
|
|
782
902
|
branchEntries: SessionEntry[],
|
|
903
|
+
reserveTokens: number,
|
|
783
904
|
keep?: number,
|
|
784
905
|
signal?: AbortSignal,
|
|
785
906
|
): Promise<
|
|
@@ -801,7 +922,11 @@ async function buildGoosedumpCompaction(
|
|
|
801
922
|
|
|
802
923
|
const generated = await goosedumpCompact(target, range, signal);
|
|
803
924
|
if (!generated.summary) return undefined;
|
|
804
|
-
const summary = mergeCompactionSummary(
|
|
925
|
+
const summary = mergeCompactionSummary(
|
|
926
|
+
preparation.previousSummary,
|
|
927
|
+
generated.summary,
|
|
928
|
+
reserveTokens,
|
|
929
|
+
);
|
|
805
930
|
|
|
806
931
|
return {
|
|
807
932
|
summary,
|
|
@@ -935,11 +1060,7 @@ async function runSettingsEditor(ctx: ExtensionContext): Promise<void> {
|
|
|
935
1060
|
const projectPath = projectSettingsPath(location);
|
|
936
1061
|
const projectRaw = readJsonObjectStrict(projectPath).goosedump;
|
|
937
1062
|
const projectValue =
|
|
938
|
-
isRecord(projectRaw) &&
|
|
939
|
-
typeof projectRaw.turnsBeforeCompact === 'number' &&
|
|
940
|
-
Number.isSafeInteger(projectRaw.turnsBeforeCompact) &&
|
|
941
|
-
projectRaw.turnsBeforeCompact >= TURNS_BEFORE_COMPACT_MIN &&
|
|
942
|
-
projectRaw.turnsBeforeCompact <= TURNS_BEFORE_COMPACT_MAX
|
|
1063
|
+
isRecord(projectRaw) && isTurnsBeforeCompact(projectRaw.turnsBeforeCompact)
|
|
943
1064
|
? projectRaw.turnsBeforeCompact
|
|
944
1065
|
: undefined;
|
|
945
1066
|
|
|
@@ -990,12 +1111,7 @@ async function runSettingsEditor(ctx: ExtensionContext): Promise<void> {
|
|
|
990
1111
|
}
|
|
991
1112
|
|
|
992
1113
|
const parsed = Number(newValue);
|
|
993
|
-
if (
|
|
994
|
-
!Number.isSafeInteger(parsed) ||
|
|
995
|
-
parsed < TURNS_BEFORE_COMPACT_MIN ||
|
|
996
|
-
parsed > TURNS_BEFORE_COMPACT_MAX
|
|
997
|
-
)
|
|
998
|
-
return;
|
|
1114
|
+
if (!isTurnsBeforeCompact(parsed)) return;
|
|
999
1115
|
try {
|
|
1000
1116
|
writeScopedGoosedumpSetting(location, scope, key, parsed);
|
|
1001
1117
|
settingsList.updateValue(id, newValue);
|
|
@@ -1289,6 +1405,7 @@ export function createGoosedumpIntegration(
|
|
|
1289
1405
|
let turnsRemaining = 0;
|
|
1290
1406
|
let counterTriggered = false;
|
|
1291
1407
|
let compactionQueued = false;
|
|
1408
|
+
let compactionHookActive = false;
|
|
1292
1409
|
let pendingKeep: number | null = null;
|
|
1293
1410
|
|
|
1294
1411
|
function syncCompactCounters(ctx: ExtensionContext, clearPending = false): void {
|
|
@@ -1339,7 +1456,7 @@ export function createGoosedumpIntegration(
|
|
|
1339
1456
|
ctx: ExtensionContext,
|
|
1340
1457
|
keep: number | null,
|
|
1341
1458
|
): 'started' | 'busy' | 'nothing-to-compact' {
|
|
1342
|
-
if (compactionQueued) return 'busy';
|
|
1459
|
+
if (compactionQueued || compactionHookActive) return 'busy';
|
|
1343
1460
|
if (keep === null && !hasCompactableHistory(ctx)) return 'nothing-to-compact';
|
|
1344
1461
|
|
|
1345
1462
|
compactionQueued = true;
|
|
@@ -1613,6 +1730,10 @@ export function createGoosedumpIntegration(
|
|
|
1613
1730
|
if (!counterTriggered || compactionQueued) return;
|
|
1614
1731
|
if (ctx.hasPendingMessages()) return;
|
|
1615
1732
|
if (!hasCompactableHistory(ctx)) return;
|
|
1733
|
+
// Pi checks this threshold immediately after agent_end. Let that native
|
|
1734
|
+
// path invoke our session_before_compact hook instead of starting a
|
|
1735
|
+
// competing manual compaction.
|
|
1736
|
+
if (!resumeAfter && piAutoCompactionPending(ctx)) return;
|
|
1616
1737
|
|
|
1617
1738
|
syncCompactCounters(ctx, true);
|
|
1618
1739
|
updateStatus(ctx);
|
|
@@ -1652,7 +1773,7 @@ export function createGoosedumpIntegration(
|
|
|
1652
1773
|
});
|
|
1653
1774
|
|
|
1654
1775
|
pi.on('turn_end', async (event, ctx) => {
|
|
1655
|
-
noteCompletedTurn(ctx);
|
|
1776
|
+
if (isCompletedAssistant(event.message)) noteCompletedTurn(ctx);
|
|
1656
1777
|
// A turn with tool results means the agent loop would keep going; compact
|
|
1657
1778
|
// between turns and resume so the run's progress is not lost.
|
|
1658
1779
|
if (event.toolResults.length > 0) maybeAutoCompact(ctx, true);
|
|
@@ -1679,12 +1800,19 @@ export function createGoosedumpIntegration(
|
|
|
1679
1800
|
const target = currentSessionTarget(ctx);
|
|
1680
1801
|
if (!target) return;
|
|
1681
1802
|
|
|
1803
|
+
// Pi checks reserveTokens immediately after agent_end. A turn-driven
|
|
1804
|
+
// ctx.compact() can reach this hook at the same time; let the first
|
|
1805
|
+
// compaction proceed and cancel the duplicate before both append entries.
|
|
1806
|
+
if (compactionHookActive) return { cancel: true };
|
|
1807
|
+
compactionHookActive = true;
|
|
1808
|
+
|
|
1682
1809
|
try {
|
|
1683
1810
|
const keep = pendingKeep ?? undefined;
|
|
1684
1811
|
const compaction = await buildGoosedumpCompaction(
|
|
1685
1812
|
target,
|
|
1686
1813
|
event.preparation,
|
|
1687
1814
|
event.branchEntries,
|
|
1815
|
+
piReserveTokens(ctx.cwd),
|
|
1688
1816
|
keep,
|
|
1689
1817
|
event.signal,
|
|
1690
1818
|
);
|
|
@@ -1708,6 +1836,7 @@ export function createGoosedumpIntegration(
|
|
|
1708
1836
|
}
|
|
1709
1837
|
return undefined;
|
|
1710
1838
|
} finally {
|
|
1839
|
+
compactionHookActive = false;
|
|
1711
1840
|
pendingKeep = null;
|
|
1712
1841
|
}
|
|
1713
1842
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-goosedump",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.6",
|
|
4
4
|
"description": "Pi extension for goosedump-backed session-history search, entry expansion, and compaction",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"compaction",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@earendil-works/pi-tui": "^0.78.0",
|
|
36
|
-
"@jarkkojs/goosedump": "^0.10.
|
|
36
|
+
"@jarkkojs/goosedump": "^0.10.6",
|
|
37
37
|
"@sinclair/typebox": "^0.34.49"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|