@doingdev/opencode-claude-manager-plugin 0.1.30 → 0.1.31
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.js +7 -18
- package/dist/claude/claude-session.service.d.ts +2 -7
- package/dist/claude/claude-session.service.js +1 -6
- package/dist/claude/tool-approval-manager.js +3 -9
- package/dist/index.d.ts +1 -1
- package/dist/manager/context-tracker.js +2 -4
- package/dist/plugin/agent-hierarchy.d.ts +1 -1
- package/dist/plugin/agent-hierarchy.js +3 -14
- package/dist/plugin/claude-manager.plugin.js +11 -50
- package/dist/plugin/service-factory.js +1 -4
- package/dist/state/file-run-state-store.js +2 -4
- package/dist/state/transcript-store.js +2 -2
- package/dist/types/contracts.d.ts +1 -24
- package/dist/util/fs-helpers.js +1 -3
- package/package.json +1 -2
|
@@ -19,9 +19,7 @@ function mergeSkillIntoAllowedTools(allowedTools, disallowedTools) {
|
|
|
19
19
|
if (allowedTools === undefined) {
|
|
20
20
|
return ['Skill'];
|
|
21
21
|
}
|
|
22
|
-
return allowedTools.includes('Skill')
|
|
23
|
-
? allowedTools
|
|
24
|
-
: [...allowedTools, 'Skill'];
|
|
22
|
+
return allowedTools.includes('Skill') ? allowedTools : [...allowedTools, 'Skill'];
|
|
25
23
|
}
|
|
26
24
|
export class ClaudeAgentSdkAdapter {
|
|
27
25
|
sdkFacade;
|
|
@@ -262,11 +260,8 @@ function normalizeSdkMessages(message, includePartials) {
|
|
|
262
260
|
return normalizeUserSdkMessage(message, sessionId);
|
|
263
261
|
}
|
|
264
262
|
if (message.type === 'tool_progress') {
|
|
265
|
-
const toolName = 'tool_name' in message && typeof message.tool_name === 'string'
|
|
266
|
-
|
|
267
|
-
: 'tool';
|
|
268
|
-
const elapsed = 'elapsed_time_seconds' in message &&
|
|
269
|
-
typeof message.elapsed_time_seconds === 'number'
|
|
263
|
+
const toolName = 'tool_name' in message && typeof message.tool_name === 'string' ? message.tool_name : 'tool';
|
|
264
|
+
const elapsed = 'elapsed_time_seconds' in message && typeof message.elapsed_time_seconds === 'number'
|
|
270
265
|
? message.elapsed_time_seconds
|
|
271
266
|
: 0;
|
|
272
267
|
return [
|
|
@@ -279,9 +274,7 @@ function normalizeSdkMessages(message, includePartials) {
|
|
|
279
274
|
];
|
|
280
275
|
}
|
|
281
276
|
if (message.type === 'tool_use_summary') {
|
|
282
|
-
const summary = 'summary' in message && typeof message.summary === 'string'
|
|
283
|
-
? message.summary
|
|
284
|
-
: '';
|
|
277
|
+
const summary = 'summary' in message && typeof message.summary === 'string' ? message.summary : '';
|
|
285
278
|
return [
|
|
286
279
|
{
|
|
287
280
|
type: 'tool_summary',
|
|
@@ -359,9 +352,7 @@ function normalizeUserSdkMessage(message, sessionId) {
|
|
|
359
352
|
if (message.tool_use_result !== undefined) {
|
|
360
353
|
const extra = truncateJsonish(message.tool_use_result, 1500);
|
|
361
354
|
if (extra) {
|
|
362
|
-
payload = payload
|
|
363
|
-
? `${payload}\n[tool_use_result] ${extra}`
|
|
364
|
-
: `[tool_use_result] ${extra}`;
|
|
355
|
+
payload = payload ? `${payload}\n[tool_use_result] ${extra}` : `[tool_use_result] ${extra}`;
|
|
365
356
|
}
|
|
366
357
|
}
|
|
367
358
|
payload = truncateString(payload, USER_MESSAGE_MAX);
|
|
@@ -439,8 +430,7 @@ function extractPartialEventText(event) {
|
|
|
439
430
|
if (typeof delta.text === 'string' && delta.text.length > 0) {
|
|
440
431
|
return delta.text;
|
|
441
432
|
}
|
|
442
|
-
if (typeof delta.partial_json === 'string' &&
|
|
443
|
-
delta.partial_json.length > 0) {
|
|
433
|
+
if (typeof delta.partial_json === 'string' && delta.partial_json.length > 0) {
|
|
444
434
|
return delta.partial_json;
|
|
445
435
|
}
|
|
446
436
|
}
|
|
@@ -462,8 +452,7 @@ function extractText(payload) {
|
|
|
462
452
|
if (typeof contentPart.text === 'string') {
|
|
463
453
|
return contentPart.text;
|
|
464
454
|
}
|
|
465
|
-
if (contentPart.type === 'tool_use' &&
|
|
466
|
-
typeof contentPart.name === 'string') {
|
|
455
|
+
if (contentPart.type === 'tool_use' && typeof contentPart.name === 'string') {
|
|
467
456
|
return `[tool:${contentPart.name}]`;
|
|
468
457
|
}
|
|
469
458
|
return '';
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
import type { ClaudeCapabilitySnapshot,
|
|
2
|
-
import type { ClaudeMetadataService } from '../metadata/claude-metadata.service.js';
|
|
1
|
+
import type { ClaudeCapabilitySnapshot, ClaudeSessionRunResult, ClaudeSessionSummary, ClaudeSessionTranscriptMessage, RunClaudeSessionInput } from '../types/contracts.js';
|
|
3
2
|
import type { ClaudeAgentSdkAdapter, ClaudeSessionEventHandler } from './claude-agent-sdk-adapter.js';
|
|
4
3
|
export declare class ClaudeSessionService {
|
|
5
4
|
private readonly sdkAdapter;
|
|
6
|
-
|
|
7
|
-
constructor(sdkAdapter: ClaudeAgentSdkAdapter, metadataService: ClaudeMetadataService);
|
|
5
|
+
constructor(sdkAdapter: ClaudeAgentSdkAdapter);
|
|
8
6
|
runTask(input: RunClaudeSessionInput, onEvent?: ClaudeSessionEventHandler): Promise<ClaudeSessionRunResult>;
|
|
9
7
|
listSessions(cwd?: string): Promise<ClaudeSessionSummary[]>;
|
|
10
8
|
getTranscript(sessionId: string, cwd?: string): Promise<ClaudeSessionTranscriptMessage[]>;
|
|
11
|
-
inspectRepository(cwd: string, options?: {
|
|
12
|
-
includeSdkProbe?: boolean;
|
|
13
|
-
}): Promise<ClaudeMetadataSnapshot>;
|
|
14
9
|
probeCapabilities(cwd: string): Promise<ClaudeCapabilitySnapshot>;
|
|
15
10
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export class ClaudeSessionService {
|
|
2
2
|
sdkAdapter;
|
|
3
|
-
|
|
4
|
-
constructor(sdkAdapter, metadataService) {
|
|
3
|
+
constructor(sdkAdapter) {
|
|
5
4
|
this.sdkAdapter = sdkAdapter;
|
|
6
|
-
this.metadataService = metadataService;
|
|
7
5
|
}
|
|
8
6
|
runTask(input, onEvent) {
|
|
9
7
|
return this.sdkAdapter.runSession(input, onEvent);
|
|
@@ -14,9 +12,6 @@ export class ClaudeSessionService {
|
|
|
14
12
|
getTranscript(sessionId, cwd) {
|
|
15
13
|
return this.sdkAdapter.getTranscript(sessionId, cwd);
|
|
16
14
|
}
|
|
17
|
-
inspectRepository(cwd, options) {
|
|
18
|
-
return this.metadataService.collect(cwd, options);
|
|
19
|
-
}
|
|
20
15
|
probeCapabilities(cwd) {
|
|
21
16
|
return this.sdkAdapter.probeCapabilities(cwd);
|
|
22
17
|
}
|
|
@@ -137,9 +137,7 @@ export class ToolApprovalManager {
|
|
|
137
137
|
const matchedRule = this.findMatchingRule(toolName, inputJson);
|
|
138
138
|
const action = matchedRule?.action ?? this.policy.defaultAction;
|
|
139
139
|
const denyMessage = action === 'deny'
|
|
140
|
-
? (matchedRule?.denyMessage ??
|
|
141
|
-
this.policy.defaultDenyMessage ??
|
|
142
|
-
'Denied by policy.')
|
|
140
|
+
? (matchedRule?.denyMessage ?? this.policy.defaultDenyMessage ?? 'Denied by policy.')
|
|
143
141
|
: undefined;
|
|
144
142
|
this.recordDecision({
|
|
145
143
|
timestamp: new Date().toISOString(),
|
|
@@ -174,9 +172,7 @@ export class ToolApprovalManager {
|
|
|
174
172
|
this.policy = { ...policy, rules: [...policy.rules] };
|
|
175
173
|
}
|
|
176
174
|
addRule(rule, position) {
|
|
177
|
-
if (position !== undefined &&
|
|
178
|
-
position >= 0 &&
|
|
179
|
-
position < this.policy.rules.length) {
|
|
175
|
+
if (position !== undefined && position >= 0 && position < this.policy.rules.length) {
|
|
180
176
|
this.policy.rules.splice(position, 0, rule);
|
|
181
177
|
}
|
|
182
178
|
else {
|
|
@@ -223,9 +219,7 @@ function matchesToolPattern(pattern, toolName) {
|
|
|
223
219
|
if (!pattern.includes('*')) {
|
|
224
220
|
return pattern === toolName;
|
|
225
221
|
}
|
|
226
|
-
const regex = new RegExp('^' +
|
|
227
|
-
pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*') +
|
|
228
|
-
'$');
|
|
222
|
+
const regex = new RegExp('^' + pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*') + '$');
|
|
229
223
|
return regex.test(toolName);
|
|
230
224
|
}
|
|
231
225
|
function safeJsonStringify(value) {
|
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,
|
|
3
|
+
export type { ClaudeCapabilitySnapshot, ClaudeSessionRunResult, ClaudeSessionSummary, ClaudeSessionTranscriptMessage, ManagerPromptRegistry, RunClaudeSessionInput, SessionContextSnapshot, GitDiffResult, GitOperationResult, PersistentRunRecord, PersistentRunResult, ActiveSessionState, 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;
|
|
@@ -19,8 +19,7 @@ export class ContextTracker {
|
|
|
19
19
|
}
|
|
20
20
|
if (result.inputTokens !== undefined) {
|
|
21
21
|
// If input tokens dropped significantly, compaction likely occurred
|
|
22
|
-
if (this.latestInputTokens !== null &&
|
|
23
|
-
result.inputTokens < this.latestInputTokens * 0.5) {
|
|
22
|
+
if (this.latestInputTokens !== null && result.inputTokens < this.latestInputTokens * 0.5) {
|
|
24
23
|
this.compactionCount++;
|
|
25
24
|
}
|
|
26
25
|
this.latestInputTokens = result.inputTokens;
|
|
@@ -85,8 +84,7 @@ export class ContextTracker {
|
|
|
85
84
|
return null;
|
|
86
85
|
}
|
|
87
86
|
isAboveTokenThreshold(thresholdTokens = 200_000) {
|
|
88
|
-
return
|
|
89
|
-
this.latestInputTokens >= thresholdTokens);
|
|
87
|
+
return this.latestInputTokens !== null && this.latestInputTokens >= thresholdTokens;
|
|
90
88
|
}
|
|
91
89
|
reset() {
|
|
92
90
|
this.totalTurns = 0;
|
|
@@ -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 ["engineer_send", "engineer_send_plan", "engineer_send_build", "engineer_compact", "engineer_clear", "engineer_status", "
|
|
14
|
+
export declare const ALL_RESTRICTED_TOOL_IDS: readonly ["engineer_send", "engineer_send_plan", "engineer_send_build", "engineer_compact", "engineer_clear", "engineer_status", "engineer_sessions", "engineer_runs", "git_diff", "git_commit", "git_reset", "approval_policy", "approval_decisions", "approval_update"];
|
|
15
15
|
type ToolPermission = 'allow' | 'ask' | 'deny';
|
|
16
16
|
type AgentPermission = {
|
|
17
17
|
'*'?: ToolPermission;
|
|
@@ -20,7 +20,6 @@ const ENGINEER_SHARED_TOOL_IDS = [
|
|
|
20
20
|
'engineer_compact',
|
|
21
21
|
'engineer_clear',
|
|
22
22
|
'engineer_status',
|
|
23
|
-
'engineer_metadata',
|
|
24
23
|
'engineer_sessions',
|
|
25
24
|
'engineer_runs',
|
|
26
25
|
];
|
|
@@ -32,23 +31,13 @@ const ENGINEER_TOOL_IDS = [
|
|
|
32
31
|
...ENGINEER_SHARED_TOOL_IDS,
|
|
33
32
|
];
|
|
34
33
|
/** Tools for the engineer_plan wrapper (plan-mode send + shared) */
|
|
35
|
-
const ENGINEER_PLAN_TOOL_IDS = [
|
|
36
|
-
'engineer_send_plan',
|
|
37
|
-
...ENGINEER_SHARED_TOOL_IDS,
|
|
38
|
-
];
|
|
34
|
+
const ENGINEER_PLAN_TOOL_IDS = ['engineer_send_plan', ...ENGINEER_SHARED_TOOL_IDS];
|
|
39
35
|
/** Tools for the engineer_build wrapper (build-mode send + shared) */
|
|
40
|
-
const ENGINEER_BUILD_TOOL_IDS = [
|
|
41
|
-
'engineer_send_build',
|
|
42
|
-
...ENGINEER_SHARED_TOOL_IDS,
|
|
43
|
-
];
|
|
36
|
+
const ENGINEER_BUILD_TOOL_IDS = ['engineer_send_build', ...ENGINEER_SHARED_TOOL_IDS];
|
|
44
37
|
/** Git tools — owned by CTO */
|
|
45
38
|
const GIT_TOOL_IDS = ['git_diff', 'git_commit', 'git_reset'];
|
|
46
39
|
/** Approval tools — owned by CTO */
|
|
47
|
-
const APPROVAL_TOOL_IDS = [
|
|
48
|
-
'approval_policy',
|
|
49
|
-
'approval_decisions',
|
|
50
|
-
'approval_update',
|
|
51
|
-
];
|
|
40
|
+
const APPROVAL_TOOL_IDS = ['approval_policy', 'approval_decisions', 'approval_update'];
|
|
52
41
|
/** All restricted tool IDs (union of all domain groups) */
|
|
53
42
|
export const ALL_RESTRICTED_TOOL_IDS = [
|
|
54
43
|
...ENGINEER_TOOL_IDS,
|
|
@@ -10,13 +10,9 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
10
10
|
await services.manager.clearSession(cwd);
|
|
11
11
|
}
|
|
12
12
|
const hasActiveSession = services.manager.getStatus().sessionId !== null;
|
|
13
|
-
const promptPreview = args.message.length > 100
|
|
14
|
-
? args.message.slice(0, 100) + '...'
|
|
15
|
-
: args.message;
|
|
13
|
+
const promptPreview = args.message.length > 100 ? args.message.slice(0, 100) + '...' : args.message;
|
|
16
14
|
context.metadata({
|
|
17
|
-
title: hasActiveSession
|
|
18
|
-
? 'Claude Code: Resuming session...'
|
|
19
|
-
: 'Claude Code: Initializing...',
|
|
15
|
+
title: hasActiveSession ? 'Claude Code: Resuming session...' : 'Claude Code: Initializing...',
|
|
20
16
|
metadata: {
|
|
21
17
|
sessionId: services.manager.getStatus().sessionId,
|
|
22
18
|
prompt: promptPreview,
|
|
@@ -44,13 +40,8 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
44
40
|
const parsed = JSON.parse(event.text);
|
|
45
41
|
toolName = parsed.name ?? 'tool';
|
|
46
42
|
if (parsed.input) {
|
|
47
|
-
const inputStr = typeof parsed.input === 'string'
|
|
48
|
-
|
|
49
|
-
: JSON.stringify(parsed.input);
|
|
50
|
-
inputPreview =
|
|
51
|
-
inputStr.length > 150
|
|
52
|
-
? inputStr.slice(0, 150) + '...'
|
|
53
|
-
: inputStr;
|
|
43
|
+
const inputStr = typeof parsed.input === 'string' ? parsed.input : JSON.stringify(parsed.input);
|
|
44
|
+
inputPreview = inputStr.length > 150 ? inputStr.slice(0, 150) + '...' : inputStr;
|
|
54
45
|
}
|
|
55
46
|
}
|
|
56
47
|
catch {
|
|
@@ -67,9 +58,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
67
58
|
});
|
|
68
59
|
}
|
|
69
60
|
else if (event.type === 'assistant') {
|
|
70
|
-
const thinkingPreview = event.text.length > 150
|
|
71
|
-
? event.text.slice(0, 150) + '...'
|
|
72
|
-
: event.text;
|
|
61
|
+
const thinkingPreview = event.text.length > 150 ? event.text.slice(0, 150) + '...' : event.text;
|
|
73
62
|
context.metadata({
|
|
74
63
|
title: `Claude Code: Thinking... (${turnsSoFar} turns, ${costLabel})`,
|
|
75
64
|
metadata: {
|
|
@@ -89,9 +78,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
89
78
|
});
|
|
90
79
|
}
|
|
91
80
|
else if (event.type === 'user') {
|
|
92
|
-
const preview = event.text.length > 200
|
|
93
|
-
? event.text.slice(0, 200) + '...'
|
|
94
|
-
: event.text;
|
|
81
|
+
const preview = event.text.length > 200 ? event.text.slice(0, 200) + '...' : event.text;
|
|
95
82
|
context.metadata({
|
|
96
83
|
title: `Claude Code: Tool result (${turnsSoFar} turns, ${costLabel})`,
|
|
97
84
|
metadata: {
|
|
@@ -123,9 +110,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
123
110
|
});
|
|
124
111
|
}
|
|
125
112
|
else if (event.type === 'tool_summary') {
|
|
126
|
-
const summary = event.text.length > 200
|
|
127
|
-
? event.text.slice(0, 200) + '...'
|
|
128
|
-
: event.text;
|
|
113
|
+
const summary = event.text.length > 200 ? event.text.slice(0, 200) + '...' : event.text;
|
|
129
114
|
context.metadata({
|
|
130
115
|
title: `Claude Code: Tool done (${turnsSoFar} turns, ${costLabel})`,
|
|
131
116
|
metadata: {
|
|
@@ -136,9 +121,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
136
121
|
});
|
|
137
122
|
}
|
|
138
123
|
else if (event.type === 'partial') {
|
|
139
|
-
const delta = event.text.length > 200
|
|
140
|
-
? event.text.slice(0, 200) + '...'
|
|
141
|
-
: event.text;
|
|
124
|
+
const delta = event.text.length > 200 ? event.text.slice(0, 200) + '...' : event.text;
|
|
142
125
|
context.metadata({
|
|
143
126
|
title: `Claude Code: Writing... (${turnsSoFar} turns, ${costLabel})`,
|
|
144
127
|
metadata: {
|
|
@@ -210,9 +193,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
210
193
|
model: tool.schema
|
|
211
194
|
.enum(['claude-opus-4-6', 'claude-sonnet-4-6', 'claude-sonnet-4-5'])
|
|
212
195
|
.optional(),
|
|
213
|
-
effort: tool.schema
|
|
214
|
-
.enum(['low', 'medium', 'high', 'max'])
|
|
215
|
-
.default('high'),
|
|
196
|
+
effort: tool.schema.enum(['low', 'medium', 'high', 'max']).default('high'),
|
|
216
197
|
mode: tool.schema.enum(['plan', 'free']).default('free'),
|
|
217
198
|
freshSession: tool.schema.boolean().default(false),
|
|
218
199
|
cwd: tool.schema.string().optional(),
|
|
@@ -231,9 +212,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
231
212
|
model: tool.schema
|
|
232
213
|
.enum(['claude-opus-4-6', 'claude-sonnet-4-6', 'claude-sonnet-4-5'])
|
|
233
214
|
.optional(),
|
|
234
|
-
effort: tool.schema
|
|
235
|
-
.enum(['low', 'medium', 'high', 'max'])
|
|
236
|
-
.default('high'),
|
|
215
|
+
effort: tool.schema.enum(['low', 'medium', 'high', 'max']).default('high'),
|
|
237
216
|
freshSession: tool.schema.boolean().default(false),
|
|
238
217
|
cwd: tool.schema.string().optional(),
|
|
239
218
|
},
|
|
@@ -253,9 +232,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
253
232
|
model: tool.schema
|
|
254
233
|
.enum(['claude-opus-4-6', 'claude-sonnet-4-6', 'claude-sonnet-4-5'])
|
|
255
234
|
.optional(),
|
|
256
|
-
effort: tool.schema
|
|
257
|
-
.enum(['low', 'medium', 'high', 'max'])
|
|
258
|
-
.default('high'),
|
|
235
|
+
effort: tool.schema.enum(['low', 'medium', 'high', 'max']).default('high'),
|
|
259
236
|
freshSession: tool.schema.boolean().default(false),
|
|
260
237
|
cwd: tool.schema.string().optional(),
|
|
261
238
|
},
|
|
@@ -361,22 +338,6 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
361
338
|
}, null, 2);
|
|
362
339
|
},
|
|
363
340
|
}),
|
|
364
|
-
engineer_metadata: tool({
|
|
365
|
-
description: 'Inspect Claude slash commands, skills, hooks, and repo settings.',
|
|
366
|
-
args: {
|
|
367
|
-
cwd: tool.schema.string().optional(),
|
|
368
|
-
includeSdkProbe: tool.schema.boolean().default(false),
|
|
369
|
-
},
|
|
370
|
-
async execute(args, context) {
|
|
371
|
-
annotateToolRun(context, 'Collecting Claude metadata', {
|
|
372
|
-
includeSdkProbe: args.includeSdkProbe,
|
|
373
|
-
});
|
|
374
|
-
const metadata = await services.sessions.inspectRepository(args.cwd ?? context.worktree, {
|
|
375
|
-
includeSdkProbe: args.includeSdkProbe,
|
|
376
|
-
});
|
|
377
|
-
return JSON.stringify(metadata, null, 2);
|
|
378
|
-
},
|
|
379
|
-
}),
|
|
380
341
|
engineer_sessions: tool({
|
|
381
342
|
description: 'List Claude sessions or inspect a saved transcript. ' +
|
|
382
343
|
'When sessionId is provided, returns both SDK transcript and local events.',
|
|
@@ -2,8 +2,6 @@ import { ClaudeAgentSdkAdapter } from '../claude/claude-agent-sdk-adapter.js';
|
|
|
2
2
|
import { ClaudeSessionService } from '../claude/claude-session.service.js';
|
|
3
3
|
import { SessionLiveTailer } from '../claude/session-live-tailer.js';
|
|
4
4
|
import { ToolApprovalManager } from '../claude/tool-approval-manager.js';
|
|
5
|
-
import { ClaudeMetadataService } from '../metadata/claude-metadata.service.js';
|
|
6
|
-
import { RepoClaudeConfigReader } from '../metadata/repo-claude-config-reader.js';
|
|
7
5
|
import { FileRunStateStore } from '../state/file-run-state-store.js';
|
|
8
6
|
import { TranscriptStore } from '../state/transcript-store.js';
|
|
9
7
|
import { ContextTracker } from '../manager/context-tracker.js';
|
|
@@ -19,8 +17,7 @@ export function getOrCreatePluginServices(worktree) {
|
|
|
19
17
|
}
|
|
20
18
|
const approvalManager = new ToolApprovalManager();
|
|
21
19
|
const sdkAdapter = new ClaudeAgentSdkAdapter(undefined, approvalManager);
|
|
22
|
-
const
|
|
23
|
-
const sessionService = new ClaudeSessionService(sdkAdapter, metadataService);
|
|
20
|
+
const sessionService = new ClaudeSessionService(sdkAdapter);
|
|
24
21
|
const contextTracker = new ContextTracker();
|
|
25
22
|
const sessionController = new SessionController(sdkAdapter, contextTracker, managerPromptRegistry.engineerSessionPrompt, managerPromptRegistry.modePrefixes);
|
|
26
23
|
const gitOps = new GitOperations(worktree);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { isFileNotFoundError, writeJsonAtomically
|
|
3
|
+
import { isFileNotFoundError, writeJsonAtomically } from '../util/fs-helpers.js';
|
|
4
4
|
export class FileRunStateStore {
|
|
5
5
|
baseDirectoryName;
|
|
6
6
|
writeQueues = new Map();
|
|
@@ -70,9 +70,7 @@ export class FileRunStateStore {
|
|
|
70
70
|
}
|
|
71
71
|
async enqueueWrite(key, operation) {
|
|
72
72
|
const previousOperation = this.writeQueues.get(key) ?? Promise.resolve();
|
|
73
|
-
const resultPromise = previousOperation
|
|
74
|
-
.catch(() => undefined)
|
|
75
|
-
.then(operation);
|
|
73
|
+
const resultPromise = previousOperation.catch(() => undefined).then(operation);
|
|
76
74
|
const settledPromise = resultPromise.then(() => undefined, () => undefined);
|
|
77
75
|
this.writeQueues.set(key, settledPromise);
|
|
78
76
|
try {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { appendTranscriptEvents, stripTrailingPartials
|
|
4
|
-
import { isFileNotFoundError, writeJsonAtomically
|
|
3
|
+
import { appendTranscriptEvents, stripTrailingPartials } from '../util/transcript-append.js';
|
|
4
|
+
import { isFileNotFoundError, writeJsonAtomically } from '../util/fs-helpers.js';
|
|
5
5
|
export class TranscriptStore {
|
|
6
6
|
baseDirectoryName;
|
|
7
7
|
constructor(baseDirectoryName = '.claude-manager') {
|
|
@@ -13,7 +13,6 @@ export interface ManagerPromptRegistry {
|
|
|
13
13
|
critical: string;
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
|
-
export type ClaudeSettingSource = 'user' | 'project' | 'local';
|
|
17
16
|
export type SessionMode = 'plan' | 'free';
|
|
18
17
|
export interface ClaudeCommandMetadata {
|
|
19
18
|
name: string;
|
|
@@ -22,34 +21,12 @@ export interface ClaudeCommandMetadata {
|
|
|
22
21
|
source: 'sdk' | 'skill' | 'command';
|
|
23
22
|
path?: string;
|
|
24
23
|
}
|
|
25
|
-
export interface ClaudeSkillMetadata {
|
|
26
|
-
name: string;
|
|
27
|
-
description: string;
|
|
28
|
-
path: string;
|
|
29
|
-
source: 'skill' | 'command';
|
|
30
|
-
}
|
|
31
|
-
export interface ClaudeHookMetadata {
|
|
32
|
-
name: string;
|
|
33
|
-
matcher?: string;
|
|
34
|
-
sourcePath: string;
|
|
35
|
-
commandCount: number;
|
|
36
|
-
}
|
|
37
24
|
export interface ClaudeAgentMetadata {
|
|
38
25
|
name: string;
|
|
39
26
|
description: string;
|
|
40
27
|
model?: string;
|
|
41
28
|
source: 'sdk' | 'filesystem';
|
|
42
29
|
}
|
|
43
|
-
export interface ClaudeMetadataSnapshot {
|
|
44
|
-
collectedAt: string;
|
|
45
|
-
cwd: string;
|
|
46
|
-
commands: ClaudeCommandMetadata[];
|
|
47
|
-
skills: ClaudeSkillMetadata[];
|
|
48
|
-
hooks: ClaudeHookMetadata[];
|
|
49
|
-
agents: ClaudeAgentMetadata[];
|
|
50
|
-
claudeMdPath?: string;
|
|
51
|
-
settingsPaths: string[];
|
|
52
|
-
}
|
|
53
30
|
export interface ClaudeSessionEvent {
|
|
54
31
|
type: 'init' | 'assistant' | 'partial' | 'user' | 'tool_call' | 'tool_progress' | 'tool_summary' | 'status' | 'system' | 'result' | 'error';
|
|
55
32
|
sessionId?: string;
|
|
@@ -75,7 +52,7 @@ export interface RunClaudeSessionInput {
|
|
|
75
52
|
forkSession?: boolean;
|
|
76
53
|
persistSession?: boolean;
|
|
77
54
|
includePartialMessages?: boolean;
|
|
78
|
-
settingSources?:
|
|
55
|
+
settingSources?: Array<'user' | 'project' | 'local'>;
|
|
79
56
|
maxTurns?: number;
|
|
80
57
|
abortSignal?: AbortSignal;
|
|
81
58
|
}
|
package/dist/util/fs-helpers.js
CHANGED
|
@@ -6,7 +6,5 @@ export async function writeJsonAtomically(filePath, data) {
|
|
|
6
6
|
await fs.rename(tempPath, filePath);
|
|
7
7
|
}
|
|
8
8
|
export function isFileNotFoundError(error) {
|
|
9
|
-
return (error instanceof Error &&
|
|
10
|
-
'code' in error &&
|
|
11
|
-
error.code === 'ENOENT');
|
|
9
|
+
return (error instanceof Error && 'code' in error && error.code === 'ENOENT');
|
|
12
10
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@doingdev/opencode-claude-manager-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.31",
|
|
4
4
|
"description": "OpenCode plugin that orchestrates Claude Code sessions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"opencode",
|
|
@@ -31,7 +31,6 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@anthropic-ai/claude-agent-sdk": "^0.2.81",
|
|
33
33
|
"@opencode-ai/plugin": "^1.2.27",
|
|
34
|
-
"json5": "^2.2.3",
|
|
35
34
|
"zod": "^4.1.8"
|
|
36
35
|
},
|
|
37
36
|
"devDependencies": {
|