acpus 0.0.2 → 0.2.0
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 +6 -103
- package/dist/catalog.d.ts +27 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +186 -0
- package/dist/catalog.js.map +1 -0
- package/dist/follow.d.ts +23 -0
- package/dist/follow.d.ts.map +1 -0
- package/dist/follow.js +109 -0
- package/dist/follow.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +522 -0
- package/dist/index.js.map +1 -0
- package/dist/io.d.ts +4 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +28 -0
- package/dist/io.js.map +1 -0
- package/dist/observations.d.ts +26 -0
- package/dist/observations.d.ts.map +1 -0
- package/dist/observations.js +60 -0
- package/dist/observations.js.map +1 -0
- package/dist/output.d.ts +9 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +51 -0
- package/dist/output.js.map +1 -0
- package/dist/runs-show.d.ts +5 -0
- package/dist/runs-show.d.ts.map +1 -0
- package/dist/runs-show.js +72 -0
- package/dist/runs-show.js.map +1 -0
- package/dist/supervisor-client.d.ts +9 -0
- package/dist/supervisor-client.d.ts.map +1 -0
- package/dist/supervisor-client.js +8 -0
- package/dist/supervisor-client.js.map +1 -0
- package/dist/supervisor.d.ts +18 -0
- package/dist/supervisor.d.ts.map +1 -0
- package/dist/supervisor.js +24 -0
- package/dist/supervisor.js.map +1 -0
- package/package.json +30 -44
- package/dist/cli.d.mts +0 -1
- package/dist/cli.mjs +0 -4017
- package/dist/index.d.mts +0 -2194
- package/dist/index.mjs +0 -243
- package/dist/monitor-app-CPlEcyHR.mjs +0 -369
- package/dist/monitor-rendering-LGr9Ebd_.mjs +0 -78
- package/dist/run-picker-app-utJ2f5CU.mjs +0 -104
- package/dist/run-workflow-DdIAC8Zu.mjs +0 -12922
- package/schemas/workflow-spec.schema.json +0 -2649
package/README.md
CHANGED
|
@@ -1,110 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
<img src="page/logo/logo-opus-mark.svg" alt="Acpus mark" width="120">
|
|
3
|
-
</p>
|
|
1
|
+
# acpus
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
<p align="center" font-style="italic">Every run is an opus.</p>
|
|
3
|
+
The `acpus` package provides the Acpus CLI for local durable ACP agent workflows.
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
<a href="https://www.npmjs.com/package/acpus"><img src="https://img.shields.io/npm/v/acpus?label=npm" alt="npm version"></a>
|
|
10
|
-
<a href="https://github.com/kelvinschen/acpus/actions/workflows/publish.yml"><img src="https://img.shields.io/github/actions/workflow/status/kelvinschen/acpus/publish.yml?label=publish" alt="Publish workflow status"></a>
|
|
11
|
-
<a href="LICENSE"><img src="https://img.shields.io/npm/l/acpus?label=license" alt="License"></a>
|
|
12
|
-
<img src="https://img.shields.io/node/v/acpus?label=node" alt="Node version">
|
|
13
|
-
</p>
|
|
5
|
+
Install:
|
|
14
6
|
|
|
15
|
-
|
|
16
|
-
> Acpus is currently in alpha. CLI/runtime interfaces will change frequently.
|
|
17
|
-
|
|
18
|
-
Acpus is a runtime-driven workflow orchestrator for ACP agents, built on the acpx agent runtime. You hand it a *workflow spec*; Acpus validates it, compiles a deterministic execution plan, conducts heterogeneous fanout across lanes, and tracks every run as a numbered, replayable execution, or say, an *opus*.
|
|
19
|
-
|
|
20
|
-
## Quick Start
|
|
21
|
-
|
|
22
|
-
```bash
|
|
7
|
+
```sh
|
|
23
8
|
npm install -g acpus
|
|
24
|
-
|
|
25
|
-
acpus plan workflows/examples/simple-feature.workflow.spec.yaml
|
|
26
|
-
|
|
27
|
-
acpus run workflows/examples/simple-feature.workflow.spec.yaml
|
|
28
|
-
|
|
29
|
-
acpus monitor
|
|
30
9
|
```
|
|
31
10
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
npx skills add kelvinschen/acpus --skill acpus
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Commands
|
|
39
|
-
|
|
40
|
-
Acpus commands are grouped by workflow phase. Optional parameters are shown in brackets.
|
|
41
|
-
|
|
42
|
-
### Compose — plan, save
|
|
43
|
-
|
|
44
|
-
| Command | Options | Purpose |
|
|
45
|
-
|---|---|---|
|
|
46
|
-
| `acpus plan <spec>` | `--global`, `--quiet`, `--json` | Validate a spec file or saved workflow name and preview the compiled execution plan |
|
|
47
|
-
| `acpus save <name> <spec>` | `--overwrite`, `--global`, `--json` | Save a workflow spec to the workflow store |
|
|
48
|
-
|
|
49
|
-
`plan --json` emits a structured plan preview for automation. `save --json` emits `{ok, workflow, path}` so scripts can capture the saved workflow path.
|
|
50
|
-
|
|
51
|
-
### Conduct — run, follow, monitor, resume
|
|
52
|
-
|
|
53
|
-
| Command | Options | Purpose |
|
|
54
|
-
|---|---|---|
|
|
55
|
-
| `acpus run [spec]` | `--global`, `--input <json-or-yaml-or-path>`, `--wait`, `--json` | Prepare and start a workflow from a spec file or saved workflow name |
|
|
56
|
-
| `acpus follow [run]` | `--json` | Select or attach to a run and stream events in real time |
|
|
57
|
-
| `acpus monitor [run]` | `--json` | Select or open a run in the terminal UI, or print the monitor view as JSON |
|
|
58
|
-
| `acpus monitor detail <run> <task-id>` | `--json` | Show bounded detail for one stage task |
|
|
59
|
-
| `acpus resume <run>` | `--allow-partial-fanout <stage...>`, `--max-fanout-items <stage=count...>`, `--skip-fanout-item <stage=index...>`, `--force`, `--wait`, `--json` | Resume a blocked or failed run, or recover a stale running/pending run with `--force` |
|
|
60
|
-
|
|
61
|
-
`--input` accepts an inline JSON object or a JSON/YAML file path, for example `--input input.yaml`.
|
|
62
|
-
|
|
63
|
-
<figure align="center">
|
|
64
|
-
<img src="page/img/monitor_basic.webp" alt="Acpus monitor TUI — real-time run inspection with stage progress, lane status, and event stream" width="720">
|
|
65
|
-
<br>
|
|
66
|
-
<sup><em>Real-time run inspection — stages, lanes, and the event stream at a glance.</em></sup>
|
|
67
|
-
</figure>
|
|
68
|
-
|
|
69
|
-
### Catalogue — list, show
|
|
70
|
-
|
|
71
|
-
| Command | Options | Purpose |
|
|
72
|
-
|---|---|---|
|
|
73
|
-
| `acpus list workflows` | `--global`, `--json` | List saved workflows |
|
|
74
|
-
| `acpus list runs` | `--json` | List project runs |
|
|
75
|
-
| `acpus show workflow <name>` | `--global`, `--json` | Display a saved workflow |
|
|
76
|
-
| `acpus show run <id>` | `--json` | Display a run by logical run id or run directory |
|
|
77
|
-
|
|
78
|
-
### Internal
|
|
79
|
-
|
|
80
|
-
| Command | Purpose |
|
|
81
|
-
|---|---|
|
|
82
|
-
| `acpus _run-worker <run>` | Hidden background worker entry point used by `run` and `resume`; not intended for direct use |
|
|
83
|
-
|
|
84
|
-
## Architecture
|
|
85
|
-
|
|
86
|
-
Acpus sits between the author and the acpx runtime. The main agent produces a *workflow spec*. Acpus reads it, validates it against the JSON schema, and compiles it into an *execution plan* — a deterministic sequence of stages, each containing parallel lanes that map to independent acpx sessions.
|
|
87
|
-
|
|
88
|
-
Run directories live under `.acpus/runs/<id>/`. Each contains:
|
|
89
|
-
|
|
90
|
-
- `workflow.spec.yaml` — the original workflow spec
|
|
91
|
-
- `execution-plan.json` — the compiled plan
|
|
92
|
-
- `input.json` — resolved inputs at launch time
|
|
93
|
-
- `outputs/` — stage outputs and final artefacts
|
|
94
|
-
- `attempts/` — raw attempt records with agent transcripts
|
|
95
|
-
- `acpx-state/` — run-local acpx session state
|
|
96
|
-
- `sessions/` — per-lane session logs
|
|
97
|
-
- `events.ndjson` — timestamped event log for the entire run
|
|
98
|
-
|
|
99
|
-
The orchestrator does not generate or execute ACPX flow files directly. It drives acpx through its runtime API.
|
|
100
|
-
|
|
101
|
-
## Documentation
|
|
102
|
-
|
|
103
|
-
- [Developer documentation](docs/README.md)
|
|
104
|
-
- [Design and implementation specifications](specs/INDEX.md)
|
|
105
|
-
- [CLI guide](docs/cli.md)
|
|
106
|
-
- [Error code guide](docs/error-codes.md)
|
|
107
|
-
|
|
108
|
-
## License
|
|
11
|
+
Use it to lint Workflow Specs, run Workflows, inspect Runs, control Runs, replay persisted Runs, and open the terminal visualizer.
|
|
109
12
|
|
|
110
|
-
|
|
13
|
+
See the repository README for full usage: https://github.com/kelvinschen/acpus
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { globalWorkflowRoot, type Diagnostic } from "@acpus/core";
|
|
2
|
+
export type WorkflowCatalogScope = "project" | "global";
|
|
3
|
+
export type WorkflowCatalogStatus = "ready" | "invalid" | "conflict";
|
|
4
|
+
export interface WorkflowCatalogEntry {
|
|
5
|
+
scope: WorkflowCatalogScope;
|
|
6
|
+
ref?: string;
|
|
7
|
+
name?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
input?: Record<string, unknown>;
|
|
10
|
+
inputKeys: string[];
|
|
11
|
+
path: string;
|
|
12
|
+
status: WorkflowCatalogStatus;
|
|
13
|
+
diagnostics: Diagnostic[];
|
|
14
|
+
}
|
|
15
|
+
export interface ResolvedWorkflowTarget {
|
|
16
|
+
sourcePath: string;
|
|
17
|
+
source: string;
|
|
18
|
+
workflowRef?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function projectWorkflowRoot(workspace?: string): string;
|
|
21
|
+
export { globalWorkflowRoot };
|
|
22
|
+
export declare function listWorkflowCatalog(workspace?: string): WorkflowCatalogEntry[];
|
|
23
|
+
export declare function resolveWorkflowTarget(target: string, workspace?: string): ResolvedWorkflowTarget;
|
|
24
|
+
export declare function findWorkflowCatalogEntry(target: string, workspace?: string): WorkflowCatalogEntry;
|
|
25
|
+
export declare function looksLikeWorkflowPath(target: string): boolean;
|
|
26
|
+
export declare function resolveWorkflowPath(path: string): string;
|
|
27
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAsC,KAAK,UAAU,EAAmB,MAAM,aAAa,CAAC;AAEvH,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,QAAQ,CAAC;AACxD,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,CAAC;AAErE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,oBAAoB,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,qBAAqB,CAAC;IAC9B,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,mBAAmB,CAAC,SAAS,SAAgB,GAAG,MAAM,CAErE;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAE9B,wBAAgB,mBAAmB,CAAC,SAAS,SAAgB,GAAG,oBAAoB,EAAE,CA+BrF;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,SAAgB,GAAG,sBAAsB,CAyBvG;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,SAAgB,GAAG,oBAAoB,CAUxG;AA+FD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAO7D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQxD"}
|
package/dist/catalog.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { parse as parseYaml } from "yaml";
|
|
5
|
+
import { globalWorkflowRoot, lintWorkflow, workflowSourcePolicy } from "@acpus/core";
|
|
6
|
+
export function projectWorkflowRoot(workspace = process.cwd()) {
|
|
7
|
+
return resolve(workspace, ".acpus", "workflows");
|
|
8
|
+
}
|
|
9
|
+
export { globalWorkflowRoot };
|
|
10
|
+
export function listWorkflowCatalog(workspace = process.cwd()) {
|
|
11
|
+
const sourcePolicy = workflowSourcePolicy(workspace);
|
|
12
|
+
const entries = [
|
|
13
|
+
...scanScope("project", projectWorkflowRoot(workspace), sourcePolicy),
|
|
14
|
+
...scanScope("global", globalWorkflowRoot(), sourcePolicy)
|
|
15
|
+
];
|
|
16
|
+
for (const scope of ["project", "global"]) {
|
|
17
|
+
const byName = new Map();
|
|
18
|
+
for (const entry of entries) {
|
|
19
|
+
if (entry.scope !== scope || !entry.name || entry.status === "invalid")
|
|
20
|
+
continue;
|
|
21
|
+
const group = byName.get(entry.name) ?? [];
|
|
22
|
+
group.push(entry);
|
|
23
|
+
byName.set(entry.name, group);
|
|
24
|
+
}
|
|
25
|
+
for (const [name, group] of byName) {
|
|
26
|
+
if (group.length <= 1)
|
|
27
|
+
continue;
|
|
28
|
+
for (const entry of group) {
|
|
29
|
+
entry.status = "conflict";
|
|
30
|
+
entry.ref = undefined;
|
|
31
|
+
entry.diagnostics = [{
|
|
32
|
+
severity: "error",
|
|
33
|
+
code: "CATALOG_CONFLICT",
|
|
34
|
+
message: `Workflow name '${name}' is duplicated in ${scope} catalog.`,
|
|
35
|
+
path: "$.name"
|
|
36
|
+
}];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return entries;
|
|
41
|
+
}
|
|
42
|
+
export function resolveWorkflowTarget(target, workspace = process.cwd()) {
|
|
43
|
+
if (looksLikeWorkflowPath(target)) {
|
|
44
|
+
const sourcePath = resolveWorkflowPath(target);
|
|
45
|
+
return { sourcePath, source: readFileSync(sourcePath, "utf8") };
|
|
46
|
+
}
|
|
47
|
+
const catalog = listWorkflowCatalog(workspace);
|
|
48
|
+
const matches = catalog.filter((entry) => entry.status === "ready" && matchesCatalogTarget(entry, target));
|
|
49
|
+
if (matches.length === 0) {
|
|
50
|
+
const blocked = catalog.find((entry) => matchesCatalogTarget(entry, target));
|
|
51
|
+
if (blocked) {
|
|
52
|
+
throw new Error(`Workflow '${target}' is ${blocked.status}: ${blocked.diagnostics.map((d) => d.message).join("; ")}`);
|
|
53
|
+
}
|
|
54
|
+
throw new Error(`Workflow '${target}' was not found in the Workflow Catalog.`);
|
|
55
|
+
}
|
|
56
|
+
if (matches.length > 1) {
|
|
57
|
+
throw new Error(`Workflow short name '${target}' is ambiguous; use a full ref such as ${matches.map((m) => m.ref).join(" or ")}.`);
|
|
58
|
+
}
|
|
59
|
+
const entry = matches[0];
|
|
60
|
+
return {
|
|
61
|
+
sourcePath: entry.path,
|
|
62
|
+
source: readFileSync(entry.path, "utf8"),
|
|
63
|
+
workflowRef: entry.ref
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function findWorkflowCatalogEntry(target, workspace = process.cwd()) {
|
|
67
|
+
const catalog = listWorkflowCatalog(workspace);
|
|
68
|
+
const matches = catalog.filter((entry) => matchesCatalogTarget(entry, target));
|
|
69
|
+
if (matches.length === 0) {
|
|
70
|
+
throw new Error(`Workflow '${target}' was not found in the Workflow Catalog.`);
|
|
71
|
+
}
|
|
72
|
+
if (matches.length > 1) {
|
|
73
|
+
throw new Error(`Workflow name '${target}' is ambiguous; use a full ref when available.`);
|
|
74
|
+
}
|
|
75
|
+
return matches[0];
|
|
76
|
+
}
|
|
77
|
+
function matchesCatalogTarget(entry, target) {
|
|
78
|
+
return entry.ref === target || entry.name === target || (entry.name !== undefined && `${entry.scope}:${entry.name}` === target);
|
|
79
|
+
}
|
|
80
|
+
function scanScope(scope, root, sourcePolicy) {
|
|
81
|
+
if (!existsSync(root))
|
|
82
|
+
return [];
|
|
83
|
+
const files = collectCandidateFiles(root);
|
|
84
|
+
return files.map((file) => entryFromFile(scope, file, sourcePolicy));
|
|
85
|
+
}
|
|
86
|
+
function collectCandidateFiles(root) {
|
|
87
|
+
const out = [];
|
|
88
|
+
const visit = (dir) => {
|
|
89
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
90
|
+
const path = join(dir, entry.name);
|
|
91
|
+
if (entry.isDirectory()) {
|
|
92
|
+
visit(path);
|
|
93
|
+
}
|
|
94
|
+
else if (entry.isFile() && isWorkflowCandidate(entry.name)) {
|
|
95
|
+
out.push(path);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
visit(root);
|
|
100
|
+
return out.sort();
|
|
101
|
+
}
|
|
102
|
+
function entryFromFile(scope, path, sourcePolicy) {
|
|
103
|
+
const source = readFileSync(path, "utf8");
|
|
104
|
+
const parsed = parseSpecSummary(source);
|
|
105
|
+
const lint = lintCatalogEntry(source, path, sourcePolicy);
|
|
106
|
+
const name = parsed.name;
|
|
107
|
+
const status = lint.ok && name ? "ready" : "invalid";
|
|
108
|
+
return {
|
|
109
|
+
scope,
|
|
110
|
+
ref: status === "ready" ? `${scope}:${name}` : undefined,
|
|
111
|
+
name,
|
|
112
|
+
description: parsed.description,
|
|
113
|
+
input: parsed.input,
|
|
114
|
+
inputKeys: Object.keys(parsed.input ?? {}),
|
|
115
|
+
path,
|
|
116
|
+
status,
|
|
117
|
+
diagnostics: lint.ok && !name
|
|
118
|
+
? [{ severity: "error", code: "CATALOG_NAME", message: "Workflow Spec must declare a string name.", path: "$.name" }]
|
|
119
|
+
: lint.diagnostics
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function lintCatalogEntry(source, path, sourcePolicy) {
|
|
123
|
+
try {
|
|
124
|
+
return lintWorkflow(source, {
|
|
125
|
+
sourcePath: path,
|
|
126
|
+
includeResolver: sourcePolicy.createIncludeResolver(path)
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
return {
|
|
131
|
+
ok: false,
|
|
132
|
+
diagnostics: [{
|
|
133
|
+
severity: "error",
|
|
134
|
+
code: "CATALOG_LINT",
|
|
135
|
+
message: error instanceof Error ? error.message : String(error),
|
|
136
|
+
path: "$"
|
|
137
|
+
}]
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function parseSpecSummary(source) {
|
|
142
|
+
try {
|
|
143
|
+
const parsed = parseYaml(source);
|
|
144
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
|
|
145
|
+
return {};
|
|
146
|
+
const map = parsed;
|
|
147
|
+
return {
|
|
148
|
+
name: typeof map.name === "string" ? map.name : undefined,
|
|
149
|
+
description: typeof map.description === "string" ? map.description : undefined,
|
|
150
|
+
input: typeof map.input === "object" && map.input !== null && !Array.isArray(map.input)
|
|
151
|
+
? map.input
|
|
152
|
+
: undefined
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
return {};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function isWorkflowCandidate(filename) {
|
|
160
|
+
return filename === "workflow.yaml"
|
|
161
|
+
|| filename === "workflow.yml"
|
|
162
|
+
|| filename.endsWith(".workflow.yaml")
|
|
163
|
+
|| filename.endsWith(".workflow.yml")
|
|
164
|
+
|| filename.endsWith(".workflow.spec.yaml")
|
|
165
|
+
|| filename.endsWith(".workflow.spec.yml");
|
|
166
|
+
}
|
|
167
|
+
export function looksLikeWorkflowPath(target) {
|
|
168
|
+
return target.startsWith(".")
|
|
169
|
+
|| target.startsWith("/")
|
|
170
|
+
|| target.startsWith("~")
|
|
171
|
+
|| target.includes("/")
|
|
172
|
+
|| target.endsWith(".yaml")
|
|
173
|
+
|| target.endsWith(".yml");
|
|
174
|
+
}
|
|
175
|
+
export function resolveWorkflowPath(path) {
|
|
176
|
+
if (path === "~")
|
|
177
|
+
return homedir();
|
|
178
|
+
if (path.startsWith("~/"))
|
|
179
|
+
return resolve(homedir(), path.slice(2));
|
|
180
|
+
const resolved = resolve(process.cwd(), path);
|
|
181
|
+
if (!existsSync(resolved) || !statSync(resolved).isFile()) {
|
|
182
|
+
throw new Error(`Workflow Spec path not found: ${path}`);
|
|
183
|
+
}
|
|
184
|
+
return resolved;
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,oBAAoB,EAAoC,MAAM,aAAa,CAAC;AAuBvH,MAAM,UAAU,mBAAmB,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE;IAC3D,OAAO,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AACnD,CAAC;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAE9B,MAAM,UAAU,mBAAmB,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE;IAC3D,MAAM,YAAY,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG;QACd,GAAG,SAAS,CAAC,SAAS,EAAE,mBAAmB,CAAC,SAAS,CAAC,EAAE,YAAY,CAAC;QACrE,GAAG,SAAS,CAAC,QAAQ,EAAE,kBAAkB,EAAE,EAAE,YAAY,CAAC;KAC3D,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAU,EAAE,CAAC;QACnD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkC,CAAC;QACzD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,KAAK,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;gBAAE,SAAS;YACjF,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAC3C,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClB,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;YACnC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC;gBAAE,SAAS;YAChC,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;gBAC1B,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC;gBAC1B,KAAK,CAAC,GAAG,GAAG,SAAS,CAAC;gBACtB,KAAK,CAAC,WAAW,GAAG,CAAC;wBACnB,QAAQ,EAAE,OAAO;wBACjB,IAAI,EAAE,kBAAkB;wBACxB,OAAO,EAAE,kBAAkB,IAAI,sBAAsB,KAAK,WAAW;wBACrE,IAAI,EAAE,QAAQ;qBACf,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAc,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE;IAC7E,IAAI,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,CAAC;IAClE,CAAC;IAED,MAAM,OAAO,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO,IAAI,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3G,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7E,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,aAAa,MAAM,QAAQ,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxH,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,aAAa,MAAM,0CAA0C,CAAC,CAAC;IACjF,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,wBAAwB,MAAM,0CAA0C,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrI,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,OAAO;QACL,UAAU,EAAE,KAAK,CAAC,IAAI;QACtB,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC;QACxC,WAAW,EAAE,KAAK,CAAC,GAAG;KACvB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,MAAc,EAAE,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE;IAChF,MAAM,OAAO,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/E,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,aAAa,MAAM,0CAA0C,CAAC,CAAC;IACjF,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,kBAAkB,MAAM,gDAAgD,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED,SAAS,oBAAoB,CAAC,KAA2B,EAAE,MAAc;IACvE,OAAO,KAAK,CAAC,GAAG,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,MAAM,CAAC,CAAC;AAClI,CAAC;AAED,SAAS,SAAS,CAAC,KAA2B,EAAE,IAAY,EAAE,YAAqD;IACjH,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY;IACzC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,KAAK,GAAG,CAAC,GAAW,EAAQ,EAAE;QAClC,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACnC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,KAAK,CAAC,IAAI,CAAC,CAAC;YACd,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7D,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,CAAC;IACZ,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AAED,SAAS,aAAa,CAAC,KAA2B,EAAE,IAAY,EAAE,YAAqD;IACrH,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,MAAM,MAAM,GAA0B,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAE5E,OAAO;QACL,KAAK;QACL,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;QACxD,IAAI;QACJ,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;QAC1C,IAAI;QACJ,MAAM;QACN,WAAW,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI;YAC3B,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,2CAA2C,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;YACrH,CAAC,CAAC,IAAI,CAAC,WAAW;KACrB,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAc,EAAE,IAAY,EAAE,YAAqD;IAC3G,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,MAAM,EAAE;YAC1B,UAAU,EAAE,IAAI;YAChB,eAAe,EAAE,YAAY,CAAC,qBAAqB,CAAC,IAAI,CAAC;SAC1D,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,EAAE,EAAE,KAAK;YACT,WAAW,EAAE,CAAC;oBACZ,QAAQ,EAAE,OAAO;oBACjB,IAAI,EAAE,cAAc;oBACpB,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;oBAC/D,IAAI,EAAE,GAAG;iBACV,CAAC;SACH,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAc;IACtC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAY,CAAC;QAC5C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,CAAC;QACtF,MAAM,GAAG,GAAG,MAAiC,CAAC;QAC9C,OAAO;YACL,IAAI,EAAE,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;YACzD,WAAW,EAAE,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;YAC9E,KAAK,EAAE,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAI,GAAG,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;gBACrF,CAAC,CAAC,GAAG,CAAC,KAAgC;gBACtC,CAAC,CAAC,SAAS;SACd,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAgB;IAC3C,OAAO,QAAQ,KAAK,eAAe;WAC9B,QAAQ,KAAK,cAAc;WAC3B,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC;WACnC,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC;WAClC,QAAQ,CAAC,QAAQ,CAAC,qBAAqB,CAAC;WACxC,QAAQ,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,OAAO,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;WACxB,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;WACtB,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;WACtB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;WACpB,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;WACxB,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,OAAO,EAAE,CAAC;IACnC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
package/dist/follow.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FollowLoop — polls a running Run and emits observations to stdout.
|
|
3
|
+
*
|
|
4
|
+
* Used by `acpus workflows run <spec>` (foreground follow mode) and
|
|
5
|
+
* `acpus workflows run <spec> --json`.
|
|
6
|
+
* Tracks node state changes and deduplicates: only emits when a node is first
|
|
7
|
+
* observed or when its state changes.
|
|
8
|
+
*
|
|
9
|
+
* Ctrl-C detaches (exit 0) without cancelling the Run.
|
|
10
|
+
*/
|
|
11
|
+
import type { RunSupervisorClient, RunStatus } from "@acpus/runtime";
|
|
12
|
+
export interface FollowOptions {
|
|
13
|
+
/** Emit JSONL observations instead of human-readable glyphs */
|
|
14
|
+
json?: boolean;
|
|
15
|
+
/** Polling interval in milliseconds (default 400) */
|
|
16
|
+
intervalMs?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Run a follow loop until the Run reaches a terminal state.
|
|
20
|
+
* Returns the terminal RunStatus for exit-code mapping.
|
|
21
|
+
*/
|
|
22
|
+
export declare function followRun(client: RunSupervisorClient, runId: string, options?: FollowOptions): Promise<RunStatus>;
|
|
23
|
+
//# sourceMappingURL=follow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"follow.d.ts","sourceRoot":"","sources":["../src/follow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAgC,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGnG,MAAM,WAAW,aAAa;IAC5B,+DAA+D;IAC/D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,mBAAmB,EAC3B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,SAAS,CAAC,CAuFpB"}
|
package/dist/follow.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FollowLoop — polls a running Run and emits observations to stdout.
|
|
3
|
+
*
|
|
4
|
+
* Used by `acpus workflows run <spec>` (foreground follow mode) and
|
|
5
|
+
* `acpus workflows run <spec> --json`.
|
|
6
|
+
* Tracks node state changes and deduplicates: only emits when a node is first
|
|
7
|
+
* observed or when its state changes.
|
|
8
|
+
*
|
|
9
|
+
* Ctrl-C detaches (exit 0) without cancelling the Run.
|
|
10
|
+
*/
|
|
11
|
+
import { formatObservation, formatTerminalSummary } from "./observations.js";
|
|
12
|
+
/**
|
|
13
|
+
* Run a follow loop until the Run reaches a terminal state.
|
|
14
|
+
* Returns the terminal RunStatus for exit-code mapping.
|
|
15
|
+
*/
|
|
16
|
+
export async function followRun(client, runId, options = {}) {
|
|
17
|
+
const intervalMs = options.intervalMs ?? 400;
|
|
18
|
+
// Pin the supervisor alive while following
|
|
19
|
+
client.clientKind = "follow";
|
|
20
|
+
const lastObserved = new Map();
|
|
21
|
+
let lastRunStatus;
|
|
22
|
+
let runName = "";
|
|
23
|
+
// Register Ctrl-C handler: detach (exit 0) without cancelling
|
|
24
|
+
let detached = false;
|
|
25
|
+
const onSigint = () => {
|
|
26
|
+
detached = true;
|
|
27
|
+
process.off("SIGINT", onSigint);
|
|
28
|
+
// Don't call process.exit(0) here — it skips the finally block and
|
|
29
|
+
// prevents cleanup. Instead, set the flag and let the loop exit naturally.
|
|
30
|
+
};
|
|
31
|
+
process.on("SIGINT", onSigint);
|
|
32
|
+
try {
|
|
33
|
+
for (;;) {
|
|
34
|
+
if (detached) {
|
|
35
|
+
// Ctrl-C detach: the Run continues in the background supervisor.
|
|
36
|
+
// Return a non-terminal status so the caller maps to exit 0.
|
|
37
|
+
return "running";
|
|
38
|
+
}
|
|
39
|
+
let run;
|
|
40
|
+
let nodes;
|
|
41
|
+
try {
|
|
42
|
+
[run, nodes] = await Promise.all([
|
|
43
|
+
client.getRun(runId),
|
|
44
|
+
client.getNodeStates(runId)
|
|
45
|
+
]);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
// Transient fetch error — retry after interval
|
|
49
|
+
if (!options.json) {
|
|
50
|
+
process.stderr.write(`⚠ poll error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
51
|
+
}
|
|
52
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
runName = run.workflowName;
|
|
56
|
+
// Emit Run-level observation on first poll or status change.
|
|
57
|
+
// Terminal states are handled by formatTerminalSummary below; skip here
|
|
58
|
+
// to avoid duplicate "Run ... completed" lines with different glyphs.
|
|
59
|
+
if (lastRunStatus === undefined || run.status !== lastRunStatus) {
|
|
60
|
+
if (!isTerminal(run.status)) {
|
|
61
|
+
const event = { type: "run", runId, status: run.status };
|
|
62
|
+
emit(formatObservation(event, runName, options.json));
|
|
63
|
+
}
|
|
64
|
+
lastRunStatus = run.status;
|
|
65
|
+
}
|
|
66
|
+
// Emit Node-level observations for new/changed nodes
|
|
67
|
+
for (const node of nodes) {
|
|
68
|
+
const prev = lastObserved.get(node.nodeKey);
|
|
69
|
+
if (!prev || prev.state !== node.state) {
|
|
70
|
+
const duration = computeDuration(node);
|
|
71
|
+
const event = {
|
|
72
|
+
type: "node",
|
|
73
|
+
nodeKey: node.nodeKey,
|
|
74
|
+
state: node.state,
|
|
75
|
+
duration,
|
|
76
|
+
error: node.error
|
|
77
|
+
};
|
|
78
|
+
emit(formatObservation(event, undefined, options.json));
|
|
79
|
+
}
|
|
80
|
+
lastObserved.set(node.nodeKey, node);
|
|
81
|
+
}
|
|
82
|
+
// Check if Run is terminal
|
|
83
|
+
if (isTerminal(run.status)) {
|
|
84
|
+
const summary = formatTerminalSummary(runId, run.status, runName, options.json);
|
|
85
|
+
emit(summary);
|
|
86
|
+
return run.status;
|
|
87
|
+
}
|
|
88
|
+
// Wait before next poll
|
|
89
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
process.off("SIGINT", onSigint);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function emit(line) {
|
|
97
|
+
process.stdout.write(line + "\n");
|
|
98
|
+
}
|
|
99
|
+
function isTerminal(status) {
|
|
100
|
+
return status === "completed" || status === "failed" || status === "cancelled" || status === "paused";
|
|
101
|
+
}
|
|
102
|
+
function computeDuration(node) {
|
|
103
|
+
if (!node.startedAt)
|
|
104
|
+
return undefined;
|
|
105
|
+
const start = Date.parse(node.startedAt);
|
|
106
|
+
const end = node.completedAt ? Date.parse(node.completedAt) : Date.now();
|
|
107
|
+
return end - start;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=follow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"follow.js","sourceRoot":"","sources":["../src/follow.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|