ocpipe 0.5.10 → 0.5.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/package.json +1 -1
- package/src/claude-code.ts +58 -4
- package/src/types.ts +5 -0
package/package.json
CHANGED
package/src/claude-code.ts
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
* Uses the Claude Agent SDK v2 for running LLM agents with session management.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { execSync } from 'child_process'
|
|
8
|
+
import { existsSync, readFileSync } from 'fs'
|
|
9
|
+
import { join } from 'path'
|
|
10
|
+
import { homedir } from 'os'
|
|
7
11
|
import {
|
|
8
12
|
unstable_v2_createSession,
|
|
9
13
|
unstable_v2_resumeSession,
|
|
@@ -51,6 +55,27 @@ function printToolEvent(color: string, type: string, title: string): void {
|
|
|
51
55
|
console.error(line)
|
|
52
56
|
}
|
|
53
57
|
|
|
58
|
+
/** Resolve the Claude Code executable path.
|
|
59
|
+
* Priority: 1) explicit option, 2) `which claude` from PATH, 3) common default paths. */
|
|
60
|
+
function resolveClaudeCodePath(explicit?: string): string | undefined {
|
|
61
|
+
if (explicit) return explicit
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
const found = execSync('which claude', { encoding: 'utf8', timeout: 3000 }).trim()
|
|
65
|
+
if (found) return found
|
|
66
|
+
} catch {}
|
|
67
|
+
|
|
68
|
+
const defaults = [
|
|
69
|
+
join(homedir(), '.local', 'bin', 'claude'),
|
|
70
|
+
'/usr/local/bin/claude',
|
|
71
|
+
]
|
|
72
|
+
for (const p of defaults) {
|
|
73
|
+
if (existsSync(p)) return p
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return undefined
|
|
77
|
+
}
|
|
78
|
+
|
|
54
79
|
/** Normalize model ID to Claude Code format (opus, sonnet, haiku). */
|
|
55
80
|
function normalizeModelId(modelId: string): string {
|
|
56
81
|
const lower = modelId.toLowerCase()
|
|
@@ -60,6 +85,21 @@ function normalizeModelId(modelId: string): string {
|
|
|
60
85
|
return modelId
|
|
61
86
|
}
|
|
62
87
|
|
|
88
|
+
/** loadAgentDefinition loads an OpenCode agent definition file and extracts the
|
|
89
|
+
* markdown body (stripping the YAML frontmatter) for use as a system prompt. */
|
|
90
|
+
function loadAgentDefinition(agent: string, workdir?: string): string | undefined {
|
|
91
|
+
if (!agent || !workdir) return undefined
|
|
92
|
+
|
|
93
|
+
const agentPath = join(workdir, '.opencode', 'agents', `${agent}.md`)
|
|
94
|
+
if (!existsSync(agentPath)) return undefined
|
|
95
|
+
|
|
96
|
+
const content = readFileSync(agentPath, 'utf8')
|
|
97
|
+
|
|
98
|
+
// Strip YAML frontmatter (--- delimited block at the start).
|
|
99
|
+
const stripped = content.replace(/^---\n[\s\S]*?\n---\n*/, '')
|
|
100
|
+
return stripped.trim() || undefined
|
|
101
|
+
}
|
|
102
|
+
|
|
63
103
|
/** Extract text from assistant messages. */
|
|
64
104
|
function getAssistantText(msg: SDKMessage): string | null {
|
|
65
105
|
if (msg.type !== 'assistant') return null
|
|
@@ -102,9 +142,11 @@ export async function runClaudeCodeAgent(
|
|
|
102
142
|
): Promise<RunAgentResult> {
|
|
103
143
|
const {
|
|
104
144
|
prompt,
|
|
145
|
+
agent,
|
|
105
146
|
model,
|
|
106
147
|
sessionId,
|
|
107
148
|
timeoutSec = 600,
|
|
149
|
+
workdir,
|
|
108
150
|
claudeCode,
|
|
109
151
|
signal,
|
|
110
152
|
} = options
|
|
@@ -121,9 +163,20 @@ export async function runClaudeCodeAgent(
|
|
|
121
163
|
|
|
122
164
|
// Build session options with configurable permission mode (default: acceptEdits)
|
|
123
165
|
const permissionMode = claudeCode?.permissionMode ?? 'acceptEdits'
|
|
166
|
+
|
|
167
|
+
// Resolve system prompt: explicit option > agent definition file > none
|
|
168
|
+
const systemPrompt = claudeCode?.systemPrompt ?? loadAgentDefinition(agent, workdir)
|
|
169
|
+
|
|
124
170
|
const sessionOptions: SDKSessionOptions = {
|
|
125
171
|
model: modelStr,
|
|
126
172
|
permissionMode,
|
|
173
|
+
...(workdir && { cwd: workdir }),
|
|
174
|
+
...(systemPrompt && { systemPrompt }),
|
|
175
|
+
// Enable session persistence so close+resume works.
|
|
176
|
+
// The v2 SDK defaults persistSession to false, unlike v1 which defaults to true.
|
|
177
|
+
// Without this, session.close() destroys the session and resumeSession() fails
|
|
178
|
+
// with "No conversation found with session ID".
|
|
179
|
+
...({ persistSession: true }),
|
|
127
180
|
hooks: {
|
|
128
181
|
PreToolUse: [{ hooks: [logToolCall] }],
|
|
129
182
|
},
|
|
@@ -132,10 +185,11 @@ export async function runClaudeCodeAgent(
|
|
|
132
185
|
claudeCode?.dangerouslySkipPermissions && {
|
|
133
186
|
allowDangerouslySkipPermissions: true,
|
|
134
187
|
}),
|
|
135
|
-
//
|
|
136
|
-
...(
|
|
137
|
-
|
|
138
|
-
|
|
188
|
+
// Resolve executable path: explicit option > PATH lookup > default locations
|
|
189
|
+
...(() => {
|
|
190
|
+
const resolved = resolveClaudeCodePath(claudeCode?.pathToClaudeCodeExecutable)
|
|
191
|
+
return resolved ? { pathToClaudeCodeExecutable: resolved } : {}
|
|
192
|
+
})(),
|
|
139
193
|
}
|
|
140
194
|
|
|
141
195
|
console.error(
|
package/src/types.ts
CHANGED
|
@@ -26,6 +26,11 @@ export interface ClaudeCodeOptions {
|
|
|
26
26
|
dangerouslySkipPermissions?: boolean
|
|
27
27
|
/** Path to Claude Code executable (default: auto-detected). */
|
|
28
28
|
pathToClaudeCodeExecutable?: string
|
|
29
|
+
/**
|
|
30
|
+
* System prompt for the Claude Code session.
|
|
31
|
+
* Can be a full string or use the preset format with append.
|
|
32
|
+
*/
|
|
33
|
+
systemPrompt?: string | { type: 'preset'; preset: 'claude_code'; append: string }
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
/** Model configuration for LLM backends. */
|