@doingdev/opencode-claude-manager-plugin 0.1.19 → 0.1.21

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 (54) hide show
  1. package/README.md +40 -89
  2. package/dist/index.d.ts +5 -4
  3. package/dist/index.js +5 -4
  4. package/dist/plugin/orchestrator.plugin.d.ts +14 -0
  5. package/dist/plugin/orchestrator.plugin.js +108 -0
  6. package/dist/prompts/registry.d.ts +8 -2
  7. package/dist/prompts/registry.js +30 -133
  8. package/dist/safety/bash-safety.d.ts +21 -0
  9. package/dist/safety/bash-safety.js +62 -0
  10. package/package.json +3 -6
  11. package/dist/claude/claude-agent-sdk-adapter.d.ts +0 -27
  12. package/dist/claude/claude-agent-sdk-adapter.js +0 -520
  13. package/dist/claude/claude-session.service.d.ts +0 -15
  14. package/dist/claude/claude-session.service.js +0 -23
  15. package/dist/claude/delegated-can-use-tool.d.ts +0 -7
  16. package/dist/claude/delegated-can-use-tool.js +0 -178
  17. package/dist/claude/session-live-tailer.d.ts +0 -51
  18. package/dist/claude/session-live-tailer.js +0 -269
  19. package/dist/claude/tool-approval-manager.d.ts +0 -27
  20. package/dist/claude/tool-approval-manager.js +0 -238
  21. package/dist/manager/context-tracker.d.ts +0 -33
  22. package/dist/manager/context-tracker.js +0 -108
  23. package/dist/manager/git-operations.d.ts +0 -12
  24. package/dist/manager/git-operations.js +0 -76
  25. package/dist/manager/manager-orchestrator.d.ts +0 -17
  26. package/dist/manager/manager-orchestrator.js +0 -178
  27. package/dist/manager/persistent-manager.d.ts +0 -73
  28. package/dist/manager/persistent-manager.js +0 -167
  29. package/dist/manager/session-controller.d.ts +0 -45
  30. package/dist/manager/session-controller.js +0 -147
  31. package/dist/manager/task-planner.d.ts +0 -5
  32. package/dist/manager/task-planner.js +0 -15
  33. package/dist/metadata/claude-metadata.service.d.ts +0 -12
  34. package/dist/metadata/claude-metadata.service.js +0 -38
  35. package/dist/metadata/repo-claude-config-reader.d.ts +0 -7
  36. package/dist/metadata/repo-claude-config-reader.js +0 -154
  37. package/dist/plugin/claude-code-permission-bridge.d.ts +0 -15
  38. package/dist/plugin/claude-code-permission-bridge.js +0 -184
  39. package/dist/plugin/claude-manager.plugin.d.ts +0 -2
  40. package/dist/plugin/claude-manager.plugin.js +0 -578
  41. package/dist/plugin/service-factory.d.ts +0 -12
  42. package/dist/plugin/service-factory.js +0 -41
  43. package/dist/state/file-run-state-store.d.ts +0 -14
  44. package/dist/state/file-run-state-store.js +0 -87
  45. package/dist/state/transcript-store.d.ts +0 -15
  46. package/dist/state/transcript-store.js +0 -44
  47. package/dist/types/contracts.d.ts +0 -215
  48. package/dist/types/contracts.js +0 -1
  49. package/dist/util/fs-helpers.d.ts +0 -2
  50. package/dist/util/fs-helpers.js +0 -12
  51. package/dist/util/transcript-append.d.ts +0 -7
  52. package/dist/util/transcript-append.js +0 -29
  53. package/dist/worktree/worktree-coordinator.d.ts +0 -21
  54. package/dist/worktree/worktree-coordinator.js +0 -64
