@xopcai/xopc 0.0.28 → 0.0.29

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.
Files changed (160) hide show
  1. package/dist/extensions/telegram/xopc.extension.json +1 -1
  2. package/dist/gateway/static/root/assets/agents-CkgFSiCY.js +216 -0
  3. package/dist/gateway/static/root/assets/agents-CkgFSiCY.js.map +1 -0
  4. package/dist/gateway/static/root/assets/{apps-page-Co95hLOJ.js → apps-page-Bmq19MS-.js} +2 -2
  5. package/dist/gateway/static/root/assets/{apps-page-Co95hLOJ.js.map → apps-page-Bmq19MS-.js.map} +1 -1
  6. package/dist/gateway/static/root/assets/channels-settings-CE7jrdkO.js +9 -0
  7. package/dist/gateway/static/root/assets/channels-settings-CE7jrdkO.js.map +1 -0
  8. package/dist/gateway/static/root/assets/cron-page-BpPPcykJ.js +2 -0
  9. package/dist/gateway/static/root/assets/cron-page-BpPPcykJ.js.map +1 -0
  10. package/dist/gateway/static/root/assets/{cron-utils-BmzF4m1y.js → cron-utils-N1PqD2DB.js} +2 -2
  11. package/dist/gateway/static/root/assets/{cron-utils-BmzF4m1y.js.map → cron-utils-N1PqD2DB.js.map} +1 -1
  12. package/dist/gateway/static/root/assets/{dist-Dn-ufXyc.js → dist--p2HQ2QF.js} +2 -2
  13. package/dist/gateway/static/root/assets/{dist-Dn-ufXyc.js.map → dist--p2HQ2QF.js.map} +1 -1
  14. package/dist/gateway/static/root/assets/{extension-debug-page-BZ8xQ74_.js → extension-debug-page-DwHCB_6T.js} +2 -2
  15. package/dist/gateway/static/root/assets/{extension-debug-page-BZ8xQ74_.js.map → extension-debug-page-DwHCB_6T.js.map} +1 -1
  16. package/dist/gateway/static/root/assets/{extension-page-BlNgKxwW.js → extension-page-BsYwQIex.js} +2 -2
  17. package/dist/gateway/static/root/assets/{extension-page-BlNgKxwW.js.map → extension-page-BsYwQIex.js.map} +1 -1
  18. package/dist/gateway/static/root/assets/{extension-settings-page-CWTdW_oY.js → extension-settings-page-nsisEgjB.js} +2 -2
  19. package/dist/gateway/static/root/assets/{extension-settings-page-CWTdW_oY.js.map → extension-settings-page-nsisEgjB.js.map} +1 -1
  20. package/dist/gateway/static/root/assets/index-CR8zUHGR.js +4734 -0
  21. package/dist/gateway/static/root/assets/{index-lV8FGWlt.js.map → index-CR8zUHGR.js.map} +1 -1
  22. package/dist/gateway/static/root/assets/index-Dnfha4O2.css +1 -0
  23. package/dist/gateway/static/root/assets/logs-page-CQwdV_Xw.js +2 -0
  24. package/dist/gateway/static/root/assets/{logs-page-DG31RpvG.js.map → logs-page-CQwdV_Xw.js.map} +1 -1
  25. package/dist/gateway/static/root/assets/sessions-page-Be5kIGl_.js +2 -0
  26. package/dist/gateway/static/root/assets/sessions-page-Be5kIGl_.js.map +1 -0
  27. package/dist/gateway/static/root/assets/settings-page-PodSlNwr.js +2 -0
  28. package/dist/gateway/static/root/assets/settings-page-PodSlNwr.js.map +1 -0
  29. package/dist/gateway/static/root/assets/skills-page-Clg8deH0.js +3 -0
  30. package/dist/gateway/static/root/assets/{skills-page-lb7vYtlP.js.map → skills-page-Clg8deH0.js.map} +1 -1
  31. package/dist/gateway/static/root/index.html +2 -2
  32. package/dist/package.js +1 -1
  33. package/dist/src/agent/lifecycle/hook-handler.d.ts +2 -0
  34. package/dist/src/agent/lifecycle/hook-handler.js +24 -0
  35. package/dist/src/agent/lifecycle/hook-handler.js.map +1 -1
  36. package/dist/src/agent/messaging/command-handler.js +10 -2
  37. package/dist/src/agent/messaging/command-handler.js.map +1 -1
  38. package/dist/src/agent/service/process-direct-streaming.js +77 -20
  39. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  40. package/dist/src/agent/service.d.ts +15 -0
  41. package/dist/src/agent/service.js +21 -1
  42. package/dist/src/agent/service.js.map +1 -1
  43. package/dist/src/channels/index.js +2 -2
  44. package/dist/src/channels/manager.js +2 -2
  45. package/dist/src/cli/agent-chat-log-level-preset.d.ts +3 -2
  46. package/dist/src/cli/agent-chat-log-level-preset.js +6 -3
  47. package/dist/src/cli/agent-chat-log-level-preset.js.map +1 -1
  48. package/dist/src/cli/index.js +4 -3
  49. package/dist/src/cli/index.js.map +1 -1
  50. package/dist/src/config/schema.js +5 -2
  51. package/dist/src/config/schema.js.map +1 -1
  52. package/dist/src/extensions/hooks.js +5 -1
  53. package/dist/src/extensions/hooks.js.map +1 -1
  54. package/dist/src/extensions/loader.d.ts +1 -0
  55. package/dist/src/extensions/loader.js +3 -1
  56. package/dist/src/extensions/loader.js.map +1 -1
  57. package/dist/src/extensions/sdk/index.d.ts +1 -1
  58. package/dist/src/extensions/sdk/index.js.map +1 -1
  59. package/dist/src/extensions/types/core.d.ts +8 -0
  60. package/dist/src/extensions/types/hooks.d.ts +16 -1
  61. package/dist/src/extensions/types/hooks.js +1 -0
  62. package/dist/src/extensions/types/hooks.js.map +1 -1
  63. package/dist/src/gateway/agents-admin.d.ts +19 -1
  64. package/dist/src/gateway/agents-admin.js +164 -3
  65. package/dist/src/gateway/agents-admin.js.map +1 -1
  66. package/dist/src/gateway/hono/app.js +1 -0
  67. package/dist/src/gateway/hono/app.js.map +1 -1
  68. package/dist/src/gateway/hono/routes/agents.js +59 -5
  69. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  70. package/dist/src/gateway/hono/routes/config.js +2 -2
  71. package/dist/src/gateway/hono/routes/config.js.map +1 -1
  72. package/dist/src/gateway/hono/routes/public-gateway.js +1 -0
  73. package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
  74. package/dist/src/gateway/hono/routes/sessions.js +17 -0
  75. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  76. package/dist/src/gateway/service.d.ts +2 -0
  77. package/dist/src/gateway/service.js +31 -4
  78. package/dist/src/gateway/service.js.map +1 -1
  79. package/dist/src/session/client-history.d.ts +21 -0
  80. package/dist/src/session/client-history.js +89 -0
  81. package/dist/src/session/client-history.js.map +1 -0
  82. package/dist/src/session/index.d.ts +1 -0
  83. package/dist/src/session/index.js +2 -1
  84. package/dist/src/session/manager.d.ts +2 -0
  85. package/dist/src/session/manager.js +5 -0
  86. package/dist/src/session/manager.js.map +1 -1
  87. package/dist/src/session/thinking-resolve.js +1 -1
  88. package/dist/src/session/thinking-resolve.js.map +1 -1
  89. package/dist/src/tui/backends/embedded-backend.d.ts +1 -1
  90. package/dist/src/tui/backends/embedded-backend.js +15 -2
  91. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  92. package/dist/src/tui/backends/gateway-sse-backend.d.ts +4 -0
  93. package/dist/src/tui/backends/gateway-sse-backend.js +34 -4
  94. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  95. package/dist/src/tui/chat-history.d.ts +4 -0
  96. package/dist/src/tui/chat-history.js +29 -0
  97. package/dist/src/tui/chat-history.js.map +1 -0
  98. package/dist/src/tui/components/chat-log.d.ts +3 -1
  99. package/dist/src/tui/components/chat-log.js +17 -3
  100. package/dist/src/tui/components/chat-log.js.map +1 -1
  101. package/dist/src/tui/components/custom-editor.d.ts +1 -0
  102. package/dist/src/tui/components/custom-editor.js +8 -2
  103. package/dist/src/tui/components/custom-editor.js.map +1 -1
  104. package/dist/src/tui/components/fuzzy-filter.d.ts +17 -0
  105. package/dist/src/tui/components/fuzzy-filter.js +85 -0
  106. package/dist/src/tui/components/fuzzy-filter.js.map +1 -0
  107. package/dist/src/tui/components/searchable-select-list.d.ts +39 -0
  108. package/dist/src/tui/components/searchable-select-list.js +257 -0
  109. package/dist/src/tui/components/searchable-select-list.js.map +1 -0
  110. package/dist/src/tui/theme.d.ts +2 -0
  111. package/dist/src/tui/theme.js +7 -1
  112. package/dist/src/tui/theme.js.map +1 -1
  113. package/dist/src/tui/tui-agent-events.d.ts +7 -0
  114. package/dist/src/tui/tui-agent-events.js +103 -0
  115. package/dist/src/tui/tui-agent-events.js.map +1 -0
  116. package/dist/src/tui/tui-backend.d.ts +8 -12
  117. package/dist/src/tui/tui-commands.d.ts +23 -0
  118. package/dist/src/tui/tui-commands.js +165 -0
  119. package/dist/src/tui/tui-commands.js.map +1 -0
  120. package/dist/src/tui/tui-lifecycle.d.ts +26 -0
  121. package/dist/src/tui/tui-lifecycle.js +57 -0
  122. package/dist/src/tui/tui-lifecycle.js.map +1 -0
  123. package/dist/src/tui/tui-local-shell.d.ts +28 -0
  124. package/dist/src/tui/tui-local-shell.js +147 -0
  125. package/dist/src/tui/tui-local-shell.js.map +1 -0
  126. package/dist/src/tui/tui-overlays.d.ts +8 -0
  127. package/dist/src/tui/tui-overlays.js +22 -0
  128. package/dist/src/tui/tui-overlays.js.map +1 -0
  129. package/dist/src/tui/tui-picker-overlay.d.ts +26 -0
  130. package/dist/src/tui/tui-picker-overlay.js +69 -0
  131. package/dist/src/tui/tui-picker-overlay.js.map +1 -0
  132. package/dist/src/tui/tui-stdio-filter.d.ts +17 -0
  133. package/dist/src/tui/tui-stdio-filter.js +96 -0
  134. package/dist/src/tui/tui-stdio-filter.js.map +1 -0
  135. package/dist/src/tui/tui-submit.d.ts +25 -0
  136. package/dist/src/tui/tui-submit.js +102 -0
  137. package/dist/src/tui/tui-submit.js.map +1 -0
  138. package/dist/src/tui/tui-suspend.d.ts +10 -0
  139. package/dist/src/tui/tui-suspend.js +18 -0
  140. package/dist/src/tui/tui-suspend.js.map +1 -0
  141. package/dist/src/tui/tui-types.d.ts +1 -0
  142. package/dist/src/tui/tui-types.js.map +1 -1
  143. package/dist/src/tui/tui.d.ts +2 -0
  144. package/dist/src/tui/tui.js +175 -312
  145. package/dist/src/tui/tui.js.map +1 -1
  146. package/package.json +2 -6
  147. package/dist/gateway/static/root/assets/agents-DplaQYS2.js +0 -216
  148. package/dist/gateway/static/root/assets/agents-DplaQYS2.js.map +0 -1
  149. package/dist/gateway/static/root/assets/channels-settings-CkfSST0k.js +0 -9
  150. package/dist/gateway/static/root/assets/channels-settings-CkfSST0k.js.map +0 -1
  151. package/dist/gateway/static/root/assets/cron-page-D9q6KqL8.js +0 -2
  152. package/dist/gateway/static/root/assets/cron-page-D9q6KqL8.js.map +0 -1
  153. package/dist/gateway/static/root/assets/index-OT4cGzon.css +0 -1
  154. package/dist/gateway/static/root/assets/index-lV8FGWlt.js +0 -4734
  155. package/dist/gateway/static/root/assets/logs-page-DG31RpvG.js +0 -2
  156. package/dist/gateway/static/root/assets/sessions-page-CdmjxDEM.js +0 -2
  157. package/dist/gateway/static/root/assets/sessions-page-CdmjxDEM.js.map +0 -1
  158. package/dist/gateway/static/root/assets/settings-page-DU2XLf5s.js +0 -2
  159. package/dist/gateway/static/root/assets/settings-page-DU2XLf5s.js.map +0 -1
  160. package/dist/gateway/static/root/assets/skills-page-lb7vYtlP.js +0 -3
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":[],"sources":["../../../../../src/gateway/hono/routes/config.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { type Config, BindingsConfigSchema } from '../../../config/schema.js';\nimport { CredentialResolver } from '../../../auth/credentials.js';\nimport { applyToolsWebPatch } from '../../config-tools-web.js';\nimport { buildSafeWebConfigPayload } from '../lib/config-payload.js';\nimport { normalizePatchAgentModel } from '../lib/agent-model.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nexport function registerConfigRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service, strictRateLimitMiddleware } = deps;\n\n authenticated.post('/api/config/reload', strictRateLimitMiddleware, async (c) => {\n const result = await service.reloadConfig();\n return c.json({ ok: true, payload: result });\n });\n\n authenticated.post('/api/heartbeat/trigger', strictRateLimitMiddleware, async (c) => {\n let reason = 'manual';\n try {\n const body = await c.req.json();\n if (body && typeof body === 'object' && typeof (body as { reason?: unknown }).reason === 'string') {\n const r = (body as { reason: string }).reason.trim();\n if (r) reason = r.slice(0, 120);\n }\n } catch {\n /* empty or invalid body */\n }\n service.requestHeartbeatNow({ reason });\n return c.json({ ok: true, payload: { scheduled: true } });\n });\n\n authenticated.get('/api/config', async (c) => {\n const safeConfig = await buildSafeWebConfigPayload(service);\n return c.json({ ok: true, payload: { config: safeConfig } });\n });\n\n authenticated.patch('/api/config', strictRateLimitMiddleware, async (c) => {\n const body = await c.req.json();\n \n // Merge updates into current config\n const config: Config = service.currentConfig as Config;\n \n // Update agent defaults\n if (body.agents?.defaults) {\n if (!config.agents) config.agents = { defaults: { workspace: '~/.xopc/workspace', model: 'anthropic/claude-sonnet-4-5', maxTokens: 8192, temperature: 0.7, maxToolIterations: 20, maxRequestsPerTurn: 50, maxToolFailuresPerTurn: 3, thinkingDefault: 'medium', reasoningDefault: 'off', verboseDefault: 'off' } };\n if (!config.agents.defaults) config.agents.defaults = {} as any;\n \n if (body.agents.defaults.model !== undefined) {\n config.agents.defaults.model = normalizePatchAgentModel(body.agents.defaults.model) as Config['agents']['defaults']['model'];\n }\n if (body.agents.defaults.maxTokens !== undefined) {\n config.agents.defaults.maxTokens = body.agents.defaults.maxTokens;\n }\n if (body.agents.defaults.temperature !== undefined) {\n config.agents.defaults.temperature = body.agents.defaults.temperature;\n }\n if (body.agents.defaults.maxToolIterations !== undefined) {\n config.agents.defaults.maxToolIterations = body.agents.defaults.maxToolIterations;\n }\n if (body.agents.defaults.workspace !== undefined) {\n config.agents.defaults.workspace = body.agents.defaults.workspace;\n }\n if (body.agents.defaults.thinkingDefault !== undefined) {\n config.agents.defaults.thinkingDefault = body.agents.defaults.thinkingDefault;\n }\n if (body.agents.defaults.reasoningDefault !== undefined) {\n config.agents.defaults.reasoningDefault = body.agents.defaults.reasoningDefault;\n }\n if (body.agents.defaults.verboseDefault !== undefined) {\n config.agents.defaults.verboseDefault = body.agents.defaults.verboseDefault;\n }\n if (body.agents.defaults.imageModel !== undefined) {\n const v = body.agents.defaults.imageModel;\n if (v === '' || v === null) {\n delete (config.agents.defaults as Record<string, unknown>).imageModel;\n } else {\n config.agents.defaults.imageModel = normalizePatchAgentModel(v) as Config['agents']['defaults']['imageModel'];\n }\n }\n if (body.agents.defaults.imageGenerationModel !== undefined) {\n const v = body.agents.defaults.imageGenerationModel;\n if (v === '' || v === null) {\n delete (config.agents.defaults as Record<string, unknown>).imageGenerationModel;\n } else {\n config.agents.defaults.imageGenerationModel = normalizePatchAgentModel(\n v,\n ) as Config['agents']['defaults']['imageGenerationModel'];\n }\n }\n if (body.agents.defaults.mediaMaxMb !== undefined) {\n const v = body.agents.defaults.mediaMaxMb;\n if (v === null) {\n delete (config.agents.defaults as Record<string, unknown>).mediaMaxMb;\n } else {\n const n = typeof v === 'number' ? v : Number(v);\n if (!Number.isNaN(n) && n > 0) {\n config.agents.defaults.mediaMaxMb = n;\n }\n }\n }\n if (body.agents.defaults.browser !== undefined) {\n const b = body.agents.defaults.browser;\n if (b === null) {\n delete (config.agents.defaults as Record<string, unknown>).browser;\n } else if (typeof b === 'object' && !Array.isArray(b)) {\n const br = b as Record<string, unknown>;\n if (!config.agents.defaults.browser) {\n config.agents.defaults.browser = { enabled: false, headless: true };\n }\n const target = config.agents.defaults.browser;\n if (br.enabled !== undefined) {\n target.enabled = Boolean(br.enabled);\n }\n if (br.headless !== undefined) {\n target.headless = Boolean(br.headless);\n }\n }\n }\n\n const dPatch = body.agents.defaults as Record<string, unknown>;\n const def = config.agents.defaults as Record<string, unknown>;\n\n if (dPatch.maxTaskDurationMs !== undefined) {\n const v = dPatch.maxTaskDurationMs;\n if (v === null) {\n delete def.maxTaskDurationMs;\n } else if (typeof v === 'number' && Number.isFinite(v)) {\n const ms = Math.floor(v);\n if (ms >= 60_000 && ms <= 14_400_000) {\n def.maxTaskDurationMs = ms;\n }\n }\n }\n if (dPatch.maxRequestsPerTurn !== undefined) {\n const v = dPatch.maxRequestsPerTurn;\n if (v === null) {\n delete def.maxRequestsPerTurn;\n } else if (typeof v === 'number' && Number.isFinite(v)) {\n const n = Math.floor(v);\n if (n >= 10 && n <= 200) {\n def.maxRequestsPerTurn = n;\n }\n }\n }\n if (dPatch.maxToolFailuresPerTurn !== undefined) {\n const v = dPatch.maxToolFailuresPerTurn;\n if (v === null) {\n delete def.maxToolFailuresPerTurn;\n } else if (typeof v === 'number' && Number.isFinite(v)) {\n const n = Math.floor(v);\n if (n >= 1 && n <= 20) {\n def.maxToolFailuresPerTurn = n;\n }\n }\n }\n\n if (dPatch.compaction !== undefined) {\n const c = dPatch.compaction;\n if (c === null) {\n delete def.compaction;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.compaction || typeof def.compaction !== 'object') {\n def.compaction = {};\n }\n const t = def.compaction as Record<string, unknown>;\n if (p.enabled !== undefined) t.enabled = Boolean(p.enabled);\n if (p.mode === 'default' || p.mode === 'safeguard') t.mode = p.mode;\n if (typeof p.reserveTokens === 'number' && Number.isFinite(p.reserveTokens)) {\n t.reserveTokens = Math.floor(p.reserveTokens);\n }\n if (typeof p.triggerThreshold === 'number' && Number.isFinite(p.triggerThreshold)) {\n const x = p.triggerThreshold;\n if (x >= 0.5 && x <= 0.95) t.triggerThreshold = x;\n }\n if (typeof p.minMessagesBeforeCompact === 'number' && Number.isFinite(p.minMessagesBeforeCompact)) {\n t.minMessagesBeforeCompact = Math.floor(p.minMessagesBeforeCompact);\n }\n if (typeof p.keepRecentMessages === 'number' && Number.isFinite(p.keepRecentMessages)) {\n t.keepRecentMessages = Math.floor(p.keepRecentMessages);\n }\n if (typeof p.evictionWindow === 'number' && Number.isFinite(p.evictionWindow)) {\n const x = p.evictionWindow;\n if (x >= 0.1 && x <= 0.5) t.evictionWindow = x;\n }\n if (typeof p.retentionWindow === 'number' && Number.isFinite(p.retentionWindow)) {\n const n = Math.floor(p.retentionWindow);\n if (n >= 3 && n <= 20) t.retentionWindow = n;\n }\n }\n }\n\n if (dPatch.pruning !== undefined) {\n const c = dPatch.pruning;\n if (c === null) {\n delete def.pruning;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.pruning || typeof def.pruning !== 'object') {\n def.pruning = {};\n }\n const t = def.pruning as Record<string, unknown>;\n if (p.enabled !== undefined) t.enabled = Boolean(p.enabled);\n if (typeof p.maxToolResultChars === 'number' && Number.isFinite(p.maxToolResultChars)) {\n t.maxToolResultChars = Math.floor(p.maxToolResultChars);\n }\n if (typeof p.headKeepRatio === 'number' && Number.isFinite(p.headKeepRatio)) {\n t.headKeepRatio = p.headKeepRatio;\n }\n if (typeof p.tailKeepRatio === 'number' && Number.isFinite(p.tailKeepRatio)) {\n t.tailKeepRatio = p.tailKeepRatio;\n }\n }\n }\n\n if (dPatch.memory !== undefined) {\n const c = dPatch.memory;\n if (c === null) {\n delete def.memory;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.memory || typeof def.memory !== 'object') {\n def.memory = {};\n }\n const t = def.memory as Record<string, unknown>;\n if (p.enabled !== undefined) {\n if (p.enabled === null) delete t.enabled;\n else t.enabled = Boolean(p.enabled);\n }\n if (p.useEnhancedSystem !== undefined) {\n if (p.useEnhancedSystem === null) delete t.useEnhancedSystem;\n else t.useEnhancedSystem = Boolean(p.useEnhancedSystem);\n }\n if (p.userProfileEnabled !== undefined) {\n if (p.userProfileEnabled === null) delete t.userProfileEnabled;\n else t.userProfileEnabled = Boolean(p.userProfileEnabled);\n }\n if (p.memoryCharLimit !== undefined) {\n if (p.memoryCharLimit === null) delete t.memoryCharLimit;\n else if (typeof p.memoryCharLimit === 'number' && p.memoryCharLimit > 0) {\n t.memoryCharLimit = Math.floor(p.memoryCharLimit);\n }\n }\n if (p.userCharLimit !== undefined) {\n if (p.userCharLimit === null) delete t.userCharLimit;\n else if (typeof p.userCharLimit === 'number' && p.userCharLimit > 0) {\n t.userCharLimit = Math.floor(p.userCharLimit);\n }\n }\n if (p.provider === 'none' || p.provider === 'stub') {\n t.provider = p.provider;\n } else if (p.provider === null) {\n delete t.provider;\n }\n if (p.injectionFrequency === 'every-turn' || p.injectionFrequency === 'first-turn') {\n t.injectionFrequency = p.injectionFrequency;\n } else if (p.injectionFrequency === null) {\n delete t.injectionFrequency;\n }\n if (p.contextCadence !== undefined) {\n if (p.contextCadence === null) delete t.contextCadence;\n else if (typeof p.contextCadence === 'number' && p.contextCadence >= 1) {\n t.contextCadence = Math.floor(p.contextCadence);\n }\n }\n if (p.dialecticCadence !== undefined) {\n if (p.dialecticCadence === null) delete t.dialecticCadence;\n else if (typeof p.dialecticCadence === 'number' && p.dialecticCadence >= 1) {\n t.dialecticCadence = Math.floor(p.dialecticCadence);\n }\n }\n\n // Dreaming (schemaless patch): agents.defaults.memory.dreaming\n if (p.dreaming !== undefined) {\n const d0 = p.dreaming;\n if (d0 === null) {\n delete (t as { dreaming?: unknown }).dreaming;\n } else if (typeof d0 === 'object' && d0 !== null && !Array.isArray(d0)) {\n if (!('dreaming' in t) || typeof (t as { dreaming?: unknown }).dreaming !== 'object') {\n (t as { dreaming?: Record<string, unknown> }).dreaming = {};\n }\n const dt = (t as { dreaming: Record<string, unknown> }).dreaming;\n const dp = d0 as Record<string, unknown>;\n\n if (dp.enabled !== undefined) {\n if (dp.enabled === null) delete dt.enabled;\n else dt.enabled = Boolean(dp.enabled);\n }\n if (dp.frequency !== undefined) {\n const v = dp.frequency;\n if (v === null || v === '') delete dt.frequency;\n else if (typeof v === 'string') dt.frequency = v;\n }\n if (dp.timezone !== undefined) {\n const v = dp.timezone;\n if (v === null || v === '') delete dt.timezone;\n else if (typeof v === 'string') dt.timezone = v;\n }\n\n // Accept either `phases.deep` or `deep`.\n if (dp.phases !== undefined || dp.deep !== undefined) {\n if (!('phases' in dt) || typeof (dt as { phases?: unknown }).phases !== 'object' || (dt as { phases?: unknown }).phases === null) {\n dt.phases = {};\n }\n const phases = (dt as { phases: Record<string, unknown> }).phases;\n if (!('deep' in phases) || typeof phases.deep !== 'object' || phases.deep === null) {\n phases.deep = {};\n }\n const deep = phases.deep as Record<string, unknown>;\n\n const deepPatchRaw =\n typeof dp.phases === 'object' && dp.phases !== null && !Array.isArray(dp.phases)\n ? (dp.phases as Record<string, unknown>).deep\n : dp.deep;\n const deepPatch =\n typeof deepPatchRaw === 'object' && deepPatchRaw !== null && !Array.isArray(deepPatchRaw)\n ? (deepPatchRaw as Record<string, unknown>)\n : null;\n\n if (deepPatch) {\n if (deepPatch.enabled !== undefined) {\n if (deepPatch.enabled === null) delete deep.enabled;\n else deep.enabled = Boolean(deepPatch.enabled);\n }\n if (deepPatch.minScore !== undefined) {\n const v = deepPatch.minScore;\n if (v === null) delete deep.minScore;\n else if (typeof v === 'number' && Number.isFinite(v)) deep.minScore = v;\n }\n if (deepPatch.minRecallCount !== undefined) {\n const v = deepPatch.minRecallCount;\n if (v === null) delete deep.minRecallCount;\n else if (typeof v === 'number' && Number.isFinite(v)) deep.minRecallCount = Math.floor(v);\n }\n if (deepPatch.limit !== undefined) {\n const v = deepPatch.limit;\n if (v === null) delete deep.limit;\n else if (typeof v === 'number' && Number.isFinite(v)) deep.limit = Math.floor(v);\n }\n }\n }\n }\n }\n }\n }\n\n if (dPatch.sessionSearch !== undefined) {\n const c = dPatch.sessionSearch;\n if (c === null) {\n delete def.sessionSearch;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.sessionSearch || typeof def.sessionSearch !== 'object') {\n def.sessionSearch = {};\n }\n const t = def.sessionSearch as Record<string, unknown>;\n if (p.summaryModel !== undefined) {\n if (p.summaryModel === null || p.summaryModel === '') {\n delete t.summaryModel;\n } else if (typeof p.summaryModel === 'string') {\n t.summaryModel = p.summaryModel;\n }\n }\n }\n }\n\n if (dPatch.backgroundReview !== undefined) {\n const c = dPatch.backgroundReview;\n if (c === null) {\n delete def.backgroundReview;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.backgroundReview || typeof def.backgroundReview !== 'object') {\n def.backgroundReview = {};\n }\n const t = def.backgroundReview as Record<string, unknown>;\n if (p.enabled !== undefined) {\n if (p.enabled === null) delete t.enabled;\n else t.enabled = Boolean(p.enabled);\n }\n if (p.memoryNudgeInterval !== undefined) {\n if (p.memoryNudgeInterval === null) delete t.memoryNudgeInterval;\n else if (typeof p.memoryNudgeInterval === 'number' && p.memoryNudgeInterval >= 0) {\n t.memoryNudgeInterval = Math.floor(p.memoryNudgeInterval);\n }\n }\n if (p.skillNudgeInterval !== undefined) {\n if (p.skillNudgeInterval === null) delete t.skillNudgeInterval;\n else if (typeof p.skillNudgeInterval === 'number' && p.skillNudgeInterval >= 0) {\n t.skillNudgeInterval = Math.floor(p.skillNudgeInterval);\n }\n }\n if (p.maxToolRounds !== undefined) {\n if (p.maxToolRounds === null) delete t.maxToolRounds;\n else if (typeof p.maxToolRounds === 'number' && p.maxToolRounds >= 1 && p.maxToolRounds <= 32) {\n t.maxToolRounds = Math.floor(p.maxToolRounds);\n }\n }\n if (p.maxHistoryMessages !== undefined) {\n if (p.maxHistoryMessages === null) delete t.maxHistoryMessages;\n else if (typeof p.maxHistoryMessages === 'number' && p.maxHistoryMessages >= 10 && p.maxHistoryMessages <= 200) {\n t.maxHistoryMessages = Math.floor(p.maxHistoryMessages);\n }\n }\n if (p.maxDurationMs !== undefined) {\n if (p.maxDurationMs === null) delete t.maxDurationMs;\n else if (typeof p.maxDurationMs === 'number' && p.maxDurationMs >= 30_000 && p.maxDurationMs <= 600_000) {\n t.maxDurationMs = Math.floor(p.maxDurationMs);\n }\n }\n }\n }\n\n if (dPatch.webExtract !== undefined) {\n const c = dPatch.webExtract;\n if (c === null) {\n delete def.webExtract;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.webExtract || typeof def.webExtract !== 'object') {\n def.webExtract = {};\n }\n const t = def.webExtract as Record<string, unknown>;\n if (p.model !== undefined) {\n if (p.model === null || p.model === '') {\n delete t.model;\n } else if (typeof p.model === 'string') {\n t.model = p.model;\n }\n }\n if (p.maxLength !== undefined) {\n if (p.maxLength === null) delete t.maxLength;\n else if (typeof p.maxLength === 'number' && p.maxLength > 0) {\n t.maxLength = p.maxLength;\n }\n }\n }\n }\n\n if (dPatch.delegate !== undefined) {\n const c = dPatch.delegate;\n if (c === null) {\n delete def.delegate;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.delegate || typeof def.delegate !== 'object') {\n def.delegate = {};\n }\n const t = def.delegate as Record<string, unknown>;\n if (p.enabled !== undefined) {\n if (p.enabled === null) delete t.enabled;\n else t.enabled = Boolean(p.enabled);\n }\n }\n }\n\n if (dPatch.executeCode !== undefined) {\n const c = dPatch.executeCode;\n if (c === null) {\n delete def.executeCode;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.executeCode || typeof def.executeCode !== 'object') {\n def.executeCode = {};\n }\n const t = def.executeCode as Record<string, unknown>;\n if (p.enabled !== undefined) {\n if (p.enabled === null) delete t.enabled;\n else t.enabled = Boolean(p.enabled);\n }\n }\n }\n\n if (dPatch.systemPromptOverride !== undefined) {\n const v = dPatch.systemPromptOverride;\n if (v === null || v === '') {\n delete def.systemPromptOverride;\n } else if (typeof v === 'string') {\n def.systemPromptOverride = v;\n }\n }\n\n if (dPatch.skills !== undefined) {\n const v = dPatch.skills;\n if (v === null) {\n delete def.skills;\n } else if (Array.isArray(v) && v.every((x) => typeof x === 'string')) {\n def.skills = v;\n }\n }\n\n if (dPatch.tools !== undefined) {\n const t0 = dPatch.tools;\n if (t0 === null) {\n delete def.tools;\n } else if (typeof t0 === 'object' && !Array.isArray(t0)) {\n const p = t0 as { disable?: unknown };\n if (!def.tools || typeof def.tools !== 'object') {\n def.tools = {};\n }\n const t = def.tools as { disable?: string[] };\n if (p.disable !== undefined) {\n if (p.disable === null || (Array.isArray(p.disable) && p.disable.length === 0)) {\n delete t.disable;\n } else if (Array.isArray(p.disable) && p.disable.every((x) => typeof x === 'string')) {\n t.disable = p.disable;\n }\n }\n }\n }\n\n if (dPatch.params !== undefined) {\n const v = dPatch.params;\n if (v === null) {\n delete def.params;\n } else if (typeof v === 'object' && !Array.isArray(v) && v !== null) {\n def.params = v as Record<string, unknown>;\n }\n }\n }\n \n // Update channels — use `in` / null so `weixin: null` removes the block; avoid `if (ch.weixin)` missing null.\n const patchChannels = body.channels;\n if (patchChannels != null && typeof patchChannels === 'object' && !Array.isArray(patchChannels)) {\n if ('telegram' in patchChannels) {\n const tgRaw = patchChannels.telegram;\n if (tgRaw === null) {\n if (config.channels) delete config.channels.telegram;\n } else if (typeof tgRaw === 'object' && !Array.isArray(tgRaw)) {\n const bodyTg = tgRaw as Record<string, unknown>;\n if (!config.channels) config.channels = { telegram: { enabled: false, botToken: '', allowFrom: [], groupAllowFrom: [], debug: false, dmPolicy: 'pairing' as const, groupPolicy: 'open' as const, replyToMode: 'off' as const, historyLimit: 50, textChunkLimit: 4000 } };\n if (!config.channels.telegram) config.channels.telegram = {} as any;\n const tg = config.channels.telegram as Record<string, unknown>;\n\n if (bodyTg.enabled !== undefined) {\n tg.enabled = bodyTg.enabled;\n }\n if (bodyTg.botToken !== undefined) {\n tg.botToken = bodyTg.botToken;\n }\n if (bodyTg.allowFrom !== undefined) {\n tg.allowFrom = bodyTg.allowFrom;\n }\n if (bodyTg.apiRoot !== undefined) {\n tg.apiRoot = bodyTg.apiRoot;\n }\n if (bodyTg.debug !== undefined) {\n tg.debug = bodyTg.debug;\n }\n if (bodyTg.streamMode !== undefined) {\n tg.streamMode = bodyTg.streamMode;\n }\n if (bodyTg.groupAllowFrom !== undefined) {\n tg.groupAllowFrom = bodyTg.groupAllowFrom;\n }\n if (bodyTg.dmPolicy !== undefined) {\n tg.dmPolicy = bodyTg.dmPolicy;\n }\n if (bodyTg.groupPolicy !== undefined) {\n tg.groupPolicy = bodyTg.groupPolicy;\n }\n if (bodyTg.replyToMode !== undefined) {\n tg.replyToMode = bodyTg.replyToMode;\n }\n if (bodyTg.historyLimit !== undefined) {\n tg.historyLimit = bodyTg.historyLimit;\n }\n if (bodyTg.textChunkLimit !== undefined) {\n tg.textChunkLimit = bodyTg.textChunkLimit;\n }\n if (bodyTg.proxy !== undefined) {\n tg.proxy = bodyTg.proxy;\n }\n if (bodyTg.accounts !== undefined) {\n tg.accounts = bodyTg.accounts;\n }\n }\n }\n\n if ('weixin' in patchChannels) {\n const wxRaw = patchChannels.weixin;\n if (wxRaw === null) {\n if (config.channels) delete config.channels.weixin;\n } else if (typeof wxRaw === 'object' && !Array.isArray(wxRaw)) {\n const wx = wxRaw as Record<string, unknown>;\n if (!config.channels) config.channels = {} as any;\n if (!config.channels.weixin) {\n config.channels.weixin = {\n enabled: false,\n dmPolicy: 'pairing',\n allowFrom: [],\n debug: false,\n historyLimit: 50,\n textChunkLimit: 4000,\n };\n }\n const wxTarget = config.channels.weixin as Record<string, unknown>;\n if (wx.enabled !== undefined) wxTarget.enabled = wx.enabled;\n if (wx.dmPolicy !== undefined) wxTarget.dmPolicy = wx.dmPolicy;\n if (wx.allowFrom !== undefined) wxTarget.allowFrom = wx.allowFrom;\n if (wx.debug !== undefined) wxTarget.debug = wx.debug;\n if (wx.streamMode !== undefined) wxTarget.streamMode = wx.streamMode;\n if (wx.historyLimit !== undefined) wxTarget.historyLimit = wx.historyLimit;\n if (wx.textChunkLimit !== undefined) wxTarget.textChunkLimit = wx.textChunkLimit;\n if ('routeTag' in wx) {\n const rt = wx.routeTag;\n if (rt === null || rt === undefined || rt === '') {\n delete wxTarget.routeTag;\n } else {\n wxTarget.routeTag = rt as string | number;\n }\n }\n if (wx.accounts !== undefined) wxTarget.accounts = wx.accounts;\n }\n }\n\n if ('feishu' in patchChannels) {\n const fsRaw = patchChannels.feishu;\n if (fsRaw === null) {\n if (config.channels) delete config.channels.feishu;\n } else if (typeof fsRaw === 'object' && !Array.isArray(fsRaw)) {\n const fs = fsRaw as Record<string, unknown>;\n if (!config.channels) config.channels = {} as any;\n if (!config.channels.feishu) {\n config.channels.feishu = {\n enabled: false,\n appId: '',\n appSecret: '',\n domain: 'feishu',\n connectionMode: 'websocket',\n dmPolicy: 'pairing',\n groupPolicy: 'allowlist',\n allowFrom: [],\n groupAllowFrom: [],\n requireMention: true,\n historyLimit: 50,\n textChunkLimit: 4000,\n accounts: {},\n };\n }\n const fsTarget = config.channels.feishu as Record<string, unknown>;\n\n if (fs.enabled !== undefined) fsTarget.enabled = fs.enabled;\n if (fs.defaultAccount !== undefined) {\n const da = fs.defaultAccount;\n if (da === null || da === '') delete fsTarget.defaultAccount;\n else fsTarget.defaultAccount = String(da);\n }\n if (fs.appId !== undefined) fsTarget.appId = fs.appId;\n if (fs.appSecret !== undefined) fsTarget.appSecret = fs.appSecret;\n if (fs.domain !== undefined) fsTarget.domain = fs.domain;\n if (fs.connectionMode !== undefined) fsTarget.connectionMode = fs.connectionMode;\n if (fs.verificationToken !== undefined) {\n const v = fs.verificationToken;\n if (v === null || (typeof v === 'string' && !String(v).trim())) delete fsTarget.verificationToken;\n else fsTarget.verificationToken = v;\n }\n if (fs.encryptKey !== undefined) {\n const v = fs.encryptKey;\n if (v === null || (typeof v === 'string' && !String(v).trim())) delete fsTarget.encryptKey;\n else fsTarget.encryptKey = v;\n }\n if (fs.webhookHost !== undefined) {\n const v = fs.webhookHost;\n if (v === null || (typeof v === 'string' && !String(v).trim())) delete fsTarget.webhookHost;\n else fsTarget.webhookHost = v;\n }\n if (fs.webhookPort !== undefined) fsTarget.webhookPort = fs.webhookPort;\n if (fs.webhookPath !== undefined) {\n const v = fs.webhookPath;\n if (v === null || (typeof v === 'string' && !String(v).trim())) delete fsTarget.webhookPath;\n else fsTarget.webhookPath = v;\n }\n if (fs.dmPolicy !== undefined) fsTarget.dmPolicy = fs.dmPolicy;\n if (fs.groupPolicy !== undefined) fsTarget.groupPolicy = fs.groupPolicy;\n if (fs.allowFrom !== undefined) fsTarget.allowFrom = fs.allowFrom;\n if (fs.groupAllowFrom !== undefined) {\n const ga = fs.groupAllowFrom;\n if (ga === null || (Array.isArray(ga) && ga.length === 0)) delete fsTarget.groupAllowFrom;\n else fsTarget.groupAllowFrom = ga;\n }\n if (fs.requireMention !== undefined) fsTarget.requireMention = fs.requireMention;\n if (fs.historyLimit !== undefined) fsTarget.historyLimit = fs.historyLimit;\n if (fs.textChunkLimit !== undefined) fsTarget.textChunkLimit = fs.textChunkLimit;\n if (fs.renderMode !== undefined) fsTarget.renderMode = fs.renderMode;\n if (fs.streaming !== undefined) fsTarget.streaming = fs.streaming;\n if (fs.reactionNotifications !== undefined) {\n fsTarget.reactionNotifications = fs.reactionNotifications;\n }\n if (fs.tools !== undefined) fsTarget.tools = fs.tools;\n if (fs.actions !== undefined) fsTarget.actions = fs.actions;\n if (fs.accounts !== undefined) fsTarget.accounts = fs.accounts;\n }\n }\n }\n \n // Update gateway heartbeat (partial merge)\n if (body.gateway?.heartbeat !== undefined && typeof body.gateway.heartbeat === 'object') {\n if (!config.gateway) {\n config.gateway = {\n host: '0.0.0.0',\n port: 18790,\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: 100,\n corsOrigins: ['*'],\n };\n }\n if (!config.gateway.heartbeat) {\n config.gateway.heartbeat = { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false };\n }\n const h = config.gateway.heartbeat;\n const p = body.gateway.heartbeat as Record<string, unknown>;\n if (p.enabled !== undefined) h.enabled = Boolean(p.enabled);\n if (p.intervalMs !== undefined && typeof p.intervalMs === 'number' && Number.isFinite(p.intervalMs)) {\n h.intervalMs = p.intervalMs;\n }\n if (p.includeSystemPromptSection !== undefined) {\n h.includeSystemPromptSection = Boolean(p.includeSystemPromptSection);\n }\n if (p.target !== undefined) {\n if (p.target === null || p.target === '') delete (h as { target?: string }).target;\n else (h as { target?: string }).target = String(p.target);\n }\n if (p.targetChatId !== undefined) {\n if (p.targetChatId === null || p.targetChatId === '') delete (h as { targetChatId?: string }).targetChatId;\n else (h as { targetChatId?: string }).targetChatId = String(p.targetChatId);\n }\n if (p.prompt !== undefined) {\n if (p.prompt === null || p.prompt === '') delete (h as { prompt?: string }).prompt;\n else (h as { prompt?: string }).prompt = String(p.prompt);\n }\n if (p.ackMaxChars !== undefined) {\n if (p.ackMaxChars === null || p.ackMaxChars === '') delete (h as { ackMaxChars?: number }).ackMaxChars;\n else if (typeof p.ackMaxChars === 'number' && Number.isFinite(p.ackMaxChars)) {\n (h as { ackMaxChars?: number }).ackMaxChars = p.ackMaxChars;\n }\n }\n if (p.isolatedSession !== undefined) {\n if (p.isolatedSession === null || p.isolatedSession === false) {\n delete (h as { isolatedSession?: boolean }).isolatedSession;\n } else {\n (h as { isolatedSession?: boolean }).isolatedSession = Boolean(p.isolatedSession);\n }\n }\n if (p.activeHours !== undefined) {\n if (p.activeHours === null) {\n delete (h as { activeHours?: unknown }).activeHours;\n } else if (typeof p.activeHours === 'object' && p.activeHours !== null) {\n const ah = p.activeHours as Record<string, unknown>;\n const start = typeof ah.start === 'string' ? ah.start : '';\n const end = typeof ah.end === 'string' ? ah.end : '';\n if (start && end) {\n (h as { activeHours?: { start: string; end: string; timezone?: string } }).activeHours = {\n start,\n end,\n ...(typeof ah.timezone === 'string' && ah.timezone.trim() ? { timezone: ah.timezone } : {}),\n };\n } else {\n delete (h as { activeHours?: unknown }).activeHours;\n }\n }\n }\n }\n if (body.gateway?.auth !== undefined) {\n if (!config.gateway) {\n config.gateway = {\n host: '0.0.0.0',\n port: 18790,\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: 100,\n corsOrigins: ['*'],\n };\n }\n if (!config.gateway.auth) config.gateway.auth = { mode: 'token' };\n const a = body.gateway.auth;\n if (a.mode !== undefined) {\n config.gateway.auth.mode = a.mode;\n }\n if (a.token !== undefined) {\n config.gateway.auth.token = a.token;\n }\n }\n\n if (body.update !== undefined && typeof body.update === 'object' && body.update !== null) {\n const p = body.update as Record<string, unknown>;\n if (p.channel === 'stable' || p.channel === 'beta' || p.channel === 'dev') {\n if (!config.update) {\n config.update = { checkOnStart: true, channel: p.channel };\n } else {\n config.update.channel = p.channel;\n }\n }\n }\n\n // Update providers config - save to credential system instead of config\n if (body.providers) {\n const resolver = new CredentialResolver();\n for (const [key, apiKey] of Object.entries(body.providers)) {\n if (\n apiKey !== undefined &&\n typeof apiKey === 'string' &&\n apiKey.trim() &&\n apiKey !== '***' &&\n apiKey !== '••••••••••••'\n ) {\n await resolver.saveApiKey(key, apiKey, { profileName: 'default' });\n }\n }\n }\n\n // Update STT config\n if (body.stt !== undefined) {\n config.stt = body.stt;\n }\n\n // Update TTS config\n if (body.tts !== undefined) {\n config.tts = body.tts;\n }\n\n const toolsPatchErr = applyToolsWebPatch(config, body as Record<string, unknown>);\n if (toolsPatchErr) {\n return c.json({ ok: false, error: { message: toolsPatchErr } }, 400);\n }\n\n if (body.bindings !== undefined) {\n if (!Array.isArray(body.bindings)) {\n return c.json({ ok: false, error: { message: 'bindings must be an array' } }, 400);\n }\n const parsed = BindingsConfigSchema.safeParse(body.bindings);\n if (!parsed.success) {\n return c.json(\n { ok: false, error: { message: parsed.error.issues.map((i) => i.message).join('; ') } },\n 400,\n );\n }\n config.bindings = parsed.data;\n }\n\n // Save config\n const result = await service.saveConfig(config);\n if (!result.saved) {\n return c.json({ ok: false, error: result.error }, 500);\n }\n\n if (body.gateway?.heartbeat !== undefined && typeof body.gateway.heartbeat === 'object') {\n service.reloadHeartbeatFromCurrentConfig();\n }\n\n const safeConfig = await buildSafeWebConfigPayload(service);\n return c.json({ ok: true, payload: { config: safeConfig } });\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"config.js","names":[],"sources":["../../../../../src/gateway/hono/routes/config.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { type Config, BindingsConfigSchema } from '../../../config/schema.js';\nimport { CredentialResolver } from '../../../auth/credentials.js';\nimport { applyToolsWebPatch } from '../../config-tools-web.js';\nimport { buildSafeWebConfigPayload } from '../lib/config-payload.js';\nimport { normalizePatchAgentModel } from '../lib/agent-model.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nexport function registerConfigRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service, strictRateLimitMiddleware } = deps;\n\n authenticated.post('/api/config/reload', strictRateLimitMiddleware, async (c) => {\n const result = await service.reloadConfig();\n return c.json({ ok: true, payload: result });\n });\n\n authenticated.post('/api/heartbeat/trigger', strictRateLimitMiddleware, async (c) => {\n let reason = 'manual';\n try {\n const body = await c.req.json();\n if (body && typeof body === 'object' && typeof (body as { reason?: unknown }).reason === 'string') {\n const r = (body as { reason: string }).reason.trim();\n if (r) reason = r.slice(0, 120);\n }\n } catch {\n /* empty or invalid body */\n }\n service.requestHeartbeatNow({ reason });\n return c.json({ ok: true, payload: { scheduled: true } });\n });\n\n authenticated.get('/api/config', async (c) => {\n const safeConfig = await buildSafeWebConfigPayload(service);\n return c.json({ ok: true, payload: { config: safeConfig } });\n });\n\n authenticated.patch('/api/config', strictRateLimitMiddleware, async (c) => {\n const body = await c.req.json();\n \n // Merge updates into current config\n const config: Config = service.currentConfig as Config;\n \n // Update agent defaults\n if (body.agents?.defaults) {\n if (!config.agents) config.agents = { defaults: { workspace: '~/.xopc/workspace', model: 'anthropic/claude-sonnet-4-5', maxTokens: 8192, temperature: 0.7, maxToolIterations: 20, maxRequestsPerTurn: 50, maxToolFailuresPerTurn: 3, thinkingDefault: 'medium', reasoningDefault: 'stream', verboseDefault: 'full' } };\n if (!config.agents.defaults) config.agents.defaults = {} as any;\n \n if (body.agents.defaults.model !== undefined) {\n config.agents.defaults.model = normalizePatchAgentModel(body.agents.defaults.model) as Config['agents']['defaults']['model'];\n }\n if (body.agents.defaults.maxTokens !== undefined) {\n config.agents.defaults.maxTokens = body.agents.defaults.maxTokens;\n }\n if (body.agents.defaults.temperature !== undefined) {\n config.agents.defaults.temperature = body.agents.defaults.temperature;\n }\n if (body.agents.defaults.maxToolIterations !== undefined) {\n config.agents.defaults.maxToolIterations = body.agents.defaults.maxToolIterations;\n }\n if (body.agents.defaults.workspace !== undefined) {\n config.agents.defaults.workspace = body.agents.defaults.workspace;\n }\n if (body.agents.defaults.thinkingDefault !== undefined) {\n config.agents.defaults.thinkingDefault = body.agents.defaults.thinkingDefault;\n }\n if (body.agents.defaults.reasoningDefault !== undefined) {\n config.agents.defaults.reasoningDefault = body.agents.defaults.reasoningDefault;\n }\n if (body.agents.defaults.verboseDefault !== undefined) {\n config.agents.defaults.verboseDefault = body.agents.defaults.verboseDefault;\n }\n if (body.agents.defaults.imageModel !== undefined) {\n const v = body.agents.defaults.imageModel;\n if (v === '' || v === null) {\n delete (config.agents.defaults as Record<string, unknown>).imageModel;\n } else {\n config.agents.defaults.imageModel = normalizePatchAgentModel(v) as Config['agents']['defaults']['imageModel'];\n }\n }\n if (body.agents.defaults.imageGenerationModel !== undefined) {\n const v = body.agents.defaults.imageGenerationModel;\n if (v === '' || v === null) {\n delete (config.agents.defaults as Record<string, unknown>).imageGenerationModel;\n } else {\n config.agents.defaults.imageGenerationModel = normalizePatchAgentModel(\n v,\n ) as Config['agents']['defaults']['imageGenerationModel'];\n }\n }\n if (body.agents.defaults.mediaMaxMb !== undefined) {\n const v = body.agents.defaults.mediaMaxMb;\n if (v === null) {\n delete (config.agents.defaults as Record<string, unknown>).mediaMaxMb;\n } else {\n const n = typeof v === 'number' ? v : Number(v);\n if (!Number.isNaN(n) && n > 0) {\n config.agents.defaults.mediaMaxMb = n;\n }\n }\n }\n if (body.agents.defaults.browser !== undefined) {\n const b = body.agents.defaults.browser;\n if (b === null) {\n delete (config.agents.defaults as Record<string, unknown>).browser;\n } else if (typeof b === 'object' && !Array.isArray(b)) {\n const br = b as Record<string, unknown>;\n if (!config.agents.defaults.browser) {\n config.agents.defaults.browser = { enabled: false, headless: true };\n }\n const target = config.agents.defaults.browser;\n if (br.enabled !== undefined) {\n target.enabled = Boolean(br.enabled);\n }\n if (br.headless !== undefined) {\n target.headless = Boolean(br.headless);\n }\n }\n }\n\n const dPatch = body.agents.defaults as Record<string, unknown>;\n const def = config.agents.defaults as Record<string, unknown>;\n\n if (dPatch.maxTaskDurationMs !== undefined) {\n const v = dPatch.maxTaskDurationMs;\n if (v === null) {\n delete def.maxTaskDurationMs;\n } else if (typeof v === 'number' && Number.isFinite(v)) {\n const ms = Math.floor(v);\n if (ms >= 60_000 && ms <= 14_400_000) {\n def.maxTaskDurationMs = ms;\n }\n }\n }\n if (dPatch.maxRequestsPerTurn !== undefined) {\n const v = dPatch.maxRequestsPerTurn;\n if (v === null) {\n delete def.maxRequestsPerTurn;\n } else if (typeof v === 'number' && Number.isFinite(v)) {\n const n = Math.floor(v);\n if (n >= 10 && n <= 200) {\n def.maxRequestsPerTurn = n;\n }\n }\n }\n if (dPatch.maxToolFailuresPerTurn !== undefined) {\n const v = dPatch.maxToolFailuresPerTurn;\n if (v === null) {\n delete def.maxToolFailuresPerTurn;\n } else if (typeof v === 'number' && Number.isFinite(v)) {\n const n = Math.floor(v);\n if (n >= 1 && n <= 20) {\n def.maxToolFailuresPerTurn = n;\n }\n }\n }\n\n if (dPatch.compaction !== undefined) {\n const c = dPatch.compaction;\n if (c === null) {\n delete def.compaction;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.compaction || typeof def.compaction !== 'object') {\n def.compaction = {};\n }\n const t = def.compaction as Record<string, unknown>;\n if (p.enabled !== undefined) t.enabled = Boolean(p.enabled);\n if (p.mode === 'default' || p.mode === 'safeguard') t.mode = p.mode;\n if (typeof p.reserveTokens === 'number' && Number.isFinite(p.reserveTokens)) {\n t.reserveTokens = Math.floor(p.reserveTokens);\n }\n if (typeof p.triggerThreshold === 'number' && Number.isFinite(p.triggerThreshold)) {\n const x = p.triggerThreshold;\n if (x >= 0.5 && x <= 0.95) t.triggerThreshold = x;\n }\n if (typeof p.minMessagesBeforeCompact === 'number' && Number.isFinite(p.minMessagesBeforeCompact)) {\n t.minMessagesBeforeCompact = Math.floor(p.minMessagesBeforeCompact);\n }\n if (typeof p.keepRecentMessages === 'number' && Number.isFinite(p.keepRecentMessages)) {\n t.keepRecentMessages = Math.floor(p.keepRecentMessages);\n }\n if (typeof p.evictionWindow === 'number' && Number.isFinite(p.evictionWindow)) {\n const x = p.evictionWindow;\n if (x >= 0.1 && x <= 0.5) t.evictionWindow = x;\n }\n if (typeof p.retentionWindow === 'number' && Number.isFinite(p.retentionWindow)) {\n const n = Math.floor(p.retentionWindow);\n if (n >= 3 && n <= 20) t.retentionWindow = n;\n }\n }\n }\n\n if (dPatch.pruning !== undefined) {\n const c = dPatch.pruning;\n if (c === null) {\n delete def.pruning;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.pruning || typeof def.pruning !== 'object') {\n def.pruning = {};\n }\n const t = def.pruning as Record<string, unknown>;\n if (p.enabled !== undefined) t.enabled = Boolean(p.enabled);\n if (typeof p.maxToolResultChars === 'number' && Number.isFinite(p.maxToolResultChars)) {\n t.maxToolResultChars = Math.floor(p.maxToolResultChars);\n }\n if (typeof p.headKeepRatio === 'number' && Number.isFinite(p.headKeepRatio)) {\n t.headKeepRatio = p.headKeepRatio;\n }\n if (typeof p.tailKeepRatio === 'number' && Number.isFinite(p.tailKeepRatio)) {\n t.tailKeepRatio = p.tailKeepRatio;\n }\n }\n }\n\n if (dPatch.memory !== undefined) {\n const c = dPatch.memory;\n if (c === null) {\n delete def.memory;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.memory || typeof def.memory !== 'object') {\n def.memory = {};\n }\n const t = def.memory as Record<string, unknown>;\n if (p.enabled !== undefined) {\n if (p.enabled === null) delete t.enabled;\n else t.enabled = Boolean(p.enabled);\n }\n if (p.useEnhancedSystem !== undefined) {\n if (p.useEnhancedSystem === null) delete t.useEnhancedSystem;\n else t.useEnhancedSystem = Boolean(p.useEnhancedSystem);\n }\n if (p.userProfileEnabled !== undefined) {\n if (p.userProfileEnabled === null) delete t.userProfileEnabled;\n else t.userProfileEnabled = Boolean(p.userProfileEnabled);\n }\n if (p.memoryCharLimit !== undefined) {\n if (p.memoryCharLimit === null) delete t.memoryCharLimit;\n else if (typeof p.memoryCharLimit === 'number' && p.memoryCharLimit > 0) {\n t.memoryCharLimit = Math.floor(p.memoryCharLimit);\n }\n }\n if (p.userCharLimit !== undefined) {\n if (p.userCharLimit === null) delete t.userCharLimit;\n else if (typeof p.userCharLimit === 'number' && p.userCharLimit > 0) {\n t.userCharLimit = Math.floor(p.userCharLimit);\n }\n }\n if (p.provider === 'none' || p.provider === 'stub') {\n t.provider = p.provider;\n } else if (p.provider === null) {\n delete t.provider;\n }\n if (p.injectionFrequency === 'every-turn' || p.injectionFrequency === 'first-turn') {\n t.injectionFrequency = p.injectionFrequency;\n } else if (p.injectionFrequency === null) {\n delete t.injectionFrequency;\n }\n if (p.contextCadence !== undefined) {\n if (p.contextCadence === null) delete t.contextCadence;\n else if (typeof p.contextCadence === 'number' && p.contextCadence >= 1) {\n t.contextCadence = Math.floor(p.contextCadence);\n }\n }\n if (p.dialecticCadence !== undefined) {\n if (p.dialecticCadence === null) delete t.dialecticCadence;\n else if (typeof p.dialecticCadence === 'number' && p.dialecticCadence >= 1) {\n t.dialecticCadence = Math.floor(p.dialecticCadence);\n }\n }\n\n // Dreaming (schemaless patch): agents.defaults.memory.dreaming\n if (p.dreaming !== undefined) {\n const d0 = p.dreaming;\n if (d0 === null) {\n delete (t as { dreaming?: unknown }).dreaming;\n } else if (typeof d0 === 'object' && d0 !== null && !Array.isArray(d0)) {\n if (!('dreaming' in t) || typeof (t as { dreaming?: unknown }).dreaming !== 'object') {\n (t as { dreaming?: Record<string, unknown> }).dreaming = {};\n }\n const dt = (t as { dreaming: Record<string, unknown> }).dreaming;\n const dp = d0 as Record<string, unknown>;\n\n if (dp.enabled !== undefined) {\n if (dp.enabled === null) delete dt.enabled;\n else dt.enabled = Boolean(dp.enabled);\n }\n if (dp.frequency !== undefined) {\n const v = dp.frequency;\n if (v === null || v === '') delete dt.frequency;\n else if (typeof v === 'string') dt.frequency = v;\n }\n if (dp.timezone !== undefined) {\n const v = dp.timezone;\n if (v === null || v === '') delete dt.timezone;\n else if (typeof v === 'string') dt.timezone = v;\n }\n\n // Accept either `phases.deep` or `deep`.\n if (dp.phases !== undefined || dp.deep !== undefined) {\n if (!('phases' in dt) || typeof (dt as { phases?: unknown }).phases !== 'object' || (dt as { phases?: unknown }).phases === null) {\n dt.phases = {};\n }\n const phases = (dt as { phases: Record<string, unknown> }).phases;\n if (!('deep' in phases) || typeof phases.deep !== 'object' || phases.deep === null) {\n phases.deep = {};\n }\n const deep = phases.deep as Record<string, unknown>;\n\n const deepPatchRaw =\n typeof dp.phases === 'object' && dp.phases !== null && !Array.isArray(dp.phases)\n ? (dp.phases as Record<string, unknown>).deep\n : dp.deep;\n const deepPatch =\n typeof deepPatchRaw === 'object' && deepPatchRaw !== null && !Array.isArray(deepPatchRaw)\n ? (deepPatchRaw as Record<string, unknown>)\n : null;\n\n if (deepPatch) {\n if (deepPatch.enabled !== undefined) {\n if (deepPatch.enabled === null) delete deep.enabled;\n else deep.enabled = Boolean(deepPatch.enabled);\n }\n if (deepPatch.minScore !== undefined) {\n const v = deepPatch.minScore;\n if (v === null) delete deep.minScore;\n else if (typeof v === 'number' && Number.isFinite(v)) deep.minScore = v;\n }\n if (deepPatch.minRecallCount !== undefined) {\n const v = deepPatch.minRecallCount;\n if (v === null) delete deep.minRecallCount;\n else if (typeof v === 'number' && Number.isFinite(v)) deep.minRecallCount = Math.floor(v);\n }\n if (deepPatch.limit !== undefined) {\n const v = deepPatch.limit;\n if (v === null) delete deep.limit;\n else if (typeof v === 'number' && Number.isFinite(v)) deep.limit = Math.floor(v);\n }\n }\n }\n }\n }\n }\n }\n\n if (dPatch.sessionSearch !== undefined) {\n const c = dPatch.sessionSearch;\n if (c === null) {\n delete def.sessionSearch;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.sessionSearch || typeof def.sessionSearch !== 'object') {\n def.sessionSearch = {};\n }\n const t = def.sessionSearch as Record<string, unknown>;\n if (p.summaryModel !== undefined) {\n if (p.summaryModel === null || p.summaryModel === '') {\n delete t.summaryModel;\n } else if (typeof p.summaryModel === 'string') {\n t.summaryModel = p.summaryModel;\n }\n }\n }\n }\n\n if (dPatch.backgroundReview !== undefined) {\n const c = dPatch.backgroundReview;\n if (c === null) {\n delete def.backgroundReview;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.backgroundReview || typeof def.backgroundReview !== 'object') {\n def.backgroundReview = {};\n }\n const t = def.backgroundReview as Record<string, unknown>;\n if (p.enabled !== undefined) {\n if (p.enabled === null) delete t.enabled;\n else t.enabled = Boolean(p.enabled);\n }\n if (p.memoryNudgeInterval !== undefined) {\n if (p.memoryNudgeInterval === null) delete t.memoryNudgeInterval;\n else if (typeof p.memoryNudgeInterval === 'number' && p.memoryNudgeInterval >= 0) {\n t.memoryNudgeInterval = Math.floor(p.memoryNudgeInterval);\n }\n }\n if (p.skillNudgeInterval !== undefined) {\n if (p.skillNudgeInterval === null) delete t.skillNudgeInterval;\n else if (typeof p.skillNudgeInterval === 'number' && p.skillNudgeInterval >= 0) {\n t.skillNudgeInterval = Math.floor(p.skillNudgeInterval);\n }\n }\n if (p.maxToolRounds !== undefined) {\n if (p.maxToolRounds === null) delete t.maxToolRounds;\n else if (typeof p.maxToolRounds === 'number' && p.maxToolRounds >= 1 && p.maxToolRounds <= 32) {\n t.maxToolRounds = Math.floor(p.maxToolRounds);\n }\n }\n if (p.maxHistoryMessages !== undefined) {\n if (p.maxHistoryMessages === null) delete t.maxHistoryMessages;\n else if (typeof p.maxHistoryMessages === 'number' && p.maxHistoryMessages >= 10 && p.maxHistoryMessages <= 200) {\n t.maxHistoryMessages = Math.floor(p.maxHistoryMessages);\n }\n }\n if (p.maxDurationMs !== undefined) {\n if (p.maxDurationMs === null) delete t.maxDurationMs;\n else if (typeof p.maxDurationMs === 'number' && p.maxDurationMs >= 30_000 && p.maxDurationMs <= 600_000) {\n t.maxDurationMs = Math.floor(p.maxDurationMs);\n }\n }\n }\n }\n\n if (dPatch.webExtract !== undefined) {\n const c = dPatch.webExtract;\n if (c === null) {\n delete def.webExtract;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.webExtract || typeof def.webExtract !== 'object') {\n def.webExtract = {};\n }\n const t = def.webExtract as Record<string, unknown>;\n if (p.model !== undefined) {\n if (p.model === null || p.model === '') {\n delete t.model;\n } else if (typeof p.model === 'string') {\n t.model = p.model;\n }\n }\n if (p.maxLength !== undefined) {\n if (p.maxLength === null) delete t.maxLength;\n else if (typeof p.maxLength === 'number' && p.maxLength > 0) {\n t.maxLength = p.maxLength;\n }\n }\n }\n }\n\n if (dPatch.delegate !== undefined) {\n const c = dPatch.delegate;\n if (c === null) {\n delete def.delegate;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.delegate || typeof def.delegate !== 'object') {\n def.delegate = {};\n }\n const t = def.delegate as Record<string, unknown>;\n if (p.enabled !== undefined) {\n if (p.enabled === null) delete t.enabled;\n else t.enabled = Boolean(p.enabled);\n }\n }\n }\n\n if (dPatch.executeCode !== undefined) {\n const c = dPatch.executeCode;\n if (c === null) {\n delete def.executeCode;\n } else if (typeof c === 'object' && !Array.isArray(c)) {\n const p = c as Record<string, unknown>;\n if (!def.executeCode || typeof def.executeCode !== 'object') {\n def.executeCode = {};\n }\n const t = def.executeCode as Record<string, unknown>;\n if (p.enabled !== undefined) {\n if (p.enabled === null) delete t.enabled;\n else t.enabled = Boolean(p.enabled);\n }\n }\n }\n\n if (dPatch.systemPromptOverride !== undefined) {\n const v = dPatch.systemPromptOverride;\n if (v === null || v === '') {\n delete def.systemPromptOverride;\n } else if (typeof v === 'string') {\n def.systemPromptOverride = v;\n }\n }\n\n if (dPatch.skills !== undefined) {\n const v = dPatch.skills;\n if (v === null) {\n delete def.skills;\n } else if (Array.isArray(v) && v.every((x) => typeof x === 'string')) {\n def.skills = v;\n }\n }\n\n if (dPatch.tools !== undefined) {\n const t0 = dPatch.tools;\n if (t0 === null) {\n delete def.tools;\n } else if (typeof t0 === 'object' && !Array.isArray(t0)) {\n const p = t0 as { disable?: unknown };\n if (!def.tools || typeof def.tools !== 'object') {\n def.tools = {};\n }\n const t = def.tools as { disable?: string[] };\n if (p.disable !== undefined) {\n if (p.disable === null || (Array.isArray(p.disable) && p.disable.length === 0)) {\n delete t.disable;\n } else if (Array.isArray(p.disable) && p.disable.every((x) => typeof x === 'string')) {\n t.disable = p.disable;\n }\n }\n }\n }\n\n if (dPatch.params !== undefined) {\n const v = dPatch.params;\n if (v === null) {\n delete def.params;\n } else if (typeof v === 'object' && !Array.isArray(v) && v !== null) {\n def.params = v as Record<string, unknown>;\n }\n }\n }\n \n // Update channels — use `in` / null so `weixin: null` removes the block; avoid `if (ch.weixin)` missing null.\n const patchChannels = body.channels;\n if (patchChannels != null && typeof patchChannels === 'object' && !Array.isArray(patchChannels)) {\n if ('telegram' in patchChannels) {\n const tgRaw = patchChannels.telegram;\n if (tgRaw === null) {\n if (config.channels) delete config.channels.telegram;\n } else if (typeof tgRaw === 'object' && !Array.isArray(tgRaw)) {\n const bodyTg = tgRaw as Record<string, unknown>;\n if (!config.channels) config.channels = { telegram: { enabled: false, botToken: '', allowFrom: [], groupAllowFrom: [], debug: false, dmPolicy: 'pairing' as const, groupPolicy: 'open' as const, replyToMode: 'off' as const, historyLimit: 50, textChunkLimit: 4000 } };\n if (!config.channels.telegram) config.channels.telegram = {} as any;\n const tg = config.channels.telegram as Record<string, unknown>;\n\n if (bodyTg.enabled !== undefined) {\n tg.enabled = bodyTg.enabled;\n }\n if (bodyTg.botToken !== undefined) {\n tg.botToken = bodyTg.botToken;\n }\n if (bodyTg.allowFrom !== undefined) {\n tg.allowFrom = bodyTg.allowFrom;\n }\n if (bodyTg.apiRoot !== undefined) {\n tg.apiRoot = bodyTg.apiRoot;\n }\n if (bodyTg.debug !== undefined) {\n tg.debug = bodyTg.debug;\n }\n if (bodyTg.streamMode !== undefined) {\n tg.streamMode = bodyTg.streamMode;\n }\n if (bodyTg.groupAllowFrom !== undefined) {\n tg.groupAllowFrom = bodyTg.groupAllowFrom;\n }\n if (bodyTg.dmPolicy !== undefined) {\n tg.dmPolicy = bodyTg.dmPolicy;\n }\n if (bodyTg.groupPolicy !== undefined) {\n tg.groupPolicy = bodyTg.groupPolicy;\n }\n if (bodyTg.replyToMode !== undefined) {\n tg.replyToMode = bodyTg.replyToMode;\n }\n if (bodyTg.historyLimit !== undefined) {\n tg.historyLimit = bodyTg.historyLimit;\n }\n if (bodyTg.textChunkLimit !== undefined) {\n tg.textChunkLimit = bodyTg.textChunkLimit;\n }\n if (bodyTg.proxy !== undefined) {\n tg.proxy = bodyTg.proxy;\n }\n if (bodyTg.accounts !== undefined) {\n tg.accounts = bodyTg.accounts;\n }\n }\n }\n\n if ('weixin' in patchChannels) {\n const wxRaw = patchChannels.weixin;\n if (wxRaw === null) {\n if (config.channels) delete config.channels.weixin;\n } else if (typeof wxRaw === 'object' && !Array.isArray(wxRaw)) {\n const wx = wxRaw as Record<string, unknown>;\n if (!config.channels) config.channels = {} as any;\n if (!config.channels.weixin) {\n config.channels.weixin = {\n enabled: false,\n dmPolicy: 'pairing',\n allowFrom: [],\n debug: false,\n historyLimit: 50,\n textChunkLimit: 4000,\n };\n }\n const wxTarget = config.channels.weixin as Record<string, unknown>;\n if (wx.enabled !== undefined) wxTarget.enabled = wx.enabled;\n if (wx.dmPolicy !== undefined) wxTarget.dmPolicy = wx.dmPolicy;\n if (wx.allowFrom !== undefined) wxTarget.allowFrom = wx.allowFrom;\n if (wx.debug !== undefined) wxTarget.debug = wx.debug;\n if (wx.streamMode !== undefined) wxTarget.streamMode = wx.streamMode;\n if (wx.historyLimit !== undefined) wxTarget.historyLimit = wx.historyLimit;\n if (wx.textChunkLimit !== undefined) wxTarget.textChunkLimit = wx.textChunkLimit;\n if ('routeTag' in wx) {\n const rt = wx.routeTag;\n if (rt === null || rt === undefined || rt === '') {\n delete wxTarget.routeTag;\n } else {\n wxTarget.routeTag = rt as string | number;\n }\n }\n if (wx.accounts !== undefined) wxTarget.accounts = wx.accounts;\n }\n }\n\n if ('feishu' in patchChannels) {\n const fsRaw = patchChannels.feishu;\n if (fsRaw === null) {\n if (config.channels) delete config.channels.feishu;\n } else if (typeof fsRaw === 'object' && !Array.isArray(fsRaw)) {\n const fs = fsRaw as Record<string, unknown>;\n if (!config.channels) config.channels = {} as any;\n if (!config.channels.feishu) {\n config.channels.feishu = {\n enabled: false,\n appId: '',\n appSecret: '',\n domain: 'feishu',\n connectionMode: 'websocket',\n dmPolicy: 'pairing',\n groupPolicy: 'allowlist',\n allowFrom: [],\n groupAllowFrom: [],\n requireMention: true,\n historyLimit: 50,\n textChunkLimit: 4000,\n accounts: {},\n };\n }\n const fsTarget = config.channels.feishu as Record<string, unknown>;\n\n if (fs.enabled !== undefined) fsTarget.enabled = fs.enabled;\n if (fs.defaultAccount !== undefined) {\n const da = fs.defaultAccount;\n if (da === null || da === '') delete fsTarget.defaultAccount;\n else fsTarget.defaultAccount = String(da);\n }\n if (fs.appId !== undefined) fsTarget.appId = fs.appId;\n if (fs.appSecret !== undefined) fsTarget.appSecret = fs.appSecret;\n if (fs.domain !== undefined) fsTarget.domain = fs.domain;\n if (fs.connectionMode !== undefined) fsTarget.connectionMode = fs.connectionMode;\n if (fs.verificationToken !== undefined) {\n const v = fs.verificationToken;\n if (v === null || (typeof v === 'string' && !String(v).trim())) delete fsTarget.verificationToken;\n else fsTarget.verificationToken = v;\n }\n if (fs.encryptKey !== undefined) {\n const v = fs.encryptKey;\n if (v === null || (typeof v === 'string' && !String(v).trim())) delete fsTarget.encryptKey;\n else fsTarget.encryptKey = v;\n }\n if (fs.webhookHost !== undefined) {\n const v = fs.webhookHost;\n if (v === null || (typeof v === 'string' && !String(v).trim())) delete fsTarget.webhookHost;\n else fsTarget.webhookHost = v;\n }\n if (fs.webhookPort !== undefined) fsTarget.webhookPort = fs.webhookPort;\n if (fs.webhookPath !== undefined) {\n const v = fs.webhookPath;\n if (v === null || (typeof v === 'string' && !String(v).trim())) delete fsTarget.webhookPath;\n else fsTarget.webhookPath = v;\n }\n if (fs.dmPolicy !== undefined) fsTarget.dmPolicy = fs.dmPolicy;\n if (fs.groupPolicy !== undefined) fsTarget.groupPolicy = fs.groupPolicy;\n if (fs.allowFrom !== undefined) fsTarget.allowFrom = fs.allowFrom;\n if (fs.groupAllowFrom !== undefined) {\n const ga = fs.groupAllowFrom;\n if (ga === null || (Array.isArray(ga) && ga.length === 0)) delete fsTarget.groupAllowFrom;\n else fsTarget.groupAllowFrom = ga;\n }\n if (fs.requireMention !== undefined) fsTarget.requireMention = fs.requireMention;\n if (fs.historyLimit !== undefined) fsTarget.historyLimit = fs.historyLimit;\n if (fs.textChunkLimit !== undefined) fsTarget.textChunkLimit = fs.textChunkLimit;\n if (fs.renderMode !== undefined) fsTarget.renderMode = fs.renderMode;\n if (fs.streaming !== undefined) fsTarget.streaming = fs.streaming;\n if (fs.reactionNotifications !== undefined) {\n fsTarget.reactionNotifications = fs.reactionNotifications;\n }\n if (fs.tools !== undefined) fsTarget.tools = fs.tools;\n if (fs.actions !== undefined) fsTarget.actions = fs.actions;\n if (fs.accounts !== undefined) fsTarget.accounts = fs.accounts;\n }\n }\n }\n \n // Update gateway heartbeat (partial merge)\n if (body.gateway?.heartbeat !== undefined && typeof body.gateway.heartbeat === 'object') {\n if (!config.gateway) {\n config.gateway = {\n host: '0.0.0.0',\n port: 18790,\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: 100,\n corsOrigins: ['*'],\n };\n }\n if (!config.gateway.heartbeat) {\n config.gateway.heartbeat = { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false };\n }\n const h = config.gateway.heartbeat;\n const p = body.gateway.heartbeat as Record<string, unknown>;\n if (p.enabled !== undefined) h.enabled = Boolean(p.enabled);\n if (p.intervalMs !== undefined && typeof p.intervalMs === 'number' && Number.isFinite(p.intervalMs)) {\n h.intervalMs = p.intervalMs;\n }\n if (p.includeSystemPromptSection !== undefined) {\n h.includeSystemPromptSection = Boolean(p.includeSystemPromptSection);\n }\n if (p.target !== undefined) {\n if (p.target === null || p.target === '') delete (h as { target?: string }).target;\n else (h as { target?: string }).target = String(p.target);\n }\n if (p.targetChatId !== undefined) {\n if (p.targetChatId === null || p.targetChatId === '') delete (h as { targetChatId?: string }).targetChatId;\n else (h as { targetChatId?: string }).targetChatId = String(p.targetChatId);\n }\n if (p.prompt !== undefined) {\n if (p.prompt === null || p.prompt === '') delete (h as { prompt?: string }).prompt;\n else (h as { prompt?: string }).prompt = String(p.prompt);\n }\n if (p.ackMaxChars !== undefined) {\n if (p.ackMaxChars === null || p.ackMaxChars === '') delete (h as { ackMaxChars?: number }).ackMaxChars;\n else if (typeof p.ackMaxChars === 'number' && Number.isFinite(p.ackMaxChars)) {\n (h as { ackMaxChars?: number }).ackMaxChars = p.ackMaxChars;\n }\n }\n if (p.isolatedSession !== undefined) {\n if (p.isolatedSession === null || p.isolatedSession === false) {\n delete (h as { isolatedSession?: boolean }).isolatedSession;\n } else {\n (h as { isolatedSession?: boolean }).isolatedSession = Boolean(p.isolatedSession);\n }\n }\n if (p.activeHours !== undefined) {\n if (p.activeHours === null) {\n delete (h as { activeHours?: unknown }).activeHours;\n } else if (typeof p.activeHours === 'object' && p.activeHours !== null) {\n const ah = p.activeHours as Record<string, unknown>;\n const start = typeof ah.start === 'string' ? ah.start : '';\n const end = typeof ah.end === 'string' ? ah.end : '';\n if (start && end) {\n (h as { activeHours?: { start: string; end: string; timezone?: string } }).activeHours = {\n start,\n end,\n ...(typeof ah.timezone === 'string' && ah.timezone.trim() ? { timezone: ah.timezone } : {}),\n };\n } else {\n delete (h as { activeHours?: unknown }).activeHours;\n }\n }\n }\n }\n if (body.gateway?.auth !== undefined) {\n if (!config.gateway) {\n config.gateway = {\n host: '0.0.0.0',\n port: 18790,\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: 100,\n corsOrigins: ['*'],\n };\n }\n if (!config.gateway.auth) config.gateway.auth = { mode: 'token' };\n const a = body.gateway.auth;\n if (a.mode !== undefined) {\n config.gateway.auth.mode = a.mode;\n }\n if (a.token !== undefined) {\n config.gateway.auth.token = a.token;\n }\n }\n\n if (body.update !== undefined && typeof body.update === 'object' && body.update !== null) {\n const p = body.update as Record<string, unknown>;\n if (p.channel === 'stable' || p.channel === 'beta' || p.channel === 'dev') {\n if (!config.update) {\n config.update = { checkOnStart: true, channel: p.channel };\n } else {\n config.update.channel = p.channel;\n }\n }\n }\n\n // Update providers config - save to credential system instead of config\n if (body.providers) {\n const resolver = new CredentialResolver();\n for (const [key, apiKey] of Object.entries(body.providers)) {\n if (\n apiKey !== undefined &&\n typeof apiKey === 'string' &&\n apiKey.trim() &&\n apiKey !== '***' &&\n apiKey !== '••••••••••••'\n ) {\n await resolver.saveApiKey(key, apiKey, { profileName: 'default' });\n }\n }\n }\n\n // Update STT config\n if (body.stt !== undefined) {\n config.stt = body.stt;\n }\n\n // Update TTS config\n if (body.tts !== undefined) {\n config.tts = body.tts;\n }\n\n const toolsPatchErr = applyToolsWebPatch(config, body as Record<string, unknown>);\n if (toolsPatchErr) {\n return c.json({ ok: false, error: { message: toolsPatchErr } }, 400);\n }\n\n if (body.bindings !== undefined) {\n if (!Array.isArray(body.bindings)) {\n return c.json({ ok: false, error: { message: 'bindings must be an array' } }, 400);\n }\n const parsed = BindingsConfigSchema.safeParse(body.bindings);\n if (!parsed.success) {\n return c.json(\n { ok: false, error: { message: parsed.error.issues.map((i) => i.message).join('; ') } },\n 400,\n );\n }\n config.bindings = parsed.data;\n }\n\n // Save config\n const result = await service.saveConfig(config);\n if (!result.saved) {\n return c.json({ ok: false, error: result.error }, 500);\n }\n\n if (body.gateway?.heartbeat !== undefined && typeof body.gateway.heartbeat === 'object') {\n service.reloadHeartbeatFromCurrentConfig();\n }\n\n const safeConfig = await buildSafeWebConfigPayload(service);\n return c.json({ ok: true, payload: { config: safeConfig } });\n });\n}\n"],"mappings":"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"}
@@ -38,6 +38,7 @@ function registerPublicGatewayRoutes(app, service) {
38
38
  "POST /api/agents",
39
39
  "PATCH /api/agents/:id",
40
40
  "DELETE /api/agents/:id",
41
+ "GET/PUT/DELETE /api/agents/:id/avatar",
41
42
  "GET/PUT /api/agents/:id/files/...",
42
43
  "DELETE /api/providers/:providerId/key",
43
44
  "PATCH /api/config",
@@ -1 +1 @@
1
- {"version":3,"file":"public-gateway.js","names":[],"sources":["../../../../../src/gateway/hono/routes/public-gateway.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { PACKAGE_VERSION } from '../../../package-version.js';\nimport type { GatewayService } from '../../service.js';\nimport { serveStaticFile } from '../lib/static-ui.js';\n\nexport function registerPublicGatewayRoutes(app: Hono, service: GatewayService): void {\n app.get('/health', (c) => {\n return c.json(service.getHealth());\n });\n\n /** Public liveness probe (no auth) — minimal payload for CLI / load balancers. */\n app.get('/api/health', (c) => {\n const health = service.getHealth();\n return c.json({\n status: 'ok',\n version: health.version,\n uptime: health.uptime,\n });\n });\n\n app.get('/api', (c) => {\n return c.json({\n service: 'xopc-gateway',\n version: PACKAGE_VERSION,\n transport: 'streamable-http',\n endpoints: [\n 'GET /health',\n 'GET /api/health',\n 'GET /status',\n 'GET /api/status',\n 'POST /api/agent (SSE stream / JSON)',\n 'POST /api/agent/abort',\n 'POST /api/agent/steer',\n 'POST /api/send',\n 'GET /api/events (SSE stream)',\n 'GET /api/channels/status',\n 'POST /api/channels/weixin/login/start',\n 'GET /api/channels/weixin/login/:sessionKey',\n 'GET /api/config',\n 'GET /api/agents',\n 'POST /api/agents',\n 'PATCH /api/agents/:id',\n 'DELETE /api/agents/:id',\n 'GET/PUT /api/agents/:id/files/...',\n 'DELETE /api/providers/:providerId/key',\n 'PATCH /api/config',\n 'POST /api/config/reload',\n 'POST /api/heartbeat/trigger',\n '... /api/cron/*',\n 'GET/PATCH /api/sessions/:key/agent-config',\n '... /api/sessions/*',\n 'GET /api/host/fs/meta',\n 'GET /api/host/fs/list',\n ],\n });\n });\n\n app.get('/assets/*', (c) => {\n const path = c.req.path.replace('/assets/', '');\n const response = serveStaticFile(`assets/${path}`);\n if (response) return response;\n return c.text('Not found', 404);\n });\n\n /** From `web/public/channel-icons/` (Vite copies to static root). Public: img requests send no Bearer token. */\n app.get('/channel-icons/*', (c) => {\n const path = c.req.path.replace('/channel-icons/', '');\n const response = serveStaticFile(`channel-icons/${path}`);\n if (response) return response;\n return c.text('Not found', 404);\n });\n\n app.get('/favicon.ico', (c) => {\n const response = serveStaticFile('favicon.ico');\n if (response) return response;\n return c.text('Not found', 404);\n });\n\n app.get('/logo.svg', (c) => {\n const response = serveStaticFile('logo.svg');\n if (response) return response;\n return c.text('Not found', 404);\n });\n\n app.get('/logo-dark.svg', (c) => {\n const response = serveStaticFile('logo-dark.svg');\n if (response) return response;\n return c.text('Not found', 404);\n });\n\n app.get('/', (c) => {\n const response = serveStaticFile('index.html');\n if (response) return response;\n return c.text('UI not found', 404);\n });\n}\n"],"mappings":";;;sBAE8D;AAI9D,SAAgB,4BAA4B,KAAW,SAA+B;AACpF,KAAI,IAAI,YAAY,MAAM;AACxB,SAAO,EAAE,KAAK,QAAQ,WAAW,CAAC;GAClC;;AAGF,KAAI,IAAI,gBAAgB,MAAM;EAC5B,MAAM,SAAS,QAAQ,WAAW;AAClC,SAAO,EAAE,KAAK;GACZ,QAAQ;GACR,SAAS,OAAO;GAChB,QAAQ,OAAO;GAChB,CAAC;GACF;AAEF,KAAI,IAAI,SAAS,MAAM;AACrB,SAAO,EAAE,KAAK;GACZ,SAAS;GACT,SAAS;GACT,WAAW;GACX,WAAW;IACT;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD;GACF,CAAC;GACF;AAEF,KAAI,IAAI,cAAc,MAAM;EAE1B,MAAM,WAAW,gBAAgB,UADpB,EAAE,IAAI,KAAK,QAAQ,YAAY,GACG,GAAG;AAClD,MAAI,SAAU,QAAO;AACrB,SAAO,EAAE,KAAK,aAAa,IAAI;GAC/B;;AAGF,KAAI,IAAI,qBAAqB,MAAM;EAEjC,MAAM,WAAW,gBAAgB,iBADpB,EAAE,IAAI,KAAK,QAAQ,mBAAmB,GACG,GAAG;AACzD,MAAI,SAAU,QAAO;AACrB,SAAO,EAAE,KAAK,aAAa,IAAI;GAC/B;AAEF,KAAI,IAAI,iBAAiB,MAAM;EAC7B,MAAM,WAAW,gBAAgB,cAAc;AAC/C,MAAI,SAAU,QAAO;AACrB,SAAO,EAAE,KAAK,aAAa,IAAI;GAC/B;AAEF,KAAI,IAAI,cAAc,MAAM;EAC1B,MAAM,WAAW,gBAAgB,WAAW;AAC5C,MAAI,SAAU,QAAO;AACrB,SAAO,EAAE,KAAK,aAAa,IAAI;GAC/B;AAEF,KAAI,IAAI,mBAAmB,MAAM;EAC/B,MAAM,WAAW,gBAAgB,gBAAgB;AACjD,MAAI,SAAU,QAAO;AACrB,SAAO,EAAE,KAAK,aAAa,IAAI;GAC/B;AAEF,KAAI,IAAI,MAAM,MAAM;EAClB,MAAM,WAAW,gBAAgB,aAAa;AAC9C,MAAI,SAAU,QAAO;AACrB,SAAO,EAAE,KAAK,gBAAgB,IAAI;GAClC"}
1
+ {"version":3,"file":"public-gateway.js","names":[],"sources":["../../../../../src/gateway/hono/routes/public-gateway.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { PACKAGE_VERSION } from '../../../package-version.js';\nimport type { GatewayService } from '../../service.js';\nimport { serveStaticFile } from '../lib/static-ui.js';\n\nexport function registerPublicGatewayRoutes(app: Hono, service: GatewayService): void {\n app.get('/health', (c) => {\n return c.json(service.getHealth());\n });\n\n /** Public liveness probe (no auth) — minimal payload for CLI / load balancers. */\n app.get('/api/health', (c) => {\n const health = service.getHealth();\n return c.json({\n status: 'ok',\n version: health.version,\n uptime: health.uptime,\n });\n });\n\n app.get('/api', (c) => {\n return c.json({\n service: 'xopc-gateway',\n version: PACKAGE_VERSION,\n transport: 'streamable-http',\n endpoints: [\n 'GET /health',\n 'GET /api/health',\n 'GET /status',\n 'GET /api/status',\n 'POST /api/agent (SSE stream / JSON)',\n 'POST /api/agent/abort',\n 'POST /api/agent/steer',\n 'POST /api/send',\n 'GET /api/events (SSE stream)',\n 'GET /api/channels/status',\n 'POST /api/channels/weixin/login/start',\n 'GET /api/channels/weixin/login/:sessionKey',\n 'GET /api/config',\n 'GET /api/agents',\n 'POST /api/agents',\n 'PATCH /api/agents/:id',\n 'DELETE /api/agents/:id',\n 'GET/PUT/DELETE /api/agents/:id/avatar',\n 'GET/PUT /api/agents/:id/files/...',\n 'DELETE /api/providers/:providerId/key',\n 'PATCH /api/config',\n 'POST /api/config/reload',\n 'POST /api/heartbeat/trigger',\n '... /api/cron/*',\n 'GET/PATCH /api/sessions/:key/agent-config',\n '... /api/sessions/*',\n 'GET /api/host/fs/meta',\n 'GET /api/host/fs/list',\n ],\n });\n });\n\n app.get('/assets/*', (c) => {\n const path = c.req.path.replace('/assets/', '');\n const response = serveStaticFile(`assets/${path}`);\n if (response) return response;\n return c.text('Not found', 404);\n });\n\n /** From `web/public/channel-icons/` (Vite copies to static root). Public: img requests send no Bearer token. */\n app.get('/channel-icons/*', (c) => {\n const path = c.req.path.replace('/channel-icons/', '');\n const response = serveStaticFile(`channel-icons/${path}`);\n if (response) return response;\n return c.text('Not found', 404);\n });\n\n app.get('/favicon.ico', (c) => {\n const response = serveStaticFile('favicon.ico');\n if (response) return response;\n return c.text('Not found', 404);\n });\n\n app.get('/logo.svg', (c) => {\n const response = serveStaticFile('logo.svg');\n if (response) return response;\n return c.text('Not found', 404);\n });\n\n app.get('/logo-dark.svg', (c) => {\n const response = serveStaticFile('logo-dark.svg');\n if (response) return response;\n return c.text('Not found', 404);\n });\n\n app.get('/', (c) => {\n const response = serveStaticFile('index.html');\n if (response) return response;\n return c.text('UI not found', 404);\n });\n}\n"],"mappings":";;;sBAE8D;AAI9D,SAAgB,4BAA4B,KAAW,SAA+B;AACpF,KAAI,IAAI,YAAY,MAAM;AACxB,SAAO,EAAE,KAAK,QAAQ,WAAW,CAAC;GAClC;;AAGF,KAAI,IAAI,gBAAgB,MAAM;EAC5B,MAAM,SAAS,QAAQ,WAAW;AAClC,SAAO,EAAE,KAAK;GACZ,QAAQ;GACR,SAAS,OAAO;GAChB,QAAQ,OAAO;GAChB,CAAC;GACF;AAEF,KAAI,IAAI,SAAS,MAAM;AACrB,SAAO,EAAE,KAAK;GACZ,SAAS;GACT,SAAS;GACT,WAAW;GACX,WAAW;IACT;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD;GACF,CAAC;GACF;AAEF,KAAI,IAAI,cAAc,MAAM;EAE1B,MAAM,WAAW,gBAAgB,UADpB,EAAE,IAAI,KAAK,QAAQ,YAAY,GACG,GAAG;AAClD,MAAI,SAAU,QAAO;AACrB,SAAO,EAAE,KAAK,aAAa,IAAI;GAC/B;;AAGF,KAAI,IAAI,qBAAqB,MAAM;EAEjC,MAAM,WAAW,gBAAgB,iBADpB,EAAE,IAAI,KAAK,QAAQ,mBAAmB,GACG,GAAG;AACzD,MAAI,SAAU,QAAO;AACrB,SAAO,EAAE,KAAK,aAAa,IAAI;GAC/B;AAEF,KAAI,IAAI,iBAAiB,MAAM;EAC7B,MAAM,WAAW,gBAAgB,cAAc;AAC/C,MAAI,SAAU,QAAO;AACrB,SAAO,EAAE,KAAK,aAAa,IAAI;GAC/B;AAEF,KAAI,IAAI,cAAc,MAAM;EAC1B,MAAM,WAAW,gBAAgB,WAAW;AAC5C,MAAI,SAAU,QAAO;AACrB,SAAO,EAAE,KAAK,aAAa,IAAI;GAC/B;AAEF,KAAI,IAAI,mBAAmB,MAAM;EAC/B,MAAM,WAAW,gBAAgB,gBAAgB;AACjD,MAAI,SAAU,QAAO;AACrB,SAAO,EAAE,KAAK,aAAa,IAAI;GAC/B;AAEF,KAAI,IAAI,MAAM,MAAM;EAClB,MAAM,WAAW,gBAAgB,aAAa;AAC9C,MAAI,SAAU,QAAO;AACrB,SAAO,EAAE,KAAK,gBAAgB,IAAI;GAClC"}
@@ -1,5 +1,6 @@
1
1
  import { buildSessionKey, init_session_key, parseSessionKey } from "../../../routing/session-key.js";
2
2
  import { agentExists, getDefaultAgentId, init_resolve_route } from "../../../routing/resolve-route.js";
3
+ import { messagesToClientHistory } from "../../../session/client-history.js";
3
4
  //#region src/gateway/hono/routes/sessions.ts
4
5
  init_session_key();
5
6
  init_resolve_route();
@@ -92,6 +93,22 @@ function registerSessionsRoutes(authenticated, deps) {
92
93
  }, 400);
93
94
  return c.json({ ok: true });
94
95
  });
