cueline 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +8 -0
- package/.codex-plugin/plugin.json +18 -0
- package/LICENSE +21 -0
- package/README.ja.md +144 -0
- package/README.ko.md +144 -0
- package/README.md +144 -0
- package/README.zh-CN.md +144 -0
- package/README.zh-TW.md +144 -0
- package/THIRD_PARTY_NOTICES.md +11 -0
- package/bin/cueline +14 -0
- package/config/routing.default.json +28 -0
- package/config/routing.schema.json +58 -0
- package/dist/src/api.d.ts +34 -0
- package/dist/src/api.js +153 -0
- package/dist/src/api.js.map +1 -0
- package/dist/src/browser/browser-adapter.d.ts +15 -0
- package/dist/src/browser/browser-adapter.js +2 -0
- package/dist/src/browser/browser-adapter.js.map +1 -0
- package/dist/src/browser/codex-iab/bootstrap.d.ts +66 -0
- package/dist/src/browser/codex-iab/bootstrap.js +41 -0
- package/dist/src/browser/codex-iab/bootstrap.js.map +1 -0
- package/dist/src/browser/codex-iab/chatgpt-client.d.ts +10 -0
- package/dist/src/browser/codex-iab/chatgpt-client.js +180 -0
- package/dist/src/browser/codex-iab/chatgpt-client.js.map +1 -0
- package/dist/src/browser/codex-iab/selectors.d.ts +3 -0
- package/dist/src/browser/codex-iab/selectors.js +17 -0
- package/dist/src/browser/codex-iab/selectors.js.map +1 -0
- package/dist/src/cli/main.d.ts +7 -0
- package/dist/src/cli/main.js +196 -0
- package/dist/src/cli/main.js.map +1 -0
- package/dist/src/cli/skill-links.d.ts +2 -0
- package/dist/src/cli/skill-links.js +64 -0
- package/dist/src/cli/skill-links.js.map +1 -0
- package/dist/src/core/controller-loop.d.ts +36 -0
- package/dist/src/core/controller-loop.js +292 -0
- package/dist/src/core/controller-loop.js.map +1 -0
- package/dist/src/core/errors.d.ts +10 -0
- package/dist/src/core/errors.js +18 -0
- package/dist/src/core/errors.js.map +1 -0
- package/dist/src/core/ids.d.ts +5 -0
- package/dist/src/core/ids.js +51 -0
- package/dist/src/core/ids.js.map +1 -0
- package/dist/src/core/runtime.d.ts +12 -0
- package/dist/src/core/runtime.js +35 -0
- package/dist/src/core/runtime.js.map +1 -0
- package/dist/src/core/state-machine.d.ts +28 -0
- package/dist/src/core/state-machine.js +99 -0
- package/dist/src/core/state-machine.js.map +1 -0
- package/dist/src/jobs/locks.d.ts +8 -0
- package/dist/src/jobs/locks.js +24 -0
- package/dist/src/jobs/locks.js.map +1 -0
- package/dist/src/jobs/status.d.ts +22 -0
- package/dist/src/jobs/status.js +53 -0
- package/dist/src/jobs/status.js.map +1 -0
- package/dist/src/jobs/supervisor.d.ts +22 -0
- package/dist/src/jobs/supervisor.js +96 -0
- package/dist/src/jobs/supervisor.js.map +1 -0
- package/dist/src/protocol/parse-command.d.ts +2 -0
- package/dist/src/protocol/parse-command.js +23 -0
- package/dist/src/protocol/parse-command.js.map +1 -0
- package/dist/src/protocol/types.d.ts +67 -0
- package/dist/src/protocol/types.js +2 -0
- package/dist/src/protocol/types.js.map +1 -0
- package/dist/src/protocol/validate-command.d.ts +2 -0
- package/dist/src/protocol/validate-command.js +181 -0
- package/dist/src/protocol/validate-command.js.map +1 -0
- package/dist/src/router/availability.d.ts +3 -0
- package/dist/src/router/availability.js +55 -0
- package/dist/src/router/availability.js.map +1 -0
- package/dist/src/router/config-loader.d.ts +3 -0
- package/dist/src/router/config-loader.js +92 -0
- package/dist/src/router/config-loader.js.map +1 -0
- package/dist/src/router/materialize.d.ts +8 -0
- package/dist/src/router/materialize.js +39 -0
- package/dist/src/router/materialize.js.map +1 -0
- package/dist/src/router/resolver.d.ts +6 -0
- package/dist/src/router/resolver.js +55 -0
- package/dist/src/router/resolver.js.map +1 -0
- package/dist/src/router/types.d.ts +24 -0
- package/dist/src/router/types.js +2 -0
- package/dist/src/router/types.js.map +1 -0
- package/dist/src/runners/process-runner.d.ts +15 -0
- package/dist/src/runners/process-runner.js +124 -0
- package/dist/src/runners/process-runner.js.map +1 -0
- package/dist/src/runners/registry.d.ts +17 -0
- package/dist/src/runners/registry.js +57 -0
- package/dist/src/runners/registry.js.map +1 -0
- package/dist/src/runners/runner-adapter.d.ts +32 -0
- package/dist/src/runners/runner-adapter.js +4 -0
- package/dist/src/runners/runner-adapter.js.map +1 -0
- package/dist/src/state/atomic-write.d.ts +1 -0
- package/dist/src/state/atomic-write.js +27 -0
- package/dist/src/state/atomic-write.js.map +1 -0
- package/dist/src/state/event-log.d.ts +8 -0
- package/dist/src/state/event-log.js +56 -0
- package/dist/src/state/event-log.js.map +1 -0
- package/dist/src/state/paths.d.ts +9 -0
- package/dist/src/state/paths.js +37 -0
- package/dist/src/state/paths.js.map +1 -0
- package/dist/src/state/store.d.ts +23 -0
- package/dist/src/state/store.js +108 -0
- package/dist/src/state/store.js.map +1 -0
- package/dist/src/version.d.ts +1 -0
- package/dist/src/version.js +2 -0
- package/dist/src/version.js.map +1 -0
- package/docs/architecture.md +83 -0
- package/docs/assets/README.md +51 -0
- package/docs/assets/cueline-banner-dark.svg +41 -0
- package/docs/assets/cueline-banner-light.svg +41 -0
- package/docs/assets/cueline-loop-en.svg +77 -0
- package/docs/assets/cueline-loop-ja.svg +77 -0
- package/docs/assets/cueline-loop-ko.svg +77 -0
- package/docs/assets/cueline-loop-zh-CN.svg +77 -0
- package/docs/assets/cueline-loop-zh-TW.svg +77 -0
- package/docs/assets/cueline-mark-dark.svg +10 -0
- package/docs/assets/cueline-mark-light.svg +10 -0
- package/docs/assets/cueline-wordmark-dark.svg +19 -0
- package/docs/assets/cueline-wordmark-light.svg +19 -0
- package/docs/compatibility.md +60 -0
- package/docs/controller-protocol.md +106 -0
- package/docs/provenance.md +10 -0
- package/docs/runner-contract.md +61 -0
- package/docs/state-and-recovery.md +67 -0
- package/evals/evals.json +41 -0
- package/install.sh +70 -0
- package/package.json +73 -0
- package/schemas/controller-command.schema.json +53 -0
- package/schemas/controller-observation.schema.json +32 -0
- package/skills/cueline/SKILL.md +80 -0
- package/skills/cueline/agents/openai.yaml +4 -0
package/README.zh-TW.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
<picture>
|
|
2
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/cueline-banner-dark.svg">
|
|
3
|
+
<img alt="CueLine — ChatGPT 下指令,你的機器執行。" src="docs/assets/cueline-banner-light.svg" width="100%">
|
|
4
|
+
</picture>
|
|
5
|
+
|
|
6
|
+
<p align="center">
|
|
7
|
+
<a href="https://github.com/Seraphim0916/cueline/actions/workflows/ci.yml"><img alt="ci" src="https://github.com/Seraphim0916/cueline/actions/workflows/ci.yml/badge.svg"></a>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
<a href="README.md">English</a> · <b>繁體中文</b> · <a href="README.zh-CN.md">简体中文</a> · <a href="README.ja.md">日本語</a> · <a href="README.ko.md">한국어</a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
**CueLine 把方向盤交給一個已經開著的 ChatGPT 網頁對話:由它規劃整趟執行、喊出每一步;而 CueLine 負責檢查每一道指令,並在你這台機器上把事情真的做完。**
|
|
15
|
+
|
|
16
|
+
那個網頁碰不到你的機器。它每一輪只吐出一小段文字指令。CueLine 判斷這道指令格式對不對、屬不屬於這次執行、對應到哪個本機工作行程(worker)——然後才執行它、保留證據,再把證據交回去。
|
|
17
|
+
|
|
18
|
+
CueLine 是獨立實作,**沒有任何 runtime npm 相依套件**,也不是 Omnilane 或 GPT Relay 的包裝層。
|
|
19
|
+
|
|
20
|
+
## 一次執行實際上怎麼跑
|
|
21
|
+
|
|
22
|
+
<img alt="一次 CueLine 執行像一本提示本:機器送出觀測,主控端喊出一道指令,已註冊的 runner 執行它,直到主控端喊 complete。" src="docs/assets/cueline-loop-zh-TW.svg" width="100%">
|
|
23
|
+
|
|
24
|
+
每一輪:CueLine 先把自己「即將問什麼」寫進紀錄,送出一份觀測(observation)到對話裡,再讀回**恰好一個** `<CueLineControl>` 封包。主控端從五個動作裡挑一個——`dispatch`、`wait`、`inspect`、`complete`、`blocked`——封包以外的任何文字都不會被執行。指令若寫錯 run、寫錯輪次,或工作定義有問題,會被退回去做有次數上限的修正,而不是靠猜。迴圈停在 `complete` 或 `blocked`,或是輪數用完(預設 12 輪)。
|
|
25
|
+
|
|
26
|
+
主控端決定*該發生什麼*;本機這一側決定*能不能發生、怎麼發生*:通道(lane)必須啟用、候選項必須在任何程序啟動**之前**就確認可用、`argv[0]` 必須早已由你的路由設定註冊過。沒有任何東西會經過 shell。工作行程一旦啟動,就不會偷偷改用第二個候選項——失敗是以證據的形式回報,不是自動重試。
|
|
27
|
+
|
|
28
|
+
這是允許清單(allow-list),不是沙箱。已註冊的工作行程擁有跟 CueLine 行程本身相同的權限;`advise` 對應 Codex 的唯讀沙箱、`work` 對應 `workspace-write`,但你註冊了什麼,就等於你授權了什麼。
|
|
29
|
+
|
|
30
|
+
## 五分鐘上手
|
|
31
|
+
|
|
32
|
+
你需要 Node.js 22 以上、帶內建瀏覽器的 Codex,以及——若要用內建的預設通道——`PATH` 上有 `codex` CLI。
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git clone https://github.com/Seraphim0916/cueline.git
|
|
36
|
+
cd cueline
|
|
37
|
+
npm ci
|
|
38
|
+
npm run build
|
|
39
|
+
./install.sh # 建立 ~/.codex/skills/cueline 與 ~/.local/bin/cueline 兩個符號連結
|
|
40
|
+
cueline doctor
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`install.sh` 只建立那兩個符號連結,不做別的;它拒絕覆寫不屬於自己的路徑,而 `./install.sh --uninstall` 也只移除自己建立的連結。
|
|
44
|
+
|
|
45
|
+
接著,在 Codex 裡:
|
|
46
|
+
|
|
47
|
+
1. 用 Codex 的內建瀏覽器開啟 `https://chatgpt.com` 並登入。
|
|
48
|
+
2. 讓你要當主控的那個對話保持選取狀態——該頁面當下選的模型就是主控端。CueLine 不會替你切換模型,也不會檢查你的訂閱方案。
|
|
49
|
+
3. 請 Codex 用 CueLine 處理這件事:*「用 CueLine:檢視這個 repository,提出下一步變更,並附上證據。」*
|
|
50
|
+
4. 留著回傳的 `runId`。中斷的執行要續跑,就靠它。
|
|
51
|
+
|
|
52
|
+
內建的 `cueline` skill 是從 Codex 自己的 Node runtime 驅動這個套件的——內建瀏覽器的物件就活在那裡。另外開一個單獨的 `node` 行程並不會繼承它。
|
|
53
|
+
|
|
54
|
+
## 從程式碼驅動
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
import { createCodexIabAdapter, runCueLine } from "cueline";
|
|
58
|
+
|
|
59
|
+
const result = await runCueLine({
|
|
60
|
+
request: "Inspect the repository, delegate an implementation plan, and report the evidence.",
|
|
61
|
+
browser: createCodexIabAdapter(),
|
|
62
|
+
// 選填:conversationUrl、routingConfig / routingConfigPath、home、cwd、limits。
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (result.status === "complete") {
|
|
66
|
+
console.log(result.finalDeliveryText);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`startCueLineRun` 是明確的啟動入口(`runCueLine` 是它的別名)。`continueCueLineRun({ runId })` 會在同一個對話裡續跑被中斷的執行,並沿用已保存的對話網址,除非你另外傳入新的 adapter。`loadCueLineRunState(runId)` 只讀取已保存的狀態,不驅動任何東西。已經走到 `complete` 或 `blocked` 的執行會原樣回傳,絕不會被再派工一次。
|
|
71
|
+
|
|
72
|
+
## CLI
|
|
73
|
+
|
|
74
|
+
CLI 不驅動瀏覽器。它只告訴你本機這一半健不健康。
|
|
75
|
+
|
|
76
|
+
```console
|
|
77
|
+
$ cueline doctor
|
|
78
|
+
CueLine 0.1.0
|
|
79
|
+
status ok
|
|
80
|
+
node 22.14.0 ok
|
|
81
|
+
config /Users/you/cueline/config/routing.default.json valid
|
|
82
|
+
home /Users/you/.cueline
|
|
83
|
+
available_lanes 1
|
|
84
|
+
|
|
85
|
+
$ cueline routing
|
|
86
|
+
default codex-default available
|
|
87
|
+
|
|
88
|
+
$ cueline jobs
|
|
89
|
+
No jobs.
|
|
90
|
+
|
|
91
|
+
$ cueline config path
|
|
92
|
+
/Users/you/cueline/config/routing.default.json
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Node 版本太舊、或沒有任何通道解析得出來時,`cueline doctor` 會以非零狀態結束,因此可以直接拿來當前置檢查。`cueline routing` 會告訴你某個通道為什麼不可用,而不是安靜地改選別的。`cueline help` 會列出全部。
|
|
96
|
+
|
|
97
|
+
## 設定
|
|
98
|
+
|
|
99
|
+
`CUELINE_CONFIG` 用來指定路由設定檔;`CUELINE_HOME` 用來搬動本機狀態(預設 `~/.cueline`)。
|
|
100
|
+
|
|
101
|
+
內建的 `default` 通道只有一個候選項 `codex-default`:以 stdin 傳入任務執行 `codex exec`,`advise` 用 `read-only`、`work` 用 `workspace-write`。要註冊別的工作行程,複製一份 [`config/routing.default.json`](config/routing.default.json)、加入你的候選項,再把 `CUELINE_CONFIG` 指過去——`argv[0]` 裡的執行檔就是透過這個動作被註冊的,而且它也必須在 `PATH` 上,通道才解析得出來。
|
|
102
|
+
|
|
103
|
+
狀態放在 `CUELINE_HOME` 底下:
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
runs/<run-id>/events.jsonl 只追加、具權威性
|
|
107
|
+
runs/<run-id>/snapshot.json 重播的最佳化產物,可丟棄
|
|
108
|
+
jobs/<job-id>.json 每個工作的執行證據
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
事件日誌才是紀錄本身:主控端的這一輪在送出之前就先寫下、工作在行程啟動之前就先註冊,所以「意圖」與「副作用」之間若被中斷,會留下痕跡。壞掉的快照會被忽略、從第 1 號事件重建,而不是硬信它。
|
|
112
|
+
|
|
113
|
+
## 驗證
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npm ci
|
|
117
|
+
npm run typecheck
|
|
118
|
+
npm test
|
|
119
|
+
npm run smoke:fake
|
|
120
|
+
bash test/shell/install.test.sh
|
|
121
|
+
npm pack --dry-run
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`npm run smoke:fake` 會用假的瀏覽器與假的 runner,離線跑完整個主控迴圈。它證明的是迴圈,不是線上頁面——只有真正透過內建瀏覽器完成一輪,才能證明後者。
|
|
125
|
+
|
|
126
|
+
## 0.1 的限制
|
|
127
|
+
|
|
128
|
+
只支援純文字。一次執行只對應一個對話。不切換模型、不支援圖片、不支援檔案上傳,也不支援 Deep Research、Projects 或 Apps。工作行程一旦啟動就沒有自動重試或改道——失敗的 `work` 工作會被標記為副作用不明確後回報,因為 CueLine 無法證明它做到哪裡。macOS 是主要的桌面目標、Linux 是 CI 目標;Windows 未經驗證,而且 `install.sh` 不是 Windows 安裝程式。adapter 依賴 ChatGPT 網頁目前的介面,所以介面一改,會以明確的 `COMPOSER_MISSING`、`SEND_BUTTON_MISSING` 或回應逾時浮現——絕不會變成捏造的答案。
|
|
129
|
+
|
|
130
|
+
完整矩陣見 [compatibility](docs/compatibility.md)。
|
|
131
|
+
|
|
132
|
+
## 文件
|
|
133
|
+
|
|
134
|
+
[architecture](docs/architecture.md) · [controller protocol](docs/controller-protocol.md) · [runner contract](docs/runner-contract.md) · [state and recovery](docs/state-and-recovery.md) · [compatibility](docs/compatibility.md) · [provenance](docs/provenance.md)(皆為英文)
|
|
135
|
+
|
|
136
|
+
## 開發
|
|
137
|
+
|
|
138
|
+
TypeScript、ESM,只用 Node 內建模組。`npm run build` 會編譯到 `dist/`;測試以 `node --test` 跑編譯後的產物。CI 涵蓋 Ubuntu 與 macOS 上的 Node 22 與 24。
|
|
139
|
+
|
|
140
|
+
CueLine 是獨立專案,與 OpenAI 或任何其他公司皆無隸屬關係,亦未獲其背書或贊助。見 [provenance](docs/provenance.md) 與 [third-party notices](THIRD_PARTY_NOTICES.md)。
|
|
141
|
+
|
|
142
|
+
## 授權
|
|
143
|
+
|
|
144
|
+
MIT。見 [LICENSE](LICENSE)。
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
CueLine independently implements a deterministic model-routing pattern informed by Omnilane. It does not import Omnilane at runtime.
|
|
4
|
+
|
|
5
|
+
Omnilane is licensed under the MIT License:
|
|
6
|
+
|
|
7
|
+
> Copyright (c) 2026 Seraphim0916
|
|
8
|
+
|
|
9
|
+
The complete MIT terms are reproduced in `LICENSE`; they permit use, modification, and redistribution when the copyright and permission notice are preserved.
|
|
10
|
+
|
|
11
|
+
GPT Relay was inspected as a behavioral reference for browser interaction and recovery boundaries. CueLine does not copy or redistribute GPT Relay source code, assets, credentials, cookies, or session data.
|
package/bin/cueline
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
set -eu
|
|
3
|
+
|
|
4
|
+
SELF=$0
|
|
5
|
+
while test -L "$SELF"; do
|
|
6
|
+
SELF_DIR=$(CDPATH= cd -- "$(dirname -- "$SELF")" && pwd)
|
|
7
|
+
LINK_TARGET=$(readlink "$SELF")
|
|
8
|
+
case $LINK_TARGET in
|
|
9
|
+
/*) SELF=$LINK_TARGET ;;
|
|
10
|
+
*) SELF=$SELF_DIR/$LINK_TARGET ;;
|
|
11
|
+
esac
|
|
12
|
+
done
|
|
13
|
+
ROOT=$(CDPATH= cd -- "$(dirname -- "$SELF")/.." && pwd)
|
|
14
|
+
exec node "$ROOT/dist/src/cli/main.js" "$@"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./routing.schema.json",
|
|
3
|
+
"version": 1,
|
|
4
|
+
"lanes": {
|
|
5
|
+
"default": {
|
|
6
|
+
"enabled": true,
|
|
7
|
+
"candidates": [
|
|
8
|
+
{
|
|
9
|
+
"id": "codex-default",
|
|
10
|
+
"argv": [
|
|
11
|
+
"codex",
|
|
12
|
+
"exec",
|
|
13
|
+
"--skip-git-repo-check",
|
|
14
|
+
"--ephemeral",
|
|
15
|
+
"--color",
|
|
16
|
+
"never",
|
|
17
|
+
"-C",
|
|
18
|
+
"{workdir}",
|
|
19
|
+
"-s",
|
|
20
|
+
"{sandbox}",
|
|
21
|
+
"-"
|
|
22
|
+
],
|
|
23
|
+
"task_input": "stdin"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "CueLine routing configuration",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": ["version", "lanes"],
|
|
6
|
+
"properties": {
|
|
7
|
+
"$schema": {
|
|
8
|
+
"type": "string"
|
|
9
|
+
},
|
|
10
|
+
"version": {
|
|
11
|
+
"const": 1
|
|
12
|
+
},
|
|
13
|
+
"lanes": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"minProperties": 1,
|
|
16
|
+
"additionalProperties": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"required": ["enabled", "candidates"],
|
|
19
|
+
"properties": {
|
|
20
|
+
"enabled": {
|
|
21
|
+
"type": "boolean"
|
|
22
|
+
},
|
|
23
|
+
"candidates": {
|
|
24
|
+
"type": "array",
|
|
25
|
+
"minItems": 1,
|
|
26
|
+
"items": {
|
|
27
|
+
"type": "object",
|
|
28
|
+
"required": ["id", "argv"],
|
|
29
|
+
"properties": {
|
|
30
|
+
"id": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"minLength": 1
|
|
33
|
+
},
|
|
34
|
+
"argv": {
|
|
35
|
+
"type": "array",
|
|
36
|
+
"minItems": 1,
|
|
37
|
+
"items": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"minLength": 1
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"task_input": {
|
|
43
|
+
"enum": ["argv", "stdin"]
|
|
44
|
+
},
|
|
45
|
+
"enabled": {
|
|
46
|
+
"type": "boolean"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"additionalProperties": false
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"additionalProperties": false
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"additionalProperties": false
|
|
58
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { BrowserAdapter } from "./browser/browser-adapter.js";
|
|
2
|
+
import { createCodexIabAdapter, type CodexIabAdapterOptions } from "./browser/codex-iab/chatgpt-client.js";
|
|
3
|
+
import { type CueLineResult } from "./core/controller-loop.js";
|
|
4
|
+
import { type CueLineRunState } from "./core/state-machine.js";
|
|
5
|
+
import type { RoutingConfig } from "./router/types.js";
|
|
6
|
+
export interface CueLineRuntimeOptions {
|
|
7
|
+
browser?: BrowserAdapter;
|
|
8
|
+
browserOptions?: Omit<CodexIabAdapterOptions, "conversationUrl">;
|
|
9
|
+
conversationUrl?: string;
|
|
10
|
+
routingConfig?: RoutingConfig;
|
|
11
|
+
routingConfigPath?: string;
|
|
12
|
+
home?: string;
|
|
13
|
+
cwd?: string;
|
|
14
|
+
environment?: NodeJS.ProcessEnv;
|
|
15
|
+
defaultTimeoutMs?: number;
|
|
16
|
+
maxRounds?: number;
|
|
17
|
+
maxRepairAttempts?: number;
|
|
18
|
+
now?: () => Date;
|
|
19
|
+
}
|
|
20
|
+
export interface StartCueLineRunOptions extends CueLineRuntimeOptions {
|
|
21
|
+
request: string;
|
|
22
|
+
runId?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface ContinueCueLineRunOptions extends CueLineRuntimeOptions {
|
|
25
|
+
runId: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function defaultRoutingConfigPath(): string;
|
|
28
|
+
export declare function routingConfigPath(environment?: NodeJS.ProcessEnv, explicitPath?: string): string;
|
|
29
|
+
export declare function loadCueLineRunState(runId: string, options?: Pick<CueLineRuntimeOptions, "home" | "environment">): Promise<CueLineRunState>;
|
|
30
|
+
export declare function startCueLineRun(options: StartCueLineRunOptions): Promise<CueLineResult>;
|
|
31
|
+
export declare function runCueLine(options: StartCueLineRunOptions): Promise<CueLineResult>;
|
|
32
|
+
export declare function continueCueLineRun(options: ContinueCueLineRunOptions): Promise<CueLineResult>;
|
|
33
|
+
export { createCodexIabAdapter };
|
|
34
|
+
export type { BrowserAdapter, CueLineResult, CueLineRunState, RoutingConfig };
|
package/dist/src/api.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { createCodexIabAdapter, } from "./browser/codex-iab/chatgpt-client.js";
|
|
3
|
+
import { continueControllerLoop, runControllerLoop, } from "./core/controller-loop.js";
|
|
4
|
+
import { CueLineError } from "./core/errors.js";
|
|
5
|
+
import { runtimeCwd, runtimeEnvironment } from "./core/runtime.js";
|
|
6
|
+
import { initialRunState, reduceRunState, } from "./core/state-machine.js";
|
|
7
|
+
import { JobStatusStore } from "./jobs/status.js";
|
|
8
|
+
import { JobSupervisor } from "./jobs/supervisor.js";
|
|
9
|
+
import { executableAvailability } from "./router/availability.js";
|
|
10
|
+
import { loadRoutingConfig } from "./router/config-loader.js";
|
|
11
|
+
import { materializeRunnerSpec } from "./router/materialize.js";
|
|
12
|
+
import { resolveRoute } from "./router/resolver.js";
|
|
13
|
+
import { ProcessRunner } from "./runners/process-runner.js";
|
|
14
|
+
import { RunnerRegistry } from "./runners/registry.js";
|
|
15
|
+
import { defaultCueLineHome } from "./state/paths.js";
|
|
16
|
+
import { RunStore } from "./state/store.js";
|
|
17
|
+
function assertNotNested(environment) {
|
|
18
|
+
if (environment.CUELINE_DEPTH !== undefined) {
|
|
19
|
+
throw new CueLineError("NESTED_ROUTING_REJECTED", "nested CueLine routing is not allowed");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function defaultRoutingConfigPath() {
|
|
23
|
+
return fileURLToPath(new URL("../../config/routing.default.json", import.meta.url));
|
|
24
|
+
}
|
|
25
|
+
export function routingConfigPath(environment = runtimeEnvironment(), explicitPath) {
|
|
26
|
+
return explicitPath ?? environment.CUELINE_CONFIG ?? defaultRoutingConfigPath();
|
|
27
|
+
}
|
|
28
|
+
async function persistedRunState(home, runId) {
|
|
29
|
+
const store = await RunStore.load({
|
|
30
|
+
home,
|
|
31
|
+
runId,
|
|
32
|
+
initialState: initialRunState(runId, ""),
|
|
33
|
+
reducer: reduceRunState,
|
|
34
|
+
});
|
|
35
|
+
const state = store.state;
|
|
36
|
+
if (state.request === "") {
|
|
37
|
+
throw new CueLineError("RUN_NOT_FOUND", `No persisted CueLine run '${runId}' was found.`);
|
|
38
|
+
}
|
|
39
|
+
return state;
|
|
40
|
+
}
|
|
41
|
+
function terminalResult(state) {
|
|
42
|
+
if (state.status !== "complete" && state.status !== "blocked") {
|
|
43
|
+
throw new CueLineError("RUN_NOT_TERMINAL", "CueLine result requested before a terminal state.");
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
runId: state.runId,
|
|
47
|
+
status: state.status,
|
|
48
|
+
...(state.finalDeliveryText === null ? {} : { finalDeliveryText: state.finalDeliveryText }),
|
|
49
|
+
...(state.conversationUrl === null ? {} : { conversationUrl: state.conversationUrl }),
|
|
50
|
+
state,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export async function loadCueLineRunState(runId, options = {}) {
|
|
54
|
+
const environment = options.environment ?? runtimeEnvironment();
|
|
55
|
+
return persistedRunState(options.home ?? defaultCueLineHome(environment), runId);
|
|
56
|
+
}
|
|
57
|
+
async function resolvedRoutingConfig(options, environment) {
|
|
58
|
+
return (options.routingConfig ??
|
|
59
|
+
(await loadRoutingConfig(routingConfigPath(environment, options.routingConfigPath))));
|
|
60
|
+
}
|
|
61
|
+
function registryFor(config) {
|
|
62
|
+
const executables = new Set();
|
|
63
|
+
for (const lane of Object.values(config.lanes)) {
|
|
64
|
+
for (const candidate of lane.candidates) {
|
|
65
|
+
const executable = candidate.argv[0];
|
|
66
|
+
if (candidate.enabled !== false && executable !== undefined)
|
|
67
|
+
executables.add(executable);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return new RunnerRegistry([...executables].map((executable) => ({ id: executable, executable })));
|
|
71
|
+
}
|
|
72
|
+
function routingInstruction(config, availability) {
|
|
73
|
+
const lanes = Object.entries(config.lanes)
|
|
74
|
+
.filter(([, lane]) => lane.enabled)
|
|
75
|
+
.map(([name, lane]) => {
|
|
76
|
+
const candidates = lane.candidates
|
|
77
|
+
.filter((candidate) => candidate.enabled !== false && availability.isAvailable(candidate, name))
|
|
78
|
+
.map((candidate) => candidate.id);
|
|
79
|
+
return `${name} [${candidates.length > 0 ? candidates.join(", ") : "unavailable"}]`;
|
|
80
|
+
});
|
|
81
|
+
return `Available routing lanes: ${lanes.join("; ")}. Use only a listed available lane and optional runner id.`;
|
|
82
|
+
}
|
|
83
|
+
async function prepareRuntime(options, persistedConversationUrl) {
|
|
84
|
+
const environment = options.environment ?? runtimeEnvironment();
|
|
85
|
+
const home = options.home ?? defaultCueLineHome(environment);
|
|
86
|
+
const cwd = options.cwd ?? runtimeCwd();
|
|
87
|
+
const config = await resolvedRoutingConfig(options, environment);
|
|
88
|
+
const availability = executableAvailability(environment, cwd);
|
|
89
|
+
const registry = registryFor(config);
|
|
90
|
+
const runner = new ProcessRunner(registry, { environment });
|
|
91
|
+
const jobSupervisor = new JobSupervisor(runner, {
|
|
92
|
+
statusStore: new JobStatusStore(home),
|
|
93
|
+
});
|
|
94
|
+
const conversationUrl = options.conversationUrl ?? persistedConversationUrl;
|
|
95
|
+
const browser = options.browser ??
|
|
96
|
+
createCodexIabAdapter({
|
|
97
|
+
...options.browserOptions,
|
|
98
|
+
...(conversationUrl === undefined ? {} : { conversationUrl }),
|
|
99
|
+
});
|
|
100
|
+
return {
|
|
101
|
+
browser,
|
|
102
|
+
jobSupervisor,
|
|
103
|
+
resolveRunnerSpec(jobId, job) {
|
|
104
|
+
const route = resolveRoute(job.lane, config, availability, job.runner);
|
|
105
|
+
return materializeRunnerSpec(jobId, job, route, {
|
|
106
|
+
cwd,
|
|
107
|
+
...(options.defaultTimeoutMs === undefined
|
|
108
|
+
? {}
|
|
109
|
+
: { timeoutMs: options.defaultTimeoutMs }),
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
controllerInstructions: [routingInstruction(config, availability)],
|
|
113
|
+
home,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
export async function startCueLineRun(options) {
|
|
117
|
+
assertNotNested(options.environment ?? runtimeEnvironment());
|
|
118
|
+
const runtime = await prepareRuntime(options);
|
|
119
|
+
return runControllerLoop({
|
|
120
|
+
request: options.request,
|
|
121
|
+
...(options.runId === undefined ? {} : { runId: options.runId }),
|
|
122
|
+
...runtime,
|
|
123
|
+
...(options.maxRounds === undefined ? {} : { maxRounds: options.maxRounds }),
|
|
124
|
+
...(options.maxRepairAttempts === undefined
|
|
125
|
+
? {}
|
|
126
|
+
: { maxRepairAttempts: options.maxRepairAttempts }),
|
|
127
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
export async function runCueLine(options) {
|
|
131
|
+
return startCueLineRun(options);
|
|
132
|
+
}
|
|
133
|
+
export async function continueCueLineRun(options) {
|
|
134
|
+
const environment = options.environment ?? runtimeEnvironment();
|
|
135
|
+
const home = options.home ?? defaultCueLineHome(environment);
|
|
136
|
+
const state = await persistedRunState(home, options.runId);
|
|
137
|
+
if (state.status === "complete" || state.status === "blocked") {
|
|
138
|
+
return terminalResult(state);
|
|
139
|
+
}
|
|
140
|
+
assertNotNested(environment);
|
|
141
|
+
const runtime = await prepareRuntime(options, state.conversationUrl ?? undefined);
|
|
142
|
+
return continueControllerLoop({
|
|
143
|
+
runId: options.runId,
|
|
144
|
+
...runtime,
|
|
145
|
+
...(options.maxRounds === undefined ? {} : { maxRounds: options.maxRounds }),
|
|
146
|
+
...(options.maxRepairAttempts === undefined
|
|
147
|
+
? {}
|
|
148
|
+
: { maxRepairAttempts: options.maxRepairAttempts }),
|
|
149
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
export { createCodexIabAdapter };
|
|
153
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,OAAO,EACL,qBAAqB,GAEtB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAElB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EACL,eAAe,EACf,cAAc,GAEf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAqC5C,SAAS,eAAe,CAAC,WAA8B;IACrD,IAAI,WAAW,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QAC5C,MAAM,IAAI,YAAY,CAAC,yBAAyB,EAAE,uCAAuC,CAAC,CAAC;IAC7F,CAAC;AACH,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,OAAO,aAAa,CAAC,IAAI,GAAG,CAAC,mCAAmC,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,WAAW,GAAsB,kBAAkB,EAAE,EACrD,YAAqB;IAErB,OAAO,YAAY,IAAI,WAAW,CAAC,cAAc,IAAI,wBAAwB,EAAE,CAAC;AAClF,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,IAAY,EAAE,KAAa;IAC1D,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC;QAChC,IAAI;QACJ,KAAK;QACL,YAAY,EAAE,eAAe,CAAC,KAAK,EAAE,EAAE,CAAC;QACxC,OAAO,EAAE,cAAc;KACxB,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1B,IAAI,KAAK,CAAC,OAAO,KAAK,EAAE,EAAE,CAAC;QACzB,MAAM,IAAI,YAAY,CAAC,eAAe,EAAE,6BAA6B,KAAK,cAAc,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,cAAc,CAAC,KAAsB;IAC5C,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9D,MAAM,IAAI,YAAY,CAAC,kBAAkB,EAAE,mDAAmD,CAAC,CAAC;IAClG,CAAC;IACD,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,CAAC,KAAK,CAAC,iBAAiB,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC3F,GAAG,CAAC,KAAK,CAAC,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,CAAC;QACrF,KAAK;KACN,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAAa,EACb,OAAO,GAAwD,EAAE;IAEjE,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,kBAAkB,EAAE,CAAC;IAChE,OAAO,iBAAiB,CAAC,OAAO,CAAC,IAAI,IAAI,kBAAkB,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,CAAC;AACnF,CAAC;AAED,KAAK,UAAU,qBAAqB,CAClC,OAA8B,EAC9B,WAA8B;IAE9B,OAAO,CACL,OAAO,CAAC,aAAa;QACrB,CAAC,MAAM,iBAAiB,CAAC,iBAAiB,CAAC,WAAW,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CACrF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,MAAqB;IACxC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACxC,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACrC,IAAI,SAAS,CAAC,OAAO,KAAK,KAAK,IAAI,UAAU,KAAK,SAAS;gBAAE,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;IACD,OAAO,IAAI,cAAc,CACvB,CAAC,GAAG,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC,CACvE,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CACzB,MAAqB,EACrB,YAAuD;IAEvD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;SACvC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;SAClC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;QACpB,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU;aAC/B,MAAM,CACL,CAAC,SAAS,EAAE,EAAE,CACZ,SAAS,CAAC,OAAO,KAAK,KAAK,IAAI,YAAY,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,CAC3E;aACA,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACpC,OAAO,GAAG,IAAI,KAAK,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC;IACtF,CAAC,CAAC,CAAC;IACL,OAAO,4BAA4B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,4DAA4D,CAAC;AAClH,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,OAA8B,EAC9B,wBAAiC;IAEjC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,kBAAkB,EAAE,CAAC;IAChE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,kBAAkB,CAAC,WAAW,CAAC,CAAC;IAC7D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC;IACxC,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACjE,MAAM,YAAY,GAAG,sBAAsB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,QAAQ,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;IAC5D,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC,MAAM,EAAE;QAC9C,WAAW,EAAE,IAAI,cAAc,CAAC,IAAI,CAAC;KACtC,CAAC,CAAC;IACH,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,wBAAwB,CAAC;IAC5E,MAAM,OAAO,GACX,OAAO,CAAC,OAAO;QACf,qBAAqB,CAAC;YACpB,GAAG,OAAO,CAAC,cAAc;YACzB,GAAG,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC;SAC9D,CAAC,CAAC;IAEL,OAAO;QACL,OAAO;QACP,aAAa;QACb,iBAAiB,CAAC,KAAK,EAAE,GAAG;YAC1B,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;YACvE,OAAO,qBAAqB,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE;gBAC9C,GAAG;gBACH,GAAG,CAAC,OAAO,CAAC,gBAAgB,KAAK,SAAS;oBACxC,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC;aAC7C,CAAC,CAAC;QACL,CAAC;QACD,sBAAsB,EAAE,CAAC,kBAAkB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAClE,IAAI;KACL,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAA+B;IAE/B,eAAe,CAAC,OAAO,CAAC,WAAW,IAAI,kBAAkB,EAAE,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC;IAC9C,OAAO,iBAAiB,CAAC;QACvB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;QAChE,GAAG,OAAO;QACV,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC;QAC5E,GAAG,CAAC,OAAO,CAAC,iBAAiB,KAAK,SAAS;YACzC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC;QACrD,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;KAC3D,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAA+B;IAC9D,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAkC;IAElC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,kBAAkB,EAAE,CAAC;IAChE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,kBAAkB,CAAC,WAAW,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC3D,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9D,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,eAAe,CAAC,WAAW,CAAC,CAAC;IAC7B,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,eAAe,IAAI,SAAS,CAAC,CAAC;IAClF,OAAO,sBAAsB,CAAC;QAC5B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,GAAG,OAAO;QACV,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC;QAC5E,GAAG,CAAC,OAAO,CAAC,iBAAiB,KAAK,SAAS;YACzC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC;QACrD,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;KAC3D,CAAC,CAAC;AACL,CAAC;AAED,OAAO,EAAE,qBAAqB,EAAE,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface BrowserTurnInput {
|
|
2
|
+
runId: string;
|
|
3
|
+
round: number;
|
|
4
|
+
requestId: string;
|
|
5
|
+
prompt: string;
|
|
6
|
+
repairAttempt?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface ControllerTurn {
|
|
9
|
+
text: string;
|
|
10
|
+
conversationUrl?: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface BrowserAdapter {
|
|
14
|
+
sendTurn(input: BrowserTurnInput): Promise<ControllerTurn>;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-adapter.js","sourceRoot":"","sources":["../../../src/browser/browser-adapter.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export interface PageChatState {
|
|
2
|
+
isAnswering: boolean;
|
|
3
|
+
assistantText: string;
|
|
4
|
+
assistantMessageCount: number;
|
|
5
|
+
}
|
|
6
|
+
export interface IabLocator {
|
|
7
|
+
count(): Promise<number>;
|
|
8
|
+
fill(value: string, options?: Record<string, unknown>): Promise<void>;
|
|
9
|
+
click(options?: {
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
}): Promise<void>;
|
|
12
|
+
waitFor?(options: {
|
|
13
|
+
state: "visible";
|
|
14
|
+
timeoutMs: number;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
export interface IabPlaywright {
|
|
18
|
+
getByRole(role: string, query: {
|
|
19
|
+
name: string;
|
|
20
|
+
}): IabLocator;
|
|
21
|
+
locator?(selector: string): IabLocator;
|
|
22
|
+
evaluate<Result, Argument = undefined>(pageFunction: (argument: Argument) => Result | Promise<Result>, argument?: Argument): Promise<Result>;
|
|
23
|
+
domSnapshot(): Promise<unknown>;
|
|
24
|
+
waitForTimeout(milliseconds: number): Promise<void>;
|
|
25
|
+
waitForLoadState?(options: {
|
|
26
|
+
state: string;
|
|
27
|
+
timeoutMs: number;
|
|
28
|
+
}): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
export interface IabTab {
|
|
31
|
+
id?: string;
|
|
32
|
+
goto(url: string): Promise<void>;
|
|
33
|
+
url(): Promise<string | undefined>;
|
|
34
|
+
title?(): Promise<string>;
|
|
35
|
+
playwright: IabPlaywright;
|
|
36
|
+
}
|
|
37
|
+
export interface IabOpenTab {
|
|
38
|
+
id?: string;
|
|
39
|
+
url?: string;
|
|
40
|
+
title?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface IabBrowser {
|
|
43
|
+
documentation?(): Promise<unknown>;
|
|
44
|
+
tabs: {
|
|
45
|
+
new: () => Promise<IabTab>;
|
|
46
|
+
selected?: () => Promise<IabTab | undefined>;
|
|
47
|
+
list?: () => Promise<IabOpenTab[]>;
|
|
48
|
+
get?: (id: string) => Promise<IabTab>;
|
|
49
|
+
};
|
|
50
|
+
user?: {
|
|
51
|
+
openTabs?(): Promise<IabOpenTab[]>;
|
|
52
|
+
claimTab?(tab: IabOpenTab): Promise<IabTab>;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
interface BrowserAgent {
|
|
56
|
+
browsers?: {
|
|
57
|
+
get?(type: string): Promise<IabBrowser>;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
declare global {
|
|
61
|
+
var iab: IabBrowser | undefined;
|
|
62
|
+
var agent: BrowserAgent | undefined;
|
|
63
|
+
}
|
|
64
|
+
export declare function resolveIabBrowser(requested?: IabBrowser): Promise<IabBrowser>;
|
|
65
|
+
export declare function readPageChatState(tab: IabTab): Promise<PageChatState>;
|
|
66
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { CueLineError } from "../../core/errors.js";
|
|
2
|
+
export async function resolveIabBrowser(requested) {
|
|
3
|
+
if (requested) {
|
|
4
|
+
await requested.documentation?.();
|
|
5
|
+
return requested;
|
|
6
|
+
}
|
|
7
|
+
if (globalThis.iab) {
|
|
8
|
+
await globalThis.iab.documentation?.();
|
|
9
|
+
return globalThis.iab;
|
|
10
|
+
}
|
|
11
|
+
if (globalThis.agent?.browsers?.get) {
|
|
12
|
+
const browser = await globalThis.agent.browsers.get("iab");
|
|
13
|
+
await browser.documentation?.();
|
|
14
|
+
globalThis.iab = browser;
|
|
15
|
+
return browser;
|
|
16
|
+
}
|
|
17
|
+
throw new CueLineError("IAB_BROWSER_MISSING", "Codex did not expose the in-app Browser runtime. Run CueLine from a Codex task with the built-in Browser available or inject an IabBrowser.");
|
|
18
|
+
}
|
|
19
|
+
export async function readPageChatState(tab) {
|
|
20
|
+
return tab.playwright.evaluate(() => {
|
|
21
|
+
const buttons = Array.from(document.querySelectorAll("button"));
|
|
22
|
+
const isAnswering = buttons.some((button) => {
|
|
23
|
+
const label = [button.getAttribute("aria-label"), button.textContent]
|
|
24
|
+
.filter(Boolean)
|
|
25
|
+
.join(" ")
|
|
26
|
+
.replace(/\s+/g, " ")
|
|
27
|
+
.trim();
|
|
28
|
+
return /stop/i.test(label) && /(answer|generat|respond|stream|thinking)/i.test(label);
|
|
29
|
+
});
|
|
30
|
+
const assistantMessages = Array.from(document.querySelectorAll('[data-message-author-role="assistant"]'));
|
|
31
|
+
const last = assistantMessages.at(-1);
|
|
32
|
+
const visibleText = last !== undefined && "innerText" in last
|
|
33
|
+
? String(last.innerText ?? last.textContent ?? "")
|
|
34
|
+
: last?.textContent ?? "";
|
|
35
|
+
const assistantText = visibleText
|
|
36
|
+
.replace(/\u00a0/g, " ")
|
|
37
|
+
.trim();
|
|
38
|
+
return { isAnswering, assistantText, assistantMessageCount: assistantMessages.length };
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../../../src/browser/codex-iab/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAmEpD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,SAAsB;IAC5D,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,SAAS,CAAC,aAAa,EAAE,EAAE,CAAC;QAClC,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,UAAU,CAAC,GAAG,EAAE,CAAC;QACnB,MAAM,UAAU,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,CAAC;QACvC,OAAO,UAAU,CAAC,GAAG,CAAC;IACxB,CAAC;IACD,IAAI,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3D,MAAM,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;QAChC,UAAU,CAAC,GAAG,GAAG,OAAO,CAAC;QACzB,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,MAAM,IAAI,YAAY,CACpB,qBAAqB,EACrB,6IAA6I,CAC9I,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,GAAW;IACjD,OAAO,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,EAAE;QAClC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;QAChE,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YAC1C,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC;iBAClE,MAAM,CAAC,OAAO,CAAC;iBACf,IAAI,CAAC,GAAG,CAAC;iBACT,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;iBACpB,IAAI,EAAE,CAAC;YACV,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,2CAA2C,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxF,CAAC,CAAC,CAAC;QAEH,MAAM,iBAAiB,GAAG,KAAK,CAAC,IAAI,CAClC,QAAQ,CAAC,gBAAgB,CAAC,wCAAwC,CAAC,CACpE,CAAC;QACF,MAAM,IAAI,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,WAAW,GACf,IAAI,KAAK,SAAS,IAAI,WAAW,IAAI,IAAI;YACvC,CAAC,CAAC,MAAM,CAAE,IAAyC,CAAC,SAAS,IAAI,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC;YACxF,CAAC,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC;QAC9B,MAAM,aAAa,GAAG,WAAW;aAC9B,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;aACvB,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,qBAAqB,EAAE,iBAAiB,CAAC,MAAM,EAAE,CAAC;IACzF,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BrowserAdapter } from "../browser-adapter.js";
|
|
2
|
+
import { type IabBrowser } from "./bootstrap.js";
|
|
3
|
+
export interface CodexIabAdapterOptions {
|
|
4
|
+
browser?: IabBrowser;
|
|
5
|
+
conversationUrl?: string;
|
|
6
|
+
timeoutMs?: number;
|
|
7
|
+
pollIntervalMs?: number;
|
|
8
|
+
stableMs?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function createCodexIabAdapter(options?: CodexIabAdapterOptions): BrowserAdapter;
|