@ai-devkit/agent-manager 0.27.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +12 -4
  2. package/dist/__tests__/adapters/CodexAdapter.test.js +199 -0
  3. package/dist/__tests__/adapters/CodexAdapter.test.js.map +1 -1
  4. package/dist/__tests__/database/DurableAgentsDatabase.test.js +100 -0
  5. package/dist/__tests__/database/DurableAgentsDatabase.test.js.map +1 -0
  6. package/dist/__tests__/print/ClaudePrintAgent.integration.test.js +7 -7
  7. package/dist/__tests__/print/ClaudePrintAgent.integration.test.js.map +1 -1
  8. package/dist/__tests__/print/ClaudePrintAgentService.test.js +7 -7
  9. package/dist/__tests__/print/ClaudePrintAgentService.test.js.map +1 -1
  10. package/dist/__tests__/print/ClaudePrintRunner.test.js +1 -1
  11. package/dist/__tests__/print/ClaudePrintRunner.test.js.map +1 -1
  12. package/dist/__tests__/print/DurableAgent.test.js +17 -0
  13. package/dist/__tests__/print/DurableAgent.test.js.map +1 -0
  14. package/dist/__tests__/print/DurableAgentRepository.sqlite.test.js +186 -0
  15. package/dist/__tests__/print/DurableAgentRepository.sqlite.test.js.map +1 -0
  16. package/dist/__tests__/print/{PrintAgentStore.test.js → DurableAgentRepository.test.js} +63 -110
  17. package/dist/__tests__/print/DurableAgentRepository.test.js.map +1 -0
  18. package/dist/adapters/CodexAdapter.d.ts +1 -0
  19. package/dist/adapters/CodexAdapter.d.ts.map +1 -1
  20. package/dist/adapters/CodexAdapter.js +16 -6
  21. package/dist/adapters/CodexAdapter.js.map +1 -1
  22. package/dist/database/connection.d.ts.map +1 -1
  23. package/dist/database/connection.js +17 -9
  24. package/dist/database/connection.js.map +1 -1
  25. package/dist/database/migrations/003_durable_agents.sql +43 -0
  26. package/dist/durable/ClaudeCliProbe.d.ts.map +1 -0
  27. package/dist/{print → durable}/ClaudeCliProbe.js +1 -1
  28. package/dist/durable/ClaudeCliProbe.js.map +1 -0
  29. package/dist/{print → durable}/ClaudePrintAgentService.d.ts +11 -11
  30. package/dist/durable/ClaudePrintAgentService.d.ts.map +1 -0
  31. package/dist/{print → durable}/ClaudePrintAgentService.js +12 -12
  32. package/dist/durable/ClaudePrintAgentService.js.map +1 -0
  33. package/dist/{print → durable}/ClaudePrintRunner.d.ts +3 -3
  34. package/dist/durable/ClaudePrintRunner.d.ts.map +1 -0
  35. package/dist/{print → durable}/ClaudePrintRunner.js +2 -2
  36. package/dist/durable/ClaudePrintRunner.js.map +1 -0
  37. package/dist/durable/DurableAgent.d.ts +61 -0
  38. package/dist/durable/DurableAgent.d.ts.map +1 -0
  39. package/dist/durable/DurableAgent.js +46 -0
  40. package/dist/durable/DurableAgent.js.map +1 -0
  41. package/dist/durable/DurableAgentRepository.d.ts +60 -0
  42. package/dist/durable/DurableAgentRepository.d.ts.map +1 -0
  43. package/dist/durable/DurableAgentRepository.js +325 -0
  44. package/dist/durable/DurableAgentRepository.js.map +1 -0
  45. package/dist/index.d.ts +11 -11
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +6 -6
  48. package/dist/index.js.map +1 -1
  49. package/package.json +1 -1
  50. package/src/__tests__/adapters/CodexAdapter.test.ts +132 -0
  51. package/src/__tests__/database/DurableAgentsDatabase.test.ts +77 -0
  52. package/src/__tests__/print/ClaudePrintAgent.integration.test.ts +6 -6
  53. package/src/__tests__/print/ClaudePrintAgentService.test.ts +7 -7
  54. package/src/__tests__/print/ClaudePrintRunner.test.ts +3 -3
  55. package/src/__tests__/print/{PrintAgent.test.ts → DurableAgent.test.ts} +6 -6
  56. package/src/__tests__/print/DurableAgentRepository.sqlite.test.ts +105 -0
  57. package/src/__tests__/print/DurableAgentRepository.test.ts +163 -0
  58. package/src/adapters/CodexAdapter.ts +14 -11
  59. package/src/database/connection.ts +15 -9
  60. package/src/database/migrations/003_durable_agents.sql +43 -0
  61. package/src/{print → durable}/ClaudeCliProbe.ts +1 -1
  62. package/src/{print → durable}/ClaudePrintAgentService.ts +21 -21
  63. package/src/{print → durable}/ClaudePrintRunner.ts +4 -4
  64. package/src/durable/DurableAgent.ts +91 -0
  65. package/src/durable/DurableAgentRepository.ts +307 -0
  66. package/src/index.ts +26 -25
  67. package/dist/__tests__/print/PrintAgent.test.js +0 -17
  68. package/dist/__tests__/print/PrintAgent.test.js.map +0 -1
  69. package/dist/__tests__/print/PrintAgentStore.test.js.map +0 -1
  70. package/dist/print/ClaudeCliProbe.d.ts.map +0 -1
  71. package/dist/print/ClaudeCliProbe.js.map +0 -1
  72. package/dist/print/ClaudePrintAgentService.d.ts.map +0 -1
  73. package/dist/print/ClaudePrintAgentService.js.map +0 -1
  74. package/dist/print/ClaudePrintRunner.d.ts.map +0 -1
  75. package/dist/print/ClaudePrintRunner.js.map +0 -1
  76. package/dist/print/PrintAgent.d.ts +0 -57
  77. package/dist/print/PrintAgent.d.ts.map +0 -1
  78. package/dist/print/PrintAgent.js +0 -42
  79. package/dist/print/PrintAgent.js.map +0 -1
  80. package/dist/print/PrintAgentStore.d.ts +0 -69
  81. package/dist/print/PrintAgentStore.d.ts.map +0 -1
  82. package/dist/print/PrintAgentStore.js +0 -484
  83. package/dist/print/PrintAgentStore.js.map +0 -1
  84. package/src/__tests__/print/PrintAgentStore.test.ts +0 -192
  85. package/src/print/PrintAgent.ts +0 -86
  86. package/src/print/PrintAgentStore.ts +0 -503
  87. /package/dist/{print → durable}/ClaudeCliProbe.d.ts +0 -0
