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