@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 +28 -24
- package/dist/bootstrap.js +5 -5
- package/dist/bootstrap.js.map +1 -1
- package/dist/drivers/opencode.d.ts +3 -0
- package/dist/drivers/opencode.d.ts.map +1 -0
- package/dist/drivers/opencode.js +176 -0
- package/dist/drivers/opencode.js.map +1 -0
- package/dist/engine.d.ts +3 -34
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +135 -41
- package/dist/engine.js.map +1 -1
- package/dist/hooks.d.ts +3 -2
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +7 -2
- package/dist/hooks.js.map +1 -1
- package/dist/pipeline-runner.d.ts +22 -18
- package/dist/pipeline-runner.d.ts.map +1 -1
- package/dist/pipeline-runner.js +69 -52
- package/dist/pipeline-runner.js.map +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +0 -1
- package/dist/registry.js.map +1 -1
- package/dist/schema.js +4 -4
- package/dist/schema.js.map +1 -1
- package/dist/schema.test.js +3 -3
- package/dist/schema.test.js.map +1 -1
- package/dist/sdk.d.ts +1 -1
- package/dist/sdk.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/bootstrap.ts +5 -5
- package/src/drivers/opencode.ts +204 -0
- package/src/engine.ts +159 -76
- package/src/hooks.ts +8 -2
- package/src/pipeline-runner.ts +73 -56
- package/src/registry.ts +0 -1
- package/src/schema.test.ts +3 -3
- package/src/schema.ts +4 -4
- package/src/sdk.ts +1 -1
- package/src/drivers/claude-code.ts +0 -250
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 (
|
|
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:
|
|
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 `
|
|
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:
|
|
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:
|
|
99
|
-
model:
|
|
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:
|
|
117
|
-
model:
|
|
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: `
|
|
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 (
|
|
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 `
|
|
298
|
-
- `
|
|
299
|
-
- `
|
|
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
|
-
- `
|
|
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
|
|
316
|
+
// Subscribe before start — handler is called for every RunEventPayload
|
|
313
317
|
const unsubscribe = runner.subscribe((event) => {
|
|
314
|
-
tauriEmit('
|
|
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
|
-
//
|
|
323
|
-
//
|
|
324
|
-
const
|
|
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 `
|
|
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)
|
|
565
|
-
| [@tagma/driver-
|
|
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
|
|
4
|
-
// workspace plugins under
|
|
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-
|
|
7
|
-
import {
|
|
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', '
|
|
19
|
+
registerPlugin('drivers', 'opencode', OpenCodeDriver);
|
|
20
20
|
// Triggers
|
|
21
21
|
registerPlugin('triggers', 'file', FileTrigger);
|
|
22
22
|
registerPlugin('triggers', 'manual', ManualTrigger);
|
package/dist/bootstrap.js.map
CHANGED
|
@@ -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,
|
|
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 @@
|
|
|
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,
|
|
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
|
|
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:
|
|
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
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EAEd,SAAS,
|
|
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"}
|