96
+ authenticated.get("/api/sessions/:key/messages", async (c) => {
97
+ const key = c.req.param("key");
98
+ const limitRaw = c.req.query("limit");
99
+ const parsedLimit = limitRaw ? Number.parseInt(limitRaw, 10) : void 0;
100
+ const limit = parsedLimit !== void 0 && Number.isFinite(parsedLimit) ? Math.min(500, Math.max(1, parsedLimit)) : void 0;
101
+ const session = await service.getSession(key);
102
+ if (!session) return c.json({
103
+ ok: false,
104
+ error: "Session not found"
105
+ }, 404);
106
+ const messages = messagesToClientHistory(session.messages, { limit });
107
+ return c.json({
108
+ ok: true,
109
+ payload: { messages }
110
+ });
111
+ });
95
112
  authenticated.get("/api/sessions/:key", async (c) => {
96
113
  const key = c.req.param("key");
97
114
  const session = await service.getSession(key);
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.js","names":[],"sources":["../../../../../src/gateway/hono/routes/sessions.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { buildSessionKey, parseSessionKey } from '../../../routing/session-key.js';\nimport { agentExists, getDefaultAgentId } from '../../../routing/resolve-route.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nexport function registerSessionsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n\n // ========== Session REST API (/api/sessions) ==========\n\n // POST /api/sessions - Create new session (reuses empty sessions)\n authenticated.post('/api/sessions', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const channel = body.channel || 'webchat';\n const routingCfg = service.currentConfig;\n let agentId =\n typeof body.agentId === 'string' && body.agentId.trim()\n ? body.agentId.trim().toLowerCase()\n : getDefaultAgentId(routingCfg);\n if (!agentExists(agentId, routingCfg)) {\n agentId = getDefaultAgentId(routingCfg);\n }\n\n // If a specific chat_id is provided, use it (for advanced use cases)\n // Otherwise, try to find and reuse an existing empty session\n if (body.chat_id) {\n const sessionKey = buildSessionKey({\n agentId,\n source: channel,\n accountId: 'default',\n peerKind: 'direct',\n peerId: body.chat_id,\n });\n\n await service.sessionManagerInstance.saveMessages(sessionKey, []);\n const session = await service.getSession(sessionKey);\n return c.json({ session }, 201);\n }\n \n // Look for existing empty sessions to reuse\n const existingSessions = await service.listSessions({\n channel,\n limit: 50,\n sortBy: 'updatedAt',\n sortOrder: 'desc',\n });\n \n // Reuse an empty session only when it matches the requested agent (session key embeds agent id).\n const emptySession = existingSessions.items.find((s) => {\n if (s.messageCount !== 0) return false;\n const parsed = parseSessionKey(s.key);\n return parsed?.agentId === agentId;\n });\n \n if (emptySession) {\n // Return existing empty session instead of creating a new one\n const session = await service.getSession(emptySession.key);\n return c.json({ session, reused: true }, 200);\n }\n \n // No empty session found, create a new one\n const chatId = `chat_${Date.now()}`;\n const sessionKey = buildSessionKey({\n agentId,\n source: channel,\n accountId: 'default',\n peerKind: 'direct',\n peerId: chatId,\n });\n\n await service.sessionManagerInstance.saveMessages(sessionKey, []);\n\n const session = await service.getSession(sessionKey);\n return c.json({ session }, 201);\n });\n\n // GET /api/sessions - List sessions\n authenticated.get('/api/sessions', async (c) => {\n const query = c.req.query();\n const result = await service.listSessions({\n status: query.status as any,\n search: query.search,\n channel: query.channel,\n limit: query.limit ? parseInt(query.limit) : undefined,\n offset: query.offset ? parseInt(query.offset) : undefined,\n });\n return c.json(result);\n });\n\n // GET /api/sessions/stats - Get session stats (must be before /:key)\n authenticated.get('/api/sessions/stats', async (c) => {\n const result = await service.getSessionStats();\n return c.json(result);\n });\n\n // GET /api/sessions/chat-ids - Get unique chat IDs from sessions (must be before /:key)\n authenticated.get('/api/sessions/chat-ids', async (c) => {\n const channel = c.req.query('channel');\n const chatIds = await service.getSessionChatIds(channel || undefined);\n return c.json({ ok: true, payload: { chatIds } });\n });\n\n // GET /api/sessions/:key/agent-config — resolved session agent settings (thinking, etc.)\n authenticated.get('/api/sessions/:key/agent-config', async (c) => {\n const key = c.req.param('key');\n const payload = await service.getSessionAgentConfig(key);\n return c.json({ ok: true, payload });\n });\n\n authenticated.patch('/api/sessions/:key/agent-config', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const result = await service.patchSessionAgentConfig(key, body);\n if (!result.ok) {\n return c.json({ ok: false, error: result.error }, 400);\n }\n return c.json({ ok: true });\n });\n\n // GET /api/sessions/:key - Get single session (must be after /stats and /chat-ids)\n authenticated.get('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const session = await service.getSession(key);\n if (!session) {\n return c.json({ error: 'Session not found' }, 404);\n }\n return c.json({ session });\n });\n\n // GET /api/sessions/:key/export - Export session (must be before /:key)\n authenticated.get('/api/sessions/:key/export', async (c) => {\n const key = c.req.param('key');\n const format = c.req.query('format') as any || 'json';\n const result = await service.exportSession(key, format);\n return c.json(result);\n });\n\n // DELETE /api/sessions/:key/messages — delete a range of messages by index (before whole-session DELETE)\n authenticated.delete('/api/sessions/:key/messages', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const startIndex = typeof body.startIndex === 'number' ? body.startIndex : -1;\n const count = typeof body.count === 'number' ? body.count : 0;\n if (startIndex < 0 || count <= 0) {\n return c.json({ error: 'Invalid startIndex or count' }, 400);\n }\n const loaded = await service.sessionManagerInstance.loadMessages(key);\n if (!loaded || startIndex >= loaded.length) {\n return c.json({ error: 'Index out of range' }, 400);\n }\n const deleteCount = Math.min(count, loaded.length - startIndex);\n const next = loaded.slice(0, startIndex).concat(loaded.slice(startIndex + deleteCount));\n await service.sessionManagerInstance.saveMessages(key, next);\n return c.json({ ok: true, deleted: deleteCount });\n });\n\n // DELETE /api/sessions/:key - Delete session\n authenticated.delete('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const result = await service.deleteSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/archive - Archive session\n authenticated.post('/api/sessions/:key/archive', async (c) => {\n const key = c.req.param('key');\n const result = await service.archiveSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/unarchive - Unarchive session\n authenticated.post('/api/sessions/:key/unarchive', async (c) => {\n const key = c.req.param('key');\n const result = await service.unarchiveSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/pin - Pin session\n authenticated.post('/api/sessions/:key/pin', async (c) => {\n const key = c.req.param('key');\n const result = await service.pinSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/unpin - Unpin session\n authenticated.post('/api/sessions/:key/unpin', async (c) => {\n const key = c.req.param('key');\n const result = await service.unpinSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/rename - Rename session\n authenticated.post('/api/sessions/:key/rename', async (c) => {\n const key = c.req.param('key');\n\n const body = await c.req.json();\n const { name } = body;\n const result = await service.renameSession(key, name);\n return c.json(result);\n });\n\n // ========== Subagent REST API (/api/subagents) ==========\n\n // GET /api/subagents - List subagent sessions\n authenticated.get('/api/subagents', async (c) => {\n const query = c.req.query();\n const result = await service.listSubagents({\n limit: query.limit ? parseInt(query.limit) : undefined,\n offset: query.offset ? parseInt(query.offset) : undefined,\n });\n return c.json(result);\n });\n\n // GET /api/subagents/:key - Get subagent session detail\n authenticated.get('/api/subagents/:key', async (c) => {\n const key = c.req.param('key');\n // Verify it's a subagent session\n if (!key.startsWith('subagent:')) {\n return c.json({ error: 'Not a subagent session' }, 400);\n }\n const session = await service.getSession(key);\n if (!session) {\n return c.json({ error: 'Subagent session not found' }, 404);\n }\n return c.json({ session });\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sessions.js","names":[],"sources":["../../../../../src/gateway/hono/routes/sessions.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { buildSessionKey, parseSessionKey } from '../../../routing/session-key.js';\nimport { agentExists, getDefaultAgentId } from '../../../routing/resolve-route.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\nimport { messagesToClientHistory } from '../../../session/client-history.js';\n\nexport function registerSessionsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n\n // ========== Session REST API (/api/sessions) ==========\n\n // POST /api/sessions - Create new session (reuses empty sessions)\n authenticated.post('/api/sessions', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const channel = body.channel || 'webchat';\n const routingCfg = service.currentConfig;\n let agentId =\n typeof body.agentId === 'string' && body.agentId.trim()\n ? body.agentId.trim().toLowerCase()\n : getDefaultAgentId(routingCfg);\n if (!agentExists(agentId, routingCfg)) {\n agentId = getDefaultAgentId(routingCfg);\n }\n\n // If a specific chat_id is provided, use it (for advanced use cases)\n // Otherwise, try to find and reuse an existing empty session\n if (body.chat_id) {\n const sessionKey = buildSessionKey({\n agentId,\n source: channel,\n accountId: 'default',\n peerKind: 'direct',\n peerId: body.chat_id,\n });\n\n await service.sessionManagerInstance.saveMessages(sessionKey, []);\n const session = await service.getSession(sessionKey);\n return c.json({ session }, 201);\n }\n \n // Look for existing empty sessions to reuse\n const existingSessions = await service.listSessions({\n channel,\n limit: 50,\n sortBy: 'updatedAt',\n sortOrder: 'desc',\n });\n \n // Reuse an empty session only when it matches the requested agent (session key embeds agent id).\n const emptySession = existingSessions.items.find((s) => {\n if (s.messageCount !== 0) return false;\n const parsed = parseSessionKey(s.key);\n return parsed?.agentId === agentId;\n });\n \n if (emptySession) {\n // Return existing empty session instead of creating a new one\n const session = await service.getSession(emptySession.key);\n return c.json({ session, reused: true }, 200);\n }\n \n // No empty session found, create a new one\n const chatId = `chat_${Date.now()}`;\n const sessionKey = buildSessionKey({\n agentId,\n source: channel,\n accountId: 'default',\n peerKind: 'direct',\n peerId: chatId,\n });\n\n await service.sessionManagerInstance.saveMessages(sessionKey, []);\n\n const session = await service.getSession(sessionKey);\n return c.json({ session }, 201);\n });\n\n // GET /api/sessions - List sessions\n authenticated.get('/api/sessions', async (c) => {\n const query = c.req.query();\n const result = await service.listSessions({\n status: query.status as any,\n search: query.search,\n channel: query.channel,\n limit: query.limit ? parseInt(query.limit) : undefined,\n offset: query.offset ? parseInt(query.offset) : undefined,\n });\n return c.json(result);\n });\n\n // GET /api/sessions/stats - Get session stats (must be before /:key)\n authenticated.get('/api/sessions/stats', async (c) => {\n const result = await service.getSessionStats();\n return c.json(result);\n });\n\n // GET /api/sessions/chat-ids - Get unique chat IDs from sessions (must be before /:key)\n authenticated.get('/api/sessions/chat-ids', async (c) => {\n const channel = c.req.query('channel');\n const chatIds = await service.getSessionChatIds(channel || undefined);\n return c.json({ ok: true, payload: { chatIds } });\n });\n\n // GET /api/sessions/:key/agent-config — resolved session agent settings (thinking, etc.)\n authenticated.get('/api/sessions/:key/agent-config', async (c) => {\n const key = c.req.param('key');\n const payload = await service.getSessionAgentConfig(key);\n return c.json({ ok: true, payload });\n });\n\n authenticated.patch('/api/sessions/:key/agent-config', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const result = await service.patchSessionAgentConfig(key, body);\n if (!result.ok) {\n return c.json({ ok: false, error: result.error }, 400);\n }\n return c.json({ ok: true });\n });\n\n // GET /api/sessions/:key/messages — flattened transcript for TUI / clients\n authenticated.get('/api/sessions/:key/messages', async (c) => {\n const key = c.req.param('key');\n const limitRaw = c.req.query('limit');\n const parsedLimit = limitRaw ? Number.parseInt(limitRaw, 10) : undefined;\n const limit =\n parsedLimit !== undefined && Number.isFinite(parsedLimit)\n ? Math.min(500, Math.max(1, parsedLimit))\n : undefined;\n\n const session = await service.getSession(key);\n if (!session) {\n return c.json({ ok: false, error: 'Session not found' }, 404);\n }\n\n const messages = messagesToClientHistory(session.messages, { limit });\n return c.json({ ok: true, payload: { messages } });\n });\n\n // GET /api/sessions/:key - Get single session (must be after /stats and /chat-ids)\n authenticated.get('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const session = await service.getSession(key);\n if (!session) {\n return c.json({ error: 'Session not found' }, 404);\n }\n return c.json({ session });\n });\n\n // GET /api/sessions/:key/export - Export session (must be before /:key)\n authenticated.get('/api/sessions/:key/export', async (c) => {\n const key = c.req.param('key');\n const format = c.req.query('format') as any || 'json';\n const result = await service.exportSession(key, format);\n return c.json(result);\n });\n\n // DELETE /api/sessions/:key/messages — delete a range of messages by index (before whole-session DELETE)\n authenticated.delete('/api/sessions/:key/messages', async (c) => {\n const key = c.req.param('key');\n const body = await c.req.json().catch(() => ({}));\n const startIndex = typeof body.startIndex === 'number' ? body.startIndex : -1;\n const count = typeof body.count === 'number' ? body.count : 0;\n if (startIndex < 0 || count <= 0) {\n return c.json({ error: 'Invalid startIndex or count' }, 400);\n }\n const loaded = await service.sessionManagerInstance.loadMessages(key);\n if (!loaded || startIndex >= loaded.length) {\n return c.json({ error: 'Index out of range' }, 400);\n }\n const deleteCount = Math.min(count, loaded.length - startIndex);\n const next = loaded.slice(0, startIndex).concat(loaded.slice(startIndex + deleteCount));\n await service.sessionManagerInstance.saveMessages(key, next);\n return c.json({ ok: true, deleted: deleteCount });\n });\n\n // DELETE /api/sessions/:key - Delete session\n authenticated.delete('/api/sessions/:key', async (c) => {\n const key = c.req.param('key');\n const result = await service.deleteSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/archive - Archive session\n authenticated.post('/api/sessions/:key/archive', async (c) => {\n const key = c.req.param('key');\n const result = await service.archiveSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/unarchive - Unarchive session\n authenticated.post('/api/sessions/:key/unarchive', async (c) => {\n const key = c.req.param('key');\n const result = await service.unarchiveSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/pin - Pin session\n authenticated.post('/api/sessions/:key/pin', async (c) => {\n const key = c.req.param('key');\n const result = await service.pinSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/unpin - Unpin session\n authenticated.post('/api/sessions/:key/unpin', async (c) => {\n const key = c.req.param('key');\n const result = await service.unpinSession(key);\n return c.json(result);\n });\n\n // POST /api/sessions/:key/rename - Rename session\n authenticated.post('/api/sessions/:key/rename', async (c) => {\n const key = c.req.param('key');\n\n const body = await c.req.json();\n const { name } = body;\n const result = await service.renameSession(key, name);\n return c.json(result);\n });\n\n // ========== Subagent REST API (/api/subagents) ==========\n\n // GET /api/subagents - List subagent sessions\n authenticated.get('/api/subagents', async (c) => {\n const query = c.req.query();\n const result = await service.listSubagents({\n limit: query.limit ? parseInt(query.limit) : undefined,\n offset: query.offset ? parseInt(query.offset) : undefined,\n });\n return c.json(result);\n });\n\n // GET /api/subagents/:key - Get subagent session detail\n authenticated.get('/api/subagents/:key', async (c) => {\n const key = c.req.param('key');\n // Verify it's a subagent session\n if (!key.startsWith('subagent:')) {\n return c.json({ error: 'Not a subagent session' }, 400);\n }\n const session = await service.getSession(key);\n if (!session) {\n return c.json({ error: 'Subagent session not found' }, 404);\n }\n return c.json({ session });\n });\n}\n"],"mappings":"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"}
@@ -170,6 +170,8 @@ export declare class GatewayService {
170
170
  }, unknown>;
