@bjoernrochel/sevro 1.0.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +34 -4
- package/README.md +7 -6
- package/dist/examples/basic/graded.json +13 -0
- package/dist/examples/basic/host.js +9 -0
- package/dist/examples/basic/host.js.map +1 -0
- package/dist/examples/basic/prompt-only.json +7 -0
- package/dist/examples/recipes/candidate.js +23 -0
- package/dist/examples/recipes/candidate.js.map +1 -0
- package/dist/examples/recipes/cases/coding-change.json +21 -0
- package/dist/examples/recipes/cases/host-tools.json +21 -0
- package/dist/examples/recipes/cases/mise.json +21 -0
- package/dist/examples/recipes/cases/node.json +21 -0
- package/dist/examples/recipes/cases/python-uv.json +21 -0
- package/dist/examples/recipes/cases/semantic.json +17 -0
- package/dist/examples/recipes/coding-change/check.js +16 -0
- package/dist/examples/recipes/coding-change/check.js.map +1 -0
- package/dist/examples/recipes/executable.js +20 -0
- package/dist/examples/recipes/executable.js.map +1 -0
- package/dist/examples/recipes/extension-artifacts.js +56 -0
- package/dist/examples/recipes/extension-artifacts.js.map +1 -0
- package/dist/examples/recipes/extension-methods.js +167 -0
- package/dist/examples/recipes/extension-methods.js.map +1 -0
- package/dist/examples/recipes/extension.js +28 -0
- package/dist/examples/recipes/extension.js.map +1 -0
- package/dist/examples/recipes/modules.js +9 -0
- package/dist/examples/recipes/modules.js.map +1 -0
- package/dist/examples/recipes/repository-skill/.agents/skills/startup-guide/SKILL.md +7 -0
- package/dist/examples/recipes/repository-skill/.claude/skills/startup-guide/SKILL.md +7 -0
- package/dist/examples/recipes/repository-skill/README.md +3 -0
- package/dist/examples/recipes/run-inputs.js +144 -0
- package/dist/examples/recipes/run-inputs.js.map +1 -0
- package/dist/examples/recipes/run-options.js +103 -0
- package/dist/examples/recipes/run-options.js.map +1 -0
- package/dist/examples/recipes/run.js +62 -0
- package/dist/examples/recipes/run.js.map +1 -0
- package/dist/examples/recipes/runtime/empty.json +1 -0
- package/dist/examples/recipes/runtime/goals.json +1 -0
- package/dist/examples/recipes/runtime/mise.json +6 -0
- package/dist/examples/recipes/runtime/path.json +1 -0
- package/dist/examples/recipes/runtime/plugins.json +4 -0
- package/dist/examples/recipes/runtime/python-uv.json +10 -0
- package/dist/examples/recipes/semantic-judge.js +27 -0
- package/dist/examples/recipes/semantic-judge.js.map +1 -0
- package/dist/examples/templates/coding/adapter.js +14 -0
- package/dist/examples/templates/coding/adapter.js.map +1 -0
- package/dist/examples/templates/coding/case.json +15 -0
- package/dist/examples/templates/repository-skill/.agents/skills/startup-guide/SKILL.md +6 -0
- package/dist/examples/templates/repository-skill/extension-data.js +61 -0
- package/dist/examples/templates/repository-skill/extension-data.js.map +1 -0
- package/dist/examples/templates/repository-skill/extension.js +29 -0
- package/dist/examples/templates/repository-skill/extension.js.map +1 -0
- package/dist/examples/templates/response/adapter.js +13 -0
- package/dist/examples/templates/response/adapter.js.map +1 -0
- package/dist/examples/templates/response/case.json +13 -0
- package/dist/src/advisory.js +86 -0
- package/dist/src/advisory.js.map +1 -0
- package/dist/src/candidate-artifacts.js +139 -0
- package/dist/src/candidate-artifacts.js.map +1 -0
- package/dist/src/candidate-codex-state.js +110 -0
- package/dist/src/candidate-codex-state.js.map +1 -0
- package/dist/src/case-validation.js +92 -0
- package/dist/src/case-validation.js.map +1 -0
- package/dist/src/cli/cancellation.js +21 -0
- package/dist/src/cli/cancellation.js.map +1 -0
- package/dist/src/cli/command.js +60 -0
- package/dist/src/cli/command.js.map +1 -0
- package/dist/src/cli/completion.js +14 -0
- package/dist/src/cli/completion.js.map +1 -0
- package/dist/src/cli/demo.js +45 -0
- package/dist/src/cli/demo.js.map +1 -0
- package/dist/src/cli/evaluation.js +40 -0
- package/dist/src/cli/evaluation.js.map +1 -0
- package/dist/src/cli/extension.js +54 -0
- package/dist/src/cli/extension.js.map +1 -0
- package/dist/src/cli/help.js +190 -0
- package/dist/src/cli/help.js.map +1 -0
- package/dist/src/cli/hosts.js +33 -0
- package/dist/src/cli/hosts.js.map +1 -0
- package/dist/src/cli/init-settings.js +29 -0
- package/dist/src/cli/init-settings.js.map +1 -0
- package/dist/src/cli/init.js +82 -0
- package/dist/src/cli/init.js.map +1 -0
- package/dist/src/cli/invocation.js +431 -0
- package/dist/src/cli/invocation.js.map +1 -0
- package/dist/src/cli/loading.js +110 -0
- package/dist/src/cli/loading.js.map +1 -0
- package/dist/src/cli/preparation.js +88 -0
- package/dist/src/cli/preparation.js.map +1 -0
- package/dist/src/cli/presentation.js +61 -0
- package/dist/src/cli/presentation.js.map +1 -0
- package/dist/src/cli/progress.js +5 -0
- package/dist/src/cli/progress.js.map +1 -0
- package/dist/src/cli/run-manifest.js +108 -0
- package/dist/src/cli/run-manifest.js.map +1 -0
- package/dist/src/cli/run-options.js +367 -0
- package/dist/src/cli/run-options.js.map +1 -0
- package/dist/src/cli/run-overrides.js +51 -0
- package/dist/src/cli/run-overrides.js.map +1 -0
- package/dist/src/cli/settings.js +127 -0
- package/dist/src/cli/settings.js.map +1 -0
- package/dist/src/cli/summary.js +28 -0
- package/dist/src/cli/summary.js.map +1 -0
- package/dist/src/cli.js +20 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/contract-types.js +2 -0
- package/dist/src/contract-types.js.map +1 -0
- package/dist/src/engine.js +4 -0
- package/dist/src/engine.js.map +1 -0
- package/dist/src/evaluation/advisory.js +85 -0
- package/dist/src/evaluation/advisory.js.map +1 -0
- package/dist/src/evaluation/check-plan.js +292 -0
- package/dist/src/evaluation/check-plan.js.map +1 -0
- package/dist/src/evaluation/collection.js +61 -0
- package/dist/src/evaluation/collection.js.map +1 -0
- package/dist/src/evaluation/context.js +2 -0
- package/dist/src/evaluation/context.js.map +1 -0
- package/dist/src/evaluation/grading-host.js +28 -0
- package/dist/src/evaluation/grading-host.js.map +1 -0
- package/dist/src/evaluation/grading.js +154 -0
- package/dist/src/evaluation/grading.js.map +1 -0
- package/dist/src/evaluation/invocation-plan.js +312 -0
- package/dist/src/evaluation/invocation-plan.js.map +1 -0
- package/dist/src/evaluation/plan.js +376 -0
- package/dist/src/evaluation/plan.js.map +1 -0
- package/dist/src/evaluation/progress.js +14 -0
- package/dist/src/evaluation/progress.js.map +1 -0
- package/dist/src/evaluation/resources.js +159 -0
- package/dist/src/evaluation/resources.js.map +1 -0
- package/dist/src/evaluation/run.js +148 -0
- package/dist/src/evaluation/run.js.map +1 -0
- package/dist/src/evaluation/scheduler.js +27 -0
- package/dist/src/evaluation/scheduler.js.map +1 -0
- package/dist/src/evaluation/semantic.js +183 -0
- package/dist/src/evaluation/semantic.js.map +1 -0
- package/dist/src/evaluation/trial.js +593 -0
- package/dist/src/evaluation/trial.js.map +1 -0
- package/dist/src/evaluation/types.js +20 -0
- package/dist/src/evaluation/types.js.map +1 -0
- package/dist/src/evidence/host-results.js +67 -0
- package/dist/src/evidence/host-results.js.map +1 -0
- package/dist/src/evidence/retained-artifacts.js +17 -0
- package/dist/src/evidence/retained-artifacts.js.map +1 -0
- package/dist/src/evidence/trial-writer.js +131 -0
- package/dist/src/evidence/trial-writer.js.map +1 -0
- package/dist/src/evidence/usage.js +14 -0
- package/dist/src/evidence/usage.js.map +1 -0
- package/dist/src/executable.js +20 -0
- package/dist/src/executable.js.map +1 -0
- package/dist/src/extension-client.js +212 -0
- package/dist/src/extension-client.js.map +1 -0
- package/dist/src/extension-session.js +236 -0
- package/dist/src/extension-session.js.map +1 -0
- package/dist/src/fixtures/advisory.js +206 -0
- package/dist/src/fixtures/advisory.js.map +1 -0
- package/dist/src/fixtures/bin.js +41 -0
- package/dist/src/fixtures/bin.js.map +1 -0
- package/dist/src/fixtures/cleanup.js +43 -0
- package/dist/src/fixtures/cleanup.js.map +1 -0
- package/dist/src/fixtures/create.js +94 -0
- package/dist/src/fixtures/create.js.map +1 -0
- package/dist/src/fixtures/generated.js +181 -0
- package/dist/src/fixtures/generated.js.map +1 -0
- package/dist/src/fixtures/git-hooks.js +16 -0
- package/dist/src/fixtures/git-hooks.js.map +1 -0
- package/dist/src/fixtures/preparation.js +201 -0
- package/dist/src/fixtures/preparation.js.map +1 -0
- package/dist/src/fixtures/repository.js +255 -0
- package/dist/src/fixtures/repository.js.map +1 -0
- package/dist/src/fixtures/setup.js +175 -0
- package/dist/src/fixtures/setup.js.map +1 -0
- package/dist/src/fixtures/tools.js +57 -0
- package/dist/src/fixtures/tools.js.map +1 -0
- package/dist/src/fixtures/workspace-state.js +155 -0
- package/dist/src/fixtures/workspace-state.js.map +1 -0
- package/dist/src/generated/cli-result.cjs +2 -0
- package/dist/src/generated/extension.cjs +2 -0
- package/dist/src/generated/report.cjs +2 -0
- package/dist/src/generated/run-evidence.cjs +2 -0
- package/dist/src/generated/runtime.cjs +2 -0
- package/dist/src/git.js +72 -0
- package/dist/src/git.js.map +1 -0
- package/dist/src/graders/artifact.js +68 -0
- package/dist/src/graders/artifact.js.map +1 -0
- package/dist/src/graders/git-head.js +112 -0
- package/dist/src/graders/git-head.js.map +1 -0
- package/dist/src/graders/output.js +345 -0
- package/dist/src/graders/output.js.map +1 -0
- package/dist/src/graders/semantic.js +132 -0
- package/dist/src/graders/semantic.js.map +1 -0
- package/dist/src/graders/shell.js +321 -0
- package/dist/src/graders/shell.js.map +1 -0
- package/dist/src/host-diagnostic-redaction.js +52 -0
- package/dist/src/host-diagnostic-redaction.js.map +1 -0
- package/dist/src/host-diagnostics.js +248 -0
- package/dist/src/host-diagnostics.js.map +1 -0
- package/dist/src/hosts/claude-continuation.js +89 -0
- package/dist/src/hosts/claude-continuation.js.map +1 -0
- package/dist/src/hosts/claude-credential.js +121 -0
- package/dist/src/hosts/claude-credential.js.map +1 -0
- package/dist/src/hosts/claude-events.js +136 -0
- package/dist/src/hosts/claude-events.js.map +1 -0
- package/dist/src/hosts/claude-keychain.js +100 -0
- package/dist/src/hosts/claude-keychain.js.map +1 -0
- package/dist/src/hosts/claude-login-recovery.js +67 -0
- package/dist/src/hosts/claude-login-recovery.js.map +1 -0
- package/dist/src/hosts/claude-login-refresh.js +146 -0
- package/dist/src/hosts/claude-login-refresh.js.map +1 -0
- package/dist/src/hosts/claude-login-store.js +124 -0
- package/dist/src/hosts/claude-login-store.js.map +1 -0
- package/dist/src/hosts/claude-login.js +74 -0
- package/dist/src/hosts/claude-login.js.map +1 -0
- package/dist/src/hosts/claude-native-goal.js +138 -0
- package/dist/src/hosts/claude-native-goal.js.map +1 -0
- package/dist/src/hosts/claude-process.js +10 -0
- package/dist/src/hosts/claude-process.js.map +1 -0
- package/dist/src/hosts/claude-refresh-lock.js +76 -0
- package/dist/src/hosts/claude-refresh-lock.js.map +1 -0
- package/dist/src/hosts/claude-repository-invocation.js +229 -0
- package/dist/src/hosts/claude-repository-invocation.js.map +1 -0
- package/dist/src/hosts/claude-settings.js +158 -0
- package/dist/src/hosts/claude-settings.js.map +1 -0
- package/dist/src/hosts/claude-skill-activations.js +131 -0
- package/dist/src/hosts/claude-skill-activations.js.map +1 -0
- package/dist/src/hosts/claude-state.js +237 -0
- package/dist/src/hosts/claude-state.js.map +1 -0
- package/dist/src/hosts/claude-tool-calls.js +150 -0
- package/dist/src/hosts/claude-tool-calls.js.map +1 -0
- package/dist/src/hosts/claude.js +373 -0
- package/dist/src/hosts/claude.js.map +1 -0
- package/dist/src/hosts/codex-app-server.js +764 -0
- package/dist/src/hosts/codex-app-server.js.map +1 -0
- package/dist/src/hosts/codex-configuration.js +91 -0
- package/dist/src/hosts/codex-configuration.js.map +1 -0
- package/dist/src/hosts/codex-events.js +104 -0
- package/dist/src/hosts/codex-events.js.map +1 -0
- package/dist/src/hosts/codex-exec-controls.js +434 -0
- package/dist/src/hosts/codex-exec-controls.js.map +1 -0
- package/dist/src/hosts/codex-invocation.js +54 -0
- package/dist/src/hosts/codex-invocation.js.map +1 -0
- package/dist/src/hosts/codex-marketplace.js +185 -0
- package/dist/src/hosts/codex-marketplace.js.map +1 -0
- package/dist/src/hosts/codex-native-calls.js +516 -0
- package/dist/src/hosts/codex-native-calls.js.map +1 -0
- package/dist/src/hosts/codex-process.js +10 -0
- package/dist/src/hosts/codex-process.js.map +1 -0
- package/dist/src/hosts/codex-profile.js +206 -0
- package/dist/src/hosts/codex-profile.js.map +1 -0
- package/dist/src/hosts/codex-session-files.js +89 -0
- package/dist/src/hosts/codex-session-files.js.map +1 -0
- package/dist/src/hosts/codex-state.js +310 -0
- package/dist/src/hosts/codex-state.js.map +1 -0
- package/dist/src/hosts/codex.js +527 -0
- package/dist/src/hosts/codex.js.map +1 -0
- package/dist/src/hosts/isolation-common.js +43 -0
- package/dist/src/hosts/isolation-common.js.map +1 -0
- package/dist/src/hosts/isolation-roots.js +64 -0
- package/dist/src/hosts/isolation-roots.js.map +1 -0
- package/dist/src/hosts/isolation.js +12 -0
- package/dist/src/hosts/isolation.js.map +1 -0
- package/dist/src/hosts/linux-sandbox.js +127 -0
- package/dist/src/hosts/linux-sandbox.js.map +1 -0
- package/dist/src/hosts/mac-sandbox.js +137 -0
- package/dist/src/hosts/mac-sandbox.js.map +1 -0
- package/dist/src/hosts/native-controls.js +151 -0
- package/dist/src/hosts/native-controls.js.map +1 -0
- package/dist/src/hosts/native-request.js +33 -0
- package/dist/src/hosts/native-request.js.map +1 -0
- package/dist/src/hosts/process-lifecycle.js +167 -0
- package/dist/src/hosts/process-lifecycle.js.map +1 -0
- package/dist/src/hosts/protected-worktrees.js +81 -0
- package/dist/src/hosts/protected-worktrees.js.map +1 -0
- package/dist/src/hosts/skill-hook-catalog.js +100 -0
- package/dist/src/hosts/skill-hook-catalog.js.map +1 -0
- package/dist/src/hosts/skill-hook-handler.js +228 -0
- package/dist/src/hosts/skill-hook-handler.js.map +1 -0
- package/dist/src/hosts/skill-hooks.js +423 -0
- package/dist/src/hosts/skill-hooks.js.map +1 -0
- package/dist/src/hosts/workspace-fingerprint.js +72 -0
- package/dist/src/hosts/workspace-fingerprint.js.map +1 -0
- package/dist/src/identity.js +167 -0
- package/dist/src/identity.js.map +1 -0
- package/dist/src/instrumentation.js +83 -0
- package/dist/src/instrumentation.js.map +1 -0
- package/dist/src/native-transcript-state.js +85 -0
- package/dist/src/native-transcript-state.js.map +1 -0
- package/dist/src/native-transcript-view.js +65 -0
- package/dist/src/native-transcript-view.js.map +1 -0
- package/dist/src/native-transcripts.js +208 -0
- package/dist/src/native-transcripts.js.map +1 -0
- package/dist/src/paths.js +13 -0
- package/dist/src/paths.js.map +1 -0
- package/dist/src/process-lifecycle.js +101 -0
- package/dist/src/process-lifecycle.js.map +1 -0
- package/dist/src/provenance.js +263 -0
- package/dist/src/provenance.js.map +1 -0
- package/dist/src/prune.js +228 -0
- package/dist/src/prune.js.map +1 -0
- package/dist/src/report.js +276 -0
- package/dist/src/report.js.map +1 -0
- package/dist/src/resolved-case.js +29 -0
- package/dist/src/resolved-case.js.map +1 -0
- package/dist/src/results-lock.js +40 -0
- package/dist/src/results-lock.js.map +1 -0
- package/dist/src/results.js +127 -0
- package/dist/src/results.js.map +1 -0
- package/dist/src/run-owner.js +283 -0
- package/dist/src/run-owner.js.map +1 -0
- package/dist/src/runner-paths.js +11 -0
- package/dist/src/runner-paths.js.map +1 -0
- package/dist/src/runtime/config.js +323 -0
- package/dist/src/runtime/config.js.map +1 -0
- package/dist/src/runtime/discovery-apple.js +65 -0
- package/dist/src/runtime/discovery-apple.js.map +1 -0
- package/dist/src/runtime/discovery-providers.js +37 -0
- package/dist/src/runtime/discovery-providers.js.map +1 -0
- package/dist/src/runtime/discovery.js +40 -0
- package/dist/src/runtime/discovery.js.map +1 -0
- package/dist/src/runtime/hook-processes.js +81 -0
- package/dist/src/runtime/hook-processes.js.map +1 -0
- package/dist/src/runtime/hooks.js +304 -0
- package/dist/src/runtime/hooks.js.map +1 -0
- package/dist/src/runtime/paths.js +244 -0
- package/dist/src/runtime/paths.js.map +1 -0
- package/dist/src/runtime/query.js +76 -0
- package/dist/src/runtime/query.js.map +1 -0
- package/dist/src/runtime/seeds.js +98 -0
- package/dist/src/runtime/seeds.js.map +1 -0
- package/dist/src/runtime/shared-cache.js +81 -0
- package/dist/src/runtime/shared-cache.js.map +1 -0
- package/dist/src/runtime/state.js +106 -0
- package/dist/src/runtime/state.js.map +1 -0
- package/dist/src/runtime-process.js +148 -0
- package/dist/src/runtime-process.js.map +1 -0
- package/dist/src/schema-types.js +2 -0
- package/dist/src/schema-types.js.map +1 -0
- package/dist/src/schema.js +16 -0
- package/dist/src/schema.js.map +1 -0
- package/dist/src/shell.js +5 -0
- package/dist/src/shell.js.map +1 -0
- package/dist/src/sqlite-lock.js +18 -0
- package/dist/src/sqlite-lock.js.map +1 -0
- package/dist/src/storage.js +21 -0
- package/dist/src/storage.js.map +1 -0
- package/dist/src/transcript-retention.js +109 -0
- package/dist/src/transcript-retention.js.map +1 -0
- package/dist/src/value-guards.js +26 -0
- package/dist/src/value-guards.js.map +1 -0
- package/docs/architecture.md +5 -2
- package/docs/creating-cases.md +2 -3
- package/docs/development-cli.md +12 -7
- package/docs/documentation-quality.md +4 -3
- package/docs/evaluation-workflow.md +8 -8
- package/docs/getting-started.md +7 -6
- package/docs/guide-evaluation.md +1 -1
- package/docs/identity-v1.md +4 -1
- package/docs/installing.md +31 -13
- package/docs/licensing.md +2 -2
- package/docs/native-hosts.md +1 -1
- package/docs/recipes.md +41 -40
- package/docs/releases.md +20 -4
- package/docs/run-settings-v1.md +3 -3
- package/docs/specs/repository-guide.md +1 -1
- package/docs/troubleshooting.md +1 -1
- package/docs/typescript-quality.md +18 -1
- package/examples/recipes/executable.ts +19 -0
- package/examples/recipes/extension-artifacts.ts +1 -1
- package/examples/recipes/extension.ts +2 -1
- package/examples/recipes/modules.ts +9 -0
- package/examples/recipes/run-inputs.ts +14 -19
- package/examples/recipes/run-options.ts +9 -8
- package/examples/recipes/run.ts +21 -7
- package/examples/templates/repository-skill/extension-data.ts +1 -1
- package/examples/templates/repository-skill/extension.ts +2 -1
- package/package.json +14 -6
- package/src/cli/demo.ts +3 -2
- package/src/cli/help.ts +4 -3
- package/src/cli/init-settings.ts +5 -4
- package/src/cli/init.ts +9 -8
- package/src/cli/invocation.ts +2 -1
- package/src/cli/preparation.ts +2 -2
- package/src/cli.ts +1 -1
- package/src/executable.ts +19 -0
- package/src/extension-client.ts +6 -12
- package/src/fixtures/setup.ts +3 -2
- package/src/git.ts +2 -1
- package/src/graders/git-head.ts +3 -2
- package/src/graders/shell.ts +4 -3
- package/src/hosts/claude-keychain.ts +3 -2
- package/src/hosts/claude-login-refresh.ts +3 -2
- package/src/hosts/claude-refresh-lock.ts +2 -1
- package/src/hosts/claude-settings.ts +3 -1
- package/src/hosts/claude.ts +1 -1
- package/src/hosts/isolation-roots.ts +3 -2
- package/src/hosts/process-lifecycle.ts +4 -6
- package/src/hosts/protected-worktrees.ts +2 -1
- package/src/hosts/skill-hook-handler.ts +1 -1
- package/src/hosts/skill-hooks.ts +10 -2
- package/src/provenance.ts +7 -6
- package/src/results-lock.ts +4 -4
- package/src/run-owner.ts +15 -9
- package/src/runner-paths.ts +21 -0
- package/src/runtime/hook-processes.ts +2 -1
- package/src/runtime/hooks.ts +9 -7
- package/src/runtime-process.ts +194 -0
- package/src/sqlite-lock.ts +25 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { isAbsolute, join, sep } from "node:path";
|
|
2
|
+
import { minimalRoots as minimalProtectedRoots } from "../paths.js";
|
|
3
|
+
import { containsControl } from "../value-guards.js";
|
|
4
|
+
import { insideRuntimeRoot, isRuntimeHomeRoot } from "../runtime/paths.js";
|
|
5
|
+
import { workspaceBoundaryException } from "../fixtures/workspace-state.js";
|
|
6
|
+
import { nativeStatePath, nativeStateProtectedRoots, } from "../native-transcript-state.js";
|
|
7
|
+
const LINUX_MINIMAL_READ_ROOTS = [
|
|
8
|
+
"/bin",
|
|
9
|
+
"/sbin",
|
|
10
|
+
"/usr",
|
|
11
|
+
"/etc",
|
|
12
|
+
"/lib",
|
|
13
|
+
"/lib64",
|
|
14
|
+
"/nix/store",
|
|
15
|
+
"/run/current-system/sw",
|
|
16
|
+
];
|
|
17
|
+
function toml(value) {
|
|
18
|
+
if (containsControl(value))
|
|
19
|
+
throw new Error("Codex profile value contains a control character");
|
|
20
|
+
return JSON.stringify(value);
|
|
21
|
+
}
|
|
22
|
+
/** Runner-owned Codex command policy; the Codex parent keeps access to auth. */
|
|
23
|
+
export function codexPermissionProfile(options) {
|
|
24
|
+
if (!/^[a-z][a-z0-9_]*$/.test(options.id))
|
|
25
|
+
throw new Error("invalid Codex permission profile ID");
|
|
26
|
+
if (!validProfilePaths(options))
|
|
27
|
+
throw new Error("Codex profile paths must be absolute and protected");
|
|
28
|
+
const name = options.id;
|
|
29
|
+
return [
|
|
30
|
+
`default_permissions = ${toml(name)}`,
|
|
31
|
+
'approval_policy = "never"',
|
|
32
|
+
"allow_login_shell = false",
|
|
33
|
+
...codexFeatureLines(options.localHttp),
|
|
34
|
+
"",
|
|
35
|
+
"[shell_environment_policy]",
|
|
36
|
+
'inherit = "none"',
|
|
37
|
+
"ignore_default_excludes = false",
|
|
38
|
+
"",
|
|
39
|
+
"[shell_environment_policy.set]",
|
|
40
|
+
...commandEnvironmentLines(options.commandEnvironment, options.executableReadRoots),
|
|
41
|
+
`HOME = ${toml(options.commandHome)}`,
|
|
42
|
+
`TMPDIR = ${toml(options.commandTemp)}`,
|
|
43
|
+
`TMPPREFIX = ${toml(join(options.commandTemp, sep))}`,
|
|
44
|
+
"",
|
|
45
|
+
`[permissions.${name}]`,
|
|
46
|
+
'extends = ":workspace"',
|
|
47
|
+
"",
|
|
48
|
+
`[permissions.${name}.filesystem]`,
|
|
49
|
+
'":root" = "deny"',
|
|
50
|
+
'":minimal" = "read"',
|
|
51
|
+
...(process.platform === "linux"
|
|
52
|
+
? []
|
|
53
|
+
: ['":tmpdir" = "deny"', '":slash_tmp" = "deny"']),
|
|
54
|
+
...minimalProtectedRoots(profileProtectedRoots(options))
|
|
55
|
+
.sort()
|
|
56
|
+
.map((root) => `${toml(root)} = "deny"`),
|
|
57
|
+
...readRootLines(options),
|
|
58
|
+
...(options.nativeWriteRoots ?? []).map((root) => `${toml(root)} = "write"`),
|
|
59
|
+
`${toml(options.commandHome)} = "write"`,
|
|
60
|
+
`${toml(options.commandTemp)} = "write"`,
|
|
61
|
+
...optionalRootLines(options.runtimeWriteRoot, "write"),
|
|
62
|
+
// Override Codex's metadata carveout only for this isolated fixture.
|
|
63
|
+
`${toml(join(options.workspace, ".git"))} = "write"`,
|
|
64
|
+
"",
|
|
65
|
+
`[permissions.${name}.filesystem.":workspace_roots"]`,
|
|
66
|
+
'"." = "write"',
|
|
67
|
+
"",
|
|
68
|
+
`[permissions.${name}.network]`,
|
|
69
|
+
...networkProfile(options.localHttp),
|
|
70
|
+
"",
|
|
71
|
+
].join("\n");
|
|
72
|
+
}
|
|
73
|
+
function codexFeatureLines(localHttp) {
|
|
74
|
+
return [
|
|
75
|
+
"[features]",
|
|
76
|
+
"hooks = false",
|
|
77
|
+
...(localHttp ? ["network_proxy = true"] : []),
|
|
78
|
+
];
|
|
79
|
+
}
|
|
80
|
+
function networkProfile(localHttp) {
|
|
81
|
+
if (!localHttp)
|
|
82
|
+
return ["enabled = false"];
|
|
83
|
+
return [
|
|
84
|
+
"enabled = true",
|
|
85
|
+
"allow_local_binding = true",
|
|
86
|
+
"allow_upstream_proxy = false",
|
|
87
|
+
'domains = { "localhost" = "allow", "127.0.0.1" = "allow", "::1" = "allow" }',
|
|
88
|
+
];
|
|
89
|
+
}
|
|
90
|
+
function profileProtectedRoots(options) {
|
|
91
|
+
const readRoots = profileReadRoots(options);
|
|
92
|
+
const trustedRoots = [
|
|
93
|
+
...readRoots,
|
|
94
|
+
...(options.nativeWriteRoots ?? []),
|
|
95
|
+
...(options.runtimeWriteRoot ? [options.runtimeWriteRoot] : []),
|
|
96
|
+
];
|
|
97
|
+
const baselines = [
|
|
98
|
+
...LINUX_MINIMAL_READ_ROOTS,
|
|
99
|
+
...readRoots,
|
|
100
|
+
...(options.nativeWriteRoots ?? []),
|
|
101
|
+
options.workspace,
|
|
102
|
+
options.commandHome,
|
|
103
|
+
options.commandTemp,
|
|
104
|
+
...(options.runtimeWriteRoot ? [options.runtimeWriteRoot] : []),
|
|
105
|
+
];
|
|
106
|
+
return options.protectedRoots.filter((root) => (!implicitLinuxHomeBoundary(root, readRoots, baselines) ||
|
|
107
|
+
process.platform !== "linux") &&
|
|
108
|
+
!implicitNativeBoundary(root, trustedRoots, baselines) &&
|
|
109
|
+
!implicitWorkspaceBoundary(root, options.workspace, baselines));
|
|
110
|
+
}
|
|
111
|
+
function implicitWorkspaceBoundary(root, workspace, baselines) {
|
|
112
|
+
return (process.platform === "linux" &&
|
|
113
|
+
workspaceBoundaryException(root, workspace).length > 0 &&
|
|
114
|
+
!hasBroaderBaseline(root, root, baselines));
|
|
115
|
+
}
|
|
116
|
+
function implicitNativeBoundary(root, trustedRoots, baselines) {
|
|
117
|
+
const canonicalRoot = nativeStatePath();
|
|
118
|
+
if (!supportedNativeNamespace(canonicalRoot))
|
|
119
|
+
return false;
|
|
120
|
+
const boundary = nativeBoundaryRoot(root, canonicalRoot);
|
|
121
|
+
if (!boundary)
|
|
122
|
+
return false;
|
|
123
|
+
const descendant = trustedRoots.some((read) => insideRuntimeRoot(boundary, read));
|
|
124
|
+
return descendant && !hasBroaderBaseline(root, boundary, baselines);
|
|
125
|
+
}
|
|
126
|
+
function nativeBoundaryRoot(root, canonicalRoot) {
|
|
127
|
+
if (nativeStateProtectedRoots().includes(root))
|
|
128
|
+
return canonicalRoot;
|
|
129
|
+
return insideRuntimeRoot(canonicalRoot, root) ? root : null;
|
|
130
|
+
}
|
|
131
|
+
function hasBroaderBaseline(root, boundary, baselines) {
|
|
132
|
+
return baselines.some((baseline) => insideRuntimeRoot(baseline, boundary) ||
|
|
133
|
+
insideRuntimeRoot(baseline, root));
|
|
134
|
+
}
|
|
135
|
+
function supportedNativeNamespace(root) {
|
|
136
|
+
if (process.platform === "linux")
|
|
137
|
+
return [
|
|
138
|
+
"/var/tmp/sevro-native-private",
|
|
139
|
+
"/private/var/tmp/sevro-native-private",
|
|
140
|
+
].includes(root);
|
|
141
|
+
return (process.platform === "darwin" &&
|
|
142
|
+
/^\/private\/var\/folders\/[^/]+\/[^/]+\/T\/sevro-native-private$/.test(root));
|
|
143
|
+
}
|
|
144
|
+
/** Codex masks deny ancestors after read mounts; the empty-root policy already hides safe HOME ancestors. */
|
|
145
|
+
function implicitLinuxHomeBoundary(root, readRoots, baselines) {
|
|
146
|
+
if (!isRuntimeHomeRoot(root))
|
|
147
|
+
return false;
|
|
148
|
+
const descendant = readRoots.some((read) => insideRuntimeRoot(root, read));
|
|
149
|
+
return (descendant &&
|
|
150
|
+
!baselines.some((baseline) => insideRuntimeRoot(baseline, root)));
|
|
151
|
+
}
|
|
152
|
+
function commandEnvironmentLines(environment = {}, executableReadRoots) {
|
|
153
|
+
const systemPath = environment.PATH ??
|
|
154
|
+
"/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin";
|
|
155
|
+
const path = process.platform === "linux"
|
|
156
|
+
? [...executableReadRoots, systemPath].join(":")
|
|
157
|
+
: systemPath;
|
|
158
|
+
return [
|
|
159
|
+
`PATH = ${toml(path)}`,
|
|
160
|
+
...Object.entries(environment)
|
|
161
|
+
.filter(([name]) => !["PATH", "HOME", "TMPDIR"].includes(name))
|
|
162
|
+
.map(([name, value]) => `${toml(name)} = ${toml(value)}`),
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
function optionalRootLines(root, permission) {
|
|
166
|
+
return root ? [`${toml(root)} = ${toml(permission)}`] : [];
|
|
167
|
+
}
|
|
168
|
+
function readRootLines(options) {
|
|
169
|
+
return profileReadRoots(options)
|
|
170
|
+
.sort()
|
|
171
|
+
.map((path) => `${toml(path)} = "read"`);
|
|
172
|
+
}
|
|
173
|
+
function profileReadRoots(options) {
|
|
174
|
+
const roots = [
|
|
175
|
+
...options.executableReadRoots,
|
|
176
|
+
...(options.runtimeReadRoots ?? []),
|
|
177
|
+
...(options.nativeReadRoots ?? []),
|
|
178
|
+
];
|
|
179
|
+
if (options.pluginReadRoot)
|
|
180
|
+
roots.push(options.pluginReadRoot);
|
|
181
|
+
return [...new Set(roots)];
|
|
182
|
+
}
|
|
183
|
+
function readRoot(path) {
|
|
184
|
+
return isAbsolute(path) && path !== "/";
|
|
185
|
+
}
|
|
186
|
+
function optionalReadRoot(path) {
|
|
187
|
+
return path === undefined || readRoot(path);
|
|
188
|
+
}
|
|
189
|
+
function validProfilePaths(options) {
|
|
190
|
+
const privatePaths = [
|
|
191
|
+
options.workspace,
|
|
192
|
+
options.commandHome,
|
|
193
|
+
options.commandTemp,
|
|
194
|
+
];
|
|
195
|
+
return (privatePaths.every(isAbsolute) &&
|
|
196
|
+
validExecutableRoots(options.executableReadRoots) &&
|
|
197
|
+
optionalReadRoot(options.pluginReadRoot) &&
|
|
198
|
+
validProtectedRoots(options.protectedRoots));
|
|
199
|
+
}
|
|
200
|
+
function validExecutableRoots(paths) {
|
|
201
|
+
return paths.length > 0 && paths.every(readRoot);
|
|
202
|
+
}
|
|
203
|
+
function validProtectedRoots(paths) {
|
|
204
|
+
return paths.length > 0 && paths.every(isAbsolute);
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=codex-profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-profile.js","sourceRoot":"","sources":["codex-profile.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute, join, sep } from \"node:path\";\nimport { minimalRoots as minimalProtectedRoots } from \"../paths\";\nimport { containsControl } from \"../value-guards\";\nimport { insideRuntimeRoot, isRuntimeHomeRoot } from \"../runtime/paths\";\nimport { workspaceBoundaryException } from \"../fixtures/workspace-state\";\nimport {\n nativeStatePath,\n nativeStateProtectedRoots,\n} from \"../native-transcript-state\";\n\nconst LINUX_MINIMAL_READ_ROOTS = [\n \"/bin\",\n \"/sbin\",\n \"/usr\",\n \"/etc\",\n \"/lib\",\n \"/lib64\",\n \"/nix/store\",\n \"/run/current-system/sw\",\n];\n\nfunction toml(value: string): string {\n if (containsControl(value))\n throw new Error(\"Codex profile value contains a control character\");\n return JSON.stringify(value);\n}\n\n/** Runner-owned Codex command policy; the Codex parent keeps access to auth. */\nexport function codexPermissionProfile(options: {\n id: string;\n workspace: string;\n commandHome: string;\n commandTemp: string;\n executableReadRoots: string[];\n pluginReadRoot?: string;\n protectedRoots: string[];\n commandEnvironment?: Record<string, string>;\n runtimeReadRoots?: string[];\n nativeReadRoots?: string[];\n nativeWriteRoots?: string[];\n runtimeWriteRoot?: string;\n localHttp?: boolean;\n}): string {\n if (!/^[a-z][a-z0-9_]*$/.test(options.id))\n throw new Error(\"invalid Codex permission profile ID\");\n if (!validProfilePaths(options))\n throw new Error(\"Codex profile paths must be absolute and protected\");\n const name = options.id;\n return [\n `default_permissions = ${toml(name)}`,\n 'approval_policy = \"never\"',\n \"allow_login_shell = false\",\n ...codexFeatureLines(options.localHttp),\n \"\",\n \"[shell_environment_policy]\",\n 'inherit = \"none\"',\n \"ignore_default_excludes = false\",\n \"\",\n \"[shell_environment_policy.set]\",\n ...commandEnvironmentLines(\n options.commandEnvironment,\n options.executableReadRoots,\n ),\n `HOME = ${toml(options.commandHome)}`,\n `TMPDIR = ${toml(options.commandTemp)}`,\n `TMPPREFIX = ${toml(join(options.commandTemp, sep))}`,\n \"\",\n `[permissions.${name}]`,\n 'extends = \":workspace\"',\n \"\",\n `[permissions.${name}.filesystem]`,\n '\":root\" = \"deny\"',\n '\":minimal\" = \"read\"',\n ...(process.platform === \"linux\"\n ? []\n : ['\":tmpdir\" = \"deny\"', '\":slash_tmp\" = \"deny\"']),\n ...minimalProtectedRoots(profileProtectedRoots(options))\n .sort()\n .map((root) => `${toml(root)} = \"deny\"`),\n ...readRootLines(options),\n ...(options.nativeWriteRoots ?? []).map(\n (root) => `${toml(root)} = \"write\"`,\n ),\n `${toml(options.commandHome)} = \"write\"`,\n `${toml(options.commandTemp)} = \"write\"`,\n ...optionalRootLines(options.runtimeWriteRoot, \"write\"),\n // Override Codex's metadata carveout only for this isolated fixture.\n `${toml(join(options.workspace, \".git\"))} = \"write\"`,\n \"\",\n `[permissions.${name}.filesystem.\":workspace_roots\"]`,\n '\".\" = \"write\"',\n \"\",\n `[permissions.${name}.network]`,\n ...networkProfile(options.localHttp),\n \"\",\n ].join(\"\\n\");\n}\n\nfunction codexFeatureLines(localHttp: boolean | undefined): string[] {\n return [\n \"[features]\",\n \"hooks = false\",\n ...(localHttp ? [\"network_proxy = true\"] : []),\n ];\n}\n\nfunction networkProfile(localHttp: boolean | undefined): string[] {\n if (!localHttp) return [\"enabled = false\"];\n return [\n \"enabled = true\",\n \"allow_local_binding = true\",\n \"allow_upstream_proxy = false\",\n 'domains = { \"localhost\" = \"allow\", \"127.0.0.1\" = \"allow\", \"::1\" = \"allow\" }',\n ];\n}\n\nfunction profileProtectedRoots(\n options: Parameters<typeof codexPermissionProfile>[0],\n): string[] {\n const readRoots = profileReadRoots(options);\n const trustedRoots = [\n ...readRoots,\n ...(options.nativeWriteRoots ?? []),\n ...(options.runtimeWriteRoot ? [options.runtimeWriteRoot] : []),\n ];\n const baselines = [\n ...LINUX_MINIMAL_READ_ROOTS,\n ...readRoots,\n ...(options.nativeWriteRoots ?? []),\n options.workspace,\n options.commandHome,\n options.commandTemp,\n ...(options.runtimeWriteRoot ? [options.runtimeWriteRoot] : []),\n ];\n return options.protectedRoots.filter(\n (root) =>\n (!implicitLinuxHomeBoundary(root, readRoots, baselines) ||\n process.platform !== \"linux\") &&\n !implicitNativeBoundary(root, trustedRoots, baselines) &&\n !implicitWorkspaceBoundary(root, options.workspace, baselines),\n );\n}\n\nfunction implicitWorkspaceBoundary(\n root: string,\n workspace: string,\n baselines: string[],\n): boolean {\n return (\n process.platform === \"linux\" &&\n workspaceBoundaryException(root, workspace).length > 0 &&\n !hasBroaderBaseline(root, root, baselines)\n );\n}\n\nfunction implicitNativeBoundary(\n root: string,\n trustedRoots: string[],\n baselines: string[],\n): boolean {\n const canonicalRoot = nativeStatePath();\n if (!supportedNativeNamespace(canonicalRoot)) return false;\n const boundary = nativeBoundaryRoot(root, canonicalRoot);\n if (!boundary) return false;\n const descendant = trustedRoots.some((read) =>\n insideRuntimeRoot(boundary, read),\n );\n return descendant && !hasBroaderBaseline(root, boundary, baselines);\n}\n\nfunction nativeBoundaryRoot(\n root: string,\n canonicalRoot: string,\n): string | null {\n if (nativeStateProtectedRoots().includes(root)) return canonicalRoot;\n return insideRuntimeRoot(canonicalRoot, root) ? root : null;\n}\n\nfunction hasBroaderBaseline(\n root: string,\n boundary: string,\n baselines: string[],\n): boolean {\n return baselines.some(\n (baseline) =>\n insideRuntimeRoot(baseline, boundary) ||\n insideRuntimeRoot(baseline, root),\n );\n}\n\nfunction supportedNativeNamespace(root: string): boolean {\n if (process.platform === \"linux\")\n return [\n \"/var/tmp/sevro-native-private\",\n \"/private/var/tmp/sevro-native-private\",\n ].includes(root);\n return (\n process.platform === \"darwin\" &&\n /^\\/private\\/var\\/folders\\/[^/]+\\/[^/]+\\/T\\/sevro-native-private$/.test(\n root,\n )\n );\n}\n\n/** Codex masks deny ancestors after read mounts; the empty-root policy already hides safe HOME ancestors. */\nfunction implicitLinuxHomeBoundary(\n root: string,\n readRoots: string[],\n baselines: string[],\n): boolean {\n if (!isRuntimeHomeRoot(root)) return false;\n const descendant = readRoots.some((read) => insideRuntimeRoot(root, read));\n return (\n descendant &&\n !baselines.some((baseline) => insideRuntimeRoot(baseline, root))\n );\n}\n\nfunction commandEnvironmentLines(\n environment: Record<string, string> = {},\n executableReadRoots: string[],\n): string[] {\n const systemPath =\n environment.PATH ??\n \"/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin\";\n const path =\n process.platform === \"linux\"\n ? [...executableReadRoots, systemPath].join(\":\")\n : systemPath;\n return [\n `PATH = ${toml(path)}`,\n ...Object.entries(environment)\n .filter(([name]) => ![\"PATH\", \"HOME\", \"TMPDIR\"].includes(name))\n .map(([name, value]) => `${toml(name)} = ${toml(value)}`),\n ];\n}\n\nfunction optionalRootLines(\n root: string | undefined,\n permission: string,\n): string[] {\n return root ? [`${toml(root)} = ${toml(permission)}`] : [];\n}\n\nfunction readRootLines(\n options: Parameters<typeof codexPermissionProfile>[0],\n): string[] {\n return profileReadRoots(options)\n .sort()\n .map((path) => `${toml(path)} = \"read\"`);\n}\n\nfunction profileReadRoots(\n options: Parameters<typeof codexPermissionProfile>[0],\n): string[] {\n const roots = [\n ...options.executableReadRoots,\n ...(options.runtimeReadRoots ?? []),\n ...(options.nativeReadRoots ?? []),\n ];\n if (options.pluginReadRoot) roots.push(options.pluginReadRoot);\n return [...new Set(roots)];\n}\n\nfunction readRoot(path: string): boolean {\n return isAbsolute(path) && path !== \"/\";\n}\n\nfunction optionalReadRoot(path: string | undefined): boolean {\n return path === undefined || readRoot(path);\n}\n\nfunction validProfilePaths(\n options: Parameters<typeof codexPermissionProfile>[0],\n): boolean {\n const privatePaths = [\n options.workspace,\n options.commandHome,\n options.commandTemp,\n ];\n return (\n privatePaths.every(isAbsolute) &&\n validExecutableRoots(options.executableReadRoots) &&\n optionalReadRoot(options.pluginReadRoot) &&\n validProtectedRoots(options.protectedRoots)\n );\n}\n\nfunction validExecutableRoots(paths: string[]): boolean {\n return paths.length > 0 && paths.every(readRoot);\n}\n\nfunction validProtectedRoots(paths: string[]): boolean {\n return paths.length > 0 && paths.every(isAbsolute);\n}\n"]}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { lstat, readFile, readdir, stat } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { isMissingFile } from "../fixtures/tools.js";
|
|
4
|
+
const MAX_SESSION_BYTES = 8 * 1024 * 1024;
|
|
5
|
+
const MAX_SESSION_FILES = 1024;
|
|
6
|
+
const THREAD_ID = /^[A-Za-z0-9._-]{1,128}$/;
|
|
7
|
+
async function sessionsRootStatus(root) {
|
|
8
|
+
try {
|
|
9
|
+
const entry = await lstat(root);
|
|
10
|
+
return entry.isDirectory() && !entry.isSymbolicLink() ? "valid" : "partial";
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
return isMissingFile(error) ? "unavailable" : "partial";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
class SessionSearch {
|
|
17
|
+
suffix;
|
|
18
|
+
pending;
|
|
19
|
+
matches = [];
|
|
20
|
+
visited = 0;
|
|
21
|
+
constructor(root, suffix) {
|
|
22
|
+
this.suffix = suffix;
|
|
23
|
+
this.pending = [root];
|
|
24
|
+
}
|
|
25
|
+
async run() {
|
|
26
|
+
while (this.pending.length) {
|
|
27
|
+
const directory = this.pending.pop();
|
|
28
|
+
if (directory === undefined)
|
|
29
|
+
break;
|
|
30
|
+
try {
|
|
31
|
+
const status = await this.visitDirectory(directory);
|
|
32
|
+
if (status)
|
|
33
|
+
return { status };
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return { status: "partial" };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const [path] = this.matches;
|
|
40
|
+
return this.location(path);
|
|
41
|
+
}
|
|
42
|
+
location(path) {
|
|
43
|
+
return this.matches.length === 1 && path !== undefined
|
|
44
|
+
? { status: "found", path }
|
|
45
|
+
: { status: "unavailable" };
|
|
46
|
+
}
|
|
47
|
+
async visitDirectory(directory) {
|
|
48
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
49
|
+
for (const entry of entries) {
|
|
50
|
+
const status = this.visitEntry(directory, entry);
|
|
51
|
+
if (status)
|
|
52
|
+
return status;
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
visitEntry(directory, entry) {
|
|
57
|
+
this.visited++;
|
|
58
|
+
if (this.visited > MAX_SESSION_FILES || entry.isSymbolicLink())
|
|
59
|
+
return "partial";
|
|
60
|
+
return this.collectCandidate(directory, entry);
|
|
61
|
+
}
|
|
62
|
+
collectCandidate(directory, entry) {
|
|
63
|
+
const path = join(directory, entry.name);
|
|
64
|
+
if (entry.isDirectory())
|
|
65
|
+
this.pending.push(path);
|
|
66
|
+
else if (entry.isFile() && entry.name.endsWith(this.suffix))
|
|
67
|
+
this.matches.push(path);
|
|
68
|
+
return this.matches.length > 1 ? "ambiguous" : undefined;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Locate exactly one original thread while refusing symlinks and bounded tree overflow. */
|
|
72
|
+
export async function locateNativeSession(home, threadId) {
|
|
73
|
+
if (!THREAD_ID.test(threadId))
|
|
74
|
+
return { status: "partial" };
|
|
75
|
+
const root = join(home, "sessions");
|
|
76
|
+
const status = await sessionsRootStatus(root);
|
|
77
|
+
if (status !== "valid")
|
|
78
|
+
return { status };
|
|
79
|
+
return new SessionSearch(root, `-${threadId}.jsonl`).run();
|
|
80
|
+
}
|
|
81
|
+
export async function readNativeSession(path) {
|
|
82
|
+
if ((await stat(path)).size > MAX_SESSION_BYTES)
|
|
83
|
+
return null;
|
|
84
|
+
const bytes = await readFile(path);
|
|
85
|
+
if (bytes.byteLength > MAX_SESSION_BYTES)
|
|
86
|
+
return null;
|
|
87
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=codex-session-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-session-files.js","sourceRoot":"","sources":["codex-session-files.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,yBAAyB;AAClE,OAAO,EAAE,IAAI,EAAE,kBAAkB;AACjC,OAAO,EAAE,aAAa,EAAE,6BAA0B;AAElD,MAAM,iBAAiB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAC1C,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAC/B,MAAM,SAAS,GAAG,yBAAyB,CAAC;AAK5C,KAAK,UAAU,kBAAkB,CAC/B,IAAY;IAEZ,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;QAChC,OAAO,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1D,CAAC;AACH,CAAC;AAED,MAAM,aAAa;IAMP;IALF,OAAO,CAAW;IAClB,OAAO,GAAa,EAAE,CAAC;IACvB,OAAO,GAAG,CAAC,CAAC;IACpB,YACE,IAAY,EACJ,MAAc;QAAd,WAAM,GAAN,MAAM,CAAQ;QAEtB,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,GAAG;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACrC,IAAI,SAAS,KAAK,SAAS;gBAAE,MAAM;YACnC,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;gBACpD,IAAI,MAAM;oBAAE,OAAO,EAAE,MAAM,EAAE,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;YAC/B,CAAC;QACH,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAEO,QAAQ,CAAC,IAAwB;QACvC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,KAAK,SAAS;YACpD,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;YAC3B,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IAChC,CAAC;IAEO,KAAK,CAAC,cAAc,CAC1B,SAAiB;QAEjB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YACjD,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAC;QAC5B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,UAAU,CAChB,SAAiB,EACjB,KAAa;QAEb,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,IAAI,IAAI,CAAC,OAAO,GAAG,iBAAiB,IAAI,KAAK,CAAC,cAAc,EAAE;YAC5D,OAAO,SAAS,CAAC;QACnB,OAAO,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACjD,CAAC;IAEO,gBAAgB,CACtB,SAAiB,EACjB,KAAa;QAEb,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,KAAK,CAAC,WAAW,EAAE;YAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aAC5C,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;YACzD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,CAAC;CACF;AAED,4FAA4F;AAC5F,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAY,EACZ,QAAgB;IAEhB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAC1C,OAAO,IAAI,aAAa,CAAC,IAAI,EAAE,IAAI,QAAQ,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC;AAC7D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAY;IAClD,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,iBAAiB;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,KAAK,CAAC,UAAU,GAAG,iBAAiB;QAAE,OAAO,IAAI,CAAC;IACtD,OAAO,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACjE,CAAC","sourcesContent":["import type { Dirent } from \"node:fs\";\nimport { lstat, readFile, readdir, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { isMissingFile } from \"../fixtures/tools\";\n\nconst MAX_SESSION_BYTES = 8 * 1024 * 1024;\nconst MAX_SESSION_FILES = 1024;\nconst THREAD_ID = /^[A-Za-z0-9._-]{1,128}$/;\ntype SearchStatus = \"partial\" | \"unavailable\" | \"ambiguous\";\ntype SessionLocation =\n { status: SearchStatus } | { status: \"found\"; path: string };\n\nasync function sessionsRootStatus(\n root: string,\n): Promise<\"valid\" | \"partial\" | \"unavailable\"> {\n try {\n const entry = await lstat(root);\n return entry.isDirectory() && !entry.isSymbolicLink() ? \"valid\" : \"partial\";\n } catch (error) {\n return isMissingFile(error) ? \"unavailable\" : \"partial\";\n }\n}\n\nclass SessionSearch {\n private pending: string[];\n private matches: string[] = [];\n private visited = 0;\n constructor(\n root: string,\n private suffix: string,\n ) {\n this.pending = [root];\n }\n\n async run(): Promise<SessionLocation> {\n while (this.pending.length) {\n const directory = this.pending.pop();\n if (directory === undefined) break;\n try {\n const status = await this.visitDirectory(directory);\n if (status) return { status };\n } catch {\n return { status: \"partial\" };\n }\n }\n const [path] = this.matches;\n return this.location(path);\n }\n\n private location(path: string | undefined): SessionLocation {\n return this.matches.length === 1 && path !== undefined\n ? { status: \"found\", path }\n : { status: \"unavailable\" };\n }\n\n private async visitDirectory(\n directory: string,\n ): Promise<SearchStatus | undefined> {\n const entries = await readdir(directory, { withFileTypes: true });\n for (const entry of entries) {\n const status = this.visitEntry(directory, entry);\n if (status) return status;\n }\n return undefined;\n }\n\n private visitEntry(\n directory: string,\n entry: Dirent,\n ): SearchStatus | undefined {\n this.visited++;\n if (this.visited > MAX_SESSION_FILES || entry.isSymbolicLink())\n return \"partial\";\n return this.collectCandidate(directory, entry);\n }\n\n private collectCandidate(\n directory: string,\n entry: Dirent,\n ): SearchStatus | undefined {\n const path = join(directory, entry.name);\n if (entry.isDirectory()) this.pending.push(path);\n else if (entry.isFile() && entry.name.endsWith(this.suffix))\n this.matches.push(path);\n return this.matches.length > 1 ? \"ambiguous\" : undefined;\n }\n}\n\n/** Locate exactly one original thread while refusing symlinks and bounded tree overflow. */\nexport async function locateNativeSession(\n home: string,\n threadId: string,\n): Promise<SessionLocation> {\n if (!THREAD_ID.test(threadId)) return { status: \"partial\" };\n const root = join(home, \"sessions\");\n const status = await sessionsRootStatus(root);\n if (status !== \"valid\") return { status };\n return new SessionSearch(root, `-${threadId}.jsonl`).run();\n}\n\nexport async function readNativeSession(path: string): Promise<string | null> {\n if ((await stat(path)).size > MAX_SESSION_BYTES) return null;\n const bytes = await readFile(path);\n if (bytes.byteLength > MAX_SESSION_BYTES) return null;\n return new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n}\n"]}
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { runtimeLocalHttpEnabled, runtimeSeedSources } from "../runtime/config.js";
|
|
2
|
+
import { shellQuote } from "../shell.js";
|
|
3
|
+
import { candidateArtifactEnvironment, candidateArtifactReadRoots, } from "../candidate-artifacts.js";
|
|
4
|
+
import { codexStateEnabled, retainCandidateCodexState, } from "../candidate-codex-state.js";
|
|
5
|
+
import { randomUUID } from "node:crypto";
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
import { isMissingFile } from "../fixtures/tools.js";
|
|
8
|
+
import { cp, lstat, mkdir, readFile, realpath, rm, stat, symlink, writeFile, } from "node:fs/promises";
|
|
9
|
+
import { delimiter, dirname, join, sep } from "node:path";
|
|
10
|
+
import { candidateTranscriptEnvironment, candidateTranscriptRoots, } from "../native-transcripts.js";
|
|
11
|
+
import { prepareHookMounts } from "../runtime/hooks.js";
|
|
12
|
+
import { requireNativeHookRoots } from "../native-transcript-state.js";
|
|
13
|
+
import { requireRuntimeReadRoots, runtimeExecutableProtection, } from "../runtime/paths.js";
|
|
14
|
+
import { prepareRuntimeState } from "../runtime/state.js";
|
|
15
|
+
import { sharedCacheDenyRoots, sharedCacheRoots, } from "../runtime/shared-cache.js";
|
|
16
|
+
import { codexPermissionProfile } from "./codex-profile.js";
|
|
17
|
+
import { evaluationProtectedRoots } from "./isolation-roots.js";
|
|
18
|
+
const MAX_AUTH_BYTES = 1024 * 1024;
|
|
19
|
+
async function copyAuth(source, target) {
|
|
20
|
+
let bytes;
|
|
21
|
+
try {
|
|
22
|
+
if ((await stat(source)).size > MAX_AUTH_BYTES)
|
|
23
|
+
throw new Error("Codex auth file exceeds the size limit");
|
|
24
|
+
bytes = await readFile(source);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
throw new Error("Codex auth file is unreadable or oversized", {
|
|
28
|
+
cause: error,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
if (bytes.byteLength > MAX_AUTH_BYTES)
|
|
32
|
+
throw new Error("Codex auth file exceeds the size limit");
|
|
33
|
+
await writeFile(target, bytes, { flag: "wx", mode: 0o600 });
|
|
34
|
+
}
|
|
35
|
+
export async function codexHookMounts(request, state, installedPluginRoots) {
|
|
36
|
+
const hooks = await prepareHookMounts({
|
|
37
|
+
workspace: request.workspace,
|
|
38
|
+
stateRoot: state.stateRoot,
|
|
39
|
+
privateRoot: state.codexHome,
|
|
40
|
+
pluginRoots: installedPluginRoots,
|
|
41
|
+
protectedRoots: state.protectedRoots,
|
|
42
|
+
policy: request.runtimePolicy ?? {
|
|
43
|
+
format: "sevro.runtime.v1",
|
|
44
|
+
environment: {},
|
|
45
|
+
readOnlyRoots: [],
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
for (const [index, root] of installedPluginRoots.entries()) {
|
|
49
|
+
const curated = hooks.directories[index];
|
|
50
|
+
if (!curated)
|
|
51
|
+
throw new Error("Codex hook projection is incomplete");
|
|
52
|
+
await rm(root, { recursive: true });
|
|
53
|
+
await cp(curated, root, { recursive: true });
|
|
54
|
+
}
|
|
55
|
+
await grantCodexHookReads(state, hooks.directories);
|
|
56
|
+
return hooks;
|
|
57
|
+
}
|
|
58
|
+
/** Hooks advertise paths relative to these curated copies, not the install cache. */
|
|
59
|
+
async function grantCodexHookReads(state, roots) {
|
|
60
|
+
if (roots.length === 0)
|
|
61
|
+
return;
|
|
62
|
+
await requireNativeHookRoots(roots, state.codexHome);
|
|
63
|
+
const path = join(state.codexHome, "config.toml");
|
|
64
|
+
const config = await readFile(path, "utf8");
|
|
65
|
+
const header = `[permissions.${state.profileId}.filesystem]\n`;
|
|
66
|
+
const grants = roots
|
|
67
|
+
.map((root) => `${JSON.stringify(root)} = "read"\n`)
|
|
68
|
+
.join("");
|
|
69
|
+
await writeFile(path, config.replace(header, header + grants), {
|
|
70
|
+
mode: 0o600,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
async function privateCodexDirectories(stateRoot) {
|
|
74
|
+
const codexHome = join(stateRoot, "codex-home"), parentHome = join(stateRoot, "home"), parentTemp = join(stateRoot, "tmp"), commandHome = join(stateRoot, "command-home"), commandTemp = join(stateRoot, "command-tmp");
|
|
75
|
+
await Promise.all([codexHome, parentHome, parentTemp, commandHome, commandTemp].map((path) => mkdir(path, { mode: 0o700 })));
|
|
76
|
+
if (process.platform === "linux")
|
|
77
|
+
await mkdir(join(codexHome, "tmp", "arg0"), {
|
|
78
|
+
recursive: true,
|
|
79
|
+
mode: 0o700,
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
codexHome,
|
|
83
|
+
parentHome,
|
|
84
|
+
parentTemp,
|
|
85
|
+
commandHome,
|
|
86
|
+
commandTemp,
|
|
87
|
+
pluginCacheRoot: join(codexHome, "plugins", "cache"),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function requireUnprotectedExecutables(readRoots, protectedRoots) {
|
|
91
|
+
if (readRoots.some((readRoot) => protectedRoots.some((root) => readRoot === root || readRoot.startsWith(`${root}${sep}`))))
|
|
92
|
+
throw new Error("Codex executable resides inside a protected root");
|
|
93
|
+
}
|
|
94
|
+
function concurrencyConfiguration(limit) {
|
|
95
|
+
return limit === null
|
|
96
|
+
? ""
|
|
97
|
+
: `\n[agents]\nmax_concurrent_threads_per_session = ${limit}\n`;
|
|
98
|
+
}
|
|
99
|
+
async function writeCodexProfile(paths, profileId, request, readRoots, protectedRoots, limit, commandEnvironment = request.runtimePolicy?.environment, runtimeWriteRoot, writableCacheRoots) {
|
|
100
|
+
const profile = codexPermissionProfile({
|
|
101
|
+
localHttp: runtimeLocalHttpEnabled(request.runtimePolicy, request.runtimeRole ?? "candidate"),
|
|
102
|
+
commandEnvironment: codexProfileEnvironment(request, paths, commandEnvironment),
|
|
103
|
+
runtimeWriteRoot,
|
|
104
|
+
runtimeReadRoots: request.runtimePolicy?.readOnlyRoots,
|
|
105
|
+
nativeReadRoots: codexNativeReadRoots(request, paths.codexHome),
|
|
106
|
+
nativeWriteRoots: [
|
|
107
|
+
...codexStateWriteRoots(request, paths),
|
|
108
|
+
...writableCacheRoots,
|
|
109
|
+
],
|
|
110
|
+
id: profileId,
|
|
111
|
+
workspace: request.workspace,
|
|
112
|
+
commandHome: paths.commandHome,
|
|
113
|
+
commandTemp: paths.commandTemp,
|
|
114
|
+
executableReadRoots: readRoots,
|
|
115
|
+
...codexPluginReadRoot(request, paths.pluginCacheRoot),
|
|
116
|
+
protectedRoots,
|
|
117
|
+
});
|
|
118
|
+
await writeFile(join(paths.codexHome, "config.toml"), profile +
|
|
119
|
+
concurrencyConfiguration(limit) +
|
|
120
|
+
fixtureTrustConfiguration(request), { flag: "wx", mode: 0o600 });
|
|
121
|
+
}
|
|
122
|
+
function fixtureTrustConfiguration(request) {
|
|
123
|
+
return `\n[projects.${JSON.stringify(request.workspace)}]\ntrust_level = "untrusted"\n`;
|
|
124
|
+
}
|
|
125
|
+
function codexProfileEnvironment(request, paths, environment) {
|
|
126
|
+
return {
|
|
127
|
+
...codexCommandEnvironment(request, environment),
|
|
128
|
+
...codexTranscriptEnvironment(request, paths.codexHome),
|
|
129
|
+
...candidateTranscriptEnvironment(request.candidateTranscriptRoot),
|
|
130
|
+
...candidateArtifactEnvironment(request.candidateArtifactRoots),
|
|
131
|
+
...(request.runtimePolicy?.codexState === true
|
|
132
|
+
? {
|
|
133
|
+
SEVRO_CODEX_AGENT_SKILLS: join(paths.parentHome, ".agents", "skills"),
|
|
134
|
+
}
|
|
135
|
+
: {}),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function codexTranscriptEnvironment(request, home) {
|
|
139
|
+
return {
|
|
140
|
+
...(request.runtimePolicy?.codexState === true ? { CODEX_HOME: home } : {}),
|
|
141
|
+
...(request.runtimePolicy?.nativeTranscripts === true
|
|
142
|
+
? {
|
|
143
|
+
CODEX_HOME: home,
|
|
144
|
+
SEVRO_NATIVE_TRANSCRIPT_ROOT: join(home, "sessions"),
|
|
145
|
+
}
|
|
146
|
+
: {}),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function codexNativeReadRoots(request, home) {
|
|
150
|
+
return [
|
|
151
|
+
...linuxArg0ReadRoots(home),
|
|
152
|
+
...(request.runtimePolicy?.codexState === true
|
|
153
|
+
? [join(home, "config.toml"), join(home, "skills", ".system")]
|
|
154
|
+
: []),
|
|
155
|
+
...codexTranscriptRoots(request, home),
|
|
156
|
+
...candidateTranscriptRoots(request.candidateTranscriptRoot),
|
|
157
|
+
...candidateArtifactReadRoots(request.candidateArtifactRoots),
|
|
158
|
+
];
|
|
159
|
+
}
|
|
160
|
+
function codexTranscriptRoots(request, home) {
|
|
161
|
+
return request.runtimePolicy?.nativeTranscripts === true
|
|
162
|
+
? [join(home, "sessions")]
|
|
163
|
+
: [];
|
|
164
|
+
}
|
|
165
|
+
function linuxArg0ReadRoots(codexHome) {
|
|
166
|
+
return process.platform === "linux" ? [join(codexHome, "tmp", "arg0")] : [];
|
|
167
|
+
}
|
|
168
|
+
function codexPluginReadRoot(request, root) {
|
|
169
|
+
return request.codexMarketplace ? { pluginReadRoot: root } : {};
|
|
170
|
+
}
|
|
171
|
+
function codexHelperBinary(options, sandboxBinary) {
|
|
172
|
+
const sibling = join(dirname(options.binary), "codex-linux-sandbox");
|
|
173
|
+
return (options.sandboxBinary ?? (existsSync(sibling) ? sibling : sandboxBinary));
|
|
174
|
+
}
|
|
175
|
+
function codexCommandEnvironment(request, environment) {
|
|
176
|
+
if (!environment)
|
|
177
|
+
return undefined;
|
|
178
|
+
const path = environment.PATH ??
|
|
179
|
+
"/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin";
|
|
180
|
+
return {
|
|
181
|
+
...environment,
|
|
182
|
+
PATH: [request.fixtureBinDir, path].filter(Boolean).join(delimiter),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
async function fixtureShellRoot(request, parentHome) {
|
|
186
|
+
const root = join(request.workspace, ".git", "sevro-shell");
|
|
187
|
+
if (request.fixtureBinDir) {
|
|
188
|
+
await mkdir(root, { mode: 0o700 });
|
|
189
|
+
await writeFile(process.platform === "linux"
|
|
190
|
+
? join(parentHome, ".bash_profile")
|
|
191
|
+
: join(root, ".zprofile"), `export PATH=${shellQuote(request.fixtureBinDir)}:"$PATH"\n`, { flag: "wx", mode: 0o600 });
|
|
192
|
+
}
|
|
193
|
+
return root;
|
|
194
|
+
}
|
|
195
|
+
function codexPath(fixtureBin) {
|
|
196
|
+
const path = process.env.PATH ?? "/usr/bin:/bin";
|
|
197
|
+
return fixtureBin ? `${fixtureBin}${delimiter}${path}` : path;
|
|
198
|
+
}
|
|
199
|
+
function codexEnvironment(paths, request, shellRoot) {
|
|
200
|
+
return {
|
|
201
|
+
...request.runtimePolicy?.environment,
|
|
202
|
+
PATH: declaredCodexPath(request),
|
|
203
|
+
LANG: process.env.LANG ?? "C",
|
|
204
|
+
HOME: paths.parentHome,
|
|
205
|
+
TMPDIR: paths.parentTemp,
|
|
206
|
+
CODEX_HOME: paths.codexHome,
|
|
207
|
+
NO_COLOR: "1",
|
|
208
|
+
...(request.fixtureBinDir && process.platform === "darwin"
|
|
209
|
+
? { ZDOTDIR: shellRoot }
|
|
210
|
+
: {}),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function declaredCodexPath(request) {
|
|
214
|
+
return (request.runtimePolicy?.environment.PATH ?? codexPath(request.fixtureBinDir));
|
|
215
|
+
}
|
|
216
|
+
function codexSeedSources(request) {
|
|
217
|
+
return runtimeSeedSources(request.runtimePolicy);
|
|
218
|
+
}
|
|
219
|
+
async function codexRuntime(request, paths, stateRoot) {
|
|
220
|
+
if (!request.runtimePolicy)
|
|
221
|
+
return undefined;
|
|
222
|
+
const runtime = await prepareRuntimeState(request.workspace, request.runtimePolicy, request.runtimeRole ?? "candidate", request.candidateRuntimeRoot ?? join(stateRoot, "runtime"));
|
|
223
|
+
paths.commandHome = runtime.home;
|
|
224
|
+
paths.commandTemp = runtime.temp;
|
|
225
|
+
return runtime;
|
|
226
|
+
}
|
|
227
|
+
function applyCodexRuntime(runtime, env, paths) {
|
|
228
|
+
if (runtime)
|
|
229
|
+
Object.assign(env, runtime.environment, {
|
|
230
|
+
HOME: paths.parentHome,
|
|
231
|
+
TMPDIR: paths.parentTemp,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
function codexRuntimeProfile(runtime) {
|
|
235
|
+
return {
|
|
236
|
+
environment: runtime?.environment,
|
|
237
|
+
root: runtime?.root,
|
|
238
|
+
writableCacheRoots: runtime?.writableCacheRoots ?? [],
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
export async function prepareCodexState(stateRoot, options, limit, request, helperRoot) {
|
|
242
|
+
await requireIsolatedGitMetadata(request.workspace);
|
|
243
|
+
const paths = await privateCodexDirectories(stateRoot);
|
|
244
|
+
const runtime = await codexRuntime(request, paths, stateRoot);
|
|
245
|
+
await copyAuth(options.authFile, join(paths.codexHome, "auth.json"));
|
|
246
|
+
const protectedRoots = await evaluationProtectedRoots({
|
|
247
|
+
workspace: request.workspace,
|
|
248
|
+
projectRoot: options.projectRoot,
|
|
249
|
+
resultsRoot: options.resultsRoot,
|
|
250
|
+
additionalRoots: [
|
|
251
|
+
...options.additionalProtectedRoots,
|
|
252
|
+
...(process.platform === "linux" ? [] : [stateRoot]),
|
|
253
|
+
...codexSeedSources(request),
|
|
254
|
+
],
|
|
255
|
+
});
|
|
256
|
+
const sandboxBinary = options.sandboxBinary ?? options.binary;
|
|
257
|
+
const helperBinary = codexHelperBinary(options, sandboxBinary);
|
|
258
|
+
if (helperRoot)
|
|
259
|
+
await symlink(helperBinary, join(helperRoot, "codex-linux-sandbox"));
|
|
260
|
+
const readRoots = await Promise.all([options.binary, sandboxBinary, helperBinary].flatMap((binary) => [
|
|
261
|
+
realpath(dirname(binary)),
|
|
262
|
+
realpath(binary).then(dirname),
|
|
263
|
+
]));
|
|
264
|
+
if (helperRoot)
|
|
265
|
+
readRoots.push(helperRoot);
|
|
266
|
+
requireCodexRuntimeReadRoots(request, protectedRoots);
|
|
267
|
+
await sharedCacheRoots(request.runtimePolicy, request.runtimeRole, protectedRoots);
|
|
268
|
+
protectedRoots.push(...sharedCacheDenyRoots(request.runtimePolicy, request.runtimeRole));
|
|
269
|
+
requireUnprotectedExecutables(readRoots, runtimeExecutableProtection(readRoots, protectedRoots, Boolean(request.runtimePolicy)));
|
|
270
|
+
const profileId = `sevro_${randomUUID().replaceAll("-", "")}`;
|
|
271
|
+
const runtimeProfile = codexRuntimeProfile(runtime);
|
|
272
|
+
await writeCodexProfile(paths, profileId, request, readRoots, protectedRoots, limit, runtimeProfile.environment, runtimeProfile.root, runtimeProfile.writableCacheRoots);
|
|
273
|
+
const shellRoot = await fixtureShellRoot(request, paths.parentHome);
|
|
274
|
+
const env = codexEnvironment(paths, request, shellRoot);
|
|
275
|
+
applyCodexRuntime(runtime, env, paths);
|
|
276
|
+
await prepareCodexStateEvidence(request, stateRoot, paths);
|
|
277
|
+
return { ...paths, stateRoot, sandboxBinary, profileId, env, protectedRoots };
|
|
278
|
+
}
|
|
279
|
+
function codexStateWriteRoots(request, paths) {
|
|
280
|
+
return codexStateEnabled(request.runtimePolicy)
|
|
281
|
+
? [
|
|
282
|
+
join(paths.codexHome, "skills"),
|
|
283
|
+
join(paths.parentHome, ".agents", "skills"),
|
|
284
|
+
join(paths.commandHome, ".agents", "skills"),
|
|
285
|
+
join(paths.commandHome, ".codex", "skills"),
|
|
286
|
+
]
|
|
287
|
+
: [];
|
|
288
|
+
}
|
|
289
|
+
async function prepareCodexStateEvidence(request, stateRoot, paths) {
|
|
290
|
+
if (!codexStateEnabled(request.runtimePolicy))
|
|
291
|
+
return;
|
|
292
|
+
const skillRoots = codexStateWriteRoots(request, paths);
|
|
293
|
+
await Promise.all(skillRoots.map((root) => mkdir(root, { recursive: true, mode: 0o700 })));
|
|
294
|
+
await mkdir(join(paths.codexHome, "skills", ".system"), { mode: 0o700 });
|
|
295
|
+
await retainCandidateCodexState(request.candidateRuntimeRoot, stateRoot, paths);
|
|
296
|
+
}
|
|
297
|
+
async function requireIsolatedGitMetadata(workspace) {
|
|
298
|
+
try {
|
|
299
|
+
if (!(await lstat(join(workspace, ".git"))).isDirectory())
|
|
300
|
+
throw new Error("Codex Git metadata must be an isolated directory");
|
|
301
|
+
}
|
|
302
|
+
catch (cause) {
|
|
303
|
+
if (!isMissingFile(cause))
|
|
304
|
+
throw cause;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
function requireCodexRuntimeReadRoots(request, protectedRoots) {
|
|
308
|
+
requireRuntimeReadRoots(request.runtimePolicy?.readOnlyRoots ?? [], protectedRoots);
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=codex-state.js.map
|