|
1 | 1 | import { describe, expect, it } from "vitest"; |
| 2 | +import type { ProjectLocation, ThreadConfig } from "@/shared/contracts"; |
2 | 3 | import { createGeminiAdapter } from "."; |
| 4 | +import { buildGeminiArgs } from "./argv"; |
3 | 5 | import { geminiIntentFor } from "./plugin/intentMap"; |
4 | 6 | import { detectGeminiInvalidSessionRef } from "./session"; |
5 | 7 | import { detectGeminiTerminalStatus } from "./terminal"; |
6 | 8 |
|
| 9 | +const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; |
| 10 | + |
7 | 11 | describe("detectGeminiTerminalStatus", () => { |
8 | 12 | it("detects idle from ◇ Ready title bar indicator", () => { |
9 | 13 | const text = "0;◇ Ready (my-project)"; |
@@ -181,6 +185,68 @@ describe("detectGeminiTerminalStatus", () => { |
181 | 185 | }); |
182 | 186 | }); |
183 | 187 |
|
| 188 | +describe("buildGeminiArgs", () => { |
| 189 | + const config: ThreadConfig = { model: "gemini-2.5-pro" }; |
| 190 | + |
| 191 | + it("emits --session-id when an assignedSessionId is provided", () => { |
| 192 | + const args = buildGeminiArgs(config, "hello", undefined, "abc-uuid"); |
| 193 | + const sessionIdx = args.indexOf("--session-id"); |
| 194 | + expect(sessionIdx).toBeGreaterThanOrEqual(0); |
| 195 | + expect(args[sessionIdx + 1]).toBe("abc-uuid"); |
| 196 | + expect(args).not.toContain("--resume"); |
| 197 | + }); |
| 198 | + |
| 199 | + it("prefers --resume over --session-id when both are provided", () => { |
| 200 | + const args = buildGeminiArgs(config, "hello", "resume-uuid", "assigned-uuid"); |
| 201 | + expect(args).toContain("--resume"); |
| 202 | + expect(args).toContain("resume-uuid"); |
| 203 | + expect(args).not.toContain("--session-id"); |
| 204 | + expect(args).not.toContain("assigned-uuid"); |
| 205 | + }); |
| 206 | + |
| 207 | + it("omits both flags when neither is provided", () => { |
| 208 | + const args = buildGeminiArgs(config, "hello"); |
| 209 | + expect(args).not.toContain("--resume"); |
| 210 | + expect(args).not.toContain("--session-id"); |
| 211 | + }); |
| 212 | +}); |
| 213 | + |
| 214 | +describe("createGeminiAdapter buildLaunchArgv", () => { |
| 215 | + const project: ProjectLocation = { |
| 216 | + kind: "windows", |
| 217 | + path: "C:\\demo", |
| 218 | + }; |
| 219 | + const config: ThreadConfig = { model: "gemini-2.5-pro" }; |
| 220 | + |
| 221 | + it("assigns a stable session UUID at launch and returns it as sessionRef", () => { |
| 222 | + const adapter = createGeminiAdapter(); |
| 223 | + const argv = adapter.buildLaunchArgv(project, config, "hi"); |
| 224 | + |
| 225 | + if (argv === undefined) throw new Error("expected argv"); |
| 226 | + expect(argv.binary).toBe("gemini"); |
| 227 | + |
| 228 | + const sessionIdx = argv.args.indexOf("--session-id"); |
| 229 | + expect(sessionIdx).toBeGreaterThanOrEqual(0); |
| 230 | + const uuid = argv.args[sessionIdx + 1]!; |
| 231 | + expect(uuid).toMatch(UUID_RE); |
| 232 | + |
| 233 | + expect(argv.sessionRef?.providerSessionId).toBe(uuid); |
| 234 | + }); |
| 235 | + |
| 236 | + it("uses --resume (not --session-id) on resume", () => { |
| 237 | + const adapter = createGeminiAdapter(); |
| 238 | + const argv = adapter.buildResumeArgv(project, config, "hi", { |
| 239 | + providerSessionId: "11111111-1111-4111-8111-111111111111", |
| 240 | + discoveredAt: "2026-05-15T00:00:00.000Z", |
| 241 | + }); |
| 242 | + |
| 243 | + if (argv === undefined) throw new Error("expected argv"); |
| 244 | + expect(argv.args).toContain("--resume"); |
| 245 | + expect(argv.args).toContain("11111111-1111-4111-8111-111111111111"); |
| 246 | + expect(argv.args).not.toContain("--session-id"); |
| 247 | + }); |
| 248 | +}); |
| 249 | + |
184 | 250 | describe("detectGeminiInvalidSessionRef", () => { |
185 | 251 | it("detects Gemini invalid resume session errors", () => { |
186 | 252 | expect( |
|
0 commit comments