cueline 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +3 -3
- package/CHANGELOG.md +38 -0
- package/README.ja.md +65 -21
- package/README.ko.md +65 -21
- package/README.md +70 -23
- package/README.zh-CN.md +65 -21
- package/README.zh-TW.md +68 -22
- package/dist/src/api-contracts.d.ts +77 -0
- package/dist/src/api-contracts.js +2 -0
- package/dist/src/api-contracts.js.map +1 -0
- package/dist/src/api-controller-handoff.d.ts +6 -0
- package/dist/src/api-controller-handoff.js +253 -0
- package/dist/src/api-controller-handoff.js.map +1 -0
- package/dist/src/api-runtime-lifecycle.d.ts +22 -0
- package/dist/src/api-runtime-lifecycle.js +568 -0
- package/dist/src/api-runtime-lifecycle.js.map +1 -0
- package/dist/src/api.d.ts +9 -27
- package/dist/src/api.js +138 -42
- package/dist/src/api.js.map +1 -1
- package/dist/src/browser/browser-adapter.d.ts +11 -1
- package/dist/src/browser/codex-iab/bootstrap.d.ts +16 -0
- package/dist/src/browser/codex-iab/bootstrap.js +49 -0
- package/dist/src/browser/codex-iab/bootstrap.js.map +1 -1
- package/dist/src/browser/codex-iab/chatgpt-client.js +346 -120
- package/dist/src/browser/codex-iab/chatgpt-client.js.map +1 -1
- package/dist/src/browser/codex-iab/recovery-evidence.d.ts +6 -0
- package/dist/src/browser/codex-iab/recovery-evidence.js +37 -0
- package/dist/src/browser/codex-iab/recovery-evidence.js.map +1 -0
- package/dist/src/browser/codex-iab/submission-url.d.ts +2 -0
- package/dist/src/browser/codex-iab/submission-url.js +53 -0
- package/dist/src/browser/codex-iab/submission-url.js.map +1 -0
- package/dist/src/cli/main.js +305 -20
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/core/controller-abort.d.ts +1 -0
- package/dist/src/core/controller-abort.js +11 -0
- package/dist/src/core/controller-abort.js.map +1 -0
- package/dist/src/core/controller-command-execution.d.ts +9 -0
- package/dist/src/core/controller-command-execution.js +299 -0
- package/dist/src/core/controller-command-execution.js.map +1 -0
- package/dist/src/core/controller-loop.d.ts +3 -37
- package/dist/src/core/controller-loop.js +386 -291
- package/dist/src/core/controller-loop.js.map +1 -1
- package/dist/src/core/controller-turn.d.ts +16 -0
- package/dist/src/core/controller-turn.js +309 -0
- package/dist/src/core/controller-turn.js.map +1 -0
- package/dist/src/core/controller-types.d.ts +58 -0
- package/dist/src/core/controller-types.js +2 -0
- package/dist/src/core/controller-types.js.map +1 -0
- package/dist/src/core/persisted-run.d.ts +4 -0
- package/dist/src/core/persisted-run.js +19 -0
- package/dist/src/core/persisted-run.js.map +1 -0
- package/dist/src/core/process-liveness.d.ts +2 -0
- package/dist/src/core/process-liveness.js +44 -0
- package/dist/src/core/process-liveness.js.map +1 -0
- package/dist/src/core/run-status.d.ts +53 -0
- package/dist/src/core/run-status.js +224 -0
- package/dist/src/core/run-status.js.map +1 -0
- package/dist/src/core/state-machine.d.ts +17 -4
- package/dist/src/core/state-machine.js +170 -16
- package/dist/src/core/state-machine.js.map +1 -1
- package/dist/src/jobs/status.d.ts +7 -1
- package/dist/src/jobs/status.js.map +1 -1
- package/dist/src/jobs/supervisor.d.ts +2 -0
- package/dist/src/jobs/supervisor.js +47 -13
- package/dist/src/jobs/supervisor.js.map +1 -1
- package/dist/src/protocol/types.d.ts +1 -1
- package/dist/src/protocol/validate-command.js +18 -0
- package/dist/src/protocol/validate-command.js.map +1 -1
- package/dist/src/router/resolver.d.ts +2 -1
- package/dist/src/router/resolver.js +31 -13
- package/dist/src/router/resolver.js.map +1 -1
- package/dist/src/runners/process-runner.d.ts +2 -2
- package/dist/src/runners/process-runner.js +113 -9
- package/dist/src/runners/process-runner.js.map +1 -1
- package/dist/src/runners/runner-adapter.d.ts +9 -2
- package/dist/src/runners/runner-adapter.js.map +1 -1
- package/dist/src/state/atomic-write.js +17 -2
- package/dist/src/state/atomic-write.js.map +1 -1
- package/dist/src/state/cancellation.d.ts +42 -0
- package/dist/src/state/cancellation.js +168 -0
- package/dist/src/state/cancellation.js.map +1 -0
- package/dist/src/state/event-log.d.ts +17 -1
- package/dist/src/state/event-log.js +328 -18
- package/dist/src/state/event-log.js.map +1 -1
- package/dist/src/state/paths.d.ts +4 -0
- package/dist/src/state/paths.js +4 -0
- package/dist/src/state/paths.js.map +1 -1
- package/dist/src/state/runtime-lease.d.ts +53 -0
- package/dist/src/state/runtime-lease.js +727 -0
- package/dist/src/state/runtime-lease.js.map +1 -0
- package/dist/src/state/runtime-retirement.d.ts +16 -0
- package/dist/src/state/runtime-retirement.js +95 -0
- package/dist/src/state/runtime-retirement.js.map +1 -0
- package/dist/src/state/runtime-takeover-intent.d.ts +1 -0
- package/dist/src/state/runtime-takeover-intent.js +18 -0
- package/dist/src/state/runtime-takeover-intent.js.map +1 -0
- package/dist/src/state/store.d.ts +12 -1
- package/dist/src/state/store.js +246 -40
- 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 +16 -11
- package/docs/assets/cueline-loop-en.svg +11 -10
- package/docs/assets/cueline-loop-ja.svg +11 -10
- package/docs/assets/cueline-loop-ko.svg +11 -10
- package/docs/assets/cueline-loop-zh-CN.svg +11 -10
- package/docs/assets/cueline-loop-zh-TW.svg +11 -10
- package/docs/compatibility.md +16 -8
- package/docs/controller-protocol.md +8 -4
- package/docs/runner-contract.md +26 -6
- package/docs/state-and-recovery.md +69 -16
- package/package.json +4 -3
- package/schemas/controller-observation.schema.json +1 -1
- package/scripts/validate-plugin.mjs +66 -0
- package/skills/cueline/SKILL.md +89 -13
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { JobMode } from "../protocol/types.js";
|
|
2
2
|
export type JobExecution = "foreground" | "background";
|
|
3
|
-
export type JobResultStatus = "succeeded" | "failed" | "timed_out" | "ambiguous";
|
|
3
|
+
export type JobResultStatus = "succeeded" | "failed" | "timed_out" | "cancelled" | "ambiguous";
|
|
4
4
|
export interface RunnerSpec {
|
|
5
5
|
jobId: string;
|
|
6
|
+
runId?: string;
|
|
7
|
+
jobKey?: string;
|
|
6
8
|
argv: readonly string[];
|
|
7
9
|
stdin?: string;
|
|
8
10
|
mode: JobMode;
|
|
@@ -12,6 +14,7 @@ export interface RunnerSpec {
|
|
|
12
14
|
task?: string;
|
|
13
15
|
cwd?: string;
|
|
14
16
|
env?: NodeJS.ProcessEnv;
|
|
17
|
+
signal?: AbortSignal;
|
|
15
18
|
}
|
|
16
19
|
export interface JobResult {
|
|
17
20
|
status: JobResultStatus;
|
|
@@ -21,12 +24,16 @@ export interface JobResult {
|
|
|
21
24
|
output: string;
|
|
22
25
|
emptyOutput: boolean;
|
|
23
26
|
timedOut: boolean;
|
|
27
|
+
cancelled: boolean;
|
|
24
28
|
ambiguousSideEffects: boolean;
|
|
25
29
|
retryable: false;
|
|
26
30
|
startedAt: string;
|
|
27
31
|
finishedAt: string;
|
|
28
32
|
}
|
|
33
|
+
export interface RunnerRunHooks {
|
|
34
|
+
onSpawn?(pid: number): void | Promise<void>;
|
|
35
|
+
}
|
|
29
36
|
export interface RunnerAdapter {
|
|
30
|
-
run(spec: RunnerSpec): Promise<JobResult>;
|
|
37
|
+
run(spec: RunnerSpec, hooks?: RunnerRunHooks): Promise<JobResult>;
|
|
31
38
|
}
|
|
32
39
|
export declare function executionFor(spec: Pick<RunnerSpec, "background">): JobExecution;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-adapter.js","sourceRoot":"","sources":["../../../src/runners/runner-adapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runner-adapter.js","sourceRoot":"","sources":["../../../src/runners/runner-adapter.ts"],"names":[],"mappings":"AAiDA,MAAM,UAAU,YAAY,CAAC,IAAoC;IAC/D,OAAO,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC;AAChE,CAAC"}
|
|
@@ -2,10 +2,24 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { mkdir, open, rename, unlink } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { canonicalJson } from "../core/ids.js";
|
|
5
|
-
import { runtimePidTag } from "../core/runtime.js";
|
|
5
|
+
import { runtimePidTag, runtimePlatform } from "../core/runtime.js";
|
|
6
|
+
async function syncDirectory(directory) {
|
|
7
|
+
if (runtimePlatform() === "win32")
|
|
8
|
+
return;
|
|
9
|
+
const handle = await open(directory, "r");
|
|
10
|
+
try {
|
|
11
|
+
await handle.sync();
|
|
12
|
+
}
|
|
13
|
+
finally {
|
|
14
|
+
await handle.close();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
6
17
|
export async function atomicWriteJson(target, value) {
|
|
7
18
|
const directory = path.dirname(target);
|
|
8
|
-
await mkdir(directory, { recursive: true });
|
|
19
|
+
const created = await mkdir(directory, { recursive: true });
|
|
20
|
+
if (created !== undefined) {
|
|
21
|
+
await syncDirectory(path.dirname(created));
|
|
22
|
+
}
|
|
9
23
|
const temporary = path.join(directory, `.${path.basename(target)}.${runtimePidTag()}.${randomUUID()}.tmp`);
|
|
10
24
|
let handle;
|
|
11
25
|
try {
|
|
@@ -15,6 +29,7 @@ export async function atomicWriteJson(target, value) {
|
|
|
15
29
|
await handle.close();
|
|
16
30
|
handle = undefined;
|
|
17
31
|
await rename(temporary, target);
|
|
32
|
+
await syncDirectory(directory);
|
|
18
33
|
}
|
|
19
34
|
catch (error) {
|
|
20
35
|
if (handle !== undefined) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atomic-write.js","sourceRoot":"","sources":["../../../src/state/atomic-write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"atomic-write.js","sourceRoot":"","sources":["../../../src/state/atomic-write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEpE,KAAK,UAAU,aAAa,CAAC,SAAiB;IAC5C,IAAI,eAAe,EAAE,KAAK,OAAO;QAAE,OAAO;IAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC1C,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAc,EAAE,KAAc;IAClE,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7C,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CACzB,SAAS,EACT,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,aAAa,EAAE,IAAI,UAAU,EAAE,MAAM,CACnE,CAAC;IACF,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QAC5C,MAAM,MAAM,CAAC,SAAS,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5D,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,GAAG,SAAS,CAAC;QACnB,MAAM,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAChC,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC9C,CAAC;QACD,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
declare const CANCELLATION_PROTOCOL = "cueline/cancellation/0.1";
|
|
2
|
+
export interface RunCancellationRequest {
|
|
3
|
+
protocol: typeof CANCELLATION_PROTOCOL;
|
|
4
|
+
run_id: string;
|
|
5
|
+
target: "run";
|
|
6
|
+
reason: string;
|
|
7
|
+
requested_at: string;
|
|
8
|
+
}
|
|
9
|
+
export interface JobCancellationRequest {
|
|
10
|
+
protocol: typeof CANCELLATION_PROTOCOL;
|
|
11
|
+
run_id: string;
|
|
12
|
+
target: "job";
|
|
13
|
+
job_id: string;
|
|
14
|
+
reason: string;
|
|
15
|
+
requested_at: string;
|
|
16
|
+
}
|
|
17
|
+
export interface CancellationObservation {
|
|
18
|
+
runRequested: boolean;
|
|
19
|
+
jobRequests: string[];
|
|
20
|
+
}
|
|
21
|
+
export interface CancellationWatcherOptions {
|
|
22
|
+
home: string;
|
|
23
|
+
runId: string;
|
|
24
|
+
intervalMs?: number;
|
|
25
|
+
onRun(request: RunCancellationRequest): void | Promise<void>;
|
|
26
|
+
onJob(request: JobCancellationRequest): boolean | void | Promise<boolean | void>;
|
|
27
|
+
onError(error: unknown): void;
|
|
28
|
+
}
|
|
29
|
+
export declare function requestRunCancellation(home: string, runId: string, reason: string, now?: () => Date): Promise<RunCancellationRequest>;
|
|
30
|
+
export declare function requestJobCancellation(home: string, runId: string, jobId: string, reason: string, now?: () => Date): Promise<JobCancellationRequest>;
|
|
31
|
+
export declare function readRunCancellation(home: string, runId: string): Promise<RunCancellationRequest | undefined>;
|
|
32
|
+
export declare function readJobCancellations(home: string, runId: string): Promise<JobCancellationRequest[]>;
|
|
33
|
+
export declare function readCancellationObservation(home: string, runId: string): Promise<CancellationObservation>;
|
|
34
|
+
export declare class CancellationWatcher {
|
|
35
|
+
#private;
|
|
36
|
+
private readonly options;
|
|
37
|
+
constructor(options: CancellationWatcherOptions);
|
|
38
|
+
start(): void;
|
|
39
|
+
stop(): Promise<void>;
|
|
40
|
+
private poll;
|
|
41
|
+
}
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { CueLineError } from "../core/errors.js";
|
|
4
|
+
import { atomicWriteJson } from "./atomic-write.js";
|
|
5
|
+
import { runPaths } from "./paths.js";
|
|
6
|
+
const CANCELLATION_PROTOCOL = "cueline/cancellation/0.1";
|
|
7
|
+
const JOB_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
|
|
8
|
+
function assertJobId(jobId) {
|
|
9
|
+
if (!JOB_ID_PATTERN.test(jobId)) {
|
|
10
|
+
throw new CueLineError("JOB_ID_INVALID", "job id contains unsupported path characters", {
|
|
11
|
+
details: { jobId },
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function assertReason(reason) {
|
|
16
|
+
if (reason.trim() === "") {
|
|
17
|
+
throw new CueLineError("CANCELLATION_REASON_INVALID", "cancellation reason must contain at least one non-whitespace character");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function isNotFound(error) {
|
|
21
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
22
|
+
}
|
|
23
|
+
function parseRequest(source, runId) {
|
|
24
|
+
const value = JSON.parse(source);
|
|
25
|
+
if (value.protocol !== CANCELLATION_PROTOCOL ||
|
|
26
|
+
value.run_id !== runId ||
|
|
27
|
+
(value.target !== "run" && value.target !== "job") ||
|
|
28
|
+
typeof value.reason !== "string" ||
|
|
29
|
+
value.reason.trim() === "" ||
|
|
30
|
+
typeof value.requested_at !== "string" ||
|
|
31
|
+
(value.target === "job" &&
|
|
32
|
+
(typeof value.job_id !== "string" || !JOB_ID_PATTERN.test(value.job_id)))) {
|
|
33
|
+
throw new CueLineError("CANCELLATION_REQUEST_INVALID", `CueLine run '${runId}' has an invalid cancellation request.`);
|
|
34
|
+
}
|
|
35
|
+
if (value.target === "run") {
|
|
36
|
+
return {
|
|
37
|
+
protocol: CANCELLATION_PROTOCOL,
|
|
38
|
+
run_id: runId,
|
|
39
|
+
target: "run",
|
|
40
|
+
reason: value.reason,
|
|
41
|
+
requested_at: value.requested_at,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
protocol: CANCELLATION_PROTOCOL,
|
|
46
|
+
run_id: runId,
|
|
47
|
+
target: "job",
|
|
48
|
+
job_id: value.job_id,
|
|
49
|
+
reason: value.reason,
|
|
50
|
+
requested_at: value.requested_at,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export async function requestRunCancellation(home, runId, reason, now = () => new Date()) {
|
|
54
|
+
assertReason(reason);
|
|
55
|
+
const request = {
|
|
56
|
+
protocol: CANCELLATION_PROTOCOL,
|
|
57
|
+
run_id: runId,
|
|
58
|
+
target: "run",
|
|
59
|
+
reason,
|
|
60
|
+
requested_at: now().toISOString(),
|
|
61
|
+
};
|
|
62
|
+
await atomicWriteJson(runPaths(home, runId).runCancellation, request);
|
|
63
|
+
return request;
|
|
64
|
+
}
|
|
65
|
+
export async function requestJobCancellation(home, runId, jobId, reason, now = () => new Date()) {
|
|
66
|
+
assertJobId(jobId);
|
|
67
|
+
assertReason(reason);
|
|
68
|
+
const request = {
|
|
69
|
+
protocol: CANCELLATION_PROTOCOL,
|
|
70
|
+
run_id: runId,
|
|
71
|
+
target: "job",
|
|
72
|
+
job_id: jobId,
|
|
73
|
+
reason,
|
|
74
|
+
requested_at: now().toISOString(),
|
|
75
|
+
};
|
|
76
|
+
await atomicWriteJson(path.join(runPaths(home, runId).jobCancellationsDir, `${jobId}.json`), request);
|
|
77
|
+
return request;
|
|
78
|
+
}
|
|
79
|
+
export async function readRunCancellation(home, runId) {
|
|
80
|
+
try {
|
|
81
|
+
const request = parseRequest(await readFile(runPaths(home, runId).runCancellation, "utf8"), runId);
|
|
82
|
+
if (request.target !== "run") {
|
|
83
|
+
throw new CueLineError("CANCELLATION_REQUEST_INVALID", `CueLine run '${runId}' has a job request in its run cancellation path.`);
|
|
84
|
+
}
|
|
85
|
+
return request;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (isNotFound(error))
|
|
89
|
+
return undefined;
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export async function readJobCancellations(home, runId) {
|
|
94
|
+
const directory = runPaths(home, runId).jobCancellationsDir;
|
|
95
|
+
let names;
|
|
96
|
+
try {
|
|
97
|
+
names = await readdir(directory);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
if (isNotFound(error))
|
|
101
|
+
return [];
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
const requests = [];
|
|
105
|
+
for (const name of names.filter((candidate) => candidate.endsWith(".json")).sort()) {
|
|
106
|
+
const request = parseRequest(await readFile(path.join(directory, name), "utf8"), runId);
|
|
107
|
+
if (request.target !== "job") {
|
|
108
|
+
throw new CueLineError("CANCELLATION_REQUEST_INVALID", `CueLine run '${runId}' has a run request in its job cancellation directory.`);
|
|
109
|
+
}
|
|
110
|
+
requests.push(request);
|
|
111
|
+
}
|
|
112
|
+
return requests;
|
|
113
|
+
}
|
|
114
|
+
export async function readCancellationObservation(home, runId) {
|
|
115
|
+
const [runRequest, jobRequests] = await Promise.all([
|
|
116
|
+
readRunCancellation(home, runId),
|
|
117
|
+
readJobCancellations(home, runId),
|
|
118
|
+
]);
|
|
119
|
+
return {
|
|
120
|
+
runRequested: runRequest !== undefined,
|
|
121
|
+
jobRequests: jobRequests.map((request) => request.job_id),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
export class CancellationWatcher {
|
|
125
|
+
options;
|
|
126
|
+
#seenJobs = new Set();
|
|
127
|
+
#sawRun = false;
|
|
128
|
+
#timer;
|
|
129
|
+
#pollChain = Promise.resolve();
|
|
130
|
+
constructor(options) {
|
|
131
|
+
this.options = options;
|
|
132
|
+
}
|
|
133
|
+
start() {
|
|
134
|
+
if (this.#timer !== undefined)
|
|
135
|
+
return;
|
|
136
|
+
const schedule = () => {
|
|
137
|
+
this.#pollChain = this.#pollChain.then(() => this.poll()).catch((error) => {
|
|
138
|
+
this.options.onError(error);
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
schedule();
|
|
142
|
+
this.#timer = setInterval(schedule, this.options.intervalMs ?? 250);
|
|
143
|
+
this.#timer.unref();
|
|
144
|
+
}
|
|
145
|
+
async stop() {
|
|
146
|
+
if (this.#timer !== undefined)
|
|
147
|
+
clearInterval(this.#timer);
|
|
148
|
+
this.#timer = undefined;
|
|
149
|
+
await this.#pollChain;
|
|
150
|
+
}
|
|
151
|
+
async poll() {
|
|
152
|
+
if (!this.#sawRun) {
|
|
153
|
+
const request = await readRunCancellation(this.options.home, this.options.runId);
|
|
154
|
+
if (request !== undefined) {
|
|
155
|
+
this.#sawRun = true;
|
|
156
|
+
await this.options.onRun(request);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
for (const request of await readJobCancellations(this.options.home, this.options.runId)) {
|
|
160
|
+
if (this.#seenJobs.has(request.job_id))
|
|
161
|
+
continue;
|
|
162
|
+
const handled = await this.options.onJob(request);
|
|
163
|
+
if (handled !== false)
|
|
164
|
+
this.#seenJobs.add(request.job_id);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=cancellation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cancellation.js","sourceRoot":"","sources":["../../../src/state/cancellation.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,24 @@
|
|
|
1
|
+
declare const EVENT_SEGMENT_FENCE_PROTOCOL = "cueline/event-segment-fence/0.1";
|
|
2
|
+
export interface EventLegacyFence {
|
|
3
|
+
protocol: typeof EVENT_SEGMENT_FENCE_PROTOCOL;
|
|
4
|
+
legacy_event_count: number;
|
|
5
|
+
legacy_byte_length: number;
|
|
6
|
+
legacy_sha256: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ReadEventsOptions {
|
|
9
|
+
/** A takeover-committed legacy prefix that must win over later JSONL suffixes. */
|
|
10
|
+
legacyFence?: EventLegacyFence;
|
|
11
|
+
}
|
|
1
12
|
export interface RunEvent {
|
|
2
13
|
sequence: number;
|
|
3
14
|
timestamp: string;
|
|
4
15
|
type: string;
|
|
5
16
|
payload: unknown;
|
|
17
|
+
runtime_owner_id?: string;
|
|
6
18
|
}
|
|
19
|
+
/** Captures a complete legacy prefix without publishing it as authoritative. */
|
|
20
|
+
export declare function captureEventLegacyFence(file: string): Promise<EventLegacyFence>;
|
|
7
21
|
export declare function appendEvent(file: string, event: RunEvent): Promise<void>;
|
|
8
|
-
export declare function
|
|
22
|
+
export declare function createEventLog(file: string, event: RunEvent): Promise<void>;
|
|
23
|
+
export declare function readEvents(file: string, options?: ReadEventsOptions): Promise<RunEvent[]>;
|
|
24
|
+
export {};
|