@kenkaiiii/ggcoder 5.27.0 → 5.29.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/dist/app-sidecar-auth-broadcast.test.d.ts +2 -0
- package/dist/app-sidecar-auth-broadcast.test.d.ts.map +1 -0
- package/dist/app-sidecar-auth-broadcast.test.js +271 -0
- package/dist/app-sidecar-auth-broadcast.test.js.map +1 -0
- package/dist/app-sidecar-sessions.d.ts +7 -2
- package/dist/app-sidecar-sessions.d.ts.map +1 -1
- package/dist/app-sidecar-sessions.js +36 -8
- package/dist/app-sidecar-sessions.js.map +1 -1
- package/dist/app-sidecar-sessions.test.js +95 -0
- package/dist/app-sidecar-sessions.test.js.map +1 -1
- package/dist/app-sidecar.js +151 -10
- package/dist/app-sidecar.js.map +1 -1
- package/dist/core/agent-session-checkpoint-flush.test.d.ts +2 -0
- package/dist/core/agent-session-checkpoint-flush.test.d.ts.map +1 -0
- package/dist/core/agent-session-checkpoint-flush.test.js +201 -0
- package/dist/core/agent-session-checkpoint-flush.test.js.map +1 -0
- package/dist/core/agent-session-crash-durability.test.d.ts +2 -0
- package/dist/core/agent-session-crash-durability.test.d.ts.map +1 -0
- package/dist/core/agent-session-crash-durability.test.js +95 -0
- package/dist/core/agent-session-crash-durability.test.js.map +1 -0
- package/dist/core/agent-session.d.ts +51 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +114 -12
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/event-bus.d.ts +4 -0
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js +3 -0
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/lsp/client.d.ts +15 -0
- package/dist/core/lsp/client.d.ts.map +1 -1
- package/dist/core/lsp/client.js +39 -1
- package/dist/core/lsp/client.js.map +1 -1
- package/dist/core/lsp/manager.d.ts +3 -0
- package/dist/core/lsp/manager.d.ts.map +1 -1
- package/dist/core/lsp/manager.js +33 -1
- package/dist/core/lsp/manager.js.map +1 -1
- package/dist/core/lsp/manager.test.js +18 -0
- package/dist/core/lsp/manager.test.js.map +1 -1
- package/dist/core/mcp/client-session-recovery.test.d.ts +2 -0
- package/dist/core/mcp/client-session-recovery.test.d.ts.map +1 -0
- package/dist/core/mcp/client-session-recovery.test.js +231 -0
- package/dist/core/mcp/client-session-recovery.test.js.map +1 -0
- package/dist/core/mcp/client.d.ts +57 -0
- package/dist/core/mcp/client.d.ts.map +1 -1
- package/dist/core/mcp/client.js +146 -8
- package/dist/core/mcp/client.js.map +1 -1
- package/dist/core/mcp/elicitation-bridge.d.ts +41 -0
- package/dist/core/mcp/elicitation-bridge.d.ts.map +1 -0
- package/dist/core/mcp/elicitation-bridge.js +52 -0
- package/dist/core/mcp/elicitation-bridge.js.map +1 -0
- package/dist/core/mcp/elicitation.test.d.ts +2 -0
- package/dist/core/mcp/elicitation.test.d.ts.map +1 -0
- package/dist/core/mcp/elicitation.test.js +158 -0
- package/dist/core/mcp/elicitation.test.js.map +1 -0
- package/dist/core/mcp/index.d.ts +3 -1
- package/dist/core/mcp/index.d.ts.map +1 -1
- package/dist/core/mcp/index.js +1 -0
- package/dist/core/mcp/index.js.map +1 -1
- package/dist/core/process-manager-notifications.test.js +102 -0
- package/dist/core/process-manager-notifications.test.js.map +1 -1
- package/dist/core/process-manager.d.ts +14 -4
- package/dist/core/process-manager.d.ts.map +1 -1
- package/dist/core/process-manager.js +83 -21
- package/dist/core/process-manager.js.map +1 -1
- package/dist/core/project-discovery.d.ts +19 -0
- package/dist/core/project-discovery.d.ts.map +1 -1
- package/dist/core/project-discovery.js +100 -0
- package/dist/core/project-discovery.js.map +1 -1
- package/dist/core/run-journal.test.d.ts +2 -0
- package/dist/core/run-journal.test.d.ts.map +1 -0
- package/dist/core/run-journal.test.js +195 -0
- package/dist/core/run-journal.test.js.map +1 -0
- package/dist/core/run-lifecycle.d.ts +22 -3
- package/dist/core/run-lifecycle.d.ts.map +1 -1
- package/dist/core/run-lifecycle.js +12 -3
- package/dist/core/run-lifecycle.js.map +1 -1
- package/dist/core/session-export.d.ts.map +1 -1
- package/dist/core/session-export.js +5 -0
- package/dist/core/session-export.js.map +1 -1
- package/dist/core/session-history.d.ts +10 -0
- package/dist/core/session-history.d.ts.map +1 -1
- package/dist/core/session-history.js +17 -2
- package/dist/core/session-history.js.map +1 -1
- package/dist/core/session-history.test.js +26 -1
- package/dist/core/session-history.test.js.map +1 -1
- package/dist/core/session-manager.d.ts +63 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +94 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-notification-visibility.test.d.ts +2 -0
- package/dist/core/session-notification-visibility.test.d.ts.map +1 -0
- package/dist/core/session-notification-visibility.test.js +79 -0
- package/dist/core/session-notification-visibility.test.js.map +1 -0
- package/dist/core/session-preview.d.ts +4 -2
- package/dist/core/session-preview.d.ts.map +1 -1
- package/dist/core/session-preview.js +8 -3
- package/dist/core/session-preview.js.map +1 -1
- package/dist/core/session-storage.test.js +6 -1
- package/dist/core/session-storage.test.js.map +1 -1
- package/dist/core/settings-manager.d.ts +2 -2
- package/dist/core/slash-commands.d.ts +0 -2
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +0 -17
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/slash-commands.test.js +0 -1
- package/dist/core/slash-commands.test.js.map +1 -1
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +17 -3
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/subagent.test.js +12 -0
- package/dist/tools/subagent.test.js.map +1 -1
- package/dist/utils/image.d.ts +26 -3
- package/dist/utils/image.d.ts.map +1 -1
- package/dist/utils/image.js +83 -14
- package/dist/utils/image.js.map +1 -1
- package/dist/utils/image.test.d.ts +2 -0
- package/dist/utils/image.test.d.ts.map +1 -0
- package/dist/utils/image.test.js +139 -0
- package/dist/utils/image.test.js.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-sidecar-auth-broadcast.test.d.ts","sourceRoot":"","sources":["../src/app-sidecar-auth-broadcast.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import http from "node:http";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
8
|
+
/**
|
|
9
|
+
* Boots the REAL app sidecar daemon and drives it over HTTP, because the bug
|
|
10
|
+
* being covered is cross-session: connecting a provider in one window has to
|
|
11
|
+
* refresh the model picker in every window. A per-session unit test cannot see
|
|
12
|
+
* that — the whole failure lives in which SSE streams receive the frame.
|
|
13
|
+
*/
|
|
14
|
+
const SIDECAR = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "dist", "app-sidecar.js");
|
|
15
|
+
let tmpHome;
|
|
16
|
+
let tmpProject;
|
|
17
|
+
let daemon;
|
|
18
|
+
let port = 0;
|
|
19
|
+
const openStreams = [];
|
|
20
|
+
/** Start the daemon on an ephemeral port and wait for its listening handshake. */
|
|
21
|
+
async function startDaemon() {
|
|
22
|
+
daemon = spawn(process.execPath, [SIDECAR], {
|
|
23
|
+
cwd: tmpProject,
|
|
24
|
+
env: {
|
|
25
|
+
...process.env,
|
|
26
|
+
HOME: tmpHome,
|
|
27
|
+
USERPROFILE: tmpHome,
|
|
28
|
+
GG_APP_CWD: tmpProject,
|
|
29
|
+
GG_APP_PORT: "0",
|
|
30
|
+
},
|
|
31
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
32
|
+
});
|
|
33
|
+
port = await new Promise((resolve, reject) => {
|
|
34
|
+
let out = "";
|
|
35
|
+
const timer = setTimeout(() => reject(new Error(`daemon never listened: ${out}`)), 60_000);
|
|
36
|
+
daemon.stdout.on("data", (chunk) => {
|
|
37
|
+
out += chunk;
|
|
38
|
+
const match = /GG_APP_LISTENING (\d+)/.exec(out);
|
|
39
|
+
if (match) {
|
|
40
|
+
clearTimeout(timer);
|
|
41
|
+
resolve(Number(match[1]));
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
daemon.on("error", reject);
|
|
45
|
+
daemon.on("exit", (code) => reject(new Error(`daemon exited (${code}): ${out}`)));
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function request(method, urlPath, opts = {}) {
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
const payload = opts.body === undefined ? undefined : JSON.stringify(opts.body);
|
|
51
|
+
const req = http.request({
|
|
52
|
+
host: "127.0.0.1",
|
|
53
|
+
port,
|
|
54
|
+
path: urlPath,
|
|
55
|
+
method,
|
|
56
|
+
headers: {
|
|
57
|
+
...(payload ? { "content-type": "application/json" } : {}),
|
|
58
|
+
...(opts.session ? { "x-gg-session": opts.session } : {}),
|
|
59
|
+
},
|
|
60
|
+
}, (res) => {
|
|
61
|
+
let raw = "";
|
|
62
|
+
res.on("data", (c) => {
|
|
63
|
+
raw += c;
|
|
64
|
+
});
|
|
65
|
+
res.on("end", () => {
|
|
66
|
+
try {
|
|
67
|
+
resolve({ status: res.statusCode ?? 0, json: raw ? JSON.parse(raw) : {} });
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
resolve({ status: res.statusCode ?? 0, json: {} });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
req.on("error", reject);
|
|
75
|
+
if (payload)
|
|
76
|
+
req.write(payload);
|
|
77
|
+
req.end();
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/** Open a window's SSE stream and collect the event types it receives. */
|
|
81
|
+
function openEventStream(session) {
|
|
82
|
+
return new Promise((resolve, reject) => {
|
|
83
|
+
const types = [];
|
|
84
|
+
const req = http.request({ host: "127.0.0.1", port, path: `/events?session=${session}`, method: "GET" }, (res) => {
|
|
85
|
+
openStreams.push(res);
|
|
86
|
+
let buf = "";
|
|
87
|
+
res.on("data", (chunk) => {
|
|
88
|
+
buf += chunk;
|
|
89
|
+
let split = buf.indexOf("\n\n");
|
|
90
|
+
while (split !== -1) {
|
|
91
|
+
const frame = buf.slice(0, split);
|
|
92
|
+
buf = buf.slice(split + 2);
|
|
93
|
+
for (const line of frame.split("\n")) {
|
|
94
|
+
if (!line.startsWith("data: "))
|
|
95
|
+
continue;
|
|
96
|
+
try {
|
|
97
|
+
types.push(JSON.parse(line.slice(6)).type);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// Non-JSON keepalives are not events.
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
split = buf.indexOf("\n\n");
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
resolve({ types });
|
|
107
|
+
});
|
|
108
|
+
req.on("error", reject);
|
|
109
|
+
req.end();
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
async function createSession() {
|
|
113
|
+
const res = await request("POST", "/session", {
|
|
114
|
+
body: { mode: "code", cwd: tmpProject },
|
|
115
|
+
});
|
|
116
|
+
expect(res.status).toBe(200);
|
|
117
|
+
return res.json.sessionId;
|
|
118
|
+
}
|
|
119
|
+
async function waitFor(predicate, timeoutMs = 15_000) {
|
|
120
|
+
const deadline = Date.now() + timeoutMs;
|
|
121
|
+
while (!predicate()) {
|
|
122
|
+
if (Date.now() > deadline)
|
|
123
|
+
throw new Error("timed out waiting for condition");
|
|
124
|
+
await new Promise((r) => setTimeout(r, 25));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
beforeEach(async () => {
|
|
128
|
+
tmpHome = await fs.mkdtemp(path.join(os.tmpdir(), "gg-models-home-"));
|
|
129
|
+
tmpProject = await fs.mkdtemp(path.join(os.tmpdir(), "gg-models-project-"));
|
|
130
|
+
await fs.mkdir(path.join(tmpHome, ".gg"), { recursive: true });
|
|
131
|
+
// No auth.json: the daemon is boot-tolerant when logged out, which is exactly
|
|
132
|
+
// the state a user is in right before they connect their first provider.
|
|
133
|
+
await fs.writeFile(path.join(tmpHome, ".gg", "settings.json"), JSON.stringify({ autoCompact: false }));
|
|
134
|
+
await startDaemon();
|
|
135
|
+
});
|
|
136
|
+
afterEach(async () => {
|
|
137
|
+
for (const stream of openStreams.splice(0))
|
|
138
|
+
stream.destroy();
|
|
139
|
+
daemon?.kill("SIGKILL");
|
|
140
|
+
daemon = undefined;
|
|
141
|
+
await fs.rm(tmpHome, { recursive: true, force: true });
|
|
142
|
+
await fs.rm(tmpProject, { recursive: true, force: true });
|
|
143
|
+
});
|
|
144
|
+
describe("connecting a provider", () => {
|
|
145
|
+
it("refreshes models in every window, not just the one that connected", async () => {
|
|
146
|
+
const windowA = await createSession();
|
|
147
|
+
const windowB = await createSession();
|
|
148
|
+
const streamA = await openEventStream(windowA);
|
|
149
|
+
const streamB = await openEventStream(windowB);
|
|
150
|
+
// Logged out: no provider's models are offered yet.
|
|
151
|
+
const before = await request("GET", "/models", { session: windowA });
|
|
152
|
+
expect(before.json.models).toEqual([]);
|
|
153
|
+
// Connect a provider from window A only.
|
|
154
|
+
const connect = await request("POST", "/auth/apikey", {
|
|
155
|
+
session: windowA,
|
|
156
|
+
body: { provider: "xai", key: "sk-test-key" },
|
|
157
|
+
});
|
|
158
|
+
expect(connect.status).toBe(200);
|
|
159
|
+
// Both windows must be told, because ~/.gg/auth.json is shared. Without the
|
|
160
|
+
// fan-out, window B's picker stayed stale until the session was reopened.
|
|
161
|
+
await waitFor(() => streamA.types.includes("models_change"));
|
|
162
|
+
await waitFor(() => streamB.types.includes("models_change"));
|
|
163
|
+
// And the refetch each window now performs actually returns the new models.
|
|
164
|
+
const after = await request("GET", "/models", { session: windowB });
|
|
165
|
+
const models = after.json.models;
|
|
166
|
+
expect(models.length).toBeGreaterThan(0);
|
|
167
|
+
expect(models.every((m) => m.provider === "xai")).toBe(true);
|
|
168
|
+
}, 90_000);
|
|
169
|
+
it("closes the login modal in every window via auth_done", async () => {
|
|
170
|
+
const windowA = await createSession();
|
|
171
|
+
const windowB = await createSession();
|
|
172
|
+
const streamA = await openEventStream(windowA);
|
|
173
|
+
const streamB = await openEventStream(windowB);
|
|
174
|
+
await request("POST", "/auth/apikey", {
|
|
175
|
+
session: windowA,
|
|
176
|
+
body: { provider: "xai", key: "sk-test-key" },
|
|
177
|
+
});
|
|
178
|
+
// auth_done closes the modal; auth_change refreshes the connection dots.
|
|
179
|
+
// A second window sitting on the login screen needs both.
|
|
180
|
+
await waitFor(() => streamA.types.includes("auth_done"));
|
|
181
|
+
await waitFor(() => streamB.types.includes("auth_done"));
|
|
182
|
+
await waitFor(() => streamA.types.includes("auth_change"));
|
|
183
|
+
await waitFor(() => streamB.types.includes("auth_change"));
|
|
184
|
+
}, 90_000);
|
|
185
|
+
});
|
|
186
|
+
describe("OAuth login across windows", () => {
|
|
187
|
+
/** Park an Anthropic OAuth flow at its "paste the code" step in one window. */
|
|
188
|
+
async function startParkedLogin(session) {
|
|
189
|
+
const stream = await openEventStream(session);
|
|
190
|
+
const started = await request("POST", "/auth/oauth/start", {
|
|
191
|
+
session,
|
|
192
|
+
body: { provider: "anthropic" },
|
|
193
|
+
});
|
|
194
|
+
expect(started.status).toBe(202);
|
|
195
|
+
// The flow opens a browser URL, then blocks on the pasted code.
|
|
196
|
+
await waitFor(() => stream.types.includes("auth_need_code"));
|
|
197
|
+
return stream;
|
|
198
|
+
}
|
|
199
|
+
it("keeps login progress in the window that started it", async () => {
|
|
200
|
+
const windowA = await createSession();
|
|
201
|
+
const windowB = await createSession();
|
|
202
|
+
const streamB = await openEventStream(windowB);
|
|
203
|
+
const streamA = await startParkedLogin(windowA);
|
|
204
|
+
expect(streamA.types).toContain("auth_url");
|
|
205
|
+
expect(streamA.types).toContain("auth_need_code");
|
|
206
|
+
// Window B never pressed Connect — opening its browser or prompting it for
|
|
207
|
+
// a code it does not have would be nonsense. Progress stays scoped.
|
|
208
|
+
expect(streamB.types).not.toContain("auth_url");
|
|
209
|
+
expect(streamB.types).not.toContain("auth_need_code");
|
|
210
|
+
}, 90_000);
|
|
211
|
+
it("refuses a second window's login for the same provider", async () => {
|
|
212
|
+
const windowA = await createSession();
|
|
213
|
+
const windowB = await createSession();
|
|
214
|
+
await startParkedLogin(windowA);
|
|
215
|
+
// Two flows for one provider means two browser tabs and two token
|
|
216
|
+
// exchanges racing to write the same auth.json entry. The per-session
|
|
217
|
+
// guard cannot see across windows; the daemon-wide one must.
|
|
218
|
+
const second = await request("POST", "/auth/oauth/start", {
|
|
219
|
+
session: windowB,
|
|
220
|
+
body: { provider: "anthropic" },
|
|
221
|
+
});
|
|
222
|
+
expect(second.status).toBe(409);
|
|
223
|
+
expect(String(second.json.error)).toContain("another window");
|
|
224
|
+
}, 90_000);
|
|
225
|
+
it("allows a different provider to log in concurrently", async () => {
|
|
226
|
+
const windowA = await createSession();
|
|
227
|
+
const windowB = await createSession();
|
|
228
|
+
await startParkedLogin(windowA);
|
|
229
|
+
// The guard is per provider, not a global lock: connecting Anthropic in
|
|
230
|
+
// one window must not block connecting OpenAI in another.
|
|
231
|
+
const other = await request("POST", "/auth/oauth/start", {
|
|
232
|
+
session: windowB,
|
|
233
|
+
body: { provider: "openai" },
|
|
234
|
+
});
|
|
235
|
+
expect(other.status).toBe(202);
|
|
236
|
+
}, 90_000);
|
|
237
|
+
it("reports a failed login only to the window that attempted it", async () => {
|
|
238
|
+
const windowA = await createSession();
|
|
239
|
+
const windowB = await createSession();
|
|
240
|
+
const streamB = await openEventStream(windowB);
|
|
241
|
+
const streamA = await startParkedLogin(windowA);
|
|
242
|
+
// A malformed code fails the state check locally — no network needed.
|
|
243
|
+
const sent = await request("POST", "/auth/oauth/code", {
|
|
244
|
+
session: windowA,
|
|
245
|
+
body: { code: "bogus#mismatch" },
|
|
246
|
+
});
|
|
247
|
+
expect(sent.status).toBe(200);
|
|
248
|
+
await waitFor(() => streamA.types.includes("auth_error"));
|
|
249
|
+
// Window B attempted nothing, so it has no failure to report. Its modal
|
|
250
|
+
// correctly still offers to connect.
|
|
251
|
+
expect(streamB.types).not.toContain("auth_error");
|
|
252
|
+
}, 90_000);
|
|
253
|
+
it("frees the provider again after a failed login", async () => {
|
|
254
|
+
const windowA = await createSession();
|
|
255
|
+
const windowB = await createSession();
|
|
256
|
+
const streamA = await startParkedLogin(windowA);
|
|
257
|
+
await request("POST", "/auth/oauth/code", {
|
|
258
|
+
session: windowA,
|
|
259
|
+
body: { code: "bogus#mismatch" },
|
|
260
|
+
});
|
|
261
|
+
await waitFor(() => streamA.types.includes("auth_error"));
|
|
262
|
+
// A failed attempt must release the daemon-wide guard, or the provider
|
|
263
|
+
// would be permanently unloggable until the app restarts.
|
|
264
|
+
const retry = await request("POST", "/auth/oauth/start", {
|
|
265
|
+
session: windowB,
|
|
266
|
+
body: { provider: "anthropic" },
|
|
267
|
+
});
|
|
268
|
+
expect(retry.status).toBe(202);
|
|
269
|
+
}, 90_000);
|
|
270
|
+
});
|
|
271
|
+
//# sourceMappingURL=app-sidecar-auth-broadcast.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-sidecar-auth-broadcast.test.js","sourceRoot":"","sources":["../src/app-sidecar-auth-broadcast.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,11 @@ import { type RecentSession } from "./core/project-discovery.js";
|
|
|
3
3
|
export type SidecarSession = RecentSession & {
|
|
4
4
|
chatAgent?: ChatAgentId;
|
|
5
5
|
};
|
|
6
|
-
/**
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* List coding or chat sessions using the caps exposed by the gg-app sidecar.
|
|
8
|
+
*
|
|
9
|
+
* `homeDir` only exists so tests can point the Claude Code / Codex lookup at a
|
|
10
|
+
* fixture home; production always uses the real one.
|
|
11
|
+
*/
|
|
12
|
+
export declare function listSidecarSessions(cwd: string, requestedAgent: string | null, coderSessionsDir: string, homeDir?: string): Promise<SidecarSession[]>;
|
|
8
13
|
//# sourceMappingURL=app-sidecar-sessions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-sidecar-sessions.d.ts","sourceRoot":"","sources":["../src/app-sidecar-sessions.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,
|
|
1
|
+
{"version":3,"file":"app-sidecar-sessions.d.ts","sourceRoot":"","sources":["../src/app-sidecar-sessions.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,6BAA6B,CAAC;AAOrC,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG;IAAE,SAAS,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC;AAEzE;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,cAAc,EAAE,MAAM,GAAG,IAAI,EAC7B,gBAAgB,EAAE,MAAM,EACxB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,EAAE,CAAC,CAqC3B"}
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import { CHAT_AGENT_IDS, chatAgentSessionsDir, sessionsDirForChatAgent, } from "./chat-agents/index.js";
|
|
3
|
-
import { listRecentSessions } from "./core/project-discovery.js";
|
|
3
|
+
import { listForeignSessions, listRecentSessions, } from "./core/project-discovery.js";
|
|
4
4
|
const CODING_SESSION_LIMIT = 5;
|
|
5
5
|
const CHAT_SESSION_LIMIT = 30;
|
|
6
|
-
/**
|
|
7
|
-
|
|
6
|
+
/** Foreign rows are additive, so keep them a short tail under the native list. */
|
|
7
|
+
const FOREIGN_SESSION_LIMIT = 5;
|
|
8
|
+
/**
|
|
9
|
+
* List coding or chat sessions using the caps exposed by the gg-app sidecar.
|
|
10
|
+
*
|
|
11
|
+
* `homeDir` only exists so tests can point the Claude Code / Codex lookup at a
|
|
12
|
+
* fixture home; production always uses the real one.
|
|
13
|
+
*/
|
|
14
|
+
export async function listSidecarSessions(cwd, requestedAgent, coderSessionsDir, homeDir) {
|
|
8
15
|
if (requestedAgent !== "all") {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
// Chat agents have their own private stores; only the coding list (no
|
|
17
|
+
// requested agent) shares a cwd with Claude Code and Codex.
|
|
18
|
+
if (requestedAgent) {
|
|
19
|
+
return listRecentSessions(cwd, CHAT_SESSION_LIMIT, sessionsDirForChatAgent(coderSessionsDir, requestedAgent));
|
|
20
|
+
}
|
|
21
|
+
return listCodingSessions(cwd, coderSessionsDir, homeDir);
|
|
14
22
|
}
|
|
15
23
|
const groups = await Promise.all(CHAT_AGENT_IDS.map(async (agentId) => {
|
|
16
24
|
const sessions = await listRecentSessions(cwd, CHAT_SESSION_LIMIT, chatAgentSessionsDir(coderSessionsDir, agentId));
|
|
@@ -28,4 +36,24 @@ export async function listSidecarSessions(cwd, requestedAgent, coderSessionsDir)
|
|
|
28
36
|
.slice(0, CHAT_SESSION_LIMIT)
|
|
29
37
|
.map(({ session }) => session);
|
|
30
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* GG Coder's own sessions for this project plus any Claude Code / Codex
|
|
41
|
+
* transcripts recorded against the same cwd.
|
|
42
|
+
*
|
|
43
|
+
* The project picker already surfaces those stores, so a project can appear
|
|
44
|
+
* *because* it has Claude Code history and then show an empty session list.
|
|
45
|
+
* Foreign rows close that gap; the app imports one on click and opens it.
|
|
46
|
+
*
|
|
47
|
+
* A foreign store being slow or unreadable must never empty the native list,
|
|
48
|
+
* so its failure degrades to "no foreign rows".
|
|
49
|
+
*/
|
|
50
|
+
async function listCodingSessions(cwd, coderSessionsDir, homeDir) {
|
|
51
|
+
const [native, foreign] = await Promise.all([
|
|
52
|
+
listRecentSessions(cwd, CODING_SESSION_LIMIT, coderSessionsDir),
|
|
53
|
+
listForeignSessions(cwd, FOREIGN_SESSION_LIMIT, homeDir).catch(() => []),
|
|
54
|
+
]);
|
|
55
|
+
// Native first: a session already resumable here beats one that needs an
|
|
56
|
+
// import, even when the foreign transcript is a little newer.
|
|
57
|
+
return [...native, ...foreign];
|
|
58
|
+
}
|
|
31
59
|
//# sourceMappingURL=app-sidecar-sessions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-sidecar-sessions.js","sourceRoot":"","sources":["../src/app-sidecar-sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,uBAAuB,GAExB,MAAM,wBAAwB,CAAC;AAChC,OAAO,
|
|
1
|
+
{"version":3,"file":"app-sidecar-sessions.js","sourceRoot":"","sources":["../src/app-sidecar-sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,uBAAuB,GAExB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,mBAAmB,EACnB,kBAAkB,GAEnB,MAAM,6BAA6B,CAAC;AAErC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAC/B,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAC9B,kFAAkF;AAClF,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAIhC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAW,EACX,cAA6B,EAC7B,gBAAwB,EACxB,OAAgB;IAEhB,IAAI,cAAc,KAAK,KAAK,EAAE,CAAC;QAC7B,sEAAsE;QACtE,4DAA4D;QAC5D,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,kBAAkB,CACvB,GAAG,EACH,kBAAkB,EAClB,uBAAuB,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAC1D,CAAC;QACJ,CAAC;QACD,OAAO,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACnC,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CACvC,GAAG,EACH,kBAAkB,EAClB,oBAAoB,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAChD,CAAC;QACF,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IACzE,CAAC,CAAC,CACH,CAAC;IACF,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAC7B,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QACpC,OAAO;QACP,KAAK,EAAE,MAAM,EAAE;aACZ,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;aAClB,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;aAC5B,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;KAClB,CAAC,CAAC,CACJ,CAAC;IACF,OAAO,KAAK;SACT,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;SAC/C,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC;SAC5B,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;;;;;GAUG;AACH,KAAK,UAAU,kBAAkB,CAC/B,GAAW,EACX,gBAAwB,EACxB,OAAgB;IAEhB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1C,kBAAkB,CAAC,GAAG,EAAE,oBAAoB,EAAE,gBAAgB,CAAC;QAC/D,mBAAmB,CAAC,GAAG,EAAE,qBAAqB,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;KACzE,CAAC,CAAC;IACH,yEAAyE;IACzE,8DAA8D;IAC9D,OAAO,CAAC,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -6,6 +6,48 @@ import { chatAgentSessionsDir } from "./chat-agents/index.js";
|
|
|
6
6
|
import { listSidecarSessions } from "./app-sidecar-sessions.js";
|
|
7
7
|
import { encodeCwd } from "./core/encode-cwd.js";
|
|
8
8
|
import { archiveColdSession, archiveSessionPath } from "./core/session-storage.js";
|
|
9
|
+
import { importForeignSession } from "./core/foreign-session-import.js";
|
|
10
|
+
import { SessionManager } from "./core/session-manager.js";
|
|
11
|
+
/**
|
|
12
|
+
* Write a Claude Code transcript into a fixture `~/.claude/projects` dir.
|
|
13
|
+
* Claude's directory encoding is ambiguous, so the cwd it records inside the
|
|
14
|
+
* records — not the folder name — is what discovery matches on.
|
|
15
|
+
*/
|
|
16
|
+
async function writeClaudeTranscript(homeDir, cwd, sessionId, prompt) {
|
|
17
|
+
// The folder name is deliberately only *shaped* like Claude's encoding: since
|
|
18
|
+
// discovery reads the cwd out of the records, the exact name is irrelevant to
|
|
19
|
+
// what these tests assert. It does have to be a VALID single directory name on
|
|
20
|
+
// the host though — collapsing only "/" left Windows paths as `-C:\Users\...`,
|
|
21
|
+
// whose drive colon and backslashes made `mkdir` fail with ENOENT. Fold both
|
|
22
|
+
// separators and the drive colon into dashes so the fixture is portable.
|
|
23
|
+
const encoded = `-${cwd.replace(/[\\/:]/g, "-")}`;
|
|
24
|
+
const projectDir = path.join(homeDir, ".claude", "projects", encoded);
|
|
25
|
+
await fs.mkdir(projectDir, { recursive: true });
|
|
26
|
+
const file = path.join(projectDir, `${sessionId}.jsonl`);
|
|
27
|
+
const stamp = new Date().toISOString();
|
|
28
|
+
const records = [
|
|
29
|
+
{
|
|
30
|
+
parentUuid: null,
|
|
31
|
+
isSidechain: false,
|
|
32
|
+
type: "user",
|
|
33
|
+
uuid: "u1",
|
|
34
|
+
timestamp: stamp,
|
|
35
|
+
cwd,
|
|
36
|
+
message: { role: "user", content: prompt },
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
parentUuid: "u1",
|
|
40
|
+
isSidechain: false,
|
|
41
|
+
type: "assistant",
|
|
42
|
+
uuid: "a1",
|
|
43
|
+
timestamp: stamp,
|
|
44
|
+
cwd,
|
|
45
|
+
message: { role: "assistant", content: [{ type: "text", text: "On it." }] },
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
await fs.writeFile(file, records.map((record) => JSON.stringify(record)).join("\n") + "\n");
|
|
49
|
+
return file;
|
|
50
|
+
}
|
|
9
51
|
async function writeSessions(sessionsRoot, cwd, prefix, count) {
|
|
10
52
|
const projectSessionsDir = path.join(sessionsRoot, encodeCwd(cwd));
|
|
11
53
|
await fs.mkdir(projectSessionsDir, { recursive: true });
|
|
@@ -65,6 +107,59 @@ describe("gg-app sidecar session listings", () => {
|
|
|
65
107
|
expect(chatSessions[0]).toMatchObject({ id: "chat-30", chatAgent: "general" });
|
|
66
108
|
expect(chatSessions.at(-1)).toMatchObject({ id: "chat-1", chatAgent: "general" });
|
|
67
109
|
});
|
|
110
|
+
it("surfaces a Claude Code session for the project and opens it as a resumable GG Coder session", async () => {
|
|
111
|
+
const home = path.join(tmp, "home");
|
|
112
|
+
const transcript = await writeClaudeTranscript(home, cwd, "cc-session-1", "Add a retry to the fetch helper.");
|
|
113
|
+
// 1. It shows up in the session list, tagged with where it came from.
|
|
114
|
+
const sessions = await listSidecarSessions(cwd, null, coderSessionsDir, home);
|
|
115
|
+
const foreign = sessions.find((session) => session.source === "claude-code");
|
|
116
|
+
expect(foreign).toBeDefined();
|
|
117
|
+
expect(foreign?.path).toBe(transcript);
|
|
118
|
+
expect(foreign?.preview).toBe("Add a retry to the fetch helper.");
|
|
119
|
+
expect(foreign?.messageCount).toBe(2);
|
|
120
|
+
// 2. Clicking it (import-then-open) yields a real, loadable GG Coder session.
|
|
121
|
+
const sessionManager = new SessionManager(coderSessionsDir);
|
|
122
|
+
const imported = await importForeignSession({
|
|
123
|
+
filePath: foreign.path,
|
|
124
|
+
sessionManager,
|
|
125
|
+
provider: "anthropic",
|
|
126
|
+
model: "claude-sonnet-5",
|
|
127
|
+
cwd,
|
|
128
|
+
});
|
|
129
|
+
const loaded = await sessionManager.load(imported.sessionPath);
|
|
130
|
+
expect(loaded).not.toBeNull();
|
|
131
|
+
expect(loaded.header.cwd).toBe(cwd);
|
|
132
|
+
expect(sessionManager.getMessages(loaded.entries, loaded.header.leafId).map((m) => m.role)).toEqual(["user", "assistant"]);
|
|
133
|
+
// 3. It now also appears as a NATIVE row, so the next open skips the import.
|
|
134
|
+
const after = await listSidecarSessions(cwd, null, coderSessionsDir, home);
|
|
135
|
+
const native = after.find((session) => session.path === imported.sessionPath);
|
|
136
|
+
expect(native).toBeDefined();
|
|
137
|
+
expect(native?.source).toBeUndefined();
|
|
138
|
+
});
|
|
139
|
+
it("keeps native sessions listed ahead of foreign ones", async () => {
|
|
140
|
+
const home = path.join(tmp, "home");
|
|
141
|
+
await writeClaudeTranscript(home, cwd, "cc-session-2", "Foreign prompt.");
|
|
142
|
+
await writeSessions(coderSessionsDir, cwd, "coding", 2);
|
|
143
|
+
const sessions = await listSidecarSessions(cwd, null, coderSessionsDir, home);
|
|
144
|
+
const firstForeignIndex = sessions.findIndex((session) => session.source === "claude-code");
|
|
145
|
+
const lastNativeIndex = sessions.map((session) => session.source).lastIndexOf(undefined);
|
|
146
|
+
expect(firstForeignIndex).toBeGreaterThan(-1);
|
|
147
|
+
expect(firstForeignIndex).toBeGreaterThan(lastNativeIndex);
|
|
148
|
+
});
|
|
149
|
+
it("ignores a Claude Code session recorded against a different project", async () => {
|
|
150
|
+
const home = path.join(tmp, "home");
|
|
151
|
+
const otherCwd = path.join(tmp, "other-project");
|
|
152
|
+
await fs.mkdir(otherCwd, { recursive: true });
|
|
153
|
+
await writeClaudeTranscript(home, otherCwd, "cc-elsewhere", "Not this project.");
|
|
154
|
+
const sessions = await listSidecarSessions(cwd, null, coderSessionsDir, home);
|
|
155
|
+
expect(sessions.some((session) => session.source === "claude-code")).toBe(false);
|
|
156
|
+
});
|
|
157
|
+
it("does not mix foreign sessions into a chat-agent listing", async () => {
|
|
158
|
+
const home = path.join(tmp, "home");
|
|
159
|
+
await writeClaudeTranscript(home, cwd, "cc-session-3", "Foreign prompt.");
|
|
160
|
+
const chatSessions = await listSidecarSessions(cwd, "general", coderSessionsDir, home);
|
|
161
|
+
expect(chatSessions.some((session) => session.source === "claude-code")).toBe(false);
|
|
162
|
+
});
|
|
68
163
|
it("lists archived coding and chat sessions once despite their redirect counterparts", async () => {
|
|
69
164
|
const chatRoot = chatAgentSessionsDir(coderSessionsDir, "general");
|
|
70
165
|
await writeSessions(coderSessionsDir, cwd, "coding-archive", 1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-sidecar-sessions.test.js","sourceRoot":"","sources":["../src/app-sidecar-sessions.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAErE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"app-sidecar-sessions.test.js","sourceRoot":"","sources":["../src/app-sidecar-sessions.test.ts"],"names":[],"mappings":"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"}
|