open-tui-orchestrator 0.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +205 -0
- package/INSTALL-zh.md +96 -0
- package/INSTALL.md +96 -0
- package/LICENSE +48 -0
- package/README-zh.md +181 -0
- package/README.md +181 -0
- package/cli.mjs +37 -0
- package/docs/adapt.md +103 -0
- package/docs/assets/kimicode-agent-swarm-10-subagents.png +0 -0
- package/docs/auto-recovery.md +23 -0
- package/docs/caller-driven.md +121 -0
- package/docs/claude-adapter.md +25 -0
- package/docs/execution-contract.md +70 -0
- package/docs/inactive-windows.md +11 -0
- package/docs/kimi-adapter.md +27 -0
- package/docs/kimi-integration.md +56 -0
- package/docs/maintenance-lock.md +32 -0
- package/docs/openclaw-adapter.md +59 -0
- package/docs/openclaw-assessment-2026-09-06.md +59 -0
- package/docs/opencode-adapter.md +25 -0
- package/docs/pi-adapter.md +58 -0
- package/docs/public-readiness.md +63 -0
- package/docs/release-policy.md +39 -0
- package/docs/security-audit-2026-09-09.md +41 -0
- package/docs/trust-and-safety.md +64 -0
- package/docs/verification-2026-09-06.md +22 -0
- package/docs/verification-recovery-2026-09-06.md +36 -0
- package/orch.mjs +20 -0
- package/package.json +36 -0
- package/release.json +116 -0
- package/repair.mjs +228 -0
- package/scripts/adapt.mjs +35 -0
- package/scripts/agent-auth-prompt.txt +10 -0
- package/scripts/agent.mjs +1 -0
- package/scripts/core/adapt-lib.mjs +219 -0
- package/scripts/core/agent-auth-prompt.txt +10 -0
- package/scripts/core/agent-profiles/hermes.json +59 -0
- package/scripts/core/agent.mjs +1 -0
- package/scripts/core/checkpoint.mjs +38 -0
- package/scripts/core/claude-host.mjs +50 -0
- package/scripts/core/claude-runtime.mjs +111 -0
- package/scripts/core/contracts.mjs +161 -0
- package/scripts/core/host-cli.mjs +204 -0
- package/scripts/core/host-model.mjs +323 -0
- package/scripts/core/host-probe.mjs +16 -0
- package/scripts/core/inactive-window.mjs +32 -0
- package/scripts/core/inactive-window.ps1 +36 -0
- package/scripts/core/kimi-host.mjs +41 -0
- package/scripts/core/kimi-runtime.mjs +140 -0
- package/scripts/core/lease-lock.ps1 +32 -0
- package/scripts/core/leases.mjs +176 -0
- package/scripts/core/maintenance-lock.mjs +77 -0
- package/scripts/core/native-argv.mjs +9 -0
- package/scripts/core/network-policy.mjs +18 -0
- package/scripts/core/openclaw-bootstrap.mjs +25 -0
- package/scripts/core/openclaw-config.mjs +35 -0
- package/scripts/core/openclaw-host.mjs +29 -0
- package/scripts/core/openclaw-runtime.mjs +33 -0
- package/scripts/core/openclaw-window.mjs +44 -0
- package/scripts/core/opencode-host.mjs +80 -0
- package/scripts/core/opencode-runtime.mjs +131 -0
- package/scripts/core/orchestrate-sdk.mjs +2595 -0
- package/scripts/core/pi-host.mjs +29 -0
- package/scripts/core/pi-runtime.mjs +54 -0
- package/scripts/core/pi-shutdown.mjs +16 -0
- package/scripts/core/poll-windows.mjs +48 -0
- package/scripts/core/print-profile.mjs +79 -0
- package/scripts/core/print-runtime.mjs +106 -0
- package/scripts/core/pty-host.mjs +38 -0
- package/scripts/core/recovery.mjs +75 -0
- package/scripts/core/run-board.mjs +155 -0
- package/scripts/core/run-guardian.mjs +130 -0
- package/scripts/core/runner.mjs +274 -0
- package/scripts/core/runtime-context.mjs +23 -0
- package/scripts/core/unit-carrier.mjs +55 -0
- package/scripts/core/unit-command.mjs +96 -0
- package/scripts/core/unit-runtime.mjs +107 -0
- package/scripts/gate.mjs +162 -0
- package/scripts/host-cli.mjs +2 -0
- package/scripts/install-deps.mjs +58 -0
- package/scripts/maintenance-lock.mjs +46 -0
- package/scripts/network-policy.mjs +2 -0
- package/scripts/open-tui-orchestrator-force.mjs +239 -0
- package/scripts/open-tui-orchestrator-preflight.mjs +85 -0
- package/scripts/orchestrate-sdk.mjs +59 -0
- package/scripts/package-lock.json +242 -0
- package/scripts/package.json +9 -0
- package/scripts/platform-guard.mjs +23 -0
- package/scripts/poll-windows.mjs +8 -0
- package/scripts/release-integrity.mjs +94 -0
- package/scripts/runtime-context.mjs +2 -0
- package/scripts/sdk-dependency-check.mjs +32 -0
- package/scripts/todo-list.mjs +89 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# What this tool does on your machine (trust statement)
|
|
2
|
+
|
|
3
|
+
Read this before you run it. It is written to be specific rather than reassuring: every claim
|
|
4
|
+
here is checkable in the source, and behaviour that deviates from this page is a defect.
|
|
5
|
+
|
|
6
|
+
## It launches your own agent CLI — several of them at once
|
|
7
|
+
|
|
8
|
+
- A run splits your request into blocks and starts one process per block, using the agent CLI
|
|
9
|
+
you already have installed and authenticated (`codex`, `pi`, `opencode`, `kimi`, `claude`,
|
|
10
|
+
`openclaw`, or a CLI you adapt). It never installs an agent, never guesses a replacement
|
|
11
|
+
path, and never silently falls back to a different agent.
|
|
12
|
+
- By default those processes are **headless and invisible**: no window, no taskbar entry, no
|
|
13
|
+
focus stealing. `--mode window` restores visible Windows Terminal windows when you want to
|
|
14
|
+
watch. The hidden carrier is a ConPTY pseudo-terminal (for TUI-class agents) or a
|
|
15
|
+
no-console process (for print-class CLIs) — either way it is a real console you cannot see.
|
|
16
|
+
- **The agent's own permission model is not raised by this tool, but it is often bypassed for
|
|
17
|
+
convenience**: Codex-hosted runs pass `--dangerously-bypass-approvals-and-sandbox`, which is
|
|
18
|
+
the documented way to run Codex non-interactively. That means the agent will not stop to ask
|
|
19
|
+
you before acting inside the block it was given. Do not point this tool at work you would not
|
|
20
|
+
let an unattended agent do. For other hosts the tool uses that host's own non-interactive
|
|
21
|
+
flags; read them in `scripts/core/agent-profiles/*.json` and `scripts/core/hosts.mjs`.
|
|
22
|
+
- `--unit-cmd` / `--unit-cmd-file` let **the caller** supply the exact command that runs per
|
|
23
|
+
block. That is an explicit authorization from you (or from the agent that calls it): the tool
|
|
24
|
+
runs what you named, in your workspace, with your credentials. Treat it exactly like running
|
|
25
|
+
that command yourself.
|
|
26
|
+
|
|
27
|
+
## Files it writes
|
|
28
|
+
|
|
29
|
+
- **Per run**: `<workspace>\temp\orchestrator\` — the run directory, plan, per-block receipts,
|
|
30
|
+
`events.jsonl`, window/lease pid files, and the acceptance file you asked for. Deleting this
|
|
31
|
+
directory while nothing is running is safe; it is the tool's whole state.
|
|
32
|
+
- **Machine-level coordinator**: one registry value
|
|
33
|
+
`HKCU\Software\TuiOrchestrator\CoordinatorRoot` pointing at the coordinator directory inside
|
|
34
|
+
the **first** initiating workspace's `temp\orchestrator`. It holds the global capacity lease
|
|
35
|
+
file and short-lived mutex tickets so that two orchestrator runs (or two agents) cannot
|
|
36
|
+
overbook the machine. `ORCH_COORDINATOR_DIR` overrides it.
|
|
37
|
+
- **Release copies**: implementations live under your user directory
|
|
38
|
+
(`~/.tools/releases/<version>/open-tui-orchestrator`), switched by a junction; the tool does
|
|
39
|
+
not write to `Program Files`, the registry outside the key above, or other users' profiles.
|
|
40
|
+
- It does **not** modify your agent CLIs' configuration, credentials or session stores. Setting
|
|
41
|
+
them is out of scope: the tool only reads what it needs to inherit your model/effort choice.
|
|
42
|
+
|
|
43
|
+
## Network, telemetry, background services
|
|
44
|
+
|
|
45
|
+
- No telemetry, no analytics, no phone-home, no auto-update, no daemon. When nothing is
|
|
46
|
+
running, nothing of this tool is running.
|
|
47
|
+
- The only network access it initiates is installing **its own** locked dependencies
|
|
48
|
+
(`node cli.mjs --install-deps`, `npm ci` against the public registry — the same thing
|
|
49
|
+
`npm install` did) and whatever your agent CLI does on its own behalf. `ORCH_NPM_BIN` points
|
|
50
|
+
that install at your own or your company's npm.
|
|
51
|
+
- Your prompts, model settings and the files the agents touch go to **your** agent CLI and its
|
|
52
|
+
model provider under your own account — not to this project.
|
|
53
|
+
|
|
54
|
+
## Reading before trusting
|
|
55
|
+
|
|
56
|
+
- `release.json` carries SHA-256 hashes of every execution-core and runtime file; the entry
|
|
57
|
+
points verify them on every start and refuse to run on a mismatch
|
|
58
|
+
(`RELEASE_INTEGRITY_FAILED`). `node scripts/release-integrity.mjs` re-verifies on demand and
|
|
59
|
+
prints the exact counts for the release you have.
|
|
60
|
+
- `scripts/gate.mjs` is the machine gate: it runs the offline regression suite, the host
|
|
61
|
+
check, a deliberately failing test (proving the criteria can go red), the unknown-run
|
|
62
|
+
diagnostic, and the version/seal/docs cross-check.
|
|
63
|
+
- Removal: delete the release copies and the junction, drop `HKCU\Software\TuiOrchestrator`,
|
|
64
|
+
and delete the workspaces' `temp\orchestrator` directories. Nothing else is left behind.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# 2026-09-06 执行逻辑加固与验证
|
|
2
|
+
|
|
3
|
+
两套入口复用同一份 core 1.0.1。专用插件源码与当前启用缓存都已同步。
|
|
4
|
+
|
|
5
|
+
已落实:原始任务清单逐项保留;任务与块两层依赖校验;路径别名及目录包含冲突;跨批次共享窗口额度;每批独立 run ID、结果与回执;主控独立验收;进程身份核对后关闭;核心版本参与规划缓存。另修复 Windows PowerShell 原生参数引号丢失,以及 --status 入口遗漏。
|
|
6
|
+
|
|
7
|
+
最大块数为“标称内存 GB 的 3/4”:标称内存 GB = round(内存GB × 1024 ÷ 1000),最大窗口数 = round(标称 GB × 3 ÷ 4)。超出的任务合并进已有块串行,不新增容量批次。原始任务全部进入结果清单,未验收、被阻塞或失败都不能冒充成功。
|
|
8
|
+
|
|
9
|
+
验证结果:
|
|
10
|
+
|
|
11
|
+
- open 与 Codex 专用入口:各 106/106 项回归通过。
|
|
12
|
+
- 两套真实验收:各 8 窗、9 任务;确认 8 个活跃 Codex 子进程与探针同时重叠;第 9 项在合并块中串行;结果全部通过主控检查;窗口全部关闭。
|
|
13
|
+
- 16 个真实会话元数据均为 cwd=D:\、approval=never、provider=orchestrator-openai-https。
|
|
14
|
+
- 9 个独立父进程竞争 8 个共享名额:恰好 8 个获得名额,第 9 个被容量条件拦住;无覆盖丢失。
|
|
15
|
+
- 发布检查:12 个核心源文件可物化成独立包,内容逐字节一致。
|
|
16
|
+
- 实测后仅恢复 --status 命令分派,已额外跑完整回归;真实执行路径未改。
|
|
17
|
+
|
|
18
|
+
第一轮探针因一个窗口自行改变命令工作目录而重跑,时间重叠断言未通过,已保留失败记录。明确继承目录并把目录断言前移后,两套完整实测均通过。
|
|
19
|
+
|
|
20
|
+
完整证据见 [reliability-live-result.json](../test/reliability-live-result.json),包含运行编号、逐项验收结果、会话元数据和核心文件哈希。[执行协议](execution-contract.md) 说明主控如何自动准备验收条件,无需用户批准 TUI 操作。
|
|
21
|
+
|
|
22
|
+
清理限制:宿主自动审批检查拒绝删除本轮三个一次性探针目录,仅返回 host automatic approval review denied cleanup,未提供具体规则。未绕过;具体目录保存在证据报告 cleanup 中。该拦截发生在主控清理环节,不是 TUI 内的手动执行审批。
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# 中断恢复与依赖调度验收
|
|
2
|
+
|
|
3
|
+
本轮完成两项改动:逐任务保存执行进度并恢复剩余工作;后续块仅等待自身前置块通过验收。两套入口共用 core 1.1.0,专用源码与当前启用缓存均已同步。
|
|
4
|
+
|
|
5
|
+
- 内存公式为“标称内存 GB 的 3/4”:标称内存 GB = `round(内存GB × 1024 ÷ 1000)`,最大窗口数 = `round(标称 GB × 3 ÷ 4)`;总块数不超过上限,多余任务在已有块内串行。
|
|
6
|
+
- 启动器不再整块盲目重跑。已验证任务不会重做;仍存活的窗口由新主持接管。
|
|
7
|
+
- 开始执行、完成执行、验收通过分别记录。复验失败也保留执行证据,避免检查点文件缺失后误当作未执行。
|
|
8
|
+
- 同一批次只能有一个活跃主持。无法证明结果的已开始任务保留在清单中,由主控核查;只有已明确可安全重复的操作才允许自动重试。
|
|
9
|
+
- 工作目录仍来自发起对话,编排状态存于工作区 temp;审批为 never,Codex 传输使用 HTTPS。
|
|
10
|
+
|
|
11
|
+
## 验证结果
|
|
12
|
+
|
|
13
|
+
| 验证 | 结果 |
|
|
14
|
+
|---|---|
|
|
15
|
+
| open 完整回归 | 115/115 通过 |
|
|
16
|
+
| 专用入口完整回归 | 115/115 通过 |
|
|
17
|
+
| open 真实容量测试 | 8 个窗口完成 9 项任务,8 个探针重叠 17.055 秒 |
|
|
18
|
+
| 多余任务串行 | 第 9 项在同块第 8 项完成后开始 |
|
|
19
|
+
| 真实主持中断 | 只终止测试主持,专用入口接管同一个存活窗口;第一项只执行一次 |
|
|
20
|
+
| 已完成批次恢复 | 最终代码重新恢复成功,未增加窗口或执行尝试 |
|
|
21
|
+
| 运行策略 | 10 个实测 TUI 会话均为 D:\、never、danger-full-access、orchestrator-openai-https |
|
|
22
|
+
| 收尾 | 测试窗口均已关闭 |
|
|
23
|
+
|
|
24
|
+
真实 8 窗容量与主持中断测试后,补了一处“复验失败仍保留检查点”的小修正。最终代码通过两套 115 项回归和已完成真实批次的恢复核验;没有将较早的 8 窗测试伪称为补丁后的重新实测。报告分别记录实测时与最终代码的哈希。
|
|
25
|
+
|
|
26
|
+
第一次容量请求因新增逗号产生无法归属的片段,触发完整清单串行兜底。9 项任务虽全部完成,但只有 1 窗,因此该次容量验收明确失败;修正测试请求后重测才通过。保守规划和路径推断仍可能降低并发效率,后续优化应继续以不丢任务、不制造写入冲突为前提。
|
|
27
|
+
|
|
28
|
+
## 证据与复现
|
|
29
|
+
|
|
30
|
+
紧凑证据见 [recovery-live-result.json](../test/recovery-live-result.json),包含批次 ID、代码哈希、窗口数量、执行时间、会话策略及最终回归结果。
|
|
31
|
+
|
|
32
|
+
从目标工作目录调用测试脚本的绝对路径:`test/live-codex.mjs` 验证 8 窗与 9 项任务;`test/live-recovery.mjs` 验证真实主持中断和原窗接管。通过 ORCH_LIVE_ENTRY 指定专用入口。真实测试会使用已配置模型的额度。
|
|
33
|
+
|
|
34
|
+
运行 `node --test test/*.test.mjs` 验证离线与受控进程场景。`test/collect-recovery-evidence.mjs` 在原始测试输出与回归日志仍保留时汇总本轮证据。
|
|
35
|
+
|
|
36
|
+
临时探针和日志的收尾删除被宿主自动审批拒绝,返回 host automatic approval review denied cleanup;没有提供更具体原因。原文件按实际状态保留,未换用其它工具绕过。TUI 执行全程不需要手动批准,此拒绝发生在测试后的清理操作。
|
package/orch.mjs
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// orch — open-tui-orchestrator 强制编排入口。
|
|
3
|
+
// 与常规 --run-windows 完全相同,但跳过所有 inline 回退门:单块、纯串行、只读定性、
|
|
4
|
+
// 自改请求都会照常派发执行单元(headless 默认,--mode window 可切弹窗)。
|
|
5
|
+
// 唯一仍然生效的门是维护锁:锁定期调用照旧只回固定话术并放行。
|
|
6
|
+
// 用法: orch [--mode headless|exec|window] [--run-id id] [--acceptance-file f] <请求...>
|
|
7
|
+
import { spawn } from 'node:child_process';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import { enforceWindowsOnly } from './scripts/platform-guard.mjs';
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
if (!args.length) {
|
|
12
|
+
console.log('usage: orch [--mode headless|exec|window] [--run-id id] [--acceptance-file file] [--plan-file f] [--unit-cmd json | --unit-cmd-file f] <request>');
|
|
13
|
+
process.exit(2);
|
|
14
|
+
}
|
|
15
|
+
if (enforceWindowsOnly(args)) process.exit(1);
|
|
16
|
+
const child = spawn(process.execPath, [fileURLToPath(new URL('./cli.mjs', import.meta.url)), '--run-windows', ...args], {
|
|
17
|
+
stdio: 'inherit', windowsHide: true, env: { ...process.env, ORCH_FORCE_EXECUTE: '1' },
|
|
18
|
+
});
|
|
19
|
+
child.on('error', error => { console.error(error.message); process.exitCode = 1; });
|
|
20
|
+
child.on('exit', code => { process.exitCode = code ?? 1; });
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "open-tui-orchestrator",
|
|
3
|
+
"version": "0.9.6",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Split a multi-part agent request into a verified TODO ledger, then run the parallel blocks in hidden or visible TUI windows of the agent CLI you already use (Windows).",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": { "open-tui-orchestrator": "cli.mjs", "orch": "orch.mjs", "orch-adapt": "scripts/adapt.mjs" },
|
|
8
|
+
"scripts": {
|
|
9
|
+
"test": "node --test --test-concurrency=3 test/*.test.mjs",
|
|
10
|
+
"doctor": "node cli.mjs --agent codex --doctor",
|
|
11
|
+
"setup": "npm ci --prefix scripts"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"cli.mjs",
|
|
15
|
+
"orch.mjs",
|
|
16
|
+
"repair.mjs",
|
|
17
|
+
"package.json",
|
|
18
|
+
"release.json",
|
|
19
|
+
"README.md",
|
|
20
|
+
"README-zh.md",
|
|
21
|
+
"INSTALL.md",
|
|
22
|
+
"INSTALL-zh.md",
|
|
23
|
+
"CHANGELOG.md",
|
|
24
|
+
"LICENSE",
|
|
25
|
+
"docs",
|
|
26
|
+
"scripts",
|
|
27
|
+
"!scripts/node_modules"
|
|
28
|
+
],
|
|
29
|
+
"keywords": ["agent", "orchestrator", "parallel", "multi-agent", "tui", "cli", "windows", "codex", "claude", "automation"],
|
|
30
|
+
"author": "Yang Wenchàng (yechang1450)",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": { "type": "git", "url": "git+https://github.com/yechang1450/open-tui-orchestrator.git" },
|
|
33
|
+
"homepage": "https://github.com/yechang1450/open-tui-orchestrator#readme",
|
|
34
|
+
"bugs": { "url": "https://github.com/yechang1450/open-tui-orchestrator/issues" },
|
|
35
|
+
"engines": { "node": ">=22" }
|
|
36
|
+
}
|
package/release.json
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": 2,
|
|
3
|
+
"coreVersion": "1.14.6",
|
|
4
|
+
"files": {
|
|
5
|
+
"adapt-lib.mjs": "4704cb4dbcfb557f78b098008b3f54de2f41b6254d26dabd89e1cbea002d1854",
|
|
6
|
+
"agent-auth-prompt.txt": "18fa9c01972cd99a2fe2b1b74a440b34921a051ba6c0d54daf2f5bf1096457b0",
|
|
7
|
+
"agent-profiles/hermes.json": "0283956550eec69f7a47811db3e5125c5c1e003c6a7310a28185a615aeae34a2",
|
|
8
|
+
"agent.mjs": "e75eb20ebe560072f67d9e7803467eba4114fb23716b04f82147aebb17a12555",
|
|
9
|
+
"checkpoint.mjs": "246de59db9a7aac48b12eea1554ff281eaf9dd897e620ecf73d954f39b3cf94a",
|
|
10
|
+
"claude-host.mjs": "8ab7661e2b56eab07709b2a16c7f6e04dab8708edfbe672300254109c2323aaa",
|
|
11
|
+
"claude-runtime.mjs": "06e7aba4a5c62a2bf0f12e09089db778c265a0aa21b31a53dbac7245586abe20",
|
|
12
|
+
"contracts.mjs": "4675ff3d8d1a3d410f029267838e74fa811474f6d0e74d8a31d45f39893db71c",
|
|
13
|
+
"host-cli.mjs": "67b538db32c8aa6a7c2527b2b0fe81d2fbe8b440ab062071c6e6ecff0309b949",
|
|
14
|
+
"host-model.mjs": "497c5ac6a9a47cd8e42594f680c04d831f7bf1229ab1c2a8f192cacf9fe88547",
|
|
15
|
+
"host-probe.mjs": "90d0831ca2775e54183145638880277f8c45fbf457a8b948d65966b6f96c378f",
|
|
16
|
+
"inactive-window.mjs": "1d7ea5230fde895f862008643bf78dce976e5fd5ce4b816838e1d2d46086b671",
|
|
17
|
+
"inactive-window.ps1": "ce6bc7f91aa6ed07e2bfd61818ec72fc9cbf88f83e88066b65107943753e3f40",
|
|
18
|
+
"kimi-host.mjs": "17efd7cac6210f7f5e1d43e3a9144589edca45057009aaaa19962f7853c36ddf",
|
|
19
|
+
"kimi-runtime.mjs": "6358d32bb5fb9a4b055dad8d9b80401b3d8bb342c76ad1319eec0e0a7f4f4265",
|
|
20
|
+
"lease-lock.ps1": "75ecd1b7780e5df8489d44732320a681f6bc476acc38121fb096952180b0cdcb",
|
|
21
|
+
"leases.mjs": "4f55ad87f236d7208012495e04653418acde6ceb18d03d2036e47cb337613a09",
|
|
22
|
+
"maintenance-lock.mjs": "4fa35bd978a78e89861d65e4a22355d6a76552b7d19ea466503c059a0af8fb58",
|
|
23
|
+
"native-argv.mjs": "3b5a762eddf8a9042293ee12e9c441cafa566e14974563a04ee168a6d68834c0",
|
|
24
|
+
"network-policy.mjs": "e15fcef46f74ac07705ae87379ac6ce0b937b2f82d5ba13e94d12c5eff756f46",
|
|
25
|
+
"openclaw-bootstrap.mjs": "754b08d64669481bd94377c88b3aaebfe5c6047f34de386d7f735162a1f0b861",
|
|
26
|
+
"openclaw-config.mjs": "da7078dea9e1706053001817d8d7f281392bb113523092cc1eaf4ce11f48258f",
|
|
27
|
+
"openclaw-host.mjs": "9556c2a029dc3f19274238faa9aa10ac7e29b5ab769310a54fabe20ddc3ccdf2",
|
|
28
|
+
"openclaw-runtime.mjs": "e478d9503aa9b314357eee6b496b7aaf426b168833ff9b8033ba5292c3e0d70b",
|
|
29
|
+
"openclaw-window.mjs": "869f8b5cde5a68d7d7d689b70cd250cd1a4e7158c714bfda023f23d0386a8552",
|
|
30
|
+
"opencode-host.mjs": "6fe7ea46fa86530da3fb17005b16821d1d3d66d2139077718a9250026b854695",
|
|
31
|
+
"opencode-runtime.mjs": "e641e5cd6eacf38f581c46153ebcef1f00f21eb4576dddecc8a967c10b29ddf8",
|
|
32
|
+
"orchestrate-sdk.mjs": "5912edebbabaf1f4fda1c9ce3c223faf27fd1ba959098fd7d3811e029f25a3af",
|
|
33
|
+
"pi-host.mjs": "85b5d278d381f79dd76891e07542f64957d6d651ee33b0ac12de7731ff7e1b49",
|
|
34
|
+
"pi-runtime.mjs": "8a50996febfea9ff0b84941f9e1693869f61b7295cd4bac308e481c2d554b7f4",
|
|
35
|
+
"pi-shutdown.mjs": "c7d206b5d9f7560071ccec318a3d38faa27383d8531997b19ddfe572feb8f9f9",
|
|
36
|
+
"poll-windows.mjs": "9d0a6b0156218bac287a226fadb554718a234f0bc8caaf964700498be3794670",
|
|
37
|
+
"print-profile.mjs": "1082acd5c167da236807577d59f0742f86aed2e94d7ef3ec6db70574ebd05b2f",
|
|
38
|
+
"print-runtime.mjs": "b647b0f0c9c3645c4a7fe2b05403a294e9ad362c3dce7d29e4b129d4c0db502e",
|
|
39
|
+
"pty-host.mjs": "7169d647eaf6e53ec2a83448b8de44c8e1a1eba1d44d9f9c8d41abfbc556e144",
|
|
40
|
+
"recovery.mjs": "45e7eb9f23585fc3f51c2d6aeebb9607097640544ff43871c667df7f63fb06a4",
|
|
41
|
+
"run-board.mjs": "ee98dac04d2babe68ff3c0a88f40547a380188ed8de7135cf54c9a0f469ae9e3",
|
|
42
|
+
"run-guardian.mjs": "e1b2b17663c0a9a8a408e8a25484b87adcf7144f4d08f81c03d736a704feda6b",
|
|
43
|
+
"runner.mjs": "620dbf6efed6f0723de089fd39899aae8a21f15a5cacf329b3cddd4e84847a64",
|
|
44
|
+
"runtime-context.mjs": "39ee58751764034504a6e3c5a6cb53ded725abee5a5ccd7675ade7d690bdb58b",
|
|
45
|
+
"unit-carrier.mjs": "462b4512910a458815a1d5f7c1bce2e0e43e53e0511f5be3e13f118c879aeb48",
|
|
46
|
+
"unit-command.mjs": "93791c8e1d5ce7ccd87a9eb2a78438961faa723cb445535cadfef1254f1168ff",
|
|
47
|
+
"unit-runtime.mjs": "21a7a287e59c068c6d277281d4fb092852cfe21f4bb2df62d6695106f4f20665"
|
|
48
|
+
},
|
|
49
|
+
"runtimeFiles": {
|
|
50
|
+
"cli.mjs": "8b6817604286769142d0620ed8da96d433596e84362cee66594e099c88f1a1c4",
|
|
51
|
+
"package.json": "a2eb99224485b0848e05df19420297971e9441309bc90023b1a0b66a54060912",
|
|
52
|
+
"repair.mjs": "5a456b42560bfa21fd1e66ccdff7416f88e82fe711db5c04279717e73275a076",
|
|
53
|
+
"scripts/adapt.mjs": "20209c74212d334ea5aa1dfe35816a1b7a4b7f0415eb27c5a1975925dbbd10c5",
|
|
54
|
+
"scripts/agent-auth-prompt.txt": "18fa9c01972cd99a2fe2b1b74a440b34921a051ba6c0d54daf2f5bf1096457b0",
|
|
55
|
+
"scripts/agent.mjs": "e75eb20ebe560072f67d9e7803467eba4114fb23716b04f82147aebb17a12555",
|
|
56
|
+
"scripts/core/adapt-lib.mjs": "4704cb4dbcfb557f78b098008b3f54de2f41b6254d26dabd89e1cbea002d1854",
|
|
57
|
+
"scripts/core/agent-auth-prompt.txt": "18fa9c01972cd99a2fe2b1b74a440b34921a051ba6c0d54daf2f5bf1096457b0",
|
|
58
|
+
"scripts/core/agent-profiles/hermes.json": "0283956550eec69f7a47811db3e5125c5c1e003c6a7310a28185a615aeae34a2",
|
|
59
|
+
"scripts/core/agent.mjs": "e75eb20ebe560072f67d9e7803467eba4114fb23716b04f82147aebb17a12555",
|
|
60
|
+
"scripts/core/checkpoint.mjs": "246de59db9a7aac48b12eea1554ff281eaf9dd897e620ecf73d954f39b3cf94a",
|
|
61
|
+
"scripts/core/claude-host.mjs": "8ab7661e2b56eab07709b2a16c7f6e04dab8708edfbe672300254109c2323aaa",
|
|
62
|
+
"scripts/core/claude-runtime.mjs": "06e7aba4a5c62a2bf0f12e09089db778c265a0aa21b31a53dbac7245586abe20",
|
|
63
|
+
"scripts/core/contracts.mjs": "4675ff3d8d1a3d410f029267838e74fa811474f6d0e74d8a31d45f39893db71c",
|
|
64
|
+
"scripts/core/host-cli.mjs": "67b538db32c8aa6a7c2527b2b0fe81d2fbe8b440ab062071c6e6ecff0309b949",
|
|
65
|
+
"scripts/core/host-model.mjs": "497c5ac6a9a47cd8e42594f680c04d831f7bf1229ab1c2a8f192cacf9fe88547",
|
|
66
|
+
"scripts/core/host-probe.mjs": "90d0831ca2775e54183145638880277f8c45fbf457a8b948d65966b6f96c378f",
|
|
67
|
+
"scripts/core/inactive-window.mjs": "1d7ea5230fde895f862008643bf78dce976e5fd5ce4b816838e1d2d46086b671",
|
|
68
|
+
"scripts/core/inactive-window.ps1": "ce6bc7f91aa6ed07e2bfd61818ec72fc9cbf88f83e88066b65107943753e3f40",
|
|
69
|
+
"scripts/core/kimi-host.mjs": "17efd7cac6210f7f5e1d43e3a9144589edca45057009aaaa19962f7853c36ddf",
|
|
70
|
+
"scripts/core/kimi-runtime.mjs": "6358d32bb5fb9a4b055dad8d9b80401b3d8bb342c76ad1319eec0e0a7f4f4265",
|
|
71
|
+
"scripts/core/lease-lock.ps1": "75ecd1b7780e5df8489d44732320a681f6bc476acc38121fb096952180b0cdcb",
|
|
72
|
+
"scripts/core/leases.mjs": "4f55ad87f236d7208012495e04653418acde6ceb18d03d2036e47cb337613a09",
|
|
73
|
+
"scripts/core/maintenance-lock.mjs": "4fa35bd978a78e89861d65e4a22355d6a76552b7d19ea466503c059a0af8fb58",
|
|
74
|
+
"scripts/core/native-argv.mjs": "3b5a762eddf8a9042293ee12e9c441cafa566e14974563a04ee168a6d68834c0",
|
|
75
|
+
"scripts/core/network-policy.mjs": "e15fcef46f74ac07705ae87379ac6ce0b937b2f82d5ba13e94d12c5eff756f46",
|
|
76
|
+
"scripts/core/openclaw-bootstrap.mjs": "754b08d64669481bd94377c88b3aaebfe5c6047f34de386d7f735162a1f0b861",
|
|
77
|
+
"scripts/core/openclaw-config.mjs": "da7078dea9e1706053001817d8d7f281392bb113523092cc1eaf4ce11f48258f",
|
|
78
|
+
"scripts/core/openclaw-host.mjs": "9556c2a029dc3f19274238faa9aa10ac7e29b5ab769310a54fabe20ddc3ccdf2",
|
|
79
|
+
"scripts/core/openclaw-runtime.mjs": "e478d9503aa9b314357eee6b496b7aaf426b168833ff9b8033ba5292c3e0d70b",
|
|
80
|
+
"scripts/core/openclaw-window.mjs": "869f8b5cde5a68d7d7d689b70cd250cd1a4e7158c714bfda023f23d0386a8552",
|
|
81
|
+
"scripts/core/opencode-host.mjs": "6fe7ea46fa86530da3fb17005b16821d1d3d66d2139077718a9250026b854695",
|
|
82
|
+
"scripts/core/opencode-runtime.mjs": "e641e5cd6eacf38f581c46153ebcef1f00f21eb4576dddecc8a967c10b29ddf8",
|
|
83
|
+
"scripts/core/orchestrate-sdk.mjs": "5912edebbabaf1f4fda1c9ce3c223faf27fd1ba959098fd7d3811e029f25a3af",
|
|
84
|
+
"scripts/core/pi-host.mjs": "85b5d278d381f79dd76891e07542f64957d6d651ee33b0ac12de7731ff7e1b49",
|
|
85
|
+
"scripts/core/pi-runtime.mjs": "8a50996febfea9ff0b84941f9e1693869f61b7295cd4bac308e481c2d554b7f4",
|
|
86
|
+
"scripts/core/pi-shutdown.mjs": "c7d206b5d9f7560071ccec318a3d38faa27383d8531997b19ddfe572feb8f9f9",
|
|
87
|
+
"scripts/core/poll-windows.mjs": "9d0a6b0156218bac287a226fadb554718a234f0bc8caaf964700498be3794670",
|
|
88
|
+
"scripts/core/print-profile.mjs": "1082acd5c167da236807577d59f0742f86aed2e94d7ef3ec6db70574ebd05b2f",
|
|
89
|
+
"scripts/core/print-runtime.mjs": "b647b0f0c9c3645c4a7fe2b05403a294e9ad362c3dce7d29e4b129d4c0db502e",
|
|
90
|
+
"scripts/core/pty-host.mjs": "7169d647eaf6e53ec2a83448b8de44c8e1a1eba1d44d9f9c8d41abfbc556e144",
|
|
91
|
+
"scripts/core/recovery.mjs": "45e7eb9f23585fc3f51c2d6aeebb9607097640544ff43871c667df7f63fb06a4",
|
|
92
|
+
"scripts/core/run-board.mjs": "ee98dac04d2babe68ff3c0a88f40547a380188ed8de7135cf54c9a0f469ae9e3",
|
|
93
|
+
"scripts/core/run-guardian.mjs": "e1b2b17663c0a9a8a408e8a25484b87adcf7144f4d08f81c03d736a704feda6b",
|
|
94
|
+
"scripts/core/runner.mjs": "620dbf6efed6f0723de089fd39899aae8a21f15a5cacf329b3cddd4e84847a64",
|
|
95
|
+
"scripts/core/runtime-context.mjs": "39ee58751764034504a6e3c5a6cb53ded725abee5a5ccd7675ade7d690bdb58b",
|
|
96
|
+
"scripts/core/unit-carrier.mjs": "462b4512910a458815a1d5f7c1bce2e0e43e53e0511f5be3e13f118c879aeb48",
|
|
97
|
+
"scripts/core/unit-command.mjs": "93791c8e1d5ce7ccd87a9eb2a78438961faa723cb445535cadfef1254f1168ff",
|
|
98
|
+
"scripts/core/unit-runtime.mjs": "21a7a287e59c068c6d277281d4fb092852cfe21f4bb2df62d6695106f4f20665",
|
|
99
|
+
"scripts/gate.mjs": "8b3f12eaf2f1099a050cee8d29c7a715fd19532981c00c7115d8c40908f4e108",
|
|
100
|
+
"scripts/host-cli.mjs": "994448626766f53883a29d17a5af547dcb67f6d2b9e7e5b6b6ff60f28582978c",
|
|
101
|
+
"scripts/install-deps.mjs": "49873cecfb7af52148e2d7d06e225e6fa1501fb852ef199f016914bcf8a810de",
|
|
102
|
+
"scripts/maintenance-lock.mjs": "888d99a00ed90eb7b8650ef8ab56abcfd43b992e448c66a158acf876446f79a3",
|
|
103
|
+
"scripts/network-policy.mjs": "3a2b09ad0555475fa31d8e926da951aacd9a8997e33d80e1d46712432438d15a",
|
|
104
|
+
"scripts/open-tui-orchestrator-force.mjs": "d343662f3856c02231222cdae35b75ced0f46747e96b8b3fa7b5aecc07f6d91e",
|
|
105
|
+
"scripts/open-tui-orchestrator-preflight.mjs": "cec145e4dd1bfcc1ec6462a3c1d29eeda0f9c0e155792a8a98ab98530c2dcda3",
|
|
106
|
+
"scripts/orchestrate-sdk.mjs": "cc5107d7c720956d5d81c4ce706547f89c17db3143d6f890f27868a37570eb04",
|
|
107
|
+
"scripts/package-lock.json": "a74e3fa808ddd67d8de21278e1d4dc318bc4d238334ef00030c7d6104d5cf995",
|
|
108
|
+
"scripts/package.json": "a6b02f2ff7d3f0d6dd28a1cd7882277dcb51957feb199574dbc8e0927f0a5663",
|
|
109
|
+
"scripts/platform-guard.mjs": "3b0996ebf972bca764b6ee758f2501eaaf45531395521e0fd920abf0f1e5f80f",
|
|
110
|
+
"scripts/poll-windows.mjs": "f6a629e4af5b5ab108464962af469359200c841e2546f2c071f0d3eaac48397c",
|
|
111
|
+
"scripts/release-integrity.mjs": "841d1aa73a4b1bb3346e17348240540156fe59717521da1c1c4db0479822c6bd",
|
|
112
|
+
"scripts/runtime-context.mjs": "deb2671a6f36e428e452c9dc03b1add6f94ccbb4533c0018efc8e3c778a55045",
|
|
113
|
+
"scripts/sdk-dependency-check.mjs": "39815046e13d4cc17462b12e34643d32812c845ca1884dd64d3bfeed47cc5ebb",
|
|
114
|
+
"scripts/todo-list.mjs": "050234b9e5cb1220d2a3f2f4da8fb6372472d22c81e67fdeb995864a1556a228"
|
|
115
|
+
}
|
|
116
|
+
}
|
package/repair.mjs
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* repair.mjs - per-skill publish / integrity entry.
|
|
4
|
+
*
|
|
5
|
+
* The CLI package is self-contained and publishable when it carries its
|
|
6
|
+
* executable entrypoint, package metadata, release seal, README and license.
|
|
7
|
+
* Runtime state and developer metadata never enter a published copy.
|
|
8
|
+
*
|
|
9
|
+
* Runtime debris (use-and-discard, never bundled, safe to remove):
|
|
10
|
+
* node_modules/ temp/ __pycache__/
|
|
11
|
+
* .pytest_cache/ .cache/
|
|
12
|
+
* *.part *.tmp *.pyc *.pyo *.crdownload *.partial *.swp
|
|
13
|
+
* .enforce-state.json .DS_Store Thumbs.db
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* node repair.mjs # integrity check (read-only)
|
|
17
|
+
* node repair.mjs --clean # remove runtime debris (use-and-discard only)
|
|
18
|
+
* node repair.mjs --target <root> # publish: byte-copy the skill folder to <root>/<skill>
|
|
19
|
+
*
|
|
20
|
+
* No third-party deps; Node 22+; all reads/writes UTF-8 (no BOM) for text.
|
|
21
|
+
*/
|
|
22
|
+
import fs from 'node:fs';
|
|
23
|
+
import path from 'node:path';
|
|
24
|
+
import { fileURLToPath } from 'node:url';
|
|
25
|
+
import { verifyRelease } from './scripts/release-integrity.mjs';
|
|
26
|
+
import { lockedForMaintenance, acquireMaintenanceLock, releaseMaintenanceLock } from './scripts/core/maintenance-lock.mjs';
|
|
27
|
+
|
|
28
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
29
|
+
const SKILL = path.basename(__dirname);
|
|
30
|
+
|
|
31
|
+
const REQUIRED_FILES = ['cli.mjs', 'package.json', 'release.json', 'README.md', 'LICENSE'];
|
|
32
|
+
const OPTIONAL_FILES = ['README-zh.md', 'CHANGELOG.md'];
|
|
33
|
+
|
|
34
|
+
const DEBRIS_DIRS = new Set([
|
|
35
|
+
'node_modules',
|
|
36
|
+
'temp',
|
|
37
|
+
'__pycache__',
|
|
38
|
+
'.pytest_cache',
|
|
39
|
+
'.cache',
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
const DEBRIS_EXACT = new Set(['.agent-cache.json', '.enforce-state.json', '.DS_Store', 'Thumbs.db']);
|
|
43
|
+
const DEBRIS_RE = /\.(part|tmp|pyc|pyo|crdownload|partial|swp)$/i;
|
|
44
|
+
const PROTECTED_DIRS = new Set(['.git', '.plugin-eval', 'coverage', 'node_modules', 'temp']);
|
|
45
|
+
|
|
46
|
+
function listFiles(dir, base = '', out = []) {
|
|
47
|
+
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
48
|
+
if (e.isDirectory() && PROTECTED_DIRS.has(e.name)) continue;
|
|
49
|
+
if (e.isSymbolicLink()) continue; // 跳过符号链接:不跟随内容复制/删除(防越权/防逃逸)
|
|
50
|
+
const abs = path.join(dir, e.name);
|
|
51
|
+
const rel = path.join(base, e.name);
|
|
52
|
+
if (e.isDirectory()) listFiles(abs, rel, out);
|
|
53
|
+
else out.push(rel);
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// republish 只复制常规文件,不跟随符号链接;校验也保持一致(lstat,不 follow symlink)。
|
|
59
|
+
function isRegularFile(p) { try { return fs.lstatSync(p).isFile(); } catch { return false; } }
|
|
60
|
+
|
|
61
|
+
function isDebrisRel(rel) {
|
|
62
|
+
const parts = rel.split(path.sep);
|
|
63
|
+
if (parts.some((p) => DEBRIS_DIRS.has(p))) return true;
|
|
64
|
+
const base = path.basename(rel);
|
|
65
|
+
if (DEBRIS_EXACT.has(base)) return true;
|
|
66
|
+
if (DEBRIS_RE.test(base)) return true;
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function hasAny(relRoot) {
|
|
71
|
+
const files = listFiles(path.join(__dirname, relRoot));
|
|
72
|
+
return files.some((f) => !isDebrisRel(f));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function check() {
|
|
76
|
+
let problems = 0;
|
|
77
|
+
|
|
78
|
+
console.log(`[${SKILL}] repair.mjs - self-contained publish / integrity check`);
|
|
79
|
+
console.log(`[${SKILL}] skill root = ${__dirname}`);
|
|
80
|
+
try { const seal = verifyRelease(__dirname); console.log(` OK release seal schema=${seal.schema} core=${seal.coreVersion} files=${seal.files} runtime=${seal.runtimeFiles}`); }
|
|
81
|
+
catch (error) { console.log(` INVALID release seal ${error.message}`); problems++; }
|
|
82
|
+
for (const name of REQUIRED_FILES) {
|
|
83
|
+
const full = path.join(__dirname, name);
|
|
84
|
+
const ok = isRegularFile(full);
|
|
85
|
+
const isLink = fs.existsSync(full) && !ok; // 存在但非常规(如符号链接)→ 一致性校验失败
|
|
86
|
+
console.log(` ${ok ? 'OK ' : 'MISSING'} required ${name}${isLink ? ' (symlink/not-regular; will not be published)' : ''}`);
|
|
87
|
+
if (!ok) problems++;
|
|
88
|
+
}
|
|
89
|
+
for (const name of OPTIONAL_FILES) {
|
|
90
|
+
if (isRegularFile(path.join(__dirname, name))) {
|
|
91
|
+
console.log(` OK optional ${name}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
for (const dir of ['scripts', 'docs', 'test']) {
|
|
95
|
+
const full = path.join(__dirname, dir);
|
|
96
|
+
if (fs.existsSync(full) && fs.statSync(full).isDirectory() && hasAny(dir)) {
|
|
97
|
+
console.log(` OK source dir ${dir}/`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const debris = [];
|
|
102
|
+
for (const rel of listFiles(__dirname)) {
|
|
103
|
+
if (isDebrisRel(rel)) debris.push(rel);
|
|
104
|
+
}
|
|
105
|
+
if (debris.length) {
|
|
106
|
+
console.log(` FOUND ${debris.length} runtime debri item(s) (use-and-discard):`);
|
|
107
|
+
for (const d of debris) console.log(` ${d}`);
|
|
108
|
+
} else {
|
|
109
|
+
console.log(' OK no runtime debris');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
console.log('---');
|
|
113
|
+
if (problems) {
|
|
114
|
+
console.log(`[${SKILL}] RESULT: not publishable (${problems} required file(s) missing). Run with --target <root> to publish a clean copy.`);
|
|
115
|
+
process.exit(2);
|
|
116
|
+
}
|
|
117
|
+
console.log(`[${SKILL}] RESULT: publishable${debris.length ? ' (debris present; use --clean to remove)' : ''}.`);
|
|
118
|
+
process.exit(0);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function clean() {
|
|
122
|
+
// 维护锁(建议性):外部未上锁时本操作自行上锁、结束即解;维护会话已持锁则不碰它的锁。
|
|
123
|
+
// 注意 process.exit() 不执行 finally,必须在每个退出点前显式释放。
|
|
124
|
+
const selfLocked = !lockedForMaintenance() && (acquireMaintenanceLock({ reason: 'repair.mjs --clean' }), true);
|
|
125
|
+
try {
|
|
126
|
+
console.log(`[${SKILL}] --clean: removing runtime debris (use-and-discard only; source is untouched)`);
|
|
127
|
+
const removed = [];
|
|
128
|
+
for (const rel of listFiles(__dirname)) {
|
|
129
|
+
if (!isDebrisRel(rel)) continue;
|
|
130
|
+
const abs = path.join(__dirname, rel);
|
|
131
|
+
// Never follow out of the skill root(realpath 兜底,防符号链接逃逸)。
|
|
132
|
+
let real = abs;
|
|
133
|
+
try { real = fs.realpathSync(abs); } catch { continue; } // realpath 失败则无法确认越界,跳过不删
|
|
134
|
+
const rootReal = fs.realpathSync(__dirname);
|
|
135
|
+
if (real !== rootReal && !real.startsWith(rootReal + path.sep)) continue;
|
|
136
|
+
fs.rmSync(abs, { force: true });
|
|
137
|
+
removed.push(rel);
|
|
138
|
+
console.log(` removed ${rel}`);
|
|
139
|
+
}
|
|
140
|
+
// Also drop now-empty debris dirs (e.g. empty state/, temp/, __pycache__/).
|
|
141
|
+
for (const dir of DEBRIS_DIRS) {
|
|
142
|
+
if (PROTECTED_DIRS.has(dir)) continue;
|
|
143
|
+
const full = path.join(__dirname, dir);
|
|
144
|
+
if (fs.existsSync(full) && !fs.lstatSync(full).isSymbolicLink()) {
|
|
145
|
+
let real = null;
|
|
146
|
+
try { real = fs.realpathSync(full); } catch { continue; }
|
|
147
|
+
const rootReal = fs.realpathSync(__dirname);
|
|
148
|
+
if (real !== rootReal && !real.startsWith(rootReal + path.sep)) continue;
|
|
149
|
+
const empty = fs.readdirSync(full).length === 0;
|
|
150
|
+
if (empty) {
|
|
151
|
+
fs.rmdirSync(full);
|
|
152
|
+
removed.push(dir + '/');
|
|
153
|
+
console.log(` removed empty dir ${dir}/`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
console.log(`[${SKILL}] removed ${removed.length} debris item(s).`);
|
|
158
|
+
if (selfLocked) releaseMaintenanceLock();
|
|
159
|
+
process.exit(0);
|
|
160
|
+
} catch (e) {
|
|
161
|
+
if (selfLocked) releaseMaintenanceLock();
|
|
162
|
+
console.error(`[${SKILL}] clean failed: ${e.message}`);
|
|
163
|
+
process.exit(2);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function publish(targetRoot) {
|
|
168
|
+
let staging;
|
|
169
|
+
let selfLocked = false;
|
|
170
|
+
try {
|
|
171
|
+
if (!path.isAbsolute(targetRoot)) {
|
|
172
|
+
console.error(`[${SKILL}] --target expects an absolute root, got: ${targetRoot}`);
|
|
173
|
+
process.exit(2);
|
|
174
|
+
}
|
|
175
|
+
// publish 前必须验证必需文件
|
|
176
|
+
const missing = REQUIRED_FILES.filter((nf) => !isRegularFile(path.join(__dirname, nf)));
|
|
177
|
+
if (missing.length) { console.error("[" + SKILL + "] publish aborted: missing " + missing.join(", ")); process.exit(2); }
|
|
178
|
+
// 维护锁(建议性):外部未上锁时本发布操作自行上锁、结束即解(process.exit 不跑 finally,逐退出点显式释放)。
|
|
179
|
+
selfLocked = !lockedForMaintenance() && (acquireMaintenanceLock({ reason: 'repair.mjs --target publish' }), true);
|
|
180
|
+
verifyRelease(__dirname);
|
|
181
|
+
const dest = path.join(path.resolve(targetRoot), SKILL);
|
|
182
|
+
if (fs.existsSync(dest)) throw new Error('Publish target already exists; choose a fresh version directory');
|
|
183
|
+
const relative = path.relative(__dirname, dest);
|
|
184
|
+
if (relative !== '..' && !relative.startsWith('..' + path.sep) && !path.isAbsolute(relative)) throw new Error('Publish target must be outside the source tree');
|
|
185
|
+
let ancestor = path.dirname(dest), tail = [path.basename(dest)];
|
|
186
|
+
while (!fs.existsSync(ancestor)) { tail.unshift(path.basename(ancestor)); ancestor = path.dirname(ancestor); }
|
|
187
|
+
const physical = path.join(fs.realpathSync(ancestor), ...tail);
|
|
188
|
+
const physicalRelative = path.relative(fs.realpathSync(__dirname), physical);
|
|
189
|
+
if (physicalRelative !== '..' && !physicalRelative.startsWith('..' + path.sep) && !path.isAbsolute(physicalRelative)) throw new Error('Publish target must be outside the source tree');
|
|
190
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
191
|
+
staging = fs.mkdtempSync(path.join(path.dirname(dest), '.' + SKILL + '-staging-'));
|
|
192
|
+
console.log(`[${SKILL}] --target: publishing CLI package to ${dest}`);
|
|
193
|
+
let copied = 0;
|
|
194
|
+
for (const rel of listFiles(__dirname)) {
|
|
195
|
+
if (isDebrisRel(rel)) continue;
|
|
196
|
+
const srcAbs = path.join(__dirname, rel);
|
|
197
|
+
const dstAbs = path.join(staging, rel);
|
|
198
|
+
fs.mkdirSync(path.dirname(dstAbs), { recursive: true });
|
|
199
|
+
// Byte-copy: preserves UTF-8 no-BOM text and any binary data byte-exact.
|
|
200
|
+
fs.copyFileSync(srcAbs, dstAbs);
|
|
201
|
+
copied++;
|
|
202
|
+
}
|
|
203
|
+
verifyRelease(staging);
|
|
204
|
+
const stagedMissing = REQUIRED_FILES.filter(name => !isRegularFile(path.join(staging, name)));
|
|
205
|
+
if (stagedMissing.length) throw new Error('Staged package missing required: ' + stagedMissing.join(', '));
|
|
206
|
+
if (fs.existsSync(dest)) throw new Error('Publish target appeared during publication');
|
|
207
|
+
fs.renameSync(staging, dest);
|
|
208
|
+
staging = undefined;
|
|
209
|
+
console.log(`[${SKILL}] published ${copied} file(s) to ${dest}.`);
|
|
210
|
+
if (selfLocked) releaseMaintenanceLock();
|
|
211
|
+
process.exit(0);
|
|
212
|
+
} catch (e) {
|
|
213
|
+
if (selfLocked) releaseMaintenanceLock();
|
|
214
|
+
if (staging) { try { fs.rmSync(staging, {recursive: true, force: true}); } catch { /* preserve the original error */ } }
|
|
215
|
+
console.error(`[${SKILL}] publish failed: ${e.message}`);
|
|
216
|
+
process.exit(2);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function main() {
|
|
221
|
+
const args = process.argv.slice(2);
|
|
222
|
+
if (args.includes('--clean')) return clean();
|
|
223
|
+
const ti = args.indexOf('--target');
|
|
224
|
+
if (ti >= 0 && args[ti + 1]) return publish(args[ti + 1]);
|
|
225
|
+
return check();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
main();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// adapt — open-tui-orchestrator 的 print-class 自动适配入口。
|
|
3
|
+
// 探测被调用的 agent CLI(或 --agent 指定)表面 → 生成画像(scripts/core/agent-profiles/<id>.json)
|
|
4
|
+
// → 解析自检 → 活体验证(真实调用取回探活令牌)→ 重封 → 自动提交。
|
|
5
|
+
// 任何一步失败都回滚画像,仓库保持原状;维护锁持有期间拒绝写入(--force 例外)。
|
|
6
|
+
//
|
|
7
|
+
// node adapt.mjs [--agent <id>] [--cli <path>] [--profiles-dir <dir>]
|
|
8
|
+
// [--no-live] [--no-commit] [--suite] [--smoke] [--force] [--json]
|
|
9
|
+
import { adaptAgent } from './core/adapt-lib.mjs';
|
|
10
|
+
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
const flag = (name) => { const i = args.indexOf(name); return i >= 0 ? (args[i + 1] || '') : undefined; };
|
|
13
|
+
const has = (name) => args.includes(name);
|
|
14
|
+
|
|
15
|
+
const report = await adaptAgent({
|
|
16
|
+
id: flag('--agent') || undefined,
|
|
17
|
+
cli: flag('--cli') || undefined,
|
|
18
|
+
env: flag('--profiles-dir') ? { ...process.env, ORCH_AGENT_PROFILES_DIR: flag('--profiles-dir') } : process.env,
|
|
19
|
+
live: !has('--no-live'),
|
|
20
|
+
commit: !has('--no-commit'),
|
|
21
|
+
suite: has('--suite'),
|
|
22
|
+
smoke: has('--smoke'),
|
|
23
|
+
force: has('--force'),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (has('--json')) console.log(JSON.stringify(report, null, 2));
|
|
27
|
+
else {
|
|
28
|
+
console.log('[adapt] agent=' + (report.id || '?') + ' cli=' + (report.cli || '?') + ' version=' + (report.version || '?'));
|
|
29
|
+
if (report.profile) console.log('[adapt] profile: prompt=' + report.profile.args.prompt.join(' ') + ' approve=[' + report.profile.args.approve.join(' ') + '] model=' + (report.profile.args.model ? report.profile.args.model.join(' ') : '-') + ' effort=' + (report.profile.args.effort ? report.profile.args.effort.join(' ') : '-'));
|
|
30
|
+
if (report.live) console.log('[adapt] live: ' + JSON.stringify(report.live).slice(0, 300));
|
|
31
|
+
if (report.smoke) console.log('[adapt] block smoke: ' + JSON.stringify(report.smoke).slice(0, 200));
|
|
32
|
+
if (report.suite) console.log('[adapt] suite: exit=' + report.suite.exit);
|
|
33
|
+
console.log('[adapt] committed=' + report.committed + ' passed=' + report.passed + (report.reason ? ' reason=' + report.reason : ''));
|
|
34
|
+
}
|
|
35
|
+
process.exitCode = report.passed ? 0 : 1;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
本窗任务已经由用户授权执行;启动即开始完成指定任务,不再次询问 yes, continue 或请求重复确认。权限以本次 CLI 参数和宿主实际执行规则为准。
|
|
2
|
+
本窗执行主控分配的任务;授权仅来自用户请求及宿主规则,不因编排而扩大。
|
|
3
|
+
先检查相关文件与环境,再在上下文列出 TODO LIST(目标、依赖、动作、验证和收尾),随后完成任务。清单不必写成独立文件。
|
|
4
|
+
本窗不使用子代理;不得再调用 --run-windows、--spawn 或另开执行窗。联动与并行由主控统一安排。
|
|
5
|
+
遵守工作区 AGENTS.md、宿主沙箱及审批规则;不得绕过审批或改写信任配置。超出授权、缺少凭据或需要关键选择时如实报告阻塞,不伪报完成。
|
|
6
|
+
只修改本块范围内的文件,保留其它任务和用户的改动。适用且已安装的技能按其规则使用;不存在的技能不能当成必备工具。
|
|
7
|
+
修改后逐一真实读回产物,运行相应测试或检查;涉及中文时使用 UTF-8 并检查编码。只读任务以实际检查结果为产物,不强制创建文件。
|
|
8
|
+
最后汇报结果与验证证据;只有本块全部完成且验证通过,才在最后单独输出一行结束标记:
|
|
9
|
+
__ORCH_DONE__ <本窗token>
|
|
10
|
+
失败、阻塞或产物未落盘时禁止输出结束标记。主控仍须核对最终产物。
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { adapters as AGENTS, resolveHost as resolveAgent, launchArgs, detectHostAgent } from './host-cli.mjs';
|