@tagma/sdk 0.7.1 → 0.7.4
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 +109 -48
- package/dist/adapters/stdin-approval.d.ts +1 -5
- package/dist/adapters/stdin-approval.d.ts.map +1 -1
- package/dist/adapters/stdin-approval.js +1 -89
- package/dist/adapters/stdin-approval.js.map +1 -1
- package/dist/adapters/websocket-approval.d.ts +1 -27
- package/dist/adapters/websocket-approval.d.ts.map +1 -1
- package/dist/adapters/websocket-approval.js +1 -146
- package/dist/adapters/websocket-approval.js.map +1 -1
- package/dist/approval.d.ts +2 -12
- package/dist/approval.d.ts.map +1 -1
- package/dist/approval.js +1 -90
- package/dist/approval.js.map +1 -1
- package/dist/bootstrap.d.ts +21 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +21 -11
- package/dist/bootstrap.js.map +1 -1
- package/dist/core/run-context.d.ts +3 -0
- package/dist/core/run-context.d.ts.map +1 -1
- package/dist/core/run-context.js +2 -0
- package/dist/core/run-context.js.map +1 -1
- package/dist/core/task-executor.d.ts.map +1 -1
- package/dist/core/task-executor.js +24 -37
- package/dist/core/task-executor.js.map +1 -1
- package/dist/engine.d.ts +8 -53
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +7 -294
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +2 -60
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +1 -153
- package/dist/logger.js.map +1 -1
- package/dist/plugins.d.ts +3 -3
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +1 -1
- package/dist/plugins.js.map +1 -1
- package/dist/registry.d.ts +2 -60
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +1 -253
- package/dist/registry.js.map +1 -1
- package/dist/runner.d.ts +1 -35
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +1 -610
- package/dist/runner.js.map +1 -1
- package/dist/runtime/adapters/stdin-approval.d.ts +2 -0
- package/dist/runtime/adapters/stdin-approval.d.ts.map +1 -0
- package/dist/runtime/adapters/stdin-approval.js +2 -0
- package/dist/runtime/adapters/stdin-approval.js.map +1 -0
- package/dist/runtime/adapters/websocket-approval.d.ts +2 -0
- package/dist/runtime/adapters/websocket-approval.d.ts.map +1 -0
- package/dist/runtime/adapters/websocket-approval.js +2 -0
- package/dist/runtime/adapters/websocket-approval.js.map +1 -0
- package/dist/runtime/bun-process-runner.d.ts +2 -0
- package/dist/runtime/bun-process-runner.d.ts.map +1 -0
- package/dist/runtime/bun-process-runner.js +2 -0
- package/dist/runtime/bun-process-runner.js.map +1 -0
- package/dist/runtime.d.ts +3 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +2 -0
- package/dist/runtime.js.map +1 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +1 -7
- package/dist/schema.js.map +1 -1
- package/dist/tagma.d.ts +13 -4
- package/dist/tagma.d.ts.map +1 -1
- package/dist/tagma.js +7 -2
- package/dist/tagma.js.map +1 -1
- package/dist/triggers/file.d.ts.map +1 -1
- package/dist/triggers/file.js +74 -107
- package/dist/triggers/file.js.map +1 -1
- package/dist/validate-raw.d.ts.map +1 -1
- package/dist/validate-raw.js +1 -101
- package/dist/validate-raw.js.map +1 -1
- package/package.json +15 -4
- package/src/adapters/stdin-approval.ts +1 -106
- package/src/adapters/websocket-approval.ts +1 -224
- package/src/approval.ts +5 -127
- package/src/bootstrap.ts +24 -15
- package/src/core/run-context.test.ts +47 -0
- package/src/core/run-context.ts +4 -0
- package/src/core/task-executor.ts +28 -45
- package/src/engine-ports-mixed.test.ts +70 -44
- package/src/engine-ports.test.ts +77 -33
- package/src/engine.ts +21 -439
- package/src/index.ts +7 -4
- package/src/logger.ts +2 -182
- package/src/package-split.test.ts +15 -0
- package/src/pipeline-runner.test.ts +65 -12
- package/src/plugin-registry.test.ts +207 -4
- package/src/plugins.ts +6 -3
- package/src/registry.ts +7 -298
- package/src/runner.ts +1 -666
- package/src/runtime/adapters/stdin-approval.ts +1 -0
- package/src/runtime/adapters/websocket-approval.ts +1 -0
- package/src/runtime/bun-process-runner.ts +1 -0
- package/src/runtime-adapters.test.ts +10 -0
- package/src/runtime.ts +12 -0
- package/src/schema-ports.test.ts +23 -0
- package/src/schema.ts +1 -7
- package/src/tagma.test.ts +234 -1
- package/src/tagma.ts +24 -4
- package/src/triggers/file.test.ts +79 -0
- package/src/triggers/file.ts +85 -118
- package/src/validate-raw.ts +1 -117
package/README.md
CHANGED
|
@@ -64,6 +64,8 @@ console.log(result.success ? 'Done' : 'Failed');
|
|
|
64
64
|
|
|
65
65
|
The package root is intentionally small. Use explicit subpaths for YAML,
|
|
66
66
|
config editing, plugin registry helpers, and low-level dataflow utilities.
|
|
67
|
+
The SDK composes `@tagma/core` with `@tagma/runtime-bun`; import those packages
|
|
68
|
+
directly only when you need lower-level package boundaries.
|
|
67
69
|
|
|
68
70
|
## Features
|
|
69
71
|
|
|
@@ -75,8 +77,7 @@ config editing, plugin registry helpers, and low-level dataflow utilities.
|
|
|
75
77
|
- **Middleware** -- enrich prompts before execution (e.g. inject static context)
|
|
76
78
|
- **Completion checks** -- validate task output with `exit_code`, `file_exists`, or `output_check` plugins
|
|
77
79
|
- **Plugin schemas** -- triggers/completions/middlewares can declare a `PluginSchema` so visual editors render typed forms for their config
|
|
78
|
-
- **
|
|
79
|
-
- **Typed task ports** -- declare named, typed `ports.inputs` / `ports.outputs` when a task needs a strict, validated I/O contract
|
|
80
|
+
- **Unified task bindings** -- pass dynamic values with task-level `inputs` / `outputs`; add optional `type` metadata when a binding needs validation
|
|
80
81
|
|
|
81
82
|
## Pipeline YAML Reference
|
|
82
83
|
|
|
@@ -205,9 +206,8 @@ Each hook value can be a single command string or an array of commands.
|
|
|
205
206
|
| `middlewares` | `MiddlewareConfig[]` | No | Inherited from track | Middleware override. Set `[]` to disable inherited middlewares |
|
|
206
207
|
| `trigger` | `TriggerConfig` | No | — | Gate that must resolve before the task runs (see Triggers) |
|
|
207
208
|
| `completion` | `CompletionConfig` | No | — | Post-execution check to validate task output (see Completions) |
|
|
208
|
-
| `inputs` | `TaskInputBindings` | No | — |
|
|
209
|
-
| `outputs` | `TaskOutputBindings` | No | — |
|
|
210
|
-
| `ports` | `TaskPorts` | No | — | Typed input/output ports — see Typed Ports below |
|
|
209
|
+
| `inputs` | `TaskInputBindings` | No | — | Task input bindings for `{{inputs.<name>}}`; optional `type` enables coercion/validation |
|
|
210
|
+
| `outputs` | `TaskOutputBindings` | No | — | Named outputs published after success; optional `type` enables coercion/validation |
|
|
211
211
|
|
|
212
212
|
### Permissions
|
|
213
213
|
|
|
@@ -227,15 +227,17 @@ Track-level `middlewares` apply to all tasks in the track. Setting task-level `m
|
|
|
227
227
|
|
|
228
228
|
---
|
|
229
229
|
|
|
230
|
-
###
|
|
230
|
+
### Unified Task Bindings
|
|
231
231
|
|
|
232
|
-
Use task-level `inputs` / `outputs` for
|
|
232
|
+
Use task-level `inputs` / `outputs` for parameter passing. They are task-level only, do not inherit, and can stay lightweight by omitting `type`. Add `type`, `required`, `enum`, and `description` when a binding should be strict and editor-visible.
|
|
233
233
|
|
|
234
234
|
```yaml
|
|
235
235
|
- id: build
|
|
236
236
|
command: bun run build
|
|
237
237
|
outputs:
|
|
238
|
-
bundlePath:
|
|
238
|
+
bundlePath:
|
|
239
|
+
from: json.bundlePath
|
|
240
|
+
type: string
|
|
239
241
|
|
|
240
242
|
- id: test
|
|
241
243
|
depends_on: [build]
|
|
@@ -244,17 +246,18 @@ Use task-level `inputs` / `outputs` for ordinary parameter passing. They are tas
|
|
|
244
246
|
bundlePath:
|
|
245
247
|
from: t.build.outputs.bundlePath
|
|
246
248
|
required: true
|
|
249
|
+
type: string
|
|
247
250
|
```
|
|
248
251
|
|
|
249
|
-
Input bindings support `value`, `from`, `default`, and `
|
|
252
|
+
Input bindings support `value`, `from`, `default`, `required`, optional `type`, `enum`, and `description`. `from` accepts `taskId.outputs.name`, `taskId.stdout`, `taskId.stderr`, `taskId.normalizedOutput`, `taskId.exitCode`, or `outputs.name` to name-match direct upstream outputs.
|
|
250
253
|
|
|
251
|
-
Output bindings support `value`, `from`, and `
|
|
254
|
+
Output bindings support `value`, `from`, `default`, optional `type`, `enum`, and `description`. `from` defaults to `json.<outputName>` and also accepts `stdout`, `stderr`, or `normalizedOutput`.
|
|
252
255
|
|
|
253
|
-
|
|
256
|
+
Prompt tasks infer their structured input/output contract from neighboring command tasks that use typed `outputs` / `inputs`. The engine renders `[Inputs]` and `[Output Format]` blocks from that inferred contract.
|
|
254
257
|
|
|
255
258
|
---
|
|
256
259
|
|
|
257
|
-
### Typed
|
|
260
|
+
### Typed Binding Example
|
|
258
261
|
|
|
259
262
|
Tasks can declare named, typed `inputs` / `outputs`. Inputs flow in from upstream task outputs; outputs are extracted from a task's stdout (or the AI driver's `normalizedOutput`) on success.
|
|
260
263
|
|
|
@@ -262,40 +265,50 @@ Tasks can declare named, typed `inputs` / `outputs`. Inputs flow in from upstrea
|
|
|
262
265
|
- id: lookup-weather
|
|
263
266
|
name: Lookup weather
|
|
264
267
|
command: weather.sh --city "{{inputs.city}}"
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
268
|
+
inputs:
|
|
269
|
+
city:
|
|
270
|
+
type: string
|
|
271
|
+
required: true
|
|
272
|
+
description: Target city
|
|
273
|
+
outputs:
|
|
274
|
+
temperature:
|
|
275
|
+
type: number
|
|
276
|
+
description: Current temperature in Celsius
|
|
277
|
+
conditions:
|
|
278
|
+
type: enum
|
|
279
|
+
enum: [sunny, cloudy, rain, snow]
|
|
271
280
|
|
|
272
281
|
- id: write-report
|
|
273
282
|
depends_on: [lookup-weather]
|
|
274
283
|
prompt: 'Write a brief weather report for {{inputs.city}}.'
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
284
|
+
inputs:
|
|
285
|
+
city: { from: t.lookup-weather.outputs.city, type: string, required: true }
|
|
286
|
+
temperature: { from: t.lookup-weather.outputs.temperature, type: number, required: true }
|
|
287
|
+
conditions:
|
|
288
|
+
from: t.lookup-weather.outputs.conditions
|
|
289
|
+
type: enum
|
|
290
|
+
enum: [sunny, cloudy, rain, snow]
|
|
280
291
|
```
|
|
281
292
|
|
|
282
|
-
####
|
|
293
|
+
#### Binding fields
|
|
283
294
|
|
|
284
295
|
| Field | Type | Required | Description |
|
|
285
296
|
| ------------- | ----------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
286
|
-
| `
|
|
287
|
-
| `
|
|
297
|
+
| `value` | `unknown` | No | Literal value. For inputs, this wins over `from` |
|
|
298
|
+
| `from` | `string` | No | Inputs: upstream source such as `taskId.outputs.name`, `taskId.stdout`, or `outputs.name`. Outputs: `json.<key>`, `stdout`, `stderr`, or `normalizedOutput` |
|
|
299
|
+
| `default` | `unknown` | No | Fallback value when the source is missing |
|
|
300
|
+
| `required` | `boolean` | Inputs only | When `true`, missing upstream value and no `default` blocks the task |
|
|
301
|
+
| `type` | `'string' \| 'number' \| 'boolean' \| 'enum' \| 'json'` | No | Optional coercion type. Omit it for pass-through values |
|
|
288
302
|
| `description` | `string` | No | Free-text description; rendered into the `[Inputs]` / `[Output Format]` blocks |
|
|
289
|
-
| `required` | `boolean` | No | Inputs only. When `true`, missing upstream value (and no `default`) blocks the task |
|
|
290
|
-
| `default` | `unknown` | No | Inputs only. Fallback value when no upstream produces the port |
|
|
291
303
|
| `enum` | `string[]` | When `type: enum` | Allowed values |
|
|
292
|
-
| `from` | `string` | No | Inputs only. Explicit upstream binding — bare `portName` (match by name) or `taskId.portName` (fully qualified). Unset = match by name across all direct upstreams; ambiguous matches block |
|
|
293
304
|
|
|
294
305
|
#### Substitution and AI prompt blocks
|
|
295
306
|
|
|
296
307
|
- `{{inputs.<name>}}` is expanded verbatim in `command` and `prompt` strings before execution. Quote your placeholders in command lines (`--city "{{inputs.city}}"`) — the engine does not shell-escape.
|
|
297
|
-
- AI tasks
|
|
298
|
-
- Output extraction strategy: prefer `normalizedOutput` (AI tasks), fall back to stdout (command tasks). Find the last non-empty line that parses as a JSON object, then read each declared output key. Failures append a diagnostic to stderr; the
|
|
308
|
+
- AI tasks get `[Output Format]` and `[Inputs]` blocks when typed bindings can be inferred from neighboring command tasks.
|
|
309
|
+
- Output extraction strategy: prefer `normalizedOutput` (AI tasks), fall back to stdout (command tasks). Find the last non-empty line that parses as a JSON object, then read each declared output key. Failures append a diagnostic to stderr; the binding is absent from `outputs` and downstream tasks see it as missing.
|
|
310
|
+
|
|
311
|
+
YAML `ports` has been replaced by typed `inputs` / `outputs`. `validateRaw` reports any `ports` field as a migration error.
|
|
299
312
|
|
|
300
313
|
---
|
|
301
314
|
|
|
@@ -363,9 +376,10 @@ Tasks can declare named, typed `inputs` / `outputs`. Inputs flow in from upstrea
|
|
|
363
376
|
### Root: `@tagma/sdk`
|
|
364
377
|
|
|
365
378
|
- `createTagma(options?)`
|
|
379
|
+
- `bunRuntime()`
|
|
366
380
|
- `definePipeline(pipeline)`
|
|
367
381
|
- `PluginRegistry`
|
|
368
|
-
- stable pipeline/result/event types
|
|
382
|
+
- stable pipeline/result/event/plugin/runtime types, including `TagmaPlugin` and `TagmaRuntime`
|
|
369
383
|
- trigger error classes
|
|
370
384
|
|
|
371
385
|
### YAML: `@tagma/sdk/yaml`
|
|
@@ -391,10 +405,22 @@ Tasks can declare named, typed `inputs` / `outputs`. Inputs flow in from upstrea
|
|
|
391
405
|
- raw validation helpers
|
|
392
406
|
- task reference helpers
|
|
393
407
|
|
|
394
|
-
###
|
|
408
|
+
### Dataflow helpers: `@tagma/sdk/ports`
|
|
395
409
|
|
|
396
|
-
-
|
|
397
|
-
|
|
410
|
+
- placeholder substitution, binding resolution, output extraction, and internal prompt-contract inference
|
|
411
|
+
- the subpath name is historical; YAML `ports` is rejected by validation
|
|
412
|
+
|
|
413
|
+
### Runtime approval adapters
|
|
414
|
+
|
|
415
|
+
- `@tagma/sdk/runtime/adapters/stdin-approval`
|
|
416
|
+
- `@tagma/sdk/runtime/adapters/websocket-approval`
|
|
417
|
+
- the older `@tagma/sdk/adapters/*` subpaths remain thin compatibility re-exports
|
|
418
|
+
|
|
419
|
+
### Split packages
|
|
420
|
+
|
|
421
|
+
- `@tagma/core` -- runtime-independent orchestration, registry, approval, logging, event/result types, and the `TagmaRuntime` interface
|
|
422
|
+
- `@tagma/runtime-bun` -- Bun process execution, file watching, log storage, `bunRuntime()`, and runtime approval adapters
|
|
423
|
+
- `@tagma/sdk` -- convenience package that composes core + Bun runtime + built-in plugins
|
|
398
424
|
|
|
399
425
|
### `bootstrapBuiltins(registry)`
|
|
400
426
|
|
|
@@ -404,6 +430,17 @@ Registers all built-in plugins (opencode driver, file/manual triggers, completio
|
|
|
404
430
|
|
|
405
431
|
Parses YAML, resolves inheritance, and validates the configuration.
|
|
406
432
|
|
|
433
|
+
### `createTagma(options?)`
|
|
434
|
+
|
|
435
|
+
Creates an isolated SDK instance with its own plugin registry.
|
|
436
|
+
|
|
437
|
+
Options:
|
|
438
|
+
|
|
439
|
+
- `registry` -- use an existing `PluginRegistry` instance
|
|
440
|
+
- `builtins` -- register built-in plugins into the instance registry; defaults to `true`
|
|
441
|
+
- `plugins` -- register package-level `TagmaPlugin` capability objects into the instance registry
|
|
442
|
+
- `runtime` -- override process execution, file watching, file existence checks, log storage, time, and sleep; defaults to `bunRuntime()`
|
|
443
|
+
|
|
407
444
|
### `createTagma().run(config, options): Promise<EngineResult>`
|
|
408
445
|
|
|
409
446
|
Executes the pipeline. Returns `{ success, runId, logPath, summary, states }`.
|
|
@@ -414,7 +451,7 @@ Options:
|
|
|
414
451
|
- `signal` -- `AbortSignal` to cancel the run externally
|
|
415
452
|
- `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:
|
|
416
453
|
- `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.
|
|
417
|
-
- `task_update` — a task's status or result changed; flat fields (`status`, `startedAt?`, `finishedAt?`, `durationMs?`, `exitCode?`, `stdout?`, `stderr?`, `stdoutPath?`, `stderrPath?`, `stdoutBytes?`, `stderrBytes?`, `sessionId?`, `normalizedOutput?`, `outputs?`, `inputs?`, `resolvedDriver?`, `resolvedModel?`, `resolvedPermissions?`) so clients can fold partial updates with `??` semantics. `inputs` carries the resolved
|
|
454
|
+
- `task_update` — a task's status or result changed; flat fields (`status`, `startedAt?`, `finishedAt?`, `durationMs?`, `exitCode?`, `stdout?`, `stderr?`, `stdoutPath?`, `stderrPath?`, `stdoutBytes?`, `stderrBytes?`, `sessionId?`, `normalizedOutput?`, `outputs?`, `inputs?`, `resolvedDriver?`, `resolvedModel?`, `resolvedPermissions?`) so clients can fold partial updates with `??` semantics. `inputs` carries the resolved task input map (set once just before the task transitions to `running`); `outputs` carries the extracted binding output map after a successful terminal transition. `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.
|
|
418
455
|
- `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.
|
|
419
456
|
- `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).
|
|
420
457
|
- `run_error` — reserved for fatal engine errors surfaced over the wire.
|
|
@@ -423,7 +460,7 @@ Options:
|
|
|
423
460
|
- `maxLogRuns` -- number of per-run log directories to keep under `<workDir>/.tagma/logs/` (default: 20)
|
|
424
461
|
- `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.
|
|
425
462
|
|
|
426
|
-
> **stdout / stderr persistence.**
|
|
463
|
+
> **stdout / stderr persistence.** With the default Bun runtime, the engine streams every task's stdout and stderr to disk under `<workDir>/.tagma/logs/<runId>/<taskId>.stdout` and `.stderr`. Custom runtimes can relocate those artifacts by implementing `runtime.logStore.taskOutputPath()`. The `TaskResult.stdout` / `stderr` strings are bounded tails (8 MB / 4 MB by default) — long outputs are truncated from the head with a marker, and consumers that need the full bytes should read `TaskResult.stdoutPath` / `stderrPath`. Use `TaskResult.stdoutBytes` / `stderrBytes` to display "32 MB (truncated)" without re-stat'ing the file.
|
|
427
464
|
|
|
428
465
|
### `PipelineRunner`
|
|
429
466
|
|
|
@@ -460,7 +497,7 @@ Properties:
|
|
|
460
497
|
|
|
461
498
|
Typed error classes for trigger plugin error classification. The engine uses `instanceof` checks on these to set the correct task status (`blocked` or `timeout`) instead of matching on error message substrings.
|
|
462
499
|
|
|
463
|
-
Built-in triggers (`manual`, `file`) throw these automatically.
|
|
500
|
+
Built-in triggers (`manual`, `file`) throw these automatically. Trigger plugins should throw `TriggerBlockedError` for user/policy rejections and `TriggerTimeoutError` for genuine wait timeouts.
|
|
464
501
|
|
|
465
502
|
```ts
|
|
466
503
|
import { TriggerBlockedError, TriggerTimeoutError } from '@tagma/sdk';
|
|
@@ -470,13 +507,30 @@ throw new TriggerBlockedError('Access denied by policy');
|
|
|
470
507
|
throw new TriggerTimeoutError('File did not appear within 30s');
|
|
471
508
|
```
|
|
472
509
|
|
|
473
|
-
### `PluginRegistry.loadPlugins(names): Promise<void>`
|
|
510
|
+
### `PluginRegistry.loadPlugins(names, resolveFrom?): Promise<void>`
|
|
511
|
+
|
|
512
|
+
Dynamically loads and registers external plugin packages. Each package must default-export a `TagmaPlugin` with capability maps.
|
|
513
|
+
|
|
514
|
+
```ts
|
|
515
|
+
export default {
|
|
516
|
+
name: '@tagma/trigger-http',
|
|
517
|
+
capabilities: {
|
|
518
|
+
triggers: {
|
|
519
|
+
http: HttpTrigger,
|
|
520
|
+
},
|
|
521
|
+
},
|
|
522
|
+
} satisfies TagmaPlugin;
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
Pass `resolveFrom` when plugins are installed in a workspace-local `node_modules`.
|
|
526
|
+
|
|
527
|
+
### `PluginRegistry.registerTagmaPlugin(plugin): RegisteredCapability[]`
|
|
474
528
|
|
|
475
|
-
|
|
529
|
+
Registers every supported capability from a `TagmaPlugin` default export.
|
|
476
530
|
|
|
477
531
|
### `PluginRegistry.registerPlugin(category, type, handler): void`
|
|
478
532
|
|
|
479
|
-
Registers
|
|
533
|
+
Registers one capability handler manually. Prefer `registerTagmaPlugin()` for package-level plugins.
|
|
480
534
|
|
|
481
535
|
Plugin handlers (`TriggerPlugin`, `CompletionPlugin`, `MiddlewarePlugin`) may optionally expose a declarative `schema: PluginSchema` field so visual editors can render a typed form for the plugin's config instead of a raw key/value editor:
|
|
482
536
|
|
|
@@ -494,6 +548,8 @@ export const HttpTrigger: TriggerPlugin = {
|
|
|
494
548
|
},
|
|
495
549
|
},
|
|
496
550
|
async watch(config, ctx) {
|
|
551
|
+
// Trigger plugins should use ctx.runtime for file IO, watching, and
|
|
552
|
+
// timing so they can run under non-Bun test/runtime implementations.
|
|
497
553
|
/* ... */
|
|
498
554
|
},
|
|
499
555
|
};
|
|
@@ -612,9 +668,9 @@ Validates a resolved pipeline config without executing it. Checks DAG structure
|
|
|
612
668
|
|
|
613
669
|
Use `validateRaw` for editing raw configs in a UI; use `validateConfig` after `resolveConfig` for a final pre-run check.
|
|
614
670
|
|
|
615
|
-
### Bindings
|
|
671
|
+
### Bindings API
|
|
616
672
|
|
|
617
|
-
Pure helpers backing
|
|
673
|
+
Pure helpers backing typed task bindings and internal prompt-contract inference. Safe to use in editors, simulators, and custom drivers — no I/O, no side effects.
|
|
618
674
|
|
|
619
675
|
| Function | Description |
|
|
620
676
|
| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
@@ -623,7 +679,7 @@ Pure helpers backing lightweight bindings and `task.ports`. Safe to use in edito
|
|
|
623
679
|
| `resolveTaskBindingInputs(task, upstreamData, dependsOn)` | Resolve lightweight task-level `inputs` from literal values, upstream outputs, stdout/stderr, normalized output, defaults, and required flags |
|
|
624
680
|
| `resolveTaskInputs(task, upstreamOutputs, dependsOn)` | Gather the input values a task will consume from its direct upstreams. Applies `from` bindings, defaults, and type coercion. Returns `{ kind: 'ready', inputs, missingOptional }` or `{ kind: 'blocked', missingRequired, ambiguous, typeErrors, reason }` |
|
|
625
681
|
| `extractTaskBindingOutputs(outputs, stdout, stderr, normalizedOutput)` | Publish lightweight task-level `outputs` from final-line JSON, stdout/stderr, normalized output, literal values, or defaults |
|
|
626
|
-
| `extractTaskOutputs(ports, stdout, normalizedOutput)` |
|
|
682
|
+
| `extractTaskOutputs(ports, stdout, normalizedOutput)` | Internal helper for inferred prompt contracts. Strategy: prefer `normalizedOutput`; find the last non-empty line that parses as a JSON object; coerce each declared key. Returns `{ outputs, diagnostic }` |
|
|
627
683
|
| `prependContext(doc, block)` | Same shape as `appendContext` but prepends; the engine uses this to place `[Output Format]` and `[Inputs]` blocks before middleware-added context |
|
|
628
684
|
| `renderInputsBlock(inputsDecl, values)` | Build the `[Inputs]` `PromptContextBlock` rendered into AI prompts (`name: value # description` lines). Returns `null` when no inputs to render |
|
|
629
685
|
| `renderOutputSchemaBlock(outputsDecl)` | Build the `[Output Format]` `PromptContextBlock` instructing the model to emit a final-line JSON object matching the declared outputs. Returns `null` when no outputs declared |
|
|
@@ -634,7 +690,7 @@ Custom drivers that wrap the prompt in their own envelope can read `DriverContex
|
|
|
634
690
|
|
|
635
691
|
Validates a raw pipeline config without resolving inheritance or executing anything. Returns a flat list of `{ path, message, severity? }` objects — empty array means valid. `severity` is `'error'` (default, fatal) or `'warning'` (soft hint; non-blocking).
|
|
636
692
|
|
|
637
|
-
Checks: required fields, `prompt`/`command` exclusivity, duplicate task IDs within a track, `depends_on`/`continue_from` reference integrity (including ambiguous bare refs that exist in multiple tracks — use `trackId.taskId` to disambiguate), circular dependency detection,
|
|
693
|
+
Checks: required fields, `prompt`/`command` exclusivity, duplicate task IDs within a track, `depends_on`/`continue_from` reference integrity (including ambiguous bare refs that exist in multiple tracks — use `trackId.taskId` to disambiguate), circular dependency detection, binding shape (name format, valid `type`, duplicate names, `enum` requires non-empty `enum` array), `ports` migration errors, `{{inputs.<name>}}` references resolving to a declared or inferred input binding, and `permissions` shape (must be an object with boolean `read`/`write`/`execute`). Tolerant of half-built configs — non-array `tracks` or `tasks` produce a structured error instead of throwing.
|
|
638
694
|
|
|
639
695
|
Plugin-type checks are opt-in via `knownTypes`: when provided, references to trigger/completion/middleware/driver types that are neither built-in nor in the supplied set produce a **warning** (`severity: 'warning'`) so editors can light up uninstalled plugins without blocking save / run. Omit `knownTypes` for offline / pre-load validation — no plugin warnings are emitted in that case.
|
|
640
696
|
|
|
@@ -694,7 +750,9 @@ Use `buildDag` instead when you have a fully resolved `PipelineConfig` and need
|
|
|
694
750
|
Dual-channel logger — console + file. Creates a per-run log file at `<workDir>/.tagma/logs/<runId>/pipeline.log`.
|
|
695
751
|
|
|
696
752
|
```ts
|
|
697
|
-
|
|
753
|
+
import { bunRuntime } from '@tagma/sdk';
|
|
754
|
+
|
|
755
|
+
const logger = new Logger(workDir, runId, bunRuntime().logStore);
|
|
698
756
|
logger.info('[track]', 'message'); // console + file
|
|
699
757
|
logger.warn('[track]', 'message'); // console + file
|
|
700
758
|
logger.error('[track]', 'message'); // console + file
|
|
@@ -706,13 +764,14 @@ logger.dir; // run artifact directory
|
|
|
706
764
|
logger.close(); // close the persistent file handle (called automatically when Tagma.run completes)
|
|
707
765
|
```
|
|
708
766
|
|
|
709
|
-
Pass an optional
|
|
767
|
+
Pass an optional fourth argument to stream every appended line out as a
|
|
710
768
|
structured `LogRecord`; the engine uses this to emit `task_log` events:
|
|
711
769
|
|
|
712
770
|
```ts
|
|
771
|
+
import { bunRuntime } from '@tagma/sdk';
|
|
713
772
|
import { Logger, type LogRecord } from '@tagma/sdk/logger';
|
|
714
773
|
|
|
715
|
-
const logger = new Logger(workDir, runId, (record: LogRecord) => {
|
|
774
|
+
const logger = new Logger(workDir, runId, bunRuntime().logStore, (record: LogRecord) => {
|
|
716
775
|
// record = { level, taskId, timestamp, text }
|
|
717
776
|
// level = 'info' | 'warn' | 'error' | 'debug' | 'section' | 'quiet'
|
|
718
777
|
// taskId is extracted from a '[task:<id>]' prefix, or null for untagged lines
|
|
@@ -751,6 +810,8 @@ Truncates `text` to at most `maxBytes` UTF-8 bytes (default 16 KB), appending a
|
|
|
751
810
|
| Package | Description |
|
|
752
811
|
| ---------------------------------------------------------------------------------------- | --------------------------------------------- |
|
|
753
812
|
| [@tagma/types](https://www.npmjs.com/package/@tagma/types) | Shared TypeScript types |
|
|
813
|
+
| [@tagma/core](https://www.npmjs.com/package/@tagma/core) | Runtime-independent orchestration core |
|
|
814
|
+
| [@tagma/runtime-bun](https://www.npmjs.com/package/@tagma/runtime-bun) | Bun runtime implementation |
|
|
754
815
|
| [@tagma/driver-codex](https://www.npmjs.com/package/@tagma/driver-codex) | Codex CLI driver plugin |
|
|
755
816
|
| [@tagma/driver-claude-code](https://www.npmjs.com/package/@tagma/driver-claude-code) | Claude Code CLI driver plugin |
|
|
756
817
|
| [@tagma/middleware-lightrag](https://www.npmjs.com/package/@tagma/middleware-lightrag) | LightRAG knowledge-graph retrieval middleware |
|
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export interface StdinApprovalAdapter {
|
|
3
|
-
readonly detach: () => void;
|
|
4
|
-
}
|
|
5
|
-
export declare function attachStdinApprovalAdapter(gateway: ApprovalGateway): StdinApprovalAdapter;
|
|
1
|
+
export * from '../runtime/adapters/stdin-approval';
|
|
6
2
|
//# sourceMappingURL=stdin-approval.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdin-approval.d.ts","sourceRoot":"","sources":["../../src/adapters/stdin-approval.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stdin-approval.d.ts","sourceRoot":"","sources":["../../src/adapters/stdin-approval.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAC"}
|
|
@@ -1,90 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export function attachStdinApprovalAdapter(gateway) {
|
|
3
|
-
const queue = [];
|
|
4
|
-
let processing = false;
|
|
5
|
-
let rl = null;
|
|
6
|
-
function ensureReadline() {
|
|
7
|
-
if (!rl) {
|
|
8
|
-
rl = readline.createInterface({ input: process.stdin, terminal: false });
|
|
9
|
-
}
|
|
10
|
-
return rl;
|
|
11
|
-
}
|
|
12
|
-
function readOneLine() {
|
|
13
|
-
return new Promise((resolvePromise) => {
|
|
14
|
-
const reader = ensureReadline();
|
|
15
|
-
const handler = (line) => {
|
|
16
|
-
reader.off('line', handler);
|
|
17
|
-
resolvePromise(line);
|
|
18
|
-
};
|
|
19
|
-
reader.on('line', handler);
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
async function processNext() {
|
|
23
|
-
if (processing)
|
|
24
|
-
return;
|
|
25
|
-
processing = true;
|
|
26
|
-
try {
|
|
27
|
-
while (queue.length > 0) {
|
|
28
|
-
const req = queue.shift();
|
|
29
|
-
// If the request was already resolved by another path while queued, skip it.
|
|
30
|
-
if (!gateway.pending().some((p) => p.id === req.id))
|
|
31
|
-
continue;
|
|
32
|
-
process.stdout.write(`\n[APPROVAL REQUIRED] ${req.message}\n` +
|
|
33
|
-
` id: ${req.id}\n` +
|
|
34
|
-
` task: ${req.taskId}${req.trackId ? ` (track: ${req.trackId})` : ''}\n` +
|
|
35
|
-
` approve / reject > `);
|
|
36
|
-
const input = (await readOneLine()).trim().toLowerCase();
|
|
37
|
-
const approveAliases = new Set(['approve', 'yes', 'y', 'ok', 'true', '1']);
|
|
38
|
-
const rejectAliases = new Set(['reject', 'no', 'n', 'deny', 'false', '0']);
|
|
39
|
-
if (approveAliases.has(input)) {
|
|
40
|
-
gateway.resolve(req.id, { outcome: 'approved', actor: 'cli' });
|
|
41
|
-
}
|
|
42
|
-
else if (rejectAliases.has(input)) {
|
|
43
|
-
gateway.resolve(req.id, {
|
|
44
|
-
outcome: 'rejected',
|
|
45
|
-
actor: 'cli',
|
|
46
|
-
reason: 'user rejected via CLI',
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
process.stdout.write(` unrecognized input "${input}" — treating as rejection\n`);
|
|
51
|
-
gateway.resolve(req.id, {
|
|
52
|
-
outcome: 'rejected',
|
|
53
|
-
actor: 'cli',
|
|
54
|
-
reason: `unrecognized CLI input: ${input}`,
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
finally {
|
|
60
|
-
processing = false;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
const unsubscribe = gateway.subscribe((event) => {
|
|
64
|
-
switch (event.type) {
|
|
65
|
-
case 'requested':
|
|
66
|
-
queue.push(event.request);
|
|
67
|
-
void processNext();
|
|
68
|
-
return;
|
|
69
|
-
case 'resolved':
|
|
70
|
-
case 'expired':
|
|
71
|
-
case 'aborted': {
|
|
72
|
-
// Drop from queue if it's still waiting its turn.
|
|
73
|
-
const idx = queue.findIndex((r) => r.id === event.request.id);
|
|
74
|
-
if (idx >= 0)
|
|
75
|
-
queue.splice(idx, 1);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
return {
|
|
81
|
-
detach: () => {
|
|
82
|
-
unsubscribe();
|
|
83
|
-
if (rl) {
|
|
84
|
-
rl.close();
|
|
85
|
-
rl = null;
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
};
|
|
89
|
-
}
|
|
1
|
+
export * from '../runtime/adapters/stdin-approval';
|
|
90
2
|
//# sourceMappingURL=stdin-approval.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdin-approval.js","sourceRoot":"","sources":["../../src/adapters/stdin-approval.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"stdin-approval.js","sourceRoot":"","sources":["../../src/adapters/stdin-approval.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAC"}
|
|
@@ -1,28 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export interface WebSocketApprovalAdapterOptions {
|
|
3
|
-
port?: number;
|
|
4
|
-
hostname?: string;
|
|
5
|
-
/**
|
|
6
|
-
* M11: shared secret required from the client during the WebSocket
|
|
7
|
-
* upgrade. The token can be supplied either as the `?token=` query
|
|
8
|
-
* parameter or in the `x-tagma-token` request header. When set, any
|
|
9
|
-
* upgrade request that fails the check is rejected with HTTP 401 and
|
|
10
|
-
* never reaches the WebSocket layer (so a misconfigured client cannot
|
|
11
|
-
* exhaust rate-limit slots either). Leave undefined for backward
|
|
12
|
-
* compatibility with localhost-only deployments.
|
|
13
|
-
*/
|
|
14
|
-
token?: string;
|
|
15
|
-
/**
|
|
16
|
-
* M11: opt-out of origin checking. Defaults to false, meaning Origin
|
|
17
|
-
* headers are restricted to loopback hosts (localhost / 127.0.0.1 / ::1).
|
|
18
|
-
* Requests without an Origin header are still allowed so non-browser local
|
|
19
|
-
* clients can connect. Set true only for trusted reverse-proxy setups.
|
|
20
|
-
*/
|
|
21
|
-
allowAnyOrigin?: boolean;
|
|
22
|
-
}
|
|
23
|
-
export interface WebSocketApprovalAdapter {
|
|
24
|
-
readonly port: number;
|
|
25
|
-
readonly detach: () => void;
|
|
26
|
-
}
|
|
27
|
-
export declare function attachWebSocketApprovalAdapter(gateway: ApprovalGateway, options?: WebSocketApprovalAdapterOptions): WebSocketApprovalAdapter;
|
|
1
|
+
export * from '../runtime/adapters/websocket-approval';
|
|
28
2
|
//# sourceMappingURL=websocket-approval.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-approval.d.ts","sourceRoot":"","sources":["../../src/adapters/websocket-approval.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"websocket-approval.d.ts","sourceRoot":"","sources":["../../src/adapters/websocket-approval.ts"],"names":[],"mappings":"AAAA,cAAc,wCAAwC,CAAC"}
|