171
171
  /** Abort an in-flight webchat agent run (matches `runId` from SSE `status`). */
172
172
  abortAgentRun(runId: string): boolean;
173
+ /** Background drain for extension-initiated webchat turns (`scheduleWebchatContinuation`). */
174
+ private drainScheduledWebchatContinuation;
173
175
  /**
174
176
  * Queue steering text for an active webchat run (`Agent.steer` / tool-boundary injection).
175
177
  * `chatId` is the same as `POST /api/agent` body (`sessionKey` or legacy peer id).
@@ -26,9 +26,9 @@ import { CHAT_CHANNEL_ORDER } from "../channels/registry.js";
26
26
  import { ExtensionLoader } from "../extensions/loader.js";
27
27
  import "../extensions/index.js";
28
28
  import { AgentService } from "../agent/service.js";
29
+ import { ChannelManager } from "../channels/manager.js";
29
30
  import { ConfigHotReloader } from "../config/reload.js";
30
31
  import "../config/index.js";
31
- import { ChannelManager } from "../channels/manager.js";
32
32
  import { CronService } from "../cron/service.js";
33
33
  import "../cron/index.js";
34
34
  import { computeBundledExtensionExtensionsPatch } from "../extensions/bundled-extension-activation.js";
@@ -207,7 +207,12 @@ var GatewayService = class {
207
207
  this.channelManager.enableOutboundPersistence(resolveAgentDir(this.config, getDefaultAgentId(this.config)));
208
208
  if (this.extensionLoader) this.extensionLoader.setRuntimeContext({
209
209
  bus: this.bus,
210
- sessionManager: this.sessionManager
210
+ sessionManager: this.sessionManager,
211
+ scheduleWebchatContinuation: (sessionKey, continuationMessage) => {
212
+ queueMicrotask(() => {
213
+ this.drainScheduledWebchatContinuation(sessionKey, continuationMessage);
214
+ });
215
+ }
211
216
  });
212
217
  await this.loadExtensionsAndRegisterChannels();
213
218
  await this.channelManager.initialize();
@@ -632,6 +637,7 @@ var GatewayService = class {
632
637
  if (!runAbort) throw new Error("run abort controller missing for webchat");
633
638
  const mergedSignal = runOptions?.signal ? AbortSignal.any([runOptions.signal, runAbort.signal]) : runAbort.signal;
634
639
  this.activeWebchatRunBySession.set(sessionKey, runId);
640
+ let streamError;
635
641
  try {
636
642
  this.emit("agent.stream", {
637
643
  sessionKey,
@@ -660,9 +666,10 @@ var GatewayService = class {
660
666
  };
661
667
  } catch (error) {
662
668
  log.error({ error }, "Agent processing failed");
669
+ streamError = error instanceof Error ? error.message : "Unknown error";
663
670
  const errorEvent = {
664
671
  type: "error",
665
- content: `Error: ${error instanceof Error ? error.message : "Unknown error"}`
672
+ content: `Error: ${streamError}`
666
673
  };
667
674
  this.runRelay.publish(runId, errorEvent);
668
675
  this.emit("agent.stream", {
@@ -673,11 +680,19 @@ var GatewayService = class {
673
680
  yield errorEvent;
674
681
  return {
675
682
  status: "error",
676
- summary: error instanceof Error ? error.message : "Unknown error"
683
+ summary: streamError
677
684
  };
678
685
  } finally {
679
686
  this.activeWebchatRunBySession.delete(sessionKey);
680
687
  this.runAbortControllers.delete(runId);
688
+ const assistantPlainText = this.agentService.getLastAssistantPlainText(sessionKey);
689
+ await this.agentService.emitWebchatTurnComplete({
690
+ sessionKey,
691
+ inboundUserText: message,
692
+ assistantPlainText,
693
+ aborted: mergedSignal.aborted,
694
+ ...streamError !== void 0 ? { streamError } : {}
695
+ });
681
696
  }
682
697
  }
683
698
  const correlationMeta = inboundCorrelationMetadataFromAsyncLogContext();
@@ -715,6 +730,18 @@ var GatewayService = class {
715
730
  c.abort();
716
731
  return true;
717
732
  }
733
+ /** Background drain for extension-initiated webchat turns (`scheduleWebchatContinuation`). */
734
+ async drainScheduledWebchatContinuation(sessionKey, message) {
735
+ try {
736
+ const gen = this.runAgent(message, "webchat", sessionKey, void 0, void 0, void 0);
737
+ for await (const _ of gen);
738
+ } catch (err) {
739
+ log.warn({
740
+ err,
741
+ sessionKey
742
+ }, "Scheduled webchat continuation failed");
743
+ }
744
+ }
718
745
  /**
719
746
  * Queue steering text for an active webchat run (`Agent.steer` / tool-boundary injection).
720
747
  * `chatId` is the same as `POST /api/agent` body (`sessionKey` or legacy peer id).