@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,185 @@
|
|
|
1
|
+
import { readFile, readdir, realpath, stat } from "node:fs/promises";
|
|
2
|
+
import { join, relative, sep } from "node:path";
|
|
3
|
+
import { insideRoot as inside } from "../paths.js";
|
|
4
|
+
import { fixtureParts } from "../fixtures/preparation.js";
|
|
5
|
+
import { runCodexProcess } from "./codex-process.js";
|
|
6
|
+
import { isRecord, isUnknownArray } from "../value-guards.js";
|
|
7
|
+
function validPluginNames(declaration) {
|
|
8
|
+
const names = declaration.pluginNames;
|
|
9
|
+
return (/^[a-z][a-z0-9-]*$/.test(declaration.marketplaceName) &&
|
|
10
|
+
names.length > 0 &&
|
|
11
|
+
names.every((name) => /^[a-z][a-z0-9-]*$/.test(name)) &&
|
|
12
|
+
new Set(names).size === names.length);
|
|
13
|
+
}
|
|
14
|
+
function validArtifactPaths(declaration, paths) {
|
|
15
|
+
return (declaration.artifactPaths.length > 0 &&
|
|
16
|
+
paths.size === declaration.artifactPaths.length &&
|
|
17
|
+
declaration.artifactPaths.every((path) => path.startsWith(`${declaration.artifactRoot}/`) &&
|
|
18
|
+
fixtureParts(path).join("/") === path));
|
|
19
|
+
}
|
|
20
|
+
async function marketplaceRoot(workspace, declaration) {
|
|
21
|
+
const paths = new Set(declaration.artifactPaths);
|
|
22
|
+
if (!validPluginNames(declaration) || !validArtifactPaths(declaration, paths))
|
|
23
|
+
throw new Error("invalid Codex marketplace declaration");
|
|
24
|
+
const root = join(workspace, ...fixtureParts(declaration.artifactRoot));
|
|
25
|
+
const actualWorkspace = await realpath(workspace), actualRoot = await realpath(root);
|
|
26
|
+
if (!inside(actualWorkspace, actualRoot) || actualRoot === actualWorkspace)
|
|
27
|
+
throw new Error("Codex marketplace escapes the workspace");
|
|
28
|
+
await verifyMarketplaceManifest(actualRoot, declaration);
|
|
29
|
+
await verifyMaterializedPackage(actualRoot, declaration.artifactRoot, paths);
|
|
30
|
+
return actualRoot;
|
|
31
|
+
}
|
|
32
|
+
function objectRecord(value, message) {
|
|
33
|
+
if (!value || typeof value !== "object")
|
|
34
|
+
throw new Error(message);
|
|
35
|
+
// JSON arrays also have unknown-valued object properties; field validation follows.
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
async function marketplaceManifest(root) {
|
|
39
|
+
let value;
|
|
40
|
+
try {
|
|
41
|
+
value = JSON.parse(await readFile(join(root, ".claude-plugin", "marketplace.json"), "utf8"));
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
throw new Error("Codex marketplace manifest is unreadable", {
|
|
45
|
+
cause: error,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return objectRecord(value, "invalid Codex marketplace manifest");
|
|
49
|
+
}
|
|
50
|
+
async function verifyMarketplaceManifest(root, declaration) {
|
|
51
|
+
const document = await marketplaceManifest(root);
|
|
52
|
+
const plugins = document.plugins;
|
|
53
|
+
if (document.name !== declaration.marketplaceName ||
|
|
54
|
+
!isUnknownArray(plugins) ||
|
|
55
|
+
plugins.length !== declaration.pluginNames.length)
|
|
56
|
+
throw new Error("Codex marketplace manifest does not match declaration");
|
|
57
|
+
const found = new Set();
|
|
58
|
+
for (const entry of plugins)
|
|
59
|
+
await verifyLocalPlugin(entry, declaration.pluginNames, found, root);
|
|
60
|
+
}
|
|
61
|
+
function declaredName(name, names, found) {
|
|
62
|
+
return typeof name === "string" && names.includes(name) && !found.has(name);
|
|
63
|
+
}
|
|
64
|
+
function localSource(source) {
|
|
65
|
+
return typeof source === "string" && source.startsWith("./");
|
|
66
|
+
}
|
|
67
|
+
async function verifyLocalPlugin(entry, names, found, root) {
|
|
68
|
+
const plugin = objectRecord(entry, "invalid Codex marketplace plugin");
|
|
69
|
+
if (!declaredName(plugin.name, names, found) || !localSource(plugin.source))
|
|
70
|
+
throw new Error("Codex marketplace plugin is not a declared local source");
|
|
71
|
+
found.add(plugin.name);
|
|
72
|
+
const source = join(root, ...fixtureParts(plugin.source.slice(2)));
|
|
73
|
+
if (!inside(root, await realpath(source)))
|
|
74
|
+
throw new Error("Codex marketplace plugin escapes its artifact root");
|
|
75
|
+
}
|
|
76
|
+
async function verifyMaterializedPackage(root, artifactRoot, expected) {
|
|
77
|
+
const state = {
|
|
78
|
+
pending: [root],
|
|
79
|
+
seen: new Set(),
|
|
80
|
+
expected,
|
|
81
|
+
root,
|
|
82
|
+
artifactRoot,
|
|
83
|
+
};
|
|
84
|
+
while (state.pending.length) {
|
|
85
|
+
const directory = state.pending.pop();
|
|
86
|
+
if (directory === undefined)
|
|
87
|
+
break;
|
|
88
|
+
for (const entry of await readdir(directory, { withFileTypes: true }))
|
|
89
|
+
verifyPackageEntry(directory, entry, state);
|
|
90
|
+
}
|
|
91
|
+
if (state.seen.size !== expected.size)
|
|
92
|
+
throw new Error("Codex marketplace package is missing declared files");
|
|
93
|
+
}
|
|
94
|
+
function verifyPackageEntry(directory, entry, state) {
|
|
95
|
+
if (entry.isSymbolicLink())
|
|
96
|
+
throw new Error("Codex marketplace package contains a symlink");
|
|
97
|
+
if (entry.isDirectory()) {
|
|
98
|
+
state.pending.push(join(directory, entry.name));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (!entry.isFile())
|
|
102
|
+
throw new Error("Codex marketplace package contains a special file");
|
|
103
|
+
const path = `${state.artifactRoot}/${relative(state.root, join(directory, entry.name)).split(sep).join("/")}`;
|
|
104
|
+
if (!state.expected.has(path))
|
|
105
|
+
throw new Error("Codex marketplace package contains undeclared files");
|
|
106
|
+
state.seen.add(path);
|
|
107
|
+
}
|
|
108
|
+
async function pluginCommand(context, args) {
|
|
109
|
+
const result = await runCodexProcess({
|
|
110
|
+
diagnostics: context.diagnostics,
|
|
111
|
+
argv: [context.binary, "plugin", ...args, "--json"],
|
|
112
|
+
cwd: context.request.workspace,
|
|
113
|
+
env: context.env,
|
|
114
|
+
timeoutMs: 30_000,
|
|
115
|
+
signal: context.request.signal,
|
|
116
|
+
});
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
export async function installCodexPlugins(context) {
|
|
120
|
+
const declaration = context.request.codexMarketplace;
|
|
121
|
+
if (!declaration)
|
|
122
|
+
return [];
|
|
123
|
+
context.diagnostics.stage = "marketplace-validation";
|
|
124
|
+
const root = await marketplaceRoot(context.request.workspace, declaration);
|
|
125
|
+
context.diagnostics.stage = "marketplace-install";
|
|
126
|
+
const added = await pluginCommand(context, ["marketplace", "add", root]);
|
|
127
|
+
if (added.code !== 0)
|
|
128
|
+
throw new Error("Codex local marketplace installation failed");
|
|
129
|
+
const installed = [];
|
|
130
|
+
for (const plugin of declaration.pluginNames)
|
|
131
|
+
installed.push(await installPlugin(context, declaration, plugin));
|
|
132
|
+
return installed;
|
|
133
|
+
}
|
|
134
|
+
async function installPlugin(context, declaration, pluginName) {
|
|
135
|
+
context.diagnostics.stage = "plugin-install";
|
|
136
|
+
const installed = await pluginCommand(context, [
|
|
137
|
+
"add",
|
|
138
|
+
`${pluginName}@${declaration.marketplaceName}`,
|
|
139
|
+
]);
|
|
140
|
+
if (installed.code !== 0)
|
|
141
|
+
throw new Error("Codex local plugin installation failed");
|
|
142
|
+
context.diagnostics.stage = "plugin-receipt";
|
|
143
|
+
const path = await installedPluginPath(installed.out, declaration.marketplaceName, pluginName, context.pluginCacheRoot);
|
|
144
|
+
await verifyInstalledInvocation(context.request, pluginName, path);
|
|
145
|
+
return path;
|
|
146
|
+
}
|
|
147
|
+
function installationReceipt(text) {
|
|
148
|
+
let value;
|
|
149
|
+
try {
|
|
150
|
+
value = JSON.parse(text);
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
throw new Error("Codex plugin installation receipt is invalid", {
|
|
154
|
+
cause: error,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if (!isRecord(value))
|
|
158
|
+
throw new Error("Codex plugin installation receipt is invalid");
|
|
159
|
+
return value;
|
|
160
|
+
}
|
|
161
|
+
function matchingReceipt(receipt, marketplace, plugin, path) {
|
|
162
|
+
return (receipt.name === plugin &&
|
|
163
|
+
receipt.marketplaceName === marketplace &&
|
|
164
|
+
path !== null);
|
|
165
|
+
}
|
|
166
|
+
async function installedPluginPath(text, marketplace, plugin, cache) {
|
|
167
|
+
const receipt = installationReceipt(text);
|
|
168
|
+
const path = typeof receipt.installedPath === "string"
|
|
169
|
+
? await realpath(receipt.installedPath)
|
|
170
|
+
: null;
|
|
171
|
+
if (!matchingReceipt(receipt, marketplace, plugin, path) ||
|
|
172
|
+
path === null ||
|
|
173
|
+
!inside(await realpath(cache), path))
|
|
174
|
+
throw new Error("Codex plugin installation receipt is invalid");
|
|
175
|
+
return path;
|
|
176
|
+
}
|
|
177
|
+
async function verifyInstalledInvocation(request, plugin, path) {
|
|
178
|
+
const selected = request.explicitSkillInvocation;
|
|
179
|
+
if (selected?.pluginName !== plugin)
|
|
180
|
+
return;
|
|
181
|
+
const skill = await stat(join(path, "skills", selected.skillName, "SKILL.md")).catch(() => null);
|
|
182
|
+
if (!skill?.isFile())
|
|
183
|
+
throw new Error("invoked Codex skill is absent from the installation");
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=codex-marketplace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-marketplace.js","sourceRoot":"","sources":["codex-marketplace.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Dirent } from \"node:fs\";\nimport { readFile, readdir, realpath, stat } from \"node:fs/promises\";\nimport { join, relative, sep } from \"node:path\";\nimport { insideRoot as inside } from \"../paths\";\nimport { fixtureParts } from \"../fixtures/preparation\";\nimport type { HostAdapter } from \"../engine\";\nimport { runCodexProcess } from \"./codex-process\";\nimport { isRecord, isUnknownArray } from \"../value-guards\";\nimport type { HostDiagnostics } from \"../host-diagnostics\";\ntype Request = Parameters<HostAdapter[\"run\"]>[0];\ntype Declaration = NonNullable<Request[\"codexMarketplace\"]>;\ninterface InstallContext {\n binary: string;\n env: Record<string, string>;\n pluginCacheRoot: string;\n request: Request;\n diagnostics: HostDiagnostics;\n}\n\nfunction validPluginNames(declaration: Declaration): boolean {\n const names = declaration.pluginNames;\n return (\n /^[a-z][a-z0-9-]*$/.test(declaration.marketplaceName) &&\n names.length > 0 &&\n names.every((name) => /^[a-z][a-z0-9-]*$/.test(name)) &&\n new Set(names).size === names.length\n );\n}\nfunction validArtifactPaths(\n declaration: Declaration,\n paths: Set<string>,\n): boolean {\n return (\n declaration.artifactPaths.length > 0 &&\n paths.size === declaration.artifactPaths.length &&\n declaration.artifactPaths.every(\n (path) =>\n path.startsWith(`${declaration.artifactRoot}/`) &&\n fixtureParts(path).join(\"/\") === path,\n )\n );\n}\n\nasync function marketplaceRoot(\n workspace: string,\n declaration: Declaration,\n): Promise<string> {\n const paths = new Set(declaration.artifactPaths);\n if (!validPluginNames(declaration) || !validArtifactPaths(declaration, paths))\n throw new Error(\"invalid Codex marketplace declaration\");\n const root = join(workspace, ...fixtureParts(declaration.artifactRoot));\n const actualWorkspace = await realpath(workspace),\n actualRoot = await realpath(root);\n if (!inside(actualWorkspace, actualRoot) || actualRoot === actualWorkspace)\n throw new Error(\"Codex marketplace escapes the workspace\");\n await verifyMarketplaceManifest(actualRoot, declaration);\n await verifyMaterializedPackage(actualRoot, declaration.artifactRoot, paths);\n return actualRoot;\n}\n\nfunction objectRecord(\n value: unknown,\n message: string,\n): Record<string, unknown> {\n if (!value || typeof value !== \"object\") throw new Error(message);\n // JSON arrays also have unknown-valued object properties; field validation follows.\n return value as Record<string, unknown>;\n}\nasync function marketplaceManifest(\n root: string,\n): Promise<Record<string, unknown>> {\n let value: unknown;\n try {\n value = JSON.parse(\n await readFile(join(root, \".claude-plugin\", \"marketplace.json\"), \"utf8\"),\n );\n } catch (error) {\n throw new Error(\"Codex marketplace manifest is unreadable\", {\n cause: error,\n });\n }\n return objectRecord(value, \"invalid Codex marketplace manifest\");\n}\nasync function verifyMarketplaceManifest(\n root: string,\n declaration: Declaration,\n): Promise<void> {\n const document = await marketplaceManifest(root);\n const plugins = document.plugins;\n if (\n document.name !== declaration.marketplaceName ||\n !isUnknownArray(plugins) ||\n plugins.length !== declaration.pluginNames.length\n )\n throw new Error(\"Codex marketplace manifest does not match declaration\");\n const found = new Set<string>();\n for (const entry of plugins)\n await verifyLocalPlugin(entry, declaration.pluginNames, found, root);\n}\nfunction declaredName(\n name: unknown,\n names: string[],\n found: Set<string>,\n): name is string {\n return typeof name === \"string\" && names.includes(name) && !found.has(name);\n}\nfunction localSource(source: unknown): source is string {\n return typeof source === \"string\" && source.startsWith(\"./\");\n}\nasync function verifyLocalPlugin(\n entry: unknown,\n names: string[],\n found: Set<string>,\n root: string,\n): Promise<void> {\n const plugin = objectRecord(entry, \"invalid Codex marketplace plugin\");\n if (!declaredName(plugin.name, names, found) || !localSource(plugin.source))\n throw new Error(\"Codex marketplace plugin is not a declared local source\");\n found.add(plugin.name);\n const source = join(root, ...fixtureParts(plugin.source.slice(2)));\n if (!inside(root, await realpath(source)))\n throw new Error(\"Codex marketplace plugin escapes its artifact root\");\n}\n\ninterface PackageState {\n pending: string[];\n seen: Set<string>;\n expected: Set<string>;\n root: string;\n artifactRoot: string;\n}\nasync function verifyMaterializedPackage(\n root: string,\n artifactRoot: string,\n expected: Set<string>,\n): Promise<void> {\n const state: PackageState = {\n pending: [root],\n seen: new Set(),\n expected,\n root,\n artifactRoot,\n };\n while (state.pending.length) {\n const directory = state.pending.pop();\n if (directory === undefined) break;\n for (const entry of await readdir(directory, { withFileTypes: true }))\n verifyPackageEntry(directory, entry, state);\n }\n if (state.seen.size !== expected.size)\n throw new Error(\"Codex marketplace package is missing declared files\");\n}\nfunction verifyPackageEntry(\n directory: string,\n entry: Dirent,\n state: PackageState,\n): void {\n if (entry.isSymbolicLink())\n throw new Error(\"Codex marketplace package contains a symlink\");\n if (entry.isDirectory()) {\n state.pending.push(join(directory, entry.name));\n return;\n }\n if (!entry.isFile())\n throw new Error(\"Codex marketplace package contains a special file\");\n const path = `${state.artifactRoot}/${relative(state.root, join(directory, entry.name)).split(sep).join(\"/\")}`;\n if (!state.expected.has(path))\n throw new Error(\"Codex marketplace package contains undeclared files\");\n state.seen.add(path);\n}\n\nasync function pluginCommand(context: InstallContext, args: string[]) {\n const result = await runCodexProcess({\n diagnostics: context.diagnostics,\n argv: [context.binary, \"plugin\", ...args, \"--json\"],\n cwd: context.request.workspace,\n env: context.env,\n timeoutMs: 30_000,\n signal: context.request.signal,\n });\n return result;\n}\nexport async function installCodexPlugins(\n context: InstallContext,\n): Promise<string[]> {\n const declaration = context.request.codexMarketplace;\n if (!declaration) return [];\n context.diagnostics.stage = \"marketplace-validation\";\n const root = await marketplaceRoot(context.request.workspace, declaration);\n context.diagnostics.stage = \"marketplace-install\";\n const added = await pluginCommand(context, [\"marketplace\", \"add\", root]);\n if (added.code !== 0)\n throw new Error(\"Codex local marketplace installation failed\");\n const installed: string[] = [];\n for (const plugin of declaration.pluginNames)\n installed.push(await installPlugin(context, declaration, plugin));\n return installed;\n}\nasync function installPlugin(\n context: InstallContext,\n declaration: Declaration,\n pluginName: string,\n): Promise<string> {\n context.diagnostics.stage = \"plugin-install\";\n const installed = await pluginCommand(context, [\n \"add\",\n `${pluginName}@${declaration.marketplaceName}`,\n ]);\n if (installed.code !== 0)\n throw new Error(\"Codex local plugin installation failed\");\n context.diagnostics.stage = \"plugin-receipt\";\n const path = await installedPluginPath(\n installed.out,\n declaration.marketplaceName,\n pluginName,\n context.pluginCacheRoot,\n );\n await verifyInstalledInvocation(context.request, pluginName, path);\n return path;\n}\nfunction installationReceipt(text: string): Record<string, unknown> {\n let value: unknown;\n try {\n value = JSON.parse(text);\n } catch (error) {\n throw new Error(\"Codex plugin installation receipt is invalid\", {\n cause: error,\n });\n }\n if (!isRecord(value))\n throw new Error(\"Codex plugin installation receipt is invalid\");\n return value;\n}\nfunction matchingReceipt(\n receipt: Record<string, unknown>,\n marketplace: string,\n plugin: string,\n path: string | null,\n): boolean {\n return (\n receipt.name === plugin &&\n receipt.marketplaceName === marketplace &&\n path !== null\n );\n}\nasync function installedPluginPath(\n text: string,\n marketplace: string,\n plugin: string,\n cache: string,\n): Promise<string> {\n const receipt = installationReceipt(text);\n const path =\n typeof receipt.installedPath === \"string\"\n ? await realpath(receipt.installedPath)\n : null;\n if (\n !matchingReceipt(receipt, marketplace, plugin, path) ||\n path === null ||\n !inside(await realpath(cache), path)\n )\n throw new Error(\"Codex plugin installation receipt is invalid\");\n return path;\n}\nasync function verifyInstalledInvocation(\n request: Request,\n plugin: string,\n path: string,\n): Promise<void> {\n const selected = request.explicitSkillInvocation;\n if (selected?.pluginName !== plugin) return;\n const skill = await stat(\n join(path, \"skills\", selected.skillName, \"SKILL.md\"),\n ).catch(() => null);\n if (!skill?.isFile())\n throw new Error(\"invoked Codex skill is absent from the installation\");\n}\n"]}
|