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 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
- name: 'my-pipeline',
59
- defaultModel: { providerID: 'anthropic', modelID: 'claude-sonnet-4-20250514' },
60
- defaultAgent: 'default',
61
- }, createBaseState)
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
- const pipeline = new Pipeline({
68
- name: 'my-pipeline',
69
- defaultModel: { backend: 'claude-code', providerID: 'anthropic', modelID: 'claude-sonnet-4-20250514' },
70
- defaultAgent: 'default',
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ocpipe",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "SDK for LLM pipelines with OpenCode and Zod",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
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(`[DEBUG] Running: ${opencodeCmd.cmd} ${opencodeCmd.args.join(' ')}`)
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
- { pattern: /ProviderModelNotFoundError/, message: 'Provider/model not found' },
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
- { pattern: /authentication.*failed/i, message: 'Authentication failed' },
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.split('\n').filter(line =>
149
- pattern.test(line) || line.includes('Error') || line.includes('error:')
150
- ).slice(0, 5).join('\n')
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(new Error(`OpenCode returned empty response with errors:\n${lastLines}`))
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
- providerID: string
33
+ /** Provider ID (required for OpenCode, ignored for Claude Code). */
34
+ providerID?: string
34
35
  modelID: string
35
36
  }
36
37