@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
package/README.md
CHANGED
|
@@ -53,15 +53,15 @@ If you are testing locally, point OpenCode at the local package or plugin file u
|
|
|
53
53
|
|
|
54
54
|
### Engineer session
|
|
55
55
|
|
|
56
|
-
- `
|
|
56
|
+
- `explore` — investigate and analyze code without making edits. Read-only exploration of the codebase. Preferred first step before implementation.
|
|
57
57
|
- `message` (required) — the instruction to send.
|
|
58
|
-
- `mode` — `"plan"` (read-only investigation) or `"free"` (default, normal execution with edits).
|
|
59
58
|
- `freshSession` — set to `true` to clear the active session before sending. Use when switching to an unrelated task or when context is contaminated.
|
|
60
59
|
- `model` — `"claude-opus-4-6"` (default, recommended for most coding work), `"claude-sonnet-4-6"`, or `"claude-sonnet-4-5"` (faster/lighter tasks).
|
|
61
60
|
- `effort` — `"high"` (default), `"medium"` (lighter tasks), `"low"`, or `"max"` (especially hard problems).
|
|
62
|
-
- `
|
|
63
|
-
- `
|
|
64
|
-
- `
|
|
61
|
+
- `implement` — implement code changes; can read, edit, and create files. Use after exploration to make changes. Same args as `explore`.
|
|
62
|
+
- `compact_context` — compress session history to reclaim context window space. Preserves state while reducing token usage.
|
|
63
|
+
- `clear_session` — clear the active session to start fresh. Use when context is full or starting a new task.
|
|
64
|
+
- `session_health` — check session health metrics: context usage %, turn count, cost, and session ID.
|
|
65
65
|
|
|
66
66
|
### Git operations
|
|
67
67
|
|
|
@@ -71,9 +71,8 @@ If you are testing locally, point OpenCode at the local package or plugin file u
|
|
|
71
71
|
|
|
72
72
|
### Inspection
|
|
73
73
|
|
|
74
|
-
- `
|
|
75
|
-
- `
|
|
76
|
-
- `engineer_runs` — list or inspect persisted manager run records (may be empty if tasks were sent directly via `engineer_send` rather than the run-tracking path).
|
|
74
|
+
- `list_transcripts` — list available session transcripts or inspect a specific transcript by ID.
|
|
75
|
+
- `list_history` — list persistent run records from the manager or inspect a specific run.
|
|
77
76
|
|
|
78
77
|
### Tool approval
|
|
79
78
|
|
|
@@ -86,7 +85,7 @@ If you are testing locally, point OpenCode at the local package or plugin file u
|
|
|
86
85
|
The plugin registers a CTO → Manager → Engineer hierarchy through the OpenCode plugin `config` hook:
|
|
87
86
|
|
|
88
87
|
- **`cto`** (primary agent) — sets direction and orchestrates work by spawning `manager` subagents. Has read/search/web tools but does NOT operate Claude Code directly.
|
|
89
|
-
- **`manager`** (subagent) — operates a Claude Code engineer through a persistent session. Has the full tool surface (`
|
|
88
|
+
- **`manager`** (subagent) — operates a Claude Code engineer through a persistent session. Has the full tool surface (`explore`, `implement`, `compact_context`, `clear_session`, `session_health`, `list_transcripts`, `list_history`, `git_*`, `approval_*`) plus read/search/web tools for investigation.
|
|
90
89
|
- **Engineer** — the Claude Code persistent session itself (not an OpenCode agent). Receives instructions from the manager, executes code changes, and reports results.
|
|
91
90
|
|
|
92
91
|
These are added to OpenCode config at runtime by the plugin, so they do not require separate manual `opencode.json` entries.
|
|
@@ -95,27 +94,27 @@ These are added to OpenCode config at runtime by the plugin, so they do not requ
|
|
|
95
94
|
|
|
96
95
|
Typical flow inside OpenCode:
|
|
97
96
|
|
|
98
|
-
1.
|
|
99
|
-
2.
|
|
97
|
+
1. Explore the codebase with `explore`.
|
|
98
|
+
2. Implement changes with `implement`.
|
|
100
99
|
3. Review changes with `git_diff`, then commit or reset.
|
|
101
|
-
4. Inspect saved Claude history with `
|
|
100
|
+
4. Inspect saved Claude history with `list_transcripts` or prior orchestration records with `list_history`.
|
|
102
101
|
|
|
103
102
|
Example tasks:
|
|
104
103
|
|
|
105
104
|
```text
|
|
106
|
-
Use
|
|
105
|
+
Use implement to add the new validation logic in src/auth.ts, then review with git_diff.
|
|
107
106
|
```
|
|
108
107
|
|
|
109
108
|
Start a fresh session for an unrelated task:
|
|
110
109
|
|
|
111
110
|
```text
|
|
112
|
-
Use
|
|
111
|
+
Use explore with freshSession:true to investigate the failing CI test in test/api.test.ts.
|
|
113
112
|
```
|
|
114
113
|
|
|
115
114
|
Reclaim context mid-session:
|
|
116
115
|
|
|
117
116
|
```text
|
|
118
|
-
Use
|
|
117
|
+
Use compact_context to free up context, then continue with the next implementation step.
|
|
119
118
|
```
|
|
120
119
|
|
|
121
120
|
## Local Development
|
|
@@ -162,6 +162,7 @@ export class ClaudeAgentSdkAdapter {
|
|
|
162
162
|
forkSession: input.forkSession,
|
|
163
163
|
persistSession: input.persistSession,
|
|
164
164
|
includePartialMessages: input.includePartialMessages,
|
|
165
|
+
enableFileCheckpointing: false,
|
|
165
166
|
settingSources: input.settingSources,
|
|
166
167
|
maxTurns: input.maxTurns,
|
|
167
168
|
model: input.model,
|
|
@@ -409,7 +410,7 @@ function truncateJsonish(value, max) {
|
|
|
409
410
|
return truncateString(JSON.stringify(value), max);
|
|
410
411
|
}
|
|
411
412
|
catch {
|
|
412
|
-
return truncateString(
|
|
413
|
+
return truncateString('[non-serializable]', max);
|
|
413
414
|
}
|
|
414
415
|
}
|
|
415
416
|
function truncateString(s, max) {
|
|
@@ -99,7 +99,7 @@ export class SessionLiveTailer {
|
|
|
99
99
|
});
|
|
100
100
|
let chunk = '';
|
|
101
101
|
stream.on('data', (data) => {
|
|
102
|
-
chunk += data;
|
|
102
|
+
chunk += typeof data === 'string' ? data : data.toString('utf8');
|
|
103
103
|
});
|
|
104
104
|
stream.on('end', () => {
|
|
105
105
|
reading = false;
|
|
@@ -264,6 +264,6 @@ function stringifyContent(value) {
|
|
|
264
264
|
return JSON.stringify(value);
|
|
265
265
|
}
|
|
266
266
|
catch {
|
|
267
|
-
return
|
|
267
|
+
return '[non-serializable]';
|
|
268
268
|
}
|
|
269
269
|
}
|
|
@@ -2,10 +2,19 @@ import type { GitDiffResult, GitOperationResult } from '../types/contracts.js';
|
|
|
2
2
|
export declare class GitOperations {
|
|
3
3
|
private readonly cwd;
|
|
4
4
|
constructor(cwd: string);
|
|
5
|
-
diff(
|
|
5
|
+
diff(options?: {
|
|
6
|
+
paths?: string[];
|
|
7
|
+
staged?: boolean;
|
|
8
|
+
ref?: string;
|
|
9
|
+
}): Promise<GitDiffResult>;
|
|
6
10
|
diffStat(): Promise<string>;
|
|
7
11
|
commit(message: string): Promise<GitOperationResult>;
|
|
8
12
|
resetHard(): Promise<GitOperationResult>;
|
|
13
|
+
status(): Promise<{
|
|
14
|
+
output: string;
|
|
15
|
+
isClean: boolean;
|
|
16
|
+
}>;
|
|
17
|
+
log(count?: number): Promise<string>;
|
|
9
18
|
currentBranch(): Promise<string>;
|
|
10
19
|
recentCommits(count?: number): Promise<string>;
|
|
11
20
|
private git;
|
|
@@ -6,10 +6,15 @@ export class GitOperations {
|
|
|
6
6
|
constructor(cwd) {
|
|
7
7
|
this.cwd = cwd;
|
|
8
8
|
}
|
|
9
|
-
async diff() {
|
|
9
|
+
async diff(options = {}) {
|
|
10
|
+
const ref = options.staged ? '--cached' : (options.ref ?? 'HEAD');
|
|
11
|
+
const args = ['diff', ref];
|
|
12
|
+
if (options.paths && options.paths.length > 0) {
|
|
13
|
+
args.push('--', ...options.paths);
|
|
14
|
+
}
|
|
10
15
|
const [diffText, statOutput] = await Promise.all([
|
|
11
|
-
this.git(
|
|
12
|
-
this.git([
|
|
16
|
+
this.git(args),
|
|
17
|
+
this.git([...args, '--stat']),
|
|
13
18
|
]);
|
|
14
19
|
const stats = parseStatLine(statOutput);
|
|
15
20
|
return {
|
|
@@ -50,6 +55,16 @@ export class GitOperations {
|
|
|
50
55
|
};
|
|
51
56
|
}
|
|
52
57
|
}
|
|
58
|
+
async status() {
|
|
59
|
+
const output = await this.git(['status', '-s']);
|
|
60
|
+
return {
|
|
61
|
+
output,
|
|
62
|
+
isClean: output.trim().length === 0,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
async log(count = 5) {
|
|
66
|
+
return this.git(['log', '--oneline', `-${count}`]);
|
|
67
|
+
}
|
|
53
68
|
async currentBranch() {
|
|
54
69
|
const branch = await this.git(['rev-parse', '--abbrev-ref', 'HEAD']);
|
|
55
70
|
return branch.trim();
|
|
@@ -35,11 +35,26 @@ export declare class PersistentManager {
|
|
|
35
35
|
/**
|
|
36
36
|
* Get the current git diff.
|
|
37
37
|
*/
|
|
38
|
-
gitDiff(
|
|
38
|
+
gitDiff(options?: {
|
|
39
|
+
paths?: string[];
|
|
40
|
+
staged?: boolean;
|
|
41
|
+
ref?: string;
|
|
42
|
+
}): Promise<GitDiffResult>;
|
|
39
43
|
/**
|
|
40
44
|
* Commit all current changes.
|
|
41
45
|
*/
|
|
42
46
|
gitCommit(message: string): Promise<GitOperationResult>;
|
|
47
|
+
/**
|
|
48
|
+
* Get git status summary.
|
|
49
|
+
*/
|
|
50
|
+
gitStatus(): Promise<{
|
|
51
|
+
output: string;
|
|
52
|
+
isClean: boolean;
|
|
53
|
+
}>;
|
|
54
|
+
/**
|
|
55
|
+
* Get recent commit log.
|
|
56
|
+
*/
|
|
57
|
+
gitLog(count?: number): Promise<string>;
|
|
43
58
|
/**
|
|
44
59
|
* Hard reset to discard all uncommitted changes.
|
|
45
60
|
*/
|
|
@@ -35,8 +35,8 @@ export class PersistentManager {
|
|
|
35
35
|
/**
|
|
36
36
|
* Get the current git diff.
|
|
37
37
|
*/
|
|
38
|
-
async gitDiff() {
|
|
39
|
-
return this.gitOps.diff();
|
|
38
|
+
async gitDiff(options = {}) {
|
|
39
|
+
return this.gitOps.diff(options);
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
42
|
* Commit all current changes.
|
|
@@ -44,6 +44,18 @@ export class PersistentManager {
|
|
|
44
44
|
async gitCommit(message) {
|
|
45
45
|
return this.gitOps.commit(message);
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Get git status summary.
|
|
49
|
+
*/
|
|
50
|
+
async gitStatus() {
|
|
51
|
+
return this.gitOps.status();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get recent commit log.
|
|
55
|
+
*/
|
|
56
|
+
async gitLog(count = 5) {
|
|
57
|
+
return this.gitOps.log(count);
|
|
58
|
+
}
|
|
47
59
|
/**
|
|
48
60
|
* Hard reset to discard all uncommitted changes.
|
|
49
61
|
*/
|
|
@@ -11,7 +11,7 @@ export declare const AGENT_CTO = "cto";
|
|
|
11
11
|
export declare const AGENT_ENGINEER_PLAN = "engineer_plan";
|
|
12
12
|
export declare const AGENT_ENGINEER_BUILD = "engineer_build";
|
|
13
13
|
/** All restricted tool IDs (union of all domain groups) */
|
|
14
|
-
export declare const ALL_RESTRICTED_TOOL_IDS: readonly ["
|
|
14
|
+
export declare const ALL_RESTRICTED_TOOL_IDS: readonly ["explore", "implement", "compact_context", "clear_session", "session_health", "list_transcripts", "list_history", "git_diff", "git_commit", "git_reset", "git_status", "git_log", "approval_policy", "approval_decisions", "approval_update"];
|
|
15
15
|
type ToolPermission = 'allow' | 'ask' | 'deny';
|
|
16
16
|
type AgentPermission = {
|
|
17
17
|
'*'?: ToolPermission;
|
|
@@ -17,25 +17,20 @@ export const AGENT_ENGINEER_BUILD = 'engineer_build';
|
|
|
17
17
|
// ---------------------------------------------------------------------------
|
|
18
18
|
/** Shared engineer session tools (compact, clear, status, diagnostics) */
|
|
19
19
|
const ENGINEER_SHARED_TOOL_IDS = [
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
];
|
|
26
|
-
/** All engineer tools — generic send + mode-locked sends + shared session tools */
|
|
27
|
-
const ENGINEER_TOOL_IDS = [
|
|
28
|
-
'engineer_send',
|
|
29
|
-
'engineer_send_plan',
|
|
30
|
-
'engineer_send_build',
|
|
31
|
-
...ENGINEER_SHARED_TOOL_IDS,
|
|
20
|
+
'compact_context',
|
|
21
|
+
'clear_session',
|
|
22
|
+
'session_health',
|
|
23
|
+
'list_transcripts',
|
|
24
|
+
'list_history',
|
|
32
25
|
];
|
|
26
|
+
/** All engineer tools — mode-locked sends + shared session tools */
|
|
27
|
+
const ENGINEER_TOOL_IDS = ['explore', 'implement', ...ENGINEER_SHARED_TOOL_IDS];
|
|
33
28
|
/** Tools for the engineer_plan wrapper (plan-mode send + shared) */
|
|
34
|
-
const ENGINEER_PLAN_TOOL_IDS = ['
|
|
29
|
+
const ENGINEER_PLAN_TOOL_IDS = ['explore', ...ENGINEER_SHARED_TOOL_IDS];
|
|
35
30
|
/** Tools for the engineer_build wrapper (build-mode send + shared) */
|
|
36
|
-
const ENGINEER_BUILD_TOOL_IDS = ['
|
|
31
|
+
const ENGINEER_BUILD_TOOL_IDS = ['implement', ...ENGINEER_SHARED_TOOL_IDS];
|
|
37
32
|
/** Git tools — owned by CTO */
|
|
38
|
-
const GIT_TOOL_IDS = ['git_diff', 'git_commit', 'git_reset'];
|
|
33
|
+
const GIT_TOOL_IDS = ['git_diff', 'git_commit', 'git_reset', 'git_status', 'git_log'];
|
|
39
34
|
/** Approval tools — owned by CTO */
|
|
40
35
|
const APPROVAL_TOOL_IDS = ['approval_policy', 'approval_decisions', 'approval_update'];
|
|
41
36
|
/** All restricted tool IDs (union of all domain groups) */
|
|
@@ -87,7 +82,7 @@ function buildCtoPermissions() {
|
|
|
87
82
|
},
|
|
88
83
|
};
|
|
89
84
|
}
|
|
90
|
-
/** Engineer plan wrapper: read-only investigation +
|
|
85
|
+
/** Engineer plan wrapper: read-only investigation + explore + shared session tools. */
|
|
91
86
|
function buildEngineerPlanPermissions() {
|
|
92
87
|
const denied = {};
|
|
93
88
|
for (const toolId of ALL_RESTRICTED_TOOL_IDS) {
|
|
@@ -104,7 +99,7 @@ function buildEngineerPlanPermissions() {
|
|
|
104
99
|
...allowed,
|
|
105
100
|
};
|
|
106
101
|
}
|
|
107
|
-
/** Engineer build wrapper: read-only investigation +
|
|
102
|
+
/** Engineer build wrapper: read-only investigation + implement + shared session tools. */
|
|
108
103
|
function buildEngineerBuildPermissions() {
|
|
109
104
|
const denied = {};
|
|
110
105
|
for (const toolId of ALL_RESTRICTED_TOOL_IDS) {
|