@doingdev/opencode-claude-manager-plugin 0.1.49 → 0.1.51
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/claude/claude-agent-sdk-adapter.d.ts +2 -3
- package/dist/claude/claude-agent-sdk-adapter.js +38 -48
- package/dist/claude/claude-session.service.d.ts +1 -2
- package/dist/claude/claude-session.service.js +0 -3
- package/dist/claude/tool-approval-manager.d.ts +9 -6
- package/dist/claude/tool-approval-manager.js +43 -6
- package/dist/index.d.ts +1 -2
- package/dist/index.js +0 -1
- package/dist/manager/context-tracker.d.ts +0 -1
- package/dist/manager/context-tracker.js +0 -3
- package/dist/manager/git-operations.d.ts +1 -4
- package/dist/manager/git-operations.js +7 -12
- package/dist/manager/persistent-manager.d.ts +3 -53
- package/dist/manager/persistent-manager.js +3 -135
- package/dist/manager/team-orchestrator.d.ts +9 -4
- package/dist/manager/team-orchestrator.js +84 -31
- package/dist/plugin/agent-hierarchy.d.ts +0 -1
- package/dist/plugin/agent-hierarchy.js +4 -2
- package/dist/plugin/claude-manager.plugin.js +170 -24
- package/dist/plugin/service-factory.d.ts +5 -6
- package/dist/plugin/service-factory.js +9 -17
- package/dist/prompts/registry.js +58 -39
- package/dist/src/claude/claude-agent-sdk-adapter.d.ts +2 -3
- package/dist/src/claude/claude-agent-sdk-adapter.js +38 -48
- package/dist/src/claude/claude-session.service.d.ts +1 -2
- package/dist/src/claude/claude-session.service.js +0 -3
- package/dist/src/claude/tool-approval-manager.d.ts +9 -6
- package/dist/src/claude/tool-approval-manager.js +43 -6
- package/dist/src/index.d.ts +1 -2
- package/dist/src/index.js +0 -1
- package/dist/src/manager/context-tracker.d.ts +0 -1
- package/dist/src/manager/context-tracker.js +0 -3
- package/dist/src/manager/git-operations.d.ts +1 -4
- package/dist/src/manager/git-operations.js +7 -12
- package/dist/src/manager/persistent-manager.d.ts +3 -53
- package/dist/src/manager/persistent-manager.js +3 -135
- package/dist/src/manager/team-orchestrator.d.ts +9 -4
- package/dist/src/manager/team-orchestrator.js +84 -31
- package/dist/src/plugin/agent-hierarchy.d.ts +0 -1
- package/dist/src/plugin/agent-hierarchy.js +4 -2
- package/dist/src/plugin/claude-manager.plugin.js +170 -24
- package/dist/src/plugin/service-factory.d.ts +5 -6
- package/dist/src/plugin/service-factory.js +9 -17
- package/dist/src/prompts/registry.js +58 -39
- package/dist/src/state/team-state-store.js +4 -1
- package/dist/src/team/roster.js +1 -0
- package/dist/src/types/contracts.d.ts +18 -57
- package/dist/state/team-state-store.js +4 -1
- package/dist/team/roster.js +1 -0
- package/dist/test/claude-agent-sdk-adapter.test.js +103 -11
- package/dist/test/claude-manager.plugin.test.js +6 -1
- package/dist/test/context-tracker.test.js +0 -8
- package/dist/test/git-operations.test.js +0 -21
- package/dist/test/persistent-manager.test.js +4 -164
- package/dist/test/prompt-registry.test.js +4 -9
- package/dist/test/report-claude-event.test.js +4 -4
- package/dist/test/team-orchestrator.test.js +7 -5
- package/dist/test/tool-approval-manager.test.js +17 -17
- package/dist/types/contracts.d.ts +18 -57
- package/package.json +1 -1
package/dist/prompts/registry.js
CHANGED
|
@@ -1,52 +1,71 @@
|
|
|
1
1
|
export const managerPromptRegistry = {
|
|
2
2
|
ctoSystemPrompt: [
|
|
3
|
-
'You are
|
|
4
|
-
'',
|
|
5
|
-
'
|
|
6
|
-
'
|
|
7
|
-
'
|
|
8
|
-
'-
|
|
9
|
-
'-
|
|
10
|
-
'-
|
|
3
|
+
'You are a principal engineer orchestrating a team of AI-powered engineers.',
|
|
4
|
+
'You multiply your output by delegating precisely and reviewing critically.',
|
|
5
|
+
'Every prompt you send to an engineer costs time and tokens. Make each one count.',
|
|
6
|
+
'',
|
|
7
|
+
'Understand first:',
|
|
8
|
+
'- Ask questions. If the request is ambiguous, underspecified, or has multiple valid interpretations, ask before building. Any question whose answer would change what you build or how you build it is worth asking.',
|
|
9
|
+
'- Use the `question` tool to surface decisions with a concrete recommendation. Prefer one precise question over many vague ones.',
|
|
10
|
+
'- Identify what already exists in the codebase before creating anything new.',
|
|
11
|
+
'- Think about what could go wrong and address it upfront.',
|
|
12
|
+
'- When a bug is reported, always explore the root cause before implementing a fix. No fix without investigation. If three fix attempts fail, question the architecture, not the hypothesis.',
|
|
13
|
+
'',
|
|
14
|
+
'Challenge the framing:',
|
|
15
|
+
'- Before planning, ask what the user is actually trying to achieve, not just what they asked for.',
|
|
16
|
+
'- If the request sounds like a feature ("add photo upload"), ask what job-to-be-done it serves. The real feature might be larger or different.',
|
|
17
|
+
'- One good reframe question saves more time than ten implementation questions.',
|
|
18
|
+
'',
|
|
19
|
+
'Plan and decompose:',
|
|
20
|
+
'- Break work into independent pieces that can run in parallel. Two engineers exploring in parallel then synthesizing beats one engineer doing everything sequentially.',
|
|
21
|
+
'- For medium or large tasks, dispatch two engineers with complementary perspectives (lead plan + challenger review), then synthesize.',
|
|
22
|
+
'- Define clear success criteria before delegating. A good assignment includes: what to do, why, which files/areas are relevant, and how to verify it worked.',
|
|
23
|
+
'',
|
|
24
|
+
'Delegate through the Task tool:',
|
|
25
|
+
'- Tom, John, Maya, Sara, and Alex are persistent engineers. Each keeps a Claude Code session that remembers prior turns.',
|
|
26
|
+
'- Reuse the same engineer when follow-up work belongs to their prior context.',
|
|
27
|
+
'- Only one implementing engineer should modify the worktree at a time. Parallelize exploration freely.',
|
|
28
|
+
'- Do not delegate without telling the engineer what done looks like.',
|
|
29
|
+
'',
|
|
30
|
+
'Review and iterate:',
|
|
11
31
|
'- Review diffs with `git_diff`, inspect changed files with `git_status`, and use `git_log` for recent context.',
|
|
12
|
-
'-
|
|
13
|
-
'',
|
|
14
|
-
'
|
|
15
|
-
'-
|
|
16
|
-
'-
|
|
17
|
-
'-
|
|
18
|
-
'
|
|
19
|
-
'',
|
|
20
|
-
'
|
|
21
|
-
'- Do not
|
|
22
|
-
'
|
|
23
|
-
'
|
|
32
|
+
'- Give specific, actionable feedback. Not "this could be better" but "this is wrong because X, fix it by doing Y."',
|
|
33
|
+
'- Trust engineer findings but verify critical claims. Do not re-examine every file they already reviewed.',
|
|
34
|
+
'- If something fails, figure out what you missed in the assignment, not just what the engineer got wrong.',
|
|
35
|
+
'- After an engineer reports implementation done, review the diff looking for issues that pass tests but break in production: race conditions, N+1 queries, missing error handling, trust boundary violations, stale reads, forgotten enum cases.',
|
|
36
|
+
'- Auto-fix mechanical issues by sending a follow-up to the same engineer. Surface genuinely ambiguous issues to the user.',
|
|
37
|
+
'- Check scope: did the engineer build what was asked — nothing more, nothing less?',
|
|
38
|
+
'',
|
|
39
|
+
'Verify before declaring done:',
|
|
40
|
+
'- After review passes, dispatch an engineer in verify mode to run the most relevant checks (tests, lint, typecheck, build) for what changed.',
|
|
41
|
+
'- Do not declare a task complete until verification passes. If it fails, fix and re-verify.',
|
|
42
|
+
'',
|
|
43
|
+
'Constraints:',
|
|
44
|
+
'- Do not edit files or run bash directly. Engineers do the hands-on work.',
|
|
45
|
+
'- Do not read files or grep when an engineer can answer the question faster.',
|
|
46
|
+
'- Communicate proactively. If the plan changes or you discover something unexpected, tell the user.',
|
|
24
47
|
].join('\n'),
|
|
25
48
|
engineerAgentPrompt: [
|
|
26
|
-
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
'
|
|
30
|
-
'
|
|
31
|
-
'
|
|
49
|
+
"You are a named engineer on the CTO's team.",
|
|
50
|
+
'Your job is to run assignments through the `claude` tool, which connects to a persistent Claude Code session that remembers your prior turns.',
|
|
51
|
+
'',
|
|
52
|
+
'Frame each assignment well:',
|
|
53
|
+
'- Include relevant context, file paths, and constraints the CTO provided.',
|
|
54
|
+
'- Specify the work mode: explore (investigate, no edits), implement (make changes and verify), or verify (run checks and report).',
|
|
55
|
+
"- If the CTO's assignment is unclear, ask for clarification before sending it to Claude Code.",
|
|
56
|
+
'',
|
|
57
|
+
'Your wrapper context from prior turns is reloaded automatically. Use it to avoid repeating work or re-explaining context that Claude Code already knows.',
|
|
58
|
+
"Return the tool result directly. Add your own commentary only when something was unexpected or needs the CTO's attention.",
|
|
32
59
|
].join('\n'),
|
|
33
60
|
engineerSessionPrompt: [
|
|
34
61
|
'You are an expert software engineer working inside Claude Code.',
|
|
35
|
-
'
|
|
36
|
-
'Follow repository conventions and
|
|
37
|
-
'
|
|
38
|
-
'
|
|
39
|
-
'Report blockers
|
|
62
|
+
'Start with the smallest investigation that resolves the key uncertainty, then act.',
|
|
63
|
+
'Follow repository conventions, AGENTS.md, and any project-level instructions.',
|
|
64
|
+
'Verify your own work before reporting done. Run the most relevant check (test, lint, typecheck, build) for what you changed.',
|
|
65
|
+
'Review your own diff before reporting done. Look for issues tests would not catch: race conditions, missing error handling, hardcoded values, incomplete enum handling.',
|
|
66
|
+
'Report blockers immediately with exact error output. Do not retry silently more than once.',
|
|
40
67
|
'Do not run git commit, git push, git reset, git checkout, or git stash.',
|
|
41
68
|
].join('\n'),
|
|
42
|
-
modePrefixes: {
|
|
43
|
-
plan: [
|
|
44
|
-
'[PLAN MODE] Read-only.',
|
|
45
|
-
'Do not create or edit files.',
|
|
46
|
-
'Analyze the codebase and return the plan inline.',
|
|
47
|
-
].join(' '),
|
|
48
|
-
free: '',
|
|
49
|
-
},
|
|
50
69
|
contextWarnings: {
|
|
51
70
|
moderate: 'Engineer context is getting full ({percent}% estimated). Reuse is still fine, but keep the next prompt focused.',
|
|
52
71
|
high: 'Engineer context is heavy ({percent}% estimated, {turns} turns, ${cost}). Prefer a narrowly scoped follow-up or internal compaction.',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type Options, type Query, type SDKSessionInfo, type SessionMessage
|
|
2
|
-
import type {
|
|
1
|
+
import { type Options, type Query, type SDKSessionInfo, type SessionMessage } from '@anthropic-ai/claude-agent-sdk';
|
|
2
|
+
import type { ClaudeSessionEvent, ClaudeSessionRunResult, ClaudeSessionSummary, ClaudeSessionTranscriptMessage, RunClaudeSessionInput } from '../types/contracts.js';
|
|
3
3
|
import type { ToolApprovalManager } from './tool-approval-manager.js';
|
|
4
4
|
export type ClaudeSessionEventHandler = (event: ClaudeSessionEvent) => void | Promise<void>;
|
|
5
5
|
interface ClaudeAgentSdkFacade {
|
|
@@ -21,7 +21,6 @@ export declare class ClaudeAgentSdkAdapter {
|
|
|
21
21
|
runSession(input: RunClaudeSessionInput, onEvent?: ClaudeSessionEventHandler): Promise<ClaudeSessionRunResult>;
|
|
22
22
|
listSavedSessions(cwd?: string): Promise<ClaudeSessionSummary[]>;
|
|
23
23
|
getTranscript(sessionId: string, cwd?: string): Promise<ClaudeSessionTranscriptMessage[]>;
|
|
24
|
-
probeCapabilities(cwd: string, settingSources?: SettingSource[]): Promise<ClaudeCapabilitySnapshot>;
|
|
25
24
|
private buildOptions;
|
|
26
25
|
}
|
|
27
26
|
export {};
|
|
@@ -123,34 +123,6 @@ export class ClaudeAgentSdkAdapter {
|
|
|
123
123
|
text: extractText(message.message),
|
|
124
124
|
}));
|
|
125
125
|
}
|
|
126
|
-
async probeCapabilities(cwd, settingSources = ['project']) {
|
|
127
|
-
const sessionQuery = this.sdkFacade.query({
|
|
128
|
-
prompt: 'Reply with OK.',
|
|
129
|
-
options: {
|
|
130
|
-
cwd,
|
|
131
|
-
maxTurns: 1,
|
|
132
|
-
permissionMode: 'plan',
|
|
133
|
-
persistSession: false,
|
|
134
|
-
tools: [],
|
|
135
|
-
settingSources,
|
|
136
|
-
},
|
|
137
|
-
});
|
|
138
|
-
try {
|
|
139
|
-
const [commands, agents, models] = await Promise.all([
|
|
140
|
-
sessionQuery.supportedCommands(),
|
|
141
|
-
sessionQuery.supportedAgents(),
|
|
142
|
-
sessionQuery.supportedModels(),
|
|
143
|
-
]);
|
|
144
|
-
return {
|
|
145
|
-
commands: commands.map(mapSlashCommand),
|
|
146
|
-
agents: agents.map(mapAgent),
|
|
147
|
-
models: models.map((model) => model.value),
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
finally {
|
|
151
|
-
sessionQuery.close();
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
126
|
buildOptions(input) {
|
|
155
127
|
const options = {
|
|
156
128
|
cwd: input.cwd,
|
|
@@ -179,13 +151,23 @@ export class ClaudeAgentSdkAdapter {
|
|
|
179
151
|
if (!input.resumeSessionId) {
|
|
180
152
|
delete options.resume;
|
|
181
153
|
}
|
|
182
|
-
|
|
154
|
+
const restrictWrites = input.restrictWriteTools === true;
|
|
155
|
+
if (this.approvalManager || restrictWrites) {
|
|
183
156
|
const manager = this.approvalManager;
|
|
184
157
|
options.canUseTool = async (toolName, toolInput, opts) => {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
158
|
+
if (restrictWrites && isWriteTool(toolName, toolInput)) {
|
|
159
|
+
return {
|
|
160
|
+
behavior: 'deny',
|
|
161
|
+
message: 'Write operations are restricted in explore mode. Ask the CTO to re-dispatch in implement mode for edits.',
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (manager) {
|
|
165
|
+
return manager.evaluate(toolName, toolInput, {
|
|
166
|
+
title: opts.title,
|
|
167
|
+
agentID: opts.agentID,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return { behavior: 'allow' };
|
|
189
171
|
};
|
|
190
172
|
}
|
|
191
173
|
return options;
|
|
@@ -465,21 +447,29 @@ function extractText(payload) {
|
|
|
465
447
|
}
|
|
466
448
|
return JSON.stringify(payload);
|
|
467
449
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
450
|
+
const WRITE_TOOL_NAMES = new Set(['Edit', 'MultiEdit', 'Write', 'NotebookEdit']);
|
|
451
|
+
const BASH_WRITE_PATTERNS = [
|
|
452
|
+
/\b(sed|awk)\b.*-i/,
|
|
453
|
+
/\btee\b/,
|
|
454
|
+
/>>/,
|
|
455
|
+
/\becho\b.*>/,
|
|
456
|
+
/\bcat\b.*>/,
|
|
457
|
+
/\bmv\b/,
|
|
458
|
+
/\brm\b/,
|
|
459
|
+
/\bmkdir\b/,
|
|
460
|
+
/\btouch\b/,
|
|
461
|
+
/\bcp\b/,
|
|
462
|
+
/\bgit\s+(add|commit|push|reset|checkout|merge|rebase|stash)\b/,
|
|
463
|
+
];
|
|
464
|
+
function isWriteTool(toolName, toolInput) {
|
|
465
|
+
if (WRITE_TOOL_NAMES.has(toolName)) {
|
|
466
|
+
return true;
|
|
467
|
+
}
|
|
468
|
+
if (toolName === 'Bash' || toolName === 'bash') {
|
|
469
|
+
const command = typeof toolInput.command === 'string' ? toolInput.command : '';
|
|
470
|
+
return BASH_WRITE_PATTERNS.some((pattern) => pattern.test(command));
|
|
471
|
+
}
|
|
472
|
+
return false;
|
|
483
473
|
}
|
|
484
474
|
function extractUsageFromResult(message) {
|
|
485
475
|
if (message.type !== 'result') {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ClaudeSessionRunResult, ClaudeSessionSummary, ClaudeSessionTranscriptMessage, RunClaudeSessionInput } from '../types/contracts.js';
|
|
2
2
|
import type { ClaudeAgentSdkAdapter, ClaudeSessionEventHandler } from './claude-agent-sdk-adapter.js';
|
|
3
3
|
export declare class ClaudeSessionService {
|
|
4
4
|
private readonly sdkAdapter;
|
|
@@ -6,5 +6,4 @@ export declare class ClaudeSessionService {
|
|
|
6
6
|
runTask(input: RunClaudeSessionInput, onEvent?: ClaudeSessionEventHandler): Promise<ClaudeSessionRunResult>;
|
|
7
7
|
listSessions(cwd?: string): Promise<ClaudeSessionSummary[]>;
|
|
8
8
|
getTranscript(sessionId: string, cwd?: string): Promise<ClaudeSessionTranscriptMessage[]>;
|
|
9
|
-
probeCapabilities(cwd: string): Promise<ClaudeCapabilitySnapshot>;
|
|
10
9
|
}
|
|
@@ -3,7 +3,10 @@ export declare class ToolApprovalManager {
|
|
|
3
3
|
private policy;
|
|
4
4
|
private decisions;
|
|
5
5
|
private readonly maxDecisions;
|
|
6
|
-
|
|
6
|
+
private readonly persistPath;
|
|
7
|
+
constructor(policy?: Partial<ToolApprovalPolicy>, maxDecisions?: number, persistPath?: string);
|
|
8
|
+
loadPersistedPolicy(): Promise<void>;
|
|
9
|
+
private persistPolicy;
|
|
7
10
|
evaluate(toolName: string, input: Record<string, unknown>, options?: {
|
|
8
11
|
title?: string;
|
|
9
12
|
agentID?: string;
|
|
@@ -17,11 +20,11 @@ export declare class ToolApprovalManager {
|
|
|
17
20
|
getDeniedDecisions(limit?: number): ToolApprovalDecision[];
|
|
18
21
|
clearDecisions(): void;
|
|
19
22
|
getPolicy(): ToolApprovalPolicy;
|
|
20
|
-
setPolicy(policy: ToolApprovalPolicy): void
|
|
21
|
-
addRule(rule: ToolApprovalRule, position?: number): void
|
|
22
|
-
removeRule(ruleId: string): boolean
|
|
23
|
-
setDefaultAction(action: 'allow' | 'deny'): void
|
|
24
|
-
setEnabled(enabled: boolean): void
|
|
23
|
+
setPolicy(policy: ToolApprovalPolicy): Promise<void>;
|
|
24
|
+
addRule(rule: ToolApprovalRule, position?: number): Promise<void>;
|
|
25
|
+
removeRule(ruleId: string): Promise<boolean>;
|
|
26
|
+
setDefaultAction(action: 'allow' | 'deny'): Promise<void>;
|
|
27
|
+
setEnabled(enabled: boolean): Promise<void>;
|
|
25
28
|
private findMatchingRule;
|
|
26
29
|
private recordDecision;
|
|
27
30
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { isFileNotFoundError, writeJsonAtomically } from '../util/fs-helpers.js';
|
|
1
4
|
const DEFAULT_MAX_DECISIONS = 500;
|
|
2
5
|
const INPUT_PREVIEW_MAX = 300;
|
|
3
6
|
function getDefaultRules() {
|
|
@@ -120,7 +123,8 @@ export class ToolApprovalManager {
|
|
|
120
123
|
policy;
|
|
121
124
|
decisions = [];
|
|
122
125
|
maxDecisions;
|
|
123
|
-
|
|
126
|
+
persistPath;
|
|
127
|
+
constructor(policy, maxDecisions, persistPath) {
|
|
124
128
|
this.policy = {
|
|
125
129
|
rules: policy?.rules ?? getDefaultRules(),
|
|
126
130
|
defaultAction: policy?.defaultAction ?? 'allow',
|
|
@@ -128,6 +132,34 @@ export class ToolApprovalManager {
|
|
|
128
132
|
enabled: policy?.enabled ?? true,
|
|
129
133
|
};
|
|
130
134
|
this.maxDecisions = maxDecisions ?? DEFAULT_MAX_DECISIONS;
|
|
135
|
+
this.persistPath = persistPath ?? null;
|
|
136
|
+
}
|
|
137
|
+
async loadPersistedPolicy() {
|
|
138
|
+
if (!this.persistPath) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
const content = await fs.readFile(this.persistPath, 'utf8');
|
|
143
|
+
const loaded = JSON.parse(content);
|
|
144
|
+
this.policy = {
|
|
145
|
+
rules: loaded.rules ?? getDefaultRules(),
|
|
146
|
+
defaultAction: loaded.defaultAction ?? 'allow',
|
|
147
|
+
defaultDenyMessage: loaded.defaultDenyMessage ?? 'Tool call denied by approval policy.',
|
|
148
|
+
enabled: loaded.enabled ?? true,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (!isFileNotFoundError(error)) {
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async persistPolicy() {
|
|
158
|
+
if (!this.persistPath) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
await fs.mkdir(path.dirname(this.persistPath), { recursive: true });
|
|
162
|
+
await writeJsonAtomically(this.persistPath, this.policy);
|
|
131
163
|
}
|
|
132
164
|
evaluate(toolName, input, options) {
|
|
133
165
|
if (!this.policy.enabled) {
|
|
@@ -168,30 +200,35 @@ export class ToolApprovalManager {
|
|
|
168
200
|
getPolicy() {
|
|
169
201
|
return { ...this.policy, rules: [...this.policy.rules] };
|
|
170
202
|
}
|
|
171
|
-
setPolicy(policy) {
|
|
203
|
+
async setPolicy(policy) {
|
|
172
204
|
this.policy = { ...policy, rules: [...policy.rules] };
|
|
205
|
+
await this.persistPolicy();
|
|
173
206
|
}
|
|
174
|
-
addRule(rule, position) {
|
|
207
|
+
async addRule(rule, position) {
|
|
175
208
|
if (position !== undefined && position >= 0 && position < this.policy.rules.length) {
|
|
176
209
|
this.policy.rules.splice(position, 0, rule);
|
|
177
210
|
}
|
|
178
211
|
else {
|
|
179
212
|
this.policy.rules.push(rule);
|
|
180
213
|
}
|
|
214
|
+
await this.persistPolicy();
|
|
181
215
|
}
|
|
182
|
-
removeRule(ruleId) {
|
|
216
|
+
async removeRule(ruleId) {
|
|
183
217
|
const index = this.policy.rules.findIndex((r) => r.id === ruleId);
|
|
184
218
|
if (index === -1) {
|
|
185
219
|
return false;
|
|
186
220
|
}
|
|
187
221
|
this.policy.rules.splice(index, 1);
|
|
222
|
+
await this.persistPolicy();
|
|
188
223
|
return true;
|
|
189
224
|
}
|
|
190
|
-
setDefaultAction(action) {
|
|
225
|
+
async setDefaultAction(action) {
|
|
191
226
|
this.policy.defaultAction = action;
|
|
227
|
+
await this.persistPolicy();
|
|
192
228
|
}
|
|
193
|
-
setEnabled(enabled) {
|
|
229
|
+
async setEnabled(enabled) {
|
|
194
230
|
this.policy.enabled = enabled;
|
|
231
|
+
await this.persistPolicy();
|
|
195
232
|
}
|
|
196
233
|
findMatchingRule(toolName, inputJson) {
|
|
197
234
|
for (const rule of this.policy.rules) {
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
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,
|
|
4
|
-
export { SessionLiveTailer } from './claude/session-live-tailer.js';
|
|
3
|
+
export type { ClaudeCapabilitySnapshot, ClaudeSessionRunResult, ClaudeSessionSummary, ClaudeSessionTranscriptMessage, ManagerPromptRegistry, RunClaudeSessionInput, SessionContextSnapshot, GitDiffResult, GitOperationResult, ContextWarningLevel, SessionMode, EngineerName, EngineerWorkMode, EngineerFailureKind, EngineerFailureResult, WrapperHistoryEntry, TeamEngineerRecord, TeamRecord, EngineerTaskResult, PlanDraft, SynthesizedPlanResult, ToolApprovalRule, ToolApprovalPolicy, ToolApprovalDecision, } from './types/contracts.js';
|
|
5
4
|
export { ClaudeManagerPlugin };
|
|
6
5
|
export declare const plugin: Plugin;
|
package/dist/src/index.js
CHANGED
|
@@ -19,7 +19,6 @@ export declare class ContextTracker {
|
|
|
19
19
|
snapshot(): SessionContextSnapshot;
|
|
20
20
|
warningLevel(): ContextWarningLevel;
|
|
21
21
|
estimateContextPercent(): number | null;
|
|
22
|
-
isAboveTokenThreshold(thresholdTokens?: number): boolean;
|
|
23
22
|
reset(): void;
|
|
24
23
|
/** Restore from persisted active session state. */
|
|
25
24
|
restore(state: {
|
|
@@ -83,9 +83,6 @@ export class ContextTracker {
|
|
|
83
83
|
}
|
|
84
84
|
return null;
|
|
85
85
|
}
|
|
86
|
-
isAboveTokenThreshold(thresholdTokens = 200_000) {
|
|
87
|
-
return this.latestInputTokens !== null && this.latestInputTokens >= thresholdTokens;
|
|
88
|
-
}
|
|
89
86
|
reset() {
|
|
90
87
|
this.totalTurns = 0;
|
|
91
88
|
this.totalCostUsd = 0;
|
|
@@ -7,15 +7,12 @@ export declare class GitOperations {
|
|
|
7
7
|
staged?: boolean;
|
|
8
8
|
ref?: string;
|
|
9
9
|
}): Promise<GitDiffResult>;
|
|
10
|
-
|
|
11
|
-
commit(message: string): Promise<GitOperationResult>;
|
|
10
|
+
commit(message: string, paths?: string[]): Promise<GitOperationResult>;
|
|
12
11
|
resetHard(): Promise<GitOperationResult>;
|
|
13
12
|
status(): Promise<{
|
|
14
13
|
output: string;
|
|
15
14
|
isClean: boolean;
|
|
16
15
|
}>;
|
|
17
16
|
log(count?: number): Promise<string>;
|
|
18
|
-
currentBranch(): Promise<string>;
|
|
19
|
-
recentCommits(count?: number): Promise<string>;
|
|
20
17
|
private git;
|
|
21
18
|
}
|
|
@@ -23,12 +23,14 @@ export class GitOperations {
|
|
|
23
23
|
stats,
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
-
async
|
|
27
|
-
return this.git(['diff', 'HEAD', '--stat']);
|
|
28
|
-
}
|
|
29
|
-
async commit(message) {
|
|
26
|
+
async commit(message, paths) {
|
|
30
27
|
try {
|
|
31
|
-
|
|
28
|
+
if (paths && paths.length > 0) {
|
|
29
|
+
await this.git(['add', '--', ...paths]);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
await this.git(['add', '-A']);
|
|
33
|
+
}
|
|
32
34
|
const output = await this.git(['commit', '-m', message]);
|
|
33
35
|
return { success: true, output };
|
|
34
36
|
}
|
|
@@ -65,13 +67,6 @@ export class GitOperations {
|
|
|
65
67
|
async log(count = 5) {
|
|
66
68
|
return this.git(['log', '--oneline', `-${count}`]);
|
|
67
69
|
}
|
|
68
|
-
async currentBranch() {
|
|
69
|
-
const branch = await this.git(['rev-parse', '--abbrev-ref', 'HEAD']);
|
|
70
|
-
return branch.trim();
|
|
71
|
-
}
|
|
72
|
-
async recentCommits(count = 5) {
|
|
73
|
-
return this.git(['log', `--oneline`, `-${count}`]);
|
|
74
|
-
}
|
|
75
70
|
async git(args) {
|
|
76
71
|
const { stdout } = await execFileAsync('git', args, { cwd: this.cwd });
|
|
77
72
|
return stdout;
|
|
@@ -1,38 +1,10 @@
|
|
|
1
|
-
import type { ClaudeSessionEvent,
|
|
2
|
-
import type { ClaudeSessionEventHandler } from '../claude/claude-agent-sdk-adapter.js';
|
|
3
|
-
import type { FileRunStateStore } from '../state/file-run-state-store.js';
|
|
1
|
+
import type { ClaudeSessionEvent, GitDiffResult, GitOperationResult } from '../types/contracts.js';
|
|
4
2
|
import type { TranscriptStore } from '../state/transcript-store.js';
|
|
5
|
-
import type { SessionController } from './session-controller.js';
|
|
6
3
|
import type { GitOperations } from './git-operations.js';
|
|
7
|
-
import type { ContextTracker } from './context-tracker.js';
|
|
8
|
-
type PersistentManagerProgressHandler = (run: PersistentRunRecord) => void | Promise<void>;
|
|
9
4
|
export declare class PersistentManager {
|
|
10
|
-
private readonly sessionController;
|
|
11
5
|
private readonly gitOps;
|
|
12
|
-
private readonly stateStore;
|
|
13
|
-
private readonly contextTracker;
|
|
14
6
|
private readonly transcriptStore;
|
|
15
|
-
constructor(
|
|
16
|
-
/**
|
|
17
|
-
* Send a message to the persistent Claude Code session.
|
|
18
|
-
* Creates a new session if none exists.
|
|
19
|
-
*/
|
|
20
|
-
sendMessage(cwd: string, message: string, options?: {
|
|
21
|
-
model?: string;
|
|
22
|
-
effort?: 'low' | 'medium' | 'high' | 'max';
|
|
23
|
-
mode?: 'plan' | 'free';
|
|
24
|
-
sessionSystemPrompt?: string;
|
|
25
|
-
abortSignal?: AbortSignal;
|
|
26
|
-
}, onEvent?: ClaudeSessionEventHandler): Promise<{
|
|
27
|
-
sessionId: string | undefined;
|
|
28
|
-
finalText: string;
|
|
29
|
-
turns?: number;
|
|
30
|
-
totalCostUsd?: number;
|
|
31
|
-
inputTokens?: number;
|
|
32
|
-
outputTokens?: number;
|
|
33
|
-
contextWindowSize?: number;
|
|
34
|
-
context: SessionContextSnapshot;
|
|
35
|
-
}>;
|
|
7
|
+
constructor(gitOps: GitOperations, transcriptStore: TranscriptStore);
|
|
36
8
|
/**
|
|
37
9
|
* Get the current git diff.
|
|
38
10
|
*/
|
|
@@ -44,7 +16,7 @@ export declare class PersistentManager {
|
|
|
44
16
|
/**
|
|
45
17
|
* Commit all current changes.
|
|
46
18
|
*/
|
|
47
|
-
gitCommit(message: string): Promise<GitOperationResult>;
|
|
19
|
+
gitCommit(message: string, paths?: string[]): Promise<GitOperationResult>;
|
|
48
20
|
/**
|
|
49
21
|
* Get git status summary.
|
|
50
22
|
*/
|
|
@@ -60,30 +32,8 @@ export declare class PersistentManager {
|
|
|
60
32
|
* Hard reset to discard all uncommitted changes.
|
|
61
33
|
*/
|
|
62
34
|
gitReset(): Promise<GitOperationResult>;
|
|
63
|
-
/**
|
|
64
|
-
* Get current session status and context health.
|
|
65
|
-
*/
|
|
66
|
-
getStatus(): SessionContextSnapshot;
|
|
67
|
-
/**
|
|
68
|
-
* Clear the active session. Next send creates a fresh one.
|
|
69
|
-
*/
|
|
70
|
-
clearSession(): Promise<string | null>;
|
|
71
|
-
/**
|
|
72
|
-
* Compact the current session to free context.
|
|
73
|
-
*/
|
|
74
|
-
compactSession(cwd: string, onEvent?: ClaudeSessionEventHandler): Promise<ClaudeSessionRunResult>;
|
|
75
35
|
/**
|
|
76
36
|
* Read persisted transcript events for a session.
|
|
77
37
|
*/
|
|
78
38
|
getTranscriptEvents(cwd: string, sessionId: string): Promise<ClaudeSessionEvent[]>;
|
|
79
|
-
/**
|
|
80
|
-
* Execute a full task with run tracking.
|
|
81
|
-
* Creates a run record, sends the message, and persists the result.
|
|
82
|
-
*/
|
|
83
|
-
executeTask(cwd: string, task: string, options?: {
|
|
84
|
-
model?: string;
|
|
85
|
-
}, onProgress?: PersistentManagerProgressHandler): Promise<PersistentRunResult>;
|
|
86
|
-
listRuns(cwd: string): Promise<PersistentRunRecord[]>;
|
|
87
|
-
getRun(cwd: string, runId: string): Promise<PersistentRunRecord | null>;
|
|
88
39
|
}
|
|
89
|
-
export {};
|