ocpipe 0.5.2 → 0.5.3
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 +15 -22
- package/package.json +1 -1
- package/src/agent.ts +29 -7
- package/src/types.ts +2 -1
package/README.md
CHANGED
|
@@ -54,33 +54,26 @@ ocpipe supports two backends for running LLM agents:
|
|
|
54
54
|
**OpenCode** (default) - Requires `opencode` CLI in your PATH. Supports 75+ providers.
|
|
55
55
|
|
|
56
56
|
```typescript
|
|
57
|
-
const pipeline = new Pipeline(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
const pipeline = new Pipeline(
|
|
58
|
+
{
|
|
59
|
+
name: 'my-pipeline',
|
|
60
|
+
defaultModel: {
|
|
61
|
+
providerID: 'anthropic',
|
|
62
|
+
modelID: 'claude-sonnet-4-20250514',
|
|
63
|
+
},
|
|
64
|
+
defaultAgent: 'default',
|
|
65
|
+
},
|
|
66
|
+
createBaseState,
|
|
67
|
+
)
|
|
62
68
|
```
|
|
63
69
|
|
|
64
70
|
**Claude Code** - Uses `@anthropic-ai/claude-agent-sdk`. Install as a peer dependency.
|
|
65
71
|
|
|
66
72
|
```typescript
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
// Permission mode controls what Claude Code can do without prompting
|
|
72
|
-
// Options: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan'
|
|
73
|
-
claudeCode: { permissionMode: 'acceptEdits' }, // default: auto-approve file writes
|
|
74
|
-
}, createBaseState)
|
|
75
|
-
|
|
76
|
-
// To bypass all permission prompts (use with caution):
|
|
77
|
-
const pipeline = new Pipeline({
|
|
78
|
-
...config,
|
|
79
|
-
claudeCode: {
|
|
80
|
-
permissionMode: 'bypassPermissions',
|
|
81
|
-
dangerouslySkipPermissions: true, // required safety flag
|
|
82
|
-
},
|
|
83
|
-
}, createBaseState)
|
|
73
|
+
// modelID: 'opus', 'sonnet', or 'haiku'
|
|
74
|
+
defaultModel: { backend: 'claude-code', modelID: 'sonnet' },
|
|
75
|
+
// permissionMode: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan'
|
|
76
|
+
claudeCode: { permissionMode: 'acceptEdits' },
|
|
84
77
|
```
|
|
85
78
|
|
|
86
79
|
### Requirements
|
package/package.json
CHANGED
package/src/agent.ts
CHANGED
|
@@ -36,6 +36,9 @@ async function runOpencodeAgent(
|
|
|
36
36
|
): Promise<RunAgentResult> {
|
|
37
37
|
const { prompt, agent, model, sessionId, timeoutSec = 600, workdir } = options
|
|
38
38
|
|
|
39
|
+
if (!model.providerID) {
|
|
40
|
+
throw new Error('providerID is required for OpenCode backend')
|
|
41
|
+
}
|
|
39
42
|
const modelStr = `${model.providerID}/${model.modelID}`
|
|
40
43
|
const sessionInfo = sessionId ? `[session:${sessionId}]` : '[new session]'
|
|
41
44
|
const promptPreview = prompt.slice(0, 50).replace(/\n/g, ' ')
|
|
@@ -71,7 +74,9 @@ async function runOpencodeAgent(
|
|
|
71
74
|
|
|
72
75
|
return new Promise((resolve, reject) => {
|
|
73
76
|
const opencodeCmd = getOpencodeCommand(args)
|
|
74
|
-
console.error(
|
|
77
|
+
console.error(
|
|
78
|
+
`[DEBUG] Running: ${opencodeCmd.cmd} ${opencodeCmd.args.join(' ')}`,
|
|
79
|
+
)
|
|
75
80
|
const proc = spawn(opencodeCmd.cmd, opencodeCmd.args, {
|
|
76
81
|
cwd,
|
|
77
82
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
@@ -135,19 +140,32 @@ async function runOpencodeAgent(
|
|
|
135
140
|
|
|
136
141
|
// Check for OpenCode errors that exit with code 0 but produce no output
|
|
137
142
|
const knownErrors = [
|
|
138
|
-
{
|
|
143
|
+
{
|
|
144
|
+
pattern: /ProviderModelNotFoundError/,
|
|
145
|
+
message: 'Provider/model not found',
|
|
146
|
+
},
|
|
139
147
|
{ pattern: /ModelNotFoundError/, message: 'Model not found' },
|
|
140
148
|
{ pattern: /ProviderNotFoundError/, message: 'Provider not found' },
|
|
141
149
|
{ pattern: /API key.*not.*found/i, message: 'API key not configured' },
|
|
142
|
-
{
|
|
150
|
+
{
|
|
151
|
+
pattern: /authentication.*failed/i,
|
|
152
|
+
message: 'Authentication failed',
|
|
153
|
+
},
|
|
143
154
|
]
|
|
144
155
|
|
|
145
156
|
for (const { pattern, message } of knownErrors) {
|
|
146
157
|
if (pattern.test(stderr)) {
|
|
147
158
|
// Extract the relevant error lines
|
|
148
|
-
const errorLines = stderr
|
|
149
|
-
|
|
150
|
-
|
|
159
|
+
const errorLines = stderr
|
|
160
|
+
.split('\n')
|
|
161
|
+
.filter(
|
|
162
|
+
(line) =>
|
|
163
|
+
pattern.test(line) ||
|
|
164
|
+
line.includes('Error') ||
|
|
165
|
+
line.includes('error:'),
|
|
166
|
+
)
|
|
167
|
+
.slice(0, 5)
|
|
168
|
+
.join('\n')
|
|
151
169
|
reject(new Error(`OpenCode ${message}:\n${errorLines}`))
|
|
152
170
|
return
|
|
153
171
|
}
|
|
@@ -166,7 +184,11 @@ async function runOpencodeAgent(
|
|
|
166
184
|
// Check for empty response with errors in stderr (likely a silent failure)
|
|
167
185
|
if (response.length === 0 && stderr.includes('Error')) {
|
|
168
186
|
const lastLines = stderr.split('\n').slice(-10).join('\n')
|
|
169
|
-
reject(
|
|
187
|
+
reject(
|
|
188
|
+
new Error(
|
|
189
|
+
`OpenCode returned empty response with errors:\n${lastLines}`,
|
|
190
|
+
),
|
|
191
|
+
)
|
|
170
192
|
return
|
|
171
193
|
}
|
|
172
194
|
|
package/src/types.ts
CHANGED
|
@@ -30,7 +30,8 @@ export interface ClaudeCodeOptions {
|
|
|
30
30
|
export interface ModelConfig {
|
|
31
31
|
/** Backend to use (default: 'opencode'). */
|
|
32
32
|
backend?: BackendType
|
|
33
|
-
|
|
33
|
+
/** Provider ID (required for OpenCode, ignored for Claude Code). */
|
|
34
|
+
providerID?: string
|
|
34
35
|
modelID: string
|
|
35
36
|
}
|
|
36
37
|
|