omnilane 0.13.0 → 0.15.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/CHANGELOG.md +58 -1
- package/README.ja.md +18 -0
- package/README.ko.md +18 -0
- package/README.md +54 -2
- package/README.zh-CN.md +18 -0
- package/README.zh-TW.md +39 -2
- package/VERSION +1 -1
- package/benchmarks/workloads.tsv +4 -0
- package/bin/omnilane +10 -2
- package/bin/omnilane-mcp +126 -0
- package/completions/_omnilane +21 -4
- package/completions/omnilane.bash +19 -4
- package/completions/omnilane.fish +15 -3
- package/package.json +2 -1
- package/scripts/benchmark.py +446 -0
- package/scripts/check.sh +1 -1
- package/scripts/dispatch.sh +48 -0
- package/scripts/doctor.sh +53 -10
- package/scripts/jobs.sh +162 -2
- package/scripts/lib/common.sh +19 -0
- package/scripts/provider-probe.sh +180 -0
- package/scripts/runners/run-codex.sh +22 -5
- package/ui/app.js +56 -0
- package/ui/index.html +1 -0
- package/ui/styles.css +22 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,59 @@ semantic version tags.
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.15.0] - 2026-08-28
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Timed-out Codex jobs now print the absolute path to the matching
|
|
14
|
+
`rollout-*.jsonl` session file, resolved from the first progress event's
|
|
15
|
+
`thread_id`, so an interrupted conversation remains directly inspectable.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Codex runner now invokes `codex exec --json`, streaming JSONL events to
|
|
20
|
+
`out.txt.progress.log` before the run exits or times out. `out.txt` and the
|
|
21
|
+
Jobs display, which reads only `out.txt` and `stderr.log`, remain unchanged.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Timeout diagnostics no longer blame a usage-limit retry loop without evidence.
|
|
26
|
+
They now state that a timeout does not identify its cause, provide a
|
|
27
|
+
three-step check, and clarify that an empty progress log does not prove the
|
|
28
|
+
run made no progress.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## [0.14.0] - 2026-08-10
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- Optional `omnilane doctor --probe V` and read-only MCP `provider_probe` perform
|
|
36
|
+
one bounded advise-mode live capability check only when explicitly requested;
|
|
37
|
+
reports include routing/timing metadata but never the provider response body.
|
|
38
|
+
- Live Board retained-history search and state filters now drive a local
|
|
39
|
+
**Export visible** JSON download that excludes tokens, task/result bodies,
|
|
40
|
+
workdirs, and logs.
|
|
41
|
+
- `omnilane benchmark` provides a versioned fixed-workload quality/timing report,
|
|
42
|
+
transparent user-supplied per-call cost estimates, default no-call dry-run,
|
|
43
|
+
and an explicit `--run` provider-call gate.
|
|
44
|
+
- CI runs `omnilane doctor --strict --json` against an isolated, offline fixture
|
|
45
|
+
as a post-install acceptance contract.
|
|
46
|
+
|
|
47
|
+
- `omnilane jobs recommend` and the read-only MCP `jobs_recommend` tool derive
|
|
48
|
+
per-lane vendor suggestions from bounded completed-job metadata. A configurable
|
|
49
|
+
minimum sample gate prevents one-off successes from outranking established
|
|
50
|
+
evidence; neither surface reads task/result bodies or changes routing.
|
|
51
|
+
- `omnilane doctor --strict` keeps warning diagnostics intact but exits nonzero
|
|
52
|
+
when any warning is present, so local automation and CI can enforce a complete
|
|
53
|
+
runtime setup. JSON output now includes the applied `strict` policy and makes
|
|
54
|
+
`ok` reflect it.
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- `doctor` now validates macOS `stat -f` output before falling back to GNU
|
|
59
|
+
`stat -c`, so owner-only job-store permissions are classified consistently on
|
|
60
|
+
Linux CI instead of becoming a false strict-mode warning.
|
|
61
|
+
|
|
9
62
|
## [0.13.0] - 2026-08-03
|
|
10
63
|
|
|
11
64
|
### Changed
|
|
@@ -563,7 +616,11 @@ work to the wrong model, and records the evidence behind the shipped defaults.
|
|
|
563
616
|
- Initial shared routing table, cross-vendor dispatcher, runners, installer,
|
|
564
617
|
and baseline lint fixes.
|
|
565
618
|
|
|
566
|
-
[Unreleased]: https://github.com/Seraphim0916/omnilane/compare/v0.
|
|
619
|
+
[Unreleased]: https://github.com/Seraphim0916/omnilane/compare/v0.15.0...HEAD
|
|
620
|
+
|
|
621
|
+
[0.15.0]: https://github.com/Seraphim0916/omnilane/compare/v0.14.0...v0.15.0
|
|
622
|
+
|
|
623
|
+
[0.14.0]: https://github.com/Seraphim0916/omnilane/compare/v0.13.0...v0.14.0
|
|
567
624
|
[0.13.0]: https://github.com/Seraphim0916/omnilane/compare/v0.12.0...v0.13.0
|
|
568
625
|
[0.12.0]: https://github.com/Seraphim0916/omnilane/compare/v0.11.0...v0.12.0
|
|
569
626
|
[0.11.0]: https://github.com/Seraphim0916/omnilane/compare/v0.10.4...v0.11.0
|
package/README.ja.md
CHANGED
|
@@ -516,6 +516,24 @@ scripts/dispatch.sh --dry-run hardest-coding "…" # 解決済みプラン、
|
|
|
516
516
|
|
|
517
517
|
## 📜 リリース履歴
|
|
518
518
|
|
|
519
|
+
## v0.15.0 の新機能
|
|
520
|
+
|
|
521
|
+
- **Codex の進捗証跡をストリーミング保存** — `codex exec --json` が JSONL イベントを
|
|
522
|
+
`out.txt.progress.log` へ逐次書き込むため、タイムアウト時にも最後に到達した手順を残せます。
|
|
523
|
+
`out.txt` と Jobs の表示は変わりません。
|
|
524
|
+
- **証拠に基づくタイムアウト診断** — タイムアウト自体では原因を特定できないことを明示し、
|
|
525
|
+
三段階の確認手順と、空の進捗ログが Codex の未進行を示す証拠ではないことを案内します。
|
|
526
|
+
- **rollout 記録への直接パス** — 最初の進捗イベントの `thread_id` から対応する
|
|
527
|
+
`rollout-*.jsonl` の絶対パスをタイムアウト出力に表示し、中断された会話履歴を確認できます。
|
|
528
|
+
|
|
529
|
+
## v0.14.0 の新機能
|
|
530
|
+
|
|
531
|
+
- **根拠に基づくルーティング提案**:`jobs recommend` と MCP `jobs_recommend` は公開ジョブメタデータだけを読み、ルーティングを自動変更しません。
|
|
532
|
+
- **任意の実動プローブ**:`doctor --probe V` と MCP `provider_probe` は明示された場合だけプロバイダーを呼び出し、応答本文を報告しません。
|
|
533
|
+
- **Live Board の履歴検索・絞り込み・エクスポート**:直近 50 件を対象に、表示中の公開メタデータだけを出力します。
|
|
534
|
+
- **固定品質/コストベンチマーク**:`omnilane benchmark` は既定で dry-run、実呼び出しには `--run` が必要です。
|
|
535
|
+
- **厳格なインストール検証**:CI で隔離された `doctor --strict --json` を実行し、macOS/GNU `stat` の権限判定差も修正しました。
|
|
536
|
+
|
|
519
537
|
## v0.13.0 の新機能
|
|
520
538
|
|
|
521
539
|
- **`long-context` を AA-LCR で順序付け** — Artificial Analysis の長文脈推論
|
package/README.ko.md
CHANGED
|
@@ -499,6 +499,24 @@ scripts/dispatch.sh --dry-run hardest-coding "…" # 완전히 해석된 계
|
|
|
499
499
|
|
|
500
500
|
## 📜 릴리스 기록
|
|
501
501
|
|
|
502
|
+
## v0.15.0 새 기능
|
|
503
|
+
|
|
504
|
+
- **Codex 진행 증거의 스트리밍 보존** — `codex exec --json`이 JSONL 이벤트를
|
|
505
|
+
`out.txt.progress.log`에 순차 기록하므로 시간 초과가 나도 마지막으로 도달한 단계를 남깁니다.
|
|
506
|
+
`out.txt`와 Jobs 표시는 그대로입니다.
|
|
507
|
+
- **증거 기반 시간 초과 진단** — 시간 초과 자체로 원인을 특정하지 않는다고 밝히고,
|
|
508
|
+
세 단계 점검 목록과 빈 진행 로그가 Codex 미진행의 증거가 아니라는 점을 안내합니다.
|
|
509
|
+
- **rollout 기록으로 가는 직접 경로** — 첫 진행 이벤트의 `thread_id`로 찾은
|
|
510
|
+
`rollout-*.jsonl`의 절대 경로를 시간 초과 출력에 표시하여, 중단된 대화 이력을 확인할 수 있습니다.
|
|
511
|
+
|
|
512
|
+
## v0.14.0 새 기능
|
|
513
|
+
|
|
514
|
+
- **근거 기반 라우팅 제안**: `jobs recommend`와 MCP `jobs_recommend`는 공개 작업 메타데이터만 읽고 라우팅을 자동 변경하지 않습니다.
|
|
515
|
+
- **선택형 실제 기능 탐지**: `doctor --probe V`와 MCP `provider_probe`는 명시적으로 요청할 때만 공급자를 호출하며 응답 본문을 보고하지 않습니다.
|
|
516
|
+
- **Live Board 기록 검색·필터·내보내기**: 최근 50개 작업을 검색하고 현재 표시된 공개 메타데이터만 내보냅니다.
|
|
517
|
+
- **고정 품질/비용 벤치마크**: `omnilane benchmark`는 기본적으로 dry-run이며 실제 호출에는 `--run`이 필요합니다.
|
|
518
|
+
- **엄격한 설치 검증**: CI에서 격리된 `doctor --strict --json`을 실행하고 macOS/GNU `stat` 권한 판정 차이도 수정했습니다.
|
|
519
|
+
|
|
502
520
|
## v0.13.0 새 기능
|
|
503
521
|
|
|
504
522
|
- **`long-context` 를 AA-LCR 기준으로 정렬** — Artificial Analysis 의 장문맥 추론
|
package/README.md
CHANGED
|
@@ -195,12 +195,20 @@ The reference is memory-only and disappears when the page closes. The board
|
|
|
195
195
|
binds only to `127.0.0.1`, uses a random token, and is read-only. It shows
|
|
196
196
|
`task.txt` and the public `out.txt`, but never raw worker or vendor logs.
|
|
197
197
|
|
|
198
|
+
Search and state filters apply to the latest 50 retained jobs. **Export visible**
|
|
199
|
+
downloads only the currently visible public metadata as local JSON; it excludes
|
|
200
|
+
tokens, task text, result bodies, workdirs, and raw logs.
|
|
201
|
+
|
|
198
202
|
The board reads in English, Japanese, Korean, Traditional Chinese and Simplified
|
|
199
203
|
Chinese. It follows the browser language on first load; the switcher in the
|
|
200
204
|
header overrides that and the choice is remembered locally.
|
|
201
205
|
|
|
202
206
|
Core routing does not need Python; only this UI requires Python 3.9 or newer.
|
|
203
207
|
|
|
208
|
+
### Foreman completion inbox
|
|
209
|
+
|
|
210
|
+
Finished dispatches write a private completion record under `$OMNILANE_HOME/inbox/`. The bundled Claude Code `UserPromptSubmit` hook atomically delivers up to ten matching records on the foreman's next prompt, scoped by the dispatch `workdir`; claimed records move to `inbox/consumed/`. Set `OMNILANE_INBOX=0` on dispatch to disable record creation. The default is enabled.
|
|
211
|
+
|
|
204
212
|
## 📦 Install
|
|
205
213
|
|
|
206
214
|
Requirements: the vendor CLIs you want to route to, logged in (`codex`,
|
|
@@ -255,7 +263,8 @@ adding a routing reminder. Configure the host to launch the installed CLI:
|
|
|
255
263
|
|
|
256
264
|
The server exposes `route` plus read-only introspection: `list_lanes`,
|
|
257
265
|
`explain`, `validate`, `dry_run`, `jobs_list`, `jobs_status`, `jobs_result`,
|
|
258
|
-
`jobs_stats`, `jobs_audit`,
|
|
266
|
+
`jobs_stats`, `jobs_recommend`, `jobs_audit`, `doctor`, and the explicitly opt-in
|
|
267
|
+
`provider_probe`. `route` defaults to read-only `advise` mode. Calls that select `work` must also
|
|
259
268
|
provide an explicit `workdir`.
|
|
260
269
|
|
|
261
270
|
Node.js is the only runtime requirement (no npm packages). If you prefer
|
|
@@ -299,7 +308,8 @@ omnilane ui start # start/reuse the local Live UI;
|
|
|
299
308
|
omnilane ui status # report whether the Live UI is running
|
|
300
309
|
omnilane ui url # print the current authenticated local URL
|
|
301
310
|
omnilane ui stop # stop the Live UI
|
|
302
|
-
omnilane doctor [--json]
|
|
311
|
+
omnilane doctor [--json] [--strict] [--probe V] [--probe-timeout SEC] # live probe is opt-in
|
|
312
|
+
omnilane benchmark [--json] [--run] [--vendor V] [--cost-per-call V=USD] # dry-run by default
|
|
303
313
|
dispatch.sh [--background] [--dry-run] [--mode advise|work|sysops] [--workdir DIR]
|
|
304
314
|
[--vendor V] [--model M] [--effort E] [--timeout SEC] [--job-timeout SEC]
|
|
305
315
|
LANE "TASK" # "-" reads task from stdin
|
|
@@ -312,12 +322,24 @@ jobs.sh wait ID [--timeout N] # job exit; 124 timeout; 125 d
|
|
|
312
322
|
jobs.sh cancel ID # stop a running job: group SIGTERM, then SIGKILL
|
|
313
323
|
jobs.sh rm ID # delete one finished/dead job (refuses a running job)
|
|
314
324
|
jobs.sh [--json] stats [--last N] [--lane L] [--vendor V] # local success and routing aggregates
|
|
325
|
+
jobs.sh [--json] recommend [--last N] [--lane L] [--min-samples N] # evidence-gated vendor suggestion
|
|
315
326
|
jobs.sh audit [--last N] [--json] # read-only job integrity/privacy check
|
|
316
327
|
jobs.sh prune [--keep N] [--apply] # preview by default; completed jobs only
|
|
317
328
|
configure.sh # interactive lane menu
|
|
318
329
|
configure.sh set|get|unset|list|diff LANE [SPEC] # script/inspect routing.local.yaml, no tty
|
|
319
330
|
```
|
|
320
331
|
|
|
332
|
+
`jobs recommend` reads only validated public metadata and exit codes. It ranks
|
|
333
|
+
eligible vendors by success rate, sample count, then name; the default minimum
|
|
334
|
+
is three completed jobs. It never reads task/result bodies or changes routing.
|
|
335
|
+
|
|
336
|
+
`doctor --probe V` makes one bounded advise-mode provider call and returns only
|
|
337
|
+
availability, selected model, timing, and response byte count—not the response
|
|
338
|
+
body. Without `--probe`, doctor remains offline. `benchmark` uses the fixed TSV
|
|
339
|
+
suite in `benchmarks/workloads.tsv`; its default dry-run resolves every route
|
|
340
|
+
without provider calls. `--run` is the explicit call gate, and cost totals are
|
|
341
|
+
estimates based only on values supplied with `--cost-per-call`.
|
|
342
|
+
|
|
321
343
|
**Big decisions can get a panel, not a person.** The `arbitrate` lane ships
|
|
322
344
|
**disabled** — a panel costs one call per voter per round, so it is opt-in.
|
|
323
345
|
Enable it with `arbitrate: vote codex,claude,grok -` in `routing.local.yaml`,
|
|
@@ -547,6 +569,36 @@ working notes, including per-benchmark caveats, live in
|
|
|
547
569
|
|
|
548
570
|
## 📜 Release history
|
|
549
571
|
|
|
572
|
+
## What's new in v0.15.0
|
|
573
|
+
|
|
574
|
+
- **Streaming Codex progress evidence** — `codex exec --json` now streams JSONL
|
|
575
|
+
events into `out.txt.progress.log`, so a timeout still records its last known
|
|
576
|
+
step. `out.txt` and the Jobs display remain unchanged.
|
|
577
|
+
- **Evidence-led timeout diagnostics** — timeouts now state that they do not
|
|
578
|
+
identify the cause, list a three-step check, and clarify that an empty
|
|
579
|
+
progress log does not prove Codex made no progress.
|
|
580
|
+
- **Direct rollout recovery path** — timeout output now prints the absolute path
|
|
581
|
+
to the matching `rollout-*.jsonl`, found from the first progress event's
|
|
582
|
+
`thread_id`, so the interrupted conversation history can be inspected.
|
|
583
|
+
|
|
584
|
+
## What's new in v0.14.0
|
|
585
|
+
|
|
586
|
+
- **Evidence-based routing recommendations** — `jobs recommend` and MCP
|
|
587
|
+
`jobs_recommend` rank vendors from completed public job metadata, enforce a
|
|
588
|
+
minimum sample gate, and never change routing automatically.
|
|
589
|
+
- **Opt-in live capability probes** — `doctor --probe V` and MCP
|
|
590
|
+
`provider_probe` distinguish an installed CLI from a working provider call.
|
|
591
|
+
Default doctor remains offline; probe reports never include response bodies.
|
|
592
|
+
- **Search, filter, and export Live Board history** — search and state filters
|
|
593
|
+
cover the latest 50 jobs, while **Export visible** downloads only filtered
|
|
594
|
+
public metadata.
|
|
595
|
+
- **Repeatable quality/cost benchmark** — `omnilane benchmark` ships a fixed
|
|
596
|
+
workload suite, defaults to provider-free dry-run, and requires `--run` for
|
|
597
|
+
actual calls. Cost estimates use only explicit `--cost-per-call` values.
|
|
598
|
+
- **Strict installation acceptance** — CI runs isolated
|
|
599
|
+
`omnilane doctor --strict --json`, catching incomplete runtime wiring without
|
|
600
|
+
contacting providers.
|
|
601
|
+
|
|
550
602
|
## What's new in v0.13.0
|
|
551
603
|
|
|
552
604
|
- **`long-context` is ordered on AA-LCR** — Artificial Analysis's long-context
|
package/README.zh-CN.md
CHANGED
|
@@ -473,6 +473,24 @@ vendor 一律当成 `work`,而且它只能逐次明确指定,永远不是 lane
|
|
|
473
473
|
|
|
474
474
|
## 📜 版本历程
|
|
475
475
|
|
|
476
|
+
## v0.15.0 新功能
|
|
477
|
+
|
|
478
|
+
- **流式保留 Codex 进度证据**:`codex exec --json` 会将 JSONL 事件逐条写入
|
|
479
|
+
`out.txt.progress.log`,即使超时也会留下最后执行到哪一步。`out.txt` 与任务列表显示保持不变。
|
|
480
|
+
- **超时诊断回归证据**:超时提示明确说明它本身不足以判定原因,提供三步检查清单,并说明空的
|
|
481
|
+
进度日志不是 Codex 从未推进的证据。
|
|
482
|
+
- **直接给出 rollout 记录位置**:超时输出会根据第一条进度事件的 `thread_id`,打印
|
|
483
|
+
${CODEX_HOME:-$HOME/.codex}/sessions 下对应 `rollout-*.jsonl` 的绝对路径,便于查看
|
|
484
|
+
被中断而未回报的完整对话历程。
|
|
485
|
+
|
|
486
|
+
## v0.14.0 新功能
|
|
487
|
+
|
|
488
|
+
- **基于证据的路由建议**:`jobs recommend` 与 MCP `jobs_recommend` 只读取公开作业元数据,并且不会自动修改路由。
|
|
489
|
+
- **可选的真实能力探测**:`doctor --probe V` 与 MCP `provider_probe` 仅在明确请求时调用供应商,报告不包含回答正文。
|
|
490
|
+
- **Live Board 历史搜索、筛选与导出**:支持最近 50 条作业,并且只导出当前可见的公开元数据。
|
|
491
|
+
- **固定质量/成本基准**:`omnilane benchmark` 默认只做 dry-run,`--run` 才实际调用供应商。
|
|
492
|
+
- **严格安装验收**:CI 在隔离环境执行 `doctor --strict --json`,并修正 macOS/GNU `stat` 权限检测差异。
|
|
493
|
+
|
|
476
494
|
## v0.13.0 新功能
|
|
477
495
|
|
|
478
496
|
- **`long-context` 改用 AA-LCR 排序**——那是 Artificial Analysis 的长脉络推理基准,
|
package/README.zh-TW.md
CHANGED
|
@@ -178,6 +178,9 @@ omnilane ui stop # 正常停止
|
|
|
178
178
|
`127.0.0.1`、用隨機 token 保護、全程唯讀。畫面只顯示 `task.txt` 與公開的
|
|
179
179
|
`out.txt`,不顯示工作端或廠商原始 log。
|
|
180
180
|
|
|
181
|
+
搜尋與狀態篩選會套用到最近保留的 50 筆工作歷史。按「匯出目前結果」只會把畫面上
|
|
182
|
+
目前可見的公開中繼資料下載成 JSON;不含 token、任務本文、結果本文、工作目錄與原始 log。
|
|
183
|
+
|
|
181
184
|
畫面提供英文、日文、韓文、繁體中文與簡體中文。首次載入依瀏覽器語言決定,可用標題列
|
|
182
185
|
的切換器覆寫,選擇會記在本機。
|
|
183
186
|
|
|
@@ -228,7 +231,7 @@ omnilane ui stop # 正常停止
|
|
|
228
231
|
}
|
|
229
232
|
```
|
|
230
233
|
|
|
231
|
-
Server 提供 `route`,以及一組唯讀查詢工具:`list_lanes`、`explain`、`validate`、`dry_run`、`jobs_list`、`jobs_status`、`jobs_result`、`jobs_stats`、`jobs_audit`、`doctor`。
|
|
234
|
+
Server 提供 `route`,以及一組唯讀查詢工具:`list_lanes`、`explain`、`validate`、`dry_run`、`jobs_list`、`jobs_status`、`jobs_result`、`jobs_stats`、`jobs_recommend`、`jobs_audit`、`doctor`,以及必須明確選用的 `provider_probe`。
|
|
232
235
|
`route` 預設唯讀 `advise` 模式;選 `work` 的呼叫必須同時提供明確的
|
|
233
236
|
`workdir`。
|
|
234
237
|
|
|
@@ -266,7 +269,8 @@ omnilane ui start # 啟動或沿用本機 Live UI,
|
|
|
266
269
|
omnilane ui status # 查看 Live UI 是否運作中
|
|
267
270
|
omnilane ui url # 印出目前通過驗證的本機網址
|
|
268
271
|
omnilane ui stop # 停止 Live UI
|
|
269
|
-
omnilane doctor [--json]
|
|
272
|
+
omnilane doctor [--json] [--strict] [--probe V] [--probe-timeout SEC] # 實際探測必須明確選用
|
|
273
|
+
omnilane benchmark [--json] [--run] [--vendor V] [--cost-per-call V=USD] # 預設只乾跑
|
|
270
274
|
dispatch.sh [--background] [--dry-run] [--mode advise|work|sysops] [--workdir 目錄]
|
|
271
275
|
[--vendor V] [--model M] [--effort E] [--timeout SEC] [--job-timeout SEC]
|
|
272
276
|
通道 "任務" # "-" 表示從 stdin 讀任務
|
|
@@ -279,6 +283,7 @@ jobs.sh wait 工作ID [--timeout N] # 工作結束碼;124 逾
|
|
|
279
283
|
jobs.sh cancel 工作ID # 停止執行中的工作:整組 SIGTERM,再 SIGKILL
|
|
280
284
|
jobs.sh rm 工作ID # 刪除單一已完成/已死工作(執行中會被拒絕)
|
|
281
285
|
jobs.sh [--json] stats [--last N] [--lane L] [--vendor V] # 本機成功率與路由彙整
|
|
286
|
+
jobs.sh [--json] recommend [--last N] [--lane L] [--min-samples N] # 有證據門檻的廠商建議
|
|
282
287
|
jobs.sh audit [--last N] [--json] # 唯讀檢查工作完整性與隱私
|
|
283
288
|
jobs.sh prune [--keep N] [--apply] # 預設只預覽;只清理已完成工作
|
|
284
289
|
omnilane mcp # MCP stdio server(需 Node.js)
|
|
@@ -287,6 +292,15 @@ configure.sh # 互動通道選單
|
|
|
287
292
|
configure.sh set|get|unset|list|diff LANE [SPEC] # 非互動編輯/檢視 routing.local.yaml
|
|
288
293
|
```
|
|
289
294
|
|
|
295
|
+
`jobs recommend` 只讀取通過驗證的公開中繼資料與退出碼。候選達到最低樣本數後,
|
|
296
|
+
依成功率、樣本數、廠商名稱排序;預設至少三筆已完成工作。它不讀任務/結果本文,
|
|
297
|
+
也不修改路由。
|
|
298
|
+
|
|
299
|
+
`doctor --probe V` 只會做一次有逾時上限的 advise 模式供應商呼叫,回傳可用性、
|
|
300
|
+
選到的模型、耗時與回應位元組數,不回傳回答本文;未帶 `--probe` 時仍完全離線。
|
|
301
|
+
`benchmark` 使用 `benchmarks/workloads.tsv` 的固定題組,預設只解析路由、不呼叫供應商;
|
|
302
|
+
`--run` 才是實際呼叫閘門,成本總額也只依 `--cost-per-call` 明確提供的估值計算。
|
|
303
|
+
|
|
290
304
|
**重大決定可以開評審團,不是問一個人。**`arbitrate` 通道**預設關閉**——
|
|
291
305
|
評審團每評審每輪燒一次額度,所以做成選配。要用就在 `routing.local.yaml`
|
|
292
306
|
寫 `arbitrate: vote codex,claude,grok -`,或跑設定選單,從
|
|
@@ -483,6 +497,29 @@ vendor 一律當成 `work`,而且它只能逐次明確指定,永遠不是 lane
|
|
|
483
497
|
|
|
484
498
|
## 📜 版本歷程
|
|
485
499
|
|
|
500
|
+
## v0.15.0 新功能
|
|
501
|
+
|
|
502
|
+
- **串流保留 Codex 進度證據**:`codex exec --json` 會把 JSONL 事件逐筆寫入
|
|
503
|
+
`out.txt.progress.log`,即使逾時也能留下最後做到哪一步。`out.txt` 與工作清單顯示維持不變。
|
|
504
|
+
- **逾時診斷回到證據**:逾時訊息明示它本身不足以判定原因,提供三步檢查清單,並說明空的
|
|
505
|
+
進度日誌不是 Codex 未曾前進的證據。
|
|
506
|
+
- **直接指出 rollout 記錄位置**:逾時輸出會依第一筆進度事件的 `thread_id`,印出
|
|
507
|
+
${CODEX_HOME:-$HOME/.codex}/sessions 下對應 `rollout-*.jsonl` 的絕對路徑,方便查看
|
|
508
|
+
被中斷而未回報的完整對話歷程。
|
|
509
|
+
|
|
510
|
+
## v0.14.0 新功能
|
|
511
|
+
|
|
512
|
+
- **依證據產生路由建議**:`jobs recommend` 與 MCP `jobs_recommend` 只用已完成工作的
|
|
513
|
+
公開中繼資料排序供應商,設有最低樣本門檻,也不會自動修改路由。
|
|
514
|
+
- **選配實際能力探測**:`doctor --probe V` 與 MCP `provider_probe` 可分辨「CLI 已安裝」
|
|
515
|
+
和「供應商呼叫真的可用」。doctor 預設仍離線,探測報告不含回答本文。
|
|
516
|
+
- **Live Board 歷史搜尋、篩選與匯出**:搜尋與狀態篩選涵蓋最近 50 筆工作;
|
|
517
|
+
「匯出目前結果」只下載篩選後的公開中繼資料。
|
|
518
|
+
- **可重現的品質/成本基準**:`omnilane benchmark` 內建固定題組,預設不呼叫供應商;
|
|
519
|
+
`--run` 才會實際執行,成本也只依明確提供的 `--cost-per-call` 估值計算。
|
|
520
|
+
- **嚴格安裝驗收**:CI 以隔離環境執行 `omnilane doctor --strict --json`,
|
|
521
|
+
不接觸供應商也能抓出 runtime 接線不完整。
|
|
522
|
+
|
|
486
523
|
## v0.13.0 新功能
|
|
487
524
|
|
|
488
525
|
- **`long-context` 改用 AA-LCR 排序**——那是 Artificial Analysis 的長脈絡推理基準,
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.15.0
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# id<TAB>preferred_lane<TAB>weight<TAB>Python regex<TAB>prompt
|
|
2
|
+
exact_alpha consult 1 ^ALPHA\s*$ Return exactly ALPHA and nothing else.
|
|
3
|
+
arithmetic consult 2 ^42\s*$ Return only the integer result of 17 + 25.
|
|
4
|
+
json_contract hard-judgment 2 ^\{"status":"pass","count":3\}\s*$ Return exactly this compact JSON object with the stated key order: {"status":"pass","count":3}
|
package/bin/omnilane
CHANGED
|
@@ -52,6 +52,13 @@ case "$cmd" in
|
|
|
52
52
|
;;
|
|
53
53
|
release-audit) exec bash "$REPO/scripts/release-audit.sh" "$@" ;;
|
|
54
54
|
doctor) exec bash "$REPO/scripts/doctor.sh" "$@" ;;
|
|
55
|
+
benchmark)
|
|
56
|
+
command -v python3 >/dev/null 2>&1 || {
|
|
57
|
+
echo "omnilane: benchmark requires Python 3.9 or newer" >&2
|
|
58
|
+
exit 1
|
|
59
|
+
}
|
|
60
|
+
exec python3 "$REPO/scripts/benchmark.py" "$@"
|
|
61
|
+
;;
|
|
55
62
|
ui)
|
|
56
63
|
command -v python3 >/dev/null 2>&1 || {
|
|
57
64
|
echo "omnilane: ui requires Python 3.9 or newer" >&2
|
|
@@ -68,11 +75,12 @@ omnilane — one routing table, every harness
|
|
|
68
75
|
omnilane list effective routing table
|
|
69
76
|
omnilane route [--vendor V] [flags] LANE "TASK"
|
|
70
77
|
dispatch or consult a model
|
|
71
|
-
omnilane jobs [--json] COMMAND [ARGS] list, status, result, stats, wait, or audit
|
|
78
|
+
omnilane jobs [--json] COMMAND [ARGS] list, status, result, stats, recommend, wait, or audit
|
|
72
79
|
omnilane mcp start the MCP stdio server
|
|
73
80
|
omnilane completion bash|zsh|fish print a shell completion script
|
|
74
81
|
omnilane release-audit [flags] offline, read-only release gate
|
|
75
|
-
omnilane doctor [--json]
|
|
82
|
+
omnilane doctor [--json] [--strict] [--probe V] local health / opt-in live probe
|
|
83
|
+
omnilane benchmark [--json] [--run] [--vendor V] fixed quality/cost comparison
|
|
76
84
|
omnilane ui start|status|url|stop
|
|
77
85
|
omnilane configure interactive lane menu
|
|
78
86
|
EOF
|
package/bin/omnilane-mcp
CHANGED
|
@@ -10,6 +10,8 @@ const ROOT = path.resolve(__dirname, '..');
|
|
|
10
10
|
const DISPATCH_SCRIPT = path.join(ROOT, 'scripts', 'dispatch.sh');
|
|
11
11
|
const JOBS_SCRIPT = path.join(ROOT, 'scripts', 'jobs.sh');
|
|
12
12
|
const DOCTOR_SCRIPT = path.join(ROOT, 'scripts', 'doctor.sh');
|
|
13
|
+
const PROVIDER_PROBE_SCRIPT = process.env.OMNILANE_PROVIDER_PROBE_SCRIPT ||
|
|
14
|
+
path.join(ROOT, 'scripts', 'provider-probe.sh');
|
|
13
15
|
const LATEST_PROTOCOL_VERSION = '2025-11-25';
|
|
14
16
|
const SUPPORTED_PROTOCOL_VERSIONS = new Set([
|
|
15
17
|
'2025-11-25',
|
|
@@ -285,6 +287,37 @@ const tools = [
|
|
|
285
287
|
openWorldHint: false,
|
|
286
288
|
},
|
|
287
289
|
},
|
|
290
|
+
{
|
|
291
|
+
name: 'provider_probe',
|
|
292
|
+
description: 'Explicitly invoke one configured provider with a bounded fixed prompt to verify live inference. Incurs one provider call; never returns the provider response.',
|
|
293
|
+
inputSchema: {
|
|
294
|
+
type: 'object',
|
|
295
|
+
required: ['vendor'],
|
|
296
|
+
properties: {
|
|
297
|
+
vendor: {
|
|
298
|
+
type: 'string',
|
|
299
|
+
enum: ['codex', 'claude', 'grok', 'gemini', 'kimi', 'qwen', 'opencode', 'openrouter', 'deepseek', 'zai', 'mistral', 'groq', 'cerebras'],
|
|
300
|
+
},
|
|
301
|
+
timeout: {
|
|
302
|
+
type: 'integer',
|
|
303
|
+
minimum: 1,
|
|
304
|
+
maximum: 300,
|
|
305
|
+
default: 30,
|
|
306
|
+
},
|
|
307
|
+
json: {
|
|
308
|
+
type: 'boolean',
|
|
309
|
+
default: true,
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
additionalProperties: false,
|
|
313
|
+
},
|
|
314
|
+
annotations: {
|
|
315
|
+
readOnlyHint: true,
|
|
316
|
+
destructiveHint: false,
|
|
317
|
+
idempotentHint: false,
|
|
318
|
+
openWorldHint: true,
|
|
319
|
+
},
|
|
320
|
+
},
|
|
288
321
|
{
|
|
289
322
|
name: 'jobs_stats',
|
|
290
323
|
description: 'Aggregate local background-job outcomes and lane/vendor distribution from bounded public metadata. Never reads task or result bodies.',
|
|
@@ -311,6 +344,45 @@ const tools = [
|
|
|
311
344
|
openWorldHint: false,
|
|
312
345
|
},
|
|
313
346
|
},
|
|
347
|
+
{
|
|
348
|
+
name: 'jobs_recommend',
|
|
349
|
+
description: 'Recommend a vendor per lane from bounded local completed-job outcomes. Read-only, evidence-gated, and never reads task or result bodies.',
|
|
350
|
+
inputSchema: {
|
|
351
|
+
type: 'object',
|
|
352
|
+
properties: {
|
|
353
|
+
last: {
|
|
354
|
+
type: 'integer',
|
|
355
|
+
minimum: 1,
|
|
356
|
+
maximum: 10000,
|
|
357
|
+
description: 'Limit analysis to the most recent N jobs.',
|
|
358
|
+
},
|
|
359
|
+
lane: {
|
|
360
|
+
type: 'string',
|
|
361
|
+
pattern: '^[a-z][a-z0-9-]*$',
|
|
362
|
+
description: 'Optionally analyze one lane.',
|
|
363
|
+
},
|
|
364
|
+
min_samples: {
|
|
365
|
+
type: 'integer',
|
|
366
|
+
minimum: 1,
|
|
367
|
+
maximum: 1000,
|
|
368
|
+
default: 3,
|
|
369
|
+
description: 'Completed samples required before a vendor is eligible for recommendation.',
|
|
370
|
+
},
|
|
371
|
+
json: {
|
|
372
|
+
type: 'boolean',
|
|
373
|
+
default: false,
|
|
374
|
+
description: 'Return the versioned JSON envelope instead of the human report.',
|
|
375
|
+
},
|
|
376
|
+
},
|
|
377
|
+
additionalProperties: false,
|
|
378
|
+
},
|
|
379
|
+
annotations: {
|
|
380
|
+
readOnlyHint: true,
|
|
381
|
+
destructiveHint: false,
|
|
382
|
+
idempotentHint: true,
|
|
383
|
+
openWorldHint: false,
|
|
384
|
+
},
|
|
385
|
+
},
|
|
314
386
|
{
|
|
315
387
|
name: 'jobs_audit',
|
|
316
388
|
description: 'Bounded read-only integrity and privacy scan of the local job store. Reports findings without printing task or result content.',
|
|
@@ -435,6 +507,24 @@ function validateJsonOnlyArguments(args) {
|
|
|
435
507
|
return null;
|
|
436
508
|
}
|
|
437
509
|
|
|
510
|
+
function validateProviderProbeArguments(args) {
|
|
511
|
+
const error = validationError(args, ['vendor', 'timeout', 'json']);
|
|
512
|
+
if (error) return error;
|
|
513
|
+
const vendors = new Set([
|
|
514
|
+
'codex', 'claude', 'grok', 'gemini', 'kimi', 'qwen', 'opencode',
|
|
515
|
+
'openrouter', 'deepseek', 'zai', 'mistral', 'groq', 'cerebras',
|
|
516
|
+
]);
|
|
517
|
+
if (typeof args.vendor !== 'string' || !vendors.has(args.vendor)) {
|
|
518
|
+
return 'vendor must name one probe-capable provider';
|
|
519
|
+
}
|
|
520
|
+
if (OWN(args, 'timeout') &&
|
|
521
|
+
(!Number.isInteger(args.timeout) || args.timeout < 1 || args.timeout > 300)) {
|
|
522
|
+
return 'timeout must be an integer from 1 to 300';
|
|
523
|
+
}
|
|
524
|
+
if (OWN(args, 'json') && typeof args.json !== 'boolean') return 'json must be a boolean';
|
|
525
|
+
return null;
|
|
526
|
+
}
|
|
527
|
+
|
|
438
528
|
function validateJobsQueryArguments(args) {
|
|
439
529
|
const error = validationError(args, ['last', 'json']);
|
|
440
530
|
if (error) return error;
|
|
@@ -445,6 +535,23 @@ function validateJobsQueryArguments(args) {
|
|
|
445
535
|
return null;
|
|
446
536
|
}
|
|
447
537
|
|
|
538
|
+
function validateJobsRecommendArguments(args) {
|
|
539
|
+
const error = validationError(args, ['last', 'lane', 'min_samples', 'json']);
|
|
540
|
+
if (error) return error;
|
|
541
|
+
if (OWN(args, 'last') && (!Number.isInteger(args.last) || args.last < 1 || args.last > 10000)) {
|
|
542
|
+
return 'last must be an integer from 1 to 10000';
|
|
543
|
+
}
|
|
544
|
+
if (OWN(args, 'lane') && (typeof args.lane !== 'string' || !LANE_PATTERN.test(args.lane))) {
|
|
545
|
+
return 'lane must match ^[a-z][a-z0-9-]*$';
|
|
546
|
+
}
|
|
547
|
+
if (OWN(args, 'min_samples') &&
|
|
548
|
+
(!Number.isInteger(args.min_samples) || args.min_samples < 1 || args.min_samples > 1000)) {
|
|
549
|
+
return 'min_samples must be an integer from 1 to 1000';
|
|
550
|
+
}
|
|
551
|
+
if (OWN(args, 'json') && typeof args.json !== 'boolean') return 'json must be a boolean';
|
|
552
|
+
return null;
|
|
553
|
+
}
|
|
554
|
+
|
|
448
555
|
function validateExplainArguments(args) {
|
|
449
556
|
const error = validationError(args, ['lane', 'json']);
|
|
450
557
|
if (error) return error;
|
|
@@ -645,6 +752,14 @@ async function callTool(name, args) {
|
|
|
645
752
|
const argv = args.json === true ? ['--json'] : [];
|
|
646
753
|
return runToolScript('doctor', DOCTOR_SCRIPT, argv);
|
|
647
754
|
}
|
|
755
|
+
if (name === 'provider_probe') {
|
|
756
|
+
const error = validateProviderProbeArguments(args);
|
|
757
|
+
if (error) return toolError(error);
|
|
758
|
+
const argv = ['--vendor', args.vendor];
|
|
759
|
+
if (OWN(args, 'timeout')) argv.push('--timeout', String(args.timeout));
|
|
760
|
+
if (args.json !== false) argv.push('--json');
|
|
761
|
+
return runToolScript('provider_probe', PROVIDER_PROBE_SCRIPT, argv);
|
|
762
|
+
}
|
|
648
763
|
if (name === 'jobs_stats' || name === 'jobs_audit') {
|
|
649
764
|
const error = validateJobsQueryArguments(args);
|
|
650
765
|
if (error) return toolError(error);
|
|
@@ -654,6 +769,17 @@ async function callTool(name, args) {
|
|
|
654
769
|
if (OWN(args, 'last')) argv.push('--last', String(args.last));
|
|
655
770
|
return runToolScript(name, JOBS_SCRIPT, argv);
|
|
656
771
|
}
|
|
772
|
+
if (name === 'jobs_recommend') {
|
|
773
|
+
const error = validateJobsRecommendArguments(args);
|
|
774
|
+
if (error) return toolError(error);
|
|
775
|
+
const argv = [];
|
|
776
|
+
if (args.json === true) argv.push('--json');
|
|
777
|
+
argv.push('recommend');
|
|
778
|
+
if (OWN(args, 'last')) argv.push('--last', String(args.last));
|
|
779
|
+
if (OWN(args, 'lane')) argv.push('--lane', args.lane);
|
|
780
|
+
if (OWN(args, 'min_samples')) argv.push('--min-samples', String(args.min_samples));
|
|
781
|
+
return runToolScript(name, JOBS_SCRIPT, argv);
|
|
782
|
+
}
|
|
657
783
|
throw new RpcError(-32602, `Unknown tool: ${name}`);
|
|
658
784
|
}
|
|
659
785
|
|
package/completions/_omnilane
CHANGED
|
@@ -53,7 +53,7 @@ _omnilane() {
|
|
|
53
53
|
local command="${words[2]:-}" sub sub_index=3
|
|
54
54
|
local -a lanes ids
|
|
55
55
|
if (( CURRENT == 2 )); then
|
|
56
|
-
_values 'command' version list route dispatch jobs doctor release-audit ui configure completion help
|
|
56
|
+
_values 'command' version list route dispatch jobs doctor benchmark release-audit ui configure completion help
|
|
57
57
|
return
|
|
58
58
|
fi
|
|
59
59
|
case "$command" in
|
|
@@ -78,7 +78,7 @@ _omnilane() {
|
|
|
78
78
|
sub="${words[4]:-}"
|
|
79
79
|
fi
|
|
80
80
|
if (( CURRENT == sub_index )); then
|
|
81
|
-
_values 'job command' list status result tail retry stats wait audit prune help
|
|
81
|
+
_values 'job command' list status result tail retry stats recommend wait audit prune help
|
|
82
82
|
elif (( CURRENT == sub_index + 1 )) &&
|
|
83
83
|
[[ "$sub" == status || "$sub" == result || "$sub" == wait ||
|
|
84
84
|
"$sub" == tail || "$sub" == retry ]]; then
|
|
@@ -92,7 +92,13 @@ _omnilane() {
|
|
|
92
92
|
_arguments '--background[re-dispatch in the background]'
|
|
93
93
|
elif [[ "$sub" == wait ]]; then
|
|
94
94
|
_arguments '--timeout[maximum wait seconds]:seconds:'
|
|
95
|
-
elif [[ "$sub" == stats
|
|
95
|
+
elif [[ "$sub" == stats ]]; then
|
|
96
|
+
_arguments '--last[maximum jobs]:count:' '--lane[filter by lane]:lane:' \
|
|
97
|
+
'--vendor[filter by vendor]:vendor:' '--json[versioned metadata output]'
|
|
98
|
+
elif [[ "$sub" == recommend ]]; then
|
|
99
|
+
_arguments '--last[maximum jobs]:count:' '--lane[filter by lane]:lane:' \
|
|
100
|
+
'--min-samples[minimum completed samples]:count:' '--json[versioned metadata output]'
|
|
101
|
+
elif [[ "$sub" == audit ]]; then
|
|
96
102
|
_arguments '--last[maximum jobs]:count:' '--json[versioned metadata output]'
|
|
97
103
|
elif [[ "$sub" == prune ]]; then
|
|
98
104
|
_arguments '--keep[completed jobs to retain]:count:' \
|
|
@@ -100,7 +106,18 @@ _omnilane() {
|
|
|
100
106
|
'--apply[delete eligible jobs]'
|
|
101
107
|
fi
|
|
102
108
|
;;
|
|
103
|
-
doctor)
|
|
109
|
+
doctor)
|
|
110
|
+
_arguments '--json[versioned JSON output]' '--strict[fail on warnings]' \
|
|
111
|
+
'--probe[run one opt-in live provider probe]:vendor:' \
|
|
112
|
+
'--probe-timeout[probe timeout in seconds]:seconds:'
|
|
113
|
+
;;
|
|
114
|
+
benchmark)
|
|
115
|
+
_arguments '--json[versioned JSON output]' '--run[invoke providers in advise mode]' \
|
|
116
|
+
'*--vendor[vendor to compare]:vendor:(codex claude grok gemini kimi qwen opencode openrouter deepseek zai mistral groq cerebras)' \
|
|
117
|
+
'--timeout[per-workload timeout]:seconds:' \
|
|
118
|
+
'--workloads[TSV workload file]:file:_files' \
|
|
119
|
+
'*--cost-per-call[user-supplied vendor USD estimate]:vendor=USD:'
|
|
120
|
+
;;
|
|
104
121
|
release-audit)
|
|
105
122
|
_arguments '--target[release version]:version:' '--allow-dirty[permit a dirty worktree]' \
|
|
106
123
|
'--require-tag[require an annotated tag at HEAD]' '--manifest[include tracked inventory]' \
|
|
@@ -58,7 +58,7 @@ _omnilane() {
|
|
|
58
58
|
prev="${COMP_WORDS[COMP_CWORD-1]:-}"
|
|
59
59
|
command="${COMP_WORDS[1]:-}"
|
|
60
60
|
if [[ "$COMP_CWORD" -eq 1 ]]; then
|
|
61
|
-
|
|
61
|
+
words="version list route dispatch jobs doctor benchmark release-audit ui configure completion help"
|
|
62
62
|
else
|
|
63
63
|
case "$command" in
|
|
64
64
|
route|dispatch)
|
|
@@ -84,7 +84,7 @@ _omnilane() {
|
|
|
84
84
|
sub="${COMP_WORDS[3]:-}"
|
|
85
85
|
fi
|
|
86
86
|
if [[ "$COMP_CWORD" -eq "$sub_index" ]]; then
|
|
87
|
-
words="list status result tail retry stats wait audit prune help"
|
|
87
|
+
words="list status result tail retry stats recommend wait audit prune help"
|
|
88
88
|
elif [[ "$COMP_CWORD" -eq $((sub_index + 1)) &&
|
|
89
89
|
( "$sub" == status || "$sub" == result || "$sub" == wait ||
|
|
90
90
|
"$sub" == tail || "$sub" == retry ) ]]; then
|
|
@@ -99,7 +99,11 @@ _omnilane() {
|
|
|
99
99
|
words="--background"
|
|
100
100
|
elif [[ "$sub" == wait ]]; then
|
|
101
101
|
words="--timeout"
|
|
102
|
-
elif [[ "$sub" == stats
|
|
102
|
+
elif [[ "$sub" == stats ]]; then
|
|
103
|
+
words="--last --lane --vendor --json"
|
|
104
|
+
elif [[ "$sub" == recommend ]]; then
|
|
105
|
+
words="--last --lane --min-samples --json"
|
|
106
|
+
elif [[ "$sub" == audit ]]; then
|
|
103
107
|
words="--last --json"
|
|
104
108
|
elif [[ "$sub" == prune ]]; then
|
|
105
109
|
words="--keep --older-than --apply"
|
|
@@ -107,7 +111,18 @@ _omnilane() {
|
|
|
107
111
|
return
|
|
108
112
|
fi
|
|
109
113
|
;;
|
|
110
|
-
doctor) words="--json" ;;
|
|
114
|
+
doctor) words="--json --strict --probe --probe-timeout" ;;
|
|
115
|
+
benchmark)
|
|
116
|
+
case "$prev" in
|
|
117
|
+
--vendor) words="codex claude grok gemini kimi qwen opencode openrouter deepseek zai mistral groq cerebras" ;;
|
|
118
|
+
--workloads)
|
|
119
|
+
COMPREPLY=( $(compgen -f -- "$cur") )
|
|
120
|
+
return
|
|
121
|
+
;;
|
|
122
|
+
--timeout|--cost-per-call) return ;;
|
|
123
|
+
*) words="--json --run --vendor --timeout --workloads --cost-per-call" ;;
|
|
124
|
+
esac
|
|
125
|
+
;;
|
|
111
126
|
release-audit) words="--target --allow-dirty --require-tag --manifest --json" ;;
|
|
112
127
|
ui) words="start status url stop" ;;
|
|
113
128
|
completion) words="bash zsh" ;;
|