@caupulican/pi-adaptative 0.85.3 → 0.85.8
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 +60 -0
- package/dist/bun/cli.d.ts +1 -1
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js +1 -0
- package/dist/bun/cli.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +1 -1
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +2 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +12 -8
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +82 -88
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js +3 -0
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/auth-storage.d.ts +2 -2
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +2 -2
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.d.ts +2 -0
- package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.js +4 -3
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +4 -0
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +2 -0
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/background-tool-task-controller.d.ts +12 -7
- package/dist/core/background-tool-task-controller.d.ts.map +1 -1
- package/dist/core/background-tool-task-controller.js +55 -19
- package/dist/core/background-tool-task-controller.js.map +1 -1
- package/dist/core/bash-executor.js +2 -2
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/bedrock-scope.d.ts +26 -0
- package/dist/core/bedrock-scope.d.ts.map +1 -0
- package/dist/core/bedrock-scope.js +178 -0
- package/dist/core/bedrock-scope.js.map +1 -0
- package/dist/core/billing-failover-controller.d.ts +2 -2
- package/dist/core/billing-failover-controller.d.ts.map +1 -1
- package/dist/core/billing-failover-controller.js +1 -1
- package/dist/core/billing-failover-controller.js.map +1 -1
- package/dist/core/compaction-controller.d.ts +8 -2
- package/dist/core/compaction-controller.d.ts.map +1 -1
- package/dist/core/compaction-controller.js +73 -3
- package/dist/core/compaction-controller.js.map +1 -1
- package/dist/core/compaction-support.d.ts +2 -2
- package/dist/core/compaction-support.d.ts.map +1 -1
- package/dist/core/compaction-support.js +9 -1
- package/dist/core/compaction-support.js.map +1 -1
- package/dist/core/context/artifact-retrieval.d.ts +1 -1
- package/dist/core/context/artifact-retrieval.d.ts.map +1 -1
- package/dist/core/context/artifact-retrieval.js +1 -1
- package/dist/core/context/artifact-retrieval.js.map +1 -1
- package/dist/core/context/context-artifacts.d.ts +6 -6
- package/dist/core/context/context-artifacts.d.ts.map +1 -1
- package/dist/core/context/context-artifacts.js +151 -63
- package/dist/core/context/context-artifacts.js.map +1 -1
- package/dist/core/context/context-composition.js +1 -1
- package/dist/core/context/context-composition.js.map +1 -1
- package/dist/core/context/context-store-retention.d.ts.map +1 -1
- package/dist/core/context/context-store-retention.js +5 -2
- package/dist/core/context/context-store-retention.js.map +1 -1
- package/dist/core/context/file-store-memory-provider.js +1 -1
- package/dist/core/context/file-store-memory-provider.js.map +1 -1
- package/dist/core/context/tool-output-packer.d.ts +1 -1
- package/dist/core/context/tool-output-packer.d.ts.map +1 -1
- package/dist/core/context/tool-output-packer.js +1 -1
- package/dist/core/context/tool-output-packer.js.map +1 -1
- package/dist/core/context-gc.d.ts.map +1 -1
- package/dist/core/context-gc.js +7 -5
- package/dist/core/context-gc.js.map +1 -1
- package/dist/core/context-pipeline.d.ts +2 -2
- package/dist/core/context-pipeline.d.ts.map +1 -1
- package/dist/core/context-pipeline.js +8 -4
- package/dist/core/context-pipeline.js.map +1 -1
- package/dist/core/cost/cost-summary.d.ts +1 -1
- package/dist/core/cost/cost-summary.d.ts.map +1 -1
- package/dist/core/cost/cost-summary.js +1 -1
- package/dist/core/cost/cost-summary.js.map +1 -1
- package/dist/core/cost/daily-usage.d.ts +1 -1
- package/dist/core/cost/daily-usage.d.ts.map +1 -1
- package/dist/core/cost/daily-usage.js +2 -2
- package/dist/core/cost/daily-usage.js.map +1 -1
- package/dist/core/cost/session-usage.d.ts +1 -1
- package/dist/core/cost/session-usage.d.ts.map +1 -1
- package/dist/core/cost/session-usage.js +1 -1
- package/dist/core/cost/session-usage.js.map +1 -1
- package/dist/core/delegation/worker-actions.js +1 -1
- package/dist/core/delegation/worker-actions.js.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.d.ts +1 -1
- package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -1
- package/dist/core/delegation/worker-attempt-executor.js +3 -2
- package/dist/core/delegation/worker-attempt-executor.js.map +1 -1
- package/dist/core/delegation/worker-conversation-store.d.ts +2 -1
- package/dist/core/delegation/worker-conversation-store.d.ts.map +1 -1
- package/dist/core/delegation/worker-conversation-store.js +3 -2
- package/dist/core/delegation/worker-conversation-store.js.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.js +6 -0
- package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
- package/dist/core/extensions/builtin.d.ts +2 -2
- package/dist/core/extensions/builtin.d.ts.map +1 -1
- package/dist/core/extensions/builtin.js +2 -2
- package/dist/core/extensions/builtin.js.map +1 -1
- package/dist/core/extensions/bundled-virtual-modules.d.ts +2 -0
- package/dist/core/extensions/bundled-virtual-modules.d.ts.map +1 -0
- package/dist/core/extensions/bundled-virtual-modules.js +129 -0
- package/dist/core/extensions/bundled-virtual-modules.js.map +1 -0
- package/dist/core/extensions/factory-runtime.d.ts +22 -0
- package/dist/core/extensions/factory-runtime.d.ts.map +1 -0
- package/dist/core/extensions/factory-runtime.js +334 -0
- package/dist/core/extensions/factory-runtime.js.map +1 -0
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/lifecycle.d.ts +13 -0
- package/dist/core/extensions/lifecycle.d.ts.map +1 -0
- package/dist/core/extensions/lifecycle.js +52 -0
- package/dist/core/extensions/lifecycle.js.map +1 -0
- package/dist/core/extensions/loader.d.ts +3 -24
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +21 -528
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/virtual-modules.d.ts +51 -0
- package/dist/core/extensions/virtual-modules.d.ts.map +1 -0
- package/dist/core/extensions/virtual-modules.js +59 -0
- package/dist/core/extensions/virtual-modules.js.map +1 -0
- package/dist/core/foreground-recovery-controller.d.ts +26 -2
- package/dist/core/foreground-recovery-controller.d.ts.map +1 -1
- package/dist/core/foreground-recovery-controller.js +112 -3
- package/dist/core/foreground-recovery-controller.js.map +1 -1
- package/dist/core/foreground-terminal-handoff-controller.d.ts +27 -0
- package/dist/core/foreground-terminal-handoff-controller.d.ts.map +1 -0
- package/dist/core/foreground-terminal-handoff-controller.js +56 -0
- package/dist/core/foreground-terminal-handoff-controller.js.map +1 -0
- package/dist/core/goal-loop-controller.d.ts.map +1 -1
- package/dist/core/goal-loop-controller.js +5 -0
- package/dist/core/goal-loop-controller.js.map +1 -1
- package/dist/core/goals/compact-goal-context.d.ts +1 -1
- package/dist/core/goals/compact-goal-context.d.ts.map +1 -1
- package/dist/core/goals/compact-goal-context.js +1 -1
- package/dist/core/goals/compact-goal-context.js.map +1 -1
- package/dist/core/goals/goal-auto-continue-controller.d.ts +3 -0
- package/dist/core/goals/goal-auto-continue-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-auto-continue-controller.js +28 -7
- package/dist/core/goals/goal-auto-continue-controller.js.map +1 -1
- package/dist/core/goals/goal-session-controller.d.ts +1 -1
- package/dist/core/goals/goal-session-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-session-controller.js +1 -1
- package/dist/core/goals/goal-session-controller.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +1 -1
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/human-input-controller.d.ts +9 -0
- package/dist/core/human-input-controller.d.ts.map +1 -1
- package/dist/core/human-input-controller.js +60 -5
- package/dist/core/human-input-controller.js.map +1 -1
- package/dist/core/human-input.d.ts +12 -0
- package/dist/core/human-input.d.ts.map +1 -1
- package/dist/core/human-input.js +59 -12
- package/dist/core/human-input.js.map +1 -1
- package/dist/core/index.d.ts +3 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/local-runtime-controller.d.ts.map +1 -1
- package/dist/core/local-runtime-controller.js +15 -9
- package/dist/core/local-runtime-controller.js.map +1 -1
- package/dist/core/memory/providers/file-store.d.ts +1 -0
- package/dist/core/memory/providers/file-store.d.ts.map +1 -1
- package/dist/core/memory/providers/file-store.js +253 -126
- package/dist/core/memory/providers/file-store.js.map +1 -1
- package/dist/core/memory/providers/user-memory-archive.js +1 -1
- package/dist/core/memory/providers/user-memory-archive.js.map +1 -1
- package/dist/core/model-capability.d.ts +15 -1
- package/dist/core/model-capability.d.ts.map +1 -1
- package/dist/core/model-capability.js +24 -1
- package/dist/core/model-capability.js.map +1 -1
- package/dist/core/model-registry.d.ts +7 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +22 -1
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +1 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-router-controller.d.ts +6 -6
- package/dist/core/model-router-controller.d.ts.map +1 -1
- package/dist/core/model-router-controller.js +6 -6
- package/dist/core/model-router-controller.js.map +1 -1
- package/dist/core/model-selection-controller.js +1 -1
- package/dist/core/model-selection-controller.js.map +1 -1
- package/dist/core/model-tool-protocol.d.ts +1 -1
- package/dist/core/model-tool-protocol.d.ts.map +1 -1
- package/dist/core/model-tool-protocol.js +1 -1
- package/dist/core/model-tool-protocol.js.map +1 -1
- package/dist/core/models/context-sizing.d.ts +1 -0
- package/dist/core/models/context-sizing.d.ts.map +1 -1
- package/dist/core/models/context-sizing.js +4 -1
- package/dist/core/models/context-sizing.js.map +1 -1
- package/dist/core/models/default-model-suggestions.d.ts.map +1 -1
- package/dist/core/models/default-model-suggestions.js +20 -10
- package/dist/core/models/default-model-suggestions.js.map +1 -1
- package/dist/core/models/llamacpp-runtime.d.ts +39 -11
- package/dist/core/models/llamacpp-runtime.d.ts.map +1 -1
- package/dist/core/models/llamacpp-runtime.js +87 -31
- package/dist/core/models/llamacpp-runtime.js.map +1 -1
- package/dist/core/models/local-execution-planner.d.ts +24 -0
- package/dist/core/models/local-execution-planner.d.ts.map +1 -0
- package/dist/core/models/local-execution-planner.js +119 -0
- package/dist/core/models/local-execution-planner.js.map +1 -0
- package/dist/core/models/local-inference-profile.d.ts +34 -0
- package/dist/core/models/local-inference-profile.d.ts.map +1 -0
- package/dist/core/models/local-inference-profile.js +74 -0
- package/dist/core/models/local-inference-profile.js.map +1 -0
- package/dist/core/models/local-runtime.d.ts +23 -4
- package/dist/core/models/local-runtime.d.ts.map +1 -1
- package/dist/core/models/local-runtime.js +12 -9
- package/dist/core/models/local-runtime.js.map +1 -1
- package/dist/core/models/managed-ollama-model.d.ts +26 -0
- package/dist/core/models/managed-ollama-model.d.ts.map +1 -0
- package/dist/core/models/managed-ollama-model.js +59 -0
- package/dist/core/models/managed-ollama-model.js.map +1 -0
- package/dist/core/models/model-ref.js +11 -11
- package/dist/core/models/model-ref.js.map +1 -1
- package/dist/core/models/prism-llamacpp-lifecycle.d.ts +10 -20
- package/dist/core/models/prism-llamacpp-lifecycle.d.ts.map +1 -1
- package/dist/core/models/prism-llamacpp-lifecycle.js +11 -31
- package/dist/core/models/prism-llamacpp-lifecycle.js.map +1 -1
- package/dist/core/models/prism-llamacpp-server-probe.d.ts +10 -0
- package/dist/core/models/prism-llamacpp-server-probe.d.ts.map +1 -0
- package/dist/core/models/prism-llamacpp-server-probe.js +36 -0
- package/dist/core/models/prism-llamacpp-server-probe.js.map +1 -0
- package/dist/core/models/runtime-arbiter.d.ts +3 -0
- package/dist/core/models/runtime-arbiter.d.ts.map +1 -1
- package/dist/core/models/runtime-arbiter.js +2 -1
- package/dist/core/models/runtime-arbiter.js.map +1 -1
- package/dist/core/orchestration/model-binding.d.ts +1 -1
- package/dist/core/orchestration/model-binding.d.ts.map +1 -1
- package/dist/core/orchestration/model-binding.js +1 -1
- package/dist/core/orchestration/model-binding.js.map +1 -1
- package/dist/core/orchestration/task-profile-writer.js +1 -1
- package/dist/core/orchestration/task-profile-writer.js.map +1 -1
- package/dist/core/process-matrix/runtime.d.ts +15 -1
- package/dist/core/process-matrix/runtime.d.ts.map +1 -1
- package/dist/core/process-matrix/runtime.js +55 -34
- package/dist/core/process-matrix/runtime.js.map +1 -1
- package/dist/core/reflection-controller.d.ts +4 -3
- package/dist/core/reflection-controller.d.ts.map +1 -1
- package/dist/core/reflection-controller.js +2 -2
- package/dist/core/reflection-controller.js.map +1 -1
- package/dist/core/research/model-fitness-controller.js +1 -1
- package/dist/core/research/model-fitness-controller.js.map +1 -1
- package/dist/core/research/research-lane-controller.d.ts +2 -2
- package/dist/core/research/research-lane-controller.d.ts.map +1 -1
- package/dist/core/research/research-lane-controller.js +15 -6
- package/dist/core/research/research-lane-controller.js.map +1 -1
- package/dist/core/resource-loader.d.ts +10 -19
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +8 -70
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +5 -1
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +50 -7
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/scout-controller.d.ts +4 -3
- package/dist/core/scout-controller.d.ts.map +1 -1
- package/dist/core/scout-controller.js +2 -1
- package/dist/core/scout-controller.js.map +1 -1
- package/dist/core/sdk.d.ts +2 -2
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +13 -11
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/security/context-threat-scanner.d.ts +14 -0
- package/dist/core/security/context-threat-scanner.d.ts.map +1 -0
- package/dist/core/security/context-threat-scanner.js +71 -0
- package/dist/core/security/context-threat-scanner.js.map +1 -0
- package/dist/core/session-supervision-runtime.d.ts +4 -1
- package/dist/core/session-supervision-runtime.d.ts.map +1 -1
- package/dist/core/session-supervision-runtime.js +49 -11
- package/dist/core/session-supervision-runtime.js.map +1 -1
- package/dist/core/settings-manager.d.ts +13 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +60 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt-builder.d.ts +5 -2
- package/dist/core/system-prompt-builder.d.ts.map +1 -1
- package/dist/core/system-prompt-builder.js +22 -10
- package/dist/core/system-prompt-builder.js.map +1 -1
- package/dist/core/system-prompt.d.ts +3 -0
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +181 -55
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tool-protocol-controller.d.ts.map +1 -1
- package/dist/core/tool-protocol-controller.js +5 -3
- package/dist/core/tool-protocol-controller.js.map +1 -1
- package/dist/core/tool-recovery-logger.js +1 -1
- package/dist/core/tool-recovery-logger.js.map +1 -1
- package/dist/core/tools/artifact-retrieve.js +1 -1
- package/dist/core/tools/artifact-retrieve.js.map +1 -1
- package/dist/core/tools/bash.d.ts +2 -2
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +16 -4
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +2 -0
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +9 -1
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts +5 -8
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +88 -55
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/extensionify-runtime.d.ts +44 -0
- package/dist/core/tools/extensionify-runtime.d.ts.map +1 -0
- package/dist/core/tools/extensionify-runtime.js +115 -0
- package/dist/core/tools/extensionify-runtime.js.map +1 -0
- package/dist/core/tools/extensionify.d.ts +9 -30
- package/dist/core/tools/extensionify.d.ts.map +1 -1
- package/dist/core/tools/extensionify.js +10 -140
- package/dist/core/tools/extensionify.js.map +1 -1
- package/dist/core/tools/file-mutation-intent.d.ts +42 -15
- package/dist/core/tools/file-mutation-intent.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-intent.js +271 -77
- package/dist/core/tools/file-mutation-intent.js.map +1 -1
- package/dist/core/tools/find.d.ts +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/index.d.ts +3 -5
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +8 -44
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +1 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +1 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +1 -1
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/render-utils.js +1 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/search-command-guard.d.ts +8 -0
- package/dist/core/tools/search-command-guard.d.ts.map +1 -1
- package/dist/core/tools/search-command-guard.js +54 -0
- package/dist/core/tools/search-command-guard.js.map +1 -1
- package/dist/core/tools/shell-contract-router.d.ts.map +1 -1
- package/dist/core/tools/shell-contract-router.js +9 -4
- package/dist/core/tools/shell-contract-router.js.map +1 -1
- package/dist/core/tools/shell-session.d.ts.map +1 -1
- package/dist/core/tools/shell-session.js +6 -4
- package/dist/core/tools/shell-session.js.map +1 -1
- package/dist/core/tools/tool-definition-factory.d.ts +32 -0
- package/dist/core/tools/tool-definition-factory.d.ts.map +1 -0
- package/dist/core/tools/tool-definition-factory.js +55 -0
- package/dist/core/tools/tool-definition-factory.js.map +1 -0
- package/dist/core/tools/write.d.ts +5 -10
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +92 -73
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/util/atomic-file.d.ts.map +1 -1
- package/dist/core/util/atomic-file.js +79 -32
- package/dist/core/util/atomic-file.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +2 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +24 -18
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/auth-dialogs-controller.d.ts +6 -0
- package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -1
- package/dist/modes/interactive/auth-dialogs-controller.js +59 -12
- package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -1
- package/dist/modes/interactive/auto-learn-controller.js +1 -1
- package/dist/modes/interactive/auto-learn-controller.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +1 -1
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-event-controller.js +1 -1
- package/dist/modes/interactive/interactive-event-controller.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/local-model-commands.d.ts +1 -1
- package/dist/modes/interactive/local-model-commands.d.ts.map +1 -1
- package/dist/modes/interactive/local-model-commands.js +51 -8
- package/dist/modes/interactive/local-model-commands.js.map +1 -1
- package/dist/utils/child-process.js +1 -1
- package/dist/utils/child-process.js.map +1 -1
- package/docs/providers.md +34 -10
- package/docs/tool-boundary-performance-roadmap-2026-08-02.md +21 -18
- package/examples/extensions/built-in-tool-renderer.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/minimal-mode.ts +1 -1
- package/examples/extensions/prompt-customizer.ts +2 -2
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/ssh.ts +17 -0
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +240 -260
- package/package.json +9 -7
|
@@ -16,55 +16,82 @@ export interface FileMutationIntentOperations {
|
|
|
16
16
|
access(path: string, mode: number): Promise<void>;
|
|
17
17
|
copyFileExclusive(sourcePath: string, targetPath: string): Promise<void>;
|
|
18
18
|
hashFile(path: string, signal?: AbortSignal): Promise<string>;
|
|
19
|
+
readPayload(path: string): Promise<string>;
|
|
19
20
|
removeFile(path: string): Promise<void>;
|
|
21
|
+
stagePayload(content: string, ttlMs: number): Promise<string>;
|
|
20
22
|
}
|
|
21
|
-
export interface
|
|
22
|
-
intentId: string;
|
|
23
|
+
export interface FileMutationLease {
|
|
23
24
|
kind: FileMutationKind;
|
|
24
25
|
path: string;
|
|
25
26
|
displayPath: string;
|
|
26
|
-
}
|
|
27
|
-
export interface FileMutationLease extends PreparedFileMutation {
|
|
28
27
|
identity?: FilePathIdentity;
|
|
29
28
|
}
|
|
30
29
|
export interface FileContentReference {
|
|
31
30
|
contentRef: string;
|
|
32
31
|
byteLength: number;
|
|
33
32
|
}
|
|
33
|
+
export interface FileMutationPayloadReference {
|
|
34
|
+
payloadRef: string;
|
|
35
|
+
byteLength: number;
|
|
36
|
+
}
|
|
37
|
+
export type FileMutationPreflightFailureReason = "write_collision" | "edit_missing" | "edit_not_file";
|
|
38
|
+
export declare class FileMutationPreflightError extends Error {
|
|
39
|
+
readonly reason: FileMutationPreflightFailureReason;
|
|
40
|
+
constructor(reason: FileMutationPreflightFailureReason, message: string);
|
|
41
|
+
}
|
|
34
42
|
export interface FileMutationIntentControllerOptions {
|
|
35
43
|
operations?: FileMutationIntentOperations;
|
|
36
|
-
intentLimit?: number;
|
|
37
44
|
contentReferenceLimit?: number;
|
|
38
|
-
intentTtlMs?: number;
|
|
39
45
|
contentReferenceTtlMs?: number;
|
|
46
|
+
mutationPayloadLimit?: number;
|
|
47
|
+
mutationPayloadByteLimit?: number;
|
|
48
|
+
mutationPayloadTtlMs?: number;
|
|
40
49
|
now?: () => number;
|
|
41
50
|
}
|
|
42
51
|
export declare const localFileMutationIntentOperations: FileMutationIntentOperations;
|
|
43
52
|
/**
|
|
44
|
-
* Session-owned authority for
|
|
45
|
-
* It retains only fixed-size metadata; file
|
|
53
|
+
* Session-owned harness authority for file-mutation preflight, stale-target checks,
|
|
54
|
+
* and bounded exact-content references. It retains only fixed-size metadata; file
|
|
55
|
+
* bytes remain owned by the filesystem.
|
|
46
56
|
*/
|
|
47
57
|
export declare class FileMutationIntentController {
|
|
48
58
|
private readonly operations;
|
|
49
|
-
private readonly intentLimit;
|
|
50
59
|
private readonly contentReferenceLimit;
|
|
51
|
-
private readonly intentTtlMs;
|
|
52
60
|
private readonly contentReferenceTtlMs;
|
|
61
|
+
private readonly mutationPayloadLimit;
|
|
62
|
+
private readonly mutationPayloadByteLimit;
|
|
63
|
+
private readonly mutationPayloadTtlMs;
|
|
53
64
|
private readonly now;
|
|
54
|
-
private readonly intents;
|
|
55
|
-
private readonly intentByPath;
|
|
56
65
|
private readonly contentReferences;
|
|
66
|
+
private readonly mutationPayloads;
|
|
67
|
+
private mutationPayloadBytes;
|
|
68
|
+
private lastMutationPayloadExpiresAt;
|
|
69
|
+
private mutationPayloadOperationTail;
|
|
57
70
|
constructor(options?: FileMutationIntentControllerOptions);
|
|
58
|
-
prepare(kind: FileMutationKind, path: string, signal?: AbortSignal, displayPath?: string): Promise<
|
|
59
|
-
consume(intentId: string, kind: FileMutationKind, path: string): FileMutationLease;
|
|
71
|
+
prepare(kind: FileMutationKind, path: string, signal?: AbortSignal, displayPath?: string): Promise<FileMutationLease>;
|
|
60
72
|
assertCurrent(lease: FileMutationLease, signal?: AbortSignal): Promise<void>;
|
|
61
73
|
rememberContent(sourcePath: string, content: string): FileContentReference;
|
|
74
|
+
retainMutationPayload(kind: FileMutationKind, payload: string): Promise<FileMutationPayloadReference | undefined>;
|
|
75
|
+
readMutationPayload(payloadRef: string, kind: FileMutationKind, signal?: AbortSignal): Promise<string>;
|
|
76
|
+
assertMutationPayload(payloadRef: string, kind: FileMutationKind, signal?: AbortSignal): Promise<void>;
|
|
77
|
+
assertContentReference(contentRef: string, signal?: AbortSignal): Promise<void>;
|
|
78
|
+
copyMutationPayload(payloadRef: string, targetPath: string, signal?: AbortSignal): Promise<FileContentReference>;
|
|
79
|
+
discardMutationPayload(payloadRef: string): Promise<void>;
|
|
80
|
+
/** Release every payload owned by this controller without touching another controller's files. */
|
|
81
|
+
dispose(): Promise<void>;
|
|
62
82
|
copyReferencedContent(contentRef: string, targetPath: string, signal?: AbortSignal): Promise<FileContentReference>;
|
|
83
|
+
private requireVerifiedContentReference;
|
|
84
|
+
private requireMutationPayload;
|
|
85
|
+
private requireVerifiedMutationPayload;
|
|
86
|
+
private verifySource;
|
|
87
|
+
private copyVerifiedSource;
|
|
63
88
|
private assertCreatableParent;
|
|
64
89
|
private rememberContentDigest;
|
|
65
90
|
private touchContentReference;
|
|
66
91
|
private removeFailedCopy;
|
|
67
|
-
private
|
|
92
|
+
private deleteMutationPayload;
|
|
93
|
+
private runMutationPayloadOperation;
|
|
94
|
+
private pruneExpiredMutationPayloads;
|
|
68
95
|
private pruneExpired;
|
|
69
96
|
}
|
|
70
97
|
//# sourceMappingURL=file-mutation-intent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-mutation-intent.d.ts","sourceRoot":"","sources":["../../../src/core/tools/file-mutation-intent.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"file-mutation-intent.d.ts","sourceRoot":"","sources":["../../../src/core/tools/file-mutation-intent.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,38 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
-
import { constants } from "node:fs";
|
|
3
|
-
import { access, copyFile, lstat, open, stat, unlink } from "node:fs/promises";
|
|
4
|
-
import {
|
|
5
|
-
|
|
2
|
+
import { constants, rmSync } from "node:fs";
|
|
3
|
+
import { access, copyFile, lstat, mkdtemp, open, readFile, stat, unlink, writeFile } from "node:fs/promises";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { dirname, join, resolve } from "node:path";
|
|
6
6
|
const DEFAULT_CONTENT_REFERENCE_LIMIT = 64;
|
|
7
|
-
const DEFAULT_INTENT_TTL_MS = 10 * 60 * 1000;
|
|
8
7
|
const DEFAULT_CONTENT_REFERENCE_TTL_MS = 60 * 60 * 1000;
|
|
8
|
+
const DEFAULT_MUTATION_PAYLOAD_LIMIT = 8;
|
|
9
|
+
const DEFAULT_MUTATION_PAYLOAD_BYTE_LIMIT = 16 * 1024 * 1024;
|
|
10
|
+
const DEFAULT_MUTATION_PAYLOAD_TTL_MS = 10 * 60 * 1000;
|
|
9
11
|
const HASH_BUFFER_BYTES = 64 * 1024;
|
|
10
12
|
const CONTENT_REFERENCE_PREFIX = "file-content:";
|
|
13
|
+
const MUTATION_PAYLOAD_REFERENCE_PREFIX = "file-mutation:";
|
|
14
|
+
const LOCAL_MUTATION_PAYLOAD_DIRECTORY_PREFIX = "pi-file-mutation-payloads-";
|
|
15
|
+
const LOCAL_MUTATION_PAYLOAD_PROCESS_BYTE_LIMIT = 64 * 1024 * 1024;
|
|
16
|
+
const LOCAL_MUTATION_PAYLOAD_PROCESS_FILE_LIMIT = 64;
|
|
17
|
+
let localMutationPayloadDirectoryPromise;
|
|
18
|
+
let localMutationPayloadDirectory;
|
|
19
|
+
let localMutationPayloadCleanupRegistered = false;
|
|
20
|
+
let localMutationPayloadOperationTail = Promise.resolve();
|
|
21
|
+
let localMutationPayloadBytes = 0;
|
|
22
|
+
const localMutationPayloadFiles = new Map();
|
|
23
|
+
class MutationPayloadCapacityError extends Error {
|
|
24
|
+
constructor() {
|
|
25
|
+
super("Process mutation payload cache is full.");
|
|
26
|
+
this.name = "MutationPayloadCapacityError";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export class FileMutationPreflightError extends Error {
|
|
30
|
+
constructor(reason, message) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.name = "FileMutationPreflightError";
|
|
33
|
+
this.reason = reason;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
11
36
|
function isMissingPathError(error) {
|
|
12
37
|
return (typeof error === "object" &&
|
|
13
38
|
error !== null &&
|
|
@@ -19,10 +44,6 @@ function errorCode(error) {
|
|
|
19
44
|
? error.code
|
|
20
45
|
: undefined;
|
|
21
46
|
}
|
|
22
|
-
function normalizedPath(path) {
|
|
23
|
-
const absolutePath = resolve(path);
|
|
24
|
-
return process.platform === "win32" ? absolutePath.toLocaleLowerCase("en-US") : absolutePath;
|
|
25
|
-
}
|
|
26
47
|
function positiveBound(value, fallback, label) {
|
|
27
48
|
const resolvedValue = value ?? fallback;
|
|
28
49
|
if (!Number.isSafeInteger(resolvedValue) || resolvedValue < 1) {
|
|
@@ -85,27 +106,95 @@ async function hashLocalFile(path, signal) {
|
|
|
85
106
|
await handle.close();
|
|
86
107
|
}
|
|
87
108
|
}
|
|
109
|
+
async function getLocalMutationPayloadDirectory() {
|
|
110
|
+
localMutationPayloadDirectoryPromise ??= mkdtemp(join(tmpdir(), LOCAL_MUTATION_PAYLOAD_DIRECTORY_PREFIX)).then((path) => {
|
|
111
|
+
localMutationPayloadDirectory = path;
|
|
112
|
+
if (!localMutationPayloadCleanupRegistered) {
|
|
113
|
+
localMutationPayloadCleanupRegistered = true;
|
|
114
|
+
process.once("exit", () => {
|
|
115
|
+
if (localMutationPayloadDirectory) {
|
|
116
|
+
try {
|
|
117
|
+
rmSync(localMutationPayloadDirectory, { recursive: true, force: true });
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// Process shutdown cannot safely retry filesystem cleanup.
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return path;
|
|
126
|
+
});
|
|
127
|
+
return localMutationPayloadDirectoryPromise;
|
|
128
|
+
}
|
|
129
|
+
async function stageLocalMutationPayload(content, ttlMs) {
|
|
130
|
+
const byteLength = Buffer.byteLength(content, "utf8");
|
|
131
|
+
let stagedPath = "";
|
|
132
|
+
const operation = localMutationPayloadOperationTail.then(async () => {
|
|
133
|
+
for (const [path, record] of localMutationPayloadFiles) {
|
|
134
|
+
if (record.expiresAt > Date.now())
|
|
135
|
+
continue;
|
|
136
|
+
localMutationPayloadFiles.delete(path);
|
|
137
|
+
localMutationPayloadBytes -= record.byteLength;
|
|
138
|
+
try {
|
|
139
|
+
await unlink(path);
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
if (!isMissingPathError(error))
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (localMutationPayloadFiles.size >= LOCAL_MUTATION_PAYLOAD_PROCESS_FILE_LIMIT ||
|
|
147
|
+
localMutationPayloadBytes + byteLength > LOCAL_MUTATION_PAYLOAD_PROCESS_BYTE_LIMIT) {
|
|
148
|
+
throw new MutationPayloadCapacityError();
|
|
149
|
+
}
|
|
150
|
+
stagedPath = join(await getLocalMutationPayloadDirectory(), randomUUID());
|
|
151
|
+
await writeFile(stagedPath, content, { encoding: "utf8", flag: "wx", mode: 0o600 });
|
|
152
|
+
localMutationPayloadFiles.set(stagedPath, { byteLength, expiresAt: Date.now() + ttlMs });
|
|
153
|
+
localMutationPayloadBytes += byteLength;
|
|
154
|
+
});
|
|
155
|
+
localMutationPayloadOperationTail = operation.catch(() => { });
|
|
156
|
+
await operation;
|
|
157
|
+
return stagedPath;
|
|
158
|
+
}
|
|
159
|
+
async function removeLocalMutationPayloadOrFile(path) {
|
|
160
|
+
const operation = localMutationPayloadOperationTail.then(async () => {
|
|
161
|
+
const record = localMutationPayloadFiles.get(path);
|
|
162
|
+
if (record !== undefined) {
|
|
163
|
+
localMutationPayloadFiles.delete(path);
|
|
164
|
+
localMutationPayloadBytes -= record.byteLength;
|
|
165
|
+
}
|
|
166
|
+
await unlink(path);
|
|
167
|
+
});
|
|
168
|
+
localMutationPayloadOperationTail = operation.catch(() => { });
|
|
169
|
+
await operation;
|
|
170
|
+
}
|
|
88
171
|
export const localFileMutationIntentOperations = {
|
|
89
172
|
inspect: inspectLocalPath,
|
|
90
173
|
access,
|
|
91
174
|
copyFileExclusive: (sourcePath, targetPath) => copyFile(sourcePath, targetPath, constants.COPYFILE_EXCL),
|
|
92
175
|
hashFile: hashLocalFile,
|
|
93
|
-
|
|
176
|
+
readPayload: (path) => readFile(path, "utf8"),
|
|
177
|
+
removeFile: removeLocalMutationPayloadOrFile,
|
|
178
|
+
stagePayload: stageLocalMutationPayload,
|
|
94
179
|
};
|
|
95
180
|
/**
|
|
96
|
-
* Session-owned authority for
|
|
97
|
-
* It retains only fixed-size metadata; file
|
|
181
|
+
* Session-owned harness authority for file-mutation preflight, stale-target checks,
|
|
182
|
+
* and bounded exact-content references. It retains only fixed-size metadata; file
|
|
183
|
+
* bytes remain owned by the filesystem.
|
|
98
184
|
*/
|
|
99
185
|
export class FileMutationIntentController {
|
|
100
186
|
constructor(options = {}) {
|
|
101
|
-
this.intents = new Map();
|
|
102
|
-
this.intentByPath = new Map();
|
|
103
187
|
this.contentReferences = new Map();
|
|
188
|
+
this.mutationPayloads = new Map();
|
|
189
|
+
this.mutationPayloadBytes = 0;
|
|
190
|
+
this.lastMutationPayloadExpiresAt = 0;
|
|
191
|
+
this.mutationPayloadOperationTail = Promise.resolve();
|
|
104
192
|
this.operations = options.operations ?? localFileMutationIntentOperations;
|
|
105
|
-
this.intentLimit = positiveBound(options.intentLimit, DEFAULT_INTENT_LIMIT, "Intent limit");
|
|
106
193
|
this.contentReferenceLimit = positiveBound(options.contentReferenceLimit, DEFAULT_CONTENT_REFERENCE_LIMIT, "Content reference limit");
|
|
107
|
-
this.intentTtlMs = positiveBound(options.intentTtlMs, DEFAULT_INTENT_TTL_MS, "Intent TTL");
|
|
108
194
|
this.contentReferenceTtlMs = positiveBound(options.contentReferenceTtlMs, DEFAULT_CONTENT_REFERENCE_TTL_MS, "Content reference TTL");
|
|
195
|
+
this.mutationPayloadLimit = positiveBound(options.mutationPayloadLimit, DEFAULT_MUTATION_PAYLOAD_LIMIT, "Mutation payload limit");
|
|
196
|
+
this.mutationPayloadByteLimit = positiveBound(options.mutationPayloadByteLimit, DEFAULT_MUTATION_PAYLOAD_BYTE_LIMIT, "Mutation payload byte limit");
|
|
197
|
+
this.mutationPayloadTtlMs = positiveBound(options.mutationPayloadTtlMs, DEFAULT_MUTATION_PAYLOAD_TTL_MS, "Mutation payload TTL");
|
|
109
198
|
this.now = options.now ?? Date.now;
|
|
110
199
|
}
|
|
111
200
|
async prepare(kind, path, signal, displayPath = path) {
|
|
@@ -116,16 +205,19 @@ export class FileMutationIntentController {
|
|
|
116
205
|
let identity;
|
|
117
206
|
if (kind === "write") {
|
|
118
207
|
const existing = await this.operations.inspect(absolutePath, false);
|
|
119
|
-
if (existing)
|
|
120
|
-
throw new
|
|
208
|
+
if (existing) {
|
|
209
|
+
throw new FileMutationPreflightError("write_collision", `Write collision: ${displayPath} already exists.`);
|
|
210
|
+
}
|
|
121
211
|
await this.assertCreatableParent(absolutePath);
|
|
122
212
|
}
|
|
123
213
|
else {
|
|
124
214
|
const existing = await this.operations.inspect(absolutePath, true);
|
|
125
|
-
if (!existing)
|
|
126
|
-
throw new
|
|
127
|
-
|
|
128
|
-
|
|
215
|
+
if (!existing) {
|
|
216
|
+
throw new FileMutationPreflightError("edit_missing", `Could not edit file: ${displayPath}. Error code: ENOENT.`);
|
|
217
|
+
}
|
|
218
|
+
if (existing.kind !== "file") {
|
|
219
|
+
throw new FileMutationPreflightError("edit_not_file", `Could not edit file: ${displayPath}. Target is not a regular file.`);
|
|
220
|
+
}
|
|
129
221
|
try {
|
|
130
222
|
await this.operations.access(absolutePath, constants.R_OK | constants.W_OK);
|
|
131
223
|
}
|
|
@@ -137,46 +229,11 @@ export class FileMutationIntentController {
|
|
|
137
229
|
}
|
|
138
230
|
if (signal?.aborted)
|
|
139
231
|
throw new Error("Operation aborted");
|
|
140
|
-
|
|
141
|
-
const priorIntentId = this.intentByPath.get(key);
|
|
142
|
-
if (priorIntentId)
|
|
143
|
-
this.deleteIntent(priorIntentId);
|
|
144
|
-
while (this.intents.size >= this.intentLimit) {
|
|
145
|
-
const oldestIntentId = this.intents.keys().next().value;
|
|
146
|
-
if (typeof oldestIntentId !== "string")
|
|
147
|
-
break;
|
|
148
|
-
this.deleteIntent(oldestIntentId);
|
|
149
|
-
}
|
|
150
|
-
const intentId = randomUUID();
|
|
151
|
-
const record = {
|
|
152
|
-
intentId,
|
|
232
|
+
return {
|
|
153
233
|
kind,
|
|
154
234
|
path: absolutePath,
|
|
155
235
|
displayPath,
|
|
156
236
|
...(identity ? { identity } : {}),
|
|
157
|
-
expiresAt: this.now() + this.intentTtlMs,
|
|
158
|
-
};
|
|
159
|
-
this.intents.set(intentId, record);
|
|
160
|
-
this.intentByPath.set(key, intentId);
|
|
161
|
-
return { intentId, kind, path: absolutePath, displayPath };
|
|
162
|
-
}
|
|
163
|
-
consume(intentId, kind, path) {
|
|
164
|
-
this.pruneExpired();
|
|
165
|
-
const record = this.intents.get(intentId);
|
|
166
|
-
if (!record)
|
|
167
|
-
throw new Error("File mutation intent is invalid, expired, or belongs to another session.");
|
|
168
|
-
this.deleteIntent(intentId);
|
|
169
|
-
if (record.kind !== kind)
|
|
170
|
-
throw new Error(`File mutation intent is for ${record.kind}, not ${kind}.`);
|
|
171
|
-
if (normalizedPath(record.path) !== normalizedPath(path)) {
|
|
172
|
-
throw new Error("File mutation intent path does not match the commit path.");
|
|
173
|
-
}
|
|
174
|
-
return {
|
|
175
|
-
intentId: record.intentId,
|
|
176
|
-
kind: record.kind,
|
|
177
|
-
path: record.path,
|
|
178
|
-
displayPath: record.displayPath,
|
|
179
|
-
...(record.identity ? { identity: record.identity } : {}),
|
|
180
237
|
};
|
|
181
238
|
}
|
|
182
239
|
async assertCurrent(lease, signal) {
|
|
@@ -184,16 +241,16 @@ export class FileMutationIntentController {
|
|
|
184
241
|
throw new Error("Operation aborted");
|
|
185
242
|
if (lease.kind === "write") {
|
|
186
243
|
if (await this.operations.inspect(lease.path, false)) {
|
|
187
|
-
throw new
|
|
244
|
+
throw new FileMutationPreflightError("write_collision", `Write collision: ${lease.displayPath} became occupied after preflight; no content was overwritten.`);
|
|
188
245
|
}
|
|
189
246
|
return;
|
|
190
247
|
}
|
|
191
248
|
const current = await this.operations.inspect(lease.path, true);
|
|
192
249
|
if (!current || current.kind !== "file") {
|
|
193
|
-
throw new Error(`Could not edit file: ${lease.displayPath}. The
|
|
250
|
+
throw new Error(`Could not edit file: ${lease.displayPath}. The target no longer exists after preflight.`);
|
|
194
251
|
}
|
|
195
252
|
if (!identitiesMatch(lease.identity, current.identity)) {
|
|
196
|
-
throw new Error(`Could not edit file: ${lease.displayPath}. The file changed
|
|
253
|
+
throw new Error(`Could not edit file: ${lease.displayPath}. The file changed during edit execution; read it again before retrying.`);
|
|
197
254
|
}
|
|
198
255
|
try {
|
|
199
256
|
await this.operations.access(lease.path, constants.R_OK | constants.W_OK);
|
|
@@ -207,7 +264,97 @@ export class FileMutationIntentController {
|
|
|
207
264
|
const digest = createHash("sha256").update(content, "utf8").digest("hex");
|
|
208
265
|
return this.rememberContentDigest(sourcePath, digest, Buffer.byteLength(content, "utf8"));
|
|
209
266
|
}
|
|
267
|
+
async retainMutationPayload(kind, payload) {
|
|
268
|
+
return this.runMutationPayloadOperation(async () => {
|
|
269
|
+
await this.pruneExpiredMutationPayloads();
|
|
270
|
+
const byteLength = Buffer.byteLength(payload, "utf8");
|
|
271
|
+
if (byteLength > this.mutationPayloadByteLimit)
|
|
272
|
+
return undefined;
|
|
273
|
+
while (this.mutationPayloads.size >= this.mutationPayloadLimit ||
|
|
274
|
+
this.mutationPayloadBytes + byteLength > this.mutationPayloadByteLimit) {
|
|
275
|
+
const oldestPayloadRef = this.mutationPayloads.keys().next().value;
|
|
276
|
+
if (typeof oldestPayloadRef !== "string")
|
|
277
|
+
return undefined;
|
|
278
|
+
await this.deleteMutationPayload(oldestPayloadRef, true);
|
|
279
|
+
}
|
|
280
|
+
// Keep insertion and expiry order identical, even if the wall clock moves backward. Expiry
|
|
281
|
+
// pruning can then stop at the first live record instead of rescanning every retained payload.
|
|
282
|
+
const expiresAt = Math.max(this.lastMutationPayloadExpiresAt, this.now() + this.mutationPayloadTtlMs);
|
|
283
|
+
this.lastMutationPayloadExpiresAt = expiresAt;
|
|
284
|
+
let sourcePath;
|
|
285
|
+
try {
|
|
286
|
+
sourcePath = await this.operations.stagePayload(payload, this.mutationPayloadTtlMs);
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
if (error instanceof MutationPayloadCapacityError)
|
|
290
|
+
return undefined;
|
|
291
|
+
throw error;
|
|
292
|
+
}
|
|
293
|
+
const payloadRef = `${MUTATION_PAYLOAD_REFERENCE_PREFIX}${randomUUID()}`;
|
|
294
|
+
this.mutationPayloads.set(payloadRef, {
|
|
295
|
+
payloadRef,
|
|
296
|
+
kind,
|
|
297
|
+
sourcePath,
|
|
298
|
+
digest: createHash("sha256").update(payload, "utf8").digest("hex"),
|
|
299
|
+
byteLength,
|
|
300
|
+
expiresAt,
|
|
301
|
+
});
|
|
302
|
+
this.mutationPayloadBytes += byteLength;
|
|
303
|
+
return { payloadRef, byteLength };
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
async readMutationPayload(payloadRef, kind, signal) {
|
|
307
|
+
return this.runMutationPayloadOperation(async () => {
|
|
308
|
+
const record = await this.requireMutationPayload(payloadRef, kind, signal);
|
|
309
|
+
const payload = await this.operations.readPayload(record.sourcePath);
|
|
310
|
+
if (createHash("sha256").update(payload, "utf8").digest("hex") !== record.digest) {
|
|
311
|
+
await this.deleteMutationPayload(payloadRef);
|
|
312
|
+
throw new Error("Retained file mutation payload changed after it was cached.");
|
|
313
|
+
}
|
|
314
|
+
return payload;
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
async assertMutationPayload(payloadRef, kind, signal) {
|
|
318
|
+
await this.runMutationPayloadOperation(async () => {
|
|
319
|
+
await this.requireVerifiedMutationPayload(payloadRef, kind, signal);
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
async assertContentReference(contentRef, signal) {
|
|
323
|
+
await this.requireVerifiedContentReference(contentRef, signal);
|
|
324
|
+
}
|
|
325
|
+
async copyMutationPayload(payloadRef, targetPath, signal) {
|
|
326
|
+
return this.runMutationPayloadOperation(async () => {
|
|
327
|
+
const record = await this.requireVerifiedMutationPayload(payloadRef, "write", signal);
|
|
328
|
+
await this.copyVerifiedSource(record, targetPath, signal);
|
|
329
|
+
await this.deleteMutationPayload(payloadRef);
|
|
330
|
+
return this.rememberContentDigest(targetPath, record.digest, record.byteLength);
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
async discardMutationPayload(payloadRef) {
|
|
334
|
+
await this.runMutationPayloadOperation(() => this.deleteMutationPayload(payloadRef));
|
|
335
|
+
}
|
|
336
|
+
/** Release every payload owned by this controller without touching another controller's files. */
|
|
337
|
+
async dispose() {
|
|
338
|
+
await this.runMutationPayloadOperation(async () => {
|
|
339
|
+
let firstError;
|
|
340
|
+
for (const payloadRef of [...this.mutationPayloads.keys()]) {
|
|
341
|
+
try {
|
|
342
|
+
await this.deleteMutationPayload(payloadRef, true);
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
firstError ??= error;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
if (firstError)
|
|
349
|
+
throw firstError;
|
|
350
|
+
});
|
|
351
|
+
}
|
|
210
352
|
async copyReferencedContent(contentRef, targetPath, signal) {
|
|
353
|
+
const record = await this.requireVerifiedContentReference(contentRef, signal);
|
|
354
|
+
await this.copyVerifiedSource(record, targetPath, signal);
|
|
355
|
+
return this.rememberContentDigest(targetPath, record.digest, record.byteLength);
|
|
356
|
+
}
|
|
357
|
+
async requireVerifiedContentReference(contentRef, signal) {
|
|
211
358
|
this.pruneExpired();
|
|
212
359
|
const record = this.contentReferences.get(contentRef);
|
|
213
360
|
if (!record)
|
|
@@ -215,17 +362,51 @@ export class FileMutationIntentController {
|
|
|
215
362
|
this.touchContentReference(record);
|
|
216
363
|
if (signal?.aborted)
|
|
217
364
|
throw new Error("Operation aborted");
|
|
365
|
+
try {
|
|
366
|
+
await this.verifySource(record, signal, "File content reference source");
|
|
367
|
+
}
|
|
368
|
+
catch (error) {
|
|
369
|
+
this.contentReferences.delete(contentRef);
|
|
370
|
+
throw error;
|
|
371
|
+
}
|
|
372
|
+
return record;
|
|
373
|
+
}
|
|
374
|
+
async requireMutationPayload(payloadRef, kind, signal) {
|
|
375
|
+
await this.pruneExpiredMutationPayloads();
|
|
376
|
+
if (signal?.aborted)
|
|
377
|
+
throw new Error("Operation aborted");
|
|
378
|
+
const record = this.mutationPayloads.get(payloadRef);
|
|
379
|
+
if (!record) {
|
|
380
|
+
throw new Error("File mutation payload reference is invalid, expired, or belongs to another session.");
|
|
381
|
+
}
|
|
382
|
+
if (record.kind !== kind) {
|
|
383
|
+
throw new Error(`File mutation payload reference is for ${record.kind}, not ${kind}.`);
|
|
384
|
+
}
|
|
385
|
+
return record;
|
|
386
|
+
}
|
|
387
|
+
async requireVerifiedMutationPayload(payloadRef, kind, signal) {
|
|
388
|
+
const record = await this.requireMutationPayload(payloadRef, kind, signal);
|
|
389
|
+
try {
|
|
390
|
+
await this.verifySource(record, signal, "Retained file mutation payload");
|
|
391
|
+
}
|
|
392
|
+
catch (error) {
|
|
393
|
+
await this.deleteMutationPayload(payloadRef);
|
|
394
|
+
throw error;
|
|
395
|
+
}
|
|
396
|
+
return record;
|
|
397
|
+
}
|
|
398
|
+
async verifySource(record, signal, label) {
|
|
218
399
|
let sourceDigest;
|
|
219
400
|
try {
|
|
220
401
|
sourceDigest = await this.operations.hashFile(record.sourcePath, signal);
|
|
221
402
|
}
|
|
222
403
|
catch (error) {
|
|
223
|
-
throw new Error(
|
|
224
|
-
}
|
|
225
|
-
if (sourceDigest !== record.digest) {
|
|
226
|
-
this.contentReferences.delete(contentRef);
|
|
227
|
-
throw new Error("File content reference source changed after it was cached.");
|
|
404
|
+
throw new Error(`${label} is unavailable: ${String(error)}.`);
|
|
228
405
|
}
|
|
406
|
+
if (sourceDigest !== record.digest)
|
|
407
|
+
throw new Error(`${label} changed after it was cached.`);
|
|
408
|
+
}
|
|
409
|
+
async copyVerifiedSource(record, targetPath, signal) {
|
|
229
410
|
await this.operations.copyFileExclusive(record.sourcePath, targetPath);
|
|
230
411
|
let targetDigest;
|
|
231
412
|
try {
|
|
@@ -239,7 +420,6 @@ export class FileMutationIntentController {
|
|
|
239
420
|
await this.removeFailedCopy(targetPath, new Error("copied bytes did not match the cached digest"));
|
|
240
421
|
throw new Error("File content copy changed while it was being created; the target was removed.");
|
|
241
422
|
}
|
|
242
|
-
return this.rememberContentDigest(targetPath, record.digest, record.byteLength);
|
|
243
423
|
}
|
|
244
424
|
async assertCreatableParent(path) {
|
|
245
425
|
let candidate = dirname(path);
|
|
@@ -301,21 +481,35 @@ export class FileMutationIntentController {
|
|
|
301
481
|
throw new Error(`Copied content verification failed (${String(cause)}), and the newly created target could not be removed: ${String(cleanupError)}.`);
|
|
302
482
|
}
|
|
303
483
|
}
|
|
304
|
-
|
|
305
|
-
const record = this.
|
|
484
|
+
async deleteMutationPayload(payloadRef, strict = false) {
|
|
485
|
+
const record = this.mutationPayloads.get(payloadRef);
|
|
306
486
|
if (!record)
|
|
307
487
|
return;
|
|
308
|
-
this.
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
this.
|
|
488
|
+
this.mutationPayloads.delete(payloadRef);
|
|
489
|
+
this.mutationPayloadBytes -= record.byteLength;
|
|
490
|
+
try {
|
|
491
|
+
await this.operations.removeFile(record.sourcePath);
|
|
492
|
+
}
|
|
493
|
+
catch (error) {
|
|
494
|
+
if (strict && !isMissingPathError(error))
|
|
495
|
+
throw error;
|
|
496
|
+
}
|
|
312
497
|
}
|
|
313
|
-
|
|
498
|
+
runMutationPayloadOperation(operation) {
|
|
499
|
+
const run = this.mutationPayloadOperationTail.then(operation, operation);
|
|
500
|
+
this.mutationPayloadOperationTail = run.then(() => undefined, () => undefined);
|
|
501
|
+
return run;
|
|
502
|
+
}
|
|
503
|
+
async pruneExpiredMutationPayloads() {
|
|
314
504
|
const now = this.now();
|
|
315
|
-
for (const [
|
|
316
|
-
if (record.expiresAt
|
|
317
|
-
|
|
505
|
+
for (const [payloadRef, record] of this.mutationPayloads) {
|
|
506
|
+
if (record.expiresAt > now)
|
|
507
|
+
break;
|
|
508
|
+
await this.deleteMutationPayload(payloadRef, true);
|
|
318
509
|
}
|
|
510
|
+
}
|
|
511
|
+
pruneExpired() {
|
|
512
|
+
const now = this.now();
|
|
319
513
|
for (const [contentRef, record] of this.contentReferences) {
|
|
320
514
|
if (record.expiresAt <= now)
|
|
321
515
|
this.contentReferences.delete(contentRef);
|