@ai-devkit/agent-manager 0.28.1 → 0.30.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/__tests__/adapters/ClaudeCodeAdapter.test.js +1 -342
- package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js.map +1 -1
- package/dist/__tests__/capacity/codex.test.js +343 -0
- package/dist/__tests__/capacity/codex.test.js.map +1 -0
- package/dist/__tests__/capacity/index.test.js +50 -0
- package/dist/__tests__/capacity/index.test.js.map +1 -0
- package/dist/__tests__/database/DurableAgentsDatabase.test.js +31 -3
- package/dist/__tests__/database/DurableAgentsDatabase.test.js.map +1 -1
- package/dist/__tests__/durable/CodexCliProbe.test.js +129 -0
- package/dist/__tests__/durable/CodexCliProbe.test.js.map +1 -0
- package/dist/__tests__/durable/CodexDurableAgentRepository.test.js +84 -0
- package/dist/__tests__/durable/CodexDurableAgentRepository.test.js.map +1 -0
- package/dist/__tests__/durable/CodexPrintAgent.integration.test.js +126 -0
- package/dist/__tests__/durable/CodexPrintAgent.integration.test.js.map +1 -0
- package/dist/__tests__/durable/CodexPrintAgentService.test.js +271 -0
- package/dist/__tests__/durable/CodexPrintAgentService.test.js.map +1 -0
- package/dist/__tests__/durable/CodexPrintRunner.test.js +393 -0
- package/dist/__tests__/durable/CodexPrintRunner.test.js.map +1 -0
- package/dist/__tests__/print/ClaudeCliProbe.test.js +3 -7
- package/dist/__tests__/print/ClaudeCliProbe.test.js.map +1 -1
- package/dist/__tests__/print/ClaudePrintAgent.integration.test.js +33 -27
- package/dist/__tests__/print/ClaudePrintAgent.integration.test.js.map +1 -1
- package/dist/__tests__/print/ClaudePrintAgentService.test.js +65 -0
- package/dist/__tests__/print/ClaudePrintAgentService.test.js.map +1 -1
- package/dist/__tests__/print/ClaudePrintRunner.test.js +4 -10
- package/dist/__tests__/print/ClaudePrintRunner.test.js.map +1 -1
- package/dist/__tests__/providers/claude/ClaudeAgentMapper.test.js +79 -0
- package/dist/__tests__/providers/claude/ClaudeAgentMapper.test.js.map +1 -0
- package/dist/__tests__/providers/claude/ClaudeSessionLocator.test.js +436 -0
- package/dist/__tests__/providers/claude/ClaudeSessionLocator.test.js.map +1 -0
- package/dist/__tests__/providers/pi/durable/PiCliProbe.test.js +76 -0
- package/dist/__tests__/providers/pi/durable/PiCliProbe.test.js.map +1 -0
- package/dist/__tests__/providers/pi/durable/PiDurableAgentRepository.test.js +43 -0
- package/dist/__tests__/providers/pi/durable/PiDurableAgentRepository.test.js.map +1 -0
- package/dist/__tests__/providers/pi/durable/PiPrintAgentService.test.js +202 -0
- package/dist/__tests__/providers/pi/durable/PiPrintAgentService.test.js.map +1 -0
- package/dist/__tests__/providers/pi/durable/PiPrintProtocol.test.js +119 -0
- package/dist/__tests__/providers/pi/durable/PiPrintProtocol.test.js.map +1 -0
- package/dist/__tests__/providers/pi/durable/PiPrintRunner.test.js +386 -0
- package/dist/__tests__/providers/pi/durable/PiPrintRunner.test.js.map +1 -0
- package/dist/__tests__/providers/pi/durable/PiStreamParser.test.js +34 -0
- package/dist/__tests__/providers/pi/durable/PiStreamParser.test.js.map +1 -0
- package/dist/__tests__/utils/ClaudeSessionParser.test.js +2 -2
- package/dist/__tests__/utils/ClaudeSessionParser.test.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/capacity/codex.d.ts +36 -0
- package/dist/capacity/codex.d.ts.map +1 -0
- package/dist/capacity/codex.js +317 -0
- package/dist/capacity/codex.js.map +1 -0
- package/dist/capacity/index.d.ts +11 -0
- package/dist/capacity/index.d.ts.map +1 -0
- package/dist/capacity/index.js +49 -0
- package/dist/capacity/index.js.map +1 -0
- package/dist/capacity/types.d.ts +17 -0
- package/dist/capacity/types.d.ts.map +1 -0
- package/dist/capacity/types.js +3 -0
- package/dist/capacity/types.js.map +1 -0
- package/dist/database/migrations/004_codex_durable_sessions.sql +1 -0
- package/dist/durable/DurableAgent.d.ts +23 -3
- package/dist/durable/DurableAgent.d.ts.map +1 -1
- package/dist/durable/DurableAgent.js +12 -0
- package/dist/durable/DurableAgent.js.map +1 -1
- package/dist/durable/DurableAgentRepository.d.ts +6 -7
- package/dist/durable/DurableAgentRepository.d.ts.map +1 -1
- package/dist/durable/DurableAgentRepository.js +73 -42
- package/dist/durable/DurableAgentRepository.js.map +1 -1
- package/dist/durable/process.d.ts +8 -0
- package/dist/durable/process.d.ts.map +1 -0
- package/dist/durable/process.js +40 -0
- package/dist/durable/process.js.map +1 -0
- package/dist/durable/run.d.ts +32 -0
- package/dist/durable/run.d.ts.map +1 -0
- package/dist/durable/run.js +46 -0
- package/dist/durable/run.js.map +1 -0
- package/dist/durable/utils.d.ts +19 -0
- package/dist/durable/utils.d.ts.map +1 -0
- package/dist/durable/utils.js +52 -0
- package/dist/durable/utils.js.map +1 -0
- package/dist/index.d.ts +19 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -8
- package/dist/index.js.map +1 -1
- package/dist/providers/claude/ClaudeAgentMapper.d.ts +21 -0
- package/dist/providers/claude/ClaudeAgentMapper.d.ts.map +1 -0
- package/dist/providers/claude/ClaudeAgentMapper.js +42 -0
- package/dist/providers/claude/ClaudeAgentMapper.js.map +1 -0
- package/dist/providers/claude/ClaudeCodeAdapter.d.ts +29 -0
- package/dist/providers/claude/ClaudeCodeAdapter.d.ts.map +1 -0
- package/dist/providers/claude/ClaudeCodeAdapter.js +129 -0
- package/dist/providers/claude/ClaudeCodeAdapter.js.map +1 -0
- package/dist/{adapters/ClaudeCodeAdapter.d.ts → providers/claude/ClaudeSessionLocator.d.ts} +68 -52
- package/dist/providers/claude/ClaudeSessionLocator.d.ts.map +1 -0
- package/dist/{adapters/ClaudeCodeAdapter.js → providers/claude/ClaudeSessionLocator.js} +71 -189
- package/dist/providers/claude/ClaudeSessionLocator.js.map +1 -0
- package/dist/{utils → providers/claude}/ClaudeSessionParser.d.ts +2 -2
- package/dist/providers/claude/ClaudeSessionParser.d.ts.map +1 -0
- package/dist/{utils → providers/claude}/ClaudeSessionParser.js +1 -1
- package/dist/providers/claude/ClaudeSessionParser.js.map +1 -0
- package/dist/providers/claude/durable/ClaudeCliProbe.d.ts.map +1 -0
- package/dist/{durable → providers/claude/durable}/ClaudeCliProbe.js +4 -9
- package/dist/providers/claude/durable/ClaudeCliProbe.js.map +1 -0
- package/dist/{durable → providers/claude/durable}/ClaudePrintAgentService.d.ts +4 -9
- package/dist/providers/claude/durable/ClaudePrintAgentService.d.ts.map +1 -0
- package/dist/providers/claude/durable/ClaudePrintAgentService.js +45 -0
- package/dist/providers/claude/durable/ClaudePrintAgentService.js.map +1 -0
- package/dist/{durable → providers/claude/durable}/ClaudePrintRunner.d.ts +3 -3
- package/dist/providers/claude/durable/ClaudePrintRunner.d.ts.map +1 -0
- package/dist/providers/claude/durable/ClaudePrintRunner.js +75 -0
- package/dist/providers/claude/durable/ClaudePrintRunner.js.map +1 -0
- package/dist/providers/claude/durable/ClaudeStreamParser.d.ts +17 -0
- package/dist/providers/claude/durable/ClaudeStreamParser.d.ts.map +1 -0
- package/dist/providers/claude/durable/ClaudeStreamParser.js +69 -0
- package/dist/providers/claude/durable/ClaudeStreamParser.js.map +1 -0
- package/dist/providers/codex/durable/CodexCliProbe.d.ts +20 -0
- package/dist/providers/codex/durable/CodexCliProbe.d.ts.map +1 -0
- package/dist/providers/codex/durable/CodexCliProbe.js +61 -0
- package/dist/providers/codex/durable/CodexCliProbe.js.map +1 -0
- package/dist/providers/codex/durable/CodexPrintAgentService.d.ts +40 -0
- package/dist/providers/codex/durable/CodexPrintAgentService.d.ts.map +1 -0
- package/dist/providers/codex/durable/CodexPrintAgentService.js +50 -0
- package/dist/providers/codex/durable/CodexPrintAgentService.js.map +1 -0
- package/dist/providers/codex/durable/CodexPrintRunner.d.ts +34 -0
- package/dist/providers/codex/durable/CodexPrintRunner.d.ts.map +1 -0
- package/dist/providers/codex/durable/CodexPrintRunner.js +78 -0
- package/dist/providers/codex/durable/CodexPrintRunner.js.map +1 -0
- package/dist/providers/codex/durable/CodexStreamParser.d.ts +21 -0
- package/dist/providers/codex/durable/CodexStreamParser.d.ts.map +1 -0
- package/dist/providers/codex/durable/CodexStreamParser.js +86 -0
- package/dist/providers/codex/durable/CodexStreamParser.js.map +1 -0
- package/dist/providers/pi/durable/PiCliProbe.d.ts +20 -0
- package/dist/providers/pi/durable/PiCliProbe.d.ts.map +1 -0
- package/dist/providers/pi/durable/PiCliProbe.js +51 -0
- package/dist/providers/pi/durable/PiCliProbe.js.map +1 -0
- package/dist/providers/pi/durable/PiPrintAgentService.d.ts +39 -0
- package/dist/providers/pi/durable/PiPrintAgentService.d.ts.map +1 -0
- package/dist/providers/pi/durable/PiPrintAgentService.js +47 -0
- package/dist/providers/pi/durable/PiPrintAgentService.js.map +1 -0
- package/dist/providers/pi/durable/PiPrintProtocol.d.ts +4 -0
- package/dist/providers/pi/durable/PiPrintProtocol.d.ts.map +1 -0
- package/dist/providers/pi/durable/PiPrintProtocol.js +44 -0
- package/dist/providers/pi/durable/PiPrintProtocol.js.map +1 -0
- package/dist/providers/pi/durable/PiPrintRunner.d.ts +32 -0
- package/dist/providers/pi/durable/PiPrintRunner.d.ts.map +1 -0
- package/dist/providers/pi/durable/PiPrintRunner.js +61 -0
- package/dist/providers/pi/durable/PiPrintRunner.js.map +1 -0
- package/dist/providers/pi/durable/PiStreamParser.d.ts +21 -0
- package/dist/providers/pi/durable/PiStreamParser.d.ts.map +1 -0
- package/dist/providers/pi/durable/PiStreamParser.js +71 -0
- package/dist/providers/pi/durable/PiStreamParser.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/adapters/ClaudeCodeAdapter.test.ts +1 -307
- package/src/__tests__/capacity/codex.test.ts +184 -0
- package/src/__tests__/capacity/index.test.ts +38 -0
- package/src/__tests__/database/DurableAgentsDatabase.test.ts +28 -3
- package/src/__tests__/durable/CodexCliProbe.test.ts +63 -0
- package/src/__tests__/durable/CodexDurableAgentRepository.test.ts +54 -0
- package/src/__tests__/durable/CodexPrintAgent.integration.test.ts +79 -0
- package/src/__tests__/durable/CodexPrintAgentService.test.ts +139 -0
- package/src/__tests__/durable/CodexPrintRunner.test.ts +189 -0
- package/src/__tests__/fixtures/fake-codex.cjs +45 -0
- package/src/__tests__/print/ClaudeCliProbe.test.ts +3 -7
- package/src/__tests__/print/ClaudePrintAgent.integration.test.ts +19 -22
- package/src/__tests__/print/ClaudePrintAgentService.test.ts +33 -1
- package/src/__tests__/print/ClaudePrintRunner.test.ts +4 -10
- package/src/__tests__/providers/claude/ClaudeAgentMapper.test.ts +84 -0
- package/src/__tests__/providers/claude/ClaudeSessionLocator.test.ts +411 -0
- package/src/__tests__/providers/pi/durable/PiCliProbe.test.ts +38 -0
- package/src/__tests__/providers/pi/durable/PiDurableAgentRepository.test.ts +32 -0
- package/src/__tests__/providers/pi/durable/PiPrintAgentService.test.ts +69 -0
- package/src/__tests__/providers/pi/durable/PiPrintProtocol.test.ts +33 -0
- package/src/__tests__/providers/pi/durable/PiPrintRunner.test.ts +107 -0
- package/src/__tests__/providers/pi/durable/PiStreamParser.test.ts +24 -0
- package/src/__tests__/utils/ClaudeSessionParser.test.ts +2 -2
- package/src/adapters/index.ts +1 -1
- package/src/capacity/codex.ts +320 -0
- package/src/capacity/index.ts +57 -0
- package/src/capacity/types.ts +18 -0
- package/src/database/migrations/004_codex_durable_sessions.sql +1 -0
- package/src/durable/DurableAgent.ts +51 -3
- package/src/durable/DurableAgentRepository.ts +60 -31
- package/src/durable/process.ts +28 -0
- package/src/durable/run.ts +74 -0
- package/src/durable/utils.ts +61 -0
- package/src/index.ts +37 -15
- package/src/providers/claude/ClaudeAgentMapper.ts +62 -0
- package/src/providers/claude/ClaudeCodeAdapter.ts +160 -0
- package/src/{adapters/ClaudeCodeAdapter.ts → providers/claude/ClaudeSessionLocator.ts} +97 -239
- package/src/{utils → providers/claude}/ClaudeSessionParser.ts +2 -2
- package/src/{durable → providers/claude/durable}/ClaudeCliProbe.ts +4 -10
- package/src/providers/claude/durable/ClaudePrintAgentService.ts +66 -0
- package/src/providers/claude/durable/ClaudePrintRunner.ts +92 -0
- package/src/providers/claude/durable/ClaudeStreamParser.ts +79 -0
- package/src/providers/codex/durable/CodexCliProbe.ts +60 -0
- package/src/providers/codex/durable/CodexPrintAgentService.ts +65 -0
- package/src/providers/codex/durable/CodexPrintRunner.ts +94 -0
- package/src/providers/codex/durable/CodexStreamParser.ts +104 -0
- package/src/providers/pi/durable/PiCliProbe.ts +48 -0
- package/src/providers/pi/durable/PiPrintAgentService.ts +69 -0
- package/src/providers/pi/durable/PiPrintProtocol.ts +39 -0
- package/src/providers/pi/durable/PiPrintRunner.ts +88 -0
- package/src/providers/pi/durable/PiStreamParser.ts +84 -0
- package/dist/adapters/ClaudeCodeAdapter.d.ts.map +0 -1
- package/dist/adapters/ClaudeCodeAdapter.js.map +0 -1
- package/dist/durable/ClaudeCliProbe.d.ts.map +0 -1
- package/dist/durable/ClaudeCliProbe.js.map +0 -1
- package/dist/durable/ClaudePrintAgentService.d.ts.map +0 -1
- package/dist/durable/ClaudePrintAgentService.js +0 -66
- package/dist/durable/ClaudePrintAgentService.js.map +0 -1
- package/dist/durable/ClaudePrintRunner.d.ts.map +0 -1
- package/dist/durable/ClaudePrintRunner.js +0 -128
- package/dist/durable/ClaudePrintRunner.js.map +0 -1
- package/dist/utils/ClaudeSessionParser.d.ts.map +0 -1
- package/dist/utils/ClaudeSessionParser.js.map +0 -1
- package/src/durable/ClaudePrintAgentService.ts +0 -94
- package/src/durable/ClaudePrintRunner.ts +0 -139
- /package/dist/{durable → providers/claude/durable}/ClaudeCliProbe.d.ts +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Tests for ClaudeCodeAdapter
|
|
3
3
|
*/ import * as fs from 'fs';
|
|
4
4
|
import * as path from 'path';
|
|
5
|
-
import { ClaudeCodeAdapter } from '../../
|
|
5
|
+
import { ClaudeCodeAdapter } from '../../providers/claude/ClaudeCodeAdapter.js';
|
|
6
6
|
import { AgentStatus } from '../../adapters/AgentAdapter.js';
|
|
7
7
|
import { listAgentProcesses, enrichProcesses, captureProcessSnapshot } from '../../utils/process.js';
|
|
8
8
|
import { batchGetSessionFileBirthtimes } from '../../utils/session.js';
|
|
@@ -910,148 +910,6 @@ describe('ClaudeCodeAdapter', ()=>{
|
|
|
910
910
|
});
|
|
911
911
|
});
|
|
912
912
|
});
|
|
913
|
-
describe('discoverSessions', ()=>{
|
|
914
|
-
let tmpDir;
|
|
915
|
-
beforeEach(()=>{
|
|
916
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'claude-test-'));
|
|
917
|
-
adapter.projectsDir = path.join(tmpDir, 'projects');
|
|
918
|
-
});
|
|
919
|
-
afterEach(()=>{
|
|
920
|
-
fs.rmSync(tmpDir, {
|
|
921
|
-
recursive: true,
|
|
922
|
-
force: true
|
|
923
|
-
});
|
|
924
|
-
});
|
|
925
|
-
it('should return empty when projects dir does not exist', ()=>{
|
|
926
|
-
adapter.projectsDir = path.join(tmpDir, 'nonexistent');
|
|
927
|
-
const discoverSessions = adapter.discoverSessions.bind(adapter);
|
|
928
|
-
const result = discoverSessions([
|
|
929
|
-
{
|
|
930
|
-
pid: 1,
|
|
931
|
-
command: 'claude',
|
|
932
|
-
cwd: '/test',
|
|
933
|
-
tty: ''
|
|
934
|
-
}
|
|
935
|
-
]);
|
|
936
|
-
expect(result).toEqual([]);
|
|
937
|
-
});
|
|
938
|
-
it('should scan only directories matching process CWDs', ()=>{
|
|
939
|
-
const projectsDir = path.join(tmpDir, 'projects');
|
|
940
|
-
adapter.projectsDir = projectsDir;
|
|
941
|
-
const discoverSessions = adapter.discoverSessions.bind(adapter);
|
|
942
|
-
// /my/project → -my-project (encoded dir)
|
|
943
|
-
const encodedDir = path.join(projectsDir, '-my-project');
|
|
944
|
-
fs.mkdirSync(encodedDir, {
|
|
945
|
-
recursive: true
|
|
946
|
-
});
|
|
947
|
-
// Also create another dir that should NOT be scanned
|
|
948
|
-
const otherDir = path.join(projectsDir, '-other-project');
|
|
949
|
-
fs.mkdirSync(otherDir, {
|
|
950
|
-
recursive: true
|
|
951
|
-
});
|
|
952
|
-
const mockFiles = [
|
|
953
|
-
{
|
|
954
|
-
sessionId: 's1',
|
|
955
|
-
filePath: path.join(encodedDir, 's1.jsonl'),
|
|
956
|
-
projectDir: encodedDir,
|
|
957
|
-
birthtimeMs: 1710800324000,
|
|
958
|
-
resolvedCwd: ''
|
|
959
|
-
}
|
|
960
|
-
];
|
|
961
|
-
mockedBatchGetSessionFileBirthtimes.mockReturnValue(mockFiles);
|
|
962
|
-
const processes = [
|
|
963
|
-
{
|
|
964
|
-
pid: 1,
|
|
965
|
-
command: 'claude',
|
|
966
|
-
cwd: '/my/project',
|
|
967
|
-
tty: ''
|
|
968
|
-
}
|
|
969
|
-
];
|
|
970
|
-
const result = discoverSessions(processes);
|
|
971
|
-
expect(result).toHaveLength(1);
|
|
972
|
-
expect(result[0].resolvedCwd).toBe('/my/project');
|
|
973
|
-
// batchGetSessionFileBirthtimes called once with all dirs
|
|
974
|
-
expect(mockedBatchGetSessionFileBirthtimes).toHaveBeenCalledTimes(1);
|
|
975
|
-
expect(mockedBatchGetSessionFileBirthtimes).toHaveBeenCalledWith([
|
|
976
|
-
encodedDir
|
|
977
|
-
]);
|
|
978
|
-
});
|
|
979
|
-
it('should return empty when encoded dir does not exist', ()=>{
|
|
980
|
-
const projectsDir = path.join(tmpDir, 'projects');
|
|
981
|
-
fs.mkdirSync(projectsDir, {
|
|
982
|
-
recursive: true
|
|
983
|
-
});
|
|
984
|
-
adapter.projectsDir = projectsDir;
|
|
985
|
-
const discoverSessions = adapter.discoverSessions.bind(adapter);
|
|
986
|
-
// Process CWD /test encodes to -test, but that dir doesn't exist
|
|
987
|
-
const result = discoverSessions([
|
|
988
|
-
{
|
|
989
|
-
pid: 1,
|
|
990
|
-
command: 'claude',
|
|
991
|
-
cwd: '/test',
|
|
992
|
-
tty: ''
|
|
993
|
-
}
|
|
994
|
-
]);
|
|
995
|
-
expect(result).toEqual([]);
|
|
996
|
-
expect(mockedBatchGetSessionFileBirthtimes).not.toHaveBeenCalled();
|
|
997
|
-
});
|
|
998
|
-
it('should deduplicate when multiple processes share same CWD', ()=>{
|
|
999
|
-
const projectsDir = path.join(tmpDir, 'projects');
|
|
1000
|
-
adapter.projectsDir = projectsDir;
|
|
1001
|
-
const discoverSessions = adapter.discoverSessions.bind(adapter);
|
|
1002
|
-
const encodedDir = path.join(projectsDir, '-my-project');
|
|
1003
|
-
fs.mkdirSync(encodedDir, {
|
|
1004
|
-
recursive: true
|
|
1005
|
-
});
|
|
1006
|
-
mockedBatchGetSessionFileBirthtimes.mockReturnValue([
|
|
1007
|
-
{
|
|
1008
|
-
sessionId: 's1',
|
|
1009
|
-
filePath: path.join(encodedDir, 's1.jsonl'),
|
|
1010
|
-
projectDir: encodedDir,
|
|
1011
|
-
birthtimeMs: 1710800324000,
|
|
1012
|
-
resolvedCwd: ''
|
|
1013
|
-
}
|
|
1014
|
-
]);
|
|
1015
|
-
const processes = [
|
|
1016
|
-
{
|
|
1017
|
-
pid: 1,
|
|
1018
|
-
command: 'claude',
|
|
1019
|
-
cwd: '/my/project',
|
|
1020
|
-
tty: ''
|
|
1021
|
-
},
|
|
1022
|
-
{
|
|
1023
|
-
pid: 2,
|
|
1024
|
-
command: 'claude',
|
|
1025
|
-
cwd: '/my/project',
|
|
1026
|
-
tty: ''
|
|
1027
|
-
}
|
|
1028
|
-
];
|
|
1029
|
-
const result = discoverSessions(processes);
|
|
1030
|
-
// Should only call batch once with deduplicated dir
|
|
1031
|
-
expect(mockedBatchGetSessionFileBirthtimes).toHaveBeenCalledTimes(1);
|
|
1032
|
-
expect(mockedBatchGetSessionFileBirthtimes).toHaveBeenCalledWith([
|
|
1033
|
-
encodedDir
|
|
1034
|
-
]);
|
|
1035
|
-
expect(result).toHaveLength(1);
|
|
1036
|
-
});
|
|
1037
|
-
it('should skip processes with empty cwd', ()=>{
|
|
1038
|
-
const projectsDir = path.join(tmpDir, 'projects');
|
|
1039
|
-
fs.mkdirSync(projectsDir, {
|
|
1040
|
-
recursive: true
|
|
1041
|
-
});
|
|
1042
|
-
adapter.projectsDir = projectsDir;
|
|
1043
|
-
const discoverSessions = adapter.discoverSessions.bind(adapter);
|
|
1044
|
-
const result = discoverSessions([
|
|
1045
|
-
{
|
|
1046
|
-
pid: 1,
|
|
1047
|
-
command: 'claude',
|
|
1048
|
-
cwd: '',
|
|
1049
|
-
tty: ''
|
|
1050
|
-
}
|
|
1051
|
-
]);
|
|
1052
|
-
expect(result).toEqual([]);
|
|
1053
|
-
});
|
|
1054
|
-
});
|
|
1055
913
|
describe('helper methods', ()=>{
|
|
1056
914
|
describe('determineStatus', ()=>{
|
|
1057
915
|
it('should return "unknown" for sessions with no last entry type', ()=>{
|
|
@@ -1234,205 +1092,6 @@ describe('ClaudeCodeAdapter', ()=>{
|
|
|
1234
1092
|
force: true
|
|
1235
1093
|
});
|
|
1236
1094
|
});
|
|
1237
|
-
describe('tryPidFileMatching', ()=>{
|
|
1238
|
-
let sessionsDir;
|
|
1239
|
-
let projectsDir;
|
|
1240
|
-
beforeEach(()=>{
|
|
1241
|
-
sessionsDir = path.join(tmpDir, 'sessions');
|
|
1242
|
-
projectsDir = path.join(tmpDir, 'projects');
|
|
1243
|
-
fs.mkdirSync(sessionsDir, {
|
|
1244
|
-
recursive: true
|
|
1245
|
-
});
|
|
1246
|
-
adapter.sessionsDir = sessionsDir;
|
|
1247
|
-
adapter.projectsDir = projectsDir;
|
|
1248
|
-
});
|
|
1249
|
-
const makeProc = (pid, cwd = '/project/test', startTime)=>({
|
|
1250
|
-
pid,
|
|
1251
|
-
command: 'claude',
|
|
1252
|
-
cwd,
|
|
1253
|
-
tty: 'ttys001',
|
|
1254
|
-
startTime
|
|
1255
|
-
});
|
|
1256
|
-
const writePidFile = (pid, sessionId, cwd, startedAt)=>{
|
|
1257
|
-
fs.writeFileSync(path.join(sessionsDir, `${pid}.json`), JSON.stringify({
|
|
1258
|
-
pid,
|
|
1259
|
-
sessionId,
|
|
1260
|
-
cwd,
|
|
1261
|
-
startedAt,
|
|
1262
|
-
kind: 'interactive',
|
|
1263
|
-
entrypoint: 'cli'
|
|
1264
|
-
}));
|
|
1265
|
-
};
|
|
1266
|
-
const writeJsonl = (cwd, sessionId)=>{
|
|
1267
|
-
const encoded = cwd.replace(/[^a-zA-Z0-9]/g, '-');
|
|
1268
|
-
const projDir = path.join(projectsDir, encoded);
|
|
1269
|
-
fs.mkdirSync(projDir, {
|
|
1270
|
-
recursive: true
|
|
1271
|
-
});
|
|
1272
|
-
const filePath = path.join(projDir, `${sessionId}.jsonl`);
|
|
1273
|
-
fs.writeFileSync(filePath, JSON.stringify({
|
|
1274
|
-
type: 'assistant',
|
|
1275
|
-
timestamp: new Date().toISOString()
|
|
1276
|
-
}));
|
|
1277
|
-
return filePath;
|
|
1278
|
-
};
|
|
1279
|
-
it('should return direct match when PID file and JSONL both exist within time tolerance', ()=>{
|
|
1280
|
-
const startTime = new Date();
|
|
1281
|
-
const proc = makeProc(1001, '/project/test', startTime);
|
|
1282
|
-
writePidFile(1001, 'session-abc', '/project/test', startTime.getTime());
|
|
1283
|
-
writeJsonl('/project/test', 'session-abc');
|
|
1284
|
-
const tryMatch = adapter.tryPidFileMatching.bind(adapter);
|
|
1285
|
-
const { direct, fallback } = tryMatch([
|
|
1286
|
-
proc
|
|
1287
|
-
]);
|
|
1288
|
-
expect(direct).toHaveLength(1);
|
|
1289
|
-
expect(fallback).toHaveLength(0);
|
|
1290
|
-
expect(direct[0].sessionFile.sessionId).toBe('session-abc');
|
|
1291
|
-
expect(direct[0].sessionFile.resolvedCwd).toBe('/project/test');
|
|
1292
|
-
expect(direct[0].process.pid).toBe(1001);
|
|
1293
|
-
});
|
|
1294
|
-
it('should fall back when PID file exists but JSONL is missing', ()=>{
|
|
1295
|
-
const startTime = new Date();
|
|
1296
|
-
const proc = makeProc(1002, '/project/test', startTime);
|
|
1297
|
-
writePidFile(1002, 'nonexistent-session', '/project/test', startTime.getTime());
|
|
1298
|
-
// No JSONL file written
|
|
1299
|
-
const tryMatch = adapter.tryPidFileMatching.bind(adapter);
|
|
1300
|
-
const { direct, fallback } = tryMatch([
|
|
1301
|
-
proc
|
|
1302
|
-
]);
|
|
1303
|
-
expect(direct).toHaveLength(0);
|
|
1304
|
-
expect(fallback).toHaveLength(1);
|
|
1305
|
-
expect(fallback[0].pid).toBe(1002);
|
|
1306
|
-
});
|
|
1307
|
-
it('should fall back when startedAt is stale (>60s from proc.startTime)', ()=>{
|
|
1308
|
-
const startTime = new Date();
|
|
1309
|
-
const staleTime = startTime.getTime() - 90_000; // 90 seconds earlier
|
|
1310
|
-
const proc = makeProc(1003, '/project/test', startTime);
|
|
1311
|
-
writePidFile(1003, 'stale-session', '/project/test', staleTime);
|
|
1312
|
-
writeJsonl('/project/test', 'stale-session');
|
|
1313
|
-
const tryMatch = adapter.tryPidFileMatching.bind(adapter);
|
|
1314
|
-
const { direct, fallback } = tryMatch([
|
|
1315
|
-
proc
|
|
1316
|
-
]);
|
|
1317
|
-
expect(direct).toHaveLength(0);
|
|
1318
|
-
expect(fallback).toHaveLength(1);
|
|
1319
|
-
});
|
|
1320
|
-
it('should accept PID file when startedAt is within 60s tolerance', ()=>{
|
|
1321
|
-
const startTime = new Date();
|
|
1322
|
-
const closeTime = startTime.getTime() - 30_000; // 30 seconds earlier — within tolerance
|
|
1323
|
-
const proc = makeProc(1004, '/project/test', startTime);
|
|
1324
|
-
writePidFile(1004, 'close-session', '/project/test', closeTime);
|
|
1325
|
-
writeJsonl('/project/test', 'close-session');
|
|
1326
|
-
const tryMatch = adapter.tryPidFileMatching.bind(adapter);
|
|
1327
|
-
const { direct, fallback } = tryMatch([
|
|
1328
|
-
proc
|
|
1329
|
-
]);
|
|
1330
|
-
expect(direct).toHaveLength(1);
|
|
1331
|
-
expect(fallback).toHaveLength(0);
|
|
1332
|
-
});
|
|
1333
|
-
it('should fall back when PID file is absent', ()=>{
|
|
1334
|
-
const proc = makeProc(1005, '/project/test', new Date());
|
|
1335
|
-
// No PID file written
|
|
1336
|
-
const tryMatch = adapter.tryPidFileMatching.bind(adapter);
|
|
1337
|
-
const { direct, fallback } = tryMatch([
|
|
1338
|
-
proc
|
|
1339
|
-
]);
|
|
1340
|
-
expect(direct).toHaveLength(0);
|
|
1341
|
-
expect(fallback).toHaveLength(1);
|
|
1342
|
-
});
|
|
1343
|
-
it('should fall back when PID file contains malformed JSON', ()=>{
|
|
1344
|
-
const proc = makeProc(1006, '/project/test', new Date());
|
|
1345
|
-
fs.writeFileSync(path.join(sessionsDir, '1006.json'), 'not valid json {{{');
|
|
1346
|
-
const tryMatch = adapter.tryPidFileMatching.bind(adapter);
|
|
1347
|
-
expect(()=>{
|
|
1348
|
-
const { direct, fallback } = tryMatch([
|
|
1349
|
-
proc
|
|
1350
|
-
]);
|
|
1351
|
-
expect(direct).toHaveLength(0);
|
|
1352
|
-
expect(fallback).toHaveLength(1);
|
|
1353
|
-
}).not.toThrow();
|
|
1354
|
-
});
|
|
1355
|
-
it('should fall back for all processes when sessions dir does not exist', ()=>{
|
|
1356
|
-
adapter.sessionsDir = path.join(tmpDir, 'nonexistent-sessions');
|
|
1357
|
-
const processes = [
|
|
1358
|
-
makeProc(2001, '/a', new Date()),
|
|
1359
|
-
makeProc(2002, '/b', new Date())
|
|
1360
|
-
];
|
|
1361
|
-
const tryMatch = adapter.tryPidFileMatching.bind(adapter);
|
|
1362
|
-
const { direct, fallback } = tryMatch(processes);
|
|
1363
|
-
expect(direct).toHaveLength(0);
|
|
1364
|
-
expect(fallback).toHaveLength(2);
|
|
1365
|
-
});
|
|
1366
|
-
it('should correctly split mixed processes (some with PID files, some without)', ()=>{
|
|
1367
|
-
const startTime = new Date();
|
|
1368
|
-
const proc1 = makeProc(3001, '/project/one', startTime);
|
|
1369
|
-
const proc2 = makeProc(3002, '/project/two', startTime);
|
|
1370
|
-
const proc3 = makeProc(3003, '/project/three', startTime);
|
|
1371
|
-
writePidFile(3001, 'session-one', '/project/one', startTime.getTime());
|
|
1372
|
-
writeJsonl('/project/one', 'session-one');
|
|
1373
|
-
writePidFile(3003, 'session-three', '/project/three', startTime.getTime());
|
|
1374
|
-
writeJsonl('/project/three', 'session-three');
|
|
1375
|
-
// proc2 has no PID file
|
|
1376
|
-
const tryMatch = adapter.tryPidFileMatching.bind(adapter);
|
|
1377
|
-
const { direct, fallback } = tryMatch([
|
|
1378
|
-
proc1,
|
|
1379
|
-
proc2,
|
|
1380
|
-
proc3
|
|
1381
|
-
]);
|
|
1382
|
-
expect(direct).toHaveLength(2);
|
|
1383
|
-
expect(fallback).toHaveLength(1);
|
|
1384
|
-
expect(direct.map((d)=>d.process.pid).sort()).toEqual([
|
|
1385
|
-
3001,
|
|
1386
|
-
3003
|
|
1387
|
-
]);
|
|
1388
|
-
expect(fallback[0].pid).toBe(3002);
|
|
1389
|
-
});
|
|
1390
|
-
it('should skip stale-file check when proc.startTime is undefined', ()=>{
|
|
1391
|
-
const proc = makeProc(4001, '/project/test', undefined); // no startTime
|
|
1392
|
-
writePidFile(4001, 'no-time-session', '/project/test', Date.now() - 999_999);
|
|
1393
|
-
writeJsonl('/project/test', 'no-time-session');
|
|
1394
|
-
const tryMatch = adapter.tryPidFileMatching.bind(adapter);
|
|
1395
|
-
const { direct, fallback } = tryMatch([
|
|
1396
|
-
proc
|
|
1397
|
-
]);
|
|
1398
|
-
// startTime undefined → stale check skipped → direct match
|
|
1399
|
-
expect(direct).toHaveLength(1);
|
|
1400
|
-
expect(fallback).toHaveLength(0);
|
|
1401
|
-
});
|
|
1402
|
-
});
|
|
1403
|
-
describe('getProjectDir', ()=>{
|
|
1404
|
-
const encode = (cwd)=>adapter.getProjectDir(cwd);
|
|
1405
|
-
it('should replace path separators with hyphens', ()=>{
|
|
1406
|
-
const expected = path.join(adapter.projectsDir, '-Users-foo-bar');
|
|
1407
|
-
expect(encode('/Users/foo/bar')).toBe(expected);
|
|
1408
|
-
});
|
|
1409
|
-
it('should encode underscores as hyphens (matches Claude Code CLI)', ()=>{
|
|
1410
|
-
const expected = path.join(adapter.projectsDir, '-Users-foo-my-project');
|
|
1411
|
-
expect(encode('/Users/foo/my_project')).toBe(expected);
|
|
1412
|
-
});
|
|
1413
|
-
it('should encode dots as hyphens', ()=>{
|
|
1414
|
-
const expected = path.join(adapter.projectsDir, '-Users-foo--worktrees-x');
|
|
1415
|
-
expect(encode('/Users/foo/.worktrees/x')).toBe(expected);
|
|
1416
|
-
});
|
|
1417
|
-
it('should collide paths that differ only in non-alphanumeric chars', ()=>{
|
|
1418
|
-
// The encoding is intentionally lossy — callers must
|
|
1419
|
-
// disambiguate via session JSONL contents, not dir name.
|
|
1420
|
-
expect(encode('/a/b_c')).toBe(encode('/a/b-c'));
|
|
1421
|
-
expect(encode('/a/b_c')).toBe(encode('/a/b.c'));
|
|
1422
|
-
});
|
|
1423
|
-
it('should resolve to a real session dir when cwd contains underscores', ()=>{
|
|
1424
|
-
const cwd = '/Users/foo/my_project';
|
|
1425
|
-
const projectsDir = adapter.projectsDir;
|
|
1426
|
-
const expectedDir = path.join(projectsDir, '-Users-foo-my-project');
|
|
1427
|
-
fs.mkdirSync(expectedDir, {
|
|
1428
|
-
recursive: true
|
|
1429
|
-
});
|
|
1430
|
-
const sessionFile = path.join(expectedDir, 'session-underscore.jsonl');
|
|
1431
|
-
fs.writeFileSync(sessionFile, '');
|
|
1432
|
-
expect(encode(cwd)).toBe(expectedDir);
|
|
1433
|
-
expect(fs.existsSync(path.join(encode(cwd), 'session-underscore.jsonl'))).toBe(true);
|
|
1434
|
-
});
|
|
1435
|
-
});
|
|
1436
1095
|
describe('readSession', ()=>{
|
|
1437
1096
|
it('should parse session file with timestamps, cwd, and entry type', ()=>{
|
|
1438
1097
|
const readSession = adapter.parser.readSession.bind(adapter.parser);
|