open-multi-agent-kit 0.90.8 → 0.91.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 +41 -0
- package/README.md +21 -2
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +4 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/commands/doctor-provider-cli.d.ts +33 -0
- package/dist/commands/doctor-provider-cli.d.ts.map +1 -0
- package/dist/commands/doctor-provider-cli.js +215 -0
- package/dist/commands/doctor-provider-cli.js.map +1 -0
- package/dist/commands/doctor-provider-transport.d.ts +35 -0
- package/dist/commands/doctor-provider-transport.d.ts.map +1 -0
- package/dist/commands/doctor-provider-transport.js +185 -0
- package/dist/commands/doctor-provider-transport.js.map +1 -0
- package/dist/commands/doctor-provider.d.ts +121 -7
- package/dist/commands/doctor-provider.d.ts.map +1 -1
- package/dist/commands/doctor-provider.js +1295 -102
- package/dist/commands/doctor-provider.js.map +1 -1
- package/dist/commands/session-doctor-cli.d.ts +43 -0
- package/dist/commands/session-doctor-cli.d.ts.map +1 -0
- package/dist/commands/session-doctor-cli.js +494 -0
- package/dist/commands/session-doctor-cli.js.map +1 -0
- package/dist/commands/verify-ci.d.ts +21 -0
- package/dist/commands/verify-ci.d.ts.map +1 -0
- package/dist/commands/verify-ci.js +66 -0
- package/dist/commands/verify-ci.js.map +1 -0
- package/dist/core/agent-session-services.d.ts +3 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +3 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +140 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +1179 -95
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/agent-tool-settings.d.ts +35 -0
- package/dist/core/agent-tool-settings.d.ts.map +1 -0
- package/dist/core/agent-tool-settings.js +155 -0
- package/dist/core/agent-tool-settings.js.map +1 -0
- package/dist/core/atomic-session-file.d.ts +14 -0
- package/dist/core/atomic-session-file.d.ts.map +1 -0
- package/dist/core/atomic-session-file.js +104 -0
- package/dist/core/atomic-session-file.js.map +1 -0
- package/dist/core/command-safety.d.ts.map +1 -1
- package/dist/core/command-safety.js +0 -8
- package/dist/core/command-safety.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +6 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +12 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/hysteresis.d.ts +27 -0
- package/dist/core/compaction/hysteresis.d.ts.map +1 -0
- package/dist/core/compaction/hysteresis.js +84 -0
- package/dist/core/compaction/hysteresis.js.map +1 -0
- package/dist/core/compaction/index.d.ts +2 -0
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js +2 -0
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/compaction/transaction.d.ts +172 -0
- package/dist/core/compaction/transaction.d.ts.map +1 -0
- package/dist/core/compaction/transaction.js +824 -0
- package/dist/core/compaction/transaction.js.map +1 -0
- package/dist/core/context-budget-governor-v2.d.ts +2 -1
- package/dist/core/context-budget-governor-v2.d.ts.map +1 -1
- package/dist/core/context-budget-governor-v2.js +2 -1
- package/dist/core/context-budget-governor-v2.js.map +1 -1
- package/dist/core/context-budget-reserved-tokens.d.ts +110 -0
- package/dist/core/context-budget-reserved-tokens.d.ts.map +1 -0
- package/dist/core/context-budget-reserved-tokens.js +188 -0
- package/dist/core/context-budget-reserved-tokens.js.map +1 -0
- package/dist/core/context-budget-v2-cache-invalidation.d.ts +133 -0
- package/dist/core/context-budget-v2-cache-invalidation.d.ts.map +1 -0
- package/dist/core/context-budget-v2-cache-invalidation.js +452 -0
- package/dist/core/context-budget-v2-cache-invalidation.js.map +1 -0
- 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 +6 -0
- package/dist/core/context-budget-v2-cache-keys.js.map +1 -1
- package/dist/core/context-budget-v2-cache-provider.d.ts +4 -0
- package/dist/core/context-budget-v2-cache-provider.d.ts.map +1 -1
- package/dist/core/context-budget-v2-cache-provider.js +19 -0
- package/dist/core/context-budget-v2-cache-provider.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 +1 -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 +1 -0
- package/dist/core/context-budget-v2-planner.js.map +1 -1
- package/dist/core/context-budget-v2-types.d.ts +4 -0
- package/dist/core/context-budget-v2-types.d.ts.map +1 -1
- package/dist/core/context-budget-v2-types.js.map +1 -1
- package/dist/core/durable-file-directory.d.ts +4 -0
- package/dist/core/durable-file-directory.d.ts.map +1 -0
- package/dist/core/durable-file-directory.js +76 -0
- package/dist/core/durable-file-directory.js.map +1 -0
- package/dist/core/durable-file-identity.d.ts +26 -0
- package/dist/core/durable-file-identity.d.ts.map +1 -0
- package/dist/core/durable-file-identity.js +118 -0
- package/dist/core/durable-file-identity.js.map +1 -0
- package/dist/core/durable-file-io.d.ts +29 -0
- package/dist/core/durable-file-io.d.ts.map +1 -0
- package/dist/core/durable-file-io.js +179 -0
- package/dist/core/durable-file-io.js.map +1 -0
- package/dist/core/durable-file-lock-cleanup.d.ts +12 -0
- package/dist/core/durable-file-lock-cleanup.d.ts.map +1 -0
- package/dist/core/durable-file-lock-cleanup.js +39 -0
- package/dist/core/durable-file-lock-cleanup.js.map +1 -0
- package/dist/core/durable-file-lock-owner.d.ts +18 -0
- package/dist/core/durable-file-lock-owner.d.ts.map +1 -0
- package/dist/core/durable-file-lock-owner.js +78 -0
- package/dist/core/durable-file-lock-owner.js.map +1 -0
- package/dist/core/durable-file-lock-storage.d.ts +35 -0
- package/dist/core/durable-file-lock-storage.d.ts.map +1 -0
- package/dist/core/durable-file-lock-storage.js +263 -0
- package/dist/core/durable-file-lock-storage.js.map +1 -0
- package/dist/core/durable-file-mode.d.ts +8 -0
- package/dist/core/durable-file-mode.d.ts.map +1 -0
- package/dist/core/durable-file-mode.js +41 -0
- package/dist/core/durable-file-mode.js.map +1 -0
- package/dist/core/extensions/loader.d.ts +12 -0
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +46 -37
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +7 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +12 -0
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +7 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +6 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/metrics-sampler.d.ts +20 -0
- package/dist/core/metrics-sampler.d.ts.map +1 -1
- package/dist/core/metrics-sampler.js +52 -0
- package/dist/core/metrics-sampler.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +4 -1
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +16 -7
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/provider-resilience.d.ts +51 -0
- package/dist/core/provider-resilience.d.ts.map +1 -0
- package/dist/core/provider-resilience.js +86 -0
- package/dist/core/provider-resilience.js.map +1 -0
- package/dist/core/redaction.d.ts +8 -0
- package/dist/core/redaction.d.ts.map +1 -0
- package/dist/core/redaction.js +31 -0
- package/dist/core/redaction.js.map +1 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +36 -0
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/run-journal-store.d.ts +53 -0
- package/dist/core/run-journal-store.d.ts.map +1 -0
- package/dist/core/run-journal-store.js +278 -0
- package/dist/core/run-journal-store.js.map +1 -0
- package/dist/core/run-journal.d.ts +172 -0
- package/dist/core/run-journal.d.ts.map +1 -0
- package/dist/core/run-journal.js +1045 -0
- package/dist/core/run-journal.js.map +1 -0
- package/dist/core/sdk.d.ts +7 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +94 -3
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-doctor-plan.d.ts +128 -0
- package/dist/core/session-doctor-plan.d.ts.map +1 -0
- package/dist/core/session-doctor-plan.js +833 -0
- package/dist/core/session-doctor-plan.js.map +1 -0
- package/dist/core/session-file-compaction.d.ts +6 -0
- package/dist/core/session-file-compaction.d.ts.map +1 -0
- package/dist/core/session-file-compaction.js +169 -0
- package/dist/core/session-file-compaction.js.map +1 -0
- package/dist/core/session-file-head.d.ts +10 -0
- package/dist/core/session-file-head.d.ts.map +1 -0
- package/dist/core/session-file-head.js +78 -0
- package/dist/core/session-file-head.js.map +1 -0
- package/dist/core/session-file-persistence.d.ts +30 -0
- package/dist/core/session-file-persistence.d.ts.map +1 -0
- package/dist/core/session-file-persistence.js +106 -0
- package/dist/core/session-file-persistence.js.map +1 -0
- package/dist/core/session-integrity.d.ts +43 -0
- package/dist/core/session-integrity.d.ts.map +1 -0
- package/dist/core/session-integrity.js +420 -0
- package/dist/core/session-integrity.js.map +1 -0
- package/dist/core/session-manager.d.ts +24 -4
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +242 -125
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-owner-lease.d.ts +22 -0
- package/dist/core/session-owner-lease.d.ts.map +1 -0
- package/dist/core/session-owner-lease.js +176 -0
- package/dist/core/session-owner-lease.js.map +1 -0
- package/dist/core/session-path-policy.d.ts +132 -0
- package/dist/core/session-path-policy.d.ts.map +1 -0
- package/dist/core/session-path-policy.js +780 -0
- package/dist/core/session-path-policy.js.map +1 -0
- package/dist/core/session-repair-plan.d.ts +49 -0
- package/dist/core/session-repair-plan.d.ts.map +1 -0
- package/dist/core/session-repair-plan.js +202 -0
- package/dist/core/session-repair-plan.js.map +1 -0
- package/dist/core/session-termination.d.ts +106 -0
- package/dist/core/session-termination.d.ts.map +1 -0
- package/dist/core/session-termination.js +445 -0
- package/dist/core/session-termination.js.map +1 -0
- package/dist/core/settings-manager.d.ts +52 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +54 -5
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +47 -0
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/omp-pure-seams.d.ts +41 -0
- package/dist/core/tools/omp-pure-seams.d.ts.map +1 -0
- package/dist/core/tools/omp-pure-seams.js +142 -0
- package/dist/core/tools/omp-pure-seams.js.map +1 -0
- package/dist/core/tools/omp-seam-runtime.d.ts +100 -0
- package/dist/core/tools/omp-seam-runtime.d.ts.map +1 -0
- package/dist/core/tools/omp-seam-runtime.js +40 -0
- package/dist/core/tools/omp-seam-runtime.js.map +1 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +34 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/verified-bash-adapter.d.ts +36 -0
- package/dist/core/verified-bash-adapter.d.ts.map +1 -0
- package/dist/core/verified-bash-adapter.js +90 -0
- package/dist/core/verified-bash-adapter.js.map +1 -0
- package/dist/guardrails/command-redaction.d.ts +32 -0
- package/dist/guardrails/command-redaction.d.ts.map +1 -0
- package/dist/guardrails/command-redaction.js +776 -0
- package/dist/guardrails/command-redaction.js.map +1 -0
- package/dist/guardrails/evidence-attestation.d.ts +31 -0
- package/dist/guardrails/evidence-attestation.d.ts.map +1 -0
- package/dist/guardrails/evidence-attestation.js +178 -0
- package/dist/guardrails/evidence-attestation.js.map +1 -0
- package/dist/guardrails/evidence-receipt-store.d.ts +33 -0
- package/dist/guardrails/evidence-receipt-store.d.ts.map +1 -0
- package/dist/guardrails/evidence-receipt-store.js +446 -0
- package/dist/guardrails/evidence-receipt-store.js.map +1 -0
- package/dist/guardrails/evidence-receipt.d.ts +58 -0
- package/dist/guardrails/evidence-receipt.d.ts.map +1 -0
- package/dist/guardrails/evidence-receipt.js +389 -0
- package/dist/guardrails/evidence-receipt.js.map +1 -0
- package/dist/guardrails/evidence-system.d.ts +39 -15
- package/dist/guardrails/evidence-system.d.ts.map +1 -1
- package/dist/guardrails/evidence-system.js +255 -97
- package/dist/guardrails/evidence-system.js.map +1 -1
- package/dist/guardrails/replay-ledger-io.d.ts +6 -0
- package/dist/guardrails/replay-ledger-io.d.ts.map +1 -0
- package/dist/guardrails/replay-ledger-io.js +42 -0
- package/dist/guardrails/replay-ledger-io.js.map +1 -0
- package/dist/guardrails/replay-ledger-lock-owner.d.ts +32 -0
- package/dist/guardrails/replay-ledger-lock-owner.d.ts.map +1 -0
- package/dist/guardrails/replay-ledger-lock-owner.js +138 -0
- package/dist/guardrails/replay-ledger-lock-owner.js.map +1 -0
- package/dist/guardrails/replay-ledger-lock.d.ts +24 -0
- package/dist/guardrails/replay-ledger-lock.d.ts.map +1 -0
- package/dist/guardrails/replay-ledger-lock.js +135 -0
- package/dist/guardrails/replay-ledger-lock.js.map +1 -0
- package/dist/guardrails/replay-ledger-mutation-gate.d.ts +24 -0
- package/dist/guardrails/replay-ledger-mutation-gate.d.ts.map +1 -0
- package/dist/guardrails/replay-ledger-mutation-gate.js +205 -0
- package/dist/guardrails/replay-ledger-mutation-gate.js.map +1 -0
- package/dist/guardrails/replay-ledger-quarantine.d.ts +2 -0
- package/dist/guardrails/replay-ledger-quarantine.d.ts.map +1 -0
- package/dist/guardrails/replay-ledger-quarantine.js +19 -0
- package/dist/guardrails/replay-ledger-quarantine.js.map +1 -0
- package/dist/guardrails/replay-ledger-store.d.ts +32 -0
- package/dist/guardrails/replay-ledger-store.d.ts.map +1 -0
- package/dist/guardrails/replay-ledger-store.js +211 -0
- package/dist/guardrails/replay-ledger-store.js.map +1 -0
- package/dist/guardrails/shell-command-name-glob.d.ts +3 -0
- package/dist/guardrails/shell-command-name-glob.d.ts.map +1 -0
- package/dist/guardrails/shell-command-name-glob.js +233 -0
- package/dist/guardrails/shell-command-name-glob.js.map +1 -0
- package/dist/guardrails/shell-command-option.d.ts +7 -0
- package/dist/guardrails/shell-command-option.d.ts.map +1 -0
- package/dist/guardrails/shell-command-option.js +24 -0
- package/dist/guardrails/shell-command-option.js.map +1 -0
- package/dist/guardrails/shell-command-tokenizer.d.ts +29 -0
- package/dist/guardrails/shell-command-tokenizer.d.ts.map +1 -0
- package/dist/guardrails/shell-command-tokenizer.js +145 -0
- package/dist/guardrails/shell-command-tokenizer.js.map +1 -0
- package/dist/guardrails/shell-command-wrapper.d.ts +18 -0
- package/dist/guardrails/shell-command-wrapper.d.ts.map +1 -0
- package/dist/guardrails/shell-command-wrapper.js +42 -0
- package/dist/guardrails/shell-command-wrapper.js.map +1 -0
- package/dist/guardrails/verified-executor.d.ts +65 -0
- package/dist/guardrails/verified-executor.d.ts.map +1 -0
- package/dist/guardrails/verified-executor.js +171 -0
- package/dist/guardrails/verified-executor.js.map +1 -0
- package/dist/guardrails/workspace-fingerprint.d.ts +23 -0
- package/dist/guardrails/workspace-fingerprint.d.ts.map +1 -0
- package/dist/guardrails/workspace-fingerprint.js +634 -0
- package/dist/guardrails/workspace-fingerprint.js.map +1 -0
- package/dist/index.d.ts +15 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +12 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +11 -8
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +3 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +59 -9
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/omk-aurora-dark.json +80 -0
- package/dist/modes/interactive/theme/omk-aurora-light.json +80 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +5 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +43 -2
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +23 -5
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +3 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/types/evidence.d.ts +211 -1
- package/dist/types/evidence.d.ts.map +1 -1
- package/dist/types/evidence.js.map +1 -1
- package/dist/verify-ci.d.ts +3 -0
- package/dist/verify-ci.d.ts.map +1 -0
- package/dist/verify-ci.js +30 -0
- package/dist/verify-ci.js.map +1 -0
- package/docs/adaptorch-preview.md +1 -1
- package/docs/compaction.md +38 -4
- package/docs/extensions.md +2 -0
- package/docs/provider-resilience.md +87 -0
- package/docs/sdk.md +238 -1
- package/docs/settings.md +80 -2
- package/docs/themes.md +2 -0
- package/docs/usage.md +38 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +5 -5
- 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 +4 -4
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +22 -13
- package/package.json +6 -5
package/dist/core/sdk.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { Agent, type AgentMessage, type ThinkingLevel } from \"omk-agent-core\";\nimport { clampThinkingLevel, type Message, type Model, streamSimple } from \"omk-ai\";\nimport { getAgentDir } from \"../config.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { AgentSession } from \"./agent-session.ts\";\nimport { formatNoModelsAvailableMessage } from \"./auth-guidance.ts\";\nimport { AuthStorage } from \"./auth-storage.ts\";\nimport { DEFAULT_THINKING_LEVEL } from \"./defaults.ts\";\nimport { createDomainDispatchRuntimeSession, isDomainRoutingEnabled, tryDomainDispatch } from \"./domain-dispatch.ts\";\nimport type { ExtensionRunner, LoadExtensionsResult, SessionStartEvent, ToolDefinition } from \"./extensions/index.ts\";\nimport { tryGrokHarnessDispatch } from \"./grok-harness-dispatch.ts\";\nimport type { LoadoutAccessPolicy } from \"./loadout-access-policy.ts\";\nimport { convertToLlm } from \"./messages.ts\";\nimport { ModelRegistry } from \"./model-registry.ts\";\nimport { findInitialModel } from \"./model-resolver.ts\";\nimport { mergeProviderAttributionHeaders } from \"./provider-attribution.ts\";\nimport type { ResourceLoader } from \"./resource-loader.ts\";\nimport { DefaultResourceLoader } from \"./resource-loader.ts\";\nimport { getDefaultSessionDir, SessionManager } from \"./session-manager.ts\";\nimport { SettingsManager } from \"./settings-manager.ts\";\nimport { time } from \"./timings.ts\";\nimport type { BashSandboxPreflight } from \"./tools/bash.ts\";\nimport {\n\tallToolNames,\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\ttype ToolName,\n\twithFileMutationQueue,\n} from \"./tools/index.ts\";\n\nexport interface CreateAgentSessionOptions {\n\t/** Working directory for project-local discovery. Default: process.cwd() */\n\tcwd?: string;\n\t/** Global config directory. Default: ~/.omk/agent */\n\tagentDir?: string;\n\n\t/** Auth storage for credentials. Default: AuthStorage.create(agentDir/auth.json) */\n\tauthStorage?: AuthStorage;\n\t/** Model registry. Default: ModelRegistry.create(authStorage, agentDir/models.json) */\n\tmodelRegistry?: ModelRegistry;\n\n\t/** Model to use. Default: from settings, else first available */\n\tmodel?: Model<any>;\n\t/** Thinking level. Default: from settings, else 'medium' (clamped to model capabilities) */\n\tthinkingLevel?: ThinkingLevel;\n\t/** Models available for cycling (Ctrl+P in interactive mode) */\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel }>;\n\n\t/**\n\t * Optional default tool suppression mode when no explicit allowlist is provided.\n\t *\n\t * - \"all\": start with no tools enabled\n\t * - \"builtin\": disable the default built-in tools (read, bash, edit, write)\n\t * but keep extension/custom tools enabled\n\t */\n\tnoTools?: \"all\" | \"builtin\";\n\t/**\n\t * Optional allowlist of tool names.\n\t *\n\t * When omitted, OMK enables the default built-in tools (read, bash, edit, write)\n\t * and leaves extension/custom tools enabled unless `noTools` changes that default.\n\t * When provided, only the listed tool names are enabled.\n\t */\n\ttools?: string[];\n\t/** Optional denylist of tool names to disable. Applies after `tools` when both are provided. */\n\texcludeTools?: string[];\n\t/** Custom tools to register (in addition to built-in tools). */\n\tcustomTools?: ToolDefinition[];\n\n\t/** Resource loader. When omitted, DefaultResourceLoader is used. */\n\tresourceLoader?: ResourceLoader;\n\n\t/** Session manager. Default: SessionManager.create(cwd) */\n\tsessionManager?: SessionManager;\n\n\t/** Settings manager. Default: SettingsManager.create(cwd, agentDir) */\n\tsettingsManager?: SettingsManager;\n\t/** Session start event metadata for extension runtime startup. */\n\tsessionStartEvent?: SessionStartEvent;\n\t/**\n\t * Optional prompt hint used only for opt-in domain routing (`OMK_DOMAIN_ROUTING=1`).\n\t * This text only selects a loadout policy and is never sent to the model.\n\t */\n\tdomainRoutingPrompt?: string;\n\t/** Optional loadout enforcement policy for SDK-created sessions. */\n\tloadoutAccessPolicy?: LoadoutAccessPolicy;\n\t/** Trusted sandbox preflight used for built-in local bash execution. */\n\tbashSandboxPreflight?: BashSandboxPreflight;\n}\n\n/** Result from createAgentSession */\nexport interface CreateAgentSessionResult {\n\t/** The created session */\n\tsession: AgentSession;\n\t/** Extensions result (for UI context setup in interactive mode) */\n\textensionsResult: LoadExtensionsResult;\n\t/** Warning if session was restored with a different model than saved */\n\tmodelFallbackMessage?: string;\n}\n\n// Re-exports\n\nexport * from \"./agent-session-runtime.ts\";\nexport type {\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n\tExtensionFactory,\n\tSlashCommandInfo,\n\tSlashCommandSource,\n\tToolDefinition,\n} from \"./extensions/index.ts\";\nexport type { PromptTemplate } from \"./prompt-templates.ts\";\nexport type { Skill } from \"./skills.ts\";\nexport type { Tool } from \"./tools/index.ts\";\n\nexport {\n\twithFileMutationQueue,\n\t// Tool factories (for custom cwd)\n\tcreateCodingTools,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateBashTool,\n\tcreateEditTool,\n\tcreateWriteTool,\n\tcreateGrepTool,\n\tcreateFindTool,\n\tcreateLsTool,\n};\n\n// Helper Functions\n\nfunction getDefaultAgentDir(): string {\n\treturn getAgentDir();\n}\n\nfunction getDomainDispatchBaseToolNames(options: CreateAgentSessionOptions): string[] {\n\tif (!options.tools && (options.noTools === \"all\" || options.noTools === \"builtin\")) {\n\t\treturn [];\n\t}\n\treturn [...allToolNames];\n}\n\nfunction getAllowedToolNamesForDomainDispatch(options: CreateAgentSessionOptions): string[] | undefined {\n\treturn options.tools ?? (options.noTools === \"all\" ? [] : undefined);\n}\n\nfunction createEffectiveLoadoutAccessPolicy(\n\toptions: CreateAgentSessionOptions,\n\tresourceLoader: ResourceLoader,\n\tcwd: string,\n\tagentDir: string,\n\tprovider?: string,\n): LoadoutAccessPolicy | undefined {\n\tif (options.loadoutAccessPolicy) {\n\t\treturn options.loadoutAccessPolicy;\n\t}\n\n\tconst session = createDomainDispatchRuntimeSession({\n\t\tbaseToolNames: getDomainDispatchBaseToolNames(options),\n\t\tresourceLoader,\n\t\tcustomTools: options.customTools,\n\t\tallowedToolNames: getAllowedToolNamesForDomainDispatch(options),\n\t\texcludedToolNames: options.excludeTools,\n\t});\n\n\t// Grok OAuth: apply grok-harness domain loadout without requiring OMK_DOMAIN_ROUTING=1.\n\tif (provider) {\n\t\ttry {\n\t\t\tconst grokDispatch = tryGrokHarnessDispatch({\n\t\t\t\tprovider,\n\t\t\t\tsession,\n\t\t\t\tresourceLoader,\n\t\t\t\tcwd,\n\t\t\t\tagentDir,\n\t\t\t\tenv: process.env,\n\t\t\t});\n\t\t\tif (grokDispatch.loadoutAccessPolicy) {\n\t\t\t\treturn grokDispatch.loadoutAccessPolicy;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to opt-in domain routing.\n\t\t}\n\t}\n\n\tconst domainRoutingPrompt = options.domainRoutingPrompt?.trim();\n\tif (!domainRoutingPrompt || !isDomainRoutingEnabled(process.env)) {\n\t\treturn undefined;\n\t}\n\n\ttry {\n\t\tconst dispatch = tryDomainDispatch({\n\t\t\trole: \"coder\",\n\t\t\tinitialPrompt: domainRoutingPrompt,\n\t\t\tsession,\n\t\t\tresourceLoader,\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tenv: process.env,\n\t\t});\n\t\treturn dispatch.loadoutAccessPolicy;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Create an AgentSession with the specified options.\n *\n * @example\n * ```typescript\n * // Minimal - uses defaults\n * const { session } = await createAgentSession();\n *\n * // With explicit model\n * import { getModel } from 'omk-ai';\n * const { session } = await createAgentSession({\n * model: getModel('anthropic', 'claude-opus-4-5'),\n * thinkingLevel: 'high',\n * });\n *\n * // Continue previous session\n * const { session, modelFallbackMessage } = await createAgentSession({\n * continueSession: true,\n * });\n *\n * // Full control\n * const loader = new DefaultResourceLoader({\n * cwd: process.cwd(),\n * agentDir: getAgentDir(),\n * settingsManager: SettingsManager.create(),\n * });\n * await loader.reload();\n * const { session } = await createAgentSession({\n * model: myModel,\n * tools: [\"read\", \"bash\"],\n * resourceLoader: loader,\n * sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst cwd = resolvePath(options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd());\n\tconst agentDir = options.agentDir ? resolvePath(options.agentDir) : getDefaultAgentDir();\n\tlet resourceLoader = options.resourceLoader;\n\n\t// Use provided or create AuthStorage and ModelRegistry\n\tconst authPath = options.agentDir ? join(agentDir, \"auth.json\") : undefined;\n\tconst modelsPath = options.agentDir ? join(agentDir, \"models.json\") : undefined;\n\tconst authStorage = options.authStorage ?? AuthStorage.create(authPath);\n\tconst modelRegistry = options.modelRegistry ?? ModelRegistry.create(authStorage, modelsPath);\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd, getDefaultSessionDir(cwd, agentDir));\n\n\tif (!resourceLoader) {\n\t\tresourceLoader = new DefaultResourceLoader({ cwd, agentDir, settingsManager });\n\t\tawait resourceLoader.reload();\n\t\ttime(\"resourceLoader.reload\");\n\t}\n\n\t// Check if session has existing data to restore\n\tconst existingSession = sessionManager.buildSessionContext();\n\tconst hasExistingSession = existingSession.messages.length > 0;\n\tconst hasThinkingEntry = sessionManager.getBranch().some((entry) => entry.type === \"thinking_level_change\");\n\n\tlet model = options.model;\n\tlet modelFallbackMessage: string | undefined;\n\n\t// If session has data, try to restore model from it\n\tif (!model && hasExistingSession && existingSession.model) {\n\t\tconst restoredModel = modelRegistry.find(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel && modelRegistry.hasConfiguredAuth(restoredModel)) {\n\t\t\tmodel = restoredModel;\n\t\t}\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = `Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`;\n\t\t}\n\t}\n\n\t// If still no model, use findInitialModel (checks settings default, then provider defaults)\n\tif (!model) {\n\t\tconst result = await findInitialModel({\n\t\t\tscopedModels: [],\n\t\t\tisContinuing: hasExistingSession,\n\t\t\tdefaultProvider: settingsManager.getDefaultProvider(),\n\t\t\tdefaultModelId: settingsManager.getDefaultModel(),\n\t\t\tdefaultThinkingLevel: settingsManager.getDefaultThinkingLevel(),\n\t\t\tmodelRegistry,\n\t\t});\n\t\tmodel = result.model;\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = formatNoModelsAvailableMessage();\n\t\t} else if (modelFallbackMessage) {\n\t\t\tmodelFallbackMessage += `. Using ${model.provider}/${model.id}`;\n\t\t}\n\t}\n\n\t// Loadout policy after model resolution so Grok OAuth can auto-apply grok-harness.\n\tconst effectiveLoadoutAccessPolicy = createEffectiveLoadoutAccessPolicy(\n\t\toptions,\n\t\tresourceLoader,\n\t\tcwd,\n\t\tagentDir,\n\t\tmodel?.provider,\n\t);\n\n\tlet thinkingLevel = options.thinkingLevel;\n\n\t// If session has data, restore thinking level from it\n\tif (thinkingLevel === undefined && hasExistingSession) {\n\t\tthinkingLevel = hasThinkingEntry\n\t\t\t? (existingSession.thinkingLevel as ThinkingLevel)\n\t\t\t: (settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL);\n\t}\n\n\t// Fall back to settings default\n\tif (thinkingLevel === undefined) {\n\t\tthinkingLevel = settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;\n\t}\n\n\t// Clamp to model capabilities\n\tif (!model) {\n\t\tthinkingLevel = \"off\";\n\t} else {\n\t\tthinkingLevel = clampThinkingLevel(model, thinkingLevel) as ThinkingLevel;\n\t}\n\n\tconst defaultActiveToolNames: ToolName[] = [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst allowedToolNames = options.tools ?? (options.noTools === \"all\" ? [] : undefined);\n\tconst excludedToolNames = options.excludeTools;\n\tconst excludedToolNameSet = excludedToolNames ? new Set(excludedToolNames) : undefined;\n\tconst initialActiveToolNames: string[] = (\n\t\toptions.tools ? [...options.tools] : options.noTools ? [] : defaultActiveToolNames\n\t).filter((name) => !excludedToolNameSet?.has(name));\n\n\tlet agent: Agent;\n\n\t// Create convertToLlm wrapper that filters images if blockImages is enabled (defense-in-depth)\n\tconst convertToLlmWithBlockImages = (messages: AgentMessage[]): Message[] => {\n\t\tconst converted = convertToLlm(messages);\n\t\t// Check setting dynamically so mid-session changes take effect\n\t\tif (!settingsManager.getBlockImages()) {\n\t\t\treturn converted;\n\t\t}\n\t\t// Filter out ImageContent from all messages, replacing with text placeholder\n\t\treturn converted.map((msg) => {\n\t\t\tif (msg.role === \"user\" || msg.role === \"toolResult\") {\n\t\t\t\tconst content = msg.content;\n\t\t\t\tif (Array.isArray(content)) {\n\t\t\t\t\tconst hasImages = content.some((c) => c.type === \"image\");\n\t\t\t\t\tif (hasImages) {\n\t\t\t\t\t\tconst filteredContent = content\n\t\t\t\t\t\t\t.map((c) =>\n\t\t\t\t\t\t\t\tc.type === \"image\" ? { type: \"text\" as const, text: \"Image reading is disabled.\" } : c,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t(c, i, arr) =>\n\t\t\t\t\t\t\t\t\t// Dedupe consecutive \"Image reading is disabled.\" texts\n\t\t\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\t\t\tc.type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\tc.text === \"Image reading is disabled.\" &&\n\t\t\t\t\t\t\t\t\t\ti > 0 &&\n\t\t\t\t\t\t\t\t\t\tarr[i - 1].type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\t(arr[i - 1] as { type: \"text\"; text: string }).text === \"Image reading is disabled.\"\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\treturn { ...msg, content: filteredContent };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn msg;\n\t\t});\n\t};\n\n\tconst extensionRunnerRef: { current?: ExtensionRunner } = {};\n\n\tagent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt: \"\",\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: [],\n\t\t},\n\t\tconvertToLlm: convertToLlmWithBlockImages,\n\t\tstreamFn: async (model, context, options) => {\n\t\t\tconst auth = await modelRegistry.getApiKeyAndHeaders(model);\n\t\t\tif (!auth.ok) {\n\t\t\t\tthrow new Error(auth.error);\n\t\t\t}\n\t\t\tconst providerRetrySettings = settingsManager.getProviderRetrySettings();\n\t\t\tconst httpIdleTimeoutMs = settingsManager.getHttpIdleTimeoutMs();\n\t\t\t// SDKs treat timeout=0 as 0ms (immediate timeout), not \"no timeout\".\n\t\t\t// Use max int32 to effectively disable the timeout.\n\t\t\tconst effectiveTimeoutMs = httpIdleTimeoutMs === 0 ? 2147483647 : httpIdleTimeoutMs;\n\t\t\tconst timeoutMs = options?.timeoutMs ?? providerRetrySettings.timeoutMs ?? effectiveTimeoutMs;\n\t\t\tconst websocketConnectTimeoutMs =\n\t\t\t\toptions?.websocketConnectTimeoutMs ?? settingsManager.getWebSocketConnectTimeoutMs();\n\t\t\treturn streamSimple(model, context, {\n\t\t\t\t...options,\n\t\t\t\tapiKey: auth.apiKey,\n\t\t\t\ttimeoutMs,\n\t\t\t\twebsocketConnectTimeoutMs,\n\t\t\t\tmaxRetries: options?.maxRetries ?? providerRetrySettings.maxRetries,\n\t\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs ?? providerRetrySettings.maxRetryDelayMs,\n\t\t\t\theaders: mergeProviderAttributionHeaders(\n\t\t\t\t\tmodel,\n\t\t\t\t\tsettingsManager,\n\t\t\t\t\toptions?.sessionId,\n\t\t\t\t\tauth.headers,\n\t\t\t\t\toptions?.headers,\n\t\t\t\t),\n\t\t\t});\n\t\t},\n\t\tonPayload: async (payload, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"before_provider_request\")) {\n\t\t\t\treturn payload;\n\t\t\t}\n\t\t\treturn runner.emitBeforeProviderRequest(payload);\n\t\t},\n\t\tonResponse: async (response, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"after_provider_response\")) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait runner.emit({\n\t\t\t\ttype: \"after_provider_response\",\n\t\t\t\tstatus: response.status,\n\t\t\t\theaders: response.headers,\n\t\t\t});\n\t\t},\n\t\tsessionId: sessionManager.getSessionId(),\n\t\ttransformContext: async (messages) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner) return messages;\n\t\t\treturn runner.emitContext(messages);\n\t\t},\n\t\tsteeringMode: settingsManager.getSteeringMode(),\n\t\tfollowUpMode: settingsManager.getFollowUpMode(),\n\t\ttransport: settingsManager.getTransport(),\n\t\tthinkingBudgets: settingsManager.getThinkingBudgets(),\n\t\tmaxRetryDelayMs: settingsManager.getProviderRetrySettings().maxRetryDelayMs,\n\t});\n\n\t// Restore messages if session has existing data\n\tif (hasExistingSession) {\n\t\tagent.state.messages = existingSession.messages;\n\t\tif (!hasThinkingEntry) {\n\t\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t\t}\n\t} else {\n\t\t// Save initial model and thinking level for new sessions so they can be restored on resume\n\t\tif (model) {\n\t\t\tsessionManager.appendModelChange(model.provider, model.id);\n\t\t}\n\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t}\n\n\tconst session = new AgentSession({\n\t\tagent,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tcwd,\n\t\tscopedModels: options.scopedModels,\n\t\tresourceLoader,\n\t\tcustomTools: options.customTools,\n\t\tmodelRegistry,\n\t\tinitialActiveToolNames,\n\t\tallowedToolNames,\n\t\texcludedToolNames,\n\t\textensionRunnerRef,\n\t\tloadoutAccessPolicy: effectiveLoadoutAccessPolicy,\n\t\tbashSandboxPreflight: options.bashSandboxPreflight,\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t});\n\tconst extensionsResult = resourceLoader.getExtensions();\n\n\treturn {\n\t\tsession,\n\t\textensionsResult,\n\t\tmodelFallbackMessage,\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACN,KAAK,EAEL,0BAA0B,EAC1B,yBAAyB,GAEzB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAA4B,YAAY,EAA0B,MAAM,QAAQ,CAAC;AAC5G,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAgC,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,kCAAkC,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAErH,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAC;AAE5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAC/F,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC,OAAO,EACN,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,eAAe,EAEf,qBAAqB,GACrB,MAAM,kBAAkB,CAAC;AA8E1B,aAAa;AAEb,cAAc,4BAA4B,CAAC;AAc3C,OAAO,EACN,qBAAqB;AACrB,kCAAkC;AAClC,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,YAAY,GACZ,CAAC;AAEF,mBAAmB;AAEnB,SAAS,kBAAkB,GAAW;IACrC,OAAO,WAAW,EAAE,CAAC;AAAA,CACrB;AAOD;;;;;;;;;;GAUG;AACH,SAAS,8BAA8B,CACtC,cAA8B,EAC9B,QAAwB,EACI;IAC5B,MAAM,MAAM,GAAG,0BAA0B,CAAC,QAAQ,CAAC,CAAC;IACpD,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,EAAE,QAAQ,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,QAAwB,CAAC;IAC7B,IAAI,CAAC;QACJ,QAAQ,GAAG,yBAAyB,CAAC,QAAQ,EAAE,iEAAiE,CAAC,CAAC;IACnH,CAAC;IAAC,MAAM,CAAC;QACR,MAAM,aAAa,GAAG,cAAc;aAClC,SAAS,EAAE;aACX,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,KAAK,iBAAiB,CAAC,CAAC;QACrF,IAAI,CAAC,aAAa,EAAE,CAAC;YACpB,cAAc,CAAC,iBAAiB,CAAC,iBAAiB,EAAE;gBACnD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBACrC,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,UAAU,EAAE,KAAK,CAAC,UAAU;oBAC5B,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;iBACrE,CAAC,CAAC;aACH,CAAC,CAAC;QACJ,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7F,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,gBAAgB,CAAC;QAC9D,MAAM,WAAW,GAAG,0BAA0B,CAAC;YAC9C,SAAS,EAAE,cAAc,CAAC,YAAY,EAAE;YACxC,KAAK,EAAE,UAAU,UAAU,EAAE,EAAE;YAC/B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,MAAM,EAAE,oBAAoB;YAC5B,OAAO,EAAE,0DAA0D;YACnE,KAAK,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE;YAC/C,WAAW,EAAE,UAAU;SACvB,CAAC,CAAC;QACH,MAAM,IAAI,uBAAuB,CAChC,iDAAiD,OAAO,KAAK;YAC5D,4EAA4E,EAC7E,WAAW,CACX,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAwB,CAAC;IACxE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAC/B,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAChC,cAAc,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,MAAM,mBAAmB,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1E,cAAc,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,EAAE,mBAAmB,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IACnG,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,mBAAmB,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC;AAAA,CACjF;AAED,SAAS,8BAA8B,CAAC,OAAkC,EAAY;IACrF,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,KAAK,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,EAAE,CAAC;QACpF,OAAO,EAAE,CAAC;IACX,CAAC;IACD,OAAO,CAAC,GAAG,YAAY,CAAC,CAAC;AAAA,CACzB;AAED,SAAS,oCAAoC,CAAC,OAAkC,EAAwB;IACvG,OAAO,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AAAA,CACrE;AAED,SAAS,kCAAkC,CAC1C,OAAkC,EAClC,cAA8B,EAC9B,GAAW,EACX,QAAgB,EAChB,QAAiB,EACiB;IAClC,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC,mBAAmB,CAAC;IACpC,CAAC;IAED,MAAM,OAAO,GAAG,kCAAkC,CAAC;QAClD,aAAa,EAAE,8BAA8B,CAAC,OAAO,CAAC;QACtD,cAAc;QACd,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,gBAAgB,EAAE,oCAAoC,CAAC,OAAO,CAAC;QAC/D,iBAAiB,EAAE,OAAO,CAAC,YAAY;KACvC,CAAC,CAAC;IAEH,wFAAwF;IACxF,IAAI,QAAQ,EAAE,CAAC;QACd,IAAI,CAAC;YACJ,MAAM,YAAY,GAAG,sBAAsB,CAAC;gBAC3C,QAAQ;gBACR,OAAO;gBACP,cAAc;gBACd,GAAG;gBACH,QAAQ;gBACR,GAAG,EAAE,OAAO,CAAC,GAAG;aAChB,CAAC,CAAC;YACH,IAAI,YAAY,CAAC,mBAAmB,EAAE,CAAC;gBACtC,OAAO,YAAY,CAAC,mBAAmB,CAAC;YACzC,CAAC;QACF,CAAC;QAAC,MAAM,CAAC;YACR,yCAAyC;QAC1C,CAAC;IACF,CAAC;IAED,MAAM,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,EAAE,IAAI,EAAE,CAAC;IAChE,IAAI,CAAC,mBAAmB,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAClE,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACJ,MAAM,QAAQ,GAAG,iBAAiB,CAAC;YAClC,IAAI,EAAE,OAAO;YACb,aAAa,EAAE,mBAAmB;YAClC,OAAO;YACP,cAAc;YACd,GAAG;YACH,QAAQ;YACR,GAAG,EAAE,OAAO,CAAC,GAAG;SAChB,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,mBAAmB,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AAAA,CACD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAO,GAA8B,EAAE,EAAqC;IACpH,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC1F,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC;IACzF,IAAI,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAE5C,uDAAuD;IACvD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAChF,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACxE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAE7F,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,eAAe,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACzF,MAAM,iBAAiB,GAAG,wBAAwB,CAAC,eAAe,CAAC,CAAC;IACpE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,cAAc,CAAC,MAAM,CAAC,GAAG,EAAE,oBAAoB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;IACjH,IAAI,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IACxC,IAAI,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IACxC,MAAM,WAAW,GAAG,cAAc,CAAC,cAAc,EAAE,CAAC;IACpD,IAAI,CAAC,YAAY,IAAI,cAAc,CAAC,WAAW,EAAE,IAAI,WAAW,EAAE,CAAC;QAClE,YAAY;YACX,cAAc;iBACZ,YAAY,EAAE;iBACd,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC;iBACjC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC;QAChD,YAAY,GAAG,IAAI,mBAAmB,CAAC,YAAY,EAAE,GAAG,WAAW,eAAe,CAAC,CAAC;IACrF,CAAC;IAED,IAAI,CAAC,cAAc,EAAE,CAAC;QACrB,cAAc,GAAG,IAAI,qBAAqB,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC,CAAC;QAC/E,MAAM,cAAc,CAAC,MAAM,EAAE,CAAC;QAC9B,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAC/B,CAAC;IAED,yEAAyE;IACzE,4EAA4E;IAC5E,sDAAsD;IACtD,MAAM,eAAe,GAAG,cAAc,CAAC,mBAAmB,EAAE,CAAC;IAC7D,MAAM,kBAAkB,GAAG,8BAA8B,CAAC,cAAc,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC;IACpG,MAAM,kBAAkB,GAAG,eAAe,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/D,MAAM,gBAAgB,GAAG,cAAc,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,uBAAuB,CAAC,CAAC;IAE5G,IAAI,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC1B,IAAI,oBAAwC,CAAC;IAE7C,oDAAoD;IACpD,IAAI,CAAC,KAAK,IAAI,kBAAkB,IAAI,eAAe,CAAC,KAAK,EAAE,CAAC;QAC3D,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACxG,IAAI,aAAa,IAAI,aAAa,CAAC,iBAAiB,CAAC,aAAa,CAAC,EAAE,CAAC;YACrE,KAAK,GAAG,aAAa,CAAC;QACvB,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAC;YACZ,oBAAoB,GAAG,2BAA2B,eAAe,CAAC,KAAK,CAAC,QAAQ,IAAI,eAAe,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACrH,CAAC;IACF,CAAC;IAED,4FAA4F;IAC5F,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACrC,YAAY,EAAE,EAAE;YAChB,YAAY,EAAE,kBAAkB;YAChC,eAAe,EAAE,eAAe,CAAC,kBAAkB,EAAE;YACrD,cAAc,EAAE,eAAe,CAAC,eAAe,EAAE;YACjD,oBAAoB,EAAE,eAAe,CAAC,uBAAuB,EAAE;YAC/D,aAAa;SACb,CAAC,CAAC;QACH,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QACrB,IAAI,CAAC,KAAK,EAAE,CAAC;YACZ,oBAAoB,GAAG,8BAA8B,EAAE,CAAC;QACzD,CAAC;aAAM,IAAI,oBAAoB,EAAE,CAAC;YACjC,oBAAoB,IAAI,WAAW,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;QACjE,CAAC;IACF,CAAC;IAED,mFAAmF;IACnF,MAAM,4BAA4B,GAAG,kCAAkC,CACtE,OAAO,EACP,cAAc,EACd,GAAG,EACH,QAAQ,EACR,KAAK,EAAE,QAAQ,CACf,CAAC;IAEF,IAAI,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAE1C,sDAAsD;IACtD,IAAI,aAAa,KAAK,SAAS,IAAI,kBAAkB,EAAE,CAAC;QACvD,aAAa,GAAG,gBAAgB;YAC/B,CAAC,CAAE,eAAe,CAAC,aAA+B;YAClD,CAAC,CAAC,CAAC,eAAe,CAAC,uBAAuB,EAAE,IAAI,sBAAsB,CAAC,CAAC;IAC1E,CAAC;IAED,gCAAgC;IAChC,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QACjC,aAAa,GAAG,eAAe,CAAC,uBAAuB,EAAE,IAAI,sBAAsB,CAAC;IACrF,CAAC;IAED,8BAA8B;IAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,aAAa,GAAG,KAAK,CAAC;IACvB,CAAC;SAAM,CAAC;QACP,aAAa,GAAG,kBAAkB,CAAC,KAAK,EAAE,aAAa,CAAkB,CAAC;IAC3E,CAAC;IAED,MAAM,sBAAsB,GAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7E,MAAM,gBAAgB,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACvF,MAAM,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC;IAC/C,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACvF,MAAM,sBAAsB,GAAa,CACxC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,sBAAsB,CAClF,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,mBAAmB,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAEpD,IAAI,KAAY,CAAC;IAEjB,+FAA+F;IAC/F,MAAM,2BAA2B,GAAG,CAAC,QAAwB,EAAa,EAAE,CAAC;QAC5E,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QACzC,+DAA+D;QAC/D,IAAI,CAAC,eAAe,CAAC,cAAc,EAAE,EAAE,CAAC;YACvC,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,6EAA6E;QAC7E,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;YAC7B,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBACtD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;gBAC5B,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC5B,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;oBAC1D,IAAI,SAAS,EAAE,CAAC;wBACf,MAAM,eAAe,GAAG,OAAO;6BAC7B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACV,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,4BAA4B,EAAE,CAAC,CAAC,CAAC,CAAC,CACtF;6BACA,MAAM,CACN,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE;wBACb,wDAAwD;wBACxD,CAAC,CACA,CAAC,CAAC,IAAI,KAAK,MAAM;4BACjB,CAAC,CAAC,IAAI,KAAK,4BAA4B;4BACvC,CAAC,GAAG,CAAC;4BACL,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM;4BACzB,GAAG,CAAC,CAAC,GAAG,CAAC,CAAoC,CAAC,IAAI,KAAK,4BAA4B,CACpF,CACF,CAAC;wBACH,OAAO,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;oBAC7C,CAAC;gBACF,CAAC;YACF,CAAC;YACD,OAAO,GAAG,CAAC;QAAA,CACX,CAAC,CAAC;IAAA,CACH,CAAC;IAEF,MAAM,kBAAkB,GAAkC,EAAE,CAAC;IAE7D,KAAK,GAAG,IAAI,KAAK,CAAC;QACjB,YAAY,EAAE;YACb,YAAY,EAAE,EAAE;YAChB,KAAK;YACL,aAAa;YACb,KAAK,EAAE,EAAE;SACT;QACD,YAAY,EAAE,2BAA2B;QACzC,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;YAC5C,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;YAC5D,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC;YACD,MAAM,qBAAqB,GAAG,eAAe,CAAC,wBAAwB,EAAE,CAAC;YACzE,MAAM,iBAAiB,GAAG,eAAe,CAAC,oBAAoB,EAAE,CAAC;YACjE,qEAAqE;YACrE,oDAAoD;YACpD,MAAM,kBAAkB,GAAG,iBAAiB,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,iBAAiB,CAAC;YACpF,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,qBAAqB,CAAC,SAAS,IAAI,kBAAkB,CAAC;YAC9F,MAAM,yBAAyB,GAC9B,OAAO,EAAE,yBAAyB,IAAI,eAAe,CAAC,4BAA4B,EAAE,CAAC;YACtF,OAAO,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE;gBACnC,GAAG,OAAO;gBACV,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,SAAS;gBACT,yBAAyB;gBACzB,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,qBAAqB,CAAC,UAAU;gBACnE,eAAe,EAAE,OAAO,EAAE,eAAe,IAAI,qBAAqB,CAAC,eAAe;gBAClF,OAAO,EAAE,+BAA+B,CACvC,KAAK,EACL,eAAe,EACf,OAAO,EAAE,SAAS,EAClB,IAAI,CAAC,OAAO,EACZ,OAAO,EAAE,OAAO,CAChB;aACD,CAAC,CAAC;QAAA,CACH;QACD,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC;YAC1C,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,yBAAyB,CAAC,EAAE,CAAC;gBACrD,OAAO,OAAO,CAAC;YAChB,CAAC;YACD,OAAO,MAAM,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;QAAA,CACjD;QACD,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC;YAC1C,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,yBAAyB,CAAC,EAAE,CAAC;gBACrD,OAAO;YACR,CAAC;YACD,MAAM,MAAM,CAAC,IAAI,CAAC;gBACjB,IAAI,EAAE,yBAAyB;gBAC/B,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,OAAO,EAAE,QAAQ,CAAC,OAAO;aACzB,CAAC,CAAC;QAAA,CACH;QACD,SAAS,EAAE,cAAc,CAAC,YAAY,EAAE;QACxC,gBAAgB,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC;YAC1C,IAAI,CAAC,MAAM;gBAAE,OAAO,QAAQ,CAAC;YAC7B,OAAO,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAAA,CACpC;QACD,YAAY,EAAE,eAAe,CAAC,eAAe,EAAE;QAC/C,YAAY,EAAE,eAAe,CAAC,eAAe,EAAE;QAC/C,SAAS,EAAE,eAAe,CAAC,YAAY,EAAE;QACzC,eAAe,EAAE,eAAe,CAAC,kBAAkB,EAAE;QACrD,eAAe,EAAE,eAAe,CAAC,wBAAwB,EAAE,CAAC,eAAe;QAC3E,aAAa,EAAE,iBAAiB,CAAC,aAAa;QAC9C,YAAY,EAAE,iBAAiB,CAAC,YAAY;QAC5C,aAAa,EAAE,iBAAiB,CAAC,aAAa;QAC9C,kBAAkB,EAAE,iBAAiB,CAAC,kBAAkB;QACxD,qBAAqB,EAAE,iBAAiB,CAAC,qBAAqB;QAC9D,GAAG;QACH,wEAAuE;QACvE,iEAAiE;QACjE,mBAAmB,EAAE,6BAA6B,EAAE;KACpD,CAAC,CAAC;IAEH,gDAAgD;IAChD,IAAI,kBAAkB,EAAE,CAAC;QACxB,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,CAAC;QACnD,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACvB,cAAc,CAAC,yBAAyB,CAAC,aAAa,CAAC,CAAC;QACzD,CAAC;IACF,CAAC;SAAM,CAAC;QACP,2FAA2F;QAC3F,IAAI,KAAK,EAAE,CAAC;YACX,cAAc,CAAC,iBAAiB,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,cAAc,CAAC,yBAAyB,CAAC,aAAa,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,YAAY,CAAC;QAChC,KAAK;QACL,cAAc;QACd,eAAe;QACf,GAAG;QACH,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,cAAc;QACd,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,aAAa;QACb,sBAAsB;QACtB,gBAAgB;QAChB,iBAAiB;QACjB,kBAAkB;QAClB,mBAAmB,EAAE,4BAA4B;QACjD,oBAAoB,EAAE,OAAO,CAAC,oBAAoB;QAClD,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;QAC5C,gBAAgB,EAAE,kBAAkB,CAAC,MAAM;QAC3C,YAAY;QACZ,YAAY;QACZ,YAAY,EAAE,OAAO,CAAC,YAAY;KAClC,CAAC,CAAC;IACH,MAAM,gBAAgB,GAAG,cAAc,CAAC,aAAa,EAAE,CAAC;IAExD,OAAO;QACN,OAAO;QACP,gBAAgB;QAChB,oBAAoB;KACpB,CAAC;AAAA,CACF","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { join } from \"node:path\";\nimport {\n\tAgent,\n\ttype AgentMessage,\n\tinspectTranscriptIntegrity,\n\trepairTranscriptIntegrity,\n\ttype ThinkingLevel,\n} from \"omk-agent-core\";\nimport { createNodeResourceKeyResolver } from \"omk-agent-core/node\";\nimport { clampThinkingLevel, type Message, type Model, streamSimple, type ToolResultMessage } from \"omk-ai\";\nimport { getAgentDir } from \"../config.ts\";\nimport { ReplayLedgerManager } from \"../guardrails/evidence-system.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { AgentSession, type SessionTranscriptRepair } from \"./agent-session.ts\";\nimport { resolveAgentToolSettings } from \"./agent-tool-settings.ts\";\nimport { formatNoModelsAvailableMessage } from \"./auth-guidance.ts\";\nimport { AuthStorage } from \"./auth-storage.ts\";\nimport { DEFAULT_THINKING_LEVEL } from \"./defaults.ts\";\nimport { createDomainDispatchRuntimeSession, isDomainRoutingEnabled, tryDomainDispatch } from \"./domain-dispatch.ts\";\nimport type { ExtensionRunner, LoadExtensionsResult, SessionStartEvent, ToolDefinition } from \"./extensions/index.ts\";\nimport { tryGrokHarnessDispatch } from \"./grok-harness-dispatch.ts\";\nimport type { LoadoutAccessPolicy } from \"./loadout-access-policy.ts\";\nimport { convertToLlm } from \"./messages.ts\";\nimport { ModelRegistry } from \"./model-registry.ts\";\nimport { findInitialModel } from \"./model-resolver.ts\";\nimport { mergeProviderAttributionHeaders } from \"./provider-attribution.ts\";\nimport type { ResourceLoader } from \"./resource-loader.ts\";\nimport { DefaultResourceLoader } from \"./resource-loader.ts\";\nimport { getDefaultSessionDir, SessionManager } from \"./session-manager.ts\";\nimport { classifySessionTermination, SessionTerminationError } from \"./session-termination.ts\";\nimport { SettingsManager } from \"./settings-manager.ts\";\nimport { time } from \"./timings.ts\";\nimport type { BashSandboxPreflight } from \"./tools/bash.ts\";\nimport {\n\tallToolNames,\n\tcreateBashTool,\n\tcreateCodingTools,\n\tcreateEditTool,\n\tcreateFindTool,\n\tcreateGrepTool,\n\tcreateLsTool,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateWriteTool,\n\ttype ToolName,\n\twithFileMutationQueue,\n} from \"./tools/index.ts\";\n\nexport interface CreateAgentSessionOptions {\n\t/** Working directory for project-local discovery. Default: process.cwd() */\n\tcwd?: string;\n\t/** Global config directory. Default: ~/.omk/agent */\n\tagentDir?: string;\n\n\t/** Auth storage for credentials. Default: AuthStorage.create(agentDir/auth.json) */\n\tauthStorage?: AuthStorage;\n\t/** Model registry. Default: ModelRegistry.create(authStorage, agentDir/models.json) */\n\tmodelRegistry?: ModelRegistry;\n\n\t/** Model to use. Default: from settings, else first available */\n\tmodel?: Model<any>;\n\t/** Thinking level. Default: from settings, else 'medium' (clamped to model capabilities) */\n\tthinkingLevel?: ThinkingLevel;\n\t/** Models available for cycling (Ctrl+P in interactive mode) */\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel }>;\n\n\t/**\n\t * Optional default tool suppression mode when no explicit allowlist is provided.\n\t *\n\t * - \"all\": start with no tools enabled\n\t * - \"builtin\": disable the default built-in tools (read, bash, edit, write)\n\t * but keep extension/custom tools enabled\n\t */\n\tnoTools?: \"all\" | \"builtin\";\n\t/**\n\t * Optional allowlist of tool names.\n\t *\n\t * When omitted, OMK enables the default built-in tools (read, bash, edit, write)\n\t * and leaves extension/custom tools enabled unless `noTools` changes that default.\n\t * When provided, only the listed tool names are enabled.\n\t */\n\ttools?: string[];\n\t/** Optional denylist of tool names to disable. Applies after `tools` when both are provided. */\n\texcludeTools?: string[];\n\t/** Custom tools to register (in addition to built-in tools). */\n\tcustomTools?: ToolDefinition[];\n\n\t/** Resource loader. When omitted, DefaultResourceLoader is used. */\n\tresourceLoader?: ResourceLoader;\n\n\t/** Session manager. Default: SessionManager.create(cwd) */\n\tsessionManager?: SessionManager;\n\n\t/** Settings manager. Default: SettingsManager.create(cwd, agentDir) */\n\tsettingsManager?: SettingsManager;\n\t/** Session start event metadata for extension runtime startup. */\n\tsessionStartEvent?: SessionStartEvent;\n\t/**\n\t * Optional prompt hint used only for opt-in domain routing (`OMK_DOMAIN_ROUTING=1`).\n\t * This text only selects a loadout policy and is never sent to the model.\n\t */\n\tdomainRoutingPrompt?: string;\n\t/** Optional loadout enforcement policy for SDK-created sessions. */\n\tloadoutAccessPolicy?: LoadoutAccessPolicy;\n\t/** Trusted sandbox preflight used for built-in local bash execution. */\n\tbashSandboxPreflight?: BashSandboxPreflight;\n\t/** Optional replay ledger shared with VerifiedEvidenceExecutor freshness checks. */\n\treplayLedger?: ReplayLedgerManager;\n\t/** Goal binding for AgentSession replay events; defaults to replayLedger.goalId. */\n\treplayGoalId?: string;\n\t/** Optional lane binding for AgentSession replay events. */\n\treplayLaneId?: string;\n}\n\n/** Result from createAgentSession */\nexport interface CreateAgentSessionResult {\n\t/** The created session */\n\tsession: AgentSession;\n\t/** Extensions result (for UI context setup in interactive mode) */\n\textensionsResult: LoadExtensionsResult;\n\t/** Warning if session was restored with a different model than saved */\n\tmodelFallbackMessage?: string;\n}\n\n// Re-exports\n\nexport * from \"./agent-session-runtime.ts\";\nexport type {\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n\tExtensionFactory,\n\tSlashCommandInfo,\n\tSlashCommandSource,\n\tToolDefinition,\n} from \"./extensions/index.ts\";\nexport type { PromptTemplate } from \"./prompt-templates.ts\";\nexport type { Skill } from \"./skills.ts\";\nexport type { Tool } from \"./tools/index.ts\";\n\nexport {\n\twithFileMutationQueue,\n\t// Tool factories (for custom cwd)\n\tcreateCodingTools,\n\tcreateReadOnlyTools,\n\tcreateReadTool,\n\tcreateBashTool,\n\tcreateEditTool,\n\tcreateWriteTool,\n\tcreateGrepTool,\n\tcreateFindTool,\n\tcreateLsTool,\n};\n\n// Helper Functions\n\nfunction getDefaultAgentDir(): string {\n\treturn getAgentDir();\n}\n\ninterface SessionTranscriptRecovery {\n\tmessages: AgentMessage[];\n\trepair?: SessionTranscriptRepair;\n}\n\n/**\n * ALG001-A: inspect the restored transcript on every live session open/resume.\n *\n * - A clean transcript passes through untouched.\n * - Unambiguous missing-only tail results are auto-repaired: synthetic\n * terminal results (tool-result/v2 envelope) are persisted to the session\n * so the repair is durable and idempotent, together with a durable\n * `transcript_repaired` audit entry.\n * - Any duplicate/orphan/duplicate-call/interleaved corruption marks the\n * session (`session_corrupt` entry, once) and fails closed.\n */\nfunction recoverSessionTranscriptOnOpen(\n\tsessionManager: SessionManager,\n\tmessages: AgentMessage[],\n): SessionTranscriptRecovery {\n\tconst report = inspectTranscriptIntegrity(messages);\n\tif (report.ok) {\n\t\treturn { messages };\n\t}\n\n\tlet repaired: AgentMessage[];\n\ttry {\n\t\trepaired = repairTranscriptIntegrity(messages, \"Tool result missing; synthesized during session resume recovery\");\n\t} catch {\n\t\tconst alreadyMarked = sessionManager\n\t\t\t.getBranch()\n\t\t\t.some((entry) => entry.type === \"custom\" && entry.customType === \"session_corrupt\");\n\t\tif (!alreadyMarked) {\n\t\t\tsessionManager.appendCustomEntry(\"session_corrupt\", {\n\t\t\t\tissues: report.issues.map((issue) => ({\n\t\t\t\t\tkind: issue.kind,\n\t\t\t\t\ttoolCallId: issue.toolCallId,\n\t\t\t\t\t...(issue.toolName === undefined ? {} : { toolName: issue.toolName }),\n\t\t\t\t})),\n\t\t\t});\n\t\t}\n\t\tconst summary = report.issues.map((issue) => `${issue.kind}:${issue.toolCallId}`).join(\", \");\n\t\tconst firstIssue = report.issues[0]?.kind ?? \"missing_result\";\n\t\tconst termination = classifySessionTermination({\n\t\t\tsessionId: sessionManager.getSessionId(),\n\t\t\trunId: `resume-${randomUUID()}`,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tsource: \"inferred_on_resume\",\n\t\t\tmessage: \"Session transcript has ambiguous tool-result corruption.\",\n\t\t\tcause: { area: \"transcript\", code: firstIssue },\n\t\t\tsideEffects: \"possible\",\n\t\t});\n\t\tthrow new SessionTerminationError(\n\t\t\t`Cannot open session: corrupt tool transcript (${summary}). ` +\n\t\t\t\t\"The session has been marked corrupt; repair it explicitly before resuming.\",\n\t\t\ttermination,\n\t\t);\n\t}\n\n\tconst inserted = repaired.slice(messages.length) as ToolResultMessage[];\n\tif (inserted.length === 0) {\n\t\treturn { messages: repaired };\n\t}\n\tfor (const message of inserted) {\n\t\tsessionManager.appendMessage(message);\n\t}\n\tconst insertedToolCallIds = inserted.map((message) => message.toolCallId);\n\tsessionManager.appendCustomEntry(\"transcript_repaired\", { insertedToolCallIds, reason: \"resume\" });\n\treturn { messages: repaired, repair: { insertedToolCallIds, reason: \"resume\" } };\n}\n\nfunction getDomainDispatchBaseToolNames(options: CreateAgentSessionOptions): string[] {\n\tif (!options.tools && (options.noTools === \"all\" || options.noTools === \"builtin\")) {\n\t\treturn [];\n\t}\n\treturn [...allToolNames];\n}\n\nfunction getAllowedToolNamesForDomainDispatch(options: CreateAgentSessionOptions): string[] | undefined {\n\treturn options.tools ?? (options.noTools === \"all\" ? [] : undefined);\n}\n\nfunction createEffectiveLoadoutAccessPolicy(\n\toptions: CreateAgentSessionOptions,\n\tresourceLoader: ResourceLoader,\n\tcwd: string,\n\tagentDir: string,\n\tprovider?: string,\n): LoadoutAccessPolicy | undefined {\n\tif (options.loadoutAccessPolicy) {\n\t\treturn options.loadoutAccessPolicy;\n\t}\n\n\tconst session = createDomainDispatchRuntimeSession({\n\t\tbaseToolNames: getDomainDispatchBaseToolNames(options),\n\t\tresourceLoader,\n\t\tcustomTools: options.customTools,\n\t\tallowedToolNames: getAllowedToolNamesForDomainDispatch(options),\n\t\texcludedToolNames: options.excludeTools,\n\t});\n\n\t// Grok OAuth: apply grok-harness domain loadout without requiring OMK_DOMAIN_ROUTING=1.\n\tif (provider) {\n\t\ttry {\n\t\t\tconst grokDispatch = tryGrokHarnessDispatch({\n\t\t\t\tprovider,\n\t\t\t\tsession,\n\t\t\t\tresourceLoader,\n\t\t\t\tcwd,\n\t\t\t\tagentDir,\n\t\t\t\tenv: process.env,\n\t\t\t});\n\t\t\tif (grokDispatch.loadoutAccessPolicy) {\n\t\t\t\treturn grokDispatch.loadoutAccessPolicy;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to opt-in domain routing.\n\t\t}\n\t}\n\n\tconst domainRoutingPrompt = options.domainRoutingPrompt?.trim();\n\tif (!domainRoutingPrompt || !isDomainRoutingEnabled(process.env)) {\n\t\treturn undefined;\n\t}\n\n\ttry {\n\t\tconst dispatch = tryDomainDispatch({\n\t\t\trole: \"coder\",\n\t\t\tinitialPrompt: domainRoutingPrompt,\n\t\t\tsession,\n\t\t\tresourceLoader,\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tenv: process.env,\n\t\t});\n\t\treturn dispatch.loadoutAccessPolicy;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Create an AgentSession with the specified options.\n *\n * @example\n * ```typescript\n * // Minimal - uses defaults\n * const { session } = await createAgentSession();\n *\n * // With explicit model\n * import { getModel } from 'omk-ai';\n * const { session } = await createAgentSession({\n * model: getModel('anthropic', 'claude-opus-4-5'),\n * thinkingLevel: 'high',\n * });\n *\n * // Continue previous session\n * const { session, modelFallbackMessage } = await createAgentSession({\n * continueSession: true,\n * });\n *\n * // Full control\n * const loader = new DefaultResourceLoader({\n * cwd: process.cwd(),\n * agentDir: getAgentDir(),\n * settingsManager: SettingsManager.create(),\n * });\n * await loader.reload();\n * const { session } = await createAgentSession({\n * model: myModel,\n * tools: [\"read\", \"bash\"],\n * resourceLoader: loader,\n * sessionManager: SessionManager.inMemory(),\n * });\n * ```\n */\nexport async function createAgentSession(options: CreateAgentSessionOptions = {}): Promise<CreateAgentSessionResult> {\n\tconst cwd = resolvePath(options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd());\n\tconst agentDir = options.agentDir ? resolvePath(options.agentDir) : getDefaultAgentDir();\n\tlet resourceLoader = options.resourceLoader;\n\n\t// Use provided or create AuthStorage and ModelRegistry\n\tconst authPath = options.agentDir ? join(agentDir, \"auth.json\") : undefined;\n\tconst modelsPath = options.agentDir ? join(agentDir, \"models.json\") : undefined;\n\tconst authStorage = options.authStorage ?? AuthStorage.create(authPath);\n\tconst modelRegistry = options.modelRegistry ?? ModelRegistry.create(authStorage, modelsPath);\n\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst agentToolSettings = resolveAgentToolSettings(settingsManager);\n\tconst sessionManager = options.sessionManager ?? SessionManager.create(cwd, getDefaultSessionDir(cwd, agentDir));\n\tlet replayLedger = options.replayLedger;\n\tlet replayGoalId = options.replayGoalId;\n\tconst sessionFile = sessionManager.getSessionFile();\n\tif (!replayLedger && sessionManager.isPersisted() && sessionFile) {\n\t\treplayGoalId ??=\n\t\t\tsessionManager\n\t\t\t\t.getSessionId()\n\t\t\t\t.replace(/[^A-Za-z0-9._-]+/g, \"-\")\n\t\t\t\t.replace(/^[._-]+|[._-]+$/g, \"\") || \"session\";\n\t\treplayLedger = new ReplayLedgerManager(replayGoalId, `${sessionFile}.replay.jsonl`);\n\t}\n\n\tif (!resourceLoader) {\n\t\tresourceLoader = new DefaultResourceLoader({ cwd, agentDir, settingsManager });\n\t\tawait resourceLoader.reload();\n\t\ttime(\"resourceLoader.reload\");\n\t}\n\n\t// Check if session has existing data to restore. Live open/resume always\n\t// inspects the transcript and either auto-repairs missing-only tail results\n\t// or fails closed on ambiguous corruption (ALG001-A).\n\tconst existingSession = sessionManager.buildSessionContext();\n\tconst transcriptRecovery = recoverSessionTranscriptOnOpen(sessionManager, existingSession.messages);\n\tconst hasExistingSession = existingSession.messages.length > 0;\n\tconst hasThinkingEntry = sessionManager.getBranch().some((entry) => entry.type === \"thinking_level_change\");\n\n\tlet model = options.model;\n\tlet modelFallbackMessage: string | undefined;\n\n\t// If session has data, try to restore model from it\n\tif (!model && hasExistingSession && existingSession.model) {\n\t\tconst restoredModel = modelRegistry.find(existingSession.model.provider, existingSession.model.modelId);\n\t\tif (restoredModel && modelRegistry.hasConfiguredAuth(restoredModel)) {\n\t\t\tmodel = restoredModel;\n\t\t}\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = `Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`;\n\t\t}\n\t}\n\n\t// If still no model, use findInitialModel (checks settings default, then provider defaults)\n\tif (!model) {\n\t\tconst result = await findInitialModel({\n\t\t\tscopedModels: [],\n\t\t\tisContinuing: hasExistingSession,\n\t\t\tdefaultProvider: settingsManager.getDefaultProvider(),\n\t\t\tdefaultModelId: settingsManager.getDefaultModel(),\n\t\t\tdefaultThinkingLevel: settingsManager.getDefaultThinkingLevel(),\n\t\t\tmodelRegistry,\n\t\t});\n\t\tmodel = result.model;\n\t\tif (!model) {\n\t\t\tmodelFallbackMessage = formatNoModelsAvailableMessage();\n\t\t} else if (modelFallbackMessage) {\n\t\t\tmodelFallbackMessage += `. Using ${model.provider}/${model.id}`;\n\t\t}\n\t}\n\n\t// Loadout policy after model resolution so Grok OAuth can auto-apply grok-harness.\n\tconst effectiveLoadoutAccessPolicy = createEffectiveLoadoutAccessPolicy(\n\t\toptions,\n\t\tresourceLoader,\n\t\tcwd,\n\t\tagentDir,\n\t\tmodel?.provider,\n\t);\n\n\tlet thinkingLevel = options.thinkingLevel;\n\n\t// If session has data, restore thinking level from it\n\tif (thinkingLevel === undefined && hasExistingSession) {\n\t\tthinkingLevel = hasThinkingEntry\n\t\t\t? (existingSession.thinkingLevel as ThinkingLevel)\n\t\t\t: (settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL);\n\t}\n\n\t// Fall back to settings default\n\tif (thinkingLevel === undefined) {\n\t\tthinkingLevel = settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;\n\t}\n\n\t// Clamp to model capabilities\n\tif (!model) {\n\t\tthinkingLevel = \"off\";\n\t} else {\n\t\tthinkingLevel = clampThinkingLevel(model, thinkingLevel) as ThinkingLevel;\n\t}\n\n\tconst defaultActiveToolNames: ToolName[] = [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst allowedToolNames = options.tools ?? (options.noTools === \"all\" ? [] : undefined);\n\tconst excludedToolNames = options.excludeTools;\n\tconst excludedToolNameSet = excludedToolNames ? new Set(excludedToolNames) : undefined;\n\tconst initialActiveToolNames: string[] = (\n\t\toptions.tools ? [...options.tools] : options.noTools ? [] : defaultActiveToolNames\n\t).filter((name) => !excludedToolNameSet?.has(name));\n\n\tlet agent: Agent;\n\n\t// Create convertToLlm wrapper that filters images if blockImages is enabled (defense-in-depth)\n\tconst convertToLlmWithBlockImages = (messages: AgentMessage[]): Message[] => {\n\t\tconst converted = convertToLlm(messages);\n\t\t// Check setting dynamically so mid-session changes take effect\n\t\tif (!settingsManager.getBlockImages()) {\n\t\t\treturn converted;\n\t\t}\n\t\t// Filter out ImageContent from all messages, replacing with text placeholder\n\t\treturn converted.map((msg) => {\n\t\t\tif (msg.role === \"user\" || msg.role === \"toolResult\") {\n\t\t\t\tconst content = msg.content;\n\t\t\t\tif (Array.isArray(content)) {\n\t\t\t\t\tconst hasImages = content.some((c) => c.type === \"image\");\n\t\t\t\t\tif (hasImages) {\n\t\t\t\t\t\tconst filteredContent = content\n\t\t\t\t\t\t\t.map((c) =>\n\t\t\t\t\t\t\t\tc.type === \"image\" ? { type: \"text\" as const, text: \"Image reading is disabled.\" } : c,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t(c, i, arr) =>\n\t\t\t\t\t\t\t\t\t// Dedupe consecutive \"Image reading is disabled.\" texts\n\t\t\t\t\t\t\t\t\t!(\n\t\t\t\t\t\t\t\t\t\tc.type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\tc.text === \"Image reading is disabled.\" &&\n\t\t\t\t\t\t\t\t\t\ti > 0 &&\n\t\t\t\t\t\t\t\t\t\tarr[i - 1].type === \"text\" &&\n\t\t\t\t\t\t\t\t\t\t(arr[i - 1] as { type: \"text\"; text: string }).text === \"Image reading is disabled.\"\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\treturn { ...msg, content: filteredContent };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn msg;\n\t\t});\n\t};\n\n\tconst extensionRunnerRef: { current?: ExtensionRunner } = {};\n\n\tagent = new Agent({\n\t\tinitialState: {\n\t\t\tsystemPrompt: \"\",\n\t\t\tmodel,\n\t\t\tthinkingLevel,\n\t\t\ttools: [],\n\t\t},\n\t\tconvertToLlm: convertToLlmWithBlockImages,\n\t\tstreamFn: async (model, context, options) => {\n\t\t\tconst auth = await modelRegistry.getApiKeyAndHeaders(model);\n\t\t\tif (!auth.ok) {\n\t\t\t\tthrow new Error(auth.error);\n\t\t\t}\n\t\t\tconst providerRetrySettings = settingsManager.getProviderRetrySettings();\n\t\t\tconst httpIdleTimeoutMs = settingsManager.getHttpIdleTimeoutMs();\n\t\t\t// SDKs treat timeout=0 as 0ms (immediate timeout), not \"no timeout\".\n\t\t\t// Use max int32 to effectively disable the timeout.\n\t\t\tconst effectiveTimeoutMs = httpIdleTimeoutMs === 0 ? 2147483647 : httpIdleTimeoutMs;\n\t\t\tconst timeoutMs = options?.timeoutMs ?? providerRetrySettings.timeoutMs ?? effectiveTimeoutMs;\n\t\t\tconst websocketConnectTimeoutMs =\n\t\t\t\toptions?.websocketConnectTimeoutMs ?? settingsManager.getWebSocketConnectTimeoutMs();\n\t\t\treturn streamSimple(model, context, {\n\t\t\t\t...options,\n\t\t\t\tapiKey: auth.apiKey,\n\t\t\t\ttimeoutMs,\n\t\t\t\twebsocketConnectTimeoutMs,\n\t\t\t\tmaxRetries: options?.maxRetries ?? providerRetrySettings.maxRetries,\n\t\t\t\tmaxRetryDelayMs: options?.maxRetryDelayMs ?? providerRetrySettings.maxRetryDelayMs,\n\t\t\t\theaders: mergeProviderAttributionHeaders(\n\t\t\t\t\tmodel,\n\t\t\t\t\tsettingsManager,\n\t\t\t\t\toptions?.sessionId,\n\t\t\t\t\tauth.headers,\n\t\t\t\t\toptions?.headers,\n\t\t\t\t),\n\t\t\t});\n\t\t},\n\t\tonPayload: async (payload, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"before_provider_request\")) {\n\t\t\t\treturn payload;\n\t\t\t}\n\t\t\treturn runner.emitBeforeProviderRequest(payload);\n\t\t},\n\t\tonResponse: async (response, _model) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner?.hasHandlers(\"after_provider_response\")) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait runner.emit({\n\t\t\t\ttype: \"after_provider_response\",\n\t\t\t\tstatus: response.status,\n\t\t\t\theaders: response.headers,\n\t\t\t});\n\t\t},\n\t\tsessionId: sessionManager.getSessionId(),\n\t\ttransformContext: async (messages) => {\n\t\t\tconst runner = extensionRunnerRef.current;\n\t\t\tif (!runner) return messages;\n\t\t\treturn runner.emitContext(messages);\n\t\t},\n\t\tsteeringMode: settingsManager.getSteeringMode(),\n\t\tfollowUpMode: settingsManager.getFollowUpMode(),\n\t\ttransport: settingsManager.getTransport(),\n\t\tthinkingBudgets: settingsManager.getThinkingBudgets(),\n\t\tmaxRetryDelayMs: settingsManager.getProviderRetrySettings().maxRetryDelayMs,\n\t\ttoolTimeoutMs: agentToolSettings.toolTimeoutMs,\n\t\ttoolTimeouts: agentToolSettings.toolTimeouts,\n\t\ttoolScheduler: agentToolSettings.toolScheduler,\n\t\tmaxToolConcurrency: agentToolSettings.maxToolConcurrency,\n\t\tstrictExtensionClaims: agentToolSettings.strictExtensionClaims,\n\t\tcwd,\n\t\t// §5.5 Node identity resolver: symlink/hardlink/drive/UNC path aliases\n\t\t// conflict in the dag-v2 scheduler instead of racing (ALG002-A).\n\t\tresourceKeyResolver: createNodeResourceKeyResolver(),\n\t});\n\n\t// Restore messages if session has existing data\n\tif (hasExistingSession) {\n\t\tagent.state.messages = transcriptRecovery.messages;\n\t\tif (!hasThinkingEntry) {\n\t\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t\t}\n\t} else {\n\t\t// Save initial model and thinking level for new sessions so they can be restored on resume\n\t\tif (model) {\n\t\t\tsessionManager.appendModelChange(model.provider, model.id);\n\t\t}\n\t\tsessionManager.appendThinkingLevelChange(thinkingLevel);\n\t}\n\n\tconst session = new AgentSession({\n\t\tagent,\n\t\tsessionManager,\n\t\tsettingsManager,\n\t\tcwd,\n\t\tscopedModels: options.scopedModels,\n\t\tresourceLoader,\n\t\tcustomTools: options.customTools,\n\t\tmodelRegistry,\n\t\tinitialActiveToolNames,\n\t\tallowedToolNames,\n\t\texcludedToolNames,\n\t\textensionRunnerRef,\n\t\tloadoutAccessPolicy: effectiveLoadoutAccessPolicy,\n\t\tbashSandboxPreflight: options.bashSandboxPreflight,\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t\ttranscriptRepair: transcriptRecovery.repair,\n\t\treplayLedger,\n\t\treplayGoalId,\n\t\treplayLaneId: options.replayLaneId,\n\t});\n\tconst extensionsResult = resourceLoader.getExtensions();\n\n\treturn {\n\t\tsession,\n\t\textensionsResult,\n\t\tmodelFallbackMessage,\n\t};\n}\n"]}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure, browser-safe session doctor planner (task I38).
|
|
3
|
+
*
|
|
4
|
+
* The doctor rederives every repair decision from caller-attested,
|
|
5
|
+
* accessor-free plain data plus four pure runtime dependencies:
|
|
6
|
+
* - {@link createSessionRepairPlan} (session transcript repair),
|
|
7
|
+
* - {@link inspectRunJournal} / {@link serializeRunJournalLine} (journal
|
|
8
|
+
* integrity and terminal-record serialization),
|
|
9
|
+
* - {@link decideSessionPathAccess} (per-artifact path authorization),
|
|
10
|
+
* - {@link decideCompactionCommit} (compaction commit authorization).
|
|
11
|
+
*
|
|
12
|
+
* Runtime purity: no I/O, no wall clock, no entropy, no cryptographic
|
|
13
|
+
* primitives, and no Node-only APIs. Every journal hash is recomputed by a
|
|
14
|
+
* caller-injected synchronous hash function; the doctor never mints a
|
|
15
|
+
* termination or a hash. {@link SessionIntegrityReport} is imported as a type
|
|
16
|
+
* only, so the session-integrity module is never on this planner's runtime
|
|
17
|
+
* dependency graph. All inputs are validated strictly (plain data, exact keys,
|
|
18
|
+
* accessor-free) and the returned plan is a deep-frozen copy.
|
|
19
|
+
*/
|
|
20
|
+
import type { ToolResultMessage } from "omk-ai";
|
|
21
|
+
import type { DecideCompactionCommitInput, SessionRevisionToken } from "./compaction/transaction.ts";
|
|
22
|
+
import type { RunJournalCompletePrefix, RunJournalHashFn, RunJournalTerminalRecord } from "./run-journal.ts";
|
|
23
|
+
import type { SessionByteDigest, SessionCompletePrefix, SessionIntegrityReport } from "./session-integrity.ts";
|
|
24
|
+
import type { SessionPathAccessInput, SessionPathPlatform } from "./session-path-policy.ts";
|
|
25
|
+
export declare const SESSION_DOCTOR_PLAN_SCHEMA_VERSION: 1;
|
|
26
|
+
export type SessionDoctorMode = "inspect" | "repair_dry_run" | "repair";
|
|
27
|
+
export type SessionDoctorStatus = "healthy" | "issues" | "refused";
|
|
28
|
+
export type SessionDoctorExitCode = 0 | 1 | 2;
|
|
29
|
+
export type SessionDoctorArtifact = "session" | "journal" | "path" | "compaction" | "normalized";
|
|
30
|
+
export type SessionDoctorFindingSeverity = "advisory" | "blocked";
|
|
31
|
+
export type SessionDoctorFindingReason = "session_trailing_fragment" | "session_missing_tool_result" | "session_blocked" | "session_inspection_incomplete" | "journal_trailing_fragment" | "journal_unclosed" | "journal_blocked" | "session_path_unauthorized" | "journal_path_unauthorized" | "compaction_stale" | "compaction_deferred" | "compaction_failed" | "compaction_committed" | "compaction_duplicate" | "normalized_check_unhealthy" | "contract_violation";
|
|
32
|
+
export interface SessionDoctorFinding {
|
|
33
|
+
readonly artifact: SessionDoctorArtifact;
|
|
34
|
+
readonly reason: SessionDoctorFindingReason;
|
|
35
|
+
readonly severity: SessionDoctorFindingSeverity;
|
|
36
|
+
/** Bounded upstream reason/code (e.g. an integrity reason, journal finding code, path decision reason). */
|
|
37
|
+
readonly code?: string;
|
|
38
|
+
/** Bounded identifiers (toolCallIds, runIds, ...). */
|
|
39
|
+
readonly ids?: readonly string[];
|
|
40
|
+
}
|
|
41
|
+
export type SessionDoctorActionArtifact = "session" | "journal";
|
|
42
|
+
export type SessionDoctorActionSpec = {
|
|
43
|
+
readonly kind: "quarantine_session_trailing_fragment";
|
|
44
|
+
readonly artifact: "session";
|
|
45
|
+
readonly retainPrefix: SessionCompletePrefix;
|
|
46
|
+
readonly fragment: SessionByteDigest;
|
|
47
|
+
} | {
|
|
48
|
+
readonly kind: "append_synthetic_tool_result";
|
|
49
|
+
readonly artifact: "session";
|
|
50
|
+
readonly toolCallId: string;
|
|
51
|
+
readonly toolName: string;
|
|
52
|
+
readonly repairSequence: number;
|
|
53
|
+
readonly message: Readonly<ToolResultMessage>;
|
|
54
|
+
} | {
|
|
55
|
+
readonly kind: "quarantine_journal_trailing_fragment";
|
|
56
|
+
readonly artifact: "journal";
|
|
57
|
+
readonly completePrefix: RunJournalCompletePrefix;
|
|
58
|
+
readonly lastCompleteHash: string;
|
|
59
|
+
} | {
|
|
60
|
+
readonly kind: "recover_run";
|
|
61
|
+
readonly artifact: "journal";
|
|
62
|
+
readonly runId: string;
|
|
63
|
+
readonly terminalRecord: RunJournalTerminalRecord;
|
|
64
|
+
readonly completePrefix: RunJournalCompletePrefix;
|
|
65
|
+
readonly lastCompleteHash: string;
|
|
66
|
+
} | {
|
|
67
|
+
readonly kind: "remove_stale_lock";
|
|
68
|
+
readonly artifact: SessionDoctorActionArtifact;
|
|
69
|
+
readonly platform: SessionPathPlatform;
|
|
70
|
+
readonly targetLexical: string;
|
|
71
|
+
readonly targetRealpath: string;
|
|
72
|
+
readonly holderPid: string | null;
|
|
73
|
+
readonly artifacts: readonly SessionDoctorActionArtifact[];
|
|
74
|
+
} | {
|
|
75
|
+
readonly kind: "abandon_stale_compaction";
|
|
76
|
+
readonly artifact: "session";
|
|
77
|
+
readonly transactionId: string;
|
|
78
|
+
readonly baseRevision: Readonly<SessionRevisionToken>;
|
|
79
|
+
readonly sourceSha256: string;
|
|
80
|
+
readonly staleReason: "revision_mismatch" | "source_mismatch";
|
|
81
|
+
};
|
|
82
|
+
export type SessionDoctorAction = SessionDoctorActionSpec & {
|
|
83
|
+
readonly sequence: number;
|
|
84
|
+
};
|
|
85
|
+
export interface SessionDoctorPlan {
|
|
86
|
+
readonly schemaVersion: typeof SESSION_DOCTOR_PLAN_SCHEMA_VERSION;
|
|
87
|
+
readonly mode: SessionDoctorMode;
|
|
88
|
+
readonly sessionId: string;
|
|
89
|
+
readonly repairId: string;
|
|
90
|
+
readonly status: SessionDoctorStatus;
|
|
91
|
+
readonly exitCode: SessionDoctorExitCode;
|
|
92
|
+
readonly repairable: boolean;
|
|
93
|
+
readonly requiresReinspection: boolean;
|
|
94
|
+
readonly scheduledWrites: number;
|
|
95
|
+
readonly findings: readonly SessionDoctorFinding[];
|
|
96
|
+
readonly actions: readonly SessionDoctorAction[];
|
|
97
|
+
}
|
|
98
|
+
export type SessionDoctorNormalizedCheckArtifact = "compaction_envelope" | "evidence_link" | "workspace" | "provider_model";
|
|
99
|
+
export interface SessionDoctorNormalizedCheck {
|
|
100
|
+
readonly artifact: SessionDoctorNormalizedCheckArtifact;
|
|
101
|
+
readonly id: string;
|
|
102
|
+
readonly status: "ok" | "missing" | "invalid" | "unavailable";
|
|
103
|
+
}
|
|
104
|
+
export interface SessionDoctorJournalObservation {
|
|
105
|
+
readonly bytes: Uint8Array;
|
|
106
|
+
readonly hashFn: RunJournalHashFn;
|
|
107
|
+
/** Caller-supplied terminal record for unclosed-run recovery. The doctor never mints it. */
|
|
108
|
+
readonly terminalRecord?: RunJournalTerminalRecord;
|
|
109
|
+
}
|
|
110
|
+
export interface SessionDoctorPathObservation {
|
|
111
|
+
readonly session?: Omit<SessionPathAccessInput, "intent">;
|
|
112
|
+
readonly journal?: Omit<SessionPathAccessInput, "intent">;
|
|
113
|
+
}
|
|
114
|
+
export interface SessionDoctorPlanInput {
|
|
115
|
+
readonly schemaVersion?: typeof SESSION_DOCTOR_PLAN_SCHEMA_VERSION;
|
|
116
|
+
readonly mode: SessionDoctorMode;
|
|
117
|
+
readonly sessionId: string;
|
|
118
|
+
readonly repairId: string;
|
|
119
|
+
/** Deterministic caller-provided epoch milliseconds. */
|
|
120
|
+
readonly timestamp: number;
|
|
121
|
+
readonly report: SessionIntegrityReport;
|
|
122
|
+
readonly journal?: SessionDoctorJournalObservation;
|
|
123
|
+
readonly paths?: SessionDoctorPathObservation;
|
|
124
|
+
readonly compaction?: DecideCompactionCommitInput;
|
|
125
|
+
readonly normalizedChecks?: readonly SessionDoctorNormalizedCheck[];
|
|
126
|
+
}
|
|
127
|
+
export declare function planSessionDoctor(rawInput: unknown): SessionDoctorPlan;
|
|
128
|
+
//# sourceMappingURL=session-doctor-plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-doctor-plan.d.ts","sourceRoot":"","sources":["../../src/core/session-doctor-plan.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure, browser-safe session doctor planner (task I38).\n *\n * The doctor rederives every repair decision from caller-attested,\n * accessor-free plain data plus four pure runtime dependencies:\n * - {@link createSessionRepairPlan} (session transcript repair),\n * - {@link inspectRunJournal} / {@link serializeRunJournalLine} (journal\n * integrity and terminal-record serialization),\n * - {@link decideSessionPathAccess} (per-artifact path authorization),\n * - {@link decideCompactionCommit} (compaction commit authorization).\n *\n * Runtime purity: no I/O, no wall clock, no entropy, no cryptographic\n * primitives, and no Node-only APIs. Every journal hash is recomputed by a\n * caller-injected synchronous hash function; the doctor never mints a\n * termination or a hash. {@link SessionIntegrityReport} is imported as a type\n * only, so the session-integrity module is never on this planner's runtime\n * dependency graph. All inputs are validated strictly (plain data, exact keys,\n * accessor-free) and the returned plan is a deep-frozen copy.\n */\n\nimport type { ToolResultMessage } from \"omk-ai\";\nimport type {\n\tCompactionCommitDecision,\n\tDecideCompactionCommitInput,\n\tSessionRevisionToken,\n} from \"./compaction/transaction.ts\";\nimport { decideCompactionCommit } from \"./compaction/transaction.ts\";\nimport type { RunJournalCompletePrefix, RunJournalHashFn, RunJournalTerminalRecord } from \"./run-journal.ts\";\nimport { GENESIS_HASH, inspectRunJournal, serializeRunJournalLine } from \"./run-journal.ts\";\nimport type { SessionByteDigest, SessionCompletePrefix, SessionIntegrityReport } from \"./session-integrity.ts\";\nimport type {\n\tSessionPathAccessInput,\n\tSessionPathDecision,\n\tSessionPathIntent,\n\tSessionPathPlatform,\n} from \"./session-path-policy.ts\";\nimport { decideSessionPathAccess } from \"./session-path-policy.ts\";\nimport { createSessionRepairPlan } from \"./session-repair-plan.ts\";\n\nexport const SESSION_DOCTOR_PLAN_SCHEMA_VERSION = 1 as const;\n\nconst MAX_IDENTIFIER_LENGTH = 128;\nconst MAX_NORMALIZED_CHECKS = 128;\nconst MAX_FINDING_IDS = 64;\nconst MAX_PLAIN_DATA_DEPTH = 64;\nconst MAX_PLAIN_DATA_NODES = 200_000;\nconst CONTROL_CHAR_RE = /[\\u0000-\\u001f\\u007f]/;\n/** High-confidence credential shapes; rejected at every trust boundary. */\nconst CREDENTIAL_SHAPES = [\n\t/-----BEGIN [A-Z ]*PRIVATE KEY-----/i,\n\t/\\bsk-[A-Za-z0-9_-]{16,}\\b/,\n\t/\\bgh[pousr]_[A-Za-z0-9]{16,}\\b/,\n\t/\\bgithub_pat_[A-Za-z0-9_]{16,}\\b/,\n\t/\\bxox[baprs]-[A-Za-z0-9-]{16,}\\b/,\n\t/\\bAKIA[A-Z0-9]{16}\\b/,\n\t/\\beyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\b/,\n\t/\\bBearer\\s+[A-Za-z0-9._~+/-]{8,}={0,2}\\b/i,\n\t/(?:^|[^A-Za-z0-9])(?:[A-Za-z0-9]+[_-])*(?:authorization|api[-_ ]?key|access[-_ ]?token|token|password|secret(?:[-_ ]?key)?|private[-_ ]?key|cookie)[\"']?\\s*[:=]/i,\n] as const;\n\n// -------------------------------------------------------------------------------------------------\n// Public types.\n// -------------------------------------------------------------------------------------------------\n\nexport type SessionDoctorMode = \"inspect\" | \"repair_dry_run\" | \"repair\";\nexport type SessionDoctorStatus = \"healthy\" | \"issues\" | \"refused\";\nexport type SessionDoctorExitCode = 0 | 1 | 2;\n\nexport type SessionDoctorArtifact = \"session\" | \"journal\" | \"path\" | \"compaction\" | \"normalized\";\n\nexport type SessionDoctorFindingSeverity = \"advisory\" | \"blocked\";\n\nexport type SessionDoctorFindingReason =\n\t| \"session_trailing_fragment\"\n\t| \"session_missing_tool_result\"\n\t| \"session_blocked\"\n\t| \"session_inspection_incomplete\"\n\t| \"journal_trailing_fragment\"\n\t| \"journal_unclosed\"\n\t| \"journal_blocked\"\n\t| \"session_path_unauthorized\"\n\t| \"journal_path_unauthorized\"\n\t| \"compaction_stale\"\n\t| \"compaction_deferred\"\n\t| \"compaction_failed\"\n\t| \"compaction_committed\"\n\t| \"compaction_duplicate\"\n\t| \"normalized_check_unhealthy\"\n\t| \"contract_violation\";\n\nexport interface SessionDoctorFinding {\n\treadonly artifact: SessionDoctorArtifact;\n\treadonly reason: SessionDoctorFindingReason;\n\treadonly severity: SessionDoctorFindingSeverity;\n\t/** Bounded upstream reason/code (e.g. an integrity reason, journal finding code, path decision reason). */\n\treadonly code?: string;\n\t/** Bounded identifiers (toolCallIds, runIds, ...). */\n\treadonly ids?: readonly string[];\n}\n\nexport type SessionDoctorActionArtifact = \"session\" | \"journal\";\n\nexport type SessionDoctorActionSpec =\n\t| {\n\t\t\treadonly kind: \"quarantine_session_trailing_fragment\";\n\t\t\treadonly artifact: \"session\";\n\t\t\treadonly retainPrefix: SessionCompletePrefix;\n\t\t\treadonly fragment: SessionByteDigest;\n\t }\n\t| {\n\t\t\treadonly kind: \"append_synthetic_tool_result\";\n\t\t\treadonly artifact: \"session\";\n\t\t\treadonly toolCallId: string;\n\t\t\treadonly toolName: string;\n\t\t\treadonly repairSequence: number;\n\t\t\treadonly message: Readonly<ToolResultMessage>;\n\t }\n\t| {\n\t\t\treadonly kind: \"quarantine_journal_trailing_fragment\";\n\t\t\treadonly artifact: \"journal\";\n\t\t\treadonly completePrefix: RunJournalCompletePrefix;\n\t\t\treadonly lastCompleteHash: string;\n\t }\n\t| {\n\t\t\treadonly kind: \"recover_run\";\n\t\t\treadonly artifact: \"journal\";\n\t\t\treadonly runId: string;\n\t\t\treadonly terminalRecord: RunJournalTerminalRecord;\n\t\t\treadonly completePrefix: RunJournalCompletePrefix;\n\t\t\treadonly lastCompleteHash: string;\n\t }\n\t| {\n\t\t\treadonly kind: \"remove_stale_lock\";\n\t\t\treadonly artifact: SessionDoctorActionArtifact;\n\t\t\treadonly platform: SessionPathPlatform;\n\t\t\treadonly targetLexical: string;\n\t\t\treadonly targetRealpath: string;\n\t\t\treadonly holderPid: string | null;\n\t\t\treadonly artifacts: readonly SessionDoctorActionArtifact[];\n\t }\n\t| {\n\t\t\treadonly kind: \"abandon_stale_compaction\";\n\t\t\treadonly artifact: \"session\";\n\t\t\treadonly transactionId: string;\n\t\t\treadonly baseRevision: Readonly<SessionRevisionToken>;\n\t\t\treadonly sourceSha256: string;\n\t\t\treadonly staleReason: \"revision_mismatch\" | \"source_mismatch\";\n\t };\n\nexport type SessionDoctorAction = SessionDoctorActionSpec & { readonly sequence: number };\n\nexport interface SessionDoctorPlan {\n\treadonly schemaVersion: typeof SESSION_DOCTOR_PLAN_SCHEMA_VERSION;\n\treadonly mode: SessionDoctorMode;\n\treadonly sessionId: string;\n\treadonly repairId: string;\n\treadonly status: SessionDoctorStatus;\n\treadonly exitCode: SessionDoctorExitCode;\n\treadonly repairable: boolean;\n\treadonly requiresReinspection: boolean;\n\treadonly scheduledWrites: number;\n\treadonly findings: readonly SessionDoctorFinding[];\n\treadonly actions: readonly SessionDoctorAction[];\n}\n\nexport type SessionDoctorNormalizedCheckArtifact =\n\t| \"compaction_envelope\"\n\t| \"evidence_link\"\n\t| \"workspace\"\n\t| \"provider_model\";\n\nexport interface SessionDoctorNormalizedCheck {\n\treadonly artifact: SessionDoctorNormalizedCheckArtifact;\n\treadonly id: string;\n\treadonly status: \"ok\" | \"missing\" | \"invalid\" | \"unavailable\";\n}\n\nexport interface SessionDoctorJournalObservation {\n\treadonly bytes: Uint8Array;\n\treadonly hashFn: RunJournalHashFn;\n\t/** Caller-supplied terminal record for unclosed-run recovery. The doctor never mints it. */\n\treadonly terminalRecord?: RunJournalTerminalRecord;\n}\n\nexport interface SessionDoctorPathObservation {\n\treadonly session?: Omit<SessionPathAccessInput, \"intent\">;\n\treadonly journal?: Omit<SessionPathAccessInput, \"intent\">;\n}\n\nexport interface SessionDoctorPlanInput {\n\treadonly schemaVersion?: typeof SESSION_DOCTOR_PLAN_SCHEMA_VERSION;\n\treadonly mode: SessionDoctorMode;\n\treadonly sessionId: string;\n\treadonly repairId: string;\n\t/** Deterministic caller-provided epoch milliseconds. */\n\treadonly timestamp: number;\n\treadonly report: SessionIntegrityReport;\n\treadonly journal?: SessionDoctorJournalObservation;\n\treadonly paths?: SessionDoctorPathObservation;\n\treadonly compaction?: DecideCompactionCommitInput;\n\treadonly normalizedChecks?: readonly SessionDoctorNormalizedCheck[];\n}\n\n// -------------------------------------------------------------------------------------------------\n// Generic plain-data / exact-key / accessor-free guards (fail closed).\n// -------------------------------------------------------------------------------------------------\n\nconst TEXT_ENCODER = new TextEncoder();\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isPlainDataObject(value: unknown): value is Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n\tif (Object.getPrototypeOf(value) !== null && Object.getPrototypeOf(value) !== Object.prototype) return false;\n\tif (Object.getOwnPropertySymbols(value).length > 0) return false;\n\tfor (const key of Object.keys(value)) {\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(value, key);\n\t\tif (\n\t\t\tdescriptor === undefined ||\n\t\t\tdescriptor.get !== undefined ||\n\t\t\tdescriptor.set !== undefined ||\n\t\t\t!(\"value\" in descriptor)\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n/**\n * Strictly validate a plain dense array before any indexed value access: it\n * must be a real Array whose prototype is exactly Array.prototype, carry no\n * symbol properties or extra own properties, and expose every index 0..length-1\n * as an own data descriptor (no holes, no getters/setters). Accessor indices are\n * rejected without their getters ever executing. The length is captured once.\n */\nfunction assertStrictPlainArray(value: unknown, label: string): asserts value is unknown[] {\n\tif (typeof value !== \"object\" || value === null || !Array.isArray(value)) {\n\t\tthrow new TypeError(`${label} must be an array`);\n\t}\n\tif (Object.getPrototypeOf(value) !== Array.prototype) {\n\t\tthrow new TypeError(`${label} must use the Array prototype`);\n\t}\n\tif (Object.getOwnPropertySymbols(value).length > 0) {\n\t\tthrow new TypeError(`${label} must not carry symbol properties`);\n\t}\n\tconst length = value.length;\n\tfor (const name of Object.getOwnPropertyNames(value)) {\n\t\tif (name === \"length\") continue;\n\t\tconst index = Number(name);\n\t\tif (!Number.isSafeInteger(index) || index < 0 || index >= length || String(index) !== name) {\n\t\t\tthrow new TypeError(`${label} must not carry extra own properties`);\n\t\t}\n\t}\n\tfor (let i = 0; i < length; i += 1) {\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(value, String(i));\n\t\tif (descriptor === undefined) throw new TypeError(`${label} must be dense (no holes)`);\n\t\tif (descriptor.get !== undefined || descriptor.set !== undefined || !(\"value\" in descriptor)) {\n\t\t\tthrow new TypeError(`${label} must not expose accessor or non-data element descriptors`);\n\t\t}\n\t}\n}\n\nfunction looksLikeCredential(value: string): boolean {\n\treturn CREDENTIAL_SHAPES.some((pattern) => pattern.test(value));\n}\n\nfunction assertPlainData(value: unknown, label: string): asserts value is Record<string, unknown> {\n\tif (!isPlainDataObject(value)) {\n\t\tthrow new TypeError(`${label} must be a plain data object without accessors or a foreign prototype`);\n\t}\n}\n\n/**\n * Bounded recursive plain-data validator for trust boundaries. Walks the full\n * value tree (plain objects and dense arrays) and rejects any accessor\n * property, symbol property, foreign prototype, or sparse array slot without\n * ever executing a getter (descriptors are inspected, never read). Guards\n * SessionIntegrityReport / journal terminalRecord / compaction before any of\n * their fields are read. Primitives pass; Uint8Array and functions are not\n * validated here (callers handle those explicitly).\n */\nfunction assertPlainDataTree(value: unknown, label: string): void {\n\tlet nodes = 0;\n\tconst stack: Array<{ value: unknown; label: string; depth: number }> = [{ value, label, depth: 0 }];\n\twhile (stack.length > 0) {\n\t\tconst frame = stack.pop() as { value: unknown; label: string; depth: number };\n\t\tnodes += 1;\n\t\tif (nodes > MAX_PLAIN_DATA_NODES) {\n\t\t\tthrow new TypeError(`${label}: plain-data tree exceeds the maximum node budget`);\n\t\t}\n\t\tconst { value: current, label: currentLabel, depth } = frame;\n\t\tif (depth > MAX_PLAIN_DATA_DEPTH) {\n\t\t\tthrow new TypeError(`${currentLabel}: plain-data tree exceeds the maximum depth`);\n\t\t}\n\t\tif (current === null || typeof current !== \"object\") continue;\n\t\tif (Array.isArray(current)) {\n\t\t\tassertStrictPlainArray(current, currentLabel);\n\t\t\tfor (let index = 0; index < current.length; index += 1) {\n\t\t\t\tstack.push({ value: current[index], label: `${currentLabel}[${index}]`, depth: depth + 1 });\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tconst prototype = Object.getPrototypeOf(current);\n\t\tif (prototype !== null && prototype !== Object.prototype) {\n\t\t\tthrow new TypeError(`${currentLabel} must be a plain data object without a foreign prototype`);\n\t\t}\n\t\tif (Object.getOwnPropertySymbols(current).length > 0) {\n\t\t\tthrow new TypeError(`${currentLabel} must be a plain data object without symbol properties`);\n\t\t}\n\t\tfor (const key of Object.keys(current)) {\n\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(current, key);\n\t\t\tif (descriptor === undefined || !(\"value\" in descriptor)) {\n\t\t\t\tthrow new TypeError(`${currentLabel}.${key} must be a plain data property without accessors`);\n\t\t\t}\n\t\t\tstack.push({ value: descriptor.value, label: `${currentLabel}.${key}`, depth: depth + 1 });\n\t\t}\n\t}\n}\n\nfunction assertIdentifier(value: unknown, label: string): asserts value is string {\n\tif (typeof value !== \"string\" || value.length === 0 || value.length > MAX_IDENTIFIER_LENGTH) {\n\t\tthrow new TypeError(`${label} must be 1-${MAX_IDENTIFIER_LENGTH} characters of bounded text`);\n\t}\n\tif (CONTROL_CHAR_RE.test(value)) {\n\t\tthrow new TypeError(`${label} must not contain C0 or DEL control characters`);\n\t}\n\tif (looksLikeCredential(value)) {\n\t\tthrow new TypeError(`${label} must not contain a credential-shaped literal`);\n\t}\n}\n\nfunction assertSafeNonNegativeInt(value: unknown, label: string): asserts value is number {\n\tif (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 0) {\n\t\tthrow new TypeError(`${label} must be a non-negative safe integer`);\n\t}\n}\n\nfunction assertOnlyKeys(value: Record<string, unknown>, allowed: readonly string[], label: string): void {\n\tfor (const key of Object.keys(value)) {\n\t\tif (!allowed.includes(key)) {\n\t\t\tthrow new TypeError(`${label} contains an unsupported field: ${key}`);\n\t\t}\n\t}\n}\n\n// -------------------------------------------------------------------------------------------------\n// Input validation.\n// -------------------------------------------------------------------------------------------------\n\nconst INPUT_ALLOWED_KEYS = [\n\t\"schemaVersion\",\n\t\"mode\",\n\t\"sessionId\",\n\t\"repairId\",\n\t\"timestamp\",\n\t\"report\",\n\t\"journal\",\n\t\"paths\",\n\t\"compaction\",\n\t\"normalizedChecks\",\n];\nconst MODES = new Set<SessionDoctorMode>([\"inspect\", \"repair_dry_run\", \"repair\"]);\nconst JOURNAL_KEYS = [\"bytes\", \"hashFn\", \"terminalRecord\"];\nconst PATHS_KEYS = [\"session\", \"journal\"];\nconst PATH_INPUT_KEYS = [\"platform\", \"root\", \"target\", \"identity\", \"evidence\", \"lock\"];\nconst COMPACTION_KEYS = [\"transaction\", \"currentRevision\", \"currentSource\", \"barrier\", \"priorCommittedSourceDigests\"];\nconst NORMALIZED_KEYS = [\"artifact\", \"id\", \"status\"];\nconst NORMALIZED_ARTIFACTS = new Set<SessionDoctorNormalizedCheckArtifact>([\n\t\"compaction_envelope\",\n\t\"evidence_link\",\n\t\"workspace\",\n\t\"provider_model\",\n]);\nconst NORMALIZED_STATUSES = new Set([\"ok\", \"missing\", \"invalid\", \"unavailable\"]);\n\nfunction validateNormalizedChecks(value: unknown): readonly SessionDoctorNormalizedCheck[] {\n\tassertStrictPlainArray(value, \"normalizedChecks\");\n\tif (value.length > MAX_NORMALIZED_CHECKS) {\n\t\tthrow new TypeError(`normalizedChecks must contain at most ${MAX_NORMALIZED_CHECKS} entries`);\n\t}\n\tconst checks: SessionDoctorNormalizedCheck[] = [];\n\tfor (let index = 0; index < value.length; index++) {\n\t\tconst entry = value[index];\n\t\tassertPlainData(entry, `normalizedChecks[${index}]`);\n\t\tassertOnlyKeys(entry, NORMALIZED_KEYS, `normalizedChecks[${index}]`);\n\t\tif (!NORMALIZED_ARTIFACTS.has(entry.artifact as SessionDoctorNormalizedCheckArtifact)) {\n\t\t\tthrow new TypeError(`normalizedChecks[${index}].artifact is out of bounds`);\n\t\t}\n\t\tassertIdentifier(entry.id, `normalizedChecks[${index}].id`);\n\t\tif (!NORMALIZED_STATUSES.has(entry.status as string)) {\n\t\t\tthrow new TypeError(`normalizedChecks[${index}].status is out of bounds`);\n\t\t}\n\t\tchecks.push({\n\t\t\tartifact: entry.artifact as SessionDoctorNormalizedCheckArtifact,\n\t\t\tid: entry.id,\n\t\t\tstatus: entry.status as SessionDoctorNormalizedCheck[\"status\"],\n\t\t});\n\t}\n\treturn Object.freeze(checks);\n}\n\nfunction validatePathSubject(value: unknown, label: string): Omit<SessionPathAccessInput, \"intent\"> {\n\tassertPlainData(value, label);\n\tassertOnlyKeys(value, PATH_INPUT_KEYS, label);\n\tif (typeof value.platform !== \"string\" || (value.platform !== \"posix\" && value.platform !== \"win32\")) {\n\t\tthrow new TypeError(`${label}.platform must be posix|win32`);\n\t}\n\tif (typeof value.root !== \"string\") throw new TypeError(`${label}.root must be a string`);\n\tif (typeof value.target !== \"string\") throw new TypeError(`${label}.target must be a string`);\n\tif (!Object.hasOwn(value, \"evidence\")) throw new TypeError(`${label}.evidence is required`);\n\treturn value as unknown as Omit<SessionPathAccessInput, \"intent\">;\n}\n\ninterface ValidatedInput {\n\treadonly mode: SessionDoctorMode;\n\treadonly sessionId: string;\n\treadonly repairId: string;\n\treadonly timestamp: number;\n\treadonly report: SessionIntegrityReport;\n\treadonly journal: SessionDoctorJournalObservation | null;\n\treadonly paths: {\n\t\treadonly session: Omit<SessionPathAccessInput, \"intent\"> | null;\n\t\treadonly journal: Omit<SessionPathAccessInput, \"intent\"> | null;\n\t};\n\treadonly compaction: DecideCompactionCommitInput | null;\n\treadonly normalizedChecks: readonly SessionDoctorNormalizedCheck[];\n}\n\nfunction validateInput(rawInput: unknown): ValidatedInput {\n\tassertPlainData(rawInput, \"input\");\n\tassertOnlyKeys(rawInput, INPUT_ALLOWED_KEYS, \"input\");\n\tif (rawInput.schemaVersion !== undefined && rawInput.schemaVersion !== SESSION_DOCTOR_PLAN_SCHEMA_VERSION) {\n\t\tthrow new TypeError(\"unsupported session doctor plan schema version\");\n\t}\n\tif (!MODES.has(rawInput.mode as SessionDoctorMode)) {\n\t\tthrow new TypeError(\"mode must be inspect|repair_dry_run|repair\");\n\t}\n\tassertIdentifier(rawInput.sessionId, \"sessionId\");\n\tassertIdentifier(rawInput.repairId, \"repairId\");\n\tassertSafeNonNegativeInt(rawInput.timestamp, \"timestamp\");\n\tassertPlainData(rawInput.report, \"report\");\n\tassertPlainDataTree(rawInput.report, \"report\");\n\n\tlet journal: SessionDoctorJournalObservation | null = null;\n\tif (Object.hasOwn(rawInput, \"journal\") && rawInput.journal !== undefined) {\n\t\tassertPlainData(rawInput.journal, \"journal\");\n\t\tassertOnlyKeys(rawInput.journal, JOURNAL_KEYS, \"journal\");\n\t\tconst sourceBytes = rawInput.journal.bytes;\n\t\tif (!(sourceBytes instanceof Uint8Array)) {\n\t\t\tthrow new TypeError(\"journal.bytes must be a Uint8Array\");\n\t\t}\n\t\t// Defensive copy: isolate the plan from caller buffer aliasing and from\n\t\t// hashFn closures that mutate the caller's bytes. The plan inspects and\n\t\t// re-inspects this stable private copy.\n\t\tconst bytes = new Uint8Array(sourceBytes);\n\t\tif (typeof rawInput.journal.hashFn !== \"function\") {\n\t\t\tthrow new TypeError(\"journal.hashFn must be a function\");\n\t\t}\n\t\tlet terminalRecord: RunJournalTerminalRecord | undefined;\n\t\tif (Object.hasOwn(rawInput.journal, \"terminalRecord\") && rawInput.journal.terminalRecord !== undefined) {\n\t\t\tassertPlainData(rawInput.journal.terminalRecord, \"journal.terminalRecord\");\n\t\t\tassertPlainDataTree(rawInput.journal.terminalRecord, \"journal.terminalRecord\");\n\t\t\tterminalRecord = rawInput.journal.terminalRecord as unknown as RunJournalTerminalRecord;\n\t\t}\n\t\tjournal = Object.freeze({\n\t\t\tbytes,\n\t\t\thashFn: rawInput.journal.hashFn as RunJournalHashFn,\n\t\t\t...(terminalRecord === undefined ? {} : { terminalRecord }),\n\t\t});\n\t}\n\n\tlet pathsSession: Omit<SessionPathAccessInput, \"intent\"> | null = null;\n\tlet pathsJournal: Omit<SessionPathAccessInput, \"intent\"> | null = null;\n\tif (Object.hasOwn(rawInput, \"paths\") && rawInput.paths !== undefined) {\n\t\tassertPlainData(rawInput.paths, \"paths\");\n\t\tassertOnlyKeys(rawInput.paths, PATHS_KEYS, \"paths\");\n\t\tif (Object.hasOwn(rawInput.paths, \"session\") && rawInput.paths.session !== undefined) {\n\t\t\tpathsSession = validatePathSubject(rawInput.paths.session, \"paths.session\");\n\t\t}\n\t\tif (Object.hasOwn(rawInput.paths, \"journal\") && rawInput.paths.journal !== undefined) {\n\t\t\tpathsJournal = validatePathSubject(rawInput.paths.journal, \"paths.journal\");\n\t\t}\n\t}\n\n\tlet compaction: DecideCompactionCommitInput | null = null;\n\tif (Object.hasOwn(rawInput, \"compaction\") && rawInput.compaction !== undefined) {\n\t\tassertPlainData(rawInput.compaction, \"compaction\");\n\t\tassertOnlyKeys(rawInput.compaction, COMPACTION_KEYS, \"compaction\");\n\t\tassertPlainDataTree(rawInput.compaction, \"compaction\");\n\t\tcompaction = rawInput.compaction as unknown as DecideCompactionCommitInput;\n\t}\n\n\tconst normalizedChecks =\n\t\tObject.hasOwn(rawInput, \"normalizedChecks\") && rawInput.normalizedChecks !== undefined\n\t\t\t? validateNormalizedChecks(rawInput.normalizedChecks)\n\t\t\t: Object.freeze([] as readonly SessionDoctorNormalizedCheck[]);\n\n\treturn {\n\t\tmode: rawInput.mode as SessionDoctorMode,\n\t\tsessionId: rawInput.sessionId,\n\t\trepairId: rawInput.repairId,\n\t\ttimestamp: rawInput.timestamp,\n\t\treport: rawInput.report as unknown as SessionIntegrityReport,\n\t\tjournal,\n\t\tpaths: Object.freeze({ session: pathsSession, journal: pathsJournal }),\n\t\tcompaction,\n\t\tnormalizedChecks,\n\t};\n}\n\n// -------------------------------------------------------------------------------------------------\n// Pure helpers.\n// -------------------------------------------------------------------------------------------------\n\nfunction intentForMode(mode: SessionDoctorMode): SessionPathIntent {\n\tif (mode === \"inspect\") return \"inspect_content\";\n\tif (mode === \"repair_dry_run\") return \"repair_dry_run\";\n\treturn \"repair\";\n}\n\nfunction finding(\n\tartifact: SessionDoctorArtifact,\n\treason: SessionDoctorFindingReason,\n\tseverity: SessionDoctorFindingSeverity,\n\tcode?: string,\n\tids?: readonly string[],\n): SessionDoctorFinding {\n\tconst result: {\n\t\tartifact: SessionDoctorArtifact;\n\t\treason: SessionDoctorFindingReason;\n\t\tseverity: SessionDoctorFindingSeverity;\n\t\tcode?: string;\n\t\tids?: readonly string[];\n\t} = { artifact, reason, severity };\n\tif (code !== undefined && code.length > 0) {\n\t\tif (code.length > MAX_IDENTIFIER_LENGTH) {\n\t\t\tthrow new TypeError(\"finding code exceeds the bounded length\");\n\t\t}\n\t\tresult.code = code;\n\t}\n\tif (ids !== undefined && ids.length > 0) {\n\t\tif (ids.length > MAX_FINDING_IDS) {\n\t\t\tthrow new TypeError(`finding ids exceed the bounded limit of ${MAX_FINDING_IDS}; failing closed`);\n\t\t}\n\t\tfor (const id of ids) assertIdentifier(id, \"finding id\");\n\t\tresult.ids = Object.freeze([...ids]);\n\t}\n\treturn Object.freeze(result) as SessionDoctorFinding;\n}\n\nfunction deepFreeze<T>(value: T): T {\n\tif (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value;\n\tif (Array.isArray(value)) {\n\t\tfor (const item of value) deepFreeze(item);\n\t} else {\n\t\tfor (const child of Object.values(value as Record<string, unknown>)) deepFreeze(child);\n\t}\n\treturn Object.freeze(value);\n}\n\nfunction deepCopy<T>(value: T): T {\n\tif (typeof value !== \"object\" || value === null) return value;\n\tif (Array.isArray(value)) return deepFreeze(value.map(deepCopy)) as T;\n\tconst out: Record<string, unknown> = {};\n\tfor (const key of Object.keys(value as Record<string, unknown>)) {\n\t\tout[key] = deepCopy((value as Record<string, unknown>)[key]);\n\t}\n\treturn deepFreeze(out) as T;\n}\n\nfunction appendRecoveryRecord(\n\tbytes: Uint8Array,\n\tcompletePrefix: RunJournalCompletePrefix,\n\trecord: RunJournalTerminalRecord,\n): Uint8Array {\n\tconst suffix = TEXT_ENCODER.encode(`${serializeRunJournalLine(record)}\\n`);\n\tconst out = new Uint8Array(completePrefix.byteCount + suffix.byteLength);\n\tout.set(bytes.subarray(0, completePrefix.byteCount));\n\tout.set(suffix, completePrefix.byteCount);\n\treturn out;\n}\n\nfunction dedupPreserveOrder(values: readonly string[]): string[] {\n\tconst seen = new Set<string>();\n\tconst out: string[] = [];\n\tfor (const value of values) {\n\t\tif (!seen.has(value)) {\n\t\t\tseen.add(value);\n\t\t\tout.push(value);\n\t\t}\n\t}\n\treturn out;\n}\n\n/** The remove_stale_lock variant of {@link SessionDoctorActionSpec}. */\ntype StaleLockActionSpec = Extract<SessionDoctorActionSpec, { kind: \"remove_stale_lock\" }>;\n\nconst STALE_LOCK_ARTIFACT_RANK: Record<SessionDoctorActionArtifact, number> = {\n\tsession: 0,\n\tjournal: 1,\n};\n\n/**\n * Canonical physical target key for stale-lock dedup. Win32 compares\n * case-insensitively (lower-cased); POSIX is exact. The platform is intentionally\n * not part of the key, so a target described under conflicting platforms is\n * surfaced as a contract violation rather than silently duplicated.\n */\nfunction canonicalStaleLockTargetKey(\n\tplatform: SessionPathPlatform,\n\ttargetLexical: string,\n\ttargetRealpath: string,\n): string {\n\tconst lexical = platform === \"win32\" ? targetLexical.toLowerCase() : targetLexical;\n\tconst realpath = platform === \"win32\" ? targetRealpath.toLowerCase() : targetRealpath;\n\treturn JSON.stringify([lexical, realpath]);\n}\n\n/**\n * Deduplicate stale-lock actions from the session and journal paths by their\n * canonical physical target, merging the contributing artifacts deterministically\n * (sorted by artifact rank). A target described under conflicting platforms or\n * conflicting holder pids is a contract violation: the plan is refused and no\n * actions are reported for that target.\n */\nfunction dedupStaleLockActions(specs: readonly StaleLockActionSpec[], acc: Accumulators): StaleLockActionSpec[] {\n\tif (specs.length <= 1) return [...specs];\n\tconst groups = new Map<string, StaleLockActionSpec[]>();\n\tfor (const spec of specs) {\n\t\tconst key = canonicalStaleLockTargetKey(spec.platform, spec.targetLexical, spec.targetRealpath);\n\t\tconst group = groups.get(key);\n\t\tif (group === undefined) {\n\t\t\tgroups.set(key, [spec]);\n\t\t} else {\n\t\t\tgroup.push(spec);\n\t\t}\n\t}\n\tconst out: StaleLockActionSpec[] = [];\n\tfor (const group of groups.values()) {\n\t\tif (group.length === 1) {\n\t\t\tout.push(group[0]);\n\t\t\tcontinue;\n\t\t}\n\t\tconst platforms = new Set(group.map((spec) => spec.platform));\n\t\tconst holders = new Set(group.map((spec) => spec.holderPid));\n\t\tif (platforms.size > 1 || holders.size > 1) {\n\t\t\tacc.findings.push(finding(\"path\", \"contract_violation\", \"blocked\", \"stale_lock_target_conflict\"));\n\t\t\tacc.refused = true;\n\t\t\tcontinue;\n\t\t}\n\t\tconst mergedArtifacts = Array.from(new Set(group.flatMap((spec) => spec.artifacts))).sort(\n\t\t\t(a, b) => STALE_LOCK_ARTIFACT_RANK[a] - STALE_LOCK_ARTIFACT_RANK[b],\n\t\t);\n\t\tout.push({ ...group[0], artifacts: Object.freeze(mergedArtifacts) });\n\t}\n\treturn out;\n}\n\n// Finding sort: stable total ordering by artifact, reason, code, then ids.\nconst ARTIFACT_RANK: Record<SessionDoctorArtifact, number> = {\n\tsession: 0,\n\tjournal: 1,\n\tpath: 2,\n\tcompaction: 3,\n\tnormalized: 4,\n};\n\nfunction findingSortKey(value: SessionDoctorFinding): string {\n\treturn `${ARTIFACT_RANK[value.artifact]}|${value.reason}|${value.code ?? \"\"}|${(value.ids ?? []).join(\",\")}`;\n}\n\nfunction sortFindings(findings: SessionDoctorFinding[]): SessionDoctorFinding[] {\n\treturn [...findings].sort((a, b) => {\n\t\tconst left = findingSortKey(a);\n\t\tconst right = findingSortKey(b);\n\t\treturn left < right ? -1 : left > right ? 1 : 0;\n\t});\n}\n\n// -------------------------------------------------------------------------------------------------\n// Artifact derivations. Each mutates the shared accumulators and the refused flag.\n// -------------------------------------------------------------------------------------------------\n\ninterface Accumulators {\n\treadonly findings: SessionDoctorFinding[];\n\treadonly sessionSpecs: SessionDoctorActionSpec[];\n\treadonly journalSpecs: SessionDoctorActionSpec[];\n\treadonly pathSpecs: StaleLockActionSpec[];\n\treadonly compactionSpecs: SessionDoctorActionSpec[];\n\trefused: boolean;\n}\n\nconst REPAIRABLE_SESSION_BLOCKER_REASONS = new Set([\n\t\"integrity_finding\",\n\t\"inspection_incomplete\",\n\t\"ambiguous_transcript\",\n\t\"inconsistent_report\",\n]);\n\nfunction deriveSession(input: ValidatedInput, acc: Accumulators): void {\n\tconst report = input.report;\n\n\t// Cross-bind the session header identity to the doctored session id.\n\tconst header = report.header;\n\tif (header !== null && isRecord(header) && typeof header.id === \"string\" && header.id !== input.sessionId) {\n\t\tacc.findings.push(finding(\"session\", \"contract_violation\", \"blocked\", \"session_identity_mismatch\"));\n\t\tacc.refused = true;\n\t}\n\n\t// Ignore report.ok: createSessionRepairPlan rederives consistency and the\n\t// repairable action set with a fixed doctor_repair reason.\n\tconst sessionPlan = createSessionRepairPlan(report, {\n\t\trepairId: input.repairId,\n\t\treason: \"doctor_repair\",\n\t\ttimestamp: input.timestamp,\n\t});\n\n\tif (sessionPlan.status === \"repairable\") {\n\t\tlet quarantined = false;\n\t\tconst missingIds: string[] = [];\n\t\tconst appendSpecs: {\n\t\t\treadonly kind: \"append_synthetic_tool_result\";\n\t\t\treadonly artifact: \"session\";\n\t\t\treadonly toolCallId: string;\n\t\t\treadonly toolName: string;\n\t\t\treadonly repairSequence: number;\n\t\t\treadonly message: Readonly<ToolResultMessage>;\n\t\t}[] = [];\n\t\tfor (const action of sessionPlan.actions) {\n\t\t\tif (action.kind === \"quarantine_trailing_fragment\") {\n\t\t\t\tquarantined = true;\n\t\t\t\tacc.sessionSpecs.push({\n\t\t\t\t\tkind: \"quarantine_session_trailing_fragment\",\n\t\t\t\t\tartifact: \"session\",\n\t\t\t\t\tretainPrefix: { ...action.retainPrefix },\n\t\t\t\t\tfragment: { ...action.fragment },\n\t\t\t\t});\n\t\t\t} else if (action.kind === \"append_synthetic_tool_result\") {\n\t\t\t\tmissingIds.push(action.toolCallId);\n\t\t\t\t// Prevalidate the synthetic message as plain data before deep-copying\n\t\t\t\t// it into the action, so a non-plain runtime payload fails closed.\n\t\t\t\tassertPlainDataTree(action.message, \"session synthetic tool result message\");\n\t\t\t\tappendSpecs.push({\n\t\t\t\t\tkind: \"append_synthetic_tool_result\",\n\t\t\t\t\tartifact: \"session\",\n\t\t\t\t\ttoolCallId: action.toolCallId,\n\t\t\t\t\ttoolName: action.toolName,\n\t\t\t\t\trepairSequence: action.sequence,\n\t\t\t\t\tmessage: deepCopy(action.message),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t// Normalize session action order regardless of upstream: quarantine first,\n\t\t// then synthetic appends sorted by their upstream repair sequence.\n\t\tappendSpecs.sort((a, b) => a.repairSequence - b.repairSequence);\n\t\tfor (const spec of appendSpecs) acc.sessionSpecs.push(spec);\n\t\tif (quarantined) {\n\t\t\tacc.findings.push(finding(\"session\", \"session_trailing_fragment\", \"blocked\"));\n\t\t}\n\t\tif (missingIds.length > 0) {\n\t\t\tacc.findings.push(finding(\"session\", \"session_missing_tool_result\", \"blocked\", undefined, missingIds));\n\t\t}\n\t\treturn;\n\t}\n\n\tif (sessionPlan.status === \"blocked\") {\n\t\tfor (const blocker of sessionPlan.blockers) {\n\t\t\tif (!REPAIRABLE_SESSION_BLOCKER_REASONS.has(blocker.reason)) {\n\t\t\t\tacc.findings.push(finding(\"session\", \"contract_violation\", \"blocked\", \"unknown_blocker\"));\n\t\t\t\tacc.refused = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tswitch (blocker.reason) {\n\t\t\t\tcase \"inconsistent_report\":\n\t\t\t\t\tacc.findings.push(finding(\"session\", \"contract_violation\", \"blocked\", \"inconsistent_report\"));\n\t\t\t\t\tacc.refused = true;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"inspection_incomplete\":\n\t\t\t\t\tacc.findings.push(finding(\"session\", \"session_inspection_incomplete\", \"blocked\"));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"ambiguous_transcript\":\n\t\t\t\t\tacc.findings.push(finding(\"session\", \"session_blocked\", \"blocked\", \"ambiguous_transcript\"));\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"integrity_finding\": {\n\t\t\t\t\tconst ids: string[] = [];\n\t\t\t\t\tif (blocker.entryId !== undefined) ids.push(blocker.entryId);\n\t\t\t\t\tif (blocker.toolCallId !== undefined) ids.push(blocker.toolCallId);\n\t\t\t\t\tacc.findings.push(\n\t\t\t\t\t\tfinding(\n\t\t\t\t\t\t\t\"session\",\n\t\t\t\t\t\t\t\"session_blocked\",\n\t\t\t\t\t\t\t\"blocked\",\n\t\t\t\t\t\t\tblocker.findingReason,\n\t\t\t\t\t\t\tids.length > 0 ? ids : undefined,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tacc.findings.push(finding(\"session\", \"contract_violation\", \"blocked\", \"unknown_blocker\"));\n\t\t\t\t\tacc.refused = true;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t// status \"not_needed\": nothing to observe for the session artifact.\n}\n\nfunction deriveJournal(input: ValidatedInput, acc: Accumulators): void {\n\tconst observation = input.journal;\n\tif (observation === null) return;\n\n\tconst report = inspectRunJournal(observation.bytes, observation.hashFn);\n\tconst records = report.records;\n\tconst findingCodes = report.findings.map((f) => f.code);\n\tconst codeSet = new Set(findingCodes);\n\tconst hasSessionMismatch = codeSet.has(\"session_mismatch\");\n\tconst allBound = records.length === 0 || records.every((record) => record.sessionId === input.sessionId);\n\n\t// Cross-bind every journal record session id to the doctored session id.\n\tif (!allBound || hasSessionMismatch) {\n\t\tacc.findings.push(finding(\"journal\", \"contract_violation\", \"blocked\", \"session_identity_mismatch\"));\n\t\tacc.refused = true;\n\t}\n\n\tconst trailing = codeSet.has(\"trailing_fragment\");\n\tconst unclosed = codeSet.has(\"run_unclosed\");\n\tconst hardCodes = dedupPreserveOrder(\n\t\tfindingCodes.filter(\n\t\t\t(code) => code !== \"trailing_fragment\" && code !== \"run_unclosed\" && code !== \"session_mismatch\",\n\t\t),\n\t);\n\tconst journalCanAct = hardCodes.length === 0 && allBound && !hasSessionMismatch;\n\n\tfor (const code of hardCodes) {\n\t\tacc.findings.push(finding(\"journal\", \"journal_blocked\", \"blocked\", code));\n\t}\n\n\t// Unclosed-run recovery: only when findings are a subset of {run_unclosed, trailing_fragment}.\n\tconst recoverableState = unclosed && journalCanAct;\n\tlet recoverySucceeded = false;\n\tif (unclosed) {\n\t\tconst runIds = report.openRunId !== null ? [report.openRunId] : undefined;\n\t\tacc.findings.push(finding(\"journal\", \"journal_unclosed\", \"blocked\", undefined, runIds));\n\t\tconst supplied = Object.hasOwn(observation, \"terminalRecord\") ? observation.terminalRecord : undefined;\n\t\tif (supplied !== undefined) {\n\t\t\tif (!recoverableState) {\n\t\t\t\t// Spurious: a recovery record was supplied for a journal that is not in the recoverable state.\n\t\t\t\tacc.findings.push(finding(\"journal\", \"contract_violation\", \"blocked\", \"spurious_terminal_record\"));\n\t\t\t\tacc.refused = true;\n\t\t\t} else {\n\t\t\t\tconst recheck = inspectRunJournal(\n\t\t\t\t\tappendRecoveryRecord(observation.bytes, report.completePrefix, supplied),\n\t\t\t\t\tobservation.hashFn,\n\t\t\t\t);\n\t\t\t\tconst last = recheck.records.length > 0 ? recheck.records[recheck.records.length - 1] : null;\n\t\t\t\tconst identityOk = last !== null && serializeRunJournalLine(last) === serializeRunJournalLine(supplied);\n\t\t\t\tif (\n\t\t\t\t\trecheck.ok &&\n\t\t\t\t\trecheck.openRunId === null &&\n\t\t\t\t\tlast !== null &&\n\t\t\t\t\tlast.event === \"run_recovered\" &&\n\t\t\t\t\tidentityOk\n\t\t\t\t) {\n\t\t\t\t\trecoverySucceeded = true;\n\t\t\t\t\tconst lastCompleteHash = records.length > 0 ? records[records.length - 1].hash : GENESIS_HASH;\n\t\t\t\t\tacc.journalSpecs.push({\n\t\t\t\t\t\tkind: \"recover_run\",\n\t\t\t\t\t\tartifact: \"journal\",\n\t\t\t\t\t\trunId: last.runId,\n\t\t\t\t\t\tterminalRecord: deepCopy(supplied),\n\t\t\t\t\t\tcompletePrefix: {\n\t\t\t\t\t\t\tbyteCount: report.completePrefix.byteCount,\n\t\t\t\t\t\t\tlineCount: report.completePrefix.lineCount,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tlastCompleteHash,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tacc.findings.push(finding(\"journal\", \"contract_violation\", \"blocked\", \"forged_terminal_record\"));\n\t\t\t\t\tacc.refused = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tconst supplied = Object.hasOwn(observation, \"terminalRecord\") ? observation.terminalRecord : undefined;\n\t\tif (supplied !== undefined) {\n\t\t\t// Spurious: a recovery record was supplied with no unclosed run to recover.\n\t\t\tacc.findings.push(finding(\"journal\", \"contract_violation\", \"blocked\", \"spurious_terminal_record\"));\n\t\t\tacc.refused = true;\n\t\t}\n\t}\n\n\t// Trailing fragment: quarantine the journal tail, anchored on the complete\n\t// prefix and the last complete hash (genesis if none). When recovery\n\t// succeeded the recover_run action carries completePrefix + lastCompleteHash,\n\t// explicitly anchoring a truncate-to-prefix-then-append that already discards\n\t// the trailing fragment, so it subsumes the quarantine action.\n\tif (trailing && journalCanAct && !recoverySucceeded) {\n\t\tacc.findings.push(finding(\"journal\", \"journal_trailing_fragment\", \"blocked\"));\n\t\tconst lastCompleteHash = records.length > 0 ? records[records.length - 1].hash : GENESIS_HASH;\n\t\tacc.journalSpecs.push({\n\t\t\tkind: \"quarantine_journal_trailing_fragment\",\n\t\t\tartifact: \"journal\",\n\t\t\tcompletePrefix: { byteCount: report.completePrefix.byteCount, lineCount: report.completePrefix.lineCount },\n\t\t\tlastCompleteHash,\n\t\t});\n\t}\n}\n\nfunction deriveCompaction(input: ValidatedInput, acc: Accumulators): void {\n\tconst observation = input.compaction;\n\tif (observation === null) return;\n\n\t// Cross-bind the transaction base/source session id before rederiving.\n\tconst tx = observation.transaction;\n\tconst baseSessionId =\n\t\tisRecord(tx) && isRecord(tx.baseRevision) && typeof tx.baseRevision.sessionId === \"string\"\n\t\t\t? (tx.baseRevision.sessionId as string)\n\t\t\t: null;\n\tconst sourceSessionId =\n\t\tisRecord(tx) && isRecord(tx.source) && typeof tx.source.sessionId === \"string\"\n\t\t\t? (tx.source.sessionId as string)\n\t\t\t: null;\n\tif (baseSessionId !== input.sessionId || sourceSessionId !== input.sessionId) {\n\t\tacc.findings.push(finding(\"compaction\", \"contract_violation\", \"blocked\", \"session_identity_mismatch\"));\n\t\tacc.refused = true;\n\t\treturn;\n\t}\n\n\tconst decision: CompactionCommitDecision = decideCompactionCommit(observation);\n\tswitch (decision.decision) {\n\t\tcase \"stale\":\n\t\t\tacc.findings.push(finding(\"compaction\", \"compaction_stale\", \"blocked\"));\n\t\t\tacc.compactionSpecs.push({\n\t\t\t\tkind: \"abandon_stale_compaction\",\n\t\t\t\tartifact: \"session\",\n\t\t\t\ttransactionId: decision.transactionId,\n\t\t\t\tbaseRevision: deepCopy(tx.baseRevision),\n\t\t\t\tsourceSha256: tx.source.sourceSha256,\n\t\t\t\tstaleReason: decision.reason,\n\t\t\t});\n\t\t\tbreak;\n\t\tcase \"defer\":\n\t\t\tacc.findings.push(finding(\"compaction\", \"compaction_deferred\", \"blocked\", decision.barrierReason));\n\t\t\tbreak;\n\t\tcase \"fail_closed\":\n\t\t\tif (decision.reason === \"barrier_fail_closed\") {\n\t\t\t\tacc.findings.push(finding(\"compaction\", \"compaction_failed\", \"blocked\", decision.barrierReason));\n\t\t\t} else {\n\t\t\t\tacc.findings.push(finding(\"compaction\", \"contract_violation\", \"blocked\", decision.reason));\n\t\t\t\tacc.refused = true;\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"commit\":\n\t\t\tacc.findings.push(finding(\"compaction\", \"compaction_committed\", \"advisory\"));\n\t\t\tbreak;\n\t\tcase \"duplicate\":\n\t\t\tacc.findings.push(finding(\"compaction\", \"compaction_duplicate\", \"advisory\"));\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tacc.findings.push(finding(\"compaction\", \"contract_violation\", \"blocked\", \"unknown_decision\"));\n\t\t\tacc.refused = true;\n\t\t\tbreak;\n\t}\n}\n\ninterface StaleLockTarget {\n\treadonly platform: SessionPathPlatform;\n\treadonly targetLexical: string;\n\treadonly targetRealpath: string;\n\treadonly holderPid: string | null;\n}\n\ninterface PathAuthorization {\n\treadonly decision: SessionPathDecision | null;\n\treadonly authorized: boolean;\n\treadonly staleLock: StaleLockTarget | null;\n}\n\nfunction evaluatePath(\n\tsubject: Omit<SessionPathAccessInput, \"intent\"> | null,\n\tintent: SessionPathIntent,\n): PathAuthorization {\n\tif (subject === null) {\n\t\treturn { decision: null, authorized: false, staleLock: null };\n\t}\n\tconst decision = decideSessionPathAccess({ ...subject, intent });\n\tif (decision.status === \"authorized\") {\n\t\tconst stale = decision.plannedActions.find((action) => action.kind === \"remove_stale_lock\");\n\t\tif (stale !== undefined && stale.kind === \"remove_stale_lock\") {\n\t\t\treturn {\n\t\t\t\tdecision,\n\t\t\t\tauthorized: true,\n\t\t\t\tstaleLock: {\n\t\t\t\t\tplatform: decision.platform,\n\t\t\t\t\ttargetLexical: decision.targetLexical,\n\t\t\t\t\ttargetRealpath: decision.targetRealpath,\n\t\t\t\t\tholderPid: stale.holderPid,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\treturn { decision, authorized: true, staleLock: null };\n\t}\n\treturn { decision, authorized: false, staleLock: null };\n}\n\nfunction derivePaths(\n\tinput: ValidatedInput,\n\tacc: Accumulators,\n\tsessionPathNeeded: boolean,\n\tjournalPathNeeded: boolean,\n): void {\n\tconst intent = intentForMode(input.mode);\n\tconst requiresAuthorized = input.mode === \"repair\" || input.mode === \"repair_dry_run\";\n\n\tconst sessionAuth = evaluatePath(input.paths.session, intent);\n\tauthorizeArtifact(acc, sessionAuth, sessionPathNeeded, \"session\", \"session_path_unauthorized\", requiresAuthorized);\n\tconst journalAuth = evaluatePath(input.paths.journal, intent);\n\tauthorizeArtifact(acc, journalAuth, journalPathNeeded, \"journal\", \"journal_path_unauthorized\", requiresAuthorized);\n}\n\nfunction authorizeArtifact(\n\tacc: Accumulators,\n\tauth: PathAuthorization,\n\tneeded: boolean,\n\tartifact: SessionDoctorActionArtifact,\n\treason: SessionDoctorFindingReason,\n\trequiresAuthorized: boolean,\n): void {\n\tif (auth.authorized) {\n\t\t// Eligible stale-lock cleanup from this path decision only.\n\t\tif (auth.staleLock !== null) {\n\t\t\tacc.pathSpecs.push({\n\t\t\t\tkind: \"remove_stale_lock\",\n\t\t\t\tartifact,\n\t\t\t\tplatform: auth.staleLock.platform,\n\t\t\t\ttargetLexical: auth.staleLock.targetLexical,\n\t\t\t\ttargetRealpath: auth.staleLock.targetRealpath,\n\t\t\t\tholderPid: auth.staleLock.holderPid,\n\t\t\t\tartifacts: [artifact],\n\t\t\t});\n\t\t}\n\t\treturn;\n\t}\n\t// Not authorized (rejected, blocked, or not provided).\n\tif (needed && requiresAuthorized) {\n\t\tacc.findings.push(finding(\"path\", reason, \"blocked\", auth.decision?.reason ?? \"missing\"));\n\t\tacc.refused = true;\n\t} else if (auth.decision !== null) {\n\t\t// Provided but rejected/blocked: always a diagnostic issue.\n\t\tacc.findings.push(finding(\"path\", reason, \"blocked\", auth.decision.reason));\n\t}\n\t// Not provided and not needed (or inspect mode): nothing to report.\n}\n\nfunction deriveNormalizedChecks(input: ValidatedInput, acc: Accumulators): void {\n\tfor (const check of input.normalizedChecks) {\n\t\tif (check.status !== \"ok\") {\n\t\t\tacc.findings.push(\n\t\t\t\tfinding(\"normalized\", \"normalized_check_unhealthy\", \"blocked\", `${check.artifact}:${check.status}`),\n\t\t\t);\n\t\t}\n\t}\n}\n\n// -------------------------------------------------------------------------------------------------\n// Plan assembly.\n// -------------------------------------------------------------------------------------------------\n\nexport function planSessionDoctor(rawInput: unknown): SessionDoctorPlan {\n\tconst input = validateInput(rawInput);\n\tconst acc: Accumulators = {\n\t\tfindings: [],\n\t\tsessionSpecs: [],\n\t\tjournalSpecs: [],\n\t\tpathSpecs: [],\n\t\tcompactionSpecs: [],\n\t\trefused: false,\n\t};\n\n\tderiveSession(input, acc);\n\tderiveJournal(input, acc);\n\tderiveCompaction(input, acc);\n\n\t// Paths gate prospective repair actions. Session actions and compaction\n\t// abandon require an authorized session path; journal actions require an\n\t// authorized journal path. Inspect mode never performs writes, so paths are\n\t// only gating in dry/repair.\n\tconst writesPlanned = input.mode !== \"inspect\";\n\tconst sessionPathNeeded = writesPlanned && (acc.sessionSpecs.length > 0 || acc.compactionSpecs.length > 0);\n\tconst journalPathNeeded = writesPlanned && acc.journalSpecs.length > 0;\n\tderivePaths(input, acc, sessionPathNeeded, journalPathNeeded);\n\n\tderiveNormalizedChecks(input, acc);\n\n\t// Deduplicate stale-lock actions (session + journal paths may target the same\n\t// physical file) before sequence assignment so reported actions stay contiguous.\n\tconst dedupedPathSpecs = dedupStaleLockActions(acc.pathSpecs, acc);\n\tconst orderedSpecs: SessionDoctorActionSpec[] = [\n\t\t...acc.sessionSpecs,\n\t\t...acc.journalSpecs,\n\t\t...dedupedPathSpecs,\n\t\t...acc.compactionSpecs,\n\t];\n\tconst eligibleActions: SessionDoctorAction[] = orderedSpecs.map((spec, index) =>\n\t\tdeepFreeze({ ...spec, sequence: index }),\n\t);\n\tconst sortedFindings = Object.freeze(sortFindings(acc.findings).map((f) => deepCopy(f)));\n\n\tconst refused = acc.refused;\n\tconst reportedActions = refused || input.mode === \"inspect\" ? ([] as SessionDoctorAction[]) : eligibleActions;\n\tconst scheduledWrites = input.mode === \"repair\" && !refused ? eligibleActions.length : 0;\n\tconst requiresReinspection = scheduledWrites > 0;\n\n\t// \"healthy\" permits advisory findings (e.g. compaction_committed /\n\t// compaction_duplicate); only a blocked finding or an eligible action\n\t// downgrades the status to \"issues\".\n\tconst hasBlockingFinding = sortedFindings.some((f) => f.severity === \"blocked\");\n\tconst clean = !hasBlockingFinding && eligibleActions.length === 0;\n\tconst status: SessionDoctorStatus = refused ? \"refused\" : clean ? \"healthy\" : \"issues\";\n\tconst exitCode: SessionDoctorExitCode = refused ? 2 : clean ? 0 : 1;\n\n\treturn deepFreeze({\n\t\tschemaVersion: SESSION_DOCTOR_PLAN_SCHEMA_VERSION,\n\t\tmode: input.mode,\n\t\tsessionId: input.sessionId,\n\t\trepairId: input.repairId,\n\t\tstatus,\n\t\texitCode,\n\t\trepairable: !refused && eligibleActions.length > 0,\n\t\trequiresReinspection,\n\t\tscheduledWrites,\n\t\tfindings: sortedFindings,\n\t\tactions: Object.freeze([...reportedActions]),\n\t}) as SessionDoctorPlan;\n}\n"]}
|