@doingdev/opencode-claude-manager-plugin 0.1.11 → 0.1.12
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 -1
- package/dist/manager/persistent-manager.d.ts +10 -3
- package/dist/manager/persistent-manager.js +17 -2
- package/dist/manager/session-controller.d.ts +1 -1
- package/dist/manager/session-controller.js +3 -3
- package/dist/plugin/claude-manager.plugin.d.ts +0 -2
- package/dist/plugin/claude-manager.plugin.js +68 -23
- package/dist/plugin/service-factory.d.ts +2 -1
- package/dist/plugin/service-factory.js +3 -1
- package/dist/state/file-run-state-store.js +1 -11
- package/dist/state/transcript-store.d.ts +15 -0
- package/dist/state/transcript-store.js +44 -0
- package/dist/util/fs-helpers.d.ts +2 -0
- package/dist/util/fs-helpers.js +12 -0
- package/package.json +3 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Options, type Query, type SDKSessionInfo, type SessionMessage, type SettingSource } from '@anthropic-ai/claude-agent-sdk';
|
|
2
2
|
import type { ClaudeCapabilitySnapshot, ClaudeSessionEvent, ClaudeSessionRunResult, ClaudeSessionSummary, ClaudeSessionTranscriptMessage, RunClaudeSessionInput } from '../types/contracts.js';
|
|
3
3
|
export type ClaudeSessionEventHandler = (event: ClaudeSessionEvent) => void | Promise<void>;
|
|
4
|
-
|
|
4
|
+
interface ClaudeAgentSdkFacade {
|
|
5
5
|
query(params: {
|
|
6
6
|
prompt: string;
|
|
7
7
|
options?: Options;
|
|
@@ -22,3 +22,4 @@ export declare class ClaudeAgentSdkAdapter {
|
|
|
22
22
|
probeCapabilities(cwd: string, settingSources?: SettingSource[]): Promise<ClaudeCapabilitySnapshot>;
|
|
23
23
|
private buildOptions;
|
|
24
24
|
}
|
|
25
|
+
export {};
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import type { ClaudeSessionRunResult, PersistentRunRecord, PersistentRunResult, SessionContextSnapshot, GitDiffResult, GitOperationResult } from '../types/contracts.js';
|
|
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
|
+
import type { TranscriptStore } from '../state/transcript-store.js';
|
|
4
5
|
import type { SessionController } from './session-controller.js';
|
|
5
6
|
import type { GitOperations } from './git-operations.js';
|
|
6
7
|
import type { ContextTracker } from './context-tracker.js';
|
|
7
|
-
|
|
8
|
+
type PersistentManagerProgressHandler = (run: PersistentRunRecord) => void | Promise<void>;
|
|
8
9
|
export declare class PersistentManager {
|
|
9
10
|
private readonly sessionController;
|
|
10
11
|
private readonly gitOps;
|
|
11
12
|
private readonly stateStore;
|
|
12
13
|
private readonly contextTracker;
|
|
13
|
-
|
|
14
|
+
private readonly transcriptStore;
|
|
15
|
+
constructor(sessionController: SessionController, gitOps: GitOperations, stateStore: FileRunStateStore, contextTracker: ContextTracker, transcriptStore: TranscriptStore);
|
|
14
16
|
/**
|
|
15
17
|
* Send a message to the persistent Claude Code session.
|
|
16
18
|
* Creates a new session if none exists.
|
|
@@ -48,6 +50,10 @@ export declare class PersistentManager {
|
|
|
48
50
|
* Compact the current session to free context.
|
|
49
51
|
*/
|
|
50
52
|
compactSession(cwd: string, onEvent?: ClaudeSessionEventHandler): Promise<ClaudeSessionRunResult>;
|
|
53
|
+
/**
|
|
54
|
+
* Read persisted transcript events for a session.
|
|
55
|
+
*/
|
|
56
|
+
getTranscriptEvents(cwd: string, sessionId: string): Promise<ClaudeSessionEvent[]>;
|
|
51
57
|
/**
|
|
52
58
|
* Execute a full task with run tracking.
|
|
53
59
|
* Creates a run record, sends the message, and persists the result.
|
|
@@ -62,3 +68,4 @@ export declare class PersistentManager {
|
|
|
62
68
|
listRuns(cwd: string): Promise<PersistentRunRecord[]>;
|
|
63
69
|
getRun(cwd: string, runId: string): Promise<PersistentRunRecord | null>;
|
|
64
70
|
}
|
|
71
|
+
export {};
|
|
@@ -4,11 +4,13 @@ export class PersistentManager {
|
|
|
4
4
|
gitOps;
|
|
5
5
|
stateStore;
|
|
6
6
|
contextTracker;
|
|
7
|
-
|
|
7
|
+
transcriptStore;
|
|
8
|
+
constructor(sessionController, gitOps, stateStore, contextTracker, transcriptStore) {
|
|
8
9
|
this.sessionController = sessionController;
|
|
9
10
|
this.gitOps = gitOps;
|
|
10
11
|
this.stateStore = stateStore;
|
|
11
12
|
this.contextTracker = contextTracker;
|
|
13
|
+
this.transcriptStore = transcriptStore;
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
16
|
* Send a message to the persistent Claude Code session.
|
|
@@ -16,6 +18,9 @@ export class PersistentManager {
|
|
|
16
18
|
*/
|
|
17
19
|
async sendMessage(cwd, message, options, onEvent) {
|
|
18
20
|
const result = await this.sessionController.sendMessage(cwd, message, options, onEvent);
|
|
21
|
+
if (result.sessionId && result.events.length > 0) {
|
|
22
|
+
await this.transcriptStore.appendEvents(cwd, result.sessionId, result.events);
|
|
23
|
+
}
|
|
19
24
|
return {
|
|
20
25
|
sessionId: result.sessionId,
|
|
21
26
|
finalText: result.finalText,
|
|
@@ -58,7 +63,17 @@ export class PersistentManager {
|
|
|
58
63
|
* Compact the current session to free context.
|
|
59
64
|
*/
|
|
60
65
|
async compactSession(cwd, onEvent) {
|
|
61
|
-
|
|
66
|
+
const result = await this.sessionController.compactSession(cwd, onEvent);
|
|
67
|
+
if (result.sessionId && result.events.length > 0) {
|
|
68
|
+
await this.transcriptStore.appendEvents(cwd, result.sessionId, result.events);
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Read persisted transcript events for a session.
|
|
74
|
+
*/
|
|
75
|
+
getTranscriptEvents(cwd, sessionId) {
|
|
76
|
+
return this.transcriptStore.readEvents(cwd, sessionId);
|
|
62
77
|
}
|
|
63
78
|
/**
|
|
64
79
|
* Execute a full task with run tracking.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ClaudeSessionRunResult, SessionContextSnapshot } from '../types/contracts.js';
|
|
2
1
|
import type { ClaudeAgentSdkAdapter, ClaudeSessionEventHandler } from '../claude/claude-agent-sdk-adapter.js';
|
|
2
|
+
import type { ClaudeSessionRunResult, SessionContextSnapshot } from '../types/contracts.js';
|
|
3
3
|
import type { ContextTracker } from './context-tracker.js';
|
|
4
4
|
export declare class SessionController {
|
|
5
5
|
private readonly sdkAdapter;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { readFile, writeFile
|
|
2
|
-
import {
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
3
|
const ACTIVE_SESSION_FILE = '.claude-manager/active-session.json';
|
|
4
4
|
export class SessionController {
|
|
5
5
|
sdkAdapter;
|
|
@@ -29,7 +29,7 @@ export class SessionController {
|
|
|
29
29
|
permissionMode: 'acceptEdits',
|
|
30
30
|
includePartialMessages: true,
|
|
31
31
|
model: options?.model,
|
|
32
|
-
settingSources: options?.settingSources ?? ['project', 'local'],
|
|
32
|
+
settingSources: options?.settingSources ?? ['user', 'project', 'local'],
|
|
33
33
|
};
|
|
34
34
|
if (this.activeSessionId) {
|
|
35
35
|
// Resume existing session
|
|
@@ -104,27 +104,74 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
104
104
|
cwd: tool.schema.string().optional(),
|
|
105
105
|
},
|
|
106
106
|
async execute(args, context) {
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
const cwd = args.cwd ?? context.worktree;
|
|
108
|
+
const hasActiveSession = services.manager.getStatus().sessionId !== null;
|
|
109
|
+
context.metadata({
|
|
110
|
+
title: hasActiveSession
|
|
111
|
+
? 'Claude Code: Resuming session...'
|
|
112
|
+
: 'Claude Code: Initializing...',
|
|
113
|
+
metadata: { sessionId: services.manager.getStatus().sessionId },
|
|
109
114
|
});
|
|
110
|
-
|
|
111
|
-
|
|
115
|
+
let turnsSoFar = 0;
|
|
116
|
+
let costSoFar = 0;
|
|
117
|
+
const result = await services.manager.sendMessage(cwd, args.message, { model: args.model }, (event) => {
|
|
118
|
+
if (event.turns !== undefined) {
|
|
119
|
+
turnsSoFar = event.turns;
|
|
120
|
+
}
|
|
121
|
+
if (event.totalCostUsd !== undefined) {
|
|
122
|
+
costSoFar = event.totalCostUsd;
|
|
123
|
+
}
|
|
124
|
+
const costLabel = `$${costSoFar.toFixed(4)}`;
|
|
125
|
+
if (event.type === 'tool_call') {
|
|
126
|
+
let toolName = 'tool';
|
|
127
|
+
try {
|
|
128
|
+
toolName = JSON.parse(event.text).name ?? 'tool';
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
// ignore parse errors
|
|
132
|
+
}
|
|
133
|
+
context.metadata({
|
|
134
|
+
title: `Claude Code: Running ${toolName}... (${turnsSoFar} turns, ${costLabel})`,
|
|
135
|
+
metadata: {
|
|
136
|
+
sessionId: event.sessionId,
|
|
137
|
+
type: event.type,
|
|
138
|
+
preview: event.text.slice(0, 200),
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
else if (event.type === 'assistant') {
|
|
112
143
|
context.metadata({
|
|
113
|
-
title:
|
|
144
|
+
title: `Claude Code: Thinking... (${turnsSoFar} turns, ${costLabel})`,
|
|
114
145
|
metadata: {
|
|
146
|
+
sessionId: event.sessionId,
|
|
115
147
|
type: event.type,
|
|
116
148
|
preview: event.text.slice(0, 200),
|
|
117
149
|
},
|
|
118
150
|
});
|
|
119
151
|
}
|
|
120
152
|
});
|
|
153
|
+
const costLabel = `$${(result.totalCostUsd ?? 0).toFixed(4)}`;
|
|
154
|
+
const turns = result.turns ?? 0;
|
|
155
|
+
const contextWarning = formatContextWarning(result.context);
|
|
156
|
+
if (contextWarning) {
|
|
157
|
+
context.metadata({
|
|
158
|
+
title: `Claude Code: Context at ${result.context.estimatedContextPercent}% (${turns} turns)`,
|
|
159
|
+
metadata: { sessionId: result.sessionId, contextWarning },
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
context.metadata({
|
|
164
|
+
title: `Claude Code: Complete (${turns} turns, ${costLabel})`,
|
|
165
|
+
metadata: { sessionId: result.sessionId },
|
|
166
|
+
});
|
|
167
|
+
}
|
|
121
168
|
return JSON.stringify({
|
|
122
169
|
sessionId: result.sessionId,
|
|
123
170
|
finalText: result.finalText,
|
|
124
171
|
turns: result.turns,
|
|
125
172
|
totalCostUsd: result.totalCostUsd,
|
|
126
173
|
context: result.context,
|
|
127
|
-
contextWarning
|
|
174
|
+
contextWarning,
|
|
128
175
|
}, null, 2);
|
|
129
176
|
},
|
|
130
177
|
}),
|
|
@@ -189,6 +236,9 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
189
236
|
const status = services.manager.getStatus();
|
|
190
237
|
return JSON.stringify({
|
|
191
238
|
...status,
|
|
239
|
+
transcriptFile: status.sessionId
|
|
240
|
+
? `.claude-manager/transcripts/${status.sessionId}.json`
|
|
241
|
+
: null,
|
|
192
242
|
contextWarning: formatContextWarning(status),
|
|
193
243
|
}, null, 2);
|
|
194
244
|
},
|
|
@@ -210,18 +260,26 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
|
|
|
210
260
|
},
|
|
211
261
|
}),
|
|
212
262
|
claude_manager_sessions: tool({
|
|
213
|
-
description: 'List Claude sessions or inspect a saved transcript.'
|
|
263
|
+
description: 'List Claude sessions or inspect a saved transcript. ' +
|
|
264
|
+
'When sessionId is provided, returns both SDK transcript and local manager events.',
|
|
214
265
|
args: {
|
|
215
266
|
cwd: tool.schema.string().optional(),
|
|
216
267
|
sessionId: tool.schema.string().optional(),
|
|
217
268
|
},
|
|
218
269
|
async execute(args, context) {
|
|
219
270
|
annotateToolRun(context, 'Inspecting Claude session history', {});
|
|
271
|
+
const cwd = args.cwd ?? context.worktree;
|
|
220
272
|
if (args.sessionId) {
|
|
221
|
-
const
|
|
222
|
-
|
|
273
|
+
const [sdkTranscript, localEvents] = await Promise.all([
|
|
274
|
+
services.sessions.getTranscript(args.sessionId, cwd),
|
|
275
|
+
services.manager.getTranscriptEvents(cwd, args.sessionId),
|
|
276
|
+
]);
|
|
277
|
+
return JSON.stringify({
|
|
278
|
+
sdkTranscript,
|
|
279
|
+
localEvents: localEvents.length > 0 ? localEvents : undefined,
|
|
280
|
+
}, null, 2);
|
|
223
281
|
}
|
|
224
|
-
const sessions = await services.sessions.listSessions(
|
|
282
|
+
const sessions = await services.sessions.listSessions(cwd);
|
|
225
283
|
return JSON.stringify(sessions, null, 2);
|
|
226
284
|
},
|
|
227
285
|
}),
|
|
@@ -304,16 +362,3 @@ function formatContextWarning(context) {
|
|
|
304
362
|
.replace('{turns}', String(totalTurns))
|
|
305
363
|
.replace('{cost}', totalCostUsd.toFixed(2));
|
|
306
364
|
}
|
|
307
|
-
export function formatRunToolResult(run) {
|
|
308
|
-
return JSON.stringify({
|
|
309
|
-
runId: run.id,
|
|
310
|
-
status: run.status,
|
|
311
|
-
task: run.task,
|
|
312
|
-
sessionId: run.sessionId,
|
|
313
|
-
finalSummary: run.finalSummary,
|
|
314
|
-
messageCount: run.messages.length,
|
|
315
|
-
actionCount: run.actions.length,
|
|
316
|
-
commits: run.commits,
|
|
317
|
-
context: run.context,
|
|
318
|
-
}, null, 2);
|
|
319
|
-
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ClaudeSessionService } from '../claude/claude-session.service.js';
|
|
2
2
|
import { PersistentManager } from '../manager/persistent-manager.js';
|
|
3
|
-
|
|
3
|
+
interface ClaudeManagerPluginServices {
|
|
4
4
|
manager: PersistentManager;
|
|
5
5
|
sessions: ClaudeSessionService;
|
|
6
6
|
}
|
|
7
7
|
export declare function getOrCreatePluginServices(worktree: string): ClaudeManagerPluginServices;
|
|
8
|
+
export {};
|
|
@@ -3,6 +3,7 @@ import { ClaudeSessionService } from '../claude/claude-session.service.js';
|
|
|
3
3
|
import { ClaudeMetadataService } from '../metadata/claude-metadata.service.js';
|
|
4
4
|
import { RepoClaudeConfigReader } from '../metadata/repo-claude-config-reader.js';
|
|
5
5
|
import { FileRunStateStore } from '../state/file-run-state-store.js';
|
|
6
|
+
import { TranscriptStore } from '../state/transcript-store.js';
|
|
6
7
|
import { ContextTracker } from '../manager/context-tracker.js';
|
|
7
8
|
import { GitOperations } from '../manager/git-operations.js';
|
|
8
9
|
import { SessionController } from '../manager/session-controller.js';
|
|
@@ -21,7 +22,8 @@ export function getOrCreatePluginServices(worktree) {
|
|
|
21
22
|
const sessionController = new SessionController(sdkAdapter, contextTracker, managerPromptRegistry.claudeCodeSessionPrompt);
|
|
22
23
|
const gitOps = new GitOperations(worktree);
|
|
23
24
|
const stateStore = new FileRunStateStore();
|
|
24
|
-
const
|
|
25
|
+
const transcriptStore = new TranscriptStore();
|
|
26
|
+
const manager = new PersistentManager(sessionController, gitOps, stateStore, contextTracker, transcriptStore);
|
|
25
27
|
// Try to restore active session state (fire and forget)
|
|
26
28
|
manager.tryRestore(worktree).catch(() => { });
|
|
27
29
|
const services = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
1
|
import { promises as fs } from 'node:fs';
|
|
3
2
|
import path from 'node:path';
|
|
3
|
+
import { isFileNotFoundError, writeJsonAtomically, } from '../util/fs-helpers.js';
|
|
4
4
|
export class FileRunStateStore {
|
|
5
5
|
baseDirectoryName;
|
|
6
6
|
writeQueues = new Map();
|
|
@@ -85,13 +85,3 @@ export class FileRunStateStore {
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
-
async function writeJsonAtomically(filePath, data) {
|
|
89
|
-
const tempPath = `${filePath}.${randomUUID()}.tmp`;
|
|
90
|
-
await fs.writeFile(tempPath, `${JSON.stringify(data, null, 2)}\n`, 'utf8');
|
|
91
|
-
await fs.rename(tempPath, filePath);
|
|
92
|
-
}
|
|
93
|
-
function isFileNotFoundError(error) {
|
|
94
|
-
return (error instanceof Error &&
|
|
95
|
-
'code' in error &&
|
|
96
|
-
error.code === 'ENOENT');
|
|
97
|
-
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ClaudeSessionEvent } from '../types/contracts.js';
|
|
2
|
+
export declare class TranscriptStore {
|
|
3
|
+
private readonly baseDirectoryName;
|
|
4
|
+
constructor(baseDirectoryName?: string);
|
|
5
|
+
/**
|
|
6
|
+
* Append new events to the transcript file for the given session.
|
|
7
|
+
* Creates the file if it does not exist. Strips trailing partials before persisting.
|
|
8
|
+
*/
|
|
9
|
+
appendEvents(cwd: string, sessionId: string, newEvents: ClaudeSessionEvent[]): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Read all persisted transcript events for a session.
|
|
12
|
+
*/
|
|
13
|
+
readEvents(cwd: string, sessionId: string): Promise<ClaudeSessionEvent[]>;
|
|
14
|
+
private getTranscriptPath;
|
|
15
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { appendTranscriptEvents, stripTrailingPartials, } from '../util/transcript-append.js';
|
|
4
|
+
import { isFileNotFoundError, writeJsonAtomically, } from '../util/fs-helpers.js';
|
|
5
|
+
export class TranscriptStore {
|
|
6
|
+
baseDirectoryName;
|
|
7
|
+
constructor(baseDirectoryName = '.claude-manager') {
|
|
8
|
+
this.baseDirectoryName = baseDirectoryName;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Append new events to the transcript file for the given session.
|
|
12
|
+
* Creates the file if it does not exist. Strips trailing partials before persisting.
|
|
13
|
+
*/
|
|
14
|
+
async appendEvents(cwd, sessionId, newEvents) {
|
|
15
|
+
if (newEvents.length === 0) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const filePath = this.getTranscriptPath(cwd, sessionId);
|
|
19
|
+
const existing = await this.readEvents(cwd, sessionId);
|
|
20
|
+
const merged = appendTranscriptEvents(existing, newEvents);
|
|
21
|
+
const cleaned = stripTrailingPartials(merged);
|
|
22
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
23
|
+
await writeJsonAtomically(filePath, cleaned);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Read all persisted transcript events for a session.
|
|
27
|
+
*/
|
|
28
|
+
async readEvents(cwd, sessionId) {
|
|
29
|
+
const filePath = this.getTranscriptPath(cwd, sessionId);
|
|
30
|
+
try {
|
|
31
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
32
|
+
return JSON.parse(content);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
if (isFileNotFoundError(error)) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
getTranscriptPath(cwd, sessionId) {
|
|
42
|
+
return path.join(cwd, this.baseDirectoryName, 'transcripts', `${sessionId}.json`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { promises as fs } from 'node:fs';
|
|
3
|
+
export async function writeJsonAtomically(filePath, data) {
|
|
4
|
+
const tempPath = `${filePath}.${randomUUID()}.tmp`;
|
|
5
|
+
await fs.writeFile(tempPath, `${JSON.stringify(data, null, 2)}\n`, 'utf8');
|
|
6
|
+
await fs.rename(tempPath, filePath);
|
|
7
|
+
}
|
|
8
|
+
export function isFileNotFoundError(error) {
|
|
9
|
+
return (error instanceof Error &&
|
|
10
|
+
'code' in error &&
|
|
11
|
+
error.code === 'ENOENT');
|
|
12
|
+
}
|
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.12",
|
|
4
4
|
"description": "OpenCode plugin that orchestrates Claude Code sessions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"opencode",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"@vitest/coverage-v8": "^4.1.0",
|
|
41
41
|
"eslint": "^9.22.0",
|
|
42
42
|
"globals": "^15.15.0",
|
|
43
|
+
"knip": "^6.0.2",
|
|
43
44
|
"prettier": "^3.8.1",
|
|
44
45
|
"typescript": "^5.9.3",
|
|
45
46
|
"typescript-eslint": "^8.57.1",
|
|
@@ -51,6 +52,7 @@
|
|
|
51
52
|
"lint": "eslint .",
|
|
52
53
|
"format": "prettier --write .",
|
|
53
54
|
"test": "vitest run",
|
|
55
|
+
"knip": "knip",
|
|
54
56
|
"release": "pnpm run build && pnpm version patch && pnpm publish"
|
|
55
57
|
}
|
|
56
58
|
}
|