cueline 0.1.6 → 0.1.7
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +27 -0
- package/README.ja.md +29 -7
- package/README.ko.md +29 -7
- package/README.md +78 -11
- package/README.zh-CN.md +29 -7
- package/README.zh-TW.md +36 -8
- package/config/routing.schema.json +3 -0
- package/dist/src/api-caller-work.js +58 -14
- package/dist/src/api-caller-work.js.map +1 -1
- package/dist/src/api-contracts.d.ts +49 -0
- package/dist/src/api-controller-handoff.js +30 -38
- package/dist/src/api-controller-handoff.js.map +1 -1
- package/dist/src/api-run-verification.d.ts +3 -0
- package/dist/src/api-run-verification.js +174 -0
- package/dist/src/api-run-verification.js.map +1 -0
- package/dist/src/api-runtime-lifecycle.d.ts +6 -1
- package/dist/src/api-runtime-lifecycle.js +97 -8
- package/dist/src/api-runtime-lifecycle.js.map +1 -1
- package/dist/src/api.d.ts +17 -3
- package/dist/src/api.js +105 -38
- package/dist/src/api.js.map +1 -1
- package/dist/src/browser/browser-adapter.d.ts +15 -0
- package/dist/src/browser/codex-iab/bootstrap.d.ts +20 -0
- package/dist/src/browser/codex-iab/bootstrap.js +173 -9
- package/dist/src/browser/codex-iab/bootstrap.js.map +1 -1
- package/dist/src/browser/codex-iab/chatgpt-client.d.ts +3 -0
- package/dist/src/browser/codex-iab/chatgpt-client.js +115 -57
- package/dist/src/browser/codex-iab/chatgpt-client.js.map +1 -1
- package/dist/src/browser/codex-iab/probe.d.ts +36 -0
- package/dist/src/browser/codex-iab/probe.js +217 -0
- package/dist/src/browser/codex-iab/probe.js.map +1 -0
- package/dist/src/browser/codex-iab/recovery-evidence.d.ts +1 -1
- package/dist/src/browser/codex-iab/recovery-evidence.js +7 -10
- package/dist/src/browser/codex-iab/recovery-evidence.js.map +1 -1
- package/dist/src/browser/codex-iab/selectors.d.ts +1 -0
- package/dist/src/browser/codex-iab/selectors.js +1 -0
- package/dist/src/browser/codex-iab/selectors.js.map +1 -1
- package/dist/src/browser/codex-iab/send-button.d.ts +5 -0
- package/dist/src/browser/codex-iab/send-button.js +62 -0
- package/dist/src/browser/codex-iab/send-button.js.map +1 -0
- package/dist/src/browser/codex-iab/submission-url.js +6 -15
- package/dist/src/browser/codex-iab/submission-url.js.map +1 -1
- package/dist/src/browser/codex-iab/tab-discovery.js +45 -12
- package/dist/src/browser/codex-iab/tab-discovery.js.map +1 -1
- package/dist/src/browser/codex-iab/timing-options.d.ts +1 -0
- package/dist/src/browser/codex-iab/timing-options.js +5 -0
- package/dist/src/browser/codex-iab/timing-options.js.map +1 -0
- package/dist/src/cli/health-commands.d.ts +2 -0
- package/dist/src/cli/health-commands.js +191 -0
- package/dist/src/cli/health-commands.js.map +1 -0
- package/dist/src/cli/io.d.ts +4 -0
- package/dist/src/cli/io.js +2 -0
- package/dist/src/cli/io.js.map +1 -0
- package/dist/src/cli/main.d.ts +1 -5
- package/dist/src/cli/main.js +159 -77
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/cli/observation-commands.d.ts +2 -0
- package/dist/src/cli/observation-commands.js +239 -0
- package/dist/src/cli/observation-commands.js.map +1 -0
- package/dist/src/cli/run-status-view.d.ts +79 -0
- package/dist/src/cli/run-status-view.js +112 -0
- package/dist/src/cli/run-status-view.js.map +1 -0
- package/dist/src/core/controller-command-execution.d.ts +2 -2
- package/dist/src/core/controller-command-execution.js +82 -16
- package/dist/src/core/controller-command-execution.js.map +1 -1
- package/dist/src/core/controller-conversation-archive.d.ts +11 -0
- package/dist/src/core/controller-conversation-archive.js +109 -0
- package/dist/src/core/controller-conversation-archive.js.map +1 -0
- package/dist/src/core/controller-loop.d.ts +7 -1
- package/dist/src/core/controller-loop.js +114 -23
- package/dist/src/core/controller-loop.js.map +1 -1
- package/dist/src/core/controller-turn.d.ts +14 -2
- package/dist/src/core/controller-turn.js +109 -40
- package/dist/src/core/controller-turn.js.map +1 -1
- package/dist/src/core/controller-types.d.ts +2 -0
- package/dist/src/core/conversation-url.d.ts +3 -0
- package/dist/src/core/conversation-url.js +34 -0
- package/dist/src/core/conversation-url.js.map +1 -0
- package/dist/src/core/run-status.d.ts +9 -2
- package/dist/src/core/run-status.js +38 -25
- package/dist/src/core/run-status.js.map +1 -1
- package/dist/src/core/state-machine.d.ts +21 -1
- package/dist/src/core/state-machine.js +138 -13
- package/dist/src/core/state-machine.js.map +1 -1
- package/dist/src/core/timing.d.ts +9 -0
- package/dist/src/core/timing.js +22 -0
- package/dist/src/core/timing.js.map +1 -0
- package/dist/src/diagnostics/run-doctor.d.ts +22 -0
- package/dist/src/diagnostics/run-doctor.js +197 -0
- package/dist/src/diagnostics/run-doctor.js.map +1 -0
- package/dist/src/jobs/status.d.ts +5 -2
- package/dist/src/jobs/status.js +172 -12
- package/dist/src/jobs/status.js.map +1 -1
- package/dist/src/jobs/supervisor.js +57 -8
- package/dist/src/jobs/supervisor.js.map +1 -1
- package/dist/src/observation/run-handoff.d.ts +86 -0
- package/dist/src/observation/run-handoff.js +309 -0
- package/dist/src/observation/run-handoff.js.map +1 -0
- package/dist/src/observation/run-timeline.d.ts +32 -0
- package/dist/src/observation/run-timeline.js +278 -0
- package/dist/src/observation/run-timeline.js.map +1 -0
- package/dist/src/observation/run-watch.d.ts +15 -0
- package/dist/src/observation/run-watch.js +82 -0
- package/dist/src/observation/run-watch.js.map +1 -0
- package/dist/src/protocol/limits.d.ts +3 -0
- package/dist/src/protocol/limits.js +4 -0
- package/dist/src/protocol/limits.js.map +1 -0
- package/dist/src/protocol/lint-command.d.ts +24 -0
- package/dist/src/protocol/lint-command.js +210 -0
- package/dist/src/protocol/lint-command.js.map +1 -0
- package/dist/src/protocol/parse-command.js +4 -0
- package/dist/src/protocol/parse-command.js.map +1 -1
- package/dist/src/protocol/types.d.ts +12 -0
- package/dist/src/protocol/validate-command.js +76 -3
- package/dist/src/protocol/validate-command.js.map +1 -1
- package/dist/src/router/config-loader.js +23 -2
- package/dist/src/router/config-loader.js.map +1 -1
- package/dist/src/router/resolver.js +8 -3
- package/dist/src/router/resolver.js.map +1 -1
- package/dist/src/runners/process-runner.js +55 -12
- package/dist/src/runners/process-runner.js.map +1 -1
- package/dist/src/runners/runner-adapter.d.ts +2 -0
- package/dist/src/runners/runner-adapter.js.map +1 -1
- package/dist/src/state/atomic-write.d.ts +6 -0
- package/dist/src/state/atomic-write.js +43 -2
- package/dist/src/state/atomic-write.js.map +1 -1
- package/dist/src/state/cancellation.js +38 -4
- package/dist/src/state/cancellation.js.map +1 -1
- package/dist/src/state/event-log.js +5 -4
- package/dist/src/state/event-log.js.map +1 -1
- package/dist/src/state/private-directory.d.ts +5 -0
- package/dist/src/state/private-directory.js +37 -0
- package/dist/src/state/private-directory.js.map +1 -0
- package/dist/src/state/runtime-lease.js +19 -39
- package/dist/src/state/runtime-lease.js.map +1 -1
- package/dist/src/state/runtime-record-validation.d.ts +6 -0
- package/dist/src/state/runtime-record-validation.js +44 -0
- package/dist/src/state/runtime-record-validation.js.map +1 -0
- package/dist/src/state/runtime-retirement.js +58 -18
- package/dist/src/state/runtime-retirement.js.map +1 -1
- package/dist/src/state/runtime-takeover-intent.js +2 -2
- package/dist/src/state/runtime-takeover-intent.js.map +1 -1
- package/dist/src/state/store.d.ts +1 -0
- package/dist/src/state/store.js +12 -6
- package/dist/src/state/store.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/docs/architecture.md +4 -4
- package/docs/compatibility.md +1 -1
- package/docs/controller-protocol.md +38 -7
- package/docs/experiments/protocol-lint.md +40 -0
- package/docs/experiments/run-doctor.md +39 -0
- package/docs/experiments/run-handoff.md +39 -0
- package/docs/experiments/run-timeline.md +35 -0
- package/docs/experiments/run-watch.md +31 -0
- package/docs/runner-contract.md +4 -3
- package/docs/state-and-recovery.md +15 -5
- package/package.json +1 -1
- package/schemas/controller-command.schema.json +89 -4
- package/skills/cueline/SKILL.md +13 -7
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { routingConfigPath } from "../api.js";
|
|
2
|
+
import { CueLineError } from "../core/errors.js";
|
|
3
|
+
import { executableAvailability } from "../router/availability.js";
|
|
4
|
+
import { loadRoutingConfig } from "../router/config-loader.js";
|
|
5
|
+
import { resolveRoute } from "../router/resolver.js";
|
|
6
|
+
import { defaultCueLineHome } from "../state/paths.js";
|
|
7
|
+
import { CUELINE_VERSION } from "../version.js";
|
|
8
|
+
function routingErrorCode(error) {
|
|
9
|
+
return error instanceof CueLineError ? error.code : "ROUTE_UNAVAILABLE";
|
|
10
|
+
}
|
|
11
|
+
async function collectRoutingReport(environment) {
|
|
12
|
+
const configPath = routingConfigPath(environment);
|
|
13
|
+
let config;
|
|
14
|
+
try {
|
|
15
|
+
config = await loadRoutingConfig(configPath);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return {
|
|
19
|
+
version: CUELINE_VERSION,
|
|
20
|
+
config: {
|
|
21
|
+
path: configPath,
|
|
22
|
+
valid: false,
|
|
23
|
+
errorCode: "ROUTING_CONFIG_INVALID",
|
|
24
|
+
},
|
|
25
|
+
availableLanes: 0,
|
|
26
|
+
lanes: [],
|
|
27
|
+
findings: [
|
|
28
|
+
{
|
|
29
|
+
code: "ROUTING_CONFIG_INVALID",
|
|
30
|
+
message: "Routing configuration could not be loaded.",
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const availability = executableAvailability(environment);
|
|
36
|
+
const lanes = [];
|
|
37
|
+
for (const [lane, laneConfig] of Object.entries(config.lanes)) {
|
|
38
|
+
if (!laneConfig.enabled) {
|
|
39
|
+
lanes.push({
|
|
40
|
+
name: lane,
|
|
41
|
+
enabled: false,
|
|
42
|
+
status: "disabled",
|
|
43
|
+
selectedRunnerId: null,
|
|
44
|
+
});
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const route = resolveRoute(lane, config, availability);
|
|
49
|
+
lanes.push({
|
|
50
|
+
name: lane,
|
|
51
|
+
enabled: true,
|
|
52
|
+
status: "available",
|
|
53
|
+
selectedRunnerId: route.candidate.id,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
lanes.push({
|
|
58
|
+
name: lane,
|
|
59
|
+
enabled: true,
|
|
60
|
+
status: "unavailable",
|
|
61
|
+
selectedRunnerId: null,
|
|
62
|
+
errorCode: routingErrorCode(error),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
version: CUELINE_VERSION,
|
|
68
|
+
config: { path: configPath, valid: true },
|
|
69
|
+
availableLanes: lanes.filter((lane) => lane.status === "available").length,
|
|
70
|
+
lanes,
|
|
71
|
+
findings: [],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
async function routingCommand(json, environment, io) {
|
|
75
|
+
const report = await collectRoutingReport(environment);
|
|
76
|
+
if (json) {
|
|
77
|
+
io.stdout(JSON.stringify(report, null, 2));
|
|
78
|
+
}
|
|
79
|
+
else if (!report.config.valid) {
|
|
80
|
+
io.stdout(`config\t${report.config.path}\tinvalid\t${report.config.errorCode}`);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
for (const lane of report.lanes) {
|
|
84
|
+
io.stdout(`${lane.name}\t${lane.selectedRunnerId ?? "-"}\t${lane.status}${lane.errorCode === undefined ? "" : ` (${lane.errorCode})`}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return report.availableLanes > 0 ? 0 : 1;
|
|
88
|
+
}
|
|
89
|
+
async function collectDoctorReport(environment) {
|
|
90
|
+
const configPath = routingConfigPath(environment);
|
|
91
|
+
const home = defaultCueLineHome(environment);
|
|
92
|
+
const major = Number.parseInt(process.versions.node.split(".")[0] ?? "0", 10);
|
|
93
|
+
const nodeOk = major >= 22;
|
|
94
|
+
const availability = executableAvailability(environment);
|
|
95
|
+
const findings = [];
|
|
96
|
+
let callerLanes = 0;
|
|
97
|
+
let processAvailableLanes = 0;
|
|
98
|
+
let config;
|
|
99
|
+
try {
|
|
100
|
+
config = await loadRoutingConfig(configPath);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
findings.push({
|
|
104
|
+
code: "ROUTING_CONFIG_INVALID",
|
|
105
|
+
surface: "config",
|
|
106
|
+
message: "Routing configuration could not be loaded.",
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (config !== undefined) {
|
|
110
|
+
for (const [lane, laneConfig] of Object.entries(config.lanes)) {
|
|
111
|
+
if (!laneConfig.enabled)
|
|
112
|
+
continue;
|
|
113
|
+
callerLanes += 1;
|
|
114
|
+
try {
|
|
115
|
+
resolveRoute(lane, config, availability);
|
|
116
|
+
processAvailableLanes += 1;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// `cueline routing` reports per-lane details.
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (!nodeOk) {
|
|
124
|
+
findings.push({
|
|
125
|
+
code: "NODE_VERSION_UNSUPPORTED",
|
|
126
|
+
surface: "node",
|
|
127
|
+
message: "Node.js 22 or newer is required.",
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
if (config !== undefined && callerLanes === 0) {
|
|
131
|
+
findings.push({
|
|
132
|
+
code: "CALLER_LANES_UNAVAILABLE",
|
|
133
|
+
surface: "caller",
|
|
134
|
+
message: "No enabled caller lane is configured.",
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
const callerReady = nodeOk && config !== undefined && callerLanes > 0;
|
|
138
|
+
return {
|
|
139
|
+
version: CUELINE_VERSION,
|
|
140
|
+
status: callerReady ? "ok" : "degraded",
|
|
141
|
+
node: {
|
|
142
|
+
version: process.versions.node,
|
|
143
|
+
ok: nodeOk,
|
|
144
|
+
requirement: ">=22",
|
|
145
|
+
},
|
|
146
|
+
config: config === undefined
|
|
147
|
+
? { path: configPath, valid: false, errorCode: "ROUTING_CONFIG_INVALID" }
|
|
148
|
+
: { path: configPath, valid: true },
|
|
149
|
+
home,
|
|
150
|
+
caller: {
|
|
151
|
+
ready: callerReady,
|
|
152
|
+
enabledLanes: callerLanes,
|
|
153
|
+
},
|
|
154
|
+
process: {
|
|
155
|
+
availableLanes: processAvailableLanes,
|
|
156
|
+
},
|
|
157
|
+
findings,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
async function doctorCommand(json, environment, io) {
|
|
161
|
+
const report = await collectDoctorReport(environment);
|
|
162
|
+
if (json) {
|
|
163
|
+
io.stdout(JSON.stringify(report, null, 2));
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
io.stdout(`CueLine ${report.version}`);
|
|
167
|
+
io.stdout(`status\t${report.status}`);
|
|
168
|
+
io.stdout(`node\t${report.node.version}\t${report.node.ok ? "ok" : `requires ${report.node.requirement}`}`);
|
|
169
|
+
io.stdout(`config\t${report.config.path}\t${report.config.valid ? "valid" : "invalid"}`);
|
|
170
|
+
io.stdout(`home\t${report.home}`);
|
|
171
|
+
io.stdout(`caller_ready\t${report.caller.ready ? "yes" : "no"}`);
|
|
172
|
+
io.stdout(`caller_lanes\t${report.caller.enabledLanes}`);
|
|
173
|
+
io.stdout(`process_available_lanes\t${report.process.availableLanes}`);
|
|
174
|
+
for (const item of report.findings) {
|
|
175
|
+
io.stdout(`finding\t${item.code}\t${item.surface}\t${item.message}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return report.status === "ok" ? 0 : 1;
|
|
179
|
+
}
|
|
180
|
+
export async function handleHealthCommand(args, environment, io) {
|
|
181
|
+
if (args[0] === "routing" &&
|
|
182
|
+
(args.length === 1 || (args.length === 2 && args[1] === "--json"))) {
|
|
183
|
+
return routingCommand(args[1] === "--json", environment, io);
|
|
184
|
+
}
|
|
185
|
+
if (args[0] === "doctor" &&
|
|
186
|
+
(args.length === 1 || (args.length === 2 && args[1] === "--json"))) {
|
|
187
|
+
return doctorCommand(args[1] === "--json", environment, io);
|
|
188
|
+
}
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=health-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health-commands.js","sourceRoot":"","sources":["../../../src/cli/health-commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"io.js","sourceRoot":"","sources":["../../../src/cli/io.ts"],"names":[],"mappings":""}
|
package/dist/src/cli/main.d.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
stdout: (line: string) => void;
|
|
4
|
-
stderr: (line: string) => void;
|
|
5
|
-
}
|
|
2
|
+
import type { CliIo } from "./io.js";
|
|
6
3
|
export declare function main(args?: readonly string[], environment?: NodeJS.ProcessEnv, io?: CliIo): Promise<number>;
|
|
7
|
-
export {};
|
package/dist/src/cli/main.js
CHANGED
|
@@ -3,22 +3,24 @@ import { readdir, readFile } from "node:fs/promises";
|
|
|
3
3
|
import { realpathSync } from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
6
|
-
import { cancelCueLineJob, cancelCueLineRun, confirmManualControllerSubmission, loadCueLineRunStatus, reconcileCueLineRuntime, routingConfigPath, takeoverCueLineRuntime, } from "../api.js";
|
|
6
|
+
import { cancelCueLineJob, cancelCueLineRun, confirmManualControllerSubmission, loadCueLineRunStatus, lintControllerCommandText, reconcileCueLineRuntime, routingConfigPath, takeoverCueLineRuntime, } from "../api.js";
|
|
7
7
|
import { CueLineError } from "../core/errors.js";
|
|
8
|
-
import {
|
|
8
|
+
import { JobStatusStore } from "../jobs/status.js";
|
|
9
9
|
import { loadRoutingConfig } from "../router/config-loader.js";
|
|
10
|
-
import { resolveRoute } from "../router/resolver.js";
|
|
11
10
|
import { defaultCueLineHome } from "../state/paths.js";
|
|
12
11
|
import { readRuntimeLease } from "../state/runtime-lease.js";
|
|
13
12
|
import { readAuthoritativeRunEvents } from "../state/store.js";
|
|
14
13
|
import { CUELINE_VERSION } from "../version.js";
|
|
14
|
+
import { handleHealthCommand } from "./health-commands.js";
|
|
15
|
+
import { handleObservationCommand } from "./observation-commands.js";
|
|
16
|
+
import { safeCueLineRunStatus } from "./run-status-view.js";
|
|
15
17
|
import { installSkill, uninstallSkill } from "./skill-links.js";
|
|
16
18
|
const processIo = {
|
|
17
19
|
stdout: (line) => process.stdout.write(`${line}\n`),
|
|
18
20
|
stderr: (line) => process.stderr.write(`${line}\n`),
|
|
19
21
|
};
|
|
20
22
|
function usage() {
|
|
21
|
-
return "usage: cueline <install|uninstall|doctor|routing|jobs|run status|run reconcile|run takeover|run reconcile-runtime|run cancel|run stop|job cancel|api path|config path|help|version>";
|
|
23
|
+
return "usage: cueline <install|uninstall|doctor|routing|jobs|runs|protocol lint|run status|run doctor|run watch|run handoff|run timeline|run verify|run reconcile|run takeover|run reconcile-runtime|run cancel|run stop|job cancel|api path|config path|help|version>";
|
|
22
24
|
}
|
|
23
25
|
function help() {
|
|
24
26
|
return [
|
|
@@ -32,7 +34,14 @@ function help() {
|
|
|
32
34
|
" doctor report Node, caller readiness, state home, and process lanes",
|
|
33
35
|
" routing list every lane and the candidate that would be selected",
|
|
34
36
|
" jobs list persisted local jobs with run, key, lane, mode, and PID",
|
|
35
|
-
"
|
|
37
|
+
" protocol lint validate a Pro control envelope offline and explain corrections",
|
|
38
|
+
" runs list safe summaries of every persisted run",
|
|
39
|
+
" run status metadata-only summary for safe cross-session handoff",
|
|
40
|
+
" run doctor explain why a run is waiting or blocked and name the safe next action",
|
|
41
|
+
" run watch wait briefly for a newer durable event without owning the run",
|
|
42
|
+
" run handoff emit a restart packet with exact paths and safe next action",
|
|
43
|
+
" run timeline show a sanitized, cursor-paginated audit timeline",
|
|
44
|
+
" run verify verify durable run evidence without returning its content",
|
|
36
45
|
" run reconcile confirm one manually sent controller turn; never resends it",
|
|
37
46
|
" run takeover explicitly retire one exact stale runtime owner",
|
|
38
47
|
" run reconcile-runtime settle dead ownerless workers from persisted evidence",
|
|
@@ -47,10 +56,17 @@ function help() {
|
|
|
47
56
|
"command syntax:",
|
|
48
57
|
" cueline install",
|
|
49
58
|
" cueline uninstall",
|
|
50
|
-
" cueline doctor",
|
|
51
|
-
" cueline routing",
|
|
59
|
+
" cueline doctor [--json]",
|
|
60
|
+
" cueline routing [--json]",
|
|
52
61
|
" cueline jobs [--json]",
|
|
62
|
+
" cueline protocol lint <file> --run-id <id> --round <n> --request-id <id> [--json]",
|
|
63
|
+
" cueline runs [--json]",
|
|
53
64
|
" cueline run status <run-id> [--json]",
|
|
65
|
+
" cueline run doctor <run-id> [--json]",
|
|
66
|
+
" cueline run watch <run-id> --after <sequence> [--timeout-ms <0..30000>] [--json]",
|
|
67
|
+
" cueline run handoff <run-id> [--include-content] [--max-content-chars <16..10000>] [--json]",
|
|
68
|
+
" cueline run timeline <run-id> [--after <sequence>] [--limit <1..1000>] [--json]",
|
|
69
|
+
" cueline run verify <run-id> [--json]",
|
|
54
70
|
" cueline run reconcile <run-id> --request-id <request-id> --manual-send-confirmed [--conversation-url <url>] [--json]",
|
|
55
71
|
" cueline run takeover <run-id> [--json]",
|
|
56
72
|
" cueline run reconcile-runtime <run-id> [--json]",
|
|
@@ -76,7 +92,7 @@ function help() {
|
|
|
76
92
|
" 2 the arguments were not understood",
|
|
77
93
|
"",
|
|
78
94
|
"state effects:",
|
|
79
|
-
" Read-only: doctor, routing, jobs, run status, api path, config path, help, version.",
|
|
95
|
+
" Read-only: doctor, routing, jobs, runs, protocol lint, run status, run doctor, run watch, run handoff, run timeline, run verify, api path, config path, help, version.",
|
|
80
96
|
" Local setup: install and uninstall change only the package-owned skill link.",
|
|
81
97
|
" Durable state writes: run reconcile, takeover, reconcile-runtime, cancel/stop,",
|
|
82
98
|
" and job cancel append evidence or change local run/job state.",
|
|
@@ -90,25 +106,26 @@ function errorMessage(error) {
|
|
|
90
106
|
return `${error.code}: ${error.message}`;
|
|
91
107
|
return error instanceof Error ? error.message : String(error);
|
|
92
108
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
function jobStatusMetadata(status) {
|
|
110
|
+
return {
|
|
111
|
+
jobId: status.jobId,
|
|
112
|
+
...(status.runId === undefined ? {} : { runId: status.runId }),
|
|
113
|
+
...(status.jobKey === undefined ? {} : { jobKey: status.jobKey }),
|
|
114
|
+
...(status.lane === undefined ? {} : { lane: status.lane }),
|
|
115
|
+
...(status.mode === undefined ? {} : { mode: status.mode }),
|
|
116
|
+
...(status.runnerId === undefined ? {} : { runnerId: status.runnerId }),
|
|
117
|
+
...(status.model === undefined ? {} : { model: status.model }),
|
|
118
|
+
...(status.provider === undefined ? {} : { provider: status.provider }),
|
|
119
|
+
...(status.pid === undefined ? {} : { pid: status.pid }),
|
|
120
|
+
...(status.phase === undefined ? {} : { phase: status.phase }),
|
|
121
|
+
...(status.lastProgressAt === undefined
|
|
122
|
+
? {}
|
|
123
|
+
: { lastProgressAt: status.lastProgressAt }),
|
|
124
|
+
execution: status.execution,
|
|
125
|
+
status: status.status,
|
|
126
|
+
startedAt: status.startedAt,
|
|
127
|
+
...(status.finishedAt === undefined ? {} : { finishedAt: status.finishedAt }),
|
|
128
|
+
};
|
|
112
129
|
}
|
|
113
130
|
async function readRunJobMetadata(home) {
|
|
114
131
|
const metadata = new Map();
|
|
@@ -151,7 +168,6 @@ async function readRunJobMetadata(home) {
|
|
|
151
168
|
jobKey: record.jobKey,
|
|
152
169
|
lane: spec.lane,
|
|
153
170
|
mode: spec.mode,
|
|
154
|
-
task: spec.task,
|
|
155
171
|
execution: "foreground",
|
|
156
172
|
status: "pending",
|
|
157
173
|
startedAt: event.timestamp,
|
|
@@ -203,13 +219,23 @@ async function readJobs(home) {
|
|
|
203
219
|
else
|
|
204
220
|
throw error;
|
|
205
221
|
}
|
|
222
|
+
const statusStore = new JobStatusStore(home);
|
|
206
223
|
const statuses = [];
|
|
207
|
-
|
|
224
|
+
const jobIds = new Set();
|
|
225
|
+
for (const name of names) {
|
|
226
|
+
if (name.endsWith(".json"))
|
|
227
|
+
jobIds.add(name.slice(0, -".json".length));
|
|
228
|
+
if (name.endsWith(".terminal"))
|
|
229
|
+
jobIds.add(name.slice(0, -".terminal".length));
|
|
230
|
+
}
|
|
231
|
+
for (const jobId of [...jobIds].sort()) {
|
|
208
232
|
try {
|
|
209
|
-
|
|
233
|
+
const status = await statusStore.read(jobId);
|
|
234
|
+
if (status !== undefined)
|
|
235
|
+
statuses.push(status);
|
|
210
236
|
}
|
|
211
237
|
catch (error) {
|
|
212
|
-
throw new CueLineError("JOB_STATUS_INVALID", `unable to parse job status: ${
|
|
238
|
+
throw new CueLineError("JOB_STATUS_INVALID", `unable to parse job status: ${jobId}`, {
|
|
213
239
|
cause: error,
|
|
214
240
|
});
|
|
215
241
|
}
|
|
@@ -225,16 +251,22 @@ async function readJobs(home) {
|
|
|
225
251
|
for (const persisted of statuses) {
|
|
226
252
|
const authoritative = runMetadata.get(persisted.jobId);
|
|
227
253
|
const conflict = authoritative !== undefined && authoritative.status !== persisted.status;
|
|
254
|
+
const persistedMetadata = jobStatusMetadata(persisted);
|
|
255
|
+
const { finishedAt: _persistedFinishedAt, ...activePersistedMetadata } = persistedMetadata;
|
|
228
256
|
const status = conflict
|
|
229
257
|
? {
|
|
230
|
-
...
|
|
258
|
+
...activePersistedMetadata,
|
|
231
259
|
...authoritative,
|
|
232
260
|
execution: persisted.execution,
|
|
233
261
|
startedAt: persisted.startedAt,
|
|
234
262
|
}
|
|
235
263
|
: {
|
|
264
|
+
...(authoritative?.status === "pending" || authoritative?.status === "running"
|
|
265
|
+
? activePersistedMetadata
|
|
266
|
+
: persistedMetadata),
|
|
236
267
|
...authoritative,
|
|
237
|
-
|
|
268
|
+
execution: persisted.execution,
|
|
269
|
+
startedAt: persisted.startedAt,
|
|
238
270
|
status: authoritative?.status ?? persisted.status,
|
|
239
271
|
};
|
|
240
272
|
let observedStatus = conflict ? "conflict" : status.status;
|
|
@@ -252,7 +284,7 @@ async function readJobs(home) {
|
|
|
252
284
|
}
|
|
253
285
|
}
|
|
254
286
|
listed.push({
|
|
255
|
-
...status,
|
|
287
|
+
...jobStatusMetadata(status),
|
|
256
288
|
...(conflict ? { persistedStatus: persisted.status } : {}),
|
|
257
289
|
observedStatus,
|
|
258
290
|
});
|
|
@@ -270,14 +302,50 @@ async function jobsCommand(json, environment, io) {
|
|
|
270
302
|
return 0;
|
|
271
303
|
}
|
|
272
304
|
for (const job of jobs) {
|
|
273
|
-
io.stdout(`${job.jobId}\t${job.runId ?? "-"}\t${job.jobKey ?? "-"}\t${job.lane ?? "-"}\t${job.mode ?? "-"}\t${job.pid ?? "-"}\t${job.execution}\t${job.observedStatus}\t${job.startedAt}\trunner=${job.runnerId ?? "-"}\tmodel=${job.model ?? "-"}\tprovider=${job.provider ?? "-"}\tphase=${job.phase ?? "-"}\tprogress=${job.lastProgressAt ?? "-"}
|
|
305
|
+
io.stdout(`${job.jobId}\t${job.runId ?? "-"}\t${job.jobKey ?? "-"}\t${job.lane ?? "-"}\t${job.mode ?? "-"}\t${job.pid ?? "-"}\t${job.execution}\t${job.observedStatus}\t${job.startedAt}\trunner=${job.runnerId ?? "-"}\tmodel=${job.model ?? "-"}\tprovider=${job.provider ?? "-"}\tphase=${job.phase ?? "-"}\tprogress=${job.lastProgressAt ?? "-"}`);
|
|
274
306
|
}
|
|
275
307
|
return 0;
|
|
276
308
|
}
|
|
309
|
+
async function protocolLintCommand(file, expected, json, environment, io) {
|
|
310
|
+
const config = await loadRoutingConfig(routingConfigPath(environment));
|
|
311
|
+
const runnerLanes = Object.create(null);
|
|
312
|
+
for (const [lane, laneConfig] of Object.entries(config.lanes)) {
|
|
313
|
+
if (!laneConfig.enabled)
|
|
314
|
+
continue;
|
|
315
|
+
for (const candidate of laneConfig.candidates) {
|
|
316
|
+
if (candidate.enabled === false || runnerLanes[candidate.id] !== undefined)
|
|
317
|
+
continue;
|
|
318
|
+
runnerLanes[candidate.id] = lane;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
const text = await readFile(file, "utf8");
|
|
322
|
+
const report = lintControllerCommandText(text, {
|
|
323
|
+
expected,
|
|
324
|
+
routing: {
|
|
325
|
+
lanes: Object.entries(config.lanes)
|
|
326
|
+
.filter(([, lane]) => lane.enabled)
|
|
327
|
+
.map(([lane]) => lane),
|
|
328
|
+
runnerLanes,
|
|
329
|
+
},
|
|
330
|
+
});
|
|
331
|
+
if (json) {
|
|
332
|
+
io.stdout(JSON.stringify({ version: CUELINE_VERSION, ...report }, null, 2));
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
io.stdout(`valid\t${report.valid ? "yes" : "no"}`);
|
|
336
|
+
io.stdout(`format\t${report.format}`);
|
|
337
|
+
for (const issue of report.issues) {
|
|
338
|
+
io.stdout(`issue\t${issue.severity}\t${issue.code}\t${issue.path ?? "-"}\t${issue.message}\tsuggestion=${issue.suggestion ?? "-"}`);
|
|
339
|
+
}
|
|
340
|
+
if (report.command !== undefined)
|
|
341
|
+
io.stdout(`action\t${report.command.action}`);
|
|
342
|
+
}
|
|
343
|
+
return report.valid ? 0 : 1;
|
|
344
|
+
}
|
|
277
345
|
async function runStatusCommand(runId, json, environment, io) {
|
|
278
346
|
const status = await loadCueLineRunStatus(runId, { environment });
|
|
279
347
|
if (json) {
|
|
280
|
-
io.stdout(JSON.stringify({ version: CUELINE_VERSION, ...status }, null, 2));
|
|
348
|
+
io.stdout(JSON.stringify({ version: CUELINE_VERSION, ...safeCueLineRunStatus(status) }, null, 2));
|
|
281
349
|
return 0;
|
|
282
350
|
}
|
|
283
351
|
const controller = status.controller.responseAccepted
|
|
@@ -297,47 +365,18 @@ async function runStatusCommand(runId, json, environment, io) {
|
|
|
297
365
|
: `\theartbeat=${status.runtime.heartbeatAt}\tage_ms=${status.runtime.ageMs ?? "-"}`}`);
|
|
298
366
|
io.stdout(`sequence\t${status.lastEventSequence}`);
|
|
299
367
|
io.stdout(`controller\t${controller}\tpending=${status.controller.pendingTurns}\taccepted_commands=${status.controller.acceptedCommands}\tlast_action=${status.controller.lastAcceptedAction ?? "-"}\tlast_jobs=${status.controller.lastAcceptedJobKeys.length}`);
|
|
368
|
+
if (status.controller.archive.enabled) {
|
|
369
|
+
io.stdout(`controller_archive\tenabled=yes\tstatus=${status.controller.archive.status}\tcode=${status.controller.archive.code ?? "-"}\tproof=${status.controller.archive.proof ?? "-"}`);
|
|
370
|
+
}
|
|
300
371
|
io.stdout(`jobs\ttotal=${status.jobs.total}\tpending=${counts.pending}\trunning=${counts.running}\tsucceeded=${counts.succeeded}\tfailed=${counts.failed}\ttimed_out=${counts.timed_out}\torphaned=${counts.orphaned}\tcancelled=${counts.cancelled}\tambiguous=${counts.ambiguous}`);
|
|
301
372
|
for (const job of status.jobs.items) {
|
|
302
|
-
io.stdout(`job\t${job.jobId}\t${job.jobKey}\t${job.status}\t${job.mode}\t${job.lane}\trequired=${job.required}\tpersisted=${job.persistedStatus}\trunner=${job.execution?.runnerId ?? "-"}\tpid=${job.execution?.pid ?? "-"}\tmodel=${job.execution?.model ?? "-"}\tprovider=${job.execution?.provider ?? "-"}\tphase=${job.execution?.phase ?? "-"}\tprogress=${job.execution?.lastProgressAt ?? "-"}
|
|
373
|
+
io.stdout(`job\t${job.jobId}\t${job.jobKey}\t${job.status}\t${job.mode}\t${job.lane}\trequired=${job.required}\tpersisted=${job.persistedStatus}\trunner=${job.execution?.runnerId ?? "-"}\tpid=${job.execution?.pid ?? "-"}\tmodel=${job.execution?.model ?? "-"}\tprovider=${job.execution?.provider ?? "-"}\tphase=${job.execution?.phase ?? "-"}\tprogress=${job.execution?.lastProgressAt ?? "-"}`);
|
|
303
374
|
}
|
|
304
375
|
io.stdout(`cancellation\trun=${status.cancellation.runRequested ? "requested" : "none"}\tjobs=${status.cancellation.jobRequests.length}`);
|
|
305
376
|
io.stdout(`continue\t${status.continueAllowed ? "allowed" : "forbidden"}`);
|
|
306
377
|
io.stdout(`next\t${status.safeNextAction}`);
|
|
307
378
|
return 0;
|
|
308
379
|
}
|
|
309
|
-
async function doctorCommand(environment, io) {
|
|
310
|
-
const configPath = routingConfigPath(environment);
|
|
311
|
-
const home = defaultCueLineHome(environment);
|
|
312
|
-
const major = Number.parseInt(process.versions.node.split(".")[0] ?? "0", 10);
|
|
313
|
-
const nodeOk = major >= 22;
|
|
314
|
-
const config = await loadRoutingConfig(configPath);
|
|
315
|
-
const availability = executableAvailability(environment);
|
|
316
|
-
let callerLanes = 0;
|
|
317
|
-
let processAvailableLanes = 0;
|
|
318
|
-
for (const [lane, laneConfig] of Object.entries(config.lanes)) {
|
|
319
|
-
if (!laneConfig.enabled)
|
|
320
|
-
continue;
|
|
321
|
-
callerLanes += 1;
|
|
322
|
-
try {
|
|
323
|
-
resolveRoute(lane, config, availability);
|
|
324
|
-
processAvailableLanes += 1;
|
|
325
|
-
}
|
|
326
|
-
catch {
|
|
327
|
-
// Doctor reports the aggregate below; `cueline routing` shows lane details.
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
const callerReady = nodeOk && callerLanes > 0;
|
|
331
|
-
io.stdout(`CueLine ${CUELINE_VERSION}`);
|
|
332
|
-
io.stdout(`status\t${callerReady ? "ok" : "degraded"}`);
|
|
333
|
-
io.stdout(`node\t${process.versions.node}\t${nodeOk ? "ok" : "requires >=22"}`);
|
|
334
|
-
io.stdout(`config\t${configPath}\tvalid`);
|
|
335
|
-
io.stdout(`home\t${home}`);
|
|
336
|
-
io.stdout(`caller_ready\t${callerReady ? "yes" : "no"}`);
|
|
337
|
-
io.stdout(`caller_lanes\t${callerLanes}`);
|
|
338
|
-
io.stdout(`process_available_lanes\t${processAvailableLanes}`);
|
|
339
|
-
return callerReady ? 0 : 1;
|
|
340
|
-
}
|
|
341
380
|
export async function main(args = process.argv.slice(2), environment = process.env, io = processIo) {
|
|
342
381
|
try {
|
|
343
382
|
if (args.length === 0) {
|
|
@@ -373,13 +412,59 @@ export async function main(args = process.argv.slice(2), environment = process.e
|
|
|
373
412
|
io.stdout(await uninstallSkill(environment));
|
|
374
413
|
return 0;
|
|
375
414
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
415
|
+
const healthResult = await handleHealthCommand(args, environment, io);
|
|
416
|
+
if (healthResult !== undefined)
|
|
417
|
+
return healthResult;
|
|
379
418
|
if (args[0] === "jobs" &&
|
|
380
419
|
(args.length === 1 || (args.length === 2 && args[1] === "--json"))) {
|
|
381
|
-
return jobsCommand(args[1] === "--json", environment, io);
|
|
420
|
+
return await jobsCommand(args[1] === "--json", environment, io);
|
|
382
421
|
}
|
|
422
|
+
if (args[0] === "protocol" &&
|
|
423
|
+
args[1] === "lint" &&
|
|
424
|
+
typeof args[2] === "string") {
|
|
425
|
+
let runId;
|
|
426
|
+
let round;
|
|
427
|
+
let requestId;
|
|
428
|
+
let json = false;
|
|
429
|
+
let valid = true;
|
|
430
|
+
for (let index = 3; index < args.length; index += 1) {
|
|
431
|
+
const argument = args[index];
|
|
432
|
+
if (argument === "--run-id" && runId === undefined && typeof args[index + 1] === "string") {
|
|
433
|
+
runId = args[index + 1];
|
|
434
|
+
index += 1;
|
|
435
|
+
}
|
|
436
|
+
else if (argument === "--round" &&
|
|
437
|
+
round === undefined &&
|
|
438
|
+
typeof args[index + 1] === "string") {
|
|
439
|
+
round = Number(args[index + 1]);
|
|
440
|
+
index += 1;
|
|
441
|
+
}
|
|
442
|
+
else if (argument === "--request-id" &&
|
|
443
|
+
requestId === undefined &&
|
|
444
|
+
typeof args[index + 1] === "string") {
|
|
445
|
+
requestId = args[index + 1];
|
|
446
|
+
index += 1;
|
|
447
|
+
}
|
|
448
|
+
else if (argument === "--json" && !json) {
|
|
449
|
+
json = true;
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
valid = false;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
if (!valid ||
|
|
456
|
+
!runId ||
|
|
457
|
+
!requestId ||
|
|
458
|
+
round === undefined ||
|
|
459
|
+
!Number.isSafeInteger(round) ||
|
|
460
|
+
round < 1) {
|
|
461
|
+
throw new CueLineError("CLI_ARGUMENTS_INVALID", "usage: cueline protocol lint <file> --run-id <id> --round <n> --request-id <id> [--json]");
|
|
462
|
+
}
|
|
463
|
+
return await protocolLintCommand(args[2], { runId, round, requestId }, json, environment, io);
|
|
464
|
+
}
|
|
465
|
+
const observationResult = await handleObservationCommand(args, environment, io);
|
|
466
|
+
if (observationResult !== undefined)
|
|
467
|
+
return observationResult;
|
|
383
468
|
if (args[0] === "run" &&
|
|
384
469
|
args[1] === "takeover" &&
|
|
385
470
|
typeof args[2] === "string" &&
|
|
@@ -453,7 +538,7 @@ export async function main(args = process.argv.slice(2), environment = process.e
|
|
|
453
538
|
args[1] === "status" &&
|
|
454
539
|
typeof args[2] === "string" &&
|
|
455
540
|
(args.length === 3 || (args.length === 4 && args[3] === "--json"))) {
|
|
456
|
-
return runStatusCommand(args[2], args[3] === "--json", environment, io);
|
|
541
|
+
return await runStatusCommand(args[2], args[3] === "--json", environment, io);
|
|
457
542
|
}
|
|
458
543
|
if (args[0] === "run" &&
|
|
459
544
|
(args[1] === "cancel" || args[1] === "stop") &&
|
|
@@ -484,9 +569,6 @@ export async function main(args = process.argv.slice(2), environment = process.e
|
|
|
484
569
|
io.stdout(`${result.runId}\t${result.jobId}\t${result.outcome}`);
|
|
485
570
|
return 0;
|
|
486
571
|
}
|
|
487
|
-
if (args[0] === "doctor" && args.length === 1) {
|
|
488
|
-
return doctorCommand(environment, io);
|
|
489
|
-
}
|
|
490
572
|
io.stderr(`cueline: unrecognized command: ${args.join(" ")}`);
|
|
491
573
|
io.stderr(usage());
|
|
492
574
|
io.stderr("try `cueline help`");
|