跳到正文
Hacker News· donutloop·· 7 天前AI 评分22

Pi-Loop(原型):在 DGX Spark 上驱动参考链接入库循环的 CLI

Show HN: Pi-Loop (Prototype) – A CLI for Reference Intake loop on DGX Spark

AI 导读

Pi-Loop 是一个基于 pi SDK 的 CLI 原型,连接本地 pi agent 会话,驱动仓库的参考链接入库循环,每轮从 raw_links.md 取第一条待处理 URL 并新建会话执行 prompts/process_url_reference.md。

正文 · AI 翻译

pi-loop(Genesis Mission 分支)

一个基于 pi SDK(@earendil-works/pi-coding-agent)构建的 CLI,它连接到 本地 pi agent 会话并驱动仓库的 reference-intake loop—— 移植自 donutloop/gusty tools/pi-loop 并做了特化:AGENTS.md 功能循环变成了 raw_links.md → prompts/process_url_reference.md 流水线,具有相同的 每轮全新会话 和 停止后恢复 语义。

一轮做什么

1. claim      the harness takes the FIRST pending URL out of raw_links.md,
              removes that line (tmp file + rename) and journals the claim in
              .pi-loop-queue.json   ← the agent never sees the queue step
2. session    a brand-new pi session is created (new id, new session log) and
              prompted: read AGENTS.md, then execute
              prompts/process_url_reference.md for `URL parameter is <URL>`