@@ -11,36 +11,36 @@ afterEach(()=>{
11
11
  });
12
12
  async function loadStore() {
13
13
  const api = await import('../../index.js');
14
- expect(api).toHaveProperty('PrintAgentStore');
15
- return api.PrintAgentStore;
14
+ expect(api).toHaveProperty('DurableAgentRepository');
15
+ return api.DurableAgentRepository;
16
16
  }
17
17
  function fixture() {
18
- const root = fs.mkdtempSync(path.join(os.tmpdir(), 'print-agent-store-'));
18
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'durable-agent-store-'));
19
19
  tempDirs.push(root);
20
20
  const cwd = path.join(root, 'project');
21
21
  fs.mkdirSync(cwd);
22
22
  return {
23
23
  root,
24
24
  cwd,
25
- filePath: path.join(root, 'state', 'print-agents.json')
25
+ dbPath: path.join(root, 'state', 'agents.db')
26
26
  };
27
27
  }
28
- describe('PrintAgentStore create/list/resolve', ()=>{
28
+ describe('DurableAgentRepository create/list/resolve', ()=>{
29
29
  it('creates distinct durable identities with a canonical cwd and lists them', async ()=>{
30
- const PrintAgentStore = await loadStore();
31
- const { cwd, filePath } = fixture();
32
- const store = new PrintAgentStore({
33
- filePath,
30
+ const DurableAgentRepository = await loadStore();
31
+ const { cwd, dbPath } = fixture();
32
+ const repository = new DurableAgentRepository({
33
+ dbPath,
34
34
  now: ()=>new Date('2026-08-07T09:00:00Z')
35
35
  });
36
- const agent = await store.create({
36
+ const agent = await repository.create({
37
37
  name: 'reviewer',
38
38
  cwd
39
39
  });
40
40
  expect(agent).toMatchObject({
41
41
  name: 'reviewer',
42
42
  provider: 'claude',
43
- mode: 'print',
43
+ mode: 'durable',
44
44
  cwd: fs.realpathSync(cwd),
45
45
  state: 'ready',
46
46
  sessionHealth: 'uninitialized',
@@ -49,96 +49,53 @@ describe('PrintAgentStore create/list/resolve', ()=>{
49
49
  expect(agent.id).toMatch(/^[0-9a-f-]{36}$/);
50
50
  expect(agent.providerSessionId).toMatch(/^[0-9a-f-]{36}$/);
51
51
  expect(agent.id).not.toBe(agent.providerSessionId);
52
- expect(await store.list()).toEqual([
52
+ expect(await repository.list()).toEqual([
53
53
  agent
54
54
  ]);
55
- expect(fs.statSync(filePath).mode & 0o777).toBe(0o600);
55
+ expect(fs.existsSync(dbPath)).toBe(true);
56
56
  });
57
57
  it('resolves exact ids and names and rejects duplicate names', async ()=>{
58
- const PrintAgentStore = await loadStore();
59
- const { cwd, filePath } = fixture();
60
- const store = new PrintAgentStore({
61
- filePath
58
+ const DurableAgentRepository = await loadStore();
59
+ const { cwd, dbPath } = fixture();
60
+ const repository = new DurableAgentRepository({
61
+ dbPath
62
62
  });
63
- const agent = await store.create({
63
+ const agent = await repository.create({
64
64
  name: 'Reviewer',
65
65
  cwd
66
66
  });
67
- expect(await store.resolve(agent.id)).toMatchObject({
67
+ expect(await repository.resolve(agent.id)).toMatchObject({
68
68
  id: agent.id
69
69
  });
70
- expect(await store.resolve('reviewer')).toMatchObject({
70
+ expect(await repository.resolve('reviewer')).toMatchObject({
71
71
  id: agent.id
72
72
  });
73
- expect(await store.resolve('view')).toBeNull();
74
- await expect(store.create({
73
+ expect(await repository.resolve('view')).toBeNull();
74
+ await expect(repository.create({
75
75
  name: 'reviewer',
76
76
  cwd
77
77
  })).rejects.toMatchObject({
78
- code: 'PRINT_AGENT_NAME_CONFLICT'
78
+ code: 'DURABLE_AGENT_NAME_CONFLICT'
79
79
  });
80
80
  });
81
- it('rejects missing cwd, malformed storage, and symlinked store targets', async ()=>{
82
- const PrintAgentStore = await loadStore();
83
- const { root, cwd, filePath } = fixture();
84
- const store = new PrintAgentStore({
85
- filePath
81
+ it('rejects a missing cwd', async ()=>{
82
+ const DurableAgentRepository = await loadStore();
83
+ const { root, dbPath } = fixture();
84
+ const repository = new DurableAgentRepository({
85
+ dbPath
86
86
  });
87
- await expect(store.create({
87
+ await expect(repository.create({
88
88
  name: 'missing',
89
89
  cwd: path.join(root, 'missing')
90
90
  })).rejects.toMatchObject({
91
- code: 'PRINT_AGENT_STORE'
92
- });
93
- fs.mkdirSync(path.dirname(filePath), {
94
- recursive: true
95
- });
96
- fs.writeFileSync(filePath, '{bad json', {
97
- mode: 0o600
98
- });
99
- await expect(store.list()).rejects.toMatchObject({
100
- code: 'PRINT_AGENT_STORE'
101
- });
102
- fs.rmSync(filePath);
103
- const target = path.join(root, 'target.json');
104
- fs.writeFileSync(target, JSON.stringify({
105
- version: 1,
106
- agents: []
107
- }));
108
- fs.symlinkSync(target, filePath);
109
- await expect(store.create({
110
- name: 'unsafe',
111
- cwd
112
- })).rejects.toMatchObject({
113
- code: 'PRINT_AGENT_STORE'
114
- });
115
- });
116
- it('recovers an abandoned old mutation lock after a crash', async ()=>{
117
- const PrintAgentStore = await loadStore();
118
- const { cwd, filePath } = fixture();
119
- fs.mkdirSync(path.dirname(filePath), {
120
- recursive: true
121
- });
122
- const lockPath = `${filePath}.lock`;
123
- fs.mkdirSync(lockPath);
124
- const old = new Date(Date.now() - 60_000);
125
- fs.utimesSync(lockPath, old, old);
126
- const store = new PrintAgentStore({
127
- filePath,
128
- mutationLockStaleMs: 10
129
- });
130
- await expect(store.create({
131
- name: 'recovered',
132
- cwd
133
- })).resolves.toMatchObject({
134
- name: 'recovered'
91
+ code: 'DURABLE_AGENT_REPOSITORY'
135
92
  });
136
93
  });
137
94
  });
138
- describe('PrintAgentStore run ownership', ()=>{
95
+ describe('DurableAgentRepository run ownership', ()=>{
139
96
  it('fails fast when another exact owner is live and completes only for its token', async ()=>{
140
- const PrintAgentStore = await loadStore();
141
- const { cwd, filePath } = fixture();
97
+ const DurableAgentRepository = await loadStore();
98
+ const { cwd, dbPath } = fixture();
142
99
  const live = new Map([
143
100
  [
144
101
  process.pid,
@@ -154,27 +111,27 @@ describe('PrintAgentStore run ownership', ()=>{
154
111
  } : null;
155
112
  }
156
113
  };
157
- const store = new PrintAgentStore({
158
- filePath,
114
+ const repository = new DurableAgentRepository({
115
+ dbPath,
159
116
  processInspector
160
117
  });
161
- const agent = await store.create({
118
+ const agent = await repository.create({
162
119
  name: 'runner',
163
120
  cwd
164
121
  });
165
- const acquired = await store.acquireRun(agent.id);
166
- await expect(store.acquireRun(agent.id)).rejects.toMatchObject({
167
- code: 'PRINT_AGENT_BUSY'
122
+ const acquired = await repository.acquireRun(agent.id);
123
+ await expect(repository.acquireRun(agent.id)).rejects.toMatchObject({
124
+ code: 'DURABLE_AGENT_BUSY'
168
125
  });
169
- await expect(store.completeRun(agent.id, 'wrong-token', {
126
+ await expect(repository.completeRun(agent.id, 'wrong-token', {
170
127
  status: 'succeeded',
171
128
  exitCode: 0,
172
129
  summary: 'done',
173
130
  sessionHealth: 'healthy'
174
131
  })).rejects.toMatchObject({
175
- code: 'PRINT_AGENT_STORE'
132
+ code: 'DURABLE_AGENT_REPOSITORY'
176
133
  });
177
- const completed = await store.completeRun(agent.id, acquired.token, {
134
+ const completed = await repository.completeRun(agent.id, acquired.token, {
178
135
  status: 'succeeded',
179
136
  exitCode: 0,
180
137
  summary: 'done',
@@ -187,8 +144,8 @@ describe('PrintAgentStore run ownership', ()=>{
187
144
  });
188
145
  });
189
146
  it('retains busy for a live provider then recovers a dead run without signaling it', async ()=>{
190
- const PrintAgentStore = await loadStore();
191
- const { cwd, filePath } = fixture();
147
+ const DurableAgentRepository = await loadStore();
148
+ const { cwd, dbPath } = fixture();
192
149
  const live = new Map([
193
150
  [
194
151
  process.pid,
@@ -208,8 +165,8 @@ describe('PrintAgentStore run ownership', ()=>{
208
165
  } : null;
209
166
  }
210
167
  };
211
- const first = new PrintAgentStore({
212
- filePath,
168
+ const first = new DurableAgentRepository({
169
+ dbPath,
213
170
  processInspector
214
171
  });
215
172
  const agent = await first.create({
@@ -223,7 +180,7 @@ describe('PrintAgentStore run ownership', ()=>{
223
180
  });
224
181
  live.delete(process.pid);
225
182
  await expect(first.acquireRun(agent.id)).rejects.toMatchObject({
226
- code: 'PRINT_AGENT_BUSY'
183
+ code: 'DURABLE_AGENT_BUSY'
227
184
  });
228
185
  live.delete(4242);
229
186
  live.set(process.pid, 'replacement-owner-start');
@@ -241,17 +198,17 @@ describe('PrintAgentStore run ownership', ()=>{
241
198
  sessionHealth: 'unknown'
242
199
  });
243
200
  });
244
- it('reconciles an old incomplete lock to degraded during list', async ()=>{
245
- const PrintAgentStore = await loadStore();
246
- const { root, cwd, filePath } = fixture();
201
+ it('reconciles an interrupted run to degraded during list', async ()=>{
202
+ const DurableAgentRepository = await loadStore();
203
+ const { cwd, dbPath } = fixture();
247
204
  const live = new Map([
248
205
  [
249
206
  process.pid,
250
207
  'owner-start'
251
208
  ]
252
209
  ]);
253
- const store = new PrintAgentStore({
254
- filePath,
210
+ const repository = new DurableAgentRepository({
211
+ dbPath,
255
212
  incompleteLockGraceMs: 10,
256
213
  processInspector: {
257
214
  getIdentity: (pid)=>{
@@ -263,17 +220,13 @@ describe('PrintAgentStore run ownership', ()=>{
263
220
  }
264
221
  }
265
222
  });
266
- const agent = await store.create({
223
+ const agent = await repository.create({
267
224
  name: 'crashed',
268
225
  cwd
269
226
  });
270
- await store.acquireRun(agent.id);
271
- const lockPath = path.join(root, 'state', 'print-agent-locks', `${agent.id}.lock`);
272
- fs.unlinkSync(path.join(lockPath, 'owner.json'));
273
- const old = new Date(Date.now() - 1000);
274
- fs.utimesSync(lockPath, old, old);
227
+ await repository.acquireRun(agent.id);
275
228
  live.clear();
276
- const listed = await store.list();
229
+ const listed = await repository.list();
277
230
  expect(listed[0]).toMatchObject({
278
231
  state: 'degraded',
279
232
  sessionHealth: 'unknown',
@@ -284,12 +237,12 @@ describe('PrintAgentStore run ownership', ()=>{
284
237
  });
285
238
  });
286
239
  it('rejects send acquisition when the bound cwd is replaced by a symlink', async ()=>{
287
- const PrintAgentStore = await loadStore();
288
- const { root, cwd, filePath } = fixture();
289
- const store = new PrintAgentStore({
290
- filePath
240
+ const DurableAgentRepository = await loadStore();
241
+ const { root, cwd, dbPath } = fixture();
242
+ const repository = new DurableAgentRepository({
243
+ dbPath
291
244
  });
292
- const agent = await store.create({
245
+ const agent = await repository.create({
293
246
  name: 'bound',
294
247
  cwd
295
248
  });
@@ -298,10 +251,10 @@ describe('PrintAgentStore run ownership', ()=>{
298
251
  fs.renameSync(cwd, moved);
299
252
  fs.mkdirSync(other);
300
253
  fs.symlinkSync(other, cwd);
301
- await expect(store.acquireRun(agent.id)).rejects.toMatchObject({
302
- code: 'PRINT_AGENT_STORE'
254
+ await expect(repository.acquireRun(agent.id)).rejects.toMatchObject({
255
+ code: 'DURABLE_AGENT_REPOSITORY'
303
256
  });
304
257
  });
305
258
  });
306
259
 
307
- //# sourceMappingURL=PrintAgentStore.test.js.map
260
+ //# sourceMappingURL=DurableAgentRepository.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/__tests__/print/DurableAgentRepository.test.ts"],"sourcesContent":["import fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport { afterEach, describe, expect, it } from 'vitest';\n\nconst tempDirs: string[] = [];\n\nafterEach(() => {\n for (const dir of tempDirs.splice(0)) fs.rmSync(dir, { recursive: true, force: true });\n});\n\nasync function loadStore(): Promise<any> {\n const api = await import('../../index.js') as Record<string, unknown>;\n expect(api).toHaveProperty('DurableAgentRepository');\n return api.DurableAgentRepository;\n}\n\nfunction fixture(): { root: string; cwd: string; dbPath: string } {\n const root = fs.mkdtempSync(path.join(os.tmpdir(), 'durable-agent-store-'));\n tempDirs.push(root);\n const cwd = path.join(root, 'project');\n fs.mkdirSync(cwd);\n return { root, cwd, dbPath: path.join(root, 'state', 'agents.db') };\n}\n\ndescribe('DurableAgentRepository create/list/resolve', () => {\n it('creates distinct durable identities with a canonical cwd and lists them', async () => {\n const DurableAgentRepository = await loadStore();\n const { cwd, dbPath } = fixture();\n const repository = new DurableAgentRepository({ dbPath, now: () => new Date('2026-08-07T09:00:00Z') });\n\n const agent = await repository.create({ name: 'reviewer', cwd });\n\n expect(agent).toMatchObject({\n name: 'reviewer',\n provider: 'claude',\n mode: 'durable',\n cwd: fs.realpathSync(cwd),\n state: 'ready',\n sessionHealth: 'uninitialized',\n activeRun: null,\n });\n expect(agent.id).toMatch(/^[0-9a-f-]{36}$/);\n expect(agent.providerSessionId).toMatch(/^[0-9a-f-]{36}$/);\n expect(agent.id).not.toBe(agent.providerSessionId);\n expect(await repository.list()).toEqual([agent]);\n expect(fs.existsSync(dbPath)).toBe(true);\n });\n\n it('resolves exact ids and names and rejects duplicate names', async () => {\n const DurableAgentRepository = await loadStore();\n const { cwd, dbPath } = fixture();\n const repository = new DurableAgentRepository({ dbPath });\n const agent = await repository.create({ name: 'Reviewer', cwd });\n\n expect(await repository.resolve(agent.id)).toMatchObject({ id: agent.id });\n expect(await repository.resolve('reviewer')).toMatchObject({ id: agent.id });\n expect(await repository.resolve('view')).toBeNull();\n await expect(repository.create({ name: 'reviewer', cwd })).rejects.toMatchObject({\n code: 'DURABLE_AGENT_NAME_CONFLICT',\n });\n });\n\n it('rejects a missing cwd', async () => {\n const DurableAgentRepository = await loadStore();\n const { root, dbPath } = fixture();\n const repository = new DurableAgentRepository({ dbPath });\n\n await expect(repository.create({ name: 'missing', cwd: path.join(root, 'missing') }))\n .rejects.toMatchObject({ code: 'DURABLE_AGENT_REPOSITORY' });\n });\n});\n\ndescribe('DurableAgentRepository run ownership', () => {\n it('fails fast when another exact owner is live and completes only for its token', async () => {\n const DurableAgentRepository = await loadStore();\n const { cwd, dbPath } = fixture();\n const live = new Map<number, string>([[process.pid, 'owner-start']]);\n const processInspector = { getIdentity: (pid: number) => {\n const startedAt = live.get(pid);\n return startedAt ? { pid, startedAt } : null;\n } };\n const repository = new DurableAgentRepository({ dbPath, processInspector });\n const agent = await repository.create({ name: 'runner', cwd });\n\n const acquired = await repository.acquireRun(agent.id);\n await expect(repository.acquireRun(agent.id)).rejects.toMatchObject({ code: 'DURABLE_AGENT_BUSY' });\n await expect(repository.completeRun(agent.id, 'wrong-token', {\n status: 'succeeded', exitCode: 0, summary: 'done', sessionHealth: 'healthy',\n })).rejects.toMatchObject({ code: 'DURABLE_AGENT_REPOSITORY' });\n\n const completed = await repository.completeRun(agent.id, acquired.token, {\n status: 'succeeded', exitCode: 0, summary: 'done', sessionHealth: 'healthy',\n });\n expect(completed).toMatchObject({ state: 'ready', sessionHealth: 'healthy', activeRun: null });\n });\n\n it('retains busy for a live provider then recovers a dead run without signaling it', async () => {\n const DurableAgentRepository = await loadStore();\n const { cwd, dbPath } = fixture();\n const live = new Map<number, string>([[process.pid, 'owner-start'], [4242, 'provider-start']]);\n const processInspector = { getIdentity: (pid: number) => {\n const startedAt = live.get(pid);\n return startedAt ? { pid, startedAt } : null;\n } };\n const first = new DurableAgentRepository({ dbPath, processInspector });\n const agent = await first.create({ name: 'recoverable', cwd });\n const run = await first.acquireRun(agent.id);\n await first.recordProviderProcess(agent.id, run.token, { pid: 4242, startedAt: 'provider-start' });\n\n live.delete(process.pid);\n await expect(first.acquireRun(agent.id)).rejects.toMatchObject({ code: 'DURABLE_AGENT_BUSY' });\n\n live.delete(4242);\n live.set(process.pid, 'replacement-owner-start');\n const recovered = await first.acquireRun(agent.id);\n expect(recovered.agent).toMatchObject({\n state: 'running',\n lastResult: { status: 'interrupted' },\n });\n await first.completeRun(agent.id, recovered.token, {\n status: 'failed', exitCode: 1, summary: 'failed', sessionHealth: 'unknown',\n });\n });\n\n it('reconciles an interrupted run to degraded during list', async () => {\n const DurableAgentRepository = await loadStore();\n const { cwd, dbPath } = fixture();\n const live = new Map<number, string>([[process.pid, 'owner-start']]);\n const repository = new DurableAgentRepository({ dbPath, incompleteLockGraceMs: 10, processInspector: {\n getIdentity: (pid: number) => {\n const startedAt = live.get(pid);\n return startedAt ? { pid, startedAt } : null;\n },\n } });\n const agent = await repository.create({ name: 'crashed', cwd });\n await repository.acquireRun(agent.id);\n live.clear();\n\n const listed = await repository.list();\n\n expect(listed[0]).toMatchObject({\n state: 'degraded',\n sessionHealth: 'unknown',\n activeRun: null,\n lastResult: { status: 'interrupted' },\n });\n });\n\n it('rejects send acquisition when the bound cwd is replaced by a symlink', async () => {\n const DurableAgentRepository = await loadStore();\n const { root, cwd, dbPath } = fixture();\n const repository = new DurableAgentRepository({ dbPath });\n const agent = await repository.create({ name: 'bound', cwd });\n const moved = path.join(root, 'moved-project');\n const other = path.join(root, 'other-project');\n fs.renameSync(cwd, moved);\n fs.mkdirSync(other);\n fs.symlinkSync(other, cwd);\n\n await expect(repository.acquireRun(agent.id)).rejects.toMatchObject({ code: 'DURABLE_AGENT_REPOSITORY' });\n });\n});\n"],"names":["fs","os","path","afterEach","describe","expect","it","tempDirs","dir","splice","rmSync","recursive","force","loadStore","api","toHaveProperty","DurableAgentRepository","fixture","root","mkdtempSync","join","tmpdir","push","cwd","mkdirSync","dbPath","repository","now","Date","agent","create","name","toMatchObject","provider","mode","realpathSync","state","sessionHealth","activeRun","id","toMatch","providerSessionId","not","toBe","list","toEqual","existsSync","resolve","toBeNull","rejects","code","live","Map","process","pid","processInspector","getIdentity","startedAt","get","acquired","acquireRun","completeRun","status","exitCode","summary","completed","token","first","run","recordProviderProcess","delete","set","recovered","lastResult","incompleteLockGraceMs","clear","listed","moved","other","renameSync","symlinkSync"],"mappings":"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"}
@@ -104,5 +104,6 @@ export declare class CodexAdapter implements AgentAdapter {
104
104
  * lacks a session id.
105
105
  */
106
106
  private fileToSessionSummary;
107
+ private isSyntheticUserMessage;
107
108
  }
108
109
  //# sourceMappingURL=CodexAdapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CodexAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/CodexAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EACR,YAAY,EACZ,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACxB,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AA4D1D,qBAAa,YAAa,YAAW,YAAY;IAC7C,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IACjC,QAAQ,CAAC,YAAY,qBAAsB;IAE3C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAK;IACnD,sFAAsF;IACtF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,6BAA6B,CAAK;IAE1D,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAgB;gBAEpB,QAAQ,GAAE,aAAuC;IAO7D,SAAS,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO;IAI5C;;OAEG;IACG,YAAY,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAqDzE,OAAO,CAAC,wBAAwB;IAgBhC,OAAO,CAAC,uBAAuB;IAuB/B,OAAO,CAAC,kBAAkB;IAwB1B,OAAO,CAAC,KAAK;IAQb,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,gBAAgB;IAiCxB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IA0BzB,OAAO,CAAC,sBAAsB;IAK9B,OAAO,CAAC,mBAAmB;IAiC3B,OAAO,CAAC,wBAAwB;IAWhC,OAAO,CAAC,gBAAgB;IAgBxB;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;IAsCxB;;;OAGG;IACH,OAAO,CAAC,WAAW;IA4BnB,OAAO,CAAC,qBAAqB;IAe7B,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,kBAAkB;IAW1B;;;OAGG;IACH,OAAO,CAAC,YAAY;IAwDpB,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,qBAAqB;IAmB7B,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,iBAAiB;IAKzB;;;;;OAKG;IACH,eAAe,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,mBAAmB,EAAE;IA8ChG,OAAO,CAAC,qBAAqB;IAwC7B,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,kBAAkB;IAYpB,YAAY,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAgBzE;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IA0B9B,OAAO,CAAC,6BAA6B;IAarC;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;CA8D/B"}
1
+ {"version":3,"file":"CodexAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/CodexAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EACR,YAAY,EACZ,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACxB,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AA4D1D,qBAAa,YAAa,YAAW,YAAY;IAC7C,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IACjC,QAAQ,CAAC,YAAY,qBAAsB;IAE3C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAK;IACnD,sFAAsF;IACtF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,6BAA6B,CAAK;IAE1D,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAgB;gBAEpB,QAAQ,GAAE,aAAuC;IAO7D,SAAS,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO;IAI5C;;OAEG;IACG,YAAY,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAqDzE,OAAO,CAAC,wBAAwB;IAgBhC,OAAO,CAAC,uBAAuB;IAuB/B,OAAO,CAAC,kBAAkB;IAwB1B,OAAO,CAAC,KAAK;IAQb,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,gBAAgB;IAiCxB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IA0BzB,OAAO,CAAC,sBAAsB;IAK9B,OAAO,CAAC,mBAAmB;IAiC3B,OAAO,CAAC,wBAAwB;IAWhC,OAAO,CAAC,gBAAgB;IAgBxB;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;IAsCxB;;;OAGG;IACH,OAAO,CAAC,WAAW;IA4BnB,OAAO,CAAC,qBAAqB;IAe7B,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,kBAAkB;IAW1B;;;OAGG;IACH,OAAO,CAAC,YAAY;IAwDpB,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,qBAAqB;IAmB7B,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,iBAAiB;IAKzB;;;;;OAKG;IACH,eAAe,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,mBAAmB,EAAE;IA8ChG,OAAO,CAAC,qBAAqB;IAwC7B,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,kBAAkB;IAYpB,YAAY,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAgBzE;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IA0B9B,OAAO,CAAC,6BAA6B;IAarC;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IA8D5B,OAAO,CAAC,sBAAsB;CAGjC"}
@@ -42,10 +42,13 @@ export class CodexAdapter {
42
42
  const relevant = filterByProcessNames(snapshot, this.processNames);
43
43
  const processes = relevant.filter((process1)=>this.canHandle(process1));
44
44
  if (processes.length === 0) return [];
45
- const { cachedAgents, remaining } = this.tryRegistryCache(processes);
46
- if (remaining.length === 0) return cachedAgents;
47
- const mappingResult = this.mapSessionMappingMatches(remaining);
48
- const { direct, fallback } = this.tryResumeMatching(mappingResult.fallback);
45
+ const mappingResult = this.mapSessionMappingMatches(processes);
46
+ const { cachedAgents, remaining } = this.tryRegistryCache(mappingResult.fallback);
47
+ if (remaining.length === 0) return [
48
+ ...mappingResult.agents,
49
+ ...cachedAgents
50
+ ];
51
+ const { direct, fallback } = this.tryResumeMatching(remaining);
49
52
  const directResult = this.mapDirectMatches(direct);
50
53
  const { sessions, contentCache } = this.discoverSessions(fallback);
51
54
  if (sessions.length === 0) {
@@ -678,8 +681,12 @@ export class CodexAdapter {
678
681
  }
679
682
  const ts = this.parseTimestamp(entry.timestamp);
680
683
  if (ts) lastTimestamp = ts;
681
- if (!firstUserMessage && entry.payload?.type === 'user_message' && typeof entry.payload.message === 'string' && entry.payload.message.trim().length > 0) {
682
- firstUserMessage = entry.payload.message.trim();
684
+ if (!firstUserMessage) {
685
+ const message = this.toConversationMessage(entry, false);
686
+ const content = message?.content.trim() ?? '';
687
+ if (message?.role === 'user' && content.length > 0 && !this.isSyntheticUserMessage(content)) {
688
+ firstUserMessage = content;
689
+ }
683
690
  }
684
691
  }
685
692
  const stat = safeStat(filePath);
@@ -695,6 +702,9 @@ export class CodexAdapter {
695
702
  sessionFilePath: filePath
696
703
  };
697
704
  }
705
+ isSyntheticUserMessage(content) {
706
+ return content.startsWith('<environment_context>') && content.includes('</environment_context>');
707
+ }
698
708
  }
699
709
 
700
710
  //# sourceMappingURL=CodexAdapter.js.map