@tagma/sdk 0.6.5 → 0.6.6
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 +66 -1
- package/package.json +2 -2
- package/dist/dag.test.d.ts +0 -2
- package/dist/dag.test.d.ts.map +0 -1
- package/dist/dag.test.js +0 -42
- package/dist/dag.test.js.map +0 -1
- package/dist/engine-ports.test.d.ts +0 -2
- package/dist/engine-ports.test.d.ts.map +0 -1
- package/dist/engine-ports.test.js +0 -378
- package/dist/engine-ports.test.js.map +0 -1
- package/dist/plugin-registry.test.d.ts +0 -2
- package/dist/plugin-registry.test.d.ts.map +0 -1
- package/dist/plugin-registry.test.js +0 -188
- package/dist/plugin-registry.test.js.map +0 -1
- package/dist/ports.test.d.ts +0 -2
- package/dist/ports.test.d.ts.map +0 -1
- package/dist/ports.test.js +0 -262
- package/dist/ports.test.js.map +0 -1
- package/dist/prompt-doc.test.d.ts +0 -2
- package/dist/prompt-doc.test.d.ts.map +0 -1
- package/dist/prompt-doc.test.js +0 -145
- package/dist/prompt-doc.test.js.map +0 -1
- package/dist/runner.test.d.ts +0 -2
- package/dist/runner.test.d.ts.map +0 -1
- package/dist/runner.test.js +0 -119
- package/dist/runner.test.js.map +0 -1
- package/dist/schema-ports.test.d.ts +0 -2
- package/dist/schema-ports.test.d.ts.map +0 -1
- package/dist/schema-ports.test.js +0 -219
- package/dist/schema-ports.test.js.map +0 -1
- package/dist/schema.test.d.ts +0 -2
- package/dist/schema.test.d.ts.map +0 -1
- package/dist/schema.test.js +0 -94
- package/dist/schema.test.js.map +0 -1
- package/dist/task-ref.test.d.ts +0 -2
- package/dist/task-ref.test.d.ts.map +0 -1
- package/dist/task-ref.test.js +0 -364
- package/dist/task-ref.test.js.map +0 -1
- package/dist/validate-raw-ports.test.d.ts +0 -2
- package/dist/validate-raw-ports.test.d.ts.map +0 -1
- package/dist/validate-raw-ports.test.js +0 -157
- package/dist/validate-raw-ports.test.js.map +0 -1
package/README.md
CHANGED
|
@@ -72,6 +72,7 @@ console.log(result.success ? 'Done' : 'Failed');
|
|
|
72
72
|
- **Middleware** -- enrich prompts before execution (e.g. inject static context)
|
|
73
73
|
- **Completion checks** -- validate task output with `exit_code`, `file_exists`, or `output_check` plugins
|
|
74
74
|
- **Plugin schemas** -- triggers/completions/middlewares can declare a `PluginSchema` so visual editors render typed forms for their config
|
|
75
|
+
- **Typed task ports** -- declare named, typed `inputs` / `outputs` on a task. Inputs from upstream tasks are substituted into `command` / `prompt` via `{{inputs.<name>}}` and rendered as an `[Inputs]` context block for AI tasks; outputs are extracted from the final-line JSON object on stdout (or `normalizedOutput`) and surfaced to downstream tasks
|
|
75
76
|
|
|
76
77
|
## Pipeline YAML Reference
|
|
77
78
|
|
|
@@ -199,6 +200,7 @@ Each hook value can be a single command string or an array of commands.
|
|
|
199
200
|
| `middlewares` | `MiddlewareConfig[]` | No | Inherited from track | Middleware override. Set `[]` to disable inherited middlewares |
|
|
200
201
|
| `trigger` | `TriggerConfig` | No | — | Gate that must resolve before the task runs (see Triggers) |
|
|
201
202
|
| `completion` | `CompletionConfig` | No | — | Post-execution check to validate task output (see Completions) |
|
|
203
|
+
| `ports` | `TaskPorts` | No | — | Typed input/output ports — see Typed Ports below |
|
|
202
204
|
|
|
203
205
|
### Permissions
|
|
204
206
|
|
|
@@ -218,6 +220,51 @@ Track-level `middlewares` apply to all tasks in the track. Setting task-level `m
|
|
|
218
220
|
|
|
219
221
|
---
|
|
220
222
|
|
|
223
|
+
### Typed Ports
|
|
224
|
+
|
|
225
|
+
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.
|
|
226
|
+
|
|
227
|
+
```yaml
|
|
228
|
+
- id: lookup-weather
|
|
229
|
+
name: Lookup weather
|
|
230
|
+
command: weather.sh --city "{{inputs.city}}"
|
|
231
|
+
ports:
|
|
232
|
+
inputs:
|
|
233
|
+
- { name: city, type: string, required: true, description: Target city }
|
|
234
|
+
outputs:
|
|
235
|
+
- { name: temperature, type: number, description: Current temperature in Celsius }
|
|
236
|
+
- { name: conditions, type: enum, enum: [sunny, cloudy, rain, snow] }
|
|
237
|
+
|
|
238
|
+
- id: write-report
|
|
239
|
+
depends_on: [lookup-weather]
|
|
240
|
+
prompt: 'Write a brief weather report for {{inputs.city}}.'
|
|
241
|
+
ports:
|
|
242
|
+
inputs:
|
|
243
|
+
- { name: city, type: string, required: true }
|
|
244
|
+
- { name: temperature, type: number, required: true }
|
|
245
|
+
- { name: conditions, type: enum, enum: [sunny, cloudy, rain, snow] }
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
#### `PortDef` fields
|
|
249
|
+
|
|
250
|
+
| Field | Type | Required | Description |
|
|
251
|
+
| ------------- | ----------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
252
|
+
| `name` | `string` | Yes | Port name; also the substitution key (`{{inputs.<name>}}`) |
|
|
253
|
+
| `type` | `'string' \| 'number' \| 'boolean' \| 'enum' \| 'json'` | Yes | Coercion type. Mismatched values block the task with a typed-error diagnostic |
|
|
254
|
+
| `description` | `string` | No | Free-text description; rendered into the `[Inputs]` / `[Output Format]` blocks |
|
|
255
|
+
| `required` | `boolean` | No | Inputs only. When `true`, missing upstream value (and no `default`) blocks the task |
|
|
256
|
+
| `default` | `unknown` | No | Inputs only. Fallback value when no upstream produces the port |
|
|
257
|
+
| `enum` | `string[]` | When `type: enum` | Allowed values |
|
|
258
|
+
| `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 |
|
|
259
|
+
|
|
260
|
+
#### Substitution and AI prompt blocks
|
|
261
|
+
|
|
262
|
+
- `{{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.
|
|
263
|
+
- AI tasks additionally get two prepended `PromptContextBlock`s: `[Output Format]` (instructs the model to emit a final-line JSON object matching the declared outputs) and `[Inputs]` (renders the resolved inputs as `name: value # description`). Tasks without ports get no extra blocks.
|
|
264
|
+
- 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 port is absent from `outputs` and downstream tasks see it as missing.
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
221
268
|
### Built-in Triggers
|
|
222
269
|
|
|
223
270
|
#### `manual` — Human approval gate
|
|
@@ -306,6 +353,8 @@ Options:
|
|
|
306
353
|
- `maxLogRuns` -- number of per-run log directories to keep under `<workDir>/.tagma/logs/` (default: 20)
|
|
307
354
|
- `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.
|
|
308
355
|
|
|
356
|
+
> **stdout / stderr persistence.** The engine streams every task's stdout and stderr to disk under `<workDir>/.tagma/logs/<runId>/<taskId>.stdout` and `.stderr`. 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.
|
|
357
|
+
|
|
309
358
|
### `PipelineRunner`
|
|
310
359
|
|
|
311
360
|
Higher-level wrapper for managing multiple concurrent pipeline runs — designed for sidecar / Tauri IPC scenarios where the frontend controls pipeline lifecycle by ID.
|
|
@@ -474,11 +523,27 @@ Validates a resolved pipeline config without executing it. Checks DAG structure
|
|
|
474
523
|
|
|
475
524
|
Use `validateRaw` for editing raw configs in a UI; use `validateConfig` after `resolveConfig` for a final pre-run check.
|
|
476
525
|
|
|
526
|
+
### Typed Ports API
|
|
527
|
+
|
|
528
|
+
Pure helpers backing the `task.ports` feature (see Typed Ports above). Safe to use in editors, simulators, and custom drivers — no I/O, no side effects.
|
|
529
|
+
|
|
530
|
+
| Function | Description |
|
|
531
|
+
| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
532
|
+
| `substituteInputs(text, inputs)` | Expand `{{inputs.<name>}}` placeholders in `text`. Returns `{ text, unresolved }`. Strings pass through, numbers/booleans coerce via `String(...)`, objects/arrays via `JSON.stringify`. Caller is responsible for shell quoting |
|
|
533
|
+
| `extractInputReferences(text)` | Return the set of input port names referenced by `{{inputs.<name>}}` placeholders in `text`. Use at edit time to flag undeclared references |
|
|
534
|
+
| `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 }` |
|
|
535
|
+
| `extractTaskOutputs(ports, stdout, normalizedOutput)` | Pull declared output values from a terminated task's output. Strategy: prefer `normalizedOutput`; find the last non-empty line that parses as a JSON object; coerce each declared key. Returns `{ outputs, diagnostic }` |
|
|
536
|
+
| `prependContext(doc, block)` | Same shape as `appendContext` but prepends; the engine uses this to place `[Output Format]` and `[Inputs]` blocks before middleware-added context |
|
|
537
|
+
| `renderInputsBlock(inputsDecl, values)` | Build the `[Inputs]` `PromptContextBlock` rendered into AI prompts (`name: value # description` lines). Returns `null` when no inputs to render |
|
|
538
|
+
| `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 |
|
|
539
|
+
|
|
540
|
+
Custom drivers that wrap the prompt in their own envelope can read `DriverContext.inputs` (resolved + coerced map keyed by port name) and call `substituteInputs` themselves — the engine has already substituted into `task.prompt` upstream, so most drivers can ignore this.
|
|
541
|
+
|
|
477
542
|
### `validateRaw(config: RawPipelineConfig): ValidationError[]`
|
|
478
543
|
|
|
479
544
|
Validates a raw pipeline config without resolving inheritance or executing anything. Returns a flat list of `{ path, message }` objects — empty array means valid.
|
|
480
545
|
|
|
481
|
-
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.
|
|
546
|
+
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, port shape (name format, valid `type`, duplicate names, `enum` requires non-empty `enum` array, `required`/`from` ignored on outputs), and `{{inputs.<name>}}` references resolving to a declared input port.
|
|
482
547
|
|
|
483
548
|
Does **not** check plugin registration (plugins may not be loaded at edit time).
|
|
484
549
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tagma/sdk",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.6",
|
|
4
4
|
"description": "Local AI task orchestration engine — core SDK for tagma pipelines",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"release:publish": "bun scripts/release.ts --publish"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@tagma/types": "0.4.
|
|
45
|
+
"@tagma/types": "0.4.4",
|
|
46
46
|
"js-yaml": "^4.1.0",
|
|
47
47
|
"chokidar": "^4.0.0"
|
|
48
48
|
}
|
package/dist/dag.test.d.ts
DELETED
package/dist/dag.test.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dag.test.d.ts","sourceRoot":"","sources":["../src/dag.test.ts"],"names":[],"mappings":""}
|
package/dist/dag.test.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'bun:test';
|
|
2
|
-
import { buildDag } from './dag';
|
|
3
|
-
const PERMS = { read: true, write: false, execute: false };
|
|
4
|
-
function task(id, depends_on) {
|
|
5
|
-
return { id, name: id, prompt: 'x', permissions: PERMS, depends_on };
|
|
6
|
-
}
|
|
7
|
-
function track(id, tasks) {
|
|
8
|
-
return { id, name: id, driver: 'opencode', permissions: PERMS, tasks };
|
|
9
|
-
}
|
|
10
|
-
function pipeline(tasks) {
|
|
11
|
-
return { name: 'test', tracks: [track('t', tasks)] };
|
|
12
|
-
}
|
|
13
|
-
function qid(id) {
|
|
14
|
-
return `t.${id}`;
|
|
15
|
-
}
|
|
16
|
-
describe('buildDag', () => {
|
|
17
|
-
test('empty pipeline yields empty sorted array', () => {
|
|
18
|
-
const dag = buildDag({ name: 'empty', tracks: [track('t', [])] });
|
|
19
|
-
expect(dag.sorted).toEqual([]);
|
|
20
|
-
expect(dag.nodes.size).toBe(0);
|
|
21
|
-
});
|
|
22
|
-
test('single node returns that node', () => {
|
|
23
|
-
const dag = buildDag(pipeline([task('only')]));
|
|
24
|
-
expect(dag.sorted).toEqual([qid('only')]);
|
|
25
|
-
expect(dag.nodes.size).toBe(1);
|
|
26
|
-
});
|
|
27
|
-
test('linear chain A -> B -> C produces correct order', () => {
|
|
28
|
-
const dag = buildDag(pipeline([task('a'), task('b', ['a']), task('c', ['b'])]));
|
|
29
|
-
expect(dag.sorted).toEqual([qid('a'), qid('b'), qid('c')]);
|
|
30
|
-
});
|
|
31
|
-
test('diamond A -> B,C; B,C -> D: A first, D last, B/C in between', () => {
|
|
32
|
-
const dag = buildDag(pipeline([task('a'), task('b', ['a']), task('c', ['a']), task('d', ['b', 'c'])]));
|
|
33
|
-
expect(dag.sorted[0]).toBe(qid('a'));
|
|
34
|
-
expect(dag.sorted[dag.sorted.length - 1]).toBe(qid('d'));
|
|
35
|
-
const mid = dag.sorted.slice(1, -1).sort();
|
|
36
|
-
expect(mid).toEqual([qid('b'), qid('c')]);
|
|
37
|
-
});
|
|
38
|
-
test('cycle detection throws', () => {
|
|
39
|
-
expect(() => buildDag(pipeline([task('a', ['b']), task('b', ['a'])]))).toThrow(/[Cc]ircular|cycle/);
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
//# sourceMappingURL=dag.test.js.map
|
package/dist/dag.test.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dag.test.js","sourceRoot":"","sources":["../src/dag.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"engine-ports.test.d.ts","sourceRoot":"","sources":["../src/engine-ports.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'bun:test';
|
|
2
|
-
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
-
import { tmpdir } from 'node:os';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
-
import { PluginRegistry } from './registry';
|
|
6
|
-
import { bootstrapBuiltins } from './bootstrap';
|
|
7
|
-
import { runPipeline } from './engine';
|
|
8
|
-
// ─── Helpers ─────────────────────────────────────────────────────────
|
|
9
|
-
const PERMS = { read: true, write: false, execute: false };
|
|
10
|
-
function freshRegistry() {
|
|
11
|
-
const reg = new PluginRegistry();
|
|
12
|
-
bootstrapBuiltins(reg);
|
|
13
|
-
return reg;
|
|
14
|
-
}
|
|
15
|
-
function makeDir() {
|
|
16
|
-
return mkdtempSync(join(tmpdir(), 'tagma-ports-'));
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Write a small Node script to the workspace dir that emits the given
|
|
20
|
-
* payload on stdout as a single-line JSON object.
|
|
21
|
-
*
|
|
22
|
-
* Tests that rely on shell-quoted inline JSON (`echo '{"x":1}'`) are
|
|
23
|
-
* fragile across Windows cmd / PowerShell / Git Bash — quote handling
|
|
24
|
-
* differs widely. Putting the payload into a Node script instead keeps
|
|
25
|
-
* the command line a plain `node /path/to/file.js`, which survives any
|
|
26
|
-
* shell, and still exercises the engine's "last-line JSON" extraction
|
|
27
|
-
* on real child-process output.
|
|
28
|
-
*/
|
|
29
|
-
function writeEmitScript(dir, name, payload) {
|
|
30
|
-
const path = join(dir, `${name}.js`);
|
|
31
|
-
const src = `process.stdout.write(${JSON.stringify(JSON.stringify(payload))});\nprocess.stdout.write('\\n');\n`;
|
|
32
|
-
writeFileSync(path, src);
|
|
33
|
-
return path;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Same as writeEmitScript but echoes args joined with `|`, so downstream
|
|
37
|
-
* tests can assert that upstream input values ended up on the command
|
|
38
|
-
* line post-substitution.
|
|
39
|
-
*/
|
|
40
|
-
function writeEchoArgsScript(dir, name) {
|
|
41
|
-
const path = join(dir, `${name}.js`);
|
|
42
|
-
const src = `process.stdout.write(process.argv.slice(2).join('|'));\nprocess.stdout.write('\\n');\n`;
|
|
43
|
-
writeFileSync(path, src);
|
|
44
|
-
return path;
|
|
45
|
-
}
|
|
46
|
-
function task(overrides) {
|
|
47
|
-
return {
|
|
48
|
-
name: overrides.id,
|
|
49
|
-
permissions: PERMS,
|
|
50
|
-
driver: 'opencode',
|
|
51
|
-
...overrides,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
function pipeline(tasks) {
|
|
55
|
-
return {
|
|
56
|
-
name: 'ports-test',
|
|
57
|
-
tracks: [
|
|
58
|
-
{
|
|
59
|
-
id: 't',
|
|
60
|
-
name: 'T',
|
|
61
|
-
driver: 'opencode',
|
|
62
|
-
permissions: PERMS,
|
|
63
|
-
on_failure: 'skip_downstream',
|
|
64
|
-
tasks,
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
async function run(config, workDir, registry = freshRegistry()) {
|
|
70
|
-
const events = [];
|
|
71
|
-
const result = await runPipeline(config, workDir, {
|
|
72
|
-
registry,
|
|
73
|
-
skipPluginLoading: true,
|
|
74
|
-
onEvent: (e) => events.push(e),
|
|
75
|
-
});
|
|
76
|
-
return { events, states: result.states, success: result.success };
|
|
77
|
-
}
|
|
78
|
-
function finalUpdateFor(events, qid) {
|
|
79
|
-
let last;
|
|
80
|
-
for (const ev of events) {
|
|
81
|
-
if (ev.type === 'task_update' && ev.taskId === qid)
|
|
82
|
-
last = ev;
|
|
83
|
-
}
|
|
84
|
-
return last;
|
|
85
|
-
}
|
|
86
|
-
function finalStatusFrom(events, qid) {
|
|
87
|
-
const last = finalUpdateFor(events, qid);
|
|
88
|
-
return last && last.type === 'task_update' ? last.status : undefined;
|
|
89
|
-
}
|
|
90
|
-
// ─── Tests ────────────────────────────────────────────────────────────
|
|
91
|
-
describe('engine — ports: output extraction + input resolution', () => {
|
|
92
|
-
test('upstream outputs feed downstream inputs via name match', async () => {
|
|
93
|
-
const dir = makeDir();
|
|
94
|
-
try {
|
|
95
|
-
const emit = writeEmitScript(dir, 'emit', { city: 'Shanghai', id: 42 });
|
|
96
|
-
const echo = writeEchoArgsScript(dir, 'echo');
|
|
97
|
-
const config = pipeline([
|
|
98
|
-
task({
|
|
99
|
-
id: 'up',
|
|
100
|
-
command: `node "${emit}"`,
|
|
101
|
-
ports: {
|
|
102
|
-
outputs: [
|
|
103
|
-
{ name: 'city', type: 'string' },
|
|
104
|
-
{ name: 'id', type: 'number' },
|
|
105
|
-
],
|
|
106
|
-
},
|
|
107
|
-
}),
|
|
108
|
-
task({
|
|
109
|
-
id: 'down',
|
|
110
|
-
depends_on: ['up'],
|
|
111
|
-
command: `node "${echo}" "{{inputs.city}}" "{{inputs.id}}"`,
|
|
112
|
-
ports: {
|
|
113
|
-
inputs: [
|
|
114
|
-
{ name: 'city', type: 'string', required: true },
|
|
115
|
-
{ name: 'id', type: 'number', required: true },
|
|
116
|
-
],
|
|
117
|
-
},
|
|
118
|
-
}),
|
|
119
|
-
]);
|
|
120
|
-
const { events, success } = await run(config, dir);
|
|
121
|
-
expect(success).toBe(true);
|
|
122
|
-
// Upstream's extracted outputs land on the final task_update event
|
|
123
|
-
// so the editor can render them on the card live.
|
|
124
|
-
const upFinal = finalUpdateFor(events, 't.up');
|
|
125
|
-
expect(upFinal.type).toBe('task_update');
|
|
126
|
-
if (upFinal.type !== 'task_update')
|
|
127
|
-
return;
|
|
128
|
-
expect(upFinal.outputs).toEqual({ city: 'Shanghai', id: 42 });
|
|
129
|
-
// Downstream saw the values: echoed stdout is "Shanghai|42\n".
|
|
130
|
-
const downFinal = finalUpdateFor(events, 't.down');
|
|
131
|
-
if (downFinal.type !== 'task_update')
|
|
132
|
-
return;
|
|
133
|
-
expect(downFinal.status).toBe('success');
|
|
134
|
-
expect((downFinal.stdout ?? '').trim()).toBe('Shanghai|42');
|
|
135
|
-
expect(downFinal.inputs).toEqual({ city: 'Shanghai', id: 42 });
|
|
136
|
-
}
|
|
137
|
-
finally {
|
|
138
|
-
rmSync(dir, { recursive: true, force: true });
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
test('required input missing → downstream blocked, no spawn, upstream still succeeded', async () => {
|
|
142
|
-
const dir = makeDir();
|
|
143
|
-
try {
|
|
144
|
-
// Upstream declares `city` output but its script emits no JSON, so
|
|
145
|
-
// the engine can't extract `city` — diagnostic on stderr, no
|
|
146
|
-
// outputs. Downstream required input unresolved → blocked.
|
|
147
|
-
const noJson = join(dir, 'no-json.js');
|
|
148
|
-
writeFileSync(noJson, "process.stdout.write('hello\\n');\n");
|
|
149
|
-
const echo = writeEchoArgsScript(dir, 'echo');
|
|
150
|
-
const config = pipeline([
|
|
151
|
-
task({
|
|
152
|
-
id: 'up',
|
|
153
|
-
command: `node "${noJson}"`,
|
|
154
|
-
ports: { outputs: [{ name: 'city', type: 'string' }] },
|
|
155
|
-
}),
|
|
156
|
-
task({
|
|
157
|
-
id: 'down',
|
|
158
|
-
depends_on: ['up'],
|
|
159
|
-
command: `node "${echo}" "{{inputs.city}}"`,
|
|
160
|
-
ports: {
|
|
161
|
-
inputs: [{ name: 'city', type: 'string', required: true }],
|
|
162
|
-
},
|
|
163
|
-
}),
|
|
164
|
-
]);
|
|
165
|
-
const { events, success } = await run(config, dir);
|
|
166
|
-
expect(success).toBe(false);
|
|
167
|
-
expect(finalStatusFrom(events, 't.up')).toBe('success');
|
|
168
|
-
const downStatus = finalStatusFrom(events, 't.down');
|
|
169
|
-
expect(downStatus).toBe('blocked');
|
|
170
|
-
// The blocked update carries the engine's diagnostic in stderr so
|
|
171
|
-
// the editor can display it verbatim.
|
|
172
|
-
const downFinal = finalUpdateFor(events, 't.down');
|
|
173
|
-
if (downFinal?.type === 'task_update') {
|
|
174
|
-
expect(downFinal.stderr ?? '').toMatch(/missing required input.*city/i);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
finally {
|
|
178
|
-
rmSync(dir, { recursive: true, force: true });
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
test('optional input with default is applied when upstream does not supply it', async () => {
|
|
182
|
-
const dir = makeDir();
|
|
183
|
-
try {
|
|
184
|
-
const noop = join(dir, 'noop.js');
|
|
185
|
-
writeFileSync(noop, 'process.stdout.write("ok\\n");\n');
|
|
186
|
-
const echo = writeEchoArgsScript(dir, 'echo');
|
|
187
|
-
const config = pipeline([
|
|
188
|
-
task({ id: 'up', command: `node "${noop}"` }),
|
|
189
|
-
task({
|
|
190
|
-
id: 'down',
|
|
191
|
-
depends_on: ['up'],
|
|
192
|
-
command: `node "${echo}" "{{inputs.lang}}"`,
|
|
193
|
-
ports: {
|
|
194
|
-
inputs: [{ name: 'lang', type: 'string', default: 'en' }],
|
|
195
|
-
},
|
|
196
|
-
}),
|
|
197
|
-
]);
|
|
198
|
-
const { events, success } = await run(config, dir);
|
|
199
|
-
expect(success).toBe(true);
|
|
200
|
-
const downFinal = finalUpdateFor(events, 't.down');
|
|
201
|
-
if (downFinal?.type === 'task_update') {
|
|
202
|
-
expect((downFinal.stdout ?? '').trim()).toBe('en');
|
|
203
|
-
expect(downFinal.inputs).toEqual({ lang: 'en' });
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
finally {
|
|
207
|
-
rmSync(dir, { recursive: true, force: true });
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
test('optional input without default or upstream → empty placeholder', async () => {
|
|
211
|
-
const dir = makeDir();
|
|
212
|
-
try {
|
|
213
|
-
const noop = join(dir, 'noop.js');
|
|
214
|
-
writeFileSync(noop, 'process.stdout.write("ok\\n");\n');
|
|
215
|
-
// Use a Node script that prints `|<arg>|` so the empty substitution
|
|
216
|
-
// shows as `||` — cross-platform argv handling.
|
|
217
|
-
const sentinel = join(dir, 'sentinel.js');
|
|
218
|
-
writeFileSync(sentinel, 'process.stdout.write("<" + (process.argv[2] || "") + ">\\n");\n');
|
|
219
|
-
const config = pipeline([
|
|
220
|
-
task({ id: 'up', command: `node "${noop}"` }),
|
|
221
|
-
task({
|
|
222
|
-
id: 'down',
|
|
223
|
-
depends_on: ['up'],
|
|
224
|
-
command: `node "${sentinel}" "{{inputs.note}}"`,
|
|
225
|
-
ports: {
|
|
226
|
-
inputs: [{ name: 'note', type: 'string' }],
|
|
227
|
-
},
|
|
228
|
-
}),
|
|
229
|
-
]);
|
|
230
|
-
const { events, success } = await run(config, dir);
|
|
231
|
-
expect(success).toBe(true);
|
|
232
|
-
const downFinal = finalUpdateFor(events, 't.down');
|
|
233
|
-
if (downFinal?.type === 'task_update') {
|
|
234
|
-
expect((downFinal.stdout ?? '').trim()).toBe('<>');
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
finally {
|
|
238
|
-
rmSync(dir, { recursive: true, force: true });
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
test('tasks with no ports declared are unaffected', async () => {
|
|
242
|
-
const dir = makeDir();
|
|
243
|
-
try {
|
|
244
|
-
const config = pipeline([task({ id: 'plain', command: 'echo hello' })]);
|
|
245
|
-
const { events, success } = await run(config, dir);
|
|
246
|
-
expect(success).toBe(true);
|
|
247
|
-
const final = finalUpdateFor(events, 't.plain');
|
|
248
|
-
if (final?.type === 'task_update') {
|
|
249
|
-
expect(final.outputs).toBeFalsy();
|
|
250
|
-
expect(final.inputs).toEqual({});
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
finally {
|
|
254
|
-
rmSync(dir, { recursive: true, force: true });
|
|
255
|
-
}
|
|
256
|
-
});
|
|
257
|
-
test('ambiguous name-match blocks downstream unless disambiguated', async () => {
|
|
258
|
-
const dir = makeDir();
|
|
259
|
-
try {
|
|
260
|
-
const emitA = writeEmitScript(dir, 'emitA', { val: 'from-a' });
|
|
261
|
-
const emitB = writeEmitScript(dir, 'emitB', { val: 'from-b' });
|
|
262
|
-
const echo = writeEchoArgsScript(dir, 'echo');
|
|
263
|
-
// Two upstreams both export `val`; downstream auto-matches → ambiguous.
|
|
264
|
-
const ambigConfig = pipeline([
|
|
265
|
-
task({
|
|
266
|
-
id: 'a',
|
|
267
|
-
command: `node "${emitA}"`,
|
|
268
|
-
ports: { outputs: [{ name: 'val', type: 'string' }] },
|
|
269
|
-
}),
|
|
270
|
-
task({
|
|
271
|
-
id: 'b',
|
|
272
|
-
command: `node "${emitB}"`,
|
|
273
|
-
ports: { outputs: [{ name: 'val', type: 'string' }] },
|
|
274
|
-
}),
|
|
275
|
-
task({
|
|
276
|
-
id: 'down',
|
|
277
|
-
depends_on: ['a', 'b'],
|
|
278
|
-
command: `node "${echo}" "{{inputs.val}}"`,
|
|
279
|
-
ports: {
|
|
280
|
-
inputs: [{ name: 'val', type: 'string', required: true }],
|
|
281
|
-
},
|
|
282
|
-
}),
|
|
283
|
-
]);
|
|
284
|
-
const { events: evAmbig } = await run(ambigConfig, dir);
|
|
285
|
-
expect(finalStatusFrom(evAmbig, 't.down')).toBe('blocked');
|
|
286
|
-
const ambigFinal = finalUpdateFor(evAmbig, 't.down');
|
|
287
|
-
if (ambigFinal?.type === 'task_update') {
|
|
288
|
-
expect(ambigFinal.stderr ?? '').toMatch(/ambiguous|multiple upstreams/i);
|
|
289
|
-
}
|
|
290
|
-
// Now add an explicit `from: "t.b.val"` → downstream should succeed.
|
|
291
|
-
const dir2 = makeDir();
|
|
292
|
-
try {
|
|
293
|
-
const emitA2 = writeEmitScript(dir2, 'emitA', { val: 'from-a' });
|
|
294
|
-
const emitB2 = writeEmitScript(dir2, 'emitB', { val: 'from-b' });
|
|
295
|
-
const echo2 = writeEchoArgsScript(dir2, 'echo');
|
|
296
|
-
const explicitConfig = pipeline([
|
|
297
|
-
task({
|
|
298
|
-
id: 'a',
|
|
299
|
-
command: `node "${emitA2}"`,
|
|
300
|
-
ports: { outputs: [{ name: 'val', type: 'string' }] },
|
|
301
|
-
}),
|
|
302
|
-
task({
|
|
303
|
-
id: 'b',
|
|
304
|
-
command: `node "${emitB2}"`,
|
|
305
|
-
ports: { outputs: [{ name: 'val', type: 'string' }] },
|
|
306
|
-
}),
|
|
307
|
-
task({
|
|
308
|
-
id: 'down',
|
|
309
|
-
depends_on: ['a', 'b'],
|
|
310
|
-
command: `node "${echo2}" "{{inputs.val}}"`,
|
|
311
|
-
ports: {
|
|
312
|
-
inputs: [
|
|
313
|
-
{ name: 'val', type: 'string', required: true, from: 't.b.val' },
|
|
314
|
-
],
|
|
315
|
-
},
|
|
316
|
-
}),
|
|
317
|
-
]);
|
|
318
|
-
const { events: evExplicit, success } = await run(explicitConfig, dir2);
|
|
319
|
-
expect(success).toBe(true);
|
|
320
|
-
const downFinal = finalUpdateFor(evExplicit, 't.down');
|
|
321
|
-
if (downFinal?.type === 'task_update') {
|
|
322
|
-
expect((downFinal.stdout ?? '').trim()).toBe('from-b');
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
finally {
|
|
326
|
-
rmSync(dir2, { recursive: true, force: true });
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
finally {
|
|
330
|
-
rmSync(dir, { recursive: true, force: true });
|
|
331
|
-
}
|
|
332
|
-
});
|
|
333
|
-
test('string → number coercion happens during input resolution', async () => {
|
|
334
|
-
const dir = makeDir();
|
|
335
|
-
try {
|
|
336
|
-
// Emit `id` as a string; downstream declares it as `number`.
|
|
337
|
-
const emit = writeEmitScript(dir, 'emit', { id: '42' });
|
|
338
|
-
const script = join(dir, 'assert-number.js');
|
|
339
|
-
writeFileSync(script, `const v = process.argv[2];
|
|
340
|
-
const n = Number(v);
|
|
341
|
-
if (!Number.isFinite(n)) { process.exit(2); }
|
|
342
|
-
process.stdout.write("n=" + n + "\\n");
|
|
343
|
-
`);
|
|
344
|
-
const config = pipeline([
|
|
345
|
-
task({
|
|
346
|
-
id: 'up',
|
|
347
|
-
command: `node "${emit}"`,
|
|
348
|
-
ports: {
|
|
349
|
-
// upstream declares string — matches the emitted literal.
|
|
350
|
-
outputs: [{ name: 'id', type: 'string' }],
|
|
351
|
-
},
|
|
352
|
-
}),
|
|
353
|
-
task({
|
|
354
|
-
id: 'down',
|
|
355
|
-
depends_on: ['up'],
|
|
356
|
-
command: `node "${script}" "{{inputs.id}}"`,
|
|
357
|
-
ports: {
|
|
358
|
-
// downstream demands number — resolve should coerce "42" → 42.
|
|
359
|
-
inputs: [{ name: 'id', type: 'number', required: true }],
|
|
360
|
-
},
|
|
361
|
-
}),
|
|
362
|
-
]);
|
|
363
|
-
const { events, success } = await run(config, dir);
|
|
364
|
-
expect(success).toBe(true);
|
|
365
|
-
const downFinal = finalUpdateFor(events, 't.down');
|
|
366
|
-
if (downFinal?.type === 'task_update') {
|
|
367
|
-
expect((downFinal.stdout ?? '').trim()).toBe('n=42');
|
|
368
|
-
// Value on the wire should be the coerced number, not the raw
|
|
369
|
-
// string, so the editor renders it faithfully too.
|
|
370
|
-
expect(downFinal.inputs).toEqual({ id: 42 });
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
finally {
|
|
374
|
-
rmSync(dir, { recursive: true, force: true });
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
});
|
|
378
|
-
//# sourceMappingURL=engine-ports.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"engine-ports.test.js","sourceRoot":"","sources":["../src/engine-ports.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-registry.test.d.ts","sourceRoot":"","sources":["../src/plugin-registry.test.ts"],"names":[],"mappings":""}
|