@abot-ai/runtime 1.7.0 → 1.8.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/dist/src/capabilities/tool-request-resources.d.ts +3 -0
- package/dist/src/cli/abot.js +2 -0
- package/dist/src/cli/host-companion-bundle.mjs +751 -333
- package/dist/src/computer-access/collection-consent.d.ts +9 -0
- package/dist/src/computer-access/collection-consent.js +47 -0
- package/dist/src/computer-access/command-output-capture.d.ts +17 -6
- package/dist/src/computer-access/command-output-capture.js +134 -68
- package/dist/src/computer-access/command-output-protection.d.ts +17 -0
- package/dist/src/computer-access/command-output-protection.js +59 -0
- package/dist/src/computer-access/companion/command-output.d.ts +1 -0
- package/dist/src/computer-access/companion/command-output.js +23 -6
- package/dist/src/computer-access/companion/install-link-macos.js +2 -1
- package/dist/src/computer-access/companion/native-notifications.js +3 -2
- package/dist/src/computer-access/companion/native-session.js +6 -2
- package/dist/src/computer-access/companion/observation-filter.js +2 -26
- package/dist/src/computer-access/companion/observation-process.d.ts +2 -0
- package/dist/src/computer-access/companion/observation-process.js +51 -25
- package/dist/src/computer-access/companion/observation-redaction.d.ts +2 -7
- package/dist/src/computer-access/companion/observation-redaction.js +2 -111
- package/dist/src/computer-access/companion/secret-protection-protocol.d.ts +6 -0
- package/dist/src/computer-access/companion/secret-protection-protocol.js +6 -0
- package/dist/src/computer-access/computer/companion-sessions.js +7 -6
- package/dist/src/computer-access/computer/unix-native-process.js +23 -11
- package/dist/src/computer-access/handlers.d.ts +2 -1
- package/dist/src/computer-access/handlers.js +79 -11
- package/dist/src/computer-access/host-observation.d.ts +3 -3
- package/dist/src/computer-access/native-observation-connection.d.ts +12 -0
- package/dist/src/computer-access/native-observation-connection.js +78 -0
- package/dist/src/computer-access/native-observation-ownership.d.ts +6 -0
- package/dist/src/computer-access/native-observation-ownership.js +55 -0
- package/dist/src/computer-access/native-observation-shutdown.d.ts +7 -0
- package/dist/src/computer-access/native-observation-shutdown.js +58 -0
- package/dist/src/computer-access/observation-source.d.ts +6 -0
- package/dist/src/computer-access/observation-source.js +10 -0
- package/dist/src/computer-access/security/desktop-result.d.ts +8 -0
- package/dist/src/computer-access/security/desktop-result.js +146 -0
- package/dist/src/computer-access/security/observed-error.d.ts +2 -0
- package/dist/src/computer-access/security/observed-error.js +10 -0
- package/dist/src/computer-access/security/secret-text.d.ts +7 -0
- package/dist/src/computer-access/security/secret-text.js +111 -0
- package/dist/src/computer-access/security/system-results.d.ts +2 -0
- package/dist/src/computer-access/security/system-results.js +53 -0
- package/dist/src/computer-access/system-result-protection.d.ts +11 -0
- package/dist/src/computer-access/system-result-protection.js +1 -0
- package/dist/src/model-gateway/observability/provider-response-capture.d.ts +60 -0
- package/dist/src/model-gateway/observability/provider-response-capture.js +68 -0
- package/dist/src/model-gateway/observability/provider-response-prefix.d.ts +7 -0
- package/dist/src/model-gateway/observability/provider-response-prefix.js +14 -0
- package/dist/src/model-gateway/observability/provider-response-tail.d.ts +8 -0
- package/dist/src/model-gateway/observability/provider-response-tail.js +28 -0
- package/dist/src/model-gateway/observability/provider-sse-diagnostics.d.ts +30 -0
- package/dist/src/model-gateway/observability/provider-sse-diagnostics.js +119 -0
- package/dist/src/model-gateway/observability/provider-trace.js +30 -8
- package/dist/src/model-gateway/providers/ollama/adapter.js +8 -2
- package/dist/src/model-gateway/providers/ollama/stream-normalizer.js +70 -50
- package/dist/src/model-gateway/providers/ollama/stream-termination.d.ts +6 -0
- package/dist/src/model-gateway/providers/ollama/stream-termination.js +20 -0
- package/dist/src/model-gateway/providers/openai/adapter.js +9 -7
- package/dist/src/model-gateway/providers/openai/diagnostics.d.ts +0 -1
- package/dist/src/model-gateway/providers/openai/diagnostics.js +0 -9
- package/dist/src/model-gateway/providers/openai/function-output.d.ts +11 -0
- package/dist/src/model-gateway/providers/openai/function-output.js +37 -0
- package/dist/src/model-gateway/providers/openai/function-result.d.ts +7 -0
- package/dist/src/model-gateway/providers/openai/function-result.js +35 -0
- package/dist/src/model-gateway/providers/openai/message-output-policy.d.ts +3 -0
- package/dist/src/model-gateway/providers/openai/message-output-policy.js +16 -0
- package/dist/src/model-gateway/providers/openai/payload.d.ts +0 -2
- package/dist/src/model-gateway/providers/openai/payload.js +6 -23
- package/dist/src/model-gateway/providers/openai/response-lifetime.d.ts +2 -0
- package/dist/src/model-gateway/providers/openai/response-lifetime.js +64 -0
- package/dist/src/model-gateway/providers/openai/sse-data.d.ts +9 -0
- package/dist/src/model-gateway/providers/openai/sse-data.js +67 -0
- package/dist/src/model-gateway/providers/openai/stream-normalizer.d.ts +10 -22
- package/dist/src/model-gateway/providers/openai/stream-normalizer.js +78 -79
- package/dist/src/model-gateway/providers/openai/stream.js +13 -41
- package/dist/src/model-gateway/providers/openai/structured-message-output.d.ts +42 -0
- package/dist/src/model-gateway/providers/openai/structured-message-output.js +175 -0
- package/dist/src/model-gateway/server.js +5 -1
- package/dist/src/plugin-contract/index.d.ts +1 -0
- package/dist/src/plugin-contract/index.js +1 -0
- package/dist/src/plugin-contract/manifest.d.ts +2 -0
- package/dist/src/plugin-contract/manifest.js +1 -0
- package/dist/src/plugin-contract/platform-compatibility.d.ts +16 -0
- package/dist/src/plugin-contract/platform-compatibility.js +3 -0
- package/dist/src/plugin-sdk/computer-access.d.ts +4 -0
- package/dist/src/plugin-sdk/computer-access.js +1 -0
- package/dist/src/plugin-sdk/files-windows/process.d.ts +3 -0
- package/dist/src/plugin-sdk/files-windows/process.js +93 -0
- package/dist/src/plugin-sdk/files-windows/read-script.d.ts +1 -0
- package/dist/src/plugin-sdk/files-windows/read-script.js +43 -0
- package/dist/src/plugin-sdk/files-windows/read.d.ts +6 -0
- package/dist/src/plugin-sdk/files-windows/read.js +56 -0
- package/dist/src/plugin-sdk/files-windows/result.d.ts +4 -0
- package/dist/src/plugin-sdk/files-windows/result.js +67 -0
- package/dist/src/plugin-sdk/files.js +4 -0
- package/dist/src/plugin-sdk/index.d.ts +1 -0
- package/dist/src/plugin-sdk/index.js +1 -0
- package/dist/src/plugin-sdk/mutation-result.d.ts +7 -0
- package/dist/src/plugin-sdk/mutation-result.js +11 -0
- package/dist/src/runtime/adapters/long-term-memory/file-lock/acquisition.js +20 -3
- package/dist/src/runtime/adapters/long-term-memory/file-lock/owner-record.js +3 -1
- package/dist/src/runtime/adapters/long-term-memory/file-lock/path-observation.d.ts +3 -0
- package/dist/src/runtime/adapters/long-term-memory/file-lock/path-observation.js +20 -0
- package/dist/src/runtime/adapters/long-term-memory/file-lock/snapshot.js +7 -3
- package/dist/src/runtime/adapters/passive-learning-runtime.d.ts +1 -1
- package/dist/src/runtime/adapters/passive-learning-runtime.js +3 -3
- package/dist/src/runtime/adapters/runtime-observation-connection.d.ts +5 -0
- package/dist/src/runtime/adapters/runtime-observation-connection.js +13 -0
- package/dist/src/runtime/local-host/windows-private-access.js +2 -0
- package/dist/src/runtime/passive-learning/application-catalog.js +3 -1
- package/dist/src/runtime/passive-learning/collection-source.js +7 -0
- package/dist/src/runtime/passive-learning/service.js +2 -3
- package/dist/src/runtime/passive-learning/status-projection.d.ts +2 -0
- package/dist/src/runtime/passive-learning/status-projection.js +9 -0
- package/dist/src/runtime/plugins/installation/package.d.ts +8 -0
- package/dist/src/runtime/plugins/installation/package.js +2 -0
- package/dist/src/runtime/plugins/installation/service.d.ts +7 -0
- package/dist/src/runtime/plugins/loader.js +24 -14
- package/dist/src/runtime/plugins/manifest-platform-compatibility.d.ts +2 -0
- package/dist/src/runtime/plugins/manifest-platform-compatibility.js +39 -0
- package/dist/src/runtime/plugins/manifest-validator.js +9 -1
- package/dist/src/runtime/plugins/platform-compatibility.d.ts +4 -0
- package/dist/src/runtime/plugins/platform-compatibility.js +44 -0
- package/dist/src/runtime/request/approval-wait/activation-events.js +19 -7
- package/dist/src/runtime/request/approval-wait/execution-compaction-restore.d.ts +20 -0
- package/dist/src/runtime/request/approval-wait/execution-compaction-restore.js +118 -0
- package/dist/src/runtime/request/approval-wait/super-compaction-restore.js +2 -1
- package/dist/src/runtime/request/prepared-execution.js +3 -0
- package/dist/src/runtime/steps/execution-agent/capability-result-context.d.ts +6 -0
- package/dist/src/runtime/steps/execution-agent/capability-result-context.js +29 -0
- package/dist/src/runtime/steps/execution-agent/format.js +2 -3
- package/dist/src/runtime/steps/execution-agent/input.js +1 -1
- package/dist/src/runtime/steps/execution-agent/prompt.js +5 -5
- package/dist/src/runtime/steps/execution-agent/response-prompt.js +1 -0
- package/dist/src/runtime/steps/execution-agent/state-context.d.ts +2 -3
- package/dist/src/runtime/steps/execution-agent/state-context.js +26 -35
- package/dist/src/runtime/steps/execution-agent/work-plan-contract.d.ts +1 -3
- package/dist/src/runtime/steps/execution-agent/work-plan-contract.js +0 -55
- package/dist/src/runtime/steps/execution-agent/work-plan-schema.d.ts +3 -0
- package/dist/src/runtime/steps/execution-agent/work-plan-schema.js +61 -0
- package/dist/src/sessions/durable-session-commit.js +3 -3
- package/dist/src/sessions/prepared-session-replacement.d.ts +6 -0
- package/dist/src/sessions/prepared-session-replacement.js +46 -0
- package/dist/src/sessions/session-store.js +3 -3
- package/dist/src/shared/passive-observation-self-exclusion.d.ts +5 -0
- package/dist/src/shared/passive-observation-self-exclusion.js +37 -0
- package/dist/src/shared/windows-file-io/authority-script.d.ts +1 -0
- package/dist/src/shared/windows-file-io/authority-script.js +94 -0
- package/dist/src/shared/windows-file-io/native-script.d.ts +2 -0
- package/dist/src/shared/windows-file-io/native-script.js +120 -0
- package/dist/src/shared/windows-file-io/read-bytes-script.d.ts +1 -0
- package/dist/src/shared/windows-file-io/read-bytes-script.js +18 -0
- package/dist/src/shared/windows-job-object.d.ts +2 -0
- package/dist/src/shared/windows-job-object.js +66 -0
- package/dist/src/web-ui/app/app-bootstrap.js +14 -1
- package/dist/src/web-ui/app/app-state.js +0 -7
- package/dist/src/web-ui/app/app.js +53 -156
- package/dist/src/web-ui/app/components/automations/node-inspector.js +3 -2
- package/dist/src/web-ui/app/components/automations/step-editor-dialog.js +3 -0
- package/dist/src/web-ui/app/components/composer-submission-notice.js +50 -0
- package/dist/src/web-ui/app/components/config-workspace/model-plugin-permissions.js +7 -1
- package/dist/src/web-ui/app/components/config-workspace/workspace-mutations.js +22 -2
- package/dist/src/web-ui/app/components/home-guidance/daily-review.js +2 -2
- package/dist/src/web-ui/app/components/home-guidance/home-guidance.js +20 -6
- package/dist/src/web-ui/app/components/model-setup/context-window-feedback.js +53 -0
- package/dist/src/web-ui/app/components/model-setup/save-flow.js +3 -1
- package/dist/src/web-ui/app/components/model-setup/save-outcome.js +1 -0
- package/dist/src/web-ui/app/components/model-setup/wizard.js +12 -0
- package/dist/src/web-ui/app/components/passive-learning/activity-controls.js +4 -0
- package/dist/src/web-ui/app/components/passive-learning/collection-access.js +35 -0
- package/dist/src/web-ui/app/components/passive-learning/collection-consent-dialog.js +59 -0
- package/dist/src/web-ui/app/components/passive-learning/collection-consent-gate.js +94 -0
- package/dist/src/web-ui/app/components/passive-learning/computer-update-notice.js +6 -0
- package/dist/src/web-ui/app/components/passive-learning/failure-copy.js +1 -0
- package/dist/src/web-ui/app/components/passive-learning/home.js +7 -2
- package/dist/src/web-ui/app/components/passive-learning/macos-collection-restart-notice.js +1 -0
- package/dist/src/web-ui/app/components/passive-learning/memory.js +2 -4
- package/dist/src/web-ui/app/components/passive-learning/workspace-view.js +2 -2
- package/dist/src/web-ui/app/components/plugins/compatibility.js +13 -0
- package/dist/src/web-ui/app/components/plugins/discovery-rendering.js +9 -1
- package/dist/src/web-ui/app/components/plugins/installation-compatibility.js +7 -0
- package/dist/src/web-ui/app/components/plugins/installation.js +2 -1
- package/dist/src/web-ui/app/components/plugins/rendering.js +3 -0
- package/dist/src/web-ui/app/components/reasoning-override-prompt.js +82 -0
- package/dist/src/web-ui/app/components/runtime-config-activation.js +22 -8
- package/dist/src/web-ui/app/components/runtime-setup/optional-steps.js +7 -4
- package/dist/src/web-ui/app/components/runtime-setup/plugins.js +3 -1
- package/dist/src/web-ui/app/components/runtime-setup/rendering.js +6 -4
- package/dist/src/web-ui/app/components/runtime-setup-guide.d.ts +1 -0
- package/dist/src/web-ui/app/components/schedules/form.js +10 -8
- package/dist/src/web-ui/app/components/schedules/workspace.js +23 -4
- package/dist/src/web-ui/app/components/session-sidebar-sections.js +2 -2
- package/dist/src/web-ui/app/components/spark-chat/handoff-actions.js +9 -3
- package/dist/src/web-ui/app/components/spark-chat/placement.js +4 -7
- package/dist/src/web-ui/app/components/spark-chat/settings.js +7 -3
- package/dist/src/web-ui/app/components/system-host/macos-permissions.js +2 -0
- package/dist/src/web-ui/app/components/system-host/native-windows-access.js +50 -0
- package/dist/src/web-ui/app/components/system-host/rendering.js +3 -0
- package/dist/src/web-ui/app/components/workspace-storage-notice.js +37 -0
- package/dist/src/web-ui/app/configuration-environment-refresh.js +27 -34
- package/dist/src/web-ui/app/configuration-feature.js +9 -1
- package/dist/src/web-ui/app/controllers/app-event-bindings.js +38 -105
- package/dist/src/web-ui/app/controllers/chat-request-controller.d.ts +28 -0
- package/dist/src/web-ui/app/controllers/chat-request-controller.js +34 -66
- package/dist/src/web-ui/app/controllers/composer-attachments-controller.d.ts +15 -40
- package/dist/src/web-ui/app/controllers/composer-attachments-controller.js +26 -69
- package/dist/src/web-ui/app/controllers/composer-draft-view.d.ts +27 -0
- package/dist/src/web-ui/app/controllers/composer-draft-view.js +48 -0
- package/dist/src/web-ui/app/controllers/composer-drafts.d.ts +55 -0
- package/dist/src/web-ui/app/controllers/composer-drafts.js +120 -0
- package/dist/src/web-ui/app/controllers/composer-feature.d.ts +65 -0
- package/dist/src/web-ui/app/controllers/composer-feature.js +124 -0
- package/dist/src/web-ui/app/controllers/composer-queue-controller.d.ts +33 -94
- package/dist/src/web-ui/app/controllers/composer-queue-controller.js +185 -251
- package/dist/src/web-ui/app/controllers/composer-submission-lifecycle.d.ts +48 -0
- package/dist/src/web-ui/app/controllers/composer-submission-lifecycle.js +97 -0
- package/dist/src/web-ui/app/controllers/composer-submit-controller.d.ts +30 -61
- package/dist/src/web-ui/app/controllers/composer-submit-controller.js +56 -138
- package/dist/src/web-ui/app/controllers/composer-surface-controller.js +6 -0
- package/dist/src/web-ui/app/controllers/composer-workspace-controller.d.ts +22 -40
- package/dist/src/web-ui/app/controllers/composer-workspace-controller.js +49 -165
- package/dist/src/web-ui/app/controllers/conversation-navigation-intent.js +15 -0
- package/dist/src/web-ui/app/controllers/conversation-request-hydration.js +20 -17
- package/dist/src/web-ui/app/controllers/conversation-session-controller.d.ts +1 -2
- package/dist/src/web-ui/app/controllers/conversation-session-controller.js +49 -22
- package/dist/src/web-ui/app/controllers/conversation-workspace-activation.js +27 -0
- package/dist/src/web-ui/app/controllers/daily-memory-review.js +15 -16
- package/dist/src/web-ui/app/controllers/environment-transition.js +126 -0
- package/dist/src/web-ui/app/controllers/environment-workspace-preparation.js +18 -0
- package/dist/src/web-ui/app/controllers/home-composer-feature.d.ts +14 -36
- package/dist/src/web-ui/app/controllers/home-composer-feature.js +17 -114
- package/dist/src/web-ui/app/controllers/home-conversation-activation.js +6 -8
- package/dist/src/web-ui/app/controllers/passive-learning-controller.js +56 -0
- package/dist/src/web-ui/app/controllers/projects-controller.d.ts +1 -1
- package/dist/src/web-ui/app/controllers/projects-controller.js +6 -1
- package/dist/src/web-ui/app/controllers/reasoning-mode-controller.js +174 -0
- package/dist/src/web-ui/app/controllers/runtime-selection-controller.d.ts +7 -0
- package/dist/src/web-ui/app/controllers/runtime-selection-controller.js +20 -155
- package/dist/src/web-ui/app/controllers/session-controller.js +33 -17
- package/dist/src/web-ui/app/controllers/session-pin-updates.js +14 -0
- package/dist/src/web-ui/app/controllers/session-sidebar-controller.js +12 -14
- package/dist/src/web-ui/app/controllers/spark-chat-sync.js +2 -2
- package/dist/src/web-ui/app/controllers/steer-controller.js +9 -7
- package/dist/src/web-ui/app/controllers/tool-permission-mode-controller.js +1 -1
- package/dist/src/web-ui/app/controllers/workspace-conversation-opener.js +34 -0
- package/dist/src/web-ui/app/dashboard-feature.js +3 -2
- package/dist/src/web-ui/app/lib/reasoning-controls.js +35 -0
- package/dist/src/web-ui/app/lib/session-composer-queue-ownership.js +58 -0
- package/dist/src/web-ui/app/lib/session-composer-queue.d.ts +12 -0
- package/dist/src/web-ui/app/lib/session-composer-queue.js +25 -6
- package/dist/src/web-ui/app/passive-learning-feature.js +16 -3
- package/dist/src/web-ui/app/schedules-feature.js +5 -3
- package/dist/src/web-ui/app/services/client-preferences.d.ts +18 -10
- package/dist/src/web-ui/app/services/client-preferences.js +25 -16
- package/dist/src/web-ui/app/services/home-guidance-preferences.js +13 -13
- package/dist/src/web-ui/app/services/reasoning-override.js +12 -0
- package/dist/src/web-ui/app/services/runtime-web-client/automations.js +10 -2
- package/dist/src/web-ui/app/services/runtime-web-client/memory.js +7 -2
- package/dist/src/web-ui/app/services/runtime-web-client/system-host.js +2 -0
- package/dist/src/web-ui/app/services/runtime-web-client.d.ts +2 -0
- package/dist/src/web-ui/app/services/runtime-web-client.js +2 -0
- package/dist/src/web-ui/app/services/server-composer-queue.js +32 -0
- package/dist/src/web-ui/app/services/session-sidebar-preferences.js +5 -5
- package/dist/src/web-ui/app/services/workspace-state-storage.js +116 -0
- package/dist/src/web-ui/app/services/workspace-state.js +27 -0
- package/dist/src/web-ui/app/spark-chat-conversation.js +34 -45
- package/dist/src/web-ui/app/spark-chat-feature.js +10 -4
- package/dist/src/web-ui/app/styles/21-composer-controls.css +16 -0
- package/dist/src/web-ui/app/styles/41-plugin-management.css +8 -0
- package/dist/src/web-ui/app/styles/42-model-plugin-permissions.css +1 -0
- package/dist/src/web-ui/app/styles/49-collection-consent.css +30 -0
- package/dist/src/web-ui/app/styles/64-workspace-storage.css +23 -0
- package/dist/src/web-ui/app/styles.css +2 -0
- package/dist/src/web-ui/client-state/contracts.d.ts +15 -0
- package/dist/src/web-ui/client-state/contracts.js +13 -0
- package/dist/src/web-ui/client-state/preference-shapes.d.ts +2 -0
- package/dist/src/web-ui/client-state/preference-shapes.js +80 -0
- package/dist/src/web-ui/client-state/preferences.d.ts +3 -0
- package/dist/src/web-ui/client-state/preferences.js +84 -0
- package/dist/src/web-ui/client-state/queue.d.ts +3 -0
- package/dist/src/web-ui/client-state/queue.js +43 -0
- package/dist/src/web-ui/client-state/routes.d.ts +7 -0
- package/dist/src/web-ui/client-state/routes.js +58 -0
- package/dist/src/web-ui/client-state/store.d.ts +14 -0
- package/dist/src/web-ui/client-state/store.js +88 -0
- package/dist/src/web-ui/local-runtime/configuration-activation-source.js +2 -0
- package/dist/src/web-ui/local-runtime/http.js +11 -2
- package/dist/src/web-ui/local-runtime/model-context-capacity-error.d.ts +14 -0
- package/dist/src/web-ui/local-runtime/model-context-capacity-error.js +28 -0
- package/dist/src/web-ui/local-runtime/model-setup-context-window.d.ts +15 -0
- package/dist/src/web-ui/local-runtime/model-setup-context-window.js +25 -0
- package/dist/src/web-ui/local-runtime/model-setup-routes.js +2 -0
- package/dist/src/web-ui/local-runtime/model-setup-service.js +5 -2
- package/dist/src/web-ui/local-runtime/model-setup-validation.d.ts +1 -0
- package/dist/src/web-ui/local-runtime/model-setup-validation.js +14 -7
- package/dist/src/web-ui/local-runtime/request-body-error.d.ts +11 -0
- package/dist/src/web-ui/local-runtime/request-body-error.js +14 -0
- package/dist/src/web-ui/local-runtime/request-control-observation.js +2 -2
- package/dist/src/web-ui/local-runtime/request-execution.js +18 -18
- package/dist/src/web-ui/local-runtime/runtime-setup-connection-edit.d.ts +2 -0
- package/dist/src/web-ui/local-runtime/runtime-setup-connection-edit.js +35 -22
- package/dist/src/web-ui/local-runtime/runtime-setup-context-window.d.ts +2 -9
- package/dist/src/web-ui/local-runtime/runtime-setup-context-window.js +4 -27
- package/dist/src/web-ui/local-runtime/runtime-setup-credentials.d.ts +15 -1
- package/dist/src/web-ui/local-runtime/runtime-setup-credentials.js +30 -11
- package/dist/src/web-ui/local-runtime/runtime-setup-edit-files.d.ts +20 -0
- package/dist/src/web-ui/local-runtime/runtime-setup-edit-files.js +104 -0
- package/dist/src/web-ui/local-runtime/runtime-setup-edit-journal.d.ts +29 -0
- package/dist/src/web-ui/local-runtime/runtime-setup-edit-journal.js +151 -0
- package/dist/src/web-ui/local-runtime/runtime-setup-edit-recovery.d.ts +7 -0
- package/dist/src/web-ui/local-runtime/runtime-setup-edit-recovery.js +87 -0
- package/dist/src/web-ui/local-runtime/runtime-setup-edit-transaction.d.ts +3 -0
- package/dist/src/web-ui/local-runtime/runtime-setup-edit-transaction.js +37 -0
- package/dist/src/web-ui/local-runtime/runtime-setup-service.js +4 -0
- package/dist/src/web-ui/local-runtime-backend.js +14 -0
- package/dist/src/web-ui/plugin-management-catalog.d.ts +3 -1
- package/dist/src/web-ui/plugin-management-catalog.js +3 -1
- package/dist/src/web-ui/plugin-management-service.d.ts +1 -0
- package/dist/src/web-ui/plugin-removal-service.d.ts +1 -0
- package/dist/src/web-ui/server-readiness.d.ts +3 -0
- package/dist/src/web-ui/server-readiness.js +36 -0
- package/dist/src/web-ui/server.d.ts +2 -0
- package/dist/src/web-ui/server.js +23 -1
- package/dist/src/web-ui/system-host-service.js +13 -2
- package/dist/src/web-ui/system-host-setup/collection-consent-route.d.ts +3 -0
- package/dist/src/web-ui/system-host-setup/collection-consent-route.js +30 -0
- package/docs/installation.md +44 -5
- package/docs/plugins.md +145 -4
- package/docs/tool-execution-result-evidence-contract.md +57 -0
- package/docs/windows-companion-store.md +5 -0
- package/package.json +4 -2
- package/plugins/capability-brief/plugin.json +4 -0
- package/plugins/code-outline/README.md +20 -0
- package/plugins/code-outline/plugin.json +1 -0
- package/plugins/code-outline/source/index.ts +16 -20
- package/plugins/code-outline/source/read-failure.ts +40 -0
- package/plugins/code-outline/src/index.cjs +614 -29
- package/plugins/document-reader/README.md +33 -0
- package/plugins/document-reader/plugin.json +1 -0
- package/plugins/document-reader/source/pdf-contract.ts +57 -0
- package/plugins/document-reader/source/pdf-parser.ts +139 -0
- package/plugins/document-reader/source/pdf-process-main.ts +56 -0
- package/plugins/document-reader/source/pdf-process.ts +207 -0
- package/plugins/document-reader/source/pdf-result.ts +79 -0
- package/plugins/document-reader/source/pdf-worker.ts +39 -303
- package/plugins/document-reader/source/pdf.ts +4 -1
- package/plugins/document-reader/source/read-failure.ts +37 -0
- package/plugins/document-reader/source/reader.ts +3 -19
- package/plugins/document-reader/src/index.cjs +995 -211
- package/plugins/exec/README.md +19 -0
- package/plugins/exec/plugin.json +4 -3
- package/plugins/exec/skills/exec_skill/SKILL.md +3 -2
- package/plugins/exec/source/filesystem-file-observer.ts +98 -0
- package/plugins/exec/source/filesystem-observer.ts +8 -79
- package/plugins/exec/source/output-files.ts +12 -6
- package/plugins/exec/source/paths.ts +3 -1
- package/plugins/exec/source/process-manager.ts +8 -24
- package/plugins/exec/source/shell-platform.ts +19 -3
- package/plugins/exec/source/shell-process.ts +55 -0
- package/plugins/exec/source/windows-job-source.ts +1 -0
- package/plugins/exec/source/windows-shell-bootstrap.ts +20 -0
- package/plugins/exec/src/index.cjs +252 -96
- package/plugins/filesystem/README.md +65 -0
- package/plugins/filesystem/plugin.json +6 -2
- package/plugins/filesystem/source/atomic-write.ts +2 -0
- package/plugins/filesystem/source/bounded-io.ts +80 -306
- package/plugins/filesystem/source/directory-sample.ts +2 -0
- package/plugins/filesystem/source/errors.ts +14 -0
- package/plugins/filesystem/source/file-observation.ts +151 -0
- package/plugins/filesystem/source/file-version.ts +41 -0
- package/plugins/filesystem/source/index.ts +6 -0
- package/plugins/filesystem/source/mutation-coordinator.ts +1 -0
- package/plugins/filesystem/source/windows/authority-script.ts +1 -0
- package/plugins/filesystem/source/windows/native-script.ts +1 -0
- package/plugins/filesystem/source/windows/operations.ts +197 -0
- package/plugins/filesystem/source/windows/process.ts +214 -0
- package/plugins/filesystem/source/windows/publication-script.ts +29 -0
- package/plugins/filesystem/source/windows/read-script.ts +63 -0
- package/plugins/filesystem/source/windows/request-availability.ts +67 -0
- package/plugins/filesystem/source/windows/source.ts +42 -0
- package/plugins/filesystem/source/windows/storage-script.ts +11 -0
- package/plugins/filesystem/source/windows/streams-script.ts +24 -0
- package/plugins/filesystem/source/windows/write-script.ts +86 -0
- package/plugins/filesystem/src/index.cjs +1208 -322
- package/plugins/json-inspector/README.md +18 -0
- package/plugins/json-inspector/plugin.json +1 -0
- package/plugins/json-inspector/source/index.ts +16 -19
- package/plugins/json-inspector/source/read-failure.ts +42 -0
- package/plugins/json-inspector/src/index.cjs +612 -27
- package/plugins/local-search/README.md +29 -0
- package/plugins/local-search/plugin.json +1 -0
- package/plugins/local-search/source/errors.ts +2 -0
- package/plugins/local-search/source/paths.ts +3 -0
- package/plugins/local-search/source/ripgrep-process.ts +31 -5
- package/plugins/local-search/source/ripgrep.ts +3 -3
- package/plugins/local-search/source/windows-authority.ts +99 -0
- package/plugins/local-search/source/windows-search-lease.ts +49 -0
- package/plugins/local-search/source/windows-search-process.ts +91 -0
- package/plugins/local-search/source/windows-search-script.ts +52 -0
- package/plugins/local-search/src/index.cjs +595 -26
- package/plugins/memory/plugin.json +4 -0
- package/plugins/memory/source/lock-directory-claim.ts +56 -0
- package/plugins/memory/source/lock-owner-file.ts +71 -0
- package/plugins/memory/source/lock-path-observation.ts +26 -0
- package/plugins/memory/source/prepared-memory-replacement.ts +40 -0
- package/plugins/memory/source/store-lock.ts +12 -7
- package/plugins/memory/source/store.ts +3 -2
- package/plugins/memory/src/index.cjs +174 -25
- package/plugins/project-orientation/README.md +23 -0
- package/plugins/project-orientation/plugin.json +1 -0
- package/plugins/project-orientation/source/index.ts +12 -9
- package/plugins/project-orientation/source/inspection-failure.ts +70 -0
- package/plugins/project-orientation/source/manifest-summary.ts +9 -2
- package/plugins/project-orientation/source/tree.ts +6 -0
- package/plugins/project-orientation/src/index.cjs +647 -31
- package/plugins/system/README.md +51 -15
- package/plugins/system/plugin.json +5 -1
- package/plugins/system/skills/system_actions/SKILL.md +1 -1
- package/plugins/system/source/command-working-directory.ts +47 -0
- package/plugins/system/source/computer/handlers.ts +13 -9
- package/plugins/system/source/computer/observation-result.ts +10 -5
- package/plugins/system/source/computer/request-computers.ts +10 -3
- package/plugins/system/source/computer/request-modules.ts +3 -6
- package/plugins/system/source/computer/runtime-platform.ts +18 -0
- package/plugins/system/source/host-dispatch.ts +18 -2
- package/plugins/system/source/index.ts +5 -3
- package/plugins/system/source/local-command-output-retention.ts +16 -0
- package/plugins/system/source/local-command-output.ts +16 -8
- package/plugins/system/source/request-system-modules.ts +12 -2
- package/plugins/system/source/request-target-snapshot.ts +2 -1
- package/plugins/system/source/security/desktop-result.ts +177 -0
- package/plugins/system/source/security/observed-error.ts +10 -0
- package/plugins/system/source/security/secret-text.ts +118 -0
- package/plugins/system/source/security/system-results.ts +62 -0
- package/plugins/system/source/security/windows-output-directory.ts +82 -0
- package/plugins/system/src/index.cjs +837 -151
- package/plugins/system-probe/plugin.json +8 -2
- package/plugins/system-probe/source/disk-path.ts +8 -0
- package/plugins/system-probe/source/index.ts +10 -5
- package/plugins/system-probe/source/machine-load.ts +33 -0
- package/plugins/system-probe/source/metrics.ts +6 -8
- package/plugins/system-probe/src/index.cjs +49 -16
- package/plugins/web/plugin.json +4 -0
|
@@ -8,6 +8,14 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
8
8
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
9
9
|
var __getProtoOf = Object.getPrototypeOf;
|
|
10
10
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
|
+
var __esm = (fn, res, err) => function __init() {
|
|
12
|
+
if (err) throw err[0];
|
|
13
|
+
try {
|
|
14
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
15
|
+
} catch (e) {
|
|
16
|
+
throw err = [e], e;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
11
19
|
var __export = (target, all) => {
|
|
12
20
|
for (var name in all)
|
|
13
21
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -30,6 +38,556 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
38
|
));
|
|
31
39
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
40
|
|
|
41
|
+
// src/shared/windows-file-io/native-script.ts
|
|
42
|
+
var WINDOWS_FILESYSTEM_NATIVE;
|
|
43
|
+
var init_native_script = __esm({
|
|
44
|
+
"src/shared/windows-file-io/native-script.ts"() {
|
|
45
|
+
"use strict";
|
|
46
|
+
WINDOWS_FILESYSTEM_NATIVE = String.raw`
|
|
47
|
+
using System;
|
|
48
|
+
using System.IO;
|
|
49
|
+
using System.Text;
|
|
50
|
+
using System.Linq;
|
|
51
|
+
using System.Collections.Generic;
|
|
52
|
+
using System.ComponentModel;
|
|
53
|
+
using System.Runtime.InteropServices;
|
|
54
|
+
using System.Security.AccessControl;
|
|
55
|
+
using System.Security.Principal;
|
|
56
|
+
using System.Web.Script.Serialization;
|
|
57
|
+
using Microsoft.Win32.SafeHandles;
|
|
58
|
+
|
|
59
|
+
public sealed class FsFault : Exception {
|
|
60
|
+
public readonly string Code;
|
|
61
|
+
public FsFault(string code) : base(code) { Code = code; }
|
|
62
|
+
}
|
|
63
|
+
public static partial class AbotFilesystem {
|
|
64
|
+
[StructLayout(LayoutKind.Sequential)] struct UnicodeString { public ushort Length, MaximumLength; public IntPtr Buffer; }
|
|
65
|
+
[StructLayout(LayoutKind.Sequential)] struct ObjectAttributes {
|
|
66
|
+
public int Length; public IntPtr Root, Name; public uint Attributes; public IntPtr Security, Qos;
|
|
67
|
+
}
|
|
68
|
+
[StructLayout(LayoutKind.Sequential)] struct IoStatus { public IntPtr Status, Information; }
|
|
69
|
+
[StructLayout(LayoutKind.Sequential)] struct BasicInfo {
|
|
70
|
+
public long Created, Accessed, Modified, Changed; public uint Attributes;
|
|
71
|
+
}
|
|
72
|
+
[StructLayout(LayoutKind.Sequential)] struct FileInfo {
|
|
73
|
+
public uint Attributes; public System.Runtime.InteropServices.ComTypes.FILETIME Created, Accessed, Modified;
|
|
74
|
+
public uint Volume, SizeHigh, SizeLow, Links, IndexHigh, IndexLow;
|
|
75
|
+
}
|
|
76
|
+
[DllImport("ntdll.dll")] static extern int NtCreateFile(out SafeFileHandle file, uint access,
|
|
77
|
+
ref ObjectAttributes attributes, out IoStatus status, IntPtr allocation, uint fileAttributes,
|
|
78
|
+
uint share, uint disposition, uint options, IntPtr ea, uint eaLength);
|
|
79
|
+
[DllImport("ntdll.dll")] static extern uint RtlNtStatusToDosError(int status);
|
|
80
|
+
[DllImport("ntdll.dll")] static extern int NtSetInformationFile(SafeFileHandle file,
|
|
81
|
+
out IoStatus status, IntPtr info, uint length, int kind);
|
|
82
|
+
[DllImport("kernel32.dll", SetLastError=true)] static extern bool GetFileInformationByHandle(SafeFileHandle file, out FileInfo info);
|
|
83
|
+
[DllImport("kernel32.dll", SetLastError=true)] static extern bool GetFileInformationByHandleEx(SafeFileHandle file, int kind, IntPtr data, uint length);
|
|
84
|
+
[DllImport("kernel32.dll", SetLastError=true)] static extern bool SetFileInformationByHandle(SafeFileHandle file, int kind, ref BasicInfo info, uint length);
|
|
85
|
+
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)] static extern uint GetFinalPathNameByHandle(SafeFileHandle file, StringBuilder name, uint length, uint flags);
|
|
86
|
+
[DllImport("kernel32.dll", SetLastError=true)] static extern bool SetFilePointerEx(SafeFileHandle file, long position, out long result, uint method);
|
|
87
|
+
[DllImport("kernel32.dll", SetLastError=true)] static extern bool ReadFile(SafeFileHandle file, byte[] bytes, uint count, out uint read, IntPtr overlapped);
|
|
88
|
+
[DllImport("kernel32.dll", SetLastError=true)] static extern bool WriteFile(SafeFileHandle file, byte[] bytes, uint count, out uint written, IntPtr overlapped);
|
|
89
|
+
[DllImport("kernel32.dll", SetLastError=true)] static extern bool FlushFileBuffers(SafeFileHandle file);
|
|
90
|
+
[DllImport("advapi32.dll")] static extern uint GetSecurityInfo(SafeFileHandle file, int kind, uint information,
|
|
91
|
+
out IntPtr owner, out IntPtr group, out IntPtr dacl, out IntPtr sacl, out IntPtr descriptor);
|
|
92
|
+
[DllImport("advapi32.dll")] static extern uint SetSecurityInfo(SafeFileHandle file, int kind, uint information,
|
|
93
|
+
IntPtr owner, IntPtr group, IntPtr dacl, IntPtr sacl);
|
|
94
|
+
[DllImport("advapi32.dll", SetLastError=true)] static extern bool GetSecurityDescriptorControl(IntPtr descriptor, out ushort control, out uint revision);
|
|
95
|
+
[DllImport("kernel32.dll")] static extern IntPtr LocalFree(IntPtr value);
|
|
96
|
+
|
|
97
|
+
static void Check(bool success) { if (!success) NativeFailure((uint)Marshal.GetLastWin32Error()); }
|
|
98
|
+
static bool IsNotDirectoryError(uint code) { return code == 267; } // ERROR_DIRECTORY
|
|
99
|
+
static void NativeFailure(uint code) {
|
|
100
|
+
if (IsNotDirectoryError(code)) throw new FsFault("not_a_directory");
|
|
101
|
+
if (code == 2 || code == 3) throw new FsFault("file_not_found");
|
|
102
|
+
if (code == 80 || code == 183) throw new FsFault("filesystem_target_changed");
|
|
103
|
+
if (code == 5 || code == 32 || code == 33) throw new FsFault("filesystem_access_denied");
|
|
104
|
+
throw new FsFault("filesystem_native_operation_failed");
|
|
105
|
+
}
|
|
106
|
+
static void CheckNt(int status) { if (status < 0) NativeFailure(RtlNtStatusToDosError(status)); }
|
|
107
|
+
static SafeFileHandle OpenHandle(SafeFileHandle root, string name, bool directory,
|
|
108
|
+
uint disposition, uint access, uint share, byte[] securityDescriptor = null, bool deleteOnClose = false) {
|
|
109
|
+
IntPtr text = Marshal.StringToHGlobalUni(name), unicodePointer = IntPtr.Zero, securityPointer = IntPtr.Zero;
|
|
110
|
+
try {
|
|
111
|
+
int length = Encoding.Unicode.GetByteCount(name);
|
|
112
|
+
if (length > 65532) throw new FsFault("filesystem_invalid_path");
|
|
113
|
+
UnicodeString unicode = new UnicodeString { Length=(ushort)length, MaximumLength=(ushort)(length+2), Buffer=text };
|
|
114
|
+
unicodePointer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UnicodeString)));
|
|
115
|
+
Marshal.StructureToPtr(unicode, unicodePointer, false);
|
|
116
|
+
if (securityDescriptor != null) {
|
|
117
|
+
securityPointer = Marshal.AllocHGlobal(securityDescriptor.Length);
|
|
118
|
+
Marshal.Copy(securityDescriptor, 0, securityPointer, securityDescriptor.Length);
|
|
119
|
+
}
|
|
120
|
+
ObjectAttributes attributes = new ObjectAttributes {
|
|
121
|
+
Length=Marshal.SizeOf(typeof(ObjectAttributes)), Root=root == null ? IntPtr.Zero : root.DangerousGetHandle(),
|
|
122
|
+
Name=unicodePointer, Attributes=0x40, Security=securityPointer
|
|
123
|
+
};
|
|
124
|
+
SafeFileHandle file;
|
|
125
|
+
IoStatus status;
|
|
126
|
+
int result = NtCreateFile(out file, access | 0x100000, ref attributes, out status,
|
|
127
|
+
IntPtr.Zero, 0x80, share, disposition, 0x200020u | (directory ? 1u : 0x40u) | (deleteOnClose ? 0x1000u : 0u), IntPtr.Zero, 0);
|
|
128
|
+
if (result < 0) { if (file != null) file.Dispose(); CheckNt(result); }
|
|
129
|
+
try {
|
|
130
|
+
FileInfo info; Check(GetFileInformationByHandle(file, out info));
|
|
131
|
+
if ((info.Attributes & 0x400) != 0) throw new FsFault("filesystem_path_changed");
|
|
132
|
+
if (((info.Attributes & 0x10) != 0) != directory) throw new FsFault("filesystem_path_changed");
|
|
133
|
+
return file;
|
|
134
|
+
} catch { file.Dispose(); throw; }
|
|
135
|
+
} finally {
|
|
136
|
+
if (securityPointer != IntPtr.Zero) Marshal.FreeHGlobal(securityPointer);
|
|
137
|
+
if (unicodePointer != IntPtr.Zero) Marshal.FreeHGlobal(unicodePointer);
|
|
138
|
+
Marshal.FreeHGlobal(text);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
static BasicInfo Basic(SafeFileHandle file) {
|
|
142
|
+
IntPtr buffer = Marshal.AllocHGlobal(40);
|
|
143
|
+
try { Check(GetFileInformationByHandleEx(file, 0, buffer, 40)); return (BasicInfo)Marshal.PtrToStructure(buffer, typeof(BasicInfo)); }
|
|
144
|
+
finally { Marshal.FreeHGlobal(buffer); }
|
|
145
|
+
}
|
|
146
|
+
static Dictionary<string,object> Record(params object[] pairs) {
|
|
147
|
+
var result = new Dictionary<string,object>();
|
|
148
|
+
for (int i=0;i<pairs.Length;i+=2) result.Add((string)pairs[i], pairs[i+1]);
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
151
|
+
static string Text(Dictionary<string,object> request, string key) {
|
|
152
|
+
object value;
|
|
153
|
+
if (!request.TryGetValue(key, out value) || !(value is string)) throw new FsFault("filesystem_invalid_request");
|
|
154
|
+
return (string)value;
|
|
155
|
+
}
|
|
156
|
+
static int Limit(Dictionary<string,object> request, string key, int maximum) {
|
|
157
|
+
object value;
|
|
158
|
+
if (!request.TryGetValue(key, out value) || !(value is int)) throw new FsFault("filesystem_invalid_request");
|
|
159
|
+
int number = (int)value;
|
|
160
|
+
if (number < 0 || number > maximum) throw new FsFault("filesystem_invalid_request");
|
|
161
|
+
return number;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
`;
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// src/shared/windows-file-io/authority-script.ts
|
|
169
|
+
var WINDOWS_FILESYSTEM_AUTHORITY;
|
|
170
|
+
var init_authority_script = __esm({
|
|
171
|
+
"src/shared/windows-file-io/authority-script.ts"() {
|
|
172
|
+
"use strict";
|
|
173
|
+
WINDOWS_FILESYSTEM_AUTHORITY = String.raw`
|
|
174
|
+
public static partial class AbotFilesystem {
|
|
175
|
+
static string NativePath(string path) {
|
|
176
|
+
string full = Path.GetFullPath(path);
|
|
177
|
+
if (full.StartsWith(@"\\?\") || full.StartsWith(@"\\.\")) throw new FsFault("filesystem_invalid_path");
|
|
178
|
+
if (full.StartsWith(@"\\")) return @"\??\UNC\" + full.Substring(2);
|
|
179
|
+
if (full.Length < 3 || full[1] != ':' || full[2] != '\\') throw new FsFault("filesystem_invalid_path");
|
|
180
|
+
return @"\??\" + full;
|
|
181
|
+
}
|
|
182
|
+
static string FinalPath(SafeFileHandle handle) {
|
|
183
|
+
var value = new StringBuilder(32768);
|
|
184
|
+
uint length = GetFinalPathNameByHandle(handle, value, (uint)value.Capacity, 0);
|
|
185
|
+
Check(length != 0);
|
|
186
|
+
if (length >= value.Capacity) throw new FsFault("filesystem_invalid_path");
|
|
187
|
+
string path = value.ToString();
|
|
188
|
+
if (path.StartsWith(@"\\?\UNC\")) return @"\\" + path.Substring(8);
|
|
189
|
+
if (path.StartsWith(@"\\?\")) return path.Substring(4);
|
|
190
|
+
throw new FsFault("filesystem_path_changed");
|
|
191
|
+
}
|
|
192
|
+
static SafeFileHandle OpenRoot(Dictionary<string,object> request) {
|
|
193
|
+
string path = Path.GetFullPath(Text(request, "rootPath"));
|
|
194
|
+
SafeFileHandle root = OpenHandle(null, NativePath(path), true, 1, 0x80000000, 7);
|
|
195
|
+
try {
|
|
196
|
+
if (!String.Equals(FinalPath(root).TrimEnd('\\'), path.TrimEnd('\\'), StringComparison.OrdinalIgnoreCase))
|
|
197
|
+
throw new FsFault("filesystem_path_changed");
|
|
198
|
+
var expected = request["rootIdentity"] as Dictionary<string,object>;
|
|
199
|
+
if (expected == null || !MatchesIdentity(Identity(root), expected)) throw new FsFault("filesystem_path_changed");
|
|
200
|
+
return root;
|
|
201
|
+
} catch { root.Dispose(); throw; }
|
|
202
|
+
}
|
|
203
|
+
static string[] Components(Dictionary<string,object> request) {
|
|
204
|
+
string relative = Text(request, "relativePath");
|
|
205
|
+
if (relative == "") return new string[0];
|
|
206
|
+
string[] parts = relative.Split('/');
|
|
207
|
+
foreach (string part in parts) ValidateComponent(part);
|
|
208
|
+
return parts;
|
|
209
|
+
}
|
|
210
|
+
static void ValidateComponent(string name) {
|
|
211
|
+
if (name.Length == 0 || name == "." || name == "..") throw new FsFault("filesystem_invalid_path");
|
|
212
|
+
if (name.EndsWith(".") || name.EndsWith(" ")) throw new FsFault("filesystem_invalid_path");
|
|
213
|
+
foreach (char c in name) {
|
|
214
|
+
if (c < 32 || "\\/:*?\"<>|".IndexOf(c) >= 0) throw new FsFault("filesystem_invalid_path");
|
|
215
|
+
}
|
|
216
|
+
string stem = name.Split('.')[0].ToUpperInvariant();
|
|
217
|
+
if (stem == "CON" || stem == "PRN" || stem == "AUX" || stem == "NUL" ||
|
|
218
|
+
stem == "CONIN$" || stem == "CONOUT$") throw new FsFault("filesystem_invalid_path");
|
|
219
|
+
if (stem.Length == 4 && (stem.StartsWith("COM") || stem.StartsWith("LPT")) &&
|
|
220
|
+
"123456789\u00b9\u00b2\u00b3".IndexOf(stem[3]) >= 0) throw new FsFault("filesystem_invalid_path");
|
|
221
|
+
}
|
|
222
|
+
sealed class DirectoryChain : IDisposable {
|
|
223
|
+
public readonly SafeFileHandle Root;
|
|
224
|
+
readonly List<SafeFileHandle> children = new List<SafeFileHandle>();
|
|
225
|
+
public SafeFileHandle Current { get { return children.Count == 0 ? Root : children[children.Count-1]; } }
|
|
226
|
+
public DirectoryChain(Dictionary<string,object> request) { Root = OpenRoot(request); }
|
|
227
|
+
public void Walk(string[] parts, int count, bool create) {
|
|
228
|
+
for (int i=0;i<count;i++) children.Add(OpenHandle(Current, parts[i], true, create ? 3u : 1u, 0x80000000, 7));
|
|
229
|
+
}
|
|
230
|
+
public void Dispose() { for (int i=children.Count-1;i>=0;i--) children[i].Dispose(); Root.Dispose(); }
|
|
231
|
+
}
|
|
232
|
+
static ulong FileId(FileInfo info) {
|
|
233
|
+
ulong id=((ulong)info.IndexHigh << 32) | info.IndexLow;
|
|
234
|
+
if (id == 0) throw new FsFault("filesystem_safe_io_unsupported");
|
|
235
|
+
return id;
|
|
236
|
+
}
|
|
237
|
+
static Dictionary<string,object> Identity(SafeFileHandle file) {
|
|
238
|
+
FileInfo info; Check(GetFileInformationByHandle(file, out info));
|
|
239
|
+
BasicInfo basic = Basic(file);
|
|
240
|
+
return Record("device", info.Volume.ToString(), "inode", FileId(info).ToString(),
|
|
241
|
+
"birthtimeNs", ((basic.Created - 116444736000000000L) * 100L).ToString());
|
|
242
|
+
}
|
|
243
|
+
static bool MatchesIdentity(Dictionary<string,object> left, Dictionary<string,object> right) {
|
|
244
|
+
foreach (string key in new [] {"device", "inode", "birthtimeNs"}) {
|
|
245
|
+
if (!right.ContainsKey(key) || !Object.Equals(left[key], right[key])) return false;
|
|
246
|
+
}
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
static Dictionary<string,object> Metadata(SafeFileHandle file) {
|
|
250
|
+
FileInfo info; Check(GetFileInformationByHandle(file, out info));
|
|
251
|
+
BasicInfo basic = Basic(file);
|
|
252
|
+
ulong size = ((ulong)info.SizeHigh << 32) | info.SizeLow;
|
|
253
|
+
if (size > 9007199254740991UL) throw new FsFault("file_too_large");
|
|
254
|
+
return Record("device", info.Volume.ToString(), "inode", FileId(info).ToString(),
|
|
255
|
+
"size", (long)size, "mode", (basic.Attributes & 1) != 0 ? 292 : 438,
|
|
256
|
+
"modifiedNs", ((basic.Modified - 116444736000000000L) * 100L).ToString(),
|
|
257
|
+
"changedNs", ((basic.Changed - 116444736000000000L) * 100L).ToString());
|
|
258
|
+
}
|
|
259
|
+
static bool SameMetadata(Dictionary<string,object> left, Dictionary<string,object> right) {
|
|
260
|
+
foreach (string key in new [] {"device", "inode", "size", "mode", "modifiedNs", "changedNs"}) {
|
|
261
|
+
if (!right.ContainsKey(key) || Convert.ToString(left[key]) != Convert.ToString(right[key])) return false;
|
|
262
|
+
}
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
`;
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// src/shared/windows-file-io/read-bytes-script.ts
|
|
271
|
+
var WINDOWS_FILE_READ_BYTES;
|
|
272
|
+
var init_read_bytes_script = __esm({
|
|
273
|
+
"src/shared/windows-file-io/read-bytes-script.ts"() {
|
|
274
|
+
"use strict";
|
|
275
|
+
WINDOWS_FILE_READ_BYTES = String.raw`
|
|
276
|
+
public static partial class AbotFilesystem {
|
|
277
|
+
static byte[] ReadBytes(SafeFileHandle file, long position, int length) {
|
|
278
|
+
long actual; Check(SetFilePointerEx(file, position, out actual, 0));
|
|
279
|
+
if (actual != position) throw new FsFault("filesystem_read_incomplete");
|
|
280
|
+
var bytes = new byte[length];
|
|
281
|
+
int offset = 0;
|
|
282
|
+
while (offset < length) {
|
|
283
|
+
var chunk = new byte[Math.Min(65536, length-offset)];
|
|
284
|
+
uint read; Check(ReadFile(file, chunk, (uint)chunk.Length, out read, IntPtr.Zero));
|
|
285
|
+
if (read == 0 || read > chunk.Length) throw new FsFault("filesystem_read_incomplete");
|
|
286
|
+
Buffer.BlockCopy(chunk, 0, bytes, offset, (int)read);
|
|
287
|
+
offset += (int)read;
|
|
288
|
+
}
|
|
289
|
+
return bytes;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
`;
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// src/plugin-sdk/files-windows/read-script.ts
|
|
297
|
+
var BOUNDED_READ, WINDOWS_BOUNDED_READ_SOURCE;
|
|
298
|
+
var init_read_script = __esm({
|
|
299
|
+
"src/plugin-sdk/files-windows/read-script.ts"() {
|
|
300
|
+
"use strict";
|
|
301
|
+
init_native_script();
|
|
302
|
+
init_authority_script();
|
|
303
|
+
init_read_bytes_script();
|
|
304
|
+
BOUNDED_READ = String.raw`
|
|
305
|
+
public static partial class AbotFilesystem {
|
|
306
|
+
static object ReadBounded(Dictionary<string,object> request) {
|
|
307
|
+
long maximum;
|
|
308
|
+
if (!Int64.TryParse(Text(request, "maxBytes"), out maximum) || maximum < 0 ||
|
|
309
|
+
maximum > 9007199254740991L) throw new FsFault("filesystem_invalid_request");
|
|
310
|
+
string[] parts=Components(request);
|
|
311
|
+
if (parts.Length == 0) return Record("ok", false, "reason", "not_regular_file");
|
|
312
|
+
using (var chain=new DirectoryChain(request)) {
|
|
313
|
+
chain.Walk(parts, parts.Length-1, false);
|
|
314
|
+
using (var file=OpenHandle(chain.Current, parts[parts.Length-1], false, 1, 0x80000000, 1)) {
|
|
315
|
+
var expected=request["targetIdentity"] as Dictionary<string,object>;
|
|
316
|
+
if (expected == null || !MatchesIdentity(Identity(file), expected))
|
|
317
|
+
return Record("ok", false, "reason", "changed_during_read");
|
|
318
|
+
var before=Metadata(file);
|
|
319
|
+
long size=Convert.ToInt64(before["size"]);
|
|
320
|
+
// Both the byte array and the base64 JSON response must fit .NET strings.
|
|
321
|
+
if (size > maximum || size > (Int32.MaxValue-4096L)/4*3)
|
|
322
|
+
return Record("ok", false, "reason", "too_large", "byteCount", size);
|
|
323
|
+
var bytes=ReadBytes(file, 0, (int)size);
|
|
324
|
+
if (!SameMetadata(before, Metadata(file)))
|
|
325
|
+
return Record("ok", false, "reason", "changed_during_read");
|
|
326
|
+
return Record("ok", true, "bytes", Convert.ToBase64String(bytes), "byteCount", size);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
public static string Run(string input) {
|
|
331
|
+
var json=new JavaScriptSerializer { MaxJsonLength=Int32.MaxValue };
|
|
332
|
+
try { return json.Serialize(ReadBounded(json.Deserialize<Dictionary<string,object>>(input))); }
|
|
333
|
+
catch (FsFault error) { return json.Serialize(Record("ok", false, "code", error.Code)); }
|
|
334
|
+
catch { return json.Serialize(Record("ok", false, "code", "filesystem_native_operation_failed")); }
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
`;
|
|
338
|
+
WINDOWS_BOUNDED_READ_SOURCE = [
|
|
339
|
+
WINDOWS_FILESYSTEM_NATIVE,
|
|
340
|
+
WINDOWS_FILESYSTEM_AUTHORITY,
|
|
341
|
+
WINDOWS_FILE_READ_BYTES,
|
|
342
|
+
BOUNDED_READ
|
|
343
|
+
].join("\n");
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// src/plugin-sdk/files-windows/result.ts
|
|
348
|
+
function windowsReadError(code) {
|
|
349
|
+
const error = new Error(
|
|
350
|
+
"The Windows safe file read failed (" + code + "). No fallback read was attempted."
|
|
351
|
+
);
|
|
352
|
+
return Object.assign(error, { code });
|
|
353
|
+
}
|
|
354
|
+
function windowsReadAbortError() {
|
|
355
|
+
const error = new Error("The file read was cancelled.");
|
|
356
|
+
error.name = "AbortError";
|
|
357
|
+
return error;
|
|
358
|
+
}
|
|
359
|
+
function hasByteCount(value) {
|
|
360
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
361
|
+
}
|
|
362
|
+
function decodeNativeFailure(code) {
|
|
363
|
+
switch (code) {
|
|
364
|
+
case "filesystem_windows_policy_blocked":
|
|
365
|
+
case "filesystem_windows_helper_unavailable":
|
|
366
|
+
case "filesystem_safe_io_unsupported":
|
|
367
|
+
return Object.freeze({ ok: false, reason: "safe_open_unsupported" });
|
|
368
|
+
case "filesystem_path_changed":
|
|
369
|
+
case "filesystem_target_changed":
|
|
370
|
+
case "filesystem_read_changed":
|
|
371
|
+
case "filesystem_read_incomplete":
|
|
372
|
+
return Object.freeze({ ok: false, reason: "changed_during_read" });
|
|
373
|
+
case "file_too_large":
|
|
374
|
+
return Object.freeze({ ok: false, reason: "too_large" });
|
|
375
|
+
case "file_not_found":
|
|
376
|
+
throw windowsReadError("ENOENT");
|
|
377
|
+
case "filesystem_access_denied":
|
|
378
|
+
throw windowsReadError("EACCES");
|
|
379
|
+
default:
|
|
380
|
+
throw windowsReadError("EIO");
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
function decodeWindowsReadResult(raw, maxBytes) {
|
|
384
|
+
let value;
|
|
385
|
+
try {
|
|
386
|
+
value = JSON.parse(raw);
|
|
387
|
+
} catch {
|
|
388
|
+
throw windowsReadError("EIO");
|
|
389
|
+
}
|
|
390
|
+
if (value?.ok === false && typeof value.code === "string")
|
|
391
|
+
return decodeNativeFailure(value.code);
|
|
392
|
+
if (value?.ok === false && FAILURE_REASONS.has(value.reason)) {
|
|
393
|
+
if (value.byteCount !== void 0 && !hasByteCount(value.byteCount))
|
|
394
|
+
throw windowsReadError("EIO");
|
|
395
|
+
return Object.freeze({
|
|
396
|
+
ok: false,
|
|
397
|
+
reason: value.reason,
|
|
398
|
+
...value.byteCount !== void 0 ? { byteCount: value.byteCount } : {}
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
if (value?.ok !== true || !hasByteCount(value.byteCount))
|
|
402
|
+
throw windowsReadError("EIO");
|
|
403
|
+
if (value.byteCount > maxBytes || typeof value.bytes !== "string")
|
|
404
|
+
throw windowsReadError("EIO");
|
|
405
|
+
if (value.bytes.length !== 4 * Math.ceil(value.byteCount / 3))
|
|
406
|
+
throw windowsReadError("EIO");
|
|
407
|
+
const bytes = Buffer.from(value.bytes, "base64");
|
|
408
|
+
if (bytes.length !== value.byteCount || bytes.toString("base64") !== value.bytes)
|
|
409
|
+
throw windowsReadError("EIO");
|
|
410
|
+
return Object.freeze({ ok: true, bytes, byteCount: value.byteCount });
|
|
411
|
+
}
|
|
412
|
+
var FAILURE_REASONS;
|
|
413
|
+
var init_result = __esm({
|
|
414
|
+
"src/plugin-sdk/files-windows/result.ts"() {
|
|
415
|
+
"use strict";
|
|
416
|
+
FAILURE_REASONS = /* @__PURE__ */ new Set([
|
|
417
|
+
"not_regular_file",
|
|
418
|
+
"too_large",
|
|
419
|
+
"changed_during_read",
|
|
420
|
+
"outside_root",
|
|
421
|
+
"safe_open_unsupported"
|
|
422
|
+
]);
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
// src/plugin-sdk/files-windows/process.ts
|
|
427
|
+
async function runWindowsBoundedRead(request, maxBytes, signal, spawnProcess = import_node_child_process.spawn) {
|
|
428
|
+
if (signal?.aborted) throw windowsReadAbortError();
|
|
429
|
+
const input = JSON.stringify({
|
|
430
|
+
source: WINDOWS_BOUNDED_READ_SOURCE,
|
|
431
|
+
request: JSON.stringify(request)
|
|
432
|
+
});
|
|
433
|
+
if (Buffer.byteLength(input) > 2 * 1024 * 1024)
|
|
434
|
+
throw windowsReadError("EINVAL");
|
|
435
|
+
const outputLimit = 4 * Math.ceil(Math.min(maxBytes, 2147483647) / 3) + 4096;
|
|
436
|
+
const executable = (0, import_node_path.join)(
|
|
437
|
+
process.env.SystemRoot ?? "C:\\Windows",
|
|
438
|
+
"System32",
|
|
439
|
+
"WindowsPowerShell",
|
|
440
|
+
"v1.0",
|
|
441
|
+
"powershell.exe"
|
|
442
|
+
);
|
|
443
|
+
return new Promise((resolve, reject) => {
|
|
444
|
+
const child = spawnProcess(
|
|
445
|
+
executable,
|
|
446
|
+
["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", BOOTSTRAP],
|
|
447
|
+
{ windowsHide: true, stdio: ["pipe", "pipe", "pipe"] }
|
|
448
|
+
);
|
|
449
|
+
const chunks = [];
|
|
450
|
+
let byteCount = 0;
|
|
451
|
+
let failure;
|
|
452
|
+
let unavailable = false;
|
|
453
|
+
const stop = (error) => {
|
|
454
|
+
failure ??= error;
|
|
455
|
+
child.kill("SIGKILL");
|
|
456
|
+
};
|
|
457
|
+
const abort = () => stop(windowsReadAbortError());
|
|
458
|
+
const timer = setTimeout(() => stop(windowsReadError("ETIMEDOUT")), 15e3);
|
|
459
|
+
timer.unref();
|
|
460
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
461
|
+
child.stdout.on("data", (chunk) => {
|
|
462
|
+
if (failure) return;
|
|
463
|
+
byteCount += chunk.length;
|
|
464
|
+
if (byteCount > outputLimit) {
|
|
465
|
+
stop(windowsReadError("EOVERFLOW"));
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
chunks.push(chunk);
|
|
469
|
+
});
|
|
470
|
+
child.stderr.resume();
|
|
471
|
+
child.stdin.on("error", () => {
|
|
472
|
+
if (child.pid === void 0) return;
|
|
473
|
+
stop(windowsReadError("EIO"));
|
|
474
|
+
});
|
|
475
|
+
child.once("error", () => {
|
|
476
|
+
if (child.pid === void 0) {
|
|
477
|
+
unavailable = true;
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
stop(windowsReadError("EIO"));
|
|
481
|
+
});
|
|
482
|
+
child.once("close", (code) => {
|
|
483
|
+
clearTimeout(timer);
|
|
484
|
+
signal?.removeEventListener("abort", abort);
|
|
485
|
+
if (failure) {
|
|
486
|
+
reject(failure);
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
if (unavailable) {
|
|
490
|
+
resolve(UNAVAILABLE);
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
if (code !== 0) {
|
|
494
|
+
reject(windowsReadError("EIO"));
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
resolve(Buffer.concat(chunks).toString("utf8"));
|
|
498
|
+
});
|
|
499
|
+
if (signal?.aborted) {
|
|
500
|
+
abort();
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
child.stdin.end(input, "utf8");
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
var import_node_child_process, import_node_path, BOOTSTRAP, UNAVAILABLE;
|
|
507
|
+
var init_process = __esm({
|
|
508
|
+
"src/plugin-sdk/files-windows/process.ts"() {
|
|
509
|
+
"use strict";
|
|
510
|
+
import_node_child_process = require("node:child_process");
|
|
511
|
+
import_node_path = require("node:path");
|
|
512
|
+
init_read_script();
|
|
513
|
+
init_result();
|
|
514
|
+
BOOTSTRAP = [
|
|
515
|
+
"$ErrorActionPreference='Stop'",
|
|
516
|
+
`if ($ExecutionContext.SessionState.LanguageMode -ne 'FullLanguage') { Write-Output '{"ok":false,"code":"filesystem_windows_policy_blocked"}'; exit 0 }`,
|
|
517
|
+
"$env:PSModulePath=[IO.Path]::Combine($PSHOME,'Modules')",
|
|
518
|
+
"[Console]::InputEncoding=[Text.UTF8Encoding]::new($false)",
|
|
519
|
+
"[Console]::OutputEncoding=[Text.UTF8Encoding]::new($false)",
|
|
520
|
+
"$started=$false",
|
|
521
|
+
"try {",
|
|
522
|
+
"$envelope=[Console]::In.ReadToEnd() | ConvertFrom-Json",
|
|
523
|
+
"Add-Type -ReferencedAssemblies @('System.Web.Extensions') -TypeDefinition $envelope.source",
|
|
524
|
+
"$started=$true",
|
|
525
|
+
"[Console]::Write([AbotFilesystem]::Run($envelope.request))",
|
|
526
|
+
`} catch { if ($started) { [Console]::Write('{"ok":false,"code":"filesystem_native_operation_failed"}') } else { [Console]::Write('{"ok":false,"code":"filesystem_windows_helper_unavailable"}') } }`
|
|
527
|
+
].join(";");
|
|
528
|
+
UNAVAILABLE = '{"ok":false,"code":"filesystem_windows_helper_unavailable"}';
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
// src/plugin-sdk/files-windows/read.ts
|
|
533
|
+
var read_exports = {};
|
|
534
|
+
__export(read_exports, {
|
|
535
|
+
readWindowsBoundedRegularFile: () => readWindowsBoundedRegularFile
|
|
536
|
+
});
|
|
537
|
+
function isOutsideRoot(rootRelative) {
|
|
538
|
+
if (import_node_path2.win32.isAbsolute(rootRelative)) return true;
|
|
539
|
+
if (rootRelative === "..") return true;
|
|
540
|
+
return rootRelative.startsWith("..\\");
|
|
541
|
+
}
|
|
542
|
+
function identity(stats) {
|
|
543
|
+
return {
|
|
544
|
+
device: String(stats.dev),
|
|
545
|
+
inode: String(stats.ino),
|
|
546
|
+
birthtimeNs: String(stats.birthtimeNs)
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
async function readWindowsBoundedRegularFile(absolutePath, options) {
|
|
550
|
+
const relativePath = import_node_path2.win32.relative(options.rootPath, absolutePath);
|
|
551
|
+
if (isOutsideRoot(relativePath)) return Object.freeze({ ok: false, reason: "outside_root" });
|
|
552
|
+
if (relativePath === "") return Object.freeze({ ok: false, reason: "not_regular_file" });
|
|
553
|
+
let root;
|
|
554
|
+
try {
|
|
555
|
+
const canonicalRoot = await (0, import_promises.realpath)(options.rootPath);
|
|
556
|
+
root = await (0, import_promises.open)(canonicalRoot, "r");
|
|
557
|
+
const rootStats = await root.stat({ bigint: true });
|
|
558
|
+
if (!rootStats.isDirectory() || rootStats.ino <= 0n)
|
|
559
|
+
return Object.freeze({ ok: false, reason: "safe_open_unsupported" });
|
|
560
|
+
const targetPath = import_node_path2.win32.resolve(canonicalRoot, relativePath);
|
|
561
|
+
const target = await (0, import_promises.lstat)(targetPath, { bigint: true });
|
|
562
|
+
if (!target.isFile()) return Object.freeze({ ok: false, reason: "not_regular_file" });
|
|
563
|
+
const canonicalTarget = await (0, import_promises.realpath)(targetPath);
|
|
564
|
+
if (isOutsideRoot(import_node_path2.win32.relative(canonicalRoot, canonicalTarget)))
|
|
565
|
+
return Object.freeze({ ok: false, reason: "outside_root" });
|
|
566
|
+
if (options.signal?.aborted) throw windowsReadAbortError();
|
|
567
|
+
const raw = await runWindowsBoundedRead({
|
|
568
|
+
rootPath: canonicalRoot,
|
|
569
|
+
relativePath: relativePath.split(import_node_path2.win32.sep).join("/"),
|
|
570
|
+
rootIdentity: identity(rootStats),
|
|
571
|
+
targetIdentity: identity(target),
|
|
572
|
+
maxBytes: String(options.maxBytes)
|
|
573
|
+
}, options.maxBytes, options.signal);
|
|
574
|
+
if (options.signal?.aborted) throw windowsReadAbortError();
|
|
575
|
+
return decodeWindowsReadResult(raw, options.maxBytes);
|
|
576
|
+
} finally {
|
|
577
|
+
await root?.close();
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
var import_promises, import_node_path2;
|
|
581
|
+
var init_read = __esm({
|
|
582
|
+
"src/plugin-sdk/files-windows/read.ts"() {
|
|
583
|
+
"use strict";
|
|
584
|
+
import_promises = require("node:fs/promises");
|
|
585
|
+
import_node_path2 = require("node:path");
|
|
586
|
+
init_process();
|
|
587
|
+
init_result();
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
|
|
33
591
|
// plugins/document-reader/source/index.ts
|
|
34
592
|
var index_exports = {};
|
|
35
593
|
__export(index_exports, {
|
|
@@ -69,8 +627,8 @@ function sanitizeJsonText(value) {
|
|
|
69
627
|
|
|
70
628
|
// src/plugin-sdk/files.ts
|
|
71
629
|
var import_node_fs = require("node:fs");
|
|
72
|
-
var
|
|
73
|
-
var
|
|
630
|
+
var import_promises2 = require("node:fs/promises");
|
|
631
|
+
var import_node_path3 = require("node:path");
|
|
74
632
|
function throwIfAborted(signal) {
|
|
75
633
|
if (!signal?.aborted) return;
|
|
76
634
|
const error = new Error("The file read was cancelled.");
|
|
@@ -97,12 +655,16 @@ async function readBoundedRegularFile(absolutePath, options) {
|
|
|
97
655
|
throw new RangeError("maxBytes must be a non-negative safe integer");
|
|
98
656
|
}
|
|
99
657
|
throwIfAborted(options.signal);
|
|
658
|
+
if (process.platform === "win32") {
|
|
659
|
+
const { readWindowsBoundedRegularFile: readWindowsBoundedRegularFile2 } = await Promise.resolve().then(() => (init_read(), read_exports));
|
|
660
|
+
return readWindowsBoundedRegularFile2(absolutePath, options);
|
|
661
|
+
}
|
|
100
662
|
if (typeof import_node_fs.constants.O_NOFOLLOW !== "number") {
|
|
101
663
|
return Object.freeze({ ok: false, reason: "safe_open_unsupported" });
|
|
102
664
|
}
|
|
103
665
|
let handle;
|
|
104
666
|
try {
|
|
105
|
-
handle = await (0,
|
|
667
|
+
handle = await (0, import_promises2.open)(
|
|
106
668
|
absolutePath,
|
|
107
669
|
import_node_fs.constants.O_RDONLY | import_node_fs.constants.O_NOFOLLOW
|
|
108
670
|
);
|
|
@@ -111,14 +673,14 @@ async function readBoundedRegularFile(absolutePath, options) {
|
|
|
111
673
|
return Object.freeze({ ok: false, reason: "not_regular_file" });
|
|
112
674
|
}
|
|
113
675
|
const [canonicalRoot, canonicalTarget] = await Promise.all([
|
|
114
|
-
(0,
|
|
115
|
-
(0,
|
|
676
|
+
(0, import_promises2.realpath)(options.rootPath),
|
|
677
|
+
(0, import_promises2.realpath)(absolutePath)
|
|
116
678
|
]);
|
|
117
|
-
const rootRelative = (0,
|
|
118
|
-
if (rootRelative === ".." || rootRelative.startsWith(`..${
|
|
679
|
+
const rootRelative = (0, import_node_path3.relative)(canonicalRoot, canonicalTarget);
|
|
680
|
+
if (rootRelative === ".." || rootRelative.startsWith(`..${import_node_path3.sep}`) || rootRelative.startsWith(import_node_path3.sep)) {
|
|
119
681
|
return Object.freeze({ ok: false, reason: "outside_root" });
|
|
120
682
|
}
|
|
121
|
-
const pathIdentity = await (0,
|
|
683
|
+
const pathIdentity = await (0, import_promises2.stat)(canonicalTarget, { bigint: true });
|
|
122
684
|
if (pathIdentity.dev !== before.dev || pathIdentity.ino !== before.ino || !pathIdentity.isFile()) {
|
|
123
685
|
return Object.freeze({ ok: false, reason: "changed_during_read" });
|
|
124
686
|
}
|
|
@@ -453,6 +1015,8 @@ function documentReaderFailure(error) {
|
|
|
453
1015
|
// plugins/document-reader/source/pdf-worker.ts
|
|
454
1016
|
var import_node_module = require("node:module");
|
|
455
1017
|
var import_node_worker_threads = require("node:worker_threads");
|
|
1018
|
+
|
|
1019
|
+
// plugins/document-reader/source/pdf-contract.ts
|
|
456
1020
|
var PDF_EXTRACTION_LIMITS = Object.freeze({
|
|
457
1021
|
maxPages: MAX_PDF_PAGES,
|
|
458
1022
|
pageBatchSize: PDF_PAGE_BATCH_SIZE,
|
|
@@ -462,14 +1026,9 @@ var PDF_EXTRACTION_LIMITS = Object.freeze({
|
|
|
462
1026
|
maxYoungGenerationSizeMb: PDF_MAX_YOUNG_GENERATION_MB,
|
|
463
1027
|
stackSizeMb: PDF_MAX_STACK_MB
|
|
464
1028
|
});
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
"document_pdf_resource_limit"
|
|
469
|
-
]);
|
|
470
|
-
function pdfExtractionWorkerMain() {
|
|
471
|
-
const { parentPort, workerData } = require("node:worker_threads");
|
|
472
|
-
const data = workerData;
|
|
1029
|
+
|
|
1030
|
+
// plugins/document-reader/source/pdf-parser.ts
|
|
1031
|
+
async function runPdfParser(data, publish) {
|
|
473
1032
|
const fail = (code, message) => {
|
|
474
1033
|
const error = new Error(message);
|
|
475
1034
|
error.code = code;
|
|
@@ -479,145 +1038,119 @@ function pdfExtractionWorkerMain() {
|
|
|
479
1038
|
const message = value instanceof Error ? value.message : String(value);
|
|
480
1039
|
return message.slice(0, data.limits.maxErrorMessageCharacters);
|
|
481
1040
|
};
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
1041
|
+
let parser;
|
|
1042
|
+
try {
|
|
1043
|
+
const { PDFParse } = require(data.pdfParseEntrypoint);
|
|
1044
|
+
parser = new PDFParse({
|
|
1045
|
+
data: new Uint8Array(data.bytes),
|
|
1046
|
+
isEvalSupported: false,
|
|
1047
|
+
stopAtErrors: true
|
|
1048
|
+
});
|
|
1049
|
+
const info = await parser.getInfo();
|
|
1050
|
+
const totalPages = info.total;
|
|
1051
|
+
if (!Number.isSafeInteger(totalPages) || totalPages < 0) {
|
|
1052
|
+
fail("document_content_invalid", "The PDF page index is invalid.");
|
|
485
1053
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
if (
|
|
1054
|
+
if (totalPages > data.limits.maxPages) {
|
|
1055
|
+
fail(
|
|
1056
|
+
"document_pdf_page_limit",
|
|
1057
|
+
`The PDF exceeds the ${data.limits.maxPages}-page parsing limit.`
|
|
1058
|
+
);
|
|
1059
|
+
}
|
|
1060
|
+
const retainedParts = [];
|
|
1061
|
+
let retainedCharacters = 0;
|
|
1062
|
+
let totalCharacters = 0;
|
|
1063
|
+
let processedPages = 0;
|
|
1064
|
+
let hasContent = false;
|
|
1065
|
+
const append = (rawValue) => {
|
|
1066
|
+
const value = rawValue.replaceAll("\0", "").trim();
|
|
1067
|
+
if (value.length === 0) return;
|
|
1068
|
+
const separator = hasContent ? "\n\n" : "";
|
|
1069
|
+
hasContent = true;
|
|
1070
|
+
const nextTotal = totalCharacters + separator.length + value.length;
|
|
1071
|
+
if (!Number.isSafeInteger(nextTotal)) {
|
|
500
1072
|
fail(
|
|
501
|
-
"
|
|
502
|
-
|
|
1073
|
+
"document_pdf_resource_limit",
|
|
1074
|
+
"The PDF text exceeds the supported character range."
|
|
503
1075
|
);
|
|
504
1076
|
}
|
|
505
|
-
|
|
506
|
-
let
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
const separator = hasContent ? "\n\n" : "";
|
|
514
|
-
hasContent = true;
|
|
515
|
-
const nextTotal = totalCharacters + separator.length + value.length;
|
|
516
|
-
if (!Number.isSafeInteger(nextTotal)) {
|
|
517
|
-
fail(
|
|
518
|
-
"document_pdf_resource_limit",
|
|
519
|
-
"The PDF text exceeds the supported character range."
|
|
520
|
-
);
|
|
521
|
-
}
|
|
522
|
-
totalCharacters = nextTotal;
|
|
523
|
-
let remaining = data.limits.maxRetainedCharacters - retainedCharacters;
|
|
524
|
-
if (remaining <= 0) return;
|
|
525
|
-
if (separator.length > 0) {
|
|
526
|
-
const retainedSeparator = separator.slice(0, remaining);
|
|
527
|
-
retainedParts.push(retainedSeparator);
|
|
528
|
-
retainedCharacters += retainedSeparator.length;
|
|
529
|
-
remaining -= retainedSeparator.length;
|
|
530
|
-
}
|
|
531
|
-
if (remaining > 0) {
|
|
532
|
-
const retainedValue = value.slice(0, remaining);
|
|
533
|
-
retainedParts.push(retainedValue);
|
|
534
|
-
retainedCharacters += retainedValue.length;
|
|
535
|
-
}
|
|
536
|
-
};
|
|
537
|
-
for (let firstPage = 1; firstPage <= totalPages; firstPage += data.limits.pageBatchSize) {
|
|
538
|
-
const pageNumbers = Array.from(
|
|
539
|
-
{
|
|
540
|
-
length: Math.min(
|
|
541
|
-
data.limits.pageBatchSize,
|
|
542
|
-
totalPages - firstPage + 1
|
|
543
|
-
)
|
|
544
|
-
},
|
|
545
|
-
(_, index) => firstPage + index
|
|
546
|
-
);
|
|
547
|
-
const batch = await parser.getText({
|
|
548
|
-
partial: pageNumbers,
|
|
549
|
-
pageJoiner: ""
|
|
550
|
-
});
|
|
551
|
-
if (!Array.isArray(batch.pages)) {
|
|
552
|
-
fail(
|
|
553
|
-
"document_content_invalid",
|
|
554
|
-
"The PDF page set could not be extracted."
|
|
555
|
-
);
|
|
556
|
-
}
|
|
557
|
-
for (const page of batch.pages) {
|
|
558
|
-
if (typeof page?.text !== "string") {
|
|
559
|
-
fail("document_content_invalid", "The PDF page text is invalid.");
|
|
560
|
-
}
|
|
561
|
-
processedPages += 1;
|
|
562
|
-
append(page.text);
|
|
563
|
-
}
|
|
1077
|
+
totalCharacters = nextTotal;
|
|
1078
|
+
let remaining = data.limits.maxRetainedCharacters - retainedCharacters;
|
|
1079
|
+
if (remaining <= 0) return;
|
|
1080
|
+
if (separator.length > 0) {
|
|
1081
|
+
const retainedSeparator = separator.slice(0, remaining);
|
|
1082
|
+
retainedParts.push(retainedSeparator);
|
|
1083
|
+
retainedCharacters += retainedSeparator.length;
|
|
1084
|
+
remaining -= retainedSeparator.length;
|
|
564
1085
|
}
|
|
565
|
-
if (
|
|
1086
|
+
if (remaining > 0) {
|
|
1087
|
+
const retainedValue = value.slice(0, remaining);
|
|
1088
|
+
retainedParts.push(retainedValue);
|
|
1089
|
+
retainedCharacters += retainedValue.length;
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
for (let firstPage = 1; firstPage <= totalPages; firstPage += data.limits.pageBatchSize) {
|
|
1093
|
+
const pageNumbers = Array.from(
|
|
1094
|
+
{
|
|
1095
|
+
length: Math.min(
|
|
1096
|
+
data.limits.pageBatchSize,
|
|
1097
|
+
totalPages - firstPage + 1
|
|
1098
|
+
)
|
|
1099
|
+
},
|
|
1100
|
+
(_, index) => firstPage + index
|
|
1101
|
+
);
|
|
1102
|
+
const batch = await parser.getText({
|
|
1103
|
+
partial: pageNumbers,
|
|
1104
|
+
pageJoiner: ""
|
|
1105
|
+
});
|
|
1106
|
+
if (!Array.isArray(batch.pages)) {
|
|
566
1107
|
fail(
|
|
567
1108
|
"document_content_invalid",
|
|
568
|
-
"The PDF page set could not be extracted
|
|
1109
|
+
"The PDF page set could not be extracted."
|
|
569
1110
|
);
|
|
570
1111
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
processedPages
|
|
578
|
-
});
|
|
579
|
-
} catch (error) {
|
|
580
|
-
const candidateCode = error instanceof Error && typeof error.code === "string" ? error.code : void 0;
|
|
581
|
-
parentPort.postMessage({
|
|
582
|
-
kind: "failure",
|
|
583
|
-
...candidateCode ? { code: candidateCode } : {},
|
|
584
|
-
message: boundedMessage(error)
|
|
585
|
-
});
|
|
586
|
-
} finally {
|
|
587
|
-
if (parser) {
|
|
588
|
-
await parser.destroy().catch(() => void 0);
|
|
1112
|
+
for (const page of batch.pages) {
|
|
1113
|
+
if (typeof page?.text !== "string") {
|
|
1114
|
+
fail("document_content_invalid", "The PDF page text is invalid.");
|
|
1115
|
+
}
|
|
1116
|
+
processedPages += 1;
|
|
1117
|
+
append(page.text);
|
|
589
1118
|
}
|
|
590
|
-
parentPort.close();
|
|
591
1119
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
}
|
|
598
|
-
function createPdfExtractionWorker(bytes, pdfParseEntrypoint, limits = PDF_EXTRACTION_LIMITS) {
|
|
599
|
-
const transferredBytes = new ArrayBuffer(bytes.byteLength);
|
|
600
|
-
new Uint8Array(transferredBytes).set(bytes);
|
|
601
|
-
return new import_node_worker_threads.Worker(`(${pdfExtractionWorkerMain.toString()})()`, {
|
|
602
|
-
eval: true,
|
|
603
|
-
transferList: [transferredBytes],
|
|
604
|
-
workerData: {
|
|
605
|
-
bytes: transferredBytes,
|
|
606
|
-
pdfParseEntrypoint,
|
|
607
|
-
limits: {
|
|
608
|
-
maxPages: limits.maxPages,
|
|
609
|
-
pageBatchSize: limits.pageBatchSize,
|
|
610
|
-
maxRetainedCharacters: limits.maxRetainedCharacters,
|
|
611
|
-
maxErrorMessageCharacters: MAX_PDF_ERROR_MESSAGE_CHARS
|
|
612
|
-
}
|
|
613
|
-
},
|
|
614
|
-
resourceLimits: {
|
|
615
|
-
maxOldGenerationSizeMb: limits.maxOldGenerationSizeMb,
|
|
616
|
-
maxYoungGenerationSizeMb: limits.maxYoungGenerationSizeMb,
|
|
617
|
-
stackSizeMb: limits.stackSizeMb
|
|
1120
|
+
if (processedPages !== totalPages) {
|
|
1121
|
+
fail(
|
|
1122
|
+
"document_content_invalid",
|
|
1123
|
+
"The PDF page set could not be extracted completely."
|
|
1124
|
+
);
|
|
618
1125
|
}
|
|
619
|
-
|
|
1126
|
+
publish({
|
|
1127
|
+
kind: "success",
|
|
1128
|
+
text: retainedParts.join(""),
|
|
1129
|
+
totalCharacters,
|
|
1130
|
+
returnedCharacters: retainedCharacters,
|
|
1131
|
+
totalPages,
|
|
1132
|
+
processedPages
|
|
1133
|
+
});
|
|
1134
|
+
} catch (error) {
|
|
1135
|
+
const candidateCode = error instanceof Error && typeof error.code === "string" ? error.code : void 0;
|
|
1136
|
+
publish({
|
|
1137
|
+
kind: "failure",
|
|
1138
|
+
...candidateCode ? { code: candidateCode } : {},
|
|
1139
|
+
message: boundedMessage(error)
|
|
1140
|
+
});
|
|
1141
|
+
} finally {
|
|
1142
|
+
if (parser) {
|
|
1143
|
+
await parser.destroy().catch(() => void 0);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
620
1146
|
}
|
|
1147
|
+
|
|
1148
|
+
// plugins/document-reader/source/pdf-result.ts
|
|
1149
|
+
var CONTROLLED_PDF_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
1150
|
+
"document_content_invalid",
|
|
1151
|
+
"document_pdf_page_limit",
|
|
1152
|
+
"document_pdf_resource_limit"
|
|
1153
|
+
]);
|
|
621
1154
|
function isSafeNonNegativeInteger(value) {
|
|
622
1155
|
return Number.isSafeInteger(value) && typeof value === "number" && value >= 0;
|
|
623
1156
|
}
|
|
@@ -629,6 +1162,76 @@ function isPdfWorkerMessage(value) {
|
|
|
629
1162
|
}
|
|
630
1163
|
return candidate.kind === "success" && typeof candidate.text === "string" && isSafeNonNegativeInteger(candidate.totalCharacters) && isSafeNonNegativeInteger(candidate.returnedCharacters) && isSafeNonNegativeInteger(candidate.totalPages) && isSafeNonNegativeInteger(candidate.processedPages);
|
|
631
1164
|
}
|
|
1165
|
+
function isBoundedPdfSuccess(message, limits) {
|
|
1166
|
+
if (message.text.length !== message.returnedCharacters) return false;
|
|
1167
|
+
if (message.returnedCharacters > limits.maxRetainedCharacters) return false;
|
|
1168
|
+
if (message.returnedCharacters > message.totalCharacters) return false;
|
|
1169
|
+
if (message.totalPages > limits.maxPages) return false;
|
|
1170
|
+
return message.processedPages === message.totalPages;
|
|
1171
|
+
}
|
|
1172
|
+
function documentFromPdfMessage(message, limits) {
|
|
1173
|
+
if (!isPdfWorkerMessage(message)) {
|
|
1174
|
+
throw new Error("PDF extraction worker returned invalid data.");
|
|
1175
|
+
}
|
|
1176
|
+
if (message.kind === "failure") {
|
|
1177
|
+
if (message.code && CONTROLLED_PDF_ERROR_CODES.has(message.code)) {
|
|
1178
|
+
throw new DocumentReaderError(message.code, message.message);
|
|
1179
|
+
}
|
|
1180
|
+
throw new Error(message.message);
|
|
1181
|
+
}
|
|
1182
|
+
if (!isBoundedPdfSuccess(message, limits)) {
|
|
1183
|
+
throw new Error("PDF extraction worker exceeded its contract.");
|
|
1184
|
+
}
|
|
1185
|
+
return Object.freeze({
|
|
1186
|
+
text: message.text,
|
|
1187
|
+
textBounds: Object.freeze({
|
|
1188
|
+
truncated: message.totalCharacters > message.returnedCharacters,
|
|
1189
|
+
totalCharacters: message.totalCharacters,
|
|
1190
|
+
returnedCharacters: message.returnedCharacters,
|
|
1191
|
+
omittedCharacters: message.totalCharacters - message.returnedCharacters,
|
|
1192
|
+
maxCharacters: limits.maxRetainedCharacters
|
|
1193
|
+
}),
|
|
1194
|
+
format: Object.freeze({
|
|
1195
|
+
kind: "pdf",
|
|
1196
|
+
totalPages: message.totalPages,
|
|
1197
|
+
processedPages: message.processedPages,
|
|
1198
|
+
maxPages: limits.maxPages
|
|
1199
|
+
})
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
// plugins/document-reader/source/pdf-worker.ts
|
|
1204
|
+
function resolvePdfParseEntrypoint(pluginEntrypoint) {
|
|
1205
|
+
return (0, import_node_module.createRequire)(pluginEntrypoint).resolve("pdf-parse");
|
|
1206
|
+
}
|
|
1207
|
+
function createPdfExtractionWorker(bytes, pdfParseEntrypoint, limits = PDF_EXTRACTION_LIMITS) {
|
|
1208
|
+
const transferredBytes = new ArrayBuffer(bytes.byteLength);
|
|
1209
|
+
new Uint8Array(transferredBytes).set(bytes);
|
|
1210
|
+
return new import_node_worker_threads.Worker(
|
|
1211
|
+
`const { parentPort, workerData } = require("node:worker_threads");
|
|
1212
|
+
void (${runPdfParser.toString()})(workerData, message => parentPort.postMessage(message))
|
|
1213
|
+
.finally(() => parentPort.close());`,
|
|
1214
|
+
{
|
|
1215
|
+
eval: true,
|
|
1216
|
+
transferList: [transferredBytes],
|
|
1217
|
+
workerData: {
|
|
1218
|
+
bytes: transferredBytes,
|
|
1219
|
+
pdfParseEntrypoint,
|
|
1220
|
+
limits: {
|
|
1221
|
+
maxPages: limits.maxPages,
|
|
1222
|
+
pageBatchSize: limits.pageBatchSize,
|
|
1223
|
+
maxRetainedCharacters: limits.maxRetainedCharacters,
|
|
1224
|
+
maxErrorMessageCharacters: MAX_PDF_ERROR_MESSAGE_CHARS
|
|
1225
|
+
}
|
|
1226
|
+
},
|
|
1227
|
+
resourceLimits: {
|
|
1228
|
+
maxOldGenerationSizeMb: limits.maxOldGenerationSizeMb,
|
|
1229
|
+
maxYoungGenerationSizeMb: limits.maxYoungGenerationSizeMb,
|
|
1230
|
+
stackSizeMb: limits.stackSizeMb
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
);
|
|
1234
|
+
}
|
|
632
1235
|
function resourceLimitError(message) {
|
|
633
1236
|
return new DocumentReaderError("document_pdf_resource_limit", message);
|
|
634
1237
|
}
|
|
@@ -682,52 +1285,13 @@ async function extractPdfInWorker(bytes, params) {
|
|
|
682
1285
|
);
|
|
683
1286
|
};
|
|
684
1287
|
worker.once("message", (message) => {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
(
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
}
|
|
692
|
-
if (message.kind === "failure") {
|
|
693
|
-
settle(() => {
|
|
694
|
-
if (message.code && CONTROLLED_PDF_ERROR_CODES.has(message.code)) {
|
|
695
|
-
reject(new DocumentReaderError(message.code, message.message));
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
698
|
-
reject(new Error(message.message));
|
|
699
|
-
}, true);
|
|
700
|
-
return;
|
|
701
|
-
}
|
|
702
|
-
const validSuccess = message.text.length === message.returnedCharacters && message.returnedCharacters <= limits.maxRetainedCharacters && message.returnedCharacters <= message.totalCharacters && message.totalPages <= limits.maxPages && message.processedPages === message.totalPages;
|
|
703
|
-
if (!validSuccess) {
|
|
704
|
-
settle(
|
|
705
|
-
() => reject(new Error("PDF extraction worker exceeded its contract.")),
|
|
706
|
-
true
|
|
707
|
-
);
|
|
708
|
-
return;
|
|
709
|
-
}
|
|
710
|
-
settle(
|
|
711
|
-
() => resolve(
|
|
712
|
-
Object.freeze({
|
|
713
|
-
text: message.text,
|
|
714
|
-
textBounds: Object.freeze({
|
|
715
|
-
truncated: message.totalCharacters > message.returnedCharacters,
|
|
716
|
-
totalCharacters: message.totalCharacters,
|
|
717
|
-
returnedCharacters: message.returnedCharacters,
|
|
718
|
-
omittedCharacters: message.totalCharacters - message.returnedCharacters,
|
|
719
|
-
maxCharacters: limits.maxRetainedCharacters
|
|
720
|
-
}),
|
|
721
|
-
format: Object.freeze({
|
|
722
|
-
kind: "pdf",
|
|
723
|
-
totalPages: message.totalPages,
|
|
724
|
-
processedPages: message.processedPages,
|
|
725
|
-
maxPages: limits.maxPages
|
|
726
|
-
})
|
|
727
|
-
})
|
|
728
|
-
),
|
|
729
|
-
true
|
|
730
|
-
);
|
|
1288
|
+
settle(() => {
|
|
1289
|
+
try {
|
|
1290
|
+
resolve(documentFromPdfMessage(message, limits));
|
|
1291
|
+
} catch (error) {
|
|
1292
|
+
reject(error);
|
|
1293
|
+
}
|
|
1294
|
+
}, true);
|
|
731
1295
|
});
|
|
732
1296
|
worker.once("error", (error) => {
|
|
733
1297
|
settle(
|
|
@@ -759,6 +1323,37 @@ async function extractPdfInWorker(bytes, params) {
|
|
|
759
1323
|
});
|
|
760
1324
|
}
|
|
761
1325
|
|
|
1326
|
+
// plugins/document-reader/source/read-failure.ts
|
|
1327
|
+
function failDocumentRead(file, maxBytes) {
|
|
1328
|
+
switch (file.reason) {
|
|
1329
|
+
case "not_regular_file":
|
|
1330
|
+
return failDocument(
|
|
1331
|
+
"document_target_not_file",
|
|
1332
|
+
"The requested document is not a regular file."
|
|
1333
|
+
);
|
|
1334
|
+
case "too_large":
|
|
1335
|
+
return failDocument(
|
|
1336
|
+
"document_file_too_large",
|
|
1337
|
+
"The requested document exceeds the " + maxBytes + "-byte parsing limit."
|
|
1338
|
+
);
|
|
1339
|
+
case "outside_root":
|
|
1340
|
+
return failDocument(
|
|
1341
|
+
"document_outside_root",
|
|
1342
|
+
"The requested document resolves outside its authorized root. Do not retry this target or bypass the path restriction."
|
|
1343
|
+
);
|
|
1344
|
+
case "safe_open_unsupported":
|
|
1345
|
+
return failDocument(
|
|
1346
|
+
"document_safe_read_unavailable",
|
|
1347
|
+
"Safe file reading is unavailable on this system. On Windows, computer policy may block the required PowerShell/C# helper. Do not retry or bypass this restriction with another tool; ask the user to check the system requirements or contact their administrator."
|
|
1348
|
+
);
|
|
1349
|
+
case "changed_during_read":
|
|
1350
|
+
return failDocument(
|
|
1351
|
+
"document_changed_during_read",
|
|
1352
|
+
"The requested document changed while it was being read."
|
|
1353
|
+
);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
|
|
762
1357
|
// plugins/document-reader/source/archive.ts
|
|
763
1358
|
var import_jszip = __toESM(require("jszip"), 1);
|
|
764
1359
|
var END_OF_CENTRAL_DIRECTORY_SIGNATURE = 101010256;
|
|
@@ -1107,9 +1702,215 @@ ${content}` : ""}`);
|
|
|
1107
1702
|
return archiveResult(accumulator, archive);
|
|
1108
1703
|
}
|
|
1109
1704
|
|
|
1705
|
+
// plugins/document-reader/source/pdf-process.ts
|
|
1706
|
+
var import_node_child_process2 = require("node:child_process");
|
|
1707
|
+
|
|
1708
|
+
// plugins/document-reader/source/pdf-process-main.ts
|
|
1709
|
+
var PDF_PROCESS_HEADER_MAX_BYTES = 64 * 1024;
|
|
1710
|
+
async function pdfProcessMain(parse, maxInputBytes, maxHeaderBytes, maxHeapBytes) {
|
|
1711
|
+
console.log = console.warn = console.error = () => void 0;
|
|
1712
|
+
try {
|
|
1713
|
+
const { heap_size_limit } = require("node:v8").getHeapStatistics();
|
|
1714
|
+
if (heap_size_limit > maxHeapBytes) {
|
|
1715
|
+
const failure = {
|
|
1716
|
+
kind: "failure",
|
|
1717
|
+
code: "document_pdf_resource_limit",
|
|
1718
|
+
message: "PDF extraction could not establish its memory limit."
|
|
1719
|
+
};
|
|
1720
|
+
process.stdout.end(JSON.stringify(failure), () => process.exit(0));
|
|
1721
|
+
return;
|
|
1722
|
+
}
|
|
1723
|
+
const chunks = [];
|
|
1724
|
+
let size = 0;
|
|
1725
|
+
for await (const chunk of process.stdin) {
|
|
1726
|
+
size += chunk.length;
|
|
1727
|
+
if (size > maxInputBytes + maxHeaderBytes + 1) {
|
|
1728
|
+
throw new Error("PDF process input exceeds its limit.");
|
|
1729
|
+
}
|
|
1730
|
+
chunks.push(chunk);
|
|
1731
|
+
}
|
|
1732
|
+
const input = Buffer.concat(chunks, size);
|
|
1733
|
+
const separator = input.indexOf(10);
|
|
1734
|
+
if (separator < 0) throw new Error("Missing PDF process header.");
|
|
1735
|
+
if (separator > maxHeaderBytes)
|
|
1736
|
+
throw new Error("PDF process header is too large.");
|
|
1737
|
+
const bytes = input.subarray(separator + 1);
|
|
1738
|
+
if (bytes.length > maxInputBytes)
|
|
1739
|
+
throw new Error("PDF process input is too large.");
|
|
1740
|
+
const header = JSON.parse(
|
|
1741
|
+
input.subarray(0, separator).toString("utf8")
|
|
1742
|
+
);
|
|
1743
|
+
let result;
|
|
1744
|
+
await parse({ ...header, bytes }, (message) => {
|
|
1745
|
+
result = message;
|
|
1746
|
+
});
|
|
1747
|
+
if (!result) throw new Error("PDF parser returned no result.");
|
|
1748
|
+
process.stdout.end(JSON.stringify(result), () => process.exit(0));
|
|
1749
|
+
} catch {
|
|
1750
|
+
process.exit(1);
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
// plugins/document-reader/source/pdf-process.ts
|
|
1755
|
+
function pdfSemiSpaceLimitMb(youngGenerationMb) {
|
|
1756
|
+
const maximum = Math.floor(youngGenerationMb / 3);
|
|
1757
|
+
let size = 1;
|
|
1758
|
+
while (size * 2 <= maximum) size *= 2;
|
|
1759
|
+
return size;
|
|
1760
|
+
}
|
|
1761
|
+
function pdfProcessArguments(limits) {
|
|
1762
|
+
return [
|
|
1763
|
+
"--input-type=commonjs",
|
|
1764
|
+
"--max-old-space-size=" + limits.maxOldGenerationSizeMb,
|
|
1765
|
+
// V8's young generation uses three semi-spaces; keep it within the existing bound.
|
|
1766
|
+
"--max-semi-space-size=" + pdfSemiSpaceLimitMb(limits.maxYoungGenerationSizeMb),
|
|
1767
|
+
"--stack-size=" + Math.floor(limits.stackSizeMb * 1024),
|
|
1768
|
+
"--eval",
|
|
1769
|
+
"(" + pdfProcessMain.toString() + ")(" + runPdfParser.toString() + ", " + MAX_DOCUMENT_BYTES + ", " + PDF_PROCESS_HEADER_MAX_BYTES + ", " + (limits.maxOldGenerationSizeMb + limits.maxYoungGenerationSizeMb) * 1024 * 1024 + ")"
|
|
1770
|
+
];
|
|
1771
|
+
}
|
|
1772
|
+
function createPdfExtractionProcess(bytes, pdfParseEntrypoint, limits) {
|
|
1773
|
+
const header = Buffer.from(
|
|
1774
|
+
JSON.stringify({
|
|
1775
|
+
pdfParseEntrypoint,
|
|
1776
|
+
limits: {
|
|
1777
|
+
maxPages: limits.maxPages,
|
|
1778
|
+
pageBatchSize: limits.pageBatchSize,
|
|
1779
|
+
maxRetainedCharacters: limits.maxRetainedCharacters,
|
|
1780
|
+
maxErrorMessageCharacters: MAX_PDF_ERROR_MESSAGE_CHARS
|
|
1781
|
+
}
|
|
1782
|
+
}) + "\n"
|
|
1783
|
+
);
|
|
1784
|
+
if (header.length > PDF_PROCESS_HEADER_MAX_BYTES) {
|
|
1785
|
+
throw new Error("PDF process header exceeds its limit.");
|
|
1786
|
+
}
|
|
1787
|
+
const child = (0, import_node_child_process2.spawn)(process.execPath, pdfProcessArguments(limits), {
|
|
1788
|
+
windowsHide: true,
|
|
1789
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1790
|
+
});
|
|
1791
|
+
child.stdin.write(header);
|
|
1792
|
+
child.stdin.end(Buffer.from(bytes));
|
|
1793
|
+
return child;
|
|
1794
|
+
}
|
|
1795
|
+
function pdfCancellationError() {
|
|
1796
|
+
return new DocumentReaderError(
|
|
1797
|
+
"document_read_cancelled",
|
|
1798
|
+
"Document reading was cancelled."
|
|
1799
|
+
);
|
|
1800
|
+
}
|
|
1801
|
+
function pdfResourceError(message) {
|
|
1802
|
+
return new DocumentReaderError("document_pdf_resource_limit", message);
|
|
1803
|
+
}
|
|
1804
|
+
function didPdfProcessExitCleanly(code, signal) {
|
|
1805
|
+
if (signal !== null) return false;
|
|
1806
|
+
return code === 0;
|
|
1807
|
+
}
|
|
1808
|
+
async function extractPdfInProcess(bytes, params) {
|
|
1809
|
+
if (params.signal?.aborted) throw pdfCancellationError();
|
|
1810
|
+
if (bytes.byteLength > MAX_DOCUMENT_BYTES) {
|
|
1811
|
+
throw new DocumentReaderError(
|
|
1812
|
+
"document_file_too_large",
|
|
1813
|
+
"The PDF exceeds the input size limit."
|
|
1814
|
+
);
|
|
1815
|
+
}
|
|
1816
|
+
const limits = params.limits ?? PDF_EXTRACTION_LIMITS;
|
|
1817
|
+
const child = createPdfExtractionProcess(
|
|
1818
|
+
bytes,
|
|
1819
|
+
params.pdfParseEntrypoint,
|
|
1820
|
+
limits
|
|
1821
|
+
);
|
|
1822
|
+
const maxResultBytes = limits.maxRetainedCharacters * 6 + 4096;
|
|
1823
|
+
return new Promise((resolve, reject) => {
|
|
1824
|
+
const chunks = [];
|
|
1825
|
+
let resultBytes = 0;
|
|
1826
|
+
let failure;
|
|
1827
|
+
const stopPdfProcess = (error) => {
|
|
1828
|
+
if (failure) return;
|
|
1829
|
+
failure = error;
|
|
1830
|
+
chunks.length = 0;
|
|
1831
|
+
child.stdin.destroy();
|
|
1832
|
+
child.kill("SIGKILL");
|
|
1833
|
+
};
|
|
1834
|
+
const onAbort = () => stopPdfProcess(pdfCancellationError());
|
|
1835
|
+
const timeout = setTimeout(
|
|
1836
|
+
() => stopPdfProcess(
|
|
1837
|
+
pdfResourceError(
|
|
1838
|
+
"PDF extraction exceeded the " + limits.timeoutMs + "-millisecond time limit."
|
|
1839
|
+
)
|
|
1840
|
+
),
|
|
1841
|
+
limits.timeoutMs
|
|
1842
|
+
);
|
|
1843
|
+
timeout.unref();
|
|
1844
|
+
child.stdout.on("data", (chunk) => {
|
|
1845
|
+
if (failure) return;
|
|
1846
|
+
resultBytes += chunk.length;
|
|
1847
|
+
if (resultBytes > maxResultBytes) {
|
|
1848
|
+
stopPdfProcess(
|
|
1849
|
+
pdfResourceError("PDF extraction exceeded its result size limit.")
|
|
1850
|
+
);
|
|
1851
|
+
return;
|
|
1852
|
+
}
|
|
1853
|
+
chunks.push(chunk);
|
|
1854
|
+
});
|
|
1855
|
+
child.stderr.resume();
|
|
1856
|
+
child.stdin.on(
|
|
1857
|
+
"error",
|
|
1858
|
+
() => stopPdfProcess(
|
|
1859
|
+
new Error("PDF extraction process could not receive its input.")
|
|
1860
|
+
)
|
|
1861
|
+
);
|
|
1862
|
+
child.stdout.on(
|
|
1863
|
+
"error",
|
|
1864
|
+
() => stopPdfProcess(
|
|
1865
|
+
new Error("PDF extraction process could not return its result.")
|
|
1866
|
+
)
|
|
1867
|
+
);
|
|
1868
|
+
child.stderr.on(
|
|
1869
|
+
"error",
|
|
1870
|
+
() => stopPdfProcess(new Error("PDF extraction process stream failed."))
|
|
1871
|
+
);
|
|
1872
|
+
child.on(
|
|
1873
|
+
"error",
|
|
1874
|
+
() => stopPdfProcess(
|
|
1875
|
+
new DocumentReaderError(
|
|
1876
|
+
"document_pdf_process_unavailable",
|
|
1877
|
+
"The PDF extraction process could not be started or stopped. Do not retry or bypass this restriction with another tool; ask the user to check system requirements or contact their administrator."
|
|
1878
|
+
)
|
|
1879
|
+
)
|
|
1880
|
+
);
|
|
1881
|
+
child.once("close", (code, signal) => {
|
|
1882
|
+
clearTimeout(timeout);
|
|
1883
|
+
params.signal?.removeEventListener("abort", onAbort);
|
|
1884
|
+
if (failure) {
|
|
1885
|
+
reject(failure);
|
|
1886
|
+
return;
|
|
1887
|
+
}
|
|
1888
|
+
if (!didPdfProcessExitCleanly(code, signal)) {
|
|
1889
|
+
reject(new Error("PDF extraction process stopped unexpectedly."));
|
|
1890
|
+
return;
|
|
1891
|
+
}
|
|
1892
|
+
try {
|
|
1893
|
+
const message = JSON.parse(
|
|
1894
|
+
Buffer.concat(chunks, resultBytes).toString("utf8")
|
|
1895
|
+
);
|
|
1896
|
+
resolve(documentFromPdfMessage(message, limits));
|
|
1897
|
+
} catch (error) {
|
|
1898
|
+
if (error instanceof SyntaxError) {
|
|
1899
|
+
reject(new Error("PDF extraction process returned invalid data."));
|
|
1900
|
+
return;
|
|
1901
|
+
}
|
|
1902
|
+
reject(error);
|
|
1903
|
+
}
|
|
1904
|
+
});
|
|
1905
|
+
params.signal?.addEventListener("abort", onAbort, { once: true });
|
|
1906
|
+
if (params.signal?.aborted) onAbort();
|
|
1907
|
+
});
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1110
1910
|
// plugins/document-reader/source/pdf.ts
|
|
1111
1911
|
function extractPdfText(bytes, pdfParseEntrypoint, signal) {
|
|
1112
|
-
|
|
1912
|
+
const extract = process.platform === "win32" ? extractPdfInProcess : extractPdfInWorker;
|
|
1913
|
+
return extract(bytes, {
|
|
1113
1914
|
pdfParseEntrypoint,
|
|
1114
1915
|
...signal ? { signal } : {}
|
|
1115
1916
|
});
|
|
@@ -1164,24 +1965,7 @@ async function readDocument(document, pdfParseEntrypoint, signal) {
|
|
|
1164
1965
|
rootPath: document.rootPath,
|
|
1165
1966
|
...signal ? { signal } : {}
|
|
1166
1967
|
});
|
|
1167
|
-
if (!file.ok
|
|
1168
|
-
failDocument(
|
|
1169
|
-
"document_target_not_file",
|
|
1170
|
-
"The requested document is not a regular file."
|
|
1171
|
-
);
|
|
1172
|
-
}
|
|
1173
|
-
if (!file.ok && file.reason === "too_large") {
|
|
1174
|
-
failDocument(
|
|
1175
|
-
"document_file_too_large",
|
|
1176
|
-
`The requested document exceeds the ${MAX_DOCUMENT_BYTES}-byte parsing limit.`
|
|
1177
|
-
);
|
|
1178
|
-
}
|
|
1179
|
-
if (!file.ok) {
|
|
1180
|
-
failDocument(
|
|
1181
|
-
"document_changed_during_read",
|
|
1182
|
-
"The requested document changed while it was being read."
|
|
1183
|
-
);
|
|
1184
|
-
}
|
|
1968
|
+
if (!file.ok) failDocumentRead(file, MAX_DOCUMENT_BYTES);
|
|
1185
1969
|
const bytes = new Uint8Array(file.bytes);
|
|
1186
1970
|
return Object.freeze({
|
|
1187
1971
|
bytes: bytes.byteLength,
|
|
@@ -1198,7 +1982,7 @@ async function readDocument(document, pdfParseEntrypoint, signal) {
|
|
|
1198
1982
|
}
|
|
1199
1983
|
|
|
1200
1984
|
// plugins/document-reader/source/source-resolution.ts
|
|
1201
|
-
var
|
|
1985
|
+
var import_node_path4 = require("node:path");
|
|
1202
1986
|
var SUPPORTED_MIME_TYPES = new Set(
|
|
1203
1987
|
Object.values(EXTENSION_MIME_TYPES)
|
|
1204
1988
|
);
|
|
@@ -1208,11 +1992,11 @@ function supportedMimeType(value) {
|
|
|
1208
1992
|
return SUPPORTED_MIME_TYPES.has(alias) ? alias : void 0;
|
|
1209
1993
|
}
|
|
1210
1994
|
function mimeTypeFromName(value) {
|
|
1211
|
-
return EXTENSION_MIME_TYPES[(0,
|
|
1995
|
+
return EXTENSION_MIME_TYPES[(0, import_node_path4.extname)(value).toLowerCase()];
|
|
1212
1996
|
}
|
|
1213
1997
|
function attachmentDisplayName(attachment) {
|
|
1214
1998
|
const candidate = attachment.name?.trim() || attachment.id;
|
|
1215
|
-
return
|
|
1999
|
+
return import_node_path4.posix.basename(import_node_path4.win32.basename(candidate));
|
|
1216
2000
|
}
|
|
1217
2001
|
function attachmentMimeType(attachment) {
|
|
1218
2002
|
const displayName = attachmentDisplayName(attachment);
|
|
@@ -1254,7 +2038,7 @@ function resolveRuntimePathDocument(rawPath, loadContext, executionContext) {
|
|
|
1254
2038
|
kind: "runtime_path",
|
|
1255
2039
|
absolutePath: target.absolutePath,
|
|
1256
2040
|
rootPath: target.rootPath,
|
|
1257
|
-
displayName: (0,
|
|
2041
|
+
displayName: (0, import_node_path4.basename)(target.logicalPath),
|
|
1258
2042
|
mimeType,
|
|
1259
2043
|
path: Object.freeze({
|
|
1260
2044
|
location: target.location,
|