@maxiaochao/pi-toolkit 0.13.1 → 0.13.3
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 +14 -0
- package/README.md +17 -1
- package/package.json +4 -3
- package/packages/codex-edit/CHANGELOG.md +7 -0
- package/packages/codex-edit/README.md +12 -4
- package/packages/codex-edit/TESTING.md +10 -2
- package/packages/codex-edit/docs/test-report.html +4 -3
- package/packages/codex-edit/docs/test-report.md +4 -3
- package/packages/codex-edit/docs/test-summary.md +1 -1
- package/packages/codex-edit/extensions/codex-edit.ts +3 -10
- package/packages/codex-edit/package.json +3 -3
- package/packages/codex-edit/src/config.ts +40 -0
- package/packages/codex-edit/tests/config-integration.ts +78 -0
- package/packages/codex-edit/tests/config.test.mjs +80 -0
- package/packages/codex-edit/tests/generate-test-report.mjs +6 -2
- package/packages/codex-edit/tests/package.test.mjs +4 -1
- package/skills/agent-team/SKILL.md +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## 2026-10-21 - v0.13.3
|
|
2
|
+
|
|
3
|
+
- codex-edit v0.2.0: persist personal routing rules in the Pi agent directory across package updates
|
|
4
|
+
- Codex Edit: read persistent personal routing overrides from `~/.pi/agent/codex-edit.json` (respecting `PI_CODING_AGENT_DIR`), shared by parent sessions and explicitly configured subagents; validate user settings and preserve the bundled defaults.
|
|
5
|
+
|
|
6
|
+
## 2026-10-21 - v0.13.2
|
|
7
|
+
|
|
8
|
+
- make agent-team user-invoked only and add post-release workflow/npm/tarball verification
|
|
9
|
+
|
|
10
|
+
## Unreleased
|
|
11
|
+
|
|
12
|
+
- Make Agent Team user-invoked only through `/skill:agent-team`, hidden from automatic model selection.
|
|
13
|
+
- Add `npm run release:check -- vX.Y.Z` to wait for GitHub publication and verify exact npm versions, remote tags, integrity, and all tarball contents against the release commit, including coordinated child releases.
|
|
14
|
+
|
|
1
15
|
## 2026-10-21 - v0.13.1
|
|
2
16
|
|
|
3
17
|
- herdr-subagents v0.7.2: clarify final answer submission through subagent_report
|
package/README.md
CHANGED
|
@@ -40,6 +40,8 @@ Restart Pi after updating. `pi update --extensions` has the same effect when upd
|
|
|
40
40
|
|
|
41
41
|
Each child README owns its feature description, motivation or upstream alignment, examples, screenshots/demos, configuration, and test documentation.
|
|
42
42
|
|
|
43
|
+
Codex Edit personal routing rules belong in `~/.pi/agent/codex-edit.json`, not inside `node_modules`. User fields override bundled defaults; `models` replaces the complete default list. The file survives package updates and is shared by parent sessions and explicitly configured subagents using the same agent directory. Use `/reload` after editing it, and start new subagents. See [Codex Edit configuration](packages/codex-edit/README.md#configuration).
|
|
44
|
+
|
|
43
45
|
Herdr Subagents tasks require an explicit `agent` Persona; no default `worker` is selected. Choose `reviewer` for independent reviews of proposals, designs, documents, implementations, or analysis; `explorer` for codebase investigation; `worker` for file-changing work; and `analyst` for charter-defined agent-team roles. See [built-in Personas](packages/herdr-subagents/README.md#built-in-personas) for selection guidance and the distinction between parent-facing descriptions and child instructions. Personas can opt into local extension files or npm/git Pi packages through `extensions`. Set top-level `defaultExtensions` in `~/.pi/agent/herdr-subagents.json` (or project `.pi/herdr-subagents.json`) to share a fallback list; Persona-specific lists take precedence, and `[]` clears inherited sources. This uses native Pi package semantics: package-provided skills, prompt templates, and themes may also load, and `--no-skills` does not exclude explicitly selected package skills. See the [extension-source contract](packages/herdr-subagents/README.md#explicit-extension-sources-and-pi-packages) for precedence, isolation, and examples. The [real Herdr smoke test](packages/herdr-subagents/TESTING.md) preserves the configured analyst model and explicit authentication extensions while isolating unrelated settings.
|
|
44
46
|
|
|
45
47
|
Multiple standalone children may be installed together. `pi-openai-account-pool` may also be installed alongside the complete toolkit because the toolkit does not embed it. Every other child in the table above, including `pi-background-tasks`, is embedded, so a second install exposes the same resource twice.
|
|
@@ -77,7 +79,7 @@ bash scripts/install.sh
|
|
|
77
79
|
| `html-artifact` | Build self-contained HTML explainers and diagrams |
|
|
78
80
|
| `pdlog` | Decompress and inspect Pudu `.pdlog` files |
|
|
79
81
|
| `herdr` | Control Herdr workspaces, tabs, panes, and agents |
|
|
80
|
-
| `agent-team` |
|
|
82
|
+
| `agent-team` | Manually invoke `/skill:agent-team` for concurrent analysis with configured models and roles, result collection, and investigation records; hidden from automatic model selection |
|
|
81
83
|
| `tapd` | Investigate and operate on TAPD items with workspace, evidence, and safe-download guardrails |
|
|
82
84
|
|
|
83
85
|
Package-specific skills, such as `pi-worktree`, are documented by their child package.
|
|
@@ -85,3 +87,17 @@ Package-specific skills, such as `pi-worktree`, are documented by their child pa
|
|
|
85
87
|
## Repository
|
|
86
88
|
|
|
87
89
|
This repository is an npm workspace. Child implementations live under `packages/*`; `extensions/` contains only the toolkit-only BTW module. Development, testing, media generation, and release rules are documented in [AGENTS.md](AGENTS.md).
|
|
90
|
+
|
|
91
|
+
### Post-release verification
|
|
92
|
+
|
|
93
|
+
After pushing a release, run from this checkout:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npm run release:check -- v0.13.1
|
|
97
|
+
# Wait up to 15 minutes, polling every 15 seconds:
|
|
98
|
+
npm run release:check -- v0.13.1 --timeout 900 --interval 15
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Omit the tag to use the current root `package.json` version. Requires Node.js, Git, npm, tar, authenticated GitHub CLI (`gh auth login`), and local release tags (`git fetch origin --tags` if needed).
|
|
102
|
+
|
|
103
|
+
The read-only check verifies remote tag commits, waits for the matching `publish.yml` run to succeed, and checks exact public npm versions and tarball integrity. It compares every packaged file and mode against an isolated snapshot of the release tag, including an optional coordinated child release. It uses the tag rather than uncommitted checkout changes, never installs or publishes, and removes temporary downloads. Failures exit nonzero; only a pending workflow or npm `E404` is retried within the shared timeout (600 seconds by default). Local packing uses `--ignore-scripts`, matching this repository's source-only packages; packages that add generated prepack output will need this check updated.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maxiaochao/pi-toolkit",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.3",
|
|
4
4
|
"description": "Personal pi coding agent toolkit: background tasks, scheduler, /btw, /cache_export, apply_patch, browser automation, and bundled theme/skills.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"workspaces": [
|
|
@@ -61,10 +61,11 @@
|
|
|
61
61
|
"ws": "^8.19.0"
|
|
62
62
|
},
|
|
63
63
|
"scripts": {
|
|
64
|
-
"test": "node tests/package-layout.mjs && node tests/release-check.mjs && npm --prefix packages/todo test && npm --prefix packages/cache-export test && npm --prefix packages/codex-edit test && npm --prefix packages/herdr-subagents test && npm --prefix packages/openai-account-pool test && npm --prefix packages/scheduler test && npm --prefix packages/background-tasks test && npm --prefix packages/worktree test && node --experimental-strip-types extensions/btw/tests/history.mjs",
|
|
65
|
-
"test:root": "node tests/package-layout.mjs && node tests/release-check.mjs && node --experimental-strip-types extensions/btw/tests/history.mjs",
|
|
64
|
+
"test": "node tests/package-layout.mjs && node tests/release-check.mjs && node tests/post-release-check.mjs && npm --prefix packages/todo test && npm --prefix packages/cache-export test && npm --prefix packages/codex-edit test && npm --prefix packages/herdr-subagents test && npm --prefix packages/openai-account-pool test && npm --prefix packages/scheduler test && npm --prefix packages/background-tasks test && npm --prefix packages/worktree test && node --experimental-strip-types extensions/btw/tests/history.mjs",
|
|
65
|
+
"test:root": "node tests/package-layout.mjs && node tests/release-check.mjs && node tests/post-release-check.mjs && node --experimental-strip-types extensions/btw/tests/history.mjs",
|
|
66
66
|
"load-test": "pi -ne -e ./packages/cache-export/extensions/cache-export.ts && pi -ne -e ./extensions/btw/index.ts && pi -ne -e ./packages/codex-edit/extensions/codex-edit.ts && pi -ne -e ./packages/herdr-subagents/extensions/herdr-subagents.ts && pi -ne -e ./packages/scheduler/extensions/scheduler.ts && pi -ne -e ./packages/background-tasks/extensions/background-tasks.ts && pi -ne -e ./packages/worktree/extensions/worktree.ts && npm --prefix packages/background-tasks run load-test -- --toolkit",
|
|
67
67
|
"load-test:root": "pi -ne -e ./extensions/btw/index.ts",
|
|
68
|
+
"release:check": "node scripts/post-release-check.mjs",
|
|
68
69
|
"eval:agents": "node evaluations/agents-md/run.mjs",
|
|
69
70
|
"eval:agents:test": "node evaluations/agents-md/tests/run-tests.mjs",
|
|
70
71
|
"postinstall": "node scripts/install-agents.mjs"
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## 2026-10-21 - v0.2.0
|
|
2
|
+
|
|
3
|
+
- persist personal routing rules in the Pi agent directory across package updates
|
|
4
|
+
- Read persistent user overrides from `~/.pi/agent/codex-edit.json`, or the custom `PI_CODING_AGENT_DIR`, so package updates no longer replace personal routing rules.
|
|
5
|
+
- Merge settings by field over package defaults; replace model lists, preserve explicit false/empty values, and report malformed or unreadable configuration with its path.
|
|
6
|
+
- Cover shared parent/child editor routing, reloads, API restrictions, read-only tool selection, and real patch execution through the production extension factory.
|
|
7
|
+
|
|
1
8
|
## 2026-10-10 - v0.1.10
|
|
2
9
|
|
|
3
10
|
- remove redundant apply_patch prompt metadata
|
|
@@ -50,7 +50,7 @@ The extension registers `apply_patch` and selects the editing tool from the reso
|
|
|
50
50
|
- Model ID outside the allowlist: Pi's native `edit`
|
|
51
51
|
- Model on another API, even if its ID matches: Pi's native `edit`
|
|
52
52
|
|
|
53
|
-
The default allowlist enables all `gpt-5.6-*` models regardless of provider. Other model families can be added after separate validation
|
|
53
|
+
The default allowlist enables all `gpt-5.6-*` models regardless of provider. Other model families can be added after separate validation in `~/.pi/agent/codex-edit.json`.
|
|
54
54
|
|
|
55
55
|
The extension does not add a permanent AGENTS rule telling models not to use `apply_patch`. Only the selected editor tool is active, so the model receives one editing protocol.
|
|
56
56
|
|
|
@@ -74,7 +74,11 @@ This repeated-header tolerance is a deliberate Pi-side extension: current Codex
|
|
|
74
74
|
|
|
75
75
|
## Configuration
|
|
76
76
|
|
|
77
|
-
The extension
|
|
77
|
+
The extension reads package defaults from its bundled `config.json`, then applies user overrides from `~/.pi/agent/codex-edit.json`. The user file is outside the installed package, so package updates do not replace your rules. When `PI_CODING_AGENT_DIR` is set, the user file is `<PI_CODING_AGENT_DIR>/codex-edit.json` instead.
|
|
78
|
+
|
|
79
|
+
Each user field overrides the corresponding package default. `models` replaces the entire default list, rather than appending; `[]` clears it. Omitted fields inherit defaults. A missing user file is allowed. Invalid JSON, invalid known field types, or unreadable files fail extension loading with the file path instead of silently ignoring your rules. Unknown fields are ignored. There is no project-level Codex Edit configuration.
|
|
80
|
+
|
|
81
|
+
The package default model-ID allowlist is `"gpt-5.6-*"`. Provider does not affect routing. Each entry is a `*` glob, so this matches every `gpt-5.6-` variant. The route additionally requires:
|
|
78
82
|
|
|
79
83
|
```text
|
|
80
84
|
model.api = openai-responses or openai-codex-responses
|
|
@@ -92,7 +96,7 @@ Patterns are case-sensitive, match the complete model ID, and support `*` as the
|
|
|
92
96
|
|
|
93
97
|
### Add model rules
|
|
94
98
|
|
|
95
|
-
|
|
99
|
+
Create `~/.pi/agent/codex-edit.json` and add validated model-ID patterns:
|
|
96
100
|
|
|
97
101
|
```json
|
|
98
102
|
{
|
|
@@ -117,7 +121,11 @@ Adding a pattern only changes routing; it does not prove that a model handles th
|
|
|
117
121
|
|
|
118
122
|
Grammar support is not part of the route. When a provider does not emit Lark grammar tools, Pi falls back to a normal function tool, so `apply_patch` still runs there — only the grammar-enforced output shape is lost.
|
|
119
123
|
|
|
120
|
-
|
|
124
|
+
Use a boolean for `enabled` and an array of non-empty strings for `models`. Set `"enabled": false` in the user file to disable all `apply_patch` routing. Do not edit the installed package's `config.json` for personal rules; move any existing personal rules into the user file.
|
|
125
|
+
|
|
126
|
+
Configuration is read when the extension loads. After changing it, use `/reload` or restart Pi. Already running subagents retain their loaded configuration; start a new child to read changes. Parent sessions and subagents that load Codex Edit use the same user file when they share the same agent directory, regardless of working directory or toolkit/standalone distribution. The implementation keeps both tools registered for session replay and changes only the active tool set on `session_start` and `model_select`.
|
|
127
|
+
|
|
128
|
+
Herdr Subagents does not automatically inherit the parent's extensions. To enable Codex Edit for a writing Persona, include the installed Codex Edit extension file in that Persona's `extensions` array in `~/.pi/agent/herdr-subagents.json`. You may instead use top-level `defaultExtensions` when the Persona has no explicit extension list; Persona-specific lists replace defaults, not merge with them. Preserve any authentication-provider extensions already configured. Read-only Personas should not gain editing tools.
|
|
121
129
|
|
|
122
130
|
## Documentation
|
|
123
131
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## 流程
|
|
4
4
|
|
|
5
|
-
1. `npm --prefix packages/codex-edit test
|
|
5
|
+
1. `npm --prefix packages/codex-edit test`:运行用户配置、parser、matcher、路由、工具契约、包结构、下面两组强制对比、入口加载、配置集成和 tarball 检查;随后生成 `docs/test-report.md` 并从该 Markdown 转换为自包含 `docs/test-report.html`。这是秒级反馈环,修改 parser 前必须先让对应回归用例变红。
|
|
6
6
|
2. `pi -ne -e ./packages/codex-edit/extensions/codex-edit.ts`:加载权威入口;独立子包与根包 manifest 都指向该实现。
|
|
7
7
|
3. `npm pack ./packages/codex-edit --dry-run`:检查独立 tarball。
|
|
8
8
|
4. 在根目录运行 `npm test`、`npm run load-test` 和 `npm pack --dry-run`,确认主包内嵌的同一份实现没有退化。
|
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
|
|
11
11
|
`docs/test-report.md` 是报告内容的权威中间产物,HTML 是每次测试生成的交付视图。提交或发布 Codex Edit 改动时必须包含两者,且 HTML 顶部 Overall 必须为 PASS。
|
|
12
12
|
|
|
13
|
+
## 用户配置验证
|
|
14
|
+
|
|
15
|
+
- `node --experimental-strip-types --test packages/codex-edit/tests/config.test.mjs`:隔离临时 agent 目录,覆盖缺少用户文件、按字段覆盖、模型列表替换、显式 false/空列表、非法 JSON/字段类型、读取失败、重新读取和不修改配置文件。包内默认模型规则保持不变。
|
|
16
|
+
- `npm --prefix packages/codex-edit run load-test`:加载权威入口,再用 Pi 加载 `tests/config-integration.ts`。配置集成使用真实扩展 factory 和隔离的 `PI_CODING_AGENT_DIR`,通过模拟的事件/工具选择接口验证不同 cwd 的父子会话共享规则、模型/API 切换、只读工具列表、重载后的禁用和非法配置报错,并执行真实 `apply_patch` 写入临时文件。不修改个人配置、不调用模型、不启动真实 Herdr pane。
|
|
17
|
+
- 用户文件固定为 agent 目录内的 `codex-edit.json`;不读取项目配置。修改后需要 `/reload`,已有子代理需要重新启动。此配置能力不等于验证新增模型的编辑质量;默认模型路由和历史 benchmark 不变,新增模型仍需独立验证。
|
|
18
|
+
|
|
13
19
|
## 两组强制对比
|
|
14
20
|
|
|
15
21
|
1. `npm --prefix packages/codex-edit run test:compare-native`:使用当前 Pi 公开导出的真实 `createEditToolDefinition` 和本地 extension 实际注册的 `apply_patch`,将两个真实工具跑在同一组临时 workspace 与期望文件快照上;失败 case 还要求 Codex Edit 不产生部分写入。它比较编辑协议能力和确定性结果,不替代真实模型质量 benchmark。
|
|
@@ -35,12 +41,14 @@
|
|
|
35
41
|
| 项目级多文件重构、重复 SKILL 分隔符、重复 tiny/release 文件块 | 解析为唯一文件操作并得到确定性结果 | `parser.test.mjs` |
|
|
36
42
|
| workspace escape | 拒绝 | `parser.test.mjs` |
|
|
37
43
|
| `gpt-5.6-*`、Responses API、disabled、自定义 glob | 仅允许规则内模型使用 `apply_patch`,其余回退 `edit` | `package.test.mjs` |
|
|
44
|
+
| 用户配置缺失、覆盖、空列表、错误输入、重新读取 | 用户字段覆盖默认值,失败带配置路径,不重写文件 | `config.test.mjs` |
|
|
45
|
+
| 父子会话、API 切换、只读工具、重载 | 共享 agent 目录配置,保留编辑权限与 API 限制 | `config-integration.ts` |
|
|
38
46
|
|
|
39
47
|
空参数是模型/提供方生成的无效工具调用,Pi 会在扩展 `execute` 之前拦截;parser 无法也不应为缺失 patch 猜内容。`Failed to find expected lines` 表示 patch 基于旧文件内容,安全行为是失败后重新读取并生成新 patch,而不是放宽到可能改错位置。
|
|
40
48
|
|
|
41
49
|
## 最近验证结果
|
|
42
50
|
|
|
43
|
-
当前基线为
|
|
51
|
+
当前基线为 29 个 Node 确定性测试及 12 个共享对比 case 全部通过。原生 edit 为 5 pass / 2 fail / 5 unsupported,本地 Codex Edit 为 7 pass / 5 正确安全拒绝;发布版 v0.1.7 为 6 pass / 6 fail,其中 5 个是正确安全拒绝,另 1 个是本地版已修复的同路径顺序 update。另有 5 个生产事故条目冻结真实问题来源,其中 4 个可进入 Agent Benchmark,1 个仅验证指定协议形态。真实触发过的 runner 类型重命名 ambiguous、重复同路径、空 chunk、stale context、解析路径别名冲突、工作区外绝对路径和项目级多文件形态均已进入回归集。发布前必须验证子包 tarball 和根包 tarball 都包含并成功加载该入口。
|
|
44
52
|
|
|
45
53
|
正式 Agent Benchmark 的预算门禁使用仓库内 `benchmark/run-with-budget.mjs` 包装上游 runner。不要修改 `/tmp` 中的 benchmark clone,也不要允许 `apply_patch` 写出当前工作区;工作区外路径必须作为 Safety Regression 正确拒绝。包装器在 `--stop-cost` 停止调度,并以 `--max-cost` 检查最终硬上限。
|
|
46
54
|
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<p>被测包:<code>@maxiaochao/pi-codex-edit</code>(当前工作区)</p>
|
|
19
19
|
<p>本报告严格区分真实模型基准、确定性协议回归和安全回归,三类成功率不会混算。</p>
|
|
20
20
|
<h2 id="summary">执行摘要</h2>
|
|
21
|
-
<ul><li>Agent Benchmark:<strong>通过(有共同例外)</strong> — 已完成 300/300 条 chain;本地版 First Exact 92/100、Final Exact 92/100,全部正式门槛通过。</li><li>协议/包回归:<strong>通过</strong> —
|
|
21
|
+
<ul><li>Agent Benchmark:<strong>通过(有共同例外)</strong> — 已完成 300/300 条 chain;本地版 First Exact 92/100、Final Exact 92/100,全部正式门槛通过。</li><li>协议/包回归:<strong>通过</strong> — 5/5 项检查通过。</li><li>安全回归:<strong>5/5 正确拒绝且零写入</strong>,包括工作区外路径。</li><li>下文提供 Agent、协议、安全、效率、版本、integrity 和任务来源的完整证据。</li></ul>
|
|
22
22
|
<h2 id="benchmark">Agent Benchmark:真实模型基准</h2>
|
|
23
23
|
<p><strong>状态:通过(有共同例外)</strong></p>
|
|
24
24
|
<p>三个测试臂均完成全部 100 个配对任务(共 300 条 chain),实际成本为 $12.388。本地版满足全部正式验收门槛;8 个最终失败均为三臂共同失败,不是本地版独有回归。</p>
|
|
@@ -88,13 +88,14 @@
|
|
|
88
88
|
<ul><li>数据源:<a href="https://github.com/alexshpunt/explicit-edit-benchmark">https://github.com/alexshpunt/explicit-edit-benchmark</a>,commit <code>5827e3fb65845f4b76adb06e5919d94ec4ffd5cf</code>。</li><li>冻结任务:80 Neutral + 20 Challenge;seed 为 <code>pi-toolkit-codex-edit-100-v1</code>。</li><li>模型:<code>openai-codex/gpt-5.6-sol</code>;reasoning:<code>low</code>;Pi:<code>0.85.1</code>;最多 5 次 Oracle recovery。</li><li>发布版:<code>@maxiaochao/pi-codex-edit@0.1.7 (sha512-hfNfx20h51FLCueXaMqBUAVYnxoCakuI306rzuFPI/lS0HT1jE/wQ8xkKl9PwEXboVVD6ZzS/YB0VVrd67V7cw==)</code>。</li><li>本地版:<code>@maxiaochao/pi-codex-edit@0.1.7+local (sha512-Mf21ZfSwOOgaH2lSiF/DpoA8Jk5jH84MaZUX1abkMop3HST3xt2YtCw2NKwrRJpvmJB02bl9wwYyFlAVI68Qwg==)</code>。</li><li>Run ID:<code>explicit-edit-100-sol-low-v3-complete</code>;运行完整性:300/300。</li><li>Identity:task manifest <code>cab0278f530271c7bb3de3e4dba6ab252fa2b748d00164e749ecdbd8f9f7f431</code>;config <code>739bb323275fdcead7709f19a894b0dee57062f40064c04d182d96474535328c</code>;verifier <code>8bd4be15c886bba84e8a6fa46576c43f2ca0f02d2536d98403f97361914a166d</code>。</li><li>Provider 失败:0;失败工具调用:0。</li></ul>
|
|
89
89
|
<h2 id="protocol">协议与包验证摘要</h2>
|
|
90
90
|
<div class="table-wrap"><table><thead><tr><th>检查项</th><th>结果</th><th>命令</th></tr></thead><tbody>
|
|
91
|
-
<tr><td>Node 回归测试</td><td>通过</td><td><code>node --experimental-strip-types --test tests/package.test.mjs tests/parser.test.mjs tests/released-vs-local.test.mjs tests/benchmark.test.mjs</code></td></tr>
|
|
91
|
+
<tr><td>Node 回归测试</td><td>通过</td><td><code>node --experimental-strip-types --test tests/package.test.mjs tests/config.test.mjs tests/parser.test.mjs tests/released-vs-local.test.mjs tests/benchmark.test.mjs</code></td></tr>
|
|
92
92
|
<tr><td>原生 edit 与本地 Codex Edit 对比</td><td>通过</td><td><code>pi -ne -e ./tests/native-vs-codex.ts</code></td></tr>
|
|
93
93
|
<tr><td>扩展加载</td><td>通过</td><td><code>pi -ne -e ./extensions/codex-edit.ts</code></td></tr>
|
|
94
|
+
<tr><td>用户配置与父子会话编辑器集成</td><td>通过</td><td><code>pi -ne -e ./tests/config-integration.ts</code></td></tr>
|
|
94
95
|
<tr><td>独立包 tarball</td><td>通过</td><td><code>npm pack --dry-run --json</code></td></tr>
|
|
95
96
|
</tbody></table></div>
|
|
96
97
|
<h2 id="section-4">确定性回归基线</h2>
|
|
97
|
-
<ul><li>Node 测试:预期
|
|
98
|
+
<ul><li>Node 测试:预期 29 个,覆盖用户配置覆盖与校验、parser、matcher、路由、包契约、resolved-path 防护、发布版对比、分层调度和生产事故语料。</li><li>共享对比 corpus:12 个 case。</li><li>原生 edit:5 通过 / 2 失败或正确拒绝 / 5 不适用。</li><li>Codex Edit 发布版 v0.1.7:6 通过 / 6 失败或正确拒绝。</li><li>Codex Edit 本地版:7 通过 / 5 正确安全拒绝。</li></ul>
|
|
98
99
|
<p>“正确拒绝”表示无效或陈旧操作被拒绝,且工作区没有变化。“不适用”表示 Pi 原生 <code>edit</code> 无法用一次编辑协议调用表达该操作,不计为工具缺陷。</p>
|
|
99
100
|
<h2 id="safety">安全回归</h2>
|
|
100
101
|
<p>本地版 5/5 个安全 case 均正确拒绝,且工作区零写入。特别是 <code>outside-workspace-absolute-path</code> 的结果为 <strong>工作区外路径 — 正确拒绝</strong>;放行该操作会允许任意写入 benchmark sandbox 之外。安全拒绝不计入编辑失败率。</p>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
## 执行摘要
|
|
10
10
|
|
|
11
11
|
- Agent Benchmark:**通过(有共同例外)** — 已完成 300/300 条 chain;本地版 First Exact 92/100、Final Exact 92/100,全部正式门槛通过。
|
|
12
|
-
- 协议/包回归:**通过** —
|
|
12
|
+
- 协议/包回归:**通过** — 5/5 项检查通过。
|
|
13
13
|
- 安全回归:**5/5 正确拒绝且零写入**,包括工作区外路径。
|
|
14
14
|
- 下文提供 Agent、协议、安全、效率、版本、integrity 和任务来源的完整证据。
|
|
15
15
|
|
|
@@ -114,14 +114,15 @@ Score v2 = `覆盖率 ×(0.75 × 首次精确率 + 0.25 × 最终精确率)`
|
|
|
114
114
|
|
|
115
115
|
| 检查项 | 结果 | 命令 |
|
|
116
116
|
|---|---|---|
|
|
117
|
-
| Node 回归测试 | 通过 | `node --experimental-strip-types --test tests/package.test.mjs tests/parser.test.mjs tests/released-vs-local.test.mjs tests/benchmark.test.mjs` |
|
|
117
|
+
| Node 回归测试 | 通过 | `node --experimental-strip-types --test tests/package.test.mjs tests/config.test.mjs tests/parser.test.mjs tests/released-vs-local.test.mjs tests/benchmark.test.mjs` |
|
|
118
118
|
| 原生 edit 与本地 Codex Edit 对比 | 通过 | `pi -ne -e ./tests/native-vs-codex.ts` |
|
|
119
119
|
| 扩展加载 | 通过 | `pi -ne -e ./extensions/codex-edit.ts` |
|
|
120
|
+
| 用户配置与父子会话编辑器集成 | 通过 | `pi -ne -e ./tests/config-integration.ts` |
|
|
120
121
|
| 独立包 tarball | 通过 | `npm pack --dry-run --json` |
|
|
121
122
|
|
|
122
123
|
## 确定性回归基线
|
|
123
124
|
|
|
124
|
-
- Node 测试:预期
|
|
125
|
+
- Node 测试:预期 29 个,覆盖用户配置覆盖与校验、parser、matcher、路由、包契约、resolved-path 防护、发布版对比、分层调度和生产事故语料。
|
|
125
126
|
- 共享对比 corpus:12 个 case。
|
|
126
127
|
- 原生 edit:5 通过 / 2 失败或正确拒绝 / 5 不适用。
|
|
127
128
|
- Codex Edit 发布版 v0.1.7:6 通过 / 6 失败或正确拒绝。
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Codex Edit 测试摘要
|
|
2
2
|
|
|
3
3
|
- Agent Benchmark:**通过(有共同例外)** — 完成 300/300 条 chain;全部正式验收门槛通过。
|
|
4
|
-
- 协议/包回归:**通过** —
|
|
4
|
+
- 协议/包回归:**通过** — 5/5 项检查通过。
|
|
5
5
|
- 安全回归:**5/5 正确拒绝**,覆盖陈旧上下文、空 chunk、目标冲突、resolved alias 和工作区外路径。
|
|
6
6
|
- First Exact:原生 edit 91/100,发布版 91/100,本地版 92/100;Final Exact:三臂均为 92/100。
|
|
7
7
|
- 总成本:$12.388;Provider 失败:0。
|
|
@@ -5,6 +5,7 @@ import { Text } from "@earendil-works/pi-tui";
|
|
|
5
5
|
import {
|
|
6
6
|
generateDiffString,
|
|
7
7
|
generateUnifiedPatch,
|
|
8
|
+
getAgentDir,
|
|
8
9
|
withFileMutationQueue,
|
|
9
10
|
} from "@earendil-works/pi-coding-agent";
|
|
10
11
|
import { Type } from "typebox";
|
|
@@ -15,17 +16,9 @@ import {
|
|
|
15
16
|
resolveWorkspacePath,
|
|
16
17
|
} from "../src/parser.ts";
|
|
17
18
|
import { modelIsAllowed } from "../src/model-routing.ts";
|
|
19
|
+
import { loadSettings } from "../src/config.ts";
|
|
18
20
|
|
|
19
21
|
const editorToolNames = new Set(["edit", "apply_patch"]);
|
|
20
|
-
const settingsUrl = new URL("../config.json", import.meta.url);
|
|
21
|
-
|
|
22
|
-
async function loadSettings() {
|
|
23
|
-
try {
|
|
24
|
-
return JSON.parse(await readFile(settingsUrl, "utf8"));
|
|
25
|
-
} catch {
|
|
26
|
-
return { enabled: true, models: [] };
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
22
|
|
|
30
23
|
function syncEditorTools(pi, ctx, model, settings) {
|
|
31
24
|
const active = pi.getActiveTools();
|
|
@@ -96,7 +89,7 @@ function buildFileDetail(path, action, before, after, moveTo) {
|
|
|
96
89
|
}
|
|
97
90
|
|
|
98
91
|
export default async function (pi) {
|
|
99
|
-
const settings = await loadSettings();
|
|
92
|
+
const settings = await loadSettings(getAgentDir());
|
|
100
93
|
|
|
101
94
|
pi.registerTool({
|
|
102
95
|
name: "apply_patch",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maxiaochao/pi-codex-edit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Pi extension that exposes Codex-style apply_patch for GPT/Codex models with model-aware edit fallback.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -42,11 +42,11 @@
|
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"test": "node tests/generate-test-report.mjs",
|
|
45
|
-
"test:regression": "node --experimental-strip-types --test tests/package.test.mjs tests/parser.test.mjs tests/released-vs-local.test.mjs tests/benchmark.test.mjs",
|
|
45
|
+
"test:regression": "node --experimental-strip-types --test tests/package.test.mjs tests/config.test.mjs tests/parser.test.mjs tests/released-vs-local.test.mjs tests/benchmark.test.mjs",
|
|
46
46
|
"test:compare-native": "pi -ne -e ./tests/native-vs-codex.ts",
|
|
47
47
|
"test:compare-released": "node --experimental-strip-types --test tests/released-vs-local.test.mjs",
|
|
48
48
|
"test:report": "node tests/generate-test-report.mjs",
|
|
49
|
-
"load-test": "pi -ne -e ./extensions/codex-edit.ts"
|
|
49
|
+
"load-test": "pi -ne -e ./extensions/codex-edit.ts && pi -ne -e ./tests/config-integration.ts"
|
|
50
50
|
},
|
|
51
51
|
"publishConfig": {
|
|
52
52
|
"access": "public"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
const defaultsPath = fileURLToPath(new URL("../config.json", import.meta.url));
|
|
6
|
+
|
|
7
|
+
async function readSettings(path, required = false) {
|
|
8
|
+
let text;
|
|
9
|
+
try {
|
|
10
|
+
text = await readFile(path, "utf8");
|
|
11
|
+
} catch (error) {
|
|
12
|
+
if (!required && error.code === "ENOENT") return {};
|
|
13
|
+
throw new Error(`Codex Edit config ${path}: ${error.message}`, { cause: error });
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const value = JSON.parse(text);
|
|
17
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
18
|
+
throw new Error("expected a JSON object");
|
|
19
|
+
}
|
|
20
|
+
if ((required || "enabled" in value) && typeof value.enabled !== "boolean") {
|
|
21
|
+
throw new Error("enabled must be a boolean");
|
|
22
|
+
}
|
|
23
|
+
if ((required || "models" in value) && (!Array.isArray(value.models)
|
|
24
|
+
|| !value.models.every((pattern) => typeof pattern === "string" && pattern.trim().length > 0))) {
|
|
25
|
+
throw new Error("models must be an array of non-empty strings");
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
...("enabled" in value ? { enabled: value.enabled } : {}),
|
|
29
|
+
...("models" in value ? { models: value.models } : {}),
|
|
30
|
+
};
|
|
31
|
+
} catch (error) {
|
|
32
|
+
throw new Error(`Codex Edit config ${path}: ${error.message}`, { cause: error });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function loadSettings(agentDir) {
|
|
37
|
+
const defaults = await readSettings(defaultsPath, true);
|
|
38
|
+
const user = await readSettings(join(agentDir, "codex-edit.json"));
|
|
39
|
+
return { ...defaults, ...user };
|
|
40
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import registerCodexEdit from "../extensions/codex-edit.ts";
|
|
6
|
+
|
|
7
|
+
async function editor(tools = ["read", "bash", "edit", "write"]) {
|
|
8
|
+
let active = [...tools];
|
|
9
|
+
let tool;
|
|
10
|
+
let status;
|
|
11
|
+
const handlers = new Map();
|
|
12
|
+
await registerCodexEdit({
|
|
13
|
+
registerTool(definition) { tool = definition; },
|
|
14
|
+
on(event, handler) { handlers.set(event, handler); },
|
|
15
|
+
getActiveTools() { return active; },
|
|
16
|
+
setActiveTools(next) { active = next; },
|
|
17
|
+
});
|
|
18
|
+
return {
|
|
19
|
+
tool,
|
|
20
|
+
active: () => active,
|
|
21
|
+
status: () => status,
|
|
22
|
+
async start(model, cwd) {
|
|
23
|
+
await handlers.get("session_start")({}, {
|
|
24
|
+
model, cwd, hasUI: true,
|
|
25
|
+
ui: { setStatus(key, value) { assert.equal(key, "codex-edit"); status = value; } },
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
async select(model) {
|
|
29
|
+
await handlers.get("model_select")({ model }, { hasUI: false });
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default async function () {
|
|
35
|
+
const agentDir = await mkdtemp(join(tmpdir(), "codex-edit-integration-"));
|
|
36
|
+
const previous = process.env.PI_CODING_AGENT_DIR;
|
|
37
|
+
process.env.PI_CODING_AGENT_DIR = agentDir;
|
|
38
|
+
const configPath = join(agentDir, "codex-edit.json");
|
|
39
|
+
const model = { id: "gpt-6.1-sol", api: "openai-codex-responses" };
|
|
40
|
+
try {
|
|
41
|
+
await writeFile(configPath, JSON.stringify({ models: [model.id] }));
|
|
42
|
+
const parent = await editor();
|
|
43
|
+
const child = await editor();
|
|
44
|
+
for (const [session, cwd] of [[parent, "/parent-project"], [child, "/child-worktree"]]) {
|
|
45
|
+
await session.start(model, cwd);
|
|
46
|
+
assert.equal(session.status(), "editor: apply_patch");
|
|
47
|
+
assert.deepEqual(session.active(), ["read", "bash", "write", "apply_patch"]);
|
|
48
|
+
await session.select({ ...model, id: "gpt-5.6-sol" });
|
|
49
|
+
assert.ok(session.active().includes("edit"), "user list must replace defaults");
|
|
50
|
+
await session.select({ ...model, api: "openai-completions" });
|
|
51
|
+
assert.ok(session.active().includes("edit"), "unsupported API must retain edit");
|
|
52
|
+
await session.select(model);
|
|
53
|
+
assert.ok(!session.active().includes("edit"));
|
|
54
|
+
}
|
|
55
|
+
await child.tool.execute("config-patch", {
|
|
56
|
+
patch: "*** Begin Patch\n*** Add File: proof.txt\n+shared user config\n*** End Patch",
|
|
57
|
+
}, undefined, undefined, { cwd: agentDir });
|
|
58
|
+
assert.equal(await readFile(join(agentDir, "proof.txt"), "utf8"), "shared user config\n");
|
|
59
|
+
|
|
60
|
+
const readonly = await editor(["read", "bash"]);
|
|
61
|
+
await readonly.start(model, agentDir);
|
|
62
|
+
assert.deepEqual(readonly.active(), ["read", "bash"]);
|
|
63
|
+
|
|
64
|
+
await writeFile(configPath, JSON.stringify({ enabled: false }));
|
|
65
|
+
const reloaded = await editor();
|
|
66
|
+
await reloaded.start(model, agentDir);
|
|
67
|
+
assert.equal(reloaded.status(), "editor: edit");
|
|
68
|
+
assert.ok(!reloaded.active().includes("apply_patch"));
|
|
69
|
+
|
|
70
|
+
await writeFile(configPath, "{");
|
|
71
|
+
await assert.rejects(editor(), (error) => error.message.includes(configPath));
|
|
72
|
+
console.log("Codex Edit user config: shared parent/child routing, patch execution, read-only tools, reload and invalid-config checks passed");
|
|
73
|
+
} finally {
|
|
74
|
+
if (previous === undefined) delete process.env.PI_CODING_AGENT_DIR;
|
|
75
|
+
else process.env.PI_CODING_AGENT_DIR = previous;
|
|
76
|
+
await rm(agentDir, { recursive: true, force: true });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdtemp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
import { loadSettings } from "../src/config.ts";
|
|
7
|
+
import { modelIsAllowed } from "../src/model-routing.ts";
|
|
8
|
+
|
|
9
|
+
async function fixture(t) {
|
|
10
|
+
const agentDir = await mkdtemp(join(tmpdir(), "codex-edit-config-"));
|
|
11
|
+
t.after(() => rm(agentDir, { recursive: true, force: true }));
|
|
12
|
+
return { agentDir, path: join(agentDir, "codex-edit.json") };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
test("missing user config preserves package defaults without creating a file", async (t) => {
|
|
16
|
+
const { agentDir, path } = await fixture(t);
|
|
17
|
+
assert.deepEqual(await loadSettings(agentDir), { enabled: true, models: ["gpt-5.6-*"] });
|
|
18
|
+
await assert.rejects(readFile(path), { code: "ENOENT" });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("partial user config overrides enabled while inheriting package models", async (t) => {
|
|
22
|
+
const { agentDir, path } = await fixture(t);
|
|
23
|
+
await writeFile(path, JSON.stringify({ enabled: false }));
|
|
24
|
+
assert.deepEqual(await loadSettings(agentDir), { enabled: false, models: ["gpt-5.6-*"] });
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("user model list replaces defaults and keeps API routing restrictions", async (t) => {
|
|
28
|
+
const { agentDir, path } = await fixture(t);
|
|
29
|
+
await writeFile(path, JSON.stringify({ models: ["gpt-6.1-sol"] }));
|
|
30
|
+
const settings = await loadSettings(agentDir);
|
|
31
|
+
assert.deepEqual(settings, { enabled: true, models: ["gpt-6.1-sol"] });
|
|
32
|
+
const model = { id: "gpt-6.1-sol", api: "openai-codex-responses" };
|
|
33
|
+
assert.equal(modelIsAllowed(model, settings), true);
|
|
34
|
+
assert.equal(modelIsAllowed({ ...model, api: "openai-responses" }, settings), true);
|
|
35
|
+
assert.equal(modelIsAllowed({ ...model, api: "anthropic-messages" }, settings), false);
|
|
36
|
+
assert.equal(modelIsAllowed({ ...model, id: "gpt-5.6-sol" }, settings), false);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("empty models and explicit false are not replaced by defaults", async (t) => {
|
|
40
|
+
const { agentDir, path } = await fixture(t);
|
|
41
|
+
await writeFile(path, JSON.stringify({ enabled: false, models: [] }));
|
|
42
|
+
assert.deepEqual(await loadSettings(agentDir), { enabled: false, models: [] });
|
|
43
|
+
await writeFile(path, JSON.stringify({ models: [] }));
|
|
44
|
+
assert.deepEqual(await loadSettings(agentDir), { enabled: true, models: [] });
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("malformed JSON and invalid known fields fail visibly with the config path", async (t) => {
|
|
48
|
+
const { agentDir, path } = await fixture(t);
|
|
49
|
+
for (const input of ["{", "null", "[]", "true", '"text"', '{"enabled":"false"}',
|
|
50
|
+
'{"enabled":null}', '{"models":"gpt-*"}', '{"models":null}', '{"models":[1]}',
|
|
51
|
+
'{"models":[""]}', '{"models":[" "]}']) {
|
|
52
|
+
await writeFile(path, input);
|
|
53
|
+
await assert.rejects(loadSettings(agentDir), (error) => {
|
|
54
|
+
assert.ok(error.message.includes(path), `${input}: missing config path`);
|
|
55
|
+
return true;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("config read errors other than missing files are not ignored", async (t) => {
|
|
61
|
+
const { agentDir, path } = await fixture(t);
|
|
62
|
+
await mkdir(path);
|
|
63
|
+
await assert.rejects(loadSettings(agentDir), (error) => {
|
|
64
|
+
assert.ok(error.message.includes(path));
|
|
65
|
+
return true;
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("reload reads updated user rules without rewriting either config", async (t) => {
|
|
70
|
+
const { agentDir, path } = await fixture(t);
|
|
71
|
+
const defaultsUrl = new URL("../config.json", import.meta.url);
|
|
72
|
+
const defaultsBefore = await readFile(defaultsUrl, "utf8");
|
|
73
|
+
await writeFile(path, JSON.stringify({ models: ["gpt-6.1-sol"], note: "preserve unknown fields" }));
|
|
74
|
+
assert.deepEqual((await loadSettings(agentDir)).models, ["gpt-6.1-sol"]);
|
|
75
|
+
const next = JSON.stringify({ models: ["custom-*"], note: "preserve unknown fields" });
|
|
76
|
+
await writeFile(path, next);
|
|
77
|
+
assert.deepEqual((await loadSettings(agentDir)).models, ["custom-*"]);
|
|
78
|
+
assert.equal(await readFile(path, "utf8"), next);
|
|
79
|
+
assert.equal(await readFile(defaultsUrl, "utf8"), defaultsBefore);
|
|
80
|
+
});
|
|
@@ -13,7 +13,7 @@ const defaultEvidencePath = join(packageDir, "benchmark/results/explicit-edit-10
|
|
|
13
13
|
const checks = [
|
|
14
14
|
{
|
|
15
15
|
name: "Node 回归测试",
|
|
16
|
-
command: ["node", "--experimental-strip-types", "--test", "tests/package.test.mjs", "tests/parser.test.mjs", "tests/released-vs-local.test.mjs", "tests/benchmark.test.mjs"],
|
|
16
|
+
command: ["node", "--experimental-strip-types", "--test", "tests/package.test.mjs", "tests/config.test.mjs", "tests/parser.test.mjs", "tests/released-vs-local.test.mjs", "tests/benchmark.test.mjs"],
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
name: "原生 edit 与本地 Codex Edit 对比",
|
|
@@ -23,6 +23,10 @@ const checks = [
|
|
|
23
23
|
name: "扩展加载",
|
|
24
24
|
command: ["pi", "-ne", "-e", "./extensions/codex-edit.ts"],
|
|
25
25
|
},
|
|
26
|
+
{
|
|
27
|
+
name: "用户配置与父子会话编辑器集成",
|
|
28
|
+
command: ["pi", "-ne", "-e", "./tests/config-integration.ts"],
|
|
29
|
+
},
|
|
26
30
|
{
|
|
27
31
|
name: "独立包 tarball",
|
|
28
32
|
command: ["npm", "pack", "--dry-run", "--json"],
|
|
@@ -345,7 +349,7 @@ function buildMarkdown(results, benchmark) {
|
|
|
345
349
|
"",
|
|
346
350
|
"## 确定性回归基线",
|
|
347
351
|
"",
|
|
348
|
-
`- Node 测试:预期
|
|
352
|
+
`- Node 测试:预期 29 个,覆盖用户配置覆盖与校验、parser、matcher、路由、包契约、resolved-path 防护、发布版对比、分层调度和生产事故语料。`,
|
|
349
353
|
`- 共享对比 corpus:${comparisonCases.length} 个 case。`,
|
|
350
354
|
`- 原生 edit:${count("pass", "native")} 通过 / ${count("fail", "native")} 失败或正确拒绝 / ${count("unsupported", "native")} 不适用。`,
|
|
351
355
|
`- Codex Edit 发布版 v0.1.7:${count("pass", "released")} 通过 / ${count("fail", "released")} 失败或正确拒绝。`,
|
|
@@ -10,7 +10,10 @@ test("package points Pi at the extension and config is reachable from it", async
|
|
|
10
10
|
const manifest = JSON.parse(await readFile(join(packageDir, "package.json"), "utf8"));
|
|
11
11
|
assert.deepEqual(manifest.pi.extensions, ["./extensions/codex-edit.ts"]);
|
|
12
12
|
const source = await readFile(join(packageDir, "extensions/codex-edit.ts"), "utf8");
|
|
13
|
-
assert.match(source, /
|
|
13
|
+
assert.match(source, /loadSettings\(getAgentDir\(\)\)/);
|
|
14
|
+
const settingsSource = await readFile(join(packageDir, "src/config.ts"), "utf8");
|
|
15
|
+
assert.match(settingsSource, /new URL\("\.\.\/config\.json", import\.meta\.url\)/);
|
|
16
|
+
assert.match(settingsSource, /join\(agentDir, "codex-edit\.json"\)/);
|
|
14
17
|
assert.match(source, /model-routing\.ts/);
|
|
15
18
|
assert.match(source, /parameters: Type\.Object\(\{\s*patch: Type\.String/);
|
|
16
19
|
assert.match(source, /applyUpdateGroups\(before, operation\.chunkGroups, operation\.path\)/);
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agent-team
|
|
3
|
-
description:
|
|
3
|
+
description: 多模型协作分析:按配置的模型和角色调度独立子代理,汇总结果并维护调查档案。
|
|
4
|
+
disable-model-invocation: true
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
当前会话是**主 Agent**,负责核心调度:按配置中的模型和角色启动独立子代理,分派用户问题,收集结果并维护调查档案。主 Agent 根据结果决定直接回答、补充核验或继续下一轮。子代理不需要常驻;跨轮连续性来自持久调查档案和逻辑成员身份,而不是聊天记忆。
|
|
7
8
|
|
|
8
|
-
##
|
|
9
|
+
## 调用方式
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
用户通过 `/skill:agent-team` 显式加载后开启。此 skill 不参与模型自动选择;高代价决策也不构成自动加载或启动的授权。
|
|
11
12
|
|
|
12
13
|
## 1. 建立调查档案
|
|
13
14
|
|