@xopcai/xopc 0.0.99 → 0.0.101
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/manifest.json +1 -1
- package/dist/extensions/telegram/src/account-manager.d.ts +3 -3
- package/dist/extensions/telegram/src/account-manager.js +8 -8
- package/dist/extensions/telegram/src/account-manager.js.map +1 -1
- package/dist/extensions/telegram/src/actions/message-actions.d.ts +4 -0
- package/dist/extensions/telegram/src/actions/message-actions.js +71 -0
- package/dist/extensions/telegram/src/actions/message-actions.js.map +1 -0
- package/dist/extensions/telegram/src/adapters/config-adapter.js +9 -1
- package/dist/extensions/telegram/src/adapters/config-adapter.js.map +1 -1
- package/dist/extensions/telegram/src/adapters/config-surface.js +1 -1
- package/dist/extensions/telegram/src/adapters/config-surface.js.map +1 -1
- package/dist/extensions/telegram/src/adapters/outbound-adapter.d.ts +2 -1
- package/dist/extensions/telegram/src/adapters/outbound-adapter.js +18 -4
- package/dist/extensions/telegram/src/adapters/outbound-adapter.js.map +1 -1
- package/dist/extensions/telegram/src/adapters/security-adapter.js +2 -1
- package/dist/extensions/telegram/src/adapters/security-adapter.js.map +1 -1
- package/dist/extensions/telegram/src/adapters/streaming-adapter.js +90 -6
- package/dist/extensions/telegram/src/adapters/streaming-adapter.js.map +1 -1
- package/dist/extensions/telegram/src/adapters/types.d.ts +9 -1
- package/dist/extensions/telegram/src/api-root.d.ts +4 -0
- package/dist/extensions/telegram/src/api-root.js +42 -0
- package/dist/extensions/telegram/src/api-root.js.map +1 -0
- package/dist/extensions/telegram/src/approval-delivery.d.ts +9 -0
- package/dist/extensions/telegram/src/approval-delivery.js +36 -0
- package/dist/extensions/telegram/src/approval-delivery.js.map +1 -0
- package/dist/extensions/telegram/src/approval-store.d.ts +25 -0
- package/dist/extensions/telegram/src/approval-store.js +61 -0
- package/dist/extensions/telegram/src/approval-store.js.map +1 -0
- package/dist/extensions/telegram/src/config-schema.d.ts +185 -35
- package/dist/extensions/telegram/src/config-schema.js +67 -45
- package/dist/extensions/telegram/src/config-schema.js.map +1 -1
- package/dist/extensions/telegram/src/conversation-id.d.ts +6 -0
- package/dist/extensions/telegram/src/conversation-id.js +18 -0
- package/dist/extensions/telegram/src/conversation-id.js.map +1 -0
- package/dist/extensions/telegram/src/doctor.d.ts +5 -0
- package/dist/extensions/telegram/src/doctor.js +80 -0
- package/dist/extensions/telegram/src/doctor.js.map +1 -0
- package/dist/extensions/telegram/src/exec-approval-handler.d.ts +7 -0
- package/dist/extensions/telegram/src/exec-approval-handler.js +36 -0
- package/dist/extensions/telegram/src/exec-approval-handler.js.map +1 -0
- package/dist/extensions/telegram/src/exec-approvals.d.ts +8 -0
- package/dist/extensions/telegram/src/exec-approvals.js +20 -0
- package/dist/extensions/telegram/src/exec-approvals.js.map +1 -0
- package/dist/extensions/telegram/src/focus-handler.d.ts +12 -0
- package/dist/extensions/telegram/src/focus-handler.js +55 -0
- package/dist/extensions/telegram/src/focus-handler.js.map +1 -0
- package/dist/extensions/telegram/src/group-config-resolver.d.ts +12 -0
- package/dist/extensions/telegram/src/group-config-resolver.js +17 -0
- package/dist/extensions/telegram/src/group-config-resolver.js.map +1 -0
- package/dist/extensions/telegram/src/inbound-coalescer.d.ts +15 -0
- package/dist/extensions/telegram/src/inbound-coalescer.js +107 -0
- package/dist/extensions/telegram/src/inbound-coalescer.js.map +1 -0
- package/dist/extensions/telegram/src/inbound-processor.d.ts +1 -0
- package/dist/extensions/telegram/src/inbound-processor.js +41 -4
- package/dist/extensions/telegram/src/inbound-processor.js.map +1 -1
- package/dist/extensions/telegram/src/network-errors.d.ts +2 -0
- package/dist/extensions/telegram/src/network-errors.js +23 -0
- package/dist/extensions/telegram/src/network-errors.js.map +1 -0
- package/dist/extensions/telegram/src/plugin.d.ts +11 -0
- package/dist/extensions/telegram/src/plugin.js +191 -57
- package/dist/extensions/telegram/src/plugin.js.map +1 -1
- package/dist/extensions/telegram/src/polling-session.d.ts +17 -0
- package/dist/extensions/telegram/src/polling-session.js +112 -0
- package/dist/extensions/telegram/src/polling-session.js.map +1 -0
- package/dist/extensions/telegram/src/proxy-fetch.d.ts +2 -0
- package/dist/extensions/telegram/src/proxy-fetch.js +14 -0
- package/dist/extensions/telegram/src/proxy-fetch.js.map +1 -0
- package/dist/extensions/telegram/src/reactions.d.ts +14 -0
- package/dist/extensions/telegram/src/reactions.js +48 -0
- package/dist/extensions/telegram/src/reactions.js.map +1 -0
- package/dist/extensions/telegram/src/reply-params.d.ts +15 -0
- package/dist/extensions/telegram/src/reply-params.js +28 -0
- package/dist/extensions/telegram/src/reply-params.js.map +1 -0
- package/dist/extensions/telegram/src/startup-errors.d.ts +3 -0
- package/dist/extensions/telegram/src/startup-errors.js +27 -0
- package/dist/extensions/telegram/src/startup-errors.js.map +1 -0
- package/dist/extensions/telegram/src/telegram-actions.d.ts +25 -0
- package/dist/extensions/telegram/src/telegram-actions.js +65 -0
- package/dist/extensions/telegram/src/telegram-actions.js.map +1 -0
- package/dist/extensions/telegram/src/thread-bindings.d.ts +15 -0
- package/dist/extensions/telegram/src/thread-bindings.js +22 -0
- package/dist/extensions/telegram/src/thread-bindings.js.map +1 -0
- package/dist/extensions/telegram/src/token-resolver.d.ts +8 -0
- package/dist/extensions/telegram/src/token-resolver.js +34 -0
- package/dist/extensions/telegram/src/token-resolver.js.map +1 -0
- package/dist/extensions/telegram/src/update-offset-store.d.ts +9 -0
- package/dist/extensions/telegram/src/update-offset-store.js +66 -0
- package/dist/extensions/telegram/src/update-offset-store.js.map +1 -0
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/api/api.js +5 -3
- package/dist/extensions/weixin/src/api/api.js.map +1 -1
- package/dist/gateway/static/root/assets/{agents-4KTK-Ku7.js → agents-u8cmUfGQ.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-DkgInY2w.js → apps-page-DF8m9cUE.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-preview-renderer-DBAxQXb-.js → attachment-preview-renderer-CybMSIoS.js} +2 -2
- package/dist/gateway/static/root/assets/{attachment-process-heavy-Csq3TrrP.js → attachment-process-heavy-RnGYy9bC.js} +2 -2
- package/dist/gateway/static/root/assets/channels-settings-BM3doRvi.js +1 -0
- package/dist/gateway/static/root/assets/channels-status-swr-ah4zWEIP.js +8 -0
- package/dist/gateway/static/root/assets/{cron-api-BRDli2Mm.js → cron-api-DgMuL_2b.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-page-BzEr5Za8.js → cron-page-COfUPKfq.js} +1 -1
- package/dist/gateway/static/root/assets/{dist-BsHh1vX0.js → dist-Dzy3Q0ZH.js} +1 -1
- package/dist/gateway/static/root/assets/{docx-preview-Dxj1EkCO.js → docx-preview-CajIk2FR.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-TWt5q_ef.js → extension-debug-page-kyxxefKh.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-C3kV8ZvZ.js → extension-page-BVbCBHoI.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-Csy9LNC6.js → extension-settings-page-t1lb2A7v.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-BLLOP2CM.js → fetch-drJUxxKP.js} +1 -1
- package/dist/gateway/static/root/assets/{field-primitives-MXbM8HvY.js → field-primitives-6Vo1Yga4.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-CkoyqfRx.js → heartbeat-config-api-BF3psu4O.js} +1 -1
- package/dist/gateway/static/root/assets/index-DjNDHzwG.css +1 -0
- package/dist/gateway/static/root/assets/index-WAyKAilR.js +4840 -0
- package/dist/gateway/static/root/assets/{logs-page-B2vY41ph.js → logs-page-BTVPXcHV.js} +1 -1
- package/dist/gateway/static/root/assets/{note-detail-page-B7qE5pkO.js → note-detail-page-DqSAg_5Z.js} +1 -1
- package/dist/gateway/static/root/assets/{note-time-NBBReVR4.js → note-time-FSOjchic.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-CsWYaqYM.js → notes-page-DkRX7BE2.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-BPGY3SCT.js → sessions-page-Khdw35Zk.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-advanced-gate-DtA451RM.js → settings-advanced-gate-DspC8oEm.js} +2 -2
- package/dist/gateway/static/root/assets/{settings-form-section-DYR_SPlX.js → settings-form-section-DuxvUuur.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-BJUgZQzN.js → settings-page-DN8JBZ8F.js} +2 -2
- package/dist/gateway/static/root/assets/{share-preview-page-3u8VFmdo.js → share-preview-page-UNAcbiMb.js} +2 -2
- package/dist/gateway/static/root/assets/{skills-page-DuyhcH4U.js → skills-page-ByYT0fXZ.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-e2q2yjs4.js → theme-store-B6KXPHgK.js} +1 -1
- package/dist/gateway/static/root/assets/url-q28QhI7l.js +3 -0
- package/dist/gateway/static/root/assets/{utils-B4Vw3fnc.js → utils-DK_1H47k.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-BFY67Hhp.js → voice-api-key-field-BYN2EIMs.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-page.utils-yUJ5jexd.js → workflow-page.utils-Bi19YNTr.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-DIMHCpNt.js → workflows-page-DP57FEKW.js} +1 -1
- package/dist/gateway/static/root/index.html +5 -5
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +4 -0
- package/dist/src/agent/agent-manager.js +84 -4
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/child-agent-factory.d.ts +1 -0
- package/dist/src/agent/child-agent-factory.js +13 -10
- package/dist/src/agent/child-agent-factory.js.map +1 -1
- package/dist/src/agent/embedded/run-for-session.d.ts +1 -0
- package/dist/src/agent/embedded/run-for-session.js +2 -0
- package/dist/src/agent/embedded/run-for-session.js.map +1 -1
- package/dist/src/agent/embedded/run-turn.js +1 -17
- package/dist/src/agent/embedded/run-turn.js.map +1 -1
- package/dist/src/agent/embedded/session-runner.js +3 -1
- package/dist/src/agent/embedded/session-runner.js.map +1 -1
- package/dist/src/agent/embedded/session-tool-result-guard.d.ts +1 -0
- package/dist/src/agent/embedded/session-tool-result-guard.js +1 -0
- package/dist/src/agent/embedded/session-tool-result-guard.js.map +1 -1
- package/dist/src/agent/inbound/attachment-pipeline.d.ts +37 -0
- package/dist/src/agent/inbound/attachment-pipeline.js +169 -0
- package/dist/src/agent/inbound/attachment-pipeline.js.map +1 -0
- package/dist/src/agent/inbound/turn-dispatcher.d.ts +3 -5
- package/dist/src/agent/inbound/turn-dispatcher.js +1 -2
- package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
- package/dist/src/agent/memory/index.d.ts +2 -0
- package/dist/src/agent/memory/index.js +2 -1
- package/dist/src/agent/memory/memory-flush.d.ts +27 -0
- package/dist/src/agent/memory/memory-flush.js +124 -0
- package/dist/src/agent/memory/memory-flush.js.map +1 -0
- package/dist/src/agent/messaging/outbound-coordinator.js +2 -1
- package/dist/src/agent/messaging/outbound-coordinator.js.map +1 -1
- package/dist/src/agent/messaging/stream-manager.d.ts +2 -0
- package/dist/src/agent/messaging/stream-manager.js +3 -0
- package/dist/src/agent/messaging/stream-manager.js.map +1 -1
- package/dist/src/agent/orchestration/agent-orchestrator.d.ts +0 -4
- package/dist/src/agent/orchestration/agent-orchestrator.js +40 -107
- package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
- package/dist/src/agent/prompt/contribution.d.ts +9 -0
- package/dist/src/agent/prompt/contribution.js +1 -0
- package/dist/src/agent/prompt/safety.js +0 -10
- package/dist/src/agent/prompt/safety.js.map +1 -1
- package/dist/src/agent/prompt/sanitize-for-prompt.d.ts +6 -0
- package/dist/src/agent/prompt/sanitize-for-prompt.js +13 -0
- package/dist/src/agent/prompt/sanitize-for-prompt.js.map +1 -0
- package/dist/src/agent/prompt/sections/behavior.d.ts +5 -0
- package/dist/src/agent/prompt/sections/behavior.js +50 -0
- package/dist/src/agent/prompt/sections/behavior.js.map +1 -0
- package/dist/src/agent/prompt/sections/memory-skills.d.ts +9 -0
- package/dist/src/agent/prompt/sections/memory-skills.js +59 -0
- package/dist/src/agent/prompt/sections/memory-skills.js.map +1 -0
- package/dist/src/agent/prompt/sections/messaging-runtime.d.ts +16 -0
- package/dist/src/agent/prompt/sections/messaging-runtime.js +69 -0
- package/dist/src/agent/prompt/sections/messaging-runtime.js.map +1 -0
- package/dist/src/agent/prompt/sections/project-context.d.ts +16 -0
- package/dist/src/agent/prompt/sections/project-context.js +58 -0
- package/dist/src/agent/prompt/sections/project-context.js.map +1 -0
- package/dist/src/agent/prompt/sections/tooling.d.ts +5 -0
- package/dist/src/agent/prompt/sections/tooling.js +119 -0
- package/dist/src/agent/prompt/sections/tooling.js.map +1 -0
- package/dist/src/agent/prompt/sections/workspace-runtime.d.ts +11 -0
- package/dist/src/agent/prompt/sections/workspace-runtime.js +32 -0
- package/dist/src/agent/prompt/sections/workspace-runtime.js.map +1 -0
- package/dist/src/agent/prompt/service-prompt-builder.d.ts +13 -0
- package/dist/src/agent/prompt/service-prompt-builder.js +54 -13
- package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
- package/dist/src/agent/prompt/subagent-context.d.ts +15 -0
- package/dist/src/agent/prompt/subagent-context.js +68 -0
- package/dist/src/agent/prompt/subagent-context.js.map +1 -0
- package/dist/src/agent/prompt/system-prompt-params.d.ts +53 -0
- package/dist/src/agent/prompt/system-prompt-params.js +74 -0
- package/dist/src/agent/prompt/system-prompt-params.js.map +1 -0
- package/dist/src/agent/prompt/system-prompt.d.ts +22 -11
- package/dist/src/agent/prompt/system-prompt.js +79 -193
- package/dist/src/agent/prompt/system-prompt.js.map +1 -1
- package/dist/src/agent/prompt/types.d.ts +3 -0
- package/dist/src/agent/service/build-direct-message-content.d.ts +5 -21
- package/dist/src/agent/service/build-direct-message-content.js +11 -64
- package/dist/src/agent/service/build-direct-message-content.js.map +1 -1
- package/dist/src/agent/service/direct-turn-helpers.d.ts +1 -1
- package/dist/src/agent/service/direct-turn-helpers.js +7 -0
- package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
- package/dist/src/agent/service/process-direct-one-shot.d.ts +3 -3
- package/dist/src/agent/service/process-direct-one-shot.js +22 -17
- package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.d.ts +6 -20
- package/dist/src/agent/service/process-direct-streaming.js +39 -40
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service/webchat-tts.d.ts +4 -9
- package/dist/src/agent/service/webchat-tts.js +9 -20
- package/dist/src/agent/service/webchat-tts.js.map +1 -1
- package/dist/src/agent/service.d.ts +8 -19
- package/dist/src/agent/service.js +53 -11
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/tools/factory.js +2 -0
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/index.d.ts +1 -0
- package/dist/src/agent/tools/index.js +2 -1
- package/dist/src/agent/tools/media-read-tool.d.ts +2 -0
- package/dist/src/agent/tools/media-read-tool.js +89 -0
- package/dist/src/agent/tools/media-read-tool.js.map +1 -0
- package/dist/src/auth/credentials.js +0 -1
- package/dist/src/auth/credentials.js.map +1 -1
- package/dist/src/channels/attachments/attachment-classifiers.d.ts +8 -0
- package/dist/src/channels/attachments/attachment-classifiers.js +11 -0
- package/dist/src/channels/attachments/attachment-classifiers.js.map +1 -0
- package/dist/src/channels/attachments/inbound-persist.d.ts +13 -34
- package/dist/src/channels/attachments/inbound-persist.js +34 -102
- package/dist/src/channels/attachments/inbound-persist.js.map +1 -1
- package/dist/src/channels/attachments/inbound-types.d.ts +13 -0
- package/dist/src/channels/attachments/inbound-types.js +30 -0
- package/dist/src/channels/attachments/inbound-types.js.map +1 -0
- package/dist/src/channels/attachments/outbound-tts-persist.d.ts +3 -12
- package/dist/src/channels/attachments/outbound-tts-persist.js +28 -48
- package/dist/src/channels/attachments/outbound-tts-persist.js.map +1 -1
- package/dist/src/channels/attachments/voice-stt-webchat.d.ts +3 -3
- package/dist/src/channels/attachments/voice-stt-webchat.js +8 -14
- package/dist/src/channels/attachments/voice-stt-webchat.js.map +1 -1
- package/dist/src/channels/channel-domain.d.ts +30 -2
- package/dist/src/channels/exec-approval-runtime.d.ts +29 -0
- package/dist/src/channels/exec-approval-runtime.js +30 -0
- package/dist/src/channels/exec-approval-runtime.js.map +1 -0
- package/dist/src/channels/index.js +1 -1
- package/dist/src/channels/plugin-types.d.ts +1 -0
- package/dist/src/channels/transport-types.d.ts +2 -2
- package/dist/src/cli/bin.d.ts +1 -0
- package/dist/src/cli/bin.js +1 -0
- package/dist/src/cli/bin.js.map +1 -1
- package/dist/src/cli/commands/channels.js +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/database-schema.js +62 -0
- package/dist/src/cli/commands/doctor/checks/database-schema.js.map +1 -0
- package/dist/src/cli/commands/doctor/flow.js +2 -0
- package/dist/src/cli/commands/doctor/flow.js.map +1 -1
- package/dist/src/cli/commands/init.js +2 -57
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/onboard/channels/registry.js +1 -1
- package/dist/src/cli/commands/setup.js +6 -5
- package/dist/src/cli/commands/setup.js.map +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +1 -2
- package/dist/src/cli/utils/init-workspace-core.js.map +1 -1
- package/dist/src/config/index.js +2 -2
- package/dist/src/config/paths.d.ts +0 -13
- package/dist/src/config/paths.js +1 -20
- package/dist/src/config/paths.js.map +1 -1
- package/dist/src/config/rules.js +1 -1
- package/dist/src/config/schema.d.ts +24 -0
- package/dist/src/config/schema.js +33 -2
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/cron/executor.js +2 -2
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/oauth-async.js +36 -3
- package/dist/src/gateway/hono/oauth-async.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/channels.js +3 -3
- package/dist/src/gateway/hono/routes/config-patch/channels.js.map +1 -1
- 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/media.d.ts +3 -0
- package/dist/src/gateway/hono/routes/media.js +50 -0
- package/dist/src/gateway/hono/routes/media.js.map +1 -0
- package/dist/src/gateway/hono/routes/sessions.js +6 -0
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +1 -87
- package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
- package/dist/src/gateway/service/sessions-api.js +3 -0
- package/dist/src/gateway/service/sessions-api.js.map +1 -1
- package/dist/src/infra/http-proxy-env.d.ts +4 -0
- package/dist/src/infra/http-proxy-env.js +23 -0
- package/dist/src/infra/http-proxy-env.js.map +1 -0
- package/dist/src/media/index.d.ts +5 -0
- package/dist/src/media/index.js +5 -0
- package/dist/src/media/media-reference.d.ts +23 -0
- package/dist/src/media/media-reference.js +34 -0
- package/dist/src/media/media-reference.js.map +1 -0
- package/dist/src/media/paths.d.ts +5 -0
- package/dist/src/media/paths.js +20 -0
- package/dist/src/media/paths.js.map +1 -0
- package/dist/src/media/session-references.d.ts +8 -0
- package/dist/src/media/session-references.js +45 -0
- package/dist/src/media/session-references.js.map +1 -0
- package/dist/src/media/store.d.ts +19 -0
- package/dist/src/media/store.js +131 -0
- package/dist/src/media/store.js.map +1 -0
- package/dist/src/media/types.d.ts +34 -0
- package/dist/src/media/types.js +1 -0
- package/dist/src/media/uri.d.ts +15 -0
- package/dist/src/media/uri.js +51 -0
- package/dist/src/media/uri.js.map +1 -0
- package/dist/src/session/session-title.js +6 -3
- package/dist/src/session/session-title.js.map +1 -1
- package/dist/src/session/store.js +1 -1
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/session/types.d.ts +12 -7
- package/dist/src/session/types.js.map +1 -1
- package/dist/src/storage/sqlite/index.d.ts +4 -1
- package/dist/src/storage/sqlite/index.js +6 -2
- package/dist/src/storage/sqlite/migrations/002_add_flush_columns.sql +3 -0
- package/dist/src/storage/sqlite/migrations/discover.d.ts +4 -0
- package/dist/src/storage/sqlite/migrations/discover.js +38 -0
- package/dist/src/storage/sqlite/migrations/discover.js.map +1 -0
- package/dist/src/storage/sqlite/migrations/discover.ts +52 -0
- package/dist/src/storage/sqlite/migrations/errors.d.ts +11 -0
- package/dist/src/storage/sqlite/migrations/errors.js +27 -0
- package/dist/src/storage/sqlite/migrations/errors.js.map +1 -0
- package/dist/src/storage/sqlite/migrations/errors.ts +32 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +22 -0
- package/dist/src/storage/sqlite/migrations/runner.js +97 -0
- package/dist/src/storage/sqlite/migrations/runner.js.map +1 -0
- package/dist/src/storage/sqlite/migrations/runner.ts +153 -0
- package/dist/src/storage/sqlite/migrations/types.d.ts +12 -0
- package/dist/src/storage/sqlite/migrations/types.js +1 -0
- package/dist/src/storage/sqlite/migrations/types.ts +13 -0
- package/dist/src/storage/sqlite/row-mappers.d.ts +4 -0
- package/dist/src/storage/sqlite/row-mappers.js +4 -0
- package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
- package/dist/src/storage/sqlite/schema-version.d.ts +6 -0
- package/dist/src/storage/sqlite/schema-version.js +29 -0
- package/dist/src/storage/sqlite/schema-version.js.map +1 -0
- package/dist/src/storage/sqlite/schema.d.ts +5 -3
- package/dist/src/storage/sqlite/schema.js +24 -28
- package/dist/src/storage/sqlite/schema.js.map +1 -1
- package/dist/src/storage/sqlite/schema.sql +2 -0
- package/dist/src/storage/sqlite/session-metadata.js +1 -0
- package/dist/src/storage/sqlite/session-metadata.js.map +1 -1
- package/dist/src/storage/sqlite/session-repository.js +7 -3
- package/dist/src/storage/sqlite/session-repository.js.map +1 -1
- package/package.json +3 -3
- package/dist/gateway/static/root/assets/channels-settings-BxW1Xio4.js +0 -1
- package/dist/gateway/static/root/assets/channels-status-swr-Cxm6AvQO.js +0 -8
- package/dist/gateway/static/root/assets/index-BJDmBCSl.css +0 -1
- package/dist/gateway/static/root/assets/index-Cbg5TS5m.js +0 -4707
- package/dist/gateway/static/root/assets/url-DpFBIyN9.js +0 -3
- package/dist/src/cli/commands/onboard/workspace.d.ts +0 -14
- package/dist/src/cli/commands/onboard/workspace.js +0 -33
- package/dist/src/cli/commands/onboard/workspace.js.map +0 -1
- package/dist/src/cli/utils/workspace.d.ts +0 -35
- package/dist/src/cli/utils/workspace.js +0 -72
- package/dist/src/cli/utils/workspace.js.map +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { clearPendingTranscriptUserMessage, setPendingTranscriptUserMessage } from "../inbound/attachment-pipeline.js";
|
|
1
2
|
import { initSessionTurn } from "../../session/init-session-turn.js";
|
|
2
3
|
import "../../session/index.js";
|
|
3
4
|
import { buildDirectUserMessageContent } from "./build-direct-message-content.js";
|
|
@@ -37,25 +38,29 @@ async function runProcessDirect(deps, input) {
|
|
|
37
38
|
});
|
|
38
39
|
return slash.aggregatedText ?? "";
|
|
39
40
|
}
|
|
40
|
-
const userMessage = {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
content: turnBody.trimStart().startsWith("/skill:") ? deps.agentManager.expandSkillUserText(turnBody) : turnBody,
|
|
44
|
-
attachments: prepared,
|
|
45
|
-
sessionKey: input.sessionKey,
|
|
46
|
-
config: deps.config,
|
|
47
|
-
agentManager: deps.agentManager,
|
|
48
|
-
modelManager: deps.modelManager
|
|
49
|
-
}),
|
|
50
|
-
timestamp: Date.now()
|
|
51
|
-
};
|
|
52
|
-
const result = await runDirectAgentTurn({
|
|
53
|
-
...deps,
|
|
54
|
-
config: deps.config
|
|
55
|
-
}, {
|
|
41
|
+
const userMessage = await buildDirectUserMessageContent({
|
|
42
|
+
content: turnBody.trimStart().startsWith("/skill:") ? deps.agentManager.expandSkillUserText(turnBody) : turnBody,
|
|
43
|
+
attachments: prepared,
|
|
56
44
|
sessionKey: input.sessionKey,
|
|
57
|
-
|
|
45
|
+
config: deps.config,
|
|
46
|
+
agentManager: deps.agentManager,
|
|
47
|
+
modelManager: deps.modelManager
|
|
58
48
|
});
|
|
49
|
+
const pendingUserMessage = userMessage;
|
|
50
|
+
setPendingTranscriptUserMessage(input.sessionKey, pendingUserMessage);
|
|
51
|
+
const result = await (async () => {
|
|
52
|
+
try {
|
|
53
|
+
return await runDirectAgentTurn({
|
|
54
|
+
...deps,
|
|
55
|
+
config: deps.config
|
|
56
|
+
}, {
|
|
57
|
+
sessionKey: input.sessionKey,
|
|
58
|
+
userMessage
|
|
59
|
+
});
|
|
60
|
+
} finally {
|
|
61
|
+
clearPendingTranscriptUserMessage(input.sessionKey, pendingUserMessage);
|
|
62
|
+
}
|
|
63
|
+
})();
|
|
59
64
|
if (result.lastAssistantText) deps.onTurnComplete?.(input.sessionKey, result.lastAssistantText);
|
|
60
65
|
return result.lastAssistantText ?? "";
|
|
61
66
|
} finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-direct-one-shot.js","names":[],"sources":["../../../../src/agent/service/process-direct-one-shot.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport type { CommandHandler } from '../messaging/command-handler.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\nimport type { ModelManager } from '../models/index.js';\nimport type { SessionStore } from '../../session/index.js';\nimport type { Config } from '../../config/schema.js';\nimport { initSessionTurn } from '../../session/index.js';\nimport {
|
|
1
|
+
{"version":3,"file":"process-direct-one-shot.js","names":[],"sources":["../../../../src/agent/service/process-direct-one-shot.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport type { CommandHandler } from '../messaging/command-handler.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\nimport type { ModelManager } from '../models/index.js';\nimport type { SessionStore } from '../../session/index.js';\nimport type { Config } from '../../config/schema.js';\nimport { initSessionTurn } from '../../session/index.js';\nimport {\n buildDirectUserMessageContent,\n} from './build-direct-message-content.js';\nimport type { ProcessDirectStreamLog } from './process-direct-streaming.js';\nimport type {\n InboundAttachmentInput,\n MediaRef,\n} from '../../channels/attachments/inbound-persist.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 RunProcessDirectDeps = {\n log: ProcessDirectStreamLog;\n config: Config;\n parseSessionKey: (sessionKey: string) => { channel: string; chatId: string };\n initSessionContext: (sessionKey: string, channel: string, chatId: string) => void;\n hydrateSessionWorkspaceFromStore: (sessionKey: string) => Promise<void>;\n hydrateSessionModelFromStore: (sessionKey: string) => Promise<void>;\n agentManager: AgentInstanceGateway;\n sessionStore: SessionStore;\n modelManager: ModelManager;\n applyResolvedThinkingLevel: (sessionKey: string, thinking?: string | null) => Promise<void>;\n prepareInboundAttachments: (\n sessionKey: string,\n attachments?: InboundAttachmentInput[],\n ) => Promise<MediaRef[] | undefined>;\n commandHandler: Pick<CommandHandler, 'executeCommandAndAggregateReply'>;\n onTurnComplete?: (sessionKey: string, lastAssistantText?: string) => void;\n endDirectRequestContext: () => void;\n resetSession: (sessionKey: string) => Promise<{ sessionId: string; previousSessionId: string } | null>;\n};\n\nexport async function runProcessDirect(\n deps: RunProcessDirectDeps,\n input: {\n content: string;\n sessionKey: string;\n attachments?: InboundAttachmentInput[];\n thinking?: string;\n },\n): Promise<string> {\n const { channel, chatId } = deps.parseSessionKey(input.sessionKey);\n deps.initSessionContext(input.sessionKey, channel, chatId);\n\n try {\n let turnBody = input.content;\n let resetTriggeredAtInit = false;\n const turn = await initSessionTurn({\n cfg: deps.config,\n sessionKey: input.sessionKey,\n body: input.content,\n resetSession: deps.resetSession,\n });\n resetTriggeredAtInit = turn.resetTriggered;\n if (turn.bareReset && turn.ackMessage) {\n return turn.ackMessage;\n }\n turnBody = turn.bodyStripped;\n\n await hydratePerTurnState(deps, input.sessionKey, input.thinking);\n const prepared = await deps.prepareInboundAttachments(input.sessionKey, input.attachments);\n\n const slash = await tryRunSlashCommand(\n deps,\n { sessionKey: input.sessionKey, channel, chatId },\n turnBody,\n { skipResetCommands: resetTriggeredAtInit },\n );\n if (slash.matched) {\n const trimmed = slash.aggregatedText.trim();\n if (trimmed) {\n await deps.sessionStore.appendTranscriptMessage(input.sessionKey, {\n role: 'assistant',\n content: [{ type: 'text', text: trimmed }],\n timestamp: Date.now(),\n } as AgentMessage);\n }\n return slash.aggregatedText ?? '';\n }\n\n const textForDirect = turnBody.trimStart().startsWith('/skill:')\n ? deps.agentManager.expandSkillUserText(turnBody)\n : turnBody;\n const userMessage = await buildDirectUserMessageContent({\n content: textForDirect,\n attachments: prepared,\n sessionKey: input.sessionKey,\n config: deps.config,\n agentManager: deps.agentManager,\n modelManager: deps.modelManager,\n });\n\n const pendingUserMessage = userMessage as TranscriptUserMessage;\n setPendingTranscriptUserMessage(input.sessionKey, pendingUserMessage);\n\n const result = await (async () => {\n try {\n return await runDirectAgentTurn(\n { ...deps, config: deps.config },\n {\n sessionKey: input.sessionKey,\n userMessage,\n },\n );\n } finally {\n clearPendingTranscriptUserMessage(input.sessionKey, pendingUserMessage);\n }\n })();\n\n if (result.lastAssistantText) {\n deps.onTurnComplete?.(input.sessionKey, result.lastAssistantText);\n }\n\n return result.lastAssistantText ?? '';\n } finally {\n deps.endDirectRequestContext();\n }\n}\n"],"mappings":";;;;;;AAgDA,eAAsB,iBACpB,MACA,OAMiB;CACjB,MAAM,EAAE,SAAS,WAAW,KAAK,gBAAgB,MAAM,WAAW;AAClE,MAAK,mBAAmB,MAAM,YAAY,SAAS,OAAO;AAE1D,KAAI;EACF,IAAI,WAAW,MAAM;EACrB,IAAI,uBAAuB;EAC3B,MAAM,OAAO,MAAM,gBAAgB;GACjC,KAAK,KAAK;GACV,YAAY,MAAM;GAClB,MAAM,MAAM;GACZ,cAAc,KAAK;GACpB,CAAC;AACF,yBAAuB,KAAK;AAC5B,MAAI,KAAK,aAAa,KAAK,WACzB,QAAO,KAAK;AAEd,aAAW,KAAK;AAEhB,QAAM,oBAAoB,MAAM,MAAM,YAAY,MAAM,SAAS;EACjE,MAAM,WAAW,MAAM,KAAK,0BAA0B,MAAM,YAAY,MAAM,YAAY;EAE1F,MAAM,QAAQ,MAAM,mBAClB,MACA;GAAE,YAAY,MAAM;GAAY;GAAS;GAAQ,EACjD,UACA,EAAE,mBAAmB,sBAAsB,CAC5C;AACD,MAAI,MAAM,SAAS;GACjB,MAAM,UAAU,MAAM,eAAe,MAAM;AAC3C,OAAI,QACF,OAAM,KAAK,aAAa,wBAAwB,MAAM,YAAY;IAChE,MAAM;IACN,SAAS,CAAC;KAAE,MAAM;KAAQ,MAAM;KAAS,CAAC;IAC1C,WAAW,KAAK,KAAK;IACtB,CAAiB;AAEpB,UAAO,MAAM,kBAAkB;;EAMjC,MAAM,cAAc,MAAM,8BAA8B;GACtD,SAJoB,SAAS,WAAW,CAAC,WAAW,UAAU,GAC5D,KAAK,aAAa,oBAAoB,SAAS,GAC/C;GAGF,aAAa;GACb,YAAY,MAAM;GAClB,QAAQ,KAAK;GACb,cAAc,KAAK;GACnB,cAAc,KAAK;GACpB,CAAC;EAEF,MAAM,qBAAqB;AAC3B,kCAAgC,MAAM,YAAY,mBAAmB;EAErE,MAAM,SAAS,OAAO,YAAY;AAChC,OAAI;AACF,WAAO,MAAM,mBACX;KAAE,GAAG;KAAM,QAAQ,KAAK;KAAQ,EAChC;KACE,YAAY,MAAM;KAClB;KACD,CACF;aACO;AACR,sCAAkC,MAAM,YAAY,mBAAmB;;MAEvE;AAEJ,MAAI,OAAO,kBACT,MAAK,iBAAiB,MAAM,YAAY,OAAO,kBAAkB;AAGnE,SAAO,OAAO,qBAAqB;WAC3B;AACR,OAAK,yBAAyB"}
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import type { Config } from '../../config/schema.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { InboundAttachmentInput, MediaRef } from '../../channels/attachments/inbound-persist.js';
|
|
3
3
|
import { type SessionConfigStore, type SessionStore } from '../../session/index.js';
|
|
4
4
|
import type { SessionContext } from '../session/index.js';
|
|
5
5
|
import type { AgentInstanceGateway } from '../agent-instance-gateway.js';
|
|
6
6
|
import type { CommandHandler } from '../messaging/command-handler.js';
|
|
7
7
|
import type { ModelManager } from '../models/index.js';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
mimeType?: string;
|
|
11
|
-
data?: string;
|
|
12
|
-
name?: string;
|
|
13
|
-
size?: number;
|
|
14
|
-
workspaceRelativePath?: string;
|
|
15
|
-
};
|
|
8
|
+
import { type TranscriptUserMessage } from '../inbound/attachment-pipeline.js';
|
|
9
|
+
export type DirectStreamInboundAttachment = InboundAttachmentInput;
|
|
16
10
|
export type ProcessDirectStreamLog = {
|
|
17
11
|
info: (obj: Record<string, unknown>, msg: string) => void;
|
|
18
12
|
warn: (obj: Record<string, unknown>, msg: string) => void;
|
|
@@ -38,17 +32,9 @@ export interface ProcessDirectStreamingDeps {
|
|
|
38
32
|
applyResolvedThinkingLevel: (sessionKey: string, thinking?: string | null) => Promise<void>;
|
|
39
33
|
getConfig: () => Config | undefined;
|
|
40
34
|
sessionConfigStore: SessionConfigStore;
|
|
41
|
-
attachmentRootsForSession: (sessionKey: string) => InternalAttachmentRoots;
|
|
42
35
|
commandHandler: Pick<CommandHandler, 'executeCommandAndAggregateReply'>;
|
|
43
|
-
prepareInboundAttachments: (sessionKey: string, attachments?: DirectStreamInboundAttachment[]) => Promise<
|
|
44
|
-
|
|
45
|
-
type: 'text';
|
|
46
|
-
text: string;
|
|
47
|
-
} | {
|
|
48
|
-
type: 'image';
|
|
49
|
-
data: string;
|
|
50
|
-
mimeType: string;
|
|
51
|
-
}>>;
|
|
36
|
+
prepareInboundAttachments: (sessionKey: string, attachments?: DirectStreamInboundAttachment[]) => Promise<MediaRef[] | undefined>;
|
|
37
|
+
buildTranscriptUserMessage: (content: string, prepared: MediaRef[] | undefined, sessionKey: string) => Promise<TranscriptUserMessage>;
|
|
52
38
|
recordPersistentGoalStreamOutcome?: (sessionKey: string, outcome: {
|
|
53
39
|
skipPersistentGoalPostTurn: boolean;
|
|
54
40
|
}) => void;
|
|
@@ -58,7 +44,7 @@ export interface ProcessDirectStreamingDeps {
|
|
|
58
44
|
reloadWebchatTranscript?: (sessionKey: string) => void;
|
|
59
45
|
maybeEmitWebchatTts: (sessionKey: string, hadInboundVoice: boolean) => Promise<{
|
|
60
46
|
type: 'tts_audio';
|
|
61
|
-
|
|
47
|
+
uri: string;
|
|
62
48
|
mimeType: string;
|
|
63
49
|
name: string;
|
|
64
50
|
} | null>;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readAgentMessageContent } from "../memory/agent-message-access.js";
|
|
2
|
+
import { clearPendingTranscriptUserMessage, setPendingTranscriptUserMessage } from "../inbound/attachment-pipeline.js";
|
|
1
3
|
import { formatAgentRunErrorForClient } from "../client-error-format.js";
|
|
2
4
|
import { resolveEffectiveReasoningLevel } from "../../session/thinking-resolve.js";
|
|
3
5
|
import { initSessionTurn } from "../../session/init-session-turn.js";
|
|
@@ -77,20 +79,20 @@ async function* runProcessDirectStreaming(deps, input) {
|
|
|
77
79
|
}
|
|
78
80
|
const prepared = await deps.prepareInboundAttachments(sessionKey, input.attachments);
|
|
79
81
|
const sttCfg = mergeSttConfigFromAppConfig(deps.getConfig()?.tools?.media?.audio, deps.getConfig()?.tools?.media);
|
|
80
|
-
const voiceMerge = await mergeVoiceTranscriptsIntoUserText(
|
|
82
|
+
const voiceMerge = await mergeVoiceTranscriptsIntoUserText(prepared, turnBody, sttCfg);
|
|
81
83
|
mergedUserText = voiceMerge.text;
|
|
82
84
|
inboundVoice = voiceMerge.inboundVoice;
|
|
83
85
|
if (inboundVoice) {
|
|
84
86
|
const transcriptParts = [voiceMerge.voiceTranscripts.filter(Boolean).join("\n"), turnBody.trim()].filter(Boolean);
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
+
const voiceMedia = (prepared ?? []).filter(isVoiceLikeAttachment).map((att) => ({
|
|
88
|
+
uri: att.uri,
|
|
87
89
|
mimeType: att.mimeType,
|
|
88
90
|
name: att.name
|
|
89
91
|
}));
|
|
90
92
|
pushVisible({
|
|
91
93
|
type: "user_transcript",
|
|
92
94
|
text: transcriptParts.join("\n\n"),
|
|
93
|
-
|
|
95
|
+
media: voiceMedia
|
|
94
96
|
});
|
|
95
97
|
}
|
|
96
98
|
const armAbort = () => {
|
|
@@ -112,7 +114,8 @@ async function* runProcessDirectStreaming(deps, input) {
|
|
|
112
114
|
channel,
|
|
113
115
|
chatId,
|
|
114
116
|
senderId: context.senderId,
|
|
115
|
-
isGroup: context.isGroup
|
|
117
|
+
isGroup: context.isGroup,
|
|
118
|
+
inboundMetadata: context.metadata
|
|
116
119
|
}, mergedUserText, { skipResetCommands: resetTriggeredAtInit });
|
|
117
120
|
if (slash.matched) {
|
|
118
121
|
ranSlashCommand = true;
|
|
@@ -133,48 +136,44 @@ async function* runProcessDirectStreaming(deps, input) {
|
|
|
133
136
|
return;
|
|
134
137
|
}
|
|
135
138
|
const textForAgent = mergedUserText.trimStart().startsWith("/skill:") ? deps.agentManager.expandSkillUserText(mergedUserText) : mergedUserText;
|
|
136
|
-
const userMessage =
|
|
137
|
-
role: "user",
|
|
138
|
-
content: await deps.buildMessageContent(textForAgent, prepared, sessionKey),
|
|
139
|
-
timestamp: Date.now()
|
|
140
|
-
};
|
|
139
|
+
const userMessage = await deps.buildTranscriptUserMessage(textForAgent, prepared, sessionKey);
|
|
141
140
|
if (channel === "webchat") {
|
|
142
141
|
pushVisible({
|
|
143
142
|
type: "user_message",
|
|
144
|
-
timestamp: userMessage.timestamp,
|
|
145
|
-
content: userMessage
|
|
146
|
-
|
|
147
|
-
type: att.type,
|
|
148
|
-
mimeType: att.mimeType,
|
|
149
|
-
name: att.name,
|
|
150
|
-
size: att.size,
|
|
151
|
-
workspaceRelativePath: att.workspaceRelativePath
|
|
152
|
-
}))
|
|
143
|
+
timestamp: userMessage.timestamp ?? Date.now(),
|
|
144
|
+
content: readAgentMessageContent(userMessage),
|
|
145
|
+
media: userMessage.media
|
|
153
146
|
});
|
|
154
147
|
if (textForAgent.trim()) deps.enqueueProvisionalSessionTitle?.(sessionKey, textForAgent);
|
|
155
148
|
}
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
149
|
+
const pendingUserMessage = userMessage;
|
|
150
|
+
setPendingTranscriptUserMessage(sessionKey, pendingUserMessage);
|
|
151
|
+
try {
|
|
152
|
+
const result = await runDirectAgentTurn({
|
|
153
|
+
sessionStore: deps.sessionStore,
|
|
154
|
+
agentManager: deps.agentManager,
|
|
155
|
+
modelManager: deps.modelManager,
|
|
156
|
+
config: deps.getConfig()
|
|
157
|
+
}, {
|
|
158
|
+
sessionKey,
|
|
159
|
+
userMessage,
|
|
160
|
+
abortSignal: signal,
|
|
161
|
+
onEvent: (embeddedEvent) => {
|
|
162
|
+
const mapped = mapEmbeddedEventToGatewaySse(embeddedEvent);
|
|
163
|
+
if (mapped) {
|
|
164
|
+
if (mapped.type === "error" && typeof mapped.content === "string") mapped.content = formatStreamError(mapped.content);
|
|
165
|
+
pushVisible(mapped);
|
|
166
|
+
}
|
|
170
167
|
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
168
|
+
});
|
|
169
|
+
if (result.lastAssistantText) deps.onTurnComplete?.(sessionKey, result.lastAssistantText);
|
|
170
|
+
if (!result.ok && result.errorMessage && !abortHandled) pushVisible({
|
|
171
|
+
type: "error",
|
|
172
|
+
content: formatStreamError(result.errorMessage)
|
|
173
|
+
});
|
|
174
|
+
} finally {
|
|
175
|
+
clearPendingTranscriptUserMessage(sessionKey, pendingUserMessage);
|
|
176
|
+
}
|
|
178
177
|
} catch (err) {
|
|
179
178
|
if (!abortHandled) pushVisible({
|
|
180
179
|
type: "error",
|
|
@@ -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';\n\nimport type { Config } from '../../config/schema.js';\nimport type { InternalAttachmentRoots } from '../../channels/attachments/inbound-persist.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 { mapEmbeddedEventToGatewaySse } from '../embedded/map-stream-events.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\nimport type { CommandHandler } from '../messaging/command-handler.js';\nimport type { ModelManager } from '../models/index.js';\n\nimport { AsyncQueue } from './async-queue.js';\nimport {\n hydratePerTurnState,\n runDirectAgentTurn,\n tryRunSlashCommand,\n} from './direct-turn-helpers.js';\n\nexport type DirectStreamInboundAttachment = {\n type: string;\n mimeType?: string;\n data?: string;\n name?: string;\n size?: number;\n workspaceRelativePath?: string;\n};\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 attachmentRootsForSession: (sessionKey: string) => InternalAttachmentRoots;\n commandHandler: Pick<CommandHandler, 'executeCommandAndAggregateReply'>;\n prepareInboundAttachments: (\n sessionKey: string,\n attachments?: DirectStreamInboundAttachment[],\n ) => Promise<DirectStreamInboundAttachment[] | undefined>;\n buildMessageContent: (\n content: string,\n attachments: DirectStreamInboundAttachment[] | undefined,\n sessionKey: string,\n ) => Promise<Array<{ type: 'text'; text: string } | { type: 'image'; data: string; mimeType: string }>>;\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'; workspaceRelativePath: string; mimeType: string; name: string } | null>;\n endDirectRequestContext: () => void;\n resetSession: (sessionKey: string) => Promise<{ sessionId: string; previousSessionId: string } | null>;\n}\n\nexport interface ProcessDirectStreamingInput {\n content: string;\n sessionKey?: string;\n attachments?: DirectStreamInboundAttachment[];\n thinking?: string;\n signal?: AbortSignal;\n}\n\nexport type ProcessDirectStreamingSseEvent = { type: string; [key: string]: unknown };\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\n // Kick off the agent task in the background; events stream into `queue` as they happen\n // and the generator below drains `queue` until the task closes it.\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 pushVisible({ type: 'token', content: turn.ackMessage });\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(\n deps.attachmentRootsForSession(sessionKey),\n prepared,\n turnBody,\n sttCfg,\n );\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 voiceAttachments = (prepared ?? []).filter(isVoiceLikeAttachment).map((att) => ({\n workspaceRelativePath: att.workspaceRelativePath,\n mimeType: att.mimeType,\n name: att.name,\n }));\n pushVisible({\n type: 'user_transcript',\n text: transcriptParts.join('\\n\\n'),\n attachments: voiceAttachments,\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 { sessionKey, channel, chatId, senderId: context.senderId, isGroup: context.isGroup },\n mergedUserText,\n { skipResetCommands: resetTriggeredAtInit },\n );\n if (slash.matched) {\n ranSlashCommand = true;\n const text = slash.aggregatedText.trim();\n if (text) {\n webchatSlashReceipt = text;\n pushVisible({ type: 'token', content: text });\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 pushVisible({ type: 'token', content: webchatSlashReceipt });\n }\n return;\n }\n\n const textForAgent = mergedUserText.trimStart().startsWith('/skill:')\n ? deps.agentManager.expandSkillUserText(mergedUserText)\n : mergedUserText;\n const messageContent = await deps.buildMessageContent(textForAgent, prepared, sessionKey);\n\n const userMessage = {\n role: 'user' as const,\n content: messageContent,\n timestamp: Date.now(),\n };\n if (channel === 'webchat') {\n pushVisible({\n type: 'user_message',\n timestamp: userMessage.timestamp,\n content: userMessage.content,\n attachments: prepared?.map((att) => ({\n type: att.type,\n mimeType: att.mimeType,\n name: att.name,\n size: att.size,\n workspaceRelativePath: att.workspaceRelativePath,\n })),\n });\n if (textForAgent.trim()) {\n deps.enqueueProvisionalSessionTitle?.(sessionKey, textForAgent);\n }\n }\n\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,\n abortSignal: signal,\n onEvent: (embeddedEvent) => {\n const mapped = mapEmbeddedEventToGatewaySse(embeddedEvent);\n if (mapped) {\n if (mapped.type === 'error' && typeof mapped.content === 'string') {\n mapped.content = formatStreamError(mapped.content);\n }\n pushVisible(mapped);\n }\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 } 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; // surface unexpected throws\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 } 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';\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 { mapEmbeddedEventToGatewaySse } from '../embedded/map-stream-events.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\nimport type { CommandHandler } from '../messaging/command-handler.js';\nimport type { ModelManager } from '../models/index.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}\n\nexport interface ProcessDirectStreamingInput {\n content: string;\n sessionKey?: string;\n attachments?: DirectStreamInboundAttachment[];\n thinking?: string;\n signal?: AbortSignal;\n}\n\nexport type ProcessDirectStreamingSseEvent = { type: string; [key: string]: unknown };\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\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 pushVisible({ type: 'token', content: turn.ackMessage });\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 const text = slash.aggregatedText.trim();\n if (text) {\n webchatSlashReceipt = text;\n pushVisible({ type: 'token', content: text });\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 pushVisible({ type: 'token', content: webchatSlashReceipt });\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\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,\n abortSignal: signal,\n onEvent: (embeddedEvent) => {\n const mapped = mapEmbeddedEventToGatewaySse(embeddedEvent);\n if (mapped) {\n if (mapped.type === 'error' && typeof mapped.content === 'string') {\n mapped.content = formatStreamError(mapped.content);\n }\n pushVisible(mapped);\n }\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 } 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,8 +1,9 @@
|
|
|
1
1
|
import type { Config } from '../../config/schema.js';
|
|
2
|
+
import type { MediaRef } from '../../media/types.js';
|
|
2
3
|
import type { SessionStore } from '../../session/index.js';
|
|
3
4
|
export type WebchatTtsResult = {
|
|
4
5
|
type: 'tts_audio';
|
|
5
|
-
|
|
6
|
+
uri: string;
|
|
6
7
|
mimeType: string;
|
|
7
8
|
name: string;
|
|
8
9
|
};
|
|
@@ -15,13 +16,7 @@ export type WebchatTtsDeps = {
|
|
|
15
16
|
};
|
|
16
17
|
};
|
|
17
18
|
/**
|
|
18
|
-
* Generate TTS for webchat when config allows; persist under
|
|
19
|
+
* Generate TTS for webchat when config allows; persist under `{stateDir}/media/tts/`.
|
|
19
20
|
*/
|
|
20
21
|
export declare function maybeEmitWebchatTts(deps: WebchatTtsDeps, sessionKey: string, hadInboundVoice: boolean): Promise<WebchatTtsResult | null>;
|
|
21
|
-
export declare function
|
|
22
|
-
type: string;
|
|
23
|
-
mimeType: string;
|
|
24
|
-
name: string;
|
|
25
|
-
size: number;
|
|
26
|
-
workspaceRelativePath: string;
|
|
27
|
-
}): Promise<void>;
|
|
22
|
+
export declare function appendMediaToLastAssistant(sessionStore: SessionStore, sessionKey: string, ref: MediaRef): Promise<void>;
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { init_agent_scope, resolveAgentHomeDir } from "../agent-scope.js";
|
|
2
|
-
import { extractProfileAgentId } from "../../config/agent-profile.js";
|
|
3
1
|
import { isTTSAvailable } from "../../voice/tts/factory.js";
|
|
4
2
|
import { speak } from "../../voice/tts/speak-core.js";
|
|
5
3
|
import { mergeTtsConfigFromAppConfig } from "../../voice/tts/merge-config.js";
|
|
@@ -8,9 +6,8 @@ import { compressAudio } from "../../voice/tts/audio.js";
|
|
|
8
6
|
import "../../voice/tts/index.js";
|
|
9
7
|
import { persistOutboundTtsAudio } from "../../channels/attachments/outbound-tts-persist.js";
|
|
10
8
|
//#region src/agent/service/webchat-tts.ts
|
|
11
|
-
init_agent_scope();
|
|
12
9
|
/**
|
|
13
|
-
* Generate TTS for webchat when config allows; persist under
|
|
10
|
+
* Generate TTS for webchat when config allows; persist under `{stateDir}/media/tts/`.
|
|
14
11
|
*/
|
|
15
12
|
async function maybeEmitWebchatTts(deps, sessionKey, hadInboundVoice) {
|
|
16
13
|
const ttsConfig = mergeTtsConfigFromAppConfig(deps.config?.messages?.tts);
|
|
@@ -27,18 +24,11 @@ async function maybeEmitWebchatTts(deps, sessionKey, hadInboundVoice) {
|
|
|
27
24
|
});
|
|
28
25
|
const { buffer, format } = await compressAudio(Buffer.from(ttsResult.audio), ttsResult.format, webOut.format === "mp3" ? "mp3" : "opus");
|
|
29
26
|
const normalizedMime = format === "opus" || format === "ogg" ? "audio/ogg" : format === "mp3" || format === "mpeg" ? "audio/mpeg" : format === "wav" ? "audio/wav" : `audio/${format}`;
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
await appendAttachmentToLastAssistant(deps.sessionStore, sessionKey, {
|
|
33
|
-
type: "audio",
|
|
34
|
-
mimeType: normalizedMime,
|
|
35
|
-
name: persisted.name,
|
|
36
|
-
size: persisted.size,
|
|
37
|
-
workspaceRelativePath: persisted.workspaceRelativePath
|
|
38
|
-
});
|
|
27
|
+
const persisted = await persistOutboundTtsAudio(buffer, format);
|
|
28
|
+
await appendMediaToLastAssistant(deps.sessionStore, sessionKey, persisted);
|
|
39
29
|
return {
|
|
40
30
|
type: "tts_audio",
|
|
41
|
-
|
|
31
|
+
uri: persisted.uri,
|
|
42
32
|
mimeType: normalizedMime,
|
|
43
33
|
name: persisted.name
|
|
44
34
|
};
|
|
@@ -50,17 +40,16 @@ async function maybeEmitWebchatTts(deps, sessionKey, hadInboundVoice) {
|
|
|
50
40
|
return null;
|
|
51
41
|
}
|
|
52
42
|
}
|
|
53
|
-
async function
|
|
43
|
+
async function appendMediaToLastAssistant(sessionStore, sessionKey, ref) {
|
|
54
44
|
const loaded = await sessionStore.load(sessionKey);
|
|
55
45
|
for (let i = loaded.length - 1; i >= 0; i--) {
|
|
56
46
|
const m = loaded[i];
|
|
57
47
|
if (m.role === "assistant") {
|
|
58
|
-
const prev = m.
|
|
59
|
-
if (prev.some((x) => x.
|
|
60
|
-
const next = [...prev, att];
|
|
48
|
+
const prev = m.media ?? [];
|
|
49
|
+
if (prev.some((x) => x.uri === ref.uri)) return;
|
|
61
50
|
loaded[i] = {
|
|
62
51
|
...m,
|
|
63
|
-
|
|
52
|
+
media: [...prev, ref]
|
|
64
53
|
};
|
|
65
54
|
await sessionStore.saveMessages(sessionKey, loaded);
|
|
66
55
|
return;
|
|
@@ -68,6 +57,6 @@ async function appendAttachmentToLastAssistant(sessionStore, sessionKey, att) {
|
|
|
68
57
|
}
|
|
69
58
|
}
|
|
70
59
|
//#endregion
|
|
71
|
-
export {
|
|
60
|
+
export { appendMediaToLastAssistant, maybeEmitWebchatTts };
|
|
72
61
|
|
|
73
62
|
//# sourceMappingURL=webchat-tts.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webchat-tts.js","names":[],"sources":["../../../../src/agent/service/webchat-tts.ts"],"sourcesContent":["import type { Config } from '../../config/schema.js';\nimport { persistOutboundTtsAudio } from '../../channels/attachments/outbound-tts-persist.js';\nimport { compressAudio } from '../../voice/tts/audio.js';\nimport { speak } from '../../voice/tts/index.js';\nimport { mergeTtsConfigFromAppConfig } from '../../voice/tts/merge-config.js';\nimport { shouldUseTTS, getChannelOutputFormat } from '../../voice/tts/service.js';\nimport { isTTSAvailable } from '../../voice/tts/factory.js';\nimport
|
|
1
|
+
{"version":3,"file":"webchat-tts.js","names":[],"sources":["../../../../src/agent/service/webchat-tts.ts"],"sourcesContent":["import type { Config } from '../../config/schema.js';\nimport { persistOutboundTtsAudio } from '../../channels/attachments/outbound-tts-persist.js';\nimport type { MediaRef } from '../../media/types.js';\nimport { compressAudio } from '../../voice/tts/audio.js';\nimport { speak } from '../../voice/tts/index.js';\nimport { mergeTtsConfigFromAppConfig } from '../../voice/tts/merge-config.js';\nimport { shouldUseTTS, getChannelOutputFormat } from '../../voice/tts/service.js';\nimport { isTTSAvailable } from '../../voice/tts/factory.js';\nimport type { SessionStore } from '../../session/index.js';\nimport type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nexport type WebchatTtsResult = {\n type: 'tts_audio';\n uri: string;\n mimeType: string;\n name: string;\n};\n\nexport type WebchatTtsDeps = {\n config: Config | undefined;\n sessionStore: SessionStore;\n getLastAssistantPlainText: (sessionKey: string) => string;\n log: { warn: (obj: Record<string, unknown>, msg: string) => void };\n};\n\n/**\n * Generate TTS for webchat when config allows; persist under `{stateDir}/media/tts/`.\n */\nexport async function maybeEmitWebchatTts(\n deps: WebchatTtsDeps,\n sessionKey: string,\n hadInboundVoice: boolean,\n): Promise<WebchatTtsResult | null> {\n const ttsConfig = mergeTtsConfigFromAppConfig(deps.config?.messages?.tts);\n if (!isTTSAvailable(ttsConfig)) {\n return null;\n }\n const decision = shouldUseTTS(ttsConfig, hadInboundVoice);\n if (!decision.useTTS) {\n return null;\n }\n const text = deps.getLastAssistantPlainText(sessionKey).trim();\n if (!text) {\n return null;\n }\n try {\n const webOut = getChannelOutputFormat('webchat');\n const fmt = webOut.format as 'opus' | 'mp3' | 'wav';\n const ttsResult = await speak(text, ttsConfig, {\n appConfig: deps.config,\n tts: { format: fmt },\n });\n const { buffer, format } = await compressAudio(\n Buffer.from(ttsResult.audio),\n ttsResult.format,\n webOut.format === 'mp3' ? 'mp3' : 'opus',\n );\n const normalizedMime =\n format === 'opus' || format === 'ogg'\n ? 'audio/ogg'\n : format === 'mp3' || format === 'mpeg'\n ? 'audio/mpeg'\n : format === 'wav'\n ? 'audio/wav'\n : `audio/${format}`;\n const persisted = await persistOutboundTtsAudio(buffer, format);\n await appendMediaToLastAssistant(deps.sessionStore, sessionKey, persisted);\n return {\n type: 'tts_audio',\n uri: persisted.uri,\n mimeType: normalizedMime,\n name: persisted.name,\n };\n } catch (err) {\n deps.log.warn({ err, sessionKey }, 'Webchat TTS failed');\n return null;\n }\n}\n\nexport async function appendMediaToLastAssistant(\n sessionStore: SessionStore,\n sessionKey: string,\n ref: MediaRef,\n): Promise<void> {\n const loaded = await sessionStore.load(sessionKey);\n for (let i = loaded.length - 1; i >= 0; i--) {\n const m = loaded[i] as { role?: string; media?: MediaRef[] };\n if (m.role === 'assistant') {\n const prev = m.media ?? [];\n if (prev.some((x) => x.uri === ref.uri)) {\n return;\n }\n loaded[i] = { ...m, media: [...prev, ref] } as unknown as AgentMessage;\n await sessionStore.saveMessages(sessionKey, loaded);\n return;\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AA4BA,eAAsB,oBACpB,MACA,YACA,iBACkC;CAClC,MAAM,YAAY,4BAA4B,KAAK,QAAQ,UAAU,IAAI;AACzE,KAAI,CAAC,eAAe,UAAU,CAC5B,QAAO;AAGT,KAAI,CADa,aAAa,WAAW,gBAC5B,CAAC,OACZ,QAAO;CAET,MAAM,OAAO,KAAK,0BAA0B,WAAW,CAAC,MAAM;AAC9D,KAAI,CAAC,KACH,QAAO;AAET,KAAI;EACF,MAAM,SAAS,uBAAuB,UAAU;EAChD,MAAM,MAAM,OAAO;EACnB,MAAM,YAAY,MAAM,MAAM,MAAM,WAAW;GAC7C,WAAW,KAAK;GAChB,KAAK,EAAE,QAAQ,KAAK;GACrB,CAAC;EACF,MAAM,EAAE,QAAQ,WAAW,MAAM,cAC/B,OAAO,KAAK,UAAU,MAAM,EAC5B,UAAU,QACV,OAAO,WAAW,QAAQ,QAAQ,OACnC;EACD,MAAM,iBACJ,WAAW,UAAU,WAAW,QAC5B,cACA,WAAW,SAAS,WAAW,SAC7B,eACA,WAAW,QACT,cACA,SAAS;EACnB,MAAM,YAAY,MAAM,wBAAwB,QAAQ,OAAO;AAC/D,QAAM,2BAA2B,KAAK,cAAc,YAAY,UAAU;AAC1E,SAAO;GACL,MAAM;GACN,KAAK,UAAU;GACf,UAAU;GACV,MAAM,UAAU;GACjB;UACM,KAAK;AACZ,OAAK,IAAI,KAAK;GAAE;GAAK;GAAY,EAAE,qBAAqB;AACxD,SAAO;;;AAIX,eAAsB,2BACpB,cACA,YACA,KACe;CACf,MAAM,SAAS,MAAM,aAAa,KAAK,WAAW;AAClD,MAAK,IAAI,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;EAC3C,MAAM,IAAI,OAAO;AACjB,MAAI,EAAE,SAAS,aAAa;GAC1B,MAAM,OAAO,EAAE,SAAS,EAAE;AAC1B,OAAI,KAAK,MAAM,MAAM,EAAE,QAAQ,IAAI,IAAI,CACrC;AAEF,UAAO,KAAK;IAAE,GAAG;IAAG,OAAO,CAAC,GAAG,MAAM,IAAI;IAAE;AAC3C,SAAM,aAAa,aAAa,YAAY,OAAO;AACnD"}
|
|
@@ -9,6 +9,7 @@ import { type SkillCatalogEntry } 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';
|
|
12
|
+
import { type InboundAttachmentInput, type MediaRef } from '../channels/attachments/inbound-persist.js';
|
|
12
13
|
export type { AgentServiceConfig, AgentContext, StreamHandle } from './service.types.js';
|
|
13
14
|
export declare class AgentService {
|
|
14
15
|
/**
|
|
@@ -24,6 +25,7 @@ export declare class AgentService {
|
|
|
24
25
|
private channelManagerRef;
|
|
25
26
|
private bus;
|
|
26
27
|
private config;
|
|
28
|
+
private embeddedReasoningBySession;
|
|
27
29
|
private sessionTracker;
|
|
28
30
|
private modelManager;
|
|
29
31
|
private progressManager;
|
|
@@ -84,6 +86,7 @@ export declare class AgentService {
|
|
|
84
86
|
private workflowProgressBrokerHandle;
|
|
85
87
|
private feedbackCoordinator;
|
|
86
88
|
private agentManager;
|
|
89
|
+
private memoryFlushService;
|
|
87
90
|
/**
|
|
88
91
|
* Unified per-session state container (replaces six ad-hoc Maps). Owns webchat
|
|
89
92
|
* publishers, last assistant text, embedded stream buffer, persistent-goal stream
|
|
@@ -96,7 +99,6 @@ export declare class AgentService {
|
|
|
96
99
|
private onSessionTranscriptUpdated?;
|
|
97
100
|
private effectiveAppConfig;
|
|
98
101
|
constructor(bus: MessageBus, config: AgentServiceConfig);
|
|
99
|
-
private attachmentRootsForSession;
|
|
100
102
|
private createSessionStore;
|
|
101
103
|
private createHookRunner;
|
|
102
104
|
private createProgressManager;
|
|
@@ -148,24 +150,9 @@ export declare class AgentService {
|
|
|
148
150
|
private parseSessionKey;
|
|
149
151
|
private initSessionContext;
|
|
150
152
|
/**
|
|
151
|
-
* Persist inbound file attachments
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
prepareInboundAttachments(sessionKey: string, attachments?: Array<{
|
|
155
|
-
type: string;
|
|
156
|
-
mimeType?: string;
|
|
157
|
-
data?: string;
|
|
158
|
-
name?: string;
|
|
159
|
-
size?: number;
|
|
160
|
-
workspaceRelativePath?: string;
|
|
161
|
-
}>): Promise<Array<{
|
|
162
|
-
type: string;
|
|
163
|
-
mimeType?: string;
|
|
164
|
-
data?: string;
|
|
165
|
-
name?: string;
|
|
166
|
-
size?: number;
|
|
167
|
-
workspaceRelativePath?: string;
|
|
168
|
-
}> | undefined>;
|
|
153
|
+
* Persist inbound file attachments to the global media store.
|
|
154
|
+
*/
|
|
155
|
+
prepareInboundAttachments(_sessionKey: string, attachments?: InboundAttachmentInput[]): Promise<MediaRef[] | undefined>;
|
|
169
156
|
private endDirectRequestContext;
|
|
170
157
|
/**
|
|
171
158
|
* Reset a session's transcript and drop the in-memory agent so the next turn
|
|
@@ -206,6 +193,8 @@ export declare class AgentService {
|
|
|
206
193
|
*/
|
|
207
194
|
private handleSessionEvent;
|
|
208
195
|
private checkAndCompact;
|
|
196
|
+
private resolveMemoryFlushConfig;
|
|
197
|
+
private checkAndFlush;
|
|
209
198
|
private getContextWindow;
|
|
210
199
|
private dispose;
|
|
211
200
|
}
|