@tagma/sdk 0.4.19 → 0.5.1

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
@@ -15,7 +15,7 @@
15
15
  > the npm registry website and cannot be removed — please ignore it and use
16
16
  > the command above.)_
17
17
 
18
- A local AI task orchestration SDK for [Bun](https://bun.sh). Define multi-track pipelines in YAML, run AI coding agents (Claude Code, Codex, OpenCode) and shell commands in parallel with dependency resolution, approval gates, and lifecycle hooks.
18
+ A local AI task orchestration SDK for [Bun](https://bun.sh). Define multi-track pipelines in YAML, run AI coding agents (OpenCode, Codex, Claude Code) and shell commands in parallel with dependency resolution, approval gates, and lifecycle hooks.
19
19
 
20
20
  ## Install
21
21
 
@@ -35,7 +35,7 @@ pipeline:
35
35
  tracks:
36
36
  - id: backend
37
37
  name: Backend
38
- driver: claude-code
38
+ driver: opencode
39
39
  permissions: { read: true, write: true, execute: false }
40
40
  tasks:
41
41
  - id: implement
@@ -65,7 +65,7 @@ console.log(result.success ? 'Done' : 'Failed');
65
65
  ## Features
66
66
 
67
67
  - **Multi-track DAG execution** -- tasks run in parallel across tracks, respecting `depends_on` ordering
68
- - **Driver plugins** -- built-in `claude-code` driver; install `@tagma/driver-codex` or `@tagma/driver-opencode` for other agents
68
+ - **Driver plugins** -- built-in `opencode` driver; install `@tagma/driver-codex` or `@tagma/driver-claude-code` for other agents
69
69
  - **Session handoff** -- `continue_from` passes context between tasks (session resume or text injection)
70
70
  - **Approval gates** -- trigger-based approval with stdin and WebSocket adapters
71
71
  - **Lifecycle hooks** -- `pipeline_start`, `task_start`, `task_success`, `task_failure`, `pipeline_complete`, `pipeline_error`
@@ -80,10 +80,11 @@ console.log(result.success ? 'Done' : 'Failed');
80
80
  ```yaml
81
81
  pipeline:
82
82
  name: my-pipeline
83
- driver: claude-code
83
+ driver: opencode
84
84
  timeout: 30m
85
85
  plugins:
86
86
  - '@tagma/driver-codex'
87
+ - '@tagma/driver-claude-code'
87
88
  hooks:
88
89
  pipeline_start: 'echo starting'
89
90
  task_start: 'echo task begin'
@@ -95,8 +96,8 @@ pipeline:
95
96
  - id: track-1
96
97
  name: Track One
97
98
  color: '#3b82f6'
98
- driver: claude-code
99
- model: claude-sonnet-4-6
99
+ driver: opencode
100
+ model: opencode/big-pickle
100
101
  agent_profile: senior
101
102
  cwd: ./services/backend
102
103
  permissions:
@@ -113,8 +114,8 @@ pipeline:
113
114
  name: Do something
114
115
  prompt: 'Your prompt here'
115
116
  timeout: 10m
116
- driver: claude-code
117
- model: claude-sonnet-4-6
117
+ driver: opencode
118
+ model: opencode/big-pickle
118
119
  agent_profile: senior
119
120
  cwd: ./src
120
121
  permissions:
@@ -143,7 +144,7 @@ pipeline:
143
144
  | Field | Type | Required | Description |
144
145
  | --------- | --------------- | -------- | ------------------------------------------------------------------------------------------ |
145
146
  | `name` | `string` | Yes | Pipeline name, used in logs and run IDs |
146
- | `driver` | `string` | No | Default driver for all tracks/tasks (inherited). Built-in: `claude-code` |
147
+ | `driver` | `string` | No | Default driver for all tracks/tasks (inherited). Built-in: `opencode` |
147
148
  | `model` | `string` | No | Default model for all tracks/tasks (inherited). Exact model name, e.g. `claude-sonnet-4-6` |
148
149
  | `timeout` | `string` | No | Pipeline-level timeout. Format: `"30s"`, `"5m"`, `"2h"` |
149
150
  | `plugins` | `string[]` | No | External plugin packages to load, e.g. `["@tagma/driver-codex"]` |
@@ -280,7 +281,7 @@ Track-level `middlewares` apply to all tasks in the track. Setting task-level `m
280
281
 
281
282
  ### `bootstrapBuiltins()`
282
283
 
283
- Registers all built-in plugins (claude-code driver, file/manual triggers, completion checks, static-context middleware).
284
+ Registers all built-in plugins (opencode driver, file/manual triggers, completion checks, static-context middleware).
284
285
 
285
286
  ### `loadPipeline(yaml: string, workDir: string): Promise<PipelineConfig>`
286
287
 
@@ -294,24 +295,27 @@ Options:
294
295
 
295
296
  - `approvalGateway` -- custom `ApprovalGateway` instance (defaults to `InMemoryApprovalGateway`)
296
297
  - `signal` -- `AbortSignal` to cancel the run externally
297
- - `onEvent` -- callback for real-time `PipelineEvent` updates:
298
- - `pipeline_start` — pipeline began; includes `states: ReadonlyMap<taskId, TaskState>` (initial snapshot of all tasks at `waiting`)
299
- - `task_status_change` — a task changed status; includes `state: TaskState` (complete snapshot at the time of change: `startedAt` is populated before the `running` event; `result` and `finishedAt` are populated before any terminal-status event)
298
+ - `onEvent` -- callback for real-time `RunEventPayload` updates. Every payload carries `runId`. The editor server stamps a per-run `seq` on top of this payload before broadcasting over SSE (producing a `WireRunEvent`); the SDK itself does not stamp `seq`. Event variants:
299
+ - `run_start` — pipeline approved and all tasks transitioned to `waiting`; includes `tasks: RunTaskState[]` (wire-shape snapshot of every task). Fires only when the `pipeline_start` hook allows the run — blocked pipelines emit no wire events at all.
300
+ - `task_update` — a task's status or result changed; flat fields (`status`, `startedAt?`, `finishedAt?`, `durationMs?`, `exitCode?`, `stdout?`, `stderr?`, `stderrPath?`, `sessionId?`, `normalizedOutput?`, `resolvedDriver?`, `resolvedModel?`, `resolvedPermissions?`) so clients can fold partial updates with `??` semantics. `startedAt` is populated before the `running` transition; `finishedAt` and result fields are populated before any terminal-status transition. Terminal-state locking in the engine guarantees at most one terminal event per task.
300
301
  - `task_log` — a structured log line was written to `pipeline.log`. Mirrors every `Logger` call (info/warn/error/debug/section/quiet) and carries `{ taskId: string | null, level, timestamp, text }`. `taskId` is non-null for lines tagged with a `[task:<id>]` prefix (or passed explicitly to `section`/`quiet`) and `null` for pipeline-wide messages such as the configuration dump and DAG topology. Use this to stream the full run process into UIs without tailing the log file.
301
- - `pipeline_end` — pipeline finished; includes `success: boolean`
302
+ - `run_end` — pipeline finished; includes `success: boolean` and `abortReason: 'timeout' | 'stop_all' | 'external' | null`. `null` means the run completed on its own steam (success may still be `false` if tasks failed).
303
+ - `run_error` — reserved for fatal engine errors surfaced over the wire.
304
+ - `approval_request` / `approval_resolved` — bridged from the approval gateway so hosts see approvals on the same channel as task updates, without separately subscribing to the gateway.
302
305
  - `runId` -- caller-supplied run ID. When provided the engine uses this instead of generating its own, keeping the caller and the SDK log directories aligned on the same ID
303
306
  - `maxLogRuns` -- number of per-run log directories to keep under `<workDir>/.tagma/logs/` (default: 20)
307
+ - `skipPluginLoading` -- skip the engine's built-in `loadPlugins(config.plugins)` call. Set this when the host has already pre-loaded plugins from a custom resolution path (e.g. the editor loading from the user's workspace `node_modules`) so the engine doesn't re-resolve them via Node's default cwd-based import.
304
308
 
305
309
  ### `PipelineRunner`
306
310
 
307
311
  Higher-level wrapper for managing multiple concurrent pipeline runs — designed for sidecar / Tauri IPC scenarios where the frontend controls pipeline lifecycle by ID.
308
312
 
309
313
  ```ts
310
- const runner = new PipelineRunner(config, workDir);
314
+ const runner = new PipelineRunner(config, workDir, options?); // options: Omit<RunPipelineOptions, 'signal' | 'onEvent'>
311
315
 
312
- // Subscribe before start — handler is called for every PipelineEvent
316
+ // Subscribe before start — handler is called for every RunEventPayload
313
317
  const unsubscribe = runner.subscribe((event) => {
314
- tauriEmit('pipeline_event', { id: runner.instanceId, event });
318
+ tauriEmit('run_event', { id: runner.instanceId, event });
315
319
  });
316
320
 
317
321
  runner.start(); // returns Promise<EngineResult>, idempotent
@@ -319,16 +323,16 @@ runner.start(); // returns Promise<EngineResult>, idempotent
319
323
  // Cancel from IPC
320
324
  runner.abort();
321
325
 
322
- // Available from the first pipeline_start event onward (not just after completion)
323
- // Returns null only if the pipeline has never started
324
- const states = runner.getStates(); // ReadonlyMap<taskId, TaskState> | null
326
+ // Live wire-shape task mirror, maintained from run_start + task_update events.
327
+ // Empty map before the first run_start; safe to read at any time.
328
+ const tasks = runner.getTasks(); // ReadonlyMap<taskId, RunTaskState>
325
329
  ```
326
330
 
327
331
  Properties:
328
332
 
329
333
  - `instanceId` — stable ID assigned at construction, safe to use as a Map key before `start()`
330
- - `runId` — engine-assigned run ID, available after the first `pipeline_start` event (`null` until then)
331
- - `status` — `'idle' | 'running' | 'done' | 'aborted'`
334
+ - `runId` — engine-assigned run ID, available after the first `run_start` event (`null` until then)
335
+ - `status` — `'idle' | 'running' | 'done' | 'aborted'` (see `PipelineRunnerStatus`)
332
336
 
333
337
  ### `TriggerBlockedError` / `TriggerTimeoutError`
334
338
 
@@ -561,8 +565,8 @@ Truncates `text` to at most `maxBytes` UTF-8 bytes (default 16 KB), appending a
561
565
  | Package | Description |
562
566
  | ------------------------------------------------------------------------------ | -------------------------- |
563
567
  | [@tagma/types](https://www.npmjs.com/package/@tagma/types) | Shared TypeScript types |
564
- | [@tagma/driver-codex](https://www.npmjs.com/package/@tagma/driver-codex) | Codex CLI driver plugin |
565
- | [@tagma/driver-opencode](https://www.npmjs.com/package/@tagma/driver-opencode) | OpenCode CLI driver plugin |
568
+ | [@tagma/driver-codex](https://www.npmjs.com/package/@tagma/driver-codex) | Codex CLI driver plugin |
569
+ | [@tagma/driver-claude-code](https://www.npmjs.com/package/@tagma/driver-claude-code) | Claude Code CLI driver plugin |
566
570
 
567
571
  ## License
568
572
 
package/dist/bootstrap.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { registerPlugin } from './registry';
2
2
  // Built-in Drivers
3
- // Only claude-code is built in. Other drivers (codex, opencode) ship as
4
- // workspace plugins under plugins/ and must be declared in pipeline.yaml
3
+ // Only opencode is built in. Other drivers (codex, claude-code) ship as
4
+ // workspace plugins under packages/ and must be declared in pipeline.yaml
5
5
  // via the `plugins` field, e.g.:
6
- // plugins: ["@tagma/driver-codex", "@tagma/driver-opencode"]
7
- import { ClaudeCodeDriver } from './drivers/claude-code';
6
+ // plugins: ["@tagma/driver-codex", "@tagma/driver-claude-code"]
7
+ import { OpenCodeDriver } from './drivers/opencode';
8
8
  // Built-in Triggers
9
9
  import { FileTrigger } from './triggers/file';
10
10
  import { ManualTrigger } from './triggers/manual';
@@ -16,7 +16,7 @@ import { OutputCheckCompletion } from './completions/output-check';
16
16
  import { StaticContextMiddleware } from './middlewares/static-context';
17
17
  export function bootstrapBuiltins() {
18
18
  // Drivers
19
- registerPlugin('drivers', 'claude-code', ClaudeCodeDriver);
19
+ registerPlugin('drivers', 'opencode', OpenCodeDriver);
20
20
  // Triggers
21
21
  registerPlugin('triggers', 'file', FileTrigger);
22
22
  registerPlugin('triggers', 'manual', ManualTrigger);
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,mBAAmB;AACnB,wEAAwE;AACxE,yEAAyE;AACzE,iCAAiC;AACjC,+DAA+D;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,oBAAoB;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,uBAAuB;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,sBAAsB;AACtB,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,MAAM,UAAU,iBAAiB;IAC/B,UAAU;IACV,cAAc,CAAC,SAAS,EAAE,aAAa,EAAE,gBAAgB,CAAC,CAAC;IAE3D,WAAW;IACX,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IAChD,cAAc,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IAEpD,cAAc;IACd,cAAc,CAAC,aAAa,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAC;IAC/D,cAAc,CAAC,aAAa,EAAE,aAAa,EAAE,oBAAoB,CAAC,CAAC;IACnE,cAAc,CAAC,aAAa,EAAE,cAAc,EAAE,qBAAqB,CAAC,CAAC;IAErE,cAAc;IACd,cAAc,CAAC,aAAa,EAAE,gBAAgB,EAAE,uBAAuB,CAAC,CAAC;AAC3E,CAAC"}
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,mBAAmB;AACnB,wEAAwE;AACxE,0EAA0E;AAC1E,iCAAiC;AACjC,kEAAkE;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,oBAAoB;AACpB,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,uBAAuB;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,sBAAsB;AACtB,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,MAAM,UAAU,iBAAiB;IAC/B,UAAU;IACV,cAAc,CAAC,SAAS,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;IAEtD,WAAW;IACX,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IAChD,cAAc,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IAEpD,cAAc;IACd,cAAc,CAAC,aAAa,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAC;IAC/D,cAAc,CAAC,aAAa,EAAE,aAAa,EAAE,oBAAoB,CAAC,CAAC;IACnE,cAAc,CAAC,aAAa,EAAE,cAAc,EAAE,qBAAqB,CAAC,CAAC;IAErE,cAAc;IACd,cAAc,CAAC,aAAa,EAAE,gBAAgB,EAAE,uBAAuB,CAAC,CAAC;AAC3E,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { DriverPlugin } from '../types';
2
+ export declare const OpenCodeDriver: DriverPlugin;
3
+ //# sourceMappingURL=opencode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../src/drivers/opencode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAOb,MAAM,UAAU,CAAC;AAyBlB,eAAO,MAAM,cAAc,EAAE,YA0K5B,CAAC"}
@@ -0,0 +1,176 @@
1
+ const DEFAULT_MODEL = 'opencode/big-pickle';
2
+ // NOTE on Windows multi-line prompts: `opencode` resolves to `opencode.cmd`,
3
+ // an npm-generated batch wrapper. cmd.exe silently truncates argv elements
4
+ // at the first newline, so a multi-line prompt reaches the model as only
5
+ // its first line. The SDK's runner auto-unwraps npm .cmd shims into direct
6
+ // `node <js-entry>` invocations so newlines survive, and this driver can
7
+ // keep using the bare `opencode` name on every platform.
8
+ // tagma uses a provider-neutral reasoning_effort vocabulary (low|medium|high)
9
+ // but opencode's `--variant` is provider-specific (e.g. high|max|minimal).
10
+ // Map the tagma values to the closest opencode variant:
11
+ // low → minimal (least thinking)
12
+ // medium → <no flag, provider default>
13
+ // high → high (most thinking)
14
+ // Unknown values pass through unchanged so users who target a specific
15
+ // opencode variant (e.g. "max") still work.
16
+ const EFFORT_TO_VARIANT = {
17
+ low: 'minimal',
18
+ medium: null,
19
+ high: 'high',
20
+ };
21
+ export const OpenCodeDriver = {
22
+ name: 'opencode',
23
+ capabilities: {
24
+ sessionResume: true, // supports --session
25
+ systemPrompt: false, // no --system-prompt flag; prepend to prompt instead
26
+ outputFormat: true, // supports --format json
27
+ },
28
+ resolveModel() {
29
+ return DEFAULT_MODEL;
30
+ },
31
+ async buildCommand(task, track, ctx) {
32
+ const model = task.model ?? track.model ?? DEFAULT_MODEL;
33
+ // Resolve reasoning_effort → opencode --variant. SDK schema layer already
34
+ // resolved task → track → pipeline inheritance, so we only need to read
35
+ // task.reasoning_effort here.
36
+ const rawEffort = task.reasoning_effort ?? track.reasoning_effort;
37
+ const variant = rawEffort
38
+ ? rawEffort in EFFORT_TO_VARIANT
39
+ ? EFFORT_TO_VARIANT[rawEffort]
40
+ : rawEffort
41
+ : null;
42
+ let prompt = task.prompt;
43
+ // agent_profile has no dedicated flag; prepend to prompt
44
+ const profile = task.agent_profile ?? track.agent_profile;
45
+ if (profile) {
46
+ prompt = `[Role]\n${profile}\n\n[Task]\n${prompt}`;
47
+ }
48
+ // continue_from: prefer session resume, fall back to text injection
49
+ let sessionId = null;
50
+ if (task.continue_from) {
51
+ sessionId = ctx.sessionMap.get(task.continue_from) ?? null;
52
+ if (!sessionId) {
53
+ // no session — degrade to text context passthrough
54
+ let prev = null;
55
+ if (ctx.normalizedMap.has(task.continue_from)) {
56
+ prev = ctx.normalizedMap.get(task.continue_from);
57
+ }
58
+ if (prev !== null) {
59
+ prompt = `[Previous Output]\n${prev}\n\n[Current Task]\n${prompt}`;
60
+ }
61
+ }
62
+ }
63
+ // opencode run does not support stdin (no `-` placeholder like codex exec).
64
+ // Prompt is always a positional argument. Flags must be declared before `--`;
65
+ // the prompt follows after so that leading `--flag` content cannot be
66
+ // misread by opencode's argument parser (flag-injection mitigation).
67
+ // Shell-level injection is already prevented by Bun.spawn's direct argv array.
68
+ // Windows cmd.exe argv truncation on the `.cmd` wrapper is handled by the
69
+ // SDK runner's shim unwrapping — see note at the top of this file.
70
+ const args = [
71
+ 'opencode',
72
+ 'run',
73
+ '--model',
74
+ model,
75
+ '--format',
76
+ 'json', // JSON output for parseResult
77
+ ];
78
+ // `--variant` must precede `--` like every other flag. opencode rejects
79
+ // unknown variant names with a clear error, so we don't pre-validate.
80
+ if (variant) {
81
+ args.push('--variant', variant);
82
+ }
83
+ // session resume (must appear before --)
84
+ if (sessionId) {
85
+ args.push('--session', sessionId);
86
+ }
87
+ // `--` (POSIX end-of-options) isolates prompt from flag parsing
88
+ args.push('--', prompt);
89
+ return { args, cwd: task.cwd ?? ctx.workDir };
90
+ },
91
+ parseResult(stdout) {
92
+ // opencode --format json emits NDJSON — one JSON object per line
93
+ // (step_start / text / step_finish / …). The previous single
94
+ // `JSON.parse(stdout)` always threw on this shape and fell through to
95
+ // the catch, returning sessionId:null and losing session resume.
96
+ // Walk line-by-line, pick up the first sessionID we see, concatenate
97
+ // any text-type parts into normalizedOutput, and bail early on error
98
+ // payloads.
99
+ const lines = stdout.split(/\r?\n/);
100
+ let sessionId;
101
+ const textParts = [];
102
+ let sawAnyJson = false;
103
+ let errorReason = null;
104
+ for (const raw of lines) {
105
+ const line = raw.trim();
106
+ if (!line)
107
+ continue;
108
+ let json;
109
+ try {
110
+ json = JSON.parse(line);
111
+ }
112
+ catch {
113
+ continue; // tolerate interleaved non-JSON noise
114
+ }
115
+ sawAnyJson = true;
116
+ // M12: opencode sometimes emits {type:"error", error:{...}} with
117
+ // exit 0 for transient API failures. Force-fail so downstream
118
+ // skip_downstream / stop_all kicks in.
119
+ if (json.type === 'error') {
120
+ const err = json.error;
121
+ const msg = typeof err === 'object' && err !== null && typeof err.message === 'string'
122
+ ? err.message
123
+ : typeof err === 'string'
124
+ ? err
125
+ : null;
126
+ errorReason = msg
127
+ ? `opencode reported error: ${msg}`
128
+ : 'opencode emitted an error JSON payload';
129
+ // D21: stop at the first error. Continuing meant subsequent text
130
+ // lines got accumulated into `textParts` only to be discarded by
131
+ // the error-return below, and a later `{type:"error"}` would
132
+ // silently overwrite the original cause — operators then debugged
133
+ // a downstream symptom while the root-cause line scrolled past.
134
+ break;
135
+ }
136
+ // Session id — opencode uses `sessionID` (camelCase with capital D).
137
+ // Keep `session_id` / `sessionId` as fallbacks for forward/backward
138
+ // compatibility with other shapes.
139
+ if (!sessionId) {
140
+ const sid = json.sessionID ??
141
+ json.session_id ??
142
+ json.sessionId ??
143
+ null;
144
+ if (typeof sid === 'string' && sid.length > 0)
145
+ sessionId = sid;
146
+ }
147
+ // Extract human-readable text from text-type parts.
148
+ if (json.type === 'text') {
149
+ const part = json.part;
150
+ if (part && typeof part.text === 'string') {
151
+ textParts.push(part.text);
152
+ }
153
+ }
154
+ else if (typeof json.result === 'string') {
155
+ textParts.push(json.result);
156
+ }
157
+ else if (typeof json.content === 'string') {
158
+ textParts.push(json.content);
159
+ }
160
+ }
161
+ if (errorReason) {
162
+ return { forceFailure: true, forceFailureReason: errorReason };
163
+ }
164
+ // If nothing parsed as JSON, treat stdout as plain text.
165
+ const normalizedOutput = !sawAnyJson
166
+ ? stdout
167
+ : textParts.length > 0
168
+ ? textParts.join('\n')
169
+ : stdout;
170
+ return {
171
+ sessionId,
172
+ normalizedOutput,
173
+ };
174
+ },
175
+ };
176
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/drivers/opencode.ts"],"names":[],"mappings":"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"}
package/dist/engine.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- import type { PipelineConfig, TaskState, TaskStatus } from './types';
2
- import { type LogLevel } from './logger';
1
+ import type { PipelineConfig, TaskState, RunEventPayload } from './types';
3
2
  import { type ApprovalGateway } from './approval';
4
3
  export declare class TriggerBlockedError extends Error {
5
4
  readonly code: "TRIGGER_BLOCKED";
@@ -23,37 +22,7 @@ export interface EngineResult {
23
22
  };
24
23
  readonly states: ReadonlyMap<string, TaskState>;
25
24
  }
26
- export type PipelineEvent = {
27
- readonly type: 'task_status_change';
28
- readonly taskId: string;
29
- readonly status: TaskStatus;
30
- readonly prevStatus: TaskStatus;
31
- readonly runId: string;
32
- readonly state: TaskState;
33
- } | {
34
- readonly type: 'pipeline_start';
35
- readonly runId: string;
36
- readonly states: ReadonlyMap<string, TaskState>;
37
- } | {
38
- readonly type: 'pipeline_end';
39
- readonly runId: string;
40
- readonly success: boolean;
41
- }
42
- /**
43
- * Fine-grained log line emitted alongside every write to pipeline.log.
44
- * Consumers use this to stream the full run process into UIs without
45
- * tailing the log file. `taskId` is non-null for task-scoped lines and
46
- * null for pipeline-wide messages (e.g. configuration dumps, DAG
47
- * topology, pipeline start/end).
48
- */
49
- | {
50
- readonly type: 'task_log';
51
- readonly runId: string;
52
- readonly taskId: string | null;
53
- readonly level: LogLevel;
54
- readonly timestamp: string;
55
- readonly text: string;
56
- };
25
+ export type { RunEventPayload } from './types';
57
26
  export interface RunPipelineOptions {
58
27
  readonly approvalGateway?: ApprovalGateway;
59
28
  /**
@@ -76,7 +45,7 @@ export interface RunPipelineOptions {
76
45
  * Called on every pipeline/task status transition.
77
46
  * Use for real-time UI updates (e.g. updating a visual workflow graph).
78
47
  */
79
- readonly onEvent?: (event: PipelineEvent) => void;
48
+ readonly onEvent?: (event: RunEventPayload) => void;
80
49
  /**
81
50
  * Skip the engine's built-in `loadPlugins(config.plugins)` call.
82
51
  * Use this when the host has already pre-loaded plugins from a custom
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EAEd,SAAS,EACT,UAAU,EAUX,MAAM,SAAS,CAAC;AAgBjB,OAAO,EAA2B,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAA2B,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAM3E,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,EAAG,iBAAiB,CAAU;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,EAAG,iBAAiB,CAAU;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AA6ED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACjD;AAID,MAAM,MAAM,aAAa,GACrB;IACE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;CAC3B,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACjD,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE;AACtF;;;;;;GAMG;GACD;IACE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAEN,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;IAC3C;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAClD;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACtC;AAWD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,YAAY,CAAC,CAm1BvB"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EAEd,SAAS,EAaT,eAAe,EAEhB,MAAM,SAAS,CAAC;AAiBjB,OAAO,EAA2B,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAM3E,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,EAAG,iBAAiB,CAAU;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,EAAG,iBAAiB,CAAU;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AA6ED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACjD;AAWD,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAuC/C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;IAC3C;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CACtC;AAWD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,YAAY,CAAC,CAm5BvB"}