@doingdev/opencode-claude-manager-plugin 0.1.64 → 0.1.66

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 (125) hide show
  1. package/README.md +106 -120
  2. package/dist/claude/claude-agent-sdk-adapter.js +1 -1
  3. package/dist/index.d.ts +1 -1
  4. package/dist/manager/team-orchestrator.js +1 -1
  5. package/dist/plugin/agents/common.d.ts +2 -2
  6. package/dist/plugin/agents/common.js +5 -0
  7. package/dist/plugin/claude-manager.plugin.js +104 -0
  8. package/dist/plugin/inbox-ops.d.ts +50 -0
  9. package/dist/plugin/inbox-ops.js +166 -0
  10. package/dist/types/contracts.d.ts +18 -0
  11. package/package.json +13 -13
  12. package/dist/claude/session-live-tailer.d.ts +0 -51
  13. package/dist/claude/session-live-tailer.js +0 -269
  14. package/dist/manager/session-controller.d.ts +0 -41
  15. package/dist/manager/session-controller.js +0 -97
  16. package/dist/metadata/claude-metadata.service.d.ts +0 -12
  17. package/dist/metadata/claude-metadata.service.js +0 -38
  18. package/dist/metadata/repo-claude-config-reader.d.ts +0 -7
  19. package/dist/metadata/repo-claude-config-reader.js +0 -154
  20. package/dist/plugin/orchestrator.plugin.d.ts +0 -2
  21. package/dist/plugin/orchestrator.plugin.js +0 -116
  22. package/dist/providers/claude-code-wrapper.d.ts +0 -13
  23. package/dist/providers/claude-code-wrapper.js +0 -13
  24. package/dist/safety/bash-safety.d.ts +0 -21
  25. package/dist/safety/bash-safety.js +0 -62
  26. package/dist/src/claude/claude-agent-sdk-adapter.d.ts +0 -28
  27. package/dist/src/claude/claude-agent-sdk-adapter.js +0 -559
  28. package/dist/src/claude/claude-session.service.d.ts +0 -9
  29. package/dist/src/claude/claude-session.service.js +0 -15
  30. package/dist/src/claude/session-live-tailer.d.ts +0 -51
  31. package/dist/src/claude/session-live-tailer.js +0 -269
  32. package/dist/src/claude/tool-approval-manager.d.ts +0 -30
  33. package/dist/src/claude/tool-approval-manager.js +0 -279
  34. package/dist/src/index.d.ts +0 -5
  35. package/dist/src/index.js +0 -3
  36. package/dist/src/manager/context-tracker.d.ts +0 -32
  37. package/dist/src/manager/context-tracker.js +0 -103
  38. package/dist/src/manager/git-operations.d.ts +0 -18
  39. package/dist/src/manager/git-operations.js +0 -86
  40. package/dist/src/manager/persistent-manager.d.ts +0 -39
  41. package/dist/src/manager/persistent-manager.js +0 -44
  42. package/dist/src/manager/session-controller.d.ts +0 -41
  43. package/dist/src/manager/session-controller.js +0 -97
  44. package/dist/src/manager/team-orchestrator.d.ts +0 -81
  45. package/dist/src/manager/team-orchestrator.js +0 -612
  46. package/dist/src/plugin/agent-hierarchy.d.ts +0 -1
  47. package/dist/src/plugin/agent-hierarchy.js +0 -2
  48. package/dist/src/plugin/agents/browser-qa.d.ts +0 -14
  49. package/dist/src/plugin/agents/browser-qa.js +0 -31
  50. package/dist/src/plugin/agents/common.d.ts +0 -36
  51. package/dist/src/plugin/agents/common.js +0 -59
  52. package/dist/src/plugin/agents/cto.d.ts +0 -9
  53. package/dist/src/plugin/agents/cto.js +0 -39
  54. package/dist/src/plugin/agents/engineers.d.ts +0 -9
  55. package/dist/src/plugin/agents/engineers.js +0 -11
  56. package/dist/src/plugin/agents/index.d.ts +0 -5
  57. package/dist/src/plugin/agents/index.js +0 -5
  58. package/dist/src/plugin/agents/team-planner.d.ts +0 -10
  59. package/dist/src/plugin/agents/team-planner.js +0 -23
  60. package/dist/src/plugin/claude-manager.plugin.d.ts +0 -10
  61. package/dist/src/plugin/claude-manager.plugin.js +0 -950
  62. package/dist/src/plugin/service-factory.d.ts +0 -38
  63. package/dist/src/plugin/service-factory.js +0 -101
  64. package/dist/src/prompts/registry.d.ts +0 -2
  65. package/dist/src/prompts/registry.js +0 -210
  66. package/dist/src/state/file-run-state-store.d.ts +0 -14
  67. package/dist/src/state/file-run-state-store.js +0 -85
  68. package/dist/src/state/team-state-store.d.ts +0 -14
  69. package/dist/src/state/team-state-store.js +0 -88
  70. package/dist/src/state/transcript-store.d.ts +0 -15
  71. package/dist/src/state/transcript-store.js +0 -44
  72. package/dist/src/team/roster.d.ts +0 -5
  73. package/dist/src/team/roster.js +0 -40
  74. package/dist/src/types/contracts.d.ts +0 -261
  75. package/dist/src/types/contracts.js +0 -2
  76. package/dist/src/util/fs-helpers.d.ts +0 -8
  77. package/dist/src/util/fs-helpers.js +0 -21
  78. package/dist/src/util/project-context.d.ts +0 -10
  79. package/dist/src/util/project-context.js +0 -105
  80. package/dist/src/util/transcript-append.d.ts +0 -7
  81. package/dist/src/util/transcript-append.js +0 -29
  82. package/dist/state/file-run-state-store.d.ts +0 -14
  83. package/dist/state/file-run-state-store.js +0 -85
  84. package/dist/test/claude-agent-sdk-adapter.test.d.ts +0 -1
  85. package/dist/test/claude-agent-sdk-adapter.test.js +0 -707
  86. package/dist/test/claude-manager.plugin.test.d.ts +0 -1
  87. package/dist/test/claude-manager.plugin.test.js +0 -316
  88. package/dist/test/context-tracker.test.d.ts +0 -1
  89. package/dist/test/context-tracker.test.js +0 -130
  90. package/dist/test/cto-active-team.test.d.ts +0 -1
  91. package/dist/test/cto-active-team.test.js +0 -199
  92. package/dist/test/file-run-state-store.test.d.ts +0 -1
  93. package/dist/test/file-run-state-store.test.js +0 -82
  94. package/dist/test/fs-helpers.test.d.ts +0 -1
  95. package/dist/test/fs-helpers.test.js +0 -56
  96. package/dist/test/git-operations.test.d.ts +0 -1
  97. package/dist/test/git-operations.test.js +0 -133
  98. package/dist/test/persistent-manager.test.d.ts +0 -1
  99. package/dist/test/persistent-manager.test.js +0 -48
  100. package/dist/test/project-context.test.d.ts +0 -1
  101. package/dist/test/project-context.test.js +0 -92
  102. package/dist/test/prompt-registry.test.d.ts +0 -1
  103. package/dist/test/prompt-registry.test.js +0 -117
  104. package/dist/test/report-claude-event.test.d.ts +0 -1
  105. package/dist/test/report-claude-event.test.js +0 -304
  106. package/dist/test/session-controller.test.d.ts +0 -1
  107. package/dist/test/session-controller.test.js +0 -149
  108. package/dist/test/session-live-tailer.test.d.ts +0 -1
  109. package/dist/test/session-live-tailer.test.js +0 -313
  110. package/dist/test/team-orchestrator.test.d.ts +0 -1
  111. package/dist/test/team-orchestrator.test.js +0 -583
  112. package/dist/test/team-state-store.test.d.ts +0 -1
  113. package/dist/test/team-state-store.test.js +0 -54
  114. package/dist/test/tool-approval-manager.test.d.ts +0 -1
  115. package/dist/test/tool-approval-manager.test.js +0 -260
  116. package/dist/test/transcript-append.test.d.ts +0 -1
  117. package/dist/test/transcript-append.test.js +0 -37
  118. package/dist/test/transcript-store.test.d.ts +0 -1
  119. package/dist/test/transcript-store.test.js +0 -50
  120. package/dist/test/undo-propagation.test.d.ts +0 -1
  121. package/dist/test/undo-propagation.test.js +0 -837
  122. package/dist/util/project-context.d.ts +0 -10
  123. package/dist/util/project-context.js +0 -105
  124. package/dist/vitest.config.d.ts +0 -2
  125. package/dist/vitest.config.js +0 -11
