open-multi-agent-kit 0.96.2 → 0.98.0
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/CHANGELOG.md +51 -0
- package/README.md +43 -9
- package/dist/cli/args.d.ts +2 -3
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +13 -189
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/help.d.ts +3 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +194 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/initial-message.d.ts.map +1 -1
- package/dist/cli/initial-message.js +2 -1
- package/dist/cli/initial-message.js.map +1 -1
- package/dist/cli/resource-paths.d.ts +4 -0
- package/dist/cli/resource-paths.d.ts.map +1 -0
- package/dist/cli/resource-paths.js +59 -0
- package/dist/cli/resource-paths.js.map +1 -0
- package/dist/commands/adaptorch-doctor-cli.d.ts +13 -0
- package/dist/commands/adaptorch-doctor-cli.d.ts.map +1 -0
- package/dist/commands/adaptorch-doctor-cli.js +115 -0
- package/dist/commands/adaptorch-doctor-cli.js.map +1 -0
- package/dist/commands/resource-doctor-cli.d.ts +4 -0
- package/dist/commands/resource-doctor-cli.d.ts.map +1 -1
- package/dist/commands/resource-doctor-cli.js +35 -5
- package/dist/commands/resource-doctor-cli.js.map +1 -1
- package/dist/core/adaptorch-bridge.d.ts +11 -13
- package/dist/core/adaptorch-bridge.d.ts.map +1 -1
- package/dist/core/adaptorch-bridge.js +11 -13
- package/dist/core/adaptorch-bridge.js.map +1 -1
- package/dist/core/agent-session-snapshot.d.ts +16 -0
- package/dist/core/agent-session-snapshot.d.ts.map +1 -0
- package/dist/core/agent-session-snapshot.js +111 -0
- package/dist/core/agent-session-snapshot.js.map +1 -0
- package/dist/core/agent-session.d.ts +14 -10
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +102 -217
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/agent-tool-settings.d.ts +10 -0
- package/dist/core/agent-tool-settings.d.ts.map +1 -1
- package/dist/core/agent-tool-settings.js +10 -1
- package/dist/core/agent-tool-settings.js.map +1 -1
- package/dist/core/attachment-store.d.ts +39 -0
- package/dist/core/attachment-store.d.ts.map +1 -0
- package/dist/core/attachment-store.js +81 -0
- package/dist/core/attachment-store.js.map +1 -0
- package/dist/core/command-safety.d.ts +8 -0
- package/dist/core/command-safety.d.ts.map +1 -1
- package/dist/core/command-safety.js +140 -14
- package/dist/core/command-safety.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +13 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +60 -62
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/index.d.ts +1 -0
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js +1 -0
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/compaction/knowledge-triage-format.d.ts +9 -0
- package/dist/core/compaction/knowledge-triage-format.d.ts.map +1 -0
- package/dist/core/compaction/knowledge-triage-format.js +71 -0
- package/dist/core/compaction/knowledge-triage-format.js.map +1 -0
- package/dist/core/compaction/knowledge-triage-types.d.ts +7 -0
- package/dist/core/compaction/knowledge-triage-types.d.ts.map +1 -0
- package/dist/core/compaction/knowledge-triage-types.js +2 -0
- package/dist/core/compaction/knowledge-triage-types.js.map +1 -0
- package/dist/core/compaction/knowledge-triage.d.ts +29 -0
- package/dist/core/compaction/knowledge-triage.d.ts.map +1 -0
- package/dist/core/compaction/knowledge-triage.js +189 -0
- package/dist/core/compaction/knowledge-triage.js.map +1 -0
- package/dist/core/compaction/transaction.d.ts.map +1 -1
- package/dist/core/compaction/transaction.js +1 -1
- package/dist/core/compaction/transaction.js.map +1 -1
- package/dist/core/compaction/utils.d.ts +4 -0
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +37 -0
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/completion-sound-io.d.ts +14 -0
- package/dist/core/completion-sound-io.d.ts.map +1 -0
- package/dist/core/completion-sound-io.js +64 -0
- package/dist/core/completion-sound-io.js.map +1 -0
- package/dist/core/completion-sound.d.ts +4 -10
- package/dist/core/completion-sound.d.ts.map +1 -1
- package/dist/core/completion-sound.js +28 -58
- package/dist/core/completion-sound.js.map +1 -1
- package/dist/core/context-budget-governor-v2.d.ts +1 -1
- package/dist/core/context-budget-governor-v2.d.ts.map +1 -1
- package/dist/core/context-budget-governor-v2.js +1 -1
- package/dist/core/context-budget-governor-v2.js.map +1 -1
- package/dist/core/context-budget-relevance.d.ts +15 -2
- package/dist/core/context-budget-relevance.d.ts.map +1 -1
- package/dist/core/context-budget-relevance.js +21 -9
- package/dist/core/context-budget-relevance.js.map +1 -1
- package/dist/core/context-budget-system-prompt-items.d.ts +1 -1
- package/dist/core/context-budget-system-prompt-items.d.ts.map +1 -1
- package/dist/core/context-budget-system-prompt-items.js.map +1 -1
- package/dist/core/context-budget-system-prompt.d.ts +1 -1
- package/dist/core/context-budget-system-prompt.d.ts.map +1 -1
- package/dist/core/context-budget-system-prompt.js.map +1 -1
- package/dist/core/context-budget-v2-cache-keys.d.ts +3 -0
- package/dist/core/context-budget-v2-cache-keys.d.ts.map +1 -1
- package/dist/core/context-budget-v2-cache-keys.js +2 -0
- package/dist/core/context-budget-v2-cache-keys.js.map +1 -1
- package/dist/core/context-budget-v2-plan-cache-keys.d.ts.map +1 -1
- package/dist/core/context-budget-v2-plan-cache-keys.js +3 -0
- package/dist/core/context-budget-v2-plan-cache-keys.js.map +1 -1
- package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
- package/dist/core/context-budget-v2-planner.js +2 -1
- package/dist/core/context-budget-v2-planner.js.map +1 -1
- package/dist/core/context-budget-v2-scoring.d.ts +17 -0
- package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
- package/dist/core/context-budget-v2-scoring.js +25 -8
- package/dist/core/context-budget-v2-scoring.js.map +1 -1
- package/dist/core/context-budget-v2-selection.d.ts +2 -2
- package/dist/core/context-budget-v2-selection.d.ts.map +1 -1
- package/dist/core/context-budget-v2-selection.js +18 -1
- package/dist/core/context-budget-v2-selection.js.map +1 -1
- package/dist/core/context-budget-v2-types.d.ts +17 -0
- package/dist/core/context-budget-v2-types.d.ts.map +1 -1
- package/dist/core/context-budget-v2-types.js +15 -0
- package/dist/core/context-budget-v2-types.js.map +1 -1
- package/dist/core/context-file.d.ts +23 -0
- package/dist/core/context-file.d.ts.map +1 -0
- package/dist/core/context-file.js +17 -0
- package/dist/core/context-file.js.map +1 -0
- package/dist/core/extensions/builtin/command-safety-gate.d.ts +3 -1
- package/dist/core/extensions/builtin/command-safety-gate.d.ts.map +1 -1
- package/dist/core/extensions/builtin/command-safety-gate.js +7 -0
- package/dist/core/extensions/builtin/command-safety-gate.js.map +1 -1
- package/dist/core/extensions/types.d.ts +12 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/keybindings.d.ts +1 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +6 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-prompt-policy.d.ts +1 -1
- package/dist/core/model-prompt-policy.d.ts.map +1 -1
- package/dist/core/model-prompt-policy.js.map +1 -1
- package/dist/core/model-registry.d.ts +8 -3
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +71 -1
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/package-doctor-source-scan.d.ts +9 -0
- package/dist/core/package-doctor-source-scan.d.ts.map +1 -1
- package/dist/core/package-doctor-source-scan.js +77 -4
- package/dist/core/package-doctor-source-scan.js.map +1 -1
- package/dist/core/prompt-attachment.d.ts +51 -0
- package/dist/core/prompt-attachment.d.ts.map +1 -0
- package/dist/core/prompt-attachment.js +186 -0
- package/dist/core/prompt-attachment.js.map +1 -0
- package/dist/core/prompt-settlement.d.ts +6 -3
- package/dist/core/prompt-settlement.d.ts.map +1 -1
- package/dist/core/prompt-settlement.js +10 -14
- package/dist/core/prompt-settlement.js.map +1 -1
- package/dist/core/provider-resilience.d.ts +28 -0
- package/dist/core/provider-resilience.d.ts.map +1 -1
- package/dist/core/provider-resilience.js +50 -0
- package/dist/core/provider-resilience.js.map +1 -1
- package/dist/core/provider-retry.d.ts +1 -1
- package/dist/core/provider-retry.d.ts.map +1 -1
- package/dist/core/provider-retry.js +1 -1
- package/dist/core/provider-retry.js.map +1 -1
- package/dist/core/provider-usage.d.ts.map +1 -1
- package/dist/core/provider-usage.js +68 -2
- package/dist/core/provider-usage.js.map +1 -1
- package/dist/core/reasoning-router-promotion.d.ts +124 -0
- package/dist/core/reasoning-router-promotion.d.ts.map +1 -0
- package/dist/core/reasoning-router-promotion.js +121 -0
- package/dist/core/reasoning-router-promotion.js.map +1 -0
- package/dist/core/reasoning-router-replay-stability.d.ts +65 -0
- package/dist/core/reasoning-router-replay-stability.d.ts.map +1 -0
- package/dist/core/reasoning-router-replay-stability.js +67 -0
- package/dist/core/reasoning-router-replay-stability.js.map +1 -0
- package/dist/core/reasoning-router-v4-weights.d.ts +6 -6
- package/dist/core/reasoning-router-v4-weights.d.ts.map +1 -1
- package/dist/core/reasoning-router-v4-weights.js +3 -3
- package/dist/core/reasoning-router-v4-weights.js.map +1 -1
- package/dist/core/reasoning-router-v4.d.ts.map +1 -1
- package/dist/core/reasoning-router-v4.js +6 -6
- package/dist/core/reasoning-router-v4.js.map +1 -1
- package/dist/core/redaction.d.ts.map +1 -1
- package/dist/core/redaction.js +1 -1
- package/dist/core/redaction.js.map +1 -1
- package/dist/core/resource-admission.d.ts +2 -1
- package/dist/core/resource-admission.d.ts.map +1 -1
- package/dist/core/resource-admission.js +11 -0
- package/dist/core/resource-admission.js.map +1 -1
- package/dist/core/resource-governor-format.d.ts +1 -1
- package/dist/core/resource-governor-format.d.ts.map +1 -1
- package/dist/core/resource-governor-format.js.map +1 -1
- package/dist/core/resource-governor-settings.d.ts +6 -12
- package/dist/core/resource-governor-settings.d.ts.map +1 -1
- package/dist/core/resource-governor-settings.js.map +1 -1
- package/dist/core/resource-governor-types.d.ts +24 -0
- package/dist/core/resource-governor-types.d.ts.map +1 -0
- package/dist/core/resource-governor-types.js +15 -0
- package/dist/core/resource-governor-types.js.map +1 -0
- package/dist/core/resource-loader.d.ts +1 -7
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/resource-observation-journal.d.ts +2 -1
- package/dist/core/resource-observation-journal.d.ts.map +1 -1
- package/dist/core/resource-observation-journal.js +4 -3
- package/dist/core/resource-observation-journal.js.map +1 -1
- package/dist/core/resource-observation-report-reader.d.ts +7 -0
- package/dist/core/resource-observation-report-reader.d.ts.map +1 -0
- package/dist/core/resource-observation-report-reader.js +157 -0
- package/dist/core/resource-observation-report-reader.js.map +1 -0
- package/dist/core/resource-observation-report.d.ts +24 -0
- package/dist/core/resource-observation-report.d.ts.map +1 -0
- package/dist/core/resource-observation-report.js +101 -0
- package/dist/core/resource-observation-report.js.map +1 -0
- package/dist/core/router-feedback-collector.d.ts +1 -1
- package/dist/core/router-feedback-collector.d.ts.map +1 -1
- package/dist/core/router-feedback-collector.js.map +1 -1
- package/dist/core/session-bash-service.d.ts.map +1 -1
- package/dist/core/session-bash-service.js +4 -3
- package/dist/core/session-bash-service.js.map +1 -1
- package/dist/core/session-failure-cause.d.ts +33 -0
- package/dist/core/session-failure-cause.d.ts.map +1 -0
- package/dist/core/session-failure-cause.js +141 -0
- package/dist/core/session-failure-cause.js.map +1 -0
- package/dist/core/session-system-prompt.d.ts +1 -1
- package/dist/core/session-system-prompt.d.ts.map +1 -1
- package/dist/core/session-system-prompt.js.map +1 -1
- package/dist/core/session-termination.d.ts +1 -1
- package/dist/core/session-termination.d.ts.map +1 -1
- package/dist/core/session-termination.js +11 -2
- package/dist/core/session-termination.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +10 -14
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +13 -48
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -34
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/workload-classifier.d.ts +2 -10
- package/dist/core/workload-classifier.d.ts.map +1 -1
- package/dist/core/workload-classifier.js +17 -0
- package/dist/core/workload-classifier.js.map +1 -1
- package/dist/core/workload-family-matcher.d.ts +1 -1
- package/dist/core/workload-family-matcher.d.ts.map +1 -1
- package/dist/core/workload-family-matcher.js.map +1 -1
- package/dist/core/workload-shard-execution-types.d.ts +40 -0
- package/dist/core/workload-shard-execution-types.d.ts.map +1 -0
- package/dist/core/workload-shard-execution-types.js +14 -0
- package/dist/core/workload-shard-execution-types.js.map +1 -0
- package/dist/core/workload-shard-executor.d.ts +3 -27
- package/dist/core/workload-shard-executor.d.ts.map +1 -1
- package/dist/core/workload-shard-executor.js.map +1 -1
- package/dist/core/workload-shard-runner.d.ts +1 -1
- package/dist/core/workload-shard-runner.d.ts.map +1 -1
- package/dist/core/workload-shard-runner.js.map +1 -1
- package/dist/core/workload-types.d.ts +24 -0
- package/dist/core/workload-types.d.ts.map +1 -0
- package/dist/core/workload-types.js +15 -0
- package/dist/core/workload-types.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +2 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +27 -47
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/attachment-strip.d.ts +21 -0
- package/dist/modes/interactive/components/attachment-strip.d.ts.map +1 -0
- package/dist/modes/interactive/components/attachment-strip.js +136 -0
- package/dist/modes/interactive/components/attachment-strip.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts +6 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +26 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/status-sidebar.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-sidebar.js +12 -1
- package/dist/modes/interactive/components/status-sidebar.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +23 -4
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +174 -53
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/omk-control-panel.json +1 -1
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +42 -33
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +14 -2
- package/dist/utils/clipboard.js.map +1 -1
- package/docs/adaptorch-preview-spec.md +20 -18
- package/docs/adaptorch-preview.md +9 -9
- package/docs/compaction.md +25 -4
- package/docs/correctness-wall.md +10 -10
- package/docs/docs.json +12 -0
- package/docs/environment-variables.md +9 -2
- package/docs/extensions.md +12 -3
- package/docs/index.md +7 -1
- package/docs/metrics.md +74 -2
- package/docs/provider-resilience.md +11 -0
- package/docs/runtime-algorithms.md +359 -0
- package/docs/sdk.md +2 -2
- package/docs/settings.md +11 -10
- package/docs/usage.md +19 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +18 -18
- package/package.json +7 -7
- package/dist/core/context-budget-governor.d.ts +0 -67
- package/dist/core/context-budget-governor.d.ts.map +0 -1
- package/dist/core/context-budget-governor.js +0 -224
- package/dist/core/context-budget-governor.js.map +0 -1
- package/dist/core/lean-ctx.d.ts +0 -99
- package/dist/core/lean-ctx.d.ts.map +0 -1
- package/dist/core/lean-ctx.js +0 -225
- package/dist/core/lean-ctx.js.map +0 -1
- package/dist/core/read-anchors.d.ts +0 -110
- package/dist/core/read-anchors.d.ts.map +0 -1
- package/dist/core/read-anchors.js +0 -193
- package/dist/core/read-anchors.js.map +0 -1
- package/dist/core/recovery-checkpoint.d.ts +0 -196
- package/dist/core/recovery-checkpoint.d.ts.map +0 -1
- package/dist/core/recovery-checkpoint.js +0 -382
- package/dist/core/recovery-checkpoint.js.map +0 -1
- package/dist/core/sandbox-policy-v2.d.ts +0 -49
- package/dist/core/sandbox-policy-v2.d.ts.map +0 -1
- package/dist/core/sandbox-policy-v2.js +0 -368
- package/dist/core/sandbox-policy-v2.js.map +0 -1
- package/dist/core/tools/omp-pure-seams.d.ts +0 -41
- package/dist/core/tools/omp-pure-seams.d.ts.map +0 -1
- package/dist/core/tools/omp-pure-seams.js +0 -142
- package/dist/core/tools/omp-pure-seams.js.map +0 -1
- package/dist/core/tools/omp-seam-runtime.d.ts +0 -100
- package/dist/core/tools/omp-seam-runtime.d.ts.map +0 -1
- package/dist/core/tools/omp-seam-runtime.js +0 -40
- package/dist/core/tools/omp-seam-runtime.js.map +0 -1
- package/dist/guardrails/audit-logger.d.ts +0 -4
- package/dist/guardrails/audit-logger.d.ts.map +0 -1
- package/dist/guardrails/audit-logger.js +0 -28
- package/dist/guardrails/audit-logger.js.map +0 -1
- package/dist/guardrails/freedomd-adapter.d.ts +0 -16
- package/dist/guardrails/freedomd-adapter.d.ts.map +0 -1
- package/dist/guardrails/freedomd-adapter.js +0 -87
- package/dist/guardrails/freedomd-adapter.js.map +0 -1
- package/dist/orchestration/lane-grant-auditor.d.ts +0 -4
- package/dist/orchestration/lane-grant-auditor.d.ts.map +0 -1
- package/dist/orchestration/lane-grant-auditor.js +0 -87
- package/dist/orchestration/lane-grant-auditor.js.map +0 -1
- package/dist/types/guardrails.d.ts +0 -61
- package/dist/types/guardrails.d.ts.map +0 -1
- package/dist/types/guardrails.js +0 -9
- package/dist/types/guardrails.js.map +0 -1
- package/dist/types/lane-grant.d.ts +0 -58
- package/dist/types/lane-grant.d.ts.map +0 -1
- package/dist/types/lane-grant.js +0 -9
- package/dist/types/lane-grant.js.map +0 -1
|
@@ -1,368 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lane SA3 - Sandbox Policy V2.
|
|
3
|
-
* allow: SIZE_OK - legacy evaluator; this change only keeps strip-only TypeScript compatibility.
|
|
4
|
-
*
|
|
5
|
-
* Pure fail-closed evaluator that composes path / env / network checks for a
|
|
6
|
-
* sandbox policy. It layers general glob matching (via `minimatch`), realpath
|
|
7
|
-
* normalization (when a resolver is provided), denied-env fail-closed
|
|
8
|
-
* semantics, and IPv4 / IPv6 loopback detection on top of the existing
|
|
9
|
-
* `SandboxPolicy` types. It does not spawn, resolve through the filesystem on
|
|
10
|
-
* its own, or log env values.
|
|
11
|
-
*/
|
|
12
|
-
import path from "node:path";
|
|
13
|
-
import { minimatch } from "minimatch";
|
|
14
|
-
/** Exact sensitive environment variable names (do not end in a standard suffix). */
|
|
15
|
-
const SENSITIVE_ENV_EXACT = new Set([
|
|
16
|
-
"AWS_ACCESS_KEY_ID",
|
|
17
|
-
"AWS_SECRET_ACCESS_KEY",
|
|
18
|
-
"AWS_SESSION_TOKEN",
|
|
19
|
-
"GITHUB_TOKEN",
|
|
20
|
-
"GH_TOKEN",
|
|
21
|
-
"GITLAB_TOKEN",
|
|
22
|
-
"NPM_TOKEN",
|
|
23
|
-
"NODE_AUTH_TOKEN",
|
|
24
|
-
]);
|
|
25
|
-
/** Sensitive environment variable name suffixes. */
|
|
26
|
-
const SENSITIVE_ENV_REGEX = /(^|_)(API_KEY|API_TOKEN|ACCESS_TOKEN|SECRET|SECRET_KEY|PRIVATE_KEY|PASSWORD|PASSWD|TOKEN)$/i;
|
|
27
|
-
/**
|
|
28
|
-
* Environment variable names that are always denied because they inject code
|
|
29
|
-
* or redirect runtime loader behavior. Denial is fail-closed: presence of any
|
|
30
|
-
* of these names blocks the policy evaluation regardless of value.
|
|
31
|
-
*/
|
|
32
|
-
const ENV_DENY_NAMES = new Set([
|
|
33
|
-
"LD_PRELOAD",
|
|
34
|
-
"LD_LIBRARY_PATH",
|
|
35
|
-
"LD_AUDIT",
|
|
36
|
-
"LD_BIND_NOW",
|
|
37
|
-
"LD_PROFILE",
|
|
38
|
-
"DYLD_INSERT_LIBRARIES",
|
|
39
|
-
"DYLD_LIBRARY_PATH",
|
|
40
|
-
"DYLD_FALLBACK_LIBRARY_PATH",
|
|
41
|
-
"NODE_OPTIONS",
|
|
42
|
-
"NODE_PATH",
|
|
43
|
-
"NODE_REPL_EXTERNAL_MODULE",
|
|
44
|
-
"NODE_EXTRA_CA_CERTS",
|
|
45
|
-
"NODE_TLS_REJECT_UNAUTHORIZED",
|
|
46
|
-
"PYTHONPATH",
|
|
47
|
-
"PYTHONHOME",
|
|
48
|
-
"PYTHONSTARTUP",
|
|
49
|
-
"PYTHONINSPECT",
|
|
50
|
-
"PERL5LIB",
|
|
51
|
-
"PERLLIB",
|
|
52
|
-
"PERL5OPT",
|
|
53
|
-
"RUBYLIB",
|
|
54
|
-
"RUBYOPT",
|
|
55
|
-
"RUBYPATH",
|
|
56
|
-
"JAVA_TOOL_OPTIONS",
|
|
57
|
-
"_JAVA_OPTIONS",
|
|
58
|
-
"JDK_JAVA_OPTIONS",
|
|
59
|
-
"MAVEN_OPTS",
|
|
60
|
-
]);
|
|
61
|
-
/**
|
|
62
|
-
* Matches a URL / DSN with embedded userinfo (`scheme://user:pass@host`).
|
|
63
|
-
* Used for value-based denial; only the variable NAME is ever recorded.
|
|
64
|
-
*/
|
|
65
|
-
const AUTH_URL_REGEX = /^[a-z][a-z0-9+.-]*:\/\/[^\s/@:]+:[^\s/@]+@[^\s/@]/i;
|
|
66
|
-
/** Path patterns that look like credential / key material on disk. */
|
|
67
|
-
const SENSITIVE_PATH_REGEX = /(?:^|[/\\])(?:\.env(?:\..*)?|auth\.json|oauth\.json|\.netrc|\.npmrc|\.pgpass|credentials|id_rsa|id_dsa|id_ecdsa|id_ed25519|.*(?:token|private[_-]?key|credential).*)$/i;
|
|
68
|
-
function isSensitiveEnvName(name) {
|
|
69
|
-
if (SENSITIVE_ENV_EXACT.has(name))
|
|
70
|
-
return true;
|
|
71
|
-
return SENSITIVE_ENV_REGEX.test(name);
|
|
72
|
-
}
|
|
73
|
-
function normalizePathValue(value) {
|
|
74
|
-
const resolved = path.resolve(value);
|
|
75
|
-
let normalized = resolved.replace(/\\/g, "/");
|
|
76
|
-
if (normalized.length > 1)
|
|
77
|
-
normalized = normalized.replace(/\/+$/, "");
|
|
78
|
-
return normalized;
|
|
79
|
-
}
|
|
80
|
-
function ruleHasGlob(pattern) {
|
|
81
|
-
return /[*?[\]{}]/.test(pattern);
|
|
82
|
-
}
|
|
83
|
-
function matchesRule(pattern, candidate) {
|
|
84
|
-
const normPattern = normalizePathValue(pattern);
|
|
85
|
-
const normCandidate = normalizePathValue(candidate);
|
|
86
|
-
if (ruleHasGlob(normPattern)) {
|
|
87
|
-
if (minimatch(normCandidate, normPattern))
|
|
88
|
-
return true;
|
|
89
|
-
// also accept recursive prefix form even if the writer omitted `/**`
|
|
90
|
-
return minimatch(normCandidate, `${normPattern}/**`);
|
|
91
|
-
}
|
|
92
|
-
return normCandidate === normPattern || normCandidate.startsWith(`${normPattern}/`);
|
|
93
|
-
}
|
|
94
|
-
function matchesAny(patterns, candidate) {
|
|
95
|
-
for (const pattern of patterns) {
|
|
96
|
-
if (matchesRule(pattern, candidate))
|
|
97
|
-
return { match: true, pattern };
|
|
98
|
-
}
|
|
99
|
-
return { match: false };
|
|
100
|
-
}
|
|
101
|
-
function isInsideRoot(root, candidate) {
|
|
102
|
-
const normRoot = normalizePathValue(root);
|
|
103
|
-
const normCandidate = normalizePathValue(candidate);
|
|
104
|
-
return normCandidate === normRoot || normCandidate.startsWith(`${normRoot}/`);
|
|
105
|
-
}
|
|
106
|
-
function isSensitivePath(value) {
|
|
107
|
-
return SENSITIVE_PATH_REGEX.test(value.replace(/\\/g, "/"));
|
|
108
|
-
}
|
|
109
|
-
/** True for IPv4 / IPv6 loopback and localhost hostnames. */
|
|
110
|
-
function isLoopbackHost(host) {
|
|
111
|
-
const h = host
|
|
112
|
-
.toLowerCase()
|
|
113
|
-
.replace(/^\[|\]$/g, "")
|
|
114
|
-
.trim();
|
|
115
|
-
if (h === "localhost")
|
|
116
|
-
return true;
|
|
117
|
-
if (h === "127.0.0.1" || h === "::1" || h === "0:0:0:0:0:0:0:1")
|
|
118
|
-
return true;
|
|
119
|
-
if (h === "::ffff:127.0.0.1" || h === "::ffff:7f00:1")
|
|
120
|
-
return true;
|
|
121
|
-
if (/^127\./.test(h))
|
|
122
|
-
return true;
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
function normalizeNetworkLoopback(request) {
|
|
126
|
-
let host = request.host;
|
|
127
|
-
if (!host && request.url) {
|
|
128
|
-
try {
|
|
129
|
-
host = new URL(request.url).hostname;
|
|
130
|
-
}
|
|
131
|
-
catch {
|
|
132
|
-
host = undefined;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
if (host && isLoopbackHost(host)) {
|
|
136
|
-
return { ...request, host, loopback: true };
|
|
137
|
-
}
|
|
138
|
-
return request;
|
|
139
|
-
}
|
|
140
|
-
function hostFromRequest(request) {
|
|
141
|
-
if (request.host)
|
|
142
|
-
return request.host.toLowerCase();
|
|
143
|
-
if (!request.url)
|
|
144
|
-
return undefined;
|
|
145
|
-
try {
|
|
146
|
-
return new URL(request.url).hostname.toLowerCase();
|
|
147
|
-
}
|
|
148
|
-
catch {
|
|
149
|
-
return undefined;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
function hostMatches(patterns, host) {
|
|
153
|
-
const h = host.replace(/\.$/, "");
|
|
154
|
-
for (const raw of patterns) {
|
|
155
|
-
const p = raw.toLowerCase().replace(/\.$/, "");
|
|
156
|
-
if (h === p || h.endsWith(`.${p}`))
|
|
157
|
-
return true;
|
|
158
|
-
}
|
|
159
|
-
return false;
|
|
160
|
-
}
|
|
161
|
-
function decideNetworkV2(policy, request) {
|
|
162
|
-
if (policy.mode === "off")
|
|
163
|
-
return { allowed: true, rule: "sandbox.off", reason: "Sandbox policy is disabled." };
|
|
164
|
-
if (request.browser || request.unixSocketPath) {
|
|
165
|
-
return {
|
|
166
|
-
allowed: false,
|
|
167
|
-
rule: "network.socket_or_browser",
|
|
168
|
-
reason: "Browser and Unix socket access is denied by default.",
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
if (policy.network.mode === "none") {
|
|
172
|
-
return { allowed: false, rule: "network.none", reason: "Network access is disabled by policy." };
|
|
173
|
-
}
|
|
174
|
-
if (request.loopback) {
|
|
175
|
-
if (policy.network.mode === "loopback" ||
|
|
176
|
-
policy.network.mode === "domain-allowlist" ||
|
|
177
|
-
policy.network.mode === "all-explicit") {
|
|
178
|
-
return { allowed: true, rule: "network.loopback", reason: "Loopback access is allowed." };
|
|
179
|
-
}
|
|
180
|
-
return { allowed: false, rule: "network.loopback_denied", reason: "Loopback access is denied." };
|
|
181
|
-
}
|
|
182
|
-
const host = hostFromRequest(request);
|
|
183
|
-
if (!host)
|
|
184
|
-
return {
|
|
185
|
-
allowed: false,
|
|
186
|
-
rule: "network.unknown_host",
|
|
187
|
-
reason: "Network host could not be resolved from request.",
|
|
188
|
-
};
|
|
189
|
-
if (hostMatches(policy.network.deniedDomains, host)) {
|
|
190
|
-
return { allowed: false, rule: "network.domain_deny", reason: "Host matches a denied domain." };
|
|
191
|
-
}
|
|
192
|
-
if (policy.network.mode === "all-explicit") {
|
|
193
|
-
return {
|
|
194
|
-
allowed: true,
|
|
195
|
-
rule: "network.explicit_all",
|
|
196
|
-
reason: "Explicit network profile allows outbound host access.",
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
if (policy.network.mode === "domain-allowlist" && hostMatches(policy.network.allowedDomains, host)) {
|
|
200
|
-
return { allowed: true, rule: "network.domain_allow", reason: "Host matches an allowed domain." };
|
|
201
|
-
}
|
|
202
|
-
return { allowed: false, rule: "network.domain_not_allowed", reason: "Host is not allowed by network policy." };
|
|
203
|
-
}
|
|
204
|
-
function decidePathV2(policy, request, resolver) {
|
|
205
|
-
const requested = request.path;
|
|
206
|
-
const base = (rule, reason, candidate, action, matchedPattern) => ({
|
|
207
|
-
requestedPath: requested,
|
|
208
|
-
candidate,
|
|
209
|
-
kind: request.kind,
|
|
210
|
-
action,
|
|
211
|
-
rule,
|
|
212
|
-
reason,
|
|
213
|
-
matchedPattern,
|
|
214
|
-
});
|
|
215
|
-
const block = (rule, reason, candidate, matchedPattern) => base(rule, reason, candidate, "block", matchedPattern);
|
|
216
|
-
const allow = (rule, reason, candidate) => base(rule, reason, candidate, "allow");
|
|
217
|
-
if (requested.includes("\0")) {
|
|
218
|
-
return block("path.invalid", "Path contains a NUL byte.", requested);
|
|
219
|
-
}
|
|
220
|
-
let candidate;
|
|
221
|
-
let isSymlink = false;
|
|
222
|
-
if (resolver) {
|
|
223
|
-
const resolved = resolver(requested);
|
|
224
|
-
if (resolved.error) {
|
|
225
|
-
return block("path.resolve_error", resolved.error, requested);
|
|
226
|
-
}
|
|
227
|
-
candidate = resolved.realPath ?? resolved.nearestExistingParentRealPath ?? normalizePathValue(requested);
|
|
228
|
-
isSymlink = resolved.isSymlink === true;
|
|
229
|
-
}
|
|
230
|
-
else {
|
|
231
|
-
candidate = normalizePathValue(requested);
|
|
232
|
-
}
|
|
233
|
-
if (isSensitivePath(requested) || isSensitivePath(candidate)) {
|
|
234
|
-
return block("path.sensitive", "Sensitive credential-like path is denied.", candidate);
|
|
235
|
-
}
|
|
236
|
-
if (!isInsideRoot(policy.filesystem.root, candidate)) {
|
|
237
|
-
return block("path.root_escape", "Resolved path is outside the sandbox root.", candidate);
|
|
238
|
-
}
|
|
239
|
-
if (isSymlink && !policy.filesystem.followSymlinks) {
|
|
240
|
-
return block("path.symlink", "Symlink traversal is denied by policy.", candidate);
|
|
241
|
-
}
|
|
242
|
-
if (request.kind === "read") {
|
|
243
|
-
const denied = matchesAny(policy.filesystem.readDeny, candidate);
|
|
244
|
-
if (denied.match) {
|
|
245
|
-
return block("path.read_deny", "Read path matches a deny rule.", candidate, denied.pattern);
|
|
246
|
-
}
|
|
247
|
-
const deniedRequested = matchesAny(policy.filesystem.readDeny, requested);
|
|
248
|
-
if (deniedRequested.match) {
|
|
249
|
-
return block("path.read_deny", "Read path matches a deny rule.", candidate, deniedRequested.pattern);
|
|
250
|
-
}
|
|
251
|
-
if (matchesAny(policy.filesystem.readAllow, candidate).match) {
|
|
252
|
-
return allow("path.read_allow", "Read path is allowed.", candidate);
|
|
253
|
-
}
|
|
254
|
-
return block("path.read_not_allowed", "Read path is not in an allow rule.", candidate);
|
|
255
|
-
}
|
|
256
|
-
const denyWriteCandidate = matchesAny(policy.filesystem.denyWrite, candidate);
|
|
257
|
-
if (denyWriteCandidate.match) {
|
|
258
|
-
return block("path.deny_write", "Write path matches an unoverrideable denyWrite rule.", candidate, denyWriteCandidate.pattern);
|
|
259
|
-
}
|
|
260
|
-
const denyWriteRequested = matchesAny(policy.filesystem.denyWrite, requested);
|
|
261
|
-
if (denyWriteRequested.match) {
|
|
262
|
-
return block("path.deny_write", "Write path matches an unoverrideable denyWrite rule.", candidate, denyWriteRequested.pattern);
|
|
263
|
-
}
|
|
264
|
-
if (matchesAny(policy.filesystem.writeAllow, candidate).match ||
|
|
265
|
-
matchesAny(policy.filesystem.tempWrite, candidate).match) {
|
|
266
|
-
return allow("path.write_allow", "Write path is allowed.", candidate);
|
|
267
|
-
}
|
|
268
|
-
return block("path.write_not_allowed", "Write path is not in an allow rule.", candidate);
|
|
269
|
-
}
|
|
270
|
-
function decideEnvV2(env) {
|
|
271
|
-
const denied = [];
|
|
272
|
-
for (const [name, value] of Object.entries(env)) {
|
|
273
|
-
if (value === undefined)
|
|
274
|
-
continue;
|
|
275
|
-
if (ENV_DENY_NAMES.has(name)) {
|
|
276
|
-
denied.push(name);
|
|
277
|
-
continue;
|
|
278
|
-
}
|
|
279
|
-
if (isSensitiveEnvName(name)) {
|
|
280
|
-
denied.push(name);
|
|
281
|
-
continue;
|
|
282
|
-
}
|
|
283
|
-
if (AUTH_URL_REGEX.test(value)) {
|
|
284
|
-
// Value-based denial: the value embeds credentials. Record NAME only.
|
|
285
|
-
denied.push(name);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
if (denied.length > 0) {
|
|
289
|
-
return {
|
|
290
|
-
action: "block",
|
|
291
|
-
rule: "env.denied_pattern",
|
|
292
|
-
reason: `Environment contains denied variable(s): ${denied.join(", ")}.`,
|
|
293
|
-
deniedNames: denied,
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
return { action: "allow", rule: "env.allow", reason: "No denied environment variables.", deniedNames: [] };
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* Public: evaluate path / env / network requests against a sandbox policy.
|
|
300
|
-
* Path and env checks are fail-closed. Audit mode downgrades a would-block
|
|
301
|
-
* outcome to confirm; enforce mode keeps it block.
|
|
302
|
-
*/
|
|
303
|
-
export function evaluateSandboxPolicyV2(input) {
|
|
304
|
-
const { policy } = input;
|
|
305
|
-
const diagnostics = [];
|
|
306
|
-
const pathDecisions = [];
|
|
307
|
-
let envDecision;
|
|
308
|
-
let networkDecision;
|
|
309
|
-
let worst = "block";
|
|
310
|
-
if (policy.mode === "off") {
|
|
311
|
-
return {
|
|
312
|
-
action: "allow",
|
|
313
|
-
rule: "sandbox.off",
|
|
314
|
-
reason: "Sandbox policy is disabled.",
|
|
315
|
-
diagnostics,
|
|
316
|
-
pathDecisions,
|
|
317
|
-
};
|
|
318
|
-
}
|
|
319
|
-
// Default to allow and escalate to block on any failed check.
|
|
320
|
-
worst = "allow";
|
|
321
|
-
if (input.env) {
|
|
322
|
-
envDecision = decideEnvV2(input.env);
|
|
323
|
-
if (envDecision.action === "block") {
|
|
324
|
-
worst = "block";
|
|
325
|
-
diagnostics.push({
|
|
326
|
-
code: envDecision.rule,
|
|
327
|
-
message: `Denied env name(s): ${envDecision.deniedNames.join(", ")}`,
|
|
328
|
-
severity: "block",
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
for (const request of input.pathRequests ?? []) {
|
|
333
|
-
const decision = decidePathV2(policy, request, input.resolver);
|
|
334
|
-
pathDecisions.push(decision);
|
|
335
|
-
if (decision.action === "block") {
|
|
336
|
-
worst = "block";
|
|
337
|
-
diagnostics.push({ code: decision.rule, message: decision.reason, severity: "block" });
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
if (input.networkRequest) {
|
|
341
|
-
const normalized = normalizeNetworkLoopback(input.networkRequest);
|
|
342
|
-
networkDecision = decideNetworkV2(policy, normalized);
|
|
343
|
-
if (!networkDecision.allowed) {
|
|
344
|
-
worst = "block";
|
|
345
|
-
diagnostics.push({ code: networkDecision.rule, message: networkDecision.reason, severity: "block" });
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
let action;
|
|
349
|
-
let rule;
|
|
350
|
-
let reason;
|
|
351
|
-
if (worst === "allow") {
|
|
352
|
-
action = "allow";
|
|
353
|
-
rule = "policy.composite_allow";
|
|
354
|
-
reason = "All sandbox checks passed.";
|
|
355
|
-
}
|
|
356
|
-
else if (policy.mode === "audit") {
|
|
357
|
-
action = "confirm";
|
|
358
|
-
rule = "policy.audit_block";
|
|
359
|
-
reason = "Audit mode: a would-block check is downgraded to confirm.";
|
|
360
|
-
}
|
|
361
|
-
else {
|
|
362
|
-
action = "block";
|
|
363
|
-
rule = "policy.block";
|
|
364
|
-
reason = "One or more sandbox checks blocked the request.";
|
|
365
|
-
}
|
|
366
|
-
return { action, rule, reason, diagnostics, pathDecisions, networkDecision, envDecision };
|
|
367
|
-
}
|
|
368
|
-
//# sourceMappingURL=sandbox-policy-v2.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-policy-v2.js","sourceRoot":"","sources":["../../src/core/sandbox-policy-v2.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Lane SA3 - Sandbox Policy V2.\n * allow: SIZE_OK - legacy evaluator; this change only keeps strip-only TypeScript compatibility.\n *\n * Pure fail-closed evaluator that composes path / env / network checks for a\n * sandbox policy. It layers general glob matching (via `minimatch`), realpath\n * normalization (when a resolver is provided), denied-env fail-closed\n * semantics, and IPv4 / IPv6 loopback detection on top of the existing\n * `SandboxPolicy` types. It does not spawn, resolve through the filesystem on\n * its own, or log env values.\n */\nimport path from \"node:path\";\nimport { minimatch } from \"minimatch\";\nimport type {\n\tNetworkAccessRequest,\n\tPathAccessKind,\n\tSandboxDecision,\n\tSandboxPathResolver,\n\tSandboxPolicy,\n} from \"./sandbox/policy.ts\";\n\n/** Exact sensitive environment variable names (do not end in a standard suffix). */\nconst SENSITIVE_ENV_EXACT = new Set<string>([\n\t\"AWS_ACCESS_KEY_ID\",\n\t\"AWS_SECRET_ACCESS_KEY\",\n\t\"AWS_SESSION_TOKEN\",\n\t\"GITHUB_TOKEN\",\n\t\"GH_TOKEN\",\n\t\"GITLAB_TOKEN\",\n\t\"NPM_TOKEN\",\n\t\"NODE_AUTH_TOKEN\",\n]);\n\n/** Sensitive environment variable name suffixes. */\nconst SENSITIVE_ENV_REGEX =\n\t/(^|_)(API_KEY|API_TOKEN|ACCESS_TOKEN|SECRET|SECRET_KEY|PRIVATE_KEY|PASSWORD|PASSWD|TOKEN)$/i;\n\n/**\n * Environment variable names that are always denied because they inject code\n * or redirect runtime loader behavior. Denial is fail-closed: presence of any\n * of these names blocks the policy evaluation regardless of value.\n */\nconst ENV_DENY_NAMES = new Set<string>([\n\t\"LD_PRELOAD\",\n\t\"LD_LIBRARY_PATH\",\n\t\"LD_AUDIT\",\n\t\"LD_BIND_NOW\",\n\t\"LD_PROFILE\",\n\t\"DYLD_INSERT_LIBRARIES\",\n\t\"DYLD_LIBRARY_PATH\",\n\t\"DYLD_FALLBACK_LIBRARY_PATH\",\n\t\"NODE_OPTIONS\",\n\t\"NODE_PATH\",\n\t\"NODE_REPL_EXTERNAL_MODULE\",\n\t\"NODE_EXTRA_CA_CERTS\",\n\t\"NODE_TLS_REJECT_UNAUTHORIZED\",\n\t\"PYTHONPATH\",\n\t\"PYTHONHOME\",\n\t\"PYTHONSTARTUP\",\n\t\"PYTHONINSPECT\",\n\t\"PERL5LIB\",\n\t\"PERLLIB\",\n\t\"PERL5OPT\",\n\t\"RUBYLIB\",\n\t\"RUBYOPT\",\n\t\"RUBYPATH\",\n\t\"JAVA_TOOL_OPTIONS\",\n\t\"_JAVA_OPTIONS\",\n\t\"JDK_JAVA_OPTIONS\",\n\t\"MAVEN_OPTS\",\n]);\n\n/**\n * Matches a URL / DSN with embedded userinfo (`scheme://user:pass@host`).\n * Used for value-based denial; only the variable NAME is ever recorded.\n */\nconst AUTH_URL_REGEX = /^[a-z][a-z0-9+.-]*:\\/\\/[^\\s/@:]+:[^\\s/@]+@[^\\s/@]/i;\n\n/** Path patterns that look like credential / key material on disk. */\nconst SENSITIVE_PATH_REGEX =\n\t/(?:^|[/\\\\])(?:\\.env(?:\\..*)?|auth\\.json|oauth\\.json|\\.netrc|\\.npmrc|\\.pgpass|credentials|id_rsa|id_dsa|id_ecdsa|id_ed25519|.*(?:token|private[_-]?key|credential).*)$/i;\n\nexport interface PathAccessRequestV2 {\n\treadonly kind: PathAccessKind;\n\treadonly path: string;\n}\n\nexport interface PolicyDiagnostic {\n\treadonly code: string;\n\treadonly message: string;\n\treadonly severity: \"info\" | \"warn\" | \"block\";\n}\n\nexport interface PathDecisionV2 {\n\treadonly requestedPath: string;\n\treadonly candidate: string;\n\treadonly kind: PathAccessKind;\n\treadonly action: \"allow\" | \"block\";\n\treadonly rule: string;\n\treadonly reason: string;\n\treadonly matchedPattern?: string;\n}\n\nexport interface EnvDecisionV2 {\n\treadonly action: \"allow\" | \"block\";\n\treadonly rule: string;\n\treadonly reason: string;\n\t/** Denied variable NAMES only. Values are never recorded. */\n\treadonly deniedNames: readonly string[];\n}\n\nexport interface SandboxPolicyV2Decision {\n\treadonly action: \"allow\" | \"confirm\" | \"block\";\n\treadonly rule: string;\n\treadonly reason: string;\n\treadonly diagnostics: readonly PolicyDiagnostic[];\n\treadonly pathDecisions: readonly PathDecisionV2[];\n\treadonly networkDecision?: SandboxDecision;\n\treadonly envDecision?: EnvDecisionV2;\n}\n\nexport interface SandboxPolicyV2Input {\n\treadonly policy: SandboxPolicy;\n\treadonly pathRequests?: readonly PathAccessRequestV2[];\n\treadonly networkRequest?: NetworkAccessRequest;\n\treadonly env?: Readonly<Record<string, string | undefined>>;\n\treadonly resolver?: SandboxPathResolver;\n}\n\nfunction isSensitiveEnvName(name: string): boolean {\n\tif (SENSITIVE_ENV_EXACT.has(name)) return true;\n\treturn SENSITIVE_ENV_REGEX.test(name);\n}\n\nfunction normalizePathValue(value: string): string {\n\tconst resolved = path.resolve(value);\n\tlet normalized = resolved.replace(/\\\\/g, \"/\");\n\tif (normalized.length > 1) normalized = normalized.replace(/\\/+$/, \"\");\n\treturn normalized;\n}\n\nfunction ruleHasGlob(pattern: string): boolean {\n\treturn /[*?[\\]{}]/.test(pattern);\n}\n\nfunction matchesRule(pattern: string, candidate: string): boolean {\n\tconst normPattern = normalizePathValue(pattern);\n\tconst normCandidate = normalizePathValue(candidate);\n\tif (ruleHasGlob(normPattern)) {\n\t\tif (minimatch(normCandidate, normPattern)) return true;\n\t\t// also accept recursive prefix form even if the writer omitted `/**`\n\t\treturn minimatch(normCandidate, `${normPattern}/**`);\n\t}\n\treturn normCandidate === normPattern || normCandidate.startsWith(`${normPattern}/`);\n}\n\nfunction matchesAny(patterns: readonly string[], candidate: string): { match: boolean; pattern?: string } {\n\tfor (const pattern of patterns) {\n\t\tif (matchesRule(pattern, candidate)) return { match: true, pattern };\n\t}\n\treturn { match: false };\n}\n\nfunction isInsideRoot(root: string, candidate: string): boolean {\n\tconst normRoot = normalizePathValue(root);\n\tconst normCandidate = normalizePathValue(candidate);\n\treturn normCandidate === normRoot || normCandidate.startsWith(`${normRoot}/`);\n}\n\nfunction isSensitivePath(value: string): boolean {\n\treturn SENSITIVE_PATH_REGEX.test(value.replace(/\\\\/g, \"/\"));\n}\n\n/** True for IPv4 / IPv6 loopback and localhost hostnames. */\nfunction isLoopbackHost(host: string): boolean {\n\tconst h = host\n\t\t.toLowerCase()\n\t\t.replace(/^\\[|\\]$/g, \"\")\n\t\t.trim();\n\tif (h === \"localhost\") return true;\n\tif (h === \"127.0.0.1\" || h === \"::1\" || h === \"0:0:0:0:0:0:0:1\") return true;\n\tif (h === \"::ffff:127.0.0.1\" || h === \"::ffff:7f00:1\") return true;\n\tif (/^127\\./.test(h)) return true;\n\treturn false;\n}\n\nfunction normalizeNetworkLoopback(request: NetworkAccessRequest): NetworkAccessRequest {\n\tlet host = request.host;\n\tif (!host && request.url) {\n\t\ttry {\n\t\t\thost = new URL(request.url).hostname;\n\t\t} catch {\n\t\t\thost = undefined;\n\t\t}\n\t}\n\tif (host && isLoopbackHost(host)) {\n\t\treturn { ...request, host, loopback: true };\n\t}\n\treturn request;\n}\n\nfunction hostFromRequest(request: NetworkAccessRequest): string | undefined {\n\tif (request.host) return request.host.toLowerCase();\n\tif (!request.url) return undefined;\n\ttry {\n\t\treturn new URL(request.url).hostname.toLowerCase();\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction hostMatches(patterns: readonly string[], host: string): boolean {\n\tconst h = host.replace(/\\.$/, \"\");\n\tfor (const raw of patterns) {\n\t\tconst p = raw.toLowerCase().replace(/\\.$/, \"\");\n\t\tif (h === p || h.endsWith(`.${p}`)) return true;\n\t}\n\treturn false;\n}\n\nfunction decideNetworkV2(policy: SandboxPolicy, request: NetworkAccessRequest): SandboxDecision {\n\tif (policy.mode === \"off\") return { allowed: true, rule: \"sandbox.off\", reason: \"Sandbox policy is disabled.\" };\n\tif (request.browser || request.unixSocketPath) {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\trule: \"network.socket_or_browser\",\n\t\t\treason: \"Browser and Unix socket access is denied by default.\",\n\t\t};\n\t}\n\tif (policy.network.mode === \"none\") {\n\t\treturn { allowed: false, rule: \"network.none\", reason: \"Network access is disabled by policy.\" };\n\t}\n\tif (request.loopback) {\n\t\tif (\n\t\t\tpolicy.network.mode === \"loopback\" ||\n\t\t\tpolicy.network.mode === \"domain-allowlist\" ||\n\t\t\tpolicy.network.mode === \"all-explicit\"\n\t\t) {\n\t\t\treturn { allowed: true, rule: \"network.loopback\", reason: \"Loopback access is allowed.\" };\n\t\t}\n\t\treturn { allowed: false, rule: \"network.loopback_denied\", reason: \"Loopback access is denied.\" };\n\t}\n\tconst host = hostFromRequest(request);\n\tif (!host)\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\trule: \"network.unknown_host\",\n\t\t\treason: \"Network host could not be resolved from request.\",\n\t\t};\n\tif (hostMatches(policy.network.deniedDomains, host)) {\n\t\treturn { allowed: false, rule: \"network.domain_deny\", reason: \"Host matches a denied domain.\" };\n\t}\n\tif (policy.network.mode === \"all-explicit\") {\n\t\treturn {\n\t\t\tallowed: true,\n\t\t\trule: \"network.explicit_all\",\n\t\t\treason: \"Explicit network profile allows outbound host access.\",\n\t\t};\n\t}\n\tif (policy.network.mode === \"domain-allowlist\" && hostMatches(policy.network.allowedDomains, host)) {\n\t\treturn { allowed: true, rule: \"network.domain_allow\", reason: \"Host matches an allowed domain.\" };\n\t}\n\treturn { allowed: false, rule: \"network.domain_not_allowed\", reason: \"Host is not allowed by network policy.\" };\n}\n\nfunction decidePathV2(\n\tpolicy: SandboxPolicy,\n\trequest: PathAccessRequestV2,\n\tresolver: SandboxPathResolver | undefined,\n): PathDecisionV2 {\n\tconst requested = request.path;\n\tconst base = (\n\t\trule: string,\n\t\treason: string,\n\t\tcandidate: string,\n\t\taction: \"allow\" | \"block\",\n\t\tmatchedPattern?: string,\n\t): PathDecisionV2 => ({\n\t\trequestedPath: requested,\n\t\tcandidate,\n\t\tkind: request.kind,\n\t\taction,\n\t\trule,\n\t\treason,\n\t\tmatchedPattern,\n\t});\n\tconst block = (rule: string, reason: string, candidate: string, matchedPattern?: string): PathDecisionV2 =>\n\t\tbase(rule, reason, candidate, \"block\", matchedPattern);\n\tconst allow = (rule: string, reason: string, candidate: string): PathDecisionV2 =>\n\t\tbase(rule, reason, candidate, \"allow\");\n\n\tif (requested.includes(\"\\0\")) {\n\t\treturn block(\"path.invalid\", \"Path contains a NUL byte.\", requested);\n\t}\n\n\tlet candidate: string;\n\tlet isSymlink = false;\n\tif (resolver) {\n\t\tconst resolved = resolver(requested);\n\t\tif (resolved.error) {\n\t\t\treturn block(\"path.resolve_error\", resolved.error, requested);\n\t\t}\n\t\tcandidate = resolved.realPath ?? resolved.nearestExistingParentRealPath ?? normalizePathValue(requested);\n\t\tisSymlink = resolved.isSymlink === true;\n\t} else {\n\t\tcandidate = normalizePathValue(requested);\n\t}\n\n\tif (isSensitivePath(requested) || isSensitivePath(candidate)) {\n\t\treturn block(\"path.sensitive\", \"Sensitive credential-like path is denied.\", candidate);\n\t}\n\n\tif (!isInsideRoot(policy.filesystem.root, candidate)) {\n\t\treturn block(\"path.root_escape\", \"Resolved path is outside the sandbox root.\", candidate);\n\t}\n\n\tif (isSymlink && !policy.filesystem.followSymlinks) {\n\t\treturn block(\"path.symlink\", \"Symlink traversal is denied by policy.\", candidate);\n\t}\n\n\tif (request.kind === \"read\") {\n\t\tconst denied = matchesAny(policy.filesystem.readDeny, candidate);\n\t\tif (denied.match) {\n\t\t\treturn block(\"path.read_deny\", \"Read path matches a deny rule.\", candidate, denied.pattern);\n\t\t}\n\t\tconst deniedRequested = matchesAny(policy.filesystem.readDeny, requested);\n\t\tif (deniedRequested.match) {\n\t\t\treturn block(\"path.read_deny\", \"Read path matches a deny rule.\", candidate, deniedRequested.pattern);\n\t\t}\n\t\tif (matchesAny(policy.filesystem.readAllow, candidate).match) {\n\t\t\treturn allow(\"path.read_allow\", \"Read path is allowed.\", candidate);\n\t\t}\n\t\treturn block(\"path.read_not_allowed\", \"Read path is not in an allow rule.\", candidate);\n\t}\n\n\tconst denyWriteCandidate = matchesAny(policy.filesystem.denyWrite, candidate);\n\tif (denyWriteCandidate.match) {\n\t\treturn block(\n\t\t\t\"path.deny_write\",\n\t\t\t\"Write path matches an unoverrideable denyWrite rule.\",\n\t\t\tcandidate,\n\t\t\tdenyWriteCandidate.pattern,\n\t\t);\n\t}\n\tconst denyWriteRequested = matchesAny(policy.filesystem.denyWrite, requested);\n\tif (denyWriteRequested.match) {\n\t\treturn block(\n\t\t\t\"path.deny_write\",\n\t\t\t\"Write path matches an unoverrideable denyWrite rule.\",\n\t\t\tcandidate,\n\t\t\tdenyWriteRequested.pattern,\n\t\t);\n\t}\n\tif (\n\t\tmatchesAny(policy.filesystem.writeAllow, candidate).match ||\n\t\tmatchesAny(policy.filesystem.tempWrite, candidate).match\n\t) {\n\t\treturn allow(\"path.write_allow\", \"Write path is allowed.\", candidate);\n\t}\n\treturn block(\"path.write_not_allowed\", \"Write path is not in an allow rule.\", candidate);\n}\n\nfunction decideEnvV2(env: Readonly<Record<string, string | undefined>>): EnvDecisionV2 {\n\tconst denied: string[] = [];\n\tfor (const [name, value] of Object.entries(env)) {\n\t\tif (value === undefined) continue;\n\t\tif (ENV_DENY_NAMES.has(name)) {\n\t\t\tdenied.push(name);\n\t\t\tcontinue;\n\t\t}\n\t\tif (isSensitiveEnvName(name)) {\n\t\t\tdenied.push(name);\n\t\t\tcontinue;\n\t\t}\n\t\tif (AUTH_URL_REGEX.test(value)) {\n\t\t\t// Value-based denial: the value embeds credentials. Record NAME only.\n\t\t\tdenied.push(name);\n\t\t}\n\t}\n\tif (denied.length > 0) {\n\t\treturn {\n\t\t\taction: \"block\",\n\t\t\trule: \"env.denied_pattern\",\n\t\t\treason: `Environment contains denied variable(s): ${denied.join(\", \")}.`,\n\t\t\tdeniedNames: denied,\n\t\t};\n\t}\n\treturn { action: \"allow\", rule: \"env.allow\", reason: \"No denied environment variables.\", deniedNames: [] };\n}\n\n/**\n * Public: evaluate path / env / network requests against a sandbox policy.\n * Path and env checks are fail-closed. Audit mode downgrades a would-block\n * outcome to confirm; enforce mode keeps it block.\n */\nexport function evaluateSandboxPolicyV2(input: SandboxPolicyV2Input): SandboxPolicyV2Decision {\n\tconst { policy } = input;\n\tconst diagnostics: PolicyDiagnostic[] = [];\n\tconst pathDecisions: PathDecisionV2[] = [];\n\tlet envDecision: EnvDecisionV2 | undefined;\n\tlet networkDecision: SandboxDecision | undefined;\n\tlet worst: \"allow\" | \"block\" = \"block\";\n\n\tif (policy.mode === \"off\") {\n\t\treturn {\n\t\t\taction: \"allow\",\n\t\t\trule: \"sandbox.off\",\n\t\t\treason: \"Sandbox policy is disabled.\",\n\t\t\tdiagnostics,\n\t\t\tpathDecisions,\n\t\t};\n\t}\n\n\t// Default to allow and escalate to block on any failed check.\n\tworst = \"allow\";\n\n\tif (input.env) {\n\t\tenvDecision = decideEnvV2(input.env);\n\t\tif (envDecision.action === \"block\") {\n\t\t\tworst = \"block\";\n\t\t\tdiagnostics.push({\n\t\t\t\tcode: envDecision.rule,\n\t\t\t\tmessage: `Denied env name(s): ${envDecision.deniedNames.join(\", \")}`,\n\t\t\t\tseverity: \"block\",\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const request of input.pathRequests ?? []) {\n\t\tconst decision = decidePathV2(policy, request, input.resolver);\n\t\tpathDecisions.push(decision);\n\t\tif (decision.action === \"block\") {\n\t\t\tworst = \"block\";\n\t\t\tdiagnostics.push({ code: decision.rule, message: decision.reason, severity: \"block\" });\n\t\t}\n\t}\n\n\tif (input.networkRequest) {\n\t\tconst normalized = normalizeNetworkLoopback(input.networkRequest);\n\t\tnetworkDecision = decideNetworkV2(policy, normalized);\n\t\tif (!networkDecision.allowed) {\n\t\t\tworst = \"block\";\n\t\t\tdiagnostics.push({ code: networkDecision.rule, message: networkDecision.reason, severity: \"block\" });\n\t\t}\n\t}\n\n\tlet action: \"allow\" | \"confirm\" | \"block\";\n\tlet rule: string;\n\tlet reason: string;\n\tif (worst === \"allow\") {\n\t\taction = \"allow\";\n\t\trule = \"policy.composite_allow\";\n\t\treason = \"All sandbox checks passed.\";\n\t} else if (policy.mode === \"audit\") {\n\t\taction = \"confirm\";\n\t\trule = \"policy.audit_block\";\n\t\treason = \"Audit mode: a would-block check is downgraded to confirm.\";\n\t} else {\n\t\taction = \"block\";\n\t\trule = \"policy.block\";\n\t\treason = \"One or more sandbox checks blocked the request.\";\n\t}\n\n\treturn { action, rule, reason, diagnostics, pathDecisions, networkDecision, envDecision };\n}\n"]}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/** Error categories raised by the OMP pure-seam loader. */
|
|
2
|
-
export type OmpSeamsErrorCode = "DISABLED" | "VENDOR_NOT_FOUND" | "INVALID_SEAM";
|
|
3
|
-
/** Typed error thrown by {@link loadOmpPureSeams}. */
|
|
4
|
-
export declare class OmpSeamsError extends Error {
|
|
5
|
-
readonly code: OmpSeamsErrorCode;
|
|
6
|
-
constructor(code: OmpSeamsErrorCode, message: string);
|
|
7
|
-
}
|
|
8
|
-
/** The validated set of pure oh-my-pi seams (data/proposal-only). */
|
|
9
|
-
export interface OmpPureSeams {
|
|
10
|
-
planRead(input: unknown): unknown;
|
|
11
|
-
presentRead(plan: unknown, file: unknown): unknown;
|
|
12
|
-
planSearch(input: unknown): unknown;
|
|
13
|
-
presentSearch(plan: unknown, matches: unknown, sourceDigests?: unknown): unknown;
|
|
14
|
-
parseHashlineProposal(text: string): unknown;
|
|
15
|
-
hashProposalLine(text: string): Promise<string>;
|
|
16
|
-
hashProposalSource(text: string): Promise<string>;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Returns true unless the seams feature is explicitly disabled
|
|
20
|
-
* (OMK_OMP_SEAMS === "0"). Enabled by default per ADR-OMP-009.
|
|
21
|
-
* Reads `process.env` when no record is supplied.
|
|
22
|
-
*/
|
|
23
|
-
export declare function isOmpSeamsEnabled(env?: Record<string, string | undefined>): boolean;
|
|
24
|
-
/**
|
|
25
|
-
* Walks up from `startDir` (inclusive) looking for a `vendor/oh-my-pi`
|
|
26
|
-
* directory that contains the pure read seam marker file. Returns the absolute
|
|
27
|
-
* vendor directory path, or `undefined` when none is found within the level cap.
|
|
28
|
-
*/
|
|
29
|
-
export declare function resolveOmpVendorDir(startDir: string): string | undefined;
|
|
30
|
-
/**
|
|
31
|
-
* Loads and validates the three pure seam modules from the vendored oh-my-pi
|
|
32
|
-
* tree and returns a frozen {@link OmpPureSeams} record. Throws
|
|
33
|
-
* {@link OmpSeamsError} with code DISABLED when the feature is off,
|
|
34
|
-
* VENDOR_NOT_FOUND when the vendor tree cannot be located, or INVALID_SEAM when
|
|
35
|
-
* any expected export is missing or not a function.
|
|
36
|
-
*/
|
|
37
|
-
export declare function loadOmpPureSeams(options?: {
|
|
38
|
-
vendorDir?: string;
|
|
39
|
-
env?: Record<string, string | undefined>;
|
|
40
|
-
}): Promise<OmpPureSeams>;
|
|
41
|
-
//# sourceMappingURL=omp-pure-seams.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"omp-pure-seams.d.ts","sourceRoot":"","sources":["../../../src/core/tools/omp-pure-seams.ts"],"names":[],"mappings":"AAiBA,2DAA2D;AAC3D,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,kBAAkB,GAAG,cAAc,CAAC;AAEjF,sDAAsD;AACtD,qBAAa,aAAc,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IAEjC,YAAY,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,EAInD;CACD;AAED,qEAAqE;AACrE,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAClC,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACnD,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IACpC,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACjF,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7C,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAClD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAGnF;AAMD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAWxE;AAwBD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,CAAC,EAAE;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CACzC,GAAG,OAAO,CAAC,YAAY,CAAC,CAqExB","sourcesContent":["/**\n * Flag-gated loader for the vendored oh-my-pi \"pure\" read/search/hashline seams.\n *\n * These seams are pure data/proposal-only functions (planning + presentation +\n * hashline parsing). They do NOT touch edit/write/file-mutation paths. The\n * loader is enabled by default and opts out via OMK_OMP_SEAMS=0 (ADR-OMP-009);\n * when disabled it throws DISABLED and tool behavior falls back to the\n * pre-seam implementation byte-identically.\n *\n * The file is erasable TypeScript: no `enum`, no parameter properties, no `as`,\n * no non-null assertions, no `any` annotations, and no runtime dependencies\n * beyond the Node.js standard library.\n */\nimport { existsSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\n\n/** Error categories raised by the OMP pure-seam loader. */\nexport type OmpSeamsErrorCode = \"DISABLED\" | \"VENDOR_NOT_FOUND\" | \"INVALID_SEAM\";\n\n/** Typed error thrown by {@link loadOmpPureSeams}. */\nexport class OmpSeamsError extends Error {\n\treadonly code: OmpSeamsErrorCode;\n\n\tconstructor(code: OmpSeamsErrorCode, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"OmpSeamsError\";\n\t\tthis.code = code;\n\t}\n}\n\n/** The validated set of pure oh-my-pi seams (data/proposal-only). */\nexport interface OmpPureSeams {\n\tplanRead(input: unknown): unknown;\n\tpresentRead(plan: unknown, file: unknown): unknown;\n\tplanSearch(input: unknown): unknown;\n\tpresentSearch(plan: unknown, matches: unknown, sourceDigests?: unknown): unknown;\n\tparseHashlineProposal(text: string): unknown;\n\thashProposalLine(text: string): Promise<string>;\n\thashProposalSource(text: string): Promise<string>;\n}\n\n/**\n * Returns true unless the seams feature is explicitly disabled\n * (OMK_OMP_SEAMS === \"0\"). Enabled by default per ADR-OMP-009.\n * Reads `process.env` when no record is supplied.\n */\nexport function isOmpSeamsEnabled(env?: Record<string, string | undefined>): boolean {\n\tconst source: Record<string, string | undefined> = env ?? process.env;\n\treturn source.OMK_OMP_SEAMS !== \"0\";\n}\n\nconst VENDOR_SEGMENT = join(\"vendor\", \"oh-my-pi\");\nconst VENDOR_MARKER = join(VENDOR_SEGMENT, \"packages\", \"coding-agent\", \"src\", \"pure\", \"read.ts\");\nconst MAX_WALK_UP_LEVELS = 8;\n\n/**\n * Walks up from `startDir` (inclusive) looking for a `vendor/oh-my-pi`\n * directory that contains the pure read seam marker file. Returns the absolute\n * vendor directory path, or `undefined` when none is found within the level cap.\n */\nexport function resolveOmpVendorDir(startDir: string): string | undefined {\n\tlet dir = isAbsolute(startDir) ? startDir : resolve(startDir);\n\tfor (let level = 0; level <= MAX_WALK_UP_LEVELS; level += 1) {\n\t\tif (existsSync(join(dir, VENDOR_MARKER))) {\n\t\t\treturn join(dir, VENDOR_SEGMENT);\n\t\t}\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) break;\n\t\tdir = parent;\n\t}\n\treturn undefined;\n}\n\n// --- internal narrowing helpers (no `as`; type guards carry the signatures) ---\n\ntype SeamFn = (...args: never[]) => unknown;\ntype SeamAsyncStrFn = (...args: never[]) => Promise<string>;\n\nfunction isSeamFn(member: unknown): member is SeamFn {\n\treturn typeof member === \"function\";\n}\n\nfunction isSeamAsyncStrFn(member: unknown): member is SeamAsyncStrFn {\n\treturn typeof member === \"function\";\n}\n\nfunction expectFn<T extends SeamFn>(member: unknown, guard: (m: unknown) => m is T, name: string): T {\n\tif (guard(member)) return member;\n\tthrow new OmpSeamsError(\"INVALID_SEAM\", `OMP seam missing or non-function: ${name}`);\n}\n\nconst READ_SEAM = join(\"packages\", \"coding-agent\", \"src\", \"pure\", \"read.ts\");\nconst SEARCH_SEAM = join(\"packages\", \"coding-agent\", \"src\", \"pure\", \"search.ts\");\nconst PROPOSAL_SEAM = join(\"packages\", \"hashline\", \"src\", \"proposal.ts\");\n\n/**\n * Loads and validates the three pure seam modules from the vendored oh-my-pi\n * tree and returns a frozen {@link OmpPureSeams} record. Throws\n * {@link OmpSeamsError} with code DISABLED when the feature is off,\n * VENDOR_NOT_FOUND when the vendor tree cannot be located, or INVALID_SEAM when\n * any expected export is missing or not a function.\n */\nexport async function loadOmpPureSeams(options?: {\n\tvendorDir?: string;\n\tenv?: Record<string, string | undefined>;\n}): Promise<OmpPureSeams> {\n\tconst env: Record<string, string | undefined> = options?.env ?? process.env;\n\tif (!isOmpSeamsEnabled(env)) {\n\t\tthrow new OmpSeamsError(\n\t\t\t\"DISABLED\",\n\t\t\t\"OMP pure seams are disabled (OMK_OMP_SEAMS=0; unset or set to any other value to enable).\",\n\t\t);\n\t}\n\n\tlet vendorDir: string | undefined = options?.vendorDir ?? env.OMK_OMP_VENDOR_DIR;\n\tif (!vendorDir) {\n\t\tconst moduleUrl = new URL(\".\", import.meta.url);\n\t\tif (moduleUrl.protocol !== \"file:\") {\n\t\t\tthrow new OmpSeamsError(\n\t\t\t\t\"VENDOR_NOT_FOUND\",\n\t\t\t\t\"OMP vendor dir was not provided and the module is not a file URL.\",\n\t\t\t);\n\t\t}\n\t\tconst found = resolveOmpVendorDir(fileURLToPath(moduleUrl));\n\t\tif (!found) {\n\t\t\tthrow new OmpSeamsError(\n\t\t\t\t\"VENDOR_NOT_FOUND\",\n\t\t\t\t\"OMP vendor dir not found by walking up from the module directory.\",\n\t\t\t);\n\t\t}\n\t\tvendorDir = found;\n\t}\n\tif (!existsSync(vendorDir)) {\n\t\tthrow new OmpSeamsError(\"VENDOR_NOT_FOUND\", `OMP vendor dir does not exist: ${vendorDir}`);\n\t}\n\n\tconst readUrl = pathToFileURL(join(vendorDir, READ_SEAM)).href;\n\tconst searchUrl = pathToFileURL(join(vendorDir, SEARCH_SEAM)).href;\n\tconst proposalUrl = pathToFileURL(join(vendorDir, PROPOSAL_SEAM)).href;\n\n\tconst readMod = await import(readUrl);\n\tconst searchMod = await import(searchUrl);\n\tconst proposalMod = await import(proposalUrl);\n\n\t// Validate every expected member up front so the INVALID_SEAM error lists\n\t// ALL missing/non-function exports, not just the first one encountered.\n\tconst expected: ReadonlyArray<readonly [unknown, string]> = [\n\t\t[readMod.planRead, \"planRead\"],\n\t\t[readMod.presentRead, \"presentRead\"],\n\t\t[searchMod.planSearch, \"planSearch\"],\n\t\t[searchMod.presentSearch, \"presentSearch\"],\n\t\t[proposalMod.parseHashlineProposal, \"parseHashlineProposal\"],\n\t\t[proposalMod.hashProposalLine, \"hashProposalLine\"],\n\t\t[proposalMod.hashProposalSource, \"hashProposalSource\"],\n\t];\n\tconst missing: string[] = [];\n\tfor (const [member, name] of expected) {\n\t\tif (typeof member !== \"function\") missing.push(name);\n\t}\n\tif (missing.length > 0) {\n\t\tthrow new OmpSeamsError(\"INVALID_SEAM\", `OMP seams missing or non-function: ${missing.join(\", \")}`);\n\t}\n\n\tconst rec: OmpPureSeams = {\n\t\tplanRead: expectFn(readMod.planRead, isSeamFn, \"planRead\"),\n\t\tpresentRead: expectFn(readMod.presentRead, isSeamFn, \"presentRead\"),\n\t\tplanSearch: expectFn(searchMod.planSearch, isSeamFn, \"planSearch\"),\n\t\tpresentSearch: expectFn(searchMod.presentSearch, isSeamFn, \"presentSearch\"),\n\t\tparseHashlineProposal: expectFn(proposalMod.parseHashlineProposal, isSeamFn, \"parseHashlineProposal\"),\n\t\thashProposalLine: expectFn(proposalMod.hashProposalLine, isSeamAsyncStrFn, \"hashProposalLine\"),\n\t\thashProposalSource: expectFn(proposalMod.hashProposalSource, isSeamAsyncStrFn, \"hashProposalSource\"),\n\t};\n\tObject.freeze(rec);\n\treturn rec;\n}\n"]}
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
-
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
-
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
-
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
-
});
|
|
6
|
-
}
|
|
7
|
-
return path;
|
|
8
|
-
};
|
|
9
|
-
/**
|
|
10
|
-
* Flag-gated loader for the vendored oh-my-pi "pure" read/search/hashline seams.
|
|
11
|
-
*
|
|
12
|
-
* These seams are pure data/proposal-only functions (planning + presentation +
|
|
13
|
-
* hashline parsing). They do NOT touch edit/write/file-mutation paths. The
|
|
14
|
-
* loader is enabled by default and opts out via OMK_OMP_SEAMS=0 (ADR-OMP-009);
|
|
15
|
-
* when disabled it throws DISABLED and tool behavior falls back to the
|
|
16
|
-
* pre-seam implementation byte-identically.
|
|
17
|
-
*
|
|
18
|
-
* The file is erasable TypeScript: no `enum`, no parameter properties, no `as`,
|
|
19
|
-
* no non-null assertions, no `any` annotations, and no runtime dependencies
|
|
20
|
-
* beyond the Node.js standard library.
|
|
21
|
-
*/
|
|
22
|
-
import { existsSync } from "node:fs";
|
|
23
|
-
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
24
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
25
|
-
/** Typed error thrown by {@link loadOmpPureSeams}. */
|
|
26
|
-
export class OmpSeamsError extends Error {
|
|
27
|
-
code;
|
|
28
|
-
constructor(code, message) {
|
|
29
|
-
super(message);
|
|
30
|
-
this.name = "OmpSeamsError";
|
|
31
|
-
this.code = code;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Returns true unless the seams feature is explicitly disabled
|
|
36
|
-
* (OMK_OMP_SEAMS === "0"). Enabled by default per ADR-OMP-009.
|
|
37
|
-
* Reads `process.env` when no record is supplied.
|
|
38
|
-
*/
|
|
39
|
-
export function isOmpSeamsEnabled(env) {
|
|
40
|
-
const source = env ?? process.env;
|
|
41
|
-
return source.OMK_OMP_SEAMS !== "0";
|
|
42
|
-
}
|
|
43
|
-
const VENDOR_SEGMENT = join("vendor", "oh-my-pi");
|
|
44
|
-
const VENDOR_MARKER = join(VENDOR_SEGMENT, "packages", "coding-agent", "src", "pure", "read.ts");
|
|
45
|
-
const MAX_WALK_UP_LEVELS = 8;
|
|
46
|
-
/**
|
|
47
|
-
* Walks up from `startDir` (inclusive) looking for a `vendor/oh-my-pi`
|
|
48
|
-
* directory that contains the pure read seam marker file. Returns the absolute
|
|
49
|
-
* vendor directory path, or `undefined` when none is found within the level cap.
|
|
50
|
-
*/
|
|
51
|
-
export function resolveOmpVendorDir(startDir) {
|
|
52
|
-
let dir = isAbsolute(startDir) ? startDir : resolve(startDir);
|
|
53
|
-
for (let level = 0; level <= MAX_WALK_UP_LEVELS; level += 1) {
|
|
54
|
-
if (existsSync(join(dir, VENDOR_MARKER))) {
|
|
55
|
-
return join(dir, VENDOR_SEGMENT);
|
|
56
|
-
}
|
|
57
|
-
const parent = dirname(dir);
|
|
58
|
-
if (parent === dir)
|
|
59
|
-
break;
|
|
60
|
-
dir = parent;
|
|
61
|
-
}
|
|
62
|
-
return undefined;
|
|
63
|
-
}
|
|
64
|
-
function isSeamFn(member) {
|
|
65
|
-
return typeof member === "function";
|
|
66
|
-
}
|
|
67
|
-
function isSeamAsyncStrFn(member) {
|
|
68
|
-
return typeof member === "function";
|
|
69
|
-
}
|
|
70
|
-
function expectFn(member, guard, name) {
|
|
71
|
-
if (guard(member))
|
|
72
|
-
return member;
|
|
73
|
-
throw new OmpSeamsError("INVALID_SEAM", `OMP seam missing or non-function: ${name}`);
|
|
74
|
-
}
|
|
75
|
-
const READ_SEAM = join("packages", "coding-agent", "src", "pure", "read.ts");
|
|
76
|
-
const SEARCH_SEAM = join("packages", "coding-agent", "src", "pure", "search.ts");
|
|
77
|
-
const PROPOSAL_SEAM = join("packages", "hashline", "src", "proposal.ts");
|
|
78
|
-
/**
|
|
79
|
-
* Loads and validates the three pure seam modules from the vendored oh-my-pi
|
|
80
|
-
* tree and returns a frozen {@link OmpPureSeams} record. Throws
|
|
81
|
-
* {@link OmpSeamsError} with code DISABLED when the feature is off,
|
|
82
|
-
* VENDOR_NOT_FOUND when the vendor tree cannot be located, or INVALID_SEAM when
|
|
83
|
-
* any expected export is missing or not a function.
|
|
84
|
-
*/
|
|
85
|
-
export async function loadOmpPureSeams(options) {
|
|
86
|
-
const env = options?.env ?? process.env;
|
|
87
|
-
if (!isOmpSeamsEnabled(env)) {
|
|
88
|
-
throw new OmpSeamsError("DISABLED", "OMP pure seams are disabled (OMK_OMP_SEAMS=0; unset or set to any other value to enable).");
|
|
89
|
-
}
|
|
90
|
-
let vendorDir = options?.vendorDir ?? env.OMK_OMP_VENDOR_DIR;
|
|
91
|
-
if (!vendorDir) {
|
|
92
|
-
const moduleUrl = new URL(".", import.meta.url);
|
|
93
|
-
if (moduleUrl.protocol !== "file:") {
|
|
94
|
-
throw new OmpSeamsError("VENDOR_NOT_FOUND", "OMP vendor dir was not provided and the module is not a file URL.");
|
|
95
|
-
}
|
|
96
|
-
const found = resolveOmpVendorDir(fileURLToPath(moduleUrl));
|
|
97
|
-
if (!found) {
|
|
98
|
-
throw new OmpSeamsError("VENDOR_NOT_FOUND", "OMP vendor dir not found by walking up from the module directory.");
|
|
99
|
-
}
|
|
100
|
-
vendorDir = found;
|
|
101
|
-
}
|
|
102
|
-
if (!existsSync(vendorDir)) {
|
|
103
|
-
throw new OmpSeamsError("VENDOR_NOT_FOUND", `OMP vendor dir does not exist: ${vendorDir}`);
|
|
104
|
-
}
|
|
105
|
-
const readUrl = pathToFileURL(join(vendorDir, READ_SEAM)).href;
|
|
106
|
-
const searchUrl = pathToFileURL(join(vendorDir, SEARCH_SEAM)).href;
|
|
107
|
-
const proposalUrl = pathToFileURL(join(vendorDir, PROPOSAL_SEAM)).href;
|
|
108
|
-
const readMod = await import(__rewriteRelativeImportExtension(readUrl));
|
|
109
|
-
const searchMod = await import(__rewriteRelativeImportExtension(searchUrl));
|
|
110
|
-
const proposalMod = await import(__rewriteRelativeImportExtension(proposalUrl));
|
|
111
|
-
// Validate every expected member up front so the INVALID_SEAM error lists
|
|
112
|
-
// ALL missing/non-function exports, not just the first one encountered.
|
|
113
|
-
const expected = [
|
|
114
|
-
[readMod.planRead, "planRead"],
|
|
115
|
-
[readMod.presentRead, "presentRead"],
|
|
116
|
-
[searchMod.planSearch, "planSearch"],
|
|
117
|
-
[searchMod.presentSearch, "presentSearch"],
|
|
118
|
-
[proposalMod.parseHashlineProposal, "parseHashlineProposal"],
|
|
119
|
-
[proposalMod.hashProposalLine, "hashProposalLine"],
|
|
120
|
-
[proposalMod.hashProposalSource, "hashProposalSource"],
|
|
121
|
-
];
|
|
122
|
-
const missing = [];
|
|
123
|
-
for (const [member, name] of expected) {
|
|
124
|
-
if (typeof member !== "function")
|
|
125
|
-
missing.push(name);
|
|
126
|
-
}
|
|
127
|
-
if (missing.length > 0) {
|
|
128
|
-
throw new OmpSeamsError("INVALID_SEAM", `OMP seams missing or non-function: ${missing.join(", ")}`);
|
|
129
|
-
}
|
|
130
|
-
const rec = {
|
|
131
|
-
planRead: expectFn(readMod.planRead, isSeamFn, "planRead"),
|
|
132
|
-
presentRead: expectFn(readMod.presentRead, isSeamFn, "presentRead"),
|
|
133
|
-
planSearch: expectFn(searchMod.planSearch, isSeamFn, "planSearch"),
|
|
134
|
-
presentSearch: expectFn(searchMod.presentSearch, isSeamFn, "presentSearch"),
|
|
135
|
-
parseHashlineProposal: expectFn(proposalMod.parseHashlineProposal, isSeamFn, "parseHashlineProposal"),
|
|
136
|
-
hashProposalLine: expectFn(proposalMod.hashProposalLine, isSeamAsyncStrFn, "hashProposalLine"),
|
|
137
|
-
hashProposalSource: expectFn(proposalMod.hashProposalSource, isSeamAsyncStrFn, "hashProposalSource"),
|
|
138
|
-
};
|
|
139
|
-
Object.freeze(rec);
|
|
140
|
-
return rec;
|
|
141
|
-
}
|
|
142
|
-
//# sourceMappingURL=omp-pure-seams.js.map
|