@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 @@
|
|
|
1
|
+
{"version":3,"file":"claude-repository-invocation.js","sourceRoot":"","sources":["claude-repository-invocation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Stats } from \"node:fs\";\nimport { lstat, readFile, realpath } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { HostAdapter } from \"../engine\";\nimport { isRecord } from \"../value-guards\";\nimport type { ClaudeToolCallsObservation } from \"./claude-tool-calls\";\nimport { parseClaudeEvents, type ClaudeEvents } from \"./claude-events\";\n\ntype Entry = Record<string, unknown>;\nexport interface ClaudeRepositoryInvocation {\n skillName: string;\n skillDir: string;\n skillText: string;\n prompt: string;\n}\n\nfunction entries(text: string | ClaudeEvents): Entry[] {\n return parseClaudeEvents(text).lines.map((line) => {\n if (!line.parsed) throw line.error;\n if (!isRecord(line.value)) throw new Error(\"invalid Claude session entry\");\n return line.value;\n });\n}\n\nfunction content(entry: Entry): string {\n const blocks = isRecord(entry.message) ? entry.message.content : null;\n if (typeof blocks === \"string\") return blocks;\n if (!Array.isArray(blocks)) return \"\";\n return blocks\n .filter(isRecord)\n .filter((block) => block.type === \"text\")\n .map((block) => (typeof block.text === \"string\" ? block.text : \"\"))\n .join(\"\\n\");\n}\n\n/** Validate the native project mount before candidate execution. */\nexport async function verifyClaudeRepositoryInvocation(\n request: Parameters<HostAdapter[\"run\"]>[0],\n): Promise<ClaudeRepositoryInvocation> {\n const selected = request.explicitSkillInvocation;\n requireRepositorySelection(selected);\n const { skillName, token } = selected;\n if (!validRepositoryDeclaration(skillName, token, request.prompt))\n throw new Error(\"invalid Claude repository skill invocation\");\n let path = await realpath(request.workspace);\n for (const [index, part] of [\n \".claude\",\n \"skills\",\n skillName,\n \"SKILL.md\",\n ].entries()) {\n path = join(path, part);\n const entry = await lstat(path).catch(() => null);\n if (!safeSkillEntry(entry, index))\n throw new Error(\n \"invoked Claude repository skill is unavailable or unsafe\",\n );\n }\n return {\n skillName,\n skillDir: join(path, \"..\"),\n skillText: await readFile(path, \"utf8\"),\n prompt: request.prompt,\n };\n}\n\nfunction requireRepositorySelection(\n selected: Parameters<HostAdapter[\"run\"]>[0][\"explicitSkillInvocation\"],\n): asserts selected is Extract<\n NonNullable<Parameters<HostAdapter[\"run\"]>[0][\"explicitSkillInvocation\"]>,\n { scope: \"repository\" }\n> {\n if (!selected || selected.scope !== \"repository\")\n throw new Error(\"Claude repository invocation is not declared\");\n}\n\ntype Receipt = { accepted: boolean | null; reason: string };\ntype MatchInput = ClaudeRepositoryInvocation & {\n transcript: string;\n sessionId: string;\n};\ntype AssistantBoundary = { before: Entry[] } | { receipt: Receipt };\ntype CommandBoundary = { called: Entry } | { receipt: Receipt };\n\nfunction validRepositoryDeclaration(\n skillName: string,\n token: string,\n prompt: string,\n): boolean {\n return (\n validRepositorySkillName(skillName) &&\n token === `/${skillName}` &&\n prompt.split(token).length - 1 === 1 &&\n repositoryPromptMatches(prompt, token)\n );\n}\nfunction validRepositorySkillName(name: string): boolean {\n return /^[A-Za-z0-9._-]+$/.test(name) && ![\".\", \"..\"].includes(name);\n}\nfunction repositoryPromptMatches(prompt: string, token: string): boolean {\n return (\n prompt === token ||\n prompt.startsWith(token + \" \") ||\n prompt.startsWith(token + \"\\n\")\n );\n}\nfunction safeSkillEntry(entry: Stats | null, index: number): boolean {\n if (!entry || entry.isSymbolicLink()) return false;\n return index === 3\n ? entry.isFile() && entry.size <= 1024 * 1024\n : entry.isDirectory();\n}\n\n/** Match one exact command and complete body before the assistant starts. */\nexport function matchClaudeRepositoryInvocation(input: MatchInput): Receipt {\n let native: Entry[];\n try {\n native = entries(input.transcript);\n } catch {\n return { accepted: null, reason: \"malformed native session\" };\n }\n const boundary = assistantBoundary(native, input.sessionId);\n if (\"receipt\" in boundary) return boundary.receipt;\n return matchCommandAndBody(boundary.before, input);\n}\n\nfunction assistantBoundary(\n native: Entry[],\n sessionId: string,\n): AssistantBoundary {\n const firstAssistant = native.findIndex(\n (entry) => entry.type === \"assistant\",\n );\n const assistant = native.at(firstAssistant);\n if (firstAssistant < 0 || assistant === undefined)\n return { receipt: { accepted: null, reason: \"missing assistant turn\" } };\n if (assistant.sessionId !== sessionId || assistant.isSidechain === true)\n return {\n receipt: { accepted: false, reason: \"assistant session differs\" },\n };\n return { before: native.slice(0, firstAssistant) };\n}\n\nfunction nativeCommand(input: MatchInput, token: string): string {\n const args = input.prompt.slice(token.length).trim();\n return (\n `<command-message>${input.skillName}</command-message>\\n<command-name>${token}</command-name>` +\n (args ? `\\n<command-args>${args}</command-args>` : \"\")\n );\n}\n\nfunction matchCommandAndBody(before: Entry[], input: MatchInput): Receipt {\n const token = `/${input.skillName}`;\n if (!repositoryPromptMatches(input.prompt, token))\n return { accepted: false, reason: \"prompt differs from mounted command\" };\n const command = commandBoundary(before, input, token);\n if (\"receipt\" in command) return command.receipt;\n return mountedBodyReceipt(before, input, command.called);\n}\n\nfunction commandBoundary(\n before: Entry[],\n input: MatchInput,\n token: string,\n): CommandBoundary {\n const commands = before.filter(\n (entry) =>\n entry.type === \"user\" &&\n content(entry).includes(`<command-name>${token}</command-name>`),\n );\n const [called] = commands;\n if (commands.length !== 1 || called === undefined)\n return {\n receipt: {\n accepted: false,\n reason: \"missing or duplicate native command\",\n },\n };\n if (!commandCorrelated(called, input, nativeCommand(input, token)))\n return {\n receipt: {\n accepted: false,\n reason: \"command session or arguments differ\",\n },\n };\n return { called };\n}\n\nfunction commandCorrelated(\n called: Entry,\n input: MatchInput,\n command: string,\n): boolean {\n return (\n called.sessionId === input.sessionId &&\n called.isMeta !== true &&\n called.isSidechain !== true &&\n content(called) === command\n );\n}\n\nfunction mountedBodyReceipt(\n before: Entry[],\n input: MatchInput,\n called: Entry,\n): Receipt {\n const body = input.skillText\n .replace(/^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n/, \"\")\n .trim();\n if (!body) return { accepted: null, reason: \"empty mounted body\" };\n const prefix = `Base directory for this skill: ${input.skillDir}\\n\\n${body}`;\n const expanded = before.filter((entry) => mountedBodyMatches(entry, prefix));\n const [loaded] = expanded;\n if (expanded.length !== 1 || loaded === undefined)\n return {\n accepted: false,\n reason: \"missing, partial, or duplicate mounted body\",\n };\n if (!bodyCorrelated(loaded, input.sessionId, before, called))\n return { accepted: false, reason: \"mounted body is uncorrelated\" };\n return {\n accepted: true,\n reason: \"native command and complete mounted body matched\",\n };\n}\n\nfunction mountedBodyMatches(entry: Entry, prefix: string): boolean {\n return (\n entry.type === \"user\" &&\n (content(entry) === prefix || content(entry).startsWith(prefix + \"\\n\"))\n );\n}\n\nfunction bodyCorrelated(\n loaded: Entry,\n sessionId: string,\n before: Entry[],\n called: Entry,\n): boolean {\n return (\n loaded.sessionId === sessionId &&\n loaded.isMeta === true &&\n loaded.isSidechain !== true &&\n before.indexOf(loaded) > before.indexOf(called)\n );\n}\n\n/** Read only the completed bound native session; retain no arguments or body. */\nexport async function claudeRepositoryInvocationObservation(input: {\n invocation: ClaudeRepositoryInvocation;\n stream: string | ClaudeEvents;\n configRoot: string;\n workspace: string;\n tools: ClaudeToolCallsObservation;\n}) {\n let receipt: { accepted: boolean | null; reason: string } = {\n accepted: null,\n reason: \"native session evidence unavailable\",\n };\n try {\n receipt = await repositoryReceipt(input);\n } catch {\n /* Unavailable or malformed native evidence stays partial. */\n }\n return {\n id: \"sevro.claude.repository-invocation\" as const,\n completeness:\n receipt.accepted === true && input.tools.completeness === \"complete\"\n ? (\"complete\" as const)\n : (\"partial\" as const),\n data: {\n method: \"native_repository_command\",\n ...receipt,\n skill: input.invocation.skillName,\n },\n };\n}\n\nfunction repositorySessionId(stream: string | ClaudeEvents): string | null {\n const sessions = [\n ...new Set(\n entries(stream)\n .filter(\n (entry) =>\n entry.type === \"result\" ||\n (entry.type === \"system\" && entry.subtype === \"init\"),\n )\n .map((entry) => entry.session_id),\n ),\n ];\n const [id] = sessions;\n if (\n sessions.length !== 1 ||\n typeof id !== \"string\" ||\n !/^[A-Za-z0-9_-]{1,128}$/.test(id)\n )\n return null;\n return id;\n}\n\nasync function repositoryReceipt(\n input: Parameters<typeof claudeRepositoryInvocationObservation>[0],\n): Promise<Receipt> {\n const sessionId = repositorySessionId(input.stream);\n if (sessionId === null)\n return { accepted: null, reason: \"native session evidence unavailable\" };\n const workspace = await realpath(input.workspace);\n const path = join(\n await realpath(input.configRoot),\n \"projects\",\n workspace.replace(/[^A-Za-z0-9]/g, \"-\"),\n `${sessionId}.jsonl`,\n );\n const entry = await lstat(path);\n if (!regularTranscript(entry) || (await realpath(path)) !== path)\n return { accepted: null, reason: \"native session evidence unavailable\" };\n return matchClaudeRepositoryInvocation({\n ...input.invocation,\n sessionId,\n transcript: await readFile(path, \"utf8\"),\n });\n}\n\nfunction regularTranscript(entry: Stats): boolean {\n return (\n entry.isFile() && !entry.isSymbolicLink() && entry.size <= 8 * 1024 * 1024\n );\n}\n"]}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { isAbsolute } from "node:path";
|
|
2
|
+
import { CLAUDE_AUTH_VARIABLES } from "./claude-credential.js";
|
|
3
|
+
import { runtimeHooksEnabled } from "../runtime/hooks.js";
|
|
4
|
+
import { requireRuntimeReadRoots, isRuntimeHomeRoot } from "../runtime/paths.js";
|
|
5
|
+
import { nativeStatePath } from "../native-transcript-state.js";
|
|
6
|
+
import { workspaceStatePath, workspaceBoundaryException, } from "../fixtures/workspace-state.js";
|
|
7
|
+
function absoluteRule(root, tool) {
|
|
8
|
+
if (!isAbsolute(root) || /[\r\n()]/.test(root))
|
|
9
|
+
throw new Error("Claude protected path is invalid");
|
|
10
|
+
return `${tool}(/${root}/**)`;
|
|
11
|
+
}
|
|
12
|
+
function validPrivatePaths(privateRoot, credentialFile, roots) {
|
|
13
|
+
return !(!isAbsolute(privateRoot) ||
|
|
14
|
+
!isAbsolute(credentialFile) ||
|
|
15
|
+
!credentialFile.startsWith(`${privateRoot}/`) ||
|
|
16
|
+
roots.some((root) => !isAbsolute(root) || /[\r\n()]/.test(root)));
|
|
17
|
+
}
|
|
18
|
+
/** Keep agent tools away from the CLI's private state while core auth works. */
|
|
19
|
+
export function claudeHostSettings(privateRoot, credentialFile, pluginRoots = [], protectedRoots = [], runtimePolicy, transcriptReadRoots = [], runtime, workspace) {
|
|
20
|
+
if (!validPrivatePaths(privateRoot, credentialFile, [
|
|
21
|
+
...pluginRoots,
|
|
22
|
+
...protectedRoots,
|
|
23
|
+
]))
|
|
24
|
+
throw new Error("Claude private state paths are invalid");
|
|
25
|
+
const readRoots = runtimeReadRoots(runtimePolicy);
|
|
26
|
+
requireRuntimeReadRoots(readRoots, [privateRoot, ...protectedRoots]);
|
|
27
|
+
requireRuntimeReadRoots(runtimeCacheRoots(runtime), [
|
|
28
|
+
privateRoot,
|
|
29
|
+
...protectedRoots,
|
|
30
|
+
]);
|
|
31
|
+
return {
|
|
32
|
+
disableAllHooks: !runtimeHooksEnabled(runtimePolicy),
|
|
33
|
+
sandbox: {
|
|
34
|
+
enabled: true,
|
|
35
|
+
allowUnsandboxedCommands: false,
|
|
36
|
+
failIfUnavailable: true,
|
|
37
|
+
filesystem: claudeFilesystemPolicy(privateRoot, protectedRoots, readRoots, transcriptReadRoots, pluginRoots, runtime, workspace),
|
|
38
|
+
credentials: {
|
|
39
|
+
files: [{ path: credentialFile, mode: "deny" }],
|
|
40
|
+
envVars: CLAUDE_AUTH_VARIABLES.map((name) => ({ name, mode: "deny" })),
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
permissions: claudePermissions(privateRoot, protectedRoots, pluginRoots, runtimePolicy, transcriptReadRoots, runtime, workspace),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function claudeFilesystemPolicy(privateRoot, protectedRoots, readRoots, transcriptReadRoots, pluginRoots, runtime, workspace) {
|
|
47
|
+
const runtimeWriteRoot = runtime?.root;
|
|
48
|
+
const writableRoots = runtimeWriteRoots(runtime);
|
|
49
|
+
return {
|
|
50
|
+
denyRead: [privateRoot, ...protectedRoots],
|
|
51
|
+
allowRead: [
|
|
52
|
+
...workspaceBoundaryException(workspaceStatePath(), workspace),
|
|
53
|
+
...readRoots,
|
|
54
|
+
...transcriptReadRoots,
|
|
55
|
+
...pluginRoots,
|
|
56
|
+
...writableRoots,
|
|
57
|
+
],
|
|
58
|
+
...(writableRoots.length ? { allowWrite: writableRoots } : {}),
|
|
59
|
+
denyWrite: [
|
|
60
|
+
privateRoot,
|
|
61
|
+
...pluginRoots,
|
|
62
|
+
...writableProtectedRoots(protectedRoots, runtimeWriteRoot, workspace, runtimeCacheRoots(runtime)),
|
|
63
|
+
...readRoots,
|
|
64
|
+
...transcriptReadRoots,
|
|
65
|
+
],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function claudePermissions(privateRoot, protectedRoots, pluginRoots, policy, transcriptReadRoots, runtime, workspace) {
|
|
69
|
+
const runtimeWriteRoot = runtime?.root;
|
|
70
|
+
const roots = [
|
|
71
|
+
privateRoot,
|
|
72
|
+
...protectedRoots.filter((root) => !workspaceBoundaryException(root, workspace).length),
|
|
73
|
+
];
|
|
74
|
+
const managedWorkspace = workspaceBoundaryException(workspaceStatePath(), workspace)[0];
|
|
75
|
+
const readRoots = policy
|
|
76
|
+
? roots.filter((root) => !isRuntimeHomeRoot(root))
|
|
77
|
+
: roots;
|
|
78
|
+
const toolRoots = [...runtimeReadRoots(policy), ...transcriptReadRoots];
|
|
79
|
+
const writableRoots = runtimeWriteRoots(runtime);
|
|
80
|
+
return {
|
|
81
|
+
allow: claudeToolAllowRules(policy, runtime, managedWorkspace),
|
|
82
|
+
...(policy || managedWorkspace
|
|
83
|
+
? {
|
|
84
|
+
blockReadsOutsideWorkingDirectories: true,
|
|
85
|
+
additionalDirectories: [
|
|
86
|
+
...pluginRoots,
|
|
87
|
+
...toolRoots,
|
|
88
|
+
...writableRoots,
|
|
89
|
+
],
|
|
90
|
+
}
|
|
91
|
+
: {}),
|
|
92
|
+
deny: [
|
|
93
|
+
...writableProtectedRoots(roots, runtimeWriteRoot, workspace, runtimeCacheRoots(runtime)).flatMap((root) => protectedToolRules(root, readRoots.includes(root) &&
|
|
94
|
+
![...transcriptReadRoots, ...pluginRoots].some((path) => path.startsWith(`${root}/`)))),
|
|
95
|
+
...[...pluginRoots, ...toolRoots].map((root) => absoluteRule(root, "Edit")),
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function claudeToolAllowRules(policy, runtime, workspace) {
|
|
100
|
+
if (!policy)
|
|
101
|
+
return [
|
|
102
|
+
"Bash",
|
|
103
|
+
"Read",
|
|
104
|
+
"Skill",
|
|
105
|
+
"Agent",
|
|
106
|
+
"SendMessage",
|
|
107
|
+
workspace ? absoluteRule(workspace, "Edit") : "Edit",
|
|
108
|
+
];
|
|
109
|
+
if (!runtime)
|
|
110
|
+
return ["Bash", "Edit", "Skill", "Agent", "SendMessage"];
|
|
111
|
+
return [
|
|
112
|
+
"Bash",
|
|
113
|
+
"Skill",
|
|
114
|
+
"Agent",
|
|
115
|
+
"SendMessage",
|
|
116
|
+
absoluteRule(runtime.workspace, "Edit"),
|
|
117
|
+
absoluteRule(runtime.root, "Edit"),
|
|
118
|
+
...(runtime.cacheRoots ?? []).map((root) => absoluteRule(root, "Edit")),
|
|
119
|
+
];
|
|
120
|
+
}
|
|
121
|
+
/** Native write denies override grants; the namespace stays read-denied and has no write grant. */
|
|
122
|
+
function writableProtectedRoots(roots, runtimeWriteRoot, workspace, cacheRoots = []) {
|
|
123
|
+
const namespace = nativeStatePath();
|
|
124
|
+
return roots.filter((root) => !workspaceBoundaryException(root, workspace).length &&
|
|
125
|
+
!sharedHomeGrant(root, cacheRoots) &&
|
|
126
|
+
keepNativeWriteDeny(root, namespace, runtimeWriteRoot));
|
|
127
|
+
}
|
|
128
|
+
function sharedHomeGrant(root, cacheRoots) {
|
|
129
|
+
return (isRuntimeHomeRoot(root) &&
|
|
130
|
+
cacheRoots.some((cache) => cache.startsWith(`${root}/`)));
|
|
131
|
+
}
|
|
132
|
+
function runtimeCacheRoots(runtime) {
|
|
133
|
+
return runtime?.cacheRoots ?? [];
|
|
134
|
+
}
|
|
135
|
+
function runtimeWriteRoots(runtime) {
|
|
136
|
+
return [
|
|
137
|
+
...optionalRuntimeRoot(runtime?.root),
|
|
138
|
+
...(runtime?.cacheRoots ?? []),
|
|
139
|
+
];
|
|
140
|
+
}
|
|
141
|
+
function keepNativeWriteDeny(root, namespace, runtimeWriteRoot) {
|
|
142
|
+
return (root !== namespace ||
|
|
143
|
+
runtimeWriteRoot === undefined ||
|
|
144
|
+
!runtimeWriteRoot.startsWith(`${namespace}/`));
|
|
145
|
+
}
|
|
146
|
+
function optionalRuntimeRoot(root) {
|
|
147
|
+
return root ? [root] : [];
|
|
148
|
+
}
|
|
149
|
+
function protectedToolRules(root, denyRead) {
|
|
150
|
+
return [
|
|
151
|
+
...(denyRead ? [absoluteRule(root, "Read")] : []),
|
|
152
|
+
absoluteRule(root, "Edit"),
|
|
153
|
+
];
|
|
154
|
+
}
|
|
155
|
+
function runtimeReadRoots(policy) {
|
|
156
|
+
return policy?.readOnlyRoots ?? [];
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=claude-settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-settings.js","sourceRoot":"","sources":["claude-settings.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute } from \"node:path\";\nimport { CLAUDE_AUTH_VARIABLES } from \"./claude-credential\";\nimport type { RuntimePolicy } from \"../runtime/config\";\nimport { runtimeHooksEnabled } from \"../runtime/hooks\";\nimport { requireRuntimeReadRoots, isRuntimeHomeRoot } from \"../runtime/paths\";\nimport { nativeStatePath } from \"../native-transcript-state\";\nimport {\n workspaceStatePath,\n workspaceBoundaryException,\n} from \"../fixtures/workspace-state\";\n\ninterface WritableRuntime {\n root: string;\n workspace: string;\n cacheRoots?: string[];\n}\n\nfunction absoluteRule(root: string, tool: \"Read\" | \"Edit\"): string {\n if (!isAbsolute(root) || /[\\r\\n()]/.test(root))\n throw new Error(\"Claude protected path is invalid\");\n return `${tool}(/${root}/**)`;\n}\n\nfunction validPrivatePaths(\n privateRoot: string,\n credentialFile: string,\n roots: string[],\n): boolean {\n return !(\n !isAbsolute(privateRoot) ||\n !isAbsolute(credentialFile) ||\n !credentialFile.startsWith(`${privateRoot}/`) ||\n roots.some((root) => !isAbsolute(root) || /[\\r\\n()]/.test(root))\n );\n}\n\n/** Keep agent tools away from the CLI's private state while core auth works. */\nexport function claudeHostSettings(\n privateRoot: string,\n credentialFile: string,\n pluginRoots: string[] = [],\n protectedRoots: string[] = [],\n runtimePolicy?: RuntimePolicy,\n transcriptReadRoots: string[] = [],\n runtime?: WritableRuntime,\n workspace?: string,\n): Record<string, unknown> {\n if (\n !validPrivatePaths(privateRoot, credentialFile, [\n ...pluginRoots,\n ...protectedRoots,\n ])\n )\n throw new Error(\"Claude private state paths are invalid\");\n const readRoots = runtimeReadRoots(runtimePolicy);\n requireRuntimeReadRoots(readRoots, [privateRoot, ...protectedRoots]);\n requireRuntimeReadRoots(runtimeCacheRoots(runtime), [\n privateRoot,\n ...protectedRoots,\n ]);\n return {\n disableAllHooks: !runtimeHooksEnabled(runtimePolicy),\n sandbox: {\n enabled: true,\n allowUnsandboxedCommands: false,\n failIfUnavailable: true,\n filesystem: claudeFilesystemPolicy(\n privateRoot,\n protectedRoots,\n readRoots,\n transcriptReadRoots,\n pluginRoots,\n runtime,\n workspace,\n ),\n credentials: {\n files: [{ path: credentialFile, mode: \"deny\" }],\n envVars: CLAUDE_AUTH_VARIABLES.map((name) => ({ name, mode: \"deny\" })),\n },\n },\n permissions: claudePermissions(\n privateRoot,\n protectedRoots,\n pluginRoots,\n runtimePolicy,\n transcriptReadRoots,\n runtime,\n workspace,\n ),\n };\n}\n\nfunction claudeFilesystemPolicy(\n privateRoot: string,\n protectedRoots: string[],\n readRoots: string[],\n transcriptReadRoots: string[],\n pluginRoots: string[],\n runtime: WritableRuntime | undefined,\n workspace: string | undefined,\n) {\n const runtimeWriteRoot = runtime?.root;\n const writableRoots = runtimeWriteRoots(runtime);\n return {\n denyRead: [privateRoot, ...protectedRoots],\n allowRead: [\n ...workspaceBoundaryException(workspaceStatePath(), workspace),\n ...readRoots,\n ...transcriptReadRoots,\n ...pluginRoots,\n ...writableRoots,\n ],\n ...(writableRoots.length ? { allowWrite: writableRoots } : {}),\n denyWrite: [\n privateRoot,\n ...pluginRoots,\n ...writableProtectedRoots(\n protectedRoots,\n runtimeWriteRoot,\n workspace,\n runtimeCacheRoots(runtime),\n ),\n ...readRoots,\n ...transcriptReadRoots,\n ],\n };\n}\n\nfunction claudePermissions(\n privateRoot: string,\n protectedRoots: string[],\n pluginRoots: string[],\n policy: RuntimePolicy | undefined,\n transcriptReadRoots: string[],\n runtime: WritableRuntime | undefined,\n workspace: string | undefined,\n) {\n const runtimeWriteRoot = runtime?.root;\n const roots = [\n privateRoot,\n ...protectedRoots.filter(\n (root) => !workspaceBoundaryException(root, workspace).length,\n ),\n ];\n const managedWorkspace = workspaceBoundaryException(\n workspaceStatePath(),\n workspace,\n )[0];\n const readRoots = policy\n ? roots.filter((root) => !isRuntimeHomeRoot(root))\n : roots;\n const toolRoots = [...runtimeReadRoots(policy), ...transcriptReadRoots];\n const writableRoots = runtimeWriteRoots(runtime);\n return {\n allow: claudeToolAllowRules(policy, runtime, managedWorkspace),\n ...(policy || managedWorkspace\n ? {\n blockReadsOutsideWorkingDirectories: true,\n additionalDirectories: [\n ...pluginRoots,\n ...toolRoots,\n ...writableRoots,\n ],\n }\n : {}),\n deny: [\n ...writableProtectedRoots(\n roots,\n runtimeWriteRoot,\n workspace,\n runtimeCacheRoots(runtime),\n ).flatMap((root) =>\n protectedToolRules(\n root,\n readRoots.includes(root) &&\n ![...transcriptReadRoots, ...pluginRoots].some((path) =>\n path.startsWith(`${root}/`),\n ),\n ),\n ),\n ...[...pluginRoots, ...toolRoots].map((root) =>\n absoluteRule(root, \"Edit\"),\n ),\n ],\n };\n}\n\nfunction claudeToolAllowRules(\n policy: RuntimePolicy | undefined,\n runtime: WritableRuntime | undefined,\n workspace?: string,\n): string[] {\n if (!policy)\n return [\n \"Bash\",\n \"Read\",\n \"Skill\",\n \"Agent\",\n \"SendMessage\",\n workspace ? absoluteRule(workspace, \"Edit\") : \"Edit\",\n ];\n if (!runtime) return [\"Bash\", \"Edit\", \"Skill\", \"Agent\", \"SendMessage\"];\n return [\n \"Bash\",\n \"Skill\",\n \"Agent\",\n \"SendMessage\",\n absoluteRule(runtime.workspace, \"Edit\"),\n absoluteRule(runtime.root, \"Edit\"),\n ...(runtime.cacheRoots ?? []).map((root) => absoluteRule(root, \"Edit\")),\n ];\n}\n\n/** Native write denies override grants; the namespace stays read-denied and has no write grant. */\nfunction writableProtectedRoots(\n roots: string[],\n runtimeWriteRoot: string | undefined,\n workspace?: string,\n cacheRoots: string[] = [],\n): string[] {\n const namespace = nativeStatePath();\n return roots.filter(\n (root) =>\n !workspaceBoundaryException(root, workspace).length &&\n !sharedHomeGrant(root, cacheRoots) &&\n keepNativeWriteDeny(root, namespace, runtimeWriteRoot),\n );\n}\n\nfunction sharedHomeGrant(root: string, cacheRoots: string[]): boolean {\n return (\n isRuntimeHomeRoot(root) &&\n cacheRoots.some((cache) => cache.startsWith(`${root}/`))\n );\n}\n\nfunction runtimeCacheRoots(runtime: WritableRuntime | undefined): string[] {\n return runtime?.cacheRoots ?? [];\n}\n\nfunction runtimeWriteRoots(runtime: WritableRuntime | undefined): string[] {\n return [\n ...optionalRuntimeRoot(runtime?.root),\n ...(runtime?.cacheRoots ?? []),\n ];\n}\n\nfunction keepNativeWriteDeny(\n root: string,\n namespace: string,\n runtimeWriteRoot?: string,\n): boolean {\n return (\n root !== namespace ||\n runtimeWriteRoot === undefined ||\n !runtimeWriteRoot.startsWith(`${namespace}/`)\n );\n}\n\nfunction optionalRuntimeRoot(root: string | undefined): string[] {\n return root ? [root] : [];\n}\n\nfunction protectedToolRules(root: string, denyRead: boolean): string[] {\n return [\n ...(denyRead ? [absoluteRule(root, \"Read\")] : []),\n absoluteRule(root, \"Edit\"),\n ];\n}\n\nfunction runtimeReadRoots(policy: RuntimePolicy | undefined): string[] {\n return policy?.readOnlyRoots ?? [];\n}\n"]}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { isRecord } from "../value-guards.js";
|
|
2
|
+
import { summarizeClaudeEvents, parseClaudeEvents, } from "./claude-events.js";
|
|
3
|
+
const MAX_CALLS = 128;
|
|
4
|
+
function label(value) {
|
|
5
|
+
return typeof value === "string" && /^[A-Za-z0-9_.:-]{1,256}$/.test(value)
|
|
6
|
+
? value
|
|
7
|
+
: null;
|
|
8
|
+
}
|
|
9
|
+
function blocks(event) {
|
|
10
|
+
const content = isRecord(event.message)
|
|
11
|
+
? event.message.content
|
|
12
|
+
: null;
|
|
13
|
+
return Array.isArray(content) ? content : [];
|
|
14
|
+
}
|
|
15
|
+
function key(event, id) {
|
|
16
|
+
return JSON.stringify([
|
|
17
|
+
event.session_id ?? event.sessionId,
|
|
18
|
+
event.parent_tool_use_id ?? null,
|
|
19
|
+
id,
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
function call(event, block, state) {
|
|
23
|
+
const id = label(block.id);
|
|
24
|
+
const sessionId = label(event.session_id ?? event.sessionId);
|
|
25
|
+
const invocation = skillInput(block.input);
|
|
26
|
+
if (!id || !sessionId || !invocation) {
|
|
27
|
+
state.partial = true;
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
addCall(key(event, id), {
|
|
31
|
+
sessionId,
|
|
32
|
+
parentToolUseId: label(event.parent_tool_use_id),
|
|
33
|
+
toolUseId: id,
|
|
34
|
+
invocation,
|
|
35
|
+
status: "unknown",
|
|
36
|
+
}, state);
|
|
37
|
+
}
|
|
38
|
+
function skillInput(input) {
|
|
39
|
+
return isRecord(input) ? label(input.skill) : null;
|
|
40
|
+
}
|
|
41
|
+
function addCall(id, value, state) {
|
|
42
|
+
const previous = state.calls.get(id);
|
|
43
|
+
if (previous) {
|
|
44
|
+
state.partial ||= previous.invocation !== value.invocation;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (state.calls.size >= MAX_CALLS) {
|
|
48
|
+
state.truncated = true;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
state.calls.set(id, value);
|
|
52
|
+
}
|
|
53
|
+
function result(event, block, state) {
|
|
54
|
+
const id = label(block.tool_use_id);
|
|
55
|
+
if (!id)
|
|
56
|
+
return;
|
|
57
|
+
const pending = state.calls.get(key(event, id));
|
|
58
|
+
if (!pending)
|
|
59
|
+
return;
|
|
60
|
+
const status = resultStatus(block.is_error);
|
|
61
|
+
if (!status) {
|
|
62
|
+
state.partial = true;
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
state.partial ||= conflictingResult(pending.status, status);
|
|
66
|
+
pending.status = status;
|
|
67
|
+
}
|
|
68
|
+
function resultStatus(value) {
|
|
69
|
+
if (value !== undefined && typeof value !== "boolean")
|
|
70
|
+
return null;
|
|
71
|
+
return value === true ? "failed" : "succeeded";
|
|
72
|
+
}
|
|
73
|
+
function conflictingResult(previous, next) {
|
|
74
|
+
return previous !== "unknown" && previous !== next;
|
|
75
|
+
}
|
|
76
|
+
function visit(line, state) {
|
|
77
|
+
if (!line.parsed || !isRecord(line.value)) {
|
|
78
|
+
state.partial = true;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
for (const block of blocks(line.value))
|
|
82
|
+
visitBlock(line.value, block, state);
|
|
83
|
+
}
|
|
84
|
+
function visitBlock(event, block, state) {
|
|
85
|
+
if (!isRecord(block))
|
|
86
|
+
return;
|
|
87
|
+
switch (event.type) {
|
|
88
|
+
case "assistant":
|
|
89
|
+
if (isSkillCall(block))
|
|
90
|
+
call(event, block, state);
|
|
91
|
+
break;
|
|
92
|
+
case "user":
|
|
93
|
+
if (block.type === "tool_result")
|
|
94
|
+
result(event, block, state);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function isSkillCall(block) {
|
|
98
|
+
return block.type === "tool_use" && block.name === "Skill";
|
|
99
|
+
}
|
|
100
|
+
function completeCollection(completed, state) {
|
|
101
|
+
return (completed &&
|
|
102
|
+
!state.partial &&
|
|
103
|
+
!state.truncated &&
|
|
104
|
+
[...state.calls.values()].every((item) => item.status !== "unknown"));
|
|
105
|
+
}
|
|
106
|
+
/** Observe the native Skill seam and distinguish successful results from attempts. */
|
|
107
|
+
export function claudeSkillActivationsObservation(stream, code) {
|
|
108
|
+
const events = parseClaudeEvents(stream);
|
|
109
|
+
const summary = summarizeClaudeEvents(events, code);
|
|
110
|
+
const state = { calls: new Map(), partial: false, truncated: false };
|
|
111
|
+
for (const line of events.lines)
|
|
112
|
+
visit(line, state);
|
|
113
|
+
const calls = [...state.calls.values()];
|
|
114
|
+
const complete = completeCollection(summary.complete, state);
|
|
115
|
+
return {
|
|
116
|
+
id: "sevro.host.skill-activations",
|
|
117
|
+
completeness: complete ? "complete" : "partial",
|
|
118
|
+
data: {
|
|
119
|
+
method: "skill_tool_result",
|
|
120
|
+
visibility: "skill_tool",
|
|
121
|
+
observedSkills: [
|
|
122
|
+
...new Set(calls
|
|
123
|
+
.filter((item) => item.status === "succeeded")
|
|
124
|
+
.map((item) => item.invocation)),
|
|
125
|
+
],
|
|
126
|
+
calls,
|
|
127
|
+
truncated: state.truncated,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=claude-skill-activations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-skill-activations.js","sourceRoot":"","sources":["claude-skill-activations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,2BAAwB;AAC3C,OAAO,EACL,qBAAqB,EACrB,iBAAiB,GAGlB,2BAAwB;AAEzB,MAAM,SAAS,GAAG,GAAG,CAAC;AAetB,SAAS,KAAK,CAAC,KAAc;IAC3B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC;QACxE,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,SAAS,MAAM,CAAC,KAAY;IAC1B,MAAM,OAAO,GAAY,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC;QAC9C,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO;QACvB,CAAC,CAAC,IAAI,CAAC;IACT,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,GAAG,CAAC,KAAY,EAAE,EAAU;IACnC,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,SAAS;QACnC,KAAK,CAAC,kBAAkB,IAAI,IAAI;QAChC,EAAE;KACH,CAAC,CAAC;AACL,CAAC;AAED,SAAS,IAAI,CAAC,KAAY,EAAE,KAAY,EAAE,KAAY;IACpD,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC3B,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;IAC7D,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU,EAAE,CAAC;QACrC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;QACrB,OAAO;IACT,CAAC;IACD,OAAO,CACL,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,EACd;QACE,SAAS;QACT,eAAe,EAAE,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC;QAChD,SAAS,EAAE,EAAE;QACb,UAAU;QACV,MAAM,EAAE,SAAS;KAClB,EACD,KAAK,CACN,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACrD,CAAC;AAED,SAAS,OAAO,CAAC,EAAU,EAAE,KAAgB,EAAE,KAAY;IACzD,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACrC,IAAI,QAAQ,EAAE,CAAC;QACb,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,CAAC;QAC3D,OAAO;IACT,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC;QAClC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;QACvB,OAAO;IACT,CAAC;IACD,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,MAAM,CAAC,KAAY,EAAE,KAAY,EAAE,KAAY;IACtD,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE;QAAE,OAAO;IAChB,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;IAChD,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;QACrB,OAAO;IACT,CAAC;IACD,KAAK,CAAC,OAAO,KAAK,iBAAiB,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5D,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;AAC1B,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACnE,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;AACjD,CAAC;AAED,SAAS,iBAAiB,CACxB,QAA6B,EAC7B,IAAyB;IAEzB,OAAO,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,SAAS,KAAK,CAAC,IAAqB,EAAE,KAAY;IAChD,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;QACrB,OAAO;IACT,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAC/E,CAAC;AAED,SAAS,UAAU,CAAC,KAAY,EAAE,KAAc,EAAE,KAAY;IAC5D,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO;IAC7B,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,WAAW;YACd,IAAI,WAAW,CAAC,KAAK,CAAC;gBAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YAClD,MAAM;QACR,KAAK,MAAM;YACT,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa;gBAAE,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAAY;IAC/B,OAAO,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;AAC7D,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAkB,EAAE,KAAY;IAC1D,OAAO,CACL,SAAS;QACT,CAAC,KAAK,CAAC,OAAO;QACd,CAAC,KAAK,CAAC,SAAS;QAChB,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CACrE,CAAC;AACJ,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,iCAAiC,CAC/C,MAA6B,EAC7B,IAAY;IAEZ,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACpD,MAAM,KAAK,GAAU,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAC5E,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK;QAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC7D,OAAO;QACL,EAAE,EAAE,8BAA8B;QAClC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAE,UAAoB,CAAC,CAAC,CAAE,SAAmB;QACrE,IAAI,EAAE;YACJ,MAAM,EAAE,mBAAmB;YAC3B,UAAU,EAAE,YAAY;YACxB,cAAc,EAAE;gBACd,GAAG,IAAI,GAAG,CACR,KAAK;qBACF,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,WAAW,CAAC;qBAC7C,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAClC;aACF;YACD,KAAK;YACL,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { isRecord } from \"../value-guards\";\nimport {\n summarizeClaudeEvents,\n parseClaudeEvents,\n type ClaudeEvents,\n type ClaudeEventLine,\n} from \"./claude-events\";\n\nconst MAX_CALLS = 128;\ntype Entry = Record<string, unknown>;\ninterface SkillCall {\n sessionId: string;\n parentToolUseId: string | null;\n toolUseId: string;\n invocation: string;\n status: \"unknown\" | \"succeeded\" | \"failed\";\n}\ninterface State {\n calls: Map<string, SkillCall>;\n partial: boolean;\n truncated: boolean;\n}\n\nfunction label(value: unknown): string | null {\n return typeof value === \"string\" && /^[A-Za-z0-9_.:-]{1,256}$/.test(value)\n ? value\n : null;\n}\n\nfunction blocks(event: Entry): unknown[] {\n const content: unknown = isRecord(event.message)\n ? event.message.content\n : null;\n return Array.isArray(content) ? content : [];\n}\n\nfunction key(event: Entry, id: string): string {\n return JSON.stringify([\n event.session_id ?? event.sessionId,\n event.parent_tool_use_id ?? null,\n id,\n ]);\n}\n\nfunction call(event: Entry, block: Entry, state: State) {\n const id = label(block.id);\n const sessionId = label(event.session_id ?? event.sessionId);\n const invocation = skillInput(block.input);\n if (!id || !sessionId || !invocation) {\n state.partial = true;\n return;\n }\n addCall(\n key(event, id),\n {\n sessionId,\n parentToolUseId: label(event.parent_tool_use_id),\n toolUseId: id,\n invocation,\n status: \"unknown\",\n },\n state,\n );\n}\n\nfunction skillInput(input: unknown): string | null {\n return isRecord(input) ? label(input.skill) : null;\n}\n\nfunction addCall(id: string, value: SkillCall, state: State) {\n const previous = state.calls.get(id);\n if (previous) {\n state.partial ||= previous.invocation !== value.invocation;\n return;\n }\n if (state.calls.size >= MAX_CALLS) {\n state.truncated = true;\n return;\n }\n state.calls.set(id, value);\n}\n\nfunction result(event: Entry, block: Entry, state: State) {\n const id = label(block.tool_use_id);\n if (!id) return;\n const pending = state.calls.get(key(event, id));\n if (!pending) return;\n const status = resultStatus(block.is_error);\n if (!status) {\n state.partial = true;\n return;\n }\n state.partial ||= conflictingResult(pending.status, status);\n pending.status = status;\n}\n\nfunction resultStatus(value: unknown): \"failed\" | \"succeeded\" | null {\n if (value !== undefined && typeof value !== \"boolean\") return null;\n return value === true ? \"failed\" : \"succeeded\";\n}\n\nfunction conflictingResult(\n previous: SkillCall[\"status\"],\n next: SkillCall[\"status\"],\n): boolean {\n return previous !== \"unknown\" && previous !== next;\n}\n\nfunction visit(line: ClaudeEventLine, state: State) {\n if (!line.parsed || !isRecord(line.value)) {\n state.partial = true;\n return;\n }\n for (const block of blocks(line.value)) visitBlock(line.value, block, state);\n}\n\nfunction visitBlock(event: Entry, block: unknown, state: State) {\n if (!isRecord(block)) return;\n switch (event.type) {\n case \"assistant\":\n if (isSkillCall(block)) call(event, block, state);\n break;\n case \"user\":\n if (block.type === \"tool_result\") result(event, block, state);\n }\n}\n\nfunction isSkillCall(block: Entry): boolean {\n return block.type === \"tool_use\" && block.name === \"Skill\";\n}\n\nfunction completeCollection(completed: boolean, state: State): boolean {\n return (\n completed &&\n !state.partial &&\n !state.truncated &&\n [...state.calls.values()].every((item) => item.status !== \"unknown\")\n );\n}\n\n/** Observe the native Skill seam and distinguish successful results from attempts. */\nexport function claudeSkillActivationsObservation(\n stream: string | ClaudeEvents,\n code: number,\n) {\n const events = parseClaudeEvents(stream);\n const summary = summarizeClaudeEvents(events, code);\n const state: State = { calls: new Map(), partial: false, truncated: false };\n for (const line of events.lines) visit(line, state);\n const calls = [...state.calls.values()];\n const complete = completeCollection(summary.complete, state);\n return {\n id: \"sevro.host.skill-activations\",\n completeness: complete ? (\"complete\" as const) : (\"partial\" as const),\n data: {\n method: \"skill_tool_result\",\n visibility: \"skill_tool\",\n observedSkills: [\n ...new Set(\n calls\n .filter((item) => item.status === \"succeeded\")\n .map((item) => item.invocation),\n ),\n ],\n calls,\n truncated: state.truncated,\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { runtimeSeedSources } from "../runtime/config.js";
|
|
2
|
+
import { minimalRoots } from "../paths.js";
|
|
3
|
+
import { shellQuote } from "../shell.js";
|
|
4
|
+
import { candidateArtifactEnvironment, candidateArtifactReadRoots, } from "../candidate-artifacts.js";
|
|
5
|
+
import { cp, mkdir, realpath, stat, symlink, writeFile, } from "node:fs/promises";
|
|
6
|
+
import { delimiter, dirname, join } from "node:path";
|
|
7
|
+
import { nativeStateParent } from "../native-transcript-state.js";
|
|
8
|
+
import { workspaceBoundaryException, workspaceStatePath, } from "../fixtures/workspace-state.js";
|
|
9
|
+
import { candidateTranscriptEnvironment, candidateTranscriptRoots, } from "../native-transcripts.js";
|
|
10
|
+
import { prepareHookMounts, runtimeHooksEnabled } from "../runtime/hooks.js";
|
|
11
|
+
import { insideRuntimeRoot as inside, runtimeExecutableProtection, } from "../runtime/paths.js";
|
|
12
|
+
import { prepareRuntimeState } from "../runtime/state.js";
|
|
13
|
+
import { sharedCacheDenyRoots, sharedCacheRoots, } from "../runtime/shared-cache.js";
|
|
14
|
+
import { stageClaudeAuthentication } from "./claude-credential.js";
|
|
15
|
+
import { claudeHostSettings } from "./claude-settings.js";
|
|
16
|
+
import { evaluationProtectedRoots } from "./isolation-roots.js";
|
|
17
|
+
function claudeSeedSources(request) {
|
|
18
|
+
return runtimeSeedSources(request.runtimePolicy);
|
|
19
|
+
}
|
|
20
|
+
async function createClaudePrivateState(stateRoot, options, loginLifetimeMs) {
|
|
21
|
+
await mkdir(join(stateRoot, "private"), { mode: 0o700 });
|
|
22
|
+
const privateRoot = await realpath(join(stateRoot, "private"));
|
|
23
|
+
const home = join(stateRoot, "home"), temp = join(stateRoot, "tmp");
|
|
24
|
+
await Promise.all([home, temp].map((path) => mkdir(path, { mode: 0o700 })));
|
|
25
|
+
const authentication = await stageClaudeAuthentication(join(privateRoot, "config"), options.credentialFile, { binary: options.binary, lifetimeMs: loginLifetimeMs });
|
|
26
|
+
return {
|
|
27
|
+
privateRoot,
|
|
28
|
+
home,
|
|
29
|
+
temp,
|
|
30
|
+
authentication,
|
|
31
|
+
credential: authentication.credentialFile,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async function protectedClaudeRoots(request, options, credential) {
|
|
35
|
+
const candidates = await evaluationProtectedRoots({
|
|
36
|
+
ownedStateRoot: dirname(dirname(dirname(credential))),
|
|
37
|
+
workspace: request.workspace,
|
|
38
|
+
projectRoot: options.projectRoot,
|
|
39
|
+
resultsRoot: options.resultsRoot,
|
|
40
|
+
additionalRoots: [
|
|
41
|
+
...options.additionalProtectedRoots,
|
|
42
|
+
...claudeSeedSources(request),
|
|
43
|
+
],
|
|
44
|
+
});
|
|
45
|
+
const roots = request.runtimePolicy ? candidates : minimalRoots(candidates);
|
|
46
|
+
const namespace = await nativeStateParent();
|
|
47
|
+
if (roots.some((root) => root !== namespace && inside(root, credential)))
|
|
48
|
+
throw new Error("Claude private state overlaps a protected root");
|
|
49
|
+
const binary = await realpath(options.binary);
|
|
50
|
+
const executableRoots = runtimeExecutableProtection([dirname(binary)], roots, Boolean(request.runtimePolicy));
|
|
51
|
+
if (executableRoots.some((root) => inside(root, binary)))
|
|
52
|
+
throw new Error("Claude executable resides inside a protected root");
|
|
53
|
+
return roots;
|
|
54
|
+
}
|
|
55
|
+
async function claudeToolchainDirectory(options, roots) {
|
|
56
|
+
const directory = options.toolchainBinDir
|
|
57
|
+
? await realpath(options.toolchainBinDir)
|
|
58
|
+
: null;
|
|
59
|
+
if (directory &&
|
|
60
|
+
(roots.some((root) => inside(root, directory)) ||
|
|
61
|
+
!(await stat(directory)).isDirectory()))
|
|
62
|
+
throw new Error("Claude toolchain directory is unavailable or protected");
|
|
63
|
+
return directory;
|
|
64
|
+
}
|
|
65
|
+
async function prepareClaudeRuntime(options, roots, workspace) {
|
|
66
|
+
if (!options.uvCacheDir)
|
|
67
|
+
return null;
|
|
68
|
+
const cache = await realpath(options.uvCacheDir);
|
|
69
|
+
if (roots.some((root) => inside(root, cache)) ||
|
|
70
|
+
!(await stat(cache)).isDirectory())
|
|
71
|
+
throw new Error("Claude UV cache is unavailable or protected");
|
|
72
|
+
const runtimeRoot = join(workspace, ".git", "sevro-runtime");
|
|
73
|
+
await mkdir(runtimeRoot, { recursive: true, mode: 0o700 });
|
|
74
|
+
await cp(cache, join(runtimeRoot, "uv-cache"), {
|
|
75
|
+
recursive: true,
|
|
76
|
+
force: false,
|
|
77
|
+
errorOnExist: true,
|
|
78
|
+
});
|
|
79
|
+
return runtimeRoot;
|
|
80
|
+
}
|
|
81
|
+
function claudeEnvironment(state, request, toolchain, runtime) {
|
|
82
|
+
return {
|
|
83
|
+
...state.authentication.environment,
|
|
84
|
+
...request.runtimePolicy?.environment,
|
|
85
|
+
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB: "1",
|
|
86
|
+
PATH: claudePath(request, toolchain),
|
|
87
|
+
LANG: process.env.LANG ?? "C",
|
|
88
|
+
HOME: runtime ? join(runtime, "host-home") : state.home,
|
|
89
|
+
TMPDIR: state.temp,
|
|
90
|
+
CLAUDE_CONFIG_DIR: dirname(state.credential),
|
|
91
|
+
NO_COLOR: "1",
|
|
92
|
+
...claudeRuntimeEnvironment(runtime),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function claudePath(request, toolchain) {
|
|
96
|
+
const path = request.runtimePolicy?.environment.PATH ??
|
|
97
|
+
process.env.PATH ??
|
|
98
|
+
"/usr/bin:/bin";
|
|
99
|
+
return [request.fixtureBinDir, toolchain, path]
|
|
100
|
+
.filter(Boolean)
|
|
101
|
+
.join(delimiter);
|
|
102
|
+
}
|
|
103
|
+
function claudeRuntimeEnvironment(runtime) {
|
|
104
|
+
return runtime
|
|
105
|
+
? {
|
|
106
|
+
UV_CACHE_DIR: join(runtime, "uv-cache"),
|
|
107
|
+
UV_PROJECT_ENVIRONMENT: join(runtime, "project-environment"),
|
|
108
|
+
UV_OFFLINE: "1",
|
|
109
|
+
PYTHONDONTWRITEBYTECODE: "1",
|
|
110
|
+
}
|
|
111
|
+
: {};
|
|
112
|
+
}
|
|
113
|
+
/** `lifetimeMs` is the access-token lifetime the complete execution needs. */
|
|
114
|
+
export async function prepareClaudeState(stateRoot, options, request, pluginDirs, lifetimeMs) {
|
|
115
|
+
await requireClaudeRuntimeNamespace(request, stateRoot);
|
|
116
|
+
const state = await createClaudePrivateState(stateRoot, options, lifetimeMs);
|
|
117
|
+
const transcripts = await claudeTranscriptAccess(stateRoot, state.credential, request);
|
|
118
|
+
const roots = await protectedClaudeRoots(request, options, state.credential);
|
|
119
|
+
const toolchain = await claudeToolchainDirectory(options, roots);
|
|
120
|
+
const runtime = await prepareClaudeRuntime(options, roots, request.workspace);
|
|
121
|
+
const settingsPath = join(state.privateRoot, "settings.json");
|
|
122
|
+
const hooks = await claudeHookMounts(request, stateRoot, state.privateRoot, pluginDirs, roots);
|
|
123
|
+
const effectivePlugins = hooks?.directories ?? pluginDirs;
|
|
124
|
+
const env = claudeEnvironment(state, request, toolchain, runtime);
|
|
125
|
+
const runtimeWriteRoot = await applyClaudeRuntimeEnvironment(request, env, runtime, stateRoot);
|
|
126
|
+
const cacheRoots = await sharedCacheRoots(request.runtimePolicy, request.runtimeRole, roots);
|
|
127
|
+
await writeFile(settingsPath, JSON.stringify(claudeHostSettings(state.privateRoot, state.credential, [...pluginDirs, ...effectivePlugins], [
|
|
128
|
+
...roots,
|
|
129
|
+
...sharedCacheDenyRoots(request.runtimePolicy, request.runtimeRole),
|
|
130
|
+
], transcripts.policy, [
|
|
131
|
+
...transcripts.readRoots,
|
|
132
|
+
...candidateTranscriptRoots(request.candidateTranscriptRoot),
|
|
133
|
+
...candidateArtifactReadRoots(request.candidateArtifactRoots),
|
|
134
|
+
], runtimeWriteRoot
|
|
135
|
+
? { root: runtimeWriteRoot, workspace: request.workspace, cacheRoots }
|
|
136
|
+
: undefined, request.workspace)), { flag: "wx", mode: 0o600 });
|
|
137
|
+
Object.assign(env, transcripts.environment);
|
|
138
|
+
Object.assign(env, candidateTranscriptEnvironment(request.candidateTranscriptRoot), candidateArtifactEnvironment(request.candidateArtifactRoots));
|
|
139
|
+
if (runtime)
|
|
140
|
+
await mkdir(join(runtime, "host-home"), { mode: 0o700 });
|
|
141
|
+
return {
|
|
142
|
+
credential: state.credential,
|
|
143
|
+
settingsPath,
|
|
144
|
+
env,
|
|
145
|
+
hooks,
|
|
146
|
+
pluginDirs: effectivePlugins,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/** Claude's implicit /tmp/claude writes cannot contain the read-denied peer namespace. */
|
|
150
|
+
async function requireClaudeRuntimeNamespace(request, stateRoot) {
|
|
151
|
+
if (!request.runtimePolicy &&
|
|
152
|
+
!workspaceBoundaryException(workspaceStatePath(), request.workspace).length)
|
|
153
|
+
return;
|
|
154
|
+
const implicitRoots = await Promise.all(["/tmp/claude", "/private/tmp/claude"].map(implicitClaudeWritePaths));
|
|
155
|
+
const namespace = dirname(stateRoot);
|
|
156
|
+
if (implicitRoots
|
|
157
|
+
.flat()
|
|
158
|
+
.some((root) => inside(root, namespace) || inside(namespace, root)))
|
|
159
|
+
throw new Error("Claude namespace overlaps an implicit native writable root");
|
|
160
|
+
}
|
|
161
|
+
async function implicitClaudeWritePaths(root) {
|
|
162
|
+
try {
|
|
163
|
+
return [root, await realpath(root)];
|
|
164
|
+
}
|
|
165
|
+
catch (cause) {
|
|
166
|
+
if (cause.code !== "ENOENT")
|
|
167
|
+
throw new Error("Claude implicit native writable root is unreadable", {
|
|
168
|
+
cause,
|
|
169
|
+
});
|
|
170
|
+
return [root];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async function claudeTranscriptAccess(stateRoot, credential, request) {
|
|
174
|
+
const policy = request.runtimePolicy;
|
|
175
|
+
if (!policy?.nativeTranscripts)
|
|
176
|
+
return { policy, environment: {}, readRoots: [] };
|
|
177
|
+
const view = join(stateRoot, "native-home");
|
|
178
|
+
const projects = join(view, "projects");
|
|
179
|
+
await mkdir(projects, { recursive: true, mode: 0o700 });
|
|
180
|
+
await symlink(projects, join(dirname(credential), "projects"));
|
|
181
|
+
const startup = join(view, "shell-env");
|
|
182
|
+
const script = `export CLAUDE_CONFIG_DIR=${shellQuote(view)}\n`;
|
|
183
|
+
await writeFile(startup, script, { flag: "wx", mode: 0o600 });
|
|
184
|
+
await writeFile(join(view, ".zshenv"), script, { flag: "wx", mode: 0o600 });
|
|
185
|
+
return {
|
|
186
|
+
policy,
|
|
187
|
+
readRoots: [projects, view],
|
|
188
|
+
environment: {
|
|
189
|
+
SEVRO_NATIVE_TRANSCRIPT_ROOT: projects,
|
|
190
|
+
BASH_ENV: startup,
|
|
191
|
+
ZDOTDIR: view,
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
async function claudeHookMounts(request, stateRoot, privateRoot, pluginDirs, roots) {
|
|
196
|
+
const policy = request.runtimePolicy;
|
|
197
|
+
if (!policy || !runtimeHooksEnabled(policy))
|
|
198
|
+
return undefined;
|
|
199
|
+
return prepareHookMounts({
|
|
200
|
+
workspace: request.workspace,
|
|
201
|
+
stateRoot,
|
|
202
|
+
privateRoot,
|
|
203
|
+
pluginRoots: pluginDirs,
|
|
204
|
+
protectedRoots: [privateRoot, ...roots, ...runtimeSeedSources(policy)],
|
|
205
|
+
policy,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
async function applyClaudeRuntimeEnvironment(request, env, runtime, stateRoot) {
|
|
209
|
+
const isolated = await prepareRuntimeState(request.workspace, claudeCommandPolicy(request), request.runtimeRole ?? "candidate", claudeRuntimeDirectory(request, stateRoot));
|
|
210
|
+
if (request.runtimePolicy) {
|
|
211
|
+
Object.assign(env, isolated.environment);
|
|
212
|
+
env.PATH = [request.fixtureBinDir, isolated.environment.PATH ?? env.PATH]
|
|
213
|
+
.filter(Boolean)
|
|
214
|
+
.join(delimiter);
|
|
215
|
+
return isolated.root;
|
|
216
|
+
}
|
|
217
|
+
applyLegacyClaudeCommandEnvironment(env, isolated, runtime);
|
|
218
|
+
return undefined;
|
|
219
|
+
}
|
|
220
|
+
function claudeRuntimeDirectory(request, stateRoot) {
|
|
221
|
+
return request.runtimePolicy
|
|
222
|
+
? (request.candidateRuntimeRoot ?? join(stateRoot, "runtime"))
|
|
223
|
+
: undefined;
|
|
224
|
+
}
|
|
225
|
+
function applyLegacyClaudeCommandEnvironment(env, isolated, runtime) {
|
|
226
|
+
if (!runtime)
|
|
227
|
+
env.HOME = isolated.home;
|
|
228
|
+
env.TMPDIR = isolated.temp;
|
|
229
|
+
}
|
|
230
|
+
function claudeCommandPolicy(request) {
|
|
231
|
+
return (request.runtimePolicy ?? {
|
|
232
|
+
format: "sevro.runtime.v1",
|
|
233
|
+
environment: {},
|
|
234
|
+
readOnlyRoots: [],
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=claude-state.js.map
|