@xopcai/xopc 0.0.118 → 0.0.120
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/README.zh-CN.md +2 -1
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-dzUrQoeZ.js → agent-avatar-dicebear-APTlX9Sq.js} +1 -1
- package/dist/gateway/static/root/assets/agents-CFW_FS_V.js +2 -0
- package/dist/gateway/static/root/assets/app-management-settings-panel-DTKc5HHT.js +1 -0
- package/dist/gateway/static/root/assets/appearance-settings-BTciFrE9.js +1 -0
- package/dist/gateway/static/root/assets/{apps-page--wMEL00f.js → apps-page-DT52OrbM.js} +1 -1
- package/dist/gateway/static/root/assets/{archive-plugin-Cki4SfU2.js → archive-plugin-CiHaUMII.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-D-KnS2Do.js → attachment-load-t4gSrNjL.js} +1 -1
- package/dist/gateway/static/root/assets/automation-suggestion-card-CtysjSoQ.js +1 -0
- package/dist/gateway/static/root/assets/automations-page-B2YvT3ES.js +1 -0
- package/dist/gateway/static/root/assets/{binary-plugins-D2sgvJja.js → binary-plugins-BAbSldW5.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-DIq-4Gvb.js → block-editor-BNr_82xl.js} +28 -28
- package/dist/gateway/static/root/assets/browser-settings-page-BQEXPhDU.js +8 -0
- package/dist/gateway/static/root/assets/capability-presets-api-tzD702Gg.js +1 -0
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-AGhTueAc.js +1 -0
- package/dist/gateway/static/root/assets/channel-recipient-api-DL_KzwGE.js +1 -0
- package/dist/gateway/static/root/assets/channels-settings-DRTutLlN.js +1 -0
- package/dist/gateway/static/root/assets/cn-BQ_8x0bT.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-DneJVuge.js +2 -0
- package/dist/gateway/static/root/assets/cron-expression-B3B1eqnr.js +2 -0
- package/dist/gateway/static/root/assets/dreaming-settings-BEwWA1yf.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-DYu1KaFQ.js → extension-debug-page-Dl2kO0Sf.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-B3W6QwlZ.js → extension-page-DmbLPsx_.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-D7VQ-cxE.js → extension-settings-page-BS2rx40e.js} +1 -1
- package/dist/gateway/static/root/assets/{fetch-B7xDPu-R.js → fetch-B3ME5Eri.js} +1 -1
- package/dist/gateway/static/root/assets/format-cron-label-arqgGlVV.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-config-api-BTBLSeUu.js → gateway-config-api-DI9_BBTo.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-DAFI_T0W.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-CYj9FWCp.js → gateway-startup-retry-CSZQTz6K.js} +1 -1
- package/dist/gateway/static/root/assets/goal-detail-page-DLuz4jC9.js +1 -0
- package/dist/gateway/static/root/assets/{goals-config-api-CQQgzPr3.js → goals-config-api-Bhzqrp2w.js} +1 -1
- package/dist/gateway/static/root/assets/{goals-page-BHitvJAv.js → goals-page-DTAfv9Ft.js} +2 -2
- package/dist/gateway/static/root/assets/goals-settings-CWN2iirQ.js +1 -0
- package/dist/gateway/static/root/assets/heartbeat-settings-CkkkHvOi.js +1 -0
- package/dist/gateway/static/root/assets/index-CnjzMw5i.js +191 -0
- package/dist/gateway/static/root/assets/index-E1QinYKp.css +1 -0
- package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-kMp08SlX.js +1 -0
- package/dist/gateway/static/root/assets/{locale-store-DjbfSsfA.js → locale-store-Ba72bFmP.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-C2Uqvae9.js → logs-page-CDXDlS_W.js} +2 -2
- package/dist/gateway/static/root/assets/{markdown-split-BwOFrJ2E.js → markdown-split-Bc0w40vz.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-Cnz6Q5G6.js → media-plugins-DJ_HvgIy.js} +1 -1
- package/dist/gateway/static/root/assets/messages-CISb1HLv.js +3 -0
- package/dist/gateway/static/root/assets/models-hub-panel-BTwxMIgZ.js +2 -0
- package/dist/gateway/static/root/assets/note-detail-page-BBfOeB0m.js +2 -0
- package/dist/gateway/static/root/assets/{note-image-lightbox-B-Svpmza.js → note-image-lightbox-4zntqpZq.js} +1 -1
- package/dist/gateway/static/root/assets/notes-page-VocWOjoK.js +1 -0
- package/dist/gateway/static/root/assets/{preview-open-alternatives-Bss4TiwP.js → preview-open-alternatives-BbA7sRd_.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-CXwjuD_Q.js +1 -0
- package/dist/gateway/static/root/assets/{save-bar-controls-BRNjdgKq.js → save-bar-controls-Dividh61.js} +1 -1
- package/dist/gateway/static/root/assets/schedule-field-pRheF2CO.js +1 -0
- package/dist/gateway/static/root/assets/{schema-form-Dub9sy8r.js → schema-form-D6PiPxfr.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-CpcVySQK.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BVy_TawT.js +1 -0
- package/dist/gateway/static/root/assets/{settings-collapsible-section-BeFLavGi.js → settings-collapsible-section-BMCOfuE_.js} +1 -1
- package/dist/gateway/static/root/assets/settings-form-section-DBkGwpIN.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-CZpNyCWn.js +1 -0
- package/dist/gateway/static/root/assets/settings-page-layout-NxoW5Y57.js +1 -0
- package/dist/gateway/static/root/assets/setup-status-panel-MVHLLu_a.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-C8glrdqe.js → share-preview-page-B0suFCfj.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-C6DBbQGo.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-6hJmhwSn.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-Im1MA0Iw.js +2 -0
- package/dist/gateway/static/root/assets/system-settings-panel-CrmEnyX4.js +1 -0
- package/dist/gateway/static/root/assets/{theme-store-CD2wtgZV.js → theme-store-Bt6vAkSB.js} +1 -1
- package/dist/gateway/static/root/assets/typed-models-lib-BAsGn25g.js +1 -0
- package/dist/gateway/static/root/assets/{use-channel-catalog-DqlWTsDb.js → use-channel-catalog-C7vcAoGb.js} +1 -1
- package/dist/gateway/static/root/assets/user-profile-settings-panel-QAQWGelF.js +1 -0
- package/dist/gateway/static/root/assets/utils-Dl9efgnV.js +1 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-C73IVZeC.js → voice-api-key-field-D-6XueTv.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-player-store-C_ArLJPM.js → voice-player-store-CMC5NOJp.js} +1 -1
- package/dist/gateway/static/root/assets/workflow-run-setup-panel-DVPllR4k.js +3 -0
- package/dist/gateway/static/root/assets/workflows-page-B94WISTW.js +18 -0
- package/dist/gateway/static/root/index.html +8 -9
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +4 -5
- package/dist/src/agent/agent-manager.js +4 -8
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/context/workspace-templates/AGENTS.md +3 -2
- package/dist/src/agent/embedded/run-for-session.js +102 -14
- package/dist/src/agent/embedded/run-for-session.js.map +1 -1
- package/dist/src/agent/fallback/candidates.d.ts +0 -8
- package/dist/src/agent/fallback/candidates.js.map +1 -1
- package/dist/src/agent/index.js +1 -1
- package/dist/src/agent/lifecycle/handlers/compaction.d.ts +1 -3
- package/dist/src/agent/lifecycle/handlers/compaction.js +1 -16
- package/dist/src/agent/lifecycle/handlers/compaction.js.map +1 -1
- package/dist/src/agent/lifecycle/progress.d.ts +0 -1
- package/dist/src/agent/lifecycle/progress.js +1 -6
- package/dist/src/agent/lifecycle/progress.js.map +1 -1
- package/dist/src/agent/lifecycle/timeout-wrapper.d.ts +1 -2
- package/dist/src/agent/lifecycle/timeout-wrapper.js +1 -7
- package/dist/src/agent/lifecycle/timeout-wrapper.js.map +1 -1
- package/dist/src/agent/memory/builtin-memory-store.d.ts +1 -1
- package/dist/src/agent/memory/builtin-memory-store.js +1 -1
- package/dist/src/agent/memory/builtin-memory-store.js.map +1 -1
- package/dist/src/agent/memory/builtin-provider.d.ts +2 -2
- package/dist/src/agent/memory/builtin-provider.js +2 -2
- package/dist/src/agent/memory/builtin-provider.js.map +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.d.ts +0 -7
- package/dist/src/agent/memory/dreaming/light-sweep.js +16 -277
- package/dist/src/agent/memory/dreaming/light-sweep.js.map +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.d.ts +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.js.map +1 -1
- package/dist/src/agent/memory/dreaming/short-term-store.d.ts +3 -3
- package/dist/src/agent/memory/dreaming/short-term-store.js +5 -5
- package/dist/src/agent/memory/dreaming/short-term-store.js.map +1 -1
- package/dist/src/agent/memory/dreaming/utils.d.ts +2 -2
- package/dist/src/agent/memory/dreaming/utils.js +2 -2
- package/dist/src/agent/memory/dreaming/utils.js.map +1 -1
- package/dist/src/agent/memory/index.d.ts +0 -2
- package/dist/src/agent/memory/index.js +1 -2
- package/dist/src/agent/middleware/self-verify.d.ts +0 -1
- package/dist/src/agent/middleware/self-verify.js +0 -2
- package/dist/src/agent/middleware/self-verify.js.map +1 -1
- package/dist/src/agent/models/index.d.ts +1 -1
- package/dist/src/agent/models/manager.d.ts +4 -20
- package/dist/src/agent/models/manager.js +9 -126
- package/dist/src/agent/models/manager.js.map +1 -1
- package/dist/src/agent/orchestration/agent-orchestrator.d.ts +0 -4
- package/dist/src/agent/orchestration/agent-orchestrator.js +1 -9
- package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
- package/dist/src/agent/prompt/sections/memory-skills.js +11 -10
- package/dist/src/agent/prompt/sections/memory-skills.js.map +1 -1
- package/dist/src/agent/prompt/sections/tooling.js +4 -4
- package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.d.ts +0 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +0 -12
- package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
- package/dist/src/agent/prompt/subagent-context.js +1 -1
- package/dist/src/agent/prompt/subagent-context.js.map +1 -1
- package/dist/src/agent/prompt/types.d.ts +1 -1
- package/dist/src/agent/reply/startup-context.js +6 -105
- package/dist/src/agent/reply/startup-context.js.map +1 -1
- package/dist/src/agent/service.d.ts +1 -12
- package/dist/src/agent/service.js +3 -81
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/service.types.d.ts +2 -2
- package/dist/src/agent/session/session-config-service.d.ts +11 -11
- package/dist/src/agent/session/session-config-service.js +14 -14
- package/dist/src/agent/session/session-config-service.js.map +1 -1
- package/dist/src/agent/session/session-inspector.js +3 -2
- package/dist/src/agent/session/session-inspector.js.map +1 -1
- package/dist/src/agent/starter-agents.js +12 -12
- package/dist/src/agent/starter-agents.js.map +1 -1
- package/dist/src/agent/tools/automation-tool.d.ts +14 -0
- package/dist/src/agent/tools/automation-tool.js +102 -0
- package/dist/src/agent/tools/automation-tool.js.map +1 -0
- package/dist/src/agent/tools/delegate-tool.js +1 -1
- package/dist/src/agent/tools/delegate-tool.js.map +1 -1
- package/dist/src/agent/tools/factory.d.ts +3 -3
- package/dist/src/agent/tools/factory.js +2 -2
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/index.d.ts +1 -1
- package/dist/src/agent/tools/index.js +2 -2
- package/dist/src/agent/tools/memory-tool.js +2 -2
- package/dist/src/agent/tools/memory-tool.js.map +1 -1
- package/dist/src/agent-manifest/resolver.d.ts +1 -0
- package/dist/src/agent-manifest/resolver.js +1 -0
- package/dist/src/agent-manifest/resolver.js.map +1 -1
- package/dist/src/agent-manifest/schema.d.ts +6 -0
- package/dist/src/agent-manifest/schema.js +12 -3
- package/dist/src/agent-manifest/schema.js.map +1 -1
- package/dist/src/ai-assist/text-assist.d.ts +1 -1
- package/dist/src/ai-assist/text-assist.js +56 -0
- package/dist/src/ai-assist/text-assist.js.map +1 -1
- package/dist/src/auth/profiles/store.js.map +1 -1
- package/dist/src/automations/api/routes.d.ts +3 -0
- package/dist/src/automations/api/routes.js +193 -0
- package/dist/src/automations/api/routes.js.map +1 -0
- package/dist/src/automations/domain/index.d.ts +3 -0
- package/dist/src/automations/domain/index.js +3 -0
- package/dist/src/automations/domain/schedule.d.ts +4 -0
- package/dist/src/automations/domain/schedule.js +37 -0
- package/dist/src/automations/domain/schedule.js.map +1 -0
- package/dist/src/automations/domain/types.d.ts +160 -0
- package/dist/src/automations/domain/validation.d.ts +370 -0
- package/dist/src/automations/domain/validation.js +149 -0
- package/dist/src/automations/domain/validation.js.map +1 -0
- package/dist/src/automations/draft/automation-draft-prompt.d.ts +26 -0
- package/dist/src/automations/draft/automation-draft-prompt.js +127 -0
- package/dist/src/automations/draft/automation-draft-prompt.js.map +1 -0
- package/dist/src/automations/draft/automation-draft-service.d.ts +12 -0
- package/dist/src/automations/draft/automation-draft-service.js +135 -0
- package/dist/src/automations/draft/automation-draft-service.js.map +1 -0
- package/dist/src/automations/draft/automation-draft-validator.d.ts +99 -0
- package/dist/src/automations/draft/automation-draft-validator.js +105 -0
- package/dist/src/automations/draft/automation-draft-validator.js.map +1 -0
- package/dist/src/automations/draft/automation-draft.types.d.ts +40 -0
- package/dist/src/automations/draft/index.d.ts +3 -0
- package/dist/src/automations/draft/index.js +3 -0
- package/dist/src/automations/index.d.ts +3 -0
- package/dist/src/automations/index.js +8 -0
- package/dist/src/automations/product-events.d.ts +5 -0
- package/dist/src/automations/product-events.js +21 -0
- package/dist/src/automations/product-events.js.map +1 -0
- package/dist/src/automations/service/action-executor.d.ts +9 -0
- package/dist/src/automations/service/action-executor.js +157 -0
- package/dist/src/automations/service/action-executor.js.map +1 -0
- package/dist/src/automations/service/automation-service.d.ts +54 -0
- package/dist/src/automations/service/automation-service.js +404 -0
- package/dist/src/automations/service/automation-service.js.map +1 -0
- package/dist/src/automations/service/index.d.ts +2 -0
- package/dist/src/automations/service/index.js +3 -0
- package/dist/src/automations/storage/automation-repository.d.ts +6 -0
- package/dist/src/automations/storage/automation-repository.js +61 -0
- package/dist/src/automations/storage/automation-repository.js.map +1 -0
- package/dist/src/automations/storage/automation-run-repository.d.ts +17 -0
- package/dist/src/automations/storage/automation-run-repository.js +130 -0
- package/dist/src/automations/storage/automation-run-repository.js.map +1 -0
- package/dist/src/automations/storage/index.d.ts +2 -0
- package/dist/src/automations/storage/index.js +3 -0
- package/dist/src/channels/plugin-types.d.ts +3 -0
- package/dist/src/chat-commands/builtins/thinking.js.map +1 -1
- package/dist/src/cli/command-catalog.js +0 -39
- package/dist/src/cli/command-catalog.js.map +1 -1
- package/dist/src/cli/command-loaders.js +0 -1
- package/dist/src/cli/command-loaders.js.map +1 -1
- package/dist/src/cli/command-manifest.js +0 -4
- package/dist/src/cli/command-manifest.js.map +1 -1
- package/dist/src/cli/commands/agents.js +7 -6
- package/dist/src/cli/commands/agents.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/doctor/checks/{cron-health.d.ts → migrations.d.ts} +1 -1
- package/dist/src/cli/commands/doctor/checks/migrations.js +40 -0
- package/dist/src/cli/commands/doctor/checks/migrations.js.map +1 -0
- package/dist/src/cli/commands/doctor/flow.js +2 -2
- package/dist/src/cli/commands/doctor/flow.js.map +1 -1
- package/dist/src/cli/commands/gateway/call.js +2 -2
- package/dist/src/cli/commands/gateway/call.js.map +1 -1
- package/dist/src/cli/commands/gateway/run-foreground.js +4 -2
- package/dist/src/cli/commands/gateway/run-foreground.js.map +1 -1
- package/dist/src/cli/commands/init.js +27 -9
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/tui.js +24 -2
- package/dist/src/cli/commands/tui.js.map +1 -1
- package/dist/src/cli/templates.js +3 -2
- package/dist/src/cli/templates.js.map +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +2 -0
- package/dist/src/cli/utils/init-workspace-core.js.map +1 -1
- package/dist/src/commands/agents.config.d.ts +9 -0
- package/dist/src/commands/agents.config.js +40 -2
- package/dist/src/commands/agents.config.js.map +1 -1
- package/dist/src/config/agent-profile.js +4 -3
- package/dist/src/config/agent-profile.js.map +1 -1
- package/dist/src/config/agent-typed-models.js.map +1 -1
- package/dist/src/config/config-surface.d.ts +3 -0
- package/dist/src/config/index.d.ts +0 -1
- package/dist/src/config/index.js +3 -3
- package/dist/src/config/index.js.map +1 -1
- package/dist/src/config/paths.d.ts +0 -9
- package/dist/src/config/paths.js +1 -14
- package/dist/src/config/paths.js.map +1 -1
- package/dist/src/config/profile.js +0 -1
- package/dist/src/config/profile.js.map +1 -1
- package/dist/src/config/rules.js +0 -5
- package/dist/src/config/rules.js.map +1 -1
- package/dist/src/config/schema.d.ts +13 -12
- package/dist/src/config/schema.js +22 -26
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/config/web-patch.d.ts +0 -12
- package/dist/src/config/web-patch.js +2 -29
- package/dist/src/config/web-patch.js.map +1 -1
- package/dist/src/extensions/api.d.ts +2 -0
- package/dist/src/extensions/api.js +10 -0
- package/dist/src/extensions/api.js.map +1 -1
- package/dist/src/extensions/extension-registry-impl.d.ts +4 -1
- package/dist/src/extensions/extension-registry-impl.js +8 -0
- package/dist/src/extensions/extension-registry-impl.js.map +1 -1
- package/dist/src/extensions/loader.d.ts +3 -3
- package/dist/src/extensions/loader.js +3 -3
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/extensions/sdk/testing.d.ts +2 -0
- package/dist/src/extensions/sdk/testing.js +7 -0
- package/dist/src/extensions/sdk/testing.js.map +1 -1
- package/dist/src/extensions/types/core.d.ts +10 -1
- package/dist/src/extensions/types/index.d.ts +1 -1
- package/dist/src/extensions/types/{phase4.d.ts → registration.d.ts} +2 -2
- package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
- package/dist/src/gateway/agent-builtin-tools.js +1 -1
- package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
- package/dist/src/gateway/agents-admin.d.ts +1 -0
- package/dist/src/gateway/agents-admin.js +13 -15
- package/dist/src/gateway/agents-admin.js.map +1 -1
- package/dist/src/gateway/capability-presets-admin.d.ts +1 -0
- package/dist/src/gateway/capability-presets-admin.js +19 -10
- package/dist/src/gateway/capability-presets-admin.js.map +1 -1
- package/dist/src/gateway/dreaming-automation-reconciler.d.ts +11 -0
- package/dist/src/gateway/dreaming-automation-reconciler.js +105 -0
- package/dist/src/gateway/dreaming-automation-reconciler.js.map +1 -0
- package/dist/src/gateway/heartbeat/service.d.ts +0 -2
- package/dist/src/gateway/heartbeat/service.js +0 -7
- package/dist/src/gateway/heartbeat/service.js.map +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +5 -6
- package/dist/src/gateway/hono/lib/config-payload.js +2 -2
- package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
- package/dist/src/gateway/hono/routes/agents.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.d.ts +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +15 -6
- package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -1
- package/dist/src/gateway/hono/routes/dreaming.js +27 -37
- package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
- package/dist/src/gateway/hono/routes/home.d.ts +2 -2
- package/dist/src/gateway/hono/routes/home.js +34 -25
- package/dist/src/gateway/hono/routes/home.js.map +1 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js +10 -6
- package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
- package/dist/src/gateway/hono/routes/migrations.d.ts +3 -0
- package/dist/src/gateway/hono/routes/migrations.js +35 -0
- package/dist/src/gateway/hono/routes/migrations.js.map +1 -0
- package/dist/src/gateway/hono/routes/public-gateway.js +2 -1
- package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +14 -0
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/run-loop.js +2 -0
- package/dist/src/gateway/run-loop.js.map +1 -1
- package/dist/src/gateway/security/operator-scopes.js +5 -1
- package/dist/src/gateway/security/operator-scopes.js.map +1 -1
- package/dist/src/gateway/service/config-coordinator.d.ts +4 -4
- package/dist/src/gateway/service/config-coordinator.js +14 -8
- package/dist/src/gateway/service/config-coordinator.js.map +1 -1
- package/dist/src/gateway/service/sessions-api.d.ts +2 -1
- package/dist/src/gateway/service/sessions-api.js +6 -1
- package/dist/src/gateway/service/sessions-api.js.map +1 -1
- package/dist/src/gateway/service.d.ts +7 -3
- package/dist/src/gateway/service.js +61 -27
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/goals/goal-service.js +45 -4
- package/dist/src/goals/goal-service.js.map +1 -1
- package/dist/src/migrations/config/default-capability-preset.d.ts +10 -0
- package/dist/src/migrations/config/default-capability-preset.js +135 -0
- package/dist/src/migrations/config/default-capability-preset.js.map +1 -0
- package/dist/src/migrations/index.d.ts +4 -0
- package/dist/src/migrations/index.js +4 -0
- package/dist/src/migrations/registry.d.ts +8 -0
- package/dist/src/migrations/registry.js +18 -0
- package/dist/src/migrations/registry.js.map +1 -0
- package/dist/src/migrations/runner.d.ts +17 -0
- package/dist/src/migrations/runner.js +191 -0
- package/dist/src/migrations/runner.js.map +1 -0
- package/dist/src/migrations/types.d.ts +34 -0
- package/dist/src/notes/service.js +24 -1
- package/dist/src/notes/service.js.map +1 -1
- package/dist/src/providers/model-registry.d.ts +0 -1
- package/dist/src/providers/model-registry.js +0 -3
- package/dist/src/providers/model-registry.js.map +1 -1
- package/dist/src/routing/resolve-tui-session-key.d.ts +3 -0
- package/dist/src/routing/resolve-tui-session-key.js +14 -3
- package/dist/src/routing/resolve-tui-session-key.js.map +1 -1
- package/dist/src/session/transcript-outline.d.ts +47 -0
- package/dist/src/session/transcript-outline.js +481 -0
- package/dist/src/session/transcript-outline.js.map +1 -0
- package/dist/src/storage/sqlite/index.d.ts +0 -2
- package/dist/src/storage/sqlite/index.js +1 -3
- package/dist/src/storage/sqlite/migrations/016_automations.sql +47 -0
- package/dist/src/storage/sqlite/migrations/017_automation_run_events.sql +14 -0
- package/dist/src/storage/sqlite/migrations/018_automation_safety.sql +1 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/row-mappers.js +3 -1
- package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/schema.sql +56 -46
- package/dist/src/tui/backends/embedded-backend.d.ts +6 -0
- package/dist/src/tui/backends/embedded-backend.js +19 -9
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.d.ts +3 -0
- package/dist/src/tui/backends/gateway-sse-backend.js +14 -0
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/tui-backend.d.ts +4 -0
- package/dist/src/tui/tui-commands.d.ts +5 -0
- package/dist/src/tui/tui-commands.js +43 -0
- package/dist/src/tui/tui-commands.js.map +1 -1
- package/dist/src/tui/tui-transcript-tree.d.ts +1 -1
- package/dist/src/tui/tui-transcript-tree.js +17 -257
- package/dist/src/tui/tui-transcript-tree.js.map +1 -1
- package/dist/src/tui/tui-types.d.ts +2 -0
- package/dist/src/tui/tui-types.js.map +1 -1
- package/dist/src/tui/tui.js +7 -2
- package/dist/src/tui/tui.js.map +1 -1
- package/dist/src/workflows/domain/index.js +1 -1
- package/dist/src/workflows/domain/run.d.ts +7 -7
- package/dist/src/workflows/domain/run.js.map +1 -1
- package/dist/src/workflows/index.js +2 -2
- package/dist/src/workflows/service/workflow-run-service.d.ts +2 -0
- package/dist/src/workflows/service/workflow-run-service.js +31 -9
- package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
- package/dist/src/workflows/service/workflow-run-service.types.d.ts +1 -1
- package/package.json +4 -2
- package/dist/gateway/static/root/assets/agents-BCxZbkOw.js +0 -2
- package/dist/gateway/static/root/assets/app-management-settings-panel-bxYJVJpx.js +0 -1
- package/dist/gateway/static/root/assets/appearance-settings-BCIykXlI.js +0 -1
- package/dist/gateway/static/root/assets/browser-settings-page-DRhKdn81.js +0 -8
- package/dist/gateway/static/root/assets/capability-presets-api-CorhiHlg.js +0 -1
- package/dist/gateway/static/root/assets/capability-presets-settings-panel-qFx9Jtce.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-BAwAkqIA.js +0 -1
- package/dist/gateway/static/root/assets/cn-JdwAhgNB.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-BQLcfitM.js +0 -2
- package/dist/gateway/static/root/assets/createLucideIcon-DPHK1VkS.js +0 -1
- package/dist/gateway/static/root/assets/cron-api-qGwmL-24.js +0 -1
- package/dist/gateway/static/root/assets/cron-dreaming-jobs-nCMWCf0p.js +0 -1
- package/dist/gateway/static/root/assets/cron-page-BBWMAj8-.js +0 -3
- package/dist/gateway/static/root/assets/dreaming-settings-Dw89Obml.js +0 -1
- package/dist/gateway/static/root/assets/format-cron-label-BsotZDO5.js +0 -2
- package/dist/gateway/static/root/assets/format-interval-label-BzxafKxR.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-Cmwy58rS.js +0 -1
- package/dist/gateway/static/root/assets/goal-detail-page-l7mu5GWX.js +0 -1
- package/dist/gateway/static/root/assets/goals-settings-CYVY4NGp.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-config-api-DriO_CN9.js +0 -1
- package/dist/gateway/static/root/assets/heartbeat-settings-CUQTKxg7.js +0 -1
- package/dist/gateway/static/root/assets/index-C17Tsd_b.css +0 -1
- package/dist/gateway/static/root/assets/index-Cc41r16l.js +0 -191
- package/dist/gateway/static/root/assets/interval-presets-DFPCKW_W.js +0 -1
- package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-CcVcqstx.js +0 -1
- package/dist/gateway/static/root/assets/messages-B1iSKjiw.js +0 -3
- package/dist/gateway/static/root/assets/models-hub-panel-BfLfcta8.js +0 -2
- package/dist/gateway/static/root/assets/note-detail-page-BjwOQBfT.js +0 -2
- package/dist/gateway/static/root/assets/notes-page-DktdBiwB.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-rfVx96fq.js +0 -1
- package/dist/gateway/static/root/assets/schedule-field-CUCKODde.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-DbtMFuuH.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-5re5gAnP.js +0 -1
- package/dist/gateway/static/root/assets/settings-form-section-dmyaPOTG.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-D-WMyLlj.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Cl-DEJAU.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-CyPVvbLt.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-CleTH1oz.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-Ck8hdXqR.js +0 -2
- package/dist/gateway/static/root/assets/system-settings-panel-DI-LN_8G.js +0 -1
- package/dist/gateway/static/root/assets/typed-models-lib-kX9duch4.js +0 -1
- package/dist/gateway/static/root/assets/user-profile-settings-panel-B-UFPMXy.js +0 -1
- package/dist/gateway/static/root/assets/utils-Dm0hKalR.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-BtFGp2y_.js +0 -18
- package/dist/src/agent/fallback/error.d.ts +0 -22
- package/dist/src/agent/fallback/error.js +0 -32
- package/dist/src/agent/fallback/error.js.map +0 -1
- package/dist/src/agent/fallback/index.d.ts +0 -5
- package/dist/src/agent/fallback/index.js +0 -9
- package/dist/src/agent/fallback/index.js.map +0 -1
- package/dist/src/agent/memory/memory-flush.d.ts +0 -27
- package/dist/src/agent/memory/memory-flush.js +0 -124
- package/dist/src/agent/memory/memory-flush.js.map +0 -1
- package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.d.ts +0 -29
- package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js +0 -76
- package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js.map +0 -1
- package/dist/src/agent/service/reconcile-dreaming-cron.d.ts +0 -6
- package/dist/src/agent/service/reconcile-dreaming-cron.js +0 -84
- package/dist/src/agent/service/reconcile-dreaming-cron.js.map +0 -1
- package/dist/src/agent/tools/cronjob-tool.d.ts +0 -29
- package/dist/src/agent/tools/cronjob-tool.js +0 -274
- package/dist/src/agent/tools/cronjob-tool.js.map +0 -1
- package/dist/src/cli/commands/cron-cli.d.ts +0 -2
- package/dist/src/cli/commands/cron-cli.js +0 -15
- package/dist/src/cli/commands/cron-cli.js.map +0 -1
- package/dist/src/cli/commands/cron.d.ts +0 -4
- package/dist/src/cli/commands/cron.js +0 -188
- package/dist/src/cli/commands/cron.js.map +0 -1
- package/dist/src/cli/commands/doctor/checks/cron-health.js +0 -35
- package/dist/src/cli/commands/doctor/checks/cron-health.js.map +0 -1
- package/dist/src/cron/execution-types.d.ts +0 -42
- package/dist/src/cron/executor.d.ts +0 -67
- package/dist/src/cron/executor.js +0 -669
- package/dist/src/cron/executor.js.map +0 -1
- package/dist/src/cron/index.d.ts +0 -7
- package/dist/src/cron/index.js +0 -7
- package/dist/src/cron/job-content.d.ts +0 -5
- package/dist/src/cron/job-content.js +0 -15
- package/dist/src/cron/job-content.js.map +0 -1
- package/dist/src/cron/run-log-store.d.ts +0 -12
- package/dist/src/cron/run-log-store.js +0 -58
- package/dist/src/cron/run-log-store.js.map +0 -1
- package/dist/src/cron/schedule.d.ts +0 -10
- package/dist/src/cron/schedule.js +0 -85
- package/dist/src/cron/schedule.js.map +0 -1
- package/dist/src/cron/service.d.ts +0 -58
- package/dist/src/cron/service.js +0 -419
- package/dist/src/cron/service.js.map +0 -1
- package/dist/src/cron/types.d.ts +0 -183
- package/dist/src/cron/validation.d.ts +0 -500
- package/dist/src/cron/validation.js +0 -192
- package/dist/src/cron/validation.js.map +0 -1
- package/dist/src/cron/workflow-run-completion.d.ts +0 -23
- package/dist/src/cron/workflow-run-completion.js +0 -72
- package/dist/src/cron/workflow-run-completion.js.map +0 -1
- package/dist/src/extensions/types/phase4.js +0 -1
- package/dist/src/gateway/hono/routes/cron.d.ts +0 -3
- package/dist/src/gateway/hono/routes/cron.js +0 -109
- package/dist/src/gateway/hono/routes/cron.js.map +0 -1
- package/dist/src/storage/sqlite/cron-job-repository.d.ts +0 -6
- package/dist/src/storage/sqlite/cron-job-repository.js +0 -70
- package/dist/src/storage/sqlite/cron-job-repository.js.map +0 -1
- package/dist/src/storage/sqlite/cron-run-repository.d.ts +0 -5
- package/dist/src/storage/sqlite/cron-run-repository.js +0 -96
- package/dist/src/storage/sqlite/cron-run-repository.js.map +0 -1
- /package/dist/src/{cron → automations/domain}/types.js +0 -0
- /package/dist/src/{config/defaults.d.ts → automations/draft/automation-draft.types.js} +0 -0
- /package/dist/src/{config/defaults.js → extensions/types/registration.js} +0 -0
- /package/dist/src/{cron/execution-types.js → migrations/types.js} +0 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { init_agent_scope, resolveDefaultAgentId } from "../agent/agent-scope.js";
|
|
2
|
+
import { DREAMING_CRON_NAME, DREAMING_CRON_TAG, DREAMING_LIGHT_CRON_NAME, DREAMING_LIGHT_SWEEP_TOKEN, DREAMING_REM_CRON_NAME, DREAMING_REM_SWEEP_TOKEN, DREAMING_SWEEP_TOKEN } from "../agent/memory/dreaming/constants.js";
|
|
3
|
+
import { resolveDreamingConfig } from "../agent/memory/dreaming/config.js";
|
|
4
|
+
import { getWorkspacePath } from "../config/workspace-path-helpers.js";
|
|
5
|
+
//#region src/gateway/dreaming-automation-reconciler.ts
|
|
6
|
+
init_agent_scope();
|
|
7
|
+
const DREAMING_AUTOMATIONS = [
|
|
8
|
+
{
|
|
9
|
+
id: "system-dreaming-light",
|
|
10
|
+
phase: "light",
|
|
11
|
+
name: DREAMING_LIGHT_CRON_NAME,
|
|
12
|
+
token: DREAMING_LIGHT_SWEEP_TOKEN
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
id: "system-dreaming-deep",
|
|
16
|
+
phase: "deep",
|
|
17
|
+
name: DREAMING_CRON_NAME,
|
|
18
|
+
token: DREAMING_SWEEP_TOKEN
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: "system-dreaming-rem",
|
|
22
|
+
phase: "rem",
|
|
23
|
+
name: DREAMING_REM_CRON_NAME,
|
|
24
|
+
token: DREAMING_REM_SWEEP_TOKEN
|
|
25
|
+
}
|
|
26
|
+
];
|
|
27
|
+
function phaseDescription(phase) {
|
|
28
|
+
return `${phase === "light" ? "Light sweep" : phase === "deep" ? "Deep promotion" : "REM pattern discovery"} for memory dreaming. ${DREAMING_CRON_TAG}`;
|
|
29
|
+
}
|
|
30
|
+
function buildTrigger(config, phase) {
|
|
31
|
+
return {
|
|
32
|
+
kind: "schedule",
|
|
33
|
+
schedule: {
|
|
34
|
+
kind: "cron",
|
|
35
|
+
expr: config.phases[phase].cron,
|
|
36
|
+
...config.timezone ? { tz: config.timezone } : {}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function buildAction(config, agentId, token) {
|
|
41
|
+
const workspaceDir = getWorkspacePath(config);
|
|
42
|
+
return {
|
|
43
|
+
kind: "agent",
|
|
44
|
+
agentId,
|
|
45
|
+
instruction: token,
|
|
46
|
+
...workspaceDir ? { workingDirectory: workspaceDir } : {},
|
|
47
|
+
timeoutSeconds: 3600
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function automationNeedsUpdate(current, next) {
|
|
51
|
+
return current.name !== next.name || current.description !== next.description || current.enabled !== next.enabled || JSON.stringify(current.trigger) !== JSON.stringify(next.trigger) || JSON.stringify(current.action) !== JSON.stringify(next.action) || current.safety?.mode !== "auto_apply" || current.afterRun?.kind !== "none" || current.reliability?.disableAfterConsecutiveFailures !== 3;
|
|
52
|
+
}
|
|
53
|
+
async function reconcileDreamingAutomations(params) {
|
|
54
|
+
const { config, automationService } = params;
|
|
55
|
+
const resolved = resolveDreamingConfig(config);
|
|
56
|
+
const agentId = resolveDefaultAgentId(config);
|
|
57
|
+
const result = {
|
|
58
|
+
created: [],
|
|
59
|
+
updated: [],
|
|
60
|
+
disabled: []
|
|
61
|
+
};
|
|
62
|
+
for (const spec of DREAMING_AUTOMATIONS) {
|
|
63
|
+
const current = await automationService.get(spec.id);
|
|
64
|
+
const enabled = resolved.enabled && resolved.phases[spec.phase].enabled;
|
|
65
|
+
if (!resolved.enabled) {
|
|
66
|
+
if (current?.enabled) {
|
|
67
|
+
await automationService.update(spec.id, { enabled: false });
|
|
68
|
+
result.disabled.push(spec.id);
|
|
69
|
+
}
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const next = {
|
|
73
|
+
name: spec.name,
|
|
74
|
+
description: phaseDescription(spec.phase),
|
|
75
|
+
enabled,
|
|
76
|
+
trigger: buildTrigger(resolved, spec.phase),
|
|
77
|
+
action: buildAction(config, agentId, spec.token)
|
|
78
|
+
};
|
|
79
|
+
if (!current) {
|
|
80
|
+
await automationService.create({
|
|
81
|
+
id: spec.id,
|
|
82
|
+
...next,
|
|
83
|
+
safety: { mode: "auto_apply" },
|
|
84
|
+
afterRun: { kind: "none" },
|
|
85
|
+
reliability: { disableAfterConsecutiveFailures: 3 }
|
|
86
|
+
});
|
|
87
|
+
result.created.push(spec.id);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (automationNeedsUpdate(current, next)) {
|
|
91
|
+
await automationService.update(spec.id, {
|
|
92
|
+
...next,
|
|
93
|
+
safety: { mode: "auto_apply" },
|
|
94
|
+
afterRun: { kind: "none" },
|
|
95
|
+
reliability: { disableAfterConsecutiveFailures: 3 }
|
|
96
|
+
});
|
|
97
|
+
result.updated.push(spec.id);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { reconcileDreamingAutomations };
|
|
104
|
+
|
|
105
|
+
//# sourceMappingURL=dreaming-automation-reconciler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dreaming-automation-reconciler.js","names":[],"sources":["../../../src/gateway/dreaming-automation-reconciler.ts"],"sourcesContent":["import type { Config } from '../config/schema.js';\nimport { getWorkspacePath } from '../config/workspace-path-helpers.js';\nimport { resolveDefaultAgentId } from '../agent/agent-scope.js';\nimport { resolveDreamingConfig, type DreamingResolvedConfig } from '../agent/memory/dreaming/config.js';\nimport {\n DREAMING_CRON_NAME,\n DREAMING_CRON_TAG,\n DREAMING_LIGHT_CRON_NAME,\n DREAMING_LIGHT_SWEEP_TOKEN,\n DREAMING_REM_CRON_NAME,\n DREAMING_REM_SWEEP_TOKEN,\n DREAMING_SWEEP_TOKEN,\n type DreamingPhaseId,\n} from '../agent/memory/dreaming/constants.js';\nimport type { AutomationService } from '../automations/index.js';\nimport type { Automation, AutomationAction, AutomationTrigger } from '../automations/domain/types.js';\n\ntype DreamingAutomationSpec = {\n id: string;\n phase: DreamingPhaseId;\n name: string;\n token: string;\n};\n\nconst DREAMING_AUTOMATIONS: readonly DreamingAutomationSpec[] = [\n {\n id: 'system-dreaming-light',\n phase: 'light',\n name: DREAMING_LIGHT_CRON_NAME,\n token: DREAMING_LIGHT_SWEEP_TOKEN,\n },\n {\n id: 'system-dreaming-deep',\n phase: 'deep',\n name: DREAMING_CRON_NAME,\n token: DREAMING_SWEEP_TOKEN,\n },\n {\n id: 'system-dreaming-rem',\n phase: 'rem',\n name: DREAMING_REM_CRON_NAME,\n token: DREAMING_REM_SWEEP_TOKEN,\n },\n];\n\nexport type DreamingAutomationReconcileResult = {\n created: string[];\n updated: string[];\n disabled: string[];\n};\n\nfunction phaseDescription(phase: DreamingPhaseId): string {\n const label = phase === 'light' ? 'Light sweep' : phase === 'deep' ? 'Deep promotion' : 'REM pattern discovery';\n return `${label} for memory dreaming. ${DREAMING_CRON_TAG}`;\n}\n\nfunction buildTrigger(config: DreamingResolvedConfig, phase: DreamingPhaseId): AutomationTrigger {\n const phaseConfig = config.phases[phase];\n return {\n kind: 'schedule',\n schedule: {\n kind: 'cron',\n expr: phaseConfig.cron,\n ...(config.timezone ? { tz: config.timezone } : {}),\n },\n };\n}\n\nfunction buildAction(config: Config, agentId: string, token: string): AutomationAction {\n const workspaceDir = getWorkspacePath(config);\n return {\n kind: 'agent',\n agentId,\n instruction: token,\n ...(workspaceDir ? { workingDirectory: workspaceDir } : {}),\n timeoutSeconds: 3600,\n };\n}\n\nfunction automationNeedsUpdate(current: Automation, next: {\n name: string;\n description: string;\n enabled: boolean;\n trigger: AutomationTrigger;\n action: AutomationAction;\n}): boolean {\n return (\n current.name !== next.name ||\n current.description !== next.description ||\n current.enabled !== next.enabled ||\n JSON.stringify(current.trigger) !== JSON.stringify(next.trigger) ||\n JSON.stringify(current.action) !== JSON.stringify(next.action) ||\n current.safety?.mode !== 'auto_apply' ||\n current.afterRun?.kind !== 'none' ||\n current.reliability?.disableAfterConsecutiveFailures !== 3\n );\n}\n\nexport async function reconcileDreamingAutomations(params: {\n config: Config;\n automationService: AutomationService;\n}): Promise<DreamingAutomationReconcileResult> {\n const { config, automationService } = params;\n const resolved = resolveDreamingConfig(config);\n const agentId = resolveDefaultAgentId(config);\n const result: DreamingAutomationReconcileResult = { created: [], updated: [], disabled: [] };\n\n for (const spec of DREAMING_AUTOMATIONS) {\n const current = await automationService.get(spec.id);\n const enabled = resolved.enabled && resolved.phases[spec.phase].enabled;\n\n if (!resolved.enabled) {\n if (current?.enabled) {\n await automationService.update(spec.id, { enabled: false });\n result.disabled.push(spec.id);\n }\n continue;\n }\n\n const next = {\n name: spec.name,\n description: phaseDescription(spec.phase),\n enabled,\n trigger: buildTrigger(resolved, spec.phase),\n action: buildAction(config, agentId, spec.token),\n };\n\n if (!current) {\n await automationService.create({\n id: spec.id,\n ...next,\n safety: { mode: 'auto_apply' },\n afterRun: { kind: 'none' },\n reliability: { disableAfterConsecutiveFailures: 3 },\n });\n result.created.push(spec.id);\n continue;\n }\n\n if (automationNeedsUpdate(current, next)) {\n await automationService.update(spec.id, {\n ...next,\n safety: { mode: 'auto_apply' },\n afterRun: { kind: 'none' },\n reliability: { disableAfterConsecutiveFailures: 3 },\n });\n result.updated.push(spec.id);\n }\n }\n\n return result;\n}\n"],"mappings":";;;;;kBAEgE;AAsBhE,MAAM,uBAA0D;CAC9D;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,OAAO;EACR;CACF;AAQD,SAAS,iBAAiB,OAAgC;AAExD,QAAO,GADO,UAAU,UAAU,gBAAgB,UAAU,SAAS,mBAAmB,wBACxE,wBAAwB;;AAG1C,SAAS,aAAa,QAAgC,OAA2C;AAE/F,QAAO;EACL,MAAM;EACN,UAAU;GACR,MAAM;GACN,MALgB,OAAO,OAAO,OAKZ;GAClB,GAAI,OAAO,WAAW,EAAE,IAAI,OAAO,UAAU,GAAG,EAAE;GACnD;EACF;;AAGH,SAAS,YAAY,QAAgB,SAAiB,OAAiC;CACrF,MAAM,eAAe,iBAAiB,OAAO;AAC7C,QAAO;EACL,MAAM;EACN;EACA,aAAa;EACb,GAAI,eAAe,EAAE,kBAAkB,cAAc,GAAG,EAAE;EAC1D,gBAAgB;EACjB;;AAGH,SAAS,sBAAsB,SAAqB,MAMxC;AACV,QACE,QAAQ,SAAS,KAAK,QACtB,QAAQ,gBAAgB,KAAK,eAC7B,QAAQ,YAAY,KAAK,WACzB,KAAK,UAAU,QAAQ,QAAQ,KAAK,KAAK,UAAU,KAAK,QAAQ,IAChE,KAAK,UAAU,QAAQ,OAAO,KAAK,KAAK,UAAU,KAAK,OAAO,IAC9D,QAAQ,QAAQ,SAAS,gBACzB,QAAQ,UAAU,SAAS,UAC3B,QAAQ,aAAa,oCAAoC;;AAI7D,eAAsB,6BAA6B,QAGJ;CAC7C,MAAM,EAAE,QAAQ,sBAAsB;CACtC,MAAM,WAAW,sBAAsB,OAAO;CAC9C,MAAM,UAAU,sBAAsB,OAAO;CAC7C,MAAM,SAA4C;EAAE,SAAS,EAAE;EAAE,SAAS,EAAE;EAAE,UAAU,EAAE;EAAE;AAE5F,MAAK,MAAM,QAAQ,sBAAsB;EACvC,MAAM,UAAU,MAAM,kBAAkB,IAAI,KAAK,GAAG;EACpD,MAAM,UAAU,SAAS,WAAW,SAAS,OAAO,KAAK,OAAO;AAEhE,MAAI,CAAC,SAAS,SAAS;AACrB,OAAI,SAAS,SAAS;AACpB,UAAM,kBAAkB,OAAO,KAAK,IAAI,EAAE,SAAS,OAAO,CAAC;AAC3D,WAAO,SAAS,KAAK,KAAK,GAAG;;AAE/B;;EAGF,MAAM,OAAO;GACX,MAAM,KAAK;GACX,aAAa,iBAAiB,KAAK,MAAM;GACzC;GACA,SAAS,aAAa,UAAU,KAAK,MAAM;GAC3C,QAAQ,YAAY,QAAQ,SAAS,KAAK,MAAM;GACjD;AAED,MAAI,CAAC,SAAS;AACZ,SAAM,kBAAkB,OAAO;IAC7B,IAAI,KAAK;IACT,GAAG;IACH,QAAQ,EAAE,MAAM,cAAc;IAC9B,UAAU,EAAE,MAAM,QAAQ;IAC1B,aAAa,EAAE,iCAAiC,GAAG;IACpD,CAAC;AACF,UAAO,QAAQ,KAAK,KAAK,GAAG;AAC5B;;AAGF,MAAI,sBAAsB,SAAS,KAAK,EAAE;AACxC,SAAM,kBAAkB,OAAO,KAAK,IAAI;IACtC,GAAG;IACH,QAAQ,EAAE,MAAM,cAAc;IAC9B,UAAU,EAAE,MAAM,QAAQ;IAC1B,aAAa,EAAE,iCAAiC,GAAG;IACpD,CAAC;AACF,UAAO,QAAQ,KAAK,KAAK,GAAG;;;AAIhC,QAAO"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { AgentService } from '../../agent/service.js';
|
|
2
2
|
import type { Config } from '../../config/schema.js';
|
|
3
|
-
import { CronService } from '../../cron/service.js';
|
|
4
3
|
import type { MessageBus } from '../../infra/bus/index.js';
|
|
5
4
|
import type { SessionStore } from '../../session/store.js';
|
|
6
5
|
export interface HeartbeatRunnerConfig {
|
|
@@ -22,7 +21,6 @@ export declare function heartbeatRunnerConfigFromConfig(cfg: Config): HeartbeatR
|
|
|
22
21
|
export interface HeartbeatServiceDeps {
|
|
23
22
|
agentService: AgentService;
|
|
24
23
|
messageBus: MessageBus;
|
|
25
|
-
cronService: CronService;
|
|
26
24
|
sessionStore: SessionStore;
|
|
27
25
|
/** Current app config (for HEARTBEAT.md path under the default agent `profile/` directory). */
|
|
28
26
|
getConfig: () => Config;
|
|
@@ -80,13 +80,6 @@ var HeartbeatService = class {
|
|
|
80
80
|
log.debug({ reasons: reasonSummary }, "Heartbeat: skip (disabled)");
|
|
81
81
|
return;
|
|
82
82
|
}
|
|
83
|
-
try {
|
|
84
|
-
const metrics = await this.deps.cronService.getMetrics();
|
|
85
|
-
log.trace({
|
|
86
|
-
runningJobs: metrics.runningJobs,
|
|
87
|
-
enabledJobs: metrics.enabledJobs
|
|
88
|
-
}, "Heartbeat: cron metrics");
|
|
89
|
-
} catch {}
|
|
90
83
|
if (cfg.activeHours && !isWithinActiveHours(cfg.activeHours)) {
|
|
91
84
|
log.debug({ reasons: reasonSummary }, "Heartbeat: skip (outside active hours)");
|
|
92
85
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","names":[],"sources":["../../../../src/gateway/heartbeat/service.ts"],"sourcesContent":["import { readFile } from 'fs/promises';\n\nimport type { AgentService } from '../../agent/service.js';\nimport type { Config } from '../../config/schema.js';\nimport { CronService } from '../../cron/service.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { SessionStore } from '../../session/store.js';\nimport { appendCronEventLines } from '../../heartbeat/event-prompt.js';\nimport { isWithinActiveHours } from '../../heartbeat/active-hours.js';\nimport { isHeartbeatContentEmpty } from '../../heartbeat/content-check.js';\nimport {\n DEFAULT_ACK_MAX_CHARS,\n stripHeartbeatToken,\n shouldSilence,\n} from '../../heartbeat/tokens.js';\nimport { createHeartbeatWake } from '../../heartbeat/wake.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { resolveHeartbeatMdPath } from '../workspace-heartbeat-path.js';\n\nconst log = createLogger('HeartbeatService');\n\nconst DEFAULT_PROMPT =\n 'Read HEARTBEAT.md if it exists. Follow it strictly. If nothing needs attention, reply HEARTBEAT_OK.';\n\nexport interface HeartbeatRunnerConfig {\n enabled: boolean;\n intervalMs: number;\n target?: string;\n targetChatId?: string;\n prompt?: string;\n ackMaxChars?: number;\n isolatedSession?: boolean;\n activeHours?: {\n start: string;\n end: string;\n timezone?: string;\n };\n}\n\nfunction mapConfigToRunner(cfg: Config | undefined): HeartbeatRunnerConfig {\n const h = cfg?.gateway?.heartbeat;\n return {\n enabled: h?.enabled ?? true,\n intervalMs: h?.intervalMs ?? 1_800_000,\n target: h?.target,\n targetChatId: h?.targetChatId,\n prompt: h?.prompt,\n ackMaxChars: h?.ackMaxChars,\n isolatedSession: h?.isolatedSession,\n activeHours: h?.activeHours,\n };\n}\n\n/** Map persisted gateway config to runner options (gateway start / reload). */\nexport function heartbeatRunnerConfigFromConfig(cfg: Config): HeartbeatRunnerConfig {\n return mapConfigToRunner(cfg);\n}\n\nexport interface HeartbeatServiceDeps {\n agentService: AgentService;\n messageBus: MessageBus;\n cronService: CronService;\n sessionStore: SessionStore;\n /** Current app config (for HEARTBEAT.md path under the default agent `profile/` directory). */\n getConfig: () => Config;\n}\n\nexport class HeartbeatService {\n private intervalId: ReturnType<typeof setInterval> | null = null;\n private wake: ReturnType<typeof createHeartbeatWake>;\n private lastHeartbeatText = '';\n private lastHeartbeatAt = 0;\n private runnerConfig: HeartbeatRunnerConfig | null = null;\n\n constructor(private deps: HeartbeatServiceDeps) {\n this.wake = createHeartbeatWake((reasons) => this.runHeartbeatOnce(reasons));\n }\n\n start(config: HeartbeatRunnerConfig): void {\n if (!config.enabled) {\n log.info('Heartbeat disabled');\n this.runnerConfig = null;\n return;\n }\n\n this.runnerConfig = config;\n log.info({ intervalMs: config.intervalMs }, 'Heartbeat timer started (interval wake)');\n\n this.intervalId = setInterval(() => {\n this.wake.request({ reason: 'interval' });\n }, config.intervalMs);\n this.intervalId.unref?.();\n }\n\n /** Cron, exec completion, manual triggers, etc. */\n requestNow(opts?: { reason?: string }): void {\n this.wake.request({ reason: opts?.reason ?? 'manual' });\n }\n\n stop(): void {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n this.wake.stop();\n this.runnerConfig = null;\n log.info('Heartbeat stopped');\n }\n\n updateConfig(config: Config): void {\n const mapped = mapConfigToRunner(config);\n this.stop();\n if (mapped.enabled) {\n this.start(mapped);\n }\n log.info('Heartbeat config updated');\n }\n\n isRunning(): boolean {\n return this.intervalId !== null;\n }\n\n private async runHeartbeatOnce(reasons: string[]): Promise<void> {\n const reasonSummary = [...new Set(reasons)].join(', ') || 'unknown';\n\n const cfg = this.runnerConfig;\n if (!cfg?.enabled) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (disabled)');\n return;\n }\n\n try {\n const metrics = await this.deps.cronService.getMetrics();\n log.trace(\n { runningJobs: metrics.runningJobs, enabledJobs: metrics.enabledJobs },\n 'Heartbeat: cron metrics',\n );\n } catch {\n /* optional */\n }\n\n if (cfg.activeHours && !isWithinActiveHours(cfg.activeHours)) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (outside active hours)');\n return;\n }\n\n const heartbeatPath = resolveHeartbeatMdPath(this.deps.getConfig());\n if (!heartbeatPath) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (no HEARTBEAT path)');\n return;\n }\n let heartbeatContent: string | undefined;\n try {\n const raw = await readFile(heartbeatPath, 'utf-8');\n if (isHeartbeatContentEmpty(raw)) {\n log.debug({ path: heartbeatPath, reasons: reasonSummary }, 'Heartbeat: skip (HEARTBEAT.md empty)');\n return;\n }\n heartbeatContent = raw.trim();\n } catch {\n log.debug({ path: heartbeatPath, reasons: reasonSummary }, 'Heartbeat: HEARTBEAT.md missing; continuing');\n }\n\n const sessionKey = cfg.isolatedSession\n ? `heartbeat:isolated:${Date.now()}`\n : 'heartbeat:main';\n\n let basePrompt = (cfg.prompt?.trim() || DEFAULT_PROMPT).trim();\n if (heartbeatContent) {\n basePrompt = `${basePrompt}\\n\\n---\\nHEARTBEAT.md:\\n${heartbeatContent}\\n---`;\n }\n basePrompt = appendCronEventLines(basePrompt, reasons);\n const prompt = `${basePrompt}\\n\\nCurrent time: ${new Date().toISOString()}`;\n\n const ackMax = cfg.ackMaxChars ?? DEFAULT_ACK_MAX_CHARS;\n\n log.debug({ sessionKey, reasons: reasonSummary }, 'Heartbeat: invoking agent');\n\n // `heartbeat:main` reuses one session key; each run would otherwise append to the transcript\n // until the model rejects the request (context window exceeded). Heartbeat prompts are\n // self-contained (HEARTBEAT.md + this turn's text), so we start from an empty history.\n if (sessionKey === 'heartbeat:main') {\n try {\n await this.deps.sessionStore.saveMessages(sessionKey, [], {\n metadata: {\n sourceChannel: 'heartbeat',\n sourceChatId: 'main',\n sessionType: 'heartbeat',\n customData: { heartbeatTarget: 'main' },\n routing: {\n agentId: 'main',\n source: 'heartbeat',\n accountId: 'default',\n peerKind: 'direct',\n peerId: 'main',\n },\n },\n });\n } catch (err) {\n log.warn({ err, sessionKey }, 'Heartbeat: failed to reset main session transcript');\n }\n }\n\n let reply: string;\n try {\n reply = await this.deps.agentService.turnDispatcher.processDirect(prompt, sessionKey);\n } catch (error) {\n log.error({ err: error }, 'Heartbeat: agent call failed');\n return;\n }\n\n if (!reply?.trim()) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (empty model reply)');\n return;\n }\n\n if (shouldSilence(reply, ackMax)) {\n log.info(\n { ackMax, replyChars: reply.length, reasons: reasonSummary },\n 'Heartbeat: not sent — silent (HEARTBEAT_OK / short ack)',\n );\n return;\n }\n\n const { stripped } = stripHeartbeatToken(reply);\n const finalText = stripped || reply.trim();\n\n if (this.isDuplicate(finalText)) {\n log.info(\n { finalTextChars: finalText.length, reasons: reasonSummary },\n 'Heartbeat: not sent — duplicate within 24h',\n );\n return;\n }\n\n const target = cfg.target?.trim();\n const targetChatId = cfg.targetChatId?.trim();\n const hasDeliveryTarget = Boolean(target && targetChatId);\n\n if (hasDeliveryTarget) {\n await this.deps.messageBus.publishOutbound({\n channel: target!,\n chat_id: targetChatId!,\n content: finalText,\n type: 'message',\n });\n log.info(\n {\n reasons: reasonSummary,\n channel: target,\n chatId: targetChatId,\n contentChars: finalText.length,\n },\n 'Heartbeat: sent — outbound queued',\n );\n } else {\n log.info(\n { reasons: reasonSummary, finalTextChars: finalText.length },\n 'Heartbeat: not sent — no delivery target (set gateway.heartbeat.target + targetChatId)',\n );\n }\n\n this.lastHeartbeatText = finalText;\n this.lastHeartbeatAt = Date.now();\n }\n\n private isDuplicate(text: string): boolean {\n const DEDUP_WINDOW_MS = 24 * 60 * 60 * 1000;\n return (\n text.trim() === this.lastHeartbeatText.trim() &&\n Date.now() - this.lastHeartbeatAt < DEDUP_WINDOW_MS\n );\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service.js","names":[],"sources":["../../../../src/gateway/heartbeat/service.ts"],"sourcesContent":["import { readFile } from 'fs/promises';\n\nimport type { AgentService } from '../../agent/service.js';\nimport type { Config } from '../../config/schema.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { SessionStore } from '../../session/store.js';\nimport { appendCronEventLines } from '../../heartbeat/event-prompt.js';\nimport { isWithinActiveHours } from '../../heartbeat/active-hours.js';\nimport { isHeartbeatContentEmpty } from '../../heartbeat/content-check.js';\nimport {\n DEFAULT_ACK_MAX_CHARS,\n stripHeartbeatToken,\n shouldSilence,\n} from '../../heartbeat/tokens.js';\nimport { createHeartbeatWake } from '../../heartbeat/wake.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { resolveHeartbeatMdPath } from '../workspace-heartbeat-path.js';\n\nconst log = createLogger('HeartbeatService');\n\nconst DEFAULT_PROMPT =\n 'Read HEARTBEAT.md if it exists. Follow it strictly. If nothing needs attention, reply HEARTBEAT_OK.';\n\nexport interface HeartbeatRunnerConfig {\n enabled: boolean;\n intervalMs: number;\n target?: string;\n targetChatId?: string;\n prompt?: string;\n ackMaxChars?: number;\n isolatedSession?: boolean;\n activeHours?: {\n start: string;\n end: string;\n timezone?: string;\n };\n}\n\nfunction mapConfigToRunner(cfg: Config | undefined): HeartbeatRunnerConfig {\n const h = cfg?.gateway?.heartbeat;\n return {\n enabled: h?.enabled ?? true,\n intervalMs: h?.intervalMs ?? 1_800_000,\n target: h?.target,\n targetChatId: h?.targetChatId,\n prompt: h?.prompt,\n ackMaxChars: h?.ackMaxChars,\n isolatedSession: h?.isolatedSession,\n activeHours: h?.activeHours,\n };\n}\n\n/** Map persisted gateway config to runner options (gateway start / reload). */\nexport function heartbeatRunnerConfigFromConfig(cfg: Config): HeartbeatRunnerConfig {\n return mapConfigToRunner(cfg);\n}\n\nexport interface HeartbeatServiceDeps {\n agentService: AgentService;\n messageBus: MessageBus;\n sessionStore: SessionStore;\n /** Current app config (for HEARTBEAT.md path under the default agent `profile/` directory). */\n getConfig: () => Config;\n}\n\nexport class HeartbeatService {\n private intervalId: ReturnType<typeof setInterval> | null = null;\n private wake: ReturnType<typeof createHeartbeatWake>;\n private lastHeartbeatText = '';\n private lastHeartbeatAt = 0;\n private runnerConfig: HeartbeatRunnerConfig | null = null;\n\n constructor(private deps: HeartbeatServiceDeps) {\n this.wake = createHeartbeatWake((reasons) => this.runHeartbeatOnce(reasons));\n }\n\n start(config: HeartbeatRunnerConfig): void {\n if (!config.enabled) {\n log.info('Heartbeat disabled');\n this.runnerConfig = null;\n return;\n }\n\n this.runnerConfig = config;\n log.info({ intervalMs: config.intervalMs }, 'Heartbeat timer started (interval wake)');\n\n this.intervalId = setInterval(() => {\n this.wake.request({ reason: 'interval' });\n }, config.intervalMs);\n this.intervalId.unref?.();\n }\n\n /** Cron, exec completion, manual triggers, etc. */\n requestNow(opts?: { reason?: string }): void {\n this.wake.request({ reason: opts?.reason ?? 'manual' });\n }\n\n stop(): void {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n this.wake.stop();\n this.runnerConfig = null;\n log.info('Heartbeat stopped');\n }\n\n updateConfig(config: Config): void {\n const mapped = mapConfigToRunner(config);\n this.stop();\n if (mapped.enabled) {\n this.start(mapped);\n }\n log.info('Heartbeat config updated');\n }\n\n isRunning(): boolean {\n return this.intervalId !== null;\n }\n\n private async runHeartbeatOnce(reasons: string[]): Promise<void> {\n const reasonSummary = [...new Set(reasons)].join(', ') || 'unknown';\n\n const cfg = this.runnerConfig;\n if (!cfg?.enabled) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (disabled)');\n return;\n }\n\n if (cfg.activeHours && !isWithinActiveHours(cfg.activeHours)) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (outside active hours)');\n return;\n }\n\n const heartbeatPath = resolveHeartbeatMdPath(this.deps.getConfig());\n if (!heartbeatPath) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (no HEARTBEAT path)');\n return;\n }\n let heartbeatContent: string | undefined;\n try {\n const raw = await readFile(heartbeatPath, 'utf-8');\n if (isHeartbeatContentEmpty(raw)) {\n log.debug({ path: heartbeatPath, reasons: reasonSummary }, 'Heartbeat: skip (HEARTBEAT.md empty)');\n return;\n }\n heartbeatContent = raw.trim();\n } catch {\n log.debug({ path: heartbeatPath, reasons: reasonSummary }, 'Heartbeat: HEARTBEAT.md missing; continuing');\n }\n\n const sessionKey = cfg.isolatedSession\n ? `heartbeat:isolated:${Date.now()}`\n : 'heartbeat:main';\n\n let basePrompt = (cfg.prompt?.trim() || DEFAULT_PROMPT).trim();\n if (heartbeatContent) {\n basePrompt = `${basePrompt}\\n\\n---\\nHEARTBEAT.md:\\n${heartbeatContent}\\n---`;\n }\n basePrompt = appendCronEventLines(basePrompt, reasons);\n const prompt = `${basePrompt}\\n\\nCurrent time: ${new Date().toISOString()}`;\n\n const ackMax = cfg.ackMaxChars ?? DEFAULT_ACK_MAX_CHARS;\n\n log.debug({ sessionKey, reasons: reasonSummary }, 'Heartbeat: invoking agent');\n\n // `heartbeat:main` reuses one session key; each run would otherwise append to the transcript\n // until the model rejects the request (context window exceeded). Heartbeat prompts are\n // self-contained (HEARTBEAT.md + this turn's text), so we start from an empty history.\n if (sessionKey === 'heartbeat:main') {\n try {\n await this.deps.sessionStore.saveMessages(sessionKey, [], {\n metadata: {\n sourceChannel: 'heartbeat',\n sourceChatId: 'main',\n sessionType: 'heartbeat',\n customData: { heartbeatTarget: 'main' },\n routing: {\n agentId: 'main',\n source: 'heartbeat',\n accountId: 'default',\n peerKind: 'direct',\n peerId: 'main',\n },\n },\n });\n } catch (err) {\n log.warn({ err, sessionKey }, 'Heartbeat: failed to reset main session transcript');\n }\n }\n\n let reply: string;\n try {\n reply = await this.deps.agentService.turnDispatcher.processDirect(prompt, sessionKey);\n } catch (error) {\n log.error({ err: error }, 'Heartbeat: agent call failed');\n return;\n }\n\n if (!reply?.trim()) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (empty model reply)');\n return;\n }\n\n if (shouldSilence(reply, ackMax)) {\n log.info(\n { ackMax, replyChars: reply.length, reasons: reasonSummary },\n 'Heartbeat: not sent — silent (HEARTBEAT_OK / short ack)',\n );\n return;\n }\n\n const { stripped } = stripHeartbeatToken(reply);\n const finalText = stripped || reply.trim();\n\n if (this.isDuplicate(finalText)) {\n log.info(\n { finalTextChars: finalText.length, reasons: reasonSummary },\n 'Heartbeat: not sent — duplicate within 24h',\n );\n return;\n }\n\n const target = cfg.target?.trim();\n const targetChatId = cfg.targetChatId?.trim();\n const hasDeliveryTarget = Boolean(target && targetChatId);\n\n if (hasDeliveryTarget) {\n await this.deps.messageBus.publishOutbound({\n channel: target!,\n chat_id: targetChatId!,\n content: finalText,\n type: 'message',\n });\n log.info(\n {\n reasons: reasonSummary,\n channel: target,\n chatId: targetChatId,\n contentChars: finalText.length,\n },\n 'Heartbeat: sent — outbound queued',\n );\n } else {\n log.info(\n { reasons: reasonSummary, finalTextChars: finalText.length },\n 'Heartbeat: not sent — no delivery target (set gateway.heartbeat.target + targetChatId)',\n );\n }\n\n this.lastHeartbeatText = finalText;\n this.lastHeartbeatAt = Date.now();\n }\n\n private isDuplicate(text: string): boolean {\n const DEDUP_WINDOW_MS = 24 * 60 * 60 * 1000;\n return (\n text.trim() === this.lastHeartbeatText.trim() &&\n Date.now() - this.lastHeartbeatAt < DEDUP_WINDOW_MS\n );\n }\n}\n"],"mappings":"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"}
|
|
@@ -44,6 +44,7 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
|
|
|
44
44
|
defaultRole: string;
|
|
45
45
|
roles: Record<string, {
|
|
46
46
|
model: string;
|
|
47
|
+
fallbacks?: string[];
|
|
47
48
|
description?: string;
|
|
48
49
|
}>;
|
|
49
50
|
policy?: {
|
|
@@ -165,6 +166,7 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
|
|
|
165
166
|
defaultRole?: string;
|
|
166
167
|
roles?: Record<string, {
|
|
167
168
|
model: string;
|
|
169
|
+
fallbacks?: string[];
|
|
168
170
|
description?: string;
|
|
169
171
|
}>;
|
|
170
172
|
policy?: {
|
|
@@ -365,12 +367,6 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
|
|
|
365
367
|
dialogPolicy: unknown;
|
|
366
368
|
dialogTimeoutSeconds: number;
|
|
367
369
|
};
|
|
368
|
-
cron: {
|
|
369
|
-
enabled: boolean;
|
|
370
|
-
maxConcurrentJobs: number;
|
|
371
|
-
historyRetentionDays: number;
|
|
372
|
-
enableMetrics: boolean;
|
|
373
|
-
};
|
|
374
370
|
goals: {
|
|
375
371
|
maxTurns: number;
|
|
376
372
|
checklistMode: boolean;
|
|
@@ -401,6 +397,9 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
|
|
|
401
397
|
maxEntries: number;
|
|
402
398
|
};
|
|
403
399
|
};
|
|
400
|
+
tui: {
|
|
401
|
+
defaultAgent: string;
|
|
402
|
+
};
|
|
404
403
|
tunnel: {
|
|
405
404
|
enabled: boolean;
|
|
406
405
|
autoStart: boolean;
|
|
@@ -7,7 +7,7 @@ import { getProviderRegistry, init_plugin_registry } from "../../../providers/pl
|
|
|
7
7
|
import { getAllProviders, init_providers, isProviderConfigured } from "../../../providers/index.js";
|
|
8
8
|
import { resolveShareConfig } from "../../../share/share-config.js";
|
|
9
9
|
import { normalizeConfiguredMcpServers } from "../../../config/mcp-config-normalize.js";
|
|
10
|
-
import {
|
|
10
|
+
import { resolveGoalsConfigForWeb, resolveSessionConfigForWeb, resolveUpdateConfigForWeb } from "../../../config/web-patch.js";
|
|
11
11
|
import { GENERIC_MASKED_SECRET, maskSecretLength } from "./mask-secret-length.js";
|
|
12
12
|
import { safeToolsWebForGet } from "../../config-tools-web.js";
|
|
13
13
|
import { maskTunnelSecretForWeb } from "../../../tunnel/env.js";
|
|
@@ -174,9 +174,9 @@ async function buildSafeWebConfigPayload(service, options = {}) {
|
|
|
174
174
|
skillsStoreBaseUrl: config.gateway?.skillsStoreBaseUrl ?? "https://store.xopc.ai"
|
|
175
175
|
},
|
|
176
176
|
browser: buildSafeBrowserConfigForWeb(config.browser),
|
|
177
|
-
cron: resolveCronConfigForWeb(config),
|
|
178
177
|
goals: resolveGoalsConfigForWeb(config),
|
|
179
178
|
session: resolveSessionConfigForWeb(config),
|
|
179
|
+
tui: { defaultAgent: config.tui?.defaultAgent ?? "coder" },
|
|
180
180
|
tunnel: {
|
|
181
181
|
enabled: config.tunnel?.enabled === true,
|
|
182
182
|
autoStart: config.tunnel?.autoStart === true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-payload.js","names":["getModelsJsonPath"],"sources":["../../../../../src/gateway/hono/lib/config-payload.ts"],"sourcesContent":["import {\n listAgentEntries,\n normalizeAgentId,\n resolveDefaultAgentId,\n} from '../../../agent/agent-scope.js';\nimport {\n buildChannelCatalogForConfig,\n buildChannelCatalogFromSnapshot,\n getChannelSetupStatus,\n} from '../../../channels/catalog/channel-catalog-service.js';\nimport { normalizeConfiguredMcpServers } from '../../../config/mcp-config-normalize.js';\nimport type { Config } from '../../../config/schema.js';\nimport {\n GENERIC_MASKED_SECRET,\n maskSecretLength,\n} from './mask-secret-length.js';\nimport { maskTunnelSecretForWeb } from '../../../tunnel/env.js';\nimport { resolveShareConfig } from '../../../share/share-config.js';\nimport {\n resolveCronConfigForWeb,\n resolveGoalsConfigForWeb,\n resolveSessionConfigForWeb,\n resolveUpdateConfigForWeb,\n} from '../../../config/web-patch.js';\nimport { CredentialResolver } from '../../../auth/credentials.js';\nimport { loadModelsJson, getModelsJsonPath } from '../../../config/models-json.js';\nimport { getAllProviders, isProviderConfigured } from '../../../providers/index.js';\nimport { getProviderRegistry } from '../../../providers/plugin-registry.js';\nimport type { GatewayService } from '../../service.js';\nimport { safeToolsWebForGet } from '../../config-tools-web.js';\nimport { buildSafeProvidersConfigForWeb } from './safe-providers-config.js';\nimport { maskSttConfigForWeb, maskTtsConfigForWeb } from './safe-voice-config.js';\n\nfunction readModelsJsonProviderApiKey(providerId: string): string | undefined {\n const { config } = loadModelsJson(getModelsJsonPath());\n const entry = config.providers?.[providerId];\n const key = entry?.apiKey;\n return typeof key === 'string' && key.trim() ? key.trim() : undefined;\n}\n\n/** Length-preserving mask for LLM provider keys in GET `/api/config`. */\nasync function maskLlmProviderApiKeyForWeb(provider: string): Promise<string> {\n const resolver = new CredentialResolver();\n const stored = await resolver.revealGatewayStoredApiKey(provider);\n if (stored) return maskSecretLength(stored);\n\n const fromModelsJson = readModelsJsonProviderApiKey(provider);\n if (fromModelsJson) return maskSecretLength(fromModelsJson);\n\n // Extension plugins manage their own auth; don't show a fake gateway key mask.\n if (getProviderRegistry().has(provider)) return '';\n\n if (await isProviderConfigured(provider)) return GENERIC_MASKED_SECRET;\n return '';\n}\n\n/** MCP block for GET/PATCH `/api/config` (authenticated console editing). */\nexport function buildSafeMcpConfigForWeb(config: Config) {\n const mcp = config.mcp;\n if (!mcp) {\n return { servers: {} as Record<string, Record<string, unknown>> };\n }\n return {\n ...(mcp.sessionIdleTtlMs !== undefined ? { sessionIdleTtlMs: mcp.sessionIdleTtlMs } : {}),\n servers: normalizeConfiguredMcpServers(mcp.servers),\n };\n}\n\nfunction maskBrowserCloudConfigForWeb(cloud: unknown): Record<string, unknown> | null {\n if (!cloud || typeof cloud !== 'object' || Array.isArray(cloud)) {\n return null;\n }\n const raw = cloud as Record<string, unknown>;\n const safe: Record<string, unknown> = {};\n if (typeof raw.apiKey === 'string' && raw.apiKey.trim()) {\n safe.apiKey = maskSecretLength(raw.apiKey);\n }\n if (typeof raw.projectId === 'string' && raw.projectId.trim()) {\n safe.projectId = raw.projectId.trim();\n }\n if (typeof raw.region === 'string' && raw.region.trim()) {\n safe.region = raw.region.trim();\n }\n return Object.keys(safe).length > 0 ? safe : null;\n}\n\nexport function buildSafeBrowserConfigForWeb(browser: unknown) {\n if (!browser || typeof browser !== 'object') {\n return {\n enabled: false,\n headless: false,\n allowPrivateUrls: false,\n commandTimeout: null,\n backend: null,\n cloudProvider: null,\n cloud: null,\n cdpUrl: null,\n extension: null,\n cloakbrowser: null,\n humanize: null,\n humanPreset: null,\n dialogPolicy: null,\n dialogTimeoutSeconds: null,\n };\n }\n\n return {\n enabled: (browser as Record<string, unknown>).enabled !== false,\n headless: (browser as Record<string, unknown>).headless === true,\n allowPrivateUrls: (browser as Record<string, unknown>).allowPrivateUrls === true,\n commandTimeout:\n typeof (browser as Record<string, unknown>).commandTimeout === 'number' &&\n Number.isFinite((browser as Record<string, unknown>).commandTimeout as number)\n ? Math.floor((browser as Record<string, unknown>).commandTimeout as number)\n : null,\n backend:\n (browser as Record<string, unknown>).backend === 'local' ||\n (browser as Record<string, unknown>).backend === 'cdp' ||\n (browser as Record<string, unknown>).backend === 'cloud' ||\n (browser as Record<string, unknown>).backend === 'extension' ||\n (browser as Record<string, unknown>).backend === 'cloakbrowser'\n ? (browser as Record<string, unknown>).backend\n : null,\n cloudProvider:\n (browser as Record<string, unknown>).cloudProvider === 'browserbase' ||\n (browser as Record<string, unknown>).cloudProvider === 'browser-use'\n ? (browser as Record<string, unknown>).cloudProvider\n : null,\n cloud: maskBrowserCloudConfigForWeb((browser as Record<string, unknown>).cloud),\n cdpUrl:\n typeof (browser as Record<string, unknown>).cdpUrl === 'string' &&\n ((browser as Record<string, unknown>).cdpUrl as string).trim()\n ? ((browser as Record<string, unknown>).cdpUrl as string).trim()\n : null,\n extension:\n (browser as Record<string, unknown>).extension &&\n typeof (browser as Record<string, unknown>).extension === 'object' &&\n !Array.isArray((browser as Record<string, unknown>).extension)\n ? (browser as Record<string, unknown>).extension\n : null,\n cloakbrowser:\n (browser as Record<string, unknown>).cloakbrowser &&\n typeof (browser as Record<string, unknown>).cloakbrowser === 'object' &&\n !Array.isArray((browser as Record<string, unknown>).cloakbrowser)\n ? (browser as Record<string, unknown>).cloakbrowser\n : null,\n humanize:\n typeof (browser as Record<string, unknown>).humanize === 'boolean'\n ? (browser as Record<string, unknown>).humanize\n : null,\n humanPreset:\n (browser as Record<string, unknown>).humanPreset === 'default' ||\n (browser as Record<string, unknown>).humanPreset === 'careful'\n ? (browser as Record<string, unknown>).humanPreset\n : null,\n dialogPolicy:\n (browser as Record<string, unknown>).dialogPolicy === 'must_respond' ||\n (browser as Record<string, unknown>).dialogPolicy === 'auto_accept' ||\n (browser as Record<string, unknown>).dialogPolicy === 'auto_dismiss'\n ? (browser as Record<string, unknown>).dialogPolicy\n : null,\n dialogTimeoutSeconds:\n typeof (browser as Record<string, unknown>).dialogTimeoutSeconds === 'number' &&\n Number.isFinite((browser as Record<string, unknown>).dialogTimeoutSeconds as number)\n ? Math.floor((browser as Record<string, unknown>).dialogTimeoutSeconds as number)\n : null,\n };\n}\n\n/** Sanitized config snapshot for GET/PATCH `/api/config` (matches persisted `service.currentConfig`). */\nexport async function buildSafeWebConfigPayload(service: GatewayService, options: { locale?: string } = {}) {\n const config = service.currentConfig;\n const extensionLoader =\n typeof service.getExtensionLoader === 'function' ? service.getExtensionLoader() : undefined;\n const snapshot = extensionLoader?.getManifestSnapshot();\n const catalog = snapshot\n ? buildChannelCatalogFromSnapshot(snapshot, { locale: options.locale })\n : buildChannelCatalogForConfig(config, { locale: options.locale });\n const channelsPayload = Object.fromEntries(\n catalog.entries.map((entry) => {\n const plugin =\n typeof service.getChannelRuntimePlugin === 'function'\n ? service.getChannelRuntimePlugin(entry.id)\n : undefined;\n const channelCfgKey = entry.configPath.startsWith('channels.')\n ? entry.configPath.slice('channels.'.length).split('.')[0] || entry.id\n : entry.id;\n const channelCfg = config.channels?.[channelCfgKey] as Record<string, unknown> | undefined;\n const setupStatus = getChannelSetupStatus(config, entry.id, entry);\n return [\n entry.id,\n {\n enabled: setupStatus.enabled,\n configured: setupStatus.ready,\n setupStatus,\n config: plugin?.configSurface?.buildConfigSurface(config) ?? channelCfg ?? {},\n schema: entry.configSchema,\n uiHints: entry.uiHints,\n },\n ];\n }),\n );\n return {\n agents: {\n defaultId: resolveDefaultAgentId(config),\n list: listAgentEntries(config)\n .filter((e) => e.enabled !== false)\n .map((e) => ({\n id: normalizeAgentId(e.id),\n identity: e.identity,\n workspace: e.workspace,\n models: e.models,\n tools: e.tools,\n skills: e.skills,\n memory: e.memory,\n workflows: e.workflows,\n boundaries: e.boundaries,\n })),\n capabilityPresets: config.agents?.capabilityPresets ?? {},\n },\n channels: channelsPayload,\n providers: Object.fromEntries(\n await Promise.all(\n getAllProviders().map(async (provider) => [\n provider,\n await maskLlmProviderApiKeyForWeb(provider),\n ]),\n ),\n ),\n /** Masked `cfg.providers` for capability keys (image / STT / etc.). */\n providersConfig: buildSafeProvidersConfigForWeb(config.providers),\n gateway: {\n bind: config.gateway?.bind ?? 'loopback',\n customBindHost: config.gateway?.customBindHost,\n port: config.gateway?.port,\n corsOrigins: Array.isArray(config.gateway?.corsOrigins) ? config.gateway.corsOrigins : [],\n trustedProxies: Array.isArray(config.gateway?.trustedProxies)\n ? config.gateway.trustedProxies\n : [],\n allowRealIpFallback: config.gateway?.allowRealIpFallback === true,\n dangerouslyAllowHostHeaderOriginFallback:\n config.gateway?.dangerouslyAllowHostHeaderOriginFallback === true,\n security: {\n strict: config.gateway?.security?.strict === true,\n },\n auth: {\n mode: config.gateway?.auth?.mode || 'token',\n token: config.gateway?.auth?.token ? maskSecretLength(config.gateway.auth.token) : '',\n password: config.gateway?.auth?.password\n ? maskSecretLength(config.gateway.auth.password)\n : '',\n trustedProxy: config.gateway?.auth?.trustedProxy\n ? {\n userHeader: config.gateway.auth.trustedProxy.userHeader,\n requiredHeaders: config.gateway.auth.trustedProxy.requiredHeaders ?? [],\n allowUsers: config.gateway.auth.trustedProxy.allowUsers ?? [],\n allowLoopback: config.gateway.auth.trustedProxy.allowLoopback === true,\n }\n : undefined,\n rateLimit: {\n enabled: config.gateway?.auth?.rateLimit?.enabled !== false,\n maxAttempts:\n typeof config.gateway?.auth?.rateLimit?.maxAttempts === 'number'\n ? config.gateway.auth.rateLimit.maxAttempts\n : 5,\n windowMs:\n typeof config.gateway?.auth?.rateLimit?.windowMs === 'number'\n ? config.gateway.auth.rateLimit.windowMs\n : 900_000,\n blockDurationMs:\n typeof config.gateway?.auth?.rateLimit?.blockDurationMs === 'number'\n ? config.gateway.auth.rateLimit.blockDurationMs\n : typeof config.gateway?.auth?.rateLimit?.lockoutMs === 'number'\n ? config.gateway.auth.rateLimit.lockoutMs\n : 300_000,\n exemptLoopback: config.gateway?.auth?.rateLimit?.exemptLoopback !== false,\n },\n },\n heartbeat: {\n enabled: config.gateway?.heartbeat?.enabled,\n intervalMs: config.gateway?.heartbeat?.intervalMs,\n includeSystemPromptSection: config.gateway?.heartbeat?.includeSystemPromptSection === true,\n target: config.gateway?.heartbeat?.target,\n targetChatId: config.gateway?.heartbeat?.targetChatId,\n prompt: config.gateway?.heartbeat?.prompt,\n ackMaxChars: config.gateway?.heartbeat?.ackMaxChars,\n isolatedSession: config.gateway?.heartbeat?.isolatedSession,\n activeHours: config.gateway?.heartbeat?.activeHours,\n },\n maxSseConnections:\n typeof config.gateway?.maxSseConnections === 'number'\n ? config.gateway.maxSseConnections\n : 100,\n channelConnectDeferMode: config.gateway?.channelConnectDeferMode ?? 'auto',\n channelConnectDeferIds: Array.isArray(config.gateway?.channelConnectDeferIds)\n ? config.gateway.channelConnectDeferIds\n : [],\n channelConnectDeferSkipIds: Array.isArray(config.gateway?.channelConnectDeferSkipIds)\n ? config.gateway.channelConnectDeferSkipIds\n : [],\n share: resolveShareConfig(config.gateway?.share),\n publicUrl: config.gateway?.publicUrl ?? null,\n skillsMarketplaceProvider: config.gateway?.skillsMarketplaceProvider ?? 'skillhub',\n skillsStoreBaseUrl: config.gateway?.skillsStoreBaseUrl ?? 'https://store.xopc.ai',\n },\n browser: buildSafeBrowserConfigForWeb(config.browser),\n cron: resolveCronConfigForWeb(config),\n goals: resolveGoalsConfigForWeb(config),\n session: resolveSessionConfigForWeb(config),\n tunnel: {\n enabled: config.tunnel?.enabled === true,\n autoStart: config.tunnel?.autoStart === true,\n brokerUrl: config.tunnel?.brokerUrl ?? 'https://frp.xopc.ai/api',\n registrationSecret: config.tunnel?.registrationSecret\n ? maskTunnelSecretForWeb(config.tunnel.registrationSecret)\n : '',\n consent: config.tunnel?.consent\n ? {\n version: config.tunnel.consent.version,\n acceptedAt: config.tunnel.consent.acceptedAt,\n }\n : undefined,\n transport: { tls: 'broker_terminated' as const },\n },\n update: {\n ...resolveUpdateConfigForWeb(config),\n },\n stt: maskSttConfigForWeb(config.tools?.media?.audio),\n tts: maskTtsConfigForWeb(config.messages?.tts),\n tools: safeToolsWebForGet(config),\n bindings: Array.isArray(config.bindings) ? config.bindings : [],\n mcp: buildSafeMcpConfigForWeb(config),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config-payload.js","names":["getModelsJsonPath"],"sources":["../../../../../src/gateway/hono/lib/config-payload.ts"],"sourcesContent":["import {\n listAgentEntries,\n normalizeAgentId,\n resolveDefaultAgentId,\n} from '../../../agent/agent-scope.js';\nimport {\n buildChannelCatalogForConfig,\n buildChannelCatalogFromSnapshot,\n getChannelSetupStatus,\n} from '../../../channels/catalog/channel-catalog-service.js';\nimport { normalizeConfiguredMcpServers } from '../../../config/mcp-config-normalize.js';\nimport type { Config } from '../../../config/schema.js';\nimport {\n GENERIC_MASKED_SECRET,\n maskSecretLength,\n} from './mask-secret-length.js';\nimport { maskTunnelSecretForWeb } from '../../../tunnel/env.js';\nimport { resolveShareConfig } from '../../../share/share-config.js';\nimport {\n resolveGoalsConfigForWeb,\n resolveSessionConfigForWeb,\n resolveUpdateConfigForWeb,\n} from '../../../config/web-patch.js';\nimport { CredentialResolver } from '../../../auth/credentials.js';\nimport { loadModelsJson, getModelsJsonPath } from '../../../config/models-json.js';\nimport { getAllProviders, isProviderConfigured } from '../../../providers/index.js';\nimport { getProviderRegistry } from '../../../providers/plugin-registry.js';\nimport type { GatewayService } from '../../service.js';\nimport { safeToolsWebForGet } from '../../config-tools-web.js';\nimport { buildSafeProvidersConfigForWeb } from './safe-providers-config.js';\nimport { maskSttConfigForWeb, maskTtsConfigForWeb } from './safe-voice-config.js';\n\nfunction readModelsJsonProviderApiKey(providerId: string): string | undefined {\n const { config } = loadModelsJson(getModelsJsonPath());\n const entry = config.providers?.[providerId];\n const key = entry?.apiKey;\n return typeof key === 'string' && key.trim() ? key.trim() : undefined;\n}\n\n/** Length-preserving mask for LLM provider keys in GET `/api/config`. */\nasync function maskLlmProviderApiKeyForWeb(provider: string): Promise<string> {\n const resolver = new CredentialResolver();\n const stored = await resolver.revealGatewayStoredApiKey(provider);\n if (stored) return maskSecretLength(stored);\n\n const fromModelsJson = readModelsJsonProviderApiKey(provider);\n if (fromModelsJson) return maskSecretLength(fromModelsJson);\n\n // Extension plugins manage their own auth; don't show a fake gateway key mask.\n if (getProviderRegistry().has(provider)) return '';\n\n if (await isProviderConfigured(provider)) return GENERIC_MASKED_SECRET;\n return '';\n}\n\n/** MCP block for GET/PATCH `/api/config` (authenticated console editing). */\nexport function buildSafeMcpConfigForWeb(config: Config) {\n const mcp = config.mcp;\n if (!mcp) {\n return { servers: {} as Record<string, Record<string, unknown>> };\n }\n return {\n ...(mcp.sessionIdleTtlMs !== undefined ? { sessionIdleTtlMs: mcp.sessionIdleTtlMs } : {}),\n servers: normalizeConfiguredMcpServers(mcp.servers),\n };\n}\n\nfunction maskBrowserCloudConfigForWeb(cloud: unknown): Record<string, unknown> | null {\n if (!cloud || typeof cloud !== 'object' || Array.isArray(cloud)) {\n return null;\n }\n const raw = cloud as Record<string, unknown>;\n const safe: Record<string, unknown> = {};\n if (typeof raw.apiKey === 'string' && raw.apiKey.trim()) {\n safe.apiKey = maskSecretLength(raw.apiKey);\n }\n if (typeof raw.projectId === 'string' && raw.projectId.trim()) {\n safe.projectId = raw.projectId.trim();\n }\n if (typeof raw.region === 'string' && raw.region.trim()) {\n safe.region = raw.region.trim();\n }\n return Object.keys(safe).length > 0 ? safe : null;\n}\n\nexport function buildSafeBrowserConfigForWeb(browser: unknown) {\n if (!browser || typeof browser !== 'object') {\n return {\n enabled: false,\n headless: false,\n allowPrivateUrls: false,\n commandTimeout: null,\n backend: null,\n cloudProvider: null,\n cloud: null,\n cdpUrl: null,\n extension: null,\n cloakbrowser: null,\n humanize: null,\n humanPreset: null,\n dialogPolicy: null,\n dialogTimeoutSeconds: null,\n };\n }\n\n return {\n enabled: (browser as Record<string, unknown>).enabled !== false,\n headless: (browser as Record<string, unknown>).headless === true,\n allowPrivateUrls: (browser as Record<string, unknown>).allowPrivateUrls === true,\n commandTimeout:\n typeof (browser as Record<string, unknown>).commandTimeout === 'number' &&\n Number.isFinite((browser as Record<string, unknown>).commandTimeout as number)\n ? Math.floor((browser as Record<string, unknown>).commandTimeout as number)\n : null,\n backend:\n (browser as Record<string, unknown>).backend === 'local' ||\n (browser as Record<string, unknown>).backend === 'cdp' ||\n (browser as Record<string, unknown>).backend === 'cloud' ||\n (browser as Record<string, unknown>).backend === 'extension' ||\n (browser as Record<string, unknown>).backend === 'cloakbrowser'\n ? (browser as Record<string, unknown>).backend\n : null,\n cloudProvider:\n (browser as Record<string, unknown>).cloudProvider === 'browserbase' ||\n (browser as Record<string, unknown>).cloudProvider === 'browser-use'\n ? (browser as Record<string, unknown>).cloudProvider\n : null,\n cloud: maskBrowserCloudConfigForWeb((browser as Record<string, unknown>).cloud),\n cdpUrl:\n typeof (browser as Record<string, unknown>).cdpUrl === 'string' &&\n ((browser as Record<string, unknown>).cdpUrl as string).trim()\n ? ((browser as Record<string, unknown>).cdpUrl as string).trim()\n : null,\n extension:\n (browser as Record<string, unknown>).extension &&\n typeof (browser as Record<string, unknown>).extension === 'object' &&\n !Array.isArray((browser as Record<string, unknown>).extension)\n ? (browser as Record<string, unknown>).extension\n : null,\n cloakbrowser:\n (browser as Record<string, unknown>).cloakbrowser &&\n typeof (browser as Record<string, unknown>).cloakbrowser === 'object' &&\n !Array.isArray((browser as Record<string, unknown>).cloakbrowser)\n ? (browser as Record<string, unknown>).cloakbrowser\n : null,\n humanize:\n typeof (browser as Record<string, unknown>).humanize === 'boolean'\n ? (browser as Record<string, unknown>).humanize\n : null,\n humanPreset:\n (browser as Record<string, unknown>).humanPreset === 'default' ||\n (browser as Record<string, unknown>).humanPreset === 'careful'\n ? (browser as Record<string, unknown>).humanPreset\n : null,\n dialogPolicy:\n (browser as Record<string, unknown>).dialogPolicy === 'must_respond' ||\n (browser as Record<string, unknown>).dialogPolicy === 'auto_accept' ||\n (browser as Record<string, unknown>).dialogPolicy === 'auto_dismiss'\n ? (browser as Record<string, unknown>).dialogPolicy\n : null,\n dialogTimeoutSeconds:\n typeof (browser as Record<string, unknown>).dialogTimeoutSeconds === 'number' &&\n Number.isFinite((browser as Record<string, unknown>).dialogTimeoutSeconds as number)\n ? Math.floor((browser as Record<string, unknown>).dialogTimeoutSeconds as number)\n : null,\n };\n}\n\n/** Sanitized config snapshot for GET/PATCH `/api/config` (matches persisted `service.currentConfig`). */\nexport async function buildSafeWebConfigPayload(service: GatewayService, options: { locale?: string } = {}) {\n const config = service.currentConfig;\n const extensionLoader =\n typeof service.getExtensionLoader === 'function' ? service.getExtensionLoader() : undefined;\n const snapshot = extensionLoader?.getManifestSnapshot();\n const catalog = snapshot\n ? buildChannelCatalogFromSnapshot(snapshot, { locale: options.locale })\n : buildChannelCatalogForConfig(config, { locale: options.locale });\n const channelsPayload = Object.fromEntries(\n catalog.entries.map((entry) => {\n const plugin =\n typeof service.getChannelRuntimePlugin === 'function'\n ? service.getChannelRuntimePlugin(entry.id)\n : undefined;\n const channelCfgKey = entry.configPath.startsWith('channels.')\n ? entry.configPath.slice('channels.'.length).split('.')[0] || entry.id\n : entry.id;\n const channelCfg = config.channels?.[channelCfgKey] as Record<string, unknown> | undefined;\n const setupStatus = getChannelSetupStatus(config, entry.id, entry);\n return [\n entry.id,\n {\n enabled: setupStatus.enabled,\n configured: setupStatus.ready,\n setupStatus,\n config: plugin?.configSurface?.buildConfigSurface(config) ?? channelCfg ?? {},\n schema: entry.configSchema,\n uiHints: entry.uiHints,\n },\n ];\n }),\n );\n return {\n agents: {\n defaultId: resolveDefaultAgentId(config),\n list: listAgentEntries(config)\n .filter((e) => e.enabled !== false)\n .map((e) => ({\n id: normalizeAgentId(e.id),\n identity: e.identity,\n workspace: e.workspace,\n models: e.models,\n tools: e.tools,\n skills: e.skills,\n memory: e.memory,\n workflows: e.workflows,\n boundaries: e.boundaries,\n })),\n capabilityPresets: config.agents?.capabilityPresets ?? {},\n },\n channels: channelsPayload,\n providers: Object.fromEntries(\n await Promise.all(\n getAllProviders().map(async (provider) => [\n provider,\n await maskLlmProviderApiKeyForWeb(provider),\n ]),\n ),\n ),\n /** Masked `cfg.providers` for capability keys (image / STT / etc.). */\n providersConfig: buildSafeProvidersConfigForWeb(config.providers),\n gateway: {\n bind: config.gateway?.bind ?? 'loopback',\n customBindHost: config.gateway?.customBindHost,\n port: config.gateway?.port,\n corsOrigins: Array.isArray(config.gateway?.corsOrigins) ? config.gateway.corsOrigins : [],\n trustedProxies: Array.isArray(config.gateway?.trustedProxies)\n ? config.gateway.trustedProxies\n : [],\n allowRealIpFallback: config.gateway?.allowRealIpFallback === true,\n dangerouslyAllowHostHeaderOriginFallback:\n config.gateway?.dangerouslyAllowHostHeaderOriginFallback === true,\n security: {\n strict: config.gateway?.security?.strict === true,\n },\n auth: {\n mode: config.gateway?.auth?.mode || 'token',\n token: config.gateway?.auth?.token ? maskSecretLength(config.gateway.auth.token) : '',\n password: config.gateway?.auth?.password\n ? maskSecretLength(config.gateway.auth.password)\n : '',\n trustedProxy: config.gateway?.auth?.trustedProxy\n ? {\n userHeader: config.gateway.auth.trustedProxy.userHeader,\n requiredHeaders: config.gateway.auth.trustedProxy.requiredHeaders ?? [],\n allowUsers: config.gateway.auth.trustedProxy.allowUsers ?? [],\n allowLoopback: config.gateway.auth.trustedProxy.allowLoopback === true,\n }\n : undefined,\n rateLimit: {\n enabled: config.gateway?.auth?.rateLimit?.enabled !== false,\n maxAttempts:\n typeof config.gateway?.auth?.rateLimit?.maxAttempts === 'number'\n ? config.gateway.auth.rateLimit.maxAttempts\n : 5,\n windowMs:\n typeof config.gateway?.auth?.rateLimit?.windowMs === 'number'\n ? config.gateway.auth.rateLimit.windowMs\n : 900_000,\n blockDurationMs:\n typeof config.gateway?.auth?.rateLimit?.blockDurationMs === 'number'\n ? config.gateway.auth.rateLimit.blockDurationMs\n : typeof config.gateway?.auth?.rateLimit?.lockoutMs === 'number'\n ? config.gateway.auth.rateLimit.lockoutMs\n : 300_000,\n exemptLoopback: config.gateway?.auth?.rateLimit?.exemptLoopback !== false,\n },\n },\n heartbeat: {\n enabled: config.gateway?.heartbeat?.enabled,\n intervalMs: config.gateway?.heartbeat?.intervalMs,\n includeSystemPromptSection: config.gateway?.heartbeat?.includeSystemPromptSection === true,\n target: config.gateway?.heartbeat?.target,\n targetChatId: config.gateway?.heartbeat?.targetChatId,\n prompt: config.gateway?.heartbeat?.prompt,\n ackMaxChars: config.gateway?.heartbeat?.ackMaxChars,\n isolatedSession: config.gateway?.heartbeat?.isolatedSession,\n activeHours: config.gateway?.heartbeat?.activeHours,\n },\n maxSseConnections:\n typeof config.gateway?.maxSseConnections === 'number'\n ? config.gateway.maxSseConnections\n : 100,\n channelConnectDeferMode: config.gateway?.channelConnectDeferMode ?? 'auto',\n channelConnectDeferIds: Array.isArray(config.gateway?.channelConnectDeferIds)\n ? config.gateway.channelConnectDeferIds\n : [],\n channelConnectDeferSkipIds: Array.isArray(config.gateway?.channelConnectDeferSkipIds)\n ? config.gateway.channelConnectDeferSkipIds\n : [],\n share: resolveShareConfig(config.gateway?.share),\n publicUrl: config.gateway?.publicUrl ?? null,\n skillsMarketplaceProvider: config.gateway?.skillsMarketplaceProvider ?? 'skillhub',\n skillsStoreBaseUrl: config.gateway?.skillsStoreBaseUrl ?? 'https://store.xopc.ai',\n },\n browser: buildSafeBrowserConfigForWeb(config.browser),\n goals: resolveGoalsConfigForWeb(config),\n session: resolveSessionConfigForWeb(config),\n tui: {\n defaultAgent: config.tui?.defaultAgent ?? 'coder',\n },\n tunnel: {\n enabled: config.tunnel?.enabled === true,\n autoStart: config.tunnel?.autoStart === true,\n brokerUrl: config.tunnel?.brokerUrl ?? 'https://frp.xopc.ai/api',\n registrationSecret: config.tunnel?.registrationSecret\n ? maskTunnelSecretForWeb(config.tunnel.registrationSecret)\n : '',\n consent: config.tunnel?.consent\n ? {\n version: config.tunnel.consent.version,\n acceptedAt: config.tunnel.consent.acceptedAt,\n }\n : undefined,\n transport: { tls: 'broker_terminated' as const },\n },\n update: {\n ...resolveUpdateConfigForWeb(config),\n },\n stt: maskSttConfigForWeb(config.tools?.media?.audio),\n tts: maskTtsConfigForWeb(config.messages?.tts),\n tools: safeToolsWebForGet(config),\n bindings: Array.isArray(config.bindings) ? config.bindings : [],\n mcp: buildSafeMcpConfigForWeb(config),\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.js","names":[],"sources":["../../../../../src/gateway/hono/routes/agents.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { AgentModelsSchema, type Config, parseModelRef } from '../../../config/schema.js';\nimport { MemoryPolicySchema, ToolPolicySetSchema } from '../../../agent-manifest/schema.js';\nimport { getVoiceModelsConfig } from '../../../config/voice.js';\nimport {\n isProviderConfigured,\n resolveModel,\n} from '../../../providers/index.js';\nimport { normalizeAgentId } from '../../../agent/agent-scope.js';\nimport {\n deleteAgentAvatarFile,\n finalizeCreateAgentDirs,\n getGatewayAgentEffectiveManifest,\n listAgentProfileFiles,\n listGatewayAgents,\n prepareCreateAgent,\n prepareDeleteAgent,\n prepareUpdateAgent,\n readAgentAvatarFile,\n readAgentProfileFile,\n readUserProfileFile,\n runAfterDeletePurge,\n writeAgentAvatarFromBase64,\n writeAgentProfileFile,\n writeUserProfileFile,\n type CreateAgentBody,\n} from '../../agents-admin.js';\nimport {\n resolveImageGenerationCapabilities,\n resolveImageUnderstandingCapabilities,\n} from '../../image-capabilities.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nfunction parseProfileFiles(raw: unknown): Record<string, string> | undefined | { error: string } {\n if (raw === undefined) {\n return undefined;\n }\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'profileFiles must be an object' };\n }\n const profileFiles: Record<string, string> = {};\n for (const [name, content] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof content !== 'string') {\n return { error: `profileFiles[\"${name}\"] must be a string` };\n }\n profileFiles[name] = content;\n }\n return profileFiles;\n}\n\nfunction isParseError(value: unknown): value is { error: string } {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'error' in value &&\n typeof (value as { error: string }).error === 'string'\n );\n}\n\nfunction parseCreateAgentBody(raw: unknown): CreateAgentBody | { error: string } {\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'each agent must be an object' };\n }\n const body = raw as Record<string, unknown>;\n if (Object.hasOwn(body, 'model')) {\n return { error: 'model is not supported; use models.defaultRole and models.roles' };\n }\n if (Object.hasOwn(body, 'toolsDisable')) {\n return { error: 'toolsDisable was removed; use tools.builtin policies' };\n }\n if (Object.hasOwn(body, 'typedModels')) {\n return { error: 'typedModels is not supported; use models.roles' };\n }\n if (Object.hasOwn(body, 'agentDir')) {\n return { error: 'agentDir was removed from agent manifests' };\n }\n if (Object.hasOwn(body, 'name')) {\n return { error: 'name is not supported; write IDENTITY.md in profileFiles' };\n }\n if (Object.hasOwn(body, 'description')) {\n return { error: 'description is not supported; write IDENTITY.md in profileFiles' };\n }\n const workspace = typeof body.workspace === 'string' ? body.workspace : '';\n const models = Object.hasOwn(body, 'models')\n ? AgentModelsSchema.safeParse(body.models)\n : undefined;\n if (models && !models.success) {\n return { error: `models ${models.error.issues[0]?.message ?? 'is invalid'}` };\n }\n const id = typeof body.id === 'string' ? body.id : undefined;\n const skills = Object.hasOwn(body, 'skills')\n ? Array.isArray(body.skills)\n ? body.skills.map((x: unknown) => String(x).trim()).filter(Boolean)\n : null\n : undefined;\n if (skills === null) {\n return { error: 'skills must be an array' };\n }\n const toolsRaw = Object.hasOwn(body, 'tools') ? body.tools : undefined;\n let tools: CreateAgentBody['tools'] | undefined;\n if (toolsRaw !== undefined) {\n if (toolsRaw === null || typeof toolsRaw !== 'object' || Array.isArray(toolsRaw)) {\n return { error: 'tools must be an object' };\n }\n const parsedTools = ToolPolicySetSchema.safeParse(toolsRaw);\n if (!parsedTools.success) {\n return { error: `tools ${parsedTools.error.issues[0]?.message ?? 'is invalid'}` };\n }\n tools = parsedTools.data;\n }\n let profileFiles: Record<string, string> | undefined;\n if (Object.hasOwn(body, 'profileFiles')) {\n const parsed = parseProfileFiles(body.profileFiles);\n if (isParseError(parsed)) {\n return parsed;\n }\n profileFiles = parsed;\n }\n if (!profileFiles?.['IDENTITY.md'] && typeof body.cloneFrom !== 'string') {\n return { error: 'profileFiles.IDENTITY.md is required' };\n }\n const cloneFrom = typeof body.cloneFrom === 'string' ? body.cloneFrom : undefined;\n return {\n workspace,\n ...(models && models.data !== undefined ? { models: models.data } : {}),\n ...(id !== undefined ? { id } : {}),\n ...(skills !== undefined ? { skills } : {}),\n ...(tools !== undefined ? { tools } : {}),\n ...(profileFiles !== undefined ? { profileFiles } : {}),\n ...(cloneFrom !== undefined ? { cloneFrom } : {}),\n };\n}\n\ntype PatchModels = {\n defaultRole?: string | null;\n roles?: Record<string, { model: string; description?: string }>;\n};\n\nfunction parsePatchModels(raw: unknown): PatchModels | null | undefined | { error: string } {\n if (raw === undefined) {\n return undefined;\n }\n if (raw === null) {\n return null;\n }\n if (typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'models must be an object or null' };\n }\n const body = raw as Record<string, unknown>;\n const out: PatchModels = {};\n if (Object.hasOwn(body, 'defaultRole')) {\n out.defaultRole = body.defaultRole === null ? null : String(body.defaultRole ?? '').trim();\n }\n if (Object.hasOwn(body, 'roles')) {\n if (body.roles === null) {\n return { error: 'models.roles must be an object' };\n } else {\n const parsed = AgentModelsSchema.safeParse({ roles: body.roles });\n if (!parsed.success) {\n return { error: `models.roles ${parsed.error.issues[0]?.message ?? 'is invalid'}` };\n }\n out.roles = parsed.data?.roles;\n }\n }\n return out;\n}\n\nexport function registerAgentsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service, strictRateLimitMiddleware } = deps;\n\n authenticated.get('/api/agents', async (c) => {\n const cfg = service.currentConfig as Config;\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const payload = await listGatewayAgents(cfg, { locale });\n return c.json({ ok: true, payload });\n });\n\n authenticated.get('/api/user-profile', async (c) => {\n const res = await readUserProfileFile();\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.put('/api/user-profile', strictRateLimitMiddleware, async (c) => {\n let content = '';\n try {\n const body = (await c.req.json()) as { content?: unknown };\n content = typeof body.content === 'string' ? body.content : '';\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const res = await writeUserProfileFile(content);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.post('/api/agents', strictRateLimitMiddleware, async (c) => {\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const parsed = parseCreateAgentBody(body);\n if ('error' in parsed) {\n return c.json({ ok: false, error: { message: parsed.error } }, 400);\n }\n const prep = prepareCreateAgent(service.currentConfig as Config, parsed);\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const { nextConfig, agentId } = prep.data;\n const save = await service.saveConfig(nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n const finalized = await finalizeCreateAgentDirs(service.currentConfig as Config, agentId, {\n ...(parsed.profileFiles !== undefined ? { profileFiles: parsed.profileFiles } : {}),\n ...(parsed.cloneFrom ? { cloneFrom: parsed.cloneFrom } : {}),\n });\n if (finalized.ok === false) {\n return c.json({ ok: false, error: { message: finalized.error } }, finalized.status ?? 400);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({\n ok: true,\n payload: {\n agentId,\n agents: agentsPayload,\n },\n });\n });\n\n authenticated.get('/api/agents/:id/effective-manifest', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = getGatewayAgentEffectiveManifest(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.patch('/api/agents/:id', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n if (Object.hasOwn(body, 'model')) {\n return c.json({ ok: false, error: { message: 'model is not supported; use models.defaultRole and models.roles' } }, 400);\n }\n if (Object.hasOwn(body, 'typedModels')) {\n return c.json({ ok: false, error: { message: 'typedModels is not supported; use models.roles' } }, 400);\n }\n if (Object.hasOwn(body, 'toolsDisable')) {\n return c.json({ ok: false, error: { message: 'toolsDisable was removed; use tools.builtin policies' } }, 400);\n }\n if (Object.hasOwn(body, 'agentDir')) {\n return c.json({ ok: false, error: { message: 'agentDir was removed from agent manifests' } }, 400);\n }\n if (Object.hasOwn(body, 'name')) {\n return c.json({ ok: false, error: { message: 'name is not supported; edit IDENTITY.md' } }, 400);\n }\n if (Object.hasOwn(body, 'description')) {\n return c.json({ ok: false, error: { message: 'description is not supported; edit IDENTITY.md' } }, 400);\n }\n const skillsPatch =\n body.skills === null\n ? null\n : Array.isArray(body.skills)\n ? body.skills.map((x: unknown) => String(x).trim()).filter(Boolean)\n : undefined;\n const extendsPatch = Object.hasOwn(body, 'extends')\n ? Array.isArray(body.extends)\n ? body.extends.map((x: unknown) => String(x).trim()).filter(Boolean)\n : undefined\n : undefined;\n if (Object.hasOwn(body, 'extends') && extendsPatch === undefined) {\n return c.json({ ok: false, error: { message: 'extends must be an array' } }, 400);\n }\n let toolsPatch: CreateAgentBody['tools'] | null | undefined;\n if (Object.hasOwn(body, 'tools')) {\n if (body.tools === null) {\n toolsPatch = null;\n } else if (typeof body.tools === 'object' && !Array.isArray(body.tools)) {\n const parsedTools = ToolPolicySetSchema.safeParse(body.tools);\n if (!parsedTools.success) {\n return c.json({ ok: false, error: { message: `tools ${parsedTools.error.issues[0]?.message ?? 'is invalid'}` } }, 400);\n }\n toolsPatch = parsedTools.data;\n } else {\n return c.json({ ok: false, error: { message: 'tools must be an object or null' } }, 400);\n }\n }\n const modelsPatch = Object.hasOwn(body, 'models') ? parsePatchModels(body.models) : undefined;\n if (isParseError(modelsPatch)) {\n return c.json({ ok: false, error: { message: modelsPatch.error } }, 400);\n }\n let memoryPatch: Config['agents']['list'][number]['memory'] | undefined;\n if (Object.hasOwn(body, 'memory')) {\n const parsedMemory = MemoryPolicySchema.safeParse(body.memory);\n if (!parsedMemory.success) {\n return c.json({ ok: false, error: { message: `memory ${parsedMemory.error.issues[0]?.message ?? 'is invalid'}` } }, 400);\n }\n memoryPatch = parsedMemory.data;\n }\n\n const prep = prepareUpdateAgent(service.currentConfig as Config, id, {\n workspace: typeof body.workspace === 'string' ? body.workspace : undefined,\n ...(extendsPatch !== undefined ? { extends: extendsPatch } : {}),\n ...(modelsPatch !== undefined ? { models: modelsPatch } : {}),\n setDefault: body.setDefault === true,\n ...(skillsPatch !== undefined ? { skills: skillsPatch } : {}),\n ...(toolsPatch !== undefined ? { tools: toolsPatch } : {}),\n ...(memoryPatch !== undefined ? { memory: memoryPatch } : {}),\n });\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const save = await service.saveConfig(prep.data.nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({ ok: true, payload: agentsPayload });\n });\n\n authenticated.delete('/api/agents/:id', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const purge = c.req.query('purge') === '1' || c.req.query('purge') === 'true';\n const prep = prepareDeleteAgent(service.currentConfig as Config, id);\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const { nextConfig, agentId } = prep.data;\n const save = await service.saveConfig(nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n if (purge) {\n await runAfterDeletePurge(service.currentConfig as Config, agentId);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({\n ok: true,\n payload: { agentId, purged: purge, agents: agentsPayload },\n });\n });\n\n authenticated.get('/api/agents/:id/avatar', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await readAgentAvatarFile(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return new Response(res.data.buffer, {\n status: 200,\n headers: {\n 'Content-Type': res.data.contentType,\n 'Cache-Control': 'private, max-age=3600',\n },\n });\n });\n\n authenticated.put('/api/agents/:id/avatar', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const base64 = typeof body.base64 === 'string' ? body.base64 : '';\n const mimeType = typeof body.mimeType === 'string' ? body.mimeType : '';\n const res = await writeAgentAvatarFromBase64(service.currentConfig as Config, id, base64, mimeType);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId } });\n });\n\n authenticated.delete('/api/agents/:id/avatar', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await deleteAgentAvatarFile(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId } });\n });\n\n authenticated.get('/api/agents/:id/files', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await listAgentProfileFiles(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.get('/api/agents/:id/files/:name', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const name = decodeURIComponent(c.req.param('name') ?? '');\n const res = await readAgentProfileFile(service.currentConfig as Config, id, name);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId, name, content: res.data.content } });\n });\n\n authenticated.put('/api/agents/:id/files/:name', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const name = decodeURIComponent(c.req.param('name') ?? '');\n let content = '';\n try {\n const body = (await c.req.json()) as { content?: unknown };\n content = typeof body.content === 'string' ? body.content : '';\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const res = await writeAgentProfileFile(service.currentConfig as Config, id, name, content);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId, name } });\n });\n\n // GET /api/voice/models - Get available STT/TTS models\n authenticated.get('/api/voice/models', (c) => {\n const models = getVoiceModelsConfig();\n return c.json({ ok: true, payload: { models } });\n });\n\n authenticated.get('/api/image/capabilities', async (c) => {\n const config = service.currentConfig as Config;\n const imageGenerationProviders = await resolveImageGenerationCapabilities(config);\n const imageUnderstandingProviders = await resolveImageUnderstandingCapabilities(config);\n return c.json({\n ok: true,\n payload: {\n current: {\n imageModel: null,\n imageModelFallbacks: [],\n imageGenerationModel: null,\n imageGenerationModelFallbacks: [],\n mediaMaxMb: null,\n },\n imageGeneration: { providers: imageGenerationProviders },\n imageUnderstanding: { providers: imageUnderstandingProviders },\n },\n });\n });\n\n authenticated.post('/api/image/validate-model', strictRateLimitMiddleware, async (c) => {\n let body: { modelRef?: unknown };\n try {\n body = (await c.req.json()) as { modelRef?: unknown };\n } catch {\n return c.json({ ok: false, error: 'Invalid JSON' }, 400);\n }\n const modelRef = body.modelRef;\n if (!modelRef || typeof modelRef !== 'string') {\n return c.json({ ok: false, error: 'modelRef is required' }, 400);\n }\n\n const parsed = parseModelRef(modelRef);\n if (!parsed) {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'invalid_format',\n message: 'Model reference must be in \"provider/model\" format',\n },\n });\n }\n\n const configured = await isProviderConfigured(parsed.provider);\n if (!configured) {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'provider_not_configured',\n message: `Provider \"${parsed.provider}\" is not configured. Set the API key first.`,\n provider: parsed.provider,\n },\n });\n }\n\n try {\n resolveModel(modelRef);\n } catch {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'model_not_found',\n message: `Model not found in registry: ${modelRef}`,\n provider: parsed.provider,\n model: parsed.model,\n },\n });\n }\n\n return c.json({\n ok: true,\n payload: {\n valid: true,\n provider: parsed.provider,\n model: parsed.model,\n },\n });\n });\n\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agents.js","names":[],"sources":["../../../../../src/gateway/hono/routes/agents.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { AgentModelsSchema, type Config, parseModelRef } from '../../../config/schema.js';\nimport { MemoryPolicySchema, ToolPolicySetSchema } from '../../../agent-manifest/schema.js';\nimport { getVoiceModelsConfig } from '../../../config/voice.js';\nimport {\n isProviderConfigured,\n resolveModel,\n} from '../../../providers/index.js';\nimport { normalizeAgentId } from '../../../agent/agent-scope.js';\nimport {\n deleteAgentAvatarFile,\n finalizeCreateAgentDirs,\n getGatewayAgentEffectiveManifest,\n listAgentProfileFiles,\n listGatewayAgents,\n prepareCreateAgent,\n prepareDeleteAgent,\n prepareUpdateAgent,\n readAgentAvatarFile,\n readAgentProfileFile,\n readUserProfileFile,\n runAfterDeletePurge,\n writeAgentAvatarFromBase64,\n writeAgentProfileFile,\n writeUserProfileFile,\n type CreateAgentBody,\n} from '../../agents-admin.js';\nimport {\n resolveImageGenerationCapabilities,\n resolveImageUnderstandingCapabilities,\n} from '../../image-capabilities.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nfunction parseProfileFiles(raw: unknown): Record<string, string> | undefined | { error: string } {\n if (raw === undefined) {\n return undefined;\n }\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'profileFiles must be an object' };\n }\n const profileFiles: Record<string, string> = {};\n for (const [name, content] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof content !== 'string') {\n return { error: `profileFiles[\"${name}\"] must be a string` };\n }\n profileFiles[name] = content;\n }\n return profileFiles;\n}\n\nfunction isParseError(value: unknown): value is { error: string } {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'error' in value &&\n typeof (value as { error: string }).error === 'string'\n );\n}\n\nfunction parseCreateAgentBody(raw: unknown): CreateAgentBody | { error: string } {\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'each agent must be an object' };\n }\n const body = raw as Record<string, unknown>;\n if (Object.hasOwn(body, 'model')) {\n return { error: 'model is not supported; use models.defaultRole and models.roles' };\n }\n if (Object.hasOwn(body, 'toolsDisable')) {\n return { error: 'toolsDisable was removed; use tools.builtin policies' };\n }\n if (Object.hasOwn(body, 'typedModels')) {\n return { error: 'typedModels is not supported; use models.roles' };\n }\n if (Object.hasOwn(body, 'agentDir')) {\n return { error: 'agentDir was removed from agent manifests' };\n }\n if (Object.hasOwn(body, 'name')) {\n return { error: 'name is not supported; write IDENTITY.md in profileFiles' };\n }\n if (Object.hasOwn(body, 'description')) {\n return { error: 'description is not supported; write IDENTITY.md in profileFiles' };\n }\n const workspace = typeof body.workspace === 'string' ? body.workspace : '';\n const models = Object.hasOwn(body, 'models')\n ? AgentModelsSchema.safeParse(body.models)\n : undefined;\n if (models && !models.success) {\n return { error: `models ${models.error.issues[0]?.message ?? 'is invalid'}` };\n }\n const id = typeof body.id === 'string' ? body.id : undefined;\n const skills = Object.hasOwn(body, 'skills')\n ? Array.isArray(body.skills)\n ? body.skills.map((x: unknown) => String(x).trim()).filter(Boolean)\n : null\n : undefined;\n if (skills === null) {\n return { error: 'skills must be an array' };\n }\n const toolsRaw = Object.hasOwn(body, 'tools') ? body.tools : undefined;\n let tools: CreateAgentBody['tools'] | undefined;\n if (toolsRaw !== undefined) {\n if (toolsRaw === null || typeof toolsRaw !== 'object' || Array.isArray(toolsRaw)) {\n return { error: 'tools must be an object' };\n }\n const parsedTools = ToolPolicySetSchema.safeParse(toolsRaw);\n if (!parsedTools.success) {\n return { error: `tools ${parsedTools.error.issues[0]?.message ?? 'is invalid'}` };\n }\n tools = parsedTools.data;\n }\n let profileFiles: Record<string, string> | undefined;\n if (Object.hasOwn(body, 'profileFiles')) {\n const parsed = parseProfileFiles(body.profileFiles);\n if (isParseError(parsed)) {\n return parsed;\n }\n profileFiles = parsed;\n }\n if (!profileFiles?.['IDENTITY.md'] && typeof body.cloneFrom !== 'string') {\n return { error: 'profileFiles.IDENTITY.md is required' };\n }\n const cloneFrom = typeof body.cloneFrom === 'string' ? body.cloneFrom : undefined;\n return {\n workspace,\n ...(models && models.data !== undefined ? { models: models.data } : {}),\n ...(id !== undefined ? { id } : {}),\n ...(skills !== undefined ? { skills } : {}),\n ...(tools !== undefined ? { tools } : {}),\n ...(profileFiles !== undefined ? { profileFiles } : {}),\n ...(cloneFrom !== undefined ? { cloneFrom } : {}),\n };\n}\n\ntype PatchModels = {\n defaultRole?: string | null;\n roles?: Record<string, { model: string; fallbacks?: string[]; description?: string }>;\n};\n\nfunction parsePatchModels(raw: unknown): PatchModels | null | undefined | { error: string } {\n if (raw === undefined) {\n return undefined;\n }\n if (raw === null) {\n return null;\n }\n if (typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'models must be an object or null' };\n }\n const body = raw as Record<string, unknown>;\n const out: PatchModels = {};\n if (Object.hasOwn(body, 'defaultRole')) {\n out.defaultRole = body.defaultRole === null ? null : String(body.defaultRole ?? '').trim();\n }\n if (Object.hasOwn(body, 'roles')) {\n if (body.roles === null) {\n return { error: 'models.roles must be an object' };\n } else {\n const parsed = AgentModelsSchema.safeParse({ roles: body.roles });\n if (!parsed.success) {\n return { error: `models.roles ${parsed.error.issues[0]?.message ?? 'is invalid'}` };\n }\n out.roles = parsed.data?.roles;\n }\n }\n return out;\n}\n\nexport function registerAgentsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service, strictRateLimitMiddleware } = deps;\n\n authenticated.get('/api/agents', async (c) => {\n const cfg = service.currentConfig as Config;\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const payload = await listGatewayAgents(cfg, { locale });\n return c.json({ ok: true, payload });\n });\n\n authenticated.get('/api/user-profile', async (c) => {\n const res = await readUserProfileFile();\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.put('/api/user-profile', strictRateLimitMiddleware, async (c) => {\n let content = '';\n try {\n const body = (await c.req.json()) as { content?: unknown };\n content = typeof body.content === 'string' ? body.content : '';\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const res = await writeUserProfileFile(content);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.post('/api/agents', strictRateLimitMiddleware, async (c) => {\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const parsed = parseCreateAgentBody(body);\n if ('error' in parsed) {\n return c.json({ ok: false, error: { message: parsed.error } }, 400);\n }\n const prep = prepareCreateAgent(service.currentConfig as Config, parsed);\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const { nextConfig, agentId } = prep.data;\n const save = await service.saveConfig(nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n const finalized = await finalizeCreateAgentDirs(service.currentConfig as Config, agentId, {\n ...(parsed.profileFiles !== undefined ? { profileFiles: parsed.profileFiles } : {}),\n ...(parsed.cloneFrom ? { cloneFrom: parsed.cloneFrom } : {}),\n });\n if (finalized.ok === false) {\n return c.json({ ok: false, error: { message: finalized.error } }, finalized.status ?? 400);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({\n ok: true,\n payload: {\n agentId,\n agents: agentsPayload,\n },\n });\n });\n\n authenticated.get('/api/agents/:id/effective-manifest', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = getGatewayAgentEffectiveManifest(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.patch('/api/agents/:id', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n if (Object.hasOwn(body, 'model')) {\n return c.json({ ok: false, error: { message: 'model is not supported; use models.defaultRole and models.roles' } }, 400);\n }\n if (Object.hasOwn(body, 'typedModels')) {\n return c.json({ ok: false, error: { message: 'typedModels is not supported; use models.roles' } }, 400);\n }\n if (Object.hasOwn(body, 'toolsDisable')) {\n return c.json({ ok: false, error: { message: 'toolsDisable was removed; use tools.builtin policies' } }, 400);\n }\n if (Object.hasOwn(body, 'agentDir')) {\n return c.json({ ok: false, error: { message: 'agentDir was removed from agent manifests' } }, 400);\n }\n if (Object.hasOwn(body, 'name')) {\n return c.json({ ok: false, error: { message: 'name is not supported; edit IDENTITY.md' } }, 400);\n }\n if (Object.hasOwn(body, 'description')) {\n return c.json({ ok: false, error: { message: 'description is not supported; edit IDENTITY.md' } }, 400);\n }\n const skillsPatch =\n body.skills === null\n ? null\n : Array.isArray(body.skills)\n ? body.skills.map((x: unknown) => String(x).trim()).filter(Boolean)\n : undefined;\n const extendsPatch = Object.hasOwn(body, 'extends')\n ? Array.isArray(body.extends)\n ? body.extends.map((x: unknown) => String(x).trim()).filter(Boolean)\n : undefined\n : undefined;\n if (Object.hasOwn(body, 'extends') && extendsPatch === undefined) {\n return c.json({ ok: false, error: { message: 'extends must be an array' } }, 400);\n }\n let toolsPatch: CreateAgentBody['tools'] | null | undefined;\n if (Object.hasOwn(body, 'tools')) {\n if (body.tools === null) {\n toolsPatch = null;\n } else if (typeof body.tools === 'object' && !Array.isArray(body.tools)) {\n const parsedTools = ToolPolicySetSchema.safeParse(body.tools);\n if (!parsedTools.success) {\n return c.json({ ok: false, error: { message: `tools ${parsedTools.error.issues[0]?.message ?? 'is invalid'}` } }, 400);\n }\n toolsPatch = parsedTools.data;\n } else {\n return c.json({ ok: false, error: { message: 'tools must be an object or null' } }, 400);\n }\n }\n const modelsPatch = Object.hasOwn(body, 'models') ? parsePatchModels(body.models) : undefined;\n if (isParseError(modelsPatch)) {\n return c.json({ ok: false, error: { message: modelsPatch.error } }, 400);\n }\n let memoryPatch: Config['agents']['list'][number]['memory'] | undefined;\n if (Object.hasOwn(body, 'memory')) {\n const parsedMemory = MemoryPolicySchema.safeParse(body.memory);\n if (!parsedMemory.success) {\n return c.json({ ok: false, error: { message: `memory ${parsedMemory.error.issues[0]?.message ?? 'is invalid'}` } }, 400);\n }\n memoryPatch = parsedMemory.data;\n }\n\n const prep = prepareUpdateAgent(service.currentConfig as Config, id, {\n workspace: typeof body.workspace === 'string' ? body.workspace : undefined,\n ...(extendsPatch !== undefined ? { extends: extendsPatch } : {}),\n ...(modelsPatch !== undefined ? { models: modelsPatch } : {}),\n setDefault: body.setDefault === true,\n ...(skillsPatch !== undefined ? { skills: skillsPatch } : {}),\n ...(toolsPatch !== undefined ? { tools: toolsPatch } : {}),\n ...(memoryPatch !== undefined ? { memory: memoryPatch } : {}),\n });\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const save = await service.saveConfig(prep.data.nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({ ok: true, payload: agentsPayload });\n });\n\n authenticated.delete('/api/agents/:id', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const purge = c.req.query('purge') === '1' || c.req.query('purge') === 'true';\n const prep = prepareDeleteAgent(service.currentConfig as Config, id);\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const { nextConfig, agentId } = prep.data;\n const save = await service.saveConfig(nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n if (purge) {\n await runAfterDeletePurge(service.currentConfig as Config, agentId);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({\n ok: true,\n payload: { agentId, purged: purge, agents: agentsPayload },\n });\n });\n\n authenticated.get('/api/agents/:id/avatar', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await readAgentAvatarFile(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return new Response(res.data.buffer, {\n status: 200,\n headers: {\n 'Content-Type': res.data.contentType,\n 'Cache-Control': 'private, max-age=3600',\n },\n });\n });\n\n authenticated.put('/api/agents/:id/avatar', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const base64 = typeof body.base64 === 'string' ? body.base64 : '';\n const mimeType = typeof body.mimeType === 'string' ? body.mimeType : '';\n const res = await writeAgentAvatarFromBase64(service.currentConfig as Config, id, base64, mimeType);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId } });\n });\n\n authenticated.delete('/api/agents/:id/avatar', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await deleteAgentAvatarFile(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId } });\n });\n\n authenticated.get('/api/agents/:id/files', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await listAgentProfileFiles(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.get('/api/agents/:id/files/:name', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const name = decodeURIComponent(c.req.param('name') ?? '');\n const res = await readAgentProfileFile(service.currentConfig as Config, id, name);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId, name, content: res.data.content } });\n });\n\n authenticated.put('/api/agents/:id/files/:name', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const name = decodeURIComponent(c.req.param('name') ?? '');\n let content = '';\n try {\n const body = (await c.req.json()) as { content?: unknown };\n content = typeof body.content === 'string' ? body.content : '';\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const res = await writeAgentProfileFile(service.currentConfig as Config, id, name, content);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId, name } });\n });\n\n // GET /api/voice/models - Get available STT/TTS models\n authenticated.get('/api/voice/models', (c) => {\n const models = getVoiceModelsConfig();\n return c.json({ ok: true, payload: { models } });\n });\n\n authenticated.get('/api/image/capabilities', async (c) => {\n const config = service.currentConfig as Config;\n const imageGenerationProviders = await resolveImageGenerationCapabilities(config);\n const imageUnderstandingProviders = await resolveImageUnderstandingCapabilities(config);\n return c.json({\n ok: true,\n payload: {\n current: {\n imageModel: null,\n imageModelFallbacks: [],\n imageGenerationModel: null,\n imageGenerationModelFallbacks: [],\n mediaMaxMb: null,\n },\n imageGeneration: { providers: imageGenerationProviders },\n imageUnderstanding: { providers: imageUnderstandingProviders },\n },\n });\n });\n\n authenticated.post('/api/image/validate-model', strictRateLimitMiddleware, async (c) => {\n let body: { modelRef?: unknown };\n try {\n body = (await c.req.json()) as { modelRef?: unknown };\n } catch {\n return c.json({ ok: false, error: 'Invalid JSON' }, 400);\n }\n const modelRef = body.modelRef;\n if (!modelRef || typeof modelRef !== 'string') {\n return c.json({ ok: false, error: 'modelRef is required' }, 400);\n }\n\n const parsed = parseModelRef(modelRef);\n if (!parsed) {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'invalid_format',\n message: 'Model reference must be in \"provider/model\" format',\n },\n });\n }\n\n const configured = await isProviderConfigured(parsed.provider);\n if (!configured) {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'provider_not_configured',\n message: `Provider \"${parsed.provider}\" is not configured. Set the API key first.`,\n provider: parsed.provider,\n },\n });\n }\n\n try {\n resolveModel(modelRef);\n } catch {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'model_not_found',\n message: `Model not found in registry: ${modelRef}`,\n provider: parsed.provider,\n model: parsed.model,\n },\n });\n }\n\n return c.json({\n ok: true,\n payload: {\n valid: true,\n provider: parsed.provider,\n model: parsed.model,\n },\n });\n });\n\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `PATCH /api/config` — tail sections that are each <50 lines:
|
|
3
|
-
* update /
|
|
3
|
+
* update / goals / session / gateway.{skillsMarketplaceProvider,
|
|
4
4
|
* skillsStoreBaseUrl} / providers / providersConfig / stt / tts / tools /
|
|
5
5
|
* tunnel / bindings / mcp.
|
|
6
6
|
*
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { BindingsConfigSchema, BrowserConfigSchema, McpConfigSchema, init_schema } from "../../../../config/schema.js";
|
|
2
2
|
import { CredentialResolver, init_credentials } from "../../../../auth/credentials.js";
|
|
3
3
|
import { canonicalizeConfiguredMcpServer } from "../../../../config/mcp-config-normalize.js";
|
|
4
|
-
import {
|
|
4
|
+
import { setTuiDefaultAgentConfig } from "../../../../commands/agents.config.js";
|
|
5
|
+
import { mergeGatewaySkillsMarketplacePatch, mergeGoalsConfigPatch, mergeSessionConfigPatch, mergeUpdateConfigPatch } from "../../../../config/web-patch.js";
|
|
5
6
|
import { assertGatewayAuthConfigured, resolveGatewayAuth } from "../../../auth.js";
|
|
6
7
|
import { isMaskedSecretPatchValue } from "../../lib/mask-secret-length.js";
|
|
7
8
|
import { applyToolsWebPatch } from "../../../config-tools-web.js";
|
|
@@ -17,11 +18,6 @@ async function applyMiscPatch(config, body) {
|
|
|
17
18
|
const updateResult = mergeUpdateConfigPatch(config, body.update);
|
|
18
19
|
if (updateResult.ok === false) return patchError(updateResult.message);
|
|
19
20
|
}
|
|
20
|
-
if (body.cron !== void 0) {
|
|
21
|
-
if (typeof body.cron !== "object" || body.cron === null || Array.isArray(body.cron)) return patchError("cron must be an object");
|
|
22
|
-
const cronResult = mergeCronConfigPatch(config, body.cron);
|
|
23
|
-
if (cronResult.ok === false) return patchError(cronResult.message);
|
|
24
|
-
}
|
|
25
21
|
if (body.goals !== void 0) {
|
|
26
22
|
if (typeof body.goals !== "object" || body.goals === null || Array.isArray(body.goals)) return patchError("goals must be an object");
|
|
27
23
|
const goalsResult = mergeGoalsConfigPatch(config, body.goals);
|
|
@@ -32,6 +28,19 @@ async function applyMiscPatch(config, body) {
|
|
|
32
28
|
const sessionResult = mergeSessionConfigPatch(config, body.session);
|
|
33
29
|
if (sessionResult.ok === false) return patchError(sessionResult.message);
|
|
34
30
|
}
|
|
31
|
+
if (body.tui !== void 0) {
|
|
32
|
+
if (typeof body.tui !== "object" || body.tui === null || Array.isArray(body.tui)) return patchError("tui must be an object");
|
|
33
|
+
const tuiPatch = body.tui;
|
|
34
|
+
if (tuiPatch.defaultAgent !== void 0) if (tuiPatch.defaultAgent === null) {
|
|
35
|
+
config.tui = { ...config.tui };
|
|
36
|
+
delete config.tui.defaultAgent;
|
|
37
|
+
} else {
|
|
38
|
+
if (typeof tuiPatch.defaultAgent !== "string" || !tuiPatch.defaultAgent.trim()) return patchError("tui.defaultAgent must be a non-empty string");
|
|
39
|
+
const result = setTuiDefaultAgentConfig(config, tuiPatch.defaultAgent);
|
|
40
|
+
if (result.ok === false) return patchError(result.message);
|
|
41
|
+
config.tui = result.config.tui;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
35
44
|
if (body.browser !== void 0) {
|
|
36
45
|
if (typeof body.browser !== "object" || body.browser === null || Array.isArray(body.browser)) return patchError("browser must be an object");
|
|
37
46
|
const parsed = BrowserConfigSchema.safeParse(body.browser);
|