@kenkaiiii/ggcoder 5.34.0 → 5.34.2
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/dist/app-sidecar.js +56 -2
- package/dist/app-sidecar.js.map +1 -1
- package/dist/core/compaction/tool-result-pruner.d.ts +6 -0
- package/dist/core/compaction/tool-result-pruner.d.ts.map +1 -1
- package/dist/core/compaction/tool-result-pruner.js +26 -2
- package/dist/core/compaction/tool-result-pruner.js.map +1 -1
- package/dist/core/compaction/tool-result-pruner.test.js +69 -0
- package/dist/core/compaction/tool-result-pruner.test.js.map +1 -1
- package/dist/core/project-discovery.d.ts +23 -6
- package/dist/core/project-discovery.d.ts.map +1 -1
- package/dist/core/project-discovery.js +198 -31
- package/dist/core/project-discovery.js.map +1 -1
- package/dist/core/project-discovery.test.js +124 -0
- package/dist/core/project-discovery.test.js.map +1 -1
- package/dist/modes/acp-mode.test.js +24 -19
- package/dist/modes/acp-mode.test.js.map +1 -1
- package/package.json +4 -4
|
@@ -11,6 +11,10 @@ import type { Message } from "@kenkaiiii/gg-ai";
|
|
|
11
11
|
* 3. Large completed tool arguments — old write/edit payloads are capped once
|
|
12
12
|
* their result has returned; the files and tool result are the durable truth.
|
|
13
13
|
*
|
|
14
|
+
* `PROTECTED_TOOLS` output is never pruned: it is behavioural instruction rather
|
|
15
|
+
* than reproducible data, so a "re-run the tool" stub is not recoverable — the
|
|
16
|
+
* agent has no signal that it ever loaded the skill.
|
|
17
|
+
*
|
|
14
18
|
* Tool batches—not human turns—are the protection boundary. Autonomous research
|
|
15
19
|
* can execute dozens of provider/tool cycles for one user prompt; protecting the
|
|
16
20
|
* whole human turn lets reproducible reads refill the context immediately after
|
|
@@ -24,6 +28,8 @@ import type { Message } from "@kenkaiiii/gg-ai";
|
|
|
24
28
|
export declare const PRUNE_PROTECT_TOKENS = 40000;
|
|
25
29
|
export declare const PRUNE_MINIMUM_TOKENS = 20000;
|
|
26
30
|
export declare const PRUNE_PROTECT_TOOL_BATCHES = 2;
|
|
31
|
+
/** Tools whose output is instruction, not reproducible data — never pruned. */
|
|
32
|
+
export declare const PRUNE_PROTECTED_TOOLS: Set<string>;
|
|
27
33
|
export interface PruneOptions {
|
|
28
34
|
/** Recent tool-output token budget kept verbatim. Default 40k. */
|
|
29
35
|
protectTokens?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-result-pruner.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/tool-result-pruner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,OAAO,EAAc,MAAM,kBAAkB,CAAC;AAIzE
|
|
1
|
+
{"version":3,"file":"tool-result-pruner.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/tool-result-pruner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,OAAO,EAAc,MAAM,kBAAkB,CAAC;AAIzE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAC3C,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAC3C,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C,+EAA+E;AAC/E,eAAO,MAAM,qBAAqB,aAAqB,CAAC;AAWxD,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;CACrB;AAeD;iEACiE;AACjE,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,GAAE,YAAiB,GAAG,WAAW,CA+I/F"}
|
|
@@ -12,6 +12,10 @@ import { estimateTokens } from "./token-estimator.js";
|
|
|
12
12
|
* 3. Large completed tool arguments — old write/edit payloads are capped once
|
|
13
13
|
* their result has returned; the files and tool result are the durable truth.
|
|
14
14
|
*
|
|
15
|
+
* `PROTECTED_TOOLS` output is never pruned: it is behavioural instruction rather
|
|
16
|
+
* than reproducible data, so a "re-run the tool" stub is not recoverable — the
|
|
17
|
+
* agent has no signal that it ever loaded the skill.
|
|
18
|
+
*
|
|
15
19
|
* Tool batches—not human turns—are the protection boundary. Autonomous research
|
|
16
20
|
* can execute dozens of provider/tool cycles for one user prompt; protecting the
|
|
17
21
|
* whole human turn lets reproducible reads refill the context immediately after
|
|
@@ -25,7 +29,16 @@ import { estimateTokens } from "./token-estimator.js";
|
|
|
25
29
|
export const PRUNE_PROTECT_TOKENS = 40_000;
|
|
26
30
|
export const PRUNE_MINIMUM_TOKENS = 20_000;
|
|
27
31
|
export const PRUNE_PROTECT_TOOL_BATCHES = 2;
|
|
32
|
+
/** Tools whose output is instruction, not reproducible data — never pruned. */
|
|
33
|
+
export const PRUNE_PROTECTED_TOOLS = new Set(["skill"]);
|
|
28
34
|
const PRUNE_MARKER = "[Pruned:";
|
|
35
|
+
/**
|
|
36
|
+
* Prefix of the token-overflow stub specifically. Reaching one of these while
|
|
37
|
+
* walking backwards proves the whole older prefix was already considered, which
|
|
38
|
+
* a superseded-read stub does NOT prove — read dedup fires independently of the
|
|
39
|
+
* token budget, so an older verbatim result can sit behind one.
|
|
40
|
+
*/
|
|
41
|
+
const PRUNE_OVERFLOW_MARKER = `${PRUNE_MARKER} old tool output`;
|
|
29
42
|
/** Mutates `messages` in place; message/array identity is preserved so usage
|
|
30
43
|
* anchors and React refs stay valid. Returns what was freed. */
|
|
31
44
|
export function pruneStaleToolResults(messages, opts = {}) {
|
|
@@ -48,7 +61,7 @@ export function pruneStaleToolResults(messages, opts = {}) {
|
|
|
48
61
|
const toolBatchByCallId = new Map();
|
|
49
62
|
let recentToolBatches = 0;
|
|
50
63
|
let recentToolTokens = 0;
|
|
51
|
-
for (let msgIndex = messages.length - 1; msgIndex >= 0; msgIndex--) {
|
|
64
|
+
scan: for (let msgIndex = messages.length - 1; msgIndex >= 0; msgIndex--) {
|
|
52
65
|
const msg = messages[msgIndex];
|
|
53
66
|
if (msg.role !== "tool" || !Array.isArray(msg.content))
|
|
54
67
|
continue;
|
|
@@ -61,9 +74,20 @@ export function pruneStaleToolResults(messages, opts = {}) {
|
|
|
61
74
|
toolBatchByCallId.set(result.toolCallId, recentToolBatches);
|
|
62
75
|
if (typeof result.content !== "string")
|
|
63
76
|
continue;
|
|
64
|
-
|
|
77
|
+
// An overflow stub outside the protect zone means an earlier pass blew
|
|
78
|
+
// the token budget here and pruned every prunable result older than it in
|
|
79
|
+
// that same batch. History only grows at the tail, so nothing older can
|
|
80
|
+
// have become prunable since: stop instead of re-scanning the whole
|
|
81
|
+
// transcript every turn. Other stub kinds prove nothing about what lies
|
|
82
|
+
// behind them, so they are merely skipped.
|
|
83
|
+
if (result.content.startsWith(PRUNE_MARKER)) {
|
|
84
|
+
if (!protectedBatch && result.content.startsWith(PRUNE_OVERFLOW_MARKER))
|
|
85
|
+
break scan;
|
|
65
86
|
continue;
|
|
87
|
+
}
|
|
66
88
|
const info = callInfo.get(result.toolCallId);
|
|
89
|
+
if (info && PRUNE_PROTECTED_TOOLS.has(info.name))
|
|
90
|
+
continue;
|
|
67
91
|
// Dedup key includes the range: a partial read (offset/limit) covers
|
|
68
92
|
// different content than a full read or another range, so only an
|
|
69
93
|
// identical path+range read supersedes an older one.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-result-pruner.js","sourceRoot":"","sources":["../../../src/core/compaction/tool-result-pruner.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD
|
|
1
|
+
{"version":3,"file":"tool-result-pruner.js","sourceRoot":"","sources":["../../../src/core/compaction/tool-result-pruner.ts"],"names":[],"mappings":"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"}
|
|
@@ -209,6 +209,75 @@ describe("pruneStaleToolResults", () => {
|
|
|
209
209
|
expect(second.pruned).toBe(false);
|
|
210
210
|
expect(resultOf(messages, "old").content).toBe(stub);
|
|
211
211
|
});
|
|
212
|
+
it("never prunes skill output, which is instruction rather than reproducible data", () => {
|
|
213
|
+
const messages = [
|
|
214
|
+
{ role: "user", content: "turn 1" },
|
|
215
|
+
...toolTurn("skill-load", "skill", { skill: "evidence-led-ui" }, "s".repeat(120_000)),
|
|
216
|
+
{ role: "user", content: "turn 2" },
|
|
217
|
+
...toolTurn("old-bash", "bash", { command: "ls" }, "o".repeat(120_000)),
|
|
218
|
+
{ role: "user", content: "turn 3" },
|
|
219
|
+
{ role: "user", content: "turn 4" },
|
|
220
|
+
];
|
|
221
|
+
const result = pruneStaleToolResults(messages, {
|
|
222
|
+
protectTokens: 100,
|
|
223
|
+
minimumTokens: 1_000,
|
|
224
|
+
protectToolBatches: 0,
|
|
225
|
+
});
|
|
226
|
+
expect(result.pruned).toBe(true);
|
|
227
|
+
expect(result.prunedResults).toBe(1);
|
|
228
|
+
expect(resultOf(messages, "skill-load").content).toBe("s".repeat(120_000));
|
|
229
|
+
expect(resultOf(messages, "old-bash").content).toContain("old tool output");
|
|
230
|
+
});
|
|
231
|
+
it("stops scanning at the first stub outside the protected batches", () => {
|
|
232
|
+
const messages = [
|
|
233
|
+
{ role: "user", content: "turn 1" },
|
|
234
|
+
...toolTurn("oldest", "bash", { command: "ls" }, "o".repeat(120_000)),
|
|
235
|
+
{ role: "user", content: "turn 2" },
|
|
236
|
+
...toolTurn("middle", "bash", { command: "pwd" }, "m".repeat(120_000)),
|
|
237
|
+
{ role: "user", content: "turn 3" },
|
|
238
|
+
];
|
|
239
|
+
const opts = { protectTokens: 100, minimumTokens: 1_000, protectToolBatches: 0 };
|
|
240
|
+
expect(pruneStaleToolResults(messages, opts).prunedResults).toBe(2);
|
|
241
|
+
// Fresh output arrives; the older half is already stubbed, so the second
|
|
242
|
+
// pass must stop at "middle" rather than re-walking the whole transcript.
|
|
243
|
+
messages.push(...toolTurn("newest", "bash", { command: "env" }, "n".repeat(120_000)));
|
|
244
|
+
const second = pruneStaleToolResults(messages, opts);
|
|
245
|
+
expect(second.pruned).toBe(true);
|
|
246
|
+
expect(second.prunedResults).toBe(1);
|
|
247
|
+
expect(resultOf(messages, "newest").content).toContain("old tool output");
|
|
248
|
+
expect(resultOf(messages, "oldest").content).toContain("old tool output");
|
|
249
|
+
});
|
|
250
|
+
it("does not let a superseded-read stub strand older output behind it", () => {
|
|
251
|
+
// A read dedup stub is written regardless of the token budget, so it can
|
|
252
|
+
// sit in front of results that are still verbatim. Stopping the backwards
|
|
253
|
+
// walk at one would strand them permanently.
|
|
254
|
+
const messages = [
|
|
255
|
+
{ role: "user", content: "turn 1" },
|
|
256
|
+
...toolTurn("old-bash", "bash", { command: "ls" }, "o".repeat(400_000)),
|
|
257
|
+
{ role: "user", content: "turn 2" },
|
|
258
|
+
...toolTurn("read-1", "read", { file_path: "/a.ts" }, "a".repeat(1_000)),
|
|
259
|
+
{ role: "user", content: "turn 3" },
|
|
260
|
+
...toolTurn("read-2", "read", { file_path: "/a.ts" }, "a".repeat(1_000)),
|
|
261
|
+
{ role: "user", content: "turn 4" },
|
|
262
|
+
];
|
|
263
|
+
// A protect budget this large spares the bash output, so only the
|
|
264
|
+
// superseded read is stubbed on the first pass.
|
|
265
|
+
const first = pruneStaleToolResults(messages, {
|
|
266
|
+
protectTokens: 500_000,
|
|
267
|
+
minimumTokens: 100,
|
|
268
|
+
protectToolBatches: 0,
|
|
269
|
+
});
|
|
270
|
+
expect(first.prunedResults).toBe(1);
|
|
271
|
+
expect(resultOf(messages, "old-bash").content).toBe("o".repeat(400_000));
|
|
272
|
+
// Now the budget is tight: the older bash output must still be reachable.
|
|
273
|
+
const second = pruneStaleToolResults(messages, {
|
|
274
|
+
protectTokens: 100,
|
|
275
|
+
minimumTokens: 1_000,
|
|
276
|
+
protectToolBatches: 0,
|
|
277
|
+
});
|
|
278
|
+
expect(second.pruned).toBe(true);
|
|
279
|
+
expect(resultOf(messages, "old-bash").content).toContain("old tool output");
|
|
280
|
+
});
|
|
212
281
|
it("skips structured (non-string) tool results", () => {
|
|
213
282
|
const messages = [
|
|
214
283
|
{ role: "user", content: "turn 1" },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-result-pruner.test.js","sourceRoot":"","sources":["../../../src/core/compaction/tool-result-pruner.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tool-result-pruner.test.js","sourceRoot":"","sources":["../../../src/core/compaction/tool-result-pruner.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
export type ProjectSource = "ggcoder" | "claude-code" | "codex";
|
|
1
|
+
export type ProjectSource = "ggcoder" | "claude-code" | "codex" | "folder";
|
|
2
|
+
export interface DiscoverProjectsOptions {
|
|
3
|
+
/** The user's configured projects folder; always scanned when set. */
|
|
4
|
+
projectsRoot?: string;
|
|
5
|
+
/**
|
|
6
|
+
* Extra folders the user has explicitly added as project roots. Scanned like
|
|
7
|
+
* `projectsRoot`; an explicit list beats inference, which stays as the
|
|
8
|
+
* zero-config default for people who never open Settings.
|
|
9
|
+
*/
|
|
10
|
+
extraRoots?: readonly string[];
|
|
11
|
+
/** Project paths the user dismissed from the picker. */
|
|
12
|
+
hiddenPaths?: readonly string[];
|
|
13
|
+
}
|
|
2
14
|
export interface DiscoveredProject {
|
|
3
15
|
name: string;
|
|
4
16
|
path: string;
|
|
@@ -8,12 +20,17 @@ export interface DiscoveredProject {
|
|
|
8
20
|
sources: ProjectSource[];
|
|
9
21
|
}
|
|
10
22
|
/**
|
|
11
|
-
* Scan ggcoder + Claude Code + Codex session stores
|
|
12
|
-
*
|
|
13
|
-
* `sources` field lists every store the project
|
|
14
|
-
* show a combined badge.
|
|
23
|
+
* Scan ggcoder + Claude Code + Codex session stores AND the user's project
|
|
24
|
+
* folders, returning one row per project sorted most-recent first. Duplicates
|
|
25
|
+
* (same cwd) are collapsed; the `sources` field lists every store the project
|
|
26
|
+
* appeared in so the picker can show a combined badge.
|
|
27
|
+
*
|
|
28
|
+
* Session stores alone only ever surface projects you have *already opened with
|
|
29
|
+
* an agent*, so a folder full of real projects stayed invisible until each one
|
|
30
|
+
* had been opened by some other route. The filesystem pass fixes that: it lists
|
|
31
|
+
* the direct children of every known project root, tagged `folder`.
|
|
15
32
|
*/
|
|
16
|
-
export declare function discoverProjects(): Promise<DiscoveredProject[]>;
|
|
33
|
+
export declare function discoverProjects(options?: DiscoverProjectsOptions): Promise<DiscoveredProject[]>;
|
|
17
34
|
/**
|
|
18
35
|
* Is `value` an absolute path on ANY platform?
|
|
19
36
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-discovery.d.ts","sourceRoot":"","sources":["../../src/core/project-discovery.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,aAAa,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"project-discovery.d.ts","sourceRoot":"","sources":["../../src/core/project-discovery.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,aAAa,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE3E,MAAM,WAAW,uBAAuB;IACtC,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,wDAAwD;IACxD,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gEAAgE;IAChE,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,iBAAiB,EAAE,CAAC,CA8C9B;AAqFD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEpD;AA8dD,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,KAAK,SAAI,EACT,WAAW,SAA4B,GACtC,OAAO,CAAC,aAAa,EAAE,CAAC,CAkB1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,KAAK,SAAI,EACT,OAAO,SAAe,GACrB,OAAO,CAAC,aAAa,EAAE,CAAC,CAS1B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
|
-
import { createReadStream } from "node:fs";
|
|
2
|
+
import { createReadStream, realpathSync } from "node:fs";
|
|
3
3
|
import readline from "node:readline";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
@@ -9,33 +9,50 @@ import { getUserSessionPrompt } from "./session-preview.js";
|
|
|
9
9
|
import { isSessionPath, openSessionReadStream, resolveSessionPath } from "./session-storage.js";
|
|
10
10
|
import { parseForeignTranscript } from "./foreign-session-import.js";
|
|
11
11
|
/**
|
|
12
|
-
* Scan ggcoder + Claude Code + Codex session stores
|
|
13
|
-
*
|
|
14
|
-
* `sources` field lists every store the project
|
|
15
|
-
* show a combined badge.
|
|
12
|
+
* Scan ggcoder + Claude Code + Codex session stores AND the user's project
|
|
13
|
+
* folders, returning one row per project sorted most-recent first. Duplicates
|
|
14
|
+
* (same cwd) are collapsed; the `sources` field lists every store the project
|
|
15
|
+
* appeared in so the picker can show a combined badge.
|
|
16
|
+
*
|
|
17
|
+
* Session stores alone only ever surface projects you have *already opened with
|
|
18
|
+
* an agent*, so a folder full of real projects stayed invisible until each one
|
|
19
|
+
* had been opened by some other route. The filesystem pass fixes that: it lists
|
|
20
|
+
* the direct children of every known project root, tagged `folder`.
|
|
16
21
|
*/
|
|
17
|
-
export async function discoverProjects() {
|
|
22
|
+
export async function discoverProjects(options = {}) {
|
|
18
23
|
const [gg, cc, cx] = await Promise.all([
|
|
19
24
|
discoverGgcoderProjects(),
|
|
20
25
|
discoverClaudeProjects(),
|
|
21
26
|
discoverCodexProjects(),
|
|
22
27
|
]);
|
|
28
|
+
const fromSessions = [...gg, ...cc, ...cx];
|
|
29
|
+
const folders = await discoverFolderProjects(resolveProjectRoots(options.projectsRoot, options.extraRoots, fromSessions));
|
|
23
30
|
const byPath = new Map();
|
|
24
|
-
for (const p of [...
|
|
31
|
+
for (const p of [...fromSessions, ...folders]) {
|
|
25
32
|
const existing = byPath.get(p.path);
|
|
26
33
|
if (!existing) {
|
|
27
34
|
byPath.set(p.path, p);
|
|
28
35
|
continue;
|
|
29
36
|
}
|
|
37
|
+
// A folder's mtime is not activity: a checkout or a build touching the
|
|
38
|
+
// directory must not reorder a project above one you actually worked in.
|
|
39
|
+
// Session recency wins whenever any session store knows this project.
|
|
40
|
+
const merged = mergeSources(existing.sources, p.sources);
|
|
41
|
+
const sessionOnly = [existing, p].filter((row) => !isFolderOnly(row.sources));
|
|
30
42
|
byPath.set(p.path, {
|
|
31
43
|
name: existing.name,
|
|
32
44
|
path: existing.path,
|
|
33
|
-
lastActiveMs: Math.max(existing
|
|
45
|
+
lastActiveMs: Math.max(...(sessionOnly.length > 0 ? sessionOnly : [existing, p]).map((r) => r.lastActiveMs)),
|
|
34
46
|
lastActiveDisplay: "", // recomputed below
|
|
35
|
-
sources:
|
|
47
|
+
sources: merged,
|
|
36
48
|
});
|
|
37
49
|
}
|
|
38
|
-
|
|
50
|
+
// Hiding is by resolved path so a row dismissed once stays gone regardless of
|
|
51
|
+
// which store re-surfaces it later.
|
|
52
|
+
const hidden = new Set((options.hiddenPaths ?? []).map((p) => path.resolve(p)));
|
|
53
|
+
const merged = Array.from(byPath.values())
|
|
54
|
+
.filter((p) => !hidden.has(p.path))
|
|
55
|
+
.map((p) => ({
|
|
39
56
|
...p,
|
|
40
57
|
lastActiveDisplay: formatRelativeTime(p.lastActiveMs),
|
|
41
58
|
}));
|
|
@@ -46,7 +63,11 @@ const SOURCE_ORDER = {
|
|
|
46
63
|
ggcoder: 0,
|
|
47
64
|
"claude-code": 1,
|
|
48
65
|
codex: 2,
|
|
66
|
+
folder: 3,
|
|
49
67
|
};
|
|
68
|
+
function isFolderOnly(sources) {
|
|
69
|
+
return sources.length === 1 && sources[0] === "folder";
|
|
70
|
+
}
|
|
50
71
|
function mergeSources(a, b) {
|
|
51
72
|
const set = new Set([...a, ...b]);
|
|
52
73
|
return Array.from(set).sort((x, y) => SOURCE_ORDER[x] - SOURCE_ORDER[y]);
|
|
@@ -69,15 +90,17 @@ async function discoverGgcoderProjects() {
|
|
|
69
90
|
catch {
|
|
70
91
|
return [];
|
|
71
92
|
}
|
|
72
|
-
|
|
73
|
-
|
|
93
|
+
// Per-entry work is independent I/O (readdir + stat + a header read), so it
|
|
94
|
+
// runs concurrently; sequentially this dominated picker load time once a user
|
|
95
|
+
// had dozens of session stores.
|
|
96
|
+
const results = await mapConcurrent(entries, async (entry) => {
|
|
74
97
|
const dir = path.join(sessionsDir, entry);
|
|
75
98
|
const mtime = await maxGgcoderSessionMtime(dir);
|
|
76
99
|
if (mtime === null)
|
|
77
|
-
|
|
100
|
+
return null;
|
|
78
101
|
const rawCwd = (await readFirstFromGgcoderDir(dir, ggcoderCwdExtractor)) ?? fallbackUnderscoreDecode(entry);
|
|
79
102
|
if (!rawCwd)
|
|
80
|
-
|
|
103
|
+
return null;
|
|
81
104
|
// Normalize traversal segments (e.g. an agent launched with cwd
|
|
82
105
|
// `.../src-tauri/../..`) so the basename isn't a stray "..", and drop any
|
|
83
106
|
// Windows extended-length prefix so a session recorded as `\\?\C:\proj`
|
|
@@ -85,16 +108,33 @@ async function discoverGgcoderProjects() {
|
|
|
85
108
|
// project as a plain `C:\proj` instead of listing a prefixed duplicate.
|
|
86
109
|
const cwd = path.resolve(stripExtendedLengthPrefix(rawCwd));
|
|
87
110
|
if (!(await isDirectory(cwd)))
|
|
88
|
-
|
|
89
|
-
|
|
111
|
+
return null;
|
|
112
|
+
return {
|
|
90
113
|
name: path.basename(cwd),
|
|
91
114
|
path: cwd,
|
|
92
115
|
lastActiveMs: mtime,
|
|
93
116
|
lastActiveDisplay: formatRelativeTime(mtime),
|
|
94
117
|
sources: ["ggcoder"],
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return results;
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
return results.filter((p) => p !== null);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Bounded-concurrency `Promise.all`. Discovery fans out over hundreds of
|
|
124
|
+
* session files; an unbounded `Promise.all` exhausts the file-descriptor limit
|
|
125
|
+
* on a large store, while running sequentially is needlessly slow.
|
|
126
|
+
*/
|
|
127
|
+
const IO_CONCURRENCY = 32;
|
|
128
|
+
async function mapConcurrent(items, fn) {
|
|
129
|
+
const out = new Array(items.length);
|
|
130
|
+
let next = 0;
|
|
131
|
+
const workers = Array.from({ length: Math.min(IO_CONCURRENCY, items.length) }, async () => {
|
|
132
|
+
for (let i = next++; i < items.length; i = next++) {
|
|
133
|
+
out[i] = await fn(items[i]);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
await Promise.all(workers);
|
|
137
|
+
return out;
|
|
98
138
|
}
|
|
99
139
|
/**
|
|
100
140
|
* Is `value` an absolute path on ANY platform?
|
|
@@ -144,7 +184,7 @@ async function discoverClaudeProjects() {
|
|
|
144
184
|
catch {
|
|
145
185
|
return [];
|
|
146
186
|
}
|
|
147
|
-
const results = await
|
|
187
|
+
const results = await mapConcurrent(entries, async (entry) => {
|
|
148
188
|
const dir = path.join(projectsDir, entry);
|
|
149
189
|
const mtime = await maxJsonlMtime(dir);
|
|
150
190
|
if (mtime === null)
|
|
@@ -161,7 +201,7 @@ async function discoverClaudeProjects() {
|
|
|
161
201
|
lastActiveDisplay: formatRelativeTime(mtime),
|
|
162
202
|
sources: ["claude-code"],
|
|
163
203
|
};
|
|
164
|
-
})
|
|
204
|
+
});
|
|
165
205
|
return results.filter((p) => p !== null);
|
|
166
206
|
}
|
|
167
207
|
/**
|
|
@@ -180,28 +220,155 @@ async function discoverCodexProjects() {
|
|
|
180
220
|
return [];
|
|
181
221
|
// Process newest first so per-cwd we always start with the latest mtime.
|
|
182
222
|
files.sort((a, b) => b.mtime - a.mtime);
|
|
223
|
+
const cwds = await mapConcurrent(files, (f) => readFirstFromFile(f.path, codexCwdExtractor));
|
|
183
224
|
const byCwd = new Map();
|
|
184
|
-
|
|
185
|
-
const cwd =
|
|
225
|
+
files.forEach((f, i) => {
|
|
226
|
+
const cwd = cwds[i];
|
|
186
227
|
if (!cwd)
|
|
187
|
-
|
|
228
|
+
return;
|
|
188
229
|
const prev = byCwd.get(cwd);
|
|
189
230
|
if (prev === undefined || f.mtime > prev)
|
|
190
231
|
byCwd.set(cwd, f.mtime);
|
|
191
|
-
}
|
|
192
|
-
const results = []
|
|
193
|
-
for (const [cwd, mtime] of byCwd) {
|
|
232
|
+
});
|
|
233
|
+
const results = await mapConcurrent(Array.from(byCwd), async ([cwd, mtime]) => {
|
|
194
234
|
if (!(await isDirectory(cwd)))
|
|
195
|
-
|
|
196
|
-
|
|
235
|
+
return null;
|
|
236
|
+
return {
|
|
197
237
|
name: path.basename(cwd),
|
|
198
238
|
path: cwd,
|
|
199
239
|
lastActiveMs: mtime,
|
|
200
240
|
lastActiveDisplay: formatRelativeTime(mtime),
|
|
201
241
|
sources: ["codex"],
|
|
202
|
-
}
|
|
242
|
+
};
|
|
243
|
+
});
|
|
244
|
+
return results.filter((p) => p !== null);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* How many already-known projects must share a parent directory before that
|
|
248
|
+
* parent is treated as a project root in its own right. Users keep more than
|
|
249
|
+
* one "projects folder" (the configured root plus wherever the rest actually
|
|
250
|
+
* live), but only one is configurable — so a directory that has repeatedly
|
|
251
|
+
* acted like a root is inferred from evidence rather than guessed.
|
|
252
|
+
*/
|
|
253
|
+
const INFERRED_ROOT_MIN_PROJECTS = 3;
|
|
254
|
+
/** Directory names that are never a project of their own. */
|
|
255
|
+
const FOLDER_SCAN_IGNORED = new Set([
|
|
256
|
+
"node_modules",
|
|
257
|
+
"dist",
|
|
258
|
+
"build",
|
|
259
|
+
"out",
|
|
260
|
+
"target",
|
|
261
|
+
"vendor",
|
|
262
|
+
"coverage",
|
|
263
|
+
"tmp",
|
|
264
|
+
"temp",
|
|
265
|
+
"Library",
|
|
266
|
+
"Applications",
|
|
267
|
+
]);
|
|
268
|
+
/**
|
|
269
|
+
* Which directories should be scanned for project folders: the configured root,
|
|
270
|
+
* plus any parent that already holds several known projects.
|
|
271
|
+
*
|
|
272
|
+
* Scanning the home directory or a filesystem/temp root would list mail, music
|
|
273
|
+
* and scratch dirs as "projects", so those are never roots no matter how many
|
|
274
|
+
* sessions point inside them.
|
|
275
|
+
*/
|
|
276
|
+
function resolveProjectRoots(projectsRoot, extraRoots, discovered) {
|
|
277
|
+
const roots = new Set();
|
|
278
|
+
const configured = projectsRoot?.trim();
|
|
279
|
+
if (configured)
|
|
280
|
+
roots.add(path.resolve(configured));
|
|
281
|
+
for (const extra of extraRoots ?? []) {
|
|
282
|
+
const trimmed = extra.trim();
|
|
283
|
+
if (trimmed)
|
|
284
|
+
roots.add(path.resolve(trimmed));
|
|
285
|
+
}
|
|
286
|
+
const counts = new Map();
|
|
287
|
+
const seen = new Set();
|
|
288
|
+
for (const project of discovered) {
|
|
289
|
+
if (seen.has(project.path))
|
|
290
|
+
continue;
|
|
291
|
+
seen.add(project.path);
|
|
292
|
+
const parent = path.dirname(project.path);
|
|
293
|
+
if (parent === project.path)
|
|
294
|
+
continue;
|
|
295
|
+
counts.set(parent, (counts.get(parent) ?? 0) + 1);
|
|
296
|
+
}
|
|
297
|
+
for (const [parent, count] of counts) {
|
|
298
|
+
if (count >= INFERRED_ROOT_MIN_PROJECTS && !isUnscannableRoot(parent))
|
|
299
|
+
roots.add(parent);
|
|
300
|
+
}
|
|
301
|
+
return Array.from(roots);
|
|
302
|
+
}
|
|
303
|
+
function isUnscannableRoot(dir) {
|
|
304
|
+
const resolved = resolveExistingPath(dir);
|
|
305
|
+
if (resolved === resolveExistingPath(path.parse(resolved).root))
|
|
306
|
+
return true;
|
|
307
|
+
if (resolved === resolveExistingPath(os.homedir()))
|
|
308
|
+
return true;
|
|
309
|
+
// Scratch checkouts and test fixtures cluster as direct children of the temp
|
|
310
|
+
// dir, which would otherwise infer it as a root and list every stale
|
|
311
|
+
// `tmp.XXXX` as a project. Resolve symlinks before comparing because macOS
|
|
312
|
+
// reports the same temp directory through both `/var` and `/private/var`.
|
|
313
|
+
// Only the temp dir itself is barred — a real projects folder below it is
|
|
314
|
+
// still scannable.
|
|
315
|
+
return resolved === resolveExistingPath(os.tmpdir());
|
|
316
|
+
}
|
|
317
|
+
function resolveExistingPath(dir) {
|
|
318
|
+
const resolved = path.resolve(dir);
|
|
319
|
+
try {
|
|
320
|
+
return realpathSync(resolved);
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
return resolved;
|
|
203
324
|
}
|
|
204
|
-
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* List the direct children of each project root as projects. Directory mtime
|
|
328
|
+
* stands in for "last active" — imprecise, but these rows are session-less by
|
|
329
|
+
* definition and merging keeps real session recency where it exists.
|
|
330
|
+
*/
|
|
331
|
+
async function discoverFolderProjects(roots) {
|
|
332
|
+
const candidates = [];
|
|
333
|
+
for (const root of roots) {
|
|
334
|
+
let entries;
|
|
335
|
+
try {
|
|
336
|
+
entries = await fs.readdir(root, { withFileTypes: true });
|
|
337
|
+
}
|
|
338
|
+
catch {
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
for (const entry of entries) {
|
|
342
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink())
|
|
343
|
+
continue;
|
|
344
|
+
if (entry.name.startsWith("."))
|
|
345
|
+
continue;
|
|
346
|
+
if (FOLDER_SCAN_IGNORED.has(entry.name))
|
|
347
|
+
continue;
|
|
348
|
+
candidates.push({ name: entry.name, path: path.join(root, entry.name) });
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
// `stat` (not `lstat`) so a symlinked project folder resolves to its target:
|
|
352
|
+
// `readdir` reports a symlink as neither file nor directory, so checking the
|
|
353
|
+
// dirent alone would silently drop linked-in projects.
|
|
354
|
+
const rows = await mapConcurrent(candidates, async (c) => {
|
|
355
|
+
try {
|
|
356
|
+
const stats = await fs.stat(c.path);
|
|
357
|
+
if (!stats.isDirectory())
|
|
358
|
+
return null;
|
|
359
|
+
return {
|
|
360
|
+
name: c.name,
|
|
361
|
+
path: c.path,
|
|
362
|
+
lastActiveMs: stats.mtimeMs,
|
|
363
|
+
lastActiveDisplay: formatRelativeTime(stats.mtimeMs),
|
|
364
|
+
sources: ["folder"],
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
catch {
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
return rows.filter((r) => r !== null);
|
|
205
372
|
}
|
|
206
373
|
async function isDirectory(p) {
|
|
207
374
|
try {
|