@doingdev/opencode-claude-manager-plugin 0.1.44 → 0.1.46
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/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Plugin } from '@opencode-ai/plugin';
|
|
2
2
|
import { ClaudeManagerPlugin } from './plugin/claude-manager.plugin.js';
|
|
3
|
-
export type { ClaudeCapabilitySnapshot, ClaudeSessionRunResult, ClaudeSessionSummary, ClaudeSessionTranscriptMessage, ManagerPromptRegistry, RunClaudeSessionInput, SessionContextSnapshot, GitDiffResult, GitOperationResult, PersistentRunRecord, PersistentRunResult,
|
|
3
|
+
export type { ClaudeCapabilitySnapshot, ClaudeSessionRunResult, ClaudeSessionSummary, ClaudeSessionTranscriptMessage, ManagerPromptRegistry, RunClaudeSessionInput, SessionContextSnapshot, GitDiffResult, GitOperationResult, PersistentRunRecord, PersistentRunResult, ContextWarningLevel, SessionMode, LiveTailEvent, ToolOutputPreview, ToolApprovalRule, ToolApprovalPolicy, ToolApprovalDecision, } from './types/contracts.js';
|
|
4
4
|
export { SessionLiveTailer } from './claude/session-live-tailer.js';
|
|
5
5
|
export { ClaudeManagerPlugin };
|
|
6
6
|
export declare const plugin: Plugin;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ClaudeSessionEvent, ClaudeSessionRunResult, PersistentRunRecord, PersistentRunResult, SessionContextSnapshot, GitDiffResult, GitOperationResult } from '../types/contracts.js';
|
|
2
2
|
import type { ClaudeSessionEventHandler } from '../claude/claude-agent-sdk-adapter.js';
|
|
3
3
|
import type { FileRunStateStore } from '../state/file-run-state-store.js';
|
|
4
4
|
import type { TranscriptStore } from '../state/transcript-store.js';
|
|
@@ -12,10 +12,6 @@ export declare class PersistentManager {
|
|
|
12
12
|
private readonly stateStore;
|
|
13
13
|
private readonly contextTracker;
|
|
14
14
|
private readonly transcriptStore;
|
|
15
|
-
private static readonly slotCounts;
|
|
16
|
-
private static readonly slotWaiters;
|
|
17
|
-
private static readonly runningTaskList;
|
|
18
|
-
private static readonly SLOT_MAXIMA;
|
|
19
15
|
constructor(sessionController: SessionController, gitOps: GitOperations, stateStore: FileRunStateStore, contextTracker: ContextTracker, transcriptStore: TranscriptStore);
|
|
20
16
|
/**
|
|
21
17
|
* Send a message to the persistent Claude Code session.
|
|
@@ -65,25 +61,9 @@ export declare class PersistentManager {
|
|
|
65
61
|
*/
|
|
66
62
|
gitReset(): Promise<GitOperationResult>;
|
|
67
63
|
/**
|
|
68
|
-
* Get current session status
|
|
64
|
+
* Get current session status and context health.
|
|
69
65
|
*/
|
|
70
|
-
getStatus():
|
|
71
|
-
/**
|
|
72
|
-
* Acquire a concurrency slot. Blocks if at capacity (implement=1, verify=5, explore=unlimited).
|
|
73
|
-
*/
|
|
74
|
-
acquireSlot(slotType: AgentSlotType, taskDescription?: string): Promise<void>;
|
|
75
|
-
/**
|
|
76
|
-
* Release a concurrency slot. Wakes the next waiter if any.
|
|
77
|
-
*/
|
|
78
|
-
releaseSlot(slotType: AgentSlotType, taskDescription?: string): void;
|
|
79
|
-
/**
|
|
80
|
-
* Get current slot usage across all agent types.
|
|
81
|
-
*/
|
|
82
|
-
getSlotStatus(): SlotStatus;
|
|
83
|
-
/**
|
|
84
|
-
* List all currently running tasks with their slot types.
|
|
85
|
-
*/
|
|
86
|
-
listRunningTasks(): RunningTask[];
|
|
66
|
+
getStatus(): SessionContextSnapshot;
|
|
87
67
|
/**
|
|
88
68
|
* Clear the active session. Next send creates a fresh one.
|
|
89
69
|
*/
|
|
@@ -5,19 +5,6 @@ export class PersistentManager {
|
|
|
5
5
|
stateStore;
|
|
6
6
|
contextTracker;
|
|
7
7
|
transcriptStore;
|
|
8
|
-
// --- Slot tracking (static — shared across all instances) ---
|
|
9
|
-
static slotCounts = new Map([
|
|
10
|
-
['implement', 0],
|
|
11
|
-
['verify', 0],
|
|
12
|
-
['explore', 0],
|
|
13
|
-
]);
|
|
14
|
-
static slotWaiters = new Map();
|
|
15
|
-
static runningTaskList = [];
|
|
16
|
-
static SLOT_MAXIMA = {
|
|
17
|
-
implement: 1,
|
|
18
|
-
verify: 5,
|
|
19
|
-
explore: Infinity,
|
|
20
|
-
};
|
|
21
8
|
constructor(sessionController, gitOps, stateStore, contextTracker, transcriptStore) {
|
|
22
9
|
this.sessionController = sessionController;
|
|
23
10
|
this.gitOps = gitOps;
|
|
@@ -76,90 +63,10 @@ export class PersistentManager {
|
|
|
76
63
|
return this.gitOps.resetHard();
|
|
77
64
|
}
|
|
78
65
|
/**
|
|
79
|
-
* Get current session status
|
|
66
|
+
* Get current session status and context health.
|
|
80
67
|
*/
|
|
81
68
|
getStatus() {
|
|
82
|
-
return
|
|
83
|
-
context: this.sessionController.getContextSnapshot(),
|
|
84
|
-
slotStatus: this.getSlotStatus(),
|
|
85
|
-
runningTasks: this.listRunningTasks(),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Acquire a concurrency slot. Blocks if at capacity (implement=1, verify=5, explore=unlimited).
|
|
90
|
-
*/
|
|
91
|
-
async acquireSlot(slotType, taskDescription) {
|
|
92
|
-
const max = PersistentManager.SLOT_MAXIMA[slotType];
|
|
93
|
-
const current = PersistentManager.slotCounts.get(slotType) ?? 0;
|
|
94
|
-
if (current < max) {
|
|
95
|
-
PersistentManager.slotCounts.set(slotType, current + 1);
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
// At capacity — wait for a slot to be transferred by releaseSlot
|
|
99
|
-
await new Promise((resolve) => {
|
|
100
|
-
let waiters = PersistentManager.slotWaiters.get(slotType);
|
|
101
|
-
if (!waiters) {
|
|
102
|
-
waiters = [];
|
|
103
|
-
PersistentManager.slotWaiters.set(slotType, waiters);
|
|
104
|
-
}
|
|
105
|
-
waiters.push(resolve);
|
|
106
|
-
});
|
|
107
|
-
// Slot was transferred — count stays the same
|
|
108
|
-
}
|
|
109
|
-
if (taskDescription) {
|
|
110
|
-
PersistentManager.runningTaskList.push({
|
|
111
|
-
slotType,
|
|
112
|
-
task: taskDescription,
|
|
113
|
-
startedAt: new Date().toISOString(),
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Release a concurrency slot. Wakes the next waiter if any.
|
|
119
|
-
*/
|
|
120
|
-
releaseSlot(slotType, taskDescription) {
|
|
121
|
-
if (taskDescription) {
|
|
122
|
-
const idx = PersistentManager.runningTaskList.findIndex((t) => t.slotType === slotType && t.task === taskDescription);
|
|
123
|
-
if (idx !== -1) {
|
|
124
|
-
PersistentManager.runningTaskList.splice(idx, 1);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
const waiters = PersistentManager.slotWaiters.get(slotType);
|
|
128
|
-
if (waiters && waiters.length > 0) {
|
|
129
|
-
// Transfer the slot directly to the next waiter (don't decrement count)
|
|
130
|
-
const next = waiters.shift();
|
|
131
|
-
next();
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
const current = PersistentManager.slotCounts.get(slotType) ?? 0;
|
|
135
|
-
if (current > 0) {
|
|
136
|
-
PersistentManager.slotCounts.set(slotType, current - 1);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Get current slot usage across all agent types.
|
|
142
|
-
*/
|
|
143
|
-
getSlotStatus() {
|
|
144
|
-
return {
|
|
145
|
-
implement: {
|
|
146
|
-
used: PersistentManager.slotCounts.get('implement') ?? 0,
|
|
147
|
-
max: PersistentManager.SLOT_MAXIMA.implement,
|
|
148
|
-
},
|
|
149
|
-
verify: {
|
|
150
|
-
used: PersistentManager.slotCounts.get('verify') ?? 0,
|
|
151
|
-
max: PersistentManager.SLOT_MAXIMA.verify,
|
|
152
|
-
},
|
|
153
|
-
explore: {
|
|
154
|
-
used: PersistentManager.slotCounts.get('explore') ?? 0,
|
|
155
|
-
},
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* List all currently running tasks with their slot types.
|
|
160
|
-
*/
|
|
161
|
-
listRunningTasks() {
|
|
162
|
-
return [...PersistentManager.runningTaskList];
|
|
69
|
+
return this.sessionController.getContextSnapshot();
|
|
163
70
|
}
|
|
164
71
|
/**
|
|
165
72
|
* Clear the active session. Next send creates a fresh one.
|
|
@@ -10,8 +10,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
10
10
|
if (args.freshSession) {
|
|
11
11
|
await wrapperServices.manager.clearSession();
|
|
12
12
|
}
|
|
13
|
-
const
|
|
14
|
-
const hasActiveSession = managerStatus.context.sessionId !== null;
|
|
13
|
+
const hasActiveSession = wrapperServices.manager.getStatus().sessionId !== null;
|
|
15
14
|
const promptPreview = args.message.length > 100 ? args.message.slice(0, 100) + '...' : args.message;
|
|
16
15
|
context.metadata({
|
|
17
16
|
title: hasActiveSession
|
|
@@ -19,7 +18,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
19
18
|
: '⚡ Claude Code: Initializing...',
|
|
20
19
|
metadata: {
|
|
21
20
|
status: 'running',
|
|
22
|
-
sessionId:
|
|
21
|
+
sessionId: wrapperServices.manager.getStatus().sessionId,
|
|
23
22
|
prompt: promptPreview,
|
|
24
23
|
},
|
|
25
24
|
});
|
|
@@ -236,14 +235,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
236
235
|
sessionSystemPrompt: tool.schema.string().optional(),
|
|
237
236
|
},
|
|
238
237
|
async execute(args, context) {
|
|
239
|
-
|
|
240
|
-
await services.manager.acquireSlot('explore', taskDesc);
|
|
241
|
-
try {
|
|
242
|
-
return await executeDelegate({ ...args, mode: 'plan', wrapperType: 'explore' }, context);
|
|
243
|
-
}
|
|
244
|
-
finally {
|
|
245
|
-
services.manager.releaseSlot('explore', taskDesc);
|
|
246
|
-
}
|
|
238
|
+
return executeDelegate({ ...args, mode: 'plan', wrapperType: 'explore' }, context);
|
|
247
239
|
},
|
|
248
240
|
}),
|
|
249
241
|
verify: tool({
|
|
@@ -259,14 +251,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
259
251
|
sessionSystemPrompt: tool.schema.string().optional(),
|
|
260
252
|
},
|
|
261
253
|
async execute(args, context) {
|
|
262
|
-
|
|
263
|
-
await services.manager.acquireSlot('verify', taskDesc);
|
|
264
|
-
try {
|
|
265
|
-
return await executeDelegate({ ...args, mode: 'free', wrapperType: 'engineer_verify' }, context);
|
|
266
|
-
}
|
|
267
|
-
finally {
|
|
268
|
-
services.manager.releaseSlot('verify', taskDesc);
|
|
269
|
-
}
|
|
254
|
+
return executeDelegate({ ...args, mode: 'free', wrapperType: 'engineer_verify' }, context);
|
|
270
255
|
},
|
|
271
256
|
}),
|
|
272
257
|
implement: tool({
|
|
@@ -282,14 +267,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
282
267
|
sessionSystemPrompt: tool.schema.string().optional(),
|
|
283
268
|
},
|
|
284
269
|
async execute(args, context) {
|
|
285
|
-
|
|
286
|
-
await services.manager.acquireSlot('implement', taskDesc);
|
|
287
|
-
try {
|
|
288
|
-
return await executeDelegate({ ...args, mode: 'free', wrapperType: 'implement' }, context);
|
|
289
|
-
}
|
|
290
|
-
finally {
|
|
291
|
-
services.manager.releaseSlot('implement', taskDesc);
|
|
292
|
-
}
|
|
270
|
+
return executeDelegate({ ...args, mode: 'free', wrapperType: 'implement' }, context);
|
|
293
271
|
},
|
|
294
272
|
}),
|
|
295
273
|
compact_context: tool({
|
|
@@ -303,11 +281,11 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
303
281
|
annotateToolRun(context, 'Compacting session', {});
|
|
304
282
|
const result = await wrapperServices.manager.compactSession(context.worktree);
|
|
305
283
|
const snap = wrapperServices.manager.getStatus();
|
|
306
|
-
const contextWarning = formatContextWarning(snap
|
|
284
|
+
const contextWarning = formatContextWarning(snap);
|
|
307
285
|
context.metadata({
|
|
308
286
|
title: contextWarning
|
|
309
|
-
? `⚠️ Claude Code: Compacted — context at ${snap.
|
|
310
|
-
: `✅ Claude Code: Compacted (${snap.
|
|
287
|
+
? `⚠️ Claude Code: Compacted — context at ${snap.estimatedContextPercent}%`
|
|
288
|
+
: `✅ Claude Code: Compacted (${snap.totalTurns} turns, $${(snap.totalCostUsd ?? 0).toFixed(4)})`,
|
|
311
289
|
metadata: {
|
|
312
290
|
status: contextWarning ? 'warning' : 'success',
|
|
313
291
|
sessionId: result.sessionId,
|
|
@@ -318,7 +296,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
318
296
|
finalText: result.finalText,
|
|
319
297
|
turns: result.turns,
|
|
320
298
|
totalCostUsd: result.totalCostUsd,
|
|
321
|
-
context: snap
|
|
299
|
+
context: snap,
|
|
322
300
|
contextWarning,
|
|
323
301
|
}, null, 2);
|
|
324
302
|
},
|
|
@@ -419,10 +397,10 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
419
397
|
const status = wrapperServices.manager.getStatus();
|
|
420
398
|
return JSON.stringify({
|
|
421
399
|
...status,
|
|
422
|
-
transcriptFile: status.
|
|
423
|
-
? `.claude-manager/transcripts/${status.
|
|
400
|
+
transcriptFile: status.sessionId
|
|
401
|
+
? `.claude-manager/transcripts/${status.sessionId}.json`
|
|
424
402
|
: null,
|
|
425
|
-
contextWarning: formatContextWarning(status
|
|
403
|
+
contextWarning: formatContextWarning(status),
|
|
426
404
|
}, null, 2);
|
|
427
405
|
},
|
|
428
406
|
}),
|
package/dist/prompts/registry.js
CHANGED
|
@@ -158,25 +158,16 @@ export const managerPromptRegistry = {
|
|
|
158
158
|
' On second failure: git_reset and rewrite the prompt from scratch.',
|
|
159
159
|
' Never send three corrections for the same problem.',
|
|
160
160
|
'',
|
|
161
|
-
'##
|
|
162
|
-
'- `engineer_explore
|
|
163
|
-
'
|
|
164
|
-
'- `engineer_implement
|
|
165
|
-
'',
|
|
166
|
-
'
|
|
167
|
-
|
|
168
|
-
'
|
|
169
|
-
'
|
|
170
|
-
|
|
171
|
-
'- Before committing, run engineer_verify on the changed files to catch issues early.',
|
|
172
|
-
'- When blocked on one engineer (waiting for implement), run other explorations in parallel.',
|
|
173
|
-
"- Check getStatus().slotStatus before spawning — know what's running and what's available.",
|
|
174
|
-
'',
|
|
175
|
-
'## Available parallel agents',
|
|
176
|
-
'You have access to:',
|
|
177
|
-
'- Multiple engineer_explore agents (unlimited, read-only, different angles)',
|
|
178
|
-
'- Multiple engineer_verify agents (up to 5, verification commands)',
|
|
179
|
-
'- One engineer_implement at a time (makes changes to worktree)',
|
|
161
|
+
'## Engineers (via the Task tool)',
|
|
162
|
+
'- `engineer_explore` — read-only investigation. Use for: exploring unfamiliar code,',
|
|
163
|
+
' mapping dependencies, analyzing impact, asking "how does X work?"',
|
|
164
|
+
'- `engineer_implement` — implementation. Use for: all code changes, test runs, fixes.',
|
|
165
|
+
'- `engineer_verify` — verification. Use for: running tests, lint, typecheck, build.',
|
|
166
|
+
' Use after implementation to confirm correctness.',
|
|
167
|
+
'- You may run MULTIPLE `engineer_explore` agents in parallel for independent investigations.',
|
|
168
|
+
'- You may run MULTIPLE `engineer_verify` agents in parallel for independent verification tasks.',
|
|
169
|
+
'- Only run ONE `engineer_implement` agent at a time — it makes changes to the worktree.',
|
|
170
|
+
'- Coordinate so that only one implement/verify runs at a time to avoid git conflicts.',
|
|
180
171
|
'',
|
|
181
172
|
'## Context efficiency',
|
|
182
173
|
'- Use `engineer_explore` for broad exploration so your own context stays clean.',
|
|
@@ -98,30 +98,6 @@ export interface SessionContextSnapshot {
|
|
|
98
98
|
warningLevel: ContextWarningLevel;
|
|
99
99
|
compactionCount: number;
|
|
100
100
|
}
|
|
101
|
-
export type AgentSlotType = 'implement' | 'verify' | 'explore';
|
|
102
|
-
export interface RunningTask {
|
|
103
|
-
slotType: AgentSlotType;
|
|
104
|
-
task: string;
|
|
105
|
-
startedAt: string;
|
|
106
|
-
}
|
|
107
|
-
export interface SlotStatus {
|
|
108
|
-
implement: {
|
|
109
|
-
used: number;
|
|
110
|
-
max: number;
|
|
111
|
-
};
|
|
112
|
-
verify: {
|
|
113
|
-
used: number;
|
|
114
|
-
max: number;
|
|
115
|
-
};
|
|
116
|
-
explore: {
|
|
117
|
-
used: number;
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
export interface ManagerStatus {
|
|
121
|
-
context: SessionContextSnapshot;
|
|
122
|
-
slotStatus: SlotStatus;
|
|
123
|
-
runningTasks: RunningTask[];
|
|
124
|
-
}
|
|
125
101
|
export interface GitDiffResult {
|
|
126
102
|
hasDiff: boolean;
|
|
127
103
|
diffText: string;
|