3. tools      read/edit/write/bash/grep/find/ls + `webfetch` (this dir's fetcher)
4. verify     git HEAD moved? annotated tag present? queue line committed?
5. persist    journal status + .pi-loop-state.json, dispose the session, wait
              PI_LOOP_DELAY_SECONDS (default 60 s) and start round N+1

让循环可以安全地持续运行的规则:

  • raw_links.md 由 harness 拥有。 链接在被取用的那一刻就被移除—— 绝不由 agent 移除,绝不事后移除。被移除的行保留在日志 (lineText)中,因此可以用 --requeue-failed 放回。
  • 一条链接绝不会被派发两次。 日志在文件被 重写之前写入,因此即使两次写入之间发生崩溃,也不会重新运行某个 URL。
  • 已索引的链接不消耗轮次。 在 references.md / reference_coverage.md 中找到的 URL(工作流第 1 步无论如何都会中止这些)会以 duplicate 出队, 而不唤醒模型。规范化匹配忽略 utm_*、hl、片段、www.、末尾斜杠和默认端口; --known-level=2 还会忽略查询字符串。
  • 进度是单调的。 如果一轮没有提交任何内容,harness 会自行提交 出队(chore(loop): dequeue <host> from raw_links.md)并将该轮记录为 dequeued-no-commit, 因此一个坏掉的轮次不会使运行停滞或陷入循环。

模型配置——来自 setup/,绝不硬编码

与上游 pi-loop 相同:一份格式与 pi 从 <agentDir>/models.json 读取的完全一致的配置存放在仓库的 setup/ 目录中, 将循环指向新模型只需在那里放入一个文件——无需改代码。

  1. Discover: --models-config=PATH > PI_LOOP_MODELS_CONFIG / PI_MODELS_CONFIG

    最新的 具名 profile setup/pi_*.json(setup/pi.json 是通用 回退)位于 PI_LOOP_SETUP_DIR、<cwd>/setup,然后是 tools/../setup。

  2. 选择:--provider/--model > PI_LOOP_PROVIDER/PI_LOOP_MODEL > 第一个 provider 的第一个模型。
  3. 发布到 <agentDir>/models.json(合并,保留不相关的 provider 和 modelOverrides,丢弃遗留的顶层 models 键)。
  4. 解析通过 SDK 自身的 ModelRuntime,回退到内联模型。
  5. 探测 <baseUrl>/models 并在服务器宕机或 不提供所选 id 时快速失败(退出码 1)(PI_LOOP_SKIP_MODEL_CHECK=1 可跳过)。

agentDir 默认为 <cwd>/.pi/agent(上游使用仓库根目录),以便 models.json、认证副本和会话日志不进入论文提交—— .gitignore 覆盖 .pi/、.pi-loop-state.json 和 .pi-loop-queue.json。

在另一个 pi 会话内部:pi 会将它运行的每条命令中的 PI_MODEL/PI_PROVIDER 导出; pi-loop 在 PI_CODING_AGENT=true 时忽略这两个并会说明。使用 --model=ID / PI_LOOP_MODEL 来显式指定。任何设置也接受 无冲突的 PI_LOOP_<NAME> 拼写,它总是优先。

用法

node tools/pi-loop/pi-loop.mjs                       # loop over raw_links.md forever
node tools/pi-loop/pi-loop.mjs . --once               # exactly one link
node tools/pi-loop/pi-loop.mjs . --rounds=5           # five links
node tools/pi-loop/pi-loop.mjs . --force-reset        # ignore saved progress, restart at round 1
node tools/pi-loop/pi-loop.mjs . --push               # allow rounds to publish (default: never)
node tools/pi-loop/pi-loop.mjs . --next               # JSON: the link the next round would claim
node tools/pi-loop/pi-loop.mjs . --status             # JSON: queue + journal summary
node tools/pi-loop/pi-loop.mjs . --requeue-failed     # put lost links back into the queue
node tools/pi-loop/pi-loop.mjs . --retry-failed       # also re-dispatch aborted/no-commit links
node tools/pi-loop/pi-loop.mjs . --dry-run            # connectivity round, no tools, no queue, no state
node tools/pi-loop/pi-loop.mjs . --describe           # resolved config as JSON (pipe to jq)
node tools/pi-loop/pi-loop.mjs --help                 # full flag list (upstream + loop flags)
flag 含义
[cwd] 要驱动的仓库(默认 process.cwd())
--rounds=N / --once 要处理的链接数(默认 Infinity)
--force-reset 忽略 .pi-loop-state.json,从第 1 轮重新开始
--links=PATH 队列文件(默认 <cwd>/raw_links.md)
--prompt=PATH 每轮的工作流(默认 <cwd>/prompts/process_url_reference.md)
--journal=PATH 认领日志(默认 <cwd>/.pi-loop-queue.json)
--state=PATH 进度状态(默认 <cwd>/.pi-loop-state.json)
--known=A,B 扫描已索引 URL 的文件(默认 references.md,reference_coverage.md)
--skip-known=0 即使链接已被索引也派发
--known-level=2 将“相同路径、不同查询”也视为已索引
--retry-failed 释放 aborted / dequeued-no-commit / invalid 认领以便重新派发
--requeue-failed 将这些链接追加回 raw_links.md 并退出
--next / --status 机器路径:JSON 队列检查,无副作用
--push 允许在一轮内使用 git push origin main vX.Y.Z
--dry-run / --describe / --help 与上游 pi-loop 相同

Env(每个也接受为 PI_LOOP_<NAME>,它优先;--flag 胜过两者):

var 默认
PI_LOOP_LINKS / PI_LOOP_PROMPT / PI_LOOP_JOURNAL / PI_LOOP_STATE 与上述 flag 相同
PI_LOOP_KNOWN / PI_LOOP_SKIP_KNOWN / PI_LOOP_KNOWN_LEVEL references.md,reference_coverage.md / 1 / 1
PI_LOOP_PUSH false
PI_LOOP_AGENT_DIR <cwd>/.pi/agent
PI_LOOP_COPY_AUTH 1 — 缺失时从 ~/.pi/agent/auth.json 播种 <agentDir>/auth.json
PI_LOOP_DELAY_SECONDS 轮次之间的 60
PI_LOOP_SDK_PATH、PI_LOOP_SETUP_DIR、PI_LOOP_MODELS_CONFIG、PI_LOOP_PROVIDER、PI_LOOP_MODEL、PI_LOOP_THINKING_LEVEL、PI_LOOP_CONTEXT_WINDOW、PI_LOOP_MAX_TOKENS、PI_LOOP_SKIP_MODEL_CHECK、PI_LOOP_MODEL_CHECK_TIMEOUT_MS 与上游 pi-loop 相同

停止 / 恢复(与上游相同)

一次停止——SIGINT、错误或达到轮次目标——会在退出前将 { round, lastCommit } 持久化到 .pi-loop-state.json。在下一次运行时:

  • 已提交的进度,lastCommit == HEAD,干净的工作树 → 在下一轮恢复;
  • 否则(无状态,lastCommit != HEAD,脏工作树)→ 重新执行 AGENTS.md 在第 1 轮。

两种路径下声明都成立:已派发的 URL 不会再次派发,直到你显式地 --requeue-failed / --retry-failed 它。

查找 pi SDK

与上游一致(sdk-discovery.mjs):$PI_LOOP_SDK_PATH → 一个 node 依赖 → pi 托管安装($PI_MANAGED_INSTALL_ROOT,~/.pi/agent/install) → PATH 上的 pi 二进制文件 → 全局 npm 前缀,每次未命中时都会打印所有候选路径。

机器路径

需要 命令
下一轮会做什么 --next(JSON:next,wouldConsume,skipped,queued)
队列进展到什么程度 --status(JSON:queued,claimed,byStatus)
模型/端点是否可用 --describe | jq .endpoint
以文本形式读取引用 node tools/pi-loop/webfetch.mjs <url> [--max-chars=N] [--links] [--json] [--raw] [--out=F]

webfetch.mjs 与该轮 webfetch 工具调用的代码相同,因此脚本和 轮次总是看到相同的提取结果。

测试

node --test tools/pi-loop/*.test.mjs          # or: npm test --prefix tools/pi-loop
  • link-queue.test.mjs — 声明规则:FIFO 选取 + 行移除,规范化 去重(www.,/,hl=,utm_),重复行,日志阻止 重新派发,--retry-failed,已知索引预过滤,原子写入,--next, --requeue-failed。
  • webfetch.test.mjs — HTML → 文本,实体解码,截断预算,PDF / 二进制 / HTTP 错误 / 网络失败路径,引用 URL 规范化。
  • round-prompt.test.mjs — 轮次提示恰好携带一个 URL,禁止 触碰 raw_links.md,命名每个产物,默认关闭推送。
  • models-config.test.mjs,sdk-discovery.test.mjs — 继承自上游。

端到端:

node tools/pi-loop/pi-loop.mjs . --dry-run    # expects PI_LOOP_OK, queue untouched
node tools/pi-loop/pi-loop.mjs . --once       # one real link: commit + tag

要求

  • 已安装 pi(托管安装、全局 npm 包或 PI_LOOP_SDK_PATH)。
  • 本地模型服务器在所选 setup/ 配置中的 baseUrl 上运行 (setup/boot_agent.sh);--describe 告诉你它是否可达。

循环契约

AGENTS.md(仓库根目录)被每一轮读取,并定义质量标准: 仅合并编辑,英语/德语对等,先来源后声明,计数核对, 每个链接一次提交 + 一个附注标签。

来源:Hacker News · github.com