@tt-a1i/openpi 0.5.0 → 0.6.1
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/README.md +30 -20
- package/SETUP.md +10 -4
- package/THIRD_PARTY_NOTICES.md +16 -0
- package/bin/openpi.js +25 -15
- package/extensions/ai-providers/LICENSE.upstream +23 -0
- package/extensions/ai-providers/README.md +65 -0
- package/extensions/ai-providers/antigravity/credentials.ts +52 -0
- package/extensions/ai-providers/antigravity/discovery.ts +130 -0
- package/extensions/ai-providers/antigravity/google-conversion.ts +455 -0
- package/extensions/ai-providers/antigravity/models.ts +84 -0
- package/extensions/ai-providers/antigravity/oauth.ts +700 -0
- package/extensions/ai-providers/antigravity/provider.ts +1116 -0
- package/extensions/ai-providers/antigravity/routing.ts +340 -0
- package/extensions/ai-providers/antigravity/with-resolvers.d.ts +19 -0
- package/extensions/ai-providers/cursor/constants.ts +5 -0
- package/extensions/ai-providers/cursor/credentials.ts +14 -0
- package/extensions/ai-providers/cursor/discovery.ts +291 -0
- package/extensions/ai-providers/cursor/input-images.ts +105 -0
- package/extensions/ai-providers/cursor/models.ts +45 -0
- package/extensions/ai-providers/cursor/oauth.ts +263 -0
- package/extensions/ai-providers/cursor/proto.ts +1271 -0
- package/extensions/ai-providers/cursor/protobuf.ts +1181 -0
- package/extensions/ai-providers/cursor/provider.ts +1431 -0
- package/extensions/ai-providers/cursor/proxy.ts +213 -0
- package/extensions/ai-providers/cursor/tool-bridge.ts +68 -0
- package/extensions/ai-providers/cursor/with-resolvers.d.ts +12 -0
- package/extensions/ai-providers/index.ts +86 -0
- package/extensions/ai-providers/oauth-adapter.ts +81 -0
- package/extensions/ai-providers/usage.ts +10 -0
- package/extensions/background-terminals/index.ts +8 -1
- package/extensions/background-terminals/src/manager.ts +3 -5
- package/extensions/background-terminals/src/result-delivery.ts +43 -23
- package/extensions/cron/index.ts +68 -27
- package/extensions/cron/schedule.ts +5 -1
- package/extensions/model-info/cache-diagnostics.ts +220 -0
- package/extensions/model-info/index.ts +45 -1
- package/extensions/plan-mode/index.ts +75 -4
- package/extensions/setup/index.ts +15 -3
- package/extensions/shared/child-session.ts +39 -5
- package/extensions/shared/completion-inbox.ts +193 -0
- package/extensions/shared/setup-config.ts +10 -1
- package/extensions/shared/structured-output.ts +154 -0
- package/extensions/subagents/index.ts +64 -7
- package/extensions/subagents/src/agent-types.ts +5 -17
- package/extensions/subagents/src/backends/pi.ts +130 -48
- package/extensions/subagents/src/backends/tool-preview.ts +29 -0
- package/extensions/subagents/src/domain.ts +16 -1
- package/extensions/subagents/src/manager.ts +7 -71
- package/extensions/subagents/src/prompt.ts +19 -5
- package/extensions/subagents/src/result-artifact.ts +32 -0
- package/extensions/subagents/src/result-delivery.ts +33 -14
- package/extensions/subagents/src/runtime.ts +10 -3
- package/extensions/ui-customization/footer.ts +16 -5
- package/extensions/user-input-fold/index.ts +42 -6
- package/extensions/web/index.ts +25 -2
- package/extensions/workflows/acceptance.ts +43 -19
- package/extensions/workflows/completion-projection.ts +3 -1
- package/extensions/workflows/dashboard.ts +147 -21
- package/extensions/workflows/index.ts +75 -20
- package/extensions/workflows/model.ts +5 -1
- package/extensions/workflows/progress-projection.ts +7 -1
- package/extensions/workflows/prompt.ts +4 -10
- package/extensions/workflows/result-delivery.ts +96 -22
- package/extensions/workflows/retention.ts +6 -0
- package/extensions/workflows/runner.ts +11 -233
- package/extensions/workflows/sandbox.ts +4 -0
- package/package.json +7 -7
- package/skills/subagents/REFERENCE.md +9 -9
- package/skills/subagents/SKILL.md +2 -1
- package/skills/workflows/REFERENCE.md +5 -3
- package/skills/workflows/SKILL.md +1 -1
- package/web/adapter/pi-adapter.ts +3 -0
- package/web/host/pi-coding-agent-entry.ts +162 -0
- package/web/host/web-host.ts +330 -50
- package/web/protocol/types.ts +5 -0
- package/web/runtime/pi-runtime.ts +240 -25
- package/web/runtime/types.ts +32 -1
- package/web/ui/app.js +343 -41
- package/web/ui/index.html +3 -0
- package/web/ui/styles.css +119 -37
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
<p align="center">
|
|
21
21
|
<a href="https://www.npmjs.com/package/@tt-a1i/openpi"><img alt="npm version" src="https://img.shields.io/npm/v/@tt-a1i/openpi?style=flat-square&color=cb3837"></a>
|
|
22
22
|
<a href="https://github.com/openpi-dev/openpi/actions/workflows/ci.yml"><img alt="CI status" src="https://github.com/openpi-dev/openpi/actions/workflows/ci.yml/badge.svg"></a>
|
|
23
|
-
<a href="https://github.com/earendil-works/pi-mono"><img alt="Pi 0.
|
|
23
|
+
<a href="https://github.com/earendil-works/pi-mono"><img alt="Pi 0.85.1+" src="https://img.shields.io/badge/Pi-0.85.1%2B-2f81f7?style=flat-square"></a>
|
|
24
24
|
<img alt="Node.js 22.19+" src="https://img.shields.io/badge/Node.js-22.19%2B-3fb950?style=flat-square&logo=nodedotjs&logoColor=white">
|
|
25
25
|
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-3fb950?style=flat-square"></a>
|
|
26
26
|
</p>
|
|
@@ -123,13 +123,14 @@ OpenPI 把成熟 Coding Agent 的工作习惯做成 Pi-native 能力,但不复
|
|
|
123
123
|
| 工作面 | 已包含的能力 |
|
|
124
124
|
| ------------ | --------------------------------------------------------------------------------------------------------- |
|
|
125
125
|
| 执行 | Background Terminal、Pi-native Subagent、Dynamic Workflow、隔离 Worktree |
|
|
126
|
-
| 编排 | `pipeline` / `parallel`、结构化输出、Result Handoff、Operator、
|
|
126
|
+
| 编排 | `pipeline` / `parallel`、结构化输出、Result Handoff、Operator、Safe Replay、派生 Graph |
|
|
127
127
|
| 连续性 | Tasks、Goal、Plan Mode、Context Pivot、Session Browser、Session-scoped Cron |
|
|
128
128
|
| 自定义 Agent | `explorer` / `implementer` / `reviewer` / `advisor`,支持全局与项目角色文件、独立模型与 effort |
|
|
129
129
|
| 终端工作台 | 自定义 Footer 与任务栏、运行状态、紧凑 Tool Result、Next-action Suggestion、Git / PR 信号 |
|
|
130
130
|
| 快捷工作流 | `/btw` 旁路提问(TUI)、`/lg` 浏览 Diff(TUI)、`/pr` 查 PR、`/copy-all`、`fd`、`rg`、只读 Git 工具 |
|
|
131
131
|
| 人类决策 | `ask_user` 草稿与最终复核、parent-only `human_handoff`、Plan Ready 实施门禁 |
|
|
132
132
|
| 统一配置 | `/openpi-setup` 管理 OpenPI 自有模型、并发、Footer、输出密度与 Post-edit 偏好 |
|
|
133
|
+
| 模型授权 | `/login google-antigravity`;实验性的 `/login cursor`(支持 Pi 工具,不执行 Cursor 原生工具) |
|
|
133
134
|
|
|
134
135
|
OpenPI 采用 [MIT License](LICENSE);第三方来源与保留声明见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。
|
|
135
136
|
|
|
@@ -195,23 +196,23 @@ subagent_spawn({
|
|
|
195
196
|
每个 Subagent 都是新的进程内 Pi SDK Session:
|
|
196
197
|
|
|
197
198
|
- 默认继承父会话的 Provider 与模型;用户可明确指定 Thinking Level,否则模型根据角色建议、任务难度与目标模型实际支持的档位选择;
|
|
198
|
-
-
|
|
199
|
+
- 继承父会话当前启用且允许委派的工具、Skills 和项目说明;目标目录的项目扩展按其自身 Trust 决策加载;
|
|
199
200
|
- 最多 4 个模型发起的 Subagent 并发运行,结束后自动回传;
|
|
200
201
|
- 可 `check`、`wait`、`cancel`,也可用 `subagent_send` 继续同一子会话;
|
|
201
202
|
- 输入框下方显示实时摘要,空输入时按 `↓` 聚焦,`Enter` 或 `→` 打开管理界面。
|
|
202
203
|
|
|
203
|
-
|
|
204
|
+
内置角色提供任务分工建议,普通模式下继承父会话当前启用且允许委派的工具,包括 Bash 和已启用的联网工具。角色名称本身不是只读权限边界;Plan Mode 与自定义角色的显式工具限制仍由 Harness 执行。
|
|
204
205
|
|
|
205
|
-
| `agent_type` | 适合 | 相对 effort 建议
|
|
206
|
-
| ------------- | ---------------- |
|
|
207
|
-
| `explorer` | 代码追踪与探索 | 中等,难题可提高
|
|
208
|
-
| `implementer` | 聚焦实现 | 中高,按范围与风险调整 |
|
|
209
|
-
| `reviewer` | 正确性与回归审查 | 较高
|
|
210
|
-
| `advisor` | 深度技术建议 | 较高
|
|
206
|
+
| `agent_type` | 适合 | 相对 effort 建议 |
|
|
207
|
+
| ------------- | ---------------- | ---------------- |
|
|
208
|
+
| `explorer` | 代码追踪与探索 | 中等,难题可提高 |
|
|
209
|
+
| `implementer` | 聚焦实现 | 中高,按范围与风险调整 |
|
|
210
|
+
| `reviewer` | 正确性与回归审查 | 较高 |
|
|
211
|
+
| `advisor` | 深度技术建议 | 较高 |
|
|
211
212
|
|
|
212
213
|
上述只是模型的相对选择提示,不会为内置角色写死具体档位。用户明确指定的 `reasoning_effort` 始终优先;否则模型结合任务难度,从目标模型实际支持的档位中选择。
|
|
213
214
|
|
|
214
|
-
角色可由全局 `~/.pi/agent/agents/*.md` 或受信任项目 `.pi/agents/*.md` 覆盖。模型优先级是:显式调用 > Agent Type 文件 > `/openpi-setup` 角色模型 > 父模型继承。更高优先级定义损坏时会阻断 fallback
|
|
215
|
+
角色可由全局 `~/.pi/agent/agents/*.md` 或受信任项目 `.pi/agents/*.md` 覆盖。模型优先级是:显式调用 > Agent Type 文件 > `/openpi-setup` 角色模型 > 父模型继承。更高优先级定义损坏时会阻断 fallback,而不是悄悄退回更宽松的能力。自定义角色省略 `tools` 时继承当前父工具;显式列表只能收窄,未在父会话启用的工具不会由委派自动激活。已有角色文件不会被升级覆盖;旧版 `explorer.md` 的只读列表仍然有效。工具可用性不等于文件系统沙箱;普通模式可使用绝对路径访问其他目录,目标仓库的执行 cwd 应通过 `working_dir` 指定。
|
|
215
216
|
|
|
216
217
|
<details>
|
|
217
218
|
<summary><strong>并行写文件时如何隔离 Worktree?</strong></summary>
|
|
@@ -270,11 +271,11 @@ return agent("Synthesize the verified findings", {
|
|
|
270
271
|
| `phase()` | 标记当前阶段 |
|
|
271
272
|
| `log()` | 向实时界面与最终报告追加一行进度 |
|
|
272
273
|
| `usage()` | 读取累计 Token、缓存、成本及本轮并发/调用余量;Token 是 lower bound,不是预算器 |
|
|
273
|
-
| `agent()` | 启动 Pi Agent;支持 role、schema、
|
|
274
|
+
| `agent()` | 启动 Pi Agent;支持 role、schema、inputs、operator 与 worktree |
|
|
274
275
|
| `pipeline()` | 每个 item 完成上阶段后立即进入下一阶段;多阶段 fan-out 的默认选择 |
|
|
275
276
|
| `parallel()` | 并发 barrier;只在下一阶段确实需要全部结果时使用 |
|
|
276
277
|
|
|
277
|
-
Workflow 默认并发 8 个 Agent,单次最多 128 次调用;可配置到 64 和 1024。前台运行可实时查看,后台运行完成后自动回传;`/workflows` 展示阶段、Agent、Transcript、Graph
|
|
278
|
+
Workflow 默认并发 8 个 Agent,单次最多 128 次调用;可配置到 64 和 1024。前台运行可实时查看,后台运行完成后自动回传;`/workflows` 展示阶段、Agent、Transcript、Graph、用量与产物。普通子代理和 Workflow 都使用 Pi 原生传输超时与重试,不再用额外的 45 秒无可见输出计时器打断思考、排队或重试。显式取消和 Session 清理仍有界,原生 Provider 错误保留在 Child outcome 中。并发上限不代表账号的服务端速率额度;429 仍按 Pi 原生重试策略处理。
|
|
278
279
|
|
|
279
280
|
---
|
|
280
281
|
|
|
@@ -284,6 +285,8 @@ OpenPI 把一次调用拆成可以审计的生命周期,而不是把“进程
|
|
|
284
285
|
|
|
285
286
|
### Result Handoff 与派生 Graph
|
|
286
287
|
|
|
288
|
+
`agent(prompt, { working_dir: "/path/to/repository" })` 显式选择子代理工作目录;相对路径以父会话 cwd 解析,并在模型调用前验证。目标目录影响 Git、资源加载、Trust、Worktree 和 Replay 身份;只在 Prompt 中写路径不会切换 cwd。普通继承工具的内置角色不使用只读 Replay;明确配置只读工具的自定义角色仍保留原有 Replay 仓库边界。
|
|
289
|
+
|
|
287
290
|
成功调用返回同一 Run 内有效的 opaque `ref`。后续调用通过 `inputs: [previous.ref]` 显式接收上游结论;每个结论最多 16 KiB,合计最多 48 KiB,并标记为不可信数据。Artifacts 从这些引用派生只读 Graph,用来观察 lineage,不参与调度。
|
|
288
291
|
|
|
289
292
|
### Invocation Ledger
|
|
@@ -308,9 +311,11 @@ OpenPI 把一次调用拆成可以审计的生命周期,而不是把“进程
|
|
|
308
311
|
|
|
309
312
|
`operator: "name"` 在同一 Run 内复用一个内存 Child Session,并把同名 activation 串行化。首个 activation 固定 model、role/tool surface、effort、structured mode 与 cwd。Operator 不与 per-call Worktree 或 Replay 混用,也不承诺跨重启持久记忆。
|
|
310
313
|
|
|
311
|
-
###
|
|
314
|
+
### Deprecated Acceptance compatibility
|
|
315
|
+
|
|
316
|
+
`acceptance` 自 OpenPI 0.5 起弃用,并计划在 1.0 删除。兼容期仍读取旧 DSL、journal 与 artifact,但 ledger 只是执行任务的同一个模型所写的 `model-self-attestation`,不是 runtime-observed evidence,也不再决定 `agent().ok`;`ok` 只表示 child execution 与结果制品是否成功。
|
|
312
317
|
|
|
313
|
-
|
|
318
|
+
新 Workflow 应使用普通 `schema` 返回判断材料,由父模型结合退出码、测试结果、文件指纹和 tool receipts 等真实运行时事实综合判断。旧的可选 `acceptance: { criteria: [...] }` 仍可要求同一个 Agent 返回 ledger:
|
|
314
319
|
|
|
315
320
|
```js
|
|
316
321
|
acceptance: {
|
|
@@ -324,7 +329,7 @@ acceptance: {
|
|
|
324
329
|
}
|
|
325
330
|
```
|
|
326
331
|
|
|
327
|
-
|
|
332
|
+
条件缺失、格式错误或被拒绝时,原始输出与 ledger 仍保留并明确标注 authority/deprecation;它们不会把成功执行改成失败,也不会把失败执行改成成功。OpenPI 不会暗中再启动 reviewer、Shell 或额外 Judge 模型。
|
|
328
333
|
|
|
329
334
|
未设置 `requiredEvidence` 的 criterion 是对 `description` 的自我声明,不是有证据约束的验收门禁;需要 evidence-backed gate 时,必须声明所需证据标签。
|
|
330
335
|
|
|
@@ -408,12 +413,14 @@ macOS/Linux arm64 与 x64 缺少二进制时,OpenPI 会从官方 Release 下
|
|
|
408
413
|
|
|
409
414
|
无参数时,OpenPI 展示当前状态并引导修改;带自然语言时只改指定项:
|
|
410
415
|
|
|
411
|
-
<!-- config-contract: capabilities.discovery suggestions.enabled suggestions.model workflows.concurrency workflows.maxAgentCalls ui.showHeader ui.customFooter ui.footerStyle ui.footerLines ui.subagentResultDisplay ui.bashToolDisplay ui.fileMutationDisplay postEdit.command subagents.roleModels -->
|
|
416
|
+
<!-- config-contract: capabilities.discovery suggestions.enabled suggestions.model workflows.concurrency workflows.maxAgentCalls ui.webTheme ui.showHeader ui.customFooter ui.footerStyle ui.footerLines ui.subagentResultDisplay ui.bashToolDisplay ui.fileMutationDisplay postEdit.command subagents.roleModels -->
|
|
412
417
|
|
|
413
418
|
```text
|
|
414
419
|
/openpi-setup 开启下一步预测,选择 Registry 里的轻量模型,minimal 推理
|
|
415
420
|
/openpi-setup 让模型在合适时自主发现并采用 OpenPI 能力
|
|
416
421
|
/openpi-setup workflow 同时跑 16 个 agent,总调用最多 256
|
|
422
|
+
/openpi-setup Web 主题跟随系统
|
|
423
|
+
/openpi-setup Web 使用深色主题
|
|
417
424
|
/openpi-setup Footer 两行:cwd flex model / context cost flex git
|
|
418
425
|
/openpi-setup Bash 展开,Write/Edit 保持紧凑
|
|
419
426
|
/openpi-setup 编辑后自动跑 npm run format
|
|
@@ -434,18 +441,18 @@ Footer 布局以 `footerLines` 作为唯一持久化格式。旧版 `footerItems
|
|
|
434
441
|
| Capability discovery | `explicit`;`adaptive` 必须显式开启 |
|
|
435
442
|
| Next-action Suggestion | 关闭;启用时显式选择 Registry 模型与 reasoning |
|
|
436
443
|
| Workflow 并发 / 总调用 | 8 / 128;硬上限 64 / 1024 |
|
|
444
|
+
| Web 主题 | `system`;可选 `light` / `dark` |
|
|
437
445
|
| 大型 Header | 关闭 |
|
|
438
446
|
| Dashboard Footer | 开启;单行 `plain` |
|
|
439
447
|
| Subagent / Bash / Write/Edit | `compact` / `compact` / `compact` |
|
|
440
448
|
| Post-edit 命令 | 关闭;单条命令最多 500 字符 |
|
|
441
449
|
| 内置角色模型 | 全部继承父模型 |
|
|
442
|
-
| 主题 | 保留用户现有选择 |
|
|
443
450
|
|
|
444
451
|
</details>
|
|
445
452
|
|
|
446
453
|
### 安装要求与来源
|
|
447
454
|
|
|
448
|
-
- Pi `0.
|
|
455
|
+
- Pi `0.85.1` 或更新版本;
|
|
449
456
|
- Node.js `22.19.0` 或更新版本;
|
|
450
457
|
- npm 安装:`pi install npm:@tt-a1i/openpi`;
|
|
451
458
|
- GitHub 安装:`pi install git:github.com/openpi-dev/openpi`。
|
|
@@ -606,6 +613,8 @@ Capability discovery 默认是 `explicit`:普通父 Session 不常驻任何 Op
|
|
|
606
613
|
|
|
607
614
|
`subagent_spawn` 立即返回,结束后自动回传并重新唤醒主 Agent。交互会话没有其他工作时,主 Agent 应结束当前轮、让用户继续交互;“下一步依赖结果”本身不是阻塞理由。只有用户明确要求当前回复等完,或非交互自动化必须在同一次调用中返回完整结果时,才应调用 `subagent_wait`。
|
|
608
615
|
|
|
616
|
+
需要机器可验证的 review findings、research evidence 或 test matrix 时,可为 `subagent_spawn` 提供可选 `output_schema`。该次 Direct Subagent 只会额外获得 terminating `structured_output`,未提交匹配结果会明确失败;验证后的 JSON 会有界回传并写入私有 content-addressed artifact。省略 schema 的普通文本路径不会加载该 child tool 或 structured instruction。
|
|
617
|
+
|
|
609
618
|
</details>
|
|
610
619
|
|
|
611
620
|
<details>
|
|
@@ -646,6 +655,7 @@ Plan Mode 不猜“任意 Shell 是否只读”,只放行由已知安全零件
|
|
|
646
655
|
|
|
647
656
|
```text
|
|
648
657
|
extensions/
|
|
658
|
+
├── ai-providers/ # Antigravity 与实验性 Cursor OAuth 模型 Provider
|
|
649
659
|
├── setup/ # /openpi-setup 与受限配置工具
|
|
650
660
|
├── capabilities/ # 最小能力发现入口与 Session 工具面加载
|
|
651
661
|
├── background-terminals/ # 长进程、日志、/ps
|
|
@@ -691,6 +701,6 @@ npm 仍用于发布包的 `pack` / clean-install 验证,因为用户通过 npm
|
|
|
691
701
|
|
|
692
702
|
本项目最初基于 [davis7dotsh/my-pi-setup](https://github.com/davis7dotsh/my-pi-setup) 演进,现作为独立发行版维护。感谢原作者提供起点。
|
|
693
703
|
|
|
694
|
-
`extensions/sessions/` 改编自 [jayshah5696/pi-agent-extensions](https://github.com/jayshah5696/pi-agent-extensions)。独立可选的顶层 Session 通信 package 见 [pi-intercom](https://github.com/nicobailon/pi-intercom)。完整第三方说明见 [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)。
|
|
704
|
+
`extensions/ai-providers/` 的部分协议实现改编自 [oh-my-pi](https://github.com/can1357/oh-my-pi);`extensions/sessions/` 改编自 [jayshah5696/pi-agent-extensions](https://github.com/jayshah5696/pi-agent-extensions)。独立可选的顶层 Session 通信 package 见 [pi-intercom](https://github.com/nicobailon/pi-intercom)。完整第三方说明见 [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)。
|
|
695
705
|
|
|
696
706
|
本项目以 MIT 许可证发布(见 [`LICENSE`](LICENSE));`THIRD_PARTY_NOTICES.md` 记录第三方来源与各自许可。
|
package/SETUP.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Setup
|
|
2
2
|
|
|
3
|
-
Use Node.js 22.19.0 or newer. Install the public Pi package:
|
|
3
|
+
Use Pi 0.85.1 or newer and Node.js 22.19.0 or newer. Upgrade Pi before installing this OpenPI version; the temporary Pi 0.85.0 SDK import workaround has been removed. Install the public Pi package:
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
6
|
pi install npm:@tt-a1i/openpi
|
|
@@ -16,7 +16,7 @@ Pi installs the package dependencies automatically. Restart Pi or run `/reload`
|
|
|
16
16
|
|
|
17
17
|
## fd, rg, and read-only git tools
|
|
18
18
|
|
|
19
|
-
The `file-search` extension registers `fd` and `rg` as model tools, and `git-read` registers `git_show`, `git_diff`, and `git_log` (read-only git inspection). They stay outside an ordinary parent turn until the user explicitly asks to use `fd`/`rg`/git history, or structured file search, or the model loads the `search` group through `openpi_load_tools`. Entering or restoring Plan Mode is a runtime-safety exception: it loads `search` for that Session so diff investigation can use the structured Git boundary. The gateway is shown after an explicit OpenPI-capability request, or remains visible when the user opts into adaptive discovery;
|
|
19
|
+
The `file-search` extension registers `fd` and `rg` as model tools, and `git-read` registers `git_show`, `git_diff`, and `git_log` (read-only git inspection). They stay outside an ordinary parent turn until the user explicitly asks to use `fd`/`rg`/git history, or structured file search, or the model loads the `search` group through `openpi_load_tools`. Entering or restoring Plan Mode is a runtime-safety exception: it loads `search` for that Session so diff investigation can use the structured Git boundary. The gateway is shown after an explicit OpenPI-capability request, or remains visible when the user opts into adaptive discovery; children receive these tools only when active in the parent and permitted by their role allowlist. No setup is normally needed: at startup `fd`/`rg` silently use a system-installed binary (`fd`/`fdfind` and `rg`) when available, or an existing binary in the agent's private managed bin directory (`~/.pi/agent/bin`). Only when neither exists does it download an official release binary (macOS/Linux, arm64/x64, over HTTPS) into that directory — a persistent cache that survives package updates — and show a one-time notification. If your platform is unsupported, install `fd` and `rg` with your package manager and restart Pi. The git tools require a system `git`.
|
|
20
20
|
|
|
21
21
|
While Plan Mode is active, raw Bash `git diff`, `git show`, and `git whatchanged` are refused, as are diff-generating `git log` options such as `-p`, `--stat`, `--name-only`, and `-L`. Use `git_log` to find commits and `git_diff` / `git_show` to inspect changes; the latter commands always pass `--no-ext-diff --no-textconv --no-color`, so repository-configured `diff.external` and textconv drivers are not executed. This guarantee is scoped to the Git diff-driver boundary rather than every possible hostile Git configuration; the remaining allowlisted Git investigation commands still run inside Pi's existing project Trust boundary.
|
|
22
22
|
|
|
@@ -32,6 +32,8 @@ Add the included theme to `~/.pi/agent/settings.json` while keeping your existin
|
|
|
32
32
|
|
|
33
33
|
Pi will load the extensions and theme the next time it starts. OpenPI's Background, Subagent, and Workflow Skill files remain in the package, but ordinary turns do not advertise them in the system prompt; the matching path is disclosed only after explicit capability intent or after the model loads that group through the opt-in adaptive gateway.
|
|
34
34
|
|
|
35
|
+
The terminal theme above remains Pi-owned. OpenPI Web has a separate package-owned `system` / `light` / `dark` preference configured only through `/openpi-setup`; `system` is the default and follows the browser or operating-system color scheme.
|
|
36
|
+
|
|
35
37
|
## Configure this package
|
|
36
38
|
|
|
37
39
|
Use the single canonical package-owned command. `/my-pi-setup` remains a compatibility alias. With no arguments, the current model explains the configurable areas and uses `ask_user`: first run initializes them; later runs explain the saved state and ask whether to keep it, change one area, or review everything. With arguments, it treats the rest as a targeted natural-language request. Persist still goes through the typed `configure_my_pi_setup` tool. The writer stays hidden while a busy Session queues the setup request, becomes active only when that exact request is delivered to the model, and is hidden again afterward. One successful apply completes the episode. If the run settles without a successful apply, OpenPI appends a visible, durable closure receipt to the Session and later model context; it says that the writer is hidden and re-entry requires `/openpi-setup <request>`. OpenPI also verifies that the active writer belongs to the package source before announcing an active setup episode; duplicate or mismatched sources fail closed without injecting the setup request. A later configuration change starts a new episode with `/openpi-setup <request>` rather than reusing the hidden tool:
|
|
@@ -43,6 +45,8 @@ Use the single canonical package-owned command. `/my-pi-setup` remains a compati
|
|
|
43
45
|
/openpi-setup 开启下一步预测,使用 seal/deepseek-v4-flash,关闭推理
|
|
44
46
|
/openpi-setup 关闭下一步预测
|
|
45
47
|
/openpi-setup workflow 同时跑 16 个 agent,总任务最多 256 个
|
|
48
|
+
/openpi-setup Web theme follows the system
|
|
49
|
+
/openpi-setup use dark theme in OpenPI Web
|
|
46
50
|
/openpi-setup 显示大标题
|
|
47
51
|
/openpi-setup 切换 Footer 为 powerline
|
|
48
52
|
/openpi-setup 用 mono powerline Footer
|
|
@@ -56,11 +60,13 @@ Use the single canonical package-owned command. `/my-pi-setup` remains a compati
|
|
|
56
60
|
/openpi-setup 清除 explorer 的模型,让它继承父模型
|
|
57
61
|
```
|
|
58
62
|
|
|
59
|
-
Capability discovery defaults to `explicit`, preserving the zero-resident OpenPI tool surface until the user asks for a capability. The case-insensitive English words `subagent` and `workflow` are reserved authorization words: entering either word is sufficient to load its capability group, and the interactive editor shows it in Claude Code-style lavender before submission, with a darker purple fallback for light themes. This makes discussion that contains either English word an intentional opt-in tradeoff; conditional and negated clauses remain inert, while Chinese capability names still require a recognized action request. `adaptive` is an explicit opt-in that keeps only `openpi_load_tools` visible and allows the model to load a useful group on its own; because this can start Subagents, Workflows, or background processes, normal permission and configured concurrency/call limits still apply. Changing the setting updates the current Session immediately, while already loaded groups remain stable for that Session. Accepted Suggestion text is classified only after it becomes real editor input. The visual feedback and runtime activation share one fail-closed intent classifier. Next-action suggestions default to off. Run `/openpi-setup` to explicitly choose an available model and reasoning level. After a fully settled main-agent run, one suggestion may appear as dim inline text on the first row of an empty editor; reserved cells at the row end keep CJK IME preedit from overwriting it. `Right` accepts it into the editor without submitting, while any other editor input dismisses it. Suggestions are ephemeral and never enter session history or model context. Workflows default to 8 concurrent agents and 128 total agent calls per run; configurable hard maxima are 64 and 1024. The large decorative header defaults off and the custom dashboard footer defaults on with a one-line plain layout (`model context |flex| git pr cwd`; `thinking`, `cache`, `cost`, and `throughput` remain opt-in metrics). Footer presets are `powerline`, `powerline-mono`, and `compact`; style can also be set independently to `plain`, `powerline`, or `powerline-mono`. Custom layouts use a 2D `footerLines` array with at most one `flex` per row for left/right alignment. Nerd Font affects powerline separator glyphs (``) and adds Codex-style outline icons to compact read, terminal, edit, search, and directory activity rows; all accompanying text remains readable without it. Footer metrics use one Codicon outline family (`` model, `` context, and `` directory) plus `⎇` for the branch. A Nerd Font containing Codicons renders them as designed; without one, the text labels remain readable even if an icon falls back to an empty box. Footer changes apply immediately in the active TUI session. Subagent results default to a compact status summary; full mode remains available as a per-user setting, and `app.tools.expand` (`Ctrl+O` by default) reveals the available child report. Ordinary `read`, `grep`, `find`, and `ls` operations render as one-line semantic activity summaries. Bash and Write/Edit default to the same activity-row projection, showing the target, running/success/failure state, and useful line or diff counts without replaying stdout or previews. Select full independently for Bash or Write/Edit to keep Pi's native rendering expanded. `app.tools.expand` temporarily restores the native arguments, output, errors, diff, timing, images, truncation notices, and full-output metadata; it never changes Session history or model context. An optional post-edit command is off by default: set one (for example `npm run format`, maximum 500 characters) and it runs once in the background after each interactive-TUI turn with successful Write/Edit operations, with failures reported as a notification. It deliberately does not guess whether arbitrary Bash commands changed files. Built-in Agent roles `explorer`, `implementer`, `reviewer`, and `advisor` are shared by `subagent_spawn.agent_type` and Workflow `agent(..., { agent_type })`; all inherit the parent model by default. `/openpi-setup` may assign a currently available Registry model to any subset; clearing one returns it to inheritance and omitted roles stay unchanged. Model precedence is explicit call > selected role-file model > setup assignment > parent inheritance; effort is explicit call > selected role > parent. A trusted project `.pi/agents/<role>.md` overrides global `~/.pi/agent/agents/<role>.md`, which overrides the complete built-in role definition; overrides are diagnosed. Role-model changes apply to the next spawn or Workflow agent call without reload. Configuration is stored privately at `~/.pi/agent/my-pi-setup.json`.
|
|
63
|
+
Capability discovery defaults to `explicit`, preserving the zero-resident OpenPI tool surface until the user asks for a capability. The case-insensitive English words `subagent` and `workflow` are reserved authorization words: entering either word is sufficient to load its capability group, and the interactive editor shows it in Claude Code-style lavender before submission, with a darker purple fallback for light themes. This makes discussion that contains either English word an intentional opt-in tradeoff; conditional and negated clauses remain inert, while Chinese capability names still require a recognized action request. `adaptive` is an explicit opt-in that keeps only `openpi_load_tools` visible and allows the model to load a useful group on its own; because this can start Subagents, Workflows, or background processes, normal permission and configured concurrency/call limits still apply. Changing the setting updates the current Session immediately, while already loaded groups remain stable for that Session. Accepted Suggestion text is classified only after it becomes real editor input. The visual feedback and runtime activation share one fail-closed intent classifier. Next-action suggestions default to off. Run `/openpi-setup` to explicitly choose an available model and reasoning level. After a fully settled main-agent run, one suggestion may appear as dim inline text on the first row of an empty editor; reserved cells at the row end keep CJK IME preedit from overwriting it. `Right` accepts it into the editor without submitting, while any other editor input dismisses it. Suggestions are ephemeral and never enter session history or model context. Workflows default to 8 concurrent agents and 128 total agent calls per run; configurable hard maxima are 64 and 1024. The large decorative header defaults off and the custom dashboard footer defaults on with a one-line plain layout (`model context |flex| git pr cwd`; `thinking`, `cache`, `cost`, and `throughput` remain opt-in metrics). Footer presets are `powerline`, `powerline-mono`, and `compact`; style can also be set independently to `plain`, `powerline`, or `powerline-mono`. Custom layouts use a 2D `footerLines` array with at most one `flex` per row for left/right alignment. Nerd Font affects powerline separator glyphs (``) and adds Codex-style outline icons to compact read, terminal, edit, search, and directory activity rows; all accompanying text remains readable without it. Footer metrics use one Codicon outline family (`` model, `` context, and `` directory) plus `⎇` for the branch. A Nerd Font containing Codicons renders them as designed; without one, the text labels remain readable even if an icon falls back to an empty box. Footer changes apply immediately in the active TUI session. Subagent results default to a compact status summary; full mode remains available as a per-user setting, and `app.tools.expand` (`Ctrl+O` by default) reveals the available child report. Ordinary `read`, `grep`, `find`, and `ls` operations render as one-line semantic activity summaries. Bash and Write/Edit default to the same activity-row projection, showing the target, running/success/failure state, and useful line or diff counts without replaying stdout or previews. Select full independently for Bash or Write/Edit to keep Pi's native rendering expanded. `app.tools.expand` temporarily restores the native arguments, output, errors, diff, timing, images, truncation notices, and full-output metadata; it never changes Session history or model context. An optional post-edit command is off by default: set one (for example `npm run format`, maximum 500 characters) and it runs once in the background after each interactive-TUI turn with successful Write/Edit operations, with failures reported as a notification. It deliberately does not guess whether arbitrary Bash commands changed files. Built-in Agent roles `explorer`, `implementer`, `reviewer`, and `advisor` are shared by `subagent_spawn.agent_type` and Workflow `agent(..., { agent_type })`; all inherit the parent model and currently active child-eligible tools by default. Explicit custom role `tools` lists narrow that surface; omitted lists inherit it. Built-in investigator roles suggest read-only work but do not impose a read-only tool boundary outside Plan Mode. Existing role files are preserved, so an old global `explorer.md` allowlist continues to exclude Bash/network tools until deliberately edited. `/openpi-setup` may assign a currently available Registry model to any subset; clearing one returns it to inheritance and omitted roles stay unchanged. Model precedence is explicit call > selected role-file model > setup assignment > parent inheritance; effort is explicit call > selected role > parent. A trusted project `.pi/agents/<role>.md` overrides global `~/.pi/agent/agents/<role>.md`, which overrides the complete built-in role definition; overrides are diagnosed. Role-model changes apply to the next spawn or Workflow agent call without reload. Configuration is stored privately at `~/.pi/agent/my-pi-setup.json`.
|
|
64
|
+
|
|
65
|
+
OpenPI Web theme defaults to `system`; `light` and `dark` are explicit canonical setup choices, and the browser consumes them from each authoritative snapshot without writing a competing local preference.
|
|
60
66
|
|
|
61
67
|
Legacy `footerItems` is accepted and migrated at the input boundary, but new setup writes persist only canonical `footerLines`. Configurations written by this version are not guaranteed to retain their Footer layout when read by an older OpenPI version.
|
|
62
68
|
|
|
63
|
-
<!-- config-contract: capabilities.discovery suggestions.enabled suggestions.model workflows.concurrency workflows.maxAgentCalls ui.showHeader ui.customFooter ui.footerStyle ui.footerLines ui.subagentResultDisplay ui.bashToolDisplay ui.fileMutationDisplay postEdit.command subagents.roleModels -->
|
|
69
|
+
<!-- config-contract: capabilities.discovery suggestions.enabled suggestions.model workflows.concurrency workflows.maxAgentCalls ui.webTheme ui.showHeader ui.customFooter ui.footerStyle ui.footerLines ui.subagentResultDisplay ui.bashToolDisplay ui.fileMutationDisplay postEdit.command subagents.roleModels -->
|
|
64
70
|
|
|
65
71
|
## Optional cross-session communication
|
|
66
72
|
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Third-Party Notices
|
|
2
2
|
|
|
3
|
+
## OAuth model providers
|
|
4
|
+
|
|
5
|
+
`extensions/ai-providers/` adapts protocol and OAuth details from
|
|
6
|
+
[`oh-my-pi`](https://github.com/can1357/oh-my-pi) (Antigravity Cloud Code
|
|
7
|
+
Assist and Cursor AgentService). The upstream project is distributed under the
|
|
8
|
+
MIT License. Its copyright notice states `Copyright (c) 2025 Mario Zechner`,
|
|
9
|
+
`Copyright (c) 2025-2026 Can Bölük`, and `Copyright (c) 2026 Stencil Labs, Inc.`;
|
|
10
|
+
the complete license text is included at
|
|
11
|
+
[`extensions/ai-providers/LICENSE.upstream`](extensions/ai-providers/LICENSE.upstream).
|
|
12
|
+
The local Antigravity message conversion is adapted from the same project's
|
|
13
|
+
pi-ai 0.84.1 Google conversion implementation so the installed extension does
|
|
14
|
+
not depend on a non-public Pi runtime module.
|
|
15
|
+
|
|
16
|
+
Cursor support in this package is chat-only: it does not copy or execute
|
|
17
|
+
Cursor-native coding tools.
|
|
18
|
+
|
|
3
19
|
## Sessions extension
|
|
4
20
|
|
|
5
21
|
`extensions/sessions/` is adapted from
|
package/bin/openpi.js
CHANGED
|
@@ -67,7 +67,17 @@ const stop = () => {
|
|
|
67
67
|
};
|
|
68
68
|
|
|
69
69
|
try {
|
|
70
|
-
const
|
|
70
|
+
const bootstrap = createJiti(import.meta.url);
|
|
71
|
+
const { missingPiCodingAgentDiagnostic, resolveStandaloneJitiAliases } =
|
|
72
|
+
await bootstrap.import("../web/host/pi-coding-agent-entry.ts");
|
|
73
|
+
const aliases = resolveStandaloneJitiAliases({
|
|
74
|
+
fromUrl: import.meta.url,
|
|
75
|
+
});
|
|
76
|
+
if (!aliases["@earendil-works/pi-coding-agent"]) {
|
|
77
|
+
console.error(missingPiCodingAgentDiagnostic());
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
const jiti = createJiti(import.meta.url, { alias: aliases });
|
|
71
81
|
const [browserModule, hostModule, runtimeModule, statusModule, traceModule] =
|
|
72
82
|
await Promise.all([
|
|
73
83
|
jiti.import("../web/host/browser-launcher.ts"),
|
|
@@ -95,6 +105,20 @@ try {
|
|
|
95
105
|
: {}),
|
|
96
106
|
});
|
|
97
107
|
await host.start();
|
|
108
|
+
const onStopSignal = () => {
|
|
109
|
+
void stop().then(
|
|
110
|
+
() => process.exit(0),
|
|
111
|
+
(error) => {
|
|
112
|
+
console.error(
|
|
113
|
+
`Failed to stop OpenPI Web Workbench: ${error instanceof Error ? error.message : String(error)}`,
|
|
114
|
+
);
|
|
115
|
+
process.exit(1);
|
|
116
|
+
},
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
120
|
+
process.once(signal, onStopSignal);
|
|
121
|
+
}
|
|
98
122
|
traceWeb("web_started", {
|
|
99
123
|
...(runtime.workspaceSelected === true ? { cwd: runtime.cwd } : {}),
|
|
100
124
|
origin: host.origin,
|
|
@@ -112,20 +136,6 @@ try {
|
|
|
112
136
|
console.log(`OpenPI Web Workbench is running at ${host.origin}`);
|
|
113
137
|
if (!opened) console.log(`Open this URL in a browser: ${host.url}`);
|
|
114
138
|
}
|
|
115
|
-
|
|
116
|
-
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
117
|
-
process.once(signal, () => {
|
|
118
|
-
void stop().then(
|
|
119
|
-
() => process.exit(0),
|
|
120
|
-
(error) => {
|
|
121
|
-
console.error(
|
|
122
|
-
`Failed to stop OpenPI Web Workbench: ${error instanceof Error ? error.message : String(error)}`,
|
|
123
|
-
);
|
|
124
|
-
process.exit(1);
|
|
125
|
-
},
|
|
126
|
-
);
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
139
|
} catch (error) {
|
|
130
140
|
let cleanupError;
|
|
131
141
|
try {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Mario Zechner
|
|
4
|
+
Copyright (c) 2025-2026 Can Bölük
|
|
5
|
+
Copyright (c) 2026 Stencil Labs, Inc.
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
in the Software without restriction, including without limitation the rights
|
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
SOFTWARE.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# OAuth model providers
|
|
2
|
+
|
|
3
|
+
This extension registers two opt-in model providers backed by account OAuth:
|
|
4
|
+
|
|
5
|
+
- `google-antigravity` uses Google Cloud Code Assist and supports ordinary Pi
|
|
6
|
+
tool calls.
|
|
7
|
+
- `cursor` uses Cursor AgentService with an experimental Pi tool bridge.
|
|
8
|
+
The active Pi tools are advertised as MCP tools. A complete invocation returns
|
|
9
|
+
to Pi for permission checks and execution; the next provider turn replays the
|
|
10
|
+
paired result. Cursor-native shell, editing, web, task, and interaction tools
|
|
11
|
+
remain unsupported and fail explicitly. The provider never executes tools
|
|
12
|
+
inside its transport or widens a child session's effective tool set.
|
|
13
|
+
|
|
14
|
+
After installing OpenPI, restart Pi or run `/reload`, then authenticate and
|
|
15
|
+
select a model:
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
/login google-antigravity
|
|
19
|
+
/login cursor
|
|
20
|
+
/model
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
For source-checkout testing, follow the repository's
|
|
24
|
+
[development runtime provenance procedure](../../README.md#开发运行时区分-npm-与当前源码).
|
|
25
|
+
Remove any previously installed OpenPI source, install the checkout, and verify
|
|
26
|
+
that `pi list` reports this checkout as the only OpenPI source before reloading
|
|
27
|
+
Pi. Do not mix an installed OpenPI package with an explicitly loaded checkout
|
|
28
|
+
extension, because that does not prove which source owns the runtime behavior.
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
pi list
|
|
32
|
+
OLD_OPENPI_SOURCE=/absolute/path/to/old/openpi
|
|
33
|
+
pi remove "$OLD_OPENPI_SOURCE"
|
|
34
|
+
pi install "$PWD"
|
|
35
|
+
pi list
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The model catalog is refreshed from the authenticated account and persisted by
|
|
39
|
+
Pi. A failed refresh retains the last successful account catalog; Antigravity
|
|
40
|
+
also has a validated static baseline, while Cursor keeps the server-side `Auto`
|
|
41
|
+
route as its baseline. No provider is contacted until it is selected.
|
|
42
|
+
|
|
43
|
+
Pi's interactive clipboard flow inserts an image's local path into the editor.
|
|
44
|
+
When Cursor is selected, a supported PNG/JPEG/GIF/WebP path at the start of an
|
|
45
|
+
interactive prompt is converted into an actual image attachment (up to 10 MiB)
|
|
46
|
+
before the request is sent. The absolute path is not exposed to the model.
|
|
47
|
+
|
|
48
|
+
When Pi supplies tools, the provider directs Cursor to the advertised Pi MCP
|
|
49
|
+
catalog. Without tools it uses an explicit chat-only rule. Partial tool previews
|
|
50
|
+
and approval-only probes never execute a tool; unknown or malformed invocations
|
|
51
|
+
fail explicitly. Local HTTP/2 tests exercise a normal Pi tool lifecycle and
|
|
52
|
+
result replay, but account/model-specific compatibility still requires a live
|
|
53
|
+
smoke test. Cursor's native execution protocol is intentionally not enabled.
|
|
54
|
+
|
|
55
|
+
Cursor's token delta describes generated output only, so the provider does not
|
|
56
|
+
publish it as complete context usage. Pi 0.84.3+ can estimate an all-Cursor
|
|
57
|
+
history and trigger threshold compaction without provider usage. Older Pi hosts
|
|
58
|
+
retain the correct unknown-usage state but cannot automatically threshold-
|
|
59
|
+
compact a session with no usage-backed response. Project-wide Pi baseline
|
|
60
|
+
tracking is kept in [#328](https://github.com/openpi-dev/openpi/issues/328).
|
|
61
|
+
|
|
62
|
+
Cursor model discovery and chat use HTTP/2. They honor `PI_PROXY_CURSOR`, then
|
|
63
|
+
`PI_PROXY`, the standard `HTTPS_PROXY`/`HTTP_PROXY` variables, and `ALL_PROXY`;
|
|
64
|
+
`NO_PROXY` bypass rules apply. The proxy must support HTTP CONNECT and preserve
|
|
65
|
+
HTTP/2 ALPN negotiation to Cursor.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential codec for the Antigravity provider.
|
|
3
|
+
*
|
|
4
|
+
* pi persists whatever object `login` returns into auth.json and hands it back
|
|
5
|
+
* to `refreshToken`/`getApiKey` verbatim, so the Antigravity-specific extras
|
|
6
|
+
* (projectId, email) ride along as additional fields. `getApiKey` then packs
|
|
7
|
+
* everything the stream needs into the single `apiKey` string pi threads into
|
|
8
|
+
* `SimpleStreamOptions.apiKey`.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { OAuthCredentials } from "@earendil-works/pi-ai/compat";
|
|
12
|
+
|
|
13
|
+
/** Stored credential shape: pi's OAuth fields plus Antigravity extras. */
|
|
14
|
+
export interface AntigravityCredentials extends OAuthCredentials {
|
|
15
|
+
/** Cloud Code Assist project resolved during login provisioning. */
|
|
16
|
+
projectId?: string;
|
|
17
|
+
/** Google account email, best-effort display metadata. */
|
|
18
|
+
email?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** What the stream function needs, packed into the apiKey string. */
|
|
22
|
+
export interface AntigravityApiKeyPayload {
|
|
23
|
+
token: string;
|
|
24
|
+
projectId?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function encodeApiKey(credentials: AntigravityCredentials): string {
|
|
28
|
+
const payload: AntigravityApiKeyPayload = {
|
|
29
|
+
token: credentials.access,
|
|
30
|
+
projectId: credentials.projectId,
|
|
31
|
+
};
|
|
32
|
+
return JSON.stringify(payload);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function decodeApiKey(raw: string): AntigravityApiKeyPayload {
|
|
36
|
+
try {
|
|
37
|
+
const parsed: unknown = JSON.parse(raw);
|
|
38
|
+
if (parsed !== null && typeof parsed === "object" && "token" in parsed) {
|
|
39
|
+
const token = parsed.token;
|
|
40
|
+
if (typeof token === "string") {
|
|
41
|
+
const projectId =
|
|
42
|
+
"projectId" in parsed && typeof parsed.projectId === "string"
|
|
43
|
+
? parsed.projectId
|
|
44
|
+
: undefined;
|
|
45
|
+
return { token, projectId };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
// Not JSON: tolerate a bare access token (e.g. hand-written auth.json).
|
|
50
|
+
}
|
|
51
|
+
return { token: raw };
|
|
52
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antigravity model discovery.
|
|
3
|
+
*
|
|
4
|
+
* `POST /v1internal:fetchAvailableModels` returns a map of wire model id to
|
|
5
|
+
* metadata (reference: omp packages/catalog/src/discovery/antigravity.ts).
|
|
6
|
+
* Static models are the provider baseline. Network/protocol failures throw so
|
|
7
|
+
* createProvider can retain the last successfully persisted dynamic catalog.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { RefreshModelsContext } from "@earendil-works/pi-ai";
|
|
11
|
+
import { Type, type Static } from "typebox";
|
|
12
|
+
import { Value } from "typebox/value";
|
|
13
|
+
import { ensureAntigravityVersion, getAntigravityUserAgent } from "./oauth.ts";
|
|
14
|
+
import {
|
|
15
|
+
ANTIGRAVITY_API_URL,
|
|
16
|
+
type AntigravityProviderModel,
|
|
17
|
+
} from "./models.ts";
|
|
18
|
+
import {
|
|
19
|
+
collapseAntigravityModels,
|
|
20
|
+
type AntigravityModelDefinition,
|
|
21
|
+
} from "./routing.ts";
|
|
22
|
+
|
|
23
|
+
const DISCOVERY_ENDPOINTS = [
|
|
24
|
+
"https://daily-cloudcode-pa.googleapis.com",
|
|
25
|
+
"https://daily-cloudcode-pa.sandbox.googleapis.com",
|
|
26
|
+
] as const;
|
|
27
|
+
const FETCH_AVAILABLE_MODELS_PATH = "/v1internal:fetchAvailableModels";
|
|
28
|
+
|
|
29
|
+
// Reference: omp ANTIGRAVITY_DISCOVERY_DENYLIST.
|
|
30
|
+
const DISCOVERY_DENYLIST: Record<string, true> = {
|
|
31
|
+
chat_20706: true,
|
|
32
|
+
chat_23310: true,
|
|
33
|
+
"gemini-2.5-pro": true,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const DEFAULT_CONTEXT_WINDOW = 200_000;
|
|
37
|
+
const DEFAULT_MAX_TOKENS = 64_000;
|
|
38
|
+
|
|
39
|
+
const DiscoveryModelSchema = Type.Object({
|
|
40
|
+
displayName: Type.Optional(Type.String()),
|
|
41
|
+
supportsImages: Type.Optional(Type.Boolean()),
|
|
42
|
+
supportsThinking: Type.Optional(Type.Boolean()),
|
|
43
|
+
maxTokens: Type.Optional(Type.Number()),
|
|
44
|
+
maxOutputTokens: Type.Optional(Type.Number()),
|
|
45
|
+
isInternal: Type.Optional(Type.Boolean()),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const DiscoveryResponseSchema = Type.Object({
|
|
49
|
+
models: Type.Optional(Type.Record(Type.String(), DiscoveryModelSchema)),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
type DiscoveryResponse = Static<typeof DiscoveryResponseSchema>;
|
|
53
|
+
|
|
54
|
+
type DiscoveredModel = AntigravityProviderModel & AntigravityModelDefinition;
|
|
55
|
+
|
|
56
|
+
function positiveNumber(value: number | undefined, fallback: number): number {
|
|
57
|
+
return value !== undefined && Number.isFinite(value) && value > 0
|
|
58
|
+
? value
|
|
59
|
+
: fallback;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function toModelDefinition(
|
|
63
|
+
id: string,
|
|
64
|
+
meta: Static<typeof DiscoveryModelSchema>,
|
|
65
|
+
): DiscoveredModel {
|
|
66
|
+
const advertisedMaxTokens = positiveNumber(
|
|
67
|
+
meta.maxOutputTokens,
|
|
68
|
+
DEFAULT_MAX_TOKENS,
|
|
69
|
+
);
|
|
70
|
+
return {
|
|
71
|
+
id,
|
|
72
|
+
name: meta.displayName ?? id,
|
|
73
|
+
api: "antigravity-cloudcode",
|
|
74
|
+
provider: "google-antigravity",
|
|
75
|
+
baseUrl: ANTIGRAVITY_API_URL,
|
|
76
|
+
reasoning: meta.supportsThinking === true,
|
|
77
|
+
input: meta.supportsImages === true ? ["text", "image"] : ["text"],
|
|
78
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
79
|
+
contextWindow: positiveNumber(meta.maxTokens, DEFAULT_CONTEXT_WINDOW),
|
|
80
|
+
maxTokens: id.toLowerCase().includes("claude")
|
|
81
|
+
? Math.min(advertisedMaxTokens, DEFAULT_MAX_TOKENS)
|
|
82
|
+
: advertisedMaxTokens,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function fetchAntigravityModels(
|
|
87
|
+
context: RefreshModelsContext,
|
|
88
|
+
): Promise<DiscoveredModel[]> {
|
|
89
|
+
if (!context.allowNetwork) return [];
|
|
90
|
+
context.signal.throwIfAborted();
|
|
91
|
+
const credential = context.credential;
|
|
92
|
+
if (!credential || credential.type !== "oauth") return [];
|
|
93
|
+
await ensureAntigravityVersion(context.signal);
|
|
94
|
+
|
|
95
|
+
for (const endpoint of DISCOVERY_ENDPOINTS) {
|
|
96
|
+
if (context.signal.aborted) break;
|
|
97
|
+
try {
|
|
98
|
+
const response = await fetch(
|
|
99
|
+
`${endpoint}${FETCH_AVAILABLE_MODELS_PATH}`,
|
|
100
|
+
{
|
|
101
|
+
method: "POST",
|
|
102
|
+
headers: {
|
|
103
|
+
Authorization: `Bearer ${credential.access}`,
|
|
104
|
+
"Content-Type": "application/json",
|
|
105
|
+
"User-Agent": getAntigravityUserAgent(),
|
|
106
|
+
},
|
|
107
|
+
body: "{}",
|
|
108
|
+
signal: context.signal,
|
|
109
|
+
},
|
|
110
|
+
);
|
|
111
|
+
if (!response.ok) continue;
|
|
112
|
+
const parsed = Value.Parse(
|
|
113
|
+
DiscoveryResponseSchema,
|
|
114
|
+
await response.json(),
|
|
115
|
+
) as DiscoveryResponse;
|
|
116
|
+
if (!parsed.models) continue;
|
|
117
|
+
const discovered = Object.entries(parsed.models)
|
|
118
|
+
.filter(
|
|
119
|
+
([id, meta]) =>
|
|
120
|
+
!Object.hasOwn(DISCOVERY_DENYLIST, id) && meta.isInternal !== true,
|
|
121
|
+
)
|
|
122
|
+
.map(([id, meta]) => toModelDefinition(id, meta));
|
|
123
|
+
return collapseAntigravityModels(discovered);
|
|
124
|
+
} catch {
|
|
125
|
+
// Try the next endpoint; total failure must preserve the stored catalog.
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
context.signal.throwIfAborted();
|
|
129
|
+
throw new Error("Antigravity model discovery failed on all endpoints");
|
|
130
|
+
}
|