pi-goosedump 0.12.39 → 0.12.41
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 +6 -5
- package/dist/index.ts +201 -107
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,10 +9,11 @@ management, and compaction. Tools use the `goose_` prefix.
|
|
|
9
9
|
pi install npm:pi-goosedump
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
Bundled native binaries: Linux x64, macOS arm64, Windows x64.
|
|
12
|
+
Bundled native binaries: Linux x64 and arm64, macOS arm64, and Windows x64.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
Unsupported platforms are rejected when the extension loads. A missing packaged binary is treated as
|
|
15
|
+
a broken installation instead of falling back to a `goosedump` executable on `PATH`. Local models
|
|
16
|
+
download on first use.
|
|
16
17
|
|
|
17
18
|
## Tools
|
|
18
19
|
|
|
@@ -91,8 +92,8 @@ The footer shows the remaining turn count in hexadecimal.
|
|
|
91
92
|
- `keep:N` leaves the last N user turns verbatim.
|
|
92
93
|
- Manual requests wait until Pi is idle.
|
|
93
94
|
- Memory learning runs in the background after a successful compaction.
|
|
94
|
-
- If the turn limit expires during a tool loop,
|
|
95
|
-
|
|
95
|
+
- If the turn limit expires during a tool loop, Pi saves the current batch,
|
|
96
|
+
compacts at that turn boundary, and resumes automatically.
|
|
96
97
|
- Goosedump failures fall back to Pi's compactor.
|
|
97
98
|
|
|
98
99
|
## License
|
package/dist/index.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright (C) Jarkko Sakkinen 2026
|
|
3
3
|
|
|
4
|
-
// src/integration.ts
|
|
5
|
-
import { execFileSync } from "node:child_process";
|
|
6
|
-
|
|
7
4
|
// src/cli.ts
|
|
8
5
|
import { execFile } from "node:child_process";
|
|
9
6
|
import { existsSync } from "node:fs";
|
|
@@ -34,7 +31,6 @@ var TURNS_BEFORE_COMPACT_MIN = 0;
|
|
|
34
31
|
var TURNS_BEFORE_COMPACT_MAX = 255;
|
|
35
32
|
var SUMMARY_MAX_TOKENS_MIN = 512;
|
|
36
33
|
var SUMMARY_MAX_TOKENS_MAX = 65536;
|
|
37
|
-
var GOOSEDUMP_UNAVAILABLE_MESSAGE = "goosedump is not available. Install with: npm install @jarkkojs/goosedump";
|
|
38
34
|
var GOOSE_PROVIDERS = [
|
|
39
35
|
"pi",
|
|
40
36
|
"claude",
|
|
@@ -63,9 +59,6 @@ function missingSessionId(tool, provider = "pi") {
|
|
|
63
59
|
}
|
|
64
60
|
return textResult(`session is required for ${tool} when no current session is available`);
|
|
65
61
|
}
|
|
66
|
-
function goosedumpUnavailableResult() {
|
|
67
|
-
return textResult(GOOSEDUMP_UNAVAILABLE_MESSAGE);
|
|
68
|
-
}
|
|
69
62
|
function compactStartedMessage(keep, queued = false) {
|
|
70
63
|
const action = queued ? "Compaction queued with goosedump" : "Compacting with goosedump";
|
|
71
64
|
return keep !== null ? `${action}; keeping the last ${keep} user turn${keep === 1 ? "" : "s"}.` : `${action} up to Pi's token-based cut.`;
|
|
@@ -181,6 +174,12 @@ function parsePiMessages(output) {
|
|
|
181
174
|
role: "user",
|
|
182
175
|
content: flattenPiContent(entry.content)
|
|
183
176
|
});
|
|
177
|
+
} else if (entry.type === "compaction") {
|
|
178
|
+
messages.push({
|
|
179
|
+
id: entry.id ?? "",
|
|
180
|
+
role: "compactionSummary",
|
|
181
|
+
content: entry.summary ?? ""
|
|
182
|
+
});
|
|
184
183
|
} else if (entry.type === "branch_summary") {
|
|
185
184
|
messages.push({
|
|
186
185
|
id: entry.id ?? "",
|
|
@@ -283,33 +282,40 @@ ${m.content}`).join(`
|
|
|
283
282
|
|
|
284
283
|
// src/cli.ts
|
|
285
284
|
var require2 = createRequire(import.meta.url);
|
|
286
|
-
function
|
|
287
|
-
return require2.resolve("@jarkkojs/goosedump/bin/goosedump.js");
|
|
288
|
-
}
|
|
289
|
-
function resolveNativeGoosedumpBinary() {
|
|
290
|
-
const target = `${process.platform}-${process.arch}`;
|
|
291
|
-
let packageName;
|
|
292
|
-
let binaryName = "goosedump";
|
|
285
|
+
function nativeGoosedumpPackage(target) {
|
|
293
286
|
switch (target) {
|
|
294
287
|
case "linux-x64":
|
|
295
|
-
packageName
|
|
296
|
-
|
|
288
|
+
return { packageName: "@jarkkojs/goosedump-linux-x64", binaryName: "goosedump" };
|
|
289
|
+
case "linux-arm64":
|
|
290
|
+
return { packageName: "@jarkkojs/goosedump-linux-arm64", binaryName: "goosedump" };
|
|
297
291
|
case "darwin-arm64":
|
|
298
|
-
packageName
|
|
299
|
-
break;
|
|
292
|
+
return { packageName: "@jarkkojs/goosedump-darwin-arm64", binaryName: "goosedump" };
|
|
300
293
|
case "win32-x64":
|
|
301
|
-
packageName
|
|
302
|
-
binaryName = "goosedump.exe";
|
|
303
|
-
break;
|
|
294
|
+
return { packageName: "@jarkkojs/goosedump-win32-x64", binaryName: "goosedump.exe" };
|
|
304
295
|
default:
|
|
305
296
|
throw new Error(`unsupported platform architecture: ${target}`);
|
|
306
297
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
298
|
+
}
|
|
299
|
+
function resolveGoosedumpBinary() {
|
|
300
|
+
try {
|
|
301
|
+
return require2.resolve("@jarkkojs/goosedump/bin/goosedump.js");
|
|
302
|
+
} catch (cause) {
|
|
303
|
+
throw new Error("broken pi-goosedump installation: cannot resolve the @jarkkojs/goosedump dependency", { cause });
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function resolveNativeGoosedumpBinary() {
|
|
307
|
+
const target = `${process.platform}-${process.arch}`;
|
|
308
|
+
const { packageName, binaryName } = nativeGoosedumpPackage(target);
|
|
309
|
+
try {
|
|
310
|
+
const wrapperRequire = createRequire(resolveGoosedumpBinary());
|
|
311
|
+
const packageDir = dirname(wrapperRequire.resolve(`${packageName}/package.json`));
|
|
312
|
+
const binaryPath = join(packageDir, "bin", binaryName);
|
|
313
|
+
if (!existsSync(binaryPath))
|
|
314
|
+
throw new Error(`binary not found: ${binaryPath}`);
|
|
315
|
+
return binaryPath;
|
|
316
|
+
} catch (cause) {
|
|
317
|
+
throw new Error(`broken pi-goosedump installation: cannot resolve the packaged binary ${packageName} for ${target}`, { cause });
|
|
318
|
+
}
|
|
313
319
|
}
|
|
314
320
|
function runGoosedumpAsync(args, signal, executablePath = resolveNativeGoosedumpBinary()) {
|
|
315
321
|
return new Promise((resolve, reject) => {
|
|
@@ -384,12 +390,16 @@ async function goosedumpMemoryStatus(signal, executablePath) {
|
|
|
384
390
|
async function goosedumpListSessions(signal, executablePath) {
|
|
385
391
|
const args = ["session", "list", "--json"];
|
|
386
392
|
const output = await runGoosedumpAsync(args, signal, executablePath);
|
|
393
|
+
let parsed;
|
|
387
394
|
try {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
395
|
+
parsed = JSON.parse(output.stdout);
|
|
396
|
+
} catch (error) {
|
|
397
|
+
throw new Error("invalid goosedump session list JSON", { cause: error });
|
|
398
|
+
}
|
|
399
|
+
if (!Array.isArray(parsed)) {
|
|
400
|
+
throw new Error("invalid goosedump session list JSON: expected an array");
|
|
392
401
|
}
|
|
402
|
+
return parsed;
|
|
393
403
|
}
|
|
394
404
|
async function goosedumpRemoveSession(target, signal, executablePath) {
|
|
395
405
|
const args = ["session", "remove", target, "--yes"];
|
|
@@ -520,13 +530,32 @@ function readJsonObjectStrict(path) {
|
|
|
520
530
|
throw new Error(`${path} must contain a JSON object`);
|
|
521
531
|
return parsed;
|
|
522
532
|
}
|
|
533
|
+
function replaceFileAtomically(temporaryPath, path) {
|
|
534
|
+
if (process.platform !== "win32" || !existsSync2(path)) {
|
|
535
|
+
renameSync(temporaryPath, path);
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
const backupPath = `${path}.${randomUUID()}.bak`;
|
|
539
|
+
renameSync(path, backupPath);
|
|
540
|
+
try {
|
|
541
|
+
renameSync(temporaryPath, path);
|
|
542
|
+
} catch (error) {
|
|
543
|
+
try {
|
|
544
|
+
renameSync(backupPath, path);
|
|
545
|
+
} catch {}
|
|
546
|
+
throw error;
|
|
547
|
+
}
|
|
548
|
+
try {
|
|
549
|
+
unlinkSync(backupPath);
|
|
550
|
+
} catch {}
|
|
551
|
+
}
|
|
523
552
|
function writeJsonObjectAtomically(path, value) {
|
|
524
553
|
mkdirSync(dirname2(path), { recursive: true });
|
|
525
554
|
const temporaryPath = `${path}.${randomUUID()}.tmp`;
|
|
526
555
|
try {
|
|
527
556
|
writeFileSync(temporaryPath, `${JSON.stringify(value, null, 2)}
|
|
528
557
|
`, { flag: "wx" });
|
|
529
|
-
|
|
558
|
+
replaceFileAtomically(temporaryPath, path);
|
|
530
559
|
} catch (error) {
|
|
531
560
|
try {
|
|
532
561
|
unlinkSync(temporaryPath);
|
|
@@ -784,10 +813,10 @@ function isCompactionCancellation(error) {
|
|
|
784
813
|
class CompactionRuntime {
|
|
785
814
|
overrideDefaultCompaction;
|
|
786
815
|
nativeExecutablePath;
|
|
787
|
-
isAvailable;
|
|
788
816
|
enqueueRemember;
|
|
789
817
|
compactSettings = DEFAULT_GOOSEDUMP_SETTINGS;
|
|
790
818
|
piAutoCompactionEnabled = DEFAULT_COMPACTION_SETTINGS2.enabled;
|
|
819
|
+
piCompactionReserveTokens = DEFAULT_COMPACTION_SETTINGS2.reserveTokens;
|
|
791
820
|
turnsRemaining = 0;
|
|
792
821
|
counterTriggered = false;
|
|
793
822
|
compactionState = { phase: "idle" };
|
|
@@ -796,12 +825,15 @@ class CompactionRuntime {
|
|
|
796
825
|
operationGeneration = 0;
|
|
797
826
|
activeSessionFile = null;
|
|
798
827
|
sessionActive = false;
|
|
828
|
+
activePi = null;
|
|
799
829
|
constructor(deps) {
|
|
800
830
|
this.overrideDefaultCompaction = deps.overrideDefaultCompaction;
|
|
801
831
|
this.nativeExecutablePath = deps.nativeExecutablePath;
|
|
802
|
-
this.isAvailable = deps.isAvailable;
|
|
803
832
|
this.enqueueRemember = deps.enqueueRemember;
|
|
804
833
|
}
|
|
834
|
+
setActivePi(pi) {
|
|
835
|
+
this.activePi = pi;
|
|
836
|
+
}
|
|
805
837
|
requestCompaction(ctx, keep) {
|
|
806
838
|
if (this.compactionState.phase !== "idle")
|
|
807
839
|
return "busy";
|
|
@@ -814,7 +846,8 @@ class CompactionRuntime {
|
|
|
814
846
|
origin: "manual",
|
|
815
847
|
sessionGeneration: this.sessionGeneration,
|
|
816
848
|
sessionFile: this.activeSessionFile,
|
|
817
|
-
eligibleSettlement: this.settlementGeneration + 1
|
|
849
|
+
eligibleSettlement: this.settlementGeneration + 1,
|
|
850
|
+
resumeAfter: false
|
|
818
851
|
}
|
|
819
852
|
});
|
|
820
853
|
return this.startQueuedCompaction(ctx) ? "started" : "queued";
|
|
@@ -823,13 +856,12 @@ class CompactionRuntime {
|
|
|
823
856
|
const projectTrusted = projectSettingsTrusted(ctx);
|
|
824
857
|
this.compactSettings = resolveGoosedumpSettings(ctx.cwd, projectTrusted);
|
|
825
858
|
this.piAutoCompactionEnabled = piCompactionEnabled(ctx.cwd, projectTrusted);
|
|
859
|
+
this.piCompactionReserveTokens = piReserveTokens(ctx.cwd, projectTrusted);
|
|
826
860
|
const completedTurns = completedTurnsSinceCompaction(ctx.sessionManager.getBranch());
|
|
827
861
|
this.turnsRemaining = Math.max(0, this.compactSettings.turnsBeforeCompact - completedTurns);
|
|
828
862
|
this.counterTriggered = this.compactSettings.turnsBeforeCompact > 0 && completedTurns >= this.compactSettings.turnsBeforeCompact;
|
|
829
863
|
}
|
|
830
864
|
updateStatus(ctx) {
|
|
831
|
-
if (!this.isAvailable())
|
|
832
|
-
return;
|
|
833
865
|
const active = this.turnCompactionEnabled();
|
|
834
866
|
let dotColor = "success";
|
|
835
867
|
if (active) {
|
|
@@ -855,7 +887,7 @@ class CompactionRuntime {
|
|
|
855
887
|
this.syncCompactCounters(ctx);
|
|
856
888
|
this.updateStatus(ctx);
|
|
857
889
|
this.queueTurnCompaction(ctx, 1);
|
|
858
|
-
this.
|
|
890
|
+
this.startQueuedCompaction(ctx);
|
|
859
891
|
}
|
|
860
892
|
endSession() {
|
|
861
893
|
this.sessionGeneration += 1;
|
|
@@ -873,12 +905,18 @@ class CompactionRuntime {
|
|
|
873
905
|
this.setCompactionState(ctx, request ? this.requeueRequest(request, this.settlementGeneration + 1) : { phase: "idle" });
|
|
874
906
|
}
|
|
875
907
|
onTurnEnd(event, ctx) {
|
|
876
|
-
if (isCompletedAssistant(event.message))
|
|
908
|
+
if (!isCompletedAssistant(event.message))
|
|
909
|
+
return;
|
|
910
|
+
const resumeAfter = event.toolResults.length > 0 && !ctx.hasPendingMessages();
|
|
911
|
+
if (this.overrideDefaultCompaction) {
|
|
877
912
|
this.noteCompletedTurn(ctx);
|
|
913
|
+
const eligibleSettlement = this.settlementGeneration + 1;
|
|
914
|
+
this.queueTurnCompaction(ctx, eligibleSettlement, resumeAfter);
|
|
915
|
+
this.queueThresholdCompaction(ctx, eligibleSettlement, resumeAfter);
|
|
916
|
+
}
|
|
917
|
+
this.interruptToolLoopForQueuedCompaction(ctx, resumeAfter);
|
|
878
918
|
}
|
|
879
919
|
onAgentSettled(ctx) {
|
|
880
|
-
if (!this.isAvailable() || !this.overrideDefaultCompaction)
|
|
881
|
-
return;
|
|
882
920
|
this.settlementGeneration += 1;
|
|
883
921
|
this.syncCompactCounters(ctx);
|
|
884
922
|
this.updateStatus(ctx);
|
|
@@ -894,11 +932,11 @@ class CompactionRuntime {
|
|
|
894
932
|
this.queueTurnCompaction(ctx, this.settlementGeneration);
|
|
895
933
|
}
|
|
896
934
|
if (this.compactionState.phase === "queued" && this.compactionState.request.eligibleSettlement <= this.settlementGeneration) {
|
|
897
|
-
this.
|
|
935
|
+
this.startQueuedCompaction(ctx);
|
|
898
936
|
}
|
|
899
937
|
}
|
|
900
938
|
async onSessionBeforeCompact(event, ctx) {
|
|
901
|
-
if (!this.overrideDefaultCompaction
|
|
939
|
+
if (!this.overrideDefaultCompaction)
|
|
902
940
|
return;
|
|
903
941
|
const signal = event.signal;
|
|
904
942
|
if (signal?.aborted) {
|
|
@@ -1042,8 +1080,6 @@ class CompactionRuntime {
|
|
|
1042
1080
|
this.compactionState = { phase: "idle" };
|
|
1043
1081
|
this.resetCompactCounters(ctx);
|
|
1044
1082
|
this.updateStatus(ctx);
|
|
1045
|
-
if (!this.isAvailable())
|
|
1046
|
-
return;
|
|
1047
1083
|
const compactionEntry = event.compactionEntry;
|
|
1048
1084
|
if (!event.fromExtension || !compactionEntry || !isRecord(compactionEntry.details) || compactionEntry.details.source !== "goosedump") {
|
|
1049
1085
|
return;
|
|
@@ -1068,6 +1104,7 @@ class CompactionRuntime {
|
|
|
1068
1104
|
const projectTrusted = projectSettingsTrusted(ctx);
|
|
1069
1105
|
this.compactSettings = resolveGoosedumpSettings(ctx.cwd, projectTrusted);
|
|
1070
1106
|
this.piAutoCompactionEnabled = piCompactionEnabled(ctx.cwd, projectTrusted);
|
|
1107
|
+
this.piCompactionReserveTokens = piReserveTokens(ctx.cwd, projectTrusted);
|
|
1071
1108
|
this.turnsRemaining = this.compactSettings.turnsBeforeCompact;
|
|
1072
1109
|
this.counterTriggered = false;
|
|
1073
1110
|
}
|
|
@@ -1086,11 +1123,48 @@ class CompactionRuntime {
|
|
|
1086
1123
|
this.updateStatus(ctx);
|
|
1087
1124
|
}
|
|
1088
1125
|
noteCompletedTurn(ctx) {
|
|
1089
|
-
if (!this.
|
|
1126
|
+
if (!this.overrideDefaultCompaction)
|
|
1090
1127
|
return;
|
|
1091
1128
|
this.syncCompactCounters(ctx);
|
|
1092
1129
|
this.updateStatus(ctx);
|
|
1093
|
-
|
|
1130
|
+
}
|
|
1131
|
+
resumeAfterSuccessfulCompaction(ctx, resume) {
|
|
1132
|
+
if (!resume || !this.activePi || ctx.hasPendingMessages())
|
|
1133
|
+
return;
|
|
1134
|
+
this.activePi.sendMessage({
|
|
1135
|
+
customType: "goosedump-autocompact-resume",
|
|
1136
|
+
content: "The session was compacted to reduce context size. Continue the task you were working on from where you left off.",
|
|
1137
|
+
display: false
|
|
1138
|
+
}, { triggerTurn: true });
|
|
1139
|
+
}
|
|
1140
|
+
interruptToolLoopForQueuedCompaction(ctx, resumeAfter) {
|
|
1141
|
+
if (!resumeAfter || this.compactionState.phase !== "queued")
|
|
1142
|
+
return;
|
|
1143
|
+
const request = this.compactionState.request;
|
|
1144
|
+
if (!this.requestIsCurrent(request))
|
|
1145
|
+
return;
|
|
1146
|
+
this.compactionState = {
|
|
1147
|
+
phase: "queued",
|
|
1148
|
+
request: { ...request, resumeAfter: true }
|
|
1149
|
+
};
|
|
1150
|
+
ctx.abort();
|
|
1151
|
+
}
|
|
1152
|
+
queueThresholdCompaction(ctx, eligibleSettlement, resumeAfter) {
|
|
1153
|
+
const usage = ctx.getContextUsage();
|
|
1154
|
+
if (!this.piAutoCompactionEnabled || this.piCompactionReserveTokens <= 0 || usage?.tokens === null || usage?.tokens === undefined || usage.tokens < usage.contextWindow - this.piCompactionReserveTokens || this.compactionState.phase !== "idle" || !hasCompactableHistory(ctx)) {
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1157
|
+
this.setCompactionState(ctx, {
|
|
1158
|
+
phase: "queued",
|
|
1159
|
+
request: {
|
|
1160
|
+
keep: null,
|
|
1161
|
+
origin: "threshold",
|
|
1162
|
+
sessionGeneration: this.sessionGeneration,
|
|
1163
|
+
sessionFile: this.activeSessionFile,
|
|
1164
|
+
eligibleSettlement,
|
|
1165
|
+
resumeAfter
|
|
1166
|
+
}
|
|
1167
|
+
});
|
|
1094
1168
|
}
|
|
1095
1169
|
requestIsCurrent(request) {
|
|
1096
1170
|
return request.sessionGeneration === this.sessionGeneration && request.sessionFile === this.activeSessionFile;
|
|
@@ -1111,7 +1185,7 @@ class CompactionRuntime {
|
|
|
1111
1185
|
requestHasCompactableHistory(ctx, keep) {
|
|
1112
1186
|
return keep === null ? hasCompactableHistory(ctx) : keepBoundaryId(ctx.sessionManager.getBranch(), keep) !== undefined;
|
|
1113
1187
|
}
|
|
1114
|
-
queueTurnCompaction(ctx, eligibleSettlement) {
|
|
1188
|
+
queueTurnCompaction(ctx, eligibleSettlement, resumeAfter = false) {
|
|
1115
1189
|
if (!this.turnCompactionEnabled() || !this.counterTriggered || this.compactionState.phase !== "idle") {
|
|
1116
1190
|
return;
|
|
1117
1191
|
}
|
|
@@ -1124,7 +1198,8 @@ class CompactionRuntime {
|
|
|
1124
1198
|
origin: "turn",
|
|
1125
1199
|
sessionGeneration: this.sessionGeneration,
|
|
1126
1200
|
sessionFile: this.activeSessionFile,
|
|
1127
|
-
eligibleSettlement
|
|
1201
|
+
eligibleSettlement,
|
|
1202
|
+
resumeAfter
|
|
1128
1203
|
}
|
|
1129
1204
|
});
|
|
1130
1205
|
}
|
|
@@ -1138,7 +1213,7 @@ class CompactionRuntime {
|
|
|
1138
1213
|
this.setCompactionState(ctx, { phase: "idle" });
|
|
1139
1214
|
return false;
|
|
1140
1215
|
}
|
|
1141
|
-
if (ctx.hasPendingMessages())
|
|
1216
|
+
if (request.origin !== "turn" && ctx.hasPendingMessages())
|
|
1142
1217
|
return false;
|
|
1143
1218
|
if (!ctx.isIdle())
|
|
1144
1219
|
return false;
|
|
@@ -1149,6 +1224,7 @@ class CompactionRuntime {
|
|
|
1149
1224
|
const operation = ++this.operationGeneration;
|
|
1150
1225
|
const generation = request.sessionGeneration;
|
|
1151
1226
|
const sessionFile = request.sessionFile;
|
|
1227
|
+
const resumeAfter = request.resumeAfter;
|
|
1152
1228
|
this.setCompactionState(ctx, {
|
|
1153
1229
|
phase: "running",
|
|
1154
1230
|
request,
|
|
@@ -1163,6 +1239,7 @@ class CompactionRuntime {
|
|
|
1163
1239
|
if (!this.runningOperationIsCurrent(operation, generation, sessionFile))
|
|
1164
1240
|
return;
|
|
1165
1241
|
this.setCompactionState(ctx, { phase: "idle" });
|
|
1242
|
+
this.resumeAfterSuccessfulCompaction(ctx, resumeAfter);
|
|
1166
1243
|
},
|
|
1167
1244
|
onError: (error) => {
|
|
1168
1245
|
if (!this.runningOperationIsCurrent(operation, generation, sessionFile))
|
|
@@ -1179,17 +1256,6 @@ class CompactionRuntime {
|
|
|
1179
1256
|
});
|
|
1180
1257
|
return true;
|
|
1181
1258
|
}
|
|
1182
|
-
deferQueuedCompaction(ctx) {
|
|
1183
|
-
if (this.compactionState.phase !== "queued")
|
|
1184
|
-
return;
|
|
1185
|
-
const request = this.compactionState.request;
|
|
1186
|
-
setImmediate(() => {
|
|
1187
|
-
if (this.compactionState.phase !== "queued" || this.compactionState.request !== request || !this.contextIsCurrent(ctx)) {
|
|
1188
|
-
return;
|
|
1189
|
-
}
|
|
1190
|
-
this.startQueuedCompaction(ctx);
|
|
1191
|
-
});
|
|
1192
|
-
}
|
|
1193
1259
|
}
|
|
1194
1260
|
|
|
1195
1261
|
// src/policy.ts
|
|
@@ -1343,7 +1409,12 @@ function renderToolRoutingPolicy(options = {}) {
|
|
|
1343
1409
|
}
|
|
1344
1410
|
|
|
1345
1411
|
// src/tools.ts
|
|
1346
|
-
import {
|
|
1412
|
+
import {
|
|
1413
|
+
DEFAULT_MAX_BYTES,
|
|
1414
|
+
DEFAULT_MAX_LINES,
|
|
1415
|
+
defineTool,
|
|
1416
|
+
truncateHead
|
|
1417
|
+
} from "@earendil-works/pi-coding-agent";
|
|
1347
1418
|
import { Type } from "@sinclair/typebox";
|
|
1348
1419
|
function historyProviderParam() {
|
|
1349
1420
|
return Type.Optional(Type.Union(GOOSE_PROVIDERS.map((provider) => Type.Literal(provider)), {
|
|
@@ -1378,6 +1449,17 @@ function goosedumpErrorResult(err) {
|
|
|
1378
1449
|
const message = err instanceof Error ? err.message : String(err);
|
|
1379
1450
|
return textResult(`goosedump error: ${message}`);
|
|
1380
1451
|
}
|
|
1452
|
+
function boundedHistoryResult(text) {
|
|
1453
|
+
const output = truncateHead(text, {
|
|
1454
|
+
maxBytes: DEFAULT_MAX_BYTES,
|
|
1455
|
+
maxLines: DEFAULT_MAX_LINES
|
|
1456
|
+
});
|
|
1457
|
+
if (!output.truncated)
|
|
1458
|
+
return textResult(text);
|
|
1459
|
+
return textResult(`${output.content}
|
|
1460
|
+
|
|
1461
|
+
[Output truncated: showing ${output.outputLines} of ${output.totalLines} lines ` + `and ${output.outputBytes} of ${output.totalBytes} bytes. ` + "Use goose_get with fewer IDs or a narrower goose_grep pattern.]");
|
|
1462
|
+
}
|
|
1381
1463
|
function resolveHistoryTarget(ctx, tool, params) {
|
|
1382
1464
|
const provider = params.provider ?? "pi";
|
|
1383
1465
|
const target = resolveTarget(ctx, provider, params.session);
|
|
@@ -1401,13 +1483,11 @@ function gooseToolMeta(name) {
|
|
|
1401
1483
|
};
|
|
1402
1484
|
}
|
|
1403
1485
|
var GOOSE_MEMORY_TYPES = ["decision", "fact", "preference", "procedure", "lesson"];
|
|
1404
|
-
function defineGooseTool(
|
|
1486
|
+
function defineGooseTool(name, parameters, handler) {
|
|
1405
1487
|
return defineTool({
|
|
1406
1488
|
...gooseToolMeta(name),
|
|
1407
1489
|
parameters,
|
|
1408
1490
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
1409
|
-
if (!isAvailable())
|
|
1410
|
-
return goosedumpUnavailableResult();
|
|
1411
1491
|
try {
|
|
1412
1492
|
return await handler(params, signal, ctx);
|
|
1413
1493
|
} catch (err) {
|
|
@@ -1417,8 +1497,8 @@ function defineGooseTool(isAvailable, name, parameters, handler) {
|
|
|
1417
1497
|
});
|
|
1418
1498
|
}
|
|
1419
1499
|
function registerGooseTools(pi, deps) {
|
|
1420
|
-
const {
|
|
1421
|
-
pi.registerTool(defineGooseTool(
|
|
1500
|
+
const { nativeExecutablePath, enqueueRemember, requestCompaction } = deps;
|
|
1501
|
+
pi.registerTool(defineGooseTool("goose_remember", Type.Object({ ...historyTargetParams() }), async (params, _signal, ctx) => {
|
|
1422
1502
|
const resolved = resolveHistoryTarget(ctx, "goose_remember", params);
|
|
1423
1503
|
if (!resolved.ok)
|
|
1424
1504
|
return resolved.result;
|
|
@@ -1429,7 +1509,7 @@ function registerGooseTools(pi, deps) {
|
|
|
1429
1509
|
});
|
|
1430
1510
|
return textResult(`Memory learning queued for ${resolved.target}.`);
|
|
1431
1511
|
}));
|
|
1432
|
-
pi.registerTool(defineGooseTool(
|
|
1512
|
+
pi.registerTool(defineGooseTool("goose_recall", Type.Object({
|
|
1433
1513
|
query: Type.String({ description: PARAM_DESCRIPTIONS.memoryQuery }),
|
|
1434
1514
|
type: Type.Optional(Type.Union(GOOSE_MEMORY_TYPES.map((type) => Type.Literal(type)), { description: PARAM_DESCRIPTIONS.memoryType })),
|
|
1435
1515
|
allProjects: Type.Optional(Type.Boolean({
|
|
@@ -1459,7 +1539,7 @@ function registerGooseTools(pi, deps) {
|
|
|
1459
1539
|
return textResult(`No durable memory for "${params.query}"`);
|
|
1460
1540
|
return textResult(formatMemoryHits(hits));
|
|
1461
1541
|
}));
|
|
1462
|
-
pi.registerTool(defineGooseTool(
|
|
1542
|
+
pi.registerTool(defineGooseTool("goose_forget", Type.Object({
|
|
1463
1543
|
target: Type.String({
|
|
1464
1544
|
description: PARAM_DESCRIPTIONS.forgetTarget
|
|
1465
1545
|
})
|
|
@@ -1470,8 +1550,8 @@ function registerGooseTools(pi, deps) {
|
|
|
1470
1550
|
const res = await goosedumpMemoryForget(params.target.trim(), signal, nativeExecutablePath);
|
|
1471
1551
|
return textResult(res);
|
|
1472
1552
|
}));
|
|
1473
|
-
pi.registerTool(defineGooseTool(
|
|
1474
|
-
pi.registerTool(defineGooseTool(
|
|
1553
|
+
pi.registerTool(defineGooseTool("goose_memory_status", Type.Object({}), async (_params, signal) => textResult(await goosedumpMemoryStatus(signal, nativeExecutablePath))));
|
|
1554
|
+
pi.registerTool(defineGooseTool("goose_search", Type.Object({
|
|
1475
1555
|
query: Type.String({ description: PARAM_DESCRIPTIONS.searchQuery }),
|
|
1476
1556
|
...historyBranchParams(),
|
|
1477
1557
|
page: Type.Optional(Type.Integer({
|
|
@@ -1493,7 +1573,7 @@ function registerGooseTools(pi, deps) {
|
|
|
1493
1573
|
|
|
1494
1574
|
${text}`);
|
|
1495
1575
|
}));
|
|
1496
|
-
pi.registerTool(defineGooseTool(
|
|
1576
|
+
pi.registerTool(defineGooseTool("goose_get", Type.Object({
|
|
1497
1577
|
ids: Type.Array(Type.String(), {
|
|
1498
1578
|
minItems: 1,
|
|
1499
1579
|
description: PARAM_DESCRIPTIONS.entryIds
|
|
@@ -1507,9 +1587,9 @@ ${text}`);
|
|
|
1507
1587
|
if (messages.length === 0) {
|
|
1508
1588
|
return textResult("No entries found for the given IDs.");
|
|
1509
1589
|
}
|
|
1510
|
-
return
|
|
1590
|
+
return boundedHistoryResult(formatMessagesFull(messages));
|
|
1511
1591
|
}));
|
|
1512
|
-
pi.registerTool(defineGooseTool(
|
|
1592
|
+
pi.registerTool(defineGooseTool("goose_grep", Type.Object({
|
|
1513
1593
|
pattern: Type.String({ description: PARAM_DESCRIPTIONS.pattern }),
|
|
1514
1594
|
...historyBranchParams()
|
|
1515
1595
|
}), async (params, signal, ctx) => {
|
|
@@ -1520,9 +1600,9 @@ ${text}`);
|
|
|
1520
1600
|
if (messages.length === 0) {
|
|
1521
1601
|
return textResult(`No matches for "${params.pattern}"`);
|
|
1522
1602
|
}
|
|
1523
|
-
return
|
|
1603
|
+
return boundedHistoryResult(formatMessagesCompact(messages));
|
|
1524
1604
|
}));
|
|
1525
|
-
pi.registerTool(defineGooseTool(
|
|
1605
|
+
pi.registerTool(defineGooseTool("goose_compact", Type.Object({
|
|
1526
1606
|
keep: Type.Optional(Type.Integer({
|
|
1527
1607
|
minimum: 1,
|
|
1528
1608
|
description: PARAM_DESCRIPTIONS.keep
|
|
@@ -1537,7 +1617,7 @@ ${text}`);
|
|
|
1537
1617
|
}
|
|
1538
1618
|
return textResult(compactStartedMessage(keep, result === "queued"));
|
|
1539
1619
|
}));
|
|
1540
|
-
pi.registerTool(defineGooseTool(
|
|
1620
|
+
pi.registerTool(defineGooseTool("goose_sessions", Type.Object({
|
|
1541
1621
|
action: Type.Optional(Type.Union([Type.Literal("list"), Type.Literal("delete")], {
|
|
1542
1622
|
default: "list",
|
|
1543
1623
|
description: PARAM_DESCRIPTIONS.sessionsAction
|
|
@@ -1550,19 +1630,22 @@ ${text}`);
|
|
|
1550
1630
|
const action = params.action ?? "list";
|
|
1551
1631
|
const provider = params.provider ?? "pi";
|
|
1552
1632
|
const currentTarget = currentSessionTarget(ctx);
|
|
1633
|
+
const sessions = await goosedumpListSessions(signal, nativeExecutablePath);
|
|
1634
|
+
const cwdSessions = sessions.filter((s) => s.cwd === ctx.cwd && s.provider === provider);
|
|
1553
1635
|
if (action === "delete") {
|
|
1554
1636
|
if (!params.session) {
|
|
1555
1637
|
return textResult("goose_sessions error: session ID is required for action: delete");
|
|
1556
1638
|
}
|
|
1557
1639
|
const target = formatTarget(provider, params.session);
|
|
1640
|
+
if (!cwdSessions.some((session) => session.id === params.session)) {
|
|
1641
|
+
return textResult(`Cannot delete session ${target}: not found for ${ctx.cwd}.`);
|
|
1642
|
+
}
|
|
1558
1643
|
if (currentTarget && target === currentTarget) {
|
|
1559
1644
|
return textResult("Cannot delete the active session.");
|
|
1560
1645
|
}
|
|
1561
1646
|
await goosedumpRemoveSession(target, signal, nativeExecutablePath);
|
|
1562
1647
|
return textResult(`Deleted session ${target}`);
|
|
1563
1648
|
}
|
|
1564
|
-
const sessions = await goosedumpListSessions(signal, nativeExecutablePath);
|
|
1565
|
-
const cwdSessions = sessions.filter((s) => s.cwd === ctx.cwd && s.provider === provider);
|
|
1566
1649
|
if (cwdSessions.length === 0) {
|
|
1567
1650
|
return textResult(`No ${provider} sessions found for ${ctx.cwd}`);
|
|
1568
1651
|
}
|
|
@@ -1866,7 +1949,7 @@ async function runSettingsEditor(ctx) {
|
|
|
1866
1949
|
}
|
|
1867
1950
|
});
|
|
1868
1951
|
}
|
|
1869
|
-
async function runSearchPanel(ctx, query) {
|
|
1952
|
+
async function runSearchPanel(ctx, query, executablePath) {
|
|
1870
1953
|
const OVERLAY_WIDTH = 84;
|
|
1871
1954
|
const VIEWPORT = 18;
|
|
1872
1955
|
const PAGE_SIZE = 5;
|
|
@@ -1883,7 +1966,7 @@ async function runSearchPanel(ctx, query) {
|
|
|
1883
1966
|
let detailScroll = 0;
|
|
1884
1967
|
async function runSearch() {
|
|
1885
1968
|
try {
|
|
1886
|
-
const first = await goosedumpSearch(target, query, { scope: "lineage", page: 1 });
|
|
1969
|
+
const first = await goosedumpSearch(target, query, { scope: "lineage", page: 1 }, undefined, executablePath);
|
|
1887
1970
|
if (first.length === 0) {
|
|
1888
1971
|
entries = [];
|
|
1889
1972
|
error = `No results for "${query}"`;
|
|
@@ -1893,7 +1976,7 @@ async function runSearchPanel(ctx, query) {
|
|
|
1893
1976
|
}
|
|
1894
1977
|
const all = [...first];
|
|
1895
1978
|
for (let page = 2;page <= 10; page += 1) {
|
|
1896
|
-
const result = await goosedumpSearch(target, query, { scope: "lineage", page });
|
|
1979
|
+
const result = await goosedumpSearch(target, query, { scope: "lineage", page }, undefined, executablePath);
|
|
1897
1980
|
if (result.length === 0)
|
|
1898
1981
|
break;
|
|
1899
1982
|
all.push(...result);
|
|
@@ -1907,6 +1990,8 @@ async function runSearchPanel(ctx, query) {
|
|
|
1907
1990
|
} catch (err) {
|
|
1908
1991
|
entries = [];
|
|
1909
1992
|
error = err instanceof Error ? err.message : String(err);
|
|
1993
|
+
} finally {
|
|
1994
|
+
tui.requestRender();
|
|
1910
1995
|
}
|
|
1911
1996
|
}
|
|
1912
1997
|
if (!target) {
|
|
@@ -1916,7 +2001,7 @@ async function runSearchPanel(ctx, query) {
|
|
|
1916
2001
|
}
|
|
1917
2002
|
async function loadDetail(id) {
|
|
1918
2003
|
try {
|
|
1919
|
-
const messages = await goosedumpShow(target, { ids: [id] });
|
|
2004
|
+
const messages = await goosedumpShow(target, { ids: [id] }, undefined, executablePath);
|
|
1920
2005
|
const content = messages.length > 0 ? messages[0].content : "No content for this entry.";
|
|
1921
2006
|
detailLines = wrapTextWithAnsi(content, wrapWidth);
|
|
1922
2007
|
detailScroll = 0;
|
|
@@ -1924,6 +2009,8 @@ async function runSearchPanel(ctx, query) {
|
|
|
1924
2009
|
} catch (err) {
|
|
1925
2010
|
const message = err instanceof Error ? err.message : String(err);
|
|
1926
2011
|
ctx.ui.notify(`goosedump error: ${message}`, "error");
|
|
2012
|
+
} finally {
|
|
2013
|
+
tui.requestRender();
|
|
1927
2014
|
}
|
|
1928
2015
|
}
|
|
1929
2016
|
return {
|
|
@@ -2019,7 +2106,6 @@ async function runSearchPanel(ctx, query) {
|
|
|
2019
2106
|
if (!entry)
|
|
2020
2107
|
return;
|
|
2021
2108
|
loadDetail(entry.id);
|
|
2022
|
-
tui.requestRender();
|
|
2023
2109
|
return;
|
|
2024
2110
|
}
|
|
2025
2111
|
},
|
|
@@ -2034,6 +2120,21 @@ async function runSearchPanel(ctx, query) {
|
|
|
2034
2120
|
}
|
|
2035
2121
|
});
|
|
2036
2122
|
}
|
|
2123
|
+
function countSessionDescendants(childrenMap, target) {
|
|
2124
|
+
const seen = new Set([target]);
|
|
2125
|
+
const pending = [...childrenMap.get(target) ?? []];
|
|
2126
|
+
while (pending.length > 0) {
|
|
2127
|
+
const session = pending.pop();
|
|
2128
|
+
if (!session)
|
|
2129
|
+
continue;
|
|
2130
|
+
const key = `${session.provider}:${session.id}`;
|
|
2131
|
+
if (seen.has(key))
|
|
2132
|
+
continue;
|
|
2133
|
+
seen.add(key);
|
|
2134
|
+
pending.push(...childrenMap.get(key) ?? []);
|
|
2135
|
+
}
|
|
2136
|
+
return seen.size - 1;
|
|
2137
|
+
}
|
|
2037
2138
|
async function runSessionsPanel(ctx, executablePath) {
|
|
2038
2139
|
const OVERLAY_WIDTH = 84;
|
|
2039
2140
|
const VIEWPORT = 18;
|
|
@@ -2082,6 +2183,7 @@ async function runSessionsPanel(ctx, executablePath) {
|
|
|
2082
2183
|
let error = null;
|
|
2083
2184
|
let selected = 0;
|
|
2084
2185
|
let scroll = 0;
|
|
2186
|
+
let deletionPending = false;
|
|
2085
2187
|
function rebuildDisplayList() {
|
|
2086
2188
|
displayList = flattenTree(roots, childrenMap, expandedNodes, 0);
|
|
2087
2189
|
}
|
|
@@ -2098,7 +2200,7 @@ async function runSessionsPanel(ctx, executablePath) {
|
|
|
2098
2200
|
sessions = cwdSessions;
|
|
2099
2201
|
childrenMap = buildChildrenMap(sessions);
|
|
2100
2202
|
const sessionKeys = new Set(sessions.map((s) => `${s.provider}:${s.id}`));
|
|
2101
|
-
roots = sessions.filter((s) => s.parent === null);
|
|
2203
|
+
roots = sessions.filter((s) => s.parent === null || !sessionKeys.has(`${s.provider}:${s.parent}`));
|
|
2102
2204
|
expandedNodes = new Set([...expandedNodes].filter((key) => sessionKeys.has(key)));
|
|
2103
2205
|
rebuildDisplayList();
|
|
2104
2206
|
if (sessions.length === 0) {
|
|
@@ -2120,6 +2222,8 @@ async function runSessionsPanel(ctx, executablePath) {
|
|
|
2120
2222
|
}
|
|
2121
2223
|
loadSessions();
|
|
2122
2224
|
async function deleteSelected() {
|
|
2225
|
+
if (deletionPending)
|
|
2226
|
+
return;
|
|
2123
2227
|
const row = displayList[selected];
|
|
2124
2228
|
if (!row)
|
|
2125
2229
|
return;
|
|
@@ -2129,13 +2233,21 @@ async function runSessionsPanel(ctx, executablePath) {
|
|
|
2129
2233
|
ctx.ui.notify("Cannot delete the active session.", "error");
|
|
2130
2234
|
return;
|
|
2131
2235
|
}
|
|
2236
|
+
deletionPending = true;
|
|
2132
2237
|
try {
|
|
2238
|
+
const descendants = countSessionDescendants(childrenMap, target);
|
|
2239
|
+
const confirmed = await ctx.ui.confirm("Permanently delete session?", `Permanently remove ${target} and all descendants (${descendants} shown)? This cannot be undone.`);
|
|
2240
|
+
tui.requestRender();
|
|
2241
|
+
if (!confirmed)
|
|
2242
|
+
return;
|
|
2133
2243
|
await goosedumpRemoveSession(target, undefined, executablePath);
|
|
2134
2244
|
ctx.ui.notify(`Deleted session ${s.id}`, "info");
|
|
2135
2245
|
await loadSessions();
|
|
2136
2246
|
} catch (err) {
|
|
2137
2247
|
const message = err instanceof Error ? err.message : String(err);
|
|
2138
2248
|
ctx.ui.notify(`Failed to delete session: ${message}`, "error");
|
|
2249
|
+
} finally {
|
|
2250
|
+
deletionPending = false;
|
|
2139
2251
|
}
|
|
2140
2252
|
}
|
|
2141
2253
|
return {
|
|
@@ -2260,8 +2372,7 @@ async function runSessionsPanel(ctx, executablePath) {
|
|
|
2260
2372
|
function createGoosedumpIntegration(options = {}) {
|
|
2261
2373
|
const shouldRegisterTool = options.registerTool ?? true;
|
|
2262
2374
|
const shouldOverrideDefaultCompaction = options.overrideDefaultCompaction ?? true;
|
|
2263
|
-
const nativeExecutablePath = options.nativeExecutablePath;
|
|
2264
|
-
let goosedumpAvailable = false;
|
|
2375
|
+
const nativeExecutablePath = options.nativeExecutablePath ?? resolveNativeGoosedumpBinary();
|
|
2265
2376
|
const rememberQueue = [];
|
|
2266
2377
|
let rememberRunning = null;
|
|
2267
2378
|
function enqueueRemember(target, reportError) {
|
|
@@ -2297,31 +2408,22 @@ function createGoosedumpIntegration(options = {}) {
|
|
|
2297
2408
|
while (rememberRunning)
|
|
2298
2409
|
await rememberRunning;
|
|
2299
2410
|
}
|
|
2300
|
-
function checkGoosedump() {
|
|
2301
|
-
try {
|
|
2302
|
-
execFileSync(process.execPath, [resolveGoosedumpBinary(), "--version"], { stdio: "ignore" });
|
|
2303
|
-
return true;
|
|
2304
|
-
} catch {
|
|
2305
|
-
return false;
|
|
2306
|
-
}
|
|
2307
|
-
}
|
|
2308
2411
|
const compaction = new CompactionRuntime({
|
|
2309
2412
|
overrideDefaultCompaction: shouldOverrideDefaultCompaction,
|
|
2310
2413
|
nativeExecutablePath,
|
|
2311
|
-
isAvailable: () => goosedumpAvailable,
|
|
2312
2414
|
enqueueRemember
|
|
2313
2415
|
});
|
|
2314
2416
|
function register(pi) {
|
|
2417
|
+
compaction.setActivePi(pi);
|
|
2315
2418
|
if (shouldRegisterTool) {
|
|
2316
2419
|
registerGooseTools(pi, {
|
|
2317
|
-
isAvailable: () => goosedumpAvailable,
|
|
2318
2420
|
nativeExecutablePath,
|
|
2319
2421
|
enqueueRemember,
|
|
2320
2422
|
requestCompaction: (ctx, keep) => compaction.requestCompaction(ctx, keep)
|
|
2321
2423
|
});
|
|
2322
2424
|
}
|
|
2323
2425
|
pi.on("before_agent_start", (event) => {
|
|
2324
|
-
if (!shouldRegisterTool
|
|
2426
|
+
if (!shouldRegisterTool)
|
|
2325
2427
|
return;
|
|
2326
2428
|
return {
|
|
2327
2429
|
systemPrompt: `${event.systemPrompt}
|
|
@@ -2330,10 +2432,6 @@ ${renderToolRoutingPolicy()}`
|
|
|
2330
2432
|
};
|
|
2331
2433
|
});
|
|
2332
2434
|
pi.on("session_start", async (_event, ctx) => {
|
|
2333
|
-
goosedumpAvailable = checkGoosedump();
|
|
2334
|
-
if (!goosedumpAvailable) {
|
|
2335
|
-
ctx.ui.notify("goosedump was not found. Install with: npm install @jarkkojs/goosedump", "error");
|
|
2336
|
-
}
|
|
2337
2435
|
notifyInvalidSettings(ctx);
|
|
2338
2436
|
compaction.beginSession(ctx);
|
|
2339
2437
|
});
|
|
@@ -2363,10 +2461,6 @@ ${renderToolRoutingPolicy()}`
|
|
|
2363
2461
|
maybePi.registerCommand?.(name, {
|
|
2364
2462
|
description,
|
|
2365
2463
|
handler: async (args, ctx) => {
|
|
2366
|
-
if (!goosedumpAvailable) {
|
|
2367
|
-
ctx.ui.notify(GOOSEDUMP_UNAVAILABLE_MESSAGE, "error");
|
|
2368
|
-
return;
|
|
2369
|
-
}
|
|
2370
2464
|
try {
|
|
2371
2465
|
await handler(args, ctx);
|
|
2372
2466
|
} catch (err) {
|
|
@@ -2408,7 +2502,7 @@ ${renderToolRoutingPolicy()}`
|
|
|
2408
2502
|
const query = args.trim() || (await ctx.ui.input("Search query:", ""))?.trim() || "";
|
|
2409
2503
|
if (query.length === 0)
|
|
2410
2504
|
return;
|
|
2411
|
-
await runSearchPanel(ctx, query);
|
|
2505
|
+
await runSearchPanel(ctx, query, nativeExecutablePath);
|
|
2412
2506
|
});
|
|
2413
2507
|
registerGooseCommand("goose-sessions", "List, resume, or delete sessions for the current working directory", async (_args, ctx) => {
|
|
2414
2508
|
await runSessionsPanel(ctx, nativeExecutablePath);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-goosedump",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.41",
|
|
4
4
|
"description": "Pi extension for goosedump session search, durable memory, session management, and compaction",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"compaction",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@earendil-works/pi-tui": "^0.82.1",
|
|
41
|
-
"@jarkkojs/goosedump": "^0.12.
|
|
41
|
+
"@jarkkojs/goosedump": "^0.12.41",
|
|
42
42
|
"@sinclair/typebox": "^0.34.49"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|