@ai-devkit/agent-manager 0.34.0 → 0.35.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/AgentManager.d.ts +2 -0
- package/dist/AgentManager.d.ts.map +1 -1
- package/dist/AgentManager.js +25 -0
- package/dist/AgentManager.js.map +1 -1
- package/dist/__tests__/AgentManager.test.js +74 -0
- package/dist/__tests__/AgentManager.test.js.map +1 -1
- package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js +28 -0
- package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js.map +1 -1
- package/dist/__tests__/adapters/CodexAdapter.test.js +7 -0
- package/dist/__tests__/adapters/CodexAdapter.test.js.map +1 -1
- package/dist/__tests__/providers/copilot/CopilotAdapter.test.js +18 -0
- package/dist/__tests__/providers/copilot/CopilotAdapter.test.js.map +1 -1
- package/dist/__tests__/providers/gemini/GeminiCliAdapter.test.js +36 -0
- package/dist/__tests__/providers/gemini/GeminiCliAdapter.test.js.map +1 -1
- package/dist/__tests__/providers/grok/GrokAgentMapper.test.js +56 -0
- package/dist/__tests__/providers/grok/GrokAgentMapper.test.js.map +1 -0
- package/dist/__tests__/{adapters → providers/grok}/GrokCliAdapter.test.js +19 -6
- package/dist/__tests__/providers/grok/GrokCliAdapter.test.js.map +1 -0
- package/dist/__tests__/providers/grok/GrokSessionLocator.test.js +133 -0
- package/dist/__tests__/providers/grok/GrokSessionLocator.test.js.map +1 -0
- package/dist/__tests__/providers/opencode/OpenCodeAdapter.test.js +24 -0
- package/dist/__tests__/providers/opencode/OpenCodeAdapter.test.js.map +1 -1
- package/dist/__tests__/providers/pi/PiAdapter.test.js +30 -0
- package/dist/__tests__/providers/pi/PiAdapter.test.js.map +1 -1
- package/dist/__tests__/utils/session.test.js +18 -1
- package/dist/__tests__/utils/session.test.js.map +1 -1
- package/dist/adapters/AgentAdapter.d.ts +8 -0
- package/dist/adapters/AgentAdapter.d.ts.map +1 -1
- package/dist/adapters/AgentAdapter.js.map +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +1 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/providers/claude/ClaudeCodeAdapter.d.ts +2 -0
- package/dist/providers/claude/ClaudeCodeAdapter.d.ts.map +1 -1
- package/dist/providers/claude/ClaudeCodeAdapter.js +22 -19
- package/dist/providers/claude/ClaudeCodeAdapter.js.map +1 -1
- package/dist/providers/claude/ClaudeSessionLocator.d.ts +4 -0
- package/dist/providers/claude/ClaudeSessionLocator.d.ts.map +1 -1
- package/dist/providers/claude/ClaudeSessionLocator.js +18 -1
- package/dist/providers/claude/ClaudeSessionLocator.js.map +1 -1
- package/dist/providers/codex/CodexAdapter.d.ts +1 -0
- package/dist/providers/codex/CodexAdapter.d.ts.map +1 -1
- package/dist/providers/codex/CodexAdapter.js +8 -0
- package/dist/providers/codex/CodexAdapter.js.map +1 -1
- package/dist/providers/copilot/CopilotAdapter.d.ts +2 -0
- package/dist/providers/copilot/CopilotAdapter.d.ts.map +1 -1
- package/dist/providers/copilot/CopilotAdapter.js +24 -9
- package/dist/providers/copilot/CopilotAdapter.js.map +1 -1
- package/dist/providers/copilot/CopilotSessionLocator.d.ts +1 -0
- package/dist/providers/copilot/CopilotSessionLocator.d.ts.map +1 -1
- package/dist/providers/copilot/CopilotSessionLocator.js +9 -1
- package/dist/providers/copilot/CopilotSessionLocator.js.map +1 -1
- package/dist/providers/gemini/GeminiCliAdapter.d.ts +1 -0
- package/dist/providers/gemini/GeminiCliAdapter.d.ts.map +1 -1
- package/dist/providers/gemini/GeminiCliAdapter.js +9 -0
- package/dist/providers/gemini/GeminiCliAdapter.js.map +1 -1
- package/dist/providers/grok/GrokAgentMapper.d.ts +14 -0
- package/dist/providers/grok/GrokAgentMapper.d.ts.map +1 -0
- package/dist/providers/grok/GrokAgentMapper.js +36 -0
- package/dist/providers/grok/GrokAgentMapper.js.map +1 -0
- package/dist/providers/grok/GrokCliAdapter.d.ts +36 -0
- package/dist/providers/grok/GrokCliAdapter.d.ts.map +1 -0
- package/dist/providers/grok/GrokCliAdapter.js +98 -0
- package/dist/providers/grok/GrokCliAdapter.js.map +1 -0
- package/dist/providers/grok/GrokSessionLocator.d.ts +62 -0
- package/dist/providers/grok/GrokSessionLocator.d.ts.map +1 -0
- package/dist/providers/grok/GrokSessionLocator.js +140 -0
- package/dist/providers/grok/GrokSessionLocator.js.map +1 -0
- package/dist/providers/grok/GrokSessionParser.d.ts +54 -0
- package/dist/providers/grok/GrokSessionParser.d.ts.map +1 -0
- package/dist/providers/grok/GrokSessionParser.js +122 -0
- package/dist/providers/grok/GrokSessionParser.js.map +1 -0
- package/dist/providers/opencode/OpenCodeAdapter.d.ts +1 -0
- package/dist/providers/opencode/OpenCodeAdapter.d.ts.map +1 -1
- package/dist/providers/opencode/OpenCodeAdapter.js +3 -0
- package/dist/providers/opencode/OpenCodeAdapter.js.map +1 -1
- package/dist/providers/opencode/OpenCodeSessionLocator.d.ts +2 -0
- package/dist/providers/opencode/OpenCodeSessionLocator.d.ts.map +1 -1
- package/dist/providers/opencode/OpenCodeSessionLocator.js +31 -12
- package/dist/providers/opencode/OpenCodeSessionLocator.js.map +1 -1
- package/dist/providers/pi/PiAdapter.d.ts +1 -0
- package/dist/providers/pi/PiAdapter.d.ts.map +1 -1
- package/dist/providers/pi/PiAdapter.js +10 -0
- package/dist/providers/pi/PiAdapter.js.map +1 -1
- package/dist/providers/pi/PiSessionLocator.d.ts +1 -0
- package/dist/providers/pi/PiSessionLocator.d.ts.map +1 -1
- package/dist/providers/pi/PiSessionLocator.js +8 -1
- package/dist/providers/pi/PiSessionLocator.js.map +1 -1
- package/dist/utils/session.d.ts +2 -0
- package/dist/utils/session.d.ts.map +1 -1
- package/dist/utils/session.js +3 -0
- package/dist/utils/session.js.map +1 -1
- package/package.json +1 -1
- package/src/AgentManager.ts +34 -0
- package/src/__tests__/AgentManager.test.ts +60 -0
- package/src/__tests__/adapters/ClaudeCodeAdapter.test.ts +23 -0
- package/src/__tests__/adapters/CodexAdapter.test.ts +7 -0
- package/src/__tests__/providers/copilot/CopilotAdapter.test.ts +12 -0
- package/src/__tests__/providers/gemini/GeminiCliAdapter.test.ts +21 -0
- package/src/__tests__/providers/grok/GrokAgentMapper.test.ts +57 -0
- package/src/__tests__/{adapters → providers/grok}/GrokCliAdapter.test.ts +18 -9
- package/src/__tests__/providers/grok/GrokSessionLocator.test.ts +106 -0
- package/src/__tests__/providers/opencode/OpenCodeAdapter.test.ts +18 -0
- package/src/__tests__/providers/pi/PiAdapter.test.ts +15 -0
- package/src/__tests__/utils/session.test.ts +11 -1
- package/src/adapters/AgentAdapter.ts +9 -0
- package/src/adapters/index.ts +1 -1
- package/src/index.ts +1 -1
- package/src/providers/claude/ClaudeCodeAdapter.ts +28 -23
- package/src/providers/claude/ClaudeSessionLocator.ts +20 -0
- package/src/providers/codex/CodexAdapter.ts +8 -0
- package/src/providers/copilot/CopilotAdapter.ts +26 -10
- package/src/providers/copilot/CopilotSessionLocator.ts +7 -1
- package/src/providers/gemini/GeminiCliAdapter.ts +8 -0
- package/src/providers/grok/GrokAgentMapper.ts +41 -0
- package/src/providers/grok/GrokCliAdapter.ts +125 -0
- package/src/providers/grok/GrokSessionLocator.ts +179 -0
- package/src/providers/grok/GrokSessionParser.ts +166 -0
- package/src/providers/opencode/OpenCodeAdapter.ts +4 -0
- package/src/providers/opencode/OpenCodeSessionLocator.ts +43 -15
- package/src/providers/pi/PiAdapter.ts +12 -0
- package/src/providers/pi/PiSessionLocator.ts +16 -1
- package/src/utils/session.ts +11 -0
- package/dist/__tests__/adapters/GrokCliAdapter.test.js.map +0 -1
- package/dist/adapters/GrokCliAdapter.d.ts +0 -80
- package/dist/adapters/GrokCliAdapter.d.ts.map +0 -1
- package/dist/adapters/GrokCliAdapter.js +0 -310
- package/dist/adapters/GrokCliAdapter.js.map +0 -1
- package/src/adapters/GrokCliAdapter.ts +0 -408
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/__tests__/adapters/CodexAdapter.test.ts"],"sourcesContent":["import type { MockedFunction } from \"vitest\";\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\n\nimport { CodexAdapter } from \"../../providers/codex/CodexAdapter.js\";\nimport { AgentStatus, type ProcessInfo } from \"../../adapters/AgentAdapter.js\";\nimport { AgentRegistry, type RegistryEntry } from \"../../utils/AgentRegistry.js\";\nimport { batchGetSessionFileBirthtimes, type SessionFile } from \"../../utils/session.js\";\nimport {\n captureProcessSnapshot,\n enrichProcesses,\n listAgentProcesses,\n} from \"../../utils/process.js\";\nimport {\n generateAgentName,\n matchProcessesToSessions,\n type MatchResult,\n} from \"../../utils/matching.js\";\n\nvi.mock(\"../../utils/process.js\", async (importOriginal) => {\n const actual = (await importOriginal()) as typeof import(\"../../utils/process.js\");\n return {\n ...actual,\n listAgentProcesses: vi.fn(),\n enrichProcesses: vi.fn(),\n captureProcessSnapshot: vi.fn(),\n };\n});\n\nvi.mock(\"../../utils/session.js\", async () => {\n const actual = (await vi.importActual(\n \"../../utils/session\",\n )) as typeof import(\"../../utils/session\");\n return {\n ...actual,\n batchGetSessionFileBirthtimes: vi.fn(),\n };\n});\n\nvi.mock(\"../../utils/matching.js\", () => ({\n matchProcessesToSessions: vi.fn(),\n generateAgentName: vi.fn(),\n}));\n\nconst mockedListAgentProcesses = listAgentProcesses as MockedFunction<typeof listAgentProcesses>;\nconst mockedEnrichProcesses = enrichProcesses as MockedFunction<typeof enrichProcesses>;\nconst mockedCaptureProcessSnapshot = captureProcessSnapshot as MockedFunction<\n typeof captureProcessSnapshot\n>;\nconst mockedBatchGetSessionFileBirthtimes = batchGetSessionFileBirthtimes as MockedFunction<\n typeof batchGetSessionFileBirthtimes\n>;\nconst mockedMatchProcessesToSessions = matchProcessesToSessions as MockedFunction<\n typeof matchProcessesToSessions\n>;\nconst mockedGenerateAgentName = generateAgentName as MockedFunction<typeof generateAgentName>;\n\ndescribe(\"CodexAdapter\", () => {\n let originalHome: string | undefined;\n let tmpHome: string;\n let adapter: CodexAdapter;\n\n beforeEach(() => {\n originalHome = process.env.HOME;\n tmpHome = fs.mkdtempSync(path.join(os.tmpdir(), \"codex-adapter-\"));\n process.env.HOME = tmpHome;\n\n adapter = new CodexAdapter(new AgentRegistry(path.join(tmpHome, \"agents.json\")));\n mockedListAgentProcesses.mockReset();\n mockedEnrichProcesses.mockReset();\n mockedCaptureProcessSnapshot.mockReset();\n mockedBatchGetSessionFileBirthtimes.mockReset();\n mockedMatchProcessesToSessions.mockReset();\n mockedGenerateAgentName.mockReset();\n\n mockedEnrichProcesses.mockImplementation((processes) => processes);\n mockedCaptureProcessSnapshot.mockImplementation(async (names) =>\n enrichProcesses(names.flatMap((name) => listAgentProcesses(name))),\n );\n mockedGenerateAgentName.mockImplementation(\n (cwd, pid) => `${path.basename(cwd) || \"unknown\"} (${pid})`,\n );\n });\n\n afterEach(() => {\n process.env.HOME = originalHome;\n fs.rmSync(tmpHome, { recursive: true, force: true });\n });\n\n it(\"exposes codex type and handles Codex executable names only\", () => {\n expect(adapter.type).toBe(\"codex\");\n expect(adapter.canHandle({ pid: 1, command: \"codex\", cwd: \"/repo\", tty: \"ttys001\" })).toBe(\n true,\n );\n expect(\n adapter.canHandle({\n pid: 2,\n command: \"/usr/local/bin/CODEX --sandbox workspace-write\",\n cwd: \"/repo\",\n tty: \"ttys002\",\n }),\n ).toBe(true);\n expect(\n adapter.canHandle({ pid: 3, command: \"node app.js\", cwd: \"/repo\", tty: \"ttys003\" }),\n ).toBe(false);\n expect(\n adapter.canHandle({\n pid: 4,\n command: \"node /worktrees/feature-codex-adapter-agent-manager-package/server.js\",\n cwd: \"/repo\",\n tty: \"ttys004\",\n }),\n ).toBe(false);\n });\n\n it(\"returns no agents when no Codex process is running\", async () => {\n mockedListAgentProcesses.mockReturnValue([]);\n\n await expect(adapter.detectAgents()).resolves.toEqual([]);\n expect(mockedListAgentProcesses).toHaveBeenCalledWith(\"codex\");\n });\n\n it(\"returns process-only agents when no session files are discovered\", async () => {\n const processes: ProcessInfo[] = [\n { pid: 100, command: \"codex\", cwd: \"/repo-a\", tty: \"ttys001\" },\n ];\n mockedListAgentProcesses.mockReturnValue(processes);\n\n await expect(adapter.detectAgents()).resolves.toMatchObject([\n {\n type: \"codex\",\n status: AgentStatus.RUNNING,\n pid: 100,\n projectPath: \"/repo-a\",\n sessionId: \"pid-100\",\n summary: \"Codex process running\",\n },\n ]);\n });\n\n it(\"maps a running Codex process through legacy session matching\", async () => {\n const processInfo: ProcessInfo = {\n pid: 100,\n command: \"codex\",\n cwd: \"/repo-a\",\n tty: \"ttys001\",\n startTime: new Date(\"2026-03-18T15:00:00.000Z\"),\n };\n const { sessionFile, dateDir } = writeSession(\"sess-abc\", \"/repo-a\", [\n {\n type: \"event\",\n timestamp: new Date().toISOString(),\n payload: { type: \"token_count\", message: \"Implement adapter flow\" },\n },\n ]);\n const candidate: SessionFile = {\n sessionId: \"sess-abc\",\n filePath: sessionFile,\n projectDir: dateDir,\n birthtimeMs: new Date(\"2026-03-18T15:00:05Z\").getTime(),\n resolvedCwd: \"\",\n };\n const matches: MatchResult[] = [\n { process: processInfo, session: { ...candidate, resolvedCwd: \"/repo-a\" }, deltaMs: 5000 },\n ];\n\n mockedListAgentProcesses.mockReturnValue([processInfo]);\n mockedBatchGetSessionFileBirthtimes.mockReturnValue([candidate]);\n mockedMatchProcessesToSessions.mockReturnValue(matches);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n type: \"codex\",\n status: AgentStatus.RUNNING,\n pid: 100,\n projectPath: \"/repo-a\",\n sessionId: \"sess-abc\",\n summary: \"Implement adapter flow\",\n });\n });\n\n it(\"maps resumed sessions directly by id\", async () => {\n const sessionId = \"019eabed-4079-7071-9531-b853ddd9914e\";\n const processInfo: ProcessInfo = {\n pid: 88018,\n command: `codex resume ${sessionId}`,\n cwd: \"/repo-a\",\n tty: \"ttys001\",\n startTime: new Date(\"2026-06-10T12:00:00.000Z\"),\n };\n const { sessionFile } = writeSession(\n sessionId,\n \"/repo-a\",\n [\n {\n type: \"event\",\n timestamp: new Date().toISOString(),\n payload: { type: \"agent_message\", message: \"resumed codex conversation\" },\n },\n ],\n \"2026/06/09\",\n );\n\n mockedListAgentProcesses.mockReturnValue([processInfo]);\n mockedBatchGetSessionFileBirthtimes.mockReturnValue([]);\n\n const agents = await adapter.detectAgents();\n\n expect(mockedBatchGetSessionFileBirthtimes).not.toHaveBeenCalled();\n expect(mockedMatchProcessesToSessions).not.toHaveBeenCalled();\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n type: \"codex\",\n pid: 88018,\n sessionId,\n projectPath: \"/repo-a\",\n sessionFilePath: sessionFile,\n summary: \"resumed codex conversation\",\n });\n });\n\n it(\"uses hook session mapping before a stale registry entry for the same pid\", async () => {\n const registry = new AgentRegistry(path.join(tmpHome, \"agents.json\"));\n const staleSession = path.join(tmpHome, \"stale.jsonl\");\n fs.writeFileSync(\n staleSession,\n [\n JSON.stringify({\n type: \"session_meta\",\n payload: { id: \"stale\", timestamp: new Date().toISOString(), cwd: \"/repo-stale\" },\n }),\n JSON.stringify({\n type: \"event\",\n timestamp: new Date().toISOString(),\n payload: { type: \"agent_message\", message: \"stale\" },\n }),\n ].join(\"\\n\"),\n );\n registry.register(registryEntry({ sessionFilePath: staleSession }));\n\n const mappedAdapter = new CodexAdapter(registry);\n const { sessionFile } = writeSession(\n \"current\",\n \"/repo-current\",\n [\n {\n type: \"event\",\n timestamp: new Date().toISOString(),\n payload: { type: \"agent_message\", message: \"Hello from current mapping\" },\n },\n ],\n \"2026/06/26\",\n );\n fs.mkdirSync(path.join(tmpHome, \".codex\", \"ai-devkit\"), { recursive: true });\n fs.writeFileSync(\n path.join(tmpHome, \".codex\", \"ai-devkit\", \"sessions.json\"),\n JSON.stringify({ 100: sessionFile }),\n );\n\n mockedListAgentProcesses.mockReturnValue([\n { pid: 100, command: \"codex\", cwd: \"/repo-current\", tty: \"ttys001\", startTime: new Date() },\n ]);\n\n const agents = await mappedAdapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n pid: 100,\n sessionId: \"current\",\n sessionFilePath: sessionFile,\n summary: \"Hello from current mapping\",\n });\n expect(mockedBatchGetSessionFileBirthtimes).not.toHaveBeenCalled();\n expect(mockedMatchProcessesToSessions).not.toHaveBeenCalled();\n });\n\n it(\"uses a valid registry cache entry before scanning sessions\", async () => {\n const registry = new AgentRegistry(path.join(tmpHome, \"agents.json\"));\n const { sessionFile } = writeSession(\"cached\", \"/repo-a\", [\n {\n type: \"event\",\n timestamp: new Date().toISOString(),\n payload: { type: \"token_count\", message: \"Hello from cache\" },\n },\n ]);\n registry.register(registryEntry({ sessionId: \"cached\", sessionFilePath: sessionFile }));\n\n const cachedAdapter = new CodexAdapter(registry);\n mockedListAgentProcesses.mockReturnValue([\n { pid: 100, command: \"codex\", cwd: \"/repo-a\", tty: \"ttys001\", startTime: new Date() },\n ]);\n\n const agents = await cachedAdapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n type: \"codex\",\n pid: 100,\n sessionId: \"cached\",\n sessionFilePath: sessionFile,\n summary: \"Hello from cache\",\n });\n expect(mockedMatchProcessesToSessions).not.toHaveBeenCalled();\n expect(mockedBatchGetSessionFileBirthtimes).not.toHaveBeenCalled();\n });\n\n it(\"delegates conversation parsing and historical session listing\", async () => {\n const { sessionFile } = writeSession(\n \"listed\",\n \"/repo\",\n [\n {\n type: \"event\",\n timestamp: \"2025-01-01T00:00:01Z\",\n payload: { type: \"user_message\", message: \"first user\" },\n },\n {\n type: \"event\",\n timestamp: \"2025-01-01T00:00:02Z\",\n payload: { type: \"agent_message\", message: \"answer\" },\n },\n ],\n \"2025/01/01\",\n );\n\n expect(adapter.getConversation(sessionFile)).toEqual([\n { role: \"user\", content: \"first user\", timestamp: \"2025-01-01T00:00:01Z\" },\n { role: \"assistant\", content: \"answer\", timestamp: \"2025-01-01T00:00:02Z\" },\n ]);\n await expect(adapter.listSessions({ cwd: \"/repo\" })).resolves.toMatchObject([\n {\n type: \"codex\",\n sessionId: \"listed\",\n cwd: \"/repo\",\n firstUserMessage: \"first user\",\n sessionFilePath: sessionFile,\n },\n ]);\n });\n\n function writeSession(\n sessionId: string,\n cwd: string,\n entries: object[],\n day = \"2026/03/18\",\n ): { sessionFile: string; dateDir: string } {\n const dateDir = path.join(tmpHome, \".codex\", \"sessions\", ...day.split(\"/\"));\n fs.mkdirSync(dateDir, { recursive: true });\n const sessionFile = path.join(dateDir, `${sessionId}.jsonl`);\n fs.writeFileSync(\n sessionFile,\n [\n JSON.stringify({\n type: \"session_meta\",\n payload: { id: sessionId, timestamp: \"2026-03-18T15:00:00Z\", cwd },\n }),\n ...entries.map((entry) => JSON.stringify(entry)),\n ].join(\"\\n\"),\n );\n return { sessionFile, dateDir };\n }\n\n function registryEntry(overrides: Partial<RegistryEntry> = {}): RegistryEntry {\n return {\n name: \"codex-100\",\n type: \"codex\",\n pid: 100,\n runtime: \"tmux\",\n runtimeRef: null,\n cwd: \"/repo-a\",\n startedAt: \"2026-05-30T00:00:00.000Z\",\n sessionId: \"cached\",\n sessionFilePath: \"\",\n ...overrides,\n };\n }\n});\n"],"names":["fs","os","path","CodexAdapter","AgentStatus","AgentRegistry","batchGetSessionFileBirthtimes","captureProcessSnapshot","enrichProcesses","listAgentProcesses","generateAgentName","matchProcessesToSessions","vi","mock","importOriginal","actual","fn","importActual","mockedListAgentProcesses","mockedEnrichProcesses","mockedCaptureProcessSnapshot","mockedBatchGetSessionFileBirthtimes","mockedMatchProcessesToSessions","mockedGenerateAgentName","describe","originalHome","tmpHome","adapter","beforeEach","process","env","HOME","mkdtempSync","join","tmpdir","mockReset","mockImplementation","processes","names","flatMap","name","cwd","pid","basename","afterEach","rmSync","recursive","force","it","expect","type","toBe","canHandle","command","tty","mockReturnValue","detectAgents","resolves","toEqual","toHaveBeenCalledWith","toMatchObject","status","RUNNING","projectPath","sessionId","summary","processInfo","startTime","Date","sessionFile","dateDir","writeSession","timestamp","toISOString","payload","message","candidate","filePath","projectDir","birthtimeMs","getTime","resolvedCwd","matches","session","deltaMs","agents","toHaveLength","not","toHaveBeenCalled","sessionFilePath","registry","staleSession","writeFileSync","JSON","stringify","id","register","registryEntry","mappedAdapter","mkdirSync","cachedAdapter","getConversation","role","content","listSessions","firstUserMessage","entries","day","split","map","entry","overrides","runtime","runtimeRef","startedAt"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/__tests__/adapters/CodexAdapter.test.ts"],"sourcesContent":["import type { MockedFunction } from \"vitest\";\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\n\nimport { CodexAdapter } from \"../../providers/codex/CodexAdapter.js\";\nimport { AgentStatus, type ProcessInfo } from \"../../adapters/AgentAdapter.js\";\nimport { AgentRegistry, type RegistryEntry } from \"../../utils/AgentRegistry.js\";\nimport { batchGetSessionFileBirthtimes, type SessionFile } from \"../../utils/session.js\";\nimport {\n captureProcessSnapshot,\n enrichProcesses,\n listAgentProcesses,\n} from \"../../utils/process.js\";\nimport {\n generateAgentName,\n matchProcessesToSessions,\n type MatchResult,\n} from \"../../utils/matching.js\";\n\nvi.mock(\"../../utils/process.js\", async (importOriginal) => {\n const actual = (await importOriginal()) as typeof import(\"../../utils/process.js\");\n return {\n ...actual,\n listAgentProcesses: vi.fn(),\n enrichProcesses: vi.fn(),\n captureProcessSnapshot: vi.fn(),\n };\n});\n\nvi.mock(\"../../utils/session.js\", async () => {\n const actual = (await vi.importActual(\n \"../../utils/session\",\n )) as typeof import(\"../../utils/session\");\n return {\n ...actual,\n batchGetSessionFileBirthtimes: vi.fn(),\n };\n});\n\nvi.mock(\"../../utils/matching.js\", () => ({\n matchProcessesToSessions: vi.fn(),\n generateAgentName: vi.fn(),\n}));\n\nconst mockedListAgentProcesses = listAgentProcesses as MockedFunction<typeof listAgentProcesses>;\nconst mockedEnrichProcesses = enrichProcesses as MockedFunction<typeof enrichProcesses>;\nconst mockedCaptureProcessSnapshot = captureProcessSnapshot as MockedFunction<\n typeof captureProcessSnapshot\n>;\nconst mockedBatchGetSessionFileBirthtimes = batchGetSessionFileBirthtimes as MockedFunction<\n typeof batchGetSessionFileBirthtimes\n>;\nconst mockedMatchProcessesToSessions = matchProcessesToSessions as MockedFunction<\n typeof matchProcessesToSessions\n>;\nconst mockedGenerateAgentName = generateAgentName as MockedFunction<typeof generateAgentName>;\n\ndescribe(\"CodexAdapter\", () => {\n let originalHome: string | undefined;\n let tmpHome: string;\n let adapter: CodexAdapter;\n\n beforeEach(() => {\n originalHome = process.env.HOME;\n tmpHome = fs.mkdtempSync(path.join(os.tmpdir(), \"codex-adapter-\"));\n process.env.HOME = tmpHome;\n\n adapter = new CodexAdapter(new AgentRegistry(path.join(tmpHome, \"agents.json\")));\n mockedListAgentProcesses.mockReset();\n mockedEnrichProcesses.mockReset();\n mockedCaptureProcessSnapshot.mockReset();\n mockedBatchGetSessionFileBirthtimes.mockReset();\n mockedMatchProcessesToSessions.mockReset();\n mockedGenerateAgentName.mockReset();\n\n mockedEnrichProcesses.mockImplementation((processes) => processes);\n mockedCaptureProcessSnapshot.mockImplementation(async (names) =>\n enrichProcesses(names.flatMap((name) => listAgentProcesses(name))),\n );\n mockedGenerateAgentName.mockImplementation(\n (cwd, pid) => `${path.basename(cwd) || \"unknown\"} (${pid})`,\n );\n });\n\n afterEach(() => {\n process.env.HOME = originalHome;\n fs.rmSync(tmpHome, { recursive: true, force: true });\n });\n\n it(\"exposes codex type and handles Codex executable names only\", () => {\n expect(adapter.type).toBe(\"codex\");\n expect(adapter.canHandle({ pid: 1, command: \"codex\", cwd: \"/repo\", tty: \"ttys001\" })).toBe(\n true,\n );\n expect(\n adapter.canHandle({\n pid: 2,\n command: \"/usr/local/bin/CODEX --sandbox workspace-write\",\n cwd: \"/repo\",\n tty: \"ttys002\",\n }),\n ).toBe(true);\n expect(\n adapter.canHandle({ pid: 3, command: \"node app.js\", cwd: \"/repo\", tty: \"ttys003\" }),\n ).toBe(false);\n expect(\n adapter.canHandle({\n pid: 4,\n command: \"node /worktrees/feature-codex-adapter-agent-manager-package/server.js\",\n cwd: \"/repo\",\n tty: \"ttys004\",\n }),\n ).toBe(false);\n });\n\n it(\"returns no agents when no Codex process is running\", async () => {\n mockedListAgentProcesses.mockReturnValue([]);\n\n await expect(adapter.detectAgents()).resolves.toEqual([]);\n expect(mockedListAgentProcesses).toHaveBeenCalledWith(\"codex\");\n });\n\n it(\"returns process-only agents when no session files are discovered\", async () => {\n const processes: ProcessInfo[] = [\n { pid: 100, command: \"codex\", cwd: \"/repo-a\", tty: \"ttys001\" },\n ];\n mockedListAgentProcesses.mockReturnValue(processes);\n\n await expect(adapter.detectAgents()).resolves.toMatchObject([\n {\n type: \"codex\",\n status: AgentStatus.RUNNING,\n pid: 100,\n projectPath: \"/repo-a\",\n sessionId: \"pid-100\",\n summary: \"Codex process running\",\n },\n ]);\n });\n\n it(\"maps a running Codex process through legacy session matching\", async () => {\n const processInfo: ProcessInfo = {\n pid: 100,\n command: \"codex\",\n cwd: \"/repo-a\",\n tty: \"ttys001\",\n startTime: new Date(\"2026-03-18T15:00:00.000Z\"),\n };\n const { sessionFile, dateDir } = writeSession(\"sess-abc\", \"/repo-a\", [\n {\n type: \"event\",\n timestamp: new Date().toISOString(),\n payload: { type: \"token_count\", message: \"Implement adapter flow\" },\n },\n ]);\n const candidate: SessionFile = {\n sessionId: \"sess-abc\",\n filePath: sessionFile,\n projectDir: dateDir,\n birthtimeMs: new Date(\"2026-03-18T15:00:05Z\").getTime(),\n resolvedCwd: \"\",\n };\n const matches: MatchResult[] = [\n { process: processInfo, session: { ...candidate, resolvedCwd: \"/repo-a\" }, deltaMs: 5000 },\n ];\n\n mockedListAgentProcesses.mockReturnValue([processInfo]);\n mockedBatchGetSessionFileBirthtimes.mockReturnValue([candidate]);\n mockedMatchProcessesToSessions.mockReturnValue(matches);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n type: \"codex\",\n status: AgentStatus.RUNNING,\n pid: 100,\n projectPath: \"/repo-a\",\n sessionId: \"sess-abc\",\n summary: \"Implement adapter flow\",\n });\n });\n\n it(\"maps resumed sessions directly by id\", async () => {\n const sessionId = \"019eabed-4079-7071-9531-b853ddd9914e\";\n const processInfo: ProcessInfo = {\n pid: 88018,\n command: `codex resume ${sessionId}`,\n cwd: \"/repo-a\",\n tty: \"ttys001\",\n startTime: new Date(\"2026-06-10T12:00:00.000Z\"),\n };\n const { sessionFile } = writeSession(\n sessionId,\n \"/repo-a\",\n [\n {\n type: \"event\",\n timestamp: new Date().toISOString(),\n payload: { type: \"agent_message\", message: \"resumed codex conversation\" },\n },\n ],\n \"2026/06/09\",\n );\n\n mockedListAgentProcesses.mockReturnValue([processInfo]);\n mockedBatchGetSessionFileBirthtimes.mockReturnValue([]);\n\n const agents = await adapter.detectAgents();\n\n expect(mockedBatchGetSessionFileBirthtimes).not.toHaveBeenCalled();\n expect(mockedMatchProcessesToSessions).not.toHaveBeenCalled();\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n type: \"codex\",\n pid: 88018,\n sessionId,\n projectPath: \"/repo-a\",\n sessionFilePath: sessionFile,\n summary: \"resumed codex conversation\",\n });\n });\n\n it(\"uses hook session mapping before a stale registry entry for the same pid\", async () => {\n const registry = new AgentRegistry(path.join(tmpHome, \"agents.json\"));\n const staleSession = path.join(tmpHome, \"stale.jsonl\");\n fs.writeFileSync(\n staleSession,\n [\n JSON.stringify({\n type: \"session_meta\",\n payload: { id: \"stale\", timestamp: new Date().toISOString(), cwd: \"/repo-stale\" },\n }),\n JSON.stringify({\n type: \"event\",\n timestamp: new Date().toISOString(),\n payload: { type: \"agent_message\", message: \"stale\" },\n }),\n ].join(\"\\n\"),\n );\n registry.register(registryEntry({ sessionFilePath: staleSession }));\n\n const mappedAdapter = new CodexAdapter(registry);\n const { sessionFile } = writeSession(\n \"current\",\n \"/repo-current\",\n [\n {\n type: \"event\",\n timestamp: new Date().toISOString(),\n payload: { type: \"agent_message\", message: \"Hello from current mapping\" },\n },\n ],\n \"2026/06/26\",\n );\n fs.mkdirSync(path.join(tmpHome, \".codex\", \"ai-devkit\"), { recursive: true });\n fs.writeFileSync(\n path.join(tmpHome, \".codex\", \"ai-devkit\", \"sessions.json\"),\n JSON.stringify({ 100: sessionFile }),\n );\n\n mockedListAgentProcesses.mockReturnValue([\n { pid: 100, command: \"codex\", cwd: \"/repo-current\", tty: \"ttys001\", startTime: new Date() },\n ]);\n\n const agents = await mappedAdapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n pid: 100,\n sessionId: \"current\",\n sessionFilePath: sessionFile,\n summary: \"Hello from current mapping\",\n });\n expect(mockedBatchGetSessionFileBirthtimes).not.toHaveBeenCalled();\n expect(mockedMatchProcessesToSessions).not.toHaveBeenCalled();\n });\n\n it(\"uses a valid registry cache entry before scanning sessions\", async () => {\n const registry = new AgentRegistry(path.join(tmpHome, \"agents.json\"));\n const { sessionFile } = writeSession(\"cached\", \"/repo-a\", [\n {\n type: \"event\",\n timestamp: new Date().toISOString(),\n payload: { type: \"token_count\", message: \"Hello from cache\" },\n },\n ]);\n registry.register(registryEntry({ sessionId: \"cached\", sessionFilePath: sessionFile }));\n\n const cachedAdapter = new CodexAdapter(registry);\n mockedListAgentProcesses.mockReturnValue([\n { pid: 100, command: \"codex\", cwd: \"/repo-a\", tty: \"ttys001\", startTime: new Date() },\n ]);\n\n const agents = await cachedAdapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n type: \"codex\",\n pid: 100,\n sessionId: \"cached\",\n sessionFilePath: sessionFile,\n summary: \"Hello from cache\",\n });\n expect(mockedMatchProcessesToSessions).not.toHaveBeenCalled();\n expect(mockedBatchGetSessionFileBirthtimes).not.toHaveBeenCalled();\n });\n\n it(\"delegates conversation parsing and historical session listing\", async () => {\n const { sessionFile } = writeSession(\n \"listed\",\n \"/repo\",\n [\n {\n type: \"event\",\n timestamp: \"2025-01-01T00:00:01Z\",\n payload: { type: \"user_message\", message: \"first user\" },\n },\n {\n type: \"event\",\n timestamp: \"2025-01-01T00:00:02Z\",\n payload: { type: \"agent_message\", message: \"answer\" },\n },\n ],\n \"2025/01/01\",\n );\n\n expect(adapter.getConversation(sessionFile)).toEqual([\n { role: \"user\", content: \"first user\", timestamp: \"2025-01-01T00:00:01Z\" },\n { role: \"assistant\", content: \"answer\", timestamp: \"2025-01-01T00:00:02Z\" },\n ]);\n await expect(adapter.listSessions({ cwd: \"/repo\" })).resolves.toMatchObject([\n {\n type: \"codex\",\n sessionId: \"listed\",\n cwd: \"/repo\",\n firstUserMessage: \"first user\",\n sessionFilePath: sessionFile,\n },\n ]);\n await expect(adapter.findSessionsById(\"listed\")).resolves.toMatchObject([\n {\n type: \"codex\",\n sessionId: \"listed\",\n sessionFilePath: sessionFile,\n },\n ]);\n });\n\n function writeSession(\n sessionId: string,\n cwd: string,\n entries: object[],\n day = \"2026/03/18\",\n ): { sessionFile: string; dateDir: string } {\n const dateDir = path.join(tmpHome, \".codex\", \"sessions\", ...day.split(\"/\"));\n fs.mkdirSync(dateDir, { recursive: true });\n const sessionFile = path.join(dateDir, `${sessionId}.jsonl`);\n fs.writeFileSync(\n sessionFile,\n [\n JSON.stringify({\n type: \"session_meta\",\n payload: { id: sessionId, timestamp: \"2026-03-18T15:00:00Z\", cwd },\n }),\n ...entries.map((entry) => JSON.stringify(entry)),\n ].join(\"\\n\"),\n );\n return { sessionFile, dateDir };\n }\n\n function registryEntry(overrides: Partial<RegistryEntry> = {}): RegistryEntry {\n return {\n name: \"codex-100\",\n type: \"codex\",\n pid: 100,\n runtime: \"tmux\",\n runtimeRef: null,\n cwd: \"/repo-a\",\n startedAt: \"2026-05-30T00:00:00.000Z\",\n sessionId: \"cached\",\n sessionFilePath: \"\",\n ...overrides,\n };\n }\n});\n"],"names":["fs","os","path","CodexAdapter","AgentStatus","AgentRegistry","batchGetSessionFileBirthtimes","captureProcessSnapshot","enrichProcesses","listAgentProcesses","generateAgentName","matchProcessesToSessions","vi","mock","importOriginal","actual","fn","importActual","mockedListAgentProcesses","mockedEnrichProcesses","mockedCaptureProcessSnapshot","mockedBatchGetSessionFileBirthtimes","mockedMatchProcessesToSessions","mockedGenerateAgentName","describe","originalHome","tmpHome","adapter","beforeEach","process","env","HOME","mkdtempSync","join","tmpdir","mockReset","mockImplementation","processes","names","flatMap","name","cwd","pid","basename","afterEach","rmSync","recursive","force","it","expect","type","toBe","canHandle","command","tty","mockReturnValue","detectAgents","resolves","toEqual","toHaveBeenCalledWith","toMatchObject","status","RUNNING","projectPath","sessionId","summary","processInfo","startTime","Date","sessionFile","dateDir","writeSession","timestamp","toISOString","payload","message","candidate","filePath","projectDir","birthtimeMs","getTime","resolvedCwd","matches","session","deltaMs","agents","toHaveLength","not","toHaveBeenCalled","sessionFilePath","registry","staleSession","writeFileSync","JSON","stringify","id","register","registryEntry","mappedAdapter","mkdirSync","cachedAdapter","getConversation","role","content","listSessions","firstUserMessage","findSessionsById","entries","day","split","map","entry","overrides","runtime","runtimeRef","startedAt"],"mappings":"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"}
|
|
@@ -585,6 +585,24 @@ describe("CopilotAdapter", ()=>{
|
|
|
585
585
|
firstUserMessage: "other user"
|
|
586
586
|
});
|
|
587
587
|
});
|
|
588
|
+
it("finds an exact session ID from its session directory", async ()=>{
|
|
589
|
+
writeSession("wanted", {
|
|
590
|
+
events: [
|
|
591
|
+
sessionStart("wanted", "/repo")
|
|
592
|
+
]
|
|
593
|
+
});
|
|
594
|
+
writeSession("other", {
|
|
595
|
+
events: [
|
|
596
|
+
sessionStart("other", "/other")
|
|
597
|
+
]
|
|
598
|
+
});
|
|
599
|
+
await expect(adapter.findSessionsById("wanted")).resolves.toEqual([
|
|
600
|
+
expect.objectContaining({
|
|
601
|
+
sessionId: "wanted",
|
|
602
|
+
sessionFilePath: path.join(sessionStateDir, "wanted", "events.jsonl")
|
|
603
|
+
})
|
|
604
|
+
]);
|
|
605
|
+
});
|
|
588
606
|
it("applies strict cwd filter", async ()=>{
|
|
589
607
|
writeSession("keep", {
|
|
590
608
|
events: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/__tests__/providers/copilot/CopilotAdapter.test.ts"],"sourcesContent":["/**\n * Tests for CopilotAdapter\n */\n\nimport type { MockedFunction } from \"vitest\";\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\n\nimport { CopilotAdapter } from \"../../../providers/copilot/CopilotAdapter.js\";\nimport type { ProcessInfo } from \"../../../adapters/AgentAdapter.js\";\nimport { AgentStatus } from \"../../../adapters/AgentAdapter.js\";\nimport {\n listAgentProcesses,\n enrichProcesses,\n captureProcessSnapshot,\n} from \"../../../utils/process.js\";\nimport { generateAgentName } from \"../../../utils/matching.js\";\nimport { AgentRegistry } from \"../../../utils/AgentRegistry.js\";\n\nvi.mock(\"../../../utils/process.js\", async (importOriginal) => {\n const actual = (await importOriginal()) as typeof import(\"../../../utils/process.js\");\n return {\n ...actual,\n listAgentProcesses: vi.fn(),\n enrichProcesses: vi.fn(),\n captureProcessSnapshot: vi.fn(),\n };\n});\n\nvi.mock(\"../../../utils/matching.js\", () => ({\n generateAgentName: vi.fn(),\n}));\n\nconst mockedListAgentProcesses = listAgentProcesses as MockedFunction<typeof listAgentProcesses>;\nconst mockedEnrichProcesses = enrichProcesses as MockedFunction<typeof enrichProcesses>;\nconst mockedCaptureProcessSnapshot = captureProcessSnapshot as MockedFunction<\n typeof captureProcessSnapshot\n>;\nconst mockedGenerateAgentName = generateAgentName as MockedFunction<typeof generateAgentName>;\n\ndescribe(\"CopilotAdapter\", () => {\n let adapter: CopilotAdapter;\n let tmpDir: string;\n let sessionStateDir: string;\n\n beforeEach(() => {\n tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"copilot-test-\"));\n sessionStateDir = path.join(tmpDir, \"session-state\");\n fs.mkdirSync(sessionStateDir, { recursive: true });\n adapter = new CopilotAdapter(undefined, { sessionStateDir });\n\n mockedListAgentProcesses.mockReset();\n mockedEnrichProcesses.mockReset();\n mockedCaptureProcessSnapshot.mockReset();\n mockedGenerateAgentName.mockReset();\n mockedEnrichProcesses.mockImplementation((procs) => procs);\n // Compatibility shim for standalone adapter discovery; the manager captures once and slices by name.\n mockedCaptureProcessSnapshot.mockImplementation(async (names) =>\n enrichProcesses(names.flatMap((name) => listAgentProcesses(name))),\n );\n mockedGenerateAgentName.mockImplementation(\n (cwd, pid) => `${path.basename(cwd) || \"unknown\"} (${pid})`,\n );\n });\n\n afterEach(() => {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n });\n\n function writeSession(\n sessionId: string,\n options: {\n events?: Array<object | string>;\n workspace?: Record<string, string>;\n lockPid?: number | string;\n },\n ): string {\n const sessionDir = path.join(sessionStateDir, sessionId);\n fs.mkdirSync(sessionDir, { recursive: true });\n\n if (options.events) {\n const lines = options.events.map((entry) =>\n typeof entry === \"string\" ? entry : JSON.stringify(entry),\n );\n fs.writeFileSync(path.join(sessionDir, \"events.jsonl\"), lines.join(\"\\n\"));\n }\n\n if (options.workspace) {\n const lines = Object.entries(options.workspace).map(([key, value]) => `${key}: ${value}`);\n fs.writeFileSync(path.join(sessionDir, \"workspace.yaml\"), lines.join(\"\\n\"));\n }\n\n if (options.lockPid !== undefined) {\n fs.writeFileSync(path.join(sessionDir, `inuse.${options.lockPid}.lock`), \"\");\n }\n\n return sessionDir;\n }\n\n function sessionStart(\n sessionId: string,\n cwd: string,\n startTime = \"2026-06-09T09:50:00.000Z\",\n ): object {\n return {\n type: \"session.start\",\n data: {\n sessionId,\n startTime,\n context: {\n cwd,\n gitRoot: cwd,\n branch: \"main\",\n },\n },\n timestamp: startTime,\n };\n }\n\n describe(\"initialization\", () => {\n it(\"exposes copilot type\", () => {\n expect(adapter.type).toBe(\"copilot\");\n });\n });\n\n describe(\"canHandle\", () => {\n it(\"returns true for copilot commands\", () => {\n expect(adapter.canHandle({ pid: 1, command: \"copilot\", cwd: \"/repo\", tty: \"ttys001\" })).toBe(\n true,\n );\n });\n\n it(\"returns true for full-path Homebrew copilot commands\", () => {\n expect(\n adapter.canHandle({\n pid: 2,\n command: \"/opt/homebrew/Caskroom/copilot-cli/1.0.60/copilot\",\n cwd: \"/repo\",\n tty: \"ttys002\",\n }),\n ).toBe(true);\n });\n\n it(\"returns true for copilot.exe commands\", () => {\n expect(\n adapter.canHandle({\n pid: 3,\n command: \"/usr/bin/copilot.exe\",\n cwd: \"/repo\",\n tty: \"ttys003\",\n }),\n ).toBe(true);\n });\n\n it(\"returns false when copilot appears only in an argument\", () => {\n expect(\n adapter.canHandle({\n pid: 4,\n command: \"node /repo/copilot-plugin/index.js\",\n cwd: \"/repo\",\n tty: \"ttys004\",\n }),\n ).toBe(false);\n });\n });\n\n describe(\"detectAgents\", () => {\n it(\"returns empty list when no copilot process is running\", async () => {\n mockedListAgentProcesses.mockReturnValue([]);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toEqual([]);\n expect(mockedListAgentProcesses).toHaveBeenCalledWith(\"copilot\");\n });\n\n it(\"maps matching inuse lock and events to an active agent\", async () => {\n const processes: ProcessInfo[] = [\n {\n pid: 14096,\n command: \"/opt/homebrew/Caskroom/copilot-cli/1.0.60/copilot\",\n cwd: \"/repo\",\n tty: \"ttys001\",\n },\n ];\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n writeSession(\"sess-a\", {\n lockPid: 14096,\n events: [\n sessionStart(\"sess-a\", \"/repo\", \"2026-06-09T09:50:00.000Z\"),\n {\n type: \"user.message\",\n data: { content: \"Build the Copilot adapter\" },\n timestamp: new Date().toISOString(),\n },\n {\n type: \"assistant.message\",\n data: { content: \"I will inspect the code.\" },\n timestamp: new Date().toISOString(),\n },\n ],\n workspace: {\n id: \"sess-a\",\n cwd: \"/fallback\",\n name: \"Fallback Name\",\n created_at: \"2026-06-09T09:49:00.000Z\",\n updated_at: \"2026-06-09T09:51:00.000Z\",\n },\n });\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n type: \"copilot\",\n status: AgentStatus.WAITING,\n pid: 14096,\n projectPath: \"/repo\",\n sessionId: \"sess-a\",\n summary: \"Build the Copilot adapter\",\n sessionFilePath: path.join(sessionStateDir, \"sess-a\", \"events.jsonl\"),\n });\n });\n\n it(\"ignores invalid and unmatched lock PIDs\", async () => {\n const processes: ProcessInfo[] = [\n { pid: 100, command: \"copilot\", cwd: \"/repo\", tty: \"ttys001\" },\n ];\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n writeSession(\"invalid\", {\n lockPid: \"not-a-pid\",\n events: [sessionStart(\"invalid\", \"/invalid\")],\n });\n writeSession(\"unmatched\", {\n lockPid: 999999,\n events: [sessionStart(\"unmatched\", \"/unmatched\")],\n });\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n pid: 100,\n sessionId: \"pid-100\",\n summary: \"Copilot process running\",\n });\n });\n\n it(\"falls back to process-only agent when no session lock matches\", async () => {\n const processes: ProcessInfo[] = [\n { pid: 200, command: \"copilot\", cwd: \"/repo-b\", tty: \"ttys002\" },\n ];\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n type: \"copilot\",\n status: AgentStatus.RUNNING,\n pid: 200,\n projectPath: \"/repo-b\",\n sessionId: \"pid-200\",\n summary: \"Copilot process running\",\n });\n });\n\n it(\"suppresses wrapper process-only agents before the session lock exists\", async () => {\n const processes: ProcessInfo[] = [\n { pid: 86800, command: \"copilot\", cwd: \"/repo\", tty: \"ttys001\", ppid: 84174 },\n {\n pid: 86810,\n command: \"/custom/install/copilot\",\n cwd: \"/repo\",\n tty: \"ttys001\",\n ppid: 86800,\n },\n ];\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n pid: 86810,\n sessionId: \"pid-86810\",\n summary: \"Copilot process running\",\n });\n });\n\n it(\"carries the managed wrapper name to a process-only child before the session lock exists\", async () => {\n const registry = new AgentRegistry(path.join(tmpDir, \"agents.json\"));\n adapter = new CopilotAdapter(registry, { sessionStateDir });\n const processes: ProcessInfo[] = [\n { pid: 86800, command: \"copilot\", cwd: \"/repo\", tty: \"ttys001\", ppid: 84174 },\n {\n pid: 86810,\n command: \"/custom/install/copilot\",\n cwd: \"/repo\",\n tty: \"ttys001\",\n ppid: 86800,\n },\n ];\n registry.register({\n name: \"copilot-started\",\n type: \"copilot\",\n pid: 86800,\n runtime: \"tmux\",\n runtimeRef: { session: \"copilot-started\" },\n cwd: \"/repo\",\n startedAt: \"2026-06-13T19:15:16.211Z\",\n sessionId: \"pid-86800\",\n sessionFilePath: \"\",\n });\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n name: \"copilot-started\",\n pid: 86810,\n sessionId: \"pid-86810\",\n });\n });\n\n it(\"does not add duplicate process-only agent for wrapper process in the same terminal\", async () => {\n const processes: ProcessInfo[] = [\n { pid: 14095, command: \"copilot\", cwd: \"/repo\", tty: \"ttys001\" },\n {\n pid: 14096,\n command: \"/opt/homebrew/Caskroom/copilot-cli/1.0.60/copilot\",\n cwd: \"/repo\",\n tty: \"ttys001\",\n },\n ];\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n writeSession(\"sess-wrapper\", {\n lockPid: 14096,\n events: [\n sessionStart(\"sess-wrapper\", \"/repo\", \"2026-06-09T09:50:00.000Z\"),\n { type: \"user.message\", data: { content: \"hello\" }, timestamp: new Date().toISOString() },\n ],\n });\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n pid: 14096,\n sessionId: \"sess-wrapper\",\n });\n });\n\n it(\"carries the managed wrapper name to a lock-backed child process\", async () => {\n const registry = new AgentRegistry(path.join(tmpDir, \"agents.json\"));\n adapter = new CopilotAdapter(registry, { sessionStateDir });\n const processes: ProcessInfo[] = [\n { pid: 14095, command: \"copilot\", cwd: \"/repo\", tty: \"ttys001\", ppid: 84174 },\n {\n pid: 14096,\n command: \"/opt/homebrew/Caskroom/copilot-cli/1.0.60/copilot\",\n cwd: \"/repo\",\n tty: \"ttys001\",\n ppid: 14095,\n },\n ];\n registry.register({\n name: \"copilot-started\",\n type: \"copilot\",\n pid: 14095,\n runtime: \"tmux\",\n runtimeRef: { session: \"copilot-started\" },\n cwd: \"/repo\",\n startedAt: \"2026-06-13T19:15:16.211Z\",\n sessionId: \"pid-14095\",\n sessionFilePath: \"\",\n });\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n writeSession(\"sess-wrapper\", {\n lockPid: 14096,\n events: [\n sessionStart(\"sess-wrapper\", \"/repo\", \"2026-06-09T09:50:00.000Z\"),\n { type: \"user.message\", data: { content: \"hello\" }, timestamp: new Date().toISOString() },\n ],\n });\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n name: \"copilot-started\",\n pid: 14096,\n sessionId: \"sess-wrapper\",\n });\n });\n\n it(\"uses workspace metadata when events are missing\", async () => {\n const processes: ProcessInfo[] = [\n { pid: 300, command: \"copilot\", cwd: \"/proc-cwd\", tty: \"ttys003\" },\n ];\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n writeSession(\"workspace-only\", {\n lockPid: 300,\n workspace: {\n id: \"workspace-only\",\n cwd: \"/workspace-cwd\",\n name: \"Workspace Session\",\n created_at: \"2026-06-09T09:00:00.000Z\",\n updated_at: \"2026-06-09T09:10:00.000Z\",\n },\n });\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n pid: 300,\n projectPath: \"/workspace-cwd\",\n sessionId: \"workspace-only\",\n summary: \"Workspace Session\",\n });\n });\n });\n\n describe(\"getConversation\", () => {\n it(\"parses user and assistant message events\", () => {\n const sessionDir = writeSession(\"conv\", {\n events: [\n sessionStart(\"conv\", \"/repo\"),\n {\n type: \"user.message\",\n data: { content: \"hello\" },\n timestamp: \"2026-06-09T09:50:01.000Z\",\n },\n {\n type: \"assistant.message\",\n data: { content: \"Hi there\" },\n timestamp: \"2026-06-09T09:50:02.000Z\",\n },\n ],\n });\n\n const messages = adapter.getConversation(path.join(sessionDir, \"events.jsonl\"));\n\n expect(messages).toEqual([\n { role: \"user\", content: \"hello\", timestamp: \"2026-06-09T09:50:01.000Z\" },\n { role: \"assistant\", content: \"Hi there\", timestamp: \"2026-06-09T09:50:02.000Z\" },\n ]);\n });\n\n it(\"includes system/info/warning messages only in verbose mode\", () => {\n const sessionDir = writeSession(\"verbose\", {\n events: [\n {\n type: \"session.warning\",\n data: { message: \"MCP failed\" },\n timestamp: \"2026-06-09T09:50:01.000Z\",\n },\n {\n type: \"tool.execution_complete\",\n data: { result: { content: \"Tool result\" } },\n timestamp: \"2026-06-09T09:50:02.000Z\",\n },\n ],\n });\n const filePath = path.join(sessionDir, \"events.jsonl\");\n\n expect(adapter.getConversation(filePath)).toEqual([]);\n expect(adapter.getConversation(filePath, { verbose: true })).toEqual([\n { role: \"system\", content: \"MCP failed\", timestamp: \"2026-06-09T09:50:01.000Z\" },\n { role: \"system\", content: \"Tool result\", timestamp: \"2026-06-09T09:50:02.000Z\" },\n ]);\n });\n\n it(\"skips malformed JSONL lines and missing text\", () => {\n const sessionDir = writeSession(\"malformed\", {\n events: [\n \"not json\",\n {\n type: \"user.message\",\n data: { content: \"valid\" },\n timestamp: \"2026-06-09T09:50:01.000Z\",\n },\n { type: \"assistant.message\", data: {}, timestamp: \"2026-06-09T09:50:02.000Z\" },\n ],\n });\n\n const messages = adapter.getConversation(path.join(sessionDir, \"events.jsonl\"));\n\n expect(messages).toEqual([\n { role: \"user\", content: \"valid\", timestamp: \"2026-06-09T09:50:01.000Z\" },\n ]);\n });\n\n it(\"returns empty array for missing file\", () => {\n expect(adapter.getConversation(path.join(tmpDir, \"missing.jsonl\"))).toEqual([]);\n });\n });\n\n describe(\"listSessions\", () => {\n it(\"returns historical sessions without active locks\", async () => {\n writeSession(\"history-a\", {\n events: [\n sessionStart(\"history-a\", \"/repo-a\", \"2026-06-09T09:00:00.000Z\"),\n {\n type: \"user.message\",\n data: { content: \"first user\" },\n timestamp: \"2026-06-09T09:00:01.000Z\",\n },\n {\n type: \"assistant.message\",\n data: { content: \"answer\" },\n timestamp: \"2026-06-09T09:00:02.000Z\",\n },\n ],\n });\n writeSession(\"history-b\", {\n events: [\n sessionStart(\"history-b\", \"/repo-b\", \"2026-06-09T10:00:00.000Z\"),\n {\n type: \"user.message\",\n data: { content: \"other user\" },\n timestamp: \"2026-06-09T10:00:01.000Z\",\n },\n ],\n });\n\n const sessions = await adapter.listSessions();\n\n expect(sessions).toHaveLength(2);\n const byId = Object.fromEntries(sessions.map((session) => [session.sessionId, session]));\n expect(byId[\"history-a\"]).toMatchObject({\n type: \"copilot\",\n cwd: \"/repo-a\",\n firstUserMessage: \"first user\",\n sessionFilePath: path.join(sessionStateDir, \"history-a\", \"events.jsonl\"),\n });\n expect(byId[\"history-b\"]).toMatchObject({\n type: \"copilot\",\n cwd: \"/repo-b\",\n firstUserMessage: \"other user\",\n });\n });\n\n it(\"applies strict cwd filter\", async () => {\n writeSession(\"keep\", { events: [sessionStart(\"keep\", \"/repo\")] });\n writeSession(\"drop\", { events: [sessionStart(\"drop\", \"/other\")] });\n\n const sessions = await adapter.listSessions({ cwd: \"/repo\" });\n\n expect(sessions).toHaveLength(1);\n expect(sessions[0].sessionId).toBe(\"keep\");\n });\n\n it(\"uses workspace fallback for historical sessions without events\", async () => {\n writeSession(\"workspace-history\", {\n workspace: {\n id: \"workspace-history\",\n cwd: \"/workspace-repo\",\n name: \"Workspace History\",\n created_at: \"2026-06-09T08:00:00.000Z\",\n updated_at: \"2026-06-09T08:10:00.000Z\",\n },\n });\n\n const sessions = await adapter.listSessions();\n\n expect(sessions).toHaveLength(1);\n expect(sessions[0]).toMatchObject({\n type: \"copilot\",\n sessionId: \"workspace-history\",\n cwd: \"/workspace-repo\",\n firstUserMessage: \"\",\n sessionFilePath: path.join(sessionStateDir, \"workspace-history\", \"events.jsonl\"),\n });\n });\n\n it(\"skips session directories without events or workspace metadata\", async () => {\n fs.mkdirSync(path.join(sessionStateDir, \"empty\"), { recursive: true });\n\n const sessions = await adapter.listSessions();\n\n expect(sessions).toEqual([]);\n });\n\n it(\"returns empty when session-state directory does not exist\", async () => {\n adapter = new CopilotAdapter(undefined, { sessionStateDir: path.join(tmpDir, \"missing\") });\n\n await expect(adapter.listSessions()).resolves.toEqual([]);\n });\n });\n});\n"],"names":["fs","os","path","CopilotAdapter","AgentStatus","listAgentProcesses","enrichProcesses","captureProcessSnapshot","generateAgentName","AgentRegistry","vi","mock","importOriginal","actual","fn","mockedListAgentProcesses","mockedEnrichProcesses","mockedCaptureProcessSnapshot","mockedGenerateAgentName","describe","adapter","tmpDir","sessionStateDir","beforeEach","mkdtempSync","join","tmpdir","mkdirSync","recursive","undefined","mockReset","mockImplementation","procs","names","flatMap","name","cwd","pid","basename","afterEach","rmSync","force","writeSession","sessionId","options","sessionDir","events","lines","map","entry","JSON","stringify","writeFileSync","workspace","Object","entries","key","value","lockPid","sessionStart","startTime","type","data","context","gitRoot","branch","timestamp","it","expect","toBe","canHandle","command","tty","mockReturnValue","agents","detectAgents","toEqual","toHaveBeenCalledWith","processes","content","Date","toISOString","id","created_at","updated_at","toHaveLength","toMatchObject","status","WAITING","projectPath","summary","sessionFilePath","RUNNING","ppid","registry","register","runtime","runtimeRef","session","startedAt","messages","getConversation","role","message","result","filePath","verbose","sessions","listSessions","byId","fromEntries","firstUserMessage","resolves"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/__tests__/providers/copilot/CopilotAdapter.test.ts"],"sourcesContent":["/**\n * Tests for CopilotAdapter\n */\n\nimport type { MockedFunction } from \"vitest\";\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\n\nimport { CopilotAdapter } from \"../../../providers/copilot/CopilotAdapter.js\";\nimport type { ProcessInfo } from \"../../../adapters/AgentAdapter.js\";\nimport { AgentStatus } from \"../../../adapters/AgentAdapter.js\";\nimport {\n listAgentProcesses,\n enrichProcesses,\n captureProcessSnapshot,\n} from \"../../../utils/process.js\";\nimport { generateAgentName } from \"../../../utils/matching.js\";\nimport { AgentRegistry } from \"../../../utils/AgentRegistry.js\";\n\nvi.mock(\"../../../utils/process.js\", async (importOriginal) => {\n const actual = (await importOriginal()) as typeof import(\"../../../utils/process.js\");\n return {\n ...actual,\n listAgentProcesses: vi.fn(),\n enrichProcesses: vi.fn(),\n captureProcessSnapshot: vi.fn(),\n };\n});\n\nvi.mock(\"../../../utils/matching.js\", () => ({\n generateAgentName: vi.fn(),\n}));\n\nconst mockedListAgentProcesses = listAgentProcesses as MockedFunction<typeof listAgentProcesses>;\nconst mockedEnrichProcesses = enrichProcesses as MockedFunction<typeof enrichProcesses>;\nconst mockedCaptureProcessSnapshot = captureProcessSnapshot as MockedFunction<\n typeof captureProcessSnapshot\n>;\nconst mockedGenerateAgentName = generateAgentName as MockedFunction<typeof generateAgentName>;\n\ndescribe(\"CopilotAdapter\", () => {\n let adapter: CopilotAdapter;\n let tmpDir: string;\n let sessionStateDir: string;\n\n beforeEach(() => {\n tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"copilot-test-\"));\n sessionStateDir = path.join(tmpDir, \"session-state\");\n fs.mkdirSync(sessionStateDir, { recursive: true });\n adapter = new CopilotAdapter(undefined, { sessionStateDir });\n\n mockedListAgentProcesses.mockReset();\n mockedEnrichProcesses.mockReset();\n mockedCaptureProcessSnapshot.mockReset();\n mockedGenerateAgentName.mockReset();\n mockedEnrichProcesses.mockImplementation((procs) => procs);\n // Compatibility shim for standalone adapter discovery; the manager captures once and slices by name.\n mockedCaptureProcessSnapshot.mockImplementation(async (names) =>\n enrichProcesses(names.flatMap((name) => listAgentProcesses(name))),\n );\n mockedGenerateAgentName.mockImplementation(\n (cwd, pid) => `${path.basename(cwd) || \"unknown\"} (${pid})`,\n );\n });\n\n afterEach(() => {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n });\n\n function writeSession(\n sessionId: string,\n options: {\n events?: Array<object | string>;\n workspace?: Record<string, string>;\n lockPid?: number | string;\n },\n ): string {\n const sessionDir = path.join(sessionStateDir, sessionId);\n fs.mkdirSync(sessionDir, { recursive: true });\n\n if (options.events) {\n const lines = options.events.map((entry) =>\n typeof entry === \"string\" ? entry : JSON.stringify(entry),\n );\n fs.writeFileSync(path.join(sessionDir, \"events.jsonl\"), lines.join(\"\\n\"));\n }\n\n if (options.workspace) {\n const lines = Object.entries(options.workspace).map(([key, value]) => `${key}: ${value}`);\n fs.writeFileSync(path.join(sessionDir, \"workspace.yaml\"), lines.join(\"\\n\"));\n }\n\n if (options.lockPid !== undefined) {\n fs.writeFileSync(path.join(sessionDir, `inuse.${options.lockPid}.lock`), \"\");\n }\n\n return sessionDir;\n }\n\n function sessionStart(\n sessionId: string,\n cwd: string,\n startTime = \"2026-06-09T09:50:00.000Z\",\n ): object {\n return {\n type: \"session.start\",\n data: {\n sessionId,\n startTime,\n context: {\n cwd,\n gitRoot: cwd,\n branch: \"main\",\n },\n },\n timestamp: startTime,\n };\n }\n\n describe(\"initialization\", () => {\n it(\"exposes copilot type\", () => {\n expect(adapter.type).toBe(\"copilot\");\n });\n });\n\n describe(\"canHandle\", () => {\n it(\"returns true for copilot commands\", () => {\n expect(adapter.canHandle({ pid: 1, command: \"copilot\", cwd: \"/repo\", tty: \"ttys001\" })).toBe(\n true,\n );\n });\n\n it(\"returns true for full-path Homebrew copilot commands\", () => {\n expect(\n adapter.canHandle({\n pid: 2,\n command: \"/opt/homebrew/Caskroom/copilot-cli/1.0.60/copilot\",\n cwd: \"/repo\",\n tty: \"ttys002\",\n }),\n ).toBe(true);\n });\n\n it(\"returns true for copilot.exe commands\", () => {\n expect(\n adapter.canHandle({\n pid: 3,\n command: \"/usr/bin/copilot.exe\",\n cwd: \"/repo\",\n tty: \"ttys003\",\n }),\n ).toBe(true);\n });\n\n it(\"returns false when copilot appears only in an argument\", () => {\n expect(\n adapter.canHandle({\n pid: 4,\n command: \"node /repo/copilot-plugin/index.js\",\n cwd: \"/repo\",\n tty: \"ttys004\",\n }),\n ).toBe(false);\n });\n });\n\n describe(\"detectAgents\", () => {\n it(\"returns empty list when no copilot process is running\", async () => {\n mockedListAgentProcesses.mockReturnValue([]);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toEqual([]);\n expect(mockedListAgentProcesses).toHaveBeenCalledWith(\"copilot\");\n });\n\n it(\"maps matching inuse lock and events to an active agent\", async () => {\n const processes: ProcessInfo[] = [\n {\n pid: 14096,\n command: \"/opt/homebrew/Caskroom/copilot-cli/1.0.60/copilot\",\n cwd: \"/repo\",\n tty: \"ttys001\",\n },\n ];\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n writeSession(\"sess-a\", {\n lockPid: 14096,\n events: [\n sessionStart(\"sess-a\", \"/repo\", \"2026-06-09T09:50:00.000Z\"),\n {\n type: \"user.message\",\n data: { content: \"Build the Copilot adapter\" },\n timestamp: new Date().toISOString(),\n },\n {\n type: \"assistant.message\",\n data: { content: \"I will inspect the code.\" },\n timestamp: new Date().toISOString(),\n },\n ],\n workspace: {\n id: \"sess-a\",\n cwd: \"/fallback\",\n name: \"Fallback Name\",\n created_at: \"2026-06-09T09:49:00.000Z\",\n updated_at: \"2026-06-09T09:51:00.000Z\",\n },\n });\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n type: \"copilot\",\n status: AgentStatus.WAITING,\n pid: 14096,\n projectPath: \"/repo\",\n sessionId: \"sess-a\",\n summary: \"Build the Copilot adapter\",\n sessionFilePath: path.join(sessionStateDir, \"sess-a\", \"events.jsonl\"),\n });\n });\n\n it(\"ignores invalid and unmatched lock PIDs\", async () => {\n const processes: ProcessInfo[] = [\n { pid: 100, command: \"copilot\", cwd: \"/repo\", tty: \"ttys001\" },\n ];\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n writeSession(\"invalid\", {\n lockPid: \"not-a-pid\",\n events: [sessionStart(\"invalid\", \"/invalid\")],\n });\n writeSession(\"unmatched\", {\n lockPid: 999999,\n events: [sessionStart(\"unmatched\", \"/unmatched\")],\n });\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n pid: 100,\n sessionId: \"pid-100\",\n summary: \"Copilot process running\",\n });\n });\n\n it(\"falls back to process-only agent when no session lock matches\", async () => {\n const processes: ProcessInfo[] = [\n { pid: 200, command: \"copilot\", cwd: \"/repo-b\", tty: \"ttys002\" },\n ];\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n type: \"copilot\",\n status: AgentStatus.RUNNING,\n pid: 200,\n projectPath: \"/repo-b\",\n sessionId: \"pid-200\",\n summary: \"Copilot process running\",\n });\n });\n\n it(\"suppresses wrapper process-only agents before the session lock exists\", async () => {\n const processes: ProcessInfo[] = [\n { pid: 86800, command: \"copilot\", cwd: \"/repo\", tty: \"ttys001\", ppid: 84174 },\n {\n pid: 86810,\n command: \"/custom/install/copilot\",\n cwd: \"/repo\",\n tty: \"ttys001\",\n ppid: 86800,\n },\n ];\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n pid: 86810,\n sessionId: \"pid-86810\",\n summary: \"Copilot process running\",\n });\n });\n\n it(\"carries the managed wrapper name to a process-only child before the session lock exists\", async () => {\n const registry = new AgentRegistry(path.join(tmpDir, \"agents.json\"));\n adapter = new CopilotAdapter(registry, { sessionStateDir });\n const processes: ProcessInfo[] = [\n { pid: 86800, command: \"copilot\", cwd: \"/repo\", tty: \"ttys001\", ppid: 84174 },\n {\n pid: 86810,\n command: \"/custom/install/copilot\",\n cwd: \"/repo\",\n tty: \"ttys001\",\n ppid: 86800,\n },\n ];\n registry.register({\n name: \"copilot-started\",\n type: \"copilot\",\n pid: 86800,\n runtime: \"tmux\",\n runtimeRef: { session: \"copilot-started\" },\n cwd: \"/repo\",\n startedAt: \"2026-06-13T19:15:16.211Z\",\n sessionId: \"pid-86800\",\n sessionFilePath: \"\",\n });\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n name: \"copilot-started\",\n pid: 86810,\n sessionId: \"pid-86810\",\n });\n });\n\n it(\"does not add duplicate process-only agent for wrapper process in the same terminal\", async () => {\n const processes: ProcessInfo[] = [\n { pid: 14095, command: \"copilot\", cwd: \"/repo\", tty: \"ttys001\" },\n {\n pid: 14096,\n command: \"/opt/homebrew/Caskroom/copilot-cli/1.0.60/copilot\",\n cwd: \"/repo\",\n tty: \"ttys001\",\n },\n ];\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n writeSession(\"sess-wrapper\", {\n lockPid: 14096,\n events: [\n sessionStart(\"sess-wrapper\", \"/repo\", \"2026-06-09T09:50:00.000Z\"),\n { type: \"user.message\", data: { content: \"hello\" }, timestamp: new Date().toISOString() },\n ],\n });\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n pid: 14096,\n sessionId: \"sess-wrapper\",\n });\n });\n\n it(\"carries the managed wrapper name to a lock-backed child process\", async () => {\n const registry = new AgentRegistry(path.join(tmpDir, \"agents.json\"));\n adapter = new CopilotAdapter(registry, { sessionStateDir });\n const processes: ProcessInfo[] = [\n { pid: 14095, command: \"copilot\", cwd: \"/repo\", tty: \"ttys001\", ppid: 84174 },\n {\n pid: 14096,\n command: \"/opt/homebrew/Caskroom/copilot-cli/1.0.60/copilot\",\n cwd: \"/repo\",\n tty: \"ttys001\",\n ppid: 14095,\n },\n ];\n registry.register({\n name: \"copilot-started\",\n type: \"copilot\",\n pid: 14095,\n runtime: \"tmux\",\n runtimeRef: { session: \"copilot-started\" },\n cwd: \"/repo\",\n startedAt: \"2026-06-13T19:15:16.211Z\",\n sessionId: \"pid-14095\",\n sessionFilePath: \"\",\n });\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n writeSession(\"sess-wrapper\", {\n lockPid: 14096,\n events: [\n sessionStart(\"sess-wrapper\", \"/repo\", \"2026-06-09T09:50:00.000Z\"),\n { type: \"user.message\", data: { content: \"hello\" }, timestamp: new Date().toISOString() },\n ],\n });\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n name: \"copilot-started\",\n pid: 14096,\n sessionId: \"sess-wrapper\",\n });\n });\n\n it(\"uses workspace metadata when events are missing\", async () => {\n const processes: ProcessInfo[] = [\n { pid: 300, command: \"copilot\", cwd: \"/proc-cwd\", tty: \"ttys003\" },\n ];\n mockedListAgentProcesses.mockReturnValue(processes);\n mockedEnrichProcesses.mockReturnValue(processes);\n writeSession(\"workspace-only\", {\n lockPid: 300,\n workspace: {\n id: \"workspace-only\",\n cwd: \"/workspace-cwd\",\n name: \"Workspace Session\",\n created_at: \"2026-06-09T09:00:00.000Z\",\n updated_at: \"2026-06-09T09:10:00.000Z\",\n },\n });\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n pid: 300,\n projectPath: \"/workspace-cwd\",\n sessionId: \"workspace-only\",\n summary: \"Workspace Session\",\n });\n });\n });\n\n describe(\"getConversation\", () => {\n it(\"parses user and assistant message events\", () => {\n const sessionDir = writeSession(\"conv\", {\n events: [\n sessionStart(\"conv\", \"/repo\"),\n {\n type: \"user.message\",\n data: { content: \"hello\" },\n timestamp: \"2026-06-09T09:50:01.000Z\",\n },\n {\n type: \"assistant.message\",\n data: { content: \"Hi there\" },\n timestamp: \"2026-06-09T09:50:02.000Z\",\n },\n ],\n });\n\n const messages = adapter.getConversation(path.join(sessionDir, \"events.jsonl\"));\n\n expect(messages).toEqual([\n { role: \"user\", content: \"hello\", timestamp: \"2026-06-09T09:50:01.000Z\" },\n { role: \"assistant\", content: \"Hi there\", timestamp: \"2026-06-09T09:50:02.000Z\" },\n ]);\n });\n\n it(\"includes system/info/warning messages only in verbose mode\", () => {\n const sessionDir = writeSession(\"verbose\", {\n events: [\n {\n type: \"session.warning\",\n data: { message: \"MCP failed\" },\n timestamp: \"2026-06-09T09:50:01.000Z\",\n },\n {\n type: \"tool.execution_complete\",\n data: { result: { content: \"Tool result\" } },\n timestamp: \"2026-06-09T09:50:02.000Z\",\n },\n ],\n });\n const filePath = path.join(sessionDir, \"events.jsonl\");\n\n expect(adapter.getConversation(filePath)).toEqual([]);\n expect(adapter.getConversation(filePath, { verbose: true })).toEqual([\n { role: \"system\", content: \"MCP failed\", timestamp: \"2026-06-09T09:50:01.000Z\" },\n { role: \"system\", content: \"Tool result\", timestamp: \"2026-06-09T09:50:02.000Z\" },\n ]);\n });\n\n it(\"skips malformed JSONL lines and missing text\", () => {\n const sessionDir = writeSession(\"malformed\", {\n events: [\n \"not json\",\n {\n type: \"user.message\",\n data: { content: \"valid\" },\n timestamp: \"2026-06-09T09:50:01.000Z\",\n },\n { type: \"assistant.message\", data: {}, timestamp: \"2026-06-09T09:50:02.000Z\" },\n ],\n });\n\n const messages = adapter.getConversation(path.join(sessionDir, \"events.jsonl\"));\n\n expect(messages).toEqual([\n { role: \"user\", content: \"valid\", timestamp: \"2026-06-09T09:50:01.000Z\" },\n ]);\n });\n\n it(\"returns empty array for missing file\", () => {\n expect(adapter.getConversation(path.join(tmpDir, \"missing.jsonl\"))).toEqual([]);\n });\n });\n\n describe(\"listSessions\", () => {\n it(\"returns historical sessions without active locks\", async () => {\n writeSession(\"history-a\", {\n events: [\n sessionStart(\"history-a\", \"/repo-a\", \"2026-06-09T09:00:00.000Z\"),\n {\n type: \"user.message\",\n data: { content: \"first user\" },\n timestamp: \"2026-06-09T09:00:01.000Z\",\n },\n {\n type: \"assistant.message\",\n data: { content: \"answer\" },\n timestamp: \"2026-06-09T09:00:02.000Z\",\n },\n ],\n });\n writeSession(\"history-b\", {\n events: [\n sessionStart(\"history-b\", \"/repo-b\", \"2026-06-09T10:00:00.000Z\"),\n {\n type: \"user.message\",\n data: { content: \"other user\" },\n timestamp: \"2026-06-09T10:00:01.000Z\",\n },\n ],\n });\n\n const sessions = await adapter.listSessions();\n\n expect(sessions).toHaveLength(2);\n const byId = Object.fromEntries(sessions.map((session) => [session.sessionId, session]));\n expect(byId[\"history-a\"]).toMatchObject({\n type: \"copilot\",\n cwd: \"/repo-a\",\n firstUserMessage: \"first user\",\n sessionFilePath: path.join(sessionStateDir, \"history-a\", \"events.jsonl\"),\n });\n expect(byId[\"history-b\"]).toMatchObject({\n type: \"copilot\",\n cwd: \"/repo-b\",\n firstUserMessage: \"other user\",\n });\n });\n\n it(\"finds an exact session ID from its session directory\", async () => {\n writeSession(\"wanted\", { events: [sessionStart(\"wanted\", \"/repo\")] });\n writeSession(\"other\", { events: [sessionStart(\"other\", \"/other\")] });\n\n await expect(adapter.findSessionsById(\"wanted\")).resolves.toEqual([\n expect.objectContaining({\n sessionId: \"wanted\",\n sessionFilePath: path.join(sessionStateDir, \"wanted\", \"events.jsonl\"),\n }),\n ]);\n });\n\n it(\"applies strict cwd filter\", async () => {\n writeSession(\"keep\", { events: [sessionStart(\"keep\", \"/repo\")] });\n writeSession(\"drop\", { events: [sessionStart(\"drop\", \"/other\")] });\n\n const sessions = await adapter.listSessions({ cwd: \"/repo\" });\n\n expect(sessions).toHaveLength(1);\n expect(sessions[0].sessionId).toBe(\"keep\");\n });\n\n it(\"uses workspace fallback for historical sessions without events\", async () => {\n writeSession(\"workspace-history\", {\n workspace: {\n id: \"workspace-history\",\n cwd: \"/workspace-repo\",\n name: \"Workspace History\",\n created_at: \"2026-06-09T08:00:00.000Z\",\n updated_at: \"2026-06-09T08:10:00.000Z\",\n },\n });\n\n const sessions = await adapter.listSessions();\n\n expect(sessions).toHaveLength(1);\n expect(sessions[0]).toMatchObject({\n type: \"copilot\",\n sessionId: \"workspace-history\",\n cwd: \"/workspace-repo\",\n firstUserMessage: \"\",\n sessionFilePath: path.join(sessionStateDir, \"workspace-history\", \"events.jsonl\"),\n });\n });\n\n it(\"skips session directories without events or workspace metadata\", async () => {\n fs.mkdirSync(path.join(sessionStateDir, \"empty\"), { recursive: true });\n\n const sessions = await adapter.listSessions();\n\n expect(sessions).toEqual([]);\n });\n\n it(\"returns empty when session-state directory does not exist\", async () => {\n adapter = new CopilotAdapter(undefined, { sessionStateDir: path.join(tmpDir, \"missing\") });\n\n await expect(adapter.listSessions()).resolves.toEqual([]);\n });\n });\n});\n"],"names":["fs","os","path","CopilotAdapter","AgentStatus","listAgentProcesses","enrichProcesses","captureProcessSnapshot","generateAgentName","AgentRegistry","vi","mock","importOriginal","actual","fn","mockedListAgentProcesses","mockedEnrichProcesses","mockedCaptureProcessSnapshot","mockedGenerateAgentName","describe","adapter","tmpDir","sessionStateDir","beforeEach","mkdtempSync","join","tmpdir","mkdirSync","recursive","undefined","mockReset","mockImplementation","procs","names","flatMap","name","cwd","pid","basename","afterEach","rmSync","force","writeSession","sessionId","options","sessionDir","events","lines","map","entry","JSON","stringify","writeFileSync","workspace","Object","entries","key","value","lockPid","sessionStart","startTime","type","data","context","gitRoot","branch","timestamp","it","expect","toBe","canHandle","command","tty","mockReturnValue","agents","detectAgents","toEqual","toHaveBeenCalledWith","processes","content","Date","toISOString","id","created_at","updated_at","toHaveLength","toMatchObject","status","WAITING","projectPath","summary","sessionFilePath","RUNNING","ppid","registry","register","runtime","runtimeRef","session","startedAt","messages","getConversation","role","message","result","filePath","verbose","sessions","listSessions","byId","fromEntries","firstUserMessage","findSessionsById","resolves","objectContaining"],"mappings":"AAAA;;CAEC,GAGD,YAAYA,QAAQ,KAAK;AACzB,YAAYC,QAAQ,KAAK;AACzB,YAAYC,UAAU,OAAO;AAE7B,SAASC,cAAc,QAAQ,+CAA+C;AAE9E,SAASC,WAAW,QAAQ,oCAAoC;AAChE,SACEC,kBAAkB,EAClBC,eAAe,EACfC,sBAAsB,QACjB,4BAA4B;AACnC,SAASC,iBAAiB,QAAQ,6BAA6B;AAC/D,SAASC,aAAa,QAAQ,kCAAkC;AAEhEC,GAAGC,IAAI,CAAC,6BAA6B,OAAOC;IAC1C,MAAMC,SAAU,MAAMD;IACtB,OAAO;QACL,GAAGC,MAAM;QACTR,oBAAoBK,GAAGI,EAAE;QACzBR,iBAAiBI,GAAGI,EAAE;QACtBP,wBAAwBG,GAAGI,EAAE;IAC/B;AACF;AAEAJ,GAAGC,IAAI,CAAC,8BAA8B,IAAO,CAAA;QAC3CH,mBAAmBE,GAAGI,EAAE;IAC1B,CAAA;AAEA,MAAMC,2BAA2BV;AACjC,MAAMW,wBAAwBV;AAC9B,MAAMW,+BAA+BV;AAGrC,MAAMW,0BAA0BV;AAEhCW,SAAS,kBAAkB;IACzB,IAAIC;IACJ,IAAIC;IACJ,IAAIC;IAEJC,WAAW;QACTF,SAASrB,GAAGwB,WAAW,CAACtB,KAAKuB,IAAI,CAACxB,GAAGyB,MAAM,IAAI;QAC/CJ,kBAAkBpB,KAAKuB,IAAI,CAACJ,QAAQ;QACpCrB,GAAG2B,SAAS,CAACL,iBAAiB;YAAEM,WAAW;QAAK;QAChDR,UAAU,IAAIjB,eAAe0B,WAAW;YAAEP;QAAgB;QAE1DP,yBAAyBe,SAAS;QAClCd,sBAAsBc,SAAS;QAC/Bb,6BAA6Ba,SAAS;QACtCZ,wBAAwBY,SAAS;QACjCd,sBAAsBe,kBAAkB,CAAC,CAACC,QAAUA;QACpD,qGAAqG;QACrGf,6BAA6Bc,kBAAkB,CAAC,OAAOE,QACrD3B,gBAAgB2B,MAAMC,OAAO,CAAC,CAACC,OAAS9B,mBAAmB8B;QAE7DjB,wBAAwBa,kBAAkB,CACxC,CAACK,KAAKC,MAAQ,GAAGnC,KAAKoC,QAAQ,CAACF,QAAQ,UAAU,EAAE,EAAEC,IAAI,CAAC,CAAC;IAE/D;IAEAE,UAAU;QACRvC,GAAGwC,MAAM,CAACnB,QAAQ;YAAEO,WAAW;YAAMa,OAAO;QAAK;IACnD;IAEA,SAASC,aACPC,SAAiB,EACjBC,OAIC;QAED,MAAMC,aAAa3C,KAAKuB,IAAI,CAACH,iBAAiBqB;QAC9C3C,GAAG2B,SAAS,CAACkB,YAAY;YAAEjB,WAAW;QAAK;QAE3C,IAAIgB,QAAQE,MAAM,EAAE;YAClB,MAAMC,QAAQH,QAAQE,MAAM,CAACE,GAAG,CAAC,CAACC,QAChC,OAAOA,UAAU,WAAWA,QAAQC,KAAKC,SAAS,CAACF;YAErDjD,GAAGoD,aAAa,CAAClD,KAAKuB,IAAI,CAACoB,YAAY,iBAAiBE,MAAMtB,IAAI,CAAC;QACrE;QAEA,IAAImB,QAAQS,SAAS,EAAE;YACrB,MAAMN,QAAQO,OAAOC,OAAO,CAACX,QAAQS,SAAS,EAAEL,GAAG,CAAC,CAAC,CAACQ,KAAKC,MAAM,GAAK,GAAGD,IAAI,EAAE,EAAEC,OAAO;YACxFzD,GAAGoD,aAAa,CAAClD,KAAKuB,IAAI,CAACoB,YAAY,mBAAmBE,MAAMtB,IAAI,CAAC;QACvE;QAEA,IAAImB,QAAQc,OAAO,KAAK7B,WAAW;YACjC7B,GAAGoD,aAAa,CAAClD,KAAKuB,IAAI,CAACoB,YAAY,CAAC,MAAM,EAAED,QAAQc,OAAO,CAAC,KAAK,CAAC,GAAG;QAC3E;QAEA,OAAOb;IACT;IAEA,SAASc,aACPhB,SAAiB,EACjBP,GAAW,EACXwB,YAAY,0BAA0B;QAEtC,OAAO;YACLC,MAAM;YACNC,MAAM;gBACJnB;gBACAiB;gBACAG,SAAS;oBACP3B;oBACA4B,SAAS5B;oBACT6B,QAAQ;gBACV;YACF;YACAC,WAAWN;QACb;IACF;IAEAzC,SAAS,kBAAkB;QACzBgD,GAAG,wBAAwB;YACzBC,OAAOhD,QAAQyC,IAAI,EAAEQ,IAAI,CAAC;QAC5B;IACF;IAEAlD,SAAS,aAAa;QACpBgD,GAAG,qCAAqC;YACtCC,OAAOhD,QAAQkD,SAAS,CAAC;gBAAEjC,KAAK;gBAAGkC,SAAS;gBAAWnC,KAAK;gBAASoC,KAAK;YAAU,IAAIH,IAAI,CAC1F;QAEJ;QAEAF,GAAG,wDAAwD;YACzDC,OACEhD,QAAQkD,SAAS,CAAC;gBAChBjC,KAAK;gBACLkC,SAAS;gBACTnC,KAAK;gBACLoC,KAAK;YACP,IACAH,IAAI,CAAC;QACT;QAEAF,GAAG,yCAAyC;YAC1CC,OACEhD,QAAQkD,SAAS,CAAC;gBAChBjC,KAAK;gBACLkC,SAAS;gBACTnC,KAAK;gBACLoC,KAAK;YACP,IACAH,IAAI,CAAC;QACT;QAEAF,GAAG,0DAA0D;YAC3DC,OACEhD,QAAQkD,SAAS,CAAC;gBAChBjC,KAAK;gBACLkC,SAAS;gBACTnC,KAAK;gBACLoC,KAAK;YACP,IACAH,IAAI,CAAC;QACT;IACF;IAEAlD,SAAS,gBAAgB;QACvBgD,GAAG,yDAAyD;YAC1DpD,yBAAyB0D,eAAe,CAAC,EAAE;YAE3C,MAAMC,SAAS,MAAMtD,QAAQuD,YAAY;YAEzCP,OAAOM,QAAQE,OAAO,CAAC,EAAE;YACzBR,OAAOrD,0BAA0B8D,oBAAoB,CAAC;QACxD;QAEAV,GAAG,0DAA0D;YAC3D,MAAMW,YAA2B;gBAC/B;oBACEzC,KAAK;oBACLkC,SAAS;oBACTnC,KAAK;oBACLoC,KAAK;gBACP;aACD;YACDzD,yBAAyB0D,eAAe,CAACK;YACzC9D,sBAAsByD,eAAe,CAACK;YACtCpC,aAAa,UAAU;gBACrBgB,SAAS;gBACTZ,QAAQ;oBACNa,aAAa,UAAU,SAAS;oBAChC;wBACEE,MAAM;wBACNC,MAAM;4BAAEiB,SAAS;wBAA4B;wBAC7Cb,WAAW,IAAIc,OAAOC,WAAW;oBACnC;oBACA;wBACEpB,MAAM;wBACNC,MAAM;4BAAEiB,SAAS;wBAA2B;wBAC5Cb,WAAW,IAAIc,OAAOC,WAAW;oBACnC;iBACD;gBACD5B,WAAW;oBACT6B,IAAI;oBACJ9C,KAAK;oBACLD,MAAM;oBACNgD,YAAY;oBACZC,YAAY;gBACd;YACF;YAEA,MAAMV,SAAS,MAAMtD,QAAQuD,YAAY;YAEzCP,OAAOM,QAAQW,YAAY,CAAC;YAC5BjB,OAAOM,MAAM,CAAC,EAAE,EAAEY,aAAa,CAAC;gBAC9BzB,MAAM;gBACN0B,QAAQnF,YAAYoF,OAAO;gBAC3BnD,KAAK;gBACLoD,aAAa;gBACb9C,WAAW;gBACX+C,SAAS;gBACTC,iBAAiBzF,KAAKuB,IAAI,CAACH,iBAAiB,UAAU;YACxD;QACF;QAEA6C,GAAG,2CAA2C;YAC5C,MAAMW,YAA2B;gBAC/B;oBAAEzC,KAAK;oBAAKkC,SAAS;oBAAWnC,KAAK;oBAASoC,KAAK;gBAAU;aAC9D;YACDzD,yBAAyB0D,eAAe,CAACK;YACzC9D,sBAAsByD,eAAe,CAACK;YACtCpC,aAAa,WAAW;gBACtBgB,SAAS;gBACTZ,QAAQ;oBAACa,aAAa,WAAW;iBAAY;YAC/C;YACAjB,aAAa,aAAa;gBACxBgB,SAAS;gBACTZ,QAAQ;oBAACa,aAAa,aAAa;iBAAc;YACnD;YAEA,MAAMe,SAAS,MAAMtD,QAAQuD,YAAY;YAEzCP,OAAOM,QAAQW,YAAY,CAAC;YAC5BjB,OAAOM,MAAM,CAAC,EAAE,EAAEY,aAAa,CAAC;gBAC9BjD,KAAK;gBACLM,WAAW;gBACX+C,SAAS;YACX;QACF;QAEAvB,GAAG,iEAAiE;YAClE,MAAMW,YAA2B;gBAC/B;oBAAEzC,KAAK;oBAAKkC,SAAS;oBAAWnC,KAAK;oBAAWoC,KAAK;gBAAU;aAChE;YACDzD,yBAAyB0D,eAAe,CAACK;YACzC9D,sBAAsByD,eAAe,CAACK;YAEtC,MAAMJ,SAAS,MAAMtD,QAAQuD,YAAY;YAEzCP,OAAOM,QAAQW,YAAY,CAAC;YAC5BjB,OAAOM,MAAM,CAAC,EAAE,EAAEY,aAAa,CAAC;gBAC9BzB,MAAM;gBACN0B,QAAQnF,YAAYwF,OAAO;gBAC3BvD,KAAK;gBACLoD,aAAa;gBACb9C,WAAW;gBACX+C,SAAS;YACX;QACF;QAEAvB,GAAG,yEAAyE;YAC1E,MAAMW,YAA2B;gBAC/B;oBAAEzC,KAAK;oBAAOkC,SAAS;oBAAWnC,KAAK;oBAASoC,KAAK;oBAAWqB,MAAM;gBAAM;gBAC5E;oBACExD,KAAK;oBACLkC,SAAS;oBACTnC,KAAK;oBACLoC,KAAK;oBACLqB,MAAM;gBACR;aACD;YACD9E,yBAAyB0D,eAAe,CAACK;YACzC9D,sBAAsByD,eAAe,CAACK;YAEtC,MAAMJ,SAAS,MAAMtD,QAAQuD,YAAY;YAEzCP,OAAOM,QAAQW,YAAY,CAAC;YAC5BjB,OAAOM,MAAM,CAAC,EAAE,EAAEY,aAAa,CAAC;gBAC9BjD,KAAK;gBACLM,WAAW;gBACX+C,SAAS;YACX;QACF;QAEAvB,GAAG,2FAA2F;YAC5F,MAAM2B,WAAW,IAAIrF,cAAcP,KAAKuB,IAAI,CAACJ,QAAQ;YACrDD,UAAU,IAAIjB,eAAe2F,UAAU;gBAAExE;YAAgB;YACzD,MAAMwD,YAA2B;gBAC/B;oBAAEzC,KAAK;oBAAOkC,SAAS;oBAAWnC,KAAK;oBAASoC,KAAK;oBAAWqB,MAAM;gBAAM;gBAC5E;oBACExD,KAAK;oBACLkC,SAAS;oBACTnC,KAAK;oBACLoC,KAAK;oBACLqB,MAAM;gBACR;aACD;YACDC,SAASC,QAAQ,CAAC;gBAChB5D,MAAM;gBACN0B,MAAM;gBACNxB,KAAK;gBACL2D,SAAS;gBACTC,YAAY;oBAAEC,SAAS;gBAAkB;gBACzC9D,KAAK;gBACL+D,WAAW;gBACXxD,WAAW;gBACXgD,iBAAiB;YACnB;YACA5E,yBAAyB0D,eAAe,CAACK;YACzC9D,sBAAsByD,eAAe,CAACK;YAEtC,MAAMJ,SAAS,MAAMtD,QAAQuD,YAAY;YAEzCP,OAAOM,QAAQW,YAAY,CAAC;YAC5BjB,OAAOM,MAAM,CAAC,EAAE,EAAEY,aAAa,CAAC;gBAC9BnD,MAAM;gBACNE,KAAK;gBACLM,WAAW;YACb;QACF;QAEAwB,GAAG,sFAAsF;YACvF,MAAMW,YAA2B;gBAC/B;oBAAEzC,KAAK;oBAAOkC,SAAS;oBAAWnC,KAAK;oBAASoC,KAAK;gBAAU;gBAC/D;oBACEnC,KAAK;oBACLkC,SAAS;oBACTnC,KAAK;oBACLoC,KAAK;gBACP;aACD;YACDzD,yBAAyB0D,eAAe,CAACK;YACzC9D,sBAAsByD,eAAe,CAACK;YACtCpC,aAAa,gBAAgB;gBAC3BgB,SAAS;gBACTZ,QAAQ;oBACNa,aAAa,gBAAgB,SAAS;oBACtC;wBAAEE,MAAM;wBAAgBC,MAAM;4BAAEiB,SAAS;wBAAQ;wBAAGb,WAAW,IAAIc,OAAOC,WAAW;oBAAG;iBACzF;YACH;YAEA,MAAMP,SAAS,MAAMtD,QAAQuD,YAAY;YAEzCP,OAAOM,QAAQW,YAAY,CAAC;YAC5BjB,OAAOM,MAAM,CAAC,EAAE,EAAEY,aAAa,CAAC;gBAC9BjD,KAAK;gBACLM,WAAW;YACb;QACF;QAEAwB,GAAG,mEAAmE;YACpE,MAAM2B,WAAW,IAAIrF,cAAcP,KAAKuB,IAAI,CAACJ,QAAQ;YACrDD,UAAU,IAAIjB,eAAe2F,UAAU;gBAAExE;YAAgB;YACzD,MAAMwD,YAA2B;gBAC/B;oBAAEzC,KAAK;oBAAOkC,SAAS;oBAAWnC,KAAK;oBAASoC,KAAK;oBAAWqB,MAAM;gBAAM;gBAC5E;oBACExD,KAAK;oBACLkC,SAAS;oBACTnC,KAAK;oBACLoC,KAAK;oBACLqB,MAAM;gBACR;aACD;YACDC,SAASC,QAAQ,CAAC;gBAChB5D,MAAM;gBACN0B,MAAM;gBACNxB,KAAK;gBACL2D,SAAS;gBACTC,YAAY;oBAAEC,SAAS;gBAAkB;gBACzC9D,KAAK;gBACL+D,WAAW;gBACXxD,WAAW;gBACXgD,iBAAiB;YACnB;YACA5E,yBAAyB0D,eAAe,CAACK;YACzC9D,sBAAsByD,eAAe,CAACK;YACtCpC,aAAa,gBAAgB;gBAC3BgB,SAAS;gBACTZ,QAAQ;oBACNa,aAAa,gBAAgB,SAAS;oBACtC;wBAAEE,MAAM;wBAAgBC,MAAM;4BAAEiB,SAAS;wBAAQ;wBAAGb,WAAW,IAAIc,OAAOC,WAAW;oBAAG;iBACzF;YACH;YAEA,MAAMP,SAAS,MAAMtD,QAAQuD,YAAY;YAEzCP,OAAOM,QAAQW,YAAY,CAAC;YAC5BjB,OAAOM,MAAM,CAAC,EAAE,EAAEY,aAAa,CAAC;gBAC9BnD,MAAM;gBACNE,KAAK;gBACLM,WAAW;YACb;QACF;QAEAwB,GAAG,mDAAmD;YACpD,MAAMW,YAA2B;gBAC/B;oBAAEzC,KAAK;oBAAKkC,SAAS;oBAAWnC,KAAK;oBAAaoC,KAAK;gBAAU;aAClE;YACDzD,yBAAyB0D,eAAe,CAACK;YACzC9D,sBAAsByD,eAAe,CAACK;YACtCpC,aAAa,kBAAkB;gBAC7BgB,SAAS;gBACTL,WAAW;oBACT6B,IAAI;oBACJ9C,KAAK;oBACLD,MAAM;oBACNgD,YAAY;oBACZC,YAAY;gBACd;YACF;YAEA,MAAMV,SAAS,MAAMtD,QAAQuD,YAAY;YAEzCP,OAAOM,QAAQW,YAAY,CAAC;YAC5BjB,OAAOM,MAAM,CAAC,EAAE,EAAEY,aAAa,CAAC;gBAC9BjD,KAAK;gBACLoD,aAAa;gBACb9C,WAAW;gBACX+C,SAAS;YACX;QACF;IACF;IAEAvE,SAAS,mBAAmB;QAC1BgD,GAAG,4CAA4C;YAC7C,MAAMtB,aAAaH,aAAa,QAAQ;gBACtCI,QAAQ;oBACNa,aAAa,QAAQ;oBACrB;wBACEE,MAAM;wBACNC,MAAM;4BAAEiB,SAAS;wBAAQ;wBACzBb,WAAW;oBACb;oBACA;wBACEL,MAAM;wBACNC,MAAM;4BAAEiB,SAAS;wBAAW;wBAC5Bb,WAAW;oBACb;iBACD;YACH;YAEA,MAAMkC,WAAWhF,QAAQiF,eAAe,CAACnG,KAAKuB,IAAI,CAACoB,YAAY;YAE/DuB,OAAOgC,UAAUxB,OAAO,CAAC;gBACvB;oBAAE0B,MAAM;oBAAQvB,SAAS;oBAASb,WAAW;gBAA2B;gBACxE;oBAAEoC,MAAM;oBAAavB,SAAS;oBAAYb,WAAW;gBAA2B;aACjF;QACH;QAEAC,GAAG,8DAA8D;YAC/D,MAAMtB,aAAaH,aAAa,WAAW;gBACzCI,QAAQ;oBACN;wBACEe,MAAM;wBACNC,MAAM;4BAAEyC,SAAS;wBAAa;wBAC9BrC,WAAW;oBACb;oBACA;wBACEL,MAAM;wBACNC,MAAM;4BAAE0C,QAAQ;gCAAEzB,SAAS;4BAAc;wBAAE;wBAC3Cb,WAAW;oBACb;iBACD;YACH;YACA,MAAMuC,WAAWvG,KAAKuB,IAAI,CAACoB,YAAY;YAEvCuB,OAAOhD,QAAQiF,eAAe,CAACI,WAAW7B,OAAO,CAAC,EAAE;YACpDR,OAAOhD,QAAQiF,eAAe,CAACI,UAAU;gBAAEC,SAAS;YAAK,IAAI9B,OAAO,CAAC;gBACnE;oBAAE0B,MAAM;oBAAUvB,SAAS;oBAAcb,WAAW;gBAA2B;gBAC/E;oBAAEoC,MAAM;oBAAUvB,SAAS;oBAAeb,WAAW;gBAA2B;aACjF;QACH;QAEAC,GAAG,gDAAgD;YACjD,MAAMtB,aAAaH,aAAa,aAAa;gBAC3CI,QAAQ;oBACN;oBACA;wBACEe,MAAM;wBACNC,MAAM;4BAAEiB,SAAS;wBAAQ;wBACzBb,WAAW;oBACb;oBACA;wBAAEL,MAAM;wBAAqBC,MAAM,CAAC;wBAAGI,WAAW;oBAA2B;iBAC9E;YACH;YAEA,MAAMkC,WAAWhF,QAAQiF,eAAe,CAACnG,KAAKuB,IAAI,CAACoB,YAAY;YAE/DuB,OAAOgC,UAAUxB,OAAO,CAAC;gBACvB;oBAAE0B,MAAM;oBAAQvB,SAAS;oBAASb,WAAW;gBAA2B;aACzE;QACH;QAEAC,GAAG,wCAAwC;YACzCC,OAAOhD,QAAQiF,eAAe,CAACnG,KAAKuB,IAAI,CAACJ,QAAQ,mBAAmBuD,OAAO,CAAC,EAAE;QAChF;IACF;IAEAzD,SAAS,gBAAgB;QACvBgD,GAAG,oDAAoD;YACrDzB,aAAa,aAAa;gBACxBI,QAAQ;oBACNa,aAAa,aAAa,WAAW;oBACrC;wBACEE,MAAM;wBACNC,MAAM;4BAAEiB,SAAS;wBAAa;wBAC9Bb,WAAW;oBACb;oBACA;wBACEL,MAAM;wBACNC,MAAM;4BAAEiB,SAAS;wBAAS;wBAC1Bb,WAAW;oBACb;iBACD;YACH;YACAxB,aAAa,aAAa;gBACxBI,QAAQ;oBACNa,aAAa,aAAa,WAAW;oBACrC;wBACEE,MAAM;wBACNC,MAAM;4BAAEiB,SAAS;wBAAa;wBAC9Bb,WAAW;oBACb;iBACD;YACH;YAEA,MAAMyC,WAAW,MAAMvF,QAAQwF,YAAY;YAE3CxC,OAAOuC,UAAUtB,YAAY,CAAC;YAC9B,MAAMwB,OAAOvD,OAAOwD,WAAW,CAACH,SAAS3D,GAAG,CAAC,CAACkD,UAAY;oBAACA,QAAQvD,SAAS;oBAAEuD;iBAAQ;YACtF9B,OAAOyC,IAAI,CAAC,YAAY,EAAEvB,aAAa,CAAC;gBACtCzB,MAAM;gBACNzB,KAAK;gBACL2E,kBAAkB;gBAClBpB,iBAAiBzF,KAAKuB,IAAI,CAACH,iBAAiB,aAAa;YAC3D;YACA8C,OAAOyC,IAAI,CAAC,YAAY,EAAEvB,aAAa,CAAC;gBACtCzB,MAAM;gBACNzB,KAAK;gBACL2E,kBAAkB;YACpB;QACF;QAEA5C,GAAG,wDAAwD;YACzDzB,aAAa,UAAU;gBAAEI,QAAQ;oBAACa,aAAa,UAAU;iBAAS;YAAC;YACnEjB,aAAa,SAAS;gBAAEI,QAAQ;oBAACa,aAAa,SAAS;iBAAU;YAAC;YAElE,MAAMS,OAAOhD,QAAQ4F,gBAAgB,CAAC,WAAWC,QAAQ,CAACrC,OAAO,CAAC;gBAChER,OAAO8C,gBAAgB,CAAC;oBACtBvE,WAAW;oBACXgD,iBAAiBzF,KAAKuB,IAAI,CAACH,iBAAiB,UAAU;gBACxD;aACD;QACH;QAEA6C,GAAG,6BAA6B;YAC9BzB,aAAa,QAAQ;gBAAEI,QAAQ;oBAACa,aAAa,QAAQ;iBAAS;YAAC;YAC/DjB,aAAa,QAAQ;gBAAEI,QAAQ;oBAACa,aAAa,QAAQ;iBAAU;YAAC;YAEhE,MAAMgD,WAAW,MAAMvF,QAAQwF,YAAY,CAAC;gBAAExE,KAAK;YAAQ;YAE3DgC,OAAOuC,UAAUtB,YAAY,CAAC;YAC9BjB,OAAOuC,QAAQ,CAAC,EAAE,CAAChE,SAAS,EAAE0B,IAAI,CAAC;QACrC;QAEAF,GAAG,kEAAkE;YACnEzB,aAAa,qBAAqB;gBAChCW,WAAW;oBACT6B,IAAI;oBACJ9C,KAAK;oBACLD,MAAM;oBACNgD,YAAY;oBACZC,YAAY;gBACd;YACF;YAEA,MAAMuB,WAAW,MAAMvF,QAAQwF,YAAY;YAE3CxC,OAAOuC,UAAUtB,YAAY,CAAC;YAC9BjB,OAAOuC,QAAQ,CAAC,EAAE,EAAErB,aAAa,CAAC;gBAChCzB,MAAM;gBACNlB,WAAW;gBACXP,KAAK;gBACL2E,kBAAkB;gBAClBpB,iBAAiBzF,KAAKuB,IAAI,CAACH,iBAAiB,qBAAqB;YACnE;QACF;QAEA6C,GAAG,kEAAkE;YACnEnE,GAAG2B,SAAS,CAACzB,KAAKuB,IAAI,CAACH,iBAAiB,UAAU;gBAAEM,WAAW;YAAK;YAEpE,MAAM+E,WAAW,MAAMvF,QAAQwF,YAAY;YAE3CxC,OAAOuC,UAAU/B,OAAO,CAAC,EAAE;QAC7B;QAEAT,GAAG,6DAA6D;YAC9D/C,UAAU,IAAIjB,eAAe0B,WAAW;gBAAEP,iBAAiBpB,KAAKuB,IAAI,CAACJ,QAAQ;YAAW;YAExF,MAAM+C,OAAOhD,QAAQwF,YAAY,IAAIK,QAAQ,CAACrC,OAAO,CAAC,EAAE;QAC1D;IACF;AACF"}
|
|
@@ -1241,6 +1241,42 @@ describe("GeminiCliAdapter", ()=>{
|
|
|
1241
1241
|
firstUserMessage: "hello b"
|
|
1242
1242
|
});
|
|
1243
1243
|
});
|
|
1244
|
+
it("finds an exact session ID from Gemini metadata", async ()=>{
|
|
1245
|
+
const wantedPath = writeSession(tmpHome, "aaa", "session-one", {
|
|
1246
|
+
sessionId: "wanted",
|
|
1247
|
+
projectHash: hashProjectRoot("/repo"),
|
|
1248
|
+
startTime: "2025-01-01T00:00:00Z",
|
|
1249
|
+
directories: [
|
|
1250
|
+
"/repo"
|
|
1251
|
+
],
|
|
1252
|
+
messages: [
|
|
1253
|
+
{
|
|
1254
|
+
type: "user",
|
|
1255
|
+
content: "wanted prompt"
|
|
1256
|
+
}
|
|
1257
|
+
]
|
|
1258
|
+
});
|
|
1259
|
+
writeSession(tmpHome, "bbb", "session-two", {
|
|
1260
|
+
sessionId: "other",
|
|
1261
|
+
projectHash: hashProjectRoot("/other"),
|
|
1262
|
+
startTime: "2025-01-01T00:00:00Z",
|
|
1263
|
+
directories: [
|
|
1264
|
+
"/other"
|
|
1265
|
+
],
|
|
1266
|
+
messages: [
|
|
1267
|
+
{
|
|
1268
|
+
type: "user",
|
|
1269
|
+
content: "other prompt"
|
|
1270
|
+
}
|
|
1271
|
+
]
|
|
1272
|
+
});
|
|
1273
|
+
await expect(adapter.findSessionsById("wanted")).resolves.toEqual([
|
|
1274
|
+
expect.objectContaining({
|
|
1275
|
+
sessionId: "wanted",
|
|
1276
|
+
sessionFilePath: wantedPath
|
|
1277
|
+
})
|
|
1278
|
+
]);
|
|
1279
|
+
});
|
|
1244
1280
|
it("applies strict-equality cwd filter against directories[0]", async ()=>{
|
|
1245
1281
|
writeSession(tmpHome, "aaa", "session-keep", {
|
|
1246
1282
|
sessionId: "keep",
|