ocpipe 0.3.6 → 0.3.8

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/DESIGN.md CHANGED
@@ -75,7 +75,7 @@ const result = await predict.execute(
75
75
  // With configuration
76
76
  const predict = new Predict(AnalyzeCode, {
77
77
  agent: 'code-reviewer',
78
- model: { providerID: 'anthropic', modelID: 'claude-opus-4-5' },
78
+ model: { providerID: 'opencode', modelID: 'minimax-m2.1-free' },
79
79
  newSession: true,
80
80
  template: (inputs) => `...`,
81
81
  })
@@ -151,7 +151,7 @@ import { Pipeline, createBaseState } from 'ocpipe'
151
151
  const pipeline = new Pipeline(
152
152
  {
153
153
  name: 'code-review',
154
- defaultModel: { providerID: 'anthropic', modelID: 'claude-sonnet-4-5' },
154
+ defaultModel: { providerID: 'opencode', modelID: 'minimax-m2.1-free' },
155
155
  defaultAgent: 'general',
156
156
  checkpointDir: './ckpt',
157
157
  logDir: './logs',
@@ -170,7 +170,7 @@ const result = await pipeline.run(new CodeAnalyzer(), {
170
170
  // Run with step options
171
171
  const result = await pipeline.run(new CodeAnalyzer(), input, {
172
172
  name: 'analyze-main',
173
- model: { providerID: 'anthropic', modelID: 'claude-opus-4-5' },
173
+ model: { providerID: 'opencode', modelID: 'minimax-m2.1-free' },
174
174
  newSession: true,
175
175
  retry: { maxAttempts: 3 },
176
176
  })
@@ -253,7 +253,7 @@ vi.mock('./agent.js', () => ({
253
253
  }))
254
254
 
255
255
  const ctx = createMockContext({
256
- defaultModel: { providerID: 'anthropic', modelID: 'claude-sonnet-4-5' },
256
+ defaultModel: { providerID: 'opencode', modelID: 'minimax-m2.1-free' },
257
257
  })
258
258
 
259
259
  // Auto-generate mock outputs from schema
@@ -40,8 +40,8 @@ const Greet = signature({
40
40
  const pipeline = new Pipeline(
41
41
  {
42
42
  name: 'repl-demo',
43
- defaultModel: { providerID: 'anthropic', modelID: 'claude-haiku-4-5' },
44
- defaultAgent: 'code',
43
+ defaultModel: { providerID: 'opencode', modelID: 'minimax-m2.1-free' },
44
+ defaultAgent: 'default',
45
45
  },
46
46
  createBaseState,
47
47
  )
@@ -77,7 +77,7 @@ This will:
77
77
  STEP 1: Greeter
78
78
  ============================================================
79
79
 
80
- >>> OpenCode [code] [anthropic/claude-haiku-4-5] [new session]: Generate a friendly greeting for the given name...
80
+ >>> OpenCode [code] [opencode/minimax-m2.1-free] [new session]: Generate a friendly greeting for the given name...
81
81
 
82
82
  <<< OpenCode done (85 chars) [session:abc123]
83
83
 
@@ -146,8 +146,8 @@ import { Greeter } from './module.js'
146
146
  const pipeline = new Pipeline(
147
147
  {
148
148
  name: 'hello-world',
149
- defaultModel: { providerID: 'anthropic', modelID: 'claude-haiku-4-5' },
150
- defaultAgent: 'code',
149
+ defaultModel: { providerID: 'opencode', modelID: 'minimax-m2.1-free' },
150
+ defaultAgent: 'default',
151
151
  checkpointDir: './ckpt',
152
152
  logDir: './logs',
153
153
  },
@@ -221,8 +221,8 @@ async function main() {
221
221
  const pipeline = new Pipeline(
222
222
  {
223
223
  name: 'hello-goodbye',
224
- defaultModel: { providerID: 'anthropic', modelID: 'claude-haiku-4-5' },
225
- defaultAgent: 'code',
224
+ defaultModel: { providerID: 'opencode', modelID: 'minimax-m2.1-free' },
225
+ defaultAgent: 'default',
226
226
  checkpointDir: './ckpt',
227
227
  logDir: './logs',
228
228
  },
package/README.md CHANGED
@@ -32,8 +32,8 @@ const Greet = signature({
32
32
  const pipeline = new Pipeline(
33
33
  {
34
34
  name: 'hello-world',
35
- defaultModel: { providerID: 'anthropic', modelID: 'claude-haiku-4-5' },
36
- defaultAgent: 'code',
35
+ defaultModel: { providerID: 'opencode', modelID: 'minimax-m2.1-free' },
36
+ defaultAgent: 'default',
37
37
  },
38
38
  createBaseState,
39
39
  )
@@ -71,8 +71,8 @@ async function main() {
71
71
  const pipeline = new Pipeline(
72
72
  {
73
73
  name: 'correction-demo',
74
- defaultModel: { providerID: 'anthropic', modelID: 'claude-haiku-4-5' },
75
- defaultAgent: 'code',
74
+ defaultModel: { providerID: 'opencode', modelID: 'minimax-m2.1-free' },
75
+ defaultAgent: 'default',
76
76
  checkpointDir: './ckpt',
77
77
  logDir: './logs',
78
78
  },
package/example/index.ts CHANGED
@@ -12,8 +12,8 @@ async function main() {
12
12
  const pipeline = new Pipeline(
13
13
  {
14
14
  name: 'hello-world',
15
- defaultModel: { providerID: 'anthropic', modelID: 'claude-haiku-4-5' },
16
- defaultAgent: 'code',
15
+ defaultModel: { providerID: 'opencode', modelID: 'minimax-m2.1-free' },
16
+ defaultAgent: 'default',
17
17
  checkpointDir: './ckpt',
18
18
  logDir: './logs',
19
19
  },
package/llms.txt CHANGED
@@ -34,8 +34,8 @@ const Greet = signature({
34
34
  const pipeline = new Pipeline(
35
35
  {
36
36
  name: 'hello-world',
37
- defaultModel: { providerID: 'anthropic', modelID: 'claude-haiku-4-5' },
38
- defaultAgent: 'code',
37
+ defaultModel: { providerID: 'opencode', modelID: 'minimax-m2.1-free' },
38
+ defaultAgent: 'default',
39
39
  checkpointDir: './ckpt',
40
40
  logDir: './logs',
41
41
  },
@@ -148,7 +148,7 @@ await pipeline.run(module, input, { newSession: true })
148
148
 
149
149
  // Model override for this step
150
150
  await pipeline.run(module, input, {
151
- model: { providerID: 'anthropic', modelID: 'claude-opus-4-5' }
151
+ model: { providerID: 'opencode', modelID: 'minimax-m2.1-free' }
152
152
  })
153
153
  ```
154
154
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ocpipe",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "SDK for LLM pipelines with OpenCode and Zod",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -29,7 +29,7 @@
29
29
  "bun": ">=1.0.0"
30
30
  },
31
31
  "dependencies": {
32
- "opencode-ai": "1.1.20"
32
+ "opencode-ai": "1.1.25"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "zod": "4.3.5"
package/src/agent.ts CHANGED
@@ -4,25 +4,43 @@
4
4
  * Wraps the OpenCode CLI for running LLM agents with session management.
5
5
  */
6
6
 
7
- import { spawn, execSync } from 'child_process'
7
+ import { spawn } from 'child_process'
8
+ import { existsSync } from 'fs'
8
9
  import { mkdir } from 'fs/promises'
10
+ import { join } from 'path'
9
11
  import { PROJECT_ROOT, TMP_DIR } from './paths.js'
10
12
  import type { RunAgentOptions, RunAgentResult } from './types.js'
11
13
 
12
- /** Check if opencode is available in system PATH */
13
- function hasSystemOpencode(): boolean {
14
- try {
15
- execSync('which opencode', { stdio: 'ignore' })
16
- return true
17
- } catch {
18
- return false
14
+ /** Find opencode binary from PATH, preferring non-node_modules locations */
15
+ function findOpencode(): string | null {
16
+ const pathDirs = (process.env.PATH || '').split(':')
17
+
18
+ // First pass: look for opencode in non-node_modules directories
19
+ for (const dir of pathDirs) {
20
+ if (dir.includes('node_modules')) continue
21
+ const candidate = join(dir, 'opencode')
22
+ if (existsSync(candidate)) {
23
+ return candidate
24
+ }
25
+ }
26
+
27
+ // Second pass: check node_modules/.bin as fallback
28
+ for (const dir of pathDirs) {
29
+ if (!dir.includes('node_modules')) continue
30
+ const candidate = join(dir, 'opencode')
31
+ if (existsSync(candidate)) {
32
+ return candidate
33
+ }
19
34
  }
35
+
36
+ return null
20
37
  }
21
38
 
22
39
  /** Get command and args to invoke opencode */
23
40
  function getOpencodeCommand(args: string[]): { cmd: string; args: string[] } {
24
- if (hasSystemOpencode()) {
25
- return { cmd: 'opencode', args }
41
+ const opencode = findOpencode()
42
+ if (opencode) {
43
+ return { cmd: opencode, args }
26
44
  }
27
45
  // Fallback to bunx with ocpipe package (which has opencode-ai as dependency)
28
46
  return { cmd: 'bunx', args: ['-p', 'ocpipe', 'opencode', ...args] }
@@ -56,11 +74,14 @@ export async function runAgent(
56
74
  args.push('--session', sessionId)
57
75
  }
58
76
 
77
+ // Pass prompt as positional argument (stdin doesn't work without TTY)
78
+ args.push(prompt)
79
+
59
80
  return new Promise((resolve, reject) => {
60
81
  const opencodeCmd = getOpencodeCommand(args)
61
82
  const proc = spawn(opencodeCmd.cmd, opencodeCmd.args, {
62
83
  cwd: workdir ?? PROJECT_ROOT,
63
- stdio: ['pipe', 'pipe', 'pipe'],
84
+ stdio: ['ignore', 'pipe', 'pipe'],
64
85
  })
65
86
 
66
87
  let newSessionId = sessionId || ''
@@ -94,10 +115,6 @@ export async function runAgent(
94
115
  process.stderr.write(text)
95
116
  })
96
117
 
97
- // Send prompt to stdin
98
- proc.stdin.write(prompt)
99
- proc.stdin.end()
100
-
101
118
  // Timeout handling (0 = no timeout)
102
119
  const timeout =
103
120
  timeoutSec > 0 ?
package/src/index.ts CHANGED
@@ -22,7 +22,7 @@
22
22
  * // Run in a pipeline
23
23
  * const pipeline = new Pipeline({
24
24
  * name: 'my-workflow',
25
- * defaultModel: { providerID: 'anthropic', modelID: 'claude-sonnet-4-5' },
25
+ * defaultModel: { providerID: 'opencode', modelID: 'minimax-m2.1-free' },
26
26
  * defaultAgent: 'general',
27
27
  * checkpointDir: './ckpt',
28
28
  * logDir: './logs',