@fitlab-ai/agent-infra 0.9.9 → 0.9.11
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 +13 -3
- package/README.zh-CN.md +13 -3
- package/bin/cli.ts +17 -4
- package/dist/bin/cli.js +19 -4
- package/dist/bin/internal-cli.js +55 -4
- package/dist/lib/agent-client.js +0 -1
- package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +17 -10
- package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-context.js +11 -31
- package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +15 -33
- package/dist/lib/agent-clients/adapters/codex-sandbox.js +72 -11
- package/dist/lib/agent-clients/adapters/index.js +3 -1
- package/dist/lib/agent-clients/adapters/opencode-sandbox.js +0 -4
- package/dist/lib/agent-clients/adapters/traecli.js +65 -0
- package/dist/lib/agent-clients/config.js +14 -99
- package/dist/lib/agent-clients/reconcile.js +1 -11
- package/dist/lib/agent-clients/schema.js +5 -4
- package/dist/lib/agent-clients/tokens.js +7 -17
- package/dist/lib/agent-clients/types.js +2 -1
- package/dist/lib/decide.js +14 -30
- package/dist/lib/defaults.json +9 -0
- package/dist/lib/init.js +2 -2
- package/dist/lib/internal/codex-lifecycle.js +2 -2
- package/dist/lib/internal/codex-sandbox-controller.js +4 -3
- package/dist/lib/internal/release-workflow.js +0 -1
- package/dist/lib/internal/sandbox-control.js +2 -2
- package/dist/lib/internal/task-finalization.js +19 -9
- package/dist/lib/internal/task-ledger.js +8 -2
- package/dist/lib/internal/task-lifecycle.js +17 -93
- package/dist/lib/internal/task-orchestration.js +30 -216
- package/dist/lib/{task/commands/validate.js → internal/task-validate.js} +77 -43
- package/dist/lib/merge.js +205 -103
- package/dist/lib/process-data/normalize.js +2 -9
- package/dist/lib/run/host.js +46 -16
- package/dist/lib/run/tui.js +5 -2
- package/dist/lib/sandbox/agent-client-reconciler.js +4 -12
- package/dist/lib/sandbox/commands/create.js +3 -3
- package/dist/lib/sandbox/commands/enter.js +18 -4
- package/dist/lib/sandbox/config.js +3 -12
- package/dist/lib/sandbox/control/controller-registration.js +4 -2
- package/dist/lib/sandbox/control/executor.js +135 -40
- package/dist/lib/sandbox/control/lifecycle.js +29 -20
- package/dist/lib/sandbox/control/server.js +18 -16
- package/dist/lib/sandbox/mounts.js +3 -2
- package/dist/lib/sandbox/recovery.js +123 -22
- package/dist/lib/sandbox/workspace-identity.js +14 -0
- package/dist/lib/sandbox/workspace-view.js +8 -9
- package/dist/lib/self-update.js +278 -0
- package/dist/lib/server/protocol.js +5 -5
- package/dist/lib/task/activity-log.js +4 -1
- package/dist/lib/task/artifact-lifecycle.js +4 -2
- package/dist/lib/task/codex-orchestration.js +32 -35
- package/dist/lib/task/command-options.js +1 -3
- package/dist/lib/task/commands/cat.js +0 -5
- package/dist/lib/task/commands/decisions.js +76 -92
- package/dist/lib/task/commands/files.js +6 -6
- package/dist/lib/task/commands/grep.js +25 -61
- package/dist/lib/task/commands/issue-body.js +6 -6
- package/dist/lib/task/commands/log.js +25 -10
- package/dist/lib/task/commands/show.js +5 -6
- package/dist/lib/task/commands/status.js +8 -8
- package/dist/lib/task/commit-operation.js +21 -25
- package/dist/lib/task/commit-policy.js +1 -1
- package/dist/lib/task/control-authority.js +431 -0
- package/dist/lib/task/create.js +6 -1
- package/dist/lib/task/current-contract.js +35 -0
- package/dist/lib/task/decision-details.js +263 -0
- package/dist/lib/task/decision-intents.js +5 -2
- package/dist/lib/task/delegation-receipts.js +8 -7
- package/dist/lib/task/events.js +11 -5
- package/dist/lib/task/finalization.js +72 -46
- package/dist/lib/task/index.js +19 -29
- package/dist/lib/task/ledger-intents.js +8 -9
- package/dist/lib/task/ledger.js +13 -6
- package/dist/lib/task/lifecycle.js +16 -0
- package/dist/lib/task/orchestration.js +51 -14
- package/dist/lib/task/review-artifacts.js +31 -12
- package/dist/lib/task/review-finalization.js +19 -6
- package/dist/lib/task/verification-engine.js +38 -18
- package/dist/lib/task/verification-review.js +1 -1
- package/dist/lib/task/workspace-snapshot.js +5 -11
- package/dist/lib/task/write.js +11 -1
- package/dist/lib/update.js +6 -37
- package/dist/lib/version.js +5 -1
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-client.ts +0 -1
- package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +25 -10
- package/lib/agent-clients/adapters/codex-lifecycle/controller-context.ts +16 -33
- package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +16 -35
- package/lib/agent-clients/adapters/codex-sandbox.ts +89 -14
- package/lib/agent-clients/adapters/index.ts +3 -1
- package/lib/agent-clients/adapters/opencode-sandbox.ts +0 -5
- package/lib/agent-clients/adapters/traecli.ts +66 -0
- package/lib/agent-clients/config.ts +14 -144
- package/lib/agent-clients/reconcile.ts +1 -12
- package/lib/agent-clients/schema.ts +5 -4
- package/lib/agent-clients/tokens.ts +7 -20
- package/lib/agent-clients/types.ts +2 -1
- package/lib/decide.ts +12 -22
- package/lib/defaults.json +9 -0
- package/lib/init.ts +2 -2
- package/lib/internal/codex-lifecycle.ts +2 -2
- package/lib/internal/codex-sandbox-controller.ts +4 -3
- package/lib/internal/release-workflow.ts +0 -1
- package/lib/internal/sandbox-control.ts +2 -2
- package/lib/internal/task-finalization.ts +27 -13
- package/lib/internal/task-ledger.ts +8 -2
- package/lib/internal/task-lifecycle.ts +33 -76
- package/lib/internal/task-orchestration.ts +33 -190
- package/lib/{task/commands/validate.ts → internal/task-validate.ts} +77 -41
- package/lib/merge.ts +236 -120
- package/lib/process-data/normalize.ts +2 -8
- package/lib/run/host.ts +63 -14
- package/lib/run/tui.ts +5 -3
- package/lib/sandbox/agent-client-reconciler.ts +5 -15
- package/lib/sandbox/commands/create.ts +4 -4
- package/lib/sandbox/commands/enter.ts +24 -4
- package/lib/sandbox/config.ts +2 -14
- package/lib/sandbox/control/container-identity.ts +2 -2
- package/lib/sandbox/control/controller-registration.ts +8 -3
- package/lib/sandbox/control/executor.ts +156 -53
- package/lib/sandbox/control/lifecycle.ts +34 -28
- package/lib/sandbox/control/protocol.ts +1 -3
- package/lib/sandbox/control/server.ts +15 -12
- package/lib/sandbox/control/state.ts +7 -7
- package/lib/sandbox/mounts.ts +4 -3
- package/lib/sandbox/recovery.ts +162 -34
- package/lib/sandbox/tools.ts +1 -1
- package/lib/sandbox/workspace-identity.ts +28 -0
- package/lib/sandbox/workspace-view.ts +14 -10
- package/lib/self-update.ts +341 -0
- package/lib/server/protocol.ts +5 -5
- package/lib/task/activity-log.ts +6 -1
- package/lib/task/artifact-lifecycle.ts +5 -3
- package/lib/task/codex-orchestration.ts +40 -45
- package/lib/task/command-options.ts +1 -2
- package/lib/task/commands/cat.ts +0 -4
- package/lib/task/commands/decisions.ts +80 -75
- package/lib/task/commands/files.ts +6 -6
- package/lib/task/commands/grep.ts +23 -51
- package/lib/task/commands/issue-body.ts +6 -6
- package/lib/task/commands/log.ts +22 -10
- package/lib/task/commands/show.ts +5 -6
- package/lib/task/commands/status.ts +8 -8
- package/lib/task/commit-operation.ts +25 -30
- package/lib/task/commit-policy.ts +1 -2
- package/lib/task/control-authority.ts +563 -0
- package/lib/task/create.ts +6 -1
- package/lib/task/current-contract.ts +49 -0
- package/lib/task/decision-details.ts +340 -0
- package/lib/task/decision-intents.ts +7 -2
- package/lib/task/delegation-receipts.ts +8 -6
- package/lib/task/events.ts +10 -5
- package/lib/task/finalization.ts +84 -42
- package/lib/task/index.ts +19 -28
- package/lib/task/ledger-intents.ts +6 -8
- package/lib/task/ledger.ts +17 -7
- package/lib/task/lifecycle.ts +20 -0
- package/lib/task/orchestration.ts +42 -16
- package/lib/task/review-artifacts.ts +53 -15
- package/lib/task/review-finalization.ts +33 -7
- package/lib/task/verification-engine.ts +33 -21
- package/lib/task/verification-review.ts +1 -1
- package/lib/task/workspace-snapshot.ts +4 -13
- package/lib/task/write.ts +20 -1
- package/lib/update.ts +6 -40
- package/lib/version.ts +6 -1
- package/package.json +1 -1
- package/templates/.agents/QUICKSTART.en.md +2 -3
- package/templates/.agents/QUICKSTART.zh-CN.md +2 -3
- package/templates/.agents/README.en.md +5 -3
- package/templates/.agents/README.zh-CN.md +5 -3
- package/templates/.agents/rules/README.en.md +1 -0
- package/templates/.agents/rules/README.zh-CN.md +1 -0
- package/templates/.agents/rules/compatibility-policy.en.md +40 -0
- package/templates/.agents/rules/compatibility-policy.zh-CN.md +40 -0
- package/templates/.agents/rules/create-issue.github.en.md +1 -1
- package/templates/.agents/rules/create-issue.github.zh-CN.md +1 -1
- package/templates/.agents/rules/human-decision-context.en.md +9 -7
- package/templates/.agents/rules/human-decision-context.zh-CN.md +9 -7
- package/templates/.agents/rules/issue-fields.github.en.md +1 -1
- package/templates/.agents/rules/issue-fields.github.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.en.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.github.en.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-sync.github.en.md +1 -1
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +2 -2
- package/templates/.agents/rules/lifecycle-orchestration.en.md +4 -4
- package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +4 -4
- package/templates/.agents/rules/milestone-inference.github.en.md +1 -1
- package/templates/.agents/rules/milestone-inference.github.zh-CN.md +1 -1
- package/templates/.agents/rules/next-step-output.en.md +3 -3
- package/templates/.agents/rules/next-step-output.zh-CN.md +3 -3
- package/templates/.agents/rules/no-mid-flow-questions.en.md +1 -1
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +1 -1
- package/templates/.agents/rules/pr-sync.en.md +2 -2
- package/templates/.agents/rules/pr-sync.github.en.md +3 -2
- package/templates/.agents/rules/pr-sync.github.zh-CN.md +3 -1
- package/templates/.agents/rules/pr-sync.zh-CN.md +2 -1
- package/templates/.agents/rules/release-commands.github.en.md +6 -0
- package/templates/.agents/rules/release-commands.github.zh-CN.md +6 -0
- package/templates/.agents/rules/review-handshake.en.md +1 -1
- package/templates/.agents/rules/review-handshake.zh-CN.md +1 -1
- package/templates/.agents/rules/review-method.en.md +1 -0
- package/templates/.agents/rules/review-method.zh-CN.md +1 -0
- package/templates/.agents/rules/task-management.en.md +1 -2
- package/templates/.agents/rules/task-management.zh-CN.md +1 -2
- package/templates/.agents/skills/analyze-task/SKILL.en.md +4 -3
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +4 -3
- package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/check-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/close-codescan/SKILL.en.md +1 -1
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +1 -1
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/code-task/SKILL.en.md +4 -3
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +5 -3
- package/templates/.agents/skills/commit/SKILL.en.md +27 -7
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -4
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +5 -5
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/complete-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/create-pr/SKILL.en.md +15 -11
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +15 -11
- package/templates/.agents/skills/create-pr/reference/change-report.en.md +46 -0
- package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +46 -0
- package/templates/.agents/skills/create-pr/scripts/change-report.mjs +203 -0
- package/templates/.agents/skills/create-release-note/SKILL.en.md +5 -6
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +5 -6
- package/templates/.agents/skills/create-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/import-issue/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/plan-task/SKILL.en.md +5 -4
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +5 -4
- package/templates/.agents/skills/restore-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/review-analysis/SKILL.en.md +5 -3
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +5 -3
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/review-code/SKILL.en.md +5 -3
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -3
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/review-code/reference/migration-risks.en.md +9 -6
- package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +9 -6
- package/templates/.agents/skills/review-plan/SKILL.en.md +5 -3
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +5 -3
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +7 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +7 -3
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +1 -1
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +1 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -2
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -2
- package/templates/.agents/skills/run-task/SKILL.en.md +6 -2
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +6 -2
- package/templates/.agents/skills/run-task/reference/host-validation.en.md +2 -2
- package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +2 -2
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +2 -2
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +159 -104
- package/templates/.agents/skills/watch-pr/SKILL.en.md +2 -2
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +2 -2
- package/templates/.agents/templates/task.en.md +1 -1
- package/templates/.agents/templates/task.zh-CN.md +1 -1
- package/templates/.claude/commands/analyze-task.en.md +1 -1
- package/templates/.claude/commands/analyze-task.zh-CN.md +1 -1
- package/templates/.claude/commands/block-task.en.md +1 -1
- package/templates/.claude/commands/block-task.zh-CN.md +1 -1
- package/templates/.claude/commands/cancel-task.en.md +1 -1
- package/templates/.claude/commands/cancel-task.zh-CN.md +1 -1
- package/templates/.claude/commands/check-task.en.md +1 -1
- package/templates/.claude/commands/check-task.zh-CN.md +1 -1
- package/templates/.claude/commands/code-task.en.md +1 -1
- package/templates/.claude/commands/code-task.zh-CN.md +1 -1
- package/templates/.claude/commands/commit.en.md +1 -1
- package/templates/.claude/commands/commit.zh-CN.md +1 -1
- package/templates/.claude/commands/complete-manual-validation.en.md +1 -1
- package/templates/.claude/commands/complete-manual-validation.zh-CN.md +1 -1
- package/templates/.claude/commands/complete-task.en.md +1 -1
- package/templates/.claude/commands/complete-task.zh-CN.md +1 -1
- package/templates/.claude/commands/create-pr.en.md +1 -1
- package/templates/.claude/commands/create-pr.zh-CN.md +1 -1
- package/templates/.claude/commands/plan-task.en.md +1 -1
- package/templates/.claude/commands/plan-task.zh-CN.md +1 -1
- package/templates/.claude/commands/review-analysis.en.md +1 -1
- package/templates/.claude/commands/review-analysis.zh-CN.md +1 -1
- package/templates/.claude/commands/review-code.en.md +1 -1
- package/templates/.claude/commands/review-code.zh-CN.md +1 -1
- package/templates/.claude/commands/review-plan.en.md +1 -1
- package/templates/.claude/commands/review-plan.zh-CN.md +1 -1
- package/templates/.claude/commands/run-manual-validation.en.md +1 -1
- package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
- package/templates/.claude/commands/run-task.en.md +1 -1
- package/templates/.claude/commands/run-task.zh-CN.md +1 -1
- package/templates/.claude/commands/watch-pr.en.md +1 -1
- package/templates/.claude/commands/watch-pr.zh-CN.md +1 -1
- package/templates/.traecli/commands/update-agent-infra.en.md +7 -0
- package/templates/.traecli/commands/update-agent-infra.zh-CN.md +7 -0
- package/dist/lib/builtin-tuis.js +0 -40
- package/lib/builtin-tuis.ts +0 -56
package/README.md
CHANGED
|
@@ -121,6 +121,15 @@ brew install fitlab-ai/tap/agent-infra
|
|
|
121
121
|
|
|
122
122
|
### Updating agent-infra
|
|
123
123
|
|
|
124
|
+
```bash
|
|
125
|
+
ai update
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`ai update` updates the installed agent-infra CLI. In an initialized project,
|
|
129
|
+
use `ai sync` to refresh project seed files and the file registry.
|
|
130
|
+
|
|
131
|
+
The equivalent package-manager commands remain:
|
|
132
|
+
|
|
124
133
|
```bash
|
|
125
134
|
npm update -g @fitlab-ai/agent-infra
|
|
126
135
|
# or, if installed via Homebrew:
|
|
@@ -142,7 +151,7 @@ ai init
|
|
|
142
151
|
# or: agent-infra init
|
|
143
152
|
```
|
|
144
153
|
|
|
145
|
-
The CLI collects project metadata, lets you select the enabled Agent Clients, installs
|
|
154
|
+
The CLI collects project metadata, lets you select the enabled Agent Clients, installs any client-specific `update-agent-infra` seed commands, and generates `.agents/.airc.json`.
|
|
146
155
|
|
|
147
156
|
> `ai` is a shorthand for `agent-infra`. Both commands are equivalent.
|
|
148
157
|
|
|
@@ -156,12 +165,13 @@ Open the project in any AI TUI and run `update-agent-infra`:
|
|
|
156
165
|
| Codex | `$update-agent-infra` |
|
|
157
166
|
| Antigravity CLI | `/update-agent-infra` |
|
|
158
167
|
| OpenCode | `/update-agent-infra` |
|
|
168
|
+
| TraeCode CLI | `/update-agent-infra` |
|
|
159
169
|
|
|
160
170
|
This detects the packaged template version and renders all managed files. The same command is used both for first-time setup and for future template upgrades.
|
|
161
171
|
|
|
162
172
|
## Core Commands
|
|
163
173
|
|
|
164
|
-
Manage the
|
|
174
|
+
Manage the five built-in Agent Clients independently from the project lifecycle:
|
|
165
175
|
|
|
166
176
|
```bash
|
|
167
177
|
ai agent-client list
|
|
@@ -171,7 +181,7 @@ ai agent-client disable antigravity-cli
|
|
|
171
181
|
ai agent-client configure
|
|
172
182
|
```
|
|
173
183
|
|
|
174
|
-
The most-used lifecycle commands, in delivery order. The command prefix varies by TUI (`/skill` in Claude Code/Antigravity/OpenCode and `$skill` in Codex); the workflow semantics stay the same.
|
|
184
|
+
The most-used lifecycle commands, in delivery order. The command prefix varies by TUI (`/skill` in Claude Code/Antigravity/OpenCode/TraeCode and `$skill` in Codex); the workflow semantics stay the same.
|
|
175
185
|
|
|
176
186
|
| Command | Purpose |
|
|
177
187
|
|---------|---------|
|
package/README.zh-CN.md
CHANGED
|
@@ -120,6 +120,15 @@ brew install fitlab-ai/tap/agent-infra
|
|
|
120
120
|
|
|
121
121
|
### 更新 agent-infra
|
|
122
122
|
|
|
123
|
+
```bash
|
|
124
|
+
ai update
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`ai update` 用于更新已安装的 agent-infra CLI。在已初始化项目中,使用
|
|
128
|
+
`ai sync` 刷新项目 seed files 和文件注册表。
|
|
129
|
+
|
|
130
|
+
对应的包管理器命令仍然是:
|
|
131
|
+
|
|
123
132
|
```bash
|
|
124
133
|
npm update -g @fitlab-ai/agent-infra
|
|
125
134
|
# 或者通过 Homebrew 安装时:
|
|
@@ -141,7 +150,7 @@ ai init
|
|
|
141
150
|
# 或:agent-infra init
|
|
142
151
|
```
|
|
143
152
|
|
|
144
|
-
CLI 会收集项目元数据,让你选择启用的 Agent Client
|
|
153
|
+
CLI 会收集项目元数据,让你选择启用的 Agent Client,安装该客户端需要的 `update-agent-infra` 种子命令,并生成 `.agents/.airc.json`。
|
|
145
154
|
|
|
146
155
|
> `ai` 是 `agent-infra` 的简写命令,两者等价。
|
|
147
156
|
|
|
@@ -155,12 +164,13 @@ CLI 会收集项目元数据,让你选择启用的 Agent Client,为其安装
|
|
|
155
164
|
| Codex | `$update-agent-infra` |
|
|
156
165
|
| Antigravity CLI | `/update-agent-infra` |
|
|
157
166
|
| OpenCode | `/update-agent-infra` |
|
|
167
|
+
| TraeCode CLI | `/update-agent-infra` |
|
|
158
168
|
|
|
159
169
|
该命令会检测当前打包模板版本并渲染所有受管理文件。首次安装和后续升级都使用同一条命令。
|
|
160
170
|
|
|
161
171
|
## 核心命令
|
|
162
172
|
|
|
163
|
-
|
|
173
|
+
以下命令用于独立管理五个内建 Agent Client:
|
|
164
174
|
|
|
165
175
|
```bash
|
|
166
176
|
ai agent-client list
|
|
@@ -170,7 +180,7 @@ ai agent-client disable antigravity-cli
|
|
|
170
180
|
ai agent-client configure
|
|
171
181
|
```
|
|
172
182
|
|
|
173
|
-
最常用的生命周期命令,按交付顺序排列。命令前缀因 TUI 而异(Claude Code/Antigravity/OpenCode 用 `/skill`,Codex 用 `$skill`),工作流语义保持一致。
|
|
183
|
+
最常用的生命周期命令,按交付顺序排列。命令前缀因 TUI 而异(Claude Code/Antigravity/OpenCode/TraeCode 用 `/skill`,Codex 用 `$skill`),工作流语义保持一致。
|
|
174
184
|
|
|
175
185
|
| 命令 | 用途 |
|
|
176
186
|
|------|------|
|
package/bin/cli.ts
CHANGED
|
@@ -21,12 +21,13 @@ Commands:
|
|
|
21
21
|
decide Record a ruling; code-stage decisions require explicit implementation intent
|
|
22
22
|
help Show this help message
|
|
23
23
|
init Initialize a new project with update-agent-infra seed command
|
|
24
|
-
merge Merge tasks from another workspace directory (active/blocked/completed/archive)
|
|
24
|
+
merge Merge tasks from another current workspace directory (active/blocked/completed/archive)
|
|
25
25
|
run Schedule a lifecycle skill in the task sandbox tmux session
|
|
26
26
|
sandbox, s Manage Docker-based AI sandboxes
|
|
27
27
|
server Run the local AI collaboration daemon (start/stop/status/logs)
|
|
28
28
|
task, t Read-only views of .agents/workspace tasks
|
|
29
|
-
|
|
29
|
+
sync Update seed files and sync file registry for an existing project
|
|
30
|
+
update Update the agent-infra CLI itself
|
|
30
31
|
version Show version
|
|
31
32
|
|
|
32
33
|
'ai' and 'agent-infra' are interchangeable; 'ai' is the shorter form.
|
|
@@ -171,10 +172,22 @@ switch (command) {
|
|
|
171
172
|
break;
|
|
172
173
|
}
|
|
173
174
|
case 'update': {
|
|
174
|
-
const imported = await importCommand('../lib/update.ts');
|
|
175
|
+
const imported = await importCommand('../lib/self-update.ts');
|
|
175
176
|
if (!imported) break;
|
|
176
177
|
const { cmdUpdate } = imported;
|
|
177
|
-
await cmdUpdate().catch((e: unknown) => {
|
|
178
|
+
const code = await cmdUpdate().catch((e: unknown) => {
|
|
179
|
+
process.stderr.write(`Error: ${errorMessage(e)}\n`);
|
|
180
|
+
process.exitCode = 1;
|
|
181
|
+
return 1;
|
|
182
|
+
});
|
|
183
|
+
if (code !== 0) process.exitCode = code;
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
case 'sync': {
|
|
187
|
+
const imported = await importCommand('../lib/update.ts');
|
|
188
|
+
if (!imported) break;
|
|
189
|
+
const { cmdSync } = imported;
|
|
190
|
+
await cmdSync().catch((e: unknown) => {
|
|
178
191
|
process.stderr.write(`Error: ${errorMessage(e)}\n`);
|
|
179
192
|
process.exitCode = 1;
|
|
180
193
|
});
|
package/dist/bin/cli.js
CHANGED
|
@@ -25,12 +25,13 @@ Commands:
|
|
|
25
25
|
decide Record a ruling; code-stage decisions require explicit implementation intent
|
|
26
26
|
help Show this help message
|
|
27
27
|
init Initialize a new project with update-agent-infra seed command
|
|
28
|
-
merge Merge tasks from another workspace directory (active/blocked/completed/archive)
|
|
28
|
+
merge Merge tasks from another current workspace directory (active/blocked/completed/archive)
|
|
29
29
|
run Schedule a lifecycle skill in the task sandbox tmux session
|
|
30
30
|
sandbox, s Manage Docker-based AI sandboxes
|
|
31
31
|
server Run the local AI collaboration daemon (start/stop/status/logs)
|
|
32
32
|
task, t Read-only views of .agents/workspace tasks
|
|
33
|
-
|
|
33
|
+
sync Update seed files and sync file registry for an existing project
|
|
34
|
+
update Update the agent-infra CLI itself
|
|
34
35
|
version Show version
|
|
35
36
|
|
|
36
37
|
'ai' and 'agent-infra' are interchangeable; 'ai' is the shorter form.
|
|
@@ -182,11 +183,25 @@ switch (command) {
|
|
|
182
183
|
break;
|
|
183
184
|
}
|
|
184
185
|
case 'update': {
|
|
185
|
-
const imported = await importCommand('../lib/update.ts');
|
|
186
|
+
const imported = await importCommand('../lib/self-update.ts');
|
|
186
187
|
if (!imported)
|
|
187
188
|
break;
|
|
188
189
|
const { cmdUpdate } = imported;
|
|
189
|
-
await cmdUpdate().catch((e) => {
|
|
190
|
+
const code = await cmdUpdate().catch((e) => {
|
|
191
|
+
process.stderr.write(`Error: ${errorMessage(e)}\n`);
|
|
192
|
+
process.exitCode = 1;
|
|
193
|
+
return 1;
|
|
194
|
+
});
|
|
195
|
+
if (code !== 0)
|
|
196
|
+
process.exitCode = code;
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
case 'sync': {
|
|
200
|
+
const imported = await importCommand('../lib/update.ts');
|
|
201
|
+
if (!imported)
|
|
202
|
+
break;
|
|
203
|
+
const { cmdSync } = imported;
|
|
204
|
+
await cmdSync().catch((e) => {
|
|
190
205
|
process.stderr.write(`Error: ${errorMessage(e)}\n`);
|
|
191
206
|
process.exitCode = 1;
|
|
192
207
|
});
|
package/dist/bin/internal-cli.js
CHANGED
|
@@ -5,10 +5,56 @@ if (major < 22 || (major === 22 && minor < 9)) {
|
|
|
5
5
|
process.exit(1);
|
|
6
6
|
}
|
|
7
7
|
const command = process.argv[2] || '';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
const taskControlCommand = command === 'task-lifecycle' || command === 'task-orchestration' || command === 'task-finalization';
|
|
9
|
+
function taskControlTransportFailure(message) {
|
|
10
|
+
process.stdout.write(`${JSON.stringify({
|
|
11
|
+
status: 'failed', changed: false,
|
|
12
|
+
error: { code: 'TASK_CONTROL_TRANSPORT_INVALID', message }
|
|
13
|
+
})}\n`);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
if (taskControlCommand) {
|
|
17
|
+
const env = process.env;
|
|
18
|
+
const executorMarked = Boolean(env.AGENT_INFRA_EXECUTOR_MANIFEST);
|
|
19
|
+
const controlKeys = [
|
|
20
|
+
'AGENT_INFRA_CONTROL_TOKEN', 'AGENT_INFRA_CONTROL_GENERATION',
|
|
21
|
+
'AGENT_INFRA_CONTROL_DIR', 'AGENT_INFRA_CONTROL_STATUS_DIR'
|
|
22
|
+
];
|
|
23
|
+
const hasControlMarker = controlKeys.some((key) => Boolean(env[key]))
|
|
24
|
+
|| Boolean(env.AGENT_INFRA_CONTROL_CONTROLLER_BINDING);
|
|
25
|
+
const taskBindingMarker = hasControlMarker && Boolean(env.AGENT_INFRA_TASK_ID);
|
|
26
|
+
const hasCompleteClientConfig = controlKeys.every((key) => Boolean(env[key]))
|
|
27
|
+
&& !env.AGENT_INFRA_CONTROL_CONTROLLER_BINDING
|
|
28
|
+
&& (!taskBindingMarker || Boolean(env.AGENT_INFRA_RUNTIME_DIR));
|
|
29
|
+
if (executorMarked) {
|
|
30
|
+
taskControlTransportFailure('executor context is only valid for sandbox-control execute');
|
|
31
|
+
}
|
|
32
|
+
if ((hasControlMarker || taskBindingMarker) && !hasCompleteClientConfig) {
|
|
33
|
+
taskControlTransportFailure('sandbox client control configuration is incomplete or conflicting');
|
|
34
|
+
}
|
|
35
|
+
if (hasCompleteClientConfig) {
|
|
36
|
+
const { sandboxControl } = await import('../lib/internal/sandbox-control.js');
|
|
37
|
+
await sandboxControl(['client', command, ...process.argv.slice(3)]);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
switch (command) {
|
|
41
|
+
case 'task-orchestration': {
|
|
42
|
+
const { taskOrchestration } = await import('../lib/internal/task-orchestration.js');
|
|
43
|
+
await taskOrchestration(process.argv.slice(3));
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
case 'task-lifecycle': {
|
|
47
|
+
const { taskLifecycle } = await import('../lib/internal/task-lifecycle.js');
|
|
48
|
+
taskLifecycle(process.argv.slice(3));
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
case 'task-finalization': {
|
|
52
|
+
const { taskFinalization } = await import('../lib/internal/task-finalization.js');
|
|
53
|
+
taskFinalization(process.argv.slice(3));
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
12
58
|
}
|
|
13
59
|
else
|
|
14
60
|
switch (command) {
|
|
@@ -157,6 +203,11 @@ else
|
|
|
157
203
|
taskVerify(process.argv.slice(3));
|
|
158
204
|
break;
|
|
159
205
|
}
|
|
206
|
+
case 'task-validate': {
|
|
207
|
+
const { taskValidate } = await import('../lib/internal/task-validate.js');
|
|
208
|
+
taskValidate(process.argv.slice(3));
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
160
211
|
default:
|
|
161
212
|
process.stdout.write(`${JSON.stringify({
|
|
162
213
|
status: 'failed',
|
package/dist/lib/agent-client.js
CHANGED
|
@@ -96,7 +96,6 @@ async function cmdAgentClient(args) {
|
|
|
96
96
|
throw new AgentClientCommandError('AGENT_CLIENT_ARGUMENT_INVALID', 'status accepts no arguments');
|
|
97
97
|
}
|
|
98
98
|
const plan = workflowPlan(projectRoot, config, { type: 'none' });
|
|
99
|
-
process.stdout.write(`source: ${plan.source}\n`);
|
|
100
99
|
printState(plan.desired);
|
|
101
100
|
for (const seed of plan.seedOperations) {
|
|
102
101
|
process.stdout.write(` seed ${seed.target}: ${seed.kind}\n`);
|
|
@@ -145,25 +145,32 @@ function verifyLifecycleBuildIdentity(expected, actual) {
|
|
|
145
145
|
return {
|
|
146
146
|
ok: false,
|
|
147
147
|
code: 'CODEX_LIFECYCLE_PROTOCOL_MISMATCH',
|
|
148
|
-
message: 'Codex lifecycle protocol version does not match'
|
|
148
|
+
message: 'Codex lifecycle protocol version does not match',
|
|
149
|
+
warnings: []
|
|
149
150
|
};
|
|
150
151
|
}
|
|
152
|
+
const warnings = [];
|
|
151
153
|
if (actual.packageVersion !== expected.packageVersion
|
|
152
154
|
|| actual.internalExecutableBuildHash !== expected.internalExecutableBuildHash) {
|
|
153
|
-
|
|
154
|
-
ok: false,
|
|
155
|
+
warnings.push({
|
|
155
156
|
code: 'CODEX_LIFECYCLE_BUILD_MISMATCH',
|
|
156
|
-
message: 'Codex lifecycle executable build identity
|
|
157
|
-
|
|
157
|
+
message: 'Codex lifecycle executable build identity differs; rebuild the sandbox if the runtime is stale',
|
|
158
|
+
action: 'rebuild-sandbox'
|
|
159
|
+
});
|
|
158
160
|
}
|
|
159
161
|
if (actual.lifecycleContractHash !== expected.lifecycleContractHash) {
|
|
160
|
-
|
|
161
|
-
ok: false,
|
|
162
|
+
warnings.push({
|
|
162
163
|
code: 'CODEX_LIFECYCLE_CONTRACT_MISMATCH',
|
|
163
|
-
message: 'Codex lifecycle contract identity
|
|
164
|
-
|
|
164
|
+
message: 'Codex lifecycle contract identity differs; rebuild the sandbox if the runtime is stale',
|
|
165
|
+
action: 'rebuild-sandbox'
|
|
166
|
+
});
|
|
165
167
|
}
|
|
166
|
-
return {
|
|
168
|
+
return {
|
|
169
|
+
ok: true,
|
|
170
|
+
code: null,
|
|
171
|
+
message: null,
|
|
172
|
+
warnings: Object.freeze(warnings)
|
|
173
|
+
};
|
|
167
174
|
}
|
|
168
175
|
export { LIFECYCLE_PROTOCOL_VERSION, computeLifecycleBuildIdentity, isCanonicalLifecyclePackageVersion, isLifecycleProtocolVersion, readLifecycleManifestFiles, resolveLifecycleExecutableFiles, verifyLifecycleBuildIdentity };
|
|
169
176
|
//# sourceMappingURL=build-identity.js.map
|
|
@@ -2,28 +2,11 @@ import crypto from 'node:crypto';
|
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { getProcessIdentityState } from '../../../server/process-state.js';
|
|
5
|
-
import { computeLifecycleBuildIdentity } from './build-identity.js';
|
|
5
|
+
import { computeLifecycleBuildIdentity, verifyLifecycleBuildIdentity } from './build-identity.js';
|
|
6
6
|
const HEX_256 = /^[a-f0-9]{64}$/u;
|
|
7
7
|
function exactKeys(value, keys) {
|
|
8
8
|
return Object.keys(value).sort().join(',') === [...keys].sort().join(',');
|
|
9
9
|
}
|
|
10
|
-
function digestProfiles(repoRoot) {
|
|
11
|
-
const files = [
|
|
12
|
-
path.join(repoRoot, '.codex', 'agents', 'agent-infra-lifecycle-executor.toml'),
|
|
13
|
-
path.join(repoRoot, '.codex', 'agents', 'agent-infra-lifecycle-reviewer.toml')
|
|
14
|
-
];
|
|
15
|
-
const hash = crypto.createHash('sha256');
|
|
16
|
-
for (const file of files.sort()) {
|
|
17
|
-
const stat = fs.lstatSync(file);
|
|
18
|
-
if (!stat.isFile() || stat.isSymbolicLink())
|
|
19
|
-
throw new Error('CODEX_SANDBOX_CONTROLLER_BUNDLE_MISMATCH');
|
|
20
|
-
hash.update(path.basename(file));
|
|
21
|
-
hash.update('\0');
|
|
22
|
-
hash.update(fs.readFileSync(file));
|
|
23
|
-
hash.update('\0');
|
|
24
|
-
}
|
|
25
|
-
return hash.digest('hex');
|
|
26
|
-
}
|
|
27
10
|
function validProcess(value) {
|
|
28
11
|
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
29
12
|
return false;
|
|
@@ -53,7 +36,7 @@ function validateContext(value) {
|
|
|
53
36
|
if (!exactKeys(context, [
|
|
54
37
|
'buildIdentity', 'controlGeneration', 'controllerInstanceDigest', 'controllerLease',
|
|
55
38
|
'controllerProcess', 'expiresAt', 'hookDefinitionHash', 'issuedAt',
|
|
56
|
-
'
|
|
39
|
+
'taskId', 'version'
|
|
57
40
|
])
|
|
58
41
|
|| context.version !== 2
|
|
59
42
|
|| typeof context.taskId !== 'string' || context.taskId.length === 0
|
|
@@ -68,13 +51,12 @@ function validateContext(value) {
|
|
|
68
51
|
|| !Number.isSafeInteger(context.expiresAt)
|
|
69
52
|
|| context.expiresAt <= context.issuedAt
|
|
70
53
|
|| !validBuildIdentity(context.buildIdentity)
|
|
71
|
-
|| typeof context.hookDefinitionHash !== 'string' || !HEX_256.test(context.hookDefinitionHash)
|
|
72
|
-
|| typeof context.lifecycleProfilesHash !== 'string' || !HEX_256.test(context.lifecycleProfilesHash)) {
|
|
54
|
+
|| typeof context.hookDefinitionHash !== 'string' || !HEX_256.test(context.hookDefinitionHash)) {
|
|
73
55
|
throw new Error('CODEX_SANDBOX_CONTROLLER_CONTEXT_INVALID');
|
|
74
56
|
}
|
|
75
57
|
return context;
|
|
76
58
|
}
|
|
77
|
-
export function contextFromControllerLease(lease,
|
|
59
|
+
export function contextFromControllerLease(lease, input) {
|
|
78
60
|
return Object.freeze({
|
|
79
61
|
version: 2,
|
|
80
62
|
taskId: lease.taskId,
|
|
@@ -85,8 +67,7 @@ export function contextFromControllerLease(lease, hashes) {
|
|
|
85
67
|
issuedAt: lease.issuedAt,
|
|
86
68
|
expiresAt: lease.expiresAt,
|
|
87
69
|
buildIdentity: lease.buildIdentity,
|
|
88
|
-
hookDefinitionHash:
|
|
89
|
-
lifecycleProfilesHash: hashes.lifecycleProfilesHash
|
|
70
|
+
hookDefinitionHash: input.hookDefinitionHash
|
|
90
71
|
});
|
|
91
72
|
}
|
|
92
73
|
export function writeCodexSandboxControllerContext(contextPath, context) {
|
|
@@ -102,7 +83,7 @@ export function writeCodexSandboxControllerContext(contextPath, context) {
|
|
|
102
83
|
fs.rmSync(temporary, { force: true });
|
|
103
84
|
}
|
|
104
85
|
}
|
|
105
|
-
export function
|
|
86
|
+
export function verifyCodexSandboxControllerContextWithWarnings(contextPath, options = {}) {
|
|
106
87
|
let stat;
|
|
107
88
|
try {
|
|
108
89
|
stat = fs.lstatSync(contextPath);
|
|
@@ -129,12 +110,11 @@ export function verifyCodexSandboxControllerContext(contextPath, options = {}) {
|
|
|
129
110
|
|| state !== 'alive') {
|
|
130
111
|
throw new Error('CODEX_SANDBOX_CONTROLLER_CONTEXT_INVALID');
|
|
131
112
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
throw new Error(
|
|
136
|
-
}
|
|
137
|
-
return Object.freeze(context);
|
|
113
|
+
const currentBuildIdentity = computeLifecycleBuildIdentity(repoRoot);
|
|
114
|
+
const identity = verifyLifecycleBuildIdentity(context.buildIdentity, currentBuildIdentity);
|
|
115
|
+
if (!identity.ok)
|
|
116
|
+
throw new Error(`${identity.code}: ${identity.message}`);
|
|
117
|
+
return Object.freeze({ context: Object.freeze(context), warnings: identity.warnings });
|
|
138
118
|
}
|
|
139
119
|
export function controllerProofFromContext(context) {
|
|
140
120
|
return Object.freeze({
|
|
@@ -8,22 +8,8 @@ import * as toml from 'smol-toml';
|
|
|
8
8
|
import { requestCodexControllerClose, requestCodexControllerOpen, requestCodexControllerVerify, requestSandboxControl } from '../../../sandbox/control/client.js';
|
|
9
9
|
import { readSandboxControlStatus } from '../../../sandbox/control/state.js';
|
|
10
10
|
import { getProcessStartTime } from '../../../server/process-state.js';
|
|
11
|
-
import {
|
|
12
|
-
import { contextFromControllerLease, controllerProofFromContext,
|
|
13
|
-
function digestFiles(files) {
|
|
14
|
-
const hash = crypto.createHash('sha256');
|
|
15
|
-
for (const file of [...files].sort()) {
|
|
16
|
-
const stat = fs.lstatSync(file);
|
|
17
|
-
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
18
|
-
throw new Error('CODEX_SANDBOX_CONTROLLER_BUNDLE_MISMATCH');
|
|
19
|
-
}
|
|
20
|
-
hash.update(path.basename(file));
|
|
21
|
-
hash.update('\0');
|
|
22
|
-
hash.update(fs.readFileSync(file));
|
|
23
|
-
hash.update('\0');
|
|
24
|
-
}
|
|
25
|
-
return hash.digest('hex');
|
|
26
|
-
}
|
|
11
|
+
import { LIFECYCLE_PROTOCOL_VERSION } from './build-identity.js';
|
|
12
|
+
import { contextFromControllerLease, controllerProofFromContext, verifyCodexSandboxControllerContextWithWarnings as verifyContextFileWithWarnings, writeCodexSandboxControllerContext } from './controller-context.js';
|
|
27
13
|
function copyRegular(source, destination, mode) {
|
|
28
14
|
const stat = fs.lstatSync(source);
|
|
29
15
|
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
@@ -108,14 +94,15 @@ function verifyControl(taskId, control) {
|
|
|
108
94
|
if (payload.taskId !== taskId)
|
|
109
95
|
throw new Error('CODEX_SANDBOX_CONTROLLER_TASK_BINDING_INVALID');
|
|
110
96
|
}
|
|
111
|
-
function
|
|
97
|
+
function verifyCodexSandboxControllerContextWithWarnings(contextPath, options = {}) {
|
|
112
98
|
const control = options.control ?? controlFromEnvironment();
|
|
113
|
-
const
|
|
99
|
+
const fileVerification = verifyContextFileWithWarnings(contextPath, {
|
|
114
100
|
repoRoot: options.repoRoot,
|
|
115
101
|
now: options.now,
|
|
116
102
|
generation: control.generation,
|
|
117
103
|
probeProcess: options.probeProcess
|
|
118
104
|
});
|
|
105
|
+
const context = fileVerification.context;
|
|
119
106
|
const verified = (options.requestControllerVerify ?? requestCodexControllerVerify)({
|
|
120
107
|
controllerProof: controllerProofFromContext(context),
|
|
121
108
|
...control,
|
|
@@ -126,7 +113,10 @@ function verifyCodexSandboxControllerContext(contextPath, options = {}) {
|
|
|
126
113
|
|| verified.binding.controllerInstanceDigest !== context.controllerInstanceDigest) {
|
|
127
114
|
throw new Error('CODEX_SANDBOX_CONTROLLER_CONTEXT_INVALID');
|
|
128
115
|
}
|
|
129
|
-
return
|
|
116
|
+
return Object.freeze({
|
|
117
|
+
context,
|
|
118
|
+
warnings: fileVerification.warnings
|
|
119
|
+
});
|
|
130
120
|
}
|
|
131
121
|
function detectedCodexVersion() {
|
|
132
122
|
const result = spawnSync('codex', ['--version'], { encoding: 'utf8' });
|
|
@@ -261,29 +251,21 @@ function prepareCodexSandboxController(input, options = {}) {
|
|
|
261
251
|
copyRegular(hooks, path.join(home, 'hooks.json'), 0o600);
|
|
262
252
|
copyRegular(executor, path.join(home, 'agents', path.basename(executor)), 0o600);
|
|
263
253
|
copyRegular(reviewer, path.join(home, 'agents', path.basename(reviewer)), 0o600);
|
|
264
|
-
if (crypto.createHash('sha256').update(fs.readFileSync(path.join(home, 'hooks.json'))).digest('hex')
|
|
265
|
-
!== crypto.createHash('sha256').update(fs.readFileSync(hooks)).digest('hex')
|
|
266
|
-
|| digestFiles([
|
|
267
|
-
path.join(home, 'agents', path.basename(executor)),
|
|
268
|
-
path.join(home, 'agents', path.basename(reviewer))
|
|
269
|
-
]) !== digestFiles([executor, reviewer])) {
|
|
270
|
-
throw new Error('CODEX_SANDBOX_CONTROLLER_BUNDLE_MISMATCH');
|
|
271
|
-
}
|
|
272
|
-
const buildIdentity = computeLifecycleBuildIdentity(repoRoot);
|
|
273
254
|
const opened = (options.openController ?? requestCodexControllerOpen)({
|
|
274
255
|
controllerProcess: { pid: process.pid, startTime: parentStartTime },
|
|
275
256
|
...control,
|
|
276
257
|
timeoutMs: 30_000
|
|
277
258
|
});
|
|
278
259
|
const taskId = opened.lease.taskId;
|
|
260
|
+
if (opened.lease.buildIdentity.protocolVersion !== LIFECYCLE_PROTOCOL_VERSION) {
|
|
261
|
+
throw new Error('CODEX_LIFECYCLE_PROTOCOL_MISMATCH: Codex lifecycle protocol version does not match');
|
|
262
|
+
}
|
|
279
263
|
context = contextFromControllerLease(opened.lease, {
|
|
280
|
-
hookDefinitionHash: crypto.createHash('sha256').update(fs.readFileSync(hooks)).digest('hex')
|
|
281
|
-
lifecycleProfilesHash: digestFiles([executor, reviewer])
|
|
264
|
+
hookDefinitionHash: crypto.createHash('sha256').update(fs.readFileSync(hooks)).digest('hex')
|
|
282
265
|
});
|
|
283
266
|
if (opened.lease.controlGeneration !== control.generation
|
|
284
267
|
|| opened.lease.controllerProcess.pid !== process.pid
|
|
285
|
-
|| opened.lease.controllerProcess.startTime !== parentStartTime
|
|
286
|
-
|| JSON.stringify(opened.lease.buildIdentity) !== JSON.stringify(buildIdentity)) {
|
|
268
|
+
|| opened.lease.controllerProcess.startTime !== parentStartTime) {
|
|
287
269
|
throw new Error('SANDBOX_CONTROL_RESULT_INVALID');
|
|
288
270
|
}
|
|
289
271
|
(options.verifyTaskBinding ?? verifyControl)(taskId, control);
|
|
@@ -383,5 +365,5 @@ async function runCodexSandboxController(input, options = {}) {
|
|
|
383
365
|
prepared.cleanup();
|
|
384
366
|
}
|
|
385
367
|
}
|
|
386
|
-
export { prepareCodexSandboxController, runCodexSandboxController,
|
|
368
|
+
export { prepareCodexSandboxController, runCodexSandboxController, verifyCodexSandboxControllerContextWithWarnings, controllerProofFromContext };
|
|
387
369
|
//# sourceMappingURL=sandbox-controller.js.map
|
|
@@ -30,6 +30,8 @@ function resolveHostCatalogPath(value, hostHomeDir) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
const CODEX_DISABLED_FEATURE_FLAGS = ['apps', 'enable_mcp_apps'];
|
|
33
|
+
const SANDBOX_CODEX_HOOKS_PATH = '/workspace/.codex/hooks.json';
|
|
34
|
+
const CODEX_HOOK_TRUST_HASH = /^sha256:[a-f0-9]{64}$/;
|
|
33
35
|
function removeCodexMcpServers(sandboxParsed) {
|
|
34
36
|
if (!Object.hasOwn(sandboxParsed, 'mcp_servers')) {
|
|
35
37
|
return false;
|
|
@@ -61,19 +63,58 @@ function inheritDisabledCodexFeatureFlags(sandboxParsed, hostParsed) {
|
|
|
61
63
|
}
|
|
62
64
|
return changed;
|
|
63
65
|
}
|
|
64
|
-
function
|
|
65
|
-
if (!
|
|
66
|
-
return;
|
|
66
|
+
function inheritCodexHookTrustState(sandboxParsed, hostParsed, hostProjectDir) {
|
|
67
|
+
if (!hostProjectDir) {
|
|
68
|
+
return false;
|
|
67
69
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return;
|
|
70
|
+
if (Object.hasOwn(sandboxParsed, 'hooks') && !isJsonObjectRecord(sandboxParsed.hooks)) {
|
|
71
|
+
return false;
|
|
71
72
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
const sandboxHooks = sandboxParsed.hooks ?? {};
|
|
74
|
+
if (Object.hasOwn(sandboxHooks, 'state') && !isJsonObjectRecord(sandboxHooks.state)) {
|
|
75
|
+
return false;
|
|
75
76
|
}
|
|
76
|
-
|
|
77
|
+
const sandboxState = sandboxHooks.state ?? {};
|
|
78
|
+
const sandboxPrefix = `${SANDBOX_CODEX_HOOKS_PATH}:`;
|
|
79
|
+
const nextState = Object.fromEntries(Object.entries(sandboxState).filter(([key]) => !key.startsWith(sandboxPrefix)));
|
|
80
|
+
const hostState = isJsonObjectRecord(hostParsed.hooks)
|
|
81
|
+
&& isJsonObjectRecord(hostParsed.hooks.state)
|
|
82
|
+
? hostParsed.hooks.state
|
|
83
|
+
: {};
|
|
84
|
+
const hostPrefix = `${path.join(hostProjectDir, '.codex', 'hooks.json')}:`;
|
|
85
|
+
for (const [key, value] of Object.entries(hostState)) {
|
|
86
|
+
if (!key.startsWith(hostPrefix) || !isJsonObjectRecord(value)) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const trustedHash = value.trusted_hash;
|
|
90
|
+
if (typeof trustedHash !== 'string' || !CODEX_HOOK_TRUST_HASH.test(trustedHash)) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
nextState[`${sandboxPrefix}${key.slice(hostPrefix.length)}`] = {
|
|
94
|
+
trusted_hash: trustedHash,
|
|
95
|
+
...(typeof value.enabled === 'boolean' ? { enabled: value.enabled } : {})
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (JSON.stringify(sandboxState) === JSON.stringify(nextState)) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
if (Object.keys(nextState).length > 0) {
|
|
102
|
+
sandboxHooks.state = nextState;
|
|
103
|
+
sandboxParsed.hooks = sandboxHooks;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
delete sandboxHooks.state;
|
|
107
|
+
if (Object.keys(sandboxHooks).length > 0) {
|
|
108
|
+
sandboxParsed.hooks = sandboxHooks;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
delete sandboxParsed.hooks;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
function ensureCodexModelInheritance(toolDir, hostHomeDir, containerCodexDir = '/home/devuser/.codex', hostProjectDir) {
|
|
117
|
+
if (!hostHomeDir) {
|
|
77
118
|
return;
|
|
78
119
|
}
|
|
79
120
|
const sandboxConfigPath = path.join(toolDir, 'config.toml');
|
|
@@ -87,8 +128,25 @@ function ensureCodexModelInheritance(toolDir, hostHomeDir, containerCodexDir = '
|
|
|
87
128
|
return;
|
|
88
129
|
}
|
|
89
130
|
}
|
|
131
|
+
const hostConfigPath = path.join(hostHomeDir, '.codex', 'config.toml');
|
|
132
|
+
let hostParsed = null;
|
|
133
|
+
if (fs.existsSync(hostConfigPath)) {
|
|
134
|
+
try {
|
|
135
|
+
hostParsed = toml.parse(fs.readFileSync(hostConfigPath, 'utf8'));
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
// An unavailable host trust source must not leave previously projected trust active.
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (!hostParsed) {
|
|
142
|
+
if (inheritCodexHookTrustState(sandboxParsed, {}, hostProjectDir)) {
|
|
143
|
+
fs.writeFileSync(sandboxConfigPath, `${toml.stringify(sandboxParsed)}\n`, 'utf8');
|
|
144
|
+
}
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
90
147
|
let changed = removeCodexMcpServers(sandboxParsed);
|
|
91
148
|
changed = inheritDisabledCodexFeatureFlags(sandboxParsed, hostParsed) || changed;
|
|
149
|
+
changed = inheritCodexHookTrustState(sandboxParsed, hostParsed, hostProjectDir) || changed;
|
|
92
150
|
const inheritSpecs = [
|
|
93
151
|
['model', 'string'],
|
|
94
152
|
['model_reasoning_effort', 'string'],
|
|
@@ -151,7 +209,10 @@ const codexBeforeContainerCreateHook = {
|
|
|
151
209
|
message: 'Codex sandbox hook requires its resolved tool state.'
|
|
152
210
|
};
|
|
153
211
|
}
|
|
154
|
-
|
|
212
|
+
const hostProjectDir = typeof context.config?.repoRoot === 'string'
|
|
213
|
+
? context.config.repoRoot
|
|
214
|
+
: undefined;
|
|
215
|
+
ensureCodexModelInheritance(entry.dir, create.hostHome, entry.tool.containerMount, hostProjectDir);
|
|
155
216
|
ensureCodexWorkspaceTrust(entry.dir);
|
|
156
217
|
return { status: 'ready' };
|
|
157
218
|
}
|
|
@@ -3,11 +3,13 @@ import { claudeCodeAdapter } from './claude-code.js';
|
|
|
3
3
|
import { codexAdapter } from './codex.js';
|
|
4
4
|
import { antigravityCliAdapter } from './antigravity-cli.js';
|
|
5
5
|
import { opencodeAdapter } from './opencode.js';
|
|
6
|
+
import { traecliAdapter } from './traecli.js';
|
|
6
7
|
const adaptersById = new Map([
|
|
7
8
|
claudeCodeAdapter,
|
|
8
9
|
codexAdapter,
|
|
9
10
|
antigravityCliAdapter,
|
|
10
|
-
opencodeAdapter
|
|
11
|
+
opencodeAdapter,
|
|
12
|
+
traecliAdapter
|
|
11
13
|
].map((adapter) => [adapter.id, adapter]));
|
|
12
14
|
const BUILTIN_AGENT_CLIENT_ADAPTERS = Object.freeze(AGENT_CLIENT_IDS.map((id) => {
|
|
13
15
|
const adapter = adaptersById.get(id);
|
|
@@ -20,12 +20,8 @@ function ensureOpenCodeSandboxState(toolDir, hostHome, hostEnv = {}) {
|
|
|
20
20
|
const canonicalConfigDir = path.join(toolDir, '.xdg', 'config', 'opencode');
|
|
21
21
|
const canonicalStateDir = path.join(toolDir, '.xdg', 'state', 'opencode');
|
|
22
22
|
const canonicalConfigPath = path.join(canonicalConfigDir, 'opencode.json');
|
|
23
|
-
const legacyConfigPath = path.join(toolDir, 'opencode.json');
|
|
24
23
|
fs.mkdirSync(canonicalConfigDir, { recursive: true });
|
|
25
24
|
fs.mkdirSync(canonicalStateDir, { recursive: true });
|
|
26
|
-
if (!fs.existsSync(canonicalConfigPath) && fs.existsSync(legacyConfigPath)) {
|
|
27
|
-
fs.copyFileSync(legacyConfigPath, canonicalConfigPath, fs.constants.COPYFILE_EXCL);
|
|
28
|
-
}
|
|
29
25
|
const hostConfigRoot = resolveXdgRoot(hostEnv.XDG_CONFIG_HOME, path.join(hostHome, '.config'));
|
|
30
26
|
const hostConfig = readJsonObject(path.join(hostConfigRoot, 'opencode', 'opencode.json'));
|
|
31
27
|
if (!hostConfig) {
|