cueline 0.1.2 → 0.1.3
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 +17 -0
- package/README.ja.md +15 -6
- package/README.ko.md +15 -6
- package/README.md +15 -6
- package/README.zh-CN.md +15 -6
- package/README.zh-TW.md +15 -6
- package/dist/src/api.d.ts +23 -1
- package/dist/src/api.js +110 -6
- package/dist/src/api.js.map +1 -1
- package/dist/src/browser/browser-adapter.d.ts +1 -0
- package/dist/src/browser/codex-iab/bootstrap.d.ts +6 -0
- package/dist/src/browser/codex-iab/bootstrap.js.map +1 -1
- package/dist/src/browser/codex-iab/chatgpt-client.js +138 -41
- package/dist/src/browser/codex-iab/chatgpt-client.js.map +1 -1
- package/dist/src/cli/main.js +150 -8
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/core/controller-loop.d.ts +6 -0
- package/dist/src/core/controller-loop.js +240 -74
- package/dist/src/core/controller-loop.js.map +1 -1
- package/dist/src/core/run-status.d.ts +50 -0
- package/dist/src/core/run-status.js +169 -0
- package/dist/src/core/run-status.js.map +1 -0
- package/dist/src/core/state-machine.d.ts +2 -1
- package/dist/src/core/state-machine.js +22 -1
- package/dist/src/core/state-machine.js.map +1 -1
- package/dist/src/jobs/status.d.ts +6 -0
- package/dist/src/jobs/status.js.map +1 -1
- package/dist/src/jobs/supervisor.d.ts +2 -0
- package/dist/src/jobs/supervisor.js +44 -12
- 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.js +7 -1
- 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 +56 -5
- 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/cancellation.d.ts +42 -0
- package/dist/src/state/cancellation.js +160 -0
- package/dist/src/state/cancellation.js.map +1 -0
- package/dist/src/state/paths.d.ts +3 -0
- package/dist/src/state/paths.js +3 -0
- package/dist/src/state/paths.js.map +1 -1
- package/dist/src/state/runtime-lease.d.ts +28 -0
- package/dist/src/state/runtime-lease.js +179 -0
- package/dist/src/state/runtime-lease.js.map +1 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/docs/compatibility.md +3 -1
- package/docs/controller-protocol.md +4 -2
- package/docs/runner-contract.md +7 -1
- package/docs/state-and-recovery.md +34 -9
- package/package.json +3 -2
- package/schemas/controller-observation.schema.json +1 -1
- package/scripts/validate-plugin.mjs +66 -0
- package/skills/cueline/SKILL.md +33 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.3 - 2026-07-15
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Add `cueline run status <run-id> --json` with accepted-controller-response evidence, the last accepted action and job keys, runtime ownership, safe next action, cancellation requests, and derived `orphaned` jobs. A new session no longer calls a persisted `running` value active when no live owner is proven.
|
|
8
|
+
- Add an owner heartbeat lease. A second session refuses to continue an active run, and a missing or stale owner requires inspection instead of another controller send.
|
|
9
|
+
- Run independent all-`advise` dispatches concurrently. Any dispatch containing `work` remains serial to avoid overlapping mutations.
|
|
10
|
+
- Add durable `run cancel` / `run stop` and `job cancel` requests, API `AbortSignal` support, and `runTimeoutMs`. Active `advise` cancellation becomes `cancelled`; interrupted `work` or ownerless legacy work becomes `ambiguous`.
|
|
11
|
+
- Persist job run ID, job key, lane, mode, and child PID for diagnosis. `cueline jobs --json` reports an observed status and never uses PID alone as kill authorization.
|
|
12
|
+
- Reject unsupported `runner_id` explicitly, require `runner`, and explain when a runner ID such as `codex-default` was placed in `lane`.
|
|
13
|
+
- Preserve built-in-browser attach failures instead of converting them to an empty tab list. Retry safe pre-submit attachment once, recheck an empty discovery result once, cache a new tab only after it loads, and use at most one CUA coordinate fallback after a transient send-locator failure.
|
|
14
|
+
|
|
15
|
+
### Documentation
|
|
16
|
+
|
|
17
|
+
- Require `run status` before continuation and distinguish controller response acceptance, local job execution, runtime ownership, and outer waiter timeout.
|
|
18
|
+
- Document cancellation, run-level deadlines, `advise` concurrency, `work` serialization, and stale-job recovery semantics.
|
|
19
|
+
|
|
3
20
|
## 0.1.2 - 2026-07-15
|
|
4
21
|
|
|
5
22
|
### Fixed
|
package/README.ja.md
CHANGED
|
@@ -44,15 +44,15 @@ ChatGPT Pro のサブスクリプションと、選択された Pro モデルは
|
|
|
44
44
|
npm レジストリからインストールします。
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
|
-
npm install -g cueline@0.1.
|
|
47
|
+
npm install -g cueline@0.1.3
|
|
48
48
|
cueline install
|
|
49
49
|
cueline doctor
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
フォールバックとして、[v0.1.
|
|
52
|
+
フォールバックとして、[v0.1.3 リリース](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.3) のパッケージ済み tarball をインストールすることもできます。同じリリースに `.sha256` チェックサムも置いてあります。
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.
|
|
55
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.3/cueline-0.1.3.tgz
|
|
56
56
|
cueline install
|
|
57
57
|
cueline doctor
|
|
58
58
|
```
|
|
@@ -89,7 +89,8 @@ import { createCodexIabAdapter, runCueLine } from "cueline";
|
|
|
89
89
|
const result = await runCueLine({
|
|
90
90
|
request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
|
|
91
91
|
browser: createCodexIabAdapter(),
|
|
92
|
-
// 任意:conversationUrl、routingConfig / routingConfigPath、home、cwd、
|
|
92
|
+
// 任意:conversationUrl、routingConfig / routingConfigPath、home、cwd、
|
|
93
|
+
// runTimeoutMs、signal、ジョブごと/既定の期限。
|
|
93
94
|
});
|
|
94
95
|
|
|
95
96
|
if (result.status === "complete") {
|
|
@@ -99,7 +100,7 @@ if (result.status === "complete") {
|
|
|
99
100
|
|
|
100
101
|
Codex のランタイムでは、`cueline api path` が出力する絶対パスのモジュールを import します。それがインストールしたパッケージのビルド済み API です。
|
|
101
102
|
|
|
102
|
-
`startCueLineRun` が明示的な開始点です(`runCueLine` はその別名)。`continueCueLineRun({ runId })` は中断した実行を同じ会話で再開し、新しいアダプターを渡さないかぎり保存済みの会話 URL を再利用します。`loadCueLineRunState(runId)` は永続化された状態を読むだけで、何も駆動しません。すでに `complete`
|
|
103
|
+
`startCueLineRun` が明示的な開始点です(`runCueLine` はその別名)。`continueCueLineRun({ runId })` は中断した実行を同じ会話で再開し、新しいアダプターを渡さないかぎり保存済みの会話 URL を再利用します。`loadCueLineRunState(runId)` は永続化された状態を読むだけで、何も駆動しません。すでに `complete`、`blocked`、または `cancelled` に達した実行はそのまま返され、二度とディスパッチされません。再開前に `cueline run status <run-id> --json` を実行してください。応答が受理済みで phase が `jobs_running` なら、ChatGPT の応答後にローカルジョブを実行中です。
|
|
103
104
|
|
|
104
105
|
## CLI
|
|
105
106
|
|
|
@@ -110,7 +111,7 @@ $ cueline install
|
|
|
110
111
|
CueLine skill installed: /Users/you/.codex/skills/cueline
|
|
111
112
|
|
|
112
113
|
$ cueline doctor
|
|
113
|
-
CueLine 0.1.
|
|
114
|
+
CueLine 0.1.3
|
|
114
115
|
status ok
|
|
115
116
|
node 22.14.0 ok
|
|
116
117
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -126,6 +127,12 @@ default codex-default available
|
|
|
126
127
|
$ cueline jobs
|
|
127
128
|
No jobs.
|
|
128
129
|
|
|
130
|
+
$ cueline run status run_... --json
|
|
131
|
+
{"status":"running","phase":"jobs_running","runtime":{"ownership":"active"},...}
|
|
132
|
+
|
|
133
|
+
$ cueline run cancel run_...
|
|
134
|
+
run_... requested affected_jobs=0
|
|
135
|
+
|
|
129
136
|
$ cueline config path
|
|
130
137
|
/usr/local/lib/node_modules/cueline/config/routing.default.json
|
|
131
138
|
|
|
@@ -145,6 +152,8 @@ Node が古すぎる場合、あるいは解決できるレーンが一つもな
|
|
|
145
152
|
|
|
146
153
|
```text
|
|
147
154
|
runs/<run-id>/events.jsonl 追記のみ、正本
|
|
155
|
+
runs/<run-id>/runtime.json ライブ owner の heartbeat 証拠
|
|
156
|
+
runs/<run-id>/cancel.json 存在する場合は永続キャンセル要求
|
|
148
157
|
runs/<run-id>/snapshot.json リプレイの最適化、破棄可能
|
|
149
158
|
jobs/<job-id>.json ジョブごとの実行証拠
|
|
150
159
|
```
|
package/README.ko.md
CHANGED
|
@@ -44,15 +44,15 @@ ChatGPT Pro 구독과 선택된 Pro 모델은 서로 다른 것입니다. 계정
|
|
|
44
44
|
npm 레지스트리에서 설치합니다:
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
|
-
npm install -g cueline@0.1.
|
|
47
|
+
npm install -g cueline@0.1.3
|
|
48
48
|
cueline install
|
|
49
49
|
cueline doctor
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
대안으로, [v0.1.
|
|
52
|
+
대안으로, [v0.1.3 릴리스](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.3)의 패키지 tarball을 설치할 수도 있습니다. 같은 릴리스에 `.sha256` 체크섬도 함께 있습니다.
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.
|
|
55
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.3/cueline-0.1.3.tgz
|
|
56
56
|
cueline install
|
|
57
57
|
cueline doctor
|
|
58
58
|
```
|
|
@@ -89,7 +89,8 @@ import { createCodexIabAdapter, runCueLine } from "cueline";
|
|
|
89
89
|
const result = await runCueLine({
|
|
90
90
|
request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
|
|
91
91
|
browser: createCodexIabAdapter(),
|
|
92
|
-
// 선택: conversationUrl, routingConfig / routingConfigPath, home, cwd,
|
|
92
|
+
// 선택: conversationUrl, routingConfig / routingConfigPath, home, cwd,
|
|
93
|
+
// runTimeoutMs, signal, 작업별/기본 제한 시간.
|
|
93
94
|
});
|
|
94
95
|
|
|
95
96
|
if (result.status === "complete") {
|
|
@@ -99,7 +100,7 @@ if (result.status === "complete") {
|
|
|
99
100
|
|
|
100
101
|
Codex 런타임에서는 `cueline api path`가 출력하는 절대 경로 모듈을 import하세요. 그것이 설치한 패키지의 빌드된 API입니다.
|
|
101
102
|
|
|
102
|
-
`startCueLineRun`이 명시적인 시작점입니다(`runCueLine`은 그 별칭). `continueCueLineRun({ runId })`은 중단된 실행을 같은 대화에서 재개하며, 새 어댑터를 넘기지 않는 한 저장된 대화 URL을 재사용합니다. `loadCueLineRunState(runId)`는 저장된 상태를 읽기만 하고 아무것도 구동하지 않습니다. 이미 `complete
|
|
103
|
+
`startCueLineRun`이 명시적인 시작점입니다(`runCueLine`은 그 별칭). `continueCueLineRun({ runId })`은 중단된 실행을 같은 대화에서 재개하며, 새 어댑터를 넘기지 않는 한 저장된 대화 URL을 재사용합니다. `loadCueLineRunState(runId)`는 저장된 상태를 읽기만 하고 아무것도 구동하지 않습니다. 이미 `complete`, `blocked`, `cancelled`에 도달한 실행은 그대로 반환되며, 두 번 디스패치되지 않습니다. 재개 전 `cueline run status <run-id> --json`을 실행하십시오. 응답이 수락되었고 phase가 `jobs_running`이면 ChatGPT 응답은 끝났고 로컬 작업이 실행 중입니다.
|
|
103
104
|
|
|
104
105
|
## CLI
|
|
105
106
|
|
|
@@ -110,7 +111,7 @@ $ cueline install
|
|
|
110
111
|
CueLine skill installed: /Users/you/.codex/skills/cueline
|
|
111
112
|
|
|
112
113
|
$ cueline doctor
|
|
113
|
-
CueLine 0.1.
|
|
114
|
+
CueLine 0.1.3
|
|
114
115
|
status ok
|
|
115
116
|
node 22.14.0 ok
|
|
116
117
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -126,6 +127,12 @@ default codex-default available
|
|
|
126
127
|
$ cueline jobs
|
|
127
128
|
No jobs.
|
|
128
129
|
|
|
130
|
+
$ cueline run status run_... --json
|
|
131
|
+
{"status":"running","phase":"jobs_running","runtime":{"ownership":"active"},...}
|
|
132
|
+
|
|
133
|
+
$ cueline run cancel run_...
|
|
134
|
+
run_... requested affected_jobs=0
|
|
135
|
+
|
|
129
136
|
$ cueline config path
|
|
130
137
|
/usr/local/lib/node_modules/cueline/config/routing.default.json
|
|
131
138
|
|
|
@@ -145,6 +152,8 @@ Node 버전이 너무 낮거나 해석 가능한 레인이 하나도 없으면 `
|
|
|
145
152
|
|
|
146
153
|
```text
|
|
147
154
|
runs/<run-id>/events.jsonl 추가 전용, 정본
|
|
155
|
+
runs/<run-id>/runtime.json 활성 owner의 heartbeat 증거
|
|
156
|
+
runs/<run-id>/cancel.json 존재할 때 지속 취소 요청
|
|
148
157
|
runs/<run-id>/snapshot.json 재생 최적화용, 버려도 무방
|
|
149
158
|
jobs/<job-id>.json 작업별 실행 증거
|
|
150
159
|
```
|
package/README.md
CHANGED
|
@@ -44,15 +44,15 @@ You need Node.js 22+, Codex with its built-in Browser, and — for the bundled d
|
|
|
44
44
|
Install from the npm registry:
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
|
-
npm install -g cueline@0.1.
|
|
47
|
+
npm install -g cueline@0.1.3
|
|
48
48
|
cueline install
|
|
49
49
|
cueline doctor
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
As a fallback, install the packaged tarball from the [v0.1.
|
|
52
|
+
As a fallback, install the packaged tarball from the [v0.1.3 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.3), which also carries its `.sha256` checksum:
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.
|
|
55
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.3/cueline-0.1.3.tgz
|
|
56
56
|
cueline install
|
|
57
57
|
cueline doctor
|
|
58
58
|
```
|
|
@@ -89,7 +89,8 @@ import { createCodexIabAdapter, runCueLine } from "cueline";
|
|
|
89
89
|
const result = await runCueLine({
|
|
90
90
|
request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
|
|
91
91
|
browser: createCodexIabAdapter(),
|
|
92
|
-
// Optional: conversationUrl, routingConfig / routingConfigPath, home, cwd,
|
|
92
|
+
// Optional: conversationUrl, routingConfig / routingConfigPath, home, cwd,
|
|
93
|
+
// runTimeoutMs, signal, and per-job/default limits.
|
|
93
94
|
});
|
|
94
95
|
|
|
95
96
|
if (result.status === "complete") {
|
|
@@ -97,7 +98,7 @@ if (result.status === "complete") {
|
|
|
97
98
|
}
|
|
98
99
|
```
|
|
99
100
|
|
|
100
|
-
`startCueLineRun` is the explicit start (`runCueLine` is its alias). `continueCueLineRun({ runId })` resumes an interrupted run in the same conversation, and reuses the stored conversation URL unless you hand it a new adapter. `loadCueLineRunState(runId)` reads persisted state without driving anything. A run that already reached `complete` or `
|
|
101
|
+
`startCueLineRun` is the explicit start (`runCueLine` is its alias). `continueCueLineRun({ runId })` resumes an interrupted run in the same conversation, and reuses the stored conversation URL unless you hand it a new adapter. `loadCueLineRunState(runId)` reads persisted state without driving anything. A run that already reached `complete`, `blocked`, or `cancelled` is returned as-is, never dispatched twice. Before continuation, run `cueline run status <run-id> --json`: an accepted response plus `jobs_running` means ChatGPT already answered and local jobs are executing.
|
|
101
102
|
|
|
102
103
|
Inside Codex's runtime, import the absolute module that `cueline api path` prints — that is the built API of the package you installed.
|
|
103
104
|
|
|
@@ -110,7 +111,7 @@ $ cueline install
|
|
|
110
111
|
CueLine skill installed: /Users/you/.codex/skills/cueline
|
|
111
112
|
|
|
112
113
|
$ cueline doctor
|
|
113
|
-
CueLine 0.1.
|
|
114
|
+
CueLine 0.1.3
|
|
114
115
|
status ok
|
|
115
116
|
node 22.14.0 ok
|
|
116
117
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -126,6 +127,12 @@ default codex-default available
|
|
|
126
127
|
$ cueline jobs
|
|
127
128
|
No jobs.
|
|
128
129
|
|
|
130
|
+
$ cueline run status run_... --json
|
|
131
|
+
{"status":"running","phase":"jobs_running","runtime":{"ownership":"active"},...}
|
|
132
|
+
|
|
133
|
+
$ cueline run cancel run_...
|
|
134
|
+
run_... requested affected_jobs=0
|
|
135
|
+
|
|
129
136
|
$ cueline config path
|
|
130
137
|
/usr/local/lib/node_modules/cueline/config/routing.default.json
|
|
131
138
|
|
|
@@ -145,6 +152,8 @@ State lives under `CUELINE_HOME`:
|
|
|
145
152
|
|
|
146
153
|
```text
|
|
147
154
|
runs/<run-id>/events.jsonl append-only, authoritative
|
|
155
|
+
runs/<run-id>/runtime.json live-owner heartbeat evidence
|
|
156
|
+
runs/<run-id>/cancel.json durable cancellation request, when present
|
|
148
157
|
runs/<run-id>/snapshot.json a replay optimization, disposable
|
|
149
158
|
jobs/<job-id>.json per-job execution evidence
|
|
150
159
|
```
|
package/README.zh-CN.md
CHANGED
|
@@ -44,15 +44,15 @@ ChatGPT Pro 订阅套餐与“选定的 Pro 模型”是两回事。账号或个
|
|
|
44
44
|
从 npm registry 安装:
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
|
-
npm install -g cueline@0.1.
|
|
47
|
+
npm install -g cueline@0.1.3
|
|
48
48
|
cueline install
|
|
49
49
|
cueline doctor
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
作为后备,也可以安装 [v0.1.
|
|
52
|
+
作为后备,也可以安装 [v0.1.3 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.3) 上的打包 tarball,该 release 同时附带它的 `.sha256` 校验值:
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.
|
|
55
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.3/cueline-0.1.3.tgz
|
|
56
56
|
cueline install
|
|
57
57
|
cueline doctor
|
|
58
58
|
```
|
|
@@ -89,7 +89,8 @@ import { createCodexIabAdapter, runCueLine } from "cueline";
|
|
|
89
89
|
const result = await runCueLine({
|
|
90
90
|
request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
|
|
91
91
|
browser: createCodexIabAdapter(),
|
|
92
|
-
// 可选:conversationUrl、routingConfig / routingConfigPath、home、cwd、
|
|
92
|
+
// 可选:conversationUrl、routingConfig / routingConfigPath、home、cwd、
|
|
93
|
+
// runTimeoutMs、signal,以及作业/默认期限。
|
|
93
94
|
});
|
|
94
95
|
|
|
95
96
|
if (result.status === "complete") {
|
|
@@ -99,7 +100,7 @@ if (result.status === "complete") {
|
|
|
99
100
|
|
|
100
101
|
在 Codex 的 runtime 里,import `cueline api path` 打印出的那个绝对路径模块——那就是你安装的那份包构建出来的 API。
|
|
101
102
|
|
|
102
|
-
`startCueLineRun` 是显式的启动入口(`runCueLine` 是它的别名)。`continueCueLineRun({ runId })` 会在同一个会话中续跑被中断的运行,并复用已保存的会话链接,除非你传入新的 adapter。`loadCueLineRunState(runId)` 只读取已持久化的状态,不驱动任何东西。已经到达 `complete` 或 `
|
|
103
|
+
`startCueLineRun` 是显式的启动入口(`runCueLine` 是它的别名)。`continueCueLineRun({ runId })` 会在同一个会话中续跑被中断的运行,并复用已保存的会话链接,除非你传入新的 adapter。`loadCueLineRunState(runId)` 只读取已持久化的状态,不驱动任何东西。已经到达 `complete`、`blocked` 或 `cancelled` 的运行会原样返回,绝不会被再次派发。续跑前先执行 `cueline run status <run-id> --json`;已接受回复且 phase 为 `jobs_running` 表示 ChatGPT 已回复,本地作业正在执行。
|
|
103
104
|
|
|
104
105
|
## CLI
|
|
105
106
|
|
|
@@ -110,7 +111,7 @@ $ cueline install
|
|
|
110
111
|
CueLine skill installed: /Users/you/.codex/skills/cueline
|
|
111
112
|
|
|
112
113
|
$ cueline doctor
|
|
113
|
-
CueLine 0.1.
|
|
114
|
+
CueLine 0.1.3
|
|
114
115
|
status ok
|
|
115
116
|
node 22.14.0 ok
|
|
116
117
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -126,6 +127,12 @@ default codex-default available
|
|
|
126
127
|
$ cueline jobs
|
|
127
128
|
No jobs.
|
|
128
129
|
|
|
130
|
+
$ cueline run status run_... --json
|
|
131
|
+
{"status":"running","phase":"jobs_running","runtime":{"ownership":"active"},...}
|
|
132
|
+
|
|
133
|
+
$ cueline run cancel run_...
|
|
134
|
+
run_... requested affected_jobs=0
|
|
135
|
+
|
|
129
136
|
$ cueline config path
|
|
130
137
|
/usr/local/lib/node_modules/cueline/config/routing.default.json
|
|
131
138
|
|
|
@@ -145,6 +152,8 @@ CueLine skill removed: /Users/you/.codex/skills/cueline
|
|
|
145
152
|
|
|
146
153
|
```text
|
|
147
154
|
runs/<run-id>/events.jsonl 仅追加、具权威性
|
|
155
|
+
runs/<run-id>/runtime.json 活跃 owner 的 heartbeat 证据
|
|
156
|
+
runs/<run-id>/cancel.json 存在时表示持久取消请求
|
|
148
157
|
runs/<run-id>/snapshot.json 重放优化产物,可丢弃
|
|
149
158
|
jobs/<job-id>.json 每个作业的执行证据
|
|
150
159
|
```
|
package/README.zh-TW.md
CHANGED
|
@@ -44,15 +44,15 @@ ChatGPT Pro 訂閱方案與「選定的 Pro 模型」是兩回事。帳號或個
|
|
|
44
44
|
從 npm registry 安裝:
|
|
45
45
|
|
|
46
46
|
```bash
|
|
47
|
-
npm install -g cueline@0.1.
|
|
47
|
+
npm install -g cueline@0.1.3
|
|
48
48
|
cueline install
|
|
49
49
|
cueline doctor
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
作為備援,也可以安裝 [v0.1.
|
|
52
|
+
作為備援,也可以安裝 [v0.1.3 release](https://github.com/Seraphim0916/cueline/releases/tag/v0.1.3) 上的打包 tarball,該 release 同時附上它的 `.sha256` 校驗碼:
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.
|
|
55
|
+
npm install -g https://github.com/Seraphim0916/cueline/releases/download/v0.1.3/cueline-0.1.3.tgz
|
|
56
56
|
cueline install
|
|
57
57
|
cueline doctor
|
|
58
58
|
```
|
|
@@ -89,7 +89,8 @@ import { createCodexIabAdapter, runCueLine } from "cueline";
|
|
|
89
89
|
const result = await runCueLine({
|
|
90
90
|
request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
|
|
91
91
|
browser: createCodexIabAdapter(),
|
|
92
|
-
// 選填:conversationUrl、routingConfig / routingConfigPath、home、cwd、
|
|
92
|
+
// 選填:conversationUrl、routingConfig / routingConfigPath、home、cwd、
|
|
93
|
+
// runTimeoutMs、signal,以及各工作/預設期限。
|
|
93
94
|
});
|
|
94
95
|
|
|
95
96
|
if (result.status === "complete") {
|
|
@@ -99,7 +100,7 @@ if (result.status === "complete") {
|
|
|
99
100
|
|
|
100
101
|
在 Codex 的 runtime 裡,import `cueline api path` 印出的那個絕對路徑模組——那就是你安裝的那份套件建置出來的 API。
|
|
101
102
|
|
|
102
|
-
`startCueLineRun` 是明確的啟動入口(`runCueLine` 是它的別名)。`continueCueLineRun({ runId })` 會在同一個對話裡續跑被中斷的執行,並沿用已保存的對話網址,除非你另外傳入新的 adapter。`loadCueLineRunState(runId)` 只讀取已保存的狀態,不驅動任何東西。已經走到 `complete` 或 `
|
|
103
|
+
`startCueLineRun` 是明確的啟動入口(`runCueLine` 是它的別名)。`continueCueLineRun({ runId })` 會在同一個對話裡續跑被中斷的執行,並沿用已保存的對話網址,除非你另外傳入新的 adapter。`loadCueLineRunState(runId)` 只讀取已保存的狀態,不驅動任何東西。已經走到 `complete`、`blocked` 或 `cancelled` 的執行會原樣回傳,絕不會被再派工一次。續跑前先執行 `cueline run status <run-id> --json`;若回覆已採用且 phase 是 `jobs_running`,代表 ChatGPT 已回覆,現在跑的是本機工作。
|
|
103
104
|
|
|
104
105
|
## CLI
|
|
105
106
|
|
|
@@ -110,7 +111,7 @@ $ cueline install
|
|
|
110
111
|
CueLine skill installed: /Users/you/.codex/skills/cueline
|
|
111
112
|
|
|
112
113
|
$ cueline doctor
|
|
113
|
-
CueLine 0.1.
|
|
114
|
+
CueLine 0.1.3
|
|
114
115
|
status ok
|
|
115
116
|
node 22.14.0 ok
|
|
116
117
|
config /usr/local/lib/node_modules/cueline/config/routing.default.json valid
|
|
@@ -126,6 +127,12 @@ default codex-default available
|
|
|
126
127
|
$ cueline jobs
|
|
127
128
|
No jobs.
|
|
128
129
|
|
|
130
|
+
$ cueline run status run_... --json
|
|
131
|
+
{"status":"running","phase":"jobs_running","runtime":{"ownership":"active"},...}
|
|
132
|
+
|
|
133
|
+
$ cueline run cancel run_...
|
|
134
|
+
run_... requested affected_jobs=0
|
|
135
|
+
|
|
129
136
|
$ cueline config path
|
|
130
137
|
/usr/local/lib/node_modules/cueline/config/routing.default.json
|
|
131
138
|
|
|
@@ -145,6 +152,8 @@ Node 版本太舊、或沒有任何通道解析得出來時,`cueline doctor`
|
|
|
145
152
|
|
|
146
153
|
```text
|
|
147
154
|
runs/<run-id>/events.jsonl 只追加、具權威性
|
|
155
|
+
runs/<run-id>/runtime.json 活 owner 的 heartbeat 證據
|
|
156
|
+
runs/<run-id>/cancel.json 存在時代表持久取消要求
|
|
148
157
|
runs/<run-id>/snapshot.json 重播的最佳化產物,可丟棄
|
|
149
158
|
jobs/<job-id>.json 每個工作的執行證據
|
|
150
159
|
```
|
package/dist/src/api.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { BrowserAdapter } from "./browser/browser-adapter.js";
|
|
2
2
|
import { createCodexIabAdapter, type CodexIabAdapterOptions } from "./browser/codex-iab/chatgpt-client.js";
|
|
3
3
|
import { type CueLineResult } from "./core/controller-loop.js";
|
|
4
|
+
import { type CueLineRunStatusSummary } from "./core/run-status.js";
|
|
4
5
|
import { type CueLineRunState } from "./core/state-machine.js";
|
|
5
6
|
import type { RoutingConfig } from "./router/types.js";
|
|
6
7
|
export interface CueLineRuntimeOptions {
|
|
@@ -16,6 +17,9 @@ export interface CueLineRuntimeOptions {
|
|
|
16
17
|
maxRounds?: number;
|
|
17
18
|
maxRepairAttempts?: number;
|
|
18
19
|
now?: () => Date;
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
cancellationPollIntervalMs?: number;
|
|
22
|
+
runTimeoutMs?: number;
|
|
19
23
|
}
|
|
20
24
|
export interface StartCueLineRunOptions extends CueLineRuntimeOptions {
|
|
21
25
|
request: string;
|
|
@@ -26,11 +30,29 @@ export interface ContinueCueLineRunOptions extends CueLineRuntimeOptions {
|
|
|
26
30
|
reconcileRequestId?: string;
|
|
27
31
|
abandonOtherPendingTurns?: boolean;
|
|
28
32
|
}
|
|
33
|
+
export interface CueLineRunCancellationResult {
|
|
34
|
+
runId: string;
|
|
35
|
+
outcome: "requested" | "cancelled" | "already_terminal";
|
|
36
|
+
affectedJobs: number;
|
|
37
|
+
}
|
|
38
|
+
export interface CueLineJobCancellationResult {
|
|
39
|
+
runId: string;
|
|
40
|
+
jobId: string;
|
|
41
|
+
outcome: "requested" | "ambiguous" | "already_terminal";
|
|
42
|
+
}
|
|
29
43
|
export declare function defaultRoutingConfigPath(): string;
|
|
30
44
|
export declare function routingConfigPath(environment?: NodeJS.ProcessEnv, explicitPath?: string): string;
|
|
31
45
|
export declare function loadCueLineRunState(runId: string, options?: Pick<CueLineRuntimeOptions, "home" | "environment">): Promise<CueLineRunState>;
|
|
46
|
+
export declare function loadCueLineRunStatus(runId: string, options?: Pick<CueLineRuntimeOptions, "home" | "environment" | "now">): Promise<CueLineRunStatusSummary>;
|
|
47
|
+
export declare function cancelCueLineRun(runId: string, options?: Pick<CueLineRuntimeOptions, "home" | "environment" | "now"> & {
|
|
48
|
+
reason?: string;
|
|
49
|
+
}): Promise<CueLineRunCancellationResult>;
|
|
50
|
+
export declare function cancelCueLineJob(runId: string, jobId: string, options?: Pick<CueLineRuntimeOptions, "home" | "environment" | "now"> & {
|
|
51
|
+
reason?: string;
|
|
52
|
+
}): Promise<CueLineJobCancellationResult>;
|
|
32
53
|
export declare function startCueLineRun(options: StartCueLineRunOptions): Promise<CueLineResult>;
|
|
33
54
|
export declare function runCueLine(options: StartCueLineRunOptions): Promise<CueLineResult>;
|
|
34
55
|
export declare function continueCueLineRun(options: ContinueCueLineRunOptions): Promise<CueLineResult>;
|
|
35
56
|
export { createCodexIabAdapter };
|
|
36
|
-
export
|
|
57
|
+
export { CUELINE_VERSION } from "./version.js";
|
|
58
|
+
export type { BrowserAdapter, CueLineResult, CueLineRunState, CueLineRunStatusSummary, RoutingConfig, };
|
package/dist/src/api.js
CHANGED
|
@@ -3,6 +3,7 @@ import { createCodexIabAdapter, } from "./browser/codex-iab/chatgpt-client.js";
|
|
|
3
3
|
import { continueControllerLoop, runControllerLoop, } from "./core/controller-loop.js";
|
|
4
4
|
import { CueLineError } from "./core/errors.js";
|
|
5
5
|
import { runtimeCwd, runtimeEnvironment } from "./core/runtime.js";
|
|
6
|
+
import { acceptedControllerCommandEvidence, assertRunCanContinue, summarizeCueLineRunState, } from "./core/run-status.js";
|
|
6
7
|
import { initialRunState, reduceRunState, } from "./core/state-machine.js";
|
|
7
8
|
import { JobStatusStore } from "./jobs/status.js";
|
|
8
9
|
import { JobSupervisor } from "./jobs/supervisor.js";
|
|
@@ -12,7 +13,10 @@ import { materializeRunnerSpec } from "./router/materialize.js";
|
|
|
12
13
|
import { resolveRoute } from "./router/resolver.js";
|
|
13
14
|
import { ProcessRunner } from "./runners/process-runner.js";
|
|
14
15
|
import { RunnerRegistry } from "./runners/registry.js";
|
|
15
|
-
import {
|
|
16
|
+
import { readCancellationObservation, requestJobCancellation, requestRunCancellation, } from "./state/cancellation.js";
|
|
17
|
+
import { readEvents } from "./state/event-log.js";
|
|
18
|
+
import { defaultCueLineHome, runPaths } from "./state/paths.js";
|
|
19
|
+
import { readRuntimeLease } from "./state/runtime-lease.js";
|
|
16
20
|
import { RunStore } from "./state/store.js";
|
|
17
21
|
function assertNotNested(environment) {
|
|
18
22
|
if (environment.CUELINE_DEPTH !== undefined) {
|
|
@@ -25,7 +29,7 @@ export function defaultRoutingConfigPath() {
|
|
|
25
29
|
export function routingConfigPath(environment = runtimeEnvironment(), explicitPath) {
|
|
26
30
|
return explicitPath ?? environment.CUELINE_CONFIG ?? defaultRoutingConfigPath();
|
|
27
31
|
}
|
|
28
|
-
async function
|
|
32
|
+
async function persistedRunStore(home, runId) {
|
|
29
33
|
const store = await RunStore.load({
|
|
30
34
|
home,
|
|
31
35
|
runId,
|
|
@@ -36,10 +40,15 @@ async function persistedRunState(home, runId) {
|
|
|
36
40
|
if (state.request === "") {
|
|
37
41
|
throw new CueLineError("RUN_NOT_FOUND", `No persisted CueLine run '${runId}' was found.`);
|
|
38
42
|
}
|
|
39
|
-
return
|
|
43
|
+
return store;
|
|
44
|
+
}
|
|
45
|
+
async function persistedRunState(home, runId) {
|
|
46
|
+
return (await persistedRunStore(home, runId)).state;
|
|
40
47
|
}
|
|
41
48
|
function terminalResult(state) {
|
|
42
|
-
if (state.status !== "complete" &&
|
|
49
|
+
if (state.status !== "complete" &&
|
|
50
|
+
state.status !== "blocked" &&
|
|
51
|
+
state.status !== "cancelled") {
|
|
43
52
|
throw new CueLineError("RUN_NOT_TERMINAL", "CueLine result requested before a terminal state.");
|
|
44
53
|
}
|
|
45
54
|
return {
|
|
@@ -47,6 +56,7 @@ function terminalResult(state) {
|
|
|
47
56
|
status: state.status,
|
|
48
57
|
...(state.finalDeliveryText === null ? {} : { finalDeliveryText: state.finalDeliveryText }),
|
|
49
58
|
...(state.conversationUrl === null ? {} : { conversationUrl: state.conversationUrl }),
|
|
59
|
+
...(state.cancelledReason === null ? {} : { cancelledReason: state.cancelledReason }),
|
|
50
60
|
state,
|
|
51
61
|
};
|
|
52
62
|
}
|
|
@@ -54,6 +64,86 @@ export async function loadCueLineRunState(runId, options = {}) {
|
|
|
54
64
|
const environment = options.environment ?? runtimeEnvironment();
|
|
55
65
|
return persistedRunState(options.home ?? defaultCueLineHome(environment), runId);
|
|
56
66
|
}
|
|
67
|
+
export async function loadCueLineRunStatus(runId, options = {}) {
|
|
68
|
+
const environment = options.environment ?? runtimeEnvironment();
|
|
69
|
+
const home = options.home ?? defaultCueLineHome(environment);
|
|
70
|
+
const store = await persistedRunStore(home, runId);
|
|
71
|
+
const runtime = await readRuntimeLease(home, runId, {
|
|
72
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
73
|
+
});
|
|
74
|
+
const cancellation = await readCancellationObservation(home, runId);
|
|
75
|
+
const acceptedCommand = acceptedControllerCommandEvidence(await readEvents(runPaths(home, runId).events));
|
|
76
|
+
return summarizeCueLineRunState(store.state, store.lastSequence, runtime, cancellation, acceptedCommand);
|
|
77
|
+
}
|
|
78
|
+
function isTerminalRun(state) {
|
|
79
|
+
return (state.status === "complete" || state.status === "blocked" || state.status === "cancelled");
|
|
80
|
+
}
|
|
81
|
+
export async function cancelCueLineRun(runId, options = {}) {
|
|
82
|
+
const environment = options.environment ?? runtimeEnvironment();
|
|
83
|
+
const home = options.home ?? defaultCueLineHome(environment);
|
|
84
|
+
const store = await persistedRunStore(home, runId);
|
|
85
|
+
if (isTerminalRun(store.state)) {
|
|
86
|
+
return { runId, outcome: "already_terminal", affectedJobs: 0 };
|
|
87
|
+
}
|
|
88
|
+
const reason = options.reason ?? "operator requested cancellation";
|
|
89
|
+
await requestRunCancellation(home, runId, reason, options.now);
|
|
90
|
+
const runtime = await readRuntimeLease(home, runId, {
|
|
91
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
92
|
+
});
|
|
93
|
+
if (runtime.ownership === "active" ||
|
|
94
|
+
runtime.ownership === "stale" ||
|
|
95
|
+
runtime.ownership === "invalid") {
|
|
96
|
+
return { runId, outcome: "requested", affectedJobs: 0 };
|
|
97
|
+
}
|
|
98
|
+
const active = Object.values(store.state.jobs).filter((job) => job.status === "pending" || job.status === "running");
|
|
99
|
+
for (const job of active) {
|
|
100
|
+
await store.append("job_status", {
|
|
101
|
+
job_id: job.jobId,
|
|
102
|
+
status: "ambiguous",
|
|
103
|
+
error: "Run cancelled without a verifiable active runtime; process outcome is unknown.",
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
await store.append("run_cancelled", { reason });
|
|
107
|
+
await store.snapshot();
|
|
108
|
+
return { runId, outcome: "cancelled", affectedJobs: active.length };
|
|
109
|
+
}
|
|
110
|
+
export async function cancelCueLineJob(runId, jobId, options = {}) {
|
|
111
|
+
const environment = options.environment ?? runtimeEnvironment();
|
|
112
|
+
const home = options.home ?? defaultCueLineHome(environment);
|
|
113
|
+
const store = await persistedRunStore(home, runId);
|
|
114
|
+
const job = store.state.jobs[jobId];
|
|
115
|
+
if (job === undefined) {
|
|
116
|
+
throw new CueLineError("JOB_NOT_FOUND", `No job '${jobId}' exists in run '${runId}'.`);
|
|
117
|
+
}
|
|
118
|
+
if (isTerminalRun(store.state) ||
|
|
119
|
+
(job.status !== "pending" && job.status !== "running")) {
|
|
120
|
+
return { runId, jobId, outcome: "already_terminal" };
|
|
121
|
+
}
|
|
122
|
+
const reason = options.reason ?? "operator requested job cancellation";
|
|
123
|
+
await requestJobCancellation(home, runId, jobId, reason, options.now);
|
|
124
|
+
const runtime = await readRuntimeLease(home, runId, {
|
|
125
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
126
|
+
});
|
|
127
|
+
if (runtime.ownership === "active" ||
|
|
128
|
+
runtime.ownership === "stale" ||
|
|
129
|
+
runtime.ownership === "invalid") {
|
|
130
|
+
return { runId, jobId, outcome: "requested" };
|
|
131
|
+
}
|
|
132
|
+
await store.append("job_status", {
|
|
133
|
+
job_id: jobId,
|
|
134
|
+
status: "ambiguous",
|
|
135
|
+
error: "Job cancelled without a verifiable active runtime; process outcome is unknown.",
|
|
136
|
+
});
|
|
137
|
+
if (store.state.status === "running") {
|
|
138
|
+
await store.append("run_failed", {
|
|
139
|
+
code: "JOB_CANCELLED_WITHOUT_ACTIVE_RUNTIME",
|
|
140
|
+
message: `Job '${jobId}' was marked ambiguous because no active owner could confirm termination.`,
|
|
141
|
+
stage: "job_cancellation",
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
await store.snapshot();
|
|
145
|
+
return { runId, jobId, outcome: "ambiguous" };
|
|
146
|
+
}
|
|
57
147
|
async function resolvedRoutingConfig(options, environment) {
|
|
58
148
|
return (options.routingConfig ??
|
|
59
149
|
(await loadRoutingConfig(routingConfigPath(environment, options.routingConfigPath))));
|
|
@@ -78,7 +168,7 @@ function routingInstruction(config, availability) {
|
|
|
78
168
|
.map((candidate) => candidate.id);
|
|
79
169
|
return `${name} [${candidates.length > 0 ? candidates.join(", ") : "unavailable"}]`;
|
|
80
170
|
});
|
|
81
|
-
return `Available routing lanes: ${lanes.join("; ")}. Use only a listed
|
|
171
|
+
return `Available routing lanes: ${lanes.join("; ")}. Use only a listed lane. Select an optional candidate with the field runner; never use runner_id or place a runner ID in lane.`;
|
|
82
172
|
}
|
|
83
173
|
async function prepareRuntime(options, persistedConversationUrl) {
|
|
84
174
|
const environment = options.environment ?? runtimeEnvironment();
|
|
@@ -126,6 +216,11 @@ export async function startCueLineRun(options) {
|
|
|
126
216
|
? {}
|
|
127
217
|
: { maxRepairAttempts: options.maxRepairAttempts }),
|
|
128
218
|
...(options.now === undefined ? {} : { now: options.now }),
|
|
219
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
220
|
+
...(options.cancellationPollIntervalMs === undefined
|
|
221
|
+
? {}
|
|
222
|
+
: { cancellationPollIntervalMs: options.cancellationPollIntervalMs }),
|
|
223
|
+
...(options.runTimeoutMs === undefined ? {} : { runTimeoutMs: options.runTimeoutMs }),
|
|
129
224
|
});
|
|
130
225
|
}
|
|
131
226
|
export async function runCueLine(options) {
|
|
@@ -135,9 +230,12 @@ export async function continueCueLineRun(options) {
|
|
|
135
230
|
const environment = options.environment ?? runtimeEnvironment();
|
|
136
231
|
const home = options.home ?? defaultCueLineHome(environment);
|
|
137
232
|
const state = await persistedRunState(home, options.runId);
|
|
138
|
-
if (state
|
|
233
|
+
if (isTerminalRun(state)) {
|
|
139
234
|
return terminalResult(state);
|
|
140
235
|
}
|
|
236
|
+
assertRunCanContinue(state, await readRuntimeLease(home, options.runId, {
|
|
237
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
238
|
+
}), await readCancellationObservation(home, options.runId));
|
|
141
239
|
assertNotNested(environment);
|
|
142
240
|
const runtime = await prepareRuntime(options, state.conversationUrl ?? undefined);
|
|
143
241
|
return continueControllerLoop({
|
|
@@ -154,7 +252,13 @@ export async function continueCueLineRun(options) {
|
|
|
154
252
|
? {}
|
|
155
253
|
: { maxRepairAttempts: options.maxRepairAttempts }),
|
|
156
254
|
...(options.now === undefined ? {} : { now: options.now }),
|
|
255
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
256
|
+
...(options.cancellationPollIntervalMs === undefined
|
|
257
|
+
? {}
|
|
258
|
+
: { cancellationPollIntervalMs: options.cancellationPollIntervalMs }),
|
|
259
|
+
...(options.runTimeoutMs === undefined ? {} : { runTimeoutMs: options.runTimeoutMs }),
|
|
157
260
|
});
|
|
158
261
|
}
|
|
159
262
|
export { createCodexIabAdapter };
|
|
263
|
+
export { CUELINE_VERSION } from "./version.js";
|
|
160
264
|
//# sourceMappingURL=api.js.map
|