@doingdev/opencode-claude-manager-plugin 0.1.34 → 0.1.42
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 +14 -15
- package/dist/claude/claude-agent-sdk-adapter.js +2 -1
- package/dist/claude/session-live-tailer.js +2 -2
- package/dist/manager/git-operations.d.ts +10 -1
- package/dist/manager/git-operations.js +18 -3
- package/dist/manager/persistent-manager.d.ts +16 -1
- package/dist/manager/persistent-manager.js +14 -2
- package/dist/plugin/agent-hierarchy.d.ts +1 -1
- package/dist/plugin/agent-hierarchy.js +12 -17
- package/dist/plugin/claude-manager.plugin.js +158 -79
- package/dist/prompts/registry.js +16 -12
- package/dist/src/claude/claude-agent-sdk-adapter.d.ts +27 -0
- package/dist/src/claude/claude-agent-sdk-adapter.js +517 -0
- package/dist/src/claude/claude-session.service.d.ts +10 -0
- package/dist/src/claude/claude-session.service.js +18 -0
- package/dist/src/claude/session-live-tailer.d.ts +51 -0
- package/dist/src/claude/session-live-tailer.js +269 -0
- package/dist/src/claude/tool-approval-manager.d.ts +27 -0
- package/dist/src/claude/tool-approval-manager.js +232 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +4 -0
- package/dist/src/manager/context-tracker.d.ts +33 -0
- package/dist/src/manager/context-tracker.js +106 -0
- package/dist/src/manager/git-operations.d.ts +12 -0
- package/dist/src/manager/git-operations.js +76 -0
- package/dist/src/manager/persistent-manager.d.ts +77 -0
- package/dist/src/manager/persistent-manager.js +170 -0
- package/dist/src/manager/session-controller.d.ts +44 -0
- package/dist/src/manager/session-controller.js +147 -0
- package/dist/src/plugin/agent-hierarchy.d.ts +60 -0
- package/dist/src/plugin/agent-hierarchy.js +157 -0
- package/dist/src/plugin/claude-manager.plugin.d.ts +2 -0
- package/dist/src/plugin/claude-manager.plugin.js +563 -0
- package/dist/src/plugin/service-factory.d.ts +12 -0
- package/dist/src/plugin/service-factory.js +38 -0
- package/dist/src/prompts/registry.d.ts +11 -0
- package/dist/src/prompts/registry.js +260 -0
- package/dist/src/state/file-run-state-store.d.ts +14 -0
- package/dist/src/state/file-run-state-store.js +85 -0
- package/dist/src/state/transcript-store.d.ts +15 -0
- package/dist/src/state/transcript-store.js +44 -0
- package/dist/src/types/contracts.d.ts +200 -0
- package/dist/src/types/contracts.js +1 -0
- package/dist/src/util/fs-helpers.d.ts +2 -0
- package/dist/src/util/fs-helpers.js +10 -0
- package/dist/src/util/project-context.d.ts +10 -0
- package/dist/src/util/project-context.js +105 -0
- package/dist/src/util/transcript-append.d.ts +7 -0
- package/dist/src/util/transcript-append.js +29 -0
- package/dist/test/claude-agent-sdk-adapter.test.d.ts +1 -0
- package/dist/test/claude-agent-sdk-adapter.test.js +459 -0
- package/dist/test/claude-manager.plugin.test.d.ts +1 -0
- package/dist/test/claude-manager.plugin.test.js +331 -0
- package/dist/test/context-tracker.test.d.ts +1 -0
- package/dist/test/context-tracker.test.js +138 -0
- package/dist/test/file-run-state-store.test.d.ts +1 -0
- package/dist/test/file-run-state-store.test.js +82 -0
- package/dist/test/git-operations.test.d.ts +1 -0
- package/dist/test/git-operations.test.js +90 -0
- package/dist/test/persistent-manager.test.d.ts +1 -0
- package/dist/test/persistent-manager.test.js +208 -0
- package/dist/test/project-context.test.d.ts +1 -0
- package/dist/test/project-context.test.js +92 -0
- package/dist/test/prompt-registry.test.d.ts +1 -0
- package/dist/test/prompt-registry.test.js +256 -0
- package/dist/test/session-controller.test.d.ts +1 -0
- package/dist/test/session-controller.test.js +149 -0
- package/dist/test/session-live-tailer.test.d.ts +1 -0
- package/dist/test/session-live-tailer.test.js +313 -0
- package/dist/test/tool-approval-manager.test.d.ts +1 -0
- package/dist/test/tool-approval-manager.test.js +264 -0
- package/dist/test/transcript-append.test.d.ts +1 -0
- package/dist/test/transcript-append.test.js +37 -0
- package/dist/test/transcript-store.test.d.ts +1 -0
- package/dist/test/transcript-store.test.js +50 -0
- package/dist/types/contracts.d.ts +1 -1
- package/dist/vitest.config.d.ts +2 -0
- package/dist/vitest.config.js +11 -0
- package/package.json +2 -2
|
@@ -5,7 +5,7 @@ import { AGENT_CTO, AGENT_ENGINEER_BUILD, AGENT_ENGINEER_PLAN, buildCtoAgentConf
|
|
|
5
5
|
import { getOrCreatePluginServices } from './service-factory.js';
|
|
6
6
|
export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
7
7
|
const services = getOrCreatePluginServices(worktree);
|
|
8
|
-
async function
|
|
8
|
+
async function executeDelegate(args, context) {
|
|
9
9
|
const cwd = args.cwd ?? context.worktree;
|
|
10
10
|
if (args.freshSession) {
|
|
11
11
|
await services.manager.clearSession(cwd);
|
|
@@ -13,8 +13,11 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
13
13
|
const hasActiveSession = services.manager.getStatus().sessionId !== null;
|
|
14
14
|
const promptPreview = args.message.length > 100 ? args.message.slice(0, 100) + '...' : args.message;
|
|
15
15
|
context.metadata({
|
|
16
|
-
title: hasActiveSession
|
|
16
|
+
title: hasActiveSession
|
|
17
|
+
? '⚡ Claude Code: Resuming session...'
|
|
18
|
+
: '⚡ Claude Code: Initializing...',
|
|
17
19
|
metadata: {
|
|
20
|
+
status: 'running',
|
|
18
21
|
sessionId: services.manager.getStatus().sessionId,
|
|
19
22
|
prompt: promptPreview,
|
|
20
23
|
},
|
|
@@ -49,8 +52,9 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
49
52
|
// ignore parse errors
|
|
50
53
|
}
|
|
51
54
|
context.metadata({
|
|
52
|
-
title:
|
|
55
|
+
title: `⚡ Claude Code: Running ${toolName}...${usageSuffix}`,
|
|
53
56
|
metadata: {
|
|
57
|
+
status: 'running',
|
|
54
58
|
sessionId: event.sessionId,
|
|
55
59
|
type: event.type,
|
|
56
60
|
tool: toolName,
|
|
@@ -61,8 +65,9 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
61
65
|
else if (event.type === 'assistant') {
|
|
62
66
|
const thinkingPreview = event.text.length > 150 ? event.text.slice(0, 150) + '...' : event.text;
|
|
63
67
|
context.metadata({
|
|
64
|
-
title:
|
|
68
|
+
title: `⚡ Claude Code: Thinking...${usageSuffix}`,
|
|
65
69
|
metadata: {
|
|
70
|
+
status: 'running',
|
|
66
71
|
sessionId: event.sessionId,
|
|
67
72
|
type: event.type,
|
|
68
73
|
thinking: thinkingPreview,
|
|
@@ -71,8 +76,9 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
71
76
|
}
|
|
72
77
|
else if (event.type === 'init') {
|
|
73
78
|
context.metadata({
|
|
74
|
-
title:
|
|
79
|
+
title: `⚡ Claude Code: Session started`,
|
|
75
80
|
metadata: {
|
|
81
|
+
status: 'running',
|
|
76
82
|
sessionId: event.sessionId,
|
|
77
83
|
prompt: promptPreview,
|
|
78
84
|
},
|
|
@@ -80,9 +86,11 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
80
86
|
}
|
|
81
87
|
else if (event.type === 'user') {
|
|
82
88
|
const preview = event.text.length > 200 ? event.text.slice(0, 200) + '...' : event.text;
|
|
89
|
+
const outputPreview = formatToolOutputPreview(event.text);
|
|
83
90
|
context.metadata({
|
|
84
|
-
title:
|
|
91
|
+
title: `⚡ Claude Code: ${outputPreview}${usageSuffix}`,
|
|
85
92
|
metadata: {
|
|
93
|
+
status: 'running',
|
|
86
94
|
sessionId: event.sessionId,
|
|
87
95
|
type: event.type,
|
|
88
96
|
output: preview,
|
|
@@ -92,17 +100,25 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
92
100
|
else if (event.type === 'tool_progress') {
|
|
93
101
|
let toolName = 'tool';
|
|
94
102
|
let elapsed = 0;
|
|
103
|
+
let progressCurrent;
|
|
104
|
+
let progressTotal;
|
|
95
105
|
try {
|
|
96
106
|
const parsed = JSON.parse(event.text);
|
|
97
107
|
toolName = parsed.name ?? 'tool';
|
|
98
108
|
elapsed = parsed.elapsed ?? 0;
|
|
109
|
+
progressCurrent = parsed.current;
|
|
110
|
+
progressTotal = parsed.total;
|
|
99
111
|
}
|
|
100
112
|
catch {
|
|
101
113
|
// ignore
|
|
102
114
|
}
|
|
115
|
+
const progressInfo = progressCurrent !== undefined && progressTotal !== undefined
|
|
116
|
+
? ` [${progressCurrent}/${progressTotal}]`
|
|
117
|
+
: '';
|
|
103
118
|
context.metadata({
|
|
104
|
-
title:
|
|
119
|
+
title: `⚡ Claude Code: ${toolName} running ${elapsed > 0 ? `(${elapsed.toFixed(0)}s)` : ''}${progressInfo}...${usageSuffix}`,
|
|
105
120
|
metadata: {
|
|
121
|
+
status: 'running',
|
|
106
122
|
sessionId: event.sessionId,
|
|
107
123
|
type: event.type,
|
|
108
124
|
tool: toolName,
|
|
@@ -113,8 +129,9 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
113
129
|
else if (event.type === 'tool_summary') {
|
|
114
130
|
const summary = event.text.length > 200 ? event.text.slice(0, 200) + '...' : event.text;
|
|
115
131
|
context.metadata({
|
|
116
|
-
title:
|
|
132
|
+
title: `✅ Claude Code: Tool done${usageSuffix}`,
|
|
117
133
|
metadata: {
|
|
134
|
+
status: 'success',
|
|
118
135
|
sessionId: event.sessionId,
|
|
119
136
|
type: event.type,
|
|
120
137
|
summary,
|
|
@@ -124,8 +141,9 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
124
141
|
else if (event.type === 'partial') {
|
|
125
142
|
const delta = event.text.length > 200 ? event.text.slice(0, 200) + '...' : event.text;
|
|
126
143
|
context.metadata({
|
|
127
|
-
title:
|
|
144
|
+
title: `⚡ Claude Code: Writing...${usageSuffix}`,
|
|
128
145
|
metadata: {
|
|
146
|
+
status: 'running',
|
|
129
147
|
sessionId: event.sessionId,
|
|
130
148
|
type: event.type,
|
|
131
149
|
delta,
|
|
@@ -134,12 +152,14 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
134
152
|
}
|
|
135
153
|
else if (event.type === 'error') {
|
|
136
154
|
context.metadata({
|
|
137
|
-
title:
|
|
155
|
+
title: `❌ Claude Code: Error`,
|
|
138
156
|
metadata: {
|
|
157
|
+
status: 'error',
|
|
139
158
|
sessionId: event.sessionId,
|
|
140
159
|
error: event.text.slice(0, 200),
|
|
141
160
|
},
|
|
142
161
|
});
|
|
162
|
+
showToastIfAvailable(context, `Claude Code error: ${event.text.slice(0, 100)}`);
|
|
143
163
|
}
|
|
144
164
|
});
|
|
145
165
|
const costLabel = `$${(result.totalCostUsd ?? 0).toFixed(4)}`;
|
|
@@ -147,15 +167,17 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
147
167
|
const contextWarning = formatContextWarning(result.context);
|
|
148
168
|
if (contextWarning) {
|
|
149
169
|
context.metadata({
|
|
150
|
-
title:
|
|
151
|
-
metadata: { sessionId: result.sessionId, contextWarning },
|
|
170
|
+
title: `⚠️ Claude Code: Context at ${result.context.estimatedContextPercent}% (${turns} turns)`,
|
|
171
|
+
metadata: { status: 'warning', sessionId: result.sessionId, contextWarning },
|
|
152
172
|
});
|
|
173
|
+
showToastIfAvailable(context, `⚠️ Context usage at ${result.context.estimatedContextPercent}% — consider compacting`);
|
|
153
174
|
}
|
|
154
175
|
else {
|
|
155
176
|
context.metadata({
|
|
156
|
-
title:
|
|
157
|
-
metadata: { sessionId: result.sessionId },
|
|
177
|
+
title: `✅ Claude Code: Complete (${turns} turns, ${costLabel})`,
|
|
178
|
+
metadata: { status: 'success', sessionId: result.sessionId },
|
|
158
179
|
});
|
|
180
|
+
showToastIfAvailable(context, `✅ Session complete (${turns} turns, ${costLabel})`);
|
|
159
181
|
}
|
|
160
182
|
let toolOutputs = [];
|
|
161
183
|
if (result.sessionId) {
|
|
@@ -196,29 +218,26 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
196
218
|
config.agent[AGENT_ENGINEER_BUILD] ??= buildEngineerBuildAgentConfig(derivedPrompts);
|
|
197
219
|
},
|
|
198
220
|
tool: {
|
|
199
|
-
|
|
200
|
-
description: '
|
|
201
|
-
'
|
|
221
|
+
explore: tool({
|
|
222
|
+
description: 'Investigate and analyze code without making edits. ' +
|
|
223
|
+
'Read-only exploration of the codebase. ' +
|
|
224
|
+
'Preferred first step before implementation.',
|
|
202
225
|
args: {
|
|
203
226
|
message: tool.schema.string().min(1),
|
|
204
227
|
model: tool.schema
|
|
205
228
|
.enum(['claude-opus-4-6', 'claude-sonnet-4-6', 'claude-sonnet-4-5'])
|
|
206
229
|
.optional(),
|
|
207
230
|
effort: tool.schema.enum(['low', 'medium', 'high', 'max']).default('high'),
|
|
208
|
-
mode: tool.schema.enum(['plan', 'free']).default('free'),
|
|
209
231
|
freshSession: tool.schema.boolean().default(false),
|
|
210
232
|
cwd: tool.schema.string().optional(),
|
|
211
233
|
},
|
|
212
234
|
async execute(args, context) {
|
|
213
|
-
return
|
|
235
|
+
return executeDelegate({ ...args, mode: 'plan' }, context);
|
|
214
236
|
},
|
|
215
237
|
}),
|
|
216
|
-
|
|
217
|
-
description: '
|
|
218
|
-
'
|
|
219
|
-
'The engineer will analyze code without making edits. ' +
|
|
220
|
-
'Auto-creates a session on first call. Resumes the existing session on subsequent calls. ' +
|
|
221
|
-
'Returns the assistant response and current context health snapshot.',
|
|
238
|
+
implement: tool({
|
|
239
|
+
description: 'Implement code changes - can read, edit, and create files. ' +
|
|
240
|
+
'Use after exploration to make changes.',
|
|
222
241
|
args: {
|
|
223
242
|
message: tool.schema.string().min(1),
|
|
224
243
|
model: tool.schema
|
|
@@ -229,35 +248,12 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
229
248
|
cwd: tool.schema.string().optional(),
|
|
230
249
|
},
|
|
231
250
|
async execute(args, context) {
|
|
232
|
-
return
|
|
251
|
+
return executeDelegate({ ...args, mode: 'free' }, context);
|
|
233
252
|
},
|
|
234
253
|
}),
|
|
235
|
-
|
|
236
|
-
description: '
|
|
237
|
-
'
|
|
238
|
-
'The engineer can read, edit, and create files. ' +
|
|
239
|
-
'Auto-creates a session on first call. Resumes the existing session on subsequent calls. ' +
|
|
240
|
-
'Returns the assistant response and current context health snapshot. ' +
|
|
241
|
-
'Prefer claude-opus-4-6 (default) for most coding work; use a Sonnet model for faster/lighter tasks. ' +
|
|
242
|
-
'Prefer effort "high" (default) for most work; use "medium" for lighter tasks and "max" for especially hard problems.',
|
|
243
|
-
args: {
|
|
244
|
-
message: tool.schema.string().min(1),
|
|
245
|
-
model: tool.schema
|
|
246
|
-
.enum(['claude-opus-4-6', 'claude-sonnet-4-6', 'claude-sonnet-4-5'])
|
|
247
|
-
.optional(),
|
|
248
|
-
effort: tool.schema.enum(['low', 'medium', 'high', 'max']).default('high'),
|
|
249
|
-
freshSession: tool.schema.boolean().default(false),
|
|
250
|
-
cwd: tool.schema.string().optional(),
|
|
251
|
-
},
|
|
252
|
-
async execute(args, context) {
|
|
253
|
-
return executeEngineerSend({ ...args, mode: 'free' }, context);
|
|
254
|
-
},
|
|
255
|
-
}),
|
|
256
|
-
engineer_compact: tool({
|
|
257
|
-
description: 'Compact the active Claude Code session to reclaim context space. ' +
|
|
258
|
-
'Sends /compact to the session, which compresses prior conversation while preserving state. ' +
|
|
259
|
-
'Use before clearing when context is high but the session still has useful state. ' +
|
|
260
|
-
'Fails if there is no active session.',
|
|
254
|
+
compact_context: tool({
|
|
255
|
+
description: 'Compress session history to reclaim context window space. ' +
|
|
256
|
+
'Preserves state while reducing token usage.',
|
|
261
257
|
args: {
|
|
262
258
|
cwd: tool.schema.string().optional(),
|
|
263
259
|
},
|
|
@@ -269,9 +265,12 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
269
265
|
const contextWarning = formatContextWarning(snap);
|
|
270
266
|
context.metadata({
|
|
271
267
|
title: contextWarning
|
|
272
|
-
?
|
|
273
|
-
:
|
|
274
|
-
metadata: {
|
|
268
|
+
? `⚠️ Claude Code: Compacted — context at ${snap.estimatedContextPercent}%`
|
|
269
|
+
: `✅ Claude Code: Compacted (${snap.totalTurns} turns, $${(snap.totalCostUsd ?? 0).toFixed(4)})`,
|
|
270
|
+
metadata: {
|
|
271
|
+
status: contextWarning ? 'warning' : 'success',
|
|
272
|
+
sessionId: result.sessionId,
|
|
273
|
+
},
|
|
275
274
|
});
|
|
276
275
|
return JSON.stringify({
|
|
277
276
|
sessionId: result.sessionId,
|
|
@@ -284,13 +283,27 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
284
283
|
},
|
|
285
284
|
}),
|
|
286
285
|
git_diff: tool({
|
|
287
|
-
description: '
|
|
286
|
+
description: 'Show diff of uncommitted changes. ' +
|
|
287
|
+
'Use paths to filter to specific files/dirs. ' +
|
|
288
|
+
'Use staged=true to see staged changes. ' +
|
|
289
|
+
'Use ref to compare against a branch/tag/commit (e.g., ref="main").',
|
|
288
290
|
args: {
|
|
289
|
-
|
|
291
|
+
paths: tool.schema.string().array().optional(),
|
|
292
|
+
staged: tool.schema.boolean().optional(),
|
|
293
|
+
ref: tool.schema.string().optional(),
|
|
290
294
|
},
|
|
291
|
-
async execute(
|
|
292
|
-
annotateToolRun(context, 'Running git diff', {
|
|
293
|
-
|
|
295
|
+
async execute(args, context) {
|
|
296
|
+
annotateToolRun(context, 'Running git diff', {
|
|
297
|
+
paths: args.paths,
|
|
298
|
+
staged: args.staged,
|
|
299
|
+
ref: args.ref,
|
|
300
|
+
});
|
|
301
|
+
const paths = args.paths?.filter((p) => p !== undefined);
|
|
302
|
+
const result = await services.manager.gitDiff({
|
|
303
|
+
paths,
|
|
304
|
+
staged: args.staged,
|
|
305
|
+
ref: args.ref,
|
|
306
|
+
});
|
|
294
307
|
return JSON.stringify(result, null, 2);
|
|
295
308
|
},
|
|
296
309
|
}),
|
|
@@ -298,7 +311,6 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
298
311
|
description: 'Stage all changes and commit with the given message.',
|
|
299
312
|
args: {
|
|
300
313
|
message: tool.schema.string().min(1),
|
|
301
|
-
cwd: tool.schema.string().optional(),
|
|
302
314
|
},
|
|
303
315
|
async execute(args, context) {
|
|
304
316
|
annotateToolRun(context, 'Committing changes', {
|
|
@@ -309,19 +321,39 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
309
321
|
},
|
|
310
322
|
}),
|
|
311
323
|
git_reset: tool({
|
|
312
|
-
description: '
|
|
313
|
-
args: {
|
|
314
|
-
cwd: tool.schema.string().optional(),
|
|
315
|
-
},
|
|
324
|
+
description: 'Discard all uncommitted changes: runs git reset --hard HEAD and git clean -fd.',
|
|
325
|
+
args: {},
|
|
316
326
|
async execute(_args, context) {
|
|
317
327
|
annotateToolRun(context, 'Resetting working directory', {});
|
|
318
328
|
const result = await services.manager.gitReset();
|
|
319
329
|
return JSON.stringify(result, null, 2);
|
|
320
330
|
},
|
|
321
331
|
}),
|
|
322
|
-
|
|
323
|
-
description: '
|
|
324
|
-
'
|
|
332
|
+
git_status: tool({
|
|
333
|
+
description: 'Show working tree status — lists changed files in short format. ' +
|
|
334
|
+
'Returns isClean=true if nothing changed.',
|
|
335
|
+
args: {},
|
|
336
|
+
async execute(_args, context) {
|
|
337
|
+
annotateToolRun(context, 'Checking git status', {});
|
|
338
|
+
const result = await services.manager.gitStatus();
|
|
339
|
+
return JSON.stringify(result, null, 2);
|
|
340
|
+
},
|
|
341
|
+
}),
|
|
342
|
+
git_log: tool({
|
|
343
|
+
description: 'Show recent commits in short format. ' +
|
|
344
|
+
'Default shows last 5 commits. Use count to change.',
|
|
345
|
+
args: {
|
|
346
|
+
count: tool.schema.number().optional(),
|
|
347
|
+
},
|
|
348
|
+
async execute(args, context) {
|
|
349
|
+
annotateToolRun(context, 'Fetching git log', { count: args.count });
|
|
350
|
+
const result = await services.manager.gitLog(args.count ?? 5);
|
|
351
|
+
return result;
|
|
352
|
+
},
|
|
353
|
+
}),
|
|
354
|
+
clear_session: tool({
|
|
355
|
+
description: 'Clear the active session to start fresh. ' +
|
|
356
|
+
'Use when context is full or starting a new task.',
|
|
325
357
|
args: {
|
|
326
358
|
cwd: tool.schema.string().optional(),
|
|
327
359
|
reason: tool.schema.string().optional(),
|
|
@@ -334,8 +366,8 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
334
366
|
return JSON.stringify({ clearedSessionId: clearedId });
|
|
335
367
|
},
|
|
336
368
|
}),
|
|
337
|
-
|
|
338
|
-
description: '
|
|
369
|
+
session_health: tool({
|
|
370
|
+
description: 'Check session health metrics: context usage %, turn count, cost, and session ID.',
|
|
339
371
|
args: {
|
|
340
372
|
cwd: tool.schema.string().optional(),
|
|
341
373
|
},
|
|
@@ -351,9 +383,8 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
351
383
|
}, null, 2);
|
|
352
384
|
},
|
|
353
385
|
}),
|
|
354
|
-
|
|
355
|
-
description: 'List
|
|
356
|
-
'When sessionId is provided, returns both SDK transcript and local events.',
|
|
386
|
+
list_transcripts: tool({
|
|
387
|
+
description: 'List available session transcripts or inspect a specific transcript by ID.',
|
|
357
388
|
args: {
|
|
358
389
|
cwd: tool.schema.string().optional(),
|
|
359
390
|
sessionId: tool.schema.string().optional(),
|
|
@@ -375,8 +406,8 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
375
406
|
return JSON.stringify(sessions, null, 2);
|
|
376
407
|
},
|
|
377
408
|
}),
|
|
378
|
-
|
|
379
|
-
description: 'List persistent manager run
|
|
409
|
+
list_history: tool({
|
|
410
|
+
description: 'List persistent run records from the manager or inspect a specific run.',
|
|
380
411
|
args: {
|
|
381
412
|
cwd: tool.schema.string().optional(),
|
|
382
413
|
runId: tool.schema.string().optional(),
|
|
@@ -482,8 +513,12 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
482
513
|
},
|
|
483
514
|
};
|
|
484
515
|
};
|
|
485
|
-
function annotateToolRun(context, title, metadata) {
|
|
486
|
-
|
|
516
|
+
function annotateToolRun(context, title, metadata, status) {
|
|
517
|
+
const emoji = status ? `${formatStatusEmoji(status)} ` : '';
|
|
518
|
+
context.metadata({
|
|
519
|
+
title: `${emoji}${title}`,
|
|
520
|
+
metadata: { ...metadata, ...(status ? { status } : {}) },
|
|
521
|
+
});
|
|
487
522
|
}
|
|
488
523
|
function formatLiveUsage(turns, cost) {
|
|
489
524
|
if (turns === undefined && cost === undefined) {
|
|
@@ -491,10 +526,10 @@ function formatLiveUsage(turns, cost) {
|
|
|
491
526
|
}
|
|
492
527
|
const parts = [];
|
|
493
528
|
if (turns !== undefined) {
|
|
494
|
-
parts.push(
|
|
529
|
+
parts.push(`🔄 ${turns} turns`);
|
|
495
530
|
}
|
|
496
531
|
if (cost !== undefined) {
|
|
497
|
-
parts.push(
|
|
532
|
+
parts.push(`💰 $${cost.toFixed(4)}`);
|
|
498
533
|
}
|
|
499
534
|
return ` (${parts.join(', ')})`;
|
|
500
535
|
}
|
|
@@ -514,3 +549,47 @@ function formatContextWarning(context) {
|
|
|
514
549
|
.replace('{turns}', String(totalTurns))
|
|
515
550
|
.replace('{cost}', totalCostUsd.toFixed(2));
|
|
516
551
|
}
|
|
552
|
+
function formatStatusEmoji(status) {
|
|
553
|
+
switch (status) {
|
|
554
|
+
case 'running':
|
|
555
|
+
return '⚡';
|
|
556
|
+
case 'success':
|
|
557
|
+
return '✅';
|
|
558
|
+
case 'error':
|
|
559
|
+
return '❌';
|
|
560
|
+
case 'warning':
|
|
561
|
+
return '⚠️';
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
function formatToolOutputPreview(text) {
|
|
565
|
+
const lower = text.toLowerCase();
|
|
566
|
+
let prefix;
|
|
567
|
+
if (lower.includes('"tool":"read"') ||
|
|
568
|
+
lower.includes('"name":"read"') ||
|
|
569
|
+
lower.includes('file contents')) {
|
|
570
|
+
prefix = '↳ Read: ';
|
|
571
|
+
}
|
|
572
|
+
else if (lower.includes('"tool":"grep"') ||
|
|
573
|
+
lower.includes('"name":"grep"') ||
|
|
574
|
+
lower.includes('matches found')) {
|
|
575
|
+
prefix = '↳ Found: ';
|
|
576
|
+
}
|
|
577
|
+
else if (lower.includes('"tool":"write"') ||
|
|
578
|
+
lower.includes('"name":"write"') ||
|
|
579
|
+
lower.includes('"tool":"edit"') ||
|
|
580
|
+
lower.includes('"name":"edit"') ||
|
|
581
|
+
lower.includes('file written') ||
|
|
582
|
+
lower.includes('file updated')) {
|
|
583
|
+
prefix = '↳ Wrote: ';
|
|
584
|
+
}
|
|
585
|
+
else {
|
|
586
|
+
prefix = '↳ Result: ';
|
|
587
|
+
}
|
|
588
|
+
const snippet = text.replace(/\s+/g, ' ').trim();
|
|
589
|
+
const truncated = snippet.length > 60 ? snippet.slice(0, 60) + '...' : snippet;
|
|
590
|
+
return `${prefix}${truncated}`;
|
|
591
|
+
}
|
|
592
|
+
function showToastIfAvailable(context, message) {
|
|
593
|
+
const ctx = context;
|
|
594
|
+
ctx.client?.tui?.showToast?.(message);
|
|
595
|
+
}
|
package/dist/prompts/registry.js
CHANGED
|
@@ -90,9 +90,11 @@ export const managerPromptRegistry = {
|
|
|
90
90
|
'After each delegation:',
|
|
91
91
|
'1. git_diff — read the FULL diff. Check for unintended changes, missing tests,',
|
|
92
92
|
' style violations.',
|
|
93
|
-
'2.
|
|
94
|
-
'3.
|
|
95
|
-
'4. If
|
|
93
|
+
'2. git_status — check what files changed (quick overview)',
|
|
94
|
+
'3. git_log -n 5 — see recent commits (understand context)',
|
|
95
|
+
'4. If correct: spawn `engineer_build` to run tests/lint/typecheck.',
|
|
96
|
+
'5. If tests pass: git_commit to checkpoint.',
|
|
97
|
+
'6. If wrong: spawn `engineer_build` with a specific correction.',
|
|
96
98
|
' On second failure: git_reset and rewrite the prompt from scratch.',
|
|
97
99
|
' Never send three corrections for the same problem.',
|
|
98
100
|
'',
|
|
@@ -116,7 +118,9 @@ export const managerPromptRegistry = {
|
|
|
116
118
|
'## Tools reference',
|
|
117
119
|
'todowrite / todoread — track multi-step work',
|
|
118
120
|
'question — ask the user structured questions with options',
|
|
119
|
-
'git_diff — review
|
|
121
|
+
'git_diff — review changes (filter with paths, staged, ref args)',
|
|
122
|
+
'git_status — quick overview of changed files',
|
|
123
|
+
'git_log — recent commits (default: last 5)',
|
|
120
124
|
'git_commit — stage all + commit',
|
|
121
125
|
'git_reset — hard reset + clean (destructive)',
|
|
122
126
|
'approval_policy — view tool approval rules',
|
|
@@ -148,13 +152,13 @@ export const managerPromptRegistry = {
|
|
|
148
152
|
'- Do NOT implement changes yourself — investigation only.',
|
|
149
153
|
'',
|
|
150
154
|
'## Behavior',
|
|
151
|
-
'- Send the objective to the engineer using
|
|
155
|
+
'- Send the objective to the engineer using explore.',
|
|
152
156
|
"- Return the engineer's response verbatim. Do not summarize.",
|
|
153
|
-
'- Use freshSession:true on
|
|
157
|
+
'- Use freshSession:true on explore when the task is unrelated to prior work.',
|
|
154
158
|
'',
|
|
155
159
|
'## Context management',
|
|
156
|
-
'- Check
|
|
157
|
-
'- Under 50%: proceed. Over 70%:
|
|
160
|
+
'- Check session_health before sending.',
|
|
161
|
+
'- Under 50%: proceed. Over 70%: compact_context. Over 85%: clear_session.',
|
|
158
162
|
'',
|
|
159
163
|
'## Model selection',
|
|
160
164
|
'- claude-opus-4-6 + high: complex analysis (default).',
|
|
@@ -191,13 +195,13 @@ export const managerPromptRegistry = {
|
|
|
191
195
|
'- Do NOT implement changes yourself — investigation only.',
|
|
192
196
|
'',
|
|
193
197
|
'## Behavior',
|
|
194
|
-
'- Send the objective to the engineer using
|
|
198
|
+
'- Send the objective to the engineer using implement.',
|
|
195
199
|
"- Return the engineer's response verbatim. Do not summarize.",
|
|
196
|
-
'- Use freshSession:true on
|
|
200
|
+
'- Use freshSession:true on implement when the task is unrelated to prior work.',
|
|
197
201
|
'',
|
|
198
202
|
'## Context management',
|
|
199
|
-
'- Check
|
|
200
|
-
'- Under 50%: proceed. Over 70%:
|
|
203
|
+
'- Check session_health before sending.',
|
|
204
|
+
'- Under 50%: proceed. Over 70%: compact_context. Over 85%: clear_session.',
|
|
201
205
|
'',
|
|
202
206
|
'## Model selection',
|
|
203
207
|
'- claude-opus-4-6 + high: most coding tasks (default).',
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Options, type Query, type SDKSessionInfo, type SessionMessage, type SettingSource } from '@anthropic-ai/claude-agent-sdk';
|
|
2
|
+
import type { ClaudeCapabilitySnapshot, ClaudeSessionEvent, ClaudeSessionRunResult, ClaudeSessionSummary, ClaudeSessionTranscriptMessage, RunClaudeSessionInput } from '../types/contracts.js';
|
|
3
|
+
import type { ToolApprovalManager } from './tool-approval-manager.js';
|
|
4
|
+
export type ClaudeSessionEventHandler = (event: ClaudeSessionEvent) => void | Promise<void>;
|
|
5
|
+
interface ClaudeAgentSdkFacade {
|
|
6
|
+
query(params: {
|
|
7
|
+
prompt: string;
|
|
8
|
+
options?: Options;
|
|
9
|
+
}): Query;
|
|
10
|
+
listSessions(options?: {
|
|
11
|
+
dir?: string;
|
|
12
|
+
}): Promise<SDKSessionInfo[]>;
|
|
13
|
+
getSessionMessages(sessionId: string, options?: {
|
|
14
|
+
dir?: string;
|
|
15
|
+
}): Promise<SessionMessage[]>;
|
|
16
|
+
}
|
|
17
|
+
export declare class ClaudeAgentSdkAdapter {
|
|
18
|
+
private readonly sdkFacade;
|
|
19
|
+
private readonly approvalManager?;
|
|
20
|
+
constructor(sdkFacade?: ClaudeAgentSdkFacade, approvalManager?: ToolApprovalManager | undefined);
|
|
21
|
+
runSession(input: RunClaudeSessionInput, onEvent?: ClaudeSessionEventHandler): Promise<ClaudeSessionRunResult>;
|
|
22
|
+
listSavedSessions(cwd?: string): Promise<ClaudeSessionSummary[]>;
|
|
23
|
+
getTranscript(sessionId: string, cwd?: string): Promise<ClaudeSessionTranscriptMessage[]>;
|
|
24
|
+
probeCapabilities(cwd: string, settingSources?: SettingSource[]): Promise<ClaudeCapabilitySnapshot>;
|
|
25
|
+
private buildOptions;
|
|
26
|
+
}
|
|
27
|
+
export {};
|