@@ -1,578 +0,0 @@
1
- import { tool } from '@opencode-ai/plugin';
2
- import { managerPromptRegistry } from '../prompts/registry.js';
3
- import { getOrCreatePluginServices } from './service-factory.js';
4
- const MANAGER_TOOL_IDS = [
5
- 'claude_manager_send',
6
- 'claude_manager_git_diff',
7
- 'claude_manager_git_commit',
8
- 'claude_manager_git_reset',
9
- 'claude_manager_clear',
10
- 'claude_manager_status',
11
- 'claude_manager_metadata',
12
- 'claude_manager_sessions',
13
- 'claude_manager_runs',
14
- 'claude_manager_approval_policy',
15
- 'claude_manager_approval_decisions',
16
- 'claude_manager_approval_update',
17
- ];
18
- export const ClaudeManagerPlugin = async ({ worktree }) => {
19
- const services = getOrCreatePluginServices(worktree);
20
- return {
21
- config: async (config) => {
22
- config.agent ??= {};
23
- config.command ??= {};
24
- config.permission ??= {};
25
- const globalPermissions = config.permission;
26
- const managerPermissions = {};
27
- const researchPermissions = {};
28
- for (const toolId of MANAGER_TOOL_IDS) {
29
- globalPermissions[toolId] ??= 'deny';
30
- managerPermissions[toolId] = 'allow';
31
- // Research agent can inspect but not send or modify
32
- researchPermissions[toolId] =
33
- toolId === 'claude_manager_send' ||
34
- toolId === 'claude_manager_git_commit' ||
35
- toolId === 'claude_manager_git_reset' ||
36
- toolId === 'claude_manager_clear' ||
37
- toolId === 'claude_manager_approval_update'
38
- ? 'deny'
39
- : 'allow';
40
- }
41
- config.agent['claude-manager'] ??= {
42
- description: 'Primary agent that operates Claude Code through a persistent session, reviews work via git diff, and commits/resets changes.',
43
- mode: 'primary',
44
- color: '#D97757',
45
- permission: {
46
- '*': 'deny',
47
- read: 'allow',
48
- grep: 'allow',
49
- glob: 'allow',
50
- codesearch: 'allow',
51
- webfetch: 'allow',
52
- websearch: 'allow',
53
- todowrite: 'allow',
54
- todoread: 'allow',
55
- question: 'allow',
56
- ...managerPermissions,
57
- },
58
- prompt: managerPromptRegistry.managerSystemPrompt,
59
- };
60
- config.agent['claude-manager-research'] ??= {
61
- description: 'Subagent that inspects Claude metadata, prior sessions, and manager runs without changing repository state.',
62
- mode: 'subagent',
63
- color: 'info',
64
- permission: {
65
- '*': 'deny',
66
- ...researchPermissions,
67
- },
68
- prompt: [
69
- 'Focus on inspection and summarization.',
70
- 'Use claude_manager_status, claude_manager_metadata, claude_manager_sessions, and claude_manager_runs to gather information.',
71
- ].join(' '),
72
- };
73
- config.command['claude-run'] ??= {
74
- description: 'Send a task to the persistent Claude Code session.',
75
- agent: 'claude-manager',
76
- subtask: true,
77
- template: [
78
- 'Use claude_manager_send to send the following task to Claude Code:',
79
- '$ARGUMENTS',
80
- 'After it completes, review the result and use claude_manager_git_diff if changes were expected. Commit or reset accordingly.',
81
- ].join('\n\n'),
82
- };
83
- config.command['claude-metadata'] ??= {
84
- description: 'Inspect bundled Claude commands, skills, hooks, and agents.',
85
- agent: 'claude-manager-research',
86
- subtask: true,
87
- template: [
88
- 'Use claude_manager_metadata to inspect the current repository.',
89
- 'Summarize Claude commands, skills, hooks, discovered agents, and important config files.',
90
- ].join(' '),
91
- };
92
- config.command['claude-sessions'] ??= {
93
- description: 'Inspect Claude session history and manager run records.',
94
- agent: 'claude-manager-research',
95
- subtask: true,
96
- template: [
97
- 'Use claude_manager_sessions and claude_manager_runs to inspect recent Claude activity for this repository.',
98
- 'If the user provided extra arguments, use them to focus the inspection:',
99
- '$ARGUMENTS',
100
- ].join('\n\n'),
101
- };
102
- },
103
- 'command.execute.before': async (input, output) => {
104
- const commandText = buildCommandText(input.command, input.arguments);
105
- if (commandText) {
106
- output.parts = rewriteCommandParts(output.parts, commandText);
107
- }
108
- },
109
- tool: {
110
- claude_manager_send: tool({
111
- description: 'Send a message to the persistent Claude Code session. ' +
112
- 'Auto-creates a session on first call. Resumes the existing session on subsequent calls. ' +
113
- 'Returns the assistant response and current context health snapshot. ' +
114
- 'Use mode "plan" for read-only investigation and planning (no edits), ' +
115
- 'or "free" (default) for normal execution with edit permissions.',
116
- args: {
117
- message: tool.schema.string().min(1),
118
- model: tool.schema.string().optional(),
119
- mode: tool.schema.enum(['plan', 'free']).default('free'),
120
- cwd: tool.schema.string().optional(),
121
- },
122
- async execute(args, context) {
123
- const cwd = args.cwd ?? context.worktree;
124
- const hasActiveSession = services.manager.getStatus().sessionId !== null;
125
- const promptPreview = args.message.length > 100
126
- ? args.message.slice(0, 100) + '...'
127
- : args.message;
128
- context.metadata({
129
- title: hasActiveSession
130
- ? 'Claude Code: Resuming session...'
131
- : 'Claude Code: Initializing...',
132
- metadata: {
133
- sessionId: services.manager.getStatus().sessionId,
134
- prompt: promptPreview,
135
- },
136
- });
137
- let turnsSoFar = 0;
138
- let costSoFar = 0;
139
- const result = await services.manager.sendMessage(cwd, args.message, { model: args.model, mode: args.mode, abortSignal: context.abort }, (event) => {
140
- if (event.turns !== undefined) {
141
- turnsSoFar = event.turns;
142
- }
143
- if (event.totalCostUsd !== undefined) {
144
- costSoFar = event.totalCostUsd;
145
- }
146
- const costLabel = `$${costSoFar.toFixed(4)}`;
147
- if (event.type === 'tool_call') {
148
- let toolName = 'tool';
149
- let inputPreview = '';
150
- try {
151
- const parsed = JSON.parse(event.text);
152
- toolName = parsed.name ?? 'tool';
153
- if (parsed.input) {
154
- const inputStr = typeof parsed.input === 'string'
155
- ? parsed.input
156
- : JSON.stringify(parsed.input);
157
- inputPreview =
158
- inputStr.length > 150
159
- ? inputStr.slice(0, 150) + '...'
160
- : inputStr;
161
- }
162
- }
163
- catch {
164
- // ignore parse errors
165
- }
166
- context.metadata({
167
- title: `Claude Code: Running ${toolName}... (${turnsSoFar} turns, ${costLabel})`,
168
- metadata: {
169
- sessionId: event.sessionId,
170
- type: event.type,
171
- tool: toolName,
172
- input: inputPreview,
173
- },
174
- });
175
- }
176
- else if (event.type === 'assistant') {
177
- const thinkingPreview = event.text.length > 150
178
- ? event.text.slice(0, 150) + '...'
179
- : event.text;
180
- context.metadata({
181
- title: `Claude Code: Thinking... (${turnsSoFar} turns, ${costLabel})`,
182
- metadata: {
183
- sessionId: event.sessionId,
184
- type: event.type,
185
- thinking: thinkingPreview,
186
- },
187
- });
188
- }
189
- else if (event.type === 'init') {
190
- context.metadata({
191
- title: `Claude Code: Session started`,
192
- metadata: {
193
- sessionId: event.sessionId,
194
- prompt: promptPreview,
195
- },
196
- });
197
- }
198
- else if (event.type === 'user') {
199
- const preview = event.text.length > 200
200
- ? event.text.slice(0, 200) + '...'
201
- : event.text;
202
- context.metadata({
203
- title: `Claude Code: Tool result (${turnsSoFar} turns, ${costLabel})`,
204
- metadata: {
205
- sessionId: event.sessionId,
206
- type: event.type,
207
- output: preview,
208
- },
209
- });
210
- }
211
- else if (event.type === 'tool_progress') {
212
- let toolName = 'tool';
213
- let elapsed = 0;
214
- try {
215
- const parsed = JSON.parse(event.text);
216
- toolName = parsed.name ?? 'tool';
217
- elapsed = parsed.elapsed ?? 0;
218
- }
219
- catch {
220
- // ignore
221
- }
222
- context.metadata({
223
- title: `Claude Code: ${toolName} running ${elapsed > 0 ? `(${elapsed.toFixed(0)}s)` : ''}... (${turnsSoFar} turns, ${costLabel})`,
224
- metadata: {
225
- sessionId: event.sessionId,
226
- type: event.type,
227
- tool: toolName,
228
- elapsed,
229
- },
230
- });
231
- }
232
- else if (event.type === 'tool_summary') {
233
- const summary = event.text.length > 200
234
- ? event.text.slice(0, 200) + '...'
235
- : event.text;
236
- context.metadata({
237
- title: `Claude Code: Tool done (${turnsSoFar} turns, ${costLabel})`,
238
- metadata: {
239
- sessionId: event.sessionId,
240
- type: event.type,
241
- summary,
242
- },
243
- });
244
- }
245
- else if (event.type === 'partial') {
246
- const delta = event.text.length > 200
247
- ? event.text.slice(0, 200) + '...'
248
- : event.text;
249
- context.metadata({
250
- title: `Claude Code: Writing... (${turnsSoFar} turns, ${costLabel})`,
251
- metadata: {
252
- sessionId: event.sessionId,
253
- type: event.type,
254
- delta,
255
- },
256
- });
257
- }
258
- else if (event.type === 'error') {
259
- context.metadata({
260
- title: `Claude Code: Error`,
261
- metadata: {
262
- sessionId: event.sessionId,
263
- error: event.text.slice(0, 200),
264
- },
265
- });
266
- }
267
- });
268
- const costLabel = `$${(result.totalCostUsd ?? 0).toFixed(4)}`;
269
- const turns = result.turns ?? 0;
270
- const contextWarning = formatContextWarning(result.context);
271
- if (contextWarning) {
272
- context.metadata({
273
- title: `Claude Code: Context at ${result.context.estimatedContextPercent}% (${turns} turns)`,
274
- metadata: { sessionId: result.sessionId, contextWarning },
275
- });
276
- }
277
- else {
278
- context.metadata({
279
- title: `Claude Code: Complete (${turns} turns, ${costLabel})`,
280
- metadata: { sessionId: result.sessionId },
281
- });
282
- }
283
- // Fetch recent tool output from the JSONL file for richer feedback.
284
- let toolOutputs = [];
285
- if (result.sessionId) {
286
- try {
287
- toolOutputs = await services.liveTailer.getToolOutputPreview(result.sessionId, cwd, 3);
288
- }
289
- catch {
290
- // Non-critical — the JSONL file may not exist yet.
291
- }
292
- }
293
- return JSON.stringify({
294
- sessionId: result.sessionId,
295
- finalText: result.finalText,
296
- turns: result.turns,
297
- totalCostUsd: result.totalCostUsd,
298
- context: result.context,
299
- contextWarning,
300
- toolOutputs: toolOutputs.length > 0 ? toolOutputs : undefined,
301
- }, null, 2);
302
- },
303
- }),
304
- claude_manager_git_diff: tool({
305
- description: 'Run git diff to see all current changes (staged + unstaged) relative to HEAD.',
306
- args: {
307
- cwd: tool.schema.string().optional(),
308
- },
309
- async execute(_args, context) {
310
- annotateToolRun(context, 'Running git diff', {});
311
- const result = await services.manager.gitDiff();
312
- return JSON.stringify(result, null, 2);
313
- },
314
- }),
315
- claude_manager_git_commit: tool({
316
- description: 'Stage all changes and commit with the given message.',
317
- args: {
318
- message: tool.schema.string().min(1),
319
- cwd: tool.schema.string().optional(),
320
- },
321
- async execute(args, context) {
322
- annotateToolRun(context, 'Committing changes', {
323
- message: args.message,
324
- });
325
- const result = await services.manager.gitCommit(args.message);
326
- return JSON.stringify(result, null, 2);
327
- },
328
- }),
329
- claude_manager_git_reset: tool({
330
- description: 'Run git reset --hard HEAD and git clean -fd to discard ALL uncommitted changes and untracked files.',
331
- args: {
332
- cwd: tool.schema.string().optional(),
333
- },
334
- async execute(_args, context) {
335
- annotateToolRun(context, 'Resetting working directory', {});
336
- const result = await services.manager.gitReset();
337
- return JSON.stringify(result, null, 2);
338
- },
339
- }),
340
- claude_manager_clear: tool({
341
- description: 'Clear the active Claude Code session. The next send will start a fresh session. ' +
342
- 'Use when context is full, the session is confused, or starting a different task.',
343
- args: {
344
- cwd: tool.schema.string().optional(),
345
- reason: tool.schema.string().optional(),
346
- },
347
- async execute(args, context) {
348
- annotateToolRun(context, 'Clearing session', {
349
- reason: args.reason,
350
- });
351
- const clearedId = await services.manager.clearSession(args.cwd ?? context.worktree);
352
- return JSON.stringify({ clearedSessionId: clearedId });
353
- },
354
- }),
355
- claude_manager_status: tool({
356
- description: 'Get the current persistent session status: context usage %, turns, cost, active session ID.',
357
- args: {
358
- cwd: tool.schema.string().optional(),
359
- },
360
- async execute(_args, context) {
361
- annotateToolRun(context, 'Checking session status', {});
362
- const status = services.manager.getStatus();
363
- return JSON.stringify({
364
- ...status,
365
- transcriptFile: status.sessionId
366
- ? `.claude-manager/transcripts/${status.sessionId}.json`
367
- : null,
368
- contextWarning: formatContextWarning(status),
369
- }, null, 2);
370
- },
371
- }),
372
- claude_manager_metadata: tool({
373
- description: 'Inspect Claude slash commands, skills, hooks, and repo settings.',
374
- args: {
375
- cwd: tool.schema.string().optional(),
376
- includeSdkProbe: tool.schema.boolean().default(false),
377
- },
378
- async execute(args, context) {
379
- annotateToolRun(context, 'Collecting Claude metadata', {
380
- includeSdkProbe: args.includeSdkProbe,
381
- });
382
- const metadata = await services.sessions.inspectRepository(args.cwd ?? context.worktree, {
383
- includeSdkProbe: args.includeSdkProbe,
384
- });
385
- return JSON.stringify(metadata, null, 2);
386
- },
387
- }),
388
- claude_manager_sessions: tool({
389
- description: 'List Claude sessions or inspect a saved transcript. ' +
390
- 'When sessionId is provided, returns both SDK transcript and local manager events.',
391
- args: {
392
- cwd: tool.schema.string().optional(),
393
- sessionId: tool.schema.string().optional(),
394
- },
395
- async execute(args, context) {
396
- annotateToolRun(context, 'Inspecting Claude session history', {});
397
- const cwd = args.cwd ?? context.worktree;
398
- if (args.sessionId) {
399
- const [sdkTranscript, localEvents] = await Promise.all([
400
- services.sessions.getTranscript(args.sessionId, cwd),
401
- services.manager.getTranscriptEvents(cwd, args.sessionId),
402
- ]);
403
- return JSON.stringify({
404
- sdkTranscript,
405
- localEvents: localEvents.length > 0 ? localEvents : undefined,
406
- }, null, 2);
407
- }
408
- const sessions = await services.sessions.listSessions(cwd);
409
- return JSON.stringify(sessions, null, 2);
410
- },
411
- }),
412
- claude_manager_runs: tool({
413
- description: 'List persistent manager run records.',
414
- args: {
415
- cwd: tool.schema.string().optional(),
416
- runId: tool.schema.string().optional(),
417
- },
418
- async execute(args, context) {
419
- annotateToolRun(context, 'Reading manager run state', {});
420
- if (args.runId) {
421
- const run = await services.manager.getRun(args.cwd ?? context.worktree, args.runId);
422
- return JSON.stringify(run, null, 2);
423
- }
424
- const runs = await services.manager.listRuns(args.cwd ?? context.worktree);
425
- return JSON.stringify(runs, null, 2);
426
- },
427
- }),
428
- claude_manager_approval_policy: tool({
429
- description: 'View the current tool approval policy: rules, default action, and enabled status.',
430
- args: {},
431
- async execute(_args, context) {
432
- annotateToolRun(context, 'Reading approval policy', {});
433
- return JSON.stringify(services.approvalManager.getPolicy(), null, 2);
434
- },
435
- }),
436
- claude_manager_approval_decisions: tool({
437
- description: 'View recent tool approval decisions. Shows what tools were allowed or denied. ' +
438
- 'Use deniedOnly to see only denied calls.',
439
- args: {
440
- limit: tool.schema.number().optional(),
441
- deniedOnly: tool.schema.boolean().optional(),
442
- },
443
- async execute(args, context) {
444
- annotateToolRun(context, 'Reading approval decisions', {});
445
- const decisions = args.deniedOnly
446
- ? services.approvalManager.getDeniedDecisions(args.limit)
447
- : services.approvalManager.getDecisions(args.limit);
448
- return JSON.stringify({ total: decisions.length, decisions }, null, 2);
449
- },
450
- }),
451
- claude_manager_approval_update: tool({
452
- description: 'Update the tool approval policy. Add/remove rules, change default action, or enable/disable. ' +
453
- 'Rules are evaluated top-to-bottom; first match wins.',
454
- args: {
455
- action: tool.schema.enum([
456
- 'addRule',
457
- 'removeRule',
458
- 'setDefault',
459
- 'setEnabled',
460
- 'clearDecisions',
461
- ]),
462
- ruleId: tool.schema.string().optional(),
463
- toolPattern: tool.schema.string().optional(),
464
- inputPattern: tool.schema.string().optional(),
465
- ruleAction: tool.schema.enum(['allow', 'deny']).optional(),
466
- denyMessage: tool.schema.string().optional(),
467
- description: tool.schema.string().optional(),
468
- position: tool.schema.number().optional(),
469
- defaultAction: tool.schema.enum(['allow', 'deny']).optional(),
470
- enabled: tool.schema.boolean().optional(),
471
- },
472
- async execute(args, context) {
473
- annotateToolRun(context, `Updating approval: ${args.action}`, {});
474
- if (args.action === 'addRule') {
475
- if (!args.ruleId || !args.toolPattern || !args.ruleAction) {
476
- return JSON.stringify({
477
- error: 'addRule requires ruleId, toolPattern, and ruleAction',
478
- });
479
- }
480
- services.approvalManager.addRule({
481
- id: args.ruleId,
482
- toolPattern: args.toolPattern,
483
- inputPattern: args.inputPattern,
484
- action: args.ruleAction,
485
- denyMessage: args.denyMessage,
486
- description: args.description,
487
- }, args.position);
488
- }
489
- else if (args.action === 'removeRule') {
490
- if (!args.ruleId) {
491
- return JSON.stringify({ error: 'removeRule requires ruleId' });
492
- }
493
- const removed = services.approvalManager.removeRule(args.ruleId);
494
- return JSON.stringify({ removed });
495
- }
496
- else if (args.action === 'setDefault') {
497
- if (!args.defaultAction) {
498
- return JSON.stringify({
499
- error: 'setDefault requires defaultAction',
500
- });
501
- }
502
- services.approvalManager.setDefaultAction(args.defaultAction);
503
- }
504
- else if (args.action === 'setEnabled') {
505
- if (args.enabled === undefined) {
506
- return JSON.stringify({ error: 'setEnabled requires enabled' });
507
- }
508
- services.approvalManager.setEnabled(args.enabled);
509
- }
510
- else if (args.action === 'clearDecisions') {
511
- services.approvalManager.clearDecisions();
512
- }
513
- return JSON.stringify(services.approvalManager.getPolicy(), null, 2);
514
- },
515
- }),
516
- },
517
- };
518
- };
519
- function annotateToolRun(context, title, metadata) {
520
- context.metadata({ title, metadata });
521
- }
522
- function buildCommandText(command, rawArguments) {
523
- const argumentsText = rawArguments.trim();
524
- if (command === 'claude-run') {
525
- return [
526
- 'Use `claude_manager_send` to send the following task to Claude Code:',
527
- argumentsText
528
- ? argumentsText
529
- : 'Inspect the current repository and wait for follow-up instructions.',
530
- 'After it completes, review the result. If code changes were expected, use `claude_manager_git_diff` to review, then `claude_manager_git_commit` or `claude_manager_git_reset` accordingly.',
531
- ].join('\n\n');
532
- }
533
- if (command === 'claude-metadata') {
534
- return [
535
- 'Call `claude_manager_metadata` immediately for the current repository.',
536
- argumentsText ? `Focus: ${argumentsText}` : '',
537
- 'Then summarize the discovered Claude commands, skills, hooks, agents, and config files briefly.',
538
- ]
539
- .filter(Boolean)
540
- .join('\n\n');
541
- }
542
- if (command === 'claude-sessions') {
543
- return [
544
- 'Call `claude_manager_sessions` and `claude_manager_runs` immediately for the current repository.',
545
- argumentsText ? `Focus: ${argumentsText}` : '',
546
- 'Then summarize the most relevant recent Claude activity briefly.',
547
- ]
548
- .filter(Boolean)
549
- .join('\n\n');
550
- }
551
- return null;
552
- }
553
- function rewriteCommandParts(parts, text) {
554
- let hasRewrittenText = false;
555
- return parts.map((part) => {
556
- if (part.type !== 'text' || hasRewrittenText) {
557
- return part;
558
- }
559
- hasRewrittenText = true;
560
- return { ...part, text };
561
- });
562
- }
563
- function formatContextWarning(context) {
564
- const { warningLevel, estimatedContextPercent, totalTurns, totalCostUsd } = context;
565
- if (warningLevel === 'ok' || estimatedContextPercent === null) {
566
- return null;
567
- }
568
- const templates = managerPromptRegistry.contextWarnings;
569
- const template = warningLevel === 'critical'
570
- ? templates.critical
571
- : warningLevel === 'high'
572
- ? templates.high
573
- : templates.moderate;
574
- return template
575
- .replace('{percent}', String(estimatedContextPercent))
576
- .replace('{turns}', String(totalTurns))
577
- .replace('{cost}', totalCostUsd.toFixed(2));
578
- }
@@ -1,12 +0,0 @@
1
- import { ClaudeSessionService } from '../claude/claude-session.service.js';
2
- import { SessionLiveTailer } from '../claude/session-live-tailer.js';
3
- import { ToolApprovalManager } from '../claude/tool-approval-manager.js';
4
- import { PersistentManager } from '../manager/persistent-manager.js';
5
- interface ClaudeManagerPluginServices {
6
- manager: PersistentManager;
7
- sessions: ClaudeSessionService;
8
- approvalManager: ToolApprovalManager;
9
- liveTailer: SessionLiveTailer;
10
- }
11
- export declare function getOrCreatePluginServices(worktree: string): ClaudeManagerPluginServices;
12
- export {};
@@ -1,41 +0,0 @@
1
- import { ClaudeAgentSdkAdapter } from '../claude/claude-agent-sdk-adapter.js';
2
- import { ClaudeSessionService } from '../claude/claude-session.service.js';
3
- import { SessionLiveTailer } from '../claude/session-live-tailer.js';
4
- import { ToolApprovalManager } from '../claude/tool-approval-manager.js';
5
- import { ClaudeMetadataService } from '../metadata/claude-metadata.service.js';
6
- import { RepoClaudeConfigReader } from '../metadata/repo-claude-config-reader.js';
7
- import { FileRunStateStore } from '../state/file-run-state-store.js';
8
- import { TranscriptStore } from '../state/transcript-store.js';
9
- import { ContextTracker } from '../manager/context-tracker.js';
10
- import { GitOperations } from '../manager/git-operations.js';
11
- import { SessionController } from '../manager/session-controller.js';
12
- import { PersistentManager } from '../manager/persistent-manager.js';
13
- import { managerPromptRegistry } from '../prompts/registry.js';
14
- const serviceCache = new Map();
15
- export function getOrCreatePluginServices(worktree) {
16
- const cachedServices = serviceCache.get(worktree);
17
- if (cachedServices) {
18
- return cachedServices;
19
- }
20
- const approvalManager = new ToolApprovalManager();
21
- const sdkAdapter = new ClaudeAgentSdkAdapter(undefined, approvalManager);
22
- const metadataService = new ClaudeMetadataService(new RepoClaudeConfigReader(), sdkAdapter);
23
- const sessionService = new ClaudeSessionService(sdkAdapter, metadataService);
24
- const contextTracker = new ContextTracker();
25
- const sessionController = new SessionController(sdkAdapter, contextTracker, managerPromptRegistry.claudeCodeSessionPrompt, managerPromptRegistry.modePrefixes);
26
- const gitOps = new GitOperations(worktree);
27
- const stateStore = new FileRunStateStore();
28
- const transcriptStore = new TranscriptStore();
29
- const manager = new PersistentManager(sessionController, gitOps, stateStore, contextTracker, transcriptStore);
30
- // Try to restore active session state (fire and forget)
31
- manager.tryRestore(worktree).catch(() => { });
32
- const liveTailer = new SessionLiveTailer();
33
- const services = {
34
- manager,
35
- sessions: sessionService,
36
- approvalManager,
37
- liveTailer,
38
- };
39
- serviceCache.set(worktree, services);
40
- return services;
41
- }
@@ -1,14 +0,0 @@
1
- import type { PersistentRunRecord } from '../types/contracts.js';
2
- export declare class FileRunStateStore {
3
- private readonly baseDirectoryName;
4
- private readonly writeQueues;
5
- constructor(baseDirectoryName?: string);
6
- saveRun(run: PersistentRunRecord): Promise<void>;
7
- getRun(cwd: string, runId: string): Promise<PersistentRunRecord | null>;
8
- listRuns(cwd: string): Promise<PersistentRunRecord[]>;
9
- updateRun(cwd: string, runId: string, update: (run: PersistentRunRecord) => PersistentRunRecord): Promise<PersistentRunRecord>;
10
- private getRunKey;
11
- private getRunsDirectory;
12
- private getRunPath;
13
- private enqueueWrite;
14
- }