@xopcai/xopc 0.0.118 → 0.0.119
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 -1
- package/README.zh-CN.md +2 -1
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-dzUrQoeZ.js → agent-avatar-dicebear-CU8J6zou.js} +1 -1
- package/dist/gateway/static/root/assets/agents-B0hkpLhP.js +2 -0
- package/dist/gateway/static/root/assets/app-management-settings-panel-B9vfYoEr.js +1 -0
- package/dist/gateway/static/root/assets/appearance-settings-ClOzIO24.js +1 -0
- package/dist/gateway/static/root/assets/{apps-page--wMEL00f.js → apps-page-DU0dz9Zo.js} +1 -1
- package/dist/gateway/static/root/assets/{archive-plugin-Cki4SfU2.js → archive-plugin-BkVIgZzA.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-D-KnS2Do.js → attachment-load-CaCMWh1D.js} +1 -1
- package/dist/gateway/static/root/assets/automation-suggestion-card-DhGDpKP3.js +1 -0
- package/dist/gateway/static/root/assets/automations-page-CTedroVo.js +1 -0
- package/dist/gateway/static/root/assets/{binary-plugins-D2sgvJja.js → binary-plugins-B4TO_bsn.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-DIq-4Gvb.js → block-editor-DJRWwWNI.js} +28 -28
- package/dist/gateway/static/root/assets/browser-settings-page-FCDwOOBK.js +8 -0
- package/dist/gateway/static/root/assets/capability-presets-api-Befi89CL.js +1 -0
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-_G8eb2vJ.js +1 -0
- package/dist/gateway/static/root/assets/channel-recipient-api-BNSuJb5f.js +1 -0
- package/dist/gateway/static/root/assets/channels-settings-C3d5JBJX.js +1 -0
- package/dist/gateway/static/root/assets/cn-BQ_8x0bT.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-yaUNvt5u.js +2 -0
- package/dist/gateway/static/root/assets/cron-expression-B3B1eqnr.js +2 -0
- package/dist/gateway/static/root/assets/dreaming-settings-DNrdg1Ve.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-DYu1KaFQ.js → extension-debug-page-DYh402XV.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-B3W6QwlZ.js → extension-page-Cr_TizrN.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-D7VQ-cxE.js → extension-settings-page-BU1KoKRj.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-B7xDPu-R.js → fetch-Y7AEX4H3.js} +1 -1
- package/dist/gateway/static/root/assets/format-cron-label-arqgGlVV.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-config-api-BTBLSeUu.js → gateway-config-api-RbMmAOpX.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-C79wkXef.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-CYj9FWCp.js → gateway-startup-retry-DiD_Tx4N.js} +1 -1
- package/dist/gateway/static/root/assets/goal-detail-page-9paXuHdo.js +1 -0
- package/dist/gateway/static/root/assets/{goals-config-api-CQQgzPr3.js → goals-config-api-DqxVi0p5.js} +1 -1
- package/dist/gateway/static/root/assets/{goals-page-BHitvJAv.js → goals-page-CS0R-Af2.js} +2 -2
- package/dist/gateway/static/root/assets/goals-settings-CSuzZ8Ae.js +1 -0
- package/dist/gateway/static/root/assets/heartbeat-settings-DXPaYJm3.js +1 -0
- package/dist/gateway/static/root/assets/index-BoKafJIZ.js +191 -0
- package/dist/gateway/static/root/assets/index-CArhCcYn.css +1 -0
- package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-Dvg53qnd.js +1 -0
- package/dist/gateway/static/root/assets/{logs-page-C2Uqvae9.js → logs-page-DLXPcksQ.js} +2 -2
- package/dist/gateway/static/root/assets/{markdown-split-BwOFrJ2E.js → markdown-split-CpHxbtWJ.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-Cnz6Q5G6.js → media-plugins-SFPQRSxq.js} +1 -1
- package/dist/gateway/static/root/assets/messages-CrDHEbss.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-BDF2iyRk.js +2 -0
- package/dist/gateway/static/root/assets/note-detail-page-CSb_hwig.js +2 -0
- package/dist/gateway/static/root/assets/{note-image-lightbox-B-Svpmza.js → note-image-lightbox-BUYURRgn.js} +1 -1
- package/dist/gateway/static/root/assets/notes-page-BsIBSFyZ.js +1 -0
- package/dist/gateway/static/root/assets/{preview-open-alternatives-Bss4TiwP.js → preview-open-alternatives-BHz9iWYA.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-CwzSovcS.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-BRNjdgKq.js → save-bar-controls-CefkOlRg.js} +1 -1
- package/dist/gateway/static/root/assets/schedule-field-CmTRoOcE.js +1 -0
- package/dist/gateway/static/root/assets/{schema-form-Dub9sy8r.js → schema-form-FMKv1vGu.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-PHmX-NmA.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BRAeKJN4.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-BeFLavGi.js → settings-collapsible-section-BouO6JTi.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-form-section-dmyaPOTG.js → settings-form-section-D-4lBl6X.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-KKrbFjy8.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-layout-BJ4Gsef5.js +1 -0
- package/dist/gateway/static/root/assets/setup-status-panel-CrUjHPQo.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-C8glrdqe.js → share-preview-page-BDy2btRN.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-B18OBmH5.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-C28-2uKQ.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-Bm2ebkwl.js +2 -0
- package/dist/gateway/static/root/assets/system-settings-panel-CRngrlnZ.js +1 -0
- package/dist/gateway/static/root/assets/typed-models-lib-BltBc0b-.js +1 -0
- package/dist/gateway/static/root/assets/{use-channel-catalog-DqlWTsDb.js → use-channel-catalog-CjN-51e6.js} +1 -1
- package/dist/gateway/static/root/assets/user-profile-settings-panel-DJ1dKwZy.js +1 -0
- package/dist/gateway/static/root/assets/utils-B5M5-YvK.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-C73IVZeC.js → voice-api-key-field-CeEevm7z.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-player-store-C_ArLJPM.js → voice-player-store-B7ykUlHM.js} +1 -1
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-C4PzUQjB.js +3 -0
- package/dist/gateway/static/root/assets/workflows-page-BL84_-Ky.js +18 -0
- package/dist/gateway/static/root/index.html +6 -7
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +4 -5
- package/dist/src/agent/agent-manager.js +4 -8
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/embedded/run-for-session.js +102 -14
- package/dist/src/agent/embedded/run-for-session.js.map +1 -1
- package/dist/src/agent/fallback/candidates.d.ts +0 -8
- package/dist/src/agent/fallback/candidates.js.map +1 -1
- package/dist/src/agent/index.js +1 -1
- package/dist/src/agent/lifecycle/handlers/compaction.d.ts +1 -3
- package/dist/src/agent/lifecycle/handlers/compaction.js +1 -16
- package/dist/src/agent/lifecycle/handlers/compaction.js.map +1 -1
- package/dist/src/agent/lifecycle/progress.d.ts +0 -1
- package/dist/src/agent/lifecycle/progress.js +1 -6
- package/dist/src/agent/lifecycle/progress.js.map +1 -1
- package/dist/src/agent/lifecycle/timeout-wrapper.d.ts +1 -2
- package/dist/src/agent/lifecycle/timeout-wrapper.js +1 -7
- package/dist/src/agent/lifecycle/timeout-wrapper.js.map +1 -1
- package/dist/src/agent/middleware/self-verify.d.ts +0 -1
- package/dist/src/agent/middleware/self-verify.js +0 -2
- package/dist/src/agent/middleware/self-verify.js.map +1 -1
- package/dist/src/agent/models/index.d.ts +1 -1
- package/dist/src/agent/models/manager.d.ts +4 -20
- package/dist/src/agent/models/manager.js +9 -126
- package/dist/src/agent/models/manager.js.map +1 -1
- package/dist/src/agent/orchestration/agent-orchestrator.d.ts +0 -4
- package/dist/src/agent/orchestration/agent-orchestrator.js +1 -9
- package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
- package/dist/src/agent/prompt/sections/tooling.js +2 -2
- package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.d.ts +0 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +0 -12
- package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
- package/dist/src/agent/prompt/subagent-context.js +1 -1
- package/dist/src/agent/prompt/subagent-context.js.map +1 -1
- package/dist/src/agent/prompt/types.d.ts +1 -1
- package/dist/src/agent/service.d.ts +1 -9
- package/dist/src/agent/service.js +3 -40
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/service.types.d.ts +2 -2
- package/dist/src/agent/session/session-config-service.d.ts +11 -11
- package/dist/src/agent/session/session-config-service.js +14 -14
- package/dist/src/agent/session/session-config-service.js.map +1 -1
- package/dist/src/agent/session/session-inspector.js +3 -2
- package/dist/src/agent/session/session-inspector.js.map +1 -1
- package/dist/src/agent/starter-agents.js +12 -12
- package/dist/src/agent/starter-agents.js.map +1 -1
- package/dist/src/agent/tools/automation-tool.d.ts +14 -0
- package/dist/src/agent/tools/automation-tool.js +102 -0
- package/dist/src/agent/tools/automation-tool.js.map +1 -0
- package/dist/src/agent/tools/delegate-tool.js +1 -1
- package/dist/src/agent/tools/delegate-tool.js.map +1 -1
- package/dist/src/agent/tools/factory.d.ts +3 -3
- package/dist/src/agent/tools/factory.js +2 -2
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/index.d.ts +1 -1
- package/dist/src/agent/tools/index.js +2 -2
- package/dist/src/agent-manifest/resolver.d.ts +1 -0
- package/dist/src/agent-manifest/resolver.js +1 -0
- package/dist/src/agent-manifest/resolver.js.map +1 -1
- package/dist/src/agent-manifest/schema.d.ts +6 -0
- package/dist/src/agent-manifest/schema.js +12 -3
- package/dist/src/agent-manifest/schema.js.map +1 -1
- package/dist/src/ai-assist/text-assist.d.ts +1 -1
- package/dist/src/ai-assist/text-assist.js +56 -0
- package/dist/src/ai-assist/text-assist.js.map +1 -1
- package/dist/src/auth/profiles/store.js.map +1 -1
- package/dist/src/automations/api/routes.d.ts +3 -0
- package/dist/src/automations/api/routes.js +193 -0
- package/dist/src/automations/api/routes.js.map +1 -0
- package/dist/src/automations/domain/index.d.ts +3 -0
- package/dist/src/automations/domain/index.js +3 -0
- package/dist/src/automations/domain/schedule.d.ts +4 -0
- package/dist/src/automations/domain/schedule.js +37 -0
- package/dist/src/automations/domain/schedule.js.map +1 -0
- package/dist/src/automations/domain/types.d.ts +160 -0
- package/dist/src/automations/domain/validation.d.ts +370 -0
- package/dist/src/automations/domain/validation.js +149 -0
- package/dist/src/automations/domain/validation.js.map +1 -0
- package/dist/src/automations/draft/automation-draft-prompt.d.ts +26 -0
- package/dist/src/automations/draft/automation-draft-prompt.js +127 -0
- package/dist/src/automations/draft/automation-draft-prompt.js.map +1 -0
- package/dist/src/automations/draft/automation-draft-service.d.ts +12 -0
- package/dist/src/automations/draft/automation-draft-service.js +135 -0
- package/dist/src/automations/draft/automation-draft-service.js.map +1 -0
- package/dist/src/automations/draft/automation-draft-validator.d.ts +99 -0
- package/dist/src/automations/draft/automation-draft-validator.js +105 -0
- package/dist/src/automations/draft/automation-draft-validator.js.map +1 -0
- package/dist/src/automations/draft/automation-draft.types.d.ts +40 -0
- package/dist/src/automations/draft/index.d.ts +3 -0
- package/dist/src/automations/draft/index.js +3 -0
- package/dist/src/automations/index.d.ts +3 -0
- package/dist/src/automations/index.js +8 -0
- package/dist/src/automations/product-events.d.ts +5 -0
- package/dist/src/automations/product-events.js +21 -0
- package/dist/src/automations/product-events.js.map +1 -0
- package/dist/src/automations/service/action-executor.d.ts +9 -0
- package/dist/src/automations/service/action-executor.js +157 -0
- package/dist/src/automations/service/action-executor.js.map +1 -0
- package/dist/src/automations/service/automation-service.d.ts +54 -0
- package/dist/src/automations/service/automation-service.js +404 -0
- package/dist/src/automations/service/automation-service.js.map +1 -0
- package/dist/src/automations/service/index.d.ts +2 -0
- package/dist/src/automations/service/index.js +3 -0
- package/dist/src/automations/storage/automation-repository.d.ts +6 -0
- package/dist/src/automations/storage/automation-repository.js +61 -0
- package/dist/src/automations/storage/automation-repository.js.map +1 -0
- package/dist/src/automations/storage/automation-run-repository.d.ts +17 -0
- package/dist/src/automations/storage/automation-run-repository.js +130 -0
- package/dist/src/automations/storage/automation-run-repository.js.map +1 -0
- package/dist/src/automations/storage/index.d.ts +2 -0
- package/dist/src/automations/storage/index.js +3 -0
- package/dist/src/channels/plugin-types.d.ts +3 -0
- package/dist/src/chat-commands/builtins/thinking.js.map +1 -1
- package/dist/src/cli/command-catalog.js +0 -39
- package/dist/src/cli/command-catalog.js.map +1 -1
- package/dist/src/cli/command-loaders.js +0 -1
- package/dist/src/cli/command-loaders.js.map +1 -1
- package/dist/src/cli/command-manifest.js +0 -4
- package/dist/src/cli/command-manifest.js.map +1 -1
- package/dist/src/cli/commands/agents.js +7 -6
- package/dist/src/cli/commands/agents.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/doctor/checks/{cron-health.d.ts → migrations.d.ts} +1 -1
- package/dist/src/cli/commands/doctor/checks/migrations.js +40 -0
- package/dist/src/cli/commands/doctor/checks/migrations.js.map +1 -0
- package/dist/src/cli/commands/doctor/flow.js +2 -2
- package/dist/src/cli/commands/doctor/flow.js.map +1 -1
- package/dist/src/cli/commands/gateway/call.js +2 -2
- package/dist/src/cli/commands/gateway/call.js.map +1 -1
- package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
- package/dist/src/cli/commands/gateway/run-foreground.js +4 -2
- package/dist/src/cli/commands/gateway/run-foreground.js.map +1 -1
- package/dist/src/cli/commands/init.js +26 -8
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/tui.js +24 -2
- package/dist/src/cli/commands/tui.js.map +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +2 -0
- package/dist/src/cli/utils/init-workspace-core.js.map +1 -1
- package/dist/src/commands/agents.config.d.ts +9 -0
- package/dist/src/commands/agents.config.js +40 -2
- package/dist/src/commands/agents.config.js.map +1 -1
- package/dist/src/config/agent-profile.js +4 -3
- package/dist/src/config/agent-profile.js.map +1 -1
- package/dist/src/config/agent-typed-models.js.map +1 -1
- package/dist/src/config/config-surface.d.ts +3 -0
- package/dist/src/config/index.d.ts +0 -1
- package/dist/src/config/index.js +3 -3
- package/dist/src/config/index.js.map +1 -1
- package/dist/src/config/paths.d.ts +0 -9
- package/dist/src/config/paths.js +1 -14
- package/dist/src/config/paths.js.map +1 -1
- package/dist/src/config/profile.js +0 -1
- package/dist/src/config/profile.js.map +1 -1
- package/dist/src/config/rules.js +0 -5
- package/dist/src/config/rules.js.map +1 -1
- package/dist/src/config/schema.d.ts +13 -12
- package/dist/src/config/schema.js +22 -26
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/config/web-patch.d.ts +0 -12
- package/dist/src/config/web-patch.js +2 -29
- package/dist/src/config/web-patch.js.map +1 -1
- package/dist/src/extensions/api.d.ts +2 -0
- package/dist/src/extensions/api.js +10 -0
- package/dist/src/extensions/api.js.map +1 -1
- package/dist/src/extensions/extension-registry-impl.d.ts +4 -1
- package/dist/src/extensions/extension-registry-impl.js +8 -0
- package/dist/src/extensions/extension-registry-impl.js.map +1 -1
- package/dist/src/extensions/loader.d.ts +3 -3
- package/dist/src/extensions/loader.js +3 -3
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/extensions/sdk/testing.d.ts +2 -0
- package/dist/src/extensions/sdk/testing.js +7 -0
- package/dist/src/extensions/sdk/testing.js.map +1 -1
- package/dist/src/extensions/types/core.d.ts +10 -1
- package/dist/src/extensions/types/index.d.ts +1 -1
- package/dist/src/extensions/types/{phase4.d.ts → registration.d.ts} +2 -2
- package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
- package/dist/src/gateway/agent-builtin-tools.js +1 -1
- package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
- package/dist/src/gateway/agents-admin.d.ts +1 -0
- package/dist/src/gateway/agents-admin.js +13 -15
- package/dist/src/gateway/agents-admin.js.map +1 -1
- package/dist/src/gateway/capability-presets-admin.d.ts +1 -0
- package/dist/src/gateway/capability-presets-admin.js +19 -10
- package/dist/src/gateway/capability-presets-admin.js.map +1 -1
- package/dist/src/gateway/dreaming-automation-reconciler.d.ts +11 -0
- package/dist/src/gateway/dreaming-automation-reconciler.js +105 -0
- package/dist/src/gateway/dreaming-automation-reconciler.js.map +1 -0
- package/dist/src/gateway/heartbeat/service.d.ts +0 -2
- package/dist/src/gateway/heartbeat/service.js +0 -7
- package/dist/src/gateway/heartbeat/service.js.map +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +5 -6
- package/dist/src/gateway/hono/lib/config-payload.js +2 -2
- package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
- package/dist/src/gateway/hono/routes/agents.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.d.ts +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +12 -6
- package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -1
- package/dist/src/gateway/hono/routes/dreaming.js +27 -37
- package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
- package/dist/src/gateway/hono/routes/home.d.ts +2 -2
- package/dist/src/gateway/hono/routes/home.js +34 -25
- package/dist/src/gateway/hono/routes/home.js.map +1 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js +10 -6
- package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
- package/dist/src/gateway/hono/routes/migrations.d.ts +3 -0
- package/dist/src/gateway/hono/routes/migrations.js +35 -0
- package/dist/src/gateway/hono/routes/migrations.js.map +1 -0
- package/dist/src/gateway/hono/routes/public-gateway.js +2 -1
- package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +14 -0
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/run-loop.js +2 -0
- package/dist/src/gateway/run-loop.js.map +1 -1
- package/dist/src/gateway/security/operator-scopes.js +5 -1
- package/dist/src/gateway/security/operator-scopes.js.map +1 -1
- package/dist/src/gateway/service/config-coordinator.d.ts +4 -4
- package/dist/src/gateway/service/config-coordinator.js +14 -8
- package/dist/src/gateway/service/config-coordinator.js.map +1 -1
- package/dist/src/gateway/service/sessions-api.d.ts +2 -1
- package/dist/src/gateway/service/sessions-api.js +6 -1
- package/dist/src/gateway/service/sessions-api.js.map +1 -1
- package/dist/src/gateway/service.d.ts +7 -3
- package/dist/src/gateway/service.js +61 -27
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/goals/goal-service.js +45 -4
- package/dist/src/goals/goal-service.js.map +1 -1
- package/dist/src/infra/update-restart.js +1 -1
- package/dist/src/migrations/config/default-capability-preset.d.ts +10 -0
- package/dist/src/migrations/config/default-capability-preset.js +135 -0
- package/dist/src/migrations/config/default-capability-preset.js.map +1 -0
- package/dist/src/migrations/index.d.ts +4 -0
- package/dist/src/migrations/index.js +4 -0
- package/dist/src/migrations/registry.d.ts +8 -0
- package/dist/src/migrations/registry.js +18 -0
- package/dist/src/migrations/registry.js.map +1 -0
- package/dist/src/migrations/runner.d.ts +17 -0
- package/dist/src/migrations/runner.js +191 -0
- package/dist/src/migrations/runner.js.map +1 -0
- package/dist/src/migrations/types.d.ts +34 -0
- package/dist/src/notes/service.js +24 -1
- package/dist/src/notes/service.js.map +1 -1
- package/dist/src/providers/model-registry.d.ts +0 -1
- package/dist/src/providers/model-registry.js +0 -3
- package/dist/src/providers/model-registry.js.map +1 -1
- package/dist/src/routing/resolve-tui-session-key.d.ts +3 -0
- package/dist/src/routing/resolve-tui-session-key.js +14 -3
- package/dist/src/routing/resolve-tui-session-key.js.map +1 -1
- package/dist/src/session/transcript-outline.d.ts +47 -0
- package/dist/src/session/transcript-outline.js +481 -0
- package/dist/src/session/transcript-outline.js.map +1 -0
- package/dist/src/storage/sqlite/index.d.ts +0 -2
- package/dist/src/storage/sqlite/index.js +1 -3
- package/dist/src/storage/sqlite/migrations/016_automations.sql +47 -0
- package/dist/src/storage/sqlite/migrations/017_automation_run_events.sql +14 -0
- package/dist/src/storage/sqlite/migrations/018_automation_safety.sql +1 -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/migrations/runner.js.map +1 -1
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/schema.sql +56 -46
- package/dist/src/tui/backends/embedded-backend.d.ts +6 -0
- package/dist/src/tui/backends/embedded-backend.js +18 -7
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.d.ts +3 -0
- package/dist/src/tui/backends/gateway-sse-backend.js +14 -0
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/tui-backend.d.ts +4 -0
- package/dist/src/tui/tui-commands.d.ts +5 -0
- package/dist/src/tui/tui-commands.js +43 -0
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui-transcript-tree.d.ts +1 -1
- package/dist/src/tui/tui-transcript-tree.js +17 -257
- package/dist/src/tui/tui-transcript-tree.js.map +1 -1
- package/dist/src/tui/tui-types.d.ts +2 -0
- package/dist/src/tui/tui-types.js.map +1 -1
- package/dist/src/tui/tui.js +7 -2
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/workflows/domain/index.js +1 -1
- package/dist/src/workflows/domain/run.d.ts +7 -7
- package/dist/src/workflows/domain/run.js.map +1 -1
- package/dist/src/workflows/index.js +2 -2
- package/dist/src/workflows/service/workflow-run-service.d.ts +2 -0
- package/dist/src/workflows/service/workflow-run-service.js +31 -9
- package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
- package/dist/src/workflows/service/workflow-run-service.types.d.ts +1 -1
- package/package.json +4 -2
- package/dist/gateway/static/root/assets/agents-BCxZbkOw.js +0 -2
- package/dist/gateway/static/root/assets/app-management-settings-panel-bxYJVJpx.js +0 -1
- package/dist/gateway/static/root/assets/appearance-settings-BCIykXlI.js +0 -1
- package/dist/gateway/static/root/assets/browser-settings-page-DRhKdn81.js +0 -8
- package/dist/gateway/static/root/assets/capability-presets-api-CorhiHlg.js +0 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-qFx9Jtce.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-BAwAkqIA.js +0 -1
- package/dist/gateway/static/root/assets/cn-JdwAhgNB.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-BQLcfitM.js +0 -2
- package/dist/gateway/static/root/assets/createLucideIcon-DPHK1VkS.js +0 -1
- package/dist/gateway/static/root/assets/cron-api-qGwmL-24.js +0 -1
- package/dist/gateway/static/root/assets/cron-dreaming-jobs-nCMWCf0p.js +0 -1
- package/dist/gateway/static/root/assets/cron-page-BBWMAj8-.js +0 -3
- package/dist/gateway/static/root/assets/dreaming-settings-Dw89Obml.js +0 -1
- package/dist/gateway/static/root/assets/format-cron-label-BsotZDO5.js +0 -2
- package/dist/gateway/static/root/assets/format-interval-label-BzxafKxR.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-Cmwy58rS.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-l7mu5GWX.js +0 -1
- package/dist/gateway/static/root/assets/goals-settings-CYVY4NGp.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-config-api-DriO_CN9.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-CUQTKxg7.js +0 -1
- package/dist/gateway/static/root/assets/index-C17Tsd_b.css +0 -1
- package/dist/gateway/static/root/assets/index-Cc41r16l.js +0 -191
- package/dist/gateway/static/root/assets/interval-presets-DFPCKW_W.js +0 -1
- package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-CcVcqstx.js +0 -1
- package/dist/gateway/static/root/assets/messages-B1iSKjiw.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-panel-BfLfcta8.js +0 -2
- package/dist/gateway/static/root/assets/note-detail-page-BjwOQBfT.js +0 -2
- package/dist/gateway/static/root/assets/notes-page-DktdBiwB.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-rfVx96fq.js +0 -1
- package/dist/gateway/static/root/assets/schedule-field-CUCKODde.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-DbtMFuuH.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-5re5gAnP.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-D-WMyLlj.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Cl-DEJAU.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-CyPVvbLt.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-CleTH1oz.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-Ck8hdXqR.js +0 -2
- package/dist/gateway/static/root/assets/system-settings-panel-DI-LN_8G.js +0 -1
- package/dist/gateway/static/root/assets/typed-models-lib-kX9duch4.js +0 -1
- package/dist/gateway/static/root/assets/user-profile-settings-panel-B-UFPMXy.js +0 -1
- package/dist/gateway/static/root/assets/utils-Dm0hKalR.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-BtFGp2y_.js +0 -18
- package/dist/src/agent/fallback/error.d.ts +0 -22
- package/dist/src/agent/fallback/error.js +0 -32
- package/dist/src/agent/fallback/error.js.map +0 -1
- package/dist/src/agent/fallback/index.d.ts +0 -5
- package/dist/src/agent/fallback/index.js +0 -9
- package/dist/src/agent/fallback/index.js.map +0 -1
- package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.d.ts +0 -29
- package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js +0 -76
- package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js.map +0 -1
- package/dist/src/agent/service/reconcile-dreaming-cron.d.ts +0 -6
- package/dist/src/agent/service/reconcile-dreaming-cron.js +0 -84
- package/dist/src/agent/service/reconcile-dreaming-cron.js.map +0 -1
- package/dist/src/agent/tools/cronjob-tool.d.ts +0 -29
- package/dist/src/agent/tools/cronjob-tool.js +0 -274
- package/dist/src/agent/tools/cronjob-tool.js.map +0 -1
- package/dist/src/cli/commands/cron-cli.d.ts +0 -2
- package/dist/src/cli/commands/cron-cli.js +0 -15
- package/dist/src/cli/commands/cron-cli.js.map +0 -1
- package/dist/src/cli/commands/cron.d.ts +0 -4
- package/dist/src/cli/commands/cron.js +0 -188
- package/dist/src/cli/commands/cron.js.map +0 -1
- package/dist/src/cli/commands/doctor/checks/cron-health.js +0 -35
- package/dist/src/cli/commands/doctor/checks/cron-health.js.map +0 -1
- package/dist/src/cron/execution-types.d.ts +0 -42
- package/dist/src/cron/executor.d.ts +0 -67
- package/dist/src/cron/executor.js +0 -669
- package/dist/src/cron/executor.js.map +0 -1
- package/dist/src/cron/index.d.ts +0 -7
- package/dist/src/cron/index.js +0 -7
- package/dist/src/cron/job-content.d.ts +0 -5
- package/dist/src/cron/job-content.js +0 -15
- package/dist/src/cron/job-content.js.map +0 -1
- package/dist/src/cron/run-log-store.d.ts +0 -12
- package/dist/src/cron/run-log-store.js +0 -58
- package/dist/src/cron/run-log-store.js.map +0 -1
- package/dist/src/cron/schedule.d.ts +0 -10
- package/dist/src/cron/schedule.js +0 -85
- package/dist/src/cron/schedule.js.map +0 -1
- package/dist/src/cron/service.d.ts +0 -58
- package/dist/src/cron/service.js +0 -419
- package/dist/src/cron/service.js.map +0 -1
- package/dist/src/cron/types.d.ts +0 -183
- package/dist/src/cron/validation.d.ts +0 -500
- package/dist/src/cron/validation.js +0 -192
- package/dist/src/cron/validation.js.map +0 -1
- package/dist/src/cron/workflow-run-completion.d.ts +0 -23
- package/dist/src/cron/workflow-run-completion.js +0 -72
- package/dist/src/cron/workflow-run-completion.js.map +0 -1
- package/dist/src/extensions/types/phase4.js +0 -1
- package/dist/src/gateway/hono/routes/cron.d.ts +0 -3
- package/dist/src/gateway/hono/routes/cron.js +0 -109
- package/dist/src/gateway/hono/routes/cron.js.map +0 -1
- package/dist/src/storage/sqlite/cron-job-repository.d.ts +0 -6
- package/dist/src/storage/sqlite/cron-job-repository.js +0 -70
- package/dist/src/storage/sqlite/cron-job-repository.js.map +0 -1
- package/dist/src/storage/sqlite/cron-run-repository.d.ts +0 -5
- package/dist/src/storage/sqlite/cron-run-repository.js +0 -96
- package/dist/src/storage/sqlite/cron-run-repository.js.map +0 -1
- /package/dist/src/{cron → automations/domain}/types.js +0 -0
- /package/dist/src/{config/defaults.d.ts → automations/draft/automation-draft.types.js} +0 -0
- /package/dist/src/{config/defaults.js → extensions/types/registration.js} +0 -0
- /package/dist/src/{cron/execution-types.js → migrations/types.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-coordinator.js","names":["writeConfigToDisk"],"sources":["../../../../src/gateway/service/config-coordinator.ts"],"sourcesContent":["/**\n * GatewayConfigCoordinator — owns config persistence, hot-reload, and the\n * per-section reload handlers.\n *\n * Was 350 lines of `GatewayService` covering nine concerns:\n * - manual `reloadConfig()` (CLI/UI trigger)\n * - `saveConfig()` / `updateConfig()` (PATCH /api/config)\n * - `setBundledExtensionActivationTarget` (extension store install)\n * - `afterWeixinCredentialsPersisted` / `afterFeishuCredentialsPersisted`\n * (QR-login follow-ups that bypass the watcher)\n * - `ConfigHotReloader` (fs.watch → debounced per-section dispatch)\n * - Eight section reload handlers (models / agents / channels / cron /\n * heartbeat / tools / mcp / extensions)\n * - `scheduleChannelPluginsAfterPersist` (coalesces rapid saves so\n * Telegram/Weixin do not stop/start repeatedly)\n *\n * Pulled out so the gateway composition root stays focused on lifecycle, and\n * each handler is reachable from one place when adding a new config section.\n *\n * **Config state ownership.** `GatewayService.config` is still the single\n * source of truth — this coordinator reads it via `getConfig()` and writes it\n * back via `setConfig()` after every reload / persist. We pass through rather\n * than holding our own copy so other coordinators (sessions, marketplace,\n * agent runner) see the latest config the moment a reload commits.\n */\nimport type { Config } from '../../config/schema.js';\nimport type { Config as SurfaceConfig } from '../../config/config-surface.js';\nimport type { AgentService } from '../../agent/service.js';\nimport type { ChannelManager } from '../../channels/manager.js';\nimport type { CronService } from '../../cron/index.js';\nimport type { HeartbeatService } from '../heartbeat/index.js';\nimport type { ExtensionLoader } from '../../extensions/loader.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport { ConfigHotReloader } from '../../config/reload.js';\nimport { loadConfig, saveConfig as writeConfigToDisk } from '../../config/index.js';\nimport { sanitizeTunnelConfig } from '../../tunnel/tunnel-config.js';\nimport { getModelRegistry } from '../../providers/index.js';\nimport { disposeAllSessionMcpRuntimes } from '../../agent/mcp/bundle-mcp-tools.js';\nimport { computeBundledExtensionExtensionsPatch } from '../../extensions/bundled-extension-activation.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('GatewayConfigCoordinator');\n\nexport interface GatewayConfigCoordinatorOptions {\n configPath: string;\n bus: MessageBus;\n /** Hot reload (fs.watch) — disabled in tests / certain CLI modes. */\n enableHotReload: boolean;\n getConfig: () => Config;\n /** Writes the new config back into `GatewayService.config`. */\n setConfig: (next: Config) => void;\n getAgentService: () => AgentService;\n getChannelManager: () => ChannelManager;\n getCronService: () => CronService;\n getHeartbeatService: () => HeartbeatService | null;\n getExtensionLoader: () => ExtensionLoader | null;\n /** Re-evaluate browser-extension server attachment after agent defaults change. */\n reconcileBrowserExtensionServer: () => Promise<void>;\n /** Latest channel status snapshot for the `channels.status` SSE event. */\n getChannelsStatus: () => unknown;\n /** SSE emit (used for `config.reload` + `channels.status`). */\n emit: (type: string, payload: unknown) => void;\n}\n\nexport class GatewayConfigCoordinator {\n private readonly opts: GatewayConfigCoordinatorOptions;\n private configReloader: ConfigHotReloader | null = null;\n private channelReloadFlushPromise: Promise<void> | null = null;\n private channelReloadPending = false;\n\n constructor(opts: GatewayConfigCoordinatorOptions) {\n this.opts = opts;\n }\n\n // ── Lifecycle ──────────────────────────────────────────────────────────\n\n /** Start the fs.watch-based reloader (idempotent — only starts once). */\n startHotReloader(): void {\n if (this.configReloader) return;\n this.configReloader = new ConfigHotReloader(\n this.opts.configPath,\n this.opts.getConfig(),\n {\n onModelsReload: (newConfig) => this.handleModelsReload(newConfig),\n onAgentDefaultsReload: (newConfig) => this.handleAgentDefaultsReload(newConfig),\n onChannelsReload: (newConfig) => this.handleChannelsReload(newConfig),\n onCronReload: (newConfig) => this.handleCronReload(newConfig),\n onHeartbeatReload: (newConfig) => this.handleHeartbeatReload(newConfig),\n onToolsReload: (newConfig) => this.handleToolsReload(newConfig),\n onMcpReload: (newConfig) => this.handleMcpReload(newConfig),\n onExtensionsReload: async (newConfig, changedPaths) => {\n await this.handleExtensionsReload(newConfig, changedPaths);\n },\n onFullRestart: (newConfig) => {\n log.warn(\n { requiresProcessRestart: true, hint: 'Restart the gateway process (hot reload cannot apply this change).' },\n 'Config reload: full gateway restart required — see prior \"restartPaths\" info log',\n );\n this.opts.setConfig(newConfig);\n this.opts.emit('config.reload', { section: 'full', requiresRestart: true });\n },\n },\n {\n debounceMs: 300,\n enabled: this.opts.enableHotReload,\n }\n );\n this.configReloader.start();\n }\n\n async stopHotReloader(): Promise<void> {\n if (this.configReloader) {\n await this.configReloader.stop();\n this.configReloader = null;\n }\n }\n\n // ── Manual reload (UI trigger) ─────────────────────────────────────────\n\n async reloadConfig(): Promise<{ reloaded: boolean; error?: string }> {\n if (!this.configReloader) {\n return { reloaded: false, error: 'Config reloader not initialized' };\n }\n const result = await this.configReloader.triggerReload();\n return { reloaded: result.success, error: result.error };\n }\n\n // ── Persist (PATCH /api/config, marketplace install, etc.) ─────────────\n\n async saveConfig(config: Config): Promise<{ saved: boolean; error?: string }> {\n try {\n await this.writeConfigAndReloadFromDisk(config);\n this.scheduleChannelPluginsAfterPersist();\n return { saved: true };\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ err, errorMessage: em, phase: 'infra.config' }, `Failed to save config: ${em}`);\n return { saved: false, error: em };\n }\n }\n\n /** Merge partial updates into `currentConfig` and persist. */\n async updateConfig(updates: Partial<Config>): Promise<{ updated: boolean; error?: string }> {\n try {\n log.debug('Updating configuration...');\n const merged = { ...this.opts.getConfig(), ...updates };\n this.opts.setConfig(merged);\n await this.writeConfigAndReloadFromDisk(merged);\n this.scheduleChannelPluginsAfterPersist();\n log.debug('Configuration updated successfully');\n return { updated: true };\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ err, errorMessage: em, phase: 'infra.config' }, `Failed to update config: ${em}`);\n return { updated: false, error: em };\n }\n }\n\n /**\n * App store (phase 1): persist `extensions.enabled` / `extensions.disabled`\n * for a bundled extension. Marketplace-only extensions hot-load on enable;\n * disable still needs a gateway restart to unload.\n */\n async setBundledExtensionActivationTarget(\n extensionId: string,\n wanted: boolean,\n ): Promise<{ ok: boolean; error?: string; requiresGatewayRestart: boolean }> {\n const loader = this.opts.getExtensionLoader();\n if (!loader) {\n return { ok: false, error: 'Extension loader unavailable', requiresGatewayRestart: false };\n }\n const id = extensionId.trim();\n if (!id) {\n return { ok: false, error: 'Invalid extension id', requiresGatewayRestart: false };\n }\n const patch = computeBundledExtensionExtensionsPatch(loader, this.opts.getConfig(), id, wanted);\n if (patch.ok === false) {\n return { ok: false, error: patch.error, requiresGatewayRestart: false };\n }\n const newConfig = { ...this.opts.getConfig(), extensions: patch.extensions } as Config;\n const saved = await this.saveConfig(newConfig);\n if (!saved.saved) {\n return { ok: false, error: saved.error ?? 'Failed to save config', requiresGatewayRestart: false };\n }\n loader.setConfig(this.opts.getConfig() as unknown as SurfaceConfig);\n\n let requiresGatewayRestart = true;\n if (wanted) {\n try {\n loader.invalidateManifestCache();\n await loader.loadByActivationPlan();\n requiresGatewayRestart = false;\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn(\n { err, extensionId: id, errorMessage: em },\n `Extension hot-load after bundled activation failed: ${em}`,\n );\n requiresGatewayRestart = true;\n }\n }\n\n this.opts.emit('config.reload', { section: 'extensions', source: 'bundled-activation' });\n return { ok: true, requiresGatewayRestart };\n }\n\n // ── QR-login follow-ups (bypass fs watcher) ────────────────────────────\n\n async afterWeixinCredentialsPersisted(): Promise<void> {\n const next = loadConfig(this.opts.configPath);\n this.opts.setConfig(next);\n this.opts.getAgentService().applyAgentDefaultsFromConfig(next);\n this.configReloader?.syncCurrentConfig(next);\n await this.handleChannelsReload(next);\n const { weixinPlugin } = await import('../../channels/weixin/index.js');\n await weixinPlugin.reloadMonitorsWithConfig(this.opts.getConfig(), this.opts.bus);\n log.info('Weixin monitors restarted after credential login');\n }\n\n async afterFeishuCredentialsPersisted(): Promise<void> {\n const next = loadConfig(this.opts.configPath);\n this.opts.setConfig(next);\n this.opts.getAgentService().applyAgentDefaultsFromConfig(next);\n this.configReloader?.syncCurrentConfig(next);\n await this.handleChannelsReload(next);\n log.info('Feishu config applied after QR setup');\n }\n\n // ── Section reload handlers (also used by manual triggers) ─────────────\n\n /**\n * Apply `latest.channels` to every registered channel plugin (Telegram,\n * Weixin, extensions). Single runtime path for: file watcher hot reload, API\n * saves, and Weixin QR follow-up.\n */\n async handleChannelsReload(newConfig: Config): Promise<void> {\n log.debug('Reloading channels config...');\n this.opts.setConfig(newConfig);\n await this.opts.getChannelManager().updateConfig(newConfig);\n this.opts.emit('config.reload', { section: 'channels' });\n this.opts.emit('channels.status', { channels: this.opts.getChannelsStatus() });\n log.debug('Channels config reloaded');\n }\n\n /**\n * Apply `gateway.heartbeat` from current config after PATCH /api/config (and\n * when hot reload is off). File watcher uses `handleHeartbeatReload` with\n * the same effect when paths match.\n */\n reloadHeartbeatFromCurrentConfig(): void {\n this.handleHeartbeatReload(this.opts.getConfig());\n }\n\n // ── Internals ──────────────────────────────────────────────────────────\n\n private handleModelsReload(newConfig: Config): void {\n log.debug('Reloading models config...');\n this.opts.setConfig(newConfig);\n getModelRegistry().refresh();\n this.opts.emit('config.reload', { section: 'models' });\n log.debug('Models config reloaded');\n }\n\n private handleAgentDefaultsReload(newConfig: Config): void {\n log.debug('Reloading agent defaults...');\n this.opts.setConfig(newConfig);\n this.opts.getAgentService().applyAgentDefaultsFromConfig(newConfig);\n void this.opts.reconcileBrowserExtensionServer();\n this.opts.emit('config.reload', { section: 'agents' });\n log.debug('Agent defaults reloaded');\n }\n\n /**\n * Coalesces rapid saves so Telegram/Weixin do not stop/start repeatedly.\n * The persist path schedules the channel apply; the same coalescer absorbs\n * follow-up saves until the first flush settles.\n */\n private scheduleChannelPluginsAfterPersist(): void {\n this.channelReloadPending = true;\n if (this.channelReloadFlushPromise) return;\n this.channelReloadFlushPromise = (async () => {\n try {\n while (this.channelReloadPending) {\n this.channelReloadPending = false;\n await this.handleChannelsReload(this.opts.getConfig());\n }\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ err, errorMessage: em }, `Channel reload after persist failed: ${em}`);\n } finally {\n this.channelReloadFlushPromise = null;\n if (this.channelReloadPending) {\n this.scheduleChannelPluginsAfterPersist();\n }\n }\n })();\n }\n\n private handleCronReload(newConfig: Config): void {\n log.debug('Reloading cron config...');\n this.opts.setConfig(newConfig);\n this.opts.getCronService().updateConfig(newConfig);\n this.opts.emit('config.reload', { section: 'cron' });\n log.debug('Cron config reloaded');\n }\n\n private handleHeartbeatReload(newConfig: Config): void {\n log.debug('Reloading heartbeat config...');\n this.opts.setConfig(newConfig);\n this.opts.getHeartbeatService()?.updateConfig(newConfig);\n this.opts.emit('config.reload', { section: 'heartbeat' });\n log.debug('Heartbeat config reloaded');\n }\n\n private handleToolsReload(newConfig: Config): void {\n log.debug('Reloading tools config...');\n this.opts.setConfig(newConfig);\n this.opts.emit('config.reload', { section: 'tools' });\n log.debug('Tools config reloaded');\n }\n\n private handleMcpReload(newConfig: Config): void {\n log.debug('Reloading MCP config...');\n this.opts.setConfig(newConfig);\n void disposeAllSessionMcpRuntimes().catch((err) => {\n log.warn({ err }, 'MCP runtime dispose on config reload failed');\n });\n this.opts.emit('config.reload', { section: 'mcp' });\n log.debug('MCP config reloaded');\n }\n\n /** Dispatch config hot reload to extensions that registered `registerReload`. */\n private async handleExtensionsReload(\n newConfig: Config,\n changedPaths: string[],\n ): Promise<void> {\n this.opts.setConfig(newConfig);\n const loader = this.opts.getExtensionLoader();\n loader?.setConfig(newConfig as unknown as SurfaceConfig);\n\n if (!loader) {\n this.opts.emit('config.reload', {\n section: 'extensions',\n source: 'extension-reload',\n changedPaths,\n });\n return;\n }\n\n const registry = loader.getRegistry();\n const matchingRegs = registry.getMatchingReloadRegistrations(changedPaths);\n\n if (matchingRegs.length === 0) {\n log.debug({ changedPaths }, 'No extension reload handlers matched');\n this.opts.emit('config.reload', {\n section: 'extensions',\n source: 'extension-reload',\n changedPaths,\n });\n return;\n }\n\n for (const reg of matchingRegs) {\n const relevantPaths = changedPaths.filter(\n (p) =>\n reg.configPrefixes.length === 0 ||\n reg.configPrefixes.some(\n (prefix) => p === prefix || p.startsWith(`${prefix}.`),\n ),\n );\n\n log.info(\n { extensionId: reg.extensionId, relevantPaths },\n 'Calling extension reload handler',\n );\n\n try {\n const result = await reg.handler(newConfig, relevantPaths);\n if (result.success) {\n log.info({ extensionId: reg.extensionId }, 'Extension reload succeeded');\n } else {\n log.warn(\n { extensionId: reg.extensionId, error: result.error },\n `Extension reload reported failure: ${result.error ?? 'unknown'}`,\n );\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n log.error(\n { err, extensionId: reg.extensionId, errorMessage },\n `Extension reload handler threw: ${errorMessage}`,\n );\n }\n }\n\n this.opts.emit('config.reload', {\n section: 'extensions',\n source: 'extension-reload',\n changedPaths,\n });\n }\n\n /**\n * Persist and replace `currentConfig` with the validated file contents so\n * runtime matches disk (PATCH merge objects can drift from Zod-normalized\n * output).\n */\n private async writeConfigAndReloadFromDisk(configToWrite: Config): Promise<void> {\n await writeConfigToDisk(configToWrite, this.opts.configPath);\n const reloaded = loadConfig(this.opts.configPath);\n this.opts.setConfig(reloaded);\n if (sanitizeTunnelConfig(reloaded)) {\n await writeConfigToDisk(reloaded, this.opts.configPath);\n }\n this.opts.getAgentService().applyAgentDefaultsFromConfig(reloaded);\n await this.opts.reconcileBrowserExtensionServer();\n // Hot-apply: reconcile managed dreaming cron jobs immediately after config persists.\n await this.opts.getAgentService().reconcileDreamingNow().catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, errorMessage: em }, `Dreaming cron reconcile after save failed: ${em}`);\n });\n // Align watcher baseline before channel hooks run so fs `change` does not\n // re-apply the same diff concurrently.\n this.configReloader?.syncCurrentConfig(reloaded);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config-coordinator.js","names":["writeConfigToDisk"],"sources":["../../../../src/gateway/service/config-coordinator.ts"],"sourcesContent":["/**\n * GatewayConfigCoordinator — owns config persistence, hot-reload, and the\n * per-section reload handlers.\n *\n * Was 350 lines of `GatewayService` covering nine concerns:\n * - manual `reloadConfig()` (CLI/UI trigger)\n * - `saveConfig()` / `updateConfig()` (PATCH /api/config)\n * - `setBundledExtensionActivationTarget` (extension store install)\n * - `afterWeixinCredentialsPersisted` / `afterFeishuCredentialsPersisted`\n * (QR-login follow-ups that bypass the watcher)\n * - `ConfigHotReloader` (fs.watch → debounced per-section dispatch)\n * - Section reload handlers (models / agents / channels /\n * heartbeat / tools / mcp / extensions)\n * - `scheduleChannelPluginsAfterPersist` (coalesces rapid saves so\n * Telegram/Weixin do not stop/start repeatedly)\n *\n * Pulled out so the gateway composition root stays focused on lifecycle, and\n * each handler is reachable from one place when adding a new config section.\n *\n * **Config state ownership.** `GatewayService.config` is still the single\n * source of truth — this coordinator reads it via `getConfig()` and writes it\n * back via `setConfig()` after every reload / persist. We pass through rather\n * than holding our own copy so other coordinators (sessions, marketplace,\n * agent runner) see the latest config the moment a reload commits.\n */\nimport type { Config } from '../../config/schema.js';\nimport type { Config as SurfaceConfig } from '../../config/config-surface.js';\nimport type { AgentService } from '../../agent/service.js';\nimport type { ChannelManager } from '../../channels/manager.js';\nimport type { HeartbeatService } from '../heartbeat/index.js';\nimport type { ExtensionLoader } from '../../extensions/loader.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport { ConfigHotReloader } from '../../config/reload.js';\nimport { loadConfig, saveConfig as writeConfigToDisk } from '../../config/index.js';\nimport { sanitizeTunnelConfig } from '../../tunnel/tunnel-config.js';\nimport { getModelRegistry } from '../../providers/index.js';\nimport { disposeAllSessionMcpRuntimes } from '../../agent/mcp/bundle-mcp-tools.js';\nimport { computeBundledExtensionExtensionsPatch } from '../../extensions/bundled-extension-activation.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('GatewayConfigCoordinator');\n\nexport interface GatewayConfigCoordinatorOptions {\n configPath: string;\n bus: MessageBus;\n /** Hot reload (fs.watch) — disabled in tests / certain CLI modes. */\n enableHotReload: boolean;\n getConfig: () => Config;\n /** Writes the new config back into `GatewayService.config`. */\n setConfig: (next: Config) => void;\n getAgentService: () => AgentService;\n getChannelManager: () => ChannelManager;\n getHeartbeatService: () => HeartbeatService | null;\n getExtensionLoader: () => ExtensionLoader | null;\n /** Re-evaluate browser-extension server attachment after agent defaults change. */\n reconcileBrowserExtensionServer: () => Promise<void>;\n /** Sync built-in dreaming automations after memory.dreaming changes. */\n reconcileDreamingAutomations: () => Promise<void>;\n /** Latest channel status snapshot for the `channels.status` SSE event. */\n getChannelsStatus: () => unknown;\n /** SSE emit (used for `config.reload` + `channels.status`). */\n emit: (type: string, payload: unknown) => void;\n}\n\nexport class GatewayConfigCoordinator {\n private readonly opts: GatewayConfigCoordinatorOptions;\n private configReloader: ConfigHotReloader | null = null;\n private channelReloadFlushPromise: Promise<void> | null = null;\n private channelReloadPending = false;\n\n constructor(opts: GatewayConfigCoordinatorOptions) {\n this.opts = opts;\n }\n\n // ── Lifecycle ──────────────────────────────────────────────────────────\n\n /** Start the fs.watch-based reloader (idempotent — only starts once). */\n startHotReloader(): void {\n if (this.configReloader) return;\n this.configReloader = new ConfigHotReloader(\n this.opts.configPath,\n this.opts.getConfig(),\n {\n onModelsReload: (newConfig) => this.handleModelsReload(newConfig),\n onAgentDefaultsReload: (newConfig) => this.handleAgentDefaultsReload(newConfig),\n onChannelsReload: (newConfig) => this.handleChannelsReload(newConfig),\n onCronReload: (newConfig) => this.handleAutomationReload(newConfig),\n onHeartbeatReload: (newConfig) => this.handleHeartbeatReload(newConfig),\n onToolsReload: (newConfig) => this.handleToolsReload(newConfig),\n onMcpReload: (newConfig) => this.handleMcpReload(newConfig),\n onExtensionsReload: async (newConfig, changedPaths) => {\n await this.handleExtensionsReload(newConfig, changedPaths);\n },\n onFullRestart: (newConfig) => {\n log.warn(\n { requiresProcessRestart: true, hint: 'Restart the gateway process (hot reload cannot apply this change).' },\n 'Config reload: full gateway restart required — see prior \"restartPaths\" info log',\n );\n this.opts.setConfig(newConfig);\n this.opts.emit('config.reload', { section: 'full', requiresRestart: true });\n },\n },\n {\n debounceMs: 300,\n enabled: this.opts.enableHotReload,\n }\n );\n this.configReloader.start();\n }\n\n async stopHotReloader(): Promise<void> {\n if (this.configReloader) {\n await this.configReloader.stop();\n this.configReloader = null;\n }\n }\n\n // ── Manual reload (UI trigger) ─────────────────────────────────────────\n\n async reloadConfig(): Promise<{ reloaded: boolean; error?: string }> {\n if (!this.configReloader) {\n return { reloaded: false, error: 'Config reloader not initialized' };\n }\n const result = await this.configReloader.triggerReload();\n return { reloaded: result.success, error: result.error };\n }\n\n // ── Persist (PATCH /api/config, marketplace install, etc.) ─────────────\n\n async saveConfig(config: Config): Promise<{ saved: boolean; error?: string }> {\n try {\n await this.writeConfigAndReloadFromDisk(config);\n this.scheduleChannelPluginsAfterPersist();\n return { saved: true };\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ err, errorMessage: em, phase: 'infra.config' }, `Failed to save config: ${em}`);\n return { saved: false, error: em };\n }\n }\n\n /** Merge partial updates into `currentConfig` and persist. */\n async updateConfig(updates: Partial<Config>): Promise<{ updated: boolean; error?: string }> {\n try {\n log.debug('Updating configuration...');\n const merged = { ...this.opts.getConfig(), ...updates };\n this.opts.setConfig(merged);\n await this.writeConfigAndReloadFromDisk(merged);\n this.scheduleChannelPluginsAfterPersist();\n log.debug('Configuration updated successfully');\n return { updated: true };\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ err, errorMessage: em, phase: 'infra.config' }, `Failed to update config: ${em}`);\n return { updated: false, error: em };\n }\n }\n\n /**\n * App store (phase 1): persist `extensions.enabled` / `extensions.disabled`\n * for a bundled extension. Marketplace-only extensions hot-load on enable;\n * disable still needs a gateway restart to unload.\n */\n async setBundledExtensionActivationTarget(\n extensionId: string,\n wanted: boolean,\n ): Promise<{ ok: boolean; error?: string; requiresGatewayRestart: boolean }> {\n const loader = this.opts.getExtensionLoader();\n if (!loader) {\n return { ok: false, error: 'Extension loader unavailable', requiresGatewayRestart: false };\n }\n const id = extensionId.trim();\n if (!id) {\n return { ok: false, error: 'Invalid extension id', requiresGatewayRestart: false };\n }\n const patch = computeBundledExtensionExtensionsPatch(loader, this.opts.getConfig(), id, wanted);\n if (patch.ok === false) {\n return { ok: false, error: patch.error, requiresGatewayRestart: false };\n }\n const newConfig = { ...this.opts.getConfig(), extensions: patch.extensions } as Config;\n const saved = await this.saveConfig(newConfig);\n if (!saved.saved) {\n return { ok: false, error: saved.error ?? 'Failed to save config', requiresGatewayRestart: false };\n }\n loader.setConfig(this.opts.getConfig() as unknown as SurfaceConfig);\n\n let requiresGatewayRestart = true;\n if (wanted) {\n try {\n loader.invalidateManifestCache();\n await loader.loadByActivationPlan();\n requiresGatewayRestart = false;\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn(\n { err, extensionId: id, errorMessage: em },\n `Extension hot-load after bundled activation failed: ${em}`,\n );\n requiresGatewayRestart = true;\n }\n }\n\n this.opts.emit('config.reload', { section: 'extensions', source: 'bundled-activation' });\n return { ok: true, requiresGatewayRestart };\n }\n\n // ── QR-login follow-ups (bypass fs watcher) ────────────────────────────\n\n async afterWeixinCredentialsPersisted(): Promise<void> {\n const next = loadConfig(this.opts.configPath);\n this.opts.setConfig(next);\n this.opts.getAgentService().applyAgentDefaultsFromConfig(next);\n this.configReloader?.syncCurrentConfig(next);\n await this.handleChannelsReload(next);\n const { weixinPlugin } = await import('../../channels/weixin/index.js');\n await weixinPlugin.reloadMonitorsWithConfig(this.opts.getConfig(), this.opts.bus);\n log.info('Weixin monitors restarted after credential login');\n }\n\n async afterFeishuCredentialsPersisted(): Promise<void> {\n const next = loadConfig(this.opts.configPath);\n this.opts.setConfig(next);\n this.opts.getAgentService().applyAgentDefaultsFromConfig(next);\n this.configReloader?.syncCurrentConfig(next);\n await this.handleChannelsReload(next);\n log.info('Feishu config applied after QR setup');\n }\n\n // ── Section reload handlers (also used by manual triggers) ─────────────\n\n /**\n * Apply `latest.channels` to every registered channel plugin (Telegram,\n * Weixin, extensions). Single runtime path for: file watcher hot reload, API\n * saves, and Weixin QR follow-up.\n */\n async handleChannelsReload(newConfig: Config): Promise<void> {\n log.debug('Reloading channels config...');\n this.opts.setConfig(newConfig);\n await this.opts.getChannelManager().updateConfig(newConfig);\n this.opts.emit('config.reload', { section: 'channels' });\n this.opts.emit('channels.status', { channels: this.opts.getChannelsStatus() });\n log.debug('Channels config reloaded');\n }\n\n /**\n * Apply `gateway.heartbeat` from current config after PATCH /api/config (and\n * when hot reload is off). File watcher uses `handleHeartbeatReload` with\n * the same effect when paths match.\n */\n reloadHeartbeatFromCurrentConfig(): void {\n this.handleHeartbeatReload(this.opts.getConfig());\n }\n\n // ── Internals ──────────────────────────────────────────────────────────\n\n private handleModelsReload(newConfig: Config): void {\n log.debug('Reloading models config...');\n this.opts.setConfig(newConfig);\n getModelRegistry().refresh();\n this.opts.emit('config.reload', { section: 'models' });\n log.debug('Models config reloaded');\n }\n\n private handleAgentDefaultsReload(newConfig: Config): void {\n log.debug('Reloading agent defaults...');\n this.opts.setConfig(newConfig);\n this.opts.getAgentService().applyAgentDefaultsFromConfig(newConfig);\n void this.opts.reconcileBrowserExtensionServer();\n void this.opts.reconcileDreamingAutomations().catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, errorMessage: em }, `Dreaming automation refresh failed: ${em}`);\n });\n this.opts.emit('config.reload', { section: 'agents' });\n log.debug('Agent defaults reloaded');\n }\n\n /**\n * Coalesces rapid saves so Telegram/Weixin do not stop/start repeatedly.\n * The persist path schedules the channel apply; the same coalescer absorbs\n * follow-up saves until the first flush settles.\n */\n private scheduleChannelPluginsAfterPersist(): void {\n this.channelReloadPending = true;\n if (this.channelReloadFlushPromise) return;\n this.channelReloadFlushPromise = (async () => {\n try {\n while (this.channelReloadPending) {\n this.channelReloadPending = false;\n await this.handleChannelsReload(this.opts.getConfig());\n }\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ err, errorMessage: em }, `Channel reload after persist failed: ${em}`);\n } finally {\n this.channelReloadFlushPromise = null;\n if (this.channelReloadPending) {\n this.scheduleChannelPluginsAfterPersist();\n }\n }\n })();\n }\n\n private handleAutomationReload(newConfig: Config): void {\n log.debug('Reloading automation-related config...');\n this.opts.setConfig(newConfig);\n this.opts.emit('config.reload', { section: 'automations' });\n log.debug('Automation-related config reloaded');\n }\n\n private handleHeartbeatReload(newConfig: Config): void {\n log.debug('Reloading heartbeat config...');\n this.opts.setConfig(newConfig);\n this.opts.getHeartbeatService()?.updateConfig(newConfig);\n this.opts.emit('config.reload', { section: 'heartbeat' });\n log.debug('Heartbeat config reloaded');\n }\n\n private handleToolsReload(newConfig: Config): void {\n log.debug('Reloading tools config...');\n this.opts.setConfig(newConfig);\n this.opts.emit('config.reload', { section: 'tools' });\n log.debug('Tools config reloaded');\n }\n\n private handleMcpReload(newConfig: Config): void {\n log.debug('Reloading MCP config...');\n this.opts.setConfig(newConfig);\n void disposeAllSessionMcpRuntimes().catch((err) => {\n log.warn({ err }, 'MCP runtime dispose on config reload failed');\n });\n this.opts.emit('config.reload', { section: 'mcp' });\n log.debug('MCP config reloaded');\n }\n\n /** Dispatch config hot reload to extensions that registered `registerReload`. */\n private async handleExtensionsReload(\n newConfig: Config,\n changedPaths: string[],\n ): Promise<void> {\n this.opts.setConfig(newConfig);\n const loader = this.opts.getExtensionLoader();\n loader?.setConfig(newConfig as unknown as SurfaceConfig);\n\n if (!loader) {\n this.opts.emit('config.reload', {\n section: 'extensions',\n source: 'extension-reload',\n changedPaths,\n });\n return;\n }\n\n const registry = loader.getRegistry();\n const matchingRegs = registry.getMatchingReloadRegistrations(changedPaths);\n\n if (matchingRegs.length === 0) {\n log.debug({ changedPaths }, 'No extension reload handlers matched');\n this.opts.emit('config.reload', {\n section: 'extensions',\n source: 'extension-reload',\n changedPaths,\n });\n return;\n }\n\n for (const reg of matchingRegs) {\n const relevantPaths = changedPaths.filter(\n (p) =>\n reg.configPrefixes.length === 0 ||\n reg.configPrefixes.some(\n (prefix) => p === prefix || p.startsWith(`${prefix}.`),\n ),\n );\n\n log.info(\n { extensionId: reg.extensionId, relevantPaths },\n 'Calling extension reload handler',\n );\n\n try {\n const result = await reg.handler(newConfig, relevantPaths);\n if (result.success) {\n log.info({ extensionId: reg.extensionId }, 'Extension reload succeeded');\n } else {\n log.warn(\n { extensionId: reg.extensionId, error: result.error },\n `Extension reload reported failure: ${result.error ?? 'unknown'}`,\n );\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n log.error(\n { err, extensionId: reg.extensionId, errorMessage },\n `Extension reload handler threw: ${errorMessage}`,\n );\n }\n }\n\n this.opts.emit('config.reload', {\n section: 'extensions',\n source: 'extension-reload',\n changedPaths,\n });\n }\n\n /**\n * Persist and replace `currentConfig` with the validated file contents so\n * runtime matches disk (PATCH merge objects can drift from Zod-normalized\n * output).\n */\n private async writeConfigAndReloadFromDisk(configToWrite: Config): Promise<void> {\n await writeConfigToDisk(configToWrite, this.opts.configPath);\n const reloaded = loadConfig(this.opts.configPath);\n this.opts.setConfig(reloaded);\n if (sanitizeTunnelConfig(reloaded)) {\n await writeConfigToDisk(reloaded, this.opts.configPath);\n }\n this.opts.getAgentService().applyAgentDefaultsFromConfig(reloaded);\n await this.opts.reconcileBrowserExtensionServer();\n // Keep built-in dreaming automations aligned with memory.dreaming.\n await this.opts.reconcileDreamingAutomations().catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, errorMessage: em }, `Dreaming automation refresh after save failed: ${em}`);\n });\n // Align watcher baseline before channel hooks run so fs `change` does not\n // re-apply the same diff concurrently.\n this.configReloader?.syncCurrentConfig(reloaded);\n }\n}\n"],"mappings":";;;;;;;;;;;;gBAmC4D;aAGP;AAErD,MAAM,MAAM,aAAa,2BAA2B;AAwBpD,IAAa,2BAAb,MAAsC;CACpC;CACA,iBAAmD;CACnD,4BAA0D;CAC1D,uBAA+B;CAE/B,YAAY,MAAuC;AACjD,OAAK,OAAO;;;CAMd,mBAAyB;AACvB,MAAI,KAAK,eAAgB;AACzB,OAAK,iBAAiB,IAAI,kBACxB,KAAK,KAAK,YACV,KAAK,KAAK,WAAW,EACrB;GACE,iBAAiB,cAAc,KAAK,mBAAmB,UAAU;GACjE,wBAAwB,cAAc,KAAK,0BAA0B,UAAU;GAC/E,mBAAmB,cAAc,KAAK,qBAAqB,UAAU;GACrE,eAAe,cAAc,KAAK,uBAAuB,UAAU;GACnE,oBAAoB,cAAc,KAAK,sBAAsB,UAAU;GACvE,gBAAgB,cAAc,KAAK,kBAAkB,UAAU;GAC/D,cAAc,cAAc,KAAK,gBAAgB,UAAU;GAC3D,oBAAoB,OAAO,WAAW,iBAAiB;AACrD,UAAM,KAAK,uBAAuB,WAAW,aAAa;;GAE5D,gBAAgB,cAAc;AAC5B,QAAI,KACF;KAAE,wBAAwB;KAAM,MAAM;KAAsE,EAC5G,qFACD;AACD,SAAK,KAAK,UAAU,UAAU;AAC9B,SAAK,KAAK,KAAK,iBAAiB;KAAE,SAAS;KAAQ,iBAAiB;KAAM,CAAC;;GAE9E,EACD;GACE,YAAY;GACZ,SAAS,KAAK,KAAK;GACpB,CACF;AACD,OAAK,eAAe,OAAO;;CAG7B,MAAM,kBAAiC;AACrC,MAAI,KAAK,gBAAgB;AACvB,SAAM,KAAK,eAAe,MAAM;AAChC,QAAK,iBAAiB;;;CAM1B,MAAM,eAA+D;AACnE,MAAI,CAAC,KAAK,eACR,QAAO;GAAE,UAAU;GAAO,OAAO;GAAmC;EAEtE,MAAM,SAAS,MAAM,KAAK,eAAe,eAAe;AACxD,SAAO;GAAE,UAAU,OAAO;GAAS,OAAO,OAAO;GAAO;;CAK1D,MAAM,WAAW,QAA6D;AAC5E,MAAI;AACF,SAAM,KAAK,6BAA6B,OAAO;AAC/C,QAAK,oCAAoC;AACzC,UAAO,EAAE,OAAO,MAAM;WACf,KAAK;GACZ,MAAM,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC3D,OAAI,MAAM;IAAE;IAAK,cAAc;IAAI,OAAO;IAAgB,EAAE,0BAA0B,KAAK;AAC3F,UAAO;IAAE,OAAO;IAAO,OAAO;IAAI;;;;CAKtC,MAAM,aAAa,SAAyE;AAC1F,MAAI;AACF,OAAI,MAAM,4BAA4B;GACtC,MAAM,SAAS;IAAE,GAAG,KAAK,KAAK,WAAW;IAAE,GAAG;IAAS;AACvD,QAAK,KAAK,UAAU,OAAO;AAC3B,SAAM,KAAK,6BAA6B,OAAO;AAC/C,QAAK,oCAAoC;AACzC,OAAI,MAAM,qCAAqC;AAC/C,UAAO,EAAE,SAAS,MAAM;WACjB,KAAK;GACZ,MAAM,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC3D,OAAI,MAAM;IAAE;IAAK,cAAc;IAAI,OAAO;IAAgB,EAAE,4BAA4B,KAAK;AAC7F,UAAO;IAAE,SAAS;IAAO,OAAO;IAAI;;;;;;;;CASxC,MAAM,oCACJ,aACA,QAC2E;EAC3E,MAAM,SAAS,KAAK,KAAK,oBAAoB;AAC7C,MAAI,CAAC,OACH,QAAO;GAAE,IAAI;GAAO,OAAO;GAAgC,wBAAwB;GAAO;EAE5F,MAAM,KAAK,YAAY,MAAM;AAC7B,MAAI,CAAC,GACH,QAAO;GAAE,IAAI;GAAO,OAAO;GAAwB,wBAAwB;GAAO;EAEpF,MAAM,QAAQ,uCAAuC,QAAQ,KAAK,KAAK,WAAW,EAAE,IAAI,OAAO;AAC/F,MAAI,MAAM,OAAO,MACf,QAAO;GAAE,IAAI;GAAO,OAAO,MAAM;GAAO,wBAAwB;GAAO;EAEzE,MAAM,YAAY;GAAE,GAAG,KAAK,KAAK,WAAW;GAAE,YAAY,MAAM;GAAY;EAC5E,MAAM,QAAQ,MAAM,KAAK,WAAW,UAAU;AAC9C,MAAI,CAAC,MAAM,MACT,QAAO;GAAE,IAAI;GAAO,OAAO,MAAM,SAAS;GAAyB,wBAAwB;GAAO;AAEpG,SAAO,UAAU,KAAK,KAAK,WAAW,CAA6B;EAEnE,IAAI,yBAAyB;AAC7B,MAAI,OACF,KAAI;AACF,UAAO,yBAAyB;AAChC,SAAM,OAAO,sBAAsB;AACnC,4BAAyB;WAClB,KAAK;GACZ,MAAM,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC3D,OAAI,KACF;IAAE;IAAK,aAAa;IAAI,cAAc;IAAI,EAC1C,uDAAuD,KACxD;AACD,4BAAyB;;AAI7B,OAAK,KAAK,KAAK,iBAAiB;GAAE,SAAS;GAAc,QAAQ;GAAsB,CAAC;AACxF,SAAO;GAAE,IAAI;GAAM;GAAwB;;CAK7C,MAAM,kCAAiD;EACrD,MAAM,OAAO,WAAW,KAAK,KAAK,WAAW;AAC7C,OAAK,KAAK,UAAU,KAAK;AACzB,OAAK,KAAK,iBAAiB,CAAC,6BAA6B,KAAK;AAC9D,OAAK,gBAAgB,kBAAkB,KAAK;AAC5C,QAAM,KAAK,qBAAqB,KAAK;EACrC,MAAM,EAAE,iBAAiB,MAAM,OAAO;AACtC,QAAM,aAAa,yBAAyB,KAAK,KAAK,WAAW,EAAE,KAAK,KAAK,IAAI;AACjF,MAAI,KAAK,mDAAmD;;CAG9D,MAAM,kCAAiD;EACrD,MAAM,OAAO,WAAW,KAAK,KAAK,WAAW;AAC7C,OAAK,KAAK,UAAU,KAAK;AACzB,OAAK,KAAK,iBAAiB,CAAC,6BAA6B,KAAK;AAC9D,OAAK,gBAAgB,kBAAkB,KAAK;AAC5C,QAAM,KAAK,qBAAqB,KAAK;AACrC,MAAI,KAAK,uCAAuC;;;;;;;CAUlD,MAAM,qBAAqB,WAAkC;AAC3D,MAAI,MAAM,+BAA+B;AACzC,OAAK,KAAK,UAAU,UAAU;AAC9B,QAAM,KAAK,KAAK,mBAAmB,CAAC,aAAa,UAAU;AAC3D,OAAK,KAAK,KAAK,iBAAiB,EAAE,SAAS,YAAY,CAAC;AACxD,OAAK,KAAK,KAAK,mBAAmB,EAAE,UAAU,KAAK,KAAK,mBAAmB,EAAE,CAAC;AAC9E,MAAI,MAAM,2BAA2B;;;;;;;CAQvC,mCAAyC;AACvC,OAAK,sBAAsB,KAAK,KAAK,WAAW,CAAC;;CAKnD,mBAA2B,WAAyB;AAClD,MAAI,MAAM,6BAA6B;AACvC,OAAK,KAAK,UAAU,UAAU;AAC9B,oBAAkB,CAAC,SAAS;AAC5B,OAAK,KAAK,KAAK,iBAAiB,EAAE,SAAS,UAAU,CAAC;AACtD,MAAI,MAAM,yBAAyB;;CAGrC,0BAAkC,WAAyB;AACzD,MAAI,MAAM,8BAA8B;AACxC,OAAK,KAAK,UAAU,UAAU;AAC9B,OAAK,KAAK,iBAAiB,CAAC,6BAA6B,UAAU;AAC9D,OAAK,KAAK,iCAAiC;AAC3C,OAAK,KAAK,8BAA8B,CAAC,OAAO,QAAQ;GAC3D,MAAM,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC3D,OAAI,KAAK;IAAE;IAAK,cAAc;IAAI,EAAE,uCAAuC,KAAK;IAChF;AACF,OAAK,KAAK,KAAK,iBAAiB,EAAE,SAAS,UAAU,CAAC;AACtD,MAAI,MAAM,0BAA0B;;;;;;;CAQtC,qCAAmD;AACjD,OAAK,uBAAuB;AAC5B,MAAI,KAAK,0BAA2B;AACpC,OAAK,6BAA6B,YAAY;AAC5C,OAAI;AACF,WAAO,KAAK,sBAAsB;AAChC,UAAK,uBAAuB;AAC5B,WAAM,KAAK,qBAAqB,KAAK,KAAK,WAAW,CAAC;;YAEjD,KAAK;IACZ,MAAM,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC3D,QAAI,MAAM;KAAE;KAAK,cAAc;KAAI,EAAE,wCAAwC,KAAK;aAC1E;AACR,SAAK,4BAA4B;AACjC,QAAI,KAAK,qBACP,MAAK,oCAAoC;;MAG3C;;CAGN,uBAA+B,WAAyB;AACtD,MAAI,MAAM,yCAAyC;AACnD,OAAK,KAAK,UAAU,UAAU;AAC9B,OAAK,KAAK,KAAK,iBAAiB,EAAE,SAAS,eAAe,CAAC;AAC3D,MAAI,MAAM,qCAAqC;;CAGjD,sBAA8B,WAAyB;AACrD,MAAI,MAAM,gCAAgC;AAC1C,OAAK,KAAK,UAAU,UAAU;AAC9B,OAAK,KAAK,qBAAqB,EAAE,aAAa,UAAU;AACxD,OAAK,KAAK,KAAK,iBAAiB,EAAE,SAAS,aAAa,CAAC;AACzD,MAAI,MAAM,4BAA4B;;CAGxC,kBAA0B,WAAyB;AACjD,MAAI,MAAM,4BAA4B;AACtC,OAAK,KAAK,UAAU,UAAU;AAC9B,OAAK,KAAK,KAAK,iBAAiB,EAAE,SAAS,SAAS,CAAC;AACrD,MAAI,MAAM,wBAAwB;;CAGpC,gBAAwB,WAAyB;AAC/C,MAAI,MAAM,0BAA0B;AACpC,OAAK,KAAK,UAAU,UAAU;AACzB,gCAA8B,CAAC,OAAO,QAAQ;AACjD,OAAI,KAAK,EAAE,KAAK,EAAE,8CAA8C;IAChE;AACF,OAAK,KAAK,KAAK,iBAAiB,EAAE,SAAS,OAAO,CAAC;AACnD,MAAI,MAAM,sBAAsB;;;CAIlC,MAAc,uBACZ,WACA,cACe;AACf,OAAK,KAAK,UAAU,UAAU;EAC9B,MAAM,SAAS,KAAK,KAAK,oBAAoB;AAC7C,UAAQ,UAAU,UAAsC;AAExD,MAAI,CAAC,QAAQ;AACX,QAAK,KAAK,KAAK,iBAAiB;IAC9B,SAAS;IACT,QAAQ;IACR;IACD,CAAC;AACF;;EAIF,MAAM,eADW,OAAO,aACK,CAAC,+BAA+B,aAAa;AAE1E,MAAI,aAAa,WAAW,GAAG;AAC7B,OAAI,MAAM,EAAE,cAAc,EAAE,uCAAuC;AACnE,QAAK,KAAK,KAAK,iBAAiB;IAC9B,SAAS;IACT,QAAQ;IACR;IACD,CAAC;AACF;;AAGF,OAAK,MAAM,OAAO,cAAc;GAC9B,MAAM,gBAAgB,aAAa,QAChC,MACC,IAAI,eAAe,WAAW,KAC9B,IAAI,eAAe,MAChB,WAAW,MAAM,UAAU,EAAE,WAAW,GAAG,OAAO,GAAG,CACvD,CACJ;AAED,OAAI,KACF;IAAE,aAAa,IAAI;IAAa;IAAe,EAC/C,mCACD;AAED,OAAI;IACF,MAAM,SAAS,MAAM,IAAI,QAAQ,WAAW,cAAc;AAC1D,QAAI,OAAO,QACT,KAAI,KAAK,EAAE,aAAa,IAAI,aAAa,EAAE,6BAA6B;QAExE,KAAI,KACF;KAAE,aAAa,IAAI;KAAa,OAAO,OAAO;KAAO,EACrD,sCAAsC,OAAO,SAAS,YACvD;YAEI,KAAK;IACZ,MAAM,eAAe,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AACrE,QAAI,MACF;KAAE;KAAK,aAAa,IAAI;KAAa;KAAc,EACnD,mCAAmC,eACpC;;;AAIL,OAAK,KAAK,KAAK,iBAAiB;GAC9B,SAAS;GACT,QAAQ;GACR;GACD,CAAC;;;;;;;CAQJ,MAAc,6BAA6B,eAAsC;AAC/E,QAAMA,WAAkB,eAAe,KAAK,KAAK,WAAW;EAC5D,MAAM,WAAW,WAAW,KAAK,KAAK,WAAW;AACjD,OAAK,KAAK,UAAU,SAAS;AAC7B,MAAI,qBAAqB,SAAS,CAChC,OAAMA,WAAkB,UAAU,KAAK,KAAK,WAAW;AAEzD,OAAK,KAAK,iBAAiB,CAAC,6BAA6B,SAAS;AAClE,QAAM,KAAK,KAAK,iCAAiC;AAEjD,QAAM,KAAK,KAAK,8BAA8B,CAAC,OAAO,QAAQ;GAC5D,MAAM,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC3D,OAAI,KAAK;IAAE;IAAK,cAAc;IAAI,EAAE,kDAAkD,KAAK;IAC3F;AAGF,OAAK,gBAAgB,kBAAkB,SAAS"}
|
|
@@ -64,6 +64,7 @@ export declare class GatewaySessionsApi {
|
|
|
64
64
|
nextBeforeCursor?: string;
|
|
65
65
|
};
|
|
66
66
|
}>;
|
|
67
|
+
getTimeline(key: string): Promise<import("../../session/transcript-outline.js").SessionTimelineItem[]>;
|
|
67
68
|
patch(key: string, body: SessionPatchBody): Promise<{
|
|
68
69
|
ok: true;
|
|
69
70
|
} | {
|
|
@@ -142,7 +143,7 @@ export declare class GatewaySessionsApi {
|
|
|
142
143
|
}>;
|
|
143
144
|
stats(): Promise<import("../../session/types.js").GlobalSessionStats>;
|
|
144
145
|
/**
|
|
145
|
-
* Distinct chat-id pairs from sessions, grouped by channel. Used by
|
|
146
|
+
* Distinct chat-id pairs from sessions, grouped by channel. Used by automation
|
|
146
147
|
* configuration UI to seed the "send to existing chat" picker.
|
|
147
148
|
*/
|
|
148
149
|
chatIds(channel?: string): Promise<Array<{
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { retireSessionMcpRuntimeForSessionKey } from "../../agent/mcp/bundle-mcp-runtime.js";
|
|
2
2
|
import "../../agent/mcp/bundle-mcp-tools.js";
|
|
3
|
+
import { buildSessionTimeline } from "../../session/transcript-outline.js";
|
|
3
4
|
import { collectMediaUrisFromMessages, deleteMediaUris } from "../../media/session-references.js";
|
|
4
5
|
import { getDistinctSessionChatIds } from "./session-chat-ids.js";
|
|
5
6
|
import { performSessionReset } from "../session-reset-service.js";
|
|
@@ -44,6 +45,10 @@ var GatewaySessionsApi = class {
|
|
|
44
45
|
getMessagePage(key, options) {
|
|
45
46
|
return this.opts.sessionIndex.getSessionMessagePage(key, options);
|
|
46
47
|
}
|
|
48
|
+
async getTimeline(key) {
|
|
49
|
+
if (!await this.opts.sessionIndex.getSessionMetadata(key)) return null;
|
|
50
|
+
return buildSessionTimeline(await this.opts.sessionIndex.getStore().loadTranscriptRows(key));
|
|
51
|
+
}
|
|
47
52
|
patch(key, body) {
|
|
48
53
|
return this.opts.sessionIndex.patchSession(key, body);
|
|
49
54
|
}
|
|
@@ -156,7 +161,7 @@ var GatewaySessionsApi = class {
|
|
|
156
161
|
return this.opts.sessionIndex.getStats();
|
|
157
162
|
}
|
|
158
163
|
/**
|
|
159
|
-
* Distinct chat-id pairs from sessions, grouped by channel. Used by
|
|
164
|
+
* Distinct chat-id pairs from sessions, grouped by channel. Used by automation
|
|
160
165
|
* configuration UI to seed the "send to existing chat" picker.
|
|
161
166
|
*/
|
|
162
167
|
chatIds(channel) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions-api.js","names":[],"sources":["../../../../src/gateway/service/sessions-api.ts"],"sourcesContent":["/**\n * GatewaySessionsApi — session CRUD, search, compaction, tag/pin/archive,\n * stats, and chat-id grouping for the gateway REST surface.\n *\n * Twenty-four methods, previously sitting on `GatewayService` as a mix of\n * one-line `sessionIndex.*` delegations and small composite operations (e.g.\n * `restoreCheckpoint` also evicts the in-memory agent, `runCompaction` also\n * appends a transcript context entry). Centralising them here lets routes\n * depend on the narrow `GatewaySessionsApi` surface instead of the full\n * `GatewayService`, and keeps the gateway composition root focused on\n * lifecycle + wiring.\n */\n\nimport type { AgentService } from '../../agent/service.js';\nimport type { CompactionResult } from '../../agent/memory/compaction.js';\nimport { retireSessionMcpRuntimeForSessionKey } from '../../agent/mcp/bundle-mcp-tools.js';\nimport { SessionIndex } from '../../session/index.js';\nimport type { ExportFormat, SessionListQuery } from '../../session/types.js';\nimport type { SessionPatchBody } from '../../session/patch-metadata.js';\nimport { collectMediaUrisFromMessages, deleteMediaUris } from '../../media/session-references.js';\nimport { getDistinctSessionChatIds } from './session-chat-ids.js';\nimport { performSessionReset, type SessionResetResult } from '../session-reset-service.js';\n\nexport interface GatewaySessionsApiOptions {\n sessionIndex: SessionIndex;\n /** Resolves the live agent service (created lazily; throws if gateway is starting). */\n getAgentService: () => AgentService;\n /** Read-only view of in-flight webchat runs (per session key → run id). */\n getActiveWebchatRunId: (sessionKey: string) => string | undefined;\n}\n\nexport class GatewaySessionsApi {\n private readonly opts: GatewaySessionsApiOptions;\n\n constructor(opts: GatewaySessionsApiOptions) {\n this.opts = opts;\n }\n\n // ── List / get ─────────────────────────────────────────────────────────\n\n listSessions(query?: SessionListQuery) {\n return this.opts.sessionIndex.listSessions(query);\n }\n\n /** Subagent sessions have keys starting with `subagent:`. */\n listSubagents(query?: SessionListQuery) {\n return this.opts.sessionIndex.listSubagents(query);\n }\n\n getSession(\n key: string,\n options?: { includeTranscriptSummary?: boolean; includeTranscriptRows?: boolean },\n ) {\n return this.opts.sessionIndex.getSession(key, options);\n }\n\n async resolveSession(input: {\n key?: string;\n sessionKey?: string;\n sessionId?: string;\n }): Promise<\n | {\n sessionKey: string;\n sessionId: string;\n session: Awaited<ReturnType<GatewaySessionsApi['getSession']>>;\n }\n | null\n > {\n const explicitKey = input.sessionKey?.trim() || input.key?.trim();\n const resolvedKey =\n explicitKey ||\n (input.sessionId?.trim()\n ? await this.opts.sessionIndex.resolveSessionKeyBySessionId(input.sessionId.trim())\n : null);\n if (!resolvedKey) {\n return null;\n }\n const session = await this.getSession(resolvedKey);\n if (!session?.sessionId) {\n return null;\n }\n return { sessionKey: resolvedKey, sessionId: session.sessionId, session };\n }\n\n /** Read-only: in-flight webchat agent run for this session key, if any. */\n getActiveRun(sessionKey: string): { active: boolean; runId?: string } {\n const key = sessionKey.trim();\n if (!key) return { active: false };\n const runId = this.opts.getActiveWebchatRunId(key)?.trim();\n if (!runId) return { active: false };\n return { active: true, runId };\n }\n\n getMessagePage(\n key: string,\n options?: {\n offset?: number;\n limit?: number;\n before?: string;\n includeTranscriptSummary?: boolean;\n includeTranscriptRows?: boolean;\n },\n ) {\n return this.opts.sessionIndex.getSessionMessagePage(key, options);\n }\n\n // ── Metadata patches ──────────────────────────────────────────────────\n\n patch(key: string, body: SessionPatchBody): Promise<{ ok: true } | { ok: false; error: string }> {\n return this.opts.sessionIndex.patchSession(key, body);\n }\n\n async getAgentConfig(sessionKey: string) {\n return this.opts.getAgentService().sessionInspector.agentConfig(sessionKey);\n }\n\n /** Resolved markdown workspace for a session (after hydration / mkdir). */\n getEffectiveWorkspacePath(sessionKey: string): Promise<string> {\n return this.opts.getAgentService().getEffectiveWorkspacePathForSession(sessionKey);\n }\n\n patchAgentConfig(\n sessionKey: string,\n body: {\n thinkingLevel?: string;\n model?: string | null;\n reasoningLevel?: string;\n verboseLevel?: string;\n workingDirectory?: string;\n },\n ) {\n return this.opts.getAgentService().sessionConfig.patch(sessionKey, body);\n }\n\n // ── Compaction checkpoints ────────────────────────────────────────────\n\n listCompactionCheckpoints(key: string) {\n return this.opts.sessionIndex.listCompactionCheckpoints(key);\n }\n\n getCompactionCheckpoint(key: string, checkpointId: string) {\n return this.opts.sessionIndex.getCompactionCheckpointDetail(key, checkpointId);\n }\n\n async restoreCompactionCheckpoint(key: string, checkpointId: string): Promise<void> {\n await this.opts.sessionIndex.restoreCompactionCheckpoint(key, checkpointId);\n this.opts.getAgentService().evictSessionAgent(key);\n }\n\n async runCompaction(\n key: string,\n options?: { instructions?: string; force?: boolean },\n ): Promise<CompactionResult> {\n const result = await this.opts.getAgentService().sessionInspector.compact(key, options);\n if (result.compacted) {\n void this.opts.sessionIndex\n .appendTranscriptContextEntry(key, {\n text: 'Session transcript compacted',\n data: {\n firstKeptIndex: result.firstKeptIndex,\n tokensBefore: result.tokensBefore,\n tokensAfter: result.tokensAfter,\n summaryPreview: result.summary.slice(0, 500),\n },\n })\n .catch(() => {});\n }\n return result;\n }\n\n // ── Lifecycle (delete / rename / tag / pin / archive) ─────────────────\n\n async delete(key: string): Promise<{ deleted: boolean }> {\n const messages = await this.opts.sessionIndex.loadMessages(key).catch(() => []);\n const result = await this.opts.sessionIndex.deleteSession(key);\n if (result) {\n await deleteMediaUris(collectMediaUrisFromMessages(messages));\n this.opts.getAgentService().evictSessionAgent(key);\n await retireSessionMcpRuntimeForSessionKey({ sessionKey: key, reason: 'session-delete' });\n }\n return { deleted: result };\n }\n\n /** Reset transcript in place (archive + new session id); preserves session key and overrides. */\n reset(key: string): Promise<SessionResetResult> {\n return performSessionReset(key, {\n sessionIndex: this.opts.sessionIndex,\n getAgentService: this.opts.getAgentService,\n });\n }\n\n deleteMany(keys: string[]): Promise<{ success: string[]; failed: string[] }> {\n return this.opts.sessionIndex.deleteSessions(keys);\n }\n\n async rename(key: string, name: string): Promise<{ renamed: boolean }> {\n await this.opts.sessionIndex.renameSession(key, name);\n return { renamed: true };\n }\n\n async tag(key: string, tags: string[]): Promise<{ tagged: boolean }> {\n await this.opts.sessionIndex.tagSession(key, tags);\n return { tagged: true };\n }\n\n async untag(key: string, tags: string[]): Promise<{ untagged: boolean }> {\n await this.opts.sessionIndex.untagSession(key, tags);\n return { untagged: true };\n }\n\n async archive(key: string): Promise<{ archived: boolean }> {\n await this.opts.sessionIndex.archiveSession(key);\n return { archived: true };\n }\n\n async unarchive(key: string): Promise<{ unarchived: boolean }> {\n await this.opts.sessionIndex.unarchiveSession(key);\n return { unarchived: true };\n }\n\n async pin(key: string): Promise<{ pinned: boolean }> {\n await this.opts.sessionIndex.pinSession(key);\n return { pinned: true };\n }\n\n async unpin(key: string): Promise<{ unpinned: boolean }> {\n await this.opts.sessionIndex.unpinSession(key);\n return { unpinned: true };\n }\n\n // ── Search + export + stats ───────────────────────────────────────────\n\n search(query: string) {\n return this.opts.sessionIndex.searchSessions(query);\n }\n\n searchIn(key: string, keyword: string) {\n return this.opts.sessionIndex.searchInSession(key, keyword);\n }\n\n async export(key: string, format: ExportFormat): Promise<{ content: string }> {\n const content = await this.opts.sessionIndex.exportSession(key, format);\n return { content };\n }\n\n importExport(\n targetKey: string,\n jsonContent: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n return this.opts.sessionIndex.importSessionExport(targetKey, jsonContent);\n }\n\n fork(\n key: string,\n targetKey: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n return this.opts.sessionIndex.forkSession(key, targetKey);\n }\n\n forkRows(\n key: string,\n targetKey: string,\n options: { throughRow?: number } = {},\n ): Promise<{ sessionKey: string; rowCount: number }> {\n return this.opts.sessionIndex.forkSessionRows(key, targetKey, options);\n }\n\n btwQuery(sessionKey: string, question: string): Promise<{ text: string; error?: string }> {\n return this.opts.getAgentService().sessionInspector.btwQuery(sessionKey, question);\n }\n\n stats() {\n return this.opts.sessionIndex.getStats();\n }\n\n /**\n * Distinct chat-id pairs from sessions, grouped by channel. Used by cron job\n * configuration UI to seed the \"send to existing chat\" picker.\n */\n chatIds(channel?: string): Promise<\n Array<{\n channel: string;\n chatId: string;\n lastActive: string;\n accountId?: string;\n peerKind?: string;\n peerId?: string;\n }>\n > {\n return getDistinctSessionChatIds(this.opts.sessionIndex, channel);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sessions-api.js","names":[],"sources":["../../../../src/gateway/service/sessions-api.ts"],"sourcesContent":["/**\n * GatewaySessionsApi — session CRUD, search, compaction, tag/pin/archive,\n * stats, and chat-id grouping for the gateway REST surface.\n *\n * Twenty-four methods, previously sitting on `GatewayService` as a mix of\n * one-line `sessionIndex.*` delegations and small composite operations (e.g.\n * `restoreCheckpoint` also evicts the in-memory agent, `runCompaction` also\n * appends a transcript context entry). Centralising them here lets routes\n * depend on the narrow `GatewaySessionsApi` surface instead of the full\n * `GatewayService`, and keeps the gateway composition root focused on\n * lifecycle + wiring.\n */\n\nimport type { AgentService } from '../../agent/service.js';\nimport type { CompactionResult } from '../../agent/memory/compaction.js';\nimport { retireSessionMcpRuntimeForSessionKey } from '../../agent/mcp/bundle-mcp-tools.js';\nimport { SessionIndex } from '../../session/index.js';\nimport type { ExportFormat, SessionListQuery } from '../../session/types.js';\nimport { buildSessionTimeline } from '../../session/transcript-outline.js';\nimport type { SessionPatchBody } from '../../session/patch-metadata.js';\nimport { collectMediaUrisFromMessages, deleteMediaUris } from '../../media/session-references.js';\nimport { getDistinctSessionChatIds } from './session-chat-ids.js';\nimport { performSessionReset, type SessionResetResult } from '../session-reset-service.js';\n\nexport interface GatewaySessionsApiOptions {\n sessionIndex: SessionIndex;\n /** Resolves the live agent service (created lazily; throws if gateway is starting). */\n getAgentService: () => AgentService;\n /** Read-only view of in-flight webchat runs (per session key → run id). */\n getActiveWebchatRunId: (sessionKey: string) => string | undefined;\n}\n\nexport class GatewaySessionsApi {\n private readonly opts: GatewaySessionsApiOptions;\n\n constructor(opts: GatewaySessionsApiOptions) {\n this.opts = opts;\n }\n\n // ── List / get ─────────────────────────────────────────────────────────\n\n listSessions(query?: SessionListQuery) {\n return this.opts.sessionIndex.listSessions(query);\n }\n\n /** Subagent sessions have keys starting with `subagent:`. */\n listSubagents(query?: SessionListQuery) {\n return this.opts.sessionIndex.listSubagents(query);\n }\n\n getSession(\n key: string,\n options?: { includeTranscriptSummary?: boolean; includeTranscriptRows?: boolean },\n ) {\n return this.opts.sessionIndex.getSession(key, options);\n }\n\n async resolveSession(input: {\n key?: string;\n sessionKey?: string;\n sessionId?: string;\n }): Promise<\n | {\n sessionKey: string;\n sessionId: string;\n session: Awaited<ReturnType<GatewaySessionsApi['getSession']>>;\n }\n | null\n > {\n const explicitKey = input.sessionKey?.trim() || input.key?.trim();\n const resolvedKey =\n explicitKey ||\n (input.sessionId?.trim()\n ? await this.opts.sessionIndex.resolveSessionKeyBySessionId(input.sessionId.trim())\n : null);\n if (!resolvedKey) {\n return null;\n }\n const session = await this.getSession(resolvedKey);\n if (!session?.sessionId) {\n return null;\n }\n return { sessionKey: resolvedKey, sessionId: session.sessionId, session };\n }\n\n /** Read-only: in-flight webchat agent run for this session key, if any. */\n getActiveRun(sessionKey: string): { active: boolean; runId?: string } {\n const key = sessionKey.trim();\n if (!key) return { active: false };\n const runId = this.opts.getActiveWebchatRunId(key)?.trim();\n if (!runId) return { active: false };\n return { active: true, runId };\n }\n\n getMessagePage(\n key: string,\n options?: {\n offset?: number;\n limit?: number;\n before?: string;\n includeTranscriptSummary?: boolean;\n includeTranscriptRows?: boolean;\n },\n ) {\n return this.opts.sessionIndex.getSessionMessagePage(key, options);\n }\n\n async getTimeline(key: string) {\n const metadata = await this.opts.sessionIndex.getSessionMetadata(key);\n if (!metadata) return null;\n const rows = await this.opts.sessionIndex.getStore().loadTranscriptRows(key);\n return buildSessionTimeline(rows);\n }\n\n // ── Metadata patches ──────────────────────────────────────────────────\n\n patch(key: string, body: SessionPatchBody): Promise<{ ok: true } | { ok: false; error: string }> {\n return this.opts.sessionIndex.patchSession(key, body);\n }\n\n async getAgentConfig(sessionKey: string) {\n return this.opts.getAgentService().sessionInspector.agentConfig(sessionKey);\n }\n\n /** Resolved markdown workspace for a session (after hydration / mkdir). */\n getEffectiveWorkspacePath(sessionKey: string): Promise<string> {\n return this.opts.getAgentService().getEffectiveWorkspacePathForSession(sessionKey);\n }\n\n patchAgentConfig(\n sessionKey: string,\n body: {\n thinkingLevel?: string;\n model?: string | null;\n reasoningLevel?: string;\n verboseLevel?: string;\n workingDirectory?: string;\n },\n ) {\n return this.opts.getAgentService().sessionConfig.patch(sessionKey, body);\n }\n\n // ── Compaction checkpoints ────────────────────────────────────────────\n\n listCompactionCheckpoints(key: string) {\n return this.opts.sessionIndex.listCompactionCheckpoints(key);\n }\n\n getCompactionCheckpoint(key: string, checkpointId: string) {\n return this.opts.sessionIndex.getCompactionCheckpointDetail(key, checkpointId);\n }\n\n async restoreCompactionCheckpoint(key: string, checkpointId: string): Promise<void> {\n await this.opts.sessionIndex.restoreCompactionCheckpoint(key, checkpointId);\n this.opts.getAgentService().evictSessionAgent(key);\n }\n\n async runCompaction(\n key: string,\n options?: { instructions?: string; force?: boolean },\n ): Promise<CompactionResult> {\n const result = await this.opts.getAgentService().sessionInspector.compact(key, options);\n if (result.compacted) {\n void this.opts.sessionIndex\n .appendTranscriptContextEntry(key, {\n text: 'Session transcript compacted',\n data: {\n firstKeptIndex: result.firstKeptIndex,\n tokensBefore: result.tokensBefore,\n tokensAfter: result.tokensAfter,\n summaryPreview: result.summary.slice(0, 500),\n },\n })\n .catch(() => {});\n }\n return result;\n }\n\n // ── Lifecycle (delete / rename / tag / pin / archive) ─────────────────\n\n async delete(key: string): Promise<{ deleted: boolean }> {\n const messages = await this.opts.sessionIndex.loadMessages(key).catch(() => []);\n const result = await this.opts.sessionIndex.deleteSession(key);\n if (result) {\n await deleteMediaUris(collectMediaUrisFromMessages(messages));\n this.opts.getAgentService().evictSessionAgent(key);\n await retireSessionMcpRuntimeForSessionKey({ sessionKey: key, reason: 'session-delete' });\n }\n return { deleted: result };\n }\n\n /** Reset transcript in place (archive + new session id); preserves session key and overrides. */\n reset(key: string): Promise<SessionResetResult> {\n return performSessionReset(key, {\n sessionIndex: this.opts.sessionIndex,\n getAgentService: this.opts.getAgentService,\n });\n }\n\n deleteMany(keys: string[]): Promise<{ success: string[]; failed: string[] }> {\n return this.opts.sessionIndex.deleteSessions(keys);\n }\n\n async rename(key: string, name: string): Promise<{ renamed: boolean }> {\n await this.opts.sessionIndex.renameSession(key, name);\n return { renamed: true };\n }\n\n async tag(key: string, tags: string[]): Promise<{ tagged: boolean }> {\n await this.opts.sessionIndex.tagSession(key, tags);\n return { tagged: true };\n }\n\n async untag(key: string, tags: string[]): Promise<{ untagged: boolean }> {\n await this.opts.sessionIndex.untagSession(key, tags);\n return { untagged: true };\n }\n\n async archive(key: string): Promise<{ archived: boolean }> {\n await this.opts.sessionIndex.archiveSession(key);\n return { archived: true };\n }\n\n async unarchive(key: string): Promise<{ unarchived: boolean }> {\n await this.opts.sessionIndex.unarchiveSession(key);\n return { unarchived: true };\n }\n\n async pin(key: string): Promise<{ pinned: boolean }> {\n await this.opts.sessionIndex.pinSession(key);\n return { pinned: true };\n }\n\n async unpin(key: string): Promise<{ unpinned: boolean }> {\n await this.opts.sessionIndex.unpinSession(key);\n return { unpinned: true };\n }\n\n // ── Search + export + stats ───────────────────────────────────────────\n\n search(query: string) {\n return this.opts.sessionIndex.searchSessions(query);\n }\n\n searchIn(key: string, keyword: string) {\n return this.opts.sessionIndex.searchInSession(key, keyword);\n }\n\n async export(key: string, format: ExportFormat): Promise<{ content: string }> {\n const content = await this.opts.sessionIndex.exportSession(key, format);\n return { content };\n }\n\n importExport(\n targetKey: string,\n jsonContent: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n return this.opts.sessionIndex.importSessionExport(targetKey, jsonContent);\n }\n\n fork(\n key: string,\n targetKey: string,\n ): Promise<{ sessionKey: string; rowCount: number }> {\n return this.opts.sessionIndex.forkSession(key, targetKey);\n }\n\n forkRows(\n key: string,\n targetKey: string,\n options: { throughRow?: number } = {},\n ): Promise<{ sessionKey: string; rowCount: number }> {\n return this.opts.sessionIndex.forkSessionRows(key, targetKey, options);\n }\n\n btwQuery(sessionKey: string, question: string): Promise<{ text: string; error?: string }> {\n return this.opts.getAgentService().sessionInspector.btwQuery(sessionKey, question);\n }\n\n stats() {\n return this.opts.sessionIndex.getStats();\n }\n\n /**\n * Distinct chat-id pairs from sessions, grouped by channel. Used by automation\n * configuration UI to seed the \"send to existing chat\" picker.\n */\n chatIds(channel?: string): Promise<\n Array<{\n channel: string;\n chatId: string;\n lastActive: string;\n accountId?: string;\n peerKind?: string;\n peerId?: string;\n }>\n > {\n return getDistinctSessionChatIds(this.opts.sessionIndex, channel);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AgentService } from '../agent/service.js';
|
|
2
2
|
import { MessageBus } from '../infra/bus/index.js';
|
|
3
|
-
import {
|
|
3
|
+
import { AutomationService } from '../automations/index.js';
|
|
4
4
|
import { NotesService } from '../notes/index.js';
|
|
5
5
|
import { WorkflowRunService } from '../workflows/service/workflow-run-service.js';
|
|
6
6
|
import { ExtensionLoader } from '../extensions/index.js';
|
|
@@ -22,7 +22,7 @@ export declare class GatewayService {
|
|
|
22
22
|
private configPath;
|
|
23
23
|
private _agentService;
|
|
24
24
|
private channelManager;
|
|
25
|
-
private
|
|
25
|
+
private automationService;
|
|
26
26
|
private notesService;
|
|
27
27
|
private extensionLoader;
|
|
28
28
|
private extensionMetadataSnapshot;
|
|
@@ -53,6 +53,8 @@ export declare class GatewayService {
|
|
|
53
53
|
private goalRunner;
|
|
54
54
|
private goalNotifications;
|
|
55
55
|
private connectorSupervisor;
|
|
56
|
+
private stopAutomationProductEventBridge;
|
|
57
|
+
private stopSessionTranscriptAutomationEvents;
|
|
56
58
|
/**
|
|
57
59
|
* Webchat agent invocation surface (`runAgent`, `abortAgentRun`, `steer*`,
|
|
58
60
|
* `submitClarifyResponse`, clarify-bridge dispatch). Owns the
|
|
@@ -233,7 +235,8 @@ export declare class GatewayService {
|
|
|
233
235
|
get messageBusInstance(): MessageBus;
|
|
234
236
|
/** Effective HTTP listen port (CLI `--port` override or config default). */
|
|
235
237
|
getEffectiveListenPort(): number;
|
|
236
|
-
get
|
|
238
|
+
get automationServiceInstance(): AutomationService;
|
|
239
|
+
private reconcileDreamingAutomations;
|
|
237
240
|
get notesServiceInstance(): NotesService;
|
|
238
241
|
get sessionIndexInstance(): SessionIndex;
|
|
239
242
|
/** Shared workflow run orchestrator + session bridge (one instance per gateway). */
|
|
@@ -244,6 +247,7 @@ export declare class GatewayService {
|
|
|
244
247
|
processDirect(content: string, sessionKey?: string): Promise<string>;
|
|
245
248
|
subscribe(sessionId: string, listener: (event: ServiceEvent) => Promise<void> | void): () => void;
|
|
246
249
|
emit(type: string, payload: unknown): void;
|
|
250
|
+
private startAutomationProductEventBridge;
|
|
247
251
|
/** Replay events since `lastEventId` for SSE reconnection. */
|
|
248
252
|
getEventsSince(sessionId: string, lastEventId: string): ServiceEvent[];
|
|
249
253
|
/**
|
|
@@ -16,6 +16,8 @@ import { loadConfig, saveConfig } from "../config/loader.js";
|
|
|
16
16
|
import { prewarmModelRegistry } from "../providers/model-registry.js";
|
|
17
17
|
import { init_providers, providers_exports } from "../providers/index.js";
|
|
18
18
|
import { resolveEffectiveGatewayPort } from "./host.js";
|
|
19
|
+
import { onSessionTranscriptUpdate } from "../session/transcript-events.js";
|
|
20
|
+
import { onAutomationProductEvent, publishAutomationProductEvent } from "../automations/product-events.js";
|
|
19
21
|
import { closeXopcDatabase, openXopcDatabase } from "../storage/sqlite/connection.js";
|
|
20
22
|
import { GoalRunner } from "../goals/goal-runner.js";
|
|
21
23
|
import { GoalNotificationService } from "../goals/goal-notifications.js";
|
|
@@ -31,15 +33,16 @@ import { MessageBus, MessageBusShutdownError } from "../infra/bus/queue.js";
|
|
|
31
33
|
import "../infra/bus/index.js";
|
|
32
34
|
import { AgentService } from "../agent/service.js";
|
|
33
35
|
import { ensureStarterAgentsInitialized } from "../agent/starter-agents.js";
|
|
36
|
+
import { AutomationService } from "../automations/service/automation-service.js";
|
|
37
|
+
import "../automations/index.js";
|
|
34
38
|
import { setPairingBroadcastSink } from "../channels/pairing/pairing-events.js";
|
|
35
39
|
import { registerClarifyBridge } from "./clarify-runtime.js";
|
|
36
40
|
import { ChannelManager } from "../channels/manager.js";
|
|
37
41
|
import { getWorkspacePath } from "../config/workspace-path-helpers.js";
|
|
38
42
|
import "../config/index.js";
|
|
39
43
|
import { startConnectorSupervisor } from "../connectors/supervisor.js";
|
|
40
|
-
import { CronService } from "../cron/service.js";
|
|
41
|
-
import "../cron/index.js";
|
|
42
44
|
import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
|
|
45
|
+
import { reconcileDreamingAutomations } from "./dreaming-automation-reconciler.js";
|
|
43
46
|
import { NotesStore } from "../notes/store.js";
|
|
44
47
|
import { buildNoteAgentContext } from "../notes/agent-context.js";
|
|
45
48
|
import { NotesService } from "../notes/service.js";
|
|
@@ -59,6 +62,7 @@ import { isGatewayStrictSecurityEnabled } from "./rate-limit/env-flags.js";
|
|
|
59
62
|
import "./rate-limit/index.js";
|
|
60
63
|
import { assertGatewayRuntimeConfig } from "./runtime-config.js";
|
|
61
64
|
import { auditGatewayConfig } from "./security/audit.js";
|
|
65
|
+
import { runBootstrapMigrationsSync } from "../migrations/runner.js";
|
|
62
66
|
import { scheduleGatewayUpdateCheck } from "../infra/update-startup.js";
|
|
63
67
|
import { resolveChannelConnectDeferSet } from "./resolve-channel-connect-defer.js";
|
|
64
68
|
import { restartGatewayProcessWithFreshPid } from "./respawn.js";
|
|
@@ -87,7 +91,7 @@ var GatewayService = class {
|
|
|
87
91
|
configPath;
|
|
88
92
|
_agentService = null;
|
|
89
93
|
channelManager;
|
|
90
|
-
|
|
94
|
+
automationService;
|
|
91
95
|
notesService;
|
|
92
96
|
extensionLoader = null;
|
|
93
97
|
extensionMetadataSnapshot = null;
|
|
@@ -120,6 +124,8 @@ var GatewayService = class {
|
|
|
120
124
|
goalRunner = null;
|
|
121
125
|
goalNotifications = null;
|
|
122
126
|
connectorSupervisor = null;
|
|
127
|
+
stopAutomationProductEventBridge = null;
|
|
128
|
+
stopSessionTranscriptAutomationEvents = null;
|
|
123
129
|
/**
|
|
124
130
|
* Webchat agent invocation surface (`runAgent`, `abortAgentRun`, `steer*`,
|
|
125
131
|
* `submitClarifyResponse`, clarify-bridge dispatch). Owns the
|
|
@@ -145,6 +151,7 @@ var GatewayService = class {
|
|
|
145
151
|
this.serviceConfig = serviceConfig;
|
|
146
152
|
this.bus = new MessageBus();
|
|
147
153
|
this.configPath = serviceConfig.configPath || resolveConfigPath();
|
|
154
|
+
runBootstrapMigrationsSync(this.configPath);
|
|
148
155
|
this.config = loadConfig(this.configPath);
|
|
149
156
|
const starterResult = ensureStarterAgentsInitialized(this.config);
|
|
150
157
|
if (starterResult.changed) {
|
|
@@ -204,7 +211,7 @@ var GatewayService = class {
|
|
|
204
211
|
this.workspacePath = getWorkspacePath(this.config) || "./workspace";
|
|
205
212
|
this.initializeExtensionLoader();
|
|
206
213
|
this.sessionIndex = new SessionIndex({ config: this.config });
|
|
207
|
-
this.
|
|
214
|
+
this.automationService = new AutomationService();
|
|
208
215
|
this.notesService = new NotesService(new NotesStore());
|
|
209
216
|
this.agentRunner = new GatewayAgentRunner({
|
|
210
217
|
bus: this.bus,
|
|
@@ -237,10 +244,10 @@ var GatewayService = class {
|
|
|
237
244
|
},
|
|
238
245
|
getAgentService: () => this.ensureAgentService(),
|
|
239
246
|
getChannelManager: () => this.channelManager,
|
|
240
|
-
getCronService: () => this.cronService,
|
|
241
247
|
getHeartbeatService: () => this.heartbeatService,
|
|
242
248
|
getExtensionLoader: () => this.extensionLoader,
|
|
243
249
|
reconcileBrowserExtensionServer: () => this.reconcileBrowserExtensionServer(),
|
|
250
|
+
reconcileDreamingAutomations: () => this.reconcileDreamingAutomations(),
|
|
244
251
|
getChannelsStatus: () => this.getChannelsStatus(),
|
|
245
252
|
emit: (type, payload) => this.emit(type, payload)
|
|
246
253
|
});
|
|
@@ -251,7 +258,6 @@ var GatewayService = class {
|
|
|
251
258
|
}
|
|
252
259
|
ensureAgentService() {
|
|
253
260
|
if (this._agentService) return this._agentService;
|
|
254
|
-
const cronRef = { service: this.cronService };
|
|
255
261
|
this._agentService = new AgentService(this.bus, {
|
|
256
262
|
workspace: this.workspacePath,
|
|
257
263
|
model: getAgentDefaultModelRef(this.config),
|
|
@@ -280,7 +286,7 @@ var GatewayService = class {
|
|
|
280
286
|
});
|
|
281
287
|
},
|
|
282
288
|
extensionRegistry: this.extensionLoader?.getRegistry(),
|
|
283
|
-
|
|
289
|
+
getAutomationService: () => this.automationService,
|
|
284
290
|
getWorkflowRunService: () => this.createWorkflowRunService(),
|
|
285
291
|
sourceContextResolver: async (binding) => {
|
|
286
292
|
if (binding.kind !== "note") return null;
|
|
@@ -305,16 +311,11 @@ var GatewayService = class {
|
|
|
305
311
|
getModelForSession: (sk) => this._agentService.getModelForSession(sk),
|
|
306
312
|
switchModelForSession: (sk, id) => this._agentService.switchModelForSession(sk, id)
|
|
307
313
|
});
|
|
308
|
-
this.
|
|
314
|
+
this.automationService.setDeps({
|
|
309
315
|
agentService: this._agentService,
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
sessionStore: this.sessionIndex.getStore(),
|
|
313
|
-
getDefaultCronAgentId: () => getDefaultAgentId(this.config),
|
|
314
|
-
workflowRunService: this.createWorkflowRunService(),
|
|
315
|
-
goalRunner: this.createGoalRunner()
|
|
316
|
+
getDefaultAgentId: () => getDefaultAgentId(this.config),
|
|
317
|
+
workflowRunService: this.createWorkflowRunService()
|
|
316
318
|
});
|
|
317
|
-
cronRef.service = this.cronService;
|
|
318
319
|
this._agentService.persistentGoals.setWebchatContinuationScheduler((sessionKey, message) => {
|
|
319
320
|
const scheduleWhenIdle = () => {
|
|
320
321
|
if (this._agentService.getInboundTurnDepth(sessionKey) > 0) {
|
|
@@ -336,7 +337,6 @@ var GatewayService = class {
|
|
|
336
337
|
this.heartbeatService = new HeartbeatService({
|
|
337
338
|
agentService: this.ensureAgentService(),
|
|
338
339
|
messageBus: this.bus,
|
|
339
|
-
cronService: this.cronService,
|
|
340
340
|
sessionStore: this.sessionIndex.getStore(),
|
|
341
341
|
getConfig: () => this.config
|
|
342
342
|
});
|
|
@@ -614,15 +614,12 @@ var GatewayService = class {
|
|
|
614
614
|
}, "Gateway channel startup phase-1 complete");
|
|
615
615
|
await trace.measure("sessions.initialize", () => this.sessionIndex.initialize());
|
|
616
616
|
log.debug("Session manager initialized");
|
|
617
|
-
this.
|
|
617
|
+
this.automationService.setDeps({
|
|
618
618
|
agentService: this.agentService,
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
sessionStore: this.sessionIndex.getStore(),
|
|
622
|
-
getDefaultCronAgentId: () => getDefaultAgentId(this.config),
|
|
623
|
-
workflowRunService: this.createWorkflowRunService(),
|
|
624
|
-
goalRunner: this.createGoalRunner()
|
|
619
|
+
getDefaultAgentId: () => getDefaultAgentId(this.config),
|
|
620
|
+
workflowRunService: this.createWorkflowRunService()
|
|
625
621
|
});
|
|
622
|
+
this.startAutomationProductEventBridge();
|
|
626
623
|
await trace.measure("workflows.reconcile", () => this.reconcileInterruptedWorkflowRuns());
|
|
627
624
|
this.sessionIndex.on("sessionUpdated", (data) => {
|
|
628
625
|
this.emit("session.updated", {
|
|
@@ -631,7 +628,8 @@ var GatewayService = class {
|
|
|
631
628
|
tags: data.tags
|
|
632
629
|
});
|
|
633
630
|
});
|
|
634
|
-
|
|
631
|
+
await trace.measure("automations.initialize", () => this.automationService.initialize());
|
|
632
|
+
await trace.measure("dreaming.reconcile", () => this.reconcileDreamingAutomations());
|
|
635
633
|
await this.notesService.initialize();
|
|
636
634
|
this.ensureHeartbeatService().start(heartbeatRunnerConfigFromConfig(this.config));
|
|
637
635
|
this.connectorSupervisor = startConnectorSupervisor({
|
|
@@ -775,7 +773,11 @@ var GatewayService = class {
|
|
|
775
773
|
this.lastChannelConnectDeferMode = "auto";
|
|
776
774
|
this.lastChannelConnectDeferSource = "off";
|
|
777
775
|
await this.channelManager.stop();
|
|
778
|
-
await this.
|
|
776
|
+
await this.automationService.stop();
|
|
777
|
+
this.stopAutomationProductEventBridge?.();
|
|
778
|
+
this.stopAutomationProductEventBridge = null;
|
|
779
|
+
this.stopSessionTranscriptAutomationEvents?.();
|
|
780
|
+
this.stopSessionTranscriptAutomationEvents = null;
|
|
779
781
|
await this.notesService.flush();
|
|
780
782
|
buckets.destroyAll();
|
|
781
783
|
closeXopcDatabase();
|
|
@@ -1074,8 +1076,14 @@ var GatewayService = class {
|
|
|
1074
1076
|
getEffectiveListenPort() {
|
|
1075
1077
|
return resolveEffectiveGatewayPort(this.config, this.serviceConfig.listenPort);
|
|
1076
1078
|
}
|
|
1077
|
-
get
|
|
1078
|
-
return this.
|
|
1079
|
+
get automationServiceInstance() {
|
|
1080
|
+
return this.automationService;
|
|
1081
|
+
}
|
|
1082
|
+
async reconcileDreamingAutomations() {
|
|
1083
|
+
await reconcileDreamingAutomations({
|
|
1084
|
+
config: this.config,
|
|
1085
|
+
automationService: this.automationService
|
|
1086
|
+
});
|
|
1079
1087
|
}
|
|
1080
1088
|
get notesServiceInstance() {
|
|
1081
1089
|
return this.notesService;
|
|
@@ -1134,6 +1142,32 @@ var GatewayService = class {
|
|
|
1134
1142
|
this.sse.emit(type, payload);
|
|
1135
1143
|
this.createGoalNotificationService().handleGatewayEvent(type, payload);
|
|
1136
1144
|
}
|
|
1145
|
+
startAutomationProductEventBridge() {
|
|
1146
|
+
this.stopAutomationProductEventBridge?.();
|
|
1147
|
+
this.stopSessionTranscriptAutomationEvents?.();
|
|
1148
|
+
this.stopAutomationProductEventBridge = onAutomationProductEvent((event) => {
|
|
1149
|
+
this.automationService.triggerEvent(event).catch((err) => {
|
|
1150
|
+
const em = err instanceof Error ? err.message : String(err);
|
|
1151
|
+
log.warn({
|
|
1152
|
+
err,
|
|
1153
|
+
eventType: event.type,
|
|
1154
|
+
source: event.source
|
|
1155
|
+
}, `Automation product event failed: ${em}`);
|
|
1156
|
+
});
|
|
1157
|
+
});
|
|
1158
|
+
this.stopSessionTranscriptAutomationEvents = onSessionTranscriptUpdate((update) => {
|
|
1159
|
+
if (!update.sessionKey || update.sessionKey.includes(":automation:")) return;
|
|
1160
|
+
publishAutomationProductEvent({
|
|
1161
|
+
type: "session.transcript.updated",
|
|
1162
|
+
source: "sessions",
|
|
1163
|
+
payload: {
|
|
1164
|
+
sessionKey: update.sessionKey,
|
|
1165
|
+
messageId: update.messageId,
|
|
1166
|
+
hasMessage: update.message !== void 0
|
|
1167
|
+
}
|
|
1168
|
+
});
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1137
1171
|
/** Replay events since `lastEventId` for SSE reconnection. */
|
|
1138
1172
|
getEventsSince(sessionId, lastEventId) {
|
|
1139
1173
|
return this.sse.getEventsSince(sessionId, lastEventId);
|