cueline 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +2 -2
- package/CHANGELOG.md +22 -0
- package/README.ja.md +27 -13
- package/README.ko.md +27 -13
- package/README.md +40 -15
- package/README.zh-CN.md +29 -13
- package/README.zh-TW.md +41 -16
- package/config/routing.default.json +1 -0
- package/dist/src/api-caller-work.d.ts +18 -0
- package/dist/src/api-caller-work.js +397 -0
- package/dist/src/api-caller-work.js.map +1 -0
- package/dist/src/api-contracts.d.ts +37 -0
- package/dist/src/api-controller-handoff.d.ts +2 -2
- package/dist/src/api-controller-handoff.js +82 -7
- package/dist/src/api-controller-handoff.js.map +1 -1
- package/dist/src/api-runtime-lifecycle.js +6 -1
- package/dist/src/api-runtime-lifecycle.js.map +1 -1
- package/dist/src/api.d.ts +3 -1
- package/dist/src/api.js +32 -3
- package/dist/src/api.js.map +1 -1
- package/dist/src/browser/codex-iab/bootstrap.js +35 -1
- package/dist/src/browser/codex-iab/bootstrap.js.map +1 -1
- package/dist/src/cli/main.js +13 -2
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/core/controller-command-execution.js +26 -2
- package/dist/src/core/controller-command-execution.js.map +1 -1
- package/dist/src/core/controller-loop.js +62 -17
- package/dist/src/core/controller-loop.js.map +1 -1
- package/dist/src/core/controller-turn.js +5 -0
- package/dist/src/core/controller-turn.js.map +1 -1
- package/dist/src/core/controller-types.d.ts +3 -1
- package/dist/src/core/ids.d.ts +1 -0
- package/dist/src/core/ids.js +3 -0
- package/dist/src/core/ids.js.map +1 -1
- package/dist/src/core/run-status.d.ts +30 -3
- package/dist/src/core/run-status.js +132 -4
- package/dist/src/core/run-status.js.map +1 -1
- package/dist/src/core/state-machine.d.ts +29 -1
- package/dist/src/core/state-machine.js +199 -2
- package/dist/src/core/state-machine.js.map +1 -1
- package/dist/src/jobs/status.d.ts +5 -0
- package/dist/src/jobs/status.js.map +1 -1
- package/dist/src/jobs/supervisor.js +32 -6
- package/dist/src/jobs/supervisor.js.map +1 -1
- package/dist/src/router/materialize.js +1 -0
- package/dist/src/router/materialize.js.map +1 -1
- package/dist/src/runners/process-runner.js +54 -0
- package/dist/src/runners/process-runner.js.map +1 -1
- package/dist/src/runners/runner-adapter.d.ts +9 -0
- package/dist/src/runners/runner-adapter.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/docs/architecture.md +8 -7
- package/docs/assets/cueline-loop-en.svg +1 -1
- package/docs/assets/cueline-loop-ja.svg +1 -1
- package/docs/assets/cueline-loop-ko.svg +1 -1
- package/docs/assets/cueline-loop-zh-CN.svg +1 -1
- package/docs/assets/cueline-loop-zh-TW.svg +1 -1
- package/docs/compatibility.md +7 -7
- package/docs/controller-protocol.md +4 -4
- package/docs/runner-contract.md +20 -7
- package/docs/state-and-recovery.md +11 -6
- package/package.json +2 -2
- package/skills/cueline/SKILL.md +48 -8
package/README.zh-TW.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
**CueLine 把方向盤交給一個已經開著的 ChatGPT 網頁對話:由它規劃整趟執行、喊出每一步;CueLine 檢查每一道文字指令,現在這個 Codex 才在本機執行獲准的工作。**
|
|
15
15
|
|
|
16
|
-
那個網頁碰不到你的機器,也沒有本機工具。它每一輪只吐出文字控制指令。CueLine 預設把
|
|
16
|
+
那個網頁碰不到你的機器,也沒有本機工具。它每一輪只吐出文字控制指令。CueLine 預設把 caller 工作保存成待辦:`advise` 是協調式交接;`work` 則必須先建立持久 claim 並正式 start,才能開始修改。只有雙重明確授權 `process` executor 時,才會啟動已註冊的本機工作行程。
|
|
17
17
|
|
|
18
18
|
CueLine 是獨立實作,**沒有任何 runtime npm 相依套件**,也不是 Omnilane 或 GPT Relay 的包裝層。
|
|
19
19
|
|
|
@@ -25,9 +25,9 @@ CueLine 是獨立實作,**沒有任何 runtime npm 相依套件**,也不是
|
|
|
25
25
|
|
|
26
26
|
非預設的 `maxRounds` 會在建立 run 時固定,並跨所有無 owner 的暫停累計主控總輪數。之後續跑通常省略它、沿用持久值;若傳入不同數字,CueLine 會拒絕,不會偷偷重設或放寬預算。
|
|
27
27
|
|
|
28
|
-
`startCueLineRun` 與 `runCueLine` 都預設使用 `caller` executor。使用內建瀏覽器時,CueLine 只送一次、保存精確對話 URL,然後回傳 `awaiting_controller` 並釋放 runtime lease,不會讓單一工具呼叫卡著等 Pro 思考。之後的 `continueCueLineRun` 只做一次唯讀觀測;若仍未完成,就再次回傳 `awaiting_controller`,絕不重送。`
|
|
28
|
+
`startCueLineRun` 與 `runCueLine` 都預設使用 `caller` executor。使用內建瀏覽器時,CueLine 只送一次、保存精確對話 URL,然後回傳 `awaiting_controller` 並釋放 runtime lease,不會讓單一工具呼叫卡著等 Pro 思考。之後的 `continueCueLineRun` 只做一次唯讀觀測;若仍未完成,就再次回傳 `awaiting_controller`,絕不重送。`advise` 派工回傳 `awaiting_caller`,沒有副作用 claim,需協調單一 session。`work` 派工回傳 `awaiting_caller_work`,在目前 Codex 呼叫 `claimCueLineCallerJob` 與 `startCueLineCallerJob` 前,絕對尚未開始本機修改。claim 綁定 run、job、task hash、絕對 workdir、caller identity 與 fencing token;已開始的工作不會自動重試,claim 逾期則成為 `ambiguous`。Pro 只提出與審查文字指令,沒有親自使用本機工具。
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
Process 模式必須同時指定 `executor: "process"` 與 `allowProcessExecution: true`,非終態續跑也要再次傳入第二道授權。內建 route 另加 `--ignore-user-config`,不讓隱藏 worker 載入使用者設定的 MCP server 或其命令參數。通道(lane)必須啟用、候選項必須在任何程序啟動**之前**就確認可用、`argv[0]` 必須早已由路由設定註冊。沒有任何東西會經過 shell。唯讀工作預設全域與每 lane 最多同時 2 個;只要批次包含 `work` 就維持串行。狀態會顯示解析後 runner、PID、phase、最後進度時間,以及安全辨識到的 model/provider。
|
|
31
31
|
|
|
32
32
|
主控協定刻意區分路由層級:`lane` 填的是通道名稱 `default`;`codex-default` 是該通道內的候選執行器,不是通道。CueLine 會在註冊任何工作前先驗證整份 `dispatch`;只要包含無效通道或執行器,整份派工就會被退回修正,不會先執行其中一部分。
|
|
33
33
|
|
|
@@ -48,15 +48,15 @@ ChatGPT Pro 訂閱方案與「選定的 Pro 模型」是兩回事。帳號或個
|
|
|
48
48
|
從 npm registry 安裝:
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
npm install -g cueline@0.1.
|
|
51
|
+
npm install -g cueline@0.1.6
|
|
52
52
|
cueline install
|
|
53
53
|
cueline doctor
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
作為備援,也可以安裝 [v0.1.
|
|
56
|
+
作為備援,也可以安裝 [v0.1.6 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.6) 上的打包 tarball,該 release 同時附上它的 `.sha256` 校驗碼:
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.
|
|
59
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.6/cueline-0.1.6.tgz
|
|
60
60
|
cueline install
|
|
61
61
|
cueline doctor
|
|
62
62
|
```
|
|
@@ -89,23 +89,26 @@ cueline doctor
|
|
|
89
89
|
|
|
90
90
|
```js
|
|
91
91
|
import {
|
|
92
|
+
claimCueLineCallerJob,
|
|
92
93
|
continueCueLineRun,
|
|
93
94
|
createCodexIabAdapter,
|
|
95
|
+
heartbeatCueLineCallerJob,
|
|
94
96
|
runCueLine,
|
|
97
|
+
startCueLineCallerJob,
|
|
95
98
|
submitCueLineCallerJobResult,
|
|
96
99
|
} from "cueline";
|
|
97
100
|
|
|
98
101
|
let result = await runCueLine({
|
|
99
102
|
request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
|
|
100
|
-
browser: createCodexIabAdapter(),
|
|
103
|
+
browser: createCodexIabAdapter({ browser: globalThis.browser }),
|
|
101
104
|
// 選填:conversationUrl、routingConfig / routingConfigPath、home、cwd、
|
|
102
105
|
// runTimeoutMs、signal,以及各工作/預設期限。
|
|
103
106
|
}); // 預設 executor: "caller"
|
|
104
107
|
|
|
105
|
-
while (
|
|
108
|
+
while (["awaiting_controller", "awaiting_caller", "awaiting_caller_work"].includes(result.status)) {
|
|
106
109
|
if (result.status === "awaiting_controller") {
|
|
107
110
|
await waitBeforeNextObservation(); // 有界退避;絕不重送
|
|
108
|
-
} else {
|
|
111
|
+
} else if (result.status === "awaiting_caller") {
|
|
109
112
|
for (const job of result.pendingJobs ?? []) {
|
|
110
113
|
const stdout = await executeExactLocalAdvice(job.spec.task);
|
|
111
114
|
await submitCueLineCallerJobResult(result.runId, job.jobId, {
|
|
@@ -113,6 +116,28 @@ while (result.status === "awaiting_controller" || result.status === "awaiting_ca
|
|
|
113
116
|
stdout,
|
|
114
117
|
});
|
|
115
118
|
}
|
|
119
|
+
} else {
|
|
120
|
+
for (const job of result.pendingJobs ?? []) {
|
|
121
|
+
if (job.spec.mode !== "work") continue;
|
|
122
|
+
const claim = await claimCueLineCallerJob(result.runId, job.jobId, {
|
|
123
|
+
callerId: "stable-codex-task-identity",
|
|
124
|
+
});
|
|
125
|
+
const proof = {
|
|
126
|
+
claimId: claim.claimId,
|
|
127
|
+
callerId: claim.callerId,
|
|
128
|
+
fencingToken: claim.fencingToken,
|
|
129
|
+
};
|
|
130
|
+
await startCueLineCallerJob(result.runId, job.jobId, proof);
|
|
131
|
+
const stdout = await executeExactLocalWork(job.spec.task, claim.workdir, {
|
|
132
|
+
heartbeat: () => heartbeatCueLineCallerJob(result.runId, job.jobId, proof),
|
|
133
|
+
});
|
|
134
|
+
await submitCueLineCallerJobResult(
|
|
135
|
+
result.runId,
|
|
136
|
+
job.jobId,
|
|
137
|
+
{ status: "succeeded", stdout },
|
|
138
|
+
{ claim: proof },
|
|
139
|
+
);
|
|
140
|
+
}
|
|
116
141
|
}
|
|
117
142
|
result = await continueCueLineRun({ runId: result.runId });
|
|
118
143
|
}
|
|
@@ -122,11 +147,11 @@ if (result.status === "complete") {
|
|
|
122
147
|
}
|
|
123
148
|
```
|
|
124
149
|
|
|
125
|
-
若回傳 `awaiting_controller`,代表同一個精確 request 已送出、但 Pro
|
|
150
|
+
若回傳 `awaiting_controller`,代表同一個精確 request 已送出、但 Pro 回覆尚未被觀測;稍後續跑只會唯讀觀測,不會重送。`awaiting_caller` 交接 `advise`;`awaiting_caller_work` 則必須依序 claim、start、執行、heartbeat 與帶 claim proof 提交結果。Pro 網頁從未直接使用本機工具。
|
|
126
151
|
|
|
127
152
|
在 Codex 的 runtime 裡,import `cueline api path` 印出的那個絕對路徑模組——那就是你安裝的那份套件建置出來的 API。
|
|
128
153
|
|
|
129
|
-
`startCueLineRun` 只建立持久 run 並回傳 `ready`;`runCueLine` 會建立並推進到持久 controller 觀測暫停、caller
|
|
154
|
+
`startCueLineRun` 只建立持久 run 並回傳 `ready`;`runCueLine` 會建立並推進到持久 controller 觀測暫停、caller 交接或終態。續跑前先執行 `cueline run status <run-id> --json`。單一正常送出、非人工、具精確 URL、無 job/pending command/取消的 stale caller observer 可被 fencing 後唯讀恢復;其他 stale 狀態仍須正式接管。`caller_work_pending`、`caller_work_claimed`、`caller_work_running` 分別只允許 `claim_caller_work`、`start_caller_work`、`continue_caller_work`,主控的 `dispatch` 本身不代表本機工作已開始。
|
|
130
155
|
|
|
131
156
|
## CLI
|
|
132
157
|
|
|
@@ -137,7 +162,7 @@ $ cueline install
|
|
|
137
162
|
CueLine skill installed: /Users/you/.codex/skills/cueline
|
|
138
163
|
|
|
139
164
|
$ cueline doctor
|
|
140
|
-
CueLine 0.1.
|
|
165
|
+
CueLine 0.1.6
|
|
141
166
|
status ok
|
|
142
167
|
node 22.14.0 ok
|
|
143
168
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -179,7 +204,7 @@ Node 版本太舊、或沒有任何已啟用的 caller 通道時,`cueline doct
|
|
|
179
204
|
|
|
180
205
|
`CUELINE_CONFIG` 用來指定路由設定檔;`CUELINE_HOME` 用來搬動本機狀態(預設 `~/.cueline`)。
|
|
181
206
|
|
|
182
|
-
Caller
|
|
207
|
+
Caller 模式不會啟動路由行程。只有同時選擇 `executor: "process"` 與 `allowProcessExecution: true` 時,內建的 `default` 通道才會以 `codex-default` 執行隔離的 `codex exec --ignore-user-config`;`advise` 用 `read-only`、`work` 用 `workspace-write`。
|
|
183
208
|
|
|
184
209
|
狀態放在 `CUELINE_HOME` 底下:
|
|
185
210
|
|
|
@@ -195,9 +220,9 @@ jobs/<job-id>.json 每個工作的執行證據
|
|
|
195
220
|
|
|
196
221
|
事件日誌才是紀錄本身:主控端的這一輪在送出之前就先寫下、工作在行程啟動之前就先註冊,所以「意圖」與「副作用」之間若被中斷,會留下痕跡。壞掉的快照會被忽略、從第 1 號事件重建,而不是硬信它。
|
|
197
222
|
|
|
198
|
-
續跑只會接回完全相同的對話網址。ChatGPT 把長文字自動轉成附件時,CueLine 會辨識 `attachment_ready`,且最多只點一次;模糊點擊一律記為 `possibly_sent
|
|
223
|
+
續跑只會接回完全相同的對話網址。ChatGPT 把長文字自動轉成附件時,CueLine 會辨識 `attachment_ready`,且最多只點一次;模糊點擊一律記為 `possibly_sent`,絕不補點或重送。只有實際可見、啟用且可操作的 Stop 按鈕才表示 Pro 仍在回答;隱藏殘留按鈕不會擋住完成回覆。若操作者手動送出附件,用 `cueline run reconcile RUN_ID --request-id REQUEST_ID --manual-send-confirmed` 寫入正式確認;之後仍須通過完全相同的 conversation、Pro 證據與 protocol/run/round/request identity 才能唯讀接回。
|
|
199
224
|
|
|
200
|
-
送給主控的工作證據優先採用成功且非空的 stdout,全體共用 12,000 字元上限;完整 stdout/stderr 仍保留在本機 job status
|
|
225
|
+
送給主控的工作證據優先採用成功且非空的 stdout,全體共用 12,000 字元上限;完整 stdout/stderr 仍保留在本機 job status。若 Pro 接受 `inspect(job_ids)`,下一輪會先替指定 job 保留證據預算,再處理無關工作。
|
|
201
226
|
|
|
202
227
|
## 驗證
|
|
203
228
|
|
|
@@ -214,7 +239,7 @@ npm pack --dry-run
|
|
|
214
239
|
|
|
215
240
|
## 0.1 的限制
|
|
216
241
|
|
|
217
|
-
只支援文字控制命令。一次執行只對應一個對話。選成 `Pro` 是 CueLine 唯一會做的模型切換。支援 ChatGPT 自動把長文字轉成附件,但不支援主動上傳檔案、圖片、Deep Research、Projects 或 Apps。Caller
|
|
242
|
+
只支援文字控制命令。一次執行只對應一個對話。選成 `Pro` 是 CueLine 唯一會做的模型切換。支援 ChatGPT 自動把長文字轉成附件,但不支援主動上傳檔案、圖片、Deep Research、Projects 或 Apps。Caller `work` 必須經過明確 claim/start,長工作需 heartbeat;process 執行則要雙重明確授權。任何模糊送出或已啟動工作都不會被自動重試。
|
|
218
243
|
|
|
219
244
|
完整矩陣見 [compatibility](docs/compatibility.md)。
|
|
220
245
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CueLineCallerWorkClaimOptions, CueLineCallerWorkClaimProof, CueLineCallerWorkClaimResult, CueLineCallerWorkMutationOptions, CueLineCallerWorkMutationResult } from "./api-contracts.js";
|
|
2
|
+
import type { CallerWorkClaim, CueLineRunState, StoredJob } from "./core/state-machine.js";
|
|
3
|
+
import type { RunStore } from "./state/store.js";
|
|
4
|
+
type CallerWorkMutationOptions = CueLineCallerWorkMutationOptions;
|
|
5
|
+
export declare function claimCueLineCallerJob(runId: string, jobId: string, options: CueLineCallerWorkClaimOptions): Promise<CueLineCallerWorkClaimResult>;
|
|
6
|
+
export declare function startCueLineCallerJob(runId: string, jobId: string, proof: CueLineCallerWorkClaimProof, options?: CallerWorkMutationOptions): Promise<CueLineCallerWorkMutationResult>;
|
|
7
|
+
export declare function heartbeatCueLineCallerJob(runId: string, jobId: string, proof: CueLineCallerWorkClaimProof, options?: CallerWorkMutationOptions): Promise<CueLineCallerWorkMutationResult>;
|
|
8
|
+
export declare function releaseCueLineCallerJob(runId: string, jobId: string, proof: CueLineCallerWorkClaimProof, options?: CallerWorkMutationOptions): Promise<CueLineCallerWorkMutationResult>;
|
|
9
|
+
/** Internal continuation repair: settle only claims whose durable TTL has elapsed. */
|
|
10
|
+
export declare function reconcileExpiredCallerWorkClaims(runId: string, options?: CallerWorkMutationOptions): Promise<number>;
|
|
11
|
+
/** Internal validation used while submitCueLineCallerJobResult owns the run lease. */
|
|
12
|
+
export declare function validateCallerWorkResultClaim(store: RunStore<CueLineRunState>, job: StoredJob, proof: CueLineCallerWorkClaimProof, home: string, now: Date, options?: {
|
|
13
|
+
durableTerminalIntent?: boolean;
|
|
14
|
+
}): Promise<{
|
|
15
|
+
claim: CallerWorkClaim;
|
|
16
|
+
alreadyTerminal: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { stat } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { CueLineError } from "./core/errors.js";
|
|
5
|
+
import { jobSpecHash } from "./core/ids.js";
|
|
6
|
+
import { loadPersistedRunStore } from "./core/persisted-run.js";
|
|
7
|
+
import { runtimeEnvironment } from "./core/runtime.js";
|
|
8
|
+
import { JobStatusStore } from "./jobs/status.js";
|
|
9
|
+
import { defaultCueLineHome } from "./state/paths.js";
|
|
10
|
+
import { readRuntimeLease, retireDeadRuntimeLease, RuntimeLease, } from "./state/runtime-lease.js";
|
|
11
|
+
const DEFAULT_CALLER_WORK_CLAIM_TTL_MS = 300_000;
|
|
12
|
+
const MIN_CALLER_WORK_CLAIM_TTL_MS = 1_000;
|
|
13
|
+
const MAX_CALLER_WORK_CLAIM_TTL_MS = 86_400_000;
|
|
14
|
+
function assertCallerId(value) {
|
|
15
|
+
if (value.trim() === "" || value.length > 256 || /[\u0000-\u001f\u007f]/.test(value)) {
|
|
16
|
+
throw new CueLineError("CALLER_ID_INVALID", "callerId must be a non-empty printable identifier of at most 256 characters.");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function validatedTtlMs(value) {
|
|
20
|
+
const ttlMs = value ?? DEFAULT_CALLER_WORK_CLAIM_TTL_MS;
|
|
21
|
+
if (!Number.isSafeInteger(ttlMs) ||
|
|
22
|
+
ttlMs < MIN_CALLER_WORK_CLAIM_TTL_MS ||
|
|
23
|
+
ttlMs > MAX_CALLER_WORK_CLAIM_TTL_MS) {
|
|
24
|
+
throw new CueLineError("CALLER_WORK_CLAIM_TTL_INVALID", `Caller work claim ttlMs must be an integer from ${MIN_CALLER_WORK_CLAIM_TTL_MS} to ${MAX_CALLER_WORK_CLAIM_TTL_MS}.`);
|
|
25
|
+
}
|
|
26
|
+
return ttlMs;
|
|
27
|
+
}
|
|
28
|
+
function assertClaimProof(value) {
|
|
29
|
+
assertCallerId(value.callerId);
|
|
30
|
+
if (value.claimId.trim() === "" || !Number.isSafeInteger(value.fencingToken)) {
|
|
31
|
+
throw new CueLineError("CALLER_WORK_CLAIM_PROOF_INVALID", "Caller work proof requires a non-empty claimId and a safe integer fencingToken.");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function callerWorkJob(store, jobId) {
|
|
35
|
+
if (store.state.executor !== "caller") {
|
|
36
|
+
throw new CueLineError("CALLER_EXECUTOR_REQUIRED", `Run '${store.runId}' uses the process executor; caller work cannot be claimed.`);
|
|
37
|
+
}
|
|
38
|
+
const job = store.state.jobs[jobId];
|
|
39
|
+
if (!job) {
|
|
40
|
+
throw new CueLineError("JOB_NOT_FOUND", `No job '${jobId}' exists in run '${store.runId}'.`);
|
|
41
|
+
}
|
|
42
|
+
if (job.spec.mode !== "work") {
|
|
43
|
+
throw new CueLineError("CALLER_WORK_JOB_REQUIRED", `Job '${jobId}' is advise-only and does not use a caller work claim.`);
|
|
44
|
+
}
|
|
45
|
+
if (job.spec.workdir === undefined || !path.isAbsolute(job.spec.workdir)) {
|
|
46
|
+
throw new CueLineError("CALLER_WORKDIR_REQUIRED", `Caller work job '${jobId}' is not bound to an absolute workdir.`);
|
|
47
|
+
}
|
|
48
|
+
return job;
|
|
49
|
+
}
|
|
50
|
+
async function assertWorkdirAvailable(workdir) {
|
|
51
|
+
const metadata = await stat(workdir).catch((error) => {
|
|
52
|
+
throw new CueLineError("CALLER_WORKDIR_UNAVAILABLE", `Caller workdir '${workdir}' is unavailable.`, { cause: error });
|
|
53
|
+
});
|
|
54
|
+
if (!metadata.isDirectory()) {
|
|
55
|
+
throw new CueLineError("CALLER_WORKDIR_UNAVAILABLE", `Caller workdir '${workdir}' is not a directory.`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function claimExpired(claim, now) {
|
|
59
|
+
const expiresAt = Date.parse(claim.expiresAt);
|
|
60
|
+
return !Number.isFinite(expiresAt) || expiresAt <= now.getTime();
|
|
61
|
+
}
|
|
62
|
+
function assertClaimClockMonotonic(claim, now) {
|
|
63
|
+
const heartbeatAt = Date.parse(claim.heartbeatAt);
|
|
64
|
+
if (!Number.isFinite(heartbeatAt) || now.getTime() < heartbeatAt) {
|
|
65
|
+
throw new CueLineError("CALLER_WORK_CLOCK_REGRESSION", `Caller work clock moved behind the durable heartbeat for claim '${claim.claimId}'; refusing a transition that the event reducer would reject.`, {
|
|
66
|
+
details: {
|
|
67
|
+
claim_id: claim.claimId,
|
|
68
|
+
heartbeat_at: claim.heartbeatAt,
|
|
69
|
+
observed_at: now.toISOString(),
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function expiration(now, ttlMs) {
|
|
75
|
+
return new Date(now.getTime() + ttlMs).toISOString();
|
|
76
|
+
}
|
|
77
|
+
async function writeClaimJobStatus(home, store, job, status, timestamp, error) {
|
|
78
|
+
const statusStore = new JobStatusStore(home);
|
|
79
|
+
const existing = await statusStore.read(job.jobId);
|
|
80
|
+
const next = {
|
|
81
|
+
jobId: job.jobId,
|
|
82
|
+
runId: store.runId,
|
|
83
|
+
jobKey: job.jobKey,
|
|
84
|
+
lane: job.spec.lane,
|
|
85
|
+
mode: job.spec.mode,
|
|
86
|
+
execution: "foreground",
|
|
87
|
+
status,
|
|
88
|
+
startedAt: existing?.startedAt ?? timestamp,
|
|
89
|
+
...(status === "ambiguous" ? { finishedAt: timestamp } : {}),
|
|
90
|
+
...(error === undefined ? {} : { error }),
|
|
91
|
+
};
|
|
92
|
+
await statusStore.write(next);
|
|
93
|
+
}
|
|
94
|
+
async function markStartedClaimAmbiguous(store, job, claim, home, now) {
|
|
95
|
+
const reason = await persistStartedClaimAmbiguous(store, job, claim, home, now);
|
|
96
|
+
await store.snapshot();
|
|
97
|
+
throw new CueLineError("CALLER_WORK_BECAME_AMBIGUOUS", reason, {
|
|
98
|
+
details: { run_id: store.runId, job_id: job.jobId, claim_id: claim.claimId },
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async function persistStartedClaimAmbiguous(store, job, claim, home, now) {
|
|
102
|
+
const reason = "Caller work claim expired after local work started; side effects cannot be inferred or retried.";
|
|
103
|
+
await store.append("caller_work_became_ambiguous", {
|
|
104
|
+
job_id: job.jobId,
|
|
105
|
+
claim_id: claim.claimId,
|
|
106
|
+
fencing_token: claim.fencingToken,
|
|
107
|
+
caller_id: claim.callerId,
|
|
108
|
+
reason,
|
|
109
|
+
detected_at: now.toISOString(),
|
|
110
|
+
});
|
|
111
|
+
await writeClaimJobStatus(home, store, job, "ambiguous", now.toISOString(), reason);
|
|
112
|
+
return reason;
|
|
113
|
+
}
|
|
114
|
+
async function releaseExpiredUnstartedClaim(store, job, claim, home, now) {
|
|
115
|
+
await store.append("caller_work_claim_released", {
|
|
116
|
+
job_id: job.jobId,
|
|
117
|
+
claim_id: claim.claimId,
|
|
118
|
+
fencing_token: claim.fencingToken,
|
|
119
|
+
caller_id: claim.callerId,
|
|
120
|
+
reason: "expired_before_start",
|
|
121
|
+
released_at: now.toISOString(),
|
|
122
|
+
});
|
|
123
|
+
await writeClaimJobStatus(home, store, job, "pending", now.toISOString());
|
|
124
|
+
}
|
|
125
|
+
async function assertClaimNotExpired(store, job, claim, home, now) {
|
|
126
|
+
assertClaimClockMonotonic(claim, now);
|
|
127
|
+
if (!claimExpired(claim, now))
|
|
128
|
+
return;
|
|
129
|
+
if (claim.startedAt !== null) {
|
|
130
|
+
await markStartedClaimAmbiguous(store, job, claim, home, now);
|
|
131
|
+
}
|
|
132
|
+
await releaseExpiredUnstartedClaim(store, job, claim, home, now);
|
|
133
|
+
await store.snapshot();
|
|
134
|
+
throw new CueLineError("CALLER_WORK_CLAIM_EXPIRED", `Caller work claim '${claim.claimId}' expired before local work started.`, { details: { run_id: store.runId, job_id: job.jobId, claim_id: claim.claimId } });
|
|
135
|
+
}
|
|
136
|
+
function exactClaim(job, proof) {
|
|
137
|
+
assertClaimProof(proof);
|
|
138
|
+
const claim = job.callerWork?.claim;
|
|
139
|
+
if (!claim ||
|
|
140
|
+
claim.claimId !== proof.claimId ||
|
|
141
|
+
claim.callerId !== proof.callerId ||
|
|
142
|
+
claim.fencingToken !== proof.fencingToken ||
|
|
143
|
+
claim.taskHash !== jobSpecHash(job.spec) ||
|
|
144
|
+
claim.workdir !== job.spec.workdir) {
|
|
145
|
+
throw new CueLineError("CALLER_WORK_CLAIM_MISMATCH", `Caller work proof does not match the active immutable claim for job '${job.jobId}'.`);
|
|
146
|
+
}
|
|
147
|
+
return claim;
|
|
148
|
+
}
|
|
149
|
+
function claimResult(runId, job, claim, outcome) {
|
|
150
|
+
return {
|
|
151
|
+
runId,
|
|
152
|
+
jobId: job.jobId,
|
|
153
|
+
outcome,
|
|
154
|
+
task: job.spec.task,
|
|
155
|
+
taskHash: claim.taskHash,
|
|
156
|
+
workdir: claim.workdir,
|
|
157
|
+
claimId: claim.claimId,
|
|
158
|
+
callerId: claim.callerId,
|
|
159
|
+
fencingToken: claim.fencingToken,
|
|
160
|
+
claimedAt: claim.claimedAt,
|
|
161
|
+
heartbeatAt: claim.heartbeatAt,
|
|
162
|
+
expiresAt: claim.expiresAt,
|
|
163
|
+
started: claim.startedAt !== null,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
async function withCallerWorkStore(runId, options, operation) {
|
|
167
|
+
const environment = options.environment ?? runtimeEnvironment();
|
|
168
|
+
const home = options.home ?? defaultCueLineHome(environment);
|
|
169
|
+
const now = options.now ?? (() => new Date());
|
|
170
|
+
await loadPersistedRunStore(home, runId);
|
|
171
|
+
const runtime = await readRuntimeLease(home, runId, { now });
|
|
172
|
+
const retiredOwner = (runtime.ownership === "active" || runtime.ownership === "stale") &&
|
|
173
|
+
runtime.ownerId !== undefined &&
|
|
174
|
+
(await retireDeadRuntimeLease(home, runId, runtime.ownerId))
|
|
175
|
+
? { ownerId: runtime.ownerId, ownership: runtime.ownership }
|
|
176
|
+
: undefined;
|
|
177
|
+
const lease = await RuntimeLease.claim({ home, runId, now });
|
|
178
|
+
try {
|
|
179
|
+
const store = await loadPersistedRunStore(home, runId);
|
|
180
|
+
store.bindRuntimeOwner(lease.ownerId);
|
|
181
|
+
if (retiredOwner !== undefined) {
|
|
182
|
+
await store.append("runtime_dead_owner_retired", {
|
|
183
|
+
owner_id: retiredOwner.ownerId,
|
|
184
|
+
previous_ownership: retiredOwner.ownership,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return await operation(store, home, now);
|
|
188
|
+
}
|
|
189
|
+
finally {
|
|
190
|
+
await lease.release();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
export async function claimCueLineCallerJob(runId, jobId, options) {
|
|
194
|
+
assertCallerId(options.callerId);
|
|
195
|
+
const ttlMs = validatedTtlMs(options.ttlMs);
|
|
196
|
+
return withCallerWorkStore(runId, options, async (store, home, now) => {
|
|
197
|
+
let job = callerWorkJob(store, jobId);
|
|
198
|
+
if (job.status !== "pending" && job.status !== "running") {
|
|
199
|
+
throw new CueLineError("CALLER_WORK_NOT_CLAIMABLE", `Caller work job '${jobId}' has status '${job.status}' and cannot be claimed.`);
|
|
200
|
+
}
|
|
201
|
+
const currentTime = now();
|
|
202
|
+
const existing = job.callerWork?.claim;
|
|
203
|
+
if (existing !== null && existing !== undefined) {
|
|
204
|
+
if (!claimExpired(existing, currentTime)) {
|
|
205
|
+
if (existing.callerId === options.callerId) {
|
|
206
|
+
return claimResult(runId, job, existing, "already_claimed");
|
|
207
|
+
}
|
|
208
|
+
throw new CueLineError("CALLER_WORK_ALREADY_CLAIMED", `Caller work job '${jobId}' already has an active claim.`, { details: { job_id: jobId, expires_at: existing.expiresAt } });
|
|
209
|
+
}
|
|
210
|
+
if (existing.startedAt !== null) {
|
|
211
|
+
await markStartedClaimAmbiguous(store, job, existing, home, currentTime);
|
|
212
|
+
}
|
|
213
|
+
await releaseExpiredUnstartedClaim(store, job, existing, home, currentTime);
|
|
214
|
+
job = callerWorkJob(store, jobId);
|
|
215
|
+
}
|
|
216
|
+
if (job.status !== "pending") {
|
|
217
|
+
throw new CueLineError("CALLER_WORK_CLAIM_STATE_INVALID", `Caller work job '${jobId}' is running without an active claim and cannot be reclaimed safely.`);
|
|
218
|
+
}
|
|
219
|
+
const workdir = job.spec.workdir;
|
|
220
|
+
await assertWorkdirAvailable(workdir);
|
|
221
|
+
const timestamp = currentTime.toISOString();
|
|
222
|
+
const fencingToken = (job.callerWork?.nextFencingToken ?? 0) + 1;
|
|
223
|
+
const claim = {
|
|
224
|
+
claimId: `claim_${randomUUID()}`,
|
|
225
|
+
callerId: options.callerId,
|
|
226
|
+
taskHash: jobSpecHash(job.spec),
|
|
227
|
+
workdir,
|
|
228
|
+
fencingToken,
|
|
229
|
+
claimedAt: timestamp,
|
|
230
|
+
heartbeatAt: timestamp,
|
|
231
|
+
expiresAt: expiration(currentTime, ttlMs),
|
|
232
|
+
ttlMs,
|
|
233
|
+
startedAt: null,
|
|
234
|
+
};
|
|
235
|
+
await store.append("caller_work_claimed", {
|
|
236
|
+
job_id: job.jobId,
|
|
237
|
+
claim,
|
|
238
|
+
});
|
|
239
|
+
await writeClaimJobStatus(home, store, job, "pending", timestamp);
|
|
240
|
+
await store.snapshot();
|
|
241
|
+
return claimResult(runId, job, claim, "claimed");
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
export async function startCueLineCallerJob(runId, jobId, proof, options = {}) {
|
|
245
|
+
return withCallerWorkStore(runId, options, async (store, home, now) => {
|
|
246
|
+
const job = callerWorkJob(store, jobId);
|
|
247
|
+
const claim = exactClaim(job, proof);
|
|
248
|
+
if (job.status !== "pending" && job.status !== "running") {
|
|
249
|
+
throw new CueLineError("CALLER_WORK_NOT_STARTABLE", `Caller work job '${jobId}' has terminal status '${job.status}'.`);
|
|
250
|
+
}
|
|
251
|
+
const currentTime = now();
|
|
252
|
+
await assertClaimNotExpired(store, job, claim, home, currentTime);
|
|
253
|
+
if (claim.startedAt !== null) {
|
|
254
|
+
return {
|
|
255
|
+
runId,
|
|
256
|
+
jobId,
|
|
257
|
+
claimId: claim.claimId,
|
|
258
|
+
fencingToken: claim.fencingToken,
|
|
259
|
+
outcome: "already_started",
|
|
260
|
+
heartbeatAt: claim.heartbeatAt,
|
|
261
|
+
expiresAt: claim.expiresAt,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
await assertWorkdirAvailable(claim.workdir);
|
|
265
|
+
const timestamp = currentTime.toISOString();
|
|
266
|
+
const expiresAt = expiration(currentTime, claim.ttlMs);
|
|
267
|
+
await store.append("caller_work_started", {
|
|
268
|
+
job_id: jobId,
|
|
269
|
+
claim_id: claim.claimId,
|
|
270
|
+
caller_id: claim.callerId,
|
|
271
|
+
fencing_token: claim.fencingToken,
|
|
272
|
+
task_hash: claim.taskHash,
|
|
273
|
+
workdir: claim.workdir,
|
|
274
|
+
started_at: timestamp,
|
|
275
|
+
expires_at: expiresAt,
|
|
276
|
+
});
|
|
277
|
+
await writeClaimJobStatus(home, store, job, "running", timestamp);
|
|
278
|
+
await store.snapshot();
|
|
279
|
+
return {
|
|
280
|
+
runId,
|
|
281
|
+
jobId,
|
|
282
|
+
claimId: claim.claimId,
|
|
283
|
+
fencingToken: claim.fencingToken,
|
|
284
|
+
outcome: "started",
|
|
285
|
+
heartbeatAt: timestamp,
|
|
286
|
+
expiresAt,
|
|
287
|
+
};
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
export async function heartbeatCueLineCallerJob(runId, jobId, proof, options = {}) {
|
|
291
|
+
return withCallerWorkStore(runId, options, async (store, home, now) => {
|
|
292
|
+
const job = callerWorkJob(store, jobId);
|
|
293
|
+
const claim = exactClaim(job, proof);
|
|
294
|
+
if (job.status !== "pending" && job.status !== "running") {
|
|
295
|
+
throw new CueLineError("CALLER_WORK_NOT_ACTIVE", `Caller work job '${jobId}' has terminal status '${job.status}'.`);
|
|
296
|
+
}
|
|
297
|
+
const currentTime = now();
|
|
298
|
+
await assertClaimNotExpired(store, job, claim, home, currentTime);
|
|
299
|
+
const timestamp = currentTime.toISOString();
|
|
300
|
+
const expiresAt = expiration(currentTime, claim.ttlMs);
|
|
301
|
+
await store.append("caller_work_heartbeat", {
|
|
302
|
+
job_id: jobId,
|
|
303
|
+
claim_id: claim.claimId,
|
|
304
|
+
caller_id: claim.callerId,
|
|
305
|
+
fencing_token: claim.fencingToken,
|
|
306
|
+
heartbeat_at: timestamp,
|
|
307
|
+
expires_at: expiresAt,
|
|
308
|
+
});
|
|
309
|
+
await writeClaimJobStatus(home, store, job, claim.startedAt === null ? "pending" : "running", timestamp);
|
|
310
|
+
await store.snapshot();
|
|
311
|
+
return {
|
|
312
|
+
runId,
|
|
313
|
+
jobId,
|
|
314
|
+
claimId: claim.claimId,
|
|
315
|
+
fencingToken: claim.fencingToken,
|
|
316
|
+
outcome: "heartbeat_recorded",
|
|
317
|
+
heartbeatAt: timestamp,
|
|
318
|
+
expiresAt,
|
|
319
|
+
};
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
export async function releaseCueLineCallerJob(runId, jobId, proof, options = {}) {
|
|
323
|
+
return withCallerWorkStore(runId, options, async (store, home, now) => {
|
|
324
|
+
const job = callerWorkJob(store, jobId);
|
|
325
|
+
const claim = exactClaim(job, proof);
|
|
326
|
+
const currentTime = now();
|
|
327
|
+
await assertClaimNotExpired(store, job, claim, home, currentTime);
|
|
328
|
+
if (claim.startedAt !== null) {
|
|
329
|
+
throw new CueLineError("CALLER_WORK_RELEASE_AFTER_START_FORBIDDEN", "A caller work claim cannot be released after local work started; submit a terminal result or let it become ambiguous.");
|
|
330
|
+
}
|
|
331
|
+
await store.append("caller_work_claim_released", {
|
|
332
|
+
job_id: jobId,
|
|
333
|
+
claim_id: claim.claimId,
|
|
334
|
+
caller_id: claim.callerId,
|
|
335
|
+
fencing_token: claim.fencingToken,
|
|
336
|
+
reason: "caller_released_before_start",
|
|
337
|
+
released_at: currentTime.toISOString(),
|
|
338
|
+
});
|
|
339
|
+
await writeClaimJobStatus(home, store, job, "pending", currentTime.toISOString());
|
|
340
|
+
await store.snapshot();
|
|
341
|
+
return {
|
|
342
|
+
runId,
|
|
343
|
+
jobId,
|
|
344
|
+
claimId: claim.claimId,
|
|
345
|
+
fencingToken: claim.fencingToken,
|
|
346
|
+
outcome: "released",
|
|
347
|
+
};
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
/** Internal continuation repair: settle only claims whose durable TTL has elapsed. */
|
|
351
|
+
export async function reconcileExpiredCallerWorkClaims(runId, options = {}) {
|
|
352
|
+
return withCallerWorkStore(runId, options, async (store, home, now) => {
|
|
353
|
+
if (store.state.executor !== "caller")
|
|
354
|
+
return 0;
|
|
355
|
+
const currentTime = now();
|
|
356
|
+
let affected = 0;
|
|
357
|
+
for (const job of Object.values(store.state.jobs)) {
|
|
358
|
+
const claim = job.callerWork?.claim;
|
|
359
|
+
if (job.spec.mode !== "work" ||
|
|
360
|
+
(job.status !== "pending" && job.status !== "running") ||
|
|
361
|
+
claim === null ||
|
|
362
|
+
claim === undefined ||
|
|
363
|
+
!claimExpired(claim, currentTime)) {
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
if (claim.startedAt === null) {
|
|
367
|
+
await releaseExpiredUnstartedClaim(store, job, claim, home, currentTime);
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
await persistStartedClaimAmbiguous(store, job, claim, home, currentTime);
|
|
371
|
+
}
|
|
372
|
+
affected += 1;
|
|
373
|
+
}
|
|
374
|
+
if (affected > 0)
|
|
375
|
+
await store.snapshot();
|
|
376
|
+
return affected;
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
/** Internal validation used while submitCueLineCallerJobResult owns the run lease. */
|
|
380
|
+
export async function validateCallerWorkResultClaim(store, job, proof, home, now, options = {}) {
|
|
381
|
+
const claim = exactClaim(job, proof);
|
|
382
|
+
const alreadyTerminal = job.status !== "pending" && job.status !== "running";
|
|
383
|
+
if (alreadyTerminal)
|
|
384
|
+
return { claim, alreadyTerminal };
|
|
385
|
+
if (options.durableTerminalIntent === true) {
|
|
386
|
+
if (claim.startedAt === null || job.status !== "running") {
|
|
387
|
+
throw new CueLineError("CALLER_WORK_NOT_STARTED", `Caller work job '${job.jobId}' must be durably started before recovering a terminal result.`);
|
|
388
|
+
}
|
|
389
|
+
return { claim, alreadyTerminal: false };
|
|
390
|
+
}
|
|
391
|
+
await assertClaimNotExpired(store, job, claim, home, now);
|
|
392
|
+
if (claim.startedAt === null || job.status !== "running") {
|
|
393
|
+
throw new CueLineError("CALLER_WORK_NOT_STARTED", `Caller work job '${job.jobId}' must be durably started before submitting a result.`);
|
|
394
|
+
}
|
|
395
|
+
return { claim, alreadyTerminal: false };
|
|
396
|
+
}
|
|
397
|
+
//# sourceMappingURL=api-caller-work.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-caller-work.js","sourceRoot":"","sources":["../../src/api-caller-work.ts"],"names":[],"mappings":"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"}
|