@kenkaiiii/ggcoder 5.26.3 → 5.28.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.
Files changed (91) hide show
  1. package/dist/app-sidecar-sessions.d.ts +7 -2
  2. package/dist/app-sidecar-sessions.d.ts.map +1 -1
  3. package/dist/app-sidecar-sessions.js +36 -8
  4. package/dist/app-sidecar-sessions.js.map +1 -1
  5. package/dist/app-sidecar-sessions.test.js +88 -0
  6. package/dist/app-sidecar-sessions.test.js.map +1 -1
  7. package/dist/app-sidecar.js +27 -0
  8. package/dist/app-sidecar.js.map +1 -1
  9. package/dist/core/agent-session-process-gate.test.d.ts +2 -0
  10. package/dist/core/agent-session-process-gate.test.d.ts.map +1 -0
  11. package/dist/core/agent-session-process-gate.test.js +88 -0
  12. package/dist/core/agent-session-process-gate.test.js.map +1 -0
  13. package/dist/core/agent-session.d.ts +40 -0
  14. package/dist/core/agent-session.d.ts.map +1 -1
  15. package/dist/core/agent-session.js +204 -6
  16. package/dist/core/agent-session.js.map +1 -1
  17. package/dist/core/foreign-session-import.d.ts +120 -0
  18. package/dist/core/foreign-session-import.d.ts.map +1 -0
  19. package/dist/core/foreign-session-import.js +594 -0
  20. package/dist/core/foreign-session-import.js.map +1 -0
  21. package/dist/core/foreign-session-import.test.d.ts +2 -0
  22. package/dist/core/foreign-session-import.test.d.ts.map +1 -0
  23. package/dist/core/foreign-session-import.test.js +220 -0
  24. package/dist/core/foreign-session-import.test.js.map +1 -0
  25. package/dist/core/foreign-transcript-blocks.d.ts +51 -0
  26. package/dist/core/foreign-transcript-blocks.d.ts.map +1 -0
  27. package/dist/core/foreign-transcript-blocks.js +151 -0
  28. package/dist/core/foreign-transcript-blocks.js.map +1 -0
  29. package/dist/core/mcp/catalog-cache.d.ts +63 -0
  30. package/dist/core/mcp/catalog-cache.d.ts.map +1 -0
  31. package/dist/core/mcp/catalog-cache.js +163 -0
  32. package/dist/core/mcp/catalog-cache.js.map +1 -0
  33. package/dist/core/mcp/catalog-cache.test.d.ts +2 -0
  34. package/dist/core/mcp/catalog-cache.test.d.ts.map +1 -0
  35. package/dist/core/mcp/catalog-cache.test.js +99 -0
  36. package/dist/core/mcp/catalog-cache.test.js.map +1 -0
  37. package/dist/core/mcp/client.d.ts +61 -0
  38. package/dist/core/mcp/client.d.ts.map +1 -1
  39. package/dist/core/mcp/client.js +216 -31
  40. package/dist/core/mcp/client.js.map +1 -1
  41. package/dist/core/mcp/legacy-negotiation.test.d.ts +2 -0
  42. package/dist/core/mcp/legacy-negotiation.test.d.ts.map +1 -0
  43. package/dist/core/mcp/legacy-negotiation.test.js +80 -0
  44. package/dist/core/mcp/legacy-negotiation.test.js.map +1 -0
  45. package/dist/core/mcp/oauth-provider.d.ts +1 -2
  46. package/dist/core/mcp/oauth-provider.d.ts.map +1 -1
  47. package/dist/core/mcp/oauth-provider.js +5 -1
  48. package/dist/core/mcp/oauth-provider.js.map +1 -1
  49. package/dist/core/mcp/oauth-store.d.ts +1 -1
  50. package/dist/core/mcp/oauth-store.d.ts.map +1 -1
  51. package/dist/core/mcp/oauth-store.js.map +1 -1
  52. package/dist/core/mcp/when-connected.test.d.ts +2 -0
  53. package/dist/core/mcp/when-connected.test.d.ts.map +1 -0
  54. package/dist/core/mcp/when-connected.test.js +46 -0
  55. package/dist/core/mcp/when-connected.test.js.map +1 -0
  56. package/dist/core/process-gate.d.ts +45 -0
  57. package/dist/core/process-gate.d.ts.map +1 -0
  58. package/dist/core/process-gate.js +71 -0
  59. package/dist/core/process-gate.js.map +1 -0
  60. package/dist/core/process-gate.test.d.ts +2 -0
  61. package/dist/core/process-gate.test.d.ts.map +1 -0
  62. package/dist/core/process-gate.test.js +87 -0
  63. package/dist/core/process-gate.test.js.map +1 -0
  64. package/dist/core/process-manager.d.ts +9 -0
  65. package/dist/core/process-manager.d.ts.map +1 -1
  66. package/dist/core/process-manager.js +17 -15
  67. package/dist/core/process-manager.js.map +1 -1
  68. package/dist/core/project-discovery.d.ts +19 -0
  69. package/dist/core/project-discovery.d.ts.map +1 -1
  70. package/dist/core/project-discovery.js +100 -0
  71. package/dist/core/project-discovery.js.map +1 -1
  72. package/dist/core/session-manager.d.ts +5 -1
  73. package/dist/core/session-manager.d.ts.map +1 -1
  74. package/dist/core/session-manager.js +2 -1
  75. package/dist/core/session-manager.js.map +1 -1
  76. package/dist/core/settings-manager.d.ts +1 -0
  77. package/dist/core/settings-manager.d.ts.map +1 -1
  78. package/dist/core/settings-manager.js +6 -0
  79. package/dist/core/settings-manager.js.map +1 -1
  80. package/dist/tools/tool-search.d.ts +12 -1
  81. package/dist/tools/tool-search.d.ts.map +1 -1
  82. package/dist/tools/tool-search.js +22 -3
  83. package/dist/tools/tool-search.js.map +1 -1
  84. package/dist/tools/tool-search.test.d.ts +2 -0
  85. package/dist/tools/tool-search.test.d.ts.map +1 -0
  86. package/dist/tools/tool-search.test.js +69 -0
  87. package/dist/tools/tool-search.test.js.map +1 -0
  88. package/dist/ui/App.d.ts.map +1 -1
  89. package/dist/ui/App.js +27 -1
  90. package/dist/ui/App.js.map +1 -1
  91. package/package.json +5 -5