@@ -1,313 +0,0 @@
1
- import { mkdirSync, mkdtempSync, rmSync, writeFileSync, appendFileSync } from 'node:fs';
2
- import path from 'node:path';
3
- import os from 'node:os';
4
- import { existsSync, readdirSync } from 'node:fs';
5
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
6
- import { SessionLiveTailer } from '../src/claude/session-live-tailer.js';
7
- // ── Helpers ─────────────────────────────────────────────────────────────
8
- let tmpDir;
9
- let projectsDir;
10
- function sessionDir(projectName) {
11
- const dir = path.join(projectsDir, projectName, 'sessions');
12
- mkdirSync(dir, { recursive: true });
13
- return dir;
14
- }
15
- function writeSession(projectName, sessionId, lines) {
16
- const dir = sessionDir(projectName);
17
- const filePath = path.join(dir, `${sessionId}.jsonl`);
18
- writeFileSync(filePath, lines.join('\n') + '\n', 'utf8');
19
- return filePath;
20
- }
21
- /**
22
- * Build a tailer that looks in our temp dir instead of ~/.claude/projects.
23
- * We override `findSessionFile` to search the temp projects dir.
24
- */
25
- function createTailer() {
26
- const tailer = new SessionLiveTailer();
27
- // Patch the internal discovery to use our temp dir.
28
- tailer.findSessionFile = (sessionId, cwd) => {
29
- if (!existsSync(projectsDir))
30
- return null;
31
- // Fast-path: sanitised cwd
32
- if (cwd) {
33
- const sanitised = cwd.replace(/\//g, '-');
34
- const candidate = path.join(projectsDir, sanitised, 'sessions', `${sessionId}.jsonl`);
35
- if (existsSync(candidate))
36
- return candidate;
37
- }
38
- // Scan all project directories
39
- try {
40
- for (const entry of readdirSync(projectsDir, { withFileTypes: true })) {
41
- if (!entry.isDirectory())
42
- continue;
43
- const candidate = path.join(projectsDir, entry.name, 'sessions', `${sessionId}.jsonl`);
44
- if (existsSync(candidate))
45
- return candidate;
46
- }
47
- }
48
- catch {
49
- // ignore
50
- }
51
- return null;
52
- };
53
- return tailer;
54
- }
55
- // ── Setup / teardown ────────────────────────────────────────────────────
56
- beforeEach(() => {
57
- tmpDir = mkdtempSync(path.join(os.tmpdir(), 'live-tailer-test-'));
58
- projectsDir = path.join(tmpDir, '.claude', 'projects');
59
- mkdirSync(projectsDir, { recursive: true });
60
- });
61
- afterEach(() => {
62
- rmSync(tmpDir, { recursive: true, force: true });
63
- });
64
- // ── Tests ───────────────────────────────────────────────────────────────
65
- describe('SessionLiveTailer', () => {
66
- describe('findSessionFile', () => {
67
- it('finds a session file by scanning project directories', () => {
68
- writeSession('my-project', 'ses_abc', [JSON.stringify({ type: 'system', subtype: 'init' })]);
69
- const tailer = createTailer();
70
- const found = tailer.findSessionFile('ses_abc');
71
- expect(found).not.toBeNull();
72
- expect(found).toContain('ses_abc.jsonl');
73
- });
74
- it('returns null when session does not exist', () => {
75
- const tailer = createTailer();
76
- expect(tailer.findSessionFile('ses_nonexistent')).toBeNull();
77
- });
78
- it('prefers sanitised cwd fast-path when cwd is provided', () => {
79
- // Create two projects with the same session ID
80
- writeSession('-home-user-proj', 'ses_dup', [
81
- JSON.stringify({ type: 'system', data: 'fast-path' }),
82
- ]);
83
- writeSession('other-project', 'ses_dup', [
84
- JSON.stringify({ type: 'system', data: 'scan-path' }),
85
- ]);
86
- const tailer = createTailer();
87
- const found = tailer.findSessionFile('ses_dup', '/home/user/proj');
88
- expect(found).not.toBeNull();
89
- expect(found).toContain('-home-user-proj');
90
- });
91
- });
92
- describe('sessionFileExists', () => {
93
- it('returns true when the file exists', () => {
94
- writeSession('proj', 'ses_exists', [JSON.stringify({ type: 'system' })]);
95
- const tailer = createTailer();
96
- expect(tailer.sessionFileExists('ses_exists')).toBe(true);
97
- });
98
- it('returns false when the file does not exist', () => {
99
- const tailer = createTailer();
100
- expect(tailer.sessionFileExists('ses_missing')).toBe(false);
101
- });
102
- });
103
- describe('getLastLines', () => {
104
- it('returns the last N lines from a JSONL file', async () => {
105
- const lines = Array.from({ length: 20 }, (_, i) => JSON.stringify({ type: 'line', index: i }));
106
- writeSession('proj', 'ses_lines', lines);
107
- const tailer = createTailer();
108
- const result = await tailer.getLastLines('ses_lines', undefined, 5);
109
- expect(result).toHaveLength(5);
110
- expect(JSON.parse(result[0])).toMatchObject({ index: 15 });
111
- expect(JSON.parse(result[4])).toMatchObject({ index: 19 });
112
- });
113
- it('returns all lines when file has fewer than N lines', async () => {
114
- writeSession('proj', 'ses_short', [
115
- JSON.stringify({ type: 'a' }),
116
- JSON.stringify({ type: 'b' }),
117
- ]);
118
- const tailer = createTailer();
119
- const result = await tailer.getLastLines('ses_short', undefined, 10);
120
- expect(result).toHaveLength(2);
121
- });
122
- it('returns empty array when session file not found', async () => {
123
- const tailer = createTailer();
124
- const result = await tailer.getLastLines('ses_ghost', undefined, 5);
125
- expect(result).toEqual([]);
126
- });
127
- });
128
- describe('getToolOutputPreview', () => {
129
- it('extracts tool_result from user messages (pattern 1)', async () => {
130
- const lines = [
131
- JSON.stringify({
132
- type: 'assistant',
133
- message: { content: [{ type: 'text', text: 'Searching...' }] },
134
- }),
135
- JSON.stringify({
136
- type: 'user',
137
- message: {
138
- content: [
139
- {
140
- type: 'tool_result',
141
- tool_use_id: 'toolu_grep_1',
142
- content: 'src/main.ts:42: const result = await fetch(url);',
143
- is_error: false,
144
- },
145
- ],
146
- },
147
- }),
148
- JSON.stringify({
149
- type: 'assistant',
150
- message: { content: [{ type: 'text', text: 'Found the match.' }] },
151
- }),
152
- ];
153
- writeSession('proj', 'ses_tool', lines);
154
- const tailer = createTailer();
155
- const previews = await tailer.getToolOutputPreview('ses_tool', undefined, 5);
156
- expect(previews).toHaveLength(1);
157
- expect(previews[0]).toMatchObject({
158
- toolUseId: 'toolu_grep_1',
159
- content: 'src/main.ts:42: const result = await fetch(url);',
160
- isError: false,
161
- });
162
- });
163
- it('extracts direct tool_result records (pattern 2)', async () => {
164
- const lines = [
165
- JSON.stringify({
166
- type: 'tool_result',
167
- tool_use_id: 'toolu_bash_1',
168
- content: 'npm test: 42 passed, 0 failed',
169
- is_error: false,
170
- }),
171
- ];
172
- writeSession('proj', 'ses_direct', lines);
173
- const tailer = createTailer();
174
- const previews = await tailer.getToolOutputPreview('ses_direct', undefined, 5);
175
- expect(previews).toHaveLength(1);
176
- expect(previews[0]).toMatchObject({
177
- toolUseId: 'toolu_bash_1',
178
- content: 'npm test: 42 passed, 0 failed',
179
- isError: false,
180
- });
181
- });
182
- it('handles error tool results', async () => {
183
- const lines = [
184
- JSON.stringify({
185
- type: 'tool_result',
186
- tool_use_id: 'toolu_err',
187
- content: 'ENOENT: no such file',
188
- is_error: true,
189
- }),
190
- ];
191
- writeSession('proj', 'ses_err', lines);
192
- const tailer = createTailer();
193
- const previews = await tailer.getToolOutputPreview('ses_err', undefined, 5);
194
- expect(previews).toHaveLength(1);
195
- expect(previews[0].isError).toBe(true);
196
- });
197
- it('limits results to maxEntries', async () => {
198
- const lines = Array.from({ length: 10 }, (_, i) => JSON.stringify({
199
- type: 'tool_result',
200
- tool_use_id: `toolu_${i}`,
201
- content: `result ${i}`,
202
- is_error: false,
203
- }));
204
- writeSession('proj', 'ses_limit', lines);
205
- const tailer = createTailer();
206
- const previews = await tailer.getToolOutputPreview('ses_limit', undefined, 3);
207
- expect(previews).toHaveLength(3);
208
- // Should return the last 3
209
- expect(previews[0].toolUseId).toBe('toolu_7');
210
- expect(previews[2].toolUseId).toBe('toolu_9');
211
- });
212
- it('skips non-tool-result lines', async () => {
213
- const lines = [
214
- JSON.stringify({ type: 'system', subtype: 'init' }),
215
- JSON.stringify({
216
- type: 'assistant',
217
- message: { content: [{ type: 'text', text: 'hi' }] },
218
- }),
219
- JSON.stringify({
220
- type: 'tool_result',
221
- tool_use_id: 'toolu_1',
222
- content: 'output',
223
- is_error: false,
224
- }),
225
- JSON.stringify({ type: 'result', subtype: 'success', result: 'Done' }),
226
- ];
227
- writeSession('proj', 'ses_mixed', lines);
228
- const tailer = createTailer();
229
- const previews = await tailer.getToolOutputPreview('ses_mixed', undefined, 10);
230
- expect(previews).toHaveLength(1);
231
- expect(previews[0].toolUseId).toBe('toolu_1');
232
- });
233
- it('returns empty array when session not found', async () => {
234
- const tailer = createTailer();
235
- const previews = await tailer.getToolOutputPreview('ses_nope', undefined);
236
- expect(previews).toEqual([]);
237
- });
238
- it('handles non-string content by JSON-stringifying it', async () => {
239
- const lines = [
240
- JSON.stringify({
241
- type: 'tool_result',
242
- tool_use_id: 'toolu_obj',
243
- content: [{ type: 'text', text: 'structured output' }],
244
- is_error: false,
245
- }),
246
- ];
247
- writeSession('proj', 'ses_obj', lines);
248
- const tailer = createTailer();
249
- const previews = await tailer.getToolOutputPreview('ses_obj', undefined, 5);
250
- expect(previews).toHaveLength(1);
251
- expect(previews[0].content).toBe(JSON.stringify([{ type: 'text', text: 'structured output' }]));
252
- });
253
- });
254
- describe('startTailing', () => {
255
- it('emits error event when session file not found', () => {
256
- const tailer = createTailer();
257
- const events = [];
258
- const stop = tailer.startTailing('ses_missing', undefined, (e) => events.push(e));
259
- expect(events).toHaveLength(1);
260
- expect(events[0].type).toBe('error');
261
- expect(events[0].error).toContain('ses_missing');
262
- stop();
263
- });
264
- it('picks up new lines appended after tailing starts', async () => {
265
- // Write initial content.
266
- const filePath = writeSession('proj', 'ses_tail', [
267
- JSON.stringify({ type: 'system', subtype: 'init' }),
268
- ]);
269
- const tailer = createTailer();
270
- const events = [];
271
- // Start tailing (offset begins at end of existing content).
272
- const stop = tailer.startTailing('ses_tail', undefined, (e) => events.push(e), 50);
273
- // Append a new line after a short delay.
274
- await sleep(80);
275
- appendFileSync(filePath, JSON.stringify({
276
- type: 'tool_result',
277
- tool_use_id: 'toolu_new',
278
- content: 'hello',
279
- }) + '\n');
280
- // Wait for the poll to pick it up.
281
- await sleep(200);
282
- stop();
283
- const lineEvents = events.filter((e) => e.type === 'line');
284
- expect(lineEvents.length).toBeGreaterThanOrEqual(1);
285
- expect(lineEvents[0].data).toMatchObject({
286
- type: 'tool_result',
287
- tool_use_id: 'toolu_new',
288
- });
289
- });
290
- it('stopTailing clears the interval', () => {
291
- writeSession('proj', 'ses_stop', [JSON.stringify({ type: 'system' })]);
292
- const tailer = createTailer();
293
- const stop = tailer.startTailing('ses_stop', undefined, () => { }, 50);
294
- // Stop should not throw and should be idempotent.
295
- stop();
296
- stop();
297
- tailer.stopTailing('ses_stop');
298
- });
299
- it('stopAll clears all active tails', () => {
300
- writeSession('proj', 'ses_a', [JSON.stringify({ type: 'system' })]);
301
- writeSession('proj', 'ses_b', [JSON.stringify({ type: 'system' })]);
302
- const tailer = createTailer();
303
- tailer.startTailing('ses_a', undefined, () => { }, 50);
304
- tailer.startTailing('ses_b', undefined, () => { }, 50);
305
- tailer.stopAll();
306
- // Verify idempotent — should not throw.
307
- tailer.stopAll();
308
- });
309
- });
310
- });
311
- function sleep(ms) {
312
- return new Promise((resolve) => setTimeout(resolve, ms));
313
- }
@@ -1 +0,0 @@
1
- export {};