@xopcai/xopc 0.0.111 → 0.0.113
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser-ext/icons/icon-128.png +0 -0
- package/dist/browser-ext/icons/icon-16.png +0 -0
- package/dist/browser-ext/icons/icon-32.png +0 -0
- package/dist/browser-ext/icons/icon-48.png +0 -0
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
- package/dist/extensions/feishu/src/workflow-progress.js +1 -1
- package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
- package/dist/extensions/telegram/src/inbound-processor.js +1 -1
- package/dist/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/telegram/src/update-offset-store.js +1 -1
- package/dist/extensions/telegram/src/workflow-progress.js +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/api/api.js +2 -2
- package/dist/extensions/weixin/src/auth/accounts.js +1 -1
- package/dist/extensions/weixin/src/cdn/upload.js +1 -1
- package/dist/extensions/weixin/src/delivery-to.d.ts +3 -3
- package/dist/extensions/weixin/src/delivery-to.js.map +1 -1
- package/dist/extensions/weixin/src/media/data-url.js +1 -1
- package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
- package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
- package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
- package/dist/extensions/weixin/src/workflow-progress.js +1 -1
- package/dist/gateway/static/root/apple-touch-icon.png +0 -0
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-zlx9l5Yp.js → agent-avatar-dicebear-CBlklyNr.js} +1 -1
- package/dist/gateway/static/root/assets/agent-browser-settings-page-rGbKc2Hh.js +6 -0
- package/dist/gateway/static/root/assets/{agent-defaults-tabbed-page-Bz7JWjRM.js → agent-defaults-tabbed-page-CtwVbjOA.js} +1 -1
- package/dist/gateway/static/root/assets/agents-CCBmGcwc.js +71 -0
- package/dist/gateway/static/root/assets/{app-management-settings-panel-DaQwdeCq.js → app-management-settings-panel-28E_WfMe.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-D2zv6r3P.js → appearance-settings-Do1z0XgJ.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-BIppe_jj.js → apps-page-xwCsJS15.js} +1 -1
- package/dist/gateway/static/root/assets/{archive-plugin-DEmu8eH7.js → archive-plugin-BAFlsov_.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-B98lJoN5.js → attachment-load-V3qGPC3x.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-CL9QKmyo.js → binary-plugins-DT8NvA6W.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-BOAhMAhT.js → block-editor-CdLMEcHd.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-settings-Br8iRnXp.js → channels-settings-C044DcYk.js} +1 -1
- package/dist/gateway/static/root/assets/{config-api-0o1WYdz2.js → config-api-Bf5mjpu7.js} +1 -1
- package/dist/gateway/static/root/assets/config-reload-event-Bjh2zoKp.js +1 -0
- package/dist/gateway/static/root/assets/connectors-settings-8VEWUOTj.js +2 -0
- package/dist/gateway/static/root/assets/cron-api--pAB_rps.js +1 -0
- package/dist/gateway/static/root/assets/cron-page-DqmNGNOy.js +3 -0
- package/dist/gateway/static/root/assets/dreaming-settings-6UZE1FSK.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-Cjx6pZVz.js → extension-debug-page-BGhE7msg.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BSPNL90V.js → extension-page-CvpI45WG.js} +1 -1
- package/dist/gateway/static/root/assets/extension-settings-page-DAmR5FUe.js +1 -0
- package/dist/gateway/static/root/assets/{fetch-Bs7in_4F.js → fetch-NZmjSXLl.js} +1 -1
- package/dist/gateway/static/root/assets/format-cron-label-BsotZDO5.js +2 -0
- package/dist/gateway/static/root/assets/{format-interval-label-CftJ5uXu.js → format-interval-label-qhth3BMV.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-api-Clfck-hW.js → gateway-config-api-CaXBt-9R.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-DphpbLBc.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-BkjVJc38.js → gateway-startup-retry-Be1omjh3.js} +1 -1
- package/dist/gateway/static/root/assets/{goal-detail-page-kqJue0sE.js → goal-detail-page-bv0VRDaf.js} +1 -1
- package/dist/gateway/static/root/assets/goals-page-1Ywnt4Cb.js +2 -0
- package/dist/gateway/static/root/assets/{goals-settings-CJnzNSDo.js → goals-settings-ceEBjnfc.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-Cp7CPuIn.js → heartbeat-config-api-BzO6G4fD.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-ifSI1Wbh.js → heartbeat-settings-DCST9-du.js} +1 -1
- package/dist/gateway/static/root/assets/index-Cxm6xsps.js +122 -0
- package/dist/gateway/static/root/assets/index-b_R4tKqt.css +1 -0
- package/dist/gateway/static/root/assets/interval-presets-DJmshV8n.js +1 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings--MI1rYl7.js → keyboard-shortcuts-settings-9AUUlQ5Q.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-BwrVNlyW.js → logs-page-B_wrxhee.js} +1 -1
- package/dist/gateway/static/root/assets/{markdown-split-B_oc9lJe.js → markdown-split-CYYELqAr.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-DLPvB5H3.js → media-plugins-BEcMR2M8.js} +1 -1
- package/dist/gateway/static/root/assets/messages-CkT-lcgP.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-D0JDSbNu.js +2 -0
- package/dist/gateway/static/root/assets/note-detail-page-DpFV-EO6.js +2 -0
- package/dist/gateway/static/root/assets/{note-image-lightbox-rSqAgOi9.js → note-image-lightbox-DNAoPcmm.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-C9ACGEty.js → notes-page-CdkjTch8.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-Bw_N2oZi.js → preview-open-alternatives-BPLz0AIv.js} +1 -1
- package/dist/gateway/static/root/assets/{remote-access-hub-BhcWIKuM.js → remote-access-hub-DSYVAi96.js} +1 -1
- package/dist/gateway/static/root/assets/{save-bar-controls-CNP2jmw0.js → save-bar-controls-CrWwWRVK.js} +1 -1
- package/dist/gateway/static/root/assets/schedule-field-CF2sadvN.js +1 -0
- package/dist/gateway/static/root/assets/{schema-form-CDPzua9q.js → schema-form-Di5cKjYE.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-DzkpSDZr.js → sessions-page-CenkcVjF.js} +1 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-D9sva86V.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-C9bff85B.js → settings-collapsible-section-Chh282jW.js} +1 -1
- package/dist/gateway/static/root/assets/settings-form-section-Dq-83cQd.js +1 -0
- package/dist/gateway/static/root/assets/{settings-page-DWK4Zo7s.js → settings-page-DL35U0x0.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Ctwbp9Er.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-DnutoY_S.js → share-preview-page-0FXYnSUA.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-6oRgJMpn.js → shares-settings-DIM3JNsr.js} +1 -1
- package/dist/gateway/static/root/assets/skill-reload-api-DAlNaNzL.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-CLrHVzAt.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-qP1JDtDd.js → system-settings-panel-W1pTcojB.js} +1 -1
- package/dist/gateway/static/root/assets/use-agent-defaults-form-BVRvkK7m.js +1 -0
- package/dist/gateway/static/root/assets/{use-channel-catalog-C4mg1hjD.js → use-channel-catalog-CgJibfMM.js} +1 -1
- package/dist/gateway/static/root/assets/{use-settings-tab-guard-F6C0mpJt.js → use-settings-tab-guard-Bw_qkRQE.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-BnDDb6qO.js → voice-api-key-field-vYAO71Gn.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-player-store-B2EwIhtY.js → voice-player-store-C7lziaAx.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-page.utils-CRB7WX9l.js → workflow-page.utils-sgHjOXOm.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-2Fptr0je.js → workflows-page-DYyOTmFx.js} +1 -1
- package/dist/gateway/static/root/favicon-16x16.png +0 -0
- package/dist/gateway/static/root/favicon-32x32.png +0 -0
- package/dist/gateway/static/root/favicon-icon.svg +1 -0
- package/dist/gateway/static/root/favicon.ico +0 -0
- package/dist/gateway/static/root/favicon.png +0 -0
- package/dist/gateway/static/root/favicon.svg +24 -15
- package/dist/gateway/static/root/index.html +11 -10
- package/dist/gateway/static/root/logo-dark.svg +23 -15
- package/dist/gateway/static/root/logo.svg +23 -16
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +28 -2
- package/dist/src/agent/agent-manager.js +82 -11
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/agent-scope.js +1 -1
- package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
- package/dist/src/agent/context/workspace-seed.js +2 -2
- package/dist/src/agent/context/workspace-state.js +1 -1
- package/dist/src/agent/context/workspace.js +1 -1
- package/dist/src/agent/goals/goal-locale.js +2 -2
- package/dist/src/agent/goals/persistent-goal-service.js +1 -1
- package/dist/src/agent/goals/post-turn.js +3 -3
- package/dist/src/agent/image/load-image-media.js +2 -2
- package/dist/src/agent/ipc/inbox.js +3 -3
- package/dist/src/agent/ipc/socket.js +1 -1
- package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
- package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
- package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
- package/dist/src/agent/mcp/mcp-transport.js +1 -1
- package/dist/src/agent/memory/builtin-memory-store.js +1 -1
- package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
- package/dist/src/agent/memory/dreaming/events.js +1 -1
- package/dist/src/agent/memory/dreaming/last-run.js +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
- package/dist/src/agent/memory/dreaming/preview.js +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
- package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
- package/dist/src/agent/memory/dreaming/utils.js +1 -1
- package/dist/src/agent/memory/memory-flush.js +1 -1
- package/dist/src/agent/memory/plugin-discovery.js +1 -1
- package/dist/src/agent/messaging/command-handler.d.ts +3 -0
- package/dist/src/agent/messaging/command-handler.js +5 -0
- package/dist/src/agent/messaging/command-handler.js.map +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/prompt/memory/index.js +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
- package/dist/src/agent/reply/post-compaction-context.js +1 -1
- package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
- package/dist/src/agent/sandbox/path-policy.js +2 -2
- package/dist/src/agent/service/process-direct-streaming.js +9 -4
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service/reconcile-dreaming-cron.js +8 -5
- package/dist/src/agent/service/reconcile-dreaming-cron.js.map +1 -1
- package/dist/src/agent/service.d.ts +2 -1
- package/dist/src/agent/service.js +10 -5
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/service.types.d.ts +4 -0
- package/dist/src/agent/session/session-config-service.d.ts +8 -0
- package/dist/src/agent/session/session-config-service.js +20 -0
- package/dist/src/agent/session/session-config-service.js.map +1 -1
- package/dist/src/agent/session/session-inspector.js +1 -1
- package/dist/src/agent/skills/config.js +2 -2
- package/dist/src/agent/skills/filesystem-watcher.d.ts +19 -0
- package/dist/src/agent/skills/filesystem-watcher.js +182 -0
- package/dist/src/agent/skills/filesystem-watcher.js.map +1 -0
- package/dist/src/agent/skills/hub-hash.js +2 -2
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/skills/hub-pull.js +30 -36
- package/dist/src/agent/skills/hub-pull.js.map +1 -1
- package/dist/src/agent/skills/index.js +82 -38
- package/dist/src/agent/skills/index.js.map +1 -1
- package/dist/src/agent/skills/installer.js +2 -2
- package/dist/src/agent/skills/managed-store.d.ts +19 -0
- package/dist/src/agent/skills/managed-store.js +97 -38
- package/dist/src/agent/skills/managed-store.js.map +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +1 -1
- package/dist/src/agent/skills/skill-manager.d.ts +16 -6
- package/dist/src/agent/skills/skill-manager.js +79 -24
- package/dist/src/agent/skills/skill-manager.js.map +1 -1
- package/dist/src/agent/skills/skill-view-path.js +1 -1
- package/dist/src/agent/skills/test-framework.js +1 -1
- package/dist/src/agent/skills/types.d.ts +11 -0
- package/dist/src/agent/skills/watcher.js +1 -1
- package/dist/src/agent/starter-agents.js +1 -1
- package/dist/src/agent/tools/cronjob-tool.d.ts +6 -3
- package/dist/src/agent/tools/cronjob-tool.js +58 -23
- package/dist/src/agent/tools/cronjob-tool.js.map +1 -1
- package/dist/src/agent/tools/dreaming-tool.js +1 -1
- package/dist/src/agent/tools/factory.js +1 -1
- package/dist/src/agent/tools/find.js +1 -1
- package/dist/src/agent/tools/grep.js +1 -1
- package/dist/src/agent/tools/image-generate-tool.js +1 -1
- package/dist/src/agent/tools/skill-manage-tool.js +1 -1
- package/dist/src/agent/tools/workflow-tool.js +1 -1
- package/dist/src/agent/workflow/catalog.js +1 -1
- package/dist/src/agent/workspace-runtime/registry.d.ts +5 -0
- package/dist/src/agent/workspace-runtime/registry.js +7 -0
- package/dist/src/agent/workspace-runtime/registry.js.map +1 -1
- package/dist/src/ai-assist/text-assist.d.ts +42 -0
- package/dist/src/ai-assist/text-assist.js +252 -0
- package/dist/src/ai-assist/text-assist.js.map +1 -0
- package/dist/src/auth/credentials.js +2 -2
- package/dist/src/auth/profiles/store.js +2 -2
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/browser/cache-dir-policy.js +1 -1
- package/dist/src/browser/cdp-local-launcher.js +2 -2
- package/dist/src/browser/providers/browser-ext-install.js +4 -4
- package/dist/src/browser/providers/cloakbrowser.js +5 -5
- package/dist/src/browser/providers/playwright-doctor.js +1 -1
- package/dist/src/browser/stealth.js +1 -1
- package/dist/src/channels/outbound/persist-store.js +1 -1
- package/dist/src/channels/pairing/allow-from-file.js +1 -1
- package/dist/src/channels/pairing/pairing-store.js +2 -2
- package/dist/src/channels/plugins/types.adapters.d.ts +2 -2
- package/dist/src/chat-commands/agent-edit.js +2 -2
- package/dist/src/chat-commands/builtins/config.js +3 -3
- package/dist/src/chat-commands/builtins/system.js +11 -4
- package/dist/src/chat-commands/builtins/system.js.map +1 -1
- package/dist/src/chat-commands/context.d.ts +3 -0
- package/dist/src/chat-commands/context.js +7 -0
- package/dist/src/chat-commands/context.js.map +1 -1
- package/dist/src/chat-commands/types.d.ts +2 -0
- package/dist/src/cli/commands/config.js +1 -1
- package/dist/src/cli/commands/cron.js +55 -16
- package/dist/src/cli/commands/cron.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
- package/dist/src/cli/commands/doctor/checks/cron-health.js +2 -83
- package/dist/src/cli/commands/doctor/checks/cron-health.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
- package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
- package/dist/src/cli/commands/extension-create.js +1 -1
- package/dist/src/cli/commands/extension-dev.js +2 -2
- package/dist/src/cli/commands/extension-marketplace.js +2 -2
- package/dist/src/cli/commands/extension-pack.js +2 -2
- package/dist/src/cli/commands/extension.js +3 -3
- package/dist/src/cli/commands/gateway/logs.js +1 -1
- package/dist/src/cli/commands/image.js +1 -1
- package/dist/src/cli/commands/init.js +2 -2
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/skills-test.js +1 -1
- package/dist/src/cli/templates.js +1 -1
- package/dist/src/cli/utils/gateway-client.js +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +2 -2
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/agent-typed-models.js +1 -1
- package/dist/src/config/gateway-bind.js +1 -1
- package/dist/src/config/index.js +7 -7
- package/dist/src/config/loader.js +4 -4
- package/dist/src/config/models-json.js +2 -2
- package/dist/src/config/paths-state.js +1 -1
- package/dist/src/config/paths.js +1 -1
- package/dist/src/config/profile.js +1 -1
- package/dist/src/config/reload.js +1 -1
- package/dist/src/config/schema.d.ts +0 -2
- package/dist/src/config/schema.js +0 -3
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/config/web-patch.d.ts +0 -1
- package/dist/src/config/web-patch.js +0 -2
- package/dist/src/config/web-patch.js.map +1 -1
- package/dist/src/config/workspace-path.js +1 -1
- package/dist/src/cron/executor.js +102 -71
- package/dist/src/cron/executor.js.map +1 -1
- package/dist/src/cron/index.d.ts +1 -1
- package/dist/src/cron/index.js +3 -3
- package/dist/src/cron/run-log-store.d.ts +1 -0
- package/dist/src/cron/run-log-store.js +4 -2
- package/dist/src/cron/run-log-store.js.map +1 -1
- package/dist/src/cron/schedule.d.ts +10 -0
- package/dist/src/cron/schedule.js +85 -0
- package/dist/src/cron/schedule.js.map +1 -0
- package/dist/src/cron/service.d.ts +34 -77
- package/dist/src/cron/service.js +327 -264
- package/dist/src/cron/service.js.map +1 -1
- package/dist/src/cron/types.d.ts +80 -50
- package/dist/src/cron/validation.d.ts +358 -90
- package/dist/src/cron/validation.js +152 -132
- package/dist/src/cron/validation.js.map +1 -1
- package/dist/src/cron/workflow-run-completion.js +1 -1
- package/dist/src/daemon/constants.js +1 -1
- package/dist/src/daemon/install-plan.js +2 -2
- package/dist/src/daemon/launchd.js +2 -2
- package/dist/src/daemon/schtasks.js +2 -2
- package/dist/src/daemon/systemd.js +2 -2
- package/dist/src/extensions/bundle-mcp.js +1 -1
- package/dist/src/extensions/discover-extensions.js +2 -2
- package/dist/src/extensions/health.js +1 -1
- package/dist/src/extensions/install.js +2 -2
- package/dist/src/extensions/loader.js +2 -2
- package/dist/src/extensions/lockfile.js +3 -3
- package/dist/src/extensions/security.js +1 -1
- package/dist/src/extensions/update.js +2 -2
- package/dist/src/gateway/agents-admin.js +2 -2
- package/dist/src/gateway/chat-stream/mapper.d.ts +1 -0
- package/dist/src/gateway/chat-stream/mapper.js +6 -2
- package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
- package/dist/src/gateway/chat-stream/protocol.d.ts +2 -0
- package/dist/src/gateway/file-path-classifier.js +2 -2
- package/dist/src/gateway/hono/lib/config-payload.d.ts +0 -1
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/lib/extension-store.js +2 -2
- package/dist/src/gateway/hono/lib/static-ui.js +2 -2
- package/dist/src/gateway/hono/oauth-async.js +1 -1
- package/dist/src/gateway/hono/routes/agents.js +1 -1
- package/dist/src/gateway/hono/routes/ai-assist.d.ts +3 -0
- package/dist/src/gateway/hono/routes/ai-assist.js +66 -0
- package/dist/src/gateway/hono/routes/ai-assist.js.map +1 -0
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
- package/dist/src/gateway/hono/routes/commands-skills.js +7 -0
- package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
- package/dist/src/gateway/hono/routes/cron.js +24 -5
- package/dist/src/gateway/hono/routes/cron.js.map +1 -1
- package/dist/src/gateway/hono/routes/dreaming.js +1 -1
- package/dist/src/gateway/hono/routes/home.js +5 -3
- package/dist/src/gateway/hono/routes/home.js.map +1 -1
- package/dist/src/gateway/hono/routes/host-fs.js +2 -2
- package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
- package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/shares.js +1 -1
- package/dist/src/gateway/hono/routes/workflows.js +2 -2
- package/dist/src/gateway/hono/routes/workspace.js +2 -2
- package/dist/src/gateway/lock.js +3 -3
- package/dist/src/gateway/ports.js +1 -1
- package/dist/src/gateway/service/agent-runner.js +2 -2
- package/dist/src/gateway/service/config-coordinator.js +1 -1
- package/dist/src/gateway/service/marketplace-service.d.ts +22 -10
- package/dist/src/gateway/service/marketplace-service.js +46 -5
- package/dist/src/gateway/service/marketplace-service.js.map +1 -1
- package/dist/src/gateway/service.js +11 -5
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/workspace-fs-file-list.js +1 -1
- package/dist/src/goals/goal-notifications.js +1 -1
- package/dist/src/goals/goal-workflow-judge.js +3 -3
- package/dist/src/i18n/goals-bundle.js +1 -1
- package/dist/src/i18n/index.js +1 -1
- package/dist/src/i18n/share-tool-bundle.js +2 -2
- package/dist/src/infra/brew.js +1 -1
- package/dist/src/infra/package-json.js +1 -1
- package/dist/src/infra/package-update-steps.js +1 -1
- package/dist/src/infra/path-env.js +2 -2
- package/dist/src/infra/restart.js +1 -1
- package/dist/src/infra/stable-node-path.js +1 -1
- package/dist/src/infra/update-check.js +1 -1
- package/dist/src/infra/update-global.js +1 -1
- package/dist/src/infra/update-lock.js +2 -2
- package/dist/src/infra/update-restart.js +1 -1
- package/dist/src/infra/update-runner.js +1 -1
- package/dist/src/infra/update-startup.js +1 -1
- package/dist/src/infra/write-file-atomic.js +2 -2
- package/dist/src/media/store.js +1 -1
- package/dist/src/notes/agent-context.js +1 -1
- package/dist/src/notes/service.js +1 -1
- package/dist/src/notes/store.js +2 -2
- package/dist/src/project-trust/trust-store.js +2 -2
- package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
- package/dist/src/providers/index.js +1 -1
- package/dist/src/providers/model-registry.js +4 -4
- package/dist/src/session/init-session-turn.js +2 -2
- package/dist/src/session/resolve-session.js +3 -3
- package/dist/src/session/session-title.js +2 -2
- package/dist/src/session/store-reader.d.ts +5 -0
- package/dist/src/session/store-reader.js +1 -0
- package/dist/src/session/store.js +1 -1
- package/dist/src/share/share-auto.js +2 -2
- package/dist/src/share/share-store.js +3 -3
- package/dist/src/share/share-thumbnail.js +2 -2
- package/dist/src/share/share-zip.js +1 -1
- package/dist/src/share/site-share-store.js +3 -3
- package/dist/src/share/site-static-serve.js +1 -1
- package/dist/src/storage/sqlite/connection.js +1 -1
- package/dist/src/storage/sqlite/cron-job-repository.d.ts +6 -0
- package/dist/src/storage/sqlite/cron-job-repository.js +70 -0
- package/dist/src/storage/sqlite/cron-job-repository.js.map +1 -0
- package/dist/src/storage/sqlite/cron-run-repository.js +0 -1
- package/dist/src/storage/sqlite/cron-run-repository.js.map +1 -1
- package/dist/src/storage/sqlite/index.d.ts +1 -0
- package/dist/src/storage/sqlite/index.js +2 -1
- package/dist/src/storage/sqlite/memory-index-repository.js +2 -2
- package/dist/src/storage/sqlite/migrations/009_cron_jobs.sql +24 -0
- package/dist/src/storage/sqlite/migrations/discover.js +1 -1
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +4 -4
- 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 +2 -2
- package/dist/src/storage/sqlite/schema.sql +25 -0
- package/dist/src/tui/clipboard-image.js +3 -3
- package/dist/src/tui/extension-host/load-extensions.js +1 -1
- package/dist/src/tui/theme-manager.js +1 -1
- package/dist/src/tui/tui-command-formatters.js +4 -4
- package/dist/src/tui/tui-commands.js +2 -2
- package/dist/src/tui/tui-keybindings-file.js +1 -1
- package/dist/src/tui/tui-scoped-models.js +2 -2
- package/dist/src/tui/tui-settings.js +1 -1
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/dist/src/tui/tui.js +6 -6
- package/dist/src/tunnel/frpc-binary.js +4 -4
- package/dist/src/tunnel/frpc-config.js +1 -1
- package/dist/src/tunnel/frpc-extract.js +1 -1
- package/dist/src/tunnel/tunnel-state.js +1 -1
- package/dist/src/utils/logger/audit.js +1 -1
- package/dist/src/utils/logger/log-store.js +1 -1
- package/dist/src/utils/logger/rotation.js +1 -1
- package/dist/src/utils/logger/streams.js +1 -1
- package/dist/src/voice/tts/audio.js +1 -1
- package/dist/src/voice/tts/providers/edge-speech.js +2 -2
- package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
- package/dist/src/workflows/engine/projector.js +23 -14
- package/dist/src/workflows/engine/projector.js.map +1 -1
- package/dist/src/workflows/engine/workflow-engine.d.ts +1 -0
- package/dist/src/workflows/engine/workflow-engine.js +36 -0
- package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
- package/dist/src/workflows/index.js +1 -1
- package/dist/src/workflows/service/workflow-run-service.js +2 -2
- package/dist/src/workflows/service/workflow-session-bridge.js +2 -2
- package/dist/src/workflows/store/event-store.js +1 -1
- package/dist/src/workflows/store/run-store.js +1 -1
- package/package.json +2 -3
- package/dist/gateway/static/root/assets/agent-browser-settings-page-B-0zGjt8.js +0 -6
- package/dist/gateway/static/root/assets/agents-DwDnJlXT.js +0 -71
- package/dist/gateway/static/root/assets/connectors-settings-DDvHo9in.js +0 -2
- package/dist/gateway/static/root/assets/cron-api-Dj_UZKST.js +0 -1
- package/dist/gateway/static/root/assets/cron-page-Dv7GII9G.js +0 -1
- package/dist/gateway/static/root/assets/cron-schedule-picker-DH10KgD6.js +0 -1
- package/dist/gateway/static/root/assets/dreaming-settings-L2rgZDQl.js +0 -1
- package/dist/gateway/static/root/assets/extension-settings-page-m_UQYkVc.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-CS177xni.js +0 -1
- package/dist/gateway/static/root/assets/goals-page-C0FujUB5.js +0 -2
- package/dist/gateway/static/root/assets/index-COkF54xv.js +0 -121
- package/dist/gateway/static/root/assets/index-DIaSNGEO.css +0 -1
- package/dist/gateway/static/root/assets/interval-presets-B29Ss_2y.js +0 -2
- package/dist/gateway/static/root/assets/messages-Csef1aW7.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-panel-DHGiTIvf.js +0 -2
- package/dist/gateway/static/root/assets/note-detail-page-BM7zlDiT.js +0 -2
- package/dist/gateway/static/root/assets/schedule-field-BPAWui3P.js +0 -1
- package/dist/gateway/static/root/assets/schedule-summary-B-hdSRdR.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BYS-rpzn.js +0 -1
- package/dist/gateway/static/root/assets/settings-form-section-BsrK7TBF.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-DJiksNu4.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-CU9i0nJV.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-ERbdWENm.js +0 -2
- package/dist/gateway/static/root/assets/use-agent-defaults-form-D3FGVLZb.js +0 -1
- package/dist/gateway/static/root/favicon-16.png +0 -0
- package/dist/gateway/static/root/favicon-32.png +0 -0
- package/dist/src/cron/persistence.d.ts +0 -62
- package/dist/src/cron/persistence.js +0 -188
- package/dist/src/cron/persistence.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-handler.js","names":[],"sources":["../../../../src/agent/messaging/command-handler.ts"],"sourcesContent":["/**\n * Command Handler - Parses and executes commands\n *\n * Handles command execution using the unified command system.\n */\n\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { Config } from '../../config/schema.js';\nimport { isProviderConfiguredSync } from '../../providers/index.js';\nimport type { SessionConfigStore, SessionStore } from '../../session/index.js';\nimport type { ThinkLevel } from '../transcript/thinking-types.js';\nimport type { CompactionResult } from '../memory/compaction.js';\nimport { createLogger } from '../../utils/logger.js';\nimport {\n commandRegistry,\n createCommandContext,\n type CommandContext as UnifiedCommandContext,\n} from '../../chat-commands/index.js';\nimport { getAllProviders, getModelsByProvider, getProviderDisplayName } from '../../providers/index.js';\nimport type { PersistentGoalApis } from '../goals/persistent-goal-apis.js';\nimport type { WorkflowRunServiceLike } from '../../workflows/service/workflow-run-service.types.js';\n\nconst log = createLogger('CommandHandler');\n\n/** Gateway console direct stream uses SSE tokens; there is no ChannelPlugin outbound for `webchat`. */\nfunction shouldSkipBusOutboundForChannel(channel: string): boolean {\n return channel === 'webchat';\n}\n\nexport interface CommandContext {\n sessionKey: string;\n channel: string;\n chatId: string;\n senderId: string;\n isGroup: boolean;\n /** From inbound message metadata (thread/account, etc.) for `/goal` continuation routing. */\n inboundMetadata?: Record<string, unknown>;\n}\n\nexport interface CommandHandlerConfig {\n config: Config;\n bus: MessageBus;\n sessionStore: SessionStore;\n sessionConfigStore?: SessionConfigStore;\n /** After /think persists, sync pi-agent */\n applySessionThinkingLevel?: (sessionKey: string, level: ThinkLevel) => void;\n getCurrentModel: () => string;\n switchModelForSession: (sessionKey: string, modelId: string) => Promise<boolean>;\n /** Drop in-memory agent after session file is cleared (e.g. /new) */\n invalidateAgentSession?: (sessionKey: string) => void;\n /** Reset session in place (archive transcript, new session id; preserve overrides) */\n resetSession?: (sessionKey: string) => Promise<{ sessionId: string; previousSessionId: string } | null>;\n /** Cancel streaming preview + in-flight LLM work for this session (e.g. /abort) */\n abortSessionTurn?: (sessionKey: string) => Promise<void>;\n\n compactSession?: (\n sessionKey: string,\n options?: { instructions?: string; force?: boolean },\n ) => Promise<CompactionResult>;\n\n btwQuery?: (sessionKey: string, question: string) => Promise<{ text: string; error?: string }>;\n\n getSessionContextReport?: (\n sessionKey: string,\n mode: 'list' | 'detail' | 'json',\n ) => Promise<string>;\n\n getPersistentGoalApisForCommand: (routing: {\n sessionKey: string;\n channel: string;\n chatId: string;\n inboundMetadata?: Record<string, unknown>;\n }) => PersistentGoalApis;\n getWorkflowRunService?: () => WorkflowRunServiceLike | undefined;\n}\n\nexport class CommandHandler {\n private config: Config;\n private bus: MessageBus;\n private sessionStore: SessionStore;\n private sessionConfigStore?: SessionConfigStore;\n private applySessionThinkingLevel?: (sessionKey: string, level: ThinkLevel) => void;\n private getCurrentModel: () => string;\n private switchModelForSession: (sessionKey: string, modelId: string) => Promise<boolean>;\n private invalidateAgentSession?: (sessionKey: string) => void;\n private abortSessionTurn?: (sessionKey: string) => Promise<void>;\n private compactSession?: CommandHandlerConfig['compactSession'];\n private btwQuery?: CommandHandlerConfig['btwQuery'];\n private getSessionContextReport?: CommandHandlerConfig['getSessionContextReport'];\n private getPersistentGoalApisForCommand: CommandHandlerConfig['getPersistentGoalApisForCommand'];\n private resetSession?: CommandHandlerConfig['resetSession'];\n private getWorkflowRunService?: CommandHandlerConfig['getWorkflowRunService'];\n\n constructor(handlerConfig: CommandHandlerConfig) {\n this.config = handlerConfig.config;\n this.bus = handlerConfig.bus;\n this.sessionStore = handlerConfig.sessionStore;\n this.sessionConfigStore = handlerConfig.sessionConfigStore;\n this.applySessionThinkingLevel = handlerConfig.applySessionThinkingLevel;\n this.getCurrentModel = handlerConfig.getCurrentModel;\n this.switchModelForSession = handlerConfig.switchModelForSession;\n this.invalidateAgentSession = handlerConfig.invalidateAgentSession;\n this.abortSessionTurn = handlerConfig.abortSessionTurn;\n this.compactSession = handlerConfig.compactSession;\n this.btwQuery = handlerConfig.btwQuery;\n this.getSessionContextReport = handlerConfig.getSessionContextReport;\n this.getPersistentGoalApisForCommand = handlerConfig.getPersistentGoalApisForCommand;\n this.resetSession = handlerConfig.resetSession;\n this.getWorkflowRunService = handlerConfig.getWorkflowRunService;\n }\n\n /** Replace config reference after hot reload or gateway PATCH so commands see current defaults. */\n updateAgentConfig(config: Config): void {\n this.config = config;\n }\n\n /**\n * Build the unified command context shared by all execute paths.\n * When `recorder` is set, every reply text is also captured (for SSE / CLI aggregation).\n */\n private buildCommandContext(\n context: CommandContext,\n recorder?: (text: string) => void,\n ): UnifiedCommandContext {\n const skipBusOutbound = shouldSkipBusOutboundForChannel(context.channel);\n\n return createCommandContext({\n sessionKey: context.sessionKey,\n source: context.channel as 'telegram' | 'webui' | 'cli' | 'api' | 'system' | 'gateway',\n channelId: context.channel,\n chatId: context.chatId,\n senderId: context.senderId,\n isGroup: context.isGroup,\n config: this.config,\n bus: this.bus,\n sessionStore: this.sessionStore,\n sessionConfigStore: this.sessionConfigStore,\n applySessionThinkingLevel: this.applySessionThinkingLevel,\n\n replyHandler: async (text: string, _options?) => {\n recorder?.(text);\n if (skipBusOutbound) return;\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: text,\n type: 'message',\n });\n },\n\n typingHandler: async (typing: boolean) => {\n if (skipBusOutbound) return;\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n type: typing ? 'typing_on' : 'typing_off',\n });\n },\n\n supportedFeatures: ['markdown', 'typing'],\n\n getCurrentModel: this.getCurrentModel,\n\n switchModel: async (modelId: string) => {\n return this.switchModelForSession(context.sessionKey, modelId);\n },\n\n listModels: async () => {\n const providers = getAllProviders();\n const models: Array<{ id: string; name: string; provider: string }> = [];\n\n for (const providerId of providers) {\n if (isProviderConfiguredSync(providerId)) {\n const providerModels = getModelsByProvider(providerId);\n for (const m of providerModels) {\n models.push({\n id: `${m.provider}/${m.id}`,\n name: m.name || m.id,\n provider: getProviderDisplayName(providerId),\n });\n }\n }\n }\n\n return models;\n },\n\n getUsage: async () => {\n const messages = await this.sessionStore.load(context.sessionKey);\n let promptTokens = 0;\n let completionTokens = 0;\n\n for (const msg of messages) {\n if ('usage' in msg && msg.usage) {\n const usage = msg.usage as { input?: number; output?: number };\n promptTokens += usage.input || 0;\n completionTokens += usage.output || 0;\n }\n }\n\n return {\n promptTokens,\n completionTokens,\n totalTokens: promptTokens + completionTokens,\n messageCount: messages.length,\n };\n },\n\n invalidateAgentSession: this.invalidateAgentSession,\n\n resetSession: this.resetSession\n ? async (sk) => {\n await this.resetSession!(sk);\n }\n : undefined,\n\n abortCurrentTurn: this.abortSessionTurn\n ? async () => {\n await this.abortSessionTurn!(context.sessionKey);\n }\n : undefined,\n\n compactSession: this.compactSession,\n btwQuery: this.btwQuery,\n getSessionContextReport: this.getSessionContextReport,\n persistentGoalApis: this.getPersistentGoalApisForCommand({\n sessionKey: context.sessionKey,\n channel: context.channel,\n chatId: context.chatId,\n inboundMetadata: context.inboundMetadata,\n }),\n workflowRunService: this.getWorkflowRunService?.(),\n });\n }\n\n /**\n * Execute a command using the unified command system\n */\n async executeCommand(\n commandName: string,\n args: string,\n context: CommandContext,\n ): Promise<boolean> {\n if (!commandRegistry.has(commandName)) {\n return false;\n }\n\n log.info({ command: commandName, sessionKey: context.sessionKey }, 'Executing command via new system');\n\n const cmdCtx = this.buildCommandContext(context);\n const result = await commandRegistry.execute(commandName, cmdCtx, args);\n\n if (result.content && !shouldSkipBusOutboundForChannel(context.channel)) {\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: result.content,\n type: 'message',\n });\n }\n\n return true;\n }\n\n /**\n * Run command and return all user-visible text (ctx.reply + result.content) for SSE/CLI.\n * Same bus side effects as {@link executeCommand}.\n */\n async executeCommandAndAggregateReply(\n commandName: string,\n args: string,\n context: CommandContext,\n ): Promise<{ handled: boolean; aggregatedText: string; metadata?: Record<string, unknown> }> {\n if (!commandRegistry.has(commandName)) {\n return { handled: false, aggregatedText: '' };\n }\n\n log.info({ command: commandName, sessionKey: context.sessionKey }, 'Executing command (aggregate reply)');\n\n const segments: string[] = [];\n const wrapped = this.buildCommandContext(context, (text) => segments.push(text));\n const result = await commandRegistry.execute(commandName, wrapped, args);\n\n if (result.content) {\n segments.push(result.content);\n if (!shouldSkipBusOutboundForChannel(context.channel)) {\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: result.content,\n type: 'message',\n });\n }\n }\n\n const aggregatedText = segments.filter((s) => s && s.trim()).join('\\n\\n');\n return { handled: true, aggregatedText, metadata: result.metadata };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"command-handler.js","names":[],"sources":["../../../../src/agent/messaging/command-handler.ts"],"sourcesContent":["/**\n * Command Handler - Parses and executes commands\n *\n * Handles command execution using the unified command system.\n */\n\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { Config } from '../../config/schema.js';\nimport { isProviderConfiguredSync } from '../../providers/index.js';\nimport type { SessionConfigStore, SessionStore } from '../../session/index.js';\nimport type { ThinkLevel } from '../transcript/thinking-types.js';\nimport type { CompactionResult } from '../memory/compaction.js';\nimport { createLogger } from '../../utils/logger.js';\nimport {\n commandRegistry,\n createCommandContext,\n type CommandContext as UnifiedCommandContext,\n} from '../../chat-commands/index.js';\nimport { getAllProviders, getModelsByProvider, getProviderDisplayName } from '../../providers/index.js';\nimport type { PersistentGoalApis } from '../goals/persistent-goal-apis.js';\nimport type { WorkflowRunServiceLike } from '../../workflows/service/workflow-run-service.types.js';\n\nconst log = createLogger('CommandHandler');\n\n/** Gateway console direct stream uses SSE tokens; there is no ChannelPlugin outbound for `webchat`. */\nfunction shouldSkipBusOutboundForChannel(channel: string): boolean {\n return channel === 'webchat';\n}\n\nexport interface CommandContext {\n sessionKey: string;\n channel: string;\n chatId: string;\n senderId: string;\n isGroup: boolean;\n /** From inbound message metadata (thread/account, etc.) for `/goal` continuation routing. */\n inboundMetadata?: Record<string, unknown>;\n}\n\nexport interface CommandHandlerConfig {\n config: Config;\n bus: MessageBus;\n sessionStore: SessionStore;\n sessionConfigStore?: SessionConfigStore;\n /** After /think persists, sync pi-agent */\n applySessionThinkingLevel?: (sessionKey: string, level: ThinkLevel) => void;\n getCurrentModel: () => string;\n switchModelForSession: (sessionKey: string, modelId: string) => Promise<boolean>;\n /** Drop in-memory agent after session file is cleared (e.g. /new) */\n invalidateAgentSession?: (sessionKey: string) => void;\n /** Reset session in place (archive transcript, new session id; preserve overrides) */\n resetSession?: (sessionKey: string) => Promise<{ sessionId: string; previousSessionId: string } | null>;\n /** Cancel streaming preview + in-flight LLM work for this session (e.g. /abort) */\n abortSessionTurn?: (sessionKey: string) => Promise<void>;\n /** Reload skills from disk and refresh active agent prompts. */\n reloadSkills?: () => void | Promise<void>;\n\n compactSession?: (\n sessionKey: string,\n options?: { instructions?: string; force?: boolean },\n ) => Promise<CompactionResult>;\n\n btwQuery?: (sessionKey: string, question: string) => Promise<{ text: string; error?: string }>;\n\n getSessionContextReport?: (\n sessionKey: string,\n mode: 'list' | 'detail' | 'json',\n ) => Promise<string>;\n\n getPersistentGoalApisForCommand: (routing: {\n sessionKey: string;\n channel: string;\n chatId: string;\n inboundMetadata?: Record<string, unknown>;\n }) => PersistentGoalApis;\n getWorkflowRunService?: () => WorkflowRunServiceLike | undefined;\n}\n\nexport class CommandHandler {\n private config: Config;\n private bus: MessageBus;\n private sessionStore: SessionStore;\n private sessionConfigStore?: SessionConfigStore;\n private applySessionThinkingLevel?: (sessionKey: string, level: ThinkLevel) => void;\n private getCurrentModel: () => string;\n private switchModelForSession: (sessionKey: string, modelId: string) => Promise<boolean>;\n private invalidateAgentSession?: (sessionKey: string) => void;\n private abortSessionTurn?: (sessionKey: string) => Promise<void>;\n private reloadSkills?: CommandHandlerConfig['reloadSkills'];\n private compactSession?: CommandHandlerConfig['compactSession'];\n private btwQuery?: CommandHandlerConfig['btwQuery'];\n private getSessionContextReport?: CommandHandlerConfig['getSessionContextReport'];\n private getPersistentGoalApisForCommand: CommandHandlerConfig['getPersistentGoalApisForCommand'];\n private resetSession?: CommandHandlerConfig['resetSession'];\n private getWorkflowRunService?: CommandHandlerConfig['getWorkflowRunService'];\n\n constructor(handlerConfig: CommandHandlerConfig) {\n this.config = handlerConfig.config;\n this.bus = handlerConfig.bus;\n this.sessionStore = handlerConfig.sessionStore;\n this.sessionConfigStore = handlerConfig.sessionConfigStore;\n this.applySessionThinkingLevel = handlerConfig.applySessionThinkingLevel;\n this.getCurrentModel = handlerConfig.getCurrentModel;\n this.switchModelForSession = handlerConfig.switchModelForSession;\n this.invalidateAgentSession = handlerConfig.invalidateAgentSession;\n this.abortSessionTurn = handlerConfig.abortSessionTurn;\n this.reloadSkills = handlerConfig.reloadSkills;\n this.compactSession = handlerConfig.compactSession;\n this.btwQuery = handlerConfig.btwQuery;\n this.getSessionContextReport = handlerConfig.getSessionContextReport;\n this.getPersistentGoalApisForCommand = handlerConfig.getPersistentGoalApisForCommand;\n this.resetSession = handlerConfig.resetSession;\n this.getWorkflowRunService = handlerConfig.getWorkflowRunService;\n }\n\n /** Replace config reference after hot reload or gateway PATCH so commands see current defaults. */\n updateAgentConfig(config: Config): void {\n this.config = config;\n }\n\n /**\n * Build the unified command context shared by all execute paths.\n * When `recorder` is set, every reply text is also captured (for SSE / CLI aggregation).\n */\n private buildCommandContext(\n context: CommandContext,\n recorder?: (text: string) => void,\n ): UnifiedCommandContext {\n const skipBusOutbound = shouldSkipBusOutboundForChannel(context.channel);\n\n return createCommandContext({\n sessionKey: context.sessionKey,\n source: context.channel as 'telegram' | 'webui' | 'cli' | 'api' | 'system' | 'gateway',\n channelId: context.channel,\n chatId: context.chatId,\n senderId: context.senderId,\n isGroup: context.isGroup,\n config: this.config,\n bus: this.bus,\n sessionStore: this.sessionStore,\n sessionConfigStore: this.sessionConfigStore,\n applySessionThinkingLevel: this.applySessionThinkingLevel,\n\n replyHandler: async (text: string, _options?) => {\n recorder?.(text);\n if (skipBusOutbound) return;\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: text,\n type: 'message',\n });\n },\n\n typingHandler: async (typing: boolean) => {\n if (skipBusOutbound) return;\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n type: typing ? 'typing_on' : 'typing_off',\n });\n },\n\n supportedFeatures: ['markdown', 'typing'],\n\n getCurrentModel: this.getCurrentModel,\n\n switchModel: async (modelId: string) => {\n return this.switchModelForSession(context.sessionKey, modelId);\n },\n\n listModels: async () => {\n const providers = getAllProviders();\n const models: Array<{ id: string; name: string; provider: string }> = [];\n\n for (const providerId of providers) {\n if (isProviderConfiguredSync(providerId)) {\n const providerModels = getModelsByProvider(providerId);\n for (const m of providerModels) {\n models.push({\n id: `${m.provider}/${m.id}`,\n name: m.name || m.id,\n provider: getProviderDisplayName(providerId),\n });\n }\n }\n }\n\n return models;\n },\n\n getUsage: async () => {\n const messages = await this.sessionStore.load(context.sessionKey);\n let promptTokens = 0;\n let completionTokens = 0;\n\n for (const msg of messages) {\n if ('usage' in msg && msg.usage) {\n const usage = msg.usage as { input?: number; output?: number };\n promptTokens += usage.input || 0;\n completionTokens += usage.output || 0;\n }\n }\n\n return {\n promptTokens,\n completionTokens,\n totalTokens: promptTokens + completionTokens,\n messageCount: messages.length,\n };\n },\n\n invalidateAgentSession: this.invalidateAgentSession,\n\n resetSession: this.resetSession\n ? async (sk) => {\n await this.resetSession!(sk);\n }\n : undefined,\n\n abortCurrentTurn: this.abortSessionTurn\n ? async () => {\n await this.abortSessionTurn!(context.sessionKey);\n }\n : undefined,\n reloadSkills: this.reloadSkills\n ? async () => {\n await this.reloadSkills!();\n }\n : undefined,\n\n compactSession: this.compactSession,\n btwQuery: this.btwQuery,\n getSessionContextReport: this.getSessionContextReport,\n persistentGoalApis: this.getPersistentGoalApisForCommand({\n sessionKey: context.sessionKey,\n channel: context.channel,\n chatId: context.chatId,\n inboundMetadata: context.inboundMetadata,\n }),\n workflowRunService: this.getWorkflowRunService?.(),\n });\n }\n\n /**\n * Execute a command using the unified command system\n */\n async executeCommand(\n commandName: string,\n args: string,\n context: CommandContext,\n ): Promise<boolean> {\n if (!commandRegistry.has(commandName)) {\n return false;\n }\n\n log.info({ command: commandName, sessionKey: context.sessionKey }, 'Executing command via new system');\n\n const cmdCtx = this.buildCommandContext(context);\n const result = await commandRegistry.execute(commandName, cmdCtx, args);\n\n if (result.content && !shouldSkipBusOutboundForChannel(context.channel)) {\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: result.content,\n type: 'message',\n });\n }\n\n return true;\n }\n\n /**\n * Run command and return all user-visible text (ctx.reply + result.content) for SSE/CLI.\n * Same bus side effects as {@link executeCommand}.\n */\n async executeCommandAndAggregateReply(\n commandName: string,\n args: string,\n context: CommandContext,\n ): Promise<{ handled: boolean; aggregatedText: string; metadata?: Record<string, unknown> }> {\n if (!commandRegistry.has(commandName)) {\n return { handled: false, aggregatedText: '' };\n }\n\n log.info({ command: commandName, sessionKey: context.sessionKey }, 'Executing command (aggregate reply)');\n\n const segments: string[] = [];\n const wrapped = this.buildCommandContext(context, (text) => segments.push(text));\n const result = await commandRegistry.execute(commandName, wrapped, args);\n\n if (result.content) {\n segments.push(result.content);\n if (!shouldSkipBusOutboundForChannel(context.channel)) {\n await this.bus.publishOutbound({\n channel: context.channel,\n chat_id: context.chatId,\n content: result.content,\n type: 'message',\n });\n }\n }\n\n const aggregatedText = segments.filter((s) => s && s.trim()).join('\\n\\n');\n return { handled: true, aggregatedText, metadata: result.metadata };\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
|
|
2
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
3
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
|
|
4
4
|
import { getAllModels, getDefaultModelSync, init_providers, resolveModel } from "../../providers/index.js";
|
|
5
5
|
import { resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout } from "../orchestration/run-agent-turn-with-timeout.js";
|
|
6
6
|
import { isAssistantTurnAborted, isAssistantTurnFailed, maybeRetryTurnAfterTransientLlmFailure } from "../orchestration/llm-turn-retry.js";
|
|
@@ -3,8 +3,8 @@ import { init_logger } from "../../../utils/logger.js";
|
|
|
3
3
|
import { requireXopcDatabase } from "../../../storage/sqlite/connection.js";
|
|
4
4
|
import { resolveAgentIdFromMemoriesDir, searchMemoryIndex, syncMemoryIndex } from "../../../storage/sqlite/memory-index-repository.js";
|
|
5
5
|
import "../../../storage/sqlite/index.js";
|
|
6
|
-
import { join, relative } from "path";
|
|
7
6
|
import { existsSync, readFileSync } from "fs";
|
|
7
|
+
import { join, relative } from "path";
|
|
8
8
|
//#region src/agent/prompt/memory/index.ts
|
|
9
9
|
init_logger();
|
|
10
10
|
const log = createLogger("MemorySearch");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolveStateDir } from "../../config/paths-state.js";
|
|
2
|
+
import { init_paths } from "../../config/paths.js";
|
|
2
3
|
import { createLogger } from "../../utils/logger/index.js";
|
|
3
4
|
import { init_logger } from "../../utils/logger.js";
|
|
4
|
-
import { init_paths } from "../../config/paths.js";
|
|
5
5
|
import { DEFAULT_USER_FILENAME } from "../context/workspace.js";
|
|
6
6
|
import { resolveSystemPromptBuildParams } from "./system-prompt-params.js";
|
|
7
7
|
import { buildSystemPrompt } from "./system-prompt.js";
|
|
@@ -9,8 +9,8 @@ import { createSkillConfigManager } from "../skills/config.js";
|
|
|
9
9
|
import { buildTtsSystemPromptHint } from "../../voice/tts/directives.js";
|
|
10
10
|
import { mergeTtsConfigFromAppConfig } from "../../voice/tts/merge-config.js";
|
|
11
11
|
import { selectSkillsVisibleInPrompt } from "../skills/format-skills-prompt.js";
|
|
12
|
-
import { join } from "node:path";
|
|
13
12
|
import { existsSync, readFileSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
14
|
//#region src/agent/prompt/service-prompt-builder.ts
|
|
15
15
|
/**
|
|
16
16
|
* System Prompt Builder - Builds the complete system prompt
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { init_agent_scope, resolveAgentProfileDir } from "../agent-scope.js";
|
|
2
2
|
import { resolveEffectiveAgentProfileForSession } from "../../config/agent-profile.js";
|
|
3
|
-
import { join, resolve } from "node:path";
|
|
4
3
|
import { readFileSync } from "node:fs";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
5
|
//#region src/agent/reply/post-compaction-context.ts
|
|
6
6
|
init_agent_scope();
|
|
7
7
|
const MAX_CONTEXT_CHARS = 1800;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { homedir } from "node:os";
|
|
2
|
-
import { isAbsolute, normalize, resolve, sep } from "node:path";
|
|
3
1
|
import { realpathSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, normalize, resolve, sep } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
4
|
//#region src/agent/sandbox/path-policy.ts
|
|
5
5
|
/**
|
|
6
6
|
* Path safety validation for sandbox isolation.
|
|
@@ -219,6 +219,15 @@ async function* runProcessDirectStreaming(deps, input) {
|
|
|
219
219
|
content: formatStreamError(err instanceof Error ? err.message : String(err))
|
|
220
220
|
});
|
|
221
221
|
} finally {
|
|
222
|
+
if (!userAborted && channel === "webchat") try {
|
|
223
|
+
const ttsAudioEvent = await deps.maybeEmitWebchatTts(sessionKey, inboundVoice);
|
|
224
|
+
if (ttsAudioEvent) queue.push(ttsAudioEvent);
|
|
225
|
+
} catch (ttsErr) {
|
|
226
|
+
deps.log.warn({
|
|
227
|
+
err: ttsErr,
|
|
228
|
+
sessionKey
|
|
229
|
+
}, "Failed to emit TTS audio before stream close");
|
|
230
|
+
}
|
|
222
231
|
queue.close();
|
|
223
232
|
}
|
|
224
233
|
})();
|
|
@@ -254,10 +263,6 @@ async function* runProcessDirectStreaming(deps, input) {
|
|
|
254
263
|
sessionKey
|
|
255
264
|
}, "Failed to persist webchat slash command receipt");
|
|
256
265
|
}
|
|
257
|
-
if (!userAborted) {
|
|
258
|
-
const ttsAudioEvent = await deps.maybeEmitWebchatTts(sessionKey, inboundVoice);
|
|
259
|
-
if (ttsAudioEvent) yield ttsAudioEvent;
|
|
260
|
-
}
|
|
261
266
|
deps.recordPersistentGoalStreamOutcome?.(sessionKey, { skipPersistentGoalPostTurn: ranSlashCommand });
|
|
262
267
|
} finally {
|
|
263
268
|
if (channel === "webchat") deps.unregisterWebchatSsePublisher(sessionKey);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-direct-streaming.js","names":[],"sources":["../../../../src/agent/service/process-direct-streaming.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { ImageContent } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport type { InboundAttachmentInput, MediaRef } from '../../channels/attachments/inbound-persist.js';\nimport { readAgentMessageContent } from '../memory/agent-message-access.js';\nimport {\n isVoiceLikeAttachment,\n mergeVoiceTranscriptsIntoUserText,\n mergeSttConfigFromAppConfig,\n} from '../../channels/attachments/voice-stt-webchat.js';\nimport {\n resolveEffectiveReasoningLevel,\n initSessionTurn,\n type SessionConfigStore,\n type SessionStore,\n} from '../../session/index.js';\nimport type { SessionContext } from '../session/index.js';\nimport { applyReasoningVisibilityToSseEvent } from '../streaming/reasoning-visibility-sse.js';\nimport type { ReasoningLevel } from '../transcript/thinking-types.js';\nimport { formatAgentRunErrorForClient } from '../client-error-format.js';\nimport { abortEmbeddedRun } from '../embedded/runs.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\nimport type { CommandHandler } from '../messaging/command-handler.js';\nimport type { ModelManager } from '../models/index.js';\nimport { injectSourceContextIntoUserMessage } from '../source-context/injector.js';\nimport { isSessionSourceBinding, type AgentSourceContextResolver } from '../source-context/types.js';\n\nimport { AsyncQueue } from './async-queue.js';\nimport {\n hydratePerTurnState,\n runDirectAgentTurn,\n tryRunSlashCommand,\n} from './direct-turn-helpers.js';\nimport {\n clearPendingTranscriptUserMessage,\n setPendingTranscriptUserMessage,\n type TranscriptUserMessage,\n} from '../inbound/attachment-pipeline.js';\n\nexport type DirectStreamInboundAttachment = InboundAttachmentInput;\n\nexport type ProcessDirectStreamLog = {\n info: (obj: Record<string, unknown>, msg: string) => void;\n warn: (obj: Record<string, unknown>, msg: string) => void;\n debug?: (obj: Record<string, unknown>, msg: string) => void;\n};\n\nexport interface ProcessDirectStreamingDeps {\n log: ProcessDirectStreamLog;\n parseSessionKey: (sessionKey: string) => { channel: string; chatId: string };\n initDirectStreamingSession: (\n sessionKey: string,\n channel: string,\n chatId: string,\n ) => SessionContext;\n registerWebchatSsePublisher: (\n sessionKey: string,\n publisher: (event: { type: string; [key: string]: unknown }) => void,\n ) => void;\n unregisterWebchatSsePublisher: (sessionKey: string) => void;\n agentManager: AgentInstanceGateway;\n hydrateSessionWorkspaceFromStore: (sessionKey: string) => Promise<void>;\n hydrateSessionModelFromStore: (sessionKey: string) => Promise<void>;\n sessionStore: SessionStore;\n modelManager: ModelManager;\n applyResolvedThinkingLevel: (sessionKey: string, thinking?: string | null) => Promise<void>;\n getConfig: () => Config | undefined;\n sessionConfigStore: SessionConfigStore;\n commandHandler: Pick<CommandHandler, 'executeCommandAndAggregateReply'>;\n prepareInboundAttachments: (\n sessionKey: string,\n attachments?: DirectStreamInboundAttachment[],\n ) => Promise<MediaRef[] | undefined>;\n buildTranscriptUserMessage: (\n content: string,\n prepared: MediaRef[] | undefined,\n sessionKey: string,\n ) => Promise<TranscriptUserMessage>;\n recordPersistentGoalStreamOutcome?: (\n sessionKey: string,\n outcome: { skipPersistentGoalPostTurn: boolean },\n ) => void;\n onTurnComplete?: (sessionKey: string, lastAssistantText?: string) => void;\n enqueueProvisionalSessionTitle?: (sessionKey: string, userText: string) => void;\n /** Disk-only transcript sync (slash receipt already streamed as tokens). */\n reloadWebchatTranscript?: (sessionKey: string) => void;\n maybeEmitWebchatTts: (\n sessionKey: string,\n hadInboundVoice: boolean,\n ) => Promise<{ type: 'tts_audio'; uri: string; mimeType: string; name: string } | null>;\n endDirectRequestContext: () => void;\n resetSession: (sessionKey: string) => Promise<{ sessionId: string; previousSessionId: string } | null>;\n sourceContextResolver?: AgentSourceContextResolver;\n}\n\nexport interface ProcessDirectStreamingInput {\n content: string;\n sessionKey?: string;\n attachments?: DirectStreamInboundAttachment[];\n thinking?: string;\n signal?: AbortSignal;\n runId?: string;\n}\n\nexport type ProcessDirectStreamingSseEvent = { type: string; [key: string]: unknown };\n\nfunction makeAssistantReceiptMessage(text: string): AgentMessage {\n return {\n role: 'assistant',\n content: [{ type: 'text', text }],\n timestamp: Date.now(),\n } as AgentMessage;\n}\n\nfunction pushAssistantReceipt(\n queue: AsyncQueue<ProcessDirectStreamingSseEvent>,\n text: string,\n runId?: string,\n): void {\n const message = makeAssistantReceiptMessage(text);\n queue.push({ type: 'message_start', runId, message });\n queue.push({ type: 'message_update', runId, message });\n queue.push({ type: 'message_end', runId, message });\n}\n\nexport async function* runProcessDirectStreaming(\n deps: ProcessDirectStreamingDeps,\n input: ProcessDirectStreamingInput,\n): AsyncGenerator<ProcessDirectStreamingSseEvent, void, unknown> {\n const sessionKey = input.sessionKey ?? 'agent:main:main';\n const { channel, chatId } = deps.parseSessionKey(sessionKey);\n const context = deps.initDirectStreamingSession(sessionKey, channel, chatId);\n\n const queue = new AsyncQueue<ProcessDirectStreamingSseEvent>();\n let reasoningLevel: ReasoningLevel = 'stream';\n\n const pushVisible = (event: ProcessDirectStreamingSseEvent) => {\n const visible = applyReasoningVisibilityToSseEvent(event, reasoningLevel);\n if (visible !== null) {\n queue.push(visible);\n }\n };\n\n const formatStreamError = (raw: string): string => {\n let provider: string | undefined;\n let modelRef: string | undefined;\n try {\n const resolved = deps.modelManager.getResolvedModelForSession(sessionKey);\n provider = resolved.provider;\n modelRef = deps.modelManager.getModelForSession(sessionKey);\n } catch {\n /* ignore — format without provider context */\n }\n return formatAgentRunErrorForClient(raw, { provider, modelRef });\n };\n\n if (channel === 'webchat') {\n deps.registerWebchatSsePublisher(sessionKey, pushVisible);\n }\n\n const signal = input.signal;\n let userAborted = false;\n let abortHandled = false;\n let inboundVoice = false;\n let ranSlashCommand = false;\n let mergedUserText = input.content;\n let webchatSlashReceipt: string | undefined;\n let slashCommandMetadata: Record<string, unknown> | undefined;\n\n const taskPromise = (async () => {\n try {\n const cfg = deps.getConfig();\n let turnBody = input.content;\n let resetTriggeredAtInit = false;\n if (cfg) {\n const turn = await initSessionTurn({\n cfg,\n sessionKey,\n body: input.content,\n resetSession: deps.resetSession,\n });\n resetTriggeredAtInit = turn.resetTriggered;\n if (turn.bareReset && turn.ackMessage) {\n ranSlashCommand = true;\n webchatSlashReceipt = turn.ackMessage;\n pushAssistantReceipt(queue, turn.ackMessage, input.runId);\n return;\n }\n turnBody = turn.bodyStripped;\n if (turn.isNewSession) {\n deps.log.debug(\n {\n sessionKey,\n sessionId: turn.sessionId,\n previousSessionId: turn.previousSessionId,\n resetTriggered: turn.resetTriggered,\n staleRollover: turn.staleRollover,\n },\n 'Session reset boundary at direct turn start',\n );\n }\n }\n\n await hydratePerTurnState(deps, sessionKey, input.thinking);\n {\n const defReason = (deps.getConfig()?.agents?.defaults?.reasoningDefault ?? 'stream') as ReasoningLevel;\n reasoningLevel = await resolveEffectiveReasoningLevel(deps.sessionConfigStore, sessionKey, defReason);\n }\n\n const prepared = await deps.prepareInboundAttachments(sessionKey, input.attachments);\n\n const sttCfg = mergeSttConfigFromAppConfig(deps.getConfig()?.tools?.media?.audio, deps.getConfig()?.tools?.media);\n const voiceMerge = await mergeVoiceTranscriptsIntoUserText(prepared, turnBody, sttCfg);\n mergedUserText = voiceMerge.text;\n inboundVoice = voiceMerge.inboundVoice;\n\n if (inboundVoice) {\n const transcriptParts = [\n voiceMerge.voiceTranscripts.filter(Boolean).join('\\n'),\n turnBody.trim(),\n ].filter(Boolean);\n const voiceMedia = (prepared ?? []).filter(isVoiceLikeAttachment).map((att) => ({\n uri: att.uri,\n mimeType: att.mimeType,\n name: att.name,\n }));\n pushVisible({\n type: 'user_transcript',\n text: transcriptParts.join('\\n\\n'),\n media: voiceMedia,\n });\n }\n\n const armAbort = () => {\n if (abortHandled) {\n return;\n }\n abortHandled = true;\n userAborted = true;\n void abortEmbeddedRun(sessionKey);\n queue.close();\n };\n if (signal) {\n if (signal.aborted) {\n armAbort();\n return;\n }\n signal.addEventListener('abort', armAbort, { once: true });\n }\n\n const slash = await tryRunSlashCommand(\n deps,\n {\n sessionKey,\n channel,\n chatId,\n senderId: context.senderId,\n isGroup: context.isGroup,\n inboundMetadata: context.metadata,\n },\n mergedUserText,\n { skipResetCommands: resetTriggeredAtInit },\n );\n if (slash.matched) {\n ranSlashCommand = true;\n slashCommandMetadata = slash.metadata;\n const text = slash.aggregatedText.trim();\n if (text) {\n webchatSlashReceipt = text;\n pushAssistantReceipt(queue, text, input.runId);\n } else if (channel === 'webchat') {\n webchatSlashReceipt =\n 'Command finished with no assistant text. If you used `/goal`, a follow-up turn may still be scheduled automatically.';\n pushAssistantReceipt(queue, webchatSlashReceipt, input.runId);\n }\n const workflowRun = slash.metadata?.workflowRun;\n if (workflowRun && typeof workflowRun === 'object') {\n queue.push({\n type: 'workflow_run_started',\n runId: input.runId,\n payload: { workflowRun },\n });\n }\n return;\n }\n\n const textForAgent = mergedUserText.trimStart().startsWith('/skill:')\n ? deps.agentManager.expandSkillUserText(mergedUserText)\n : mergedUserText;\n const userMessage = await deps.buildTranscriptUserMessage(textForAgent, prepared, sessionKey);\n let sourceEnrichedUserMessage: AgentMessage = userMessage;\n let sourceImages: ImageContent[] | undefined;\n if (deps.sourceContextResolver) {\n const metadata = await deps.sessionStore.getMetadata(sessionKey).catch(() => null);\n const sourceBinding = metadata?.customData && typeof metadata.customData === 'object'\n ? (metadata.customData as Record<string, unknown>).sourceBinding\n : undefined;\n if (isSessionSourceBinding(sourceBinding)) {\n const sourceContext = await deps.sourceContextResolver(sourceBinding, sessionKey);\n sourceEnrichedUserMessage = injectSourceContextIntoUserMessage(userMessage, sourceContext);\n sourceImages = sourceContext?.images;\n }\n }\n\n if (channel === 'webchat') {\n pushVisible({\n type: 'user_message',\n timestamp: userMessage.timestamp ?? Date.now(),\n content: readAgentMessageContent(userMessage),\n media: userMessage.media,\n });\n if (textForAgent.trim()) {\n deps.enqueueProvisionalSessionTitle?.(sessionKey, textForAgent);\n }\n }\n\n const pendingUserMessage = userMessage as TranscriptUserMessage;\n setPendingTranscriptUserMessage(sessionKey, pendingUserMessage);\n\n try {\n const result = await runDirectAgentTurn(\n {\n sessionStore: deps.sessionStore,\n agentManager: deps.agentManager,\n modelManager: deps.modelManager,\n config: deps.getConfig(),\n },\n {\n sessionKey,\n userMessage: sourceEnrichedUserMessage,\n abortSignal: signal,\n sourceImages,\n runId: input.runId,\n onEvent: (embeddedEvent) => {\n const event = { ...embeddedEvent };\n if (event.type === 'error' && typeof event.content === 'string') {\n event.content = formatStreamError(event.content);\n }\n pushVisible(event);\n },\n },\n );\n\n if (result.lastAssistantText) {\n deps.onTurnComplete?.(sessionKey, result.lastAssistantText);\n }\n if (!result.ok && result.errorMessage && !abortHandled) {\n pushVisible({ type: 'error', content: formatStreamError(result.errorMessage) });\n }\n } finally {\n clearPendingTranscriptUserMessage(sessionKey, pendingUserMessage);\n }\n } catch (err) {\n if (!abortHandled) {\n const em = err instanceof Error ? err.message : String(err);\n pushVisible({ type: 'error', content: formatStreamError(em) });\n }\n } finally {\n queue.close();\n }\n })();\n\n try {\n for await (const event of queue) {\n yield event;\n }\n await taskPromise;\n\n if (channel === 'webchat' && ranSlashCommand) {\n try {\n const userMsg = {\n role: 'user' as const,\n content: [{ type: 'text' as const, text: mergedUserText }],\n timestamp: Date.now(),\n } as AgentMessage;\n await deps.sessionStore.appendTranscriptMessage(sessionKey, userMsg);\n if (webchatSlashReceipt?.trim()) {\n const assistantMsg = {\n role: 'assistant' as const,\n content: [{ type: 'text' as const, text: webchatSlashReceipt.trim() }],\n timestamp: Date.now(),\n ...(slashCommandMetadata && Object.keys(slashCommandMetadata).length > 0\n ? { metadata: slashCommandMetadata }\n : {}),\n } as AgentMessage;\n await deps.sessionStore.appendTranscriptMessage(sessionKey, assistantMsg);\n }\n deps.reloadWebchatTranscript?.(sessionKey);\n } catch (err) {\n deps.log.warn({ err, sessionKey }, 'Failed to persist webchat slash command receipt');\n }\n }\n\n if (!userAborted) {\n const ttsAudioEvent = await deps.maybeEmitWebchatTts(sessionKey, inboundVoice);\n if (ttsAudioEvent) {\n yield ttsAudioEvent;\n }\n }\n\n deps.recordPersistentGoalStreamOutcome?.(sessionKey, { skipPersistentGoalPostTurn: ranSlashCommand });\n } finally {\n if (channel === 'webchat') {\n deps.unregisterWebchatSsePublisher(sessionKey);\n }\n deps.endDirectRequestContext();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"process-direct-streaming.js","names":[],"sources":["../../../../src/agent/service/process-direct-streaming.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { ImageContent } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport type { InboundAttachmentInput, MediaRef } from '../../channels/attachments/inbound-persist.js';\nimport { readAgentMessageContent } from '../memory/agent-message-access.js';\nimport {\n isVoiceLikeAttachment,\n mergeVoiceTranscriptsIntoUserText,\n mergeSttConfigFromAppConfig,\n} from '../../channels/attachments/voice-stt-webchat.js';\nimport {\n resolveEffectiveReasoningLevel,\n initSessionTurn,\n type SessionConfigStore,\n type SessionStore,\n} from '../../session/index.js';\nimport type { SessionContext } from '../session/index.js';\nimport { applyReasoningVisibilityToSseEvent } from '../streaming/reasoning-visibility-sse.js';\nimport type { ReasoningLevel } from '../transcript/thinking-types.js';\nimport { formatAgentRunErrorForClient } from '../client-error-format.js';\nimport { abortEmbeddedRun } from '../embedded/runs.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\nimport type { CommandHandler } from '../messaging/command-handler.js';\nimport type { ModelManager } from '../models/index.js';\nimport { injectSourceContextIntoUserMessage } from '../source-context/injector.js';\nimport { isSessionSourceBinding, type AgentSourceContextResolver } from '../source-context/types.js';\n\nimport { AsyncQueue } from './async-queue.js';\nimport {\n hydratePerTurnState,\n runDirectAgentTurn,\n tryRunSlashCommand,\n} from './direct-turn-helpers.js';\nimport {\n clearPendingTranscriptUserMessage,\n setPendingTranscriptUserMessage,\n type TranscriptUserMessage,\n} from '../inbound/attachment-pipeline.js';\n\nexport type DirectStreamInboundAttachment = InboundAttachmentInput;\n\nexport type ProcessDirectStreamLog = {\n info: (obj: Record<string, unknown>, msg: string) => void;\n warn: (obj: Record<string, unknown>, msg: string) => void;\n debug?: (obj: Record<string, unknown>, msg: string) => void;\n};\n\nexport interface ProcessDirectStreamingDeps {\n log: ProcessDirectStreamLog;\n parseSessionKey: (sessionKey: string) => { channel: string; chatId: string };\n initDirectStreamingSession: (\n sessionKey: string,\n channel: string,\n chatId: string,\n ) => SessionContext;\n registerWebchatSsePublisher: (\n sessionKey: string,\n publisher: (event: { type: string; [key: string]: unknown }) => void,\n ) => void;\n unregisterWebchatSsePublisher: (sessionKey: string) => void;\n agentManager: AgentInstanceGateway;\n hydrateSessionWorkspaceFromStore: (sessionKey: string) => Promise<void>;\n hydrateSessionModelFromStore: (sessionKey: string) => Promise<void>;\n sessionStore: SessionStore;\n modelManager: ModelManager;\n applyResolvedThinkingLevel: (sessionKey: string, thinking?: string | null) => Promise<void>;\n getConfig: () => Config | undefined;\n sessionConfigStore: SessionConfigStore;\n commandHandler: Pick<CommandHandler, 'executeCommandAndAggregateReply'>;\n prepareInboundAttachments: (\n sessionKey: string,\n attachments?: DirectStreamInboundAttachment[],\n ) => Promise<MediaRef[] | undefined>;\n buildTranscriptUserMessage: (\n content: string,\n prepared: MediaRef[] | undefined,\n sessionKey: string,\n ) => Promise<TranscriptUserMessage>;\n recordPersistentGoalStreamOutcome?: (\n sessionKey: string,\n outcome: { skipPersistentGoalPostTurn: boolean },\n ) => void;\n onTurnComplete?: (sessionKey: string, lastAssistantText?: string) => void;\n enqueueProvisionalSessionTitle?: (sessionKey: string, userText: string) => void;\n /** Disk-only transcript sync (slash receipt already streamed as tokens). */\n reloadWebchatTranscript?: (sessionKey: string) => void;\n maybeEmitWebchatTts: (\n sessionKey: string,\n hadInboundVoice: boolean,\n ) => Promise<{ type: 'tts_audio'; uri: string; mimeType: string; name: string } | null>;\n endDirectRequestContext: () => void;\n resetSession: (sessionKey: string) => Promise<{ sessionId: string; previousSessionId: string } | null>;\n sourceContextResolver?: AgentSourceContextResolver;\n}\n\nexport interface ProcessDirectStreamingInput {\n content: string;\n sessionKey?: string;\n attachments?: DirectStreamInboundAttachment[];\n thinking?: string;\n signal?: AbortSignal;\n runId?: string;\n}\n\nexport type ProcessDirectStreamingSseEvent = { type: string; [key: string]: unknown };\n\nfunction makeAssistantReceiptMessage(text: string): AgentMessage {\n return {\n role: 'assistant',\n content: [{ type: 'text', text }],\n timestamp: Date.now(),\n } as AgentMessage;\n}\n\nfunction pushAssistantReceipt(\n queue: AsyncQueue<ProcessDirectStreamingSseEvent>,\n text: string,\n runId?: string,\n): void {\n const message = makeAssistantReceiptMessage(text);\n queue.push({ type: 'message_start', runId, message });\n queue.push({ type: 'message_update', runId, message });\n queue.push({ type: 'message_end', runId, message });\n}\n\nexport async function* runProcessDirectStreaming(\n deps: ProcessDirectStreamingDeps,\n input: ProcessDirectStreamingInput,\n): AsyncGenerator<ProcessDirectStreamingSseEvent, void, unknown> {\n const sessionKey = input.sessionKey ?? 'agent:main:main';\n const { channel, chatId } = deps.parseSessionKey(sessionKey);\n const context = deps.initDirectStreamingSession(sessionKey, channel, chatId);\n\n const queue = new AsyncQueue<ProcessDirectStreamingSseEvent>();\n let reasoningLevel: ReasoningLevel = 'stream';\n\n const pushVisible = (event: ProcessDirectStreamingSseEvent) => {\n const visible = applyReasoningVisibilityToSseEvent(event, reasoningLevel);\n if (visible !== null) {\n queue.push(visible);\n }\n };\n\n const formatStreamError = (raw: string): string => {\n let provider: string | undefined;\n let modelRef: string | undefined;\n try {\n const resolved = deps.modelManager.getResolvedModelForSession(sessionKey);\n provider = resolved.provider;\n modelRef = deps.modelManager.getModelForSession(sessionKey);\n } catch {\n /* ignore — format without provider context */\n }\n return formatAgentRunErrorForClient(raw, { provider, modelRef });\n };\n\n if (channel === 'webchat') {\n deps.registerWebchatSsePublisher(sessionKey, pushVisible);\n }\n\n const signal = input.signal;\n let userAborted = false;\n let abortHandled = false;\n let inboundVoice = false;\n let ranSlashCommand = false;\n let mergedUserText = input.content;\n let webchatSlashReceipt: string | undefined;\n let slashCommandMetadata: Record<string, unknown> | undefined;\n\n const taskPromise = (async () => {\n try {\n const cfg = deps.getConfig();\n let turnBody = input.content;\n let resetTriggeredAtInit = false;\n if (cfg) {\n const turn = await initSessionTurn({\n cfg,\n sessionKey,\n body: input.content,\n resetSession: deps.resetSession,\n });\n resetTriggeredAtInit = turn.resetTriggered;\n if (turn.bareReset && turn.ackMessage) {\n ranSlashCommand = true;\n webchatSlashReceipt = turn.ackMessage;\n pushAssistantReceipt(queue, turn.ackMessage, input.runId);\n return;\n }\n turnBody = turn.bodyStripped;\n if (turn.isNewSession) {\n deps.log.debug(\n {\n sessionKey,\n sessionId: turn.sessionId,\n previousSessionId: turn.previousSessionId,\n resetTriggered: turn.resetTriggered,\n staleRollover: turn.staleRollover,\n },\n 'Session reset boundary at direct turn start',\n );\n }\n }\n\n await hydratePerTurnState(deps, sessionKey, input.thinking);\n {\n const defReason = (deps.getConfig()?.agents?.defaults?.reasoningDefault ?? 'stream') as ReasoningLevel;\n reasoningLevel = await resolveEffectiveReasoningLevel(deps.sessionConfigStore, sessionKey, defReason);\n }\n\n const prepared = await deps.prepareInboundAttachments(sessionKey, input.attachments);\n\n const sttCfg = mergeSttConfigFromAppConfig(deps.getConfig()?.tools?.media?.audio, deps.getConfig()?.tools?.media);\n const voiceMerge = await mergeVoiceTranscriptsIntoUserText(prepared, turnBody, sttCfg);\n mergedUserText = voiceMerge.text;\n inboundVoice = voiceMerge.inboundVoice;\n\n if (inboundVoice) {\n const transcriptParts = [\n voiceMerge.voiceTranscripts.filter(Boolean).join('\\n'),\n turnBody.trim(),\n ].filter(Boolean);\n const voiceMedia = (prepared ?? []).filter(isVoiceLikeAttachment).map((att) => ({\n uri: att.uri,\n mimeType: att.mimeType,\n name: att.name,\n }));\n pushVisible({\n type: 'user_transcript',\n text: transcriptParts.join('\\n\\n'),\n media: voiceMedia,\n });\n }\n\n const armAbort = () => {\n if (abortHandled) {\n return;\n }\n abortHandled = true;\n userAborted = true;\n void abortEmbeddedRun(sessionKey);\n queue.close();\n };\n if (signal) {\n if (signal.aborted) {\n armAbort();\n return;\n }\n signal.addEventListener('abort', armAbort, { once: true });\n }\n\n const slash = await tryRunSlashCommand(\n deps,\n {\n sessionKey,\n channel,\n chatId,\n senderId: context.senderId,\n isGroup: context.isGroup,\n inboundMetadata: context.metadata,\n },\n mergedUserText,\n { skipResetCommands: resetTriggeredAtInit },\n );\n if (slash.matched) {\n ranSlashCommand = true;\n slashCommandMetadata = slash.metadata;\n const text = slash.aggregatedText.trim();\n if (text) {\n webchatSlashReceipt = text;\n pushAssistantReceipt(queue, text, input.runId);\n } else if (channel === 'webchat') {\n webchatSlashReceipt =\n 'Command finished with no assistant text. If you used `/goal`, a follow-up turn may still be scheduled automatically.';\n pushAssistantReceipt(queue, webchatSlashReceipt, input.runId);\n }\n const workflowRun = slash.metadata?.workflowRun;\n if (workflowRun && typeof workflowRun === 'object') {\n queue.push({\n type: 'workflow_run_started',\n runId: input.runId,\n payload: { workflowRun },\n });\n }\n return;\n }\n\n const textForAgent = mergedUserText.trimStart().startsWith('/skill:')\n ? deps.agentManager.expandSkillUserText(mergedUserText)\n : mergedUserText;\n const userMessage = await deps.buildTranscriptUserMessage(textForAgent, prepared, sessionKey);\n let sourceEnrichedUserMessage: AgentMessage = userMessage;\n let sourceImages: ImageContent[] | undefined;\n if (deps.sourceContextResolver) {\n const metadata = await deps.sessionStore.getMetadata(sessionKey).catch(() => null);\n const sourceBinding = metadata?.customData && typeof metadata.customData === 'object'\n ? (metadata.customData as Record<string, unknown>).sourceBinding\n : undefined;\n if (isSessionSourceBinding(sourceBinding)) {\n const sourceContext = await deps.sourceContextResolver(sourceBinding, sessionKey);\n sourceEnrichedUserMessage = injectSourceContextIntoUserMessage(userMessage, sourceContext);\n sourceImages = sourceContext?.images;\n }\n }\n\n if (channel === 'webchat') {\n pushVisible({\n type: 'user_message',\n timestamp: userMessage.timestamp ?? Date.now(),\n content: readAgentMessageContent(userMessage),\n media: userMessage.media,\n });\n if (textForAgent.trim()) {\n deps.enqueueProvisionalSessionTitle?.(sessionKey, textForAgent);\n }\n }\n\n const pendingUserMessage = userMessage as TranscriptUserMessage;\n setPendingTranscriptUserMessage(sessionKey, pendingUserMessage);\n\n try {\n const result = await runDirectAgentTurn(\n {\n sessionStore: deps.sessionStore,\n agentManager: deps.agentManager,\n modelManager: deps.modelManager,\n config: deps.getConfig(),\n },\n {\n sessionKey,\n userMessage: sourceEnrichedUserMessage,\n abortSignal: signal,\n sourceImages,\n runId: input.runId,\n onEvent: (embeddedEvent) => {\n const event = { ...embeddedEvent };\n if (event.type === 'error' && typeof event.content === 'string') {\n event.content = formatStreamError(event.content);\n }\n pushVisible(event);\n },\n },\n );\n\n if (result.lastAssistantText) {\n deps.onTurnComplete?.(sessionKey, result.lastAssistantText);\n }\n if (!result.ok && result.errorMessage && !abortHandled) {\n pushVisible({ type: 'error', content: formatStreamError(result.errorMessage) });\n }\n } finally {\n clearPendingTranscriptUserMessage(sessionKey, pendingUserMessage);\n }\n } catch (err) {\n if (!abortHandled) {\n const em = err instanceof Error ? err.message : String(err);\n pushVisible({ type: 'error', content: formatStreamError(em) });\n }\n } finally {\n if (!userAborted && channel === 'webchat') {\n try {\n const ttsAudioEvent = await deps.maybeEmitWebchatTts(sessionKey, inboundVoice);\n if (ttsAudioEvent) {\n queue.push(ttsAudioEvent);\n }\n } catch (ttsErr) {\n deps.log.warn({ err: ttsErr, sessionKey }, 'Failed to emit TTS audio before stream close');\n }\n }\n queue.close();\n }\n })();\n\n try {\n for await (const event of queue) {\n yield event;\n }\n await taskPromise;\n\n if (channel === 'webchat' && ranSlashCommand) {\n try {\n const userMsg = {\n role: 'user' as const,\n content: [{ type: 'text' as const, text: mergedUserText }],\n timestamp: Date.now(),\n } as AgentMessage;\n await deps.sessionStore.appendTranscriptMessage(sessionKey, userMsg);\n if (webchatSlashReceipt?.trim()) {\n const assistantMsg = {\n role: 'assistant' as const,\n content: [{ type: 'text' as const, text: webchatSlashReceipt.trim() }],\n timestamp: Date.now(),\n ...(slashCommandMetadata && Object.keys(slashCommandMetadata).length > 0\n ? { metadata: slashCommandMetadata }\n : {}),\n } as AgentMessage;\n await deps.sessionStore.appendTranscriptMessage(sessionKey, assistantMsg);\n }\n deps.reloadWebchatTranscript?.(sessionKey);\n } catch (err) {\n deps.log.warn({ err, sessionKey }, 'Failed to persist webchat slash command receipt');\n }\n }\n\n deps.recordPersistentGoalStreamOutcome?.(sessionKey, { skipPersistentGoalPostTurn: ranSlashCommand });\n } finally {\n if (channel === 'webchat') {\n deps.unregisterWebchatSsePublisher(sessionKey);\n }\n deps.endDirectRequestContext();\n }\n}\n"],"mappings":"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"}
|
|
@@ -52,10 +52,14 @@ async function reconcileManagedDreamingCronJobs(cron, effectiveConfig) {
|
|
|
52
52
|
kind: "agentTurn",
|
|
53
53
|
message: spec.token
|
|
54
54
|
};
|
|
55
|
+
const desiredSchedule = {
|
|
56
|
+
kind: "cron",
|
|
57
|
+
expr: spec.schedule,
|
|
58
|
+
...dreaming.timezone ? { tz: dreaming.timezone } : {}
|
|
59
|
+
};
|
|
55
60
|
if (phaseJobs.length === 0) {
|
|
56
|
-
await cron.addJob(
|
|
61
|
+
await cron.addJob(desiredSchedule, {
|
|
57
62
|
name: spec.cronName,
|
|
58
|
-
timezone: dreaming.timezone,
|
|
59
63
|
sessionTarget: "isolated",
|
|
60
64
|
payload: desiredPayload,
|
|
61
65
|
enabled: true
|
|
@@ -65,9 +69,8 @@ async function reconcileManagedDreamingCronJobs(cron, effectiveConfig) {
|
|
|
65
69
|
const primary = phaseJobs[0];
|
|
66
70
|
for (const dup of phaseJobs.slice(1)) await cron.removeJob(dup.id).catch(() => {});
|
|
67
71
|
const payloadMessage = primary.payload?.kind === "agentTurn" ? primary.payload.message : primary.payload?.text;
|
|
68
|
-
if (primary.schedule !==
|
|
69
|
-
schedule:
|
|
70
|
-
timezone: dreaming.timezone ?? void 0,
|
|
72
|
+
if (JSON.stringify(primary.schedule) !== JSON.stringify(desiredSchedule) || primary.sessionTarget !== "isolated" || payloadMessage !== spec.token || primary.enabled !== true || primary.name !== spec.cronName) await cron.updateJob(primary.id, {
|
|
73
|
+
schedule: desiredSchedule,
|
|
71
74
|
sessionTarget: "isolated",
|
|
72
75
|
name: spec.cronName,
|
|
73
76
|
payload: desiredPayload,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconcile-dreaming-cron.js","names":[],"sources":["../../../../src/agent/service/reconcile-dreaming-cron.ts"],"sourcesContent":["import type { Config } from '../../config/schema.js';\nimport type { CronService } from '../../cron/index.js';\nimport type {
|
|
1
|
+
{"version":3,"file":"reconcile-dreaming-cron.js","names":[],"sources":["../../../../src/agent/service/reconcile-dreaming-cron.ts"],"sourcesContent":["import type { Config } from '../../config/schema.js';\nimport type { CronService } from '../../cron/index.js';\nimport type { JobData } from '../../cron/types.js';\nimport {\n DREAMING_SWEEP_TOKEN,\n DREAMING_LIGHT_CRON_NAME,\n DREAMING_LIGHT_SWEEP_TOKEN,\n DREAMING_CRON_NAME,\n DREAMING_REM_CRON_NAME,\n DREAMING_REM_SWEEP_TOKEN,\n} from '../memory/dreaming/constants.js';\nimport { resolveDreamingConfig } from '../memory/dreaming/config.js';\n\nconst DREAMING_SWEEP_TOKENS = new Set<string>([\n DREAMING_LIGHT_SWEEP_TOKEN,\n DREAMING_SWEEP_TOKEN,\n DREAMING_REM_SWEEP_TOKEN,\n]);\n\nfunction dreamingSweepTokenFromJob(job: JobData): string | undefined {\n if (job.payload?.kind !== 'agentTurn') {\n return undefined;\n }\n const msg = job.payload.message;\n return typeof msg === 'string' && DREAMING_SWEEP_TOKENS.has(msg) ? msg : undefined;\n}\n\n/**\n * Reconcile managed Dreaming cron jobs against the current effective config.\n */\nexport async function reconcileManagedDreamingCronJobs(\n cron: CronService,\n effectiveConfig: Config | undefined,\n): Promise<void> {\n const dreaming = resolveDreamingConfig(effectiveConfig);\n const jobs = await cron.listJobs();\n /** Match by sweep token — job names omit `[managed-by=…]`, so name-only matching never saw these jobs and re-added them every reconcile. */\n const managed = jobs.filter((job) => dreamingSweepTokenFromJob(job) !== undefined);\n\n const phaseSpecs: Array<{\n cronName: string;\n token: string;\n schedule: string;\n phaseEnabled: boolean;\n }> = [\n {\n cronName: DREAMING_LIGHT_CRON_NAME,\n token: DREAMING_LIGHT_SWEEP_TOKEN,\n schedule: dreaming.phases.light.cron,\n phaseEnabled: dreaming.phases.light.enabled,\n },\n {\n cronName: DREAMING_CRON_NAME,\n token: DREAMING_SWEEP_TOKEN,\n schedule: dreaming.phases.deep.cron,\n phaseEnabled: dreaming.phases.deep.enabled,\n },\n {\n cronName: DREAMING_REM_CRON_NAME,\n token: DREAMING_REM_SWEEP_TOKEN,\n schedule: dreaming.phases.rem.cron,\n phaseEnabled: dreaming.phases.rem.enabled,\n },\n ];\n\n if (!dreaming.enabled) {\n for (const job of managed) {\n await cron.removeJob(job.id).catch(() => {});\n }\n return;\n }\n\n for (const spec of phaseSpecs) {\n const phaseJobs = managed.filter((job) => dreamingSweepTokenFromJob(job) === spec.token);\n\n if (!spec.phaseEnabled) {\n for (const job of phaseJobs) {\n await cron.removeJob(job.id).catch(() => {});\n }\n continue;\n }\n\n const desiredPayload = { kind: 'agentTurn' as const, message: spec.token };\n const desiredSchedule = {\n kind: 'cron' as const,\n expr: spec.schedule,\n ...(dreaming.timezone ? { tz: dreaming.timezone } : {}),\n };\n\n if (phaseJobs.length === 0) {\n await cron.addJob(desiredSchedule, {\n name: spec.cronName,\n sessionTarget: 'isolated' as const,\n payload: desiredPayload,\n enabled: true,\n } as any);\n continue;\n }\n\n const primary = phaseJobs[0]!;\n for (const dup of phaseJobs.slice(1)) {\n await cron.removeJob(dup.id).catch(() => {});\n }\n\n const payloadMessage =\n primary.payload?.kind === 'agentTurn'\n ? primary.payload.message\n : (primary.payload as any)?.text;\n const needsUpdate =\n JSON.stringify(primary.schedule) !== JSON.stringify(desiredSchedule) ||\n primary.sessionTarget !== 'isolated' ||\n payloadMessage !== spec.token ||\n primary.enabled !== true ||\n primary.name !== spec.cronName;\n\n if (needsUpdate) {\n await cron.updateJob(primary.id, {\n schedule: desiredSchedule,\n sessionTarget: 'isolated',\n name: spec.cronName,\n payload: desiredPayload,\n enabled: true,\n } as any);\n }\n }\n}\n"],"mappings":";;;AAaA,MAAM,wBAAwB,IAAI,IAAY;CAC5C;CACA;CACA;CACD,CAAC;AAEF,SAAS,0BAA0B,KAAkC;AACnE,KAAI,IAAI,SAAS,SAAS,YACxB;CAEF,MAAM,MAAM,IAAI,QAAQ;AACxB,QAAO,OAAO,QAAQ,YAAY,sBAAsB,IAAI,IAAI,GAAG,MAAM,KAAA;;;;;AAM3E,eAAsB,iCACpB,MACA,iBACe;CACf,MAAM,WAAW,sBAAsB,gBAAgB;;CAGvD,MAAM,WAAU,MAFG,KAAK,UAAU,EAEb,QAAQ,QAAQ,0BAA0B,IAAI,KAAK,KAAA,EAAU;CAElF,MAAM,aAKD;EACH;GACE,UAAU;GACV,OAAO;GACP,UAAU,SAAS,OAAO,MAAM;GAChC,cAAc,SAAS,OAAO,MAAM;GACrC;EACD;GACE,UAAU;GACV,OAAO;GACP,UAAU,SAAS,OAAO,KAAK;GAC/B,cAAc,SAAS,OAAO,KAAK;GACpC;EACD;GACE,UAAU;GACV,OAAO;GACP,UAAU,SAAS,OAAO,IAAI;GAC9B,cAAc,SAAS,OAAO,IAAI;GACnC;EACF;AAED,KAAI,CAAC,SAAS,SAAS;AACrB,OAAK,MAAM,OAAO,QAChB,OAAM,KAAK,UAAU,IAAI,GAAG,CAAC,YAAY,GAAG;AAE9C;;AAGF,MAAK,MAAM,QAAQ,YAAY;EAC7B,MAAM,YAAY,QAAQ,QAAQ,QAAQ,0BAA0B,IAAI,KAAK,KAAK,MAAM;AAExF,MAAI,CAAC,KAAK,cAAc;AACtB,QAAK,MAAM,OAAO,UAChB,OAAM,KAAK,UAAU,IAAI,GAAG,CAAC,YAAY,GAAG;AAE9C;;EAGF,MAAM,iBAAiB;GAAE,MAAM;GAAsB,SAAS,KAAK;GAAO;EAC1E,MAAM,kBAAkB;GACtB,MAAM;GACN,MAAM,KAAK;GACX,GAAI,SAAS,WAAW,EAAE,IAAI,SAAS,UAAU,GAAG,EAAE;GACvD;AAED,MAAI,UAAU,WAAW,GAAG;AAC1B,SAAM,KAAK,OAAO,iBAAiB;IACjC,MAAM,KAAK;IACX,eAAe;IACf,SAAS;IACT,SAAS;IACV,CAAQ;AACT;;EAGF,MAAM,UAAU,UAAU;AAC1B,OAAK,MAAM,OAAO,UAAU,MAAM,EAAE,CAClC,OAAM,KAAK,UAAU,IAAI,GAAG,CAAC,YAAY,GAAG;EAG9C,MAAM,iBACJ,QAAQ,SAAS,SAAS,cACtB,QAAQ,QAAQ,UACf,QAAQ,SAAiB;AAQhC,MANE,KAAK,UAAU,QAAQ,SAAS,KAAK,KAAK,UAAU,gBAAgB,IACpE,QAAQ,kBAAkB,cAC1B,mBAAmB,KAAK,SACxB,QAAQ,YAAY,QACpB,QAAQ,SAAS,KAAK,SAGtB,OAAM,KAAK,UAAU,QAAQ,IAAI;GAC/B,UAAU;GACV,eAAe;GACf,MAAM,KAAK;GACX,SAAS;GACT,SAAS;GACV,CAAQ"}
|
|
@@ -5,7 +5,7 @@ import { SessionStore } from '../session/index.js';
|
|
|
5
5
|
import { OutboundCoordinator } from './messaging/index.js';
|
|
6
6
|
import { TurnDispatcher } from './inbound/turn-dispatcher.js';
|
|
7
7
|
import { SessionConfigService, SessionHydrator, SessionInspector } from './session/index.js';
|
|
8
|
-
import { type AgentSkillAvailabilityPayload, type SkillCatalogEntry } from './agent-manager.js';
|
|
8
|
+
import { type AgentSkillAvailabilityPayload, type SkillCatalogEntry, type SkillCatalogSnapshot } from './agent-manager.js';
|
|
9
9
|
import type { SkillMarkdownPreviewPayload } from './skills/types.js';
|
|
10
10
|
import type { AgentServiceConfig, StreamHandle } from './service.types.js';
|
|
11
11
|
import { PersistentGoalService } from './goals/persistent-goal-service.js';
|
|
@@ -109,6 +109,7 @@ export declare class AgentService {
|
|
|
109
109
|
*/
|
|
110
110
|
applyAgentDefaultsFromConfig(config: Config): void;
|
|
111
111
|
getSkillCatalog(): SkillCatalogEntry[];
|
|
112
|
+
getSkillCatalogSnapshot(): SkillCatalogSnapshot;
|
|
112
113
|
getAgentSkillAvailability(agentId: string): AgentSkillAvailabilityPayload;
|
|
113
114
|
getSkillMarkdownSource(skillName: string): SkillMarkdownPreviewPayload | null;
|
|
114
115
|
refreshSkillsAfterDiskChange(): void;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
|
|
2
|
-
import { applyConfigOverrides } from "../config/runtime-overrides.js";
|
|
3
1
|
import { init_agent_scope, resolveAgentHomeDir, resolveAgentProfileDir, resolveDefaultAgentId } from "./agent-scope.js";
|
|
4
|
-
import { extractProfileAgentId, resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
|
|
5
2
|
import { createLogger } from "../utils/logger/index.js";
|
|
6
3
|
import { init_logger } from "../utils/logger.js";
|
|
4
|
+
import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
|
|
5
|
+
import { applyConfigOverrides } from "../config/runtime-overrides.js";
|
|
6
|
+
import { extractProfileAgentId, resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
|
|
7
7
|
import { extractTextContent } from "./context/workspace.js";
|
|
8
8
|
import { parseNoteAttachmentTarget } from "../notes/attachment-ref.js";
|
|
9
9
|
import { getWorkflowProgressBroker } from "./workflow/progress-broker.js";
|
|
@@ -61,9 +61,9 @@ import { parseOutboundSessionKey } from "./service/parse-outbound-session-key.js
|
|
|
61
61
|
import { cleanTrailingErrors } from "./memory/message-sanitizer.js";
|
|
62
62
|
import { MemoryFlushService } from "./memory/memory-flush.js";
|
|
63
63
|
import { tryApplySessionTranscriptHygiene } from "./transcript/transcript-hygiene.js";
|
|
64
|
-
import { join } from "node:path";
|
|
65
64
|
import { existsSync, readFileSync } from "node:fs";
|
|
66
65
|
import { readFile } from "node:fs/promises";
|
|
66
|
+
import { join } from "node:path";
|
|
67
67
|
//#region src/agent/service.ts
|
|
68
68
|
init_schema();
|
|
69
69
|
init_logger();
|
|
@@ -231,7 +231,8 @@ var AgentService = class {
|
|
|
231
231
|
verboseLevel: config.verboseLevel,
|
|
232
232
|
gatewayClarify: config.gatewayClarify,
|
|
233
233
|
getCronService: config.getCronService,
|
|
234
|
-
getWorkflowRunService: config.getWorkflowRunService
|
|
234
|
+
getWorkflowRunService: config.getWorkflowRunService,
|
|
235
|
+
onSkillsUpdated: config.onSkillsUpdated
|
|
235
236
|
});
|
|
236
237
|
this.agentEventHandler = new AgentEventHandler({
|
|
237
238
|
progressManager: this.progressManager,
|
|
@@ -300,6 +301,7 @@ var AgentService = class {
|
|
|
300
301
|
await this.streamManager.abort();
|
|
301
302
|
this.agentOrchestrator.abort(sessionKey);
|
|
302
303
|
},
|
|
304
|
+
reloadSkills: () => this.refreshSkillsAfterDiskChange(),
|
|
303
305
|
compactSession: (sessionKey, options) => this.sessionInspector.compact(sessionKey, options),
|
|
304
306
|
btwQuery: (sessionKey, question) => this.sessionInspector.btwQuery(sessionKey, question),
|
|
305
307
|
getSessionContextReport: (sessionKey, mode) => this.sessionInspector.report(sessionKey, mode)
|
|
@@ -512,6 +514,9 @@ var AgentService = class {
|
|
|
512
514
|
getSkillCatalog() {
|
|
513
515
|
return this.agentManager.getSkillCatalog();
|
|
514
516
|
}
|
|
517
|
+
getSkillCatalogSnapshot() {
|
|
518
|
+
return this.agentManager.getSkillCatalogSnapshot();
|
|
519
|
+
}
|
|
515
520
|
getAgentSkillAvailability(agentId) {
|
|
516
521
|
return this.agentManager.getAgentSkillAvailability(agentId);
|
|
517
522
|
}
|