@abot-ai/runtime 1.6.0 → 1.7.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/README.md +2 -0
- package/dist/src/bridge/request-steering.js +60 -15
- package/dist/src/capabilities/normal-invocation/contracts.d.ts +3 -0
- package/dist/src/capabilities/normal-invocation/output-channels.d.ts +10 -0
- package/dist/src/capabilities/normal-invocation/output-channels.js +29 -0
- package/dist/src/capabilities/normal-invocation/validator.js +4 -2
- package/dist/src/capabilities/tool-types.d.ts +1 -1
- package/dist/src/cli/host-companion-bundle.mjs +7570 -6781
- package/dist/src/cli/host-companion-entry.js +5 -22
- package/dist/src/cli/host-companion-input.d.ts +3 -0
- package/dist/src/cli/host-companion-input.js +21 -0
- package/dist/src/cli/host-companion-lifecycle.d.ts +11 -0
- package/dist/src/cli/host-companion-lifecycle.js +32 -0
- package/dist/src/cli/host-companion-setup-target.d.ts +4 -0
- package/dist/src/cli/host-companion-setup-target.js +17 -0
- package/dist/src/cli/host-companion-startup.d.ts +2 -0
- package/dist/src/cli/host-companion-startup.js +7 -2
- package/dist/src/cli/host-companion.d.ts +6 -0
- package/dist/src/cli/host-companion.js +30 -27
- package/dist/src/cli/windows-companion-store-entry.d.ts +9 -0
- package/dist/src/cli/windows-companion-store-entry.js +67 -0
- package/dist/src/computer-access/command-output-capture.d.ts +37 -0
- package/dist/src/computer-access/command-output-capture.js +136 -0
- package/dist/src/computer-access/command-output-retention.d.ts +5 -0
- package/dist/src/computer-access/command-output-retention.js +90 -0
- package/dist/src/computer-access/command-output.d.ts +7 -0
- package/dist/src/computer-access/command-output.js +1 -0
- package/dist/src/computer-access/commands.d.ts +1 -0
- package/dist/src/computer-access/commands.js +1 -1
- package/dist/src/computer-access/companion/command-output-protocol.d.ts +12 -0
- package/dist/src/computer-access/companion/command-output-protocol.js +28 -0
- package/dist/src/computer-access/companion/command-output.d.ts +13 -0
- package/dist/src/computer-access/companion/command-output.js +110 -0
- package/dist/src/computer-access/companion/install-link-macos.d.ts +7 -0
- package/dist/src/computer-access/companion/install-link-macos.js +48 -0
- package/dist/src/computer-access/companion/install-link-registration.d.ts +4 -0
- package/dist/src/computer-access/companion/install-link-registration.js +184 -0
- package/dist/src/computer-access/companion/install-link-windows.d.ts +4 -0
- package/dist/src/computer-access/companion/install-link-windows.js +65 -0
- package/dist/src/computer-access/companion/install-link.d.ts +9 -0
- package/dist/src/computer-access/companion/install-link.js +54 -0
- package/dist/src/computer-access/companion/native-messages.js +3 -0
- package/dist/src/computer-access/companion/native-session.d.ts +1 -0
- package/dist/src/computer-access/companion/native-session.js +14 -2
- package/dist/src/computer-access/companion/native-supervisor.js +1 -0
- package/dist/src/computer-access/companion/notification-windows.d.ts +1 -1
- package/dist/src/computer-access/companion/notification-windows.js +8 -3
- package/dist/src/computer-access/companion/protocol.d.ts +1 -1
- package/dist/src/computer-access/companion/protocol.js +6 -0
- package/dist/src/computer-access/companion/release-version.d.ts +1 -1
- package/dist/src/computer-access/companion/release-version.js +1 -1
- package/dist/src/computer-access/companion/windows-store/connection-error.d.ts +7 -0
- package/dist/src/computer-access/companion/windows-store/connection-error.js +19 -0
- package/dist/src/computer-access/companion/windows-store/connection-link.d.ts +13 -0
- package/dist/src/computer-access/companion/windows-store/connection-link.js +109 -0
- package/dist/src/computer-access/companion/windows-store/identity.d.ts +13 -0
- package/dist/src/computer-access/companion/windows-store/identity.js +13 -0
- package/dist/src/computer-access/companion/windows-store/lifecycle.d.ts +5 -0
- package/dist/src/computer-access/companion/windows-store/lifecycle.js +90 -0
- package/dist/src/computer-access/contracts.d.ts +1 -1
- package/dist/src/computer-access/handlers.d.ts +2 -1
- package/dist/src/computer-access/handlers.js +5 -1
- package/dist/src/computer-access/process-capture.d.ts +6 -0
- package/dist/src/computer-access/process-capture.js +1 -0
- package/dist/src/computer-access/process-result.d.ts +2 -0
- package/dist/src/computer-access/process-result.js +14 -6
- package/dist/src/computer-access/process-runner.d.ts +2 -1
- package/dist/src/computer-access/process-runner.js +21 -13
- package/dist/src/model-gateway/server/configuration.d.ts +2 -0
- package/dist/src/model-gateway/server/configuration.js +73 -21
- package/dist/src/plugin-contract/install-source.d.ts +13 -0
- package/dist/src/plugin-contract/install-source.js +99 -0
- package/dist/src/plugin-contract/manifest.d.ts +2 -1
- package/dist/src/plugin-sdk/computer-access.d.ts +8 -0
- package/dist/src/plugin-sdk/computer-access.js +5 -0
- package/dist/src/runtime/adapters/in-memory-session-store.js +6 -16
- package/dist/src/runtime/admin/config-control.js +2 -1
- package/dist/src/runtime/automations/catalog.d.ts +3 -0
- package/dist/src/runtime/automations/catalog.js +1 -0
- package/dist/src/runtime/automations/model-dependency-projection.d.ts +2 -0
- package/dist/src/runtime/automations/service.d.ts +2 -0
- package/dist/src/runtime/capabilities/automation-builder/authoring-reference.d.ts +10 -5
- package/dist/src/runtime/capabilities/automation-builder/authoring-reference.js +8 -7
- package/dist/src/runtime/capabilities/automation-builder/payload-instructions.d.ts +2 -2
- package/dist/src/runtime/capabilities/automation-builder/payload-instructions.js +2 -2
- package/dist/src/runtime/capabilities/automation-builder/tool-contract.d.ts +2 -2
- package/dist/src/runtime/capabilities/automations/authoring-catalog.js +1 -1
- package/dist/src/runtime/capabilities/automations/authoring-preparation.d.ts +11 -5
- package/dist/src/runtime/capabilities/automations/tool-module.js +1 -1
- package/dist/src/runtime/capabilities/request-permission-catalog.d.ts +3 -1
- package/dist/src/runtime/capabilities/request-permission-catalog.js +21 -2
- package/dist/src/runtime/capabilities/request-permission-tool-registry.d.ts +2 -1
- package/dist/src/runtime/capabilities/request-permission-tool-registry.js +18 -10
- package/dist/src/runtime/capabilities/request-runtime-tool-registry.d.ts +2 -0
- package/dist/src/runtime/capabilities/request-runtime-tool-registry.js +1 -1
- package/dist/src/runtime/capabilities/scheduling/create-operations.d.ts +6 -0
- package/dist/src/runtime/config/builders.js +6 -5
- package/dist/src/runtime/config/effective-model-config-validation.js +4 -35
- package/dist/src/runtime/config/fields.js +15 -0
- package/dist/src/runtime/config/model-context-capacity.d.ts +20 -0
- package/dist/src/runtime/config/model-context-capacity.js +55 -0
- package/dist/src/runtime/config/model-execution-policy.d.ts +5 -1
- package/dist/src/runtime/config/model-execution-policy.js +16 -0
- package/dist/src/runtime/config/model-plugin-config.d.ts +8 -0
- package/dist/src/runtime/config/model-plugin-config.js +40 -0
- package/dist/src/runtime/config/schema.js +5 -1
- package/dist/src/runtime/config/validation/model-profile-validation.js +2 -0
- package/dist/src/runtime/config/validation/runtime-config-validation-contract.d.ts +3 -1
- package/dist/src/runtime/config/validation/runtime-config-validation-contract.js +3 -1
- package/dist/src/runtime/config/validation/runtime-root-section-validation.js +11 -4
- package/dist/src/runtime/config/validation/web-ui-config-validation.js +3 -2
- package/dist/src/runtime/config/web-ui.d.ts +5 -0
- package/dist/src/runtime/config/web-ui.js +5 -0
- package/dist/src/runtime/config.js +2 -0
- package/dist/src/runtime/local-application.d.ts +2 -0
- package/dist/src/runtime/local-host/app-owner.js +50 -6
- package/dist/src/runtime/local-host/app-request-control.d.ts +3 -1
- package/dist/src/runtime/local-host/app-request-control.js +91 -11
- package/dist/src/runtime/local-host/client-requests.js +32 -5
- package/dist/src/runtime/local-host/client-services.d.ts +2 -0
- package/dist/src/runtime/local-host/local-request-diagnostics.d.ts +9 -0
- package/dist/src/runtime/local-host/local-request-diagnostics.js +47 -0
- package/dist/src/runtime/local-host/saved-approvals.js +23 -2
- package/dist/src/runtime/model/model-selection.js +4 -1
- package/dist/src/runtime/observability/request-control-diagnostics.d.ts +6 -0
- package/dist/src/runtime/observability/request-control-diagnostics.js +52 -0
- package/dist/src/runtime/plugins/configuration-context.d.ts +9 -0
- package/dist/src/runtime/plugins/configuration-context.js +42 -0
- package/dist/src/runtime/plugins/configuration-settings.d.ts +2 -0
- package/dist/src/runtime/plugins/configuration-settings.js +26 -0
- package/dist/src/runtime/plugins/configuration-store.d.ts +23 -0
- package/dist/src/runtime/plugins/configuration-store.js +100 -0
- package/dist/src/runtime/plugins/configuration-write.d.ts +5 -0
- package/dist/src/runtime/plugins/configuration-write.js +58 -0
- package/dist/src/runtime/plugins/installation/archive.d.ts +2 -0
- package/dist/src/runtime/plugins/installation/archive.js +107 -0
- package/dist/src/runtime/plugins/installation/github-download.d.ts +9 -0
- package/dist/src/runtime/plugins/installation/github-download.js +72 -0
- package/dist/src/runtime/plugins/installation/installed-package.d.ts +9 -0
- package/dist/src/runtime/plugins/installation/installed-package.js +66 -0
- package/dist/src/runtime/plugins/installation/package.d.ts +45 -0
- package/dist/src/runtime/plugins/installation/package.js +79 -0
- package/dist/src/runtime/plugins/installation/portable-path.d.ts +2 -0
- package/dist/src/runtime/plugins/installation/portable-path.js +10 -0
- package/dist/src/runtime/plugins/installation/publication.d.ts +10 -0
- package/dist/src/runtime/plugins/installation/publication.js +17 -0
- package/dist/src/runtime/plugins/installation/service.d.ts +41 -0
- package/dist/src/runtime/plugins/installation/service.js +80 -0
- package/dist/src/runtime/plugins/loader.js +15 -29
- package/dist/src/runtime/plugins/manifest-projection.js +1 -0
- package/dist/src/runtime/plugins/manifest-validator.js +3 -0
- package/dist/src/runtime/plugins/module-cache.d.ts +2 -0
- package/dist/src/runtime/plugins/module-cache.js +19 -0
- package/dist/src/runtime/plugins/selection.d.ts +2 -0
- package/dist/src/runtime/plugins/selection.js +16 -11
- package/dist/src/runtime/ports.d.ts +6 -4
- package/dist/src/runtime/request/dependencies.d.ts +2 -1
- package/dist/src/runtime/request/execution-payload-compacted-evidence.d.ts +1 -1
- package/dist/src/runtime/request/handler.js +8 -0
- package/dist/src/runtime/request/prepared-execution.js +6 -1
- package/dist/src/runtime/request/request-steering.d.ts +4 -0
- package/dist/src/runtime/request/request-steering.js +37 -12
- package/dist/src/runtime/request/worker-capability-composition.d.ts +2 -0
- package/dist/src/runtime/request/worker-capability-composition.js +4 -1
- package/dist/src/runtime/scheduler/journal-index-state.d.ts +1 -1
- package/dist/src/sessions/assistant-initiative-message.d.ts +3 -0
- package/dist/src/sessions/assistant-initiative-message.js +12 -0
- package/dist/src/sessions/assistant-initiative.d.ts +2 -2
- package/dist/src/sessions/assistant-initiative.js +1 -7
- package/dist/src/sessions/durable-session-commit.d.ts +2 -1
- package/dist/src/sessions/durable-session-commit.js +6 -1
- package/dist/src/sessions/metadata/projection.d.ts +15 -0
- package/dist/src/sessions/metadata/projection.js +55 -0
- package/dist/src/sessions/metadata/publication.d.ts +12 -0
- package/dist/src/sessions/metadata/publication.js +78 -0
- package/dist/src/sessions/metadata/source-receipt.d.ts +5 -0
- package/dist/src/sessions/metadata/source-receipt.js +42 -0
- package/dist/src/sessions/metadata/store.d.ts +7 -0
- package/dist/src/sessions/metadata/store.js +119 -0
- package/dist/src/sessions/record/projection.d.ts +3 -1
- package/dist/src/sessions/record/projection.js +26 -18
- package/dist/src/sessions/request-lifecycle/service.js +3 -3
- package/dist/src/sessions/session-service.d.ts +2 -4
- package/dist/src/sessions/session-service.js +4 -16
- package/dist/src/sessions/session-store.d.ts +2 -1
- package/dist/src/sessions/session-store.js +9 -3
- package/dist/src/sessions/snapshot.d.ts +17 -0
- package/dist/src/sessions/snapshot.js +105 -0
- package/dist/src/sessions/types.d.ts +2 -0
- package/dist/src/shared/tool-selection.d.ts +2 -0
- package/dist/src/shared/tool-selection.js +7 -0
- package/dist/src/web-ui/app/ARCHITECTURE.md +14 -0
- package/dist/src/web-ui/app/app.js +6 -3
- package/dist/src/web-ui/app/components/config-workspace/config-model.js +2 -0
- package/dist/src/web-ui/app/components/config-workspace/model-plugin-permissions.js +130 -0
- package/dist/src/web-ui/app/components/config-workspace/model-plugin-selection.js +180 -0
- package/dist/src/web-ui/app/components/config-workspace/model-plugin-view-state.js +114 -0
- package/dist/src/web-ui/app/components/config-workspace/model-rendering.js +3 -0
- package/dist/src/web-ui/app/components/config-workspace/model-summary.js +39 -0
- package/dist/src/web-ui/app/components/config-workspace/summary-rendering.js +30 -0
- package/dist/src/web-ui/app/components/config-workspace/workspace-events.js +37 -0
- package/dist/src/web-ui/app/components/config-workspace/workspace-mutations.js +2 -0
- package/dist/src/web-ui/app/components/config-workspace/workspace-persistence.js +9 -1
- package/dist/src/web-ui/app/components/config-workspace/workspace-view.js +23 -67
- package/dist/src/web-ui/app/components/config-workspace.js +11 -2
- package/dist/src/web-ui/app/components/conversation-view.js +36 -5
- package/dist/src/web-ui/app/components/dashboard/recent-conversations.js +2 -1
- package/dist/src/web-ui/app/components/dashboard/workspace.js +2 -1
- package/dist/src/web-ui/app/components/operations-summary.js +105 -0
- package/dist/src/web-ui/app/components/passive-learning/home.js +1 -9
- package/dist/src/web-ui/app/components/plugins/configuration-draft.js +34 -0
- package/dist/src/web-ui/app/components/plugins/configuration-editor.js +147 -0
- package/dist/src/web-ui/app/components/plugins/configuration-fields.js +103 -0
- package/dist/src/web-ui/app/components/plugins/configuration-retained-secrets.js +20 -0
- package/dist/src/web-ui/app/components/plugins/configuration-settings.js +108 -0
- package/dist/src/web-ui/app/components/plugins/discovery-rendering.js +37 -0
- package/dist/src/web-ui/app/components/plugins/installation.js +212 -0
- package/dist/src/web-ui/app/components/plugins/manager.js +160 -6
- package/dist/src/web-ui/app/components/plugins/removal.js +130 -0
- package/dist/src/web-ui/app/components/plugins/rendering.js +14 -2
- package/dist/src/web-ui/app/components/plugins/summary.js +54 -0
- package/dist/src/web-ui/app/components/plugins/tabs.js +31 -0
- package/dist/src/web-ui/app/components/plugins/view-state.js +3 -1
- package/dist/src/web-ui/app/components/runtime-setup/connection-form.js +5 -2
- package/dist/src/web-ui/app/components/runtime-setup/connection-state.js +9 -1
- package/dist/src/web-ui/app/components/runtime-setup/context-window-feedback.js +71 -0
- package/dist/src/web-ui/app/components/runtime-setup/optional-steps.js +2 -0
- package/dist/src/web-ui/app/components/runtime-setup-guide.js +15 -3
- package/dist/src/web-ui/app/components/spark-chat/empty-state.js +1 -0
- package/dist/src/web-ui/app/components/spark-chat/panel.js +1 -0
- package/dist/src/web-ui/app/components/system-host/connection-card.js +35 -0
- package/dist/src/web-ui/app/components/system-host/macos-setup.js +1 -1
- package/dist/src/web-ui/app/components/system-host/manager.js +45 -12
- package/dist/src/web-ui/app/components/system-host/rendering.js +111 -106
- package/dist/src/web-ui/app/components/system-host/windows-store-setup.js +293 -0
- package/dist/src/web-ui/app/components/workspace-shell.js +6 -0
- package/dist/src/web-ui/app/computer-access-feature.js +22 -5
- package/dist/src/web-ui/app/configuration-feature.js +35 -2
- package/dist/src/web-ui/app/controllers/app-event-bindings.js +4 -1
- package/dist/src/web-ui/app/controllers/conversation-read-state-controller.d.ts +1 -0
- package/dist/src/web-ui/app/controllers/conversation-read-state-controller.js +7 -3
- package/dist/src/web-ui/app/controllers/conversation-request-hydration.js +88 -0
- package/dist/src/web-ui/app/controllers/conversation-session-controller.d.ts +9 -3
- package/dist/src/web-ui/app/controllers/conversation-session-controller.js +52 -144
- package/dist/src/web-ui/app/controllers/history-pagination.js +111 -0
- package/dist/src/web-ui/app/controllers/operations-controller.d.ts +12 -0
- package/dist/src/web-ui/app/controllers/operations-controller.js +28 -21
- package/dist/src/web-ui/app/controllers/runtime-onboarding-controller.d.ts +1 -0
- package/dist/src/web-ui/app/controllers/runtime-onboarding-controller.js +11 -0
- package/dist/src/web-ui/app/controllers/session-controller.js +10 -2
- package/dist/src/web-ui/app/controllers/session-list-pagination.js +71 -0
- package/dist/src/web-ui/app/controllers/session-sidebar-controller.js +6 -4
- package/dist/src/web-ui/app/controllers/spark-chat-reading.js +1 -0
- package/dist/src/web-ui/app/controllers/spark-chat-sync.js +24 -5
- package/dist/src/web-ui/app/controllers/workspace-route-controller.js +21 -19
- package/dist/src/web-ui/app/dashboard-feature.js +2 -2
- package/dist/src/web-ui/app/index.html +6 -2
- package/dist/src/web-ui/app/lib/history-page-messages.js +49 -0
- package/dist/src/web-ui/app/lib/request-lifecycle-view.js +8 -0
- package/dist/src/web-ui/app/lib/workspace-route.d.ts +3 -0
- package/dist/src/web-ui/app/lib/workspace-route.js +4 -0
- package/dist/src/web-ui/app/passive-learning-feature.js +0 -1
- package/dist/src/web-ui/app/runtime-onboarding-feature.js +3 -0
- package/dist/src/web-ui/app/schedules-feature.js +1 -1
- package/dist/src/web-ui/app/services/runtime-web-client/configuration.js +20 -0
- package/dist/src/web-ui/app/services/runtime-web-client/plugin-configuration.js +19 -0
- package/dist/src/web-ui/app/services/runtime-web-client/spark-chat.js +4 -4
- 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 +6 -1
- package/dist/src/web-ui/app/services/runtime-web-client.js +12 -3
- package/dist/src/web-ui/app/spark-chat-feature.js +76 -19
- package/dist/src/web-ui/app/styles/11-product-links.css +30 -0
- package/dist/src/web-ui/app/styles/41-plugin-configuration.css +79 -0
- package/dist/src/web-ui/app/styles/41-plugin-discovery.css +132 -0
- package/dist/src/web-ui/app/styles/41-plugin-management.css +6 -0
- package/dist/src/web-ui/app/styles/42-model-plugin-permissions.css +173 -0
- package/dist/src/web-ui/app/styles/46-system-host.css +61 -107
- package/dist/src/web-ui/app/styles/47-config-controls.css +13 -1
- package/dist/src/web-ui/app/styles/54-spark-chat.css +33 -1
- package/dist/src/web-ui/app/styles.css +4 -0
- package/dist/src/web-ui/local-runtime/api-router.js +11 -6
- package/dist/src/web-ui/local-runtime/approval-request-attachment.js +14 -5
- package/dist/src/web-ui/local-runtime/configuration-activation-source.d.ts +1 -1
- package/dist/src/web-ui/local-runtime/configuration-activation-source.js +9 -3
- package/dist/src/web-ui/local-runtime/contracts.d.ts +4 -3
- package/dist/src/web-ui/local-runtime/environment-registry.d.ts +5 -1
- package/dist/src/web-ui/local-runtime/environment-registry.js +53 -11
- package/dist/src/web-ui/local-runtime/history-pagination.d.ts +16 -0
- package/dist/src/web-ui/local-runtime/history-pagination.js +20 -0
- package/dist/src/web-ui/local-runtime/plugin-configuration-routes.d.ts +16 -0
- package/dist/src/web-ui/local-runtime/plugin-configuration-routes.js +68 -0
- package/dist/src/web-ui/local-runtime/plugin-installation-routes.d.ts +16 -0
- package/dist/src/web-ui/local-runtime/plugin-installation-routes.js +96 -0
- package/dist/src/web-ui/local-runtime/plugin-management-routes.d.ts +8 -1
- package/dist/src/web-ui/local-runtime/plugin-management-routes.js +17 -0
- package/dist/src/web-ui/local-runtime/plugin-mutation-admission.d.ts +7 -0
- package/dist/src/web-ui/local-runtime/plugin-mutation-admission.js +17 -0
- package/dist/src/web-ui/local-runtime/plugin-removal-routes.d.ts +18 -0
- package/dist/src/web-ui/local-runtime/plugin-removal-routes.js +60 -0
- package/dist/src/web-ui/local-runtime/realtime-controller.js +41 -2
- package/dist/src/web-ui/local-runtime/request-cancellation-route.js +28 -1
- package/dist/src/web-ui/local-runtime/request-control-observation.d.ts +19 -0
- package/dist/src/web-ui/local-runtime/request-control-observation.js +80 -0
- package/dist/src/web-ui/local-runtime/request-execution.js +69 -37
- package/dist/src/web-ui/local-runtime/runtime-setup-context-window.d.ts +20 -0
- package/dist/src/web-ui/local-runtime/runtime-setup-context-window.js +44 -0
- package/dist/src/web-ui/local-runtime/runtime-setup-routes.js +2 -0
- package/dist/src/web-ui/local-runtime/runtime-setup-validation.js +9 -2
- package/dist/src/web-ui/local-runtime/session-routes.d.ts +1 -0
- package/dist/src/web-ui/local-runtime/session-routes.js +16 -4
- package/dist/src/web-ui/local-runtime/spark-chat-routes.js +4 -3
- package/dist/src/web-ui/plugin-capability-selection.js +4 -1
- package/dist/src/web-ui/plugin-configuration-input.d.ts +12 -0
- package/dist/src/web-ui/plugin-configuration-input.js +68 -0
- package/dist/src/web-ui/plugin-configuration-retained-secrets.d.ts +9 -0
- package/dist/src/web-ui/plugin-configuration-retained-secrets.js +48 -0
- package/dist/src/web-ui/plugin-configuration-service.d.ts +52 -0
- package/dist/src/web-ui/plugin-configuration-service.js +66 -0
- package/dist/src/web-ui/plugin-configuration-view.d.ts +25 -0
- package/dist/src/web-ui/plugin-configuration-view.js +45 -0
- package/dist/src/web-ui/plugin-disabled-selection.d.ts +7 -0
- package/dist/src/web-ui/plugin-disabled-selection.js +17 -0
- package/dist/src/web-ui/plugin-management-catalog.d.ts +3 -1
- package/dist/src/web-ui/plugin-management-catalog.js +11 -1
- package/dist/src/web-ui/plugin-management-selection.js +22 -9
- package/dist/src/web-ui/plugin-management-service.d.ts +5 -1
- package/dist/src/web-ui/plugin-management-service.js +11 -7
- package/dist/src/web-ui/plugin-removal-error.d.ts +7 -0
- package/dist/src/web-ui/plugin-removal-error.js +16 -0
- package/dist/src/web-ui/plugin-removal-service.d.ts +30 -0
- package/dist/src/web-ui/plugin-removal-service.js +109 -0
- package/dist/src/web-ui/runtime-setup-gateway.d.ts +6 -2
- package/dist/src/web-ui/runtime-setup-gateway.js +30 -10
- package/dist/src/web-ui/server.js +6 -2
- package/dist/src/web-ui/session-read-state/overview.d.ts +42 -0
- package/dist/src/web-ui/session-read-state/overview.js +16 -0
- package/dist/src/web-ui/session-read-state/pagination.d.ts +15 -0
- package/dist/src/web-ui/session-read-state/pagination.js +42 -0
- package/dist/src/web-ui/session-read-state/projection.d.ts +4 -3
- package/dist/src/web-ui/session-read-state/service.d.ts +213 -20
- package/dist/src/web-ui/session-read-state/service.js +25 -23
- package/dist/src/web-ui/session-read-state/visible-messages.d.ts +3 -3
- package/dist/src/web-ui/system-host-setup/companion-linux.js +1 -1
- package/dist/src/web-ui/system-host-setup/installer-contract.d.ts +1 -1
- package/dist/src/web-ui/system-host-setup/installer-contract.js +2 -2
- package/dist/src/web-ui/system-host-setup/installers.js +0 -7
- package/dist/src/web-ui/system-host-setup/local-connection.d.ts +4 -1
- package/dist/src/web-ui/system-host-setup/local-connection.js +10 -17
- package/dist/src/web-ui/system-host-setup/routes.d.ts +2 -0
- package/dist/src/web-ui/system-host-setup/routes.js +32 -9
- package/dist/src/web-ui/system-host-setup/setup-mutation.d.ts +9 -0
- package/dist/src/web-ui/system-host-setup/setup-mutation.js +27 -0
- package/dist/src/web-ui/system-host-setup/windows-store-route.d.ts +13 -0
- package/dist/src/web-ui/system-host-setup/windows-store-route.js +68 -0
- package/docs/configuration.md +46 -0
- package/docs/installation.md +45 -24
- package/docs/plugins.md +165 -2
- package/docs/projects-and-full-plus.md +2 -6
- package/docs/runtime-library.md +0 -1
- package/docs/windows-companion-store.md +127 -0
- package/package.json +3 -3
- package/plugins/document-reader/plugin.json +1 -0
- package/plugins/exec/plugin.json +3 -0
- package/plugins/filesystem/plugin.json +2 -0
- package/plugins/local-search/plugin.json +1 -0
- package/plugins/system/README.md +43 -3
- package/plugins/system/plugin.json +5 -0
- package/plugins/system/source/companion-command-output.ts +82 -0
- package/plugins/system/source/host-dispatch.ts +4 -0
- package/plugins/system/source/index.ts +11 -5
- package/plugins/system/source/local-command-output.ts +61 -0
- package/plugins/system/source/request-system-modules.ts +2 -0
- package/plugins/system/src/index.cjs +474 -39
- package/plugins/web/README.md +2 -2
- package/plugins/web/plugin.json +4 -0
- package/runtime.config.schema.json +25 -1
- package/src/runtime/README.md +12 -2
- package/dist/src/web-ui/system-host-setup/companion-windows.d.ts +0 -2
- package/dist/src/web-ui/system-host-setup/companion-windows.js +0 -108
- package/docs/publishing.md +0 -167
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createModelPluginViewState } from "./config-workspace/model-plugin-view-state.js";
|
|
1
2
|
import { createConfigCalibrationDisclosure } from "./config-workspace/calibration-disclosure.js";
|
|
2
3
|
import { createConfigDashboardRendering } from "./config-workspace/dashboard-rendering.js";
|
|
3
4
|
import { createConfigFieldRendering } from "./config-workspace/field-rendering.js";
|
|
@@ -22,10 +23,12 @@ export {
|
|
|
22
23
|
export function createConfigWorkspace({
|
|
23
24
|
dom,
|
|
24
25
|
loadDashboard,
|
|
26
|
+
loadModelPlugins,
|
|
25
27
|
saveFile,
|
|
26
28
|
memorySetup,
|
|
27
29
|
memoryManagement,
|
|
28
30
|
pluginManagement,
|
|
31
|
+
getOperationsSummary,
|
|
29
32
|
onAddModel,
|
|
30
33
|
onRemoveModel,
|
|
31
34
|
onNavigationChange = () => {},
|
|
@@ -35,6 +38,7 @@ export function createConfigWorkspace({
|
|
|
35
38
|
}) {
|
|
36
39
|
const workspaceModel = createConfigWorkspaceModel();
|
|
37
40
|
const { state } = workspaceModel;
|
|
41
|
+
const modelPluginViewState = createModelPluginViewState(dom.configDashboard);
|
|
38
42
|
const calibrationDisclosure = createConfigCalibrationDisclosure({
|
|
39
43
|
state,
|
|
40
44
|
root: dom.configDashboard,
|
|
@@ -61,6 +65,7 @@ export function createConfigWorkspace({
|
|
|
61
65
|
});
|
|
62
66
|
|
|
63
67
|
const modelRendering = createConfigModelRendering({
|
|
68
|
+
modelPluginViewState,
|
|
64
69
|
state,
|
|
65
70
|
calibrationProfileLabel: fieldRendering.calibrationProfileLabel,
|
|
66
71
|
configFileKey: workspaceModel.configFileKey,
|
|
@@ -87,6 +92,7 @@ export function createConfigWorkspace({
|
|
|
87
92
|
});
|
|
88
93
|
|
|
89
94
|
const workspaceView = createConfigWorkspaceView({
|
|
95
|
+
modelPluginViewState,
|
|
90
96
|
onNavigationChange: () => {
|
|
91
97
|
navigationRevision += 1;
|
|
92
98
|
onNavigationChange();
|
|
@@ -95,11 +101,10 @@ export function createConfigWorkspace({
|
|
|
95
101
|
dom,
|
|
96
102
|
eventTarget,
|
|
97
103
|
pluginManagement,
|
|
104
|
+
getOperationsSummary,
|
|
98
105
|
configFileEntries: workspaceModel.configFileEntries,
|
|
99
106
|
configFileKey: workspaceModel.configFileKey,
|
|
100
|
-
countObjectKeys: fieldRendering.countObjectKeys,
|
|
101
107
|
dashboardIsBusy: workspaceModel.dashboardIsBusy,
|
|
102
|
-
dirtyFiles: workspaceModel.dirtyFiles,
|
|
103
108
|
ensureRawSelection: workspaceModel.ensureRawSelection,
|
|
104
109
|
fileStatusText: fieldRendering.fileStatusText,
|
|
105
110
|
hasPendingFileChanges: workspaceModel.hasPendingFileChanges,
|
|
@@ -115,6 +120,7 @@ export function createConfigWorkspace({
|
|
|
115
120
|
});
|
|
116
121
|
|
|
117
122
|
const workspaceMutations = createConfigWorkspaceMutations({
|
|
123
|
+
modelPluginViewState,
|
|
118
124
|
state,
|
|
119
125
|
dom,
|
|
120
126
|
confirmDiscard,
|
|
@@ -137,6 +143,7 @@ export function createConfigWorkspace({
|
|
|
137
143
|
state,
|
|
138
144
|
dom,
|
|
139
145
|
loadDashboard,
|
|
146
|
+
loadModelPlugins,
|
|
140
147
|
saveFile,
|
|
141
148
|
memorySetup,
|
|
142
149
|
memoryManagement,
|
|
@@ -160,6 +167,7 @@ export function createConfigWorkspace({
|
|
|
160
167
|
});
|
|
161
168
|
|
|
162
169
|
const workspaceEvents = createConfigWorkspaceEvents({
|
|
170
|
+
modelPluginViewState,
|
|
163
171
|
onAddModel,
|
|
164
172
|
onRemoveModel,
|
|
165
173
|
state,
|
|
@@ -190,6 +198,7 @@ export function createConfigWorkspace({
|
|
|
190
198
|
|
|
191
199
|
return {
|
|
192
200
|
activeCategory: () => state.activeCategory,
|
|
201
|
+
syncSummary: workspaceView.syncDashboardSummary,
|
|
193
202
|
setActive: calibrationDisclosure.setActive,
|
|
194
203
|
setWorkspace: (workspace) => {
|
|
195
204
|
const category = configurationCategoryForWorkspace(workspace);
|
|
@@ -81,6 +81,8 @@ export function createConversationView({
|
|
|
81
81
|
if (viewState.followMessages) scrollToEnd();
|
|
82
82
|
},
|
|
83
83
|
});
|
|
84
|
+
let historyPager;
|
|
85
|
+
let holdingPosition = false;
|
|
84
86
|
const viewState = {
|
|
85
87
|
followMessages: true,
|
|
86
88
|
messageRenderTimer: 0,
|
|
@@ -92,7 +94,7 @@ export function createConversationView({
|
|
|
92
94
|
function updateJumpToLatest() {
|
|
93
95
|
const hasOverflow =
|
|
94
96
|
dom.messagesList.scrollHeight > dom.messagesList.clientHeight + 24;
|
|
95
|
-
dom.jumpToLatestButton.hidden = viewState.followMessages || !hasOverflow;
|
|
97
|
+
dom.jumpToLatestButton.hidden = !historyPager?.hasNewer() && (viewState.followMessages || !hasOverflow);
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
function scrollToEnd() {
|
|
@@ -246,7 +248,7 @@ export function createConversationView({
|
|
|
246
248
|
);
|
|
247
249
|
const previousScrollTop = dom.messagesList.scrollTop;
|
|
248
250
|
const shouldFollow =
|
|
249
|
-
viewState.followMessages || isNearScrollEnd(dom.messagesList);
|
|
251
|
+
!holdingPosition && !historyPager?.hasNewer() && (viewState.followMessages || isNearScrollEnd(dom.messagesList));
|
|
250
252
|
const messages = preserveMessageHistory ? getMessages() : projectApprovalContinuations(getMessages());
|
|
251
253
|
conversationReasoning.beginRender(messages);
|
|
252
254
|
messageLinkPreviews.reset();
|
|
@@ -265,7 +267,12 @@ export function createConversationView({
|
|
|
265
267
|
for (const pendingApproval of getPendingApprovals()) {
|
|
266
268
|
dom.messagesList.appendChild(createApprovalCard(pendingApproval));
|
|
267
269
|
}
|
|
268
|
-
|
|
270
|
+
historyPager?.renderControls(dom.messagesList);
|
|
271
|
+
if (scrollBehavior) {
|
|
272
|
+
scrollBehavior.afterRender();
|
|
273
|
+
if (historyPager?.hasNewer()) dom.jumpToLatestButton.hidden = false;
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
269
276
|
if (shouldFollow) {
|
|
270
277
|
scrollToEnd();
|
|
271
278
|
} else {
|
|
@@ -303,7 +310,23 @@ export function createConversationView({
|
|
|
303
310
|
viewState.thinkingRenderTimer = 0;
|
|
304
311
|
}
|
|
305
312
|
|
|
313
|
+
function preserveScroll(change) {
|
|
314
|
+
const root = dom.messagesList;
|
|
315
|
+
const bounds = root.getBoundingClientRect();
|
|
316
|
+
const anchor = [...root.querySelectorAll("[data-message-id]")].find((node) => node.getBoundingClientRect().bottom > bounds.top);
|
|
317
|
+
const id = anchor?.dataset.messageId;
|
|
318
|
+
const offset = anchor?.getBoundingClientRect().top ?? 0;
|
|
319
|
+
const previousTop = root.scrollTop;
|
|
320
|
+
holdingPosition = true; viewState.followMessages = false; viewState.scrollSettleVersion += 1;
|
|
321
|
+
change();
|
|
322
|
+
const restored = [...root.querySelectorAll("[data-message-id]")].find((node) => node.dataset.messageId === id);
|
|
323
|
+
root.scrollTop = restored ? root.scrollTop + restored.getBoundingClientRect().top - offset : previousTop;
|
|
324
|
+
scrollBehavior?.preservePosition?.();
|
|
325
|
+
updateJumpToLatest();
|
|
326
|
+
}
|
|
327
|
+
|
|
306
328
|
function reset() {
|
|
329
|
+
holdingPosition = false;
|
|
307
330
|
filePreview.reset();
|
|
308
331
|
viewState.followMessages = true;
|
|
309
332
|
viewState.scrollSettleVersion += 1;
|
|
@@ -318,19 +341,27 @@ export function createConversationView({
|
|
|
318
341
|
messageLinkPreviews.reset();
|
|
319
342
|
}
|
|
320
343
|
|
|
344
|
+
function jumpToLatest() {
|
|
345
|
+
if (!historyPager?.hasNewer()) { scrollToEnd(); return; }
|
|
346
|
+
void historyPager.latest().then(scrollToEnd).catch(() => notify("Could not load latest messages", "failed"));
|
|
347
|
+
}
|
|
348
|
+
|
|
321
349
|
function bind() {
|
|
322
350
|
if (viewState.bound) return;
|
|
323
351
|
viewState.bound = true;
|
|
324
|
-
dom.jumpToLatestButton.addEventListener("click",
|
|
352
|
+
dom.jumpToLatestButton.addEventListener("click", jumpToLatest);
|
|
325
353
|
dom.messagesList.addEventListener("scroll", () => {
|
|
354
|
+
holdingPosition = false;
|
|
326
355
|
if (scrollBehavior) return;
|
|
327
|
-
viewState.followMessages = isNearScrollEnd(dom.messagesList);
|
|
356
|
+
viewState.followMessages = !historyPager?.hasNewer() && isNearScrollEnd(dom.messagesList);
|
|
328
357
|
if (!viewState.followMessages) viewState.scrollSettleVersion += 1;
|
|
329
358
|
updateJumpToLatest();
|
|
330
359
|
});
|
|
331
360
|
}
|
|
332
361
|
|
|
333
362
|
return {
|
|
363
|
+
preserveScroll,
|
|
364
|
+
setHistoryPager: (pager) => { historyPager = pager; },
|
|
334
365
|
setWorkspace: filePreview.setWorkspace,
|
|
335
366
|
closeFilePreview: filePreview.reset,
|
|
336
367
|
bind,
|
|
@@ -35,6 +35,7 @@ function unreadAvailabilityNotice({ conversations, hasUnavailableReadState }) {
|
|
|
35
35
|
|
|
36
36
|
export function renderDashboardConversations({
|
|
37
37
|
sessions = [],
|
|
38
|
+
overview,
|
|
38
39
|
loading = false,
|
|
39
40
|
error = "",
|
|
40
41
|
}) {
|
|
@@ -43,7 +44,7 @@ export function renderDashboardConversations({
|
|
|
43
44
|
recentConversations: conversations,
|
|
44
45
|
unreadCount,
|
|
45
46
|
hasUnavailableReadState,
|
|
46
|
-
} = projection;
|
|
47
|
+
} = { ...projection, ...(overview ? { unreadCount: overview.unreadCount, hasUnavailableReadState: overview.hasUnavailableReadState } : {}) };
|
|
47
48
|
const badge =
|
|
48
49
|
unreadCount > 0 && !hasUnavailableReadState
|
|
49
50
|
? `<span class="home-unread-count" aria-label="${unreadCount} unread messages">${unreadCount}</span>`
|
|
@@ -104,7 +104,8 @@ export function createDashboardWorkspace({ root, actions, passiveLearning }) {
|
|
|
104
104
|
updateLiveRegion(
|
|
105
105
|
conversations,
|
|
106
106
|
renderDashboardConversations({
|
|
107
|
-
sessions: snapshot.sessions,
|
|
107
|
+
sessions: snapshot.sessionOverview?.sessions ?? snapshot.sessions,
|
|
108
|
+
overview: snapshot.sessionOverview,
|
|
108
109
|
loading: snapshot.loadingSessions,
|
|
109
110
|
error: snapshot.sessionsError,
|
|
110
111
|
}),
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { formatTime, textOf } from "../lib/text-format.js";
|
|
2
|
+
import { getNumber } from "../lib/event-presentation.js";
|
|
3
|
+
|
|
4
|
+
export function formatDurationMs(value) {
|
|
5
|
+
const ms = typeof value === "number" ? value : Number(value);
|
|
6
|
+
if (!Number.isFinite(ms) || ms < 0) return "-";
|
|
7
|
+
const seconds = Math.round(ms / 1000);
|
|
8
|
+
if (seconds < 60) return `${seconds}s`;
|
|
9
|
+
const minutes = Math.round(seconds / 60);
|
|
10
|
+
if (minutes < 90) return `${minutes}m`;
|
|
11
|
+
const hours = Math.round(minutes / 60);
|
|
12
|
+
if (hours < 48) return `${hours}h`;
|
|
13
|
+
return `${Math.round(hours / 24)}d`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function latestHealthEvent(details) {
|
|
17
|
+
return [...details].sort(
|
|
18
|
+
(left, right) => getNumber(right.lastEventAt, 0) - getNumber(left.lastEventAt, 0),
|
|
19
|
+
)[0];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function unavailableReadValue(read, environmentId, environmentScoped) {
|
|
23
|
+
if (environmentScoped && read.environmentId !== environmentId) return "Not loaded";
|
|
24
|
+
if (read.phase === "loading") return "Loading…";
|
|
25
|
+
if (read.phase === "error") return "Unavailable";
|
|
26
|
+
if (read.phase !== "ready") return "Not loaded";
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function environmentValue(environmentId, source) {
|
|
31
|
+
const environment = textOf(environmentId) || "Current environment";
|
|
32
|
+
if (typeof source !== "string" || !source) return environment;
|
|
33
|
+
return `${environment} · ${source}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function runtimeSummary(read, environmentId) {
|
|
37
|
+
const unavailable = unavailableReadValue(read, environmentId, true);
|
|
38
|
+
const payload = unavailable ? {} : read.payload;
|
|
39
|
+
const status = payload.status || {};
|
|
40
|
+
const uptime = typeof status.uptimeMs === "number" ? formatDurationMs(status.uptimeMs) : "-";
|
|
41
|
+
return {
|
|
42
|
+
label: "Runtime · selected environment",
|
|
43
|
+
items: [
|
|
44
|
+
{ label: "Environment", value: environmentValue(environmentId, payload.source) },
|
|
45
|
+
{ label: "Uptime", value: unavailable || uptime, status: Boolean(unavailable) },
|
|
46
|
+
{ label: "PID", value: unavailable || textOf(status.pid, "-") || "-" },
|
|
47
|
+
{ label: "Node", value: unavailable || textOf(status.node?.version, "-") || "-" },
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function logFileAvailability(exists) {
|
|
53
|
+
if (exists === true) return "Available";
|
|
54
|
+
if (exists === false) return "Missing";
|
|
55
|
+
return "-";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function logsSummary(read, environmentId) {
|
|
59
|
+
const unavailable = unavailableReadValue(read, environmentId, true);
|
|
60
|
+
const log = unavailable ? {} : read.payload.log || {};
|
|
61
|
+
return {
|
|
62
|
+
label: "Logs · selected environment",
|
|
63
|
+
items: [
|
|
64
|
+
{ label: "Environment", value: environmentValue(environmentId) },
|
|
65
|
+
{ label: "Lines shown", value: unavailable || (Array.isArray(log.lines) ? String(log.lines.length) : "-"), status: Boolean(unavailable) },
|
|
66
|
+
{ label: "Last refreshed", value: unavailable || formatTime(read.refreshedAt) || "-" },
|
|
67
|
+
{ label: "Log file", value: unavailable || logFileAvailability(log.exists) },
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function healthValue(ok) {
|
|
73
|
+
if (ok === true) return "Healthy";
|
|
74
|
+
if (ok === false) return "Unhealthy";
|
|
75
|
+
return "-";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function activeStreamCount(payload) {
|
|
79
|
+
const count = payload.activeStreamingRequests;
|
|
80
|
+
if (typeof count === "number" && Number.isFinite(count) && count >= 0) return String(count);
|
|
81
|
+
if (Array.isArray(payload.activeStreamingRequestDetails)) return String(payload.activeStreamingRequestDetails.length);
|
|
82
|
+
return "-";
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function healthSummary(read) {
|
|
86
|
+
const unavailable = unavailableReadValue(read, undefined, false);
|
|
87
|
+
const payload = unavailable ? {} : read.payload;
|
|
88
|
+
const details = Array.isArray(payload.activeStreamingRequestDetails) ? payload.activeStreamingRequestDetails : [];
|
|
89
|
+
const latest = latestHealthEvent(details);
|
|
90
|
+
return {
|
|
91
|
+
label: "System health · all environments",
|
|
92
|
+
items: [
|
|
93
|
+
{ label: "Health · all environments", value: unavailable || healthValue(payload.ok), status: true },
|
|
94
|
+
{ label: "Runtime mode", value: unavailable || textOf(payload.agentMode, "-") || "-" },
|
|
95
|
+
{ label: "Active streams", value: unavailable || activeStreamCount(payload) },
|
|
96
|
+
{ label: "Latest event", value: unavailable || textOf(latest?.lastEventName || latest?.lastEventType, "-") || "-" },
|
|
97
|
+
],
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function projectOperationsSummary(tab, reads, environmentId) {
|
|
102
|
+
if (tab === "health") return healthSummary(reads.health);
|
|
103
|
+
if (tab === "logs") return logsSummary(reads.logs, environmentId);
|
|
104
|
+
return runtimeSummary(reads.runtime, environmentId);
|
|
105
|
+
}
|
|
@@ -3,7 +3,6 @@ import { agentMarkup, renderAgent } from "./agent-view.js";
|
|
|
3
3
|
import { createAgentMotion } from "./agent-motion.js";
|
|
4
4
|
import { learningFailurePresentation } from "./presentation.js";
|
|
5
5
|
import { homeActivityStartPatch, readActivityPermissions } from "./activity-controls.js";
|
|
6
|
-
import { computerUpdateNoticeMarkup, renderComputerUpdateNotice } from "./computer-update-notice.js";
|
|
7
6
|
import { macCollectionRestartNoticeMarkup, renderMacCollectionRestartNotice, handleMacCollectionRestartClick } from "./macos-collection-restart-notice.js";
|
|
8
7
|
|
|
9
8
|
function canStartHomeLearning(snapshot) {
|
|
@@ -33,7 +32,6 @@ export function createPassiveLearningHome({
|
|
|
33
32
|
actions,
|
|
34
33
|
openLearning,
|
|
35
34
|
openSetup = openLearning,
|
|
36
|
-
openComputerAccess = openSetup,
|
|
37
35
|
}) {
|
|
38
36
|
let root = null;
|
|
39
37
|
let renderedSnapshot = {};
|
|
@@ -45,7 +43,7 @@ export function createPassiveLearningHome({
|
|
|
45
43
|
root?.removeEventListener("click", handleClick);
|
|
46
44
|
root = nextRoot;
|
|
47
45
|
if (!root) return;
|
|
48
|
-
root.innerHTML = `${
|
|
46
|
+
root.innerHTML = `${macCollectionRestartNoticeMarkup()}
|
|
49
47
|
<div class="home-learning-agent">${agentMarkup({
|
|
50
48
|
compact: true,
|
|
51
49
|
actionMarkup: '<button type="button" class="home-text-button" data-learning-open>Open ABot Spark</button>',
|
|
@@ -57,11 +55,6 @@ export function createPassiveLearningHome({
|
|
|
57
55
|
|
|
58
56
|
function handleClick(event) {
|
|
59
57
|
if (handleMacCollectionRestartClick(root, event, actions)) return;
|
|
60
|
-
const update = event.target.closest("[data-learning-open-update]");
|
|
61
|
-
if (update && root.contains(update)) {
|
|
62
|
-
openComputerAccess();
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
58
|
const button = event.target.closest("[data-learning-open]");
|
|
66
59
|
if (!button || !root.contains(button) || button.disabled) return;
|
|
67
60
|
const snapshot = actions?.snapshot?.() ?? renderedSnapshot;
|
|
@@ -80,7 +73,6 @@ export function createPassiveLearningHome({
|
|
|
80
73
|
function render(snapshot) {
|
|
81
74
|
renderedSnapshot = snapshot;
|
|
82
75
|
if (!root) return;
|
|
83
|
-
renderComputerUpdateNotice(root, snapshot);
|
|
84
76
|
renderMacCollectionRestartNotice(root, snapshot);
|
|
85
77
|
renderAgent(root, snapshot);
|
|
86
78
|
motion?.update(snapshot);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { clearPluginSecretInputs } from "./configuration-fields.js";
|
|
2
|
+
|
|
3
|
+
/** Keep the actual controls mounted; never copy entered passwords into state. */
|
|
4
|
+
export function createPluginConfigurationDraft() {
|
|
5
|
+
let fields = null;
|
|
6
|
+
let owner = null;
|
|
7
|
+
function clear() {
|
|
8
|
+
clearPluginSecretInputs(fields);
|
|
9
|
+
fields = null;
|
|
10
|
+
owner = null;
|
|
11
|
+
}
|
|
12
|
+
function capture(root, review, busy) {
|
|
13
|
+
if (busy || !review || owner !== review) {
|
|
14
|
+
clear();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
fields =
|
|
18
|
+
root?.querySelector("[data-plugin-configuration-fields]") || fields;
|
|
19
|
+
}
|
|
20
|
+
function restore(root, review, busy) {
|
|
21
|
+
if (busy || !review) {
|
|
22
|
+
clear();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const replacement = root.querySelector(
|
|
26
|
+
"[data-plugin-configuration-fields]",
|
|
27
|
+
);
|
|
28
|
+
if (owner === review && fields && replacement)
|
|
29
|
+
replacement.replaceWith(fields);
|
|
30
|
+
fields = root.querySelector("[data-plugin-configuration-fields]");
|
|
31
|
+
owner = review;
|
|
32
|
+
}
|
|
33
|
+
return { capture, restore, clear };
|
|
34
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { escapeHtml } from "../../lib/text-format.js";
|
|
2
|
+
import {
|
|
3
|
+
bindPluginConfigurationFields,
|
|
4
|
+
clearPluginSecretInputs,
|
|
5
|
+
readPluginConfigurationFields,
|
|
6
|
+
renderPluginConfigurationFields,
|
|
7
|
+
} from "./configuration-fields.js";
|
|
8
|
+
|
|
9
|
+
/** A mounted dialog preserves password controls across dashboard rerenders. */
|
|
10
|
+
export function createPluginConfigurationEditor({
|
|
11
|
+
loadConfiguration,
|
|
12
|
+
saveConfiguration,
|
|
13
|
+
getEnvironmentId,
|
|
14
|
+
beginRuntimeMutation,
|
|
15
|
+
endRuntimeMutation,
|
|
16
|
+
onConfigurationSaved,
|
|
17
|
+
onClosed = () => {},
|
|
18
|
+
}) {
|
|
19
|
+
let dialog = null;
|
|
20
|
+
let busy = false;
|
|
21
|
+
let configuration = null;
|
|
22
|
+
let environment = "";
|
|
23
|
+
let generation = 0;
|
|
24
|
+
|
|
25
|
+
function close() {
|
|
26
|
+
if (busy || !dialog) return false;
|
|
27
|
+
generation += 1;
|
|
28
|
+
clearPluginSecretInputs(dialog);
|
|
29
|
+
dialog.close?.();
|
|
30
|
+
dialog.remove();
|
|
31
|
+
dialog = null;
|
|
32
|
+
configuration = null;
|
|
33
|
+
endRuntimeMutation();
|
|
34
|
+
onClosed();
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function message(text, failed = false) {
|
|
39
|
+
const status = dialog?.querySelector("[data-plugin-configuration-status]");
|
|
40
|
+
if (!status) return;
|
|
41
|
+
status.textContent = text;
|
|
42
|
+
status.className = failed ? "error-text" : "";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function setBusy(value) {
|
|
46
|
+
busy = value;
|
|
47
|
+
const fields = dialog?.querySelector("fieldset");
|
|
48
|
+
if (fields) fields.disabled = value;
|
|
49
|
+
for (const button of dialog?.querySelectorAll("button") || [])
|
|
50
|
+
button.disabled = value;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function save() {
|
|
54
|
+
if (busy || !configuration) return false;
|
|
55
|
+
if (environment !== getEnvironmentId()) return false;
|
|
56
|
+
let input;
|
|
57
|
+
try {
|
|
58
|
+
input = readPluginConfigurationFields(dialog, configuration);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
message(error.message, true);
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
setBusy(true);
|
|
64
|
+
message("Saving…");
|
|
65
|
+
try {
|
|
66
|
+
const result = await saveConfiguration(
|
|
67
|
+
configuration.pluginId,
|
|
68
|
+
input,
|
|
69
|
+
environment,
|
|
70
|
+
);
|
|
71
|
+
configuration = result.configuration;
|
|
72
|
+
onConfigurationSaved();
|
|
73
|
+
message(
|
|
74
|
+
"Saved. Close this form, then Apply changes to use these values.",
|
|
75
|
+
);
|
|
76
|
+
clearPluginSecretInputs(dialog);
|
|
77
|
+
const fields = dialog.querySelector("[data-plugin-configuration-body]");
|
|
78
|
+
fields.innerHTML = renderPluginConfigurationFields(configuration);
|
|
79
|
+
bindPluginConfigurationFields(fields.querySelector("fieldset"), () =>
|
|
80
|
+
message("Unsaved changes. Save to keep them."),
|
|
81
|
+
);
|
|
82
|
+
return true;
|
|
83
|
+
} catch (error) {
|
|
84
|
+
// Do not project transport payloads or an entered password into HTML or logs.
|
|
85
|
+
clearPluginSecretInputs(dialog);
|
|
86
|
+
message(
|
|
87
|
+
error.message || "Plugin configuration could not be saved.",
|
|
88
|
+
true,
|
|
89
|
+
);
|
|
90
|
+
return false;
|
|
91
|
+
} finally {
|
|
92
|
+
input = undefined;
|
|
93
|
+
setBusy(false);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function open(pluginId, root) {
|
|
98
|
+
if (dialog || !root?.ownerDocument || !loadConfiguration) return false;
|
|
99
|
+
if (!beginRuntimeMutation("plugin configuration")) return false;
|
|
100
|
+
environment = getEnvironmentId();
|
|
101
|
+
const request = ++generation;
|
|
102
|
+
dialog = root.ownerDocument.createElement("dialog");
|
|
103
|
+
dialog.className = "plugin-configuration-dialog";
|
|
104
|
+
dialog.setAttribute("aria-label", `Configure ${pluginId}`);
|
|
105
|
+
dialog.innerHTML = `<form><h2 tabindex="-1" autofocus>Configure ${escapeHtml(pluginId)}</h2><div data-plugin-configuration-body></div><p data-plugin-configuration-status role="status" aria-live="polite">Loading…</p><div class="plugin-configuration-actions"><button type="button" data-plugin-configuration-close>Close</button><button type="submit" class="primary-button">Save changes</button></div></form>`;
|
|
106
|
+
root.ownerDocument.body.append(dialog);
|
|
107
|
+
dialog.querySelector("form").addEventListener("submit", (event) => {
|
|
108
|
+
event.preventDefault();
|
|
109
|
+
void save();
|
|
110
|
+
});
|
|
111
|
+
dialog
|
|
112
|
+
.querySelector("[data-plugin-configuration-close]")
|
|
113
|
+
.addEventListener("click", close);
|
|
114
|
+
dialog.addEventListener("cancel", (event) => {
|
|
115
|
+
event.preventDefault();
|
|
116
|
+
close();
|
|
117
|
+
});
|
|
118
|
+
dialog.showModal();
|
|
119
|
+
setBusy(true);
|
|
120
|
+
try {
|
|
121
|
+
const result = await loadConfiguration(pluginId, environment);
|
|
122
|
+
if (request !== generation || environment !== getEnvironmentId())
|
|
123
|
+
return false;
|
|
124
|
+
configuration = result.configuration;
|
|
125
|
+
const fields = dialog.querySelector("[data-plugin-configuration-body]");
|
|
126
|
+
fields.innerHTML = renderPluginConfigurationFields(configuration);
|
|
127
|
+
bindPluginConfigurationFields(fields.querySelector("fieldset"), () =>
|
|
128
|
+
message("Unsaved changes. Save to keep them."),
|
|
129
|
+
);
|
|
130
|
+
message(
|
|
131
|
+
"Changes take effect after Apply. Clearing a required key prevents the plugin from loading until it is configured again.",
|
|
132
|
+
);
|
|
133
|
+
return true;
|
|
134
|
+
} catch (error) {
|
|
135
|
+
message(
|
|
136
|
+
error.message || "Plugin configuration could not be loaded.",
|
|
137
|
+
true,
|
|
138
|
+
);
|
|
139
|
+
return false;
|
|
140
|
+
} finally {
|
|
141
|
+
setBusy(false);
|
|
142
|
+
if (environment !== getEnvironmentId()) close();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return { open, close, save, isOpen: () => Boolean(dialog) };
|
|
147
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import {
|
|
2
|
+
renderPluginSettings,
|
|
3
|
+
bindPluginSettingFields,
|
|
4
|
+
readPluginSettingOverrides,
|
|
5
|
+
} from "./configuration-settings.js";
|
|
6
|
+
import {
|
|
7
|
+
renderRetainedPluginSecrets,
|
|
8
|
+
readRetainedPluginSecretClears,
|
|
9
|
+
} from "./configuration-retained-secrets.js";
|
|
10
|
+
import { escapeAttribute, escapeHtml } from "../../lib/text-format.js";
|
|
11
|
+
|
|
12
|
+
function renderSecret(secret, index) {
|
|
13
|
+
return `<div class="plugin-secret-field">
|
|
14
|
+
<label><span>${escapeHtml(secret.name)}${secret.required ? " (required)" : ""}</span>
|
|
15
|
+
<small>${escapeHtml(secret.env)} · ${secret.configured ? "Configured" : "Not configured"}</small>
|
|
16
|
+
<select data-plugin-secret-action="${index}" aria-label="${escapeAttribute(`Action for ${secret.name}`)}"><option value="keep">Keep current value</option><option value="set">Replace value</option><option value="clear">Clear value</option></select>
|
|
17
|
+
</label>
|
|
18
|
+
<input type="password" data-plugin-secret-value="${index}" aria-label="${escapeAttribute(`New value for ${secret.name}`)}" autocomplete="new-password" disabled hidden>
|
|
19
|
+
</div>`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function renderPluginConfigurationFields(configuration, busy = false) {
|
|
23
|
+
if (!configuration) return "";
|
|
24
|
+
const entries = Object.entries(configuration.defaults || {});
|
|
25
|
+
const secrets = configuration.secrets || [];
|
|
26
|
+
const retained = configuration.retainedSecrets || [];
|
|
27
|
+
if (!entries.length && !secrets.length && !retained.length) return "";
|
|
28
|
+
return `<fieldset class="plugin-configuration-fields" data-plugin-configuration-fields ${busy ? "disabled" : ""}>
|
|
29
|
+
<legend>Configuration</legend>
|
|
30
|
+
<p>Shared across environments in this ABot installation. Saved values stay local and are retained when the plugin is removed.</p>
|
|
31
|
+
${renderPluginSettings(configuration)}
|
|
32
|
+
${secrets.map(renderSecret).join("")}
|
|
33
|
+
${renderRetainedPluginSecrets(retained)}
|
|
34
|
+
</fieldset>`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const boundFields = new WeakSet();
|
|
38
|
+
|
|
39
|
+
export function bindPluginConfigurationFields(root, onChange = () => {}) {
|
|
40
|
+
if (!root || boundFields.has(root)) return;
|
|
41
|
+
boundFields.add(root);
|
|
42
|
+
bindPluginSettingFields(root, onChange);
|
|
43
|
+
root?.addEventListener("input", onChange);
|
|
44
|
+
for (const select of root?.querySelectorAll("[data-plugin-secret-action]") ||
|
|
45
|
+
[]) {
|
|
46
|
+
select.addEventListener("change", () => {
|
|
47
|
+
const input = root.querySelector(
|
|
48
|
+
`[data-plugin-secret-value="${select.dataset.pluginSecretAction}"]`,
|
|
49
|
+
);
|
|
50
|
+
input.hidden = select.value !== "set";
|
|
51
|
+
input.disabled = select.value !== "set";
|
|
52
|
+
input.required = select.value === "set";
|
|
53
|
+
if (select.value !== "set") input.value = "";
|
|
54
|
+
onChange();
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Secrets exist only in password controls and the one outbound save payload. */
|
|
60
|
+
export function readPluginConfigurationFields(
|
|
61
|
+
root,
|
|
62
|
+
configuration,
|
|
63
|
+
requireSecrets = false,
|
|
64
|
+
) {
|
|
65
|
+
const settings = readPluginSettingOverrides(root, configuration);
|
|
66
|
+
const secrets = Object.create(null);
|
|
67
|
+
for (const [index, secret] of (configuration.secrets || []).entries()) {
|
|
68
|
+
const action =
|
|
69
|
+
root?.querySelector(`[data-plugin-secret-action="${index}"]`)?.value ||
|
|
70
|
+
"keep";
|
|
71
|
+
if (action === "set") {
|
|
72
|
+
const value = root.querySelector(
|
|
73
|
+
`[data-plugin-secret-value="${index}"]`,
|
|
74
|
+
).value;
|
|
75
|
+
if (!value.trim()) throw new Error(`Enter a value for ${secret.name}.`);
|
|
76
|
+
secrets[secret.name] = { action, value };
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (
|
|
80
|
+
requireSecrets &&
|
|
81
|
+
secret.required &&
|
|
82
|
+
(action === "clear" || !secret.configured)
|
|
83
|
+
)
|
|
84
|
+
throw new Error(`Configure ${secret.name} before installing.`);
|
|
85
|
+
if (action === "clear") secrets[secret.name] = { action };
|
|
86
|
+
}
|
|
87
|
+
const clearRetainedSecrets = readRetainedPluginSecretClears(
|
|
88
|
+
root,
|
|
89
|
+
configuration.retainedSecrets,
|
|
90
|
+
);
|
|
91
|
+
return {
|
|
92
|
+
revision: configuration.revision,
|
|
93
|
+
settings,
|
|
94
|
+
secrets,
|
|
95
|
+
...(clearRetainedSecrets.length ? { clearRetainedSecrets } : {}),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function clearPluginSecretInputs(root) {
|
|
100
|
+
for (const input of root?.querySelectorAll("[data-plugin-secret-value]") ||
|
|
101
|
+
[])
|
|
102
|
+
input.value = "";
|
|
103
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { escapeHtml } from "../../lib/text-format.js";
|
|
2
|
+
|
|
3
|
+
export function renderRetainedPluginSecrets(secrets = []) {
|
|
4
|
+
if (!secrets.length) return "";
|
|
5
|
+
return `<section class="plugin-retained-secrets">
|
|
6
|
+
<h3>Keys no longer used by this plugin</h3>
|
|
7
|
+
<p>These saved keys stay on this device until you choose to delete them. Delete an old key before configuring a new key with the same name.</p>
|
|
8
|
+
${secrets.map((secret, index) => `<label class="plugin-setting-checkbox"><input type="checkbox" data-plugin-retained-secret="${index}"><span>Delete saved key <strong>${escapeHtml(secret.name)}</strong> <small>${escapeHtml(secret.env)}</small></span></label>`).join("")}
|
|
9
|
+
</section>`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function readRetainedPluginSecretClears(root, secrets = []) {
|
|
13
|
+
return secrets.flatMap((secret, index) => {
|
|
14
|
+
const input = root?.querySelector(
|
|
15
|
+
`[data-plugin-retained-secret="${index}"]`,
|
|
16
|
+
);
|
|
17
|
+
if (!input?.checked) return [];
|
|
18
|
+
return [{ name: secret.name, env: secret.env }];
|
|
19
|
+
});
|
|
20
|
+
}
|