@agtd/agent 0.1.1 → 0.1.2

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 (109) hide show
  1. package/dist/__tests__/codexAdapterFindFile.test.d.ts +2 -0
  2. package/dist/__tests__/codexAdapterFindFile.test.d.ts.map +1 -0
  3. package/dist/__tests__/codexAdapterFindFile.test.js +298 -0
  4. package/dist/__tests__/codexAdapterFindFile.test.js.map +1 -0
  5. package/dist/__tests__/enrichers.test.d.ts +2 -0
  6. package/dist/__tests__/enrichers.test.d.ts.map +1 -0
  7. package/dist/__tests__/enrichers.test.js +47 -0
  8. package/dist/__tests__/enrichers.test.js.map +1 -0
  9. package/dist/__tests__/tmux.integration.test.d.ts +2 -0
  10. package/dist/__tests__/tmux.integration.test.d.ts.map +1 -0
  11. package/dist/__tests__/tmux.integration.test.js +112 -0
  12. package/dist/__tests__/tmux.integration.test.js.map +1 -0
  13. package/dist/__tests__/tmux.test.d.ts +2 -0
  14. package/dist/__tests__/tmux.test.d.ts.map +1 -0
  15. package/dist/__tests__/tmux.test.js +26 -0
  16. package/dist/__tests__/tmux.test.js.map +1 -0
  17. package/dist/__tests__/transcriptAdapters.test.d.ts +2 -0
  18. package/dist/__tests__/transcriptAdapters.test.d.ts.map +1 -0
  19. package/dist/__tests__/transcriptAdapters.test.js +133 -0
  20. package/dist/__tests__/transcriptAdapters.test.js.map +1 -0
  21. package/dist/adapters/claude-code.d.ts +3 -0
  22. package/dist/adapters/claude-code.d.ts.map +1 -0
  23. package/dist/adapters/claude-code.js +48 -0
  24. package/dist/adapters/claude-code.js.map +1 -0
  25. package/dist/adapters/codex.d.ts +3 -0
  26. package/dist/adapters/codex.d.ts.map +1 -0
  27. package/dist/adapters/codex.js +33 -0
  28. package/dist/adapters/codex.js.map +1 -0
  29. package/dist/adapters/generic.d.ts +3 -0
  30. package/dist/adapters/generic.d.ts.map +1 -0
  31. package/dist/adapters/generic.js +38 -0
  32. package/dist/adapters/generic.js.map +1 -0
  33. package/dist/adapters/index.d.ts +7 -0
  34. package/dist/adapters/index.d.ts.map +1 -0
  35. package/dist/adapters/index.js +12 -0
  36. package/dist/adapters/index.js.map +1 -0
  37. package/dist/agent.d.ts +3 -0
  38. package/dist/agent.d.ts.map +1 -0
  39. package/dist/agent.js +49 -6
  40. package/dist/agent.js.map +1 -0
  41. package/dist/cli.d.ts +11 -0
  42. package/dist/cli.d.ts.map +1 -0
  43. package/dist/cli.js +120 -186
  44. package/dist/cli.js.map +1 -0
  45. package/dist/config.d.ts +26 -0
  46. package/dist/config.d.ts.map +1 -0
  47. package/dist/config.js +48 -0
  48. package/dist/config.js.map +1 -0
  49. package/dist/enrichers/git.d.ts +6 -0
  50. package/dist/enrichers/git.d.ts.map +1 -0
  51. package/dist/enrichers/git.js +20 -0
  52. package/dist/enrichers/git.js.map +1 -0
  53. package/dist/enrichers/pr.d.ts +2 -0
  54. package/dist/enrichers/pr.d.ts.map +1 -0
  55. package/dist/enrichers/pr.js +10 -0
  56. package/dist/enrichers/pr.js.map +1 -0
  57. package/dist/enrichers/transcript.d.ts +8 -0
  58. package/dist/enrichers/transcript.d.ts.map +1 -0
  59. package/dist/enrichers/transcript.js +33 -0
  60. package/dist/enrichers/transcript.js.map +1 -0
  61. package/dist/heartbeat.d.ts +4 -0
  62. package/dist/heartbeat.d.ts.map +1 -0
  63. package/dist/heartbeat.js +15 -0
  64. package/dist/heartbeat.js.map +1 -0
  65. package/dist/init.d.ts +10 -0
  66. package/dist/init.d.ts.map +1 -0
  67. package/dist/init.js +70 -0
  68. package/dist/init.js.map +1 -0
  69. package/dist/register.d.ts +3 -0
  70. package/dist/register.d.ts.map +1 -0
  71. package/dist/register.js +22 -0
  72. package/dist/register.js.map +1 -0
  73. package/dist/sessionScanner.d.ts +20 -0
  74. package/dist/sessionScanner.d.ts.map +1 -0
  75. package/dist/sessionScanner.js +479 -0
  76. package/dist/sessionScanner.js.map +1 -0
  77. package/dist/spawn.d.ts +8 -0
  78. package/dist/spawn.d.ts.map +1 -0
  79. package/dist/spawn.js +73 -0
  80. package/dist/spawn.js.map +1 -0
  81. package/dist/syncProjects.d.ts +3 -0
  82. package/dist/syncProjects.d.ts.map +1 -0
  83. package/dist/syncProjects.js +91 -0
  84. package/dist/syncProjects.js.map +1 -0
  85. package/dist/terminalBridge.d.ts +4 -0
  86. package/dist/terminalBridge.d.ts.map +1 -0
  87. package/dist/terminalBridge.js +42 -0
  88. package/dist/terminalBridge.js.map +1 -0
  89. package/dist/tmux.d.ts +21 -0
  90. package/dist/tmux.d.ts.map +1 -0
  91. package/dist/tmux.js +89 -0
  92. package/dist/tmux.js.map +1 -0
  93. package/dist/transcriptAdapters/claude-code.d.ts +3 -0
  94. package/dist/transcriptAdapters/claude-code.d.ts.map +1 -0
  95. package/dist/transcriptAdapters/claude-code.js +147 -0
  96. package/dist/transcriptAdapters/claude-code.js.map +1 -0
  97. package/dist/transcriptAdapters/codex.d.ts +3 -0
  98. package/dist/transcriptAdapters/codex.d.ts.map +1 -0
  99. package/dist/transcriptAdapters/codex.js +251 -0
  100. package/dist/transcriptAdapters/codex.js.map +1 -0
  101. package/dist/transcriptAdapters/index.d.ts +17 -0
  102. package/dist/transcriptAdapters/index.d.ts.map +1 -0
  103. package/dist/transcriptAdapters/index.js +9 -0
  104. package/dist/transcriptAdapters/index.js.map +1 -0
  105. package/dist/wsClient.d.ts +6 -0
  106. package/dist/wsClient.d.ts.map +1 -0
  107. package/dist/wsClient.js +156 -0
  108. package/dist/wsClient.js.map +1 -0
  109. package/package.json +6 -2
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=codexAdapterFindFile.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codexAdapterFindFile.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/codexAdapterFindFile.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Integration tests for codexAdapter.findFile() — the three-tier lookup:
3
+ *
4
+ * Tier 1: stored codexThreadId → exact match, unique per session
5
+ * Tier 2: tmux session creation time → used when codexThreadId absent
6
+ * Tier 3: latest thread by cwd → last resort, may collide if cwd shared
7
+ *
8
+ * node:child_process is mocked so these tests run without sqlite3 CLI or tmux.
9
+ */
10
+ import { describe, it, expect, beforeAll, afterAll, beforeEach, vi } from "vitest";
11
+ import { writeFileSync, mkdirSync, rmSync } from "node:fs";
12
+ import { join } from "node:path";
13
+ import { tmpdir } from "node:os";
14
+ vi.mock("node:child_process", () => ({
15
+ execSync: vi.fn(),
16
+ }));
17
+ // Import AFTER vi.mock so the adapter picks up the mocked execSync
18
+ import { codexAdapter } from "../transcriptAdapters/codex.js";
19
+ import { execSync } from "node:child_process";
20
+ const mockExecSync = vi.mocked(execSync);
21
+ // ---------------------------------------------------------------------------
22
+ // Fixture setup
23
+ // ---------------------------------------------------------------------------
24
+ const THREAD_ID_1 = "01234567-0000-7000-0000-000000000001";
25
+ const THREAD_ID_2 = "01234567-0000-7000-0000-000000000002";
26
+ const SHARED_CWD = "/projects/shared-project";
27
+ const TMUX_SESSION_1 = "aidash-sess_aaa11111";
28
+ const TMUX_SESSION_2 = "aidash-sess_bbb22222";
29
+ const TMUX_CREATED_1 = "1700000000"; // earlier session
30
+ const TMUX_CREATED_2 = "1700000300"; // later session (5 min later)
31
+ let tmpDir;
32
+ let jsonlPath1; // rollout file for thread 1
33
+ let jsonlPath2; // rollout file for thread 2
34
+ beforeAll(() => {
35
+ tmpDir = join(tmpdir(), "agtd-codex-findfile-" + Date.now());
36
+ mkdirSync(join(tmpDir, ".codex"), { recursive: true });
37
+ // A zero-byte file is enough — existsSync(dbPath) just needs to pass
38
+ writeFileSync(join(tmpDir, ".codex", "state_5.sqlite"), "");
39
+ // Create real JSONL files so existsSync(rolloutPath) passes
40
+ jsonlPath1 = join(tmpDir, "rollout-thread1.jsonl");
41
+ jsonlPath2 = join(tmpDir, "rollout-thread2.jsonl");
42
+ writeFileSync(jsonlPath1, JSON.stringify({
43
+ type: "response_item",
44
+ timestamp: "2026-01-01T00:00:00Z",
45
+ payload: {
46
+ type: "message",
47
+ role: "user",
48
+ content: [{ type: "text", text: "session 1 message" }],
49
+ },
50
+ }) + "\n");
51
+ writeFileSync(jsonlPath2, JSON.stringify({
52
+ type: "response_item",
53
+ timestamp: "2026-01-02T00:00:00Z",
54
+ payload: {
55
+ type: "message",
56
+ role: "user",
57
+ content: [{ type: "text", text: "session 2 message" }],
58
+ },
59
+ }) + "\n");
60
+ });
61
+ afterAll(() => {
62
+ rmSync(tmpDir, { recursive: true, force: true });
63
+ });
64
+ beforeEach(() => {
65
+ mockExecSync.mockReset();
66
+ });
67
+ // ---------------------------------------------------------------------------
68
+ // Tier 1 tests — codexThreadId direct lookup
69
+ // ---------------------------------------------------------------------------
70
+ describe("Tier 1: codexThreadId lookup", () => {
71
+ it("returns the rollout file matching the stored codexThreadId", () => {
72
+ mockExecSync.mockReturnValueOnce((jsonlPath1 + "\n"));
73
+ const session = {
74
+ id: "sess_1",
75
+ cwd: SHARED_CWD,
76
+ agentType: "codex",
77
+ codexThreadId: THREAD_ID_1,
78
+ tmuxSession: TMUX_SESSION_1,
79
+ };
80
+ const result = codexAdapter.findFile(session, tmpDir);
81
+ expect(result).toBe(jsonlPath1);
82
+ // Must query by thread ID, not by cwd
83
+ expect(mockExecSync).toHaveBeenCalledWith(expect.stringContaining(THREAD_ID_1), expect.any(Object));
84
+ });
85
+ it("two sessions with the SAME cwd get DIFFERENT transcripts via codexThreadId", () => {
86
+ // Session 1 lookup
87
+ mockExecSync.mockReturnValueOnce((jsonlPath1 + "\n"));
88
+ const session1 = {
89
+ id: "sess_1",
90
+ cwd: SHARED_CWD,
91
+ codexThreadId: THREAD_ID_1,
92
+ };
93
+ const file1 = codexAdapter.findFile(session1, tmpDir);
94
+ mockExecSync.mockReset();
95
+ // Session 2 lookup
96
+ mockExecSync.mockReturnValueOnce((jsonlPath2 + "\n"));
97
+ const session2 = {
98
+ id: "sess_2",
99
+ cwd: SHARED_CWD,
100
+ codexThreadId: THREAD_ID_2,
101
+ };
102
+ const file2 = codexAdapter.findFile(session2, tmpDir);
103
+ expect(file1).toBe(jsonlPath1);
104
+ expect(file2).toBe(jsonlPath2);
105
+ // KEY regression assertion: same cwd must not produce same transcript
106
+ expect(file1).not.toBe(file2);
107
+ });
108
+ it("falls through to Tier 2 when Tier 1 returns a non-existent path", () => {
109
+ // Tier 1: returns a path that does not exist on disk
110
+ mockExecSync
111
+ .mockReturnValueOnce(("/nonexistent/rollout.jsonl\n")) // Tier 1 sqlite3
112
+ .mockReturnValueOnce((TMUX_CREATED_1 + "\n")) // Tier 2: tmux display-message
113
+ .mockReturnValueOnce((jsonlPath1 + "\n")); // Tier 2: sqlite3 by timestamp
114
+ const session = {
115
+ id: "sess_1",
116
+ cwd: SHARED_CWD,
117
+ codexThreadId: THREAD_ID_1,
118
+ tmuxSession: TMUX_SESSION_1,
119
+ };
120
+ const result = codexAdapter.findFile(session, tmpDir);
121
+ expect(result).toBe(jsonlPath1);
122
+ });
123
+ it("falls through to Tier 3 when codexThreadId returns empty string", () => {
124
+ // Tier 1: sqlite3 returns empty (thread not found)
125
+ // Tier 2: no tmuxSession → skipped
126
+ // Tier 3: returns latest by cwd
127
+ mockExecSync
128
+ .mockReturnValueOnce(("")) // Tier 1: empty
129
+ .mockReturnValueOnce((jsonlPath2 + "\n")); // Tier 3: latest by cwd
130
+ const session = {
131
+ id: "sess_x",
132
+ cwd: SHARED_CWD,
133
+ codexThreadId: THREAD_ID_1,
134
+ tmuxSession: null, // no tmux → skip Tier 2
135
+ };
136
+ const result = codexAdapter.findFile(session, tmpDir);
137
+ expect(result).toBe(jsonlPath2);
138
+ expect(mockExecSync).toHaveBeenCalledWith(expect.stringContaining("ORDER BY updated_at DESC"), expect.any(Object));
139
+ });
140
+ });
141
+ // ---------------------------------------------------------------------------
142
+ // Tier 2 tests — tmux session creation time
143
+ // ---------------------------------------------------------------------------
144
+ describe("Tier 2: tmux session creation time lookup", () => {
145
+ it("uses tmux creation time when codexThreadId is null", () => {
146
+ mockExecSync
147
+ .mockReturnValueOnce((TMUX_CREATED_1 + "\n")) // tmux display-message
148
+ .mockReturnValueOnce((jsonlPath1 + "\n")); // sqlite3 WHERE created_at >=
149
+ const session = {
150
+ id: "sess_3",
151
+ cwd: SHARED_CWD,
152
+ codexThreadId: null,
153
+ tmuxSession: TMUX_SESSION_1,
154
+ };
155
+ const result = codexAdapter.findFile(session, tmpDir);
156
+ expect(result).toBe(jsonlPath1);
157
+ expect(mockExecSync).toHaveBeenCalledWith(expect.stringContaining(`tmux display-message -t '${TMUX_SESSION_1}'`), expect.any(Object));
158
+ expect(mockExecSync).toHaveBeenCalledWith(expect.stringContaining(`created_at >= ${TMUX_CREATED_1}`), expect.any(Object));
159
+ });
160
+ it("two sessions sharing cwd get correct files via different tmux creation times", () => {
161
+ // Session 1: earlier tmux time → finds thread 1
162
+ mockExecSync
163
+ .mockReturnValueOnce((TMUX_CREATED_1 + "\n"))
164
+ .mockReturnValueOnce((jsonlPath1 + "\n"));
165
+ const session1 = {
166
+ id: "sess_3",
167
+ cwd: SHARED_CWD,
168
+ codexThreadId: null,
169
+ tmuxSession: TMUX_SESSION_1,
170
+ };
171
+ const file1 = codexAdapter.findFile(session1, tmpDir);
172
+ expect(file1).toBe(jsonlPath1);
173
+ mockExecSync.mockReset();
174
+ // Session 2: later tmux time → finds thread 2
175
+ mockExecSync
176
+ .mockReturnValueOnce((TMUX_CREATED_2 + "\n"))
177
+ .mockReturnValueOnce((jsonlPath2 + "\n"));
178
+ const session2 = {
179
+ id: "sess_4",
180
+ cwd: SHARED_CWD,
181
+ codexThreadId: null,
182
+ tmuxSession: TMUX_SESSION_2,
183
+ };
184
+ const file2 = codexAdapter.findFile(session2, tmpDir);
185
+ expect(file2).toBe(jsonlPath2);
186
+ expect(file1).not.toBe(file2);
187
+ });
188
+ it("falls through to Tier 3 when tmux command fails", () => {
189
+ mockExecSync
190
+ .mockImplementationOnce(() => {
191
+ throw new Error("no server running on /tmp/tmux/default");
192
+ })
193
+ .mockReturnValueOnce((jsonlPath2 + "\n")); // Tier 3 fallback
194
+ const session = {
195
+ id: "sess_5",
196
+ cwd: SHARED_CWD,
197
+ codexThreadId: null,
198
+ tmuxSession: TMUX_SESSION_1,
199
+ };
200
+ const result = codexAdapter.findFile(session, tmpDir);
201
+ expect(result).toBe(jsonlPath2);
202
+ expect(mockExecSync).toHaveBeenCalledWith(expect.stringContaining("ORDER BY updated_at DESC"), expect.any(Object));
203
+ });
204
+ it("falls through to Tier 3 when tmux returns non-numeric output", () => {
205
+ mockExecSync
206
+ .mockReturnValueOnce(("not-a-number\n")) // tmux returns garbage
207
+ .mockReturnValueOnce((jsonlPath2 + "\n")); // Tier 3
208
+ const session = {
209
+ id: "sess_6",
210
+ cwd: SHARED_CWD,
211
+ codexThreadId: null,
212
+ tmuxSession: TMUX_SESSION_1,
213
+ };
214
+ const result = codexAdapter.findFile(session, tmpDir);
215
+ expect(result).toBe(jsonlPath2);
216
+ });
217
+ });
218
+ // ---------------------------------------------------------------------------
219
+ // Tier 3 tests — latest thread by cwd (last resort)
220
+ // ---------------------------------------------------------------------------
221
+ describe("Tier 3: latest thread by cwd (last resort)", () => {
222
+ it("returns latest updated thread when no codexThreadId and no tmuxSession", () => {
223
+ mockExecSync.mockReturnValueOnce((jsonlPath2 + "\n"));
224
+ const session = {
225
+ id: "sess_7",
226
+ cwd: SHARED_CWD,
227
+ codexThreadId: null,
228
+ tmuxSession: null,
229
+ };
230
+ const result = codexAdapter.findFile(session, tmpDir);
231
+ expect(result).toBe(jsonlPath2);
232
+ expect(mockExecSync).toHaveBeenCalledWith(expect.stringContaining("ORDER BY updated_at DESC LIMIT 1"), expect.any(Object));
233
+ });
234
+ it("WARNING: returns same file for two sessions with same cwd (Tier 3 limitation)", () => {
235
+ // This test documents the known limitation of Tier 3 — it cannot disambiguate
236
+ // sessions sharing the same cwd without codexThreadId or tmuxSession.
237
+ // Tier 1 and Tier 2 exist to avoid hitting this case.
238
+ const session1 = { id: "sess_8", cwd: SHARED_CWD, codexThreadId: null, tmuxSession: null };
239
+ const session2 = { id: "sess_9", cwd: SHARED_CWD, codexThreadId: null, tmuxSession: null };
240
+ mockExecSync.mockReturnValueOnce((jsonlPath2 + "\n"));
241
+ const file1 = codexAdapter.findFile(session1, tmpDir);
242
+ mockExecSync.mockReset();
243
+ mockExecSync.mockReturnValueOnce((jsonlPath2 + "\n"));
244
+ const file2 = codexAdapter.findFile(session2, tmpDir);
245
+ // Both get the same (latest) file — this is the documented limitation
246
+ expect(file1).toBe(jsonlPath2);
247
+ expect(file2).toBe(jsonlPath2);
248
+ expect(file1).toBe(file2); // expected collision — document this behavior
249
+ });
250
+ it("returns null when cwd is empty", () => {
251
+ // No SQLite DB fallback and no sessions dir
252
+ const session = {
253
+ id: "sess_10",
254
+ cwd: "",
255
+ codexThreadId: null,
256
+ tmuxSession: null,
257
+ };
258
+ const result = codexAdapter.findFile(session, join(tmpDir, "no-sessions-dir"));
259
+ expect(result).toBeNull();
260
+ });
261
+ });
262
+ // ---------------------------------------------------------------------------
263
+ // SQL injection / quoting edge cases
264
+ // ---------------------------------------------------------------------------
265
+ describe("shell quoting — paths with special characters", () => {
266
+ it("handles cwd containing single quotes in SQLite query", () => {
267
+ // This is the exact bug that broke Tier 2 before the fix:
268
+ // using single-quote outer wrapping with a cwd like /Users/foo/it's-project
269
+ // broke because the shell interpreter saw the inner ' as ending the argument.
270
+ mockExecSync.mockReturnValueOnce((jsonlPath1 + "\n"));
271
+ const session = {
272
+ id: "sess_sq",
273
+ cwd: "/projects/it's-project",
274
+ codexThreadId: THREAD_ID_1,
275
+ tmuxSession: null,
276
+ };
277
+ // Should not throw; the quoting logic must handle single quotes in paths
278
+ expect(() => codexAdapter.findFile(session, tmpDir)).not.toThrow();
279
+ });
280
+ it("Tier 3 CWD query uses double-quote outer wrapping (regression: near '/' syntax error)", () => {
281
+ // The original bug: sqlite3 'db' 'WHERE cwd='/Users/...' was broken because
282
+ // the shell split on / in the path. Fixed by using "double-quote wrapping".
283
+ // Verify the query string passed to execSync uses the correct quoting.
284
+ mockExecSync.mockReturnValueOnce((jsonlPath1 + "\n"));
285
+ const session = {
286
+ id: "sess_dq",
287
+ cwd: "/Users/robyparapat/workspace/repo/payment-connectors-service",
288
+ codexThreadId: null,
289
+ tmuxSession: null,
290
+ };
291
+ codexAdapter.findFile(session, tmpDir);
292
+ // The execSync call must use double quotes as outer wrapper for the SQL argument
293
+ // so the cwd single quotes are treated as literal characters, not shell delimiters
294
+ const call = mockExecSync.mock.calls[0][0];
295
+ expect(call).toMatch(/sqlite3 '.*' "SELECT rollout_path/);
296
+ });
297
+ });
298
+ //# sourceMappingURL=codexAdapterFindFile.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codexAdapterFindFile.test.js","sourceRoot":"","sources":["../../src/__tests__/codexAdapterFindFile.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=enrichers.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrichers.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/enrichers.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,47 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { derivePrUrl } from "../enrichers/pr.js";
3
+ import { parseTranscript } from "../enrichers/transcript.js";
4
+ describe("PR URL enricher", () => {
5
+ it("derives GitHub PR search URL from HTTPS remote", () => {
6
+ const url = derivePrUrl("https://github.com/user/repo.git", "feat/my-branch");
7
+ expect(url).toContain("github.com/user/repo/pulls");
8
+ expect(url).toContain("head:feat%2Fmy-branch");
9
+ });
10
+ it("handles SSH remote URLs", () => {
11
+ const url = derivePrUrl("git@github.com:user/repo.git", "fix/bug");
12
+ expect(url).toContain("github.com/user/repo/pulls");
13
+ expect(url).toContain("fix%2Fbug");
14
+ });
15
+ it("returns null for non-GitHub remotes", () => {
16
+ expect(derivePrUrl("https://gitlab.com/user/repo.git", "main")).toBeNull();
17
+ });
18
+ it("returns null for empty inputs", () => {
19
+ expect(derivePrUrl("", "main")).toBeNull();
20
+ expect(derivePrUrl("https://github.com/u/r", "")).toBeNull();
21
+ });
22
+ });
23
+ describe("Transcript parser", () => {
24
+ it("extracts model name", () => {
25
+ const result = parseTranscript("Using model: claude-sonnet-4-5");
26
+ expect(result.model).toBe("claude-sonnet-4-5");
27
+ });
28
+ it("extracts context percentage", () => {
29
+ const result = parseTranscript("context: 61%");
30
+ expect(result.contextPercent).toBe(61);
31
+ });
32
+ it("extracts MCP servers", () => {
33
+ const result = parseTranscript("mcp: [github, filesystem]");
34
+ expect(result.mcpServers).toEqual(["github", "filesystem"]);
35
+ });
36
+ it("returns nulls for empty input", () => {
37
+ const result = parseTranscript("");
38
+ expect(result.model).toBeNull();
39
+ expect(result.contextPercent).toBeNull();
40
+ expect(result.mcpServers).toBeNull();
41
+ });
42
+ it("handles GPT model names", () => {
43
+ const result = parseTranscript("model: gpt-4o-mini");
44
+ expect(result.model).toBe("gpt-4o-mini");
45
+ });
46
+ });
47
+ //# sourceMappingURL=enrichers.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrichers.test.js","sourceRoot":"","sources":["../../src/__tests__/enrichers.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tmux.integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmux.integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/tmux.integration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Integration tests for tmux key-sending approaches.
3
+ *
4
+ * Key findings from empirical testing:
5
+ * - Both hex mode (buildSendKeysCmd) and plain send-keys (buildSendMessageCmd) deliver
6
+ * the SAME bytes to the running program. For 'hello world' + Enter, both deliver
7
+ * the string as a single data event with bytes [68 65 6c 6c 6f 20 77 6f 72 6c 64 0d].
8
+ * - readline.emitKeypressEvents (used by Ink/Codex internally) correctly parses a
9
+ * batched data event into individual keypress events: h, e, l, l, o, ..., return.
10
+ * - However, Ink TUIs may be mid-render when input arrives; sending chars one at a
11
+ * time (with 20ms delays) is more reliable for interactive TUIs.
12
+ *
13
+ * Skipped automatically if tmux is not available.
14
+ */
15
+ import { describe, it, expect, afterEach } from "vitest";
16
+ import { execSync } from "node:child_process";
17
+ import * as fs from "node:fs";
18
+ import * as os from "node:os";
19
+ import * as path from "node:path";
20
+ import { isTmuxAvailable, tmuxExec, buildSendKeysCmd, buildSendMessageCmd, buildCapturePaneCmd, sanitizeShellArg, } from "../tmux.js";
21
+ const AVAILABLE = isTmuxAvailable();
22
+ const PREFIX = `agtd-itest-${Date.now()}`;
23
+ function killSession(name) {
24
+ try {
25
+ execSync(`tmux kill-session -t '${sanitizeShellArg(name)}'`, {
26
+ stdio: "pipe",
27
+ });
28
+ }
29
+ catch { }
30
+ }
31
+ function newSession(name) {
32
+ tmuxExec(`tmux new-session -d -s '${sanitizeShellArg(name)}'`);
33
+ }
34
+ /** Poll capture-pane every 100 ms until pattern matches or timeout. */
35
+ async function waitFor(session, pattern, timeoutMs = 5000) {
36
+ const deadline = Date.now() + timeoutMs;
37
+ while (Date.now() < deadline) {
38
+ const out = tmuxExec(buildCapturePaneCmd(session));
39
+ if (pattern.test(out))
40
+ return out;
41
+ await new Promise((r) => setTimeout(r, 100));
42
+ }
43
+ return tmuxExec(buildCapturePaneCmd(session));
44
+ }
45
+ function writeTmpScript(code) {
46
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "agtd-test-"));
47
+ const file = path.join(dir, "script.mjs");
48
+ fs.writeFileSync(file, code);
49
+ return file;
50
+ }
51
+ // ── Verify byte delivery ──────────────────────────────────────────────────
52
+ describe.skipIf(!AVAILABLE)("tmux byte delivery — both send approaches", () => {
53
+ const session = `${PREFIX}-bytes`;
54
+ afterEach(() => killSession(session));
55
+ // Raw-mode Node.js script that logs each keypress (uses readline.emitKeypressEvents
56
+ // internally, same as Ink/Codex)
57
+ const SCRIPT = writeTmpScript(`
58
+ import readline from 'readline';
59
+ readline.emitKeypressEvents(process.stdin);
60
+ if (process.stdin.isTTY) process.stdin.setRawMode(true);
61
+ process.stdin.resume();
62
+ process.stdin.setEncoding('utf8');
63
+ let buf = '';
64
+ process.stdin.on('keypress', (ch, key) => {
65
+ if (key?.name === 'return') {
66
+ process.stdout.write('GOT:' + buf + '\\n');
67
+ buf = '';
68
+ return;
69
+ }
70
+ if (key?.ctrl && key?.name === 'c') process.exit(0);
71
+ if (ch) buf += ch;
72
+ });
73
+ process.stdout.write('READY\\n');
74
+ `);
75
+ async function setup() {
76
+ killSession(session);
77
+ newSession(session);
78
+ tmuxExec(`tmux send-keys -t '${sanitizeShellArg(session)}' 'node ${SCRIPT}' Enter`);
79
+ await waitFor(session, /READY/, 3000);
80
+ await new Promise((r) => setTimeout(r, 300));
81
+ }
82
+ it("buildSendMessageCmd ('text' Enter) delivers chars via emitKeypressEvents", async () => {
83
+ await setup();
84
+ tmuxExec(buildSendMessageCmd(session, "hello world"));
85
+ const out = await waitFor(session, /GOT:/, 3000);
86
+ expect(out).toContain("GOT:hello world");
87
+ });
88
+ it("char-by-char hex mode (user-message approach) delivers chars correctly", async () => {
89
+ await setup();
90
+ // Simulate what the user-message handler now does: send each char, then CR
91
+ for (const char of "hello chars") {
92
+ tmuxExec(buildSendKeysCmd(session, char));
93
+ await new Promise((r) => setTimeout(r, 20));
94
+ }
95
+ tmuxExec(buildSendKeysCmd(session, "\r"));
96
+ const out = await waitFor(session, /GOT:/, 3000);
97
+ expect(out).toContain("GOT:hello chars");
98
+ });
99
+ it("messages with special characters (quotes, backticks) are delivered", async () => {
100
+ await setup();
101
+ const msg = "fix it's bug";
102
+ // char-by-char (agent approach)
103
+ for (const char of msg) {
104
+ tmuxExec(buildSendKeysCmd(session, char));
105
+ await new Promise((r) => setTimeout(r, 20));
106
+ }
107
+ tmuxExec(buildSendKeysCmd(session, "\r"));
108
+ const out = await waitFor(session, /GOT:/, 3000);
109
+ expect(out).toContain(`GOT:${msg}`);
110
+ });
111
+ }, { timeout: 30000 });
112
+ //# sourceMappingURL=tmux.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmux.integration.test.js","sourceRoot":"","sources":["../../src/__tests__/tmux.integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tmux.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmux.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/tmux.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { buildCreateSessionCmd, buildCreateWindowCmd, buildSendKeysCmd, buildCapturePaneCmd, } from "../tmux.js";
3
+ describe("tmux command builders", () => {
4
+ it("builds create session command", () => {
5
+ const cmd = buildCreateSessionCmd("aidash-s1", "/code/proj");
6
+ expect(cmd).toBe("tmux new-session -d -s 'aidash-s1' -c '/code/proj'");
7
+ });
8
+ it("builds create window command", () => {
9
+ const cmd = buildCreateWindowCmd("aidash-s1", "my-window", "/code/proj");
10
+ expect(cmd).toBe("tmux new-window -t 'aidash-s1' -n 'my-window' -c '/code/proj'");
11
+ });
12
+ it("builds send-keys command with hex-encoded bytes", () => {
13
+ const cmd = buildSendKeysCmd("aidash-s1", "hi");
14
+ // "hi" = 0x68 0x69
15
+ expect(cmd).toBe("tmux send-keys -t 'aidash-s1' -H 68 69");
16
+ });
17
+ it("sends Enter key as hex 0d (carriage return)", () => {
18
+ const cmd = buildSendKeysCmd("aidash-s1", "\r");
19
+ expect(cmd).toBe("tmux send-keys -t 'aidash-s1' -H 0d");
20
+ });
21
+ it("builds capture-pane command with ANSI escape preservation", () => {
22
+ const cmd = buildCapturePaneCmd("aidash-s1");
23
+ expect(cmd).toBe("tmux capture-pane -t 'aidash-s1' -p -e -S -");
24
+ });
25
+ });
26
+ //# sourceMappingURL=tmux.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmux.test.js","sourceRoot":"","sources":["../../src/__tests__/tmux.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAEpB,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,GAAG,GAAG,qBAAqB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,GAAG,GAAG,oBAAoB,CAAC,WAAW,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;QACzE,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CACd,+DAA+D,CAChE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,GAAG,GAAG,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAChD,mBAAmB;QACnB,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,GAAG,GAAG,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,GAAG,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAC7C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transcriptAdapters.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcriptAdapters.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/transcriptAdapters.test.ts"],"names":[],"mappings":""}