acpus 0.0.1 → 0.1.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 -90
- package/dist/catalog.d.ts +27 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +189 -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 +414 -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 +38 -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 +83 -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 +31 -45
- package/dist/cli.d.mts +0 -1
- package/dist/cli.mjs +0 -3860
- package/dist/index.d.mts +0 -2742
- package/dist/index.mjs +0 -2
- package/dist/monitor-app-CSjUPe9j.mjs +0 -434
- package/dist/run-workflow-CbxKhAqF.mjs +0 -13586
- package/schemas/workflow-spec.schema.json +0 -2042
package/README.md
CHANGED
|
@@ -1,97 +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
|
-
|
|
5
|
+
Install:
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
# Install
|
|
7
|
+
```sh
|
|
14
8
|
npm install -g acpus
|
|
15
|
-
|
|
16
|
-
# Validate a workflow spec
|
|
17
|
-
acpus validate --spec workflows/examples/simple-feature.workflow.spec.json
|
|
18
|
-
|
|
19
|
-
# Preview the execution plan
|
|
20
|
-
acpus preview --spec workflows/examples/simple-feature.workflow.spec.json
|
|
21
|
-
|
|
22
|
-
# Run the workflow
|
|
23
|
-
acpus run --spec workflows/examples/simple-feature.workflow.spec.json
|
|
24
|
-
|
|
25
|
-
# Follow a running workflow in real time
|
|
26
|
-
acpus follow <logical-run-id>
|
|
27
9
|
```
|
|
28
10
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
npx skills add kelvinschen/acpus --skill acpus
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Commands
|
|
36
|
-
|
|
37
|
-
Acpus commands are grouped by four verbs.
|
|
38
|
-
|
|
39
|
-
### Compose — validate, preview, save, generate
|
|
40
|
-
|
|
41
|
-
| Command | Purpose |
|
|
42
|
-
|---|---|
|
|
43
|
-
| `acpus validate --spec <path>` | Validate a workflow spec against the schema |
|
|
44
|
-
| `acpus preview --spec <path>` | Render the compiled execution plan without running |
|
|
45
|
-
| `acpus save <name> --spec <path>` | Save a spec to the local store |
|
|
46
|
-
| `acpus generate` | Scaffold a new workflow spec from a template |
|
|
47
|
-
|
|
48
|
-
### Conduct — run, follow, monitor, resume
|
|
49
|
-
|
|
50
|
-
| Command | Purpose |
|
|
51
|
-
|---|---|
|
|
52
|
-
| `acpus run --spec <path>` | Execute a workflow spec end-to-end |
|
|
53
|
-
| `acpus follow <run-id>` | Attach to a running workflow and stream output |
|
|
54
|
-
| `acpus monitor <run-id>` | Open the terminal UI for run inspection |
|
|
55
|
-
| `acpus resume <run-id>` | Resume an interrupted or failed run from last checkpoint |
|
|
56
|
-
|
|
57
|
-
### Recover — recover, diagnose
|
|
58
|
-
|
|
59
|
-
| Command | Purpose |
|
|
60
|
-
|---|---|
|
|
61
|
-
| `acpus recover <run-id>` | Attempt automatic repair of a failed run |
|
|
62
|
-
| `acpus diagnose <run-id> [--wait]` | Produce a structured diagnosis of a completed or running run |
|
|
63
|
-
|
|
64
|
-
### Catalogue — list, show
|
|
65
|
-
|
|
66
|
-
| Command | Purpose |
|
|
67
|
-
|---|---|
|
|
68
|
-
| `acpus list` | List saved specs and historical runs |
|
|
69
|
-
| `acpus show <id>` | Display details of a saved spec or past run |
|
|
70
|
-
|
|
71
|
-
## Architecture
|
|
72
|
-
|
|
73
|
-
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.
|
|
74
|
-
|
|
75
|
-
Run directories live under `.acpus/runs/<id>/`. Each contains:
|
|
76
|
-
|
|
77
|
-
- `workflow.spec.json` — the original workflow spec
|
|
78
|
-
- `execution-plan.json` — the compiled plan
|
|
79
|
-
- `input.json` — resolved inputs at launch time
|
|
80
|
-
- `outputs/` — stage outputs and final artefacts
|
|
81
|
-
- `attempts/` — raw attempt records with agent transcripts
|
|
82
|
-
- `acpx-state/` — run-local acpx session state
|
|
83
|
-
- `sessions/` — per-lane session logs
|
|
84
|
-
- `events.ndjson` — timestamped event log for the entire run
|
|
85
|
-
|
|
86
|
-
The orchestrator does not generate or execute ACPX flow files directly. It drives acpx through its runtime API.
|
|
87
|
-
|
|
88
|
-
## Documentation
|
|
89
|
-
|
|
90
|
-
- [Developer documentation](docs/README.md)
|
|
91
|
-
- [Design and implementation specifications](specs/INDEX.md)
|
|
92
|
-
- [CLI guide](docs/cli.md)
|
|
93
|
-
- [Error code guide](docs/error-codes.md)
|
|
94
|
-
|
|
95
|
-
## License
|
|
11
|
+
Use it to lint Workflow Specs, run Workflows, inspect Runs, control Runs, replay persisted Runs, and open the terminal visualizer.
|
|
96
12
|
|
|
97
|
-
|
|
13
|
+
See the repository README for full usage: https://github.com/kelvinschen/acpus
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { 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 declare function globalWorkflowRoot(): string;
|
|
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,EAAgB,KAAK,UAAU,EAAmB,MAAM,aAAa,CAAC;AAG7E,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,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,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,189 @@
|
|
|
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 { lintWorkflow } from "@acpus/core";
|
|
6
|
+
import { createIncludeResolver } from "./io.js";
|
|
7
|
+
export function projectWorkflowRoot(workspace = process.cwd()) {
|
|
8
|
+
return resolve(workspace, ".acpus", "workflows");
|
|
9
|
+
}
|
|
10
|
+
export function globalWorkflowRoot() {
|
|
11
|
+
return resolve(homedir(), ".acpus", "workflows");
|
|
12
|
+
}
|
|
13
|
+
export function listWorkflowCatalog(workspace = process.cwd()) {
|
|
14
|
+
const allowedSourceRoots = [resolve(workspace), globalWorkflowRoot()];
|
|
15
|
+
const entries = [
|
|
16
|
+
...scanScope("project", projectWorkflowRoot(workspace), allowedSourceRoots),
|
|
17
|
+
...scanScope("global", globalWorkflowRoot(), allowedSourceRoots)
|
|
18
|
+
];
|
|
19
|
+
for (const scope of ["project", "global"]) {
|
|
20
|
+
const byName = new Map();
|
|
21
|
+
for (const entry of entries) {
|
|
22
|
+
if (entry.scope !== scope || !entry.name || entry.status === "invalid")
|
|
23
|
+
continue;
|
|
24
|
+
const group = byName.get(entry.name) ?? [];
|
|
25
|
+
group.push(entry);
|
|
26
|
+
byName.set(entry.name, group);
|
|
27
|
+
}
|
|
28
|
+
for (const [name, group] of byName) {
|
|
29
|
+
if (group.length <= 1)
|
|
30
|
+
continue;
|
|
31
|
+
for (const entry of group) {
|
|
32
|
+
entry.status = "conflict";
|
|
33
|
+
entry.ref = undefined;
|
|
34
|
+
entry.diagnostics = [{
|
|
35
|
+
severity: "error",
|
|
36
|
+
code: "CATALOG_CONFLICT",
|
|
37
|
+
message: `Workflow name '${name}' is duplicated in ${scope} catalog.`,
|
|
38
|
+
path: "$.name"
|
|
39
|
+
}];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return entries;
|
|
44
|
+
}
|
|
45
|
+
export function resolveWorkflowTarget(target, workspace = process.cwd()) {
|
|
46
|
+
if (looksLikeWorkflowPath(target)) {
|
|
47
|
+
const sourcePath = resolveWorkflowPath(target);
|
|
48
|
+
return { sourcePath, source: readFileSync(sourcePath, "utf8") };
|
|
49
|
+
}
|
|
50
|
+
const catalog = listWorkflowCatalog(workspace);
|
|
51
|
+
const matches = catalog.filter((entry) => entry.status === "ready" && matchesCatalogTarget(entry, target));
|
|
52
|
+
if (matches.length === 0) {
|
|
53
|
+
const blocked = catalog.find((entry) => matchesCatalogTarget(entry, target));
|
|
54
|
+
if (blocked) {
|
|
55
|
+
throw new Error(`Workflow '${target}' is ${blocked.status}: ${blocked.diagnostics.map((d) => d.message).join("; ")}`);
|
|
56
|
+
}
|
|
57
|
+
throw new Error(`Workflow '${target}' was not found in the Workflow Catalog.`);
|
|
58
|
+
}
|
|
59
|
+
if (matches.length > 1) {
|
|
60
|
+
throw new Error(`Workflow short name '${target}' is ambiguous; use a full ref such as ${matches.map((m) => m.ref).join(" or ")}.`);
|
|
61
|
+
}
|
|
62
|
+
const entry = matches[0];
|
|
63
|
+
return {
|
|
64
|
+
sourcePath: entry.path,
|
|
65
|
+
source: readFileSync(entry.path, "utf8"),
|
|
66
|
+
workflowRef: entry.ref
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export function findWorkflowCatalogEntry(target, workspace = process.cwd()) {
|
|
70
|
+
const catalog = listWorkflowCatalog(workspace);
|
|
71
|
+
const matches = catalog.filter((entry) => matchesCatalogTarget(entry, target));
|
|
72
|
+
if (matches.length === 0) {
|
|
73
|
+
throw new Error(`Workflow '${target}' was not found in the Workflow Catalog.`);
|
|
74
|
+
}
|
|
75
|
+
if (matches.length > 1) {
|
|
76
|
+
throw new Error(`Workflow name '${target}' is ambiguous; use a full ref when available.`);
|
|
77
|
+
}
|
|
78
|
+
return matches[0];
|
|
79
|
+
}
|
|
80
|
+
function matchesCatalogTarget(entry, target) {
|
|
81
|
+
return entry.ref === target || entry.name === target || (entry.name !== undefined && `${entry.scope}:${entry.name}` === target);
|
|
82
|
+
}
|
|
83
|
+
function scanScope(scope, root, allowedSourceRoots) {
|
|
84
|
+
if (!existsSync(root))
|
|
85
|
+
return [];
|
|
86
|
+
const files = collectCandidateFiles(root);
|
|
87
|
+
return files.map((file) => entryFromFile(scope, file, allowedSourceRoots));
|
|
88
|
+
}
|
|
89
|
+
function collectCandidateFiles(root) {
|
|
90
|
+
const out = [];
|
|
91
|
+
const visit = (dir) => {
|
|
92
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
93
|
+
const path = join(dir, entry.name);
|
|
94
|
+
if (entry.isDirectory()) {
|
|
95
|
+
visit(path);
|
|
96
|
+
}
|
|
97
|
+
else if (entry.isFile() && isWorkflowCandidate(entry.name)) {
|
|
98
|
+
out.push(path);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
visit(root);
|
|
103
|
+
return out.sort();
|
|
104
|
+
}
|
|
105
|
+
function entryFromFile(scope, path, allowedSourceRoots) {
|
|
106
|
+
const source = readFileSync(path, "utf8");
|
|
107
|
+
const parsed = parseSpecSummary(source);
|
|
108
|
+
const lint = lintCatalogEntry(source, path, allowedSourceRoots);
|
|
109
|
+
const name = parsed.name;
|
|
110
|
+
const status = lint.ok && name ? "ready" : "invalid";
|
|
111
|
+
return {
|
|
112
|
+
scope,
|
|
113
|
+
ref: status === "ready" ? `${scope}:${name}` : undefined,
|
|
114
|
+
name,
|
|
115
|
+
description: parsed.description,
|
|
116
|
+
input: parsed.input,
|
|
117
|
+
inputKeys: Object.keys(parsed.input ?? {}),
|
|
118
|
+
path,
|
|
119
|
+
status,
|
|
120
|
+
diagnostics: lint.ok && !name
|
|
121
|
+
? [{ severity: "error", code: "CATALOG_NAME", message: "Workflow Spec must declare a string name.", path: "$.name" }]
|
|
122
|
+
: lint.diagnostics
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function lintCatalogEntry(source, path, allowedSourceRoots) {
|
|
126
|
+
try {
|
|
127
|
+
return lintWorkflow(source, {
|
|
128
|
+
sourcePath: path,
|
|
129
|
+
includeResolver: createIncludeResolver(allowedSourceRoots)
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
return {
|
|
134
|
+
ok: false,
|
|
135
|
+
diagnostics: [{
|
|
136
|
+
severity: "error",
|
|
137
|
+
code: "CATALOG_LINT",
|
|
138
|
+
message: error instanceof Error ? error.message : String(error),
|
|
139
|
+
path: "$"
|
|
140
|
+
}]
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function parseSpecSummary(source) {
|
|
145
|
+
try {
|
|
146
|
+
const parsed = parseYaml(source);
|
|
147
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
|
|
148
|
+
return {};
|
|
149
|
+
const map = parsed;
|
|
150
|
+
return {
|
|
151
|
+
name: typeof map.name === "string" ? map.name : undefined,
|
|
152
|
+
description: typeof map.description === "string" ? map.description : undefined,
|
|
153
|
+
input: typeof map.input === "object" && map.input !== null && !Array.isArray(map.input)
|
|
154
|
+
? map.input
|
|
155
|
+
: undefined
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return {};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function isWorkflowCandidate(filename) {
|
|
163
|
+
return filename === "workflow.yaml"
|
|
164
|
+
|| filename === "workflow.yml"
|
|
165
|
+
|| filename.endsWith(".workflow.yaml")
|
|
166
|
+
|| filename.endsWith(".workflow.yml")
|
|
167
|
+
|| filename.endsWith(".workflow.spec.yaml")
|
|
168
|
+
|| filename.endsWith(".workflow.spec.yml");
|
|
169
|
+
}
|
|
170
|
+
export function looksLikeWorkflowPath(target) {
|
|
171
|
+
return target.startsWith(".")
|
|
172
|
+
|| target.startsWith("/")
|
|
173
|
+
|| target.startsWith("~")
|
|
174
|
+
|| target.includes("/")
|
|
175
|
+
|| target.endsWith(".yaml")
|
|
176
|
+
|| target.endsWith(".yml");
|
|
177
|
+
}
|
|
178
|
+
export function resolveWorkflowPath(path) {
|
|
179
|
+
if (path === "~")
|
|
180
|
+
return homedir();
|
|
181
|
+
if (path.startsWith("~/"))
|
|
182
|
+
return resolve(homedir(), path.slice(2));
|
|
183
|
+
const resolved = resolve(process.cwd(), path);
|
|
184
|
+
if (!existsSync(resolved) || !statSync(resolved).isFile()) {
|
|
185
|
+
throw new Error(`Workflow Spec path not found: ${path}`);
|
|
186
|
+
}
|
|
187
|
+
return resolved;
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}
|
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":""}
|