@@ -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
- /** List coding or chat sessions using the caps exposed by the gg-app sidecar. */
7
- export declare function listSidecarSessions(cwd: string, requestedAgent: string | null, coderSessionsDir: string): Promise<SidecarSession[]>;
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,EAAsB,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAKrF,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG;IAAE,SAAS,CAAC,EAAE,WAAW,CAAA;CAAE,CAAC;AAEzE,iFAAiF;AACjF,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,cAAc,EAAE,MAAM,GAAG,IAAI,EAC7B,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,cAAc,EAAE,CAAC,CAgC3B"}
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
- /** List coding or chat sessions using the caps exposed by the gg-app sidecar. */
7
- export async function listSidecarSessions(cwd, requestedAgent, coderSessionsDir) {
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
- const sessionsDir = requestedAgent
10
- ? sessionsDirForChatAgent(coderSessionsDir, requestedAgent)
11
- : coderSessionsDir;
12
- const sessionLimit = requestedAgent ? CHAT_SESSION_LIMIT : CODING_SESSION_LIMIT;
13
- return listRecentSessions(cwd, sessionLimit, sessionsDir);
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,EAAE,kBAAkB,EAAsB,MAAM,6BAA6B,CAAC;AAErF,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAC/B,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAI9B,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAW,EACX,cAA6B,EAC7B,gBAAwB;IAExB,IAAI,cAAc,KAAK,KAAK,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,cAAc;YAChC,CAAC,CAAC,uBAAuB,CAAC,gBAAgB,EAAE,cAAc,CAAC;YAC3D,CAAC,CAAC,gBAAgB,CAAC;QACrB,MAAM,YAAY,GAAG,cAAc,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,oBAAoB,CAAC;QAChF,OAAO,kBAAkB,CAAC,GAAG,EAAE,YAAY,EAAE,WAAW,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"}
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,41 @@ 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
+ const projectDir = path.join(homeDir, ".claude", "projects", `-${cwd.replace(/\//g, "-")}`);
18
+ await fs.mkdir(projectDir, { recursive: true });
19
+ const file = path.join(projectDir, `${sessionId}.jsonl`);
20
+ const stamp = new Date().toISOString();
21
+ const records = [
22
+ {
23
+ parentUuid: null,
24
+ isSidechain: false,
25
+ type: "user",
26
+ uuid: "u1",
27
+ timestamp: stamp,
28
+ cwd,
29
+ message: { role: "user", content: prompt },
30
+ },
31
+ {
32
+ parentUuid: "u1",
33
+ isSidechain: false,
34
+ type: "assistant",
35
+ uuid: "a1",
36
+ timestamp: stamp,
37
+ cwd,
38
+ message: { role: "assistant", content: [{ type: "text", text: "On it." }] },
39
+ },
40
+ ];
41
+ await fs.writeFile(file, records.map((record) => JSON.stringify(record)).join("\n") + "\n");
42
+ return file;
43
+ }
9
44
  async function writeSessions(sessionsRoot, cwd, prefix, count) {
10
45
  const projectSessionsDir = path.join(sessionsRoot, encodeCwd(cwd));
11
46
  await fs.mkdir(projectSessionsDir, { recursive: true });
@@ -65,6 +100,59 @@ describe("gg-app sidecar session listings", () => {
65
100
  expect(chatSessions[0]).toMatchObject({ id: "chat-30", chatAgent: "general" });
66
101
  expect(chatSessions.at(-1)).toMatchObject({ id: "chat-1", chatAgent: "general" });
67
102
  });
103
+ it("surfaces a Claude Code session for the project and opens it as a resumable GG Coder session", async () => {
104
+ const home = path.join(tmp, "home");
105
+ const transcript = await writeClaudeTranscript(home, cwd, "cc-session-1", "Add a retry to the fetch helper.");
106
+ // 1. It shows up in the session list, tagged with where it came from.
107
+ const sessions = await listSidecarSessions(cwd, null, coderSessionsDir, home);
108
+ const foreign = sessions.find((session) => session.source === "claude-code");
109
+ expect(foreign).toBeDefined();
110
+ expect(foreign?.path).toBe(transcript);
111
+ expect(foreign?.preview).toBe("Add a retry to the fetch helper.");
112
+ expect(foreign?.messageCount).toBe(2);
113
+ // 2. Clicking it (import-then-open) yields a real, loadable GG Coder session.
114
+ const sessionManager = new SessionManager(coderSessionsDir);
115
+ const imported = await importForeignSession({
116
+ filePath: foreign.path,
117
+ sessionManager,
118
+ provider: "anthropic",
119
+ model: "claude-sonnet-5",
120
+ cwd,
121
+ });
122
+ const loaded = await sessionManager.load(imported.sessionPath);
123
+ expect(loaded).not.toBeNull();
124
+ expect(loaded.header.cwd).toBe(cwd);
125
+ expect(sessionManager.getMessages(loaded.entries, loaded.header.leafId).map((m) => m.role)).toEqual(["user", "assistant"]);
126
+ // 3. It now also appears as a NATIVE row, so the next open skips the import.
127
+ const after = await listSidecarSessions(cwd, null, coderSessionsDir, home);
128
+ const native = after.find((session) => session.path === imported.sessionPath);
129
+ expect(native).toBeDefined();
130
+ expect(native?.source).toBeUndefined();
131
+ });
132
+ it("keeps native sessions listed ahead of foreign ones", async () => {
133
+ const home = path.join(tmp, "home");
134
+ await writeClaudeTranscript(home, cwd, "cc-session-2", "Foreign prompt.");
135
+ await writeSessions(coderSessionsDir, cwd, "coding", 2);
136
+ const sessions = await listSidecarSessions(cwd, null, coderSessionsDir, home);
137
+ const firstForeignIndex = sessions.findIndex((session) => session.source === "claude-code");
138
+ const lastNativeIndex = sessions.map((session) => session.source).lastIndexOf(undefined);
139
+ expect(firstForeignIndex).toBeGreaterThan(-1);
140
+ expect(firstForeignIndex).toBeGreaterThan(lastNativeIndex);
141
+ });
142
+ it("ignores a Claude Code session recorded against a different project", async () => {
143
+ const home = path.join(tmp, "home");
144
+ const otherCwd = path.join(tmp, "other-project");
145
+ await fs.mkdir(otherCwd, { recursive: true });
146
+ await writeClaudeTranscript(home, otherCwd, "cc-elsewhere", "Not this project.");
147
+ const sessions = await listSidecarSessions(cwd, null, coderSessionsDir, home);
148
+ expect(sessions.some((session) => session.source === "claude-code")).toBe(false);
149
+ });
150
+ it("does not mix foreign sessions into a chat-agent listing", async () => {
151
+ const home = path.join(tmp, "home");
152
+ await writeClaudeTranscript(home, cwd, "cc-session-3", "Foreign prompt.");
153
+ const chatSessions = await listSidecarSessions(cwd, "general", coderSessionsDir, home);
154
+ expect(chatSessions.some((session) => session.source === "claude-code")).toBe(false);
155
+ });
68
156
  it("lists archived coding and chat sessions once despite their redirect counterparts", async () => {
69
157
  const chatRoot = chatAgentSessionsDir(coderSessionsDir, "general");
70
158
  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;AAEnF,KAAK,UAAU,aAAa,CAC1B,YAAoB,EACpB,GAAW,EACX,MAAc,EACd,KAAa;IAEb,MAAM,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IACnE,MAAM,EAAE,CAAC,KAAK,CAAC,kBAAkB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAExD,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;QACrE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG,MAAM,IAAI,KAAK,QAAQ,CAAC,CAAC;QACvE,MAAM,OAAO,GAAG;YACd;gBACE,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,CAAC;gBACV,EAAE,EAAE,GAAG,MAAM,IAAI,KAAK,EAAE;gBACxB,cAAc,EAAE,GAAG,MAAM,IAAI,KAAK,EAAE;gBACpC,SAAS;gBACT,GAAG;gBACH,QAAQ,EAAE,WAAW;gBACrB,KAAK,EAAE,iBAAiB;aACzB;YACD;gBACE,IAAI,EAAE,SAAS;gBACf,EAAE,EAAE,GAAG,MAAM,YAAY,KAAK,EAAE;gBAChC,SAAS;gBACT,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,KAAK,EAAE,EAAE;aACvD;SACF,CAAC;QACF,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QAC5F,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,IAAI,GAAW,CAAC;IAChB,IAAI,GAAW,CAAC;IAChB,IAAI,gBAAwB,CAAC;IAE7B,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;QACvE,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAChC,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAC9C,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,aAAa,CAAC,gBAAgB,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;QACzD,MAAM,aAAa,CAAC,oBAAoB,CAAC,gBAAgB,EAAE,SAAS,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QAExF,MAAM,cAAc,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC;QAC9E,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC;QAE7E,MAAM,CAAC,cAAc,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YAC1D,WAAW;YACX,WAAW;YACX,WAAW;YACX,WAAW;YACX,WAAW;SACZ,CAAC,CAAC;QACH,MAAM,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACtC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/E,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kFAAkF,EAAE,KAAK,IAAI,EAAE;QAChG,MAAM,QAAQ,GAAG,oBAAoB,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;QACnE,MAAM,aAAa,CAAC,gBAAgB,EAAE,GAAG,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC;QAChE,MAAM,aAAa,CAAC,QAAQ,EAAE,GAAG,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;QACtD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,wBAAwB,CAAC,CAAC;QAC1F,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC9E,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,kBAAkB,CAAC,WAAW,CAAC,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAEpF,MAAM,cAAc,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC;QAC9E,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;QACjF,MAAM,CAAC,cAAc,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAC;QACtE,MAAM,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"app-sidecar-sessions.test.js","sourceRoot":"","sources":["../src/app-sidecar-sessions.test.ts"],"names":[],"mappings":"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"}
@@ -3578,6 +3578,33 @@ async function createSession(deps, opts) {
3578
3578
  });
3579
3579
  return;
3580
3580
  }
3581
+ // Import a Claude Code / Codex / Cursor transcript into a resumable GG
3582
+ // Coder session. The importer never throws — it returns a typed failure so
3583
+ // the app can show the reason verbatim.
3584
+ if (method === "POST" && url === "/import-transcript") {
3585
+ void readBody(req, res).then(async (raw) => {
3586
+ if (raw === null)
3587
+ return;
3588
+ let body;
3589
+ try {
3590
+ body = JSON.parse(raw);
3591
+ }
3592
+ catch {
3593
+ json(res, 400, { error: "invalid JSON body" });
3594
+ return;
3595
+ }
3596
+ const filePath = body.path?.trim();
3597
+ if (!filePath) {
3598
+ json(res, 400, { error: "missing transcript path" });
3599
+ return;
3600
+ }
3601
+ const result = await session.importForeignTranscript(filePath, {
3602
+ ...(body.cwd ? { cwd: body.cwd } : {}),
3603
+ });
3604
+ json(res, result.ok ? 200 : 400, result);
3605
+ });
3606
+ return;
3607
+ }
3581
3608
  if (method === "POST" && url === "/thinking") {
3582
3609
  const st = session.getState();
3583
3610
  const next = getNextThinkingLevel(st.provider, st.model, session.getThinkingLevel());