@xopcai/xopc 0.0.302 → 0.0.306
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 +4 -4
- package/README.zh-CN.md +4 -4
- package/dist/browser-ext/dist/assets/{auth-B_9ZuGDx.js → auth-C3yV1y_l.js} +67 -22
- package/dist/browser-ext/dist/background.js +4 -4
- package/dist/browser-ext/dist/sidepanel.html +1 -1
- package/dist/browser-ext/dist/sidepanel.js +3 -3
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/xopc.extension.json +0 -3
- package/dist/extensions/telegram/xopc.extension.json +1 -4
- package/dist/extensions/weixin/xopc.extension.json +0 -3
- package/dist/gateway/static/root/assets/{activity-store-DCi5rh4e.js → activity-store-DLtim-_I.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-C0zP6W2B.js → agent-avatar-dicebear-iQXtiilH.js} +1 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CxOv4ivK.js +1 -0
- package/dist/gateway/static/root/assets/agents-DzKx7z3k.js +1 -0
- package/dist/gateway/static/root/assets/{api-CAV9PN9i.js → api-DfSU0-lD.js} +1 -1
- package/dist/gateway/static/root/assets/api-gpHh07OL.js +1 -0
- package/dist/gateway/static/root/assets/app-management-settings-panel-BpYFKz7B.js +1 -0
- package/dist/gateway/static/root/assets/{appearance-settings-ZFjV_opr.js → appearance-settings-BQfR5vrq.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-BceB7JHZ.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-MaKWrpgC.js → archive-plugin-BxOvZ-ZX.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-IfqbP2BN.js → attachment-load-B0FzTMAJ.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-CeI2NGSO.js → automations-page-BpXuPaPg.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-Cn_p8zY_.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-jvQ6FaBZ.js → binary-plugins-BP7wfpqy.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-D4ZIVQbk.css → block-editor-BdOTO0Yo.css} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-B7U3qlB3.js → block-editor-oMLvdnOQ.js} +3 -3
- package/dist/gateway/static/root/assets/{browser-automation-inputs-BGT0xoTv.js → browser-automation-inputs-DTxSZ00u.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page-DvLAwoiQ.js → browser-automations-page-IbJnwEY4.js} +2 -2
- package/dist/gateway/static/root/assets/browser-settings-page-CCUO3G23.js +3 -0
- package/dist/gateway/static/root/assets/button-CS04eWY9.js +1 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-BjMb5H2_.js +8 -0
- package/dist/gateway/static/root/assets/channels-settings-P22-_i13.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-C_icwbWj.js → channels-status-swr-D2AmAoty.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-BtL71IOs.js → chat-terminal-dock-B-yI3Mi1.js} +2 -2
- package/dist/gateway/static/root/assets/{computer-settings-page-Bu6ZJtmS.js → computer-settings-page-CWx_jnng.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-BLgPORmH.js +2 -0
- package/dist/gateway/static/root/assets/cron-expression-DMRRL4Zg.js +2 -0
- package/dist/gateway/static/root/assets/date-picker-BSwL0e6E.js +1 -0
- package/dist/gateway/static/root/assets/{dependency-picker-BNugauiZ.js → dependency-picker-BQTspLzC.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-DTy_3-OY.js → desktop-pet-C3lFxDF6.js} +1 -1
- package/dist/gateway/static/root/assets/desktop-pet-settings-Y8pjpXFE.js +1 -0
- package/dist/gateway/static/root/assets/device-pairing-wizard-DM4_GMzo.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-C3F7RiGW.js → extension-debug-page-CVGiGVcR.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-C0jhcCT_.js → extension-page-g3JtCP_y.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-CNvJQkrr.js → extension-settings-page-CjpoKV1f.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-D5AM8cyQ.js → gateway-config-swr-BSvXXpKM.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-realtime-BDCpS7U1.js +1 -0
- package/dist/gateway/static/root/assets/gateway-realtime-store-BGmP1obI.js +1 -0
- package/dist/gateway/static/root/assets/gateway-settings-CYG9WCZn.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-CSJWdnFs.js → gateway-startup-retry-Caf8g3sC.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-Cd1VJsHe.js → heartbeat-settings-Cl834-SS.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-CB_XVtIM.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-BNh604hw.js → image-generation-api-BwEWBUVC.js} +1 -1
- package/dist/gateway/static/root/assets/imports-page-CoMlgSIA.js +1 -0
- package/dist/gateway/static/root/assets/index-CI37dTAn.css +1 -0
- package/dist/gateway/static/root/assets/index-Do9MltC4.js +79 -0
- package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-CNq5D4pe.js +1 -0
- package/dist/gateway/static/root/assets/local-app-workbench-page-BxQlEje6.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-DyrFxW3G.js → local-apps-page-DQnRA598.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-DLK05Y1a.js → locale-store-D16nmbaN.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-CT5GrcMs.js +2 -0
- package/dist/gateway/static/root/assets/management-settings-DKcO5fQ-.js +1 -0
- package/dist/gateway/static/root/assets/{markdown-view-B8maDRWh.js → markdown-view-DCp4BlZP.js} +2 -2
- package/dist/gateway/static/root/assets/{media-plugins-5DakFba_.js → media-plugins-Cy64sn_C.js} +1 -1
- package/dist/gateway/static/root/assets/messages-C-9oo69N.js +3 -0
- package/dist/gateway/static/root/assets/note-detail-panel-5dc3LKTL.js +5 -0
- package/dist/gateway/static/root/assets/notes-page-AbwxgXuG.js +8 -0
- package/dist/gateway/static/root/assets/{page-tabs-DzJpglJJ.js → page-tabs-CgEoHSVT.js} +1 -1
- package/dist/gateway/static/root/assets/{popover-select-DldSX8GX.js → popover-select-9i-ZtHXL.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-Dj6LJsuQ.js → preview-open-alternatives-Ck2uKTbf.js} +1 -1
- package/dist/gateway/static/root/assets/{proactive-page-CwudBdrQ.js → proactive-page-Dr1mCJhZ.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-CujZXOea.js → product-open-page-DbZvJ5GE.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-DnE1zI1c.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-BD0nLYxk.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-BMFL4vis.js → registry-api-DcQdwpPu.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-TYuE6A3S.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DV554qyN.js → runtime-tools-settings-panel-CPwdgWKo.js} +2 -2
- package/dist/gateway/static/root/assets/{schema-form-Bh2Er67B.js → schema-form-8psK4cFO.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-BcWDQQFX.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-DzGQX6Hq.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-BsdM7P1d.js → settings-form-section-D_Gsz5rl.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-3yEAqoME.js → settings-page-C_Tj_mkZ.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-CE2X89qN.js +1 -0
- package/dist/gateway/static/root/assets/share-preview-page-B_M_oPsT.js +2 -0
- package/dist/gateway/static/root/assets/shares-settings-BL4H9Iym.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-WMKIgUOp.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-DYgwzl5B.js +2 -0
- package/dist/gateway/static/root/assets/{skills-page.utils-dHBD7YqU.js → skills-page.utils-Cuh6s2HM.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-lItR5Kah.js → system-settings-panel-aassGyNb.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-BjeRslap.js +1 -0
- package/dist/gateway/static/root/assets/theme-store-RUBQBsFP.js +1 -0
- package/dist/gateway/static/root/assets/tunnel-api-DJYcPWIV.js +1 -0
- package/dist/gateway/static/root/assets/{use-autosave-DO50_g_S.js → use-autosave-QGYG7oMZ.js} +1 -1
- package/dist/gateway/static/root/assets/user-model-page-PrRsd4go.js +2 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-k7tWLXzM.js → voice-api-key-field-D1s0gIRW.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-bZqN8-UF.js → voice-config-api-D2goEn5e.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-BHI6gO_u.js → work-discovery-overlay-DkFW9aJ6.js} +1 -1
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-BYToUPUY.js +3 -0
- package/dist/gateway/static/root/assets/workflows-page-Z8iZe9YP.js +6 -0
- package/dist/gateway/static/root/index.html +14 -12
- package/dist/package.js +1 -1
- package/dist/packages/gateway-contract/src/device-pairing.js +100 -7
- package/dist/packages/gateway-contract/src/gateway-scopes.js +53 -0
- package/dist/packages/gateway-contract/src/index.js +2 -0
- package/dist/packages/realtime-client/src/index.js +14 -2
- package/dist/packages/realtime-protocol/src/index.js +18 -14
- package/dist/src/agent/agent-instance-gateway.d.ts +2 -0
- package/dist/src/agent/agent-manager.d.ts +2 -0
- package/dist/src/agent/agent-manager.js +40 -12
- package/dist/src/agent/agent-scope.d.ts +4 -1
- package/dist/src/agent/agent-scope.js +19 -3
- package/dist/src/agent/commands/command-isolation.js +11 -9
- package/dist/src/agent/commands/command-registry.js +18 -33
- package/dist/src/agent/context/audit.js +12 -2
- package/dist/src/agent/context/coordinator.d.ts +13 -3
- package/dist/src/agent/context/coordinator.js +27 -11
- package/dist/src/agent/context/execution-context.js +42 -22
- package/dist/src/agent/context/execution-context.types.d.ts +4 -2
- package/dist/src/agent/context/execution-scope.d.ts +2 -2
- package/dist/src/agent/context/execution-scope.js +1 -1
- package/dist/src/agent/context/project-context.d.ts +2 -2
- package/dist/src/agent/context/project-context.js +3 -3
- package/dist/src/agent/embedded/run-for-session.d.ts +1 -0
- package/dist/src/agent/embedded/run-for-session.js +7 -1
- package/dist/src/agent/inbound/attachment-pipeline.d.ts +2 -0
- package/dist/src/agent/inbound/attachment-pipeline.js +3 -3
- package/dist/src/agent/inbound/inbound-loop.js +1 -0
- package/dist/src/agent/inbound/turn-dispatcher.js +3 -3
- package/dist/src/agent/mcp/mcp-stdio-transport.js +5 -2
- package/dist/src/agent/memory/compaction-promotion.js +7 -2
- package/dist/src/agent/memory/create-memory-manager.js +1 -0
- package/dist/src/agent/memory/manager.d.ts +6 -0
- package/dist/src/agent/memory/manager.js +74 -39
- package/dist/src/agent/memory/runtime.d.ts +3 -3
- package/dist/src/agent/memory/runtime.js +11 -4
- package/dist/src/agent/orchestration/agent-orchestrator.js +4 -1
- package/dist/src/agent/prompt/cache-boundary.d.ts +2 -0
- package/dist/src/agent/prompt/cache-boundary.js +10 -1
- package/dist/src/agent/service/build-direct-message-content.d.ts +1 -0
- package/dist/src/agent/service/build-direct-message-content.js +2 -1
- package/dist/src/agent/service/direct-turn-helpers.js +3 -2
- package/dist/src/agent/service/process-direct-streaming.d.ts +3 -1
- package/dist/src/agent/service/process-direct-streaming.js +3 -2
- package/dist/src/agent/service/webchat-tts.d.ts +0 -4
- package/dist/src/agent/service/webchat-tts.js +20 -19
- package/dist/src/agent/tools/factory.js +3 -3
- package/dist/src/agent/tools/knowledge-memory-tool.d.ts +2 -2
- package/dist/src/agent/tools/knowledge-memory-tool.js +7 -7
- package/dist/src/browser/native-messaging-host.js +2 -2
- package/dist/src/channels/attachments/voice-stt-webchat.d.ts +3 -0
- package/dist/src/channels/attachments/voice-stt-webchat.js +22 -9
- package/dist/src/cli/commands/agent.js +2 -0
- package/dist/src/cli/commands/config.js +8 -9
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +69 -44
- package/dist/src/cli/commands/extension-pack.js +0 -2
- package/dist/src/cli/commands/extension.js +4 -25
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/cli/commands/onboard/gateway.js +2 -1
- package/dist/src/cli/commands/update.js +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +5 -2
- package/dist/src/config/index.js +2 -2
- package/dist/src/config/loader.d.ts +1 -0
- package/dist/src/config/loader.js +14 -1
- package/dist/src/config/schema.d.ts +10 -3
- package/dist/src/config/schema.js +10 -2
- package/dist/src/execution-environments/local-worktree-manager.js +17 -15
- package/dist/src/execution-environments/store.js +4 -2
- package/dist/src/execution-environments/types.d.ts +3 -0
- package/dist/src/execution-environments/types.js +2 -1
- package/dist/src/execution-environments/worktree-safety.d.ts +8 -0
- package/dist/src/execution-environments/worktree-safety.js +43 -0
- package/dist/src/extensions/activation-planner.d.ts +1 -1
- package/dist/src/extensions/activation-planner.js +1 -1
- package/dist/src/extensions/api-version.d.ts +4 -0
- package/dist/src/extensions/api-version.js +15 -0
- package/dist/src/extensions/api.d.ts +3 -9
- package/dist/src/extensions/api.js +26 -32
- package/dist/src/extensions/config-validation.d.ts +8 -0
- package/dist/src/extensions/config-validation.js +25 -0
- package/dist/src/extensions/extension-registry-impl.d.ts +20 -9
- package/dist/src/extensions/extension-registry-impl.js +79 -11
- package/dist/src/extensions/hooks.d.ts +1 -1
- package/dist/src/extensions/index.d.ts +2 -1
- package/dist/src/extensions/install-transaction.d.ts +2 -0
- package/dist/src/extensions/install-transaction.js +32 -21
- package/dist/src/extensions/install.js +18 -1
- package/dist/src/extensions/loader.d.ts +5 -5
- package/dist/src/extensions/loader.js +109 -47
- package/dist/src/extensions/lockfile.d.ts +3 -5
- package/dist/src/extensions/lockfile.js +41 -14
- package/dist/src/extensions/normalize-manifest.js +6 -60
- package/dist/src/extensions/sdk/index.d.ts +3 -2
- package/dist/src/extensions/sdk/index.js +2 -2
- package/dist/src/extensions/sdk/testing.js +0 -4
- package/dist/src/extensions/security.js +5 -7
- package/dist/src/extensions/types/core.d.ts +0 -5
- package/dist/src/extensions/types/index.d.ts +1 -1
- package/dist/src/extensions/types/manifest.d.ts +1 -25
- package/dist/src/extensions/types/providers.d.ts +1 -1
- package/dist/src/extensions/types/registration.d.ts +0 -12
- package/dist/src/extensions/update.js +71 -30
- package/dist/src/gateway/heartbeat/service.js +2 -2
- package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -1
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +47 -10
- package/dist/src/gateway/hono/routes/devices.js +10 -7
- package/dist/src/gateway/hono/routes/endpoint-compatibility.js +6 -0
- package/dist/src/gateway/hono/routes/extension-gateway.js +0 -33
- package/dist/src/gateway/hono/routes/imports.js +1 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js +0 -1
- package/dist/src/gateway/hono/routes/local-apps.js +1 -1
- package/dist/src/gateway/hono/routes/realtime.js +30 -8
- package/dist/src/gateway/hono/routes/update.js +2 -2
- package/dist/src/gateway/hono/routes/user-model.js +25 -6
- package/dist/src/gateway/index.js +5 -2
- package/dist/src/gateway/lock.d.ts +2 -0
- package/dist/src/gateway/lock.js +31 -14
- package/dist/src/gateway/run-loop.js +3 -2
- package/dist/src/gateway/security/gateway-scopes.d.ts +2 -5
- package/dist/src/gateway/security/gateway-scopes.js +3 -45
- package/dist/src/gateway/security/index.js +2 -1
- package/dist/src/gateway/service/config-coordinator.js +1 -1
- package/dist/src/gateway/service.js +11 -7
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/imports/importService.d.ts +1 -1
- package/dist/src/imports/inventory.js +16 -2
- package/dist/src/imports/productImport.js +5 -5
- package/dist/src/imports/types.d.ts +3 -3
- package/dist/src/infra/exec.d.ts +2 -2
- package/dist/src/infra/exec.js +32 -27
- package/dist/src/infra/gateway-processes.js +1 -1
- package/dist/src/infra/run-command.js +15 -50
- package/dist/src/infra/update-restart.js +1 -1
- package/dist/src/infra/update-runner.js +2 -2
- package/dist/src/infra/update-startup.js +1 -1
- package/dist/src/knowledge/connected-knowledge-pipeline.js +13 -3
- package/dist/src/knowledge-memory/domain.d.ts +17 -1
- package/dist/src/knowledge-memory/index.js +2 -2
- package/dist/src/knowledge-memory/repository.d.ts +26 -4
- package/dist/src/knowledge-memory/repository.js +171 -36
- package/dist/src/mcp/channel-bridge.js +7 -3
- package/dist/src/media-understanding/registry.js +6 -1
- package/dist/src/migrations/knowledge-memory-read-policy-config.d.ts +2 -0
- package/dist/src/migrations/knowledge-memory-read-policy-config.js +48 -0
- package/dist/src/migrations/runner.js +2 -1
- package/dist/src/process/bounded-output.d.ts +10 -0
- package/dist/src/process/bounded-output.js +41 -0
- package/dist/src/process/kill-tree.d.ts +6 -17
- package/dist/src/process/kill-tree.js +43 -75
- package/dist/src/process/process-spec.d.ts +39 -0
- package/dist/src/process/process-spec.js +13 -0
- package/dist/src/process/run-process.d.ts +4 -0
- package/dist/src/process/run-process.js +97 -0
- package/dist/src/providers/plugin-registry.d.ts +1 -1
- package/dist/src/providers/plugin-registry.js +6 -0
- package/dist/src/realtime/runtime.js +3 -1
- package/dist/src/session/store.js +1 -1
- package/dist/src/storage/sqlite/device-pairing-approval.js +1 -1
- package/dist/src/storage/sqlite/index.d.ts +1 -1
- package/dist/src/storage/sqlite/index.js +2 -2
- package/dist/src/storage/sqlite/migrations/180_execution_environment_ownership.sql +7 -0
- package/dist/src/storage/sqlite/migrations/181_knowledge_item_status_events.sql +12 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/schema.sql +13 -0
- package/dist/src/storage/sqlite/transcript-repository.d.ts +4 -0
- package/dist/src/storage/sqlite/transcript-repository.js +36 -1
- package/dist/src/tui/backends/embedded-backend.d.ts +24 -8
- package/dist/src/tui/backends/embedded-backend.js +114 -10
- package/dist/src/tui/backends/gateway-realtime-backend.d.ts +18 -0
- package/dist/src/tui/backends/gateway-realtime-backend.js +32 -5
- package/dist/src/tui/components/assistant-message.d.ts +4 -1
- package/dist/src/tui/components/assistant-message.js +10 -2
- package/dist/src/tui/components/cell-render-mode.d.ts +4 -0
- package/dist/src/tui/components/cell-render-mode.js +1 -0
- package/dist/src/tui/components/chat-log.d.ts +17 -4
- package/dist/src/tui/components/chat-log.js +68 -50
- package/dist/src/tui/components/custom-editor.d.ts +2 -2
- package/dist/src/tui/components/custom-editor.js +5 -1
- package/dist/src/tui/components/pending-input-preview.d.ts +9 -0
- package/dist/src/tui/components/pending-input-preview.js +33 -0
- package/dist/src/tui/components/semantic-cell.d.ts +17 -0
- package/dist/src/tui/components/semantic-cell.js +29 -0
- package/dist/src/tui/components/tool-execution.d.ts +5 -1
- package/dist/src/tui/components/tool-execution.js +33 -10
- package/dist/src/tui/components/transcript-overlay.d.ts +29 -0
- package/dist/src/tui/components/transcript-overlay.js +114 -0
- package/dist/src/tui/components/tui-bottom-bar.js +3 -1
- package/dist/src/tui/components/user-message.d.ts +5 -1
- package/dist/src/tui/components/user-message.js +12 -1
- package/dist/src/tui/extension-host/load-extensions.d.ts +1 -1
- package/dist/src/tui/extension-host/runtime-context.js +2 -1
- package/dist/src/tui/extension-host/runtime.d.ts +1 -1
- package/dist/src/tui/format-tui-hotkeys.js +8 -1
- package/dist/src/tui/tui-agent-events.js +31 -0
- package/dist/src/tui/tui-backend.d.ts +23 -11
- package/dist/src/tui/tui-backend.js +1 -9
- package/dist/src/tui/tui-chat-input-state.d.ts +25 -0
- package/dist/src/tui/tui-chat-input-state.js +36 -0
- package/dist/src/tui/tui-command-formatters.js +2 -1
- package/dist/src/tui/tui-commands.js +1 -1
- package/dist/src/tui/tui-types.d.ts +2 -1
- package/dist/src/tui/tui-types.js +2 -1
- package/dist/src/tui/tui.js +122 -30
- package/dist/src/tui/xopc-tui-keybindings.d.ts +23 -3
- package/dist/src/tui/xopc-tui-keybindings.js +22 -2
- package/dist/src/user-context/access-policy.d.ts +2 -2
- package/dist/src/user-context/access-policy.js +10 -2
- package/dist/src/user-context/config.d.ts +23 -6
- package/dist/src/user-context/config.js +54 -7
- package/dist/src/voice/platform-streams.js +11 -1
- package/dist/src/voice/realtime/omniEngine.js +13 -1
- package/dist/src/voice/realtime/runtime.js +2 -1
- package/dist/src/voice/tts/audio.js +1 -1
- package/dist/src/voice/tts/speech-registry.js +6 -1
- package/package.json +9 -7
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-D0ITeUFb.js +0 -1
- package/dist/gateway/static/root/assets/agents-DcfWhk2S.js +0 -1
- package/dist/gateway/static/root/assets/api-fPapljyb.js +0 -1
- package/dist/gateway/static/root/assets/app-management-settings-panel-U3yDRzKF.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-FgMHY1Pr.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-DxaiBwrD.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-CHrfg3BX.js +0 -3
- package/dist/gateway/static/root/assets/button-CGlRPNzi.js +0 -1
- package/dist/gateway/static/root/assets/capabilities-settings-panel-DpYDPk_o.js +0 -8
- package/dist/gateway/static/root/assets/channels-settings-DMq-NBUQ.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-LsEiI9L5.js +0 -2
- package/dist/gateway/static/root/assets/cron-expression-B25FHn4w.js +0 -2
- package/dist/gateway/static/root/assets/date-picker-CzVHO7z9.js +0 -1
- package/dist/gateway/static/root/assets/desktop-pet-settings-CXfnejTb.js +0 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-CxKwfncn.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-CQTcIvlZ.js +0 -1
- package/dist/gateway/static/root/assets/home-page-B_uyfCGq.js +0 -1
- package/dist/gateway/static/root/assets/imports-page-DXNfRmk9.js +0 -1
- package/dist/gateway/static/root/assets/index-BAqVpc1H.css +0 -1
- package/dist/gateway/static/root/assets/index-hlU8MUEz.js +0 -79
- package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-CgW5_XVP.js +0 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-C4h3qDRL.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-Goy_QHfL.js +0 -2
- package/dist/gateway/static/root/assets/management-settings-DgQyGEpR.js +0 -1
- package/dist/gateway/static/root/assets/messages-C9h8SImu.js +0 -3
- package/dist/gateway/static/root/assets/note-detail-panel-lcZby9NY.js +0 -5
- package/dist/gateway/static/root/assets/notes-page-CDGPPI-W.js +0 -8
- package/dist/gateway/static/root/assets/project-detail-page-CyAf_sK-.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-BW5m_HhZ.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-B4JgwB0s.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-D5SmvlQ1.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-DDALROy_.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-BOHNZ-S3.js +0 -1
- package/dist/gateway/static/root/assets/share-preview-page-wV056nz2.js +0 -2
- package/dist/gateway/static/root/assets/shares-settings-io4NzfJL.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-CERFaxLj.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-CtwUqvsE.js +0 -2
- package/dist/gateway/static/root/assets/task-detail-page-CCKc67a-.js +0 -1
- package/dist/gateway/static/root/assets/theme-store-KfFEGMlp.js +0 -1
- package/dist/gateway/static/root/assets/tunnel-api-DPyLgmWw.js +0 -1
- package/dist/gateway/static/root/assets/user-model-page-CcnGgH1n.js +0 -2
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-jEMtNIG8.js +0 -3
- package/dist/gateway/static/root/assets/workflows-page-CX4bcAD-.js +0 -6
- package/dist/src/extensions/when-context.d.ts +0 -6
- package/dist/src/extensions/when-context.js +0 -26
- package/dist/src/extensions/when-expression.d.ts +0 -11
- package/dist/src/extensions/when-expression.js +0 -213
|
@@ -12,6 +12,13 @@ var ExtensionRegistryImpl = class {
|
|
|
12
12
|
gatewayMethods = /* @__PURE__ */ new Map();
|
|
13
13
|
tools = /* @__PURE__ */ new Map();
|
|
14
14
|
toolExtensionIds = /* @__PURE__ */ new Map();
|
|
15
|
+
hookOwners = /* @__PURE__ */ new Map();
|
|
16
|
+
hookPriorities = /* @__PURE__ */ new Map();
|
|
17
|
+
channelOwners = /* @__PURE__ */ new Map();
|
|
18
|
+
httpRouteOwners = /* @__PURE__ */ new Map();
|
|
19
|
+
commandOwners = /* @__PURE__ */ new Map();
|
|
20
|
+
serviceOwners = /* @__PURE__ */ new Map();
|
|
21
|
+
gatewayMethodOwners = /* @__PURE__ */ new Map();
|
|
15
22
|
channelPlugins = [];
|
|
16
23
|
cliRegistrations = [];
|
|
17
24
|
reloadRegistrations = [];
|
|
@@ -26,45 +33,106 @@ var ExtensionRegistryImpl = class {
|
|
|
26
33
|
getEnabledExtensions() {
|
|
27
34
|
return Array.from(this.extensions.values()).filter((p) => p.enabled);
|
|
28
35
|
}
|
|
29
|
-
addHook(event, handler,
|
|
36
|
+
addHook(event, handler, extensionId, priority = 0) {
|
|
30
37
|
if (!this.hooks.has(event)) this.hooks.set(event, []);
|
|
31
|
-
this.
|
|
38
|
+
const owners = this.hookOwners.get(event) ?? /* @__PURE__ */ new Map();
|
|
39
|
+
const priorities = this.hookPriorities.get(event) ?? /* @__PURE__ */ new Map();
|
|
40
|
+
owners.set(handler, extensionId);
|
|
41
|
+
priorities.set(handler, priority);
|
|
42
|
+
this.hookOwners.set(event, owners);
|
|
43
|
+
this.hookPriorities.set(event, priorities);
|
|
44
|
+
const handlers = this.hooks.get(event);
|
|
45
|
+
handlers.push(handler);
|
|
46
|
+
handlers.sort((left, right) => (priorities.get(right) ?? 0) - (priorities.get(left) ?? 0));
|
|
47
|
+
}
|
|
48
|
+
removeHook(event, handler) {
|
|
49
|
+
const handlers = this.hooks.get(event);
|
|
50
|
+
if (!handlers) return;
|
|
51
|
+
const next = handlers.filter((candidate) => candidate !== handler);
|
|
52
|
+
if (next.length > 0) this.hooks.set(event, next);
|
|
53
|
+
else this.hooks.delete(event);
|
|
54
|
+
const owners = this.hookOwners.get(event);
|
|
55
|
+
const priorities = this.hookPriorities.get(event);
|
|
56
|
+
owners?.delete(handler);
|
|
57
|
+
priorities?.delete(handler);
|
|
58
|
+
if (owners?.size === 0) this.hookOwners.delete(event);
|
|
59
|
+
if (priorities?.size === 0) this.hookPriorities.delete(event);
|
|
32
60
|
}
|
|
33
61
|
getHooks(event) {
|
|
34
62
|
return this.hooks.get(event) || [];
|
|
35
63
|
}
|
|
36
|
-
addChannelPlugin(plugin) {
|
|
64
|
+
addChannelPlugin(plugin, extensionId = "") {
|
|
37
65
|
this.channelPlugins = this.channelPlugins.filter((p) => p.id !== plugin.id);
|
|
38
66
|
this.channelPlugins.push(plugin);
|
|
67
|
+
this.channelOwners.set(plugin.id, extensionId);
|
|
39
68
|
}
|
|
40
|
-
addHttpRoute(path, handler) {
|
|
41
|
-
|
|
42
|
-
this.httpRoutes.
|
|
69
|
+
addHttpRoute(path, handler, extensionId = "") {
|
|
70
|
+
const key = this.httpRouteKey(extensionId, path);
|
|
71
|
+
if (this.httpRoutes.has(key)) log.warn({
|
|
72
|
+
extensionId,
|
|
73
|
+
path
|
|
74
|
+
}, `HTTP route already registered, overwriting`);
|
|
75
|
+
this.httpRoutes.set(key, handler);
|
|
76
|
+
this.httpRouteOwners.set(key, extensionId);
|
|
43
77
|
}
|
|
44
|
-
getHttpRoute(path) {
|
|
45
|
-
return this.httpRoutes.get(path);
|
|
78
|
+
getHttpRoute(extensionId, path) {
|
|
79
|
+
return this.httpRoutes.get(this.httpRouteKey(extensionId, path));
|
|
46
80
|
}
|
|
47
|
-
addCommand(command) {
|
|
81
|
+
addCommand(command, extensionId = "") {
|
|
48
82
|
if (this.commands.has(command.name)) log.warn({ command: command.name }, `Command already registered, overwriting`);
|
|
49
83
|
this.commands.set(command.name, command);
|
|
84
|
+
this.commandOwners.set(command.name, extensionId);
|
|
50
85
|
}
|
|
51
86
|
getCommand(name) {
|
|
52
87
|
return this.commands.get(name);
|
|
53
88
|
}
|
|
54
|
-
addService(service) {
|
|
89
|
+
addService(service, extensionId = "") {
|
|
55
90
|
if (this.services.has(service.id)) log.warn({ service: service.id }, `Service already registered, overwriting`);
|
|
56
91
|
this.services.set(service.id, service);
|
|
92
|
+
this.serviceOwners.set(service.id, extensionId);
|
|
57
93
|
}
|
|
58
94
|
getService(id) {
|
|
59
95
|
return this.services.get(id);
|
|
60
96
|
}
|
|
61
|
-
addGatewayMethod(method, handler) {
|
|
97
|
+
addGatewayMethod(method, handler, extensionId = "") {
|
|
62
98
|
if (this.gatewayMethods.has(method)) log.warn({ method }, `Gateway method already registered, overwriting`);
|
|
63
99
|
this.gatewayMethods.set(method, handler);
|
|
100
|
+
this.gatewayMethodOwners.set(method, extensionId);
|
|
64
101
|
}
|
|
65
102
|
getGatewayMethod(method) {
|
|
66
103
|
return this.gatewayMethods.get(method);
|
|
67
104
|
}
|
|
105
|
+
getServicesForExtension(extensionId) {
|
|
106
|
+
return [...this.services.entries()].filter(([id]) => this.serviceOwners.get(id) === extensionId).map(([, service]) => service);
|
|
107
|
+
}
|
|
108
|
+
removeExtensionContributions(extensionId) {
|
|
109
|
+
for (const [event, handlers] of this.hooks) for (const handler of [...handlers]) if (this.hookOwners.get(event)?.get(handler) === extensionId) this.removeHook(event, handler);
|
|
110
|
+
for (const [name, owner] of this.toolExtensionIds) if (owner === extensionId) this.removeTool(name);
|
|
111
|
+
this.channelPlugins = this.channelPlugins.filter((plugin) => {
|
|
112
|
+
const owned = this.channelOwners.get(plugin.id) === extensionId;
|
|
113
|
+
if (owned) this.channelOwners.delete(plugin.id);
|
|
114
|
+
return !owned;
|
|
115
|
+
});
|
|
116
|
+
this.removeOwnedEntries(this.httpRoutes, this.httpRouteOwners, extensionId);
|
|
117
|
+
this.removeOwnedEntries(this.commands, this.commandOwners, extensionId);
|
|
118
|
+
this.removeOwnedEntries(this.services, this.serviceOwners, extensionId);
|
|
119
|
+
this.removeOwnedEntries(this.gatewayMethods, this.gatewayMethodOwners, extensionId);
|
|
120
|
+
this.cliRegistrations = this.cliRegistrations.filter((entry) => entry.extensionId !== extensionId);
|
|
121
|
+
this.reloadRegistrations = this.reloadRegistrations.filter((entry) => entry.extensionId !== extensionId);
|
|
122
|
+
this.migrationRegistrations = this.migrationRegistrations.filter((entry) => entry.extensionId !== extensionId);
|
|
123
|
+
this.tuiRegistrations = this.tuiRegistrations.filter((entry) => entry.extensionId !== extensionId);
|
|
124
|
+
this.extensions.delete(extensionId);
|
|
125
|
+
}
|
|
126
|
+
removeOwnedEntries(values, owners, extensionId) {
|
|
127
|
+
for (const [key, owner] of owners) {
|
|
128
|
+
if (owner !== extensionId) continue;
|
|
129
|
+
owners.delete(key);
|
|
130
|
+
values.delete(key);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
httpRouteKey(extensionId, path) {
|
|
134
|
+
return `${extensionId}:${path.startsWith("/") ? path : `/${path}`}`;
|
|
135
|
+
}
|
|
68
136
|
addTool(tool, extensionId) {
|
|
69
137
|
if (this.tools.has(tool.name)) log.warn({ tool: tool.name }, `Tool already registered, overwriting`);
|
|
70
138
|
this.tools.set(tool.name, tool);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Extension Hook System
|
|
3
3
|
*/
|
|
4
4
|
import type { ExtensionHookEvent, HookAgentContext as HookContext, AgentMessage, BeforeAgentStartContext } from './types/hooks.js';
|
|
5
|
-
import { ExtensionRegistryImpl as ExtensionRegistry } from './
|
|
5
|
+
import { ExtensionRegistryImpl as ExtensionRegistry } from './extension-registry-impl.js';
|
|
6
6
|
export interface HookRunnerOptions {
|
|
7
7
|
catchErrors?: boolean;
|
|
8
8
|
logger?: HookLogger;
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export * from './types/index.js';
|
|
7
7
|
export { ExtensionApiImpl, createExtensionLogger, createPathResolver } from './api.js';
|
|
8
|
-
export { ExtensionRegistryImpl
|
|
8
|
+
export { ExtensionRegistryImpl } from './extension-registry-impl.js';
|
|
9
|
+
export { ExtensionLoader, normalizeExtensionConfig, resolveExtensionPath, areExtensionsGloballyDisabled } from './loader.js';
|
|
9
10
|
export type { ActivationPlanLoadOptions } from './loader.js';
|
|
10
11
|
export type { ExtensionRegistry } from './types/core.js';
|
|
11
12
|
export { ManifestRegistry, type ManifestRegistryEntry } from './manifest-registry.js';
|
|
@@ -8,6 +8,8 @@ export interface StagedExtensionInstall {
|
|
|
8
8
|
}
|
|
9
9
|
/** Extract, validate, install dependencies, and import-check an extension away from its live path. */
|
|
10
10
|
export declare function stageExtensionStoreZip(buffer: Buffer, extensionsDir: string): Promise<StagedExtensionInstall>;
|
|
11
|
+
export declare function stageExtensionNpm(packageSpec: string, extensionsDir: string, timeoutMs?: number): Promise<StagedExtensionInstall>;
|
|
12
|
+
export declare function stageExtensionLocal(localPath: string, extensionsDir: string): Promise<StagedExtensionInstall>;
|
|
11
13
|
/** Move a staged extension into its live path, preserving the previous version for rollback. */
|
|
12
14
|
export declare function commitStagedExtensionInstall(state: StagedExtensionInstall, overwrite: boolean): void;
|
|
13
15
|
/** Restore the previous live extension, or remove a newly committed install. */
|
|
@@ -1,36 +1,47 @@
|
|
|
1
|
-
import { installExtensionFromStoreZip } from "./install.js";
|
|
1
|
+
import { installExtensionFromStoreZip, installFromLocal, installFromNpm } from "./install.js";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync } from "node:fs";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
//#region src/extensions/install-transaction.ts
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
async function validateStagedInstall(result, stagingRoot, extensionsDir) {
|
|
7
|
+
if (!result.ok || !result.extensionId || !result.targetDir) throw new Error(result.error ?? "Extension staging failed");
|
|
8
|
+
const manifestPath = join(result.targetDir, "xopc.extension.json");
|
|
9
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
10
|
+
if (!manifest.main) throw new Error("Extension manifest must declare main");
|
|
11
|
+
const mainUrl = pathToFileURL(join(result.targetDir, manifest.main));
|
|
12
|
+
mainUrl.searchParams.set("xopcInstallCheck", `${Date.now()}-${Math.random()}`);
|
|
13
|
+
await import(mainUrl.href);
|
|
14
|
+
return {
|
|
15
|
+
extensionId: result.extensionId,
|
|
16
|
+
stagingRoot,
|
|
17
|
+
stagedExtensionDir: result.targetDir,
|
|
18
|
+
targetDir: join(extensionsDir, result.extensionId),
|
|
19
|
+
committed: false
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async function stageExtensionInstall(extensionsDir, install) {
|
|
8
23
|
mkdirSync(extensionsDir, { recursive: true });
|
|
9
24
|
const stagingRoot = mkdtempSync(join(extensionsDir, ".xopc-install-"));
|
|
10
25
|
try {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const manifestPath = join(result.targetDir, "xopc.extension.json");
|
|
14
|
-
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
15
|
-
if (!manifest.main) throw new Error("Extension manifest must declare main");
|
|
16
|
-
const mainUrl = pathToFileURL(join(result.targetDir, manifest.main));
|
|
17
|
-
mainUrl.searchParams.set("xopcInstallCheck", `${Date.now()}-${Math.random()}`);
|
|
18
|
-
await import(mainUrl.href);
|
|
19
|
-
return {
|
|
20
|
-
extensionId: result.extensionId,
|
|
21
|
-
stagingRoot,
|
|
22
|
-
stagedExtensionDir: result.targetDir,
|
|
23
|
-
targetDir: join(extensionsDir, result.extensionId),
|
|
24
|
-
committed: false
|
|
25
|
-
};
|
|
26
|
-
} catch (err) {
|
|
26
|
+
return await validateStagedInstall(await install(stagingRoot), stagingRoot, extensionsDir);
|
|
27
|
+
} catch (error) {
|
|
27
28
|
rmSync(stagingRoot, {
|
|
28
29
|
recursive: true,
|
|
29
30
|
force: true
|
|
30
31
|
});
|
|
31
|
-
throw
|
|
32
|
+
throw error;
|
|
32
33
|
}
|
|
33
34
|
}
|
|
35
|
+
/** Extract, validate, install dependencies, and import-check an extension away from its live path. */
|
|
36
|
+
async function stageExtensionStoreZip(buffer, extensionsDir) {
|
|
37
|
+
return stageExtensionInstall(extensionsDir, (stagingRoot) => installExtensionFromStoreZip(buffer, stagingRoot));
|
|
38
|
+
}
|
|
39
|
+
async function stageExtensionNpm(packageSpec, extensionsDir, timeoutMs) {
|
|
40
|
+
return stageExtensionInstall(extensionsDir, (stagingRoot) => installFromNpm(packageSpec, stagingRoot, timeoutMs));
|
|
41
|
+
}
|
|
42
|
+
async function stageExtensionLocal(localPath, extensionsDir) {
|
|
43
|
+
return stageExtensionInstall(extensionsDir, (stagingRoot) => installFromLocal(localPath, stagingRoot));
|
|
44
|
+
}
|
|
34
45
|
/** Move a staged extension into its live path, preserving the previous version for rollback. */
|
|
35
46
|
function commitStagedExtensionInstall(state, overwrite) {
|
|
36
47
|
if (existsSync(state.targetDir)) {
|
|
@@ -71,4 +82,4 @@ function finalizeStagedExtensionInstall(state) {
|
|
|
71
82
|
state.backupDir = void 0;
|
|
72
83
|
}
|
|
73
84
|
//#endregion
|
|
74
|
-
export { commitStagedExtensionInstall, finalizeStagedExtensionInstall, rollbackStagedExtensionInstall, stageExtensionStoreZip };
|
|
85
|
+
export { commitStagedExtensionInstall, finalizeStagedExtensionInstall, rollbackStagedExtensionInstall, stageExtensionLocal, stageExtensionNpm, stageExtensionStoreZip };
|
|
@@ -4,13 +4,14 @@ import { init_logger } from "../utils/logger.js";
|
|
|
4
4
|
import { init_paths, resolveBundledExtensionsDir, resolveExtensionsDir as resolveExtensionsDir$1 } from "../config/paths.js";
|
|
5
5
|
import { MAX_EXTENSION_STORE_ZIP_BYTES } from "./store-zip-limits.js";
|
|
6
6
|
import { checkEngineCompatibility } from "./engine-check.js";
|
|
7
|
+
import { EXTENSION_API_VERSION, EXTENSION_UI_API_VERSION, checkExtensionApiCompatibility } from "./api-version.js";
|
|
7
8
|
import { collectExtensionPackageDependencyIssues } from "./package-contract.js";
|
|
8
9
|
import { execFileSync } from "node:child_process";
|
|
9
10
|
import { dirname, isAbsolute, join, resolve, sep } from "path";
|
|
10
11
|
import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "fs";
|
|
11
12
|
import semver from "semver";
|
|
12
|
-
import AdmZip from "adm-zip";
|
|
13
13
|
import { tmpdir } from "os";
|
|
14
|
+
import AdmZip from "adm-zip";
|
|
14
15
|
//#region src/extensions/install.ts
|
|
15
16
|
/**
|
|
16
17
|
* Extension Installation Module
|
|
@@ -140,6 +141,7 @@ function installExtensionProdDependencies(extensionDir) {
|
|
|
140
141
|
"install",
|
|
141
142
|
"--prod",
|
|
142
143
|
"--no-frozen-lockfile",
|
|
144
|
+
"--package-import-method=copy",
|
|
143
145
|
...scriptArgs
|
|
144
146
|
]);
|
|
145
147
|
if (pnpm.ok) return pnpm;
|
|
@@ -488,6 +490,21 @@ async function installFromDirectory(sourceDir, extensionsDir) {
|
|
|
488
490
|
ok: false,
|
|
489
491
|
error: engineCheck.reason ?? `xopc ${PACKAGE_VERSION} does not satisfy engines.xopc ${manifest.engines.xopc}`
|
|
490
492
|
};
|
|
493
|
+
for (const [engineName, requiredRange, currentVersion] of [[
|
|
494
|
+
"extensionApi",
|
|
495
|
+
manifest.engines.extensionApi,
|
|
496
|
+
EXTENSION_API_VERSION
|
|
497
|
+
], [
|
|
498
|
+
"extensionUiApi",
|
|
499
|
+
manifest.engines.extensionUiApi,
|
|
500
|
+
EXTENSION_UI_API_VERSION
|
|
501
|
+
]]) {
|
|
502
|
+
const result = checkExtensionApiCompatibility(requiredRange, currentVersion, engineName);
|
|
503
|
+
if (result.parseWarning || !result.compatible) return {
|
|
504
|
+
ok: false,
|
|
505
|
+
error: result.reason ?? `Incompatible engines.${engineName}`
|
|
506
|
+
};
|
|
507
|
+
}
|
|
491
508
|
if (!manifest.main) return {
|
|
492
509
|
ok: false,
|
|
493
510
|
error: "Extension manifest must declare main"
|
|
@@ -21,8 +21,8 @@ import { type SlotRegistry } from './slots.js';
|
|
|
21
21
|
import { type ExtensionDiagnostics } from './diagnostics.js';
|
|
22
22
|
export type { ExtensionLoaderOptions, ExtensionSourceOrigin } from './discover-extensions.js';
|
|
23
23
|
export { areExtensionsGloballyDisabled } from './discover-extensions.js';
|
|
24
|
-
export { ExtensionRegistryImpl } from './extension-registry-impl.js';
|
|
25
24
|
import { ExtensionRegistryImpl } from './extension-registry-impl.js';
|
|
25
|
+
export { ExtensionRegistryImpl } from './extension-registry-impl.js';
|
|
26
26
|
export interface ActivationPlanLoadOptions extends Partial<ActivationContext> {
|
|
27
27
|
phase?: ActivationLoadPhase | 'all';
|
|
28
28
|
}
|
|
@@ -30,6 +30,7 @@ export declare class ExtensionLoader {
|
|
|
30
30
|
private registry;
|
|
31
31
|
private options;
|
|
32
32
|
private extensionInstances;
|
|
33
|
+
private startedServiceIds;
|
|
33
34
|
private jiti;
|
|
34
35
|
private _appConfig?;
|
|
35
36
|
private _runtimeContext?;
|
|
@@ -118,6 +119,7 @@ export declare class ExtensionLoader {
|
|
|
118
119
|
* Respects configured preferred plugin from config.extensions.slots
|
|
119
120
|
*/
|
|
120
121
|
private claimExtensionSlots;
|
|
122
|
+
private releaseExtensionSlots;
|
|
121
123
|
loadManifest(extensionPath: string): ExtensionManifest | null;
|
|
122
124
|
private moduleEntryCandidates;
|
|
123
125
|
private loadModule;
|
|
@@ -125,10 +127,8 @@ export declare class ExtensionLoader {
|
|
|
125
127
|
private initializeExtension;
|
|
126
128
|
startServices(): Promise<void>;
|
|
127
129
|
stopServices(): Promise<void>;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
*/
|
|
131
|
-
private validateType;
|
|
130
|
+
unloadExtension(extensionId: string): Promise<boolean>;
|
|
131
|
+
shutdown(): Promise<void>;
|
|
132
132
|
}
|
|
133
133
|
export declare function resolveExtensionPath(id: string, _options: ExtensionLoaderOptions): string | null;
|
|
134
134
|
export declare function normalizeExtensionConfig(rawConfig: Record<string, unknown>): ResolvedExtensionConfig[];
|
|
@@ -15,7 +15,9 @@ import { mergeActivationContext } from "./activation-context.js";
|
|
|
15
15
|
import { checkEngineCompatibility } from "./engine-check.js";
|
|
16
16
|
import { validateSpeechProviderContracts } from "./speech-provider-contracts.js";
|
|
17
17
|
import { validateMediaUnderstandingProviderContracts } from "./media-provider-contracts.js";
|
|
18
|
-
import {
|
|
18
|
+
import { validateExtensionConfig } from "./config-validation.js";
|
|
19
|
+
import { EXTENSION_API_VERSION, EXTENSION_UI_API_VERSION, checkExtensionApiCompatibility } from "./api-version.js";
|
|
20
|
+
import { DEFAULT_SECURITY_CONFIG, checkExtensionDirSafety, checkExtensionPathSafety, isExtensionAllowed, logSecurityIssue, provenanceTracker } from "./security.js";
|
|
19
21
|
import { getSlotRegistry } from "./slots.js";
|
|
20
22
|
import { getExtensionCache, getExtensionDiagnostics } from "./diagnostics.js";
|
|
21
23
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
@@ -59,6 +61,7 @@ var ExtensionLoader = class {
|
|
|
59
61
|
registry;
|
|
60
62
|
options;
|
|
61
63
|
extensionInstances = /* @__PURE__ */ new Map();
|
|
64
|
+
startedServiceIds = /* @__PURE__ */ new Set();
|
|
62
65
|
jiti;
|
|
63
66
|
_appConfig;
|
|
64
67
|
_runtimeContext;
|
|
@@ -316,6 +319,20 @@ var ExtensionLoader = class {
|
|
|
316
319
|
}, "Extension blocked because its path is unsafe");
|
|
317
320
|
return null;
|
|
318
321
|
}
|
|
322
|
+
if (this.securityConfig.checkPermissions) {
|
|
323
|
+
const directorySafety = checkExtensionDirSafety(extensionPath, extensionPath, source);
|
|
324
|
+
if (!directorySafety.safe) {
|
|
325
|
+
const firstIssue = directorySafety.issues[0];
|
|
326
|
+
if (firstIssue) logSecurityIssue(config.id, firstIssue);
|
|
327
|
+
const detail = firstIssue?.detail ?? "Unsafe file in extension directory";
|
|
328
|
+
this.diagnostics.error(config.id, detail);
|
|
329
|
+
log.error({
|
|
330
|
+
extensionId: config.id,
|
|
331
|
+
detail
|
|
332
|
+
}, "Extension directory safety check failed");
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
319
336
|
if (source !== "bundled" && !isExtensionAllowed(config.id, this.securityConfig)) {
|
|
320
337
|
this.diagnostics.error(config.id, "Extension is not present in extensions.security.allow");
|
|
321
338
|
log.error({
|
|
@@ -377,42 +394,40 @@ var ExtensionLoader = class {
|
|
|
377
394
|
this.diagnostics.error(config.id, engineResult.reason ?? "Incompatible xopc version (engines.xopc)");
|
|
378
395
|
return null;
|
|
379
396
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
397
|
+
for (const [engineName, requiredRange, currentVersion] of [[
|
|
398
|
+
"extensionApi",
|
|
399
|
+
manifest.engines.extensionApi,
|
|
400
|
+
EXTENSION_API_VERSION
|
|
401
|
+
], [
|
|
402
|
+
"extensionUiApi",
|
|
403
|
+
manifest.engines.extensionUiApi,
|
|
404
|
+
EXTENSION_UI_API_VERSION
|
|
405
|
+
]]) {
|
|
406
|
+
const result = checkExtensionApiCompatibility(requiredRange, currentVersion, engineName);
|
|
407
|
+
if (result.parseWarning || !result.compatible) {
|
|
408
|
+
const reason = result.reason ?? `Incompatible engines.${engineName}`;
|
|
409
|
+
log.warn({
|
|
410
|
+
extensionId: config.id,
|
|
411
|
+
requiredRange,
|
|
412
|
+
currentVersion
|
|
413
|
+
}, reason);
|
|
414
|
+
this.diagnostics.error(config.id, reason);
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
if (manifest.configSchema) {
|
|
419
|
+
const result = validateExtensionConfig(manifest.configSchema, config.config ?? {});
|
|
420
|
+
if (result.valid === false) {
|
|
421
|
+
log.error({
|
|
422
|
+
extensionId: config.id,
|
|
423
|
+
validationErrors: result.errors
|
|
424
|
+
}, `Extension config validation failed: ${result.reason}`);
|
|
425
|
+
this.diagnostics.error(config.id, `Extension config validation failed: ${result.reason}`);
|
|
426
|
+
return null;
|
|
407
427
|
}
|
|
408
428
|
log.debug({ extensionId: config.id }, "Extension config validated");
|
|
409
|
-
} catch (err) {
|
|
410
|
-
log.warn({
|
|
411
|
-
err,
|
|
412
|
-
extensionId: config.id
|
|
413
|
-
}, "Config schema validation skipped");
|
|
414
429
|
}
|
|
415
|
-
const extensionDir =
|
|
430
|
+
const extensionDir = extensionPath;
|
|
416
431
|
const api = this.createExtensionApi(manifest, config, extensionDir);
|
|
417
432
|
const module = await this.loadModule(extensionPath, manifest);
|
|
418
433
|
if (!module) {
|
|
@@ -421,7 +436,14 @@ var ExtensionLoader = class {
|
|
|
421
436
|
return null;
|
|
422
437
|
}
|
|
423
438
|
if (!this.claimExtensionSlots(config.id, manifest)) log.warn({ extensionId: config.id }, "Failed to claim required slots");
|
|
424
|
-
|
|
439
|
+
try {
|
|
440
|
+
await this.initializeExtension(module, api, manifest);
|
|
441
|
+
} catch (error) {
|
|
442
|
+
api._cleanup();
|
|
443
|
+
this.registry.removeExtensionContributions(config.id);
|
|
444
|
+
this.releaseExtensionSlots(config.id);
|
|
445
|
+
throw error;
|
|
446
|
+
}
|
|
425
447
|
validateSpeechProviderContracts({
|
|
426
448
|
extensionId: config.id,
|
|
427
449
|
manifest,
|
|
@@ -490,6 +512,9 @@ var ExtensionLoader = class {
|
|
|
490
512
|
if (!claimed) this.diagnostics.warn(extensionId, `Slot "${slotKey}" already claimed by another extension`);
|
|
491
513
|
return claimed;
|
|
492
514
|
}
|
|
515
|
+
releaseExtensionSlots(extensionId) {
|
|
516
|
+
for (const [key, claim] of this.slotRegistry.getAllClaims()) if (claim.pluginId === extensionId) this.slotRegistry.release(key, extensionId);
|
|
517
|
+
}
|
|
493
518
|
loadManifest(extensionPath) {
|
|
494
519
|
const manifestPath = join(extensionPath, EXTENSION_MANIFEST_FILE);
|
|
495
520
|
if (existsSync(manifestPath)) try {
|
|
@@ -557,13 +582,16 @@ var ExtensionLoader = class {
|
|
|
557
582
|
async initializeExtension(module, api, _manifest) {
|
|
558
583
|
if (typeof module === "function") await module(api);
|
|
559
584
|
else if (typeof module === "object" && module.register) await module.register(api);
|
|
585
|
+
if (typeof module === "object" && module.activate) await module.activate(api);
|
|
560
586
|
}
|
|
561
587
|
async startServices() {
|
|
562
588
|
const services = Array.from(this.registry.services.values());
|
|
563
589
|
for (const service of services) {
|
|
590
|
+
if (this.startedServiceIds.has(service.id)) continue;
|
|
564
591
|
const serviceLog = createServiceLogger(service.id);
|
|
565
592
|
try {
|
|
566
593
|
await service.start?.();
|
|
594
|
+
this.startedServiceIds.add(service.id);
|
|
567
595
|
serviceLog.info(`Started service`);
|
|
568
596
|
} catch (error) {
|
|
569
597
|
serviceLog.error({ err: error }, `Failed to start service`);
|
|
@@ -572,27 +600,61 @@ var ExtensionLoader = class {
|
|
|
572
600
|
}
|
|
573
601
|
async stopServices() {
|
|
574
602
|
const services = Array.from(this.registry.services.values()).reverse();
|
|
575
|
-
for (const service of services)
|
|
603
|
+
for (const service of services) {
|
|
604
|
+
if (!this.startedServiceIds.has(service.id)) continue;
|
|
576
605
|
const serviceLog = createServiceLogger(service.id);
|
|
577
606
|
try {
|
|
578
|
-
|
|
579
|
-
|
|
607
|
+
if (service.stop) {
|
|
608
|
+
await service.stop();
|
|
609
|
+
serviceLog.info(`Stopped service`);
|
|
610
|
+
}
|
|
580
611
|
} catch (error) {
|
|
581
612
|
serviceLog.error({ err: error }, `Failed to stop service`);
|
|
613
|
+
} finally {
|
|
614
|
+
this.startedServiceIds.delete(service.id);
|
|
582
615
|
}
|
|
583
616
|
}
|
|
584
617
|
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
618
|
+
async unloadExtension(extensionId) {
|
|
619
|
+
const api = this.extensionInstances.get(extensionId);
|
|
620
|
+
const record = this.registry.getExtension(extensionId);
|
|
621
|
+
if (!api || !record) return false;
|
|
622
|
+
for (const service of this.registry.getServicesForExtension(extensionId).reverse()) {
|
|
623
|
+
if (!this.startedServiceIds.has(service.id)) continue;
|
|
624
|
+
try {
|
|
625
|
+
await service.stop?.();
|
|
626
|
+
} catch (error) {
|
|
627
|
+
log.error({
|
|
628
|
+
err: error,
|
|
629
|
+
extensionId,
|
|
630
|
+
serviceId: service.id
|
|
631
|
+
}, "Extension service stop failed");
|
|
632
|
+
} finally {
|
|
633
|
+
this.startedServiceIds.delete(service.id);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
const module = record.module;
|
|
637
|
+
try {
|
|
638
|
+
if (module && typeof module === "object" && module.deactivate) await module.deactivate(api);
|
|
639
|
+
} catch (error) {
|
|
640
|
+
log.error({
|
|
641
|
+
err: error,
|
|
642
|
+
extensionId
|
|
643
|
+
}, "Extension deactivation failed");
|
|
644
|
+
} finally {
|
|
645
|
+
api._cleanup();
|
|
646
|
+
this.registry.removeExtensionContributions(extensionId);
|
|
647
|
+
this.releaseExtensionSlots(extensionId);
|
|
648
|
+
this.extensionInstances.delete(extensionId);
|
|
649
|
+
this.cache.invalidate();
|
|
650
|
+
}
|
|
651
|
+
this.diagnostics.info(extensionId, "Unloaded extension");
|
|
594
652
|
return true;
|
|
595
653
|
}
|
|
654
|
+
async shutdown() {
|
|
655
|
+
await this.stopServices();
|
|
656
|
+
for (const extensionId of [...this.extensionInstances.keys()].reverse()) await this.unloadExtension(extensionId);
|
|
657
|
+
}
|
|
596
658
|
};
|
|
597
659
|
function resolveExtensionPath(id, _options) {
|
|
598
660
|
const c = loadConfig();
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare function computeExtensionDirectoryIntegrity(extensionDir: string): string | undefined;
|
|
1
2
|
export type ExtensionSource = 'npm' | 'local' | 'git' | 'store';
|
|
2
3
|
export interface ExtensionLockEntry {
|
|
3
4
|
/** Extension ID */
|
|
@@ -37,7 +38,8 @@ export interface ExtensionsLockfile {
|
|
|
37
38
|
}
|
|
38
39
|
export declare class ExtensionLockfileManager {
|
|
39
40
|
private readonly lockfilePath;
|
|
40
|
-
|
|
41
|
+
private readonly extensionsDir;
|
|
42
|
+
constructor(lockfilePath?: string, extensionsDir?: string);
|
|
41
43
|
/**
|
|
42
44
|
* Load the lockfile
|
|
43
45
|
*/
|
|
@@ -85,10 +87,6 @@ export declare class ExtensionLockfileManager {
|
|
|
85
87
|
* Freeze current state (save with validation)
|
|
86
88
|
*/
|
|
87
89
|
freeze(): Promise<ExtensionsLockfile>;
|
|
88
|
-
/**
|
|
89
|
-
* Generate integrity hash for a file
|
|
90
|
-
*/
|
|
91
|
-
static generateIntegrity(filePath: string): Promise<string>;
|
|
92
90
|
}
|
|
93
91
|
export declare function getExtensionLockfileManager(lockfilePath?: string): ExtensionLockfileManager;
|
|
94
92
|
export declare function resetExtensionLockfileManager(): void;
|