@fitlab-ai/agent-infra 0.9.0 → 0.9.2
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 +22 -5
- package/README.zh-CN.md +21 -5
- package/bin/cli.ts +12 -0
- package/dist/bin/cli.js +14 -0
- package/dist/bin/internal-cli.js +20 -0
- package/dist/lib/agent-client.js +163 -0
- package/dist/lib/agent-clients/adapter.js +294 -0
- package/dist/lib/agent-clients/adapters/claude-code.js +62 -0
- package/dist/lib/agent-clients/adapters/codex-sandbox.js +210 -0
- package/dist/lib/agent-clients/adapters/codex.js +54 -0
- package/dist/lib/agent-clients/adapters/gemini-cli.js +64 -0
- package/dist/lib/agent-clients/adapters/index.js +20 -0
- package/dist/lib/agent-clients/adapters/opencode.js +64 -0
- package/dist/lib/agent-clients/config.js +177 -0
- package/dist/lib/agent-clients/custom-tuis.js +99 -0
- package/dist/lib/agent-clients/invocation.js +9 -0
- package/dist/lib/agent-clients/next-steps.js +38 -0
- package/dist/lib/agent-clients/project-assets.js +45 -0
- package/dist/lib/agent-clients/reconcile.js +235 -0
- package/dist/lib/agent-clients/registry.js +72 -0
- package/dist/lib/agent-clients/schema.js +57 -0
- package/dist/lib/agent-clients/types.js +29 -0
- package/dist/lib/builtin-tuis.js +9 -14
- package/dist/lib/defaults.json +85 -73
- package/dist/lib/git/review-snapshot.js +25 -10
- package/dist/lib/git/reviewed-commit-equivalence.js +110 -0
- package/dist/lib/init.js +47 -91
- package/dist/lib/internal/agent-client.js +117 -0
- package/dist/lib/internal/git-workflow.js +1 -1
- package/dist/lib/internal/platform-release-notes.js +53 -0
- package/dist/lib/internal/release-workflow.js +175 -17
- package/dist/lib/internal/task-orchestration.js +151 -0
- package/dist/lib/internal/task-review.js +65 -0
- package/dist/lib/merge.js +2 -1
- package/dist/lib/platform/adapters.js +38 -1
- package/dist/lib/platform/change-request-git-evidence.js +113 -0
- package/dist/lib/platform/github-release-notes.js +96 -0
- package/dist/lib/platform/issues.js +4 -2
- package/dist/lib/platform/merged-pr-equivalence.js +84 -0
- package/dist/lib/platform/pr-checks.js +43 -15
- package/dist/lib/platform/pull-requests.js +113 -7
- package/dist/lib/platform/release-notes.js +143 -0
- package/dist/lib/platform/releases.js +1 -1
- package/dist/lib/platform/verification-required.js +31 -9
- package/dist/lib/prompt.js +15 -3
- package/dist/lib/release/channels.js +4 -1
- package/dist/lib/release/workflow.js +4 -2
- package/dist/lib/remove-dir.js +25 -0
- package/dist/lib/run/tui.js +8 -2
- package/dist/lib/sandbox/agent-client-reconciler.js +234 -0
- package/dist/lib/sandbox/build-proxy.js +63 -0
- package/dist/lib/sandbox/clipboard/linux.js +2 -1
- package/dist/lib/sandbox/commands/create.js +133 -189
- package/dist/lib/sandbox/commands/enter.js +17 -1
- package/dist/lib/sandbox/commands/prune.js +2 -2
- package/dist/lib/sandbox/commands/rebuild.js +24 -7
- package/dist/lib/sandbox/commands/rm.js +3 -2
- package/dist/lib/sandbox/config.js +21 -4
- package/dist/lib/sandbox/constants.js +3 -0
- package/dist/lib/sandbox/dockerfile.js +2 -1
- package/dist/lib/sandbox/image-build.js +2 -1
- package/dist/lib/sandbox/managed-fs.js +10 -5
- package/dist/lib/sandbox/recovery.js +52 -36
- package/dist/lib/sandbox/runtimes/ai-tools.dockerfile +24 -3
- package/dist/lib/sandbox/runtimes/base.dockerfile +8 -1
- package/dist/lib/sandbox/runtimes/java17.dockerfile +8 -1
- package/dist/lib/sandbox/runtimes/java21.dockerfile +8 -1
- package/dist/lib/sandbox/runtimes/node20.dockerfile +8 -1
- package/dist/lib/sandbox/runtimes/node22.dockerfile +8 -1
- package/dist/lib/sandbox/runtimes/python3.dockerfile +8 -1
- package/dist/lib/sandbox/shell.js +3 -2
- package/dist/lib/sandbox/tool-types.js +8 -0
- package/dist/lib/sandbox/tools.js +2 -126
- package/dist/lib/task/artifact-lifecycle.js +1 -49
- package/dist/lib/task/commands/decisions.js +50 -20
- package/dist/lib/task/commands/issue-body.js +10 -5
- package/dist/lib/task/delegation-receipts.js +107 -0
- package/dist/lib/task/events.js +101 -2
- package/dist/lib/task/issue-form.js +2 -0
- package/dist/lib/task/orchestration.js +420 -0
- package/dist/lib/task/review-artifacts.js +143 -59
- package/dist/lib/task/review-finalization.js +166 -0
- package/dist/lib/task/review-fingerprint.js +13 -0
- package/dist/lib/task/verification-checks.js +2 -1
- package/dist/lib/task/verification-engine.js +168 -23
- package/dist/lib/task/verification-review.js +1 -1
- package/dist/lib/task/verification.js +4 -2
- package/dist/lib/task/workspace-snapshot.js +34 -0
- package/dist/lib/update.js +42 -161
- package/lib/agent-client.ts +214 -0
- package/lib/agent-clients/adapter.ts +461 -0
- package/lib/agent-clients/adapters/claude-code.ts +70 -0
- package/lib/agent-clients/adapters/codex-sandbox.ts +245 -0
- package/lib/agent-clients/adapters/codex.ts +58 -0
- package/lib/agent-clients/adapters/gemini-cli.ts +65 -0
- package/lib/agent-clients/adapters/index.ts +27 -0
- package/lib/agent-clients/adapters/opencode.ts +66 -0
- package/lib/agent-clients/config.ts +278 -0
- package/lib/agent-clients/custom-tuis.ts +149 -0
- package/lib/agent-clients/invocation.ts +19 -0
- package/lib/agent-clients/next-steps.ts +72 -0
- package/lib/agent-clients/project-assets.ts +96 -0
- package/lib/agent-clients/reconcile.ts +324 -0
- package/lib/agent-clients/registry.ts +144 -0
- package/lib/agent-clients/schema.ts +62 -0
- package/lib/agent-clients/types.ts +78 -0
- package/lib/benchmark/schemas/v1.0.0/case-manifest.schema.json +120 -0
- package/lib/benchmark/schemas/v1.0.0/common.schema.json +109 -0
- package/lib/benchmark/schemas/v1.0.0/grader-result.schema.json +160 -0
- package/lib/benchmark/schemas/v1.0.0/run-manifest.schema.json +122 -0
- package/lib/benchmark/schemas/v1.0.0/subject.schema.json +227 -0
- package/lib/builtin-tuis.ts +16 -15
- package/lib/defaults.json +24 -12
- package/lib/git/review-snapshot.ts +39 -9
- package/lib/git/reviewed-commit-equivalence.ts +135 -0
- package/lib/init.ts +53 -121
- package/lib/internal/agent-client.ts +131 -0
- package/lib/internal/git-workflow.ts +1 -1
- package/lib/internal/platform-release-notes.ts +55 -0
- package/lib/internal/release-workflow.ts +172 -18
- package/lib/internal/task-orchestration.ts +132 -0
- package/lib/internal/task-review.ts +65 -0
- package/lib/merge.ts +2 -1
- package/lib/platform/adapters.ts +142 -3
- package/lib/platform/change-request-git-evidence.ts +159 -0
- package/lib/platform/github-release-notes.ts +132 -0
- package/lib/platform/issues.ts +6 -4
- package/lib/platform/merged-pr-equivalence.ts +107 -0
- package/lib/platform/pr-checks.ts +57 -28
- package/lib/platform/pull-requests.ts +140 -25
- package/lib/platform/release-notes.ts +167 -0
- package/lib/platform/releases.ts +1 -1
- package/lib/platform/verification-required.ts +37 -9
- package/lib/prompt.ts +16 -3
- package/lib/release/channels.ts +4 -1
- package/lib/release/workflow.ts +4 -3
- package/lib/remove-dir.ts +28 -0
- package/lib/run/tui.ts +9 -1
- package/lib/sandbox/agent-client-reconciler.ts +378 -0
- package/lib/sandbox/build-proxy.ts +94 -0
- package/lib/sandbox/clipboard/linux.ts +2 -1
- package/lib/sandbox/commands/create.ts +188 -203
- package/lib/sandbox/commands/enter.ts +23 -1
- package/lib/sandbox/commands/prune.ts +2 -2
- package/lib/sandbox/commands/rebuild.ts +29 -7
- package/lib/sandbox/commands/rm.ts +3 -2
- package/lib/sandbox/config.ts +31 -4
- package/lib/sandbox/constants.ts +6 -0
- package/lib/sandbox/dockerfile.ts +2 -1
- package/lib/sandbox/image-build.ts +4 -1
- package/lib/sandbox/managed-fs.ts +18 -5
- package/lib/sandbox/recovery.ts +98 -67
- package/lib/sandbox/runtimes/ai-tools.dockerfile +24 -3
- package/lib/sandbox/runtimes/base.dockerfile +8 -1
- package/lib/sandbox/runtimes/java17.dockerfile +8 -1
- package/lib/sandbox/runtimes/java21.dockerfile +8 -1
- package/lib/sandbox/runtimes/node20.dockerfile +8 -1
- package/lib/sandbox/runtimes/node22.dockerfile +8 -1
- package/lib/sandbox/runtimes/python3.dockerfile +8 -1
- package/lib/sandbox/shell.ts +4 -2
- package/lib/sandbox/tool-types.ts +143 -0
- package/lib/sandbox/tools.ts +5 -157
- package/lib/task/artifact-lifecycle.ts +1 -38
- package/lib/task/commands/decisions.ts +53 -20
- package/lib/task/commands/issue-body.ts +10 -5
- package/lib/task/delegation-receipts.ts +170 -0
- package/lib/task/events.ts +111 -3
- package/lib/task/issue-form.ts +4 -0
- package/lib/task/orchestration.ts +543 -0
- package/lib/task/review-artifacts.ts +201 -69
- package/lib/task/review-finalization.ts +275 -0
- package/lib/task/review-fingerprint.ts +15 -1
- package/lib/task/verification-checks.ts +2 -1
- package/lib/task/verification-engine.ts +190 -25
- package/lib/task/verification-review.ts +2 -0
- package/lib/task/verification.ts +6 -3
- package/lib/task/workspace-snapshot.ts +36 -0
- package/lib/update.ts +48 -184
- package/package.json +2 -2
- package/templates/.agents/README.en.md +21 -20
- package/templates/.agents/README.zh-CN.md +21 -20
- package/templates/.agents/hooks/lifecycle-delegation.js +64 -0
- package/templates/.agents/rules/README.en.md +2 -0
- package/templates/.agents/rules/README.zh-CN.md +2 -0
- package/templates/.agents/rules/commit-and-pr.en.md +1 -0
- package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -0
- package/templates/.agents/rules/human-decision-context.en.md +14 -12
- package/templates/.agents/rules/human-decision-context.zh-CN.md +14 -12
- package/templates/.agents/rules/lifecycle-orchestration.en.md +21 -0
- package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +21 -0
- package/templates/.agents/rules/next-step-output.en.md +16 -0
- package/templates/.agents/rules/next-step-output.zh-CN.md +16 -0
- package/templates/.agents/rules/no-mid-flow-questions.en.md +2 -0
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +2 -0
- package/templates/.agents/rules/release-commands.en.md +2 -2
- package/templates/.agents/rules/release-commands.github.en.md +15 -39
- package/templates/.agents/rules/release-commands.github.zh-CN.md +14 -38
- package/templates/.agents/rules/release-commands.zh-CN.md +2 -2
- package/templates/.agents/rules/review-handshake.en.md +4 -3
- package/templates/.agents/rules/review-handshake.zh-CN.md +4 -3
- package/templates/.agents/rules/review-method.en.md +113 -0
- package/templates/.agents/rules/review-method.zh-CN.md +98 -0
- package/templates/.agents/rules/testing-discipline.en.md +20 -2
- package/templates/.agents/rules/testing-discipline.zh-CN.md +20 -2
- package/templates/.agents/skills/analyze-task/SKILL.en.md +9 -6
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +9 -6
- package/templates/.agents/skills/block-task/SKILL.en.md +4 -4
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/cancel-task/SKILL.en.md +4 -4
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/check-task/SKILL.en.md +16 -16
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -16
- package/templates/.agents/skills/close-codescan/SKILL.en.md +4 -4
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +4 -4
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/code-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/code-task/reference/fix-mode.en.md +14 -16
- package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +14 -16
- package/templates/.agents/skills/code-task/reference/output-template.en.md +3 -3
- package/templates/.agents/skills/code-task/reference/output-template.zh-CN.md +3 -3
- package/templates/.agents/skills/commit/SKILL.en.md +11 -1
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +11 -1
- package/templates/.agents/skills/commit/reference/task-status-update.en.md +24 -28
- package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +24 -28
- 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/complete-task/config/verify.en.json +0 -1
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +0 -1
- package/templates/.agents/skills/create-pr/SKILL.en.md +10 -10
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +10 -10
- package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +3 -3
- package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +3 -3
- package/templates/.agents/skills/create-release-note/SKILL.en.md +17 -38
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +16 -37
- package/templates/.agents/skills/create-task/SKILL.en.md +15 -11
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +15 -11
- package/templates/.agents/skills/create-task/reference/context-capture.en.md +29 -0
- package/templates/.agents/skills/create-task/reference/context-capture.zh-CN.md +29 -0
- package/templates/.agents/skills/import-codescan/SKILL.en.md +5 -5
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +5 -5
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/import-issue/SKILL.en.md +5 -5
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/init-labels/SKILL.en.md +4 -4
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/init-milestones/SKILL.en.md +4 -4
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/plan-task/SKILL.en.md +5 -5
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/refine-title/SKILL.en.md +1 -1
- package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/release/SKILL.en.md +1 -1
- package/templates/.agents/skills/review-analysis/SKILL.en.md +13 -2
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -3
- package/templates/.agents/skills/review-analysis/config/verify.en.json +6 -0
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +6 -0
- package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +13 -15
- package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +13 -15
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +51 -5
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +52 -6
- package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +25 -22
- package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +25 -22
- package/templates/.agents/skills/review-code/SKILL.en.md +28 -8
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +28 -8
- package/templates/.agents/skills/review-code/config/verify.en.json +7 -0
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +7 -0
- package/templates/.agents/skills/review-code/reference/concurrency-risks.en.md +25 -0
- package/templates/.agents/skills/review-code/reference/concurrency-risks.zh-CN.md +25 -0
- package/templates/.agents/skills/review-code/reference/cross-platform-risks.en.md +27 -0
- package/templates/.agents/skills/review-code/reference/cross-platform-risks.zh-CN.md +27 -0
- package/templates/.agents/skills/review-code/reference/documentation-antipatterns.en.md +13 -0
- package/templates/.agents/skills/review-code/reference/documentation-antipatterns.zh-CN.md +13 -0
- package/templates/.agents/skills/review-code/reference/migration-risks.en.md +25 -0
- package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +25 -0
- package/templates/.agents/skills/review-code/reference/output-templates.en.md +22 -24
- package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +22 -24
- package/templates/.agents/skills/review-code/reference/report-template.en.md +54 -7
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +54 -7
- package/templates/.agents/skills/review-code/reference/review-criteria.en.md +29 -24
- package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +29 -24
- package/templates/.agents/skills/review-code/reference/security-risks.en.md +25 -0
- package/templates/.agents/skills/review-code/reference/security-risks.zh-CN.md +25 -0
- package/templates/.agents/skills/review-plan/SKILL.en.md +13 -2
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -3
- package/templates/.agents/skills/review-plan/config/verify.en.json +6 -0
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +6 -0
- package/templates/.agents/skills/review-plan/reference/output-templates.en.md +13 -15
- package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +13 -15
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +61 -5
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +61 -5
- package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +21 -24
- package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +21 -24
- package/templates/.agents/skills/run-task/SKILL.en.md +22 -0
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +22 -0
- package/templates/.agents/skills/run-task/config/verify.en.json +9 -0
- package/templates/.agents/skills/run-task/config/verify.zh-CN.json +9 -0
- package/templates/.agents/skills/test/SKILL.en.md +4 -4
- package/templates/.agents/skills/test/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/test-integration/SKILL.en.md +4 -4
- package/templates/.agents/skills/test-integration/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +5 -5
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +647 -203
- package/templates/.agents/skills/upgrade-dependency/SKILL.en.md +4 -4
- package/templates/.agents/skills/upgrade-dependency/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/watch-pr/SKILL.en.md +8 -8
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +8 -8
- package/templates/.agents/templates/task.en.md +18 -0
- package/templates/.agents/templates/task.zh-CN.md +18 -0
- package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +6 -0
- package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +6 -0
- package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +6 -0
- package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +6 -0
- package/templates/.claude/commands/run-task.en.md +8 -0
- package/templates/.claude/commands/run-task.zh-CN.md +8 -0
- package/templates/.claude/settings.json +24 -0
- package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +3 -0
- package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +3 -0
- package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +3 -0
- package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +3 -0
- package/templates/.gemini/commands/_project_/run-task.en.toml +8 -0
- package/templates/.gemini/commands/_project_/run-task.zh-CN.toml +8 -0
- package/templates/.opencode/commands/run-task.en.md +11 -0
- package/templates/.opencode/commands/run-task.zh-CN.md +11 -0
|
@@ -11,7 +11,7 @@ import { hostJoin } from '../engines/wsl2-paths.ts';
|
|
|
11
11
|
import { removeManagedDir, removeWorktreeDir } from '../managed-fs.ts';
|
|
12
12
|
import { parseLabels } from './ls.ts';
|
|
13
13
|
import { runEngine, runSafe } from '../shell.ts';
|
|
14
|
-
import {
|
|
14
|
+
import { createSandboxCapabilityPlan } from '../agent-client-reconciler.ts';
|
|
15
15
|
import type { SandboxTool } from '../tools.ts';
|
|
16
16
|
|
|
17
17
|
const USAGE = `Usage: ai sandbox prune [--dry-run]`;
|
|
@@ -158,7 +158,7 @@ export async function prune(args: string[]): Promise<void> {
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
const config = loadConfig();
|
|
161
|
-
const tools =
|
|
161
|
+
const tools = [...createSandboxCapabilityPlan(config).cleanupInventory];
|
|
162
162
|
const engine = detectEngine(config);
|
|
163
163
|
const psArgs = [
|
|
164
164
|
'ps',
|
|
@@ -16,8 +16,14 @@ import {
|
|
|
16
16
|
parseImageLabels,
|
|
17
17
|
parseRefreshTimestamp
|
|
18
18
|
} from '../image-build.ts';
|
|
19
|
+
import {
|
|
20
|
+
assertBuildProxyCompatibility,
|
|
21
|
+
buildProxyFailureHint,
|
|
22
|
+
prepareBuildProxy,
|
|
23
|
+
redactBuildProxyValues
|
|
24
|
+
} from '../build-proxy.ts';
|
|
19
25
|
|
|
20
|
-
const USAGE = `Usage: ai sandbox rebuild [--quiet] [--refresh]`;
|
|
26
|
+
const USAGE = `Usage: ai sandbox rebuild [--quiet] [--refresh] [--inherit-build-proxy|-B]`;
|
|
21
27
|
|
|
22
28
|
type EngineRunFn = (engine: string, cmd: string, args: string[], opts?: { cwd?: string }) => string;
|
|
23
29
|
type EngineRunSafeFn = EngineRunFn;
|
|
@@ -33,7 +39,8 @@ export function buildArgs(
|
|
|
33
39
|
runSafeFn = runSafeEngine,
|
|
34
40
|
env = process.env,
|
|
35
41
|
refresh = false,
|
|
36
|
-
lastRefresh
|
|
42
|
+
lastRefresh,
|
|
43
|
+
buildProxyArgs = []
|
|
37
44
|
}: {
|
|
38
45
|
engine?: string;
|
|
39
46
|
runFn?: EngineRunFn;
|
|
@@ -41,6 +48,7 @@ export function buildArgs(
|
|
|
41
48
|
env?: NodeJS.ProcessEnv;
|
|
42
49
|
refresh?: boolean;
|
|
43
50
|
lastRefresh?: number;
|
|
51
|
+
buildProxyArgs?: string[];
|
|
44
52
|
} = {}
|
|
45
53
|
): string[] {
|
|
46
54
|
return buildSandboxImageArgs(config, tools, dockerfilePath, imageSignature, {
|
|
@@ -49,7 +57,8 @@ export function buildArgs(
|
|
|
49
57
|
runSafeFn,
|
|
50
58
|
env,
|
|
51
59
|
refresh,
|
|
52
|
-
lastRefresh
|
|
60
|
+
lastRefresh,
|
|
61
|
+
buildProxyArgs
|
|
53
62
|
});
|
|
54
63
|
}
|
|
55
64
|
|
|
@@ -77,6 +86,7 @@ export async function rebuild(args: string[]): Promise<void> {
|
|
|
77
86
|
options: {
|
|
78
87
|
refresh: { type: 'boolean' },
|
|
79
88
|
quiet: { type: 'boolean', short: 'q' },
|
|
89
|
+
'inherit-build-proxy': { type: 'boolean', short: 'B' },
|
|
80
90
|
help: { type: 'boolean', short: 'h' }
|
|
81
91
|
}
|
|
82
92
|
});
|
|
@@ -95,6 +105,11 @@ export async function rebuild(args: string[]): Promise<void> {
|
|
|
95
105
|
const engine = detectEngine(config);
|
|
96
106
|
|
|
97
107
|
await ensureDocker(config, undefined);
|
|
108
|
+
if (values['inherit-build-proxy'] && config.dockerfile) {
|
|
109
|
+
throw new Error('Build proxy inheritance is unavailable with a custom sandbox Dockerfile.');
|
|
110
|
+
}
|
|
111
|
+
const buildProxy = prepareBuildProxy(values['inherit-build-proxy'] ?? false, process.env, engine);
|
|
112
|
+
if (values['inherit-build-proxy']) assertBuildProxyCompatibility(engine);
|
|
98
113
|
const lastRefresh = refresh ? Date.now() : readExistingLastRefresh(config, engine);
|
|
99
114
|
p.intro(pc.cyan('Rebuilding sandbox image'));
|
|
100
115
|
|
|
@@ -105,9 +120,11 @@ export async function rebuild(args: string[]): Promise<void> {
|
|
|
105
120
|
runEngine(engine, 'docker', buildArgs(config, tools, preparedDockerfile.path, imageSignature, {
|
|
106
121
|
engine,
|
|
107
122
|
refresh,
|
|
108
|
-
lastRefresh
|
|
123
|
+
lastRefresh,
|
|
124
|
+
buildProxyArgs: buildProxy.args
|
|
109
125
|
}), {
|
|
110
|
-
cwd: config.repoRoot
|
|
126
|
+
cwd: config.repoRoot,
|
|
127
|
+
env: buildProxy.env
|
|
111
128
|
});
|
|
112
129
|
spinner.stop(pc.green('Sandbox image rebuilt'));
|
|
113
130
|
} else {
|
|
@@ -118,13 +135,18 @@ export async function rebuild(args: string[]): Promise<void> {
|
|
|
118
135
|
buildArgs(config, tools, preparedDockerfile.path, imageSignature, {
|
|
119
136
|
engine,
|
|
120
137
|
refresh,
|
|
121
|
-
lastRefresh
|
|
138
|
+
lastRefresh,
|
|
139
|
+
buildProxyArgs: buildProxy.args
|
|
122
140
|
}),
|
|
123
|
-
{ cwd: config.repoRoot }
|
|
141
|
+
{ cwd: config.repoRoot, env: buildProxy.env }
|
|
124
142
|
);
|
|
125
143
|
p.log.success(pc.green('Sandbox image rebuilt'));
|
|
126
144
|
}
|
|
127
145
|
pruneSandboxDanglingImages(config, engine);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
const message = redactBuildProxyValues(error instanceof Error ? error.message : String(error), buildProxy.redactionValues);
|
|
148
|
+
const hint = values['inherit-build-proxy'] ? `\n${buildProxyFailureHint(engine)}` : '';
|
|
149
|
+
throw new Error(`${message}${hint}`);
|
|
128
150
|
} finally {
|
|
129
151
|
preparedDockerfile.cleanup();
|
|
130
152
|
}
|
|
@@ -19,7 +19,8 @@ import { pruneSandboxDanglingImages } from '../image-prune.ts';
|
|
|
19
19
|
import { removeManagedDir, removeWorktreeDir } from '../managed-fs.ts';
|
|
20
20
|
import { runOk, runSafe, runSafeEngine } from '../shell.ts';
|
|
21
21
|
import { resolveTaskBranch } from '../task-resolver.ts';
|
|
22
|
-
import {
|
|
22
|
+
import { toolConfigDirCandidates, toolProjectDirCandidates } from '../tools.ts';
|
|
23
|
+
import { createSandboxCapabilityPlan } from '../agent-client-reconciler.ts';
|
|
23
24
|
import type { SandboxTool } from '../tools.ts';
|
|
24
25
|
import { fetchSandboxRows } from './list-running.ts';
|
|
25
26
|
import { lookupShortIdByBranch } from '../../task/short-id.ts';
|
|
@@ -353,7 +354,7 @@ export async function rm(args: string[]): Promise<void> {
|
|
|
353
354
|
}
|
|
354
355
|
|
|
355
356
|
const config = loadConfig();
|
|
356
|
-
const tools =
|
|
357
|
+
const tools = [...createSandboxCapabilityPlan(config).cleanupInventory];
|
|
357
358
|
|
|
358
359
|
if (values.purge) {
|
|
359
360
|
await rmPurge(config, tools);
|
package/lib/sandbox/config.ts
CHANGED
|
@@ -3,6 +3,9 @@ import path from 'node:path';
|
|
|
3
3
|
import { homedir, platform } from 'node:os';
|
|
4
4
|
import { execFileSync } from 'node:child_process';
|
|
5
5
|
import pc from 'picocolors';
|
|
6
|
+
import { normalizeAgentClients } from '../agent-clients/config.ts';
|
|
7
|
+
import { isAgentClientId } from '../agent-clients/types.ts';
|
|
8
|
+
import type { AgentClientState } from '../agent-clients/types.ts';
|
|
6
9
|
import { validateSandboxEngine } from './engine.ts';
|
|
7
10
|
import { hostJoin } from './engines/wsl2-paths.ts';
|
|
8
11
|
import { findRuntimeEngineMismatches } from './runtime-engines.ts';
|
|
@@ -12,7 +15,7 @@ import type { SandboxTool } from './tools.ts';
|
|
|
12
15
|
const DEFAULTS = Object.freeze({
|
|
13
16
|
engine: null,
|
|
14
17
|
runtimes: ['node22'],
|
|
15
|
-
tools: ['agent-infra'
|
|
18
|
+
tools: ['agent-infra'],
|
|
16
19
|
refreshIntervalDays: 7,
|
|
17
20
|
dockerfile: null,
|
|
18
21
|
vm: {
|
|
@@ -57,6 +60,8 @@ export type SandboxConfig = {
|
|
|
57
60
|
runtimes: string[];
|
|
58
61
|
tools: string[];
|
|
59
62
|
customTools: SandboxTool[];
|
|
63
|
+
agentClientState: AgentClientState;
|
|
64
|
+
agentClientSource: 'canonical' | 'legacy';
|
|
60
65
|
refreshIntervalDays: number;
|
|
61
66
|
dockerfile: string | null;
|
|
62
67
|
vm: SandboxVmConfig;
|
|
@@ -65,6 +70,8 @@ export type SandboxConfig = {
|
|
|
65
70
|
type AircConfig = {
|
|
66
71
|
project?: unknown;
|
|
67
72
|
org?: unknown;
|
|
73
|
+
agentClients?: unknown;
|
|
74
|
+
tuis?: unknown;
|
|
68
75
|
sandbox?: SandboxConfigInput;
|
|
69
76
|
};
|
|
70
77
|
|
|
@@ -98,6 +105,23 @@ function cloneDefaults(): SandboxConfigInput & { vm: SandboxVmConfig; runtimes:
|
|
|
98
105
|
};
|
|
99
106
|
}
|
|
100
107
|
|
|
108
|
+
function resolveSandboxToolIds(
|
|
109
|
+
sandbox: SandboxConfigInput,
|
|
110
|
+
agentClients: ReturnType<typeof normalizeAgentClients>,
|
|
111
|
+
defaults: readonly string[]
|
|
112
|
+
): string[] {
|
|
113
|
+
if (Array.isArray(sandbox.tools)) {
|
|
114
|
+
const tools = sandbox.tools.filter((tool): tool is string => typeof tool === 'string');
|
|
115
|
+
return agentClients.source === 'canonical'
|
|
116
|
+
? tools.filter((tool) => !isAgentClientId(tool))
|
|
117
|
+
: tools;
|
|
118
|
+
}
|
|
119
|
+
if (agentClients.remainingSandboxTools !== undefined) {
|
|
120
|
+
return [...agentClients.remainingSandboxTools];
|
|
121
|
+
}
|
|
122
|
+
return [...defaults];
|
|
123
|
+
}
|
|
124
|
+
|
|
101
125
|
export function loadConfig({
|
|
102
126
|
platformFn = platform,
|
|
103
127
|
writeStderr = (chunk) => process.stderr.write(chunk)
|
|
@@ -115,6 +139,8 @@ export function loadConfig({
|
|
|
115
139
|
}
|
|
116
140
|
|
|
117
141
|
const airc = JSON.parse(fs.readFileSync(configPath, 'utf8')) as AircConfig;
|
|
142
|
+
const sandboxInput = airc.sandbox;
|
|
143
|
+
const agentClients = normalizeAgentClients(airc);
|
|
118
144
|
const defaults = cloneDefaults();
|
|
119
145
|
const sandbox = airc.sandbox ?? {};
|
|
120
146
|
const engine = validateSandboxEngine(sandbox.engine ?? defaults.engine, { platformFn });
|
|
@@ -149,6 +175,7 @@ export function loadConfig({
|
|
|
149
175
|
}
|
|
150
176
|
|
|
151
177
|
const customTools = parseCustomTools(sandbox.customTools, { home });
|
|
178
|
+
const tools = resolveSandboxToolIds(sandbox, agentClients, defaults.tools);
|
|
152
179
|
|
|
153
180
|
return {
|
|
154
181
|
repoRoot,
|
|
@@ -164,10 +191,10 @@ export function loadConfig({
|
|
|
164
191
|
dotfilesDir: hostJoin(home, '.agent-infra', 'dotfiles'),
|
|
165
192
|
engine,
|
|
166
193
|
runtimes,
|
|
167
|
-
tools
|
|
168
|
-
? [...sandbox.tools]
|
|
169
|
-
: defaults.tools,
|
|
194
|
+
tools,
|
|
170
195
|
customTools,
|
|
196
|
+
agentClientState: agentClients.state,
|
|
197
|
+
agentClientSource: agentClients.source,
|
|
171
198
|
refreshIntervalDays: asNonNegativeIntegerOrDefault(
|
|
172
199
|
sandbox.refreshIntervalDays,
|
|
173
200
|
defaults.refreshIntervalDays
|
package/lib/sandbox/constants.ts
CHANGED
|
@@ -111,6 +111,12 @@ export function sandboxImageRefreshLabel(config: Pick<SandboxPathConfig, 'projec
|
|
|
111
111
|
return `${sandboxLabel(config)}.last-refresh`;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
export function sandboxRuntimeCapabilityLabel(
|
|
115
|
+
config: Pick<SandboxPathConfig, 'project'>
|
|
116
|
+
): string {
|
|
117
|
+
return `agent-infra.sandbox.runtime-capability.${config.project}`;
|
|
118
|
+
}
|
|
119
|
+
|
|
114
120
|
export function parsePositiveIntegerOption(value: unknown, optionName: string): number | undefined {
|
|
115
121
|
if (value === undefined || value === null) {
|
|
116
122
|
return undefined;
|
|
@@ -3,6 +3,7 @@ import os from 'node:os';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { createHash } from 'node:crypto';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { removeDirRecursive } from '../remove-dir.ts';
|
|
6
7
|
|
|
7
8
|
const RUNTIMES_DIR = path.join(
|
|
8
9
|
path.dirname(fileURLToPath(import.meta.url)),
|
|
@@ -88,7 +89,7 @@ export function prepareDockerfile(config: DockerfileConfig): { path: string; sig
|
|
|
88
89
|
path: tempPath,
|
|
89
90
|
signature: dockerfileSignature(config),
|
|
90
91
|
cleanup() {
|
|
91
|
-
|
|
92
|
+
removeDirRecursive(tempDir);
|
|
92
93
|
}
|
|
93
94
|
};
|
|
94
95
|
}
|
|
@@ -44,7 +44,8 @@ export function buildSandboxImageArgs(
|
|
|
44
44
|
runSafeFn = runSafeEngine,
|
|
45
45
|
env = process.env,
|
|
46
46
|
refresh = false,
|
|
47
|
-
lastRefresh
|
|
47
|
+
lastRefresh,
|
|
48
|
+
buildProxyArgs = []
|
|
48
49
|
}: {
|
|
49
50
|
engine?: string;
|
|
50
51
|
runFn?: EngineRunFn;
|
|
@@ -52,6 +53,7 @@ export function buildSandboxImageArgs(
|
|
|
52
53
|
env?: NodeJS.ProcessEnv;
|
|
53
54
|
refresh?: boolean;
|
|
54
55
|
lastRefresh?: number;
|
|
56
|
+
buildProxyArgs?: string[];
|
|
55
57
|
} = {}
|
|
56
58
|
): string[] {
|
|
57
59
|
const selectedEngine = engine ?? detectEngine({ engine: config.engine });
|
|
@@ -79,6 +81,7 @@ export function buildSandboxImageArgs(
|
|
|
79
81
|
'--label',
|
|
80
82
|
`${sandboxImageConfigLabel(config)}=${imageSignature}`
|
|
81
83
|
];
|
|
84
|
+
args.push(...buildProxyArgs);
|
|
82
85
|
|
|
83
86
|
if (lastRefresh !== undefined) {
|
|
84
87
|
args.push('--label', `${sandboxImageRefreshLabel(config)}=${lastRefresh}`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
1
|
import path from 'node:path';
|
|
3
|
-
import { run } from './shell.ts';
|
|
2
|
+
import { run, runSafe } from './shell.ts';
|
|
3
|
+
import { removeDirRecursive } from '../remove-dir.ts';
|
|
4
4
|
|
|
5
5
|
export function assertManagedPath(root: string, target: string): void {
|
|
6
6
|
const resolvedRoot = path.resolve(root);
|
|
@@ -15,13 +15,26 @@ export function assertManagedPath(root: string, target: string): void {
|
|
|
15
15
|
|
|
16
16
|
export function removeManagedDir(root: string, dir: string): void {
|
|
17
17
|
assertManagedPath(root, dir);
|
|
18
|
-
|
|
18
|
+
removeDirRecursive(dir);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export function removeWorktreeDir(
|
|
21
|
+
export function removeWorktreeDir(
|
|
22
|
+
repoRoot: string,
|
|
23
|
+
worktreeBase: string,
|
|
24
|
+
dir: string,
|
|
25
|
+
{ runFn = run, runSafeFn = runSafe }: {
|
|
26
|
+
runFn?: typeof run;
|
|
27
|
+
runSafeFn?: typeof runSafe;
|
|
28
|
+
} = {}
|
|
29
|
+
): void {
|
|
22
30
|
try {
|
|
23
|
-
|
|
31
|
+
runFn('git', ['-C', repoRoot, 'worktree', 'remove', dir, '--force']);
|
|
24
32
|
} catch {
|
|
33
|
+
// On WSL2 the worktree is registered under its `/mnt/<drive>/...` path, so
|
|
34
|
+
// `git worktree remove <windows-path>` cannot match it. Delete the managed
|
|
35
|
+
// directory directly, then prune the now-dangling worktree metadata so the
|
|
36
|
+
// branch is no longer reported as checked out.
|
|
25
37
|
removeManagedDir(worktreeBase, dir);
|
|
38
|
+
runSafeFn('git', ['-C', repoRoot, 'worktree', 'prune']);
|
|
26
39
|
}
|
|
27
40
|
}
|
package/lib/sandbox/recovery.ts
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
containerNameCandidates,
|
|
5
|
+
sandboxBranchLabel,
|
|
6
|
+
sandboxLabel,
|
|
7
|
+
sandboxRuntimeCapabilityLabel
|
|
8
|
+
} from './constants.ts';
|
|
9
|
+
import { isAgentClientId } from '../agent-clients/types.ts';
|
|
10
|
+
import {
|
|
11
|
+
createSandboxCapabilityPlan
|
|
12
|
+
} from './agent-client-reconciler.ts';
|
|
13
|
+
import type {
|
|
14
|
+
SandboxRecoveryFindingDescriptor,
|
|
15
|
+
SandboxRecoveryRepair
|
|
16
|
+
} from './tool-types.ts';
|
|
4
17
|
import type { SandboxConfig } from './config.ts';
|
|
5
18
|
import { toEnginePath } from './engines/wsl2-paths.ts';
|
|
6
19
|
import { sandboxCoreBindMounts } from './mounts.ts';
|
|
@@ -9,6 +22,7 @@ import {
|
|
|
9
22
|
declaredTmpfsSeedEntries,
|
|
10
23
|
resolveTools,
|
|
11
24
|
toolConfigDirCandidates,
|
|
25
|
+
type SandboxTool,
|
|
12
26
|
type TmpfsSeedEntry
|
|
13
27
|
} from './tools.ts';
|
|
14
28
|
import {
|
|
@@ -23,10 +37,22 @@ export type SandboxRecoveryFinding = {
|
|
|
23
37
|
message: string;
|
|
24
38
|
path?: string;
|
|
25
39
|
seed?: TmpfsSeedEntry;
|
|
40
|
+
repair?: SandboxRecoveryRepair;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
type SandboxAgentClientCheckSnapshot = {
|
|
44
|
+
adapterId: string;
|
|
45
|
+
checkId: string;
|
|
46
|
+
applicable: boolean;
|
|
47
|
+
healthy: boolean;
|
|
48
|
+
finding: SandboxRecoveryFindingDescriptor;
|
|
49
|
+
repair?: SandboxRecoveryRepair;
|
|
26
50
|
};
|
|
27
51
|
|
|
28
52
|
export type SandboxRecoverySnapshot = {
|
|
29
53
|
identityOk: boolean;
|
|
54
|
+
runtimeCapabilityOk?: boolean;
|
|
55
|
+
unexpectedCapabilityMounts?: string[];
|
|
30
56
|
mounts: Array<{
|
|
31
57
|
path: string;
|
|
32
58
|
expectedType: string;
|
|
@@ -48,12 +74,7 @@ export type SandboxRecoverySnapshot = {
|
|
|
48
74
|
targetState: 'ok' | 'missing' | 'wrong-type' | 'inaccessible';
|
|
49
75
|
}>;
|
|
50
76
|
aliasesReadable: boolean;
|
|
51
|
-
|
|
52
|
-
commandAvailable: boolean;
|
|
53
|
-
stateWritable: boolean;
|
|
54
|
-
promptsSourceExists: boolean;
|
|
55
|
-
promptsValid: boolean;
|
|
56
|
-
};
|
|
77
|
+
agentClientChecks: SandboxAgentClientCheckSnapshot[];
|
|
57
78
|
};
|
|
58
79
|
|
|
59
80
|
export type SandboxReadyResult = {
|
|
@@ -114,6 +135,19 @@ export function classifySandboxRecovery(snapshot: SandboxRecoverySnapshot): Sand
|
|
|
114
135
|
message: 'Container identity does not match the requested sandbox branch.'
|
|
115
136
|
});
|
|
116
137
|
}
|
|
138
|
+
if (snapshot.runtimeCapabilityOk === false) {
|
|
139
|
+
findings.push({
|
|
140
|
+
repairKind: 'hard-failure',
|
|
141
|
+
message: 'Container runtime capability signature does not match the current sandbox plan.'
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
for (const mountPath of snapshot.unexpectedCapabilityMounts ?? []) {
|
|
145
|
+
findings.push({
|
|
146
|
+
repairKind: 'hard-failure',
|
|
147
|
+
message: `Disabled Agent Client capability remains mounted at ${mountPath}.`,
|
|
148
|
+
path: mountPath
|
|
149
|
+
});
|
|
150
|
+
}
|
|
117
151
|
|
|
118
152
|
for (const mount of snapshot.mounts) {
|
|
119
153
|
if (
|
|
@@ -177,25 +211,11 @@ export function classifySandboxRecovery(snapshot: SandboxRecoverySnapshot): Sand
|
|
|
177
211
|
});
|
|
178
212
|
}
|
|
179
213
|
|
|
180
|
-
|
|
181
|
-
if (!
|
|
214
|
+
for (const check of snapshot.agentClientChecks) {
|
|
215
|
+
if (check.applicable && !check.healthy) {
|
|
182
216
|
findings.push({
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
if (!snapshot.codex.stateWritable) {
|
|
188
|
-
findings.push({
|
|
189
|
-
repairKind: 'permissions',
|
|
190
|
-
message: 'Codex state directory is not writable by devuser.',
|
|
191
|
-
path: '/home/devuser/.codex'
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
if (snapshot.codex.promptsSourceExists && !snapshot.codex.promptsValid) {
|
|
195
|
-
findings.push({
|
|
196
|
-
repairKind: 'builtin-link',
|
|
197
|
-
message: 'Codex prompts link does not point to the workspace commands directory.',
|
|
198
|
-
path: '/home/devuser/.codex/prompts'
|
|
217
|
+
...check.finding,
|
|
218
|
+
...(check.repair === undefined ? {} : { repair: check.repair })
|
|
199
219
|
});
|
|
200
220
|
}
|
|
201
221
|
}
|
|
@@ -277,11 +297,10 @@ function hostSourceAccessible(hostPath: string, writable: boolean): boolean {
|
|
|
277
297
|
function expectedMounts(params: {
|
|
278
298
|
config: SandboxConfig;
|
|
279
299
|
branch: string;
|
|
280
|
-
|
|
300
|
+
tools: readonly SandboxTool[];
|
|
281
301
|
actualMounts: Map<string, DockerMount>;
|
|
282
302
|
}): ExpectedMount[] {
|
|
283
|
-
const { config, branch, actualMounts } = params;
|
|
284
|
-
const tools = resolveTools(config);
|
|
303
|
+
const { config, branch, tools, actualMounts } = params;
|
|
285
304
|
const core = sandboxCoreBindMounts(config, branch).map((mount) => ({
|
|
286
305
|
path: mount.containerPath,
|
|
287
306
|
expectedType: 'bind' as const,
|
|
@@ -301,7 +320,13 @@ function expectedMounts(params: {
|
|
|
301
320
|
})
|
|
302
321
|
);
|
|
303
322
|
const persistentTools = tools
|
|
304
|
-
.filter((tool) =>
|
|
323
|
+
.filter((tool) =>
|
|
324
|
+
!tool.tmpfs
|
|
325
|
+
&& (
|
|
326
|
+
config.agentClientSource === 'canonical'
|
|
327
|
+
|| actualMounts.has(tool.containerMount)
|
|
328
|
+
)
|
|
329
|
+
)
|
|
305
330
|
.map((tool) => ({
|
|
306
331
|
path: tool.containerMount,
|
|
307
332
|
expectedType: 'bind' as const,
|
|
@@ -401,7 +426,8 @@ export function collectSandboxRecoverySnapshot(params: {
|
|
|
401
426
|
});
|
|
402
427
|
}
|
|
403
428
|
}
|
|
404
|
-
const
|
|
429
|
+
const capabilityPlan = createSandboxCapabilityPlan(params.config);
|
|
430
|
+
const tools = [...capabilityPlan.tools];
|
|
405
431
|
const seeds = declaredTmpfsSeedEntries(tools).map((seed) => {
|
|
406
432
|
const mounted = mountsByDestination.get(seed.stagingPath)?.Type === 'bind';
|
|
407
433
|
return {
|
|
@@ -434,11 +460,18 @@ export function collectSandboxRecoverySnapshot(params: {
|
|
|
434
460
|
}));
|
|
435
461
|
const labels = inspection.Config?.Labels ?? {};
|
|
436
462
|
const branchLabel = labels[sandboxBranchLabel(params.config)];
|
|
437
|
-
const
|
|
463
|
+
const selectedToolIds = new Set(tools.map((tool) => tool.id));
|
|
464
|
+
const enforceCanonicalPlan = params.config.agentClientSource === 'canonical';
|
|
465
|
+
const unexpectedCapabilityMounts = enforceCanonicalPlan
|
|
466
|
+
? capabilityPlan.cleanupInventory
|
|
467
|
+
.filter((tool) => isAgentClientId(tool.id) && !selectedToolIds.has(tool.id))
|
|
468
|
+
.map((tool) => tool.containerMount)
|
|
469
|
+
.filter((mountPath) => mountsByDestination.has(mountPath))
|
|
470
|
+
: [];
|
|
438
471
|
const mountSnapshots = expectedMounts({
|
|
439
472
|
config: params.config,
|
|
440
473
|
branch: params.branch,
|
|
441
|
-
|
|
474
|
+
tools,
|
|
442
475
|
actualMounts: mountsByDestination
|
|
443
476
|
}).map((expected) => {
|
|
444
477
|
const actual = mountsByDestination.get(expected.path);
|
|
@@ -478,6 +511,10 @@ export function collectSandboxRecoverySnapshot(params: {
|
|
|
478
511
|
identityOk: typeof inspection.Id === 'string'
|
|
479
512
|
&& inspection.Id.length > 0
|
|
480
513
|
&& branchLabel === params.branch,
|
|
514
|
+
runtimeCapabilityOk: enforceCanonicalPlan
|
|
515
|
+
? labels[sandboxRuntimeCapabilityLabel(params.config)] === capabilityPlan.runtimeSignature
|
|
516
|
+
: undefined,
|
|
517
|
+
unexpectedCapabilityMounts,
|
|
481
518
|
mounts: mountSnapshots,
|
|
482
519
|
tmpfs,
|
|
483
520
|
seeds,
|
|
@@ -488,38 +525,31 @@ export function collectSandboxRecoverySnapshot(params: {
|
|
|
488
525
|
['/home/devuser/.bash_aliases'],
|
|
489
526
|
runOkFn
|
|
490
527
|
),
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
params.container,
|
|
517
|
-
'test "$(readlink -- "$1")" = "$2"',
|
|
518
|
-
['/home/devuser/.codex/prompts', '/workspace/.codex/commands'],
|
|
519
|
-
runOkFn
|
|
520
|
-
)
|
|
521
|
-
}
|
|
522
|
-
: undefined
|
|
528
|
+
agentClientChecks: capabilityPlan.recoveryChecks.map(({ adapterId, check }) => {
|
|
529
|
+
const applicable = check.when === undefined || probe(
|
|
530
|
+
params.engine,
|
|
531
|
+
params.container,
|
|
532
|
+
check.when.script,
|
|
533
|
+
[...check.when.args],
|
|
534
|
+
runOkFn,
|
|
535
|
+
check.when.user
|
|
536
|
+
);
|
|
537
|
+
return {
|
|
538
|
+
adapterId,
|
|
539
|
+
checkId: check.id,
|
|
540
|
+
applicable,
|
|
541
|
+
healthy: !applicable || probe(
|
|
542
|
+
params.engine,
|
|
543
|
+
params.container,
|
|
544
|
+
check.probe.script,
|
|
545
|
+
[...check.probe.args],
|
|
546
|
+
runOkFn,
|
|
547
|
+
check.probe.user
|
|
548
|
+
),
|
|
549
|
+
finding: check.finding,
|
|
550
|
+
...(check.repair === undefined ? {} : { repair: check.repair })
|
|
551
|
+
};
|
|
552
|
+
})
|
|
523
553
|
};
|
|
524
554
|
}
|
|
525
555
|
|
|
@@ -626,10 +656,11 @@ function repairFindings(params: {
|
|
|
626
656
|
deps: params.deps
|
|
627
657
|
});
|
|
628
658
|
const runVerboseFn = params.deps?.runVerbose ?? runVerboseEngine;
|
|
629
|
-
|
|
659
|
+
for (const repair of params.findings.flatMap((finding) =>
|
|
660
|
+
finding.repair === undefined ? [] : [finding.repair]
|
|
661
|
+
)) {
|
|
630
662
|
runVerboseFn(params.engine, 'docker', [
|
|
631
|
-
'exec', '--user',
|
|
632
|
-
'/workspace/.codex/commands', '/home/devuser/.codex/prompts'
|
|
663
|
+
'exec', '--user', repair.user, params.container, repair.command, ...repair.args
|
|
633
664
|
]);
|
|
634
665
|
}
|
|
635
666
|
}
|
|
@@ -5,20 +5,41 @@ ENV NPM_CONFIG_PREFIX=/home/devuser/.npm-global
|
|
|
5
5
|
ENV PATH="/home/devuser/.npm-global/bin:${PATH}"
|
|
6
6
|
|
|
7
7
|
ARG AI_TOOL_PACKAGES=
|
|
8
|
-
RUN
|
|
8
|
+
RUN --mount=type=secret,id=HTTP_PROXY \
|
|
9
|
+
--mount=type=secret,id=HTTPS_PROXY \
|
|
10
|
+
--mount=type=secret,id=NO_PROXY \
|
|
11
|
+
export HTTP_PROXY="$(cat /run/secrets/HTTP_PROXY 2>/dev/null || true)" && \
|
|
12
|
+
export HTTPS_PROXY="$(cat /run/secrets/HTTPS_PROXY 2>/dev/null || true)" && \
|
|
13
|
+
export NO_PROXY="$(cat /run/secrets/NO_PROXY 2>/dev/null || true)" && \
|
|
14
|
+
export http_proxy="${HTTP_PROXY}" https_proxy="${HTTPS_PROXY}" no_proxy="${NO_PROXY}" && \
|
|
15
|
+
set -e && \
|
|
9
16
|
for pkg in ${AI_TOOL_PACKAGES}; do \
|
|
10
17
|
npm install -g "$pkg"; \
|
|
11
18
|
done
|
|
12
19
|
|
|
13
20
|
ARG AI_TOOLS_SHELL_INSTALL_B64=
|
|
14
|
-
RUN
|
|
21
|
+
RUN --mount=type=secret,id=HTTP_PROXY \
|
|
22
|
+
--mount=type=secret,id=HTTPS_PROXY \
|
|
23
|
+
--mount=type=secret,id=NO_PROXY \
|
|
24
|
+
export HTTP_PROXY="$(cat /run/secrets/HTTP_PROXY 2>/dev/null || true)" && \
|
|
25
|
+
export HTTPS_PROXY="$(cat /run/secrets/HTTPS_PROXY 2>/dev/null || true)" && \
|
|
26
|
+
export NO_PROXY="$(cat /run/secrets/NO_PROXY 2>/dev/null || true)" && \
|
|
27
|
+
export http_proxy="${HTTP_PROXY}" https_proxy="${HTTPS_PROXY}" no_proxy="${NO_PROXY}" && \
|
|
28
|
+
if [ -n "${AI_TOOLS_SHELL_INSTALL_B64}" ]; then \
|
|
15
29
|
set -e && \
|
|
16
30
|
echo "${AI_TOOLS_SHELL_INSTALL_B64}" | base64 -d > /tmp/ai-tools-install.sh && \
|
|
17
31
|
bash /tmp/ai-tools-install.sh && \
|
|
18
32
|
rm /tmp/ai-tools-install.sh; \
|
|
19
33
|
fi
|
|
20
34
|
|
|
21
|
-
RUN
|
|
35
|
+
RUN --mount=type=secret,id=HTTP_PROXY \
|
|
36
|
+
--mount=type=secret,id=HTTPS_PROXY \
|
|
37
|
+
--mount=type=secret,id=NO_PROXY \
|
|
38
|
+
export HTTP_PROXY="$(cat /run/secrets/HTTP_PROXY 2>/dev/null || true)" && \
|
|
39
|
+
export HTTPS_PROXY="$(cat /run/secrets/HTTPS_PROXY 2>/dev/null || true)" && \
|
|
40
|
+
export NO_PROXY="$(cat /run/secrets/NO_PROXY 2>/dev/null || true)" && \
|
|
41
|
+
export http_proxy="${HTTP_PROXY}" https_proxy="${HTTPS_PROXY}" no_proxy="${NO_PROXY}" && \
|
|
42
|
+
npm install -g pyright
|
|
22
43
|
|
|
23
44
|
RUN mkdir -p /home/devuser/.local/share /home/devuser/.local/state
|
|
24
45
|
|
|
@@ -19,7 +19,14 @@ RUN if [ "${HOST_UID}" = "0" ]; then \
|
|
|
19
19
|
useradd -u ${HOST_UID} -g ${HOST_GID} -m -s /bin/bash devuser; \
|
|
20
20
|
fi
|
|
21
21
|
|
|
22
|
-
RUN
|
|
22
|
+
RUN --mount=type=secret,id=HTTP_PROXY \
|
|
23
|
+
--mount=type=secret,id=HTTPS_PROXY \
|
|
24
|
+
--mount=type=secret,id=NO_PROXY \
|
|
25
|
+
export HTTP_PROXY="$(cat /run/secrets/HTTP_PROXY 2>/dev/null || true)" && \
|
|
26
|
+
export HTTPS_PROXY="$(cat /run/secrets/HTTPS_PROXY 2>/dev/null || true)" && \
|
|
27
|
+
export NO_PROXY="$(cat /run/secrets/NO_PROXY 2>/dev/null || true)" && \
|
|
28
|
+
export http_proxy="${HTTP_PROXY}" https_proxy="${HTTPS_PROXY}" no_proxy="${NO_PROXY}" && \
|
|
29
|
+
apt-get update && apt-get install -y \
|
|
23
30
|
curl wget git vim file jq \
|
|
24
31
|
build-essential ca-certificates gnupg lsb-release \
|
|
25
32
|
libevent-core-2.1-7 libncursesw6 libtinfo6 \
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
RUN
|
|
1
|
+
RUN --mount=type=secret,id=HTTP_PROXY \
|
|
2
|
+
--mount=type=secret,id=HTTPS_PROXY \
|
|
3
|
+
--mount=type=secret,id=NO_PROXY \
|
|
4
|
+
export HTTP_PROXY="$(cat /run/secrets/HTTP_PROXY 2>/dev/null || true)" && \
|
|
5
|
+
export HTTPS_PROXY="$(cat /run/secrets/HTTPS_PROXY 2>/dev/null || true)" && \
|
|
6
|
+
export NO_PROXY="$(cat /run/secrets/NO_PROXY 2>/dev/null || true)" && \
|
|
7
|
+
export http_proxy="${HTTP_PROXY}" https_proxy="${HTTPS_PROXY}" no_proxy="${NO_PROXY}" && \
|
|
8
|
+
apt-get update && apt-get install -y \
|
|
2
9
|
openjdk-17-jdk maven \
|
|
3
10
|
&& rm -rf /var/lib/apt/lists/*
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
RUN
|
|
1
|
+
RUN --mount=type=secret,id=HTTP_PROXY \
|
|
2
|
+
--mount=type=secret,id=HTTPS_PROXY \
|
|
3
|
+
--mount=type=secret,id=NO_PROXY \
|
|
4
|
+
export HTTP_PROXY="$(cat /run/secrets/HTTP_PROXY 2>/dev/null || true)" && \
|
|
5
|
+
export HTTPS_PROXY="$(cat /run/secrets/HTTPS_PROXY 2>/dev/null || true)" && \
|
|
6
|
+
export NO_PROXY="$(cat /run/secrets/NO_PROXY 2>/dev/null || true)" && \
|
|
7
|
+
export http_proxy="${HTTP_PROXY}" https_proxy="${HTTPS_PROXY}" no_proxy="${NO_PROXY}" && \
|
|
8
|
+
apt-get update && apt-get install -y \
|
|
2
9
|
openjdk-21-jdk maven \
|
|
3
10
|
&& rm -rf /var/lib/apt/lists/*
|