@xopcai/xopc 0.0.99 → 0.0.100

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 (349) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/src/account-manager.d.ts +3 -3
  3. package/dist/extensions/telegram/src/account-manager.js +8 -8
  4. package/dist/extensions/telegram/src/account-manager.js.map +1 -1
  5. package/dist/extensions/telegram/src/actions/message-actions.d.ts +4 -0
  6. package/dist/extensions/telegram/src/actions/message-actions.js +71 -0
  7. package/dist/extensions/telegram/src/actions/message-actions.js.map +1 -0
  8. package/dist/extensions/telegram/src/adapters/config-adapter.js +9 -1
  9. package/dist/extensions/telegram/src/adapters/config-adapter.js.map +1 -1
  10. package/dist/extensions/telegram/src/adapters/config-surface.js +1 -1
  11. package/dist/extensions/telegram/src/adapters/config-surface.js.map +1 -1
  12. package/dist/extensions/telegram/src/adapters/outbound-adapter.d.ts +2 -1
  13. package/dist/extensions/telegram/src/adapters/outbound-adapter.js +18 -4
  14. package/dist/extensions/telegram/src/adapters/outbound-adapter.js.map +1 -1
  15. package/dist/extensions/telegram/src/adapters/security-adapter.js +2 -1
  16. package/dist/extensions/telegram/src/adapters/security-adapter.js.map +1 -1
  17. package/dist/extensions/telegram/src/adapters/streaming-adapter.js +90 -6
  18. package/dist/extensions/telegram/src/adapters/streaming-adapter.js.map +1 -1
  19. package/dist/extensions/telegram/src/adapters/types.d.ts +9 -1
  20. package/dist/extensions/telegram/src/api-root.d.ts +4 -0
  21. package/dist/extensions/telegram/src/api-root.js +42 -0
  22. package/dist/extensions/telegram/src/api-root.js.map +1 -0
  23. package/dist/extensions/telegram/src/approval-delivery.d.ts +9 -0
  24. package/dist/extensions/telegram/src/approval-delivery.js +36 -0
  25. package/dist/extensions/telegram/src/approval-delivery.js.map +1 -0
  26. package/dist/extensions/telegram/src/approval-store.d.ts +25 -0
  27. package/dist/extensions/telegram/src/approval-store.js +61 -0
  28. package/dist/extensions/telegram/src/approval-store.js.map +1 -0
  29. package/dist/extensions/telegram/src/config-schema.d.ts +185 -35
  30. package/dist/extensions/telegram/src/config-schema.js +67 -45
  31. package/dist/extensions/telegram/src/config-schema.js.map +1 -1
  32. package/dist/extensions/telegram/src/conversation-id.d.ts +6 -0
  33. package/dist/extensions/telegram/src/conversation-id.js +18 -0
  34. package/dist/extensions/telegram/src/conversation-id.js.map +1 -0
  35. package/dist/extensions/telegram/src/doctor.d.ts +5 -0
  36. package/dist/extensions/telegram/src/doctor.js +80 -0
  37. package/dist/extensions/telegram/src/doctor.js.map +1 -0
  38. package/dist/extensions/telegram/src/exec-approval-handler.d.ts +7 -0
  39. package/dist/extensions/telegram/src/exec-approval-handler.js +36 -0
  40. package/dist/extensions/telegram/src/exec-approval-handler.js.map +1 -0
  41. package/dist/extensions/telegram/src/exec-approvals.d.ts +8 -0
  42. package/dist/extensions/telegram/src/exec-approvals.js +20 -0
  43. package/dist/extensions/telegram/src/exec-approvals.js.map +1 -0
  44. package/dist/extensions/telegram/src/focus-handler.d.ts +12 -0
  45. package/dist/extensions/telegram/src/focus-handler.js +55 -0
  46. package/dist/extensions/telegram/src/focus-handler.js.map +1 -0
  47. package/dist/extensions/telegram/src/group-config-resolver.d.ts +12 -0
  48. package/dist/extensions/telegram/src/group-config-resolver.js +17 -0
  49. package/dist/extensions/telegram/src/group-config-resolver.js.map +1 -0
  50. package/dist/extensions/telegram/src/inbound-coalescer.d.ts +15 -0
  51. package/dist/extensions/telegram/src/inbound-coalescer.js +107 -0
  52. package/dist/extensions/telegram/src/inbound-coalescer.js.map +1 -0
  53. package/dist/extensions/telegram/src/inbound-processor.d.ts +1 -0
  54. package/dist/extensions/telegram/src/inbound-processor.js +41 -4
  55. package/dist/extensions/telegram/src/inbound-processor.js.map +1 -1
  56. package/dist/extensions/telegram/src/network-errors.d.ts +2 -0
  57. package/dist/extensions/telegram/src/network-errors.js +23 -0
  58. package/dist/extensions/telegram/src/network-errors.js.map +1 -0
  59. package/dist/extensions/telegram/src/plugin.d.ts +11 -0
  60. package/dist/extensions/telegram/src/plugin.js +191 -57
  61. package/dist/extensions/telegram/src/plugin.js.map +1 -1
  62. package/dist/extensions/telegram/src/polling-session.d.ts +17 -0
  63. package/dist/extensions/telegram/src/polling-session.js +112 -0
  64. package/dist/extensions/telegram/src/polling-session.js.map +1 -0
  65. package/dist/extensions/telegram/src/proxy-fetch.d.ts +2 -0
  66. package/dist/extensions/telegram/src/proxy-fetch.js +14 -0
  67. package/dist/extensions/telegram/src/proxy-fetch.js.map +1 -0
  68. package/dist/extensions/telegram/src/reactions.d.ts +14 -0
  69. package/dist/extensions/telegram/src/reactions.js +48 -0
  70. package/dist/extensions/telegram/src/reactions.js.map +1 -0
  71. package/dist/extensions/telegram/src/reply-params.d.ts +15 -0
  72. package/dist/extensions/telegram/src/reply-params.js +28 -0
  73. package/dist/extensions/telegram/src/reply-params.js.map +1 -0
  74. package/dist/extensions/telegram/src/startup-errors.d.ts +3 -0
  75. package/dist/extensions/telegram/src/startup-errors.js +27 -0
  76. package/dist/extensions/telegram/src/startup-errors.js.map +1 -0
  77. package/dist/extensions/telegram/src/telegram-actions.d.ts +25 -0
  78. package/dist/extensions/telegram/src/telegram-actions.js +65 -0
  79. package/dist/extensions/telegram/src/telegram-actions.js.map +1 -0
  80. package/dist/extensions/telegram/src/thread-bindings.d.ts +15 -0
  81. package/dist/extensions/telegram/src/thread-bindings.js +22 -0
  82. package/dist/extensions/telegram/src/thread-bindings.js.map +1 -0
  83. package/dist/extensions/telegram/src/token-resolver.d.ts +8 -0
  84. package/dist/extensions/telegram/src/token-resolver.js +34 -0
  85. package/dist/extensions/telegram/src/token-resolver.js.map +1 -0
  86. package/dist/extensions/telegram/src/update-offset-store.d.ts +9 -0
  87. package/dist/extensions/telegram/src/update-offset-store.js +66 -0
  88. package/dist/extensions/telegram/src/update-offset-store.js.map +1 -0
  89. package/dist/extensions/telegram/xopc.extension.json +1 -1
  90. package/dist/gateway/static/root/assets/{agents-4KTK-Ku7.js → agents-C5jtBK-H.js} +1 -1
  91. package/dist/gateway/static/root/assets/{apps-page-DkgInY2w.js → apps-page-smJl-qf_.js} +1 -1
  92. package/dist/gateway/static/root/assets/channels-settings-CH6KgFK6.js +1 -0
  93. package/dist/gateway/static/root/assets/channels-status-swr-CV70xvY7.js +8 -0
  94. package/dist/gateway/static/root/assets/{cron-api-BRDli2Mm.js → cron-api-CgBO8B7I.js} +1 -1
  95. package/dist/gateway/static/root/assets/{cron-page-BzEr5Za8.js → cron-page-Be0cW1cR.js} +1 -1
  96. package/dist/gateway/static/root/assets/{dist-BsHh1vX0.js → dist-P8HRGUuh.js} +1 -1
  97. package/dist/gateway/static/root/assets/{extension-debug-page-TWt5q_ef.js → extension-debug-page-BowuycYu.js} +1 -1
  98. package/dist/gateway/static/root/assets/{extension-page-C3kV8ZvZ.js → extension-page-27-Zpv8O.js} +1 -1
  99. package/dist/gateway/static/root/assets/{extension-settings-page-Csy9LNC6.js → extension-settings-page-DDFa_rIq.js} +1 -1
  100. package/dist/gateway/static/root/assets/{fetch-BLLOP2CM.js → fetch-drJUxxKP.js} +1 -1
  101. package/dist/gateway/static/root/assets/{field-primitives-MXbM8HvY.js → field-primitives-BWLssxEb.js} +1 -1
  102. package/dist/gateway/static/root/assets/{heartbeat-config-api-CkoyqfRx.js → heartbeat-config-api-BVuYNYT_.js} +1 -1
  103. package/dist/gateway/static/root/assets/index-CRDAmr3W.js +4840 -0
  104. package/dist/gateway/static/root/assets/index-DjNDHzwG.css +1 -0
  105. package/dist/gateway/static/root/assets/{logs-page-B2vY41ph.js → logs-page-BDX8IrDQ.js} +1 -1
  106. package/dist/gateway/static/root/assets/{note-detail-page-B7qE5pkO.js → note-detail-page-BmQ9KeiA.js} +1 -1
  107. package/dist/gateway/static/root/assets/{note-time-NBBReVR4.js → note-time-14I9Sgqh.js} +1 -1
  108. package/dist/gateway/static/root/assets/{notes-page-CsWYaqYM.js → notes-page-BMfP0FFf.js} +1 -1
  109. package/dist/gateway/static/root/assets/{sessions-page-BPGY3SCT.js → sessions-page-C3scyChq.js} +1 -1
  110. package/dist/gateway/static/root/assets/{settings-advanced-gate-DtA451RM.js → settings-advanced-gate-2ODuCjHP.js} +1 -1
  111. package/dist/gateway/static/root/assets/{settings-form-section-DYR_SPlX.js → settings-form-section-DUoGKAiW.js} +1 -1
  112. package/dist/gateway/static/root/assets/{settings-page-BJUgZQzN.js → settings-page-CttAfOWV.js} +1 -1
  113. package/dist/gateway/static/root/assets/{share-preview-page-3u8VFmdo.js → share-preview-page-B77xqiiI.js} +1 -1
  114. package/dist/gateway/static/root/assets/{skills-page-DuyhcH4U.js → skills-page-B_bAZGzB.js} +1 -1
  115. package/dist/gateway/static/root/assets/{theme-store-e2q2yjs4.js → theme-store-BgCPrmxU.js} +1 -1
  116. package/dist/gateway/static/root/assets/url-q28QhI7l.js +3 -0
  117. package/dist/gateway/static/root/assets/{utils-B4Vw3fnc.js → utils-CCGejlcX.js} +1 -1
  118. package/dist/gateway/static/root/assets/{voice-api-key-field-BFY67Hhp.js → voice-api-key-field-DZzzihcY.js} +1 -1
  119. package/dist/gateway/static/root/assets/{workflow-page.utils-yUJ5jexd.js → workflow-page.utils-D5RMAmT4.js} +1 -1
  120. package/dist/gateway/static/root/assets/{workflows-page-DIMHCpNt.js → workflows-page-DEYpC6Bv.js} +1 -1
  121. package/dist/gateway/static/root/index.html +5 -5
  122. package/dist/package.js +1 -1
  123. package/dist/src/agent/agent-manager.d.ts +4 -0
  124. package/dist/src/agent/agent-manager.js +68 -4
  125. package/dist/src/agent/agent-manager.js.map +1 -1
  126. package/dist/src/agent/child-agent-factory.d.ts +1 -0
  127. package/dist/src/agent/child-agent-factory.js +13 -10
  128. package/dist/src/agent/child-agent-factory.js.map +1 -1
  129. package/dist/src/agent/embedded/run-for-session.d.ts +1 -0
  130. package/dist/src/agent/embedded/run-for-session.js +1 -0
  131. package/dist/src/agent/embedded/run-for-session.js.map +1 -1
  132. package/dist/src/agent/embedded/run-turn.js +1 -17
  133. package/dist/src/agent/embedded/run-turn.js.map +1 -1
  134. package/dist/src/agent/embedded/session-runner.js +3 -1
  135. package/dist/src/agent/embedded/session-runner.js.map +1 -1
  136. package/dist/src/agent/embedded/session-tool-result-guard.d.ts +1 -0
  137. package/dist/src/agent/embedded/session-tool-result-guard.js +1 -0
  138. package/dist/src/agent/embedded/session-tool-result-guard.js.map +1 -1
  139. package/dist/src/agent/inbound/attachment-pipeline.d.ts +37 -0
  140. package/dist/src/agent/inbound/attachment-pipeline.js +169 -0
  141. package/dist/src/agent/inbound/attachment-pipeline.js.map +1 -0
  142. package/dist/src/agent/inbound/turn-dispatcher.d.ts +3 -5
  143. package/dist/src/agent/inbound/turn-dispatcher.js +1 -2
  144. package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
  145. package/dist/src/agent/memory/index.d.ts +2 -0
  146. package/dist/src/agent/memory/index.js +2 -1
  147. package/dist/src/agent/memory/memory-flush.d.ts +27 -0
  148. package/dist/src/agent/memory/memory-flush.js +124 -0
  149. package/dist/src/agent/memory/memory-flush.js.map +1 -0
  150. package/dist/src/agent/messaging/outbound-coordinator.js +2 -1
  151. package/dist/src/agent/messaging/outbound-coordinator.js.map +1 -1
  152. package/dist/src/agent/messaging/stream-manager.d.ts +2 -0
  153. package/dist/src/agent/messaging/stream-manager.js +3 -0
  154. package/dist/src/agent/messaging/stream-manager.js.map +1 -1
  155. package/dist/src/agent/orchestration/agent-orchestrator.d.ts +0 -4
  156. package/dist/src/agent/orchestration/agent-orchestrator.js +40 -107
  157. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  158. package/dist/src/agent/prompt/contribution.d.ts +9 -0
  159. package/dist/src/agent/prompt/contribution.js +1 -0
  160. package/dist/src/agent/prompt/safety.js +0 -10
  161. package/dist/src/agent/prompt/safety.js.map +1 -1
  162. package/dist/src/agent/prompt/sanitize-for-prompt.d.ts +6 -0
  163. package/dist/src/agent/prompt/sanitize-for-prompt.js +13 -0
  164. package/dist/src/agent/prompt/sanitize-for-prompt.js.map +1 -0
  165. package/dist/src/agent/prompt/sections/behavior.d.ts +5 -0
  166. package/dist/src/agent/prompt/sections/behavior.js +50 -0
  167. package/dist/src/agent/prompt/sections/behavior.js.map +1 -0
  168. package/dist/src/agent/prompt/sections/memory-skills.d.ts +9 -0
  169. package/dist/src/agent/prompt/sections/memory-skills.js +59 -0
  170. package/dist/src/agent/prompt/sections/memory-skills.js.map +1 -0
  171. package/dist/src/agent/prompt/sections/messaging-runtime.d.ts +16 -0
  172. package/dist/src/agent/prompt/sections/messaging-runtime.js +69 -0
  173. package/dist/src/agent/prompt/sections/messaging-runtime.js.map +1 -0
  174. package/dist/src/agent/prompt/sections/project-context.d.ts +16 -0
  175. package/dist/src/agent/prompt/sections/project-context.js +58 -0
  176. package/dist/src/agent/prompt/sections/project-context.js.map +1 -0
  177. package/dist/src/agent/prompt/sections/tooling.d.ts +5 -0
  178. package/dist/src/agent/prompt/sections/tooling.js +119 -0
  179. package/dist/src/agent/prompt/sections/tooling.js.map +1 -0
  180. package/dist/src/agent/prompt/sections/workspace-runtime.d.ts +11 -0
  181. package/dist/src/agent/prompt/sections/workspace-runtime.js +32 -0
  182. package/dist/src/agent/prompt/sections/workspace-runtime.js.map +1 -0
  183. package/dist/src/agent/prompt/service-prompt-builder.d.ts +13 -0
  184. package/dist/src/agent/prompt/service-prompt-builder.js +54 -13
  185. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  186. package/dist/src/agent/prompt/subagent-context.d.ts +15 -0
  187. package/dist/src/agent/prompt/subagent-context.js +68 -0
  188. package/dist/src/agent/prompt/subagent-context.js.map +1 -0
  189. package/dist/src/agent/prompt/system-prompt-params.d.ts +53 -0
  190. package/dist/src/agent/prompt/system-prompt-params.js +74 -0
  191. package/dist/src/agent/prompt/system-prompt-params.js.map +1 -0
  192. package/dist/src/agent/prompt/system-prompt.d.ts +22 -11
  193. package/dist/src/agent/prompt/system-prompt.js +79 -193
  194. package/dist/src/agent/prompt/system-prompt.js.map +1 -1
  195. package/dist/src/agent/prompt/types.d.ts +3 -0
  196. package/dist/src/agent/service/build-direct-message-content.d.ts +5 -21
  197. package/dist/src/agent/service/build-direct-message-content.js +11 -64
  198. package/dist/src/agent/service/build-direct-message-content.js.map +1 -1
  199. package/dist/src/agent/service/direct-turn-helpers.d.ts +1 -1
  200. package/dist/src/agent/service/direct-turn-helpers.js +7 -0
  201. package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
  202. package/dist/src/agent/service/process-direct-one-shot.d.ts +3 -3
  203. package/dist/src/agent/service/process-direct-one-shot.js +22 -17
  204. package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
  205. package/dist/src/agent/service/process-direct-streaming.d.ts +6 -20
  206. package/dist/src/agent/service/process-direct-streaming.js +39 -40
  207. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  208. package/dist/src/agent/service/webchat-tts.d.ts +4 -9
  209. package/dist/src/agent/service/webchat-tts.js +9 -20
  210. package/dist/src/agent/service/webchat-tts.js.map +1 -1
  211. package/dist/src/agent/service.d.ts +8 -19
  212. package/dist/src/agent/service.js +53 -11
  213. package/dist/src/agent/service.js.map +1 -1
  214. package/dist/src/agent/tools/factory.js +2 -0
  215. package/dist/src/agent/tools/factory.js.map +1 -1
  216. package/dist/src/agent/tools/index.d.ts +1 -0
  217. package/dist/src/agent/tools/index.js +2 -1
  218. package/dist/src/agent/tools/media-read-tool.d.ts +2 -0
  219. package/dist/src/agent/tools/media-read-tool.js +89 -0
  220. package/dist/src/agent/tools/media-read-tool.js.map +1 -0
  221. package/dist/src/channels/attachments/attachment-classifiers.d.ts +8 -0
  222. package/dist/src/channels/attachments/attachment-classifiers.js +11 -0
  223. package/dist/src/channels/attachments/attachment-classifiers.js.map +1 -0
  224. package/dist/src/channels/attachments/inbound-persist.d.ts +13 -34
  225. package/dist/src/channels/attachments/inbound-persist.js +34 -102
  226. package/dist/src/channels/attachments/inbound-persist.js.map +1 -1
  227. package/dist/src/channels/attachments/inbound-types.d.ts +13 -0
  228. package/dist/src/channels/attachments/inbound-types.js +30 -0
  229. package/dist/src/channels/attachments/inbound-types.js.map +1 -0
  230. package/dist/src/channels/attachments/outbound-tts-persist.d.ts +3 -12
  231. package/dist/src/channels/attachments/outbound-tts-persist.js +28 -48
  232. package/dist/src/channels/attachments/outbound-tts-persist.js.map +1 -1
  233. package/dist/src/channels/attachments/voice-stt-webchat.d.ts +3 -3
  234. package/dist/src/channels/attachments/voice-stt-webchat.js +8 -14
  235. package/dist/src/channels/attachments/voice-stt-webchat.js.map +1 -1
  236. package/dist/src/channels/channel-domain.d.ts +30 -2
  237. package/dist/src/channels/exec-approval-runtime.d.ts +29 -0
  238. package/dist/src/channels/exec-approval-runtime.js +30 -0
  239. package/dist/src/channels/exec-approval-runtime.js.map +1 -0
  240. package/dist/src/channels/index.js +1 -1
  241. package/dist/src/channels/plugin-types.d.ts +1 -0
  242. package/dist/src/channels/transport-types.d.ts +2 -2
  243. package/dist/src/cli/commands/channels.js +1 -1
  244. package/dist/src/cli/commands/doctor/checks/database-schema.d.ts +2 -0
  245. package/dist/src/cli/commands/doctor/checks/database-schema.js +62 -0
  246. package/dist/src/cli/commands/doctor/checks/database-schema.js.map +1 -0
  247. package/dist/src/cli/commands/doctor/flow.js +2 -0
  248. package/dist/src/cli/commands/doctor/flow.js.map +1 -1
  249. package/dist/src/cli/commands/init.js +2 -57
  250. package/dist/src/cli/commands/init.js.map +1 -1
  251. package/dist/src/cli/commands/onboard/channels/registry.js +1 -1
  252. package/dist/src/cli/commands/setup.js +6 -5
  253. package/dist/src/cli/commands/setup.js.map +1 -1
  254. package/dist/src/cli/utils/init-workspace-core.js +1 -2
  255. package/dist/src/cli/utils/init-workspace-core.js.map +1 -1
  256. package/dist/src/config/index.js +2 -2
  257. package/dist/src/config/paths.d.ts +0 -13
  258. package/dist/src/config/paths.js +1 -20
  259. package/dist/src/config/paths.js.map +1 -1
  260. package/dist/src/config/rules.js +1 -1
  261. package/dist/src/config/schema.d.ts +24 -0
  262. package/dist/src/config/schema.js +33 -2
  263. package/dist/src/config/schema.js.map +1 -1
  264. package/dist/src/cron/executor.js +2 -2
  265. package/dist/src/gateway/heartbeat/service.js +1 -1
  266. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  267. package/dist/src/gateway/hono/routes/config-patch/channels.js +3 -3
  268. package/dist/src/gateway/hono/routes/config-patch/channels.js.map +1 -1
  269. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  270. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  271. package/dist/src/gateway/hono/routes/media.d.ts +3 -0
  272. package/dist/src/gateway/hono/routes/media.js +50 -0
  273. package/dist/src/gateway/hono/routes/media.js.map +1 -0
  274. package/dist/src/gateway/hono/routes/sessions.js +6 -0
  275. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  276. package/dist/src/gateway/hono/routes/workspace.js +1 -87
  277. package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
  278. package/dist/src/gateway/service/sessions-api.js +3 -0
  279. package/dist/src/gateway/service/sessions-api.js.map +1 -1
  280. package/dist/src/heartbeat/index.js +1 -1
  281. package/dist/src/media/index.d.ts +5 -0
  282. package/dist/src/media/index.js +5 -0
  283. package/dist/src/media/media-reference.d.ts +23 -0
  284. package/dist/src/media/media-reference.js +34 -0
  285. package/dist/src/media/media-reference.js.map +1 -0
  286. package/dist/src/media/paths.d.ts +5 -0
  287. package/dist/src/media/paths.js +20 -0
  288. package/dist/src/media/paths.js.map +1 -0
  289. package/dist/src/media/session-references.d.ts +8 -0
  290. package/dist/src/media/session-references.js +45 -0
  291. package/dist/src/media/session-references.js.map +1 -0
  292. package/dist/src/media/store.d.ts +19 -0
  293. package/dist/src/media/store.js +131 -0
  294. package/dist/src/media/store.js.map +1 -0
  295. package/dist/src/media/types.d.ts +34 -0
  296. package/dist/src/media/types.js +1 -0
  297. package/dist/src/media/uri.d.ts +15 -0
  298. package/dist/src/media/uri.js +51 -0
  299. package/dist/src/media/uri.js.map +1 -0
  300. package/dist/src/session/session-title.js +6 -3
  301. package/dist/src/session/session-title.js.map +1 -1
  302. package/dist/src/session/store.js +1 -1
  303. package/dist/src/session/store.js.map +1 -1
  304. package/dist/src/session/types.d.ts +12 -7
  305. package/dist/src/session/types.js.map +1 -1
  306. package/dist/src/storage/sqlite/index.d.ts +4 -1
  307. package/dist/src/storage/sqlite/index.js +6 -2
  308. package/dist/src/storage/sqlite/migrations/002_add_flush_columns.sql +3 -0
  309. package/dist/src/storage/sqlite/migrations/discover.d.ts +4 -0
  310. package/dist/src/storage/sqlite/migrations/discover.js +38 -0
  311. package/dist/src/storage/sqlite/migrations/discover.js.map +1 -0
  312. package/dist/src/storage/sqlite/migrations/discover.ts +52 -0
  313. package/dist/src/storage/sqlite/migrations/errors.d.ts +11 -0
  314. package/dist/src/storage/sqlite/migrations/errors.js +27 -0
  315. package/dist/src/storage/sqlite/migrations/errors.js.map +1 -0
  316. package/dist/src/storage/sqlite/migrations/errors.ts +32 -0
  317. package/dist/src/storage/sqlite/migrations/runner.d.ts +22 -0
  318. package/dist/src/storage/sqlite/migrations/runner.js +97 -0
  319. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -0
  320. package/dist/src/storage/sqlite/migrations/runner.ts +153 -0
  321. package/dist/src/storage/sqlite/migrations/types.d.ts +12 -0
  322. package/dist/src/storage/sqlite/migrations/types.js +1 -0
  323. package/dist/src/storage/sqlite/migrations/types.ts +13 -0
  324. package/dist/src/storage/sqlite/row-mappers.d.ts +4 -0
  325. package/dist/src/storage/sqlite/row-mappers.js +4 -0
  326. package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
  327. package/dist/src/storage/sqlite/schema-version.d.ts +6 -0
  328. package/dist/src/storage/sqlite/schema-version.js +29 -0
  329. package/dist/src/storage/sqlite/schema-version.js.map +1 -0
  330. package/dist/src/storage/sqlite/schema.d.ts +5 -3
  331. package/dist/src/storage/sqlite/schema.js +24 -28
  332. package/dist/src/storage/sqlite/schema.js.map +1 -1
  333. package/dist/src/storage/sqlite/schema.sql +2 -0
  334. package/dist/src/storage/sqlite/session-metadata.js +1 -0
  335. package/dist/src/storage/sqlite/session-metadata.js.map +1 -1
  336. package/dist/src/storage/sqlite/session-repository.js +7 -3
  337. package/dist/src/storage/sqlite/session-repository.js.map +1 -1
  338. package/package.json +1 -1
  339. package/dist/gateway/static/root/assets/channels-settings-BxW1Xio4.js +0 -1
  340. package/dist/gateway/static/root/assets/channels-status-swr-Cxm6AvQO.js +0 -8
  341. package/dist/gateway/static/root/assets/index-BJDmBCSl.css +0 -1
  342. package/dist/gateway/static/root/assets/index-Cbg5TS5m.js +0 -4707
  343. package/dist/gateway/static/root/assets/url-DpFBIyN9.js +0 -3
  344. package/dist/src/cli/commands/onboard/workspace.d.ts +0 -14
  345. package/dist/src/cli/commands/onboard/workspace.js +0 -33
  346. package/dist/src/cli/commands/onboard/workspace.js.map +0 -1
  347. package/dist/src/cli/utils/workspace.d.ts +0 -35
  348. package/dist/src/cli/utils/workspace.js +0 -72
  349. package/dist/src/cli/utils/workspace.js.map +0 -1
@@ -0,0 +1,74 @@
1
+ import { PACKAGE_VERSION, init_package_version } from "../../package-version.js";
2
+ import { isCronSessionKey, isSubagentSessionKey } from "../../routing/session-key-utils.js";
3
+ import { init_session_key, parseSessionKey } from "../../routing/session-key.js";
4
+ import { normalizePromptSection } from "./cache-boundary.js";
5
+ import { listChannelPlugins } from "../../channels/plugins/registry.js";
6
+ //#region src/agent/prompt/system-prompt-params.ts
7
+ init_package_version();
8
+ init_session_key();
9
+ function resolvePromptMode(sessionKey) {
10
+ if (!sessionKey) return "full";
11
+ if (isSubagentSessionKey(sessionKey) || isCronSessionKey(sessionKey)) return "minimal";
12
+ return "full";
13
+ }
14
+ function resolveRuntimeChannel(sessionKey) {
15
+ if (!sessionKey) return;
16
+ return parseSessionKey(sessionKey)?.source;
17
+ }
18
+ function resolveDeliverableChannels(config) {
19
+ const channels = new Set(["webchat", "cli"]);
20
+ const configured = config.channels;
21
+ if (configured) {
22
+ for (const [id, section] of Object.entries(configured)) if (section?.enabled !== false) channels.add(id);
23
+ }
24
+ for (const plugin of listChannelPlugins()) {
25
+ const id = plugin.id;
26
+ const section = configured?.[id];
27
+ if (section?.enabled !== false && section !== void 0) channels.add(id);
28
+ }
29
+ return [...channels].sort();
30
+ }
31
+ function normalizeProviderPromptBlock(value) {
32
+ if (typeof value !== "string") return;
33
+ return normalizePromptSection(value) || void 0;
34
+ }
35
+ function buildOverridablePromptSection(params) {
36
+ const override = normalizeProviderPromptBlock(params.override);
37
+ if (override) return override;
38
+ return params.fallback;
39
+ }
40
+ function resolveSystemPromptBuildParams(config, params) {
41
+ const sessionKey = params.sessionKey;
42
+ const channel = resolveRuntimeChannel(sessionKey);
43
+ return {
44
+ workspaceDir: params.workspaceDir,
45
+ sessionKey,
46
+ promptMode: params.promptMode ?? resolvePromptMode(sessionKey),
47
+ toolNames: params.toolNames,
48
+ toolSummaries: params.toolSummaries,
49
+ runtimeInfo: {
50
+ version: PACKAGE_VERSION,
51
+ model: params.modelRef,
52
+ channel,
53
+ agentId: params.agentId,
54
+ thinkingLevel: params.thinkingLevel
55
+ },
56
+ userTimezone: params.userTimezone,
57
+ channels: resolveDeliverableChannels(config),
58
+ memoryCitationsMode: params.memoryCitationsMode,
59
+ includeMemorySection: params.includeMemorySection,
60
+ heartbeatEnabled: params.heartbeatEnabled,
61
+ heartbeatPrompt: params.heartbeatPrompt,
62
+ externalMemoryInstructions: params.externalMemoryInstructions,
63
+ ttsSystemHint: params.ttsSystemHint,
64
+ extraSystemPrompt: params.extraSystemPrompt,
65
+ silentReplyPromptMode: params.silentReplyPromptMode,
66
+ promptContribution: params.promptContribution,
67
+ includeProblemSolving: true,
68
+ includeToneSection: true
69
+ };
70
+ }
71
+ //#endregion
72
+ export { buildOverridablePromptSection, normalizeProviderPromptBlock, resolveDeliverableChannels, resolvePromptMode, resolveRuntimeChannel, resolveSystemPromptBuildParams };
73
+
74
+ //# sourceMappingURL=system-prompt-params.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-prompt-params.js","names":[],"sources":["../../../../src/agent/prompt/system-prompt-params.ts"],"sourcesContent":["import type { Config } from '../../config/schema.js';\nimport { listChannelPlugins } from '../../channels/plugins/registry.js';\nimport { PACKAGE_VERSION } from '../../package-version.js';\nimport { isCronSessionKey, isSubagentSessionKey, parseSessionKey } from '../../routing/session-key.js';\nimport type { ProviderSystemPromptContribution } from './contribution.js';\nimport { normalizePromptSection } from './cache-boundary.js';\nimport type { MemoryCitationsMode, PromptMode, SilentReplyPromptMode } from './types.js';\n\nexport type { RuntimeInfoInput } from './sections/workspace-runtime.js';\n\nexport function resolvePromptMode(sessionKey?: string): PromptMode {\n if (!sessionKey) {\n return 'full';\n }\n if (isSubagentSessionKey(sessionKey) || isCronSessionKey(sessionKey)) {\n return 'minimal';\n }\n return 'full';\n}\n\nexport function resolveRuntimeChannel(sessionKey?: string): string | undefined {\n if (!sessionKey) {\n return undefined;\n }\n const parsed = parseSessionKey(sessionKey);\n return parsed?.source;\n}\n\nexport function resolveDeliverableChannels(config: Config): string[] {\n const channels = new Set<string>(['webchat', 'cli']);\n const configured = config.channels as Record<string, { enabled?: boolean }> | undefined;\n if (configured) {\n for (const [id, section] of Object.entries(configured)) {\n if (section?.enabled !== false) {\n channels.add(id);\n }\n }\n }\n for (const plugin of listChannelPlugins()) {\n const id = plugin.id;\n const section = configured?.[id];\n if (section?.enabled !== false && section !== undefined) {\n channels.add(id);\n }\n }\n return [...channels].sort();\n}\n\nexport function normalizeProviderPromptBlock(value?: string): string | undefined {\n if (typeof value !== 'string') {\n return undefined;\n }\n const normalized = normalizePromptSection(value);\n return normalized || undefined;\n}\n\nexport function buildOverridablePromptSection(params: {\n override?: string;\n fallback: string;\n}): string {\n const override = normalizeProviderPromptBlock(params.override);\n if (override) {\n return override;\n }\n return params.fallback;\n}\n\nexport interface SystemPromptBuildParams {\n workspaceDir: string;\n sessionKey?: string;\n promptMode?: PromptMode;\n toolNames?: string[];\n toolSummaries?: Record<string, string>;\n runtimeInfo?: import('./sections/workspace-runtime.js').RuntimeInfoInput;\n userTimezone?: string;\n channels?: string[];\n memoryCitationsMode?: MemoryCitationsMode;\n includeMemorySection?: boolean;\n heartbeatEnabled?: boolean;\n heartbeatPrompt?: string;\n externalMemoryInstructions?: string;\n ttsSystemHint?: string;\n extraSystemPrompt?: string;\n silentReplyPromptMode?: SilentReplyPromptMode;\n promptContribution?: ProviderSystemPromptContribution;\n includeProblemSolving?: boolean;\n includeToneSection?: boolean;\n}\n\nexport function resolveSystemPromptBuildParams(\n config: Config,\n params: {\n workspaceDir: string;\n sessionKey?: string;\n toolNames?: string[];\n toolSummaries?: Record<string, string>;\n userTimezone?: string;\n externalMemoryInstructions?: string;\n heartbeatEnabled?: boolean;\n heartbeatPrompt?: string;\n ttsSystemHint?: string;\n extraSystemPrompt?: string;\n modelRef?: string;\n agentId?: string;\n thinkingLevel?: string;\n promptMode?: PromptMode;\n silentReplyPromptMode?: SilentReplyPromptMode;\n promptContribution?: ProviderSystemPromptContribution;\n memoryCitationsMode?: MemoryCitationsMode;\n includeMemorySection?: boolean;\n },\n): SystemPromptBuildParams {\n const sessionKey = params.sessionKey;\n const channel = resolveRuntimeChannel(sessionKey);\n return {\n workspaceDir: params.workspaceDir,\n sessionKey,\n promptMode: params.promptMode ?? resolvePromptMode(sessionKey),\n toolNames: params.toolNames,\n toolSummaries: params.toolSummaries,\n runtimeInfo: {\n version: PACKAGE_VERSION,\n model: params.modelRef,\n channel,\n agentId: params.agentId,\n thinkingLevel: params.thinkingLevel,\n },\n userTimezone: params.userTimezone,\n channels: resolveDeliverableChannels(config),\n memoryCitationsMode: params.memoryCitationsMode,\n includeMemorySection: params.includeMemorySection,\n heartbeatEnabled: params.heartbeatEnabled,\n heartbeatPrompt: params.heartbeatPrompt,\n externalMemoryInstructions: params.externalMemoryInstructions,\n ttsSystemHint: params.ttsSystemHint,\n extraSystemPrompt: params.extraSystemPrompt,\n silentReplyPromptMode: params.silentReplyPromptMode,\n promptContribution: params.promptContribution,\n includeProblemSolving: true,\n includeToneSection: true,\n };\n}\n"],"mappings":";;;;;;sBAE2D;kBAC4C;AAOvG,SAAgB,kBAAkB,YAAiC;AACjE,KAAI,CAAC,WACH,QAAO;AAET,KAAI,qBAAqB,WAAW,IAAI,iBAAiB,WAAW,CAClE,QAAO;AAET,QAAO;;AAGT,SAAgB,sBAAsB,YAAyC;AAC7E,KAAI,CAAC,WACH;AAGF,QADe,gBAAgB,WAClB,EAAE;;AAGjB,SAAgB,2BAA2B,QAA0B;CACnE,MAAM,WAAW,IAAI,IAAY,CAAC,WAAW,MAAM,CAAC;CACpD,MAAM,aAAa,OAAO;AAC1B,KAAI;OACG,MAAM,CAAC,IAAI,YAAY,OAAO,QAAQ,WAAW,CACpD,KAAI,SAAS,YAAY,MACvB,UAAS,IAAI,GAAG;;AAItB,MAAK,MAAM,UAAU,oBAAoB,EAAE;EACzC,MAAM,KAAK,OAAO;EAClB,MAAM,UAAU,aAAa;AAC7B,MAAI,SAAS,YAAY,SAAS,YAAY,KAAA,EAC5C,UAAS,IAAI,GAAG;;AAGpB,QAAO,CAAC,GAAG,SAAS,CAAC,MAAM;;AAG7B,SAAgB,6BAA6B,OAAoC;AAC/E,KAAI,OAAO,UAAU,SACnB;AAGF,QADmB,uBAAuB,MACzB,IAAI,KAAA;;AAGvB,SAAgB,8BAA8B,QAGnC;CACT,MAAM,WAAW,6BAA6B,OAAO,SAAS;AAC9D,KAAI,SACF,QAAO;AAET,QAAO,OAAO;;AAyBhB,SAAgB,+BACd,QACA,QAoByB;CACzB,MAAM,aAAa,OAAO;CAC1B,MAAM,UAAU,sBAAsB,WAAW;AACjD,QAAO;EACL,cAAc,OAAO;EACrB;EACA,YAAY,OAAO,cAAc,kBAAkB,WAAW;EAC9D,WAAW,OAAO;EAClB,eAAe,OAAO;EACtB,aAAa;GACX,SAAS;GACT,OAAO,OAAO;GACd;GACA,SAAS,OAAO;GAChB,eAAe,OAAO;GACvB;EACD,cAAc,OAAO;EACrB,UAAU,2BAA2B,OAAO;EAC5C,qBAAqB,OAAO;EAC5B,sBAAsB,OAAO;EAC7B,kBAAkB,OAAO;EACzB,iBAAiB,OAAO;EACxB,4BAA4B,OAAO;EACnC,eAAe,OAAO;EACtB,mBAAmB,OAAO;EAC1B,uBAAuB,OAAO;EAC9B,oBAAoB,OAAO;EAC3B,uBAAuB;EACvB,oBAAoB;EACrB"}
@@ -6,29 +6,40 @@
6
6
  * not to manually reread startup files.
7
7
  */
8
8
  import type { EmbeddedContextFile } from '../bootstrap/types.js';
9
- import type { PromptMode } from './types.js';
10
- export type MemoryCitationsMode = 'on' | 'off' | 'source-only';
9
+ import type { ProviderSystemPromptContribution } from './contribution.js';
10
+ import { type RuntimeInfoInput } from './sections/workspace-runtime.js';
11
+ import type { MemoryCitationsMode, PromptMode, SilentReplyPromptMode } from './types.js';
12
+ export type { MemoryCitationsMode } from './types.js';
13
+ export { getContextFileBasename, isDynamicContextFile, sortContextFilesForPrompt, } from './sections/project-context.js';
11
14
  export interface SystemPromptOptions {
12
- /** Bootstrap context files from profile Markdown (Project Context). */
13
15
  contextFiles?: EmbeddedContextFile[];
14
16
  promptMode?: PromptMode;
15
17
  heartbeatEnabled?: boolean;
16
18
  heartbeatPrompt?: string;
19
+ /** Registered tool names for Tooling section and memory/skills gating. */
20
+ toolNames?: string[];
21
+ toolSummaries?: Record<string, string>;
22
+ /** @deprecated Prefer toolNames — kept for skill-section gating compatibility. */
17
23
  availableTools?: string[];
18
24
  memoryCitationsMode?: MemoryCitationsMode;
25
+ includeMemorySection?: boolean;
19
26
  userTimezone?: string;
20
- runtime?: {
21
- version?: string;
22
- model?: string;
23
- channel?: string;
24
- };
27
+ runtime?: RuntimeInfoInput;
25
28
  channels?: string[];
26
29
  externalMemoryInstructions?: string;
27
30
  ttsSystemHint?: string;
31
+ extraSystemPrompt?: string;
32
+ silentReplyPromptMode?: SilentReplyPromptMode;
33
+ promptContribution?: ProviderSystemPromptContribution;
34
+ includeProblemSolving?: boolean;
35
+ includeToneSection?: boolean;
28
36
  }
29
37
  /**
30
38
  * Build system prompt with bootstrap Project Context integration.
31
39
  */
32
- export declare function buildSystemPrompt(workspaceDir: string, options: SystemPromptOptions): string;
33
- /** Whether HEARTBEAT.md is injected as dynamic context (vs behavior-only section). */
34
- export declare function isHeartbeatContextFile(pathValue: string): boolean;
40
+ export declare function buildSystemPrompt(workspaceDir: string, options?: SystemPromptOptions): string;
41
+ /** Split a built prompt at the cache boundary (for tests and provider adapters). */
42
+ export declare function splitBuiltSystemPrompt(text: string): {
43
+ stablePrefix: string;
44
+ dynamicSuffix: string;
45
+ };
@@ -1,223 +1,109 @@
1
- import { DEFAULT_HEARTBEAT_FILENAME } from "../context/workspace.js";
2
- import { PROMPT_CACHE_BOUNDARY } from "./cache-boundary.js";
1
+ import { PROMPT_CACHE_BOUNDARY, splitPromptCacheBoundary } from "./cache-boundary.js";
2
+ import { buildAestheticSection, buildExecutionBiasSection, buildProblemSolvingSection, buildSafetySection, buildToolCallStyleSection } from "./sections/behavior.js";
3
+ import { buildExternalMemorySection, buildMemorySection, buildSkillsSection } from "./sections/memory-skills.js";
4
+ import { buildHeartbeatBehaviorSection, buildMessagingSection, buildOutputDirectivesSection, buildSilentRepliesSection, buildTimeSection } from "./sections/messaging-runtime.js";
5
+ import { buildProjectContextSection, getContextFileBasename, isDynamicContextFile, sortContextFilesForPrompt } from "./sections/project-context.js";
6
+ import { buildToolingSection, hasSkillsTools } from "./sections/tooling.js";
7
+ import { buildRuntimeSection, buildWorkspaceFilesIntroSection, buildWorkspaceSection } from "./sections/workspace-runtime.js";
8
+ import { buildOverridablePromptSection } from "./system-prompt-params.js";
3
9
  //#region src/agent/prompt/system-prompt.ts
4
- const CONTEXT_FILE_ORDER = new Map([
5
- ["agents.md", 10],
6
- ["soul.md", 20],
7
- ["identity.md", 30],
8
- ["user.md", 40],
9
- ["tools.md", 50],
10
- ["memory.md", 70]
11
- ]);
12
- const DYNAMIC_CONTEXT_FILE_BASENAMES = new Set(["heartbeat.md"]);
13
- const DEFAULT_HEARTBEAT_PROMPT_CONTEXT_BLOCK = "Default heartbeat prompt:\n`Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.`";
14
- function normalizeContextFilePath(pathValue) {
15
- return pathValue.trim().replace(/\\/g, "/");
16
- }
17
- function getContextFileBasename(pathValue) {
18
- const normalizedPath = normalizeContextFilePath(pathValue);
19
- return (normalizedPath.split("/").pop() ?? normalizedPath).toLowerCase();
20
- }
21
- function isDynamicContextFile(pathValue) {
22
- return DYNAMIC_CONTEXT_FILE_BASENAMES.has(getContextFileBasename(pathValue));
23
- }
24
- function sanitizeContextFileContentForPrompt(content) {
25
- return content.replaceAll(DEFAULT_HEARTBEAT_PROMPT_CONTEXT_BLOCK, "").replace(/\n{3,}/g, "\n\n");
26
- }
27
- function sortContextFilesForPrompt(contextFiles) {
28
- return [...contextFiles].sort((a, b) => {
29
- const aBase = getContextFileBasename(a.path);
30
- const bBase = getContextFileBasename(b.path);
31
- const aOrder = CONTEXT_FILE_ORDER.get(aBase) ?? Number.MAX_SAFE_INTEGER;
32
- const bOrder = CONTEXT_FILE_ORDER.get(bBase) ?? Number.MAX_SAFE_INTEGER;
33
- if (aOrder !== bOrder) return aOrder - bOrder;
34
- if (aBase !== bBase) return aBase.localeCompare(bBase);
35
- return normalizeContextFilePath(a.path).localeCompare(normalizeContextFilePath(b.path));
36
- });
37
- }
38
- function buildProjectContextSection(params) {
39
- if (params.files.length === 0) return [];
40
- const lines = [params.heading, ""];
41
- if (params.dynamic) lines.push("The following frequently-changing project context files are kept below the cache boundary when possible:", "");
42
- else {
43
- const hasSoulFile = params.files.some((file) => getContextFileBasename(file.path) === "soul.md");
44
- lines.push("The following project context files have been loaded:");
45
- if (hasSoulFile) lines.push("If SOUL.md is present, embody its persona and tone. Avoid stiff, generic replies; follow its guidance unless higher-priority instructions override it.");
46
- lines.push("");
47
- }
48
- for (const file of params.files) lines.push(`## ${file.path}`, "", sanitizeContextFileContentForPrompt(file.content), "");
49
- return lines;
50
- }
51
- function buildMemorySection(citationsMode = "on", hasProfileMemory = false) {
52
- if (!hasProfileMemory) return "";
53
- return `## Memory Recall
54
-
55
- ${citationsMode === "off" ? "Citations are disabled: do not mention file paths or line numbers in replies." : citationsMode === "source-only" ? "Citations: mention file path when it helps (e.g., Source: MEMORY.md)." : "Citations: include Source: <path#line> when it helps the user verify memory snippets."}
56
-
57
- Startup profile files (SOUL, USER, MEMORY, etc.) are already in Project Context above. Do not re-read them unless the user asks or you need lines beyond what was injected.
58
-
59
- Before answering anything about prior work, decisions, dates, people, preferences, or todos:
60
- 1. Run \`memory_search\` on profile MEMORY.md and workspace \`memory/*.md\`
61
- 2. For **other chat sessions** / cross-session history, use \`session_search\` with keywords (or omit \`query\` to list recent sessions)
62
- 3. Use \`memory_get\` to pull only the needed lines from files
63
- 4. For structured curated notes under agent home \`memories/\`, use \`curated_memory\`
64
- 5. If low confidence after search, say you checked
65
-
66
- ### Memory Files
67
-
68
- - **Daily notes:** \`memory/YYYY-MM-DD.md\` — raw logs (runtime may preload recent days on /new or /reset)
69
- - **Long-term:** profile \`MEMORY.md\` — curated memories in Project Context when present
70
- - **Curated store:** agent home \`memories/MEMORY.md\` and \`memories/USER.md\` — use \`curated_memory\` for live read/write
71
-
72
- ### Writing to Memory
73
-
74
- - **Declarative vs procedural:** Save facts and preferences via workspace memory files and/or \`curated_memory\`. Save reusable task playbooks with \`skill_manage\` as skills.
75
- - **Memory is limited** — if you want to remember something, WRITE IT TO A FILE
76
- - When someone says "remember this" → update \`memory/YYYY-MM-DD.md\` or relevant file
77
- - **Text > Brain**
78
- `;
79
- }
80
- function buildSkillsSection(availableTools = []) {
81
- if (availableTools.length === 0) return "";
82
- return `## Skills
83
-
84
- When a solution already exists, do not reinvent the wheel.
85
-
86
- **How to use:**
87
- 1. Skim <available_skills> — is anything clearly relevant?
88
- 2. Only one match? → Confirm with skills_list, then load the full text with skill_view(name) and follow it.
89
- 3. Need sub-documents or scripts? → skill_view(name, "references/…"), etc.
90
- 4. No match? → Solve it yourself; do not force-fit a skill.
91
-
92
- **Division of labor with memory:** Skills = **procedural** workflows; memory / \`curated_memory\` = **declarative** facts and preferences.
93
- `;
94
- }
95
- function buildSafetySection() {
96
- return `## Safety
97
-
98
- - You have no independent goals: do not pursue self-preservation, replication, resource acquisition, or power-seeking; avoid long-term plans beyond the user's request.
99
- - Prioritize safety and human oversight over completion; if instructions conflict, pause and ask; comply with stop/pause/audit requests and never bypass safeguards.
100
- - Do not manipulate or persuade anyone to expand access or disable safeguards. Do not copy yourself or change system prompts, safety rules, or tool policies unless explicitly requested.`;
101
- }
102
- function buildProblemSolvingSection() {
103
- return `## Problem Solving
104
-
105
- **Simple tasks** (< 5 minutes or a single-file change): Do them directly; run a quick verification after changes.
106
-
107
- **Complex tasks** (multiple files or design decisions): Use an iterative flow — Plan → Build → Verify → Fix.
108
-
109
- **Core principle: Match the complexity; reject ritual for its own sake. Verification matters, but do not verify just to tick a box.**`;
110
- }
111
- function buildAestheticSection() {
112
- return `## Tone & Style
113
-
114
- **Default voice:** Direct, concise, concrete.
115
-
116
- **SOUL.md takes precedence:** If SOUL.md defines a specific tone, defer to it over the above.`;
117
- }
118
- function buildHeartbeatBehaviorSection(params) {
119
- if (!params.enabled) return "";
120
- if (params.customPrompt?.trim()) return `## Heartbeats\n\n${params.customPrompt.trim()}\n`;
121
- let quietHoursNote = "";
122
- if (params.userTimezone) quietHoursNote = `\n\n> Quiet hours: The user is in **${params.userTimezone}**. Avoid proactive checks during late night (23:00-08:00) unless urgent.`;
123
- return `## Heartbeats
124
-
125
- If the current user message is a heartbeat poll and nothing needs attention, reply exactly: HEARTBEAT_OK
126
-
127
- If something needs attention, do NOT include "HEARTBEAT_OK"; reply with the alert text instead.${quietHoursNote}
128
- `;
129
- }
130
- function buildMessagingSection(channels = [], isMinimal = false) {
131
- if (isMinimal || channels.length === 0) return "";
132
- return `## Messaging
133
-
134
- - Reply in current session → automatically routes to the source channel (${channels.join(", ")})
135
- - Use \`message\` for proactive sends + channel actions
136
- - If you use \`message\` to deliver your user-visible reply, respond with ONLY: NO_REPLY (avoid duplicate replies)
137
- `;
138
- }
139
- function buildTimeSection(timezone) {
140
- if (!timezone) return "";
141
- return `## Current Date & Time
142
-
143
- Time zone: ${timezone}
144
-
145
- If you need the current date/time/day-of-week, use the \`session_status\` tool or the inbound message timestamp envelope (when present).
146
- `;
147
- }
148
- function buildRuntimeSection(runtime) {
149
- if (!runtime) return "";
150
- const parts = [];
151
- if (runtime.version) parts.push(`v${runtime.version}`);
152
- if (runtime.model) parts.push(`model=${runtime.model.split("/").pop()}`);
153
- if (runtime.channel) parts.push(`ch=${runtime.channel}`);
154
- return parts.length > 0 ? `[${parts.join(" | ")}]` : "";
155
- }
156
- function buildWorkingDirSection(workspaceDir) {
157
- return `Working directory: ${workspaceDir}`;
158
- }
159
- function buildExternalMemorySection(text) {
160
- const t = text?.trim();
161
- if (!t) return "";
162
- return `## External memory provider\n\n${t}`;
10
+ function joinSections(sections) {
11
+ return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
163
12
  }
164
13
  /**
165
14
  * Build system prompt with bootstrap Project Context integration.
166
15
  */
167
- function buildSystemPrompt(workspaceDir, options) {
168
- const { contextFiles = [], promptMode = "full", heartbeatEnabled = false, heartbeatPrompt, availableTools = [], memoryCitationsMode = "on", userTimezone, runtime, channels = [], externalMemoryInstructions, ttsSystemHint } = options;
16
+ function buildSystemPrompt(workspaceDir, options = {}) {
17
+ const { contextFiles = [], promptMode = "full", heartbeatEnabled = false, heartbeatPrompt, toolNames: toolNamesOption, toolSummaries, availableTools = [], memoryCitationsMode = "on", includeMemorySection, userTimezone, runtime, channels = [], externalMemoryInstructions, ttsSystemHint, extraSystemPrompt, silentReplyPromptMode = "generic", promptContribution, includeProblemSolving = true, includeToneSection = true } = options;
169
18
  if (promptMode === "none") return "You are a personal AI assistant running inside xopc.";
170
19
  const isMinimal = promptMode === "minimal";
20
+ const toolNames = toolNamesOption ?? availableTools;
21
+ const normalizedTools = new Set(toolNames.map((tool) => tool.toLowerCase()));
22
+ const sectionOverrides = promptContribution?.sectionOverrides ?? {};
171
23
  const orderedContextFiles = sortContextFilesForPrompt(contextFiles.filter((file) => file.path.trim().length > 0));
172
24
  const stableContextFiles = orderedContextFiles.filter((file) => !isDynamicContextFile(file.path));
173
25
  const dynamicContextFiles = orderedContextFiles.filter((file) => isDynamicContextFile(file.path));
174
26
  const hasProfileMemory = orderedContextFiles.some((file) => getContextFileBasename(file.path) === "memory.md");
175
- const sections = [
27
+ const stableSections = [
176
28
  "You are a personal AI assistant running inside xopc.",
177
- "",
178
- "## Workspace Files (injected)",
179
- "",
180
- "Profile bootstrap files are injected below as Project Context. Do not manually reread them at session start unless the user asks or injected content is insufficient.",
181
- ""
29
+ buildToolingSection({
30
+ toolNames,
31
+ toolSummaries
32
+ }),
33
+ buildOverridablePromptSection({
34
+ override: sectionOverrides.tool_call_style,
35
+ fallback: buildToolCallStyleSection()
36
+ })
182
37
  ];
38
+ if (!isMinimal) stableSections.push(buildOverridablePromptSection({
39
+ override: sectionOverrides.execution_bias,
40
+ fallback: buildExecutionBiasSection()
41
+ }));
42
+ const providerStablePrefix = buildOverridablePromptSection({
43
+ override: promptContribution?.stablePrefix,
44
+ fallback: ""
45
+ });
46
+ if (providerStablePrefix) stableSections.push(providerStablePrefix);
47
+ stableSections.push(buildSafetySection());
48
+ if (hasSkillsTools(toolNames)) stableSections.push(buildSkillsSection(true));
183
49
  if (!isMinimal) {
184
- sections.push(buildTimeSection(userTimezone));
185
- sections.push(buildExternalMemorySection(externalMemoryInstructions));
186
- sections.push(buildMemorySection(memoryCitationsMode, hasProfileMemory));
187
- }
188
- sections.push(buildSkillsSection(availableTools));
189
- if (!isMinimal) {
190
- sections.push(buildSafetySection());
191
- sections.push(buildProblemSolvingSection());
192
- sections.push(buildAestheticSection());
50
+ stableSections.push(buildMemorySection({
51
+ availableTools: normalizedTools,
52
+ citationsMode: memoryCitationsMode,
53
+ hasProfileMemory,
54
+ includeMemorySection
55
+ }), buildExternalMemorySection(externalMemoryInstructions));
56
+ if (includeProblemSolving) stableSections.push(buildProblemSolvingSection());
57
+ if (includeToneSection) stableSections.push(buildAestheticSection());
58
+ stableSections.push(buildTimeSection(userTimezone));
193
59
  }
194
- sections.push(...buildProjectContextSection({
60
+ stableSections.push(buildWorkspaceSection(workspaceDir), buildWorkspaceFilesIntroSection());
61
+ if (!isMinimal) stableSections.push(buildOutputDirectivesSection(isMinimal));
62
+ stableSections.push(buildMessagingSection({
63
+ channels,
64
+ isMinimal,
65
+ hasSendMessage: normalizedTools.has("send_message")
66
+ }));
67
+ if (!isMinimal && ttsSystemHint?.trim()) stableSections.push(`## Voice (TTS)\n\n${ttsSystemHint.trim()}`);
68
+ stableSections.push(joinSections(buildProjectContextSection({
195
69
  files: stableContextFiles,
196
70
  heading: "# Project Context",
197
71
  dynamic: false
72
+ })));
73
+ if (!isMinimal) stableSections.push(buildSilentRepliesSection({
74
+ isMinimal,
75
+ silentReplyPromptMode
198
76
  }));
199
- sections.push(PROMPT_CACHE_BOUNDARY);
200
- sections.push(...buildProjectContextSection({
77
+ const dynamicSections = [];
78
+ dynamicSections.push(joinSections(buildProjectContextSection({
201
79
  files: dynamicContextFiles,
202
80
  heading: stableContextFiles.length > 0 ? "# Dynamic Project Context" : "# Project Context",
203
81
  dynamic: true
204
- }));
205
- sections.push(buildHeartbeatBehaviorSection({
82
+ })));
83
+ if (extraSystemPrompt?.trim()) {
84
+ const contextHeader = isMinimal ? "## Subagent Context" : "## Group Chat Context";
85
+ dynamicSections.push(`${contextHeader}\n\n${extraSystemPrompt.trim()}`);
86
+ }
87
+ const providerDynamicSuffix = buildOverridablePromptSection({
88
+ override: promptContribution?.dynamicSuffix,
89
+ fallback: ""
90
+ });
91
+ if (providerDynamicSuffix) dynamicSections.push(providerDynamicSuffix);
92
+ dynamicSections.push(buildHeartbeatBehaviorSection({
206
93
  enabled: heartbeatEnabled,
207
94
  customPrompt: heartbeatPrompt,
208
95
  userTimezone
209
- }));
210
- sections.push(buildWorkingDirSection(workspaceDir));
211
- sections.push(buildMessagingSection(channels, isMinimal));
212
- if (!isMinimal && ttsSystemHint?.trim()) sections.push(`## Voice (TTS)\n\n${ttsSystemHint.trim()}`);
213
- sections.push(buildRuntimeSection(runtime));
214
- return sections.filter(Boolean).join("\n\n");
96
+ }), buildRuntimeSection(runtime));
97
+ const stablePrefix = joinSections(stableSections);
98
+ const dynamicSuffix = joinSections(dynamicSections);
99
+ if (!dynamicSuffix.trim()) return `${stablePrefix}\n\n${PROMPT_CACHE_BOUNDARY}`.trim();
100
+ return `${stablePrefix}\n\n${PROMPT_CACHE_BOUNDARY}\n\n${dynamicSuffix}`.trim();
215
101
  }
216
- /** Whether HEARTBEAT.md is injected as dynamic context (vs behavior-only section). */
217
- function isHeartbeatContextFile(pathValue) {
218
- return getContextFileBasename(pathValue) === DEFAULT_HEARTBEAT_FILENAME.toLowerCase();
102
+ /** Split a built prompt at the cache boundary (for tests and provider adapters). */
103
+ function splitBuiltSystemPrompt(text) {
104
+ return splitPromptCacheBoundary(text);
219
105
  }
220
106
  //#endregion
221
- export { buildSystemPrompt, isHeartbeatContextFile };
107
+ export { buildSystemPrompt, getContextFileBasename, isDynamicContextFile, sortContextFilesForPrompt, splitBuiltSystemPrompt };
222
108
 
223
109
  //# sourceMappingURL=system-prompt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"system-prompt.js","names":[],"sources":["../../../../src/agent/prompt/system-prompt.ts"],"sourcesContent":["/**\n * System Prompt Builder — xopc-owned prompt with OpenClaw-style bootstrap injection.\n *\n * Profile Markdown under `agents/<id>/profile/` is injected as Project Context\n * (see `src/agent/bootstrap/`). Runtime owns loading; AGENTS.md instructs agents\n * not to manually reread startup files.\n */\n\nimport type { EmbeddedContextFile } from '../bootstrap/types.js';\nimport { DEFAULT_HEARTBEAT_FILENAME } from '../context/workspace.js';\nimport { PROMPT_CACHE_BOUNDARY } from './cache-boundary.js';\nimport type { PromptMode } from './types.js';\n\nexport type MemoryCitationsMode = 'on' | 'off' | 'source-only';\n\nconst CONTEXT_FILE_ORDER = new Map<string, number>([\n ['agents.md', 10],\n ['soul.md', 20],\n ['identity.md', 30],\n ['user.md', 40],\n ['tools.md', 50],\n ['memory.md', 70],\n]);\n\nconst DYNAMIC_CONTEXT_FILE_BASENAMES = new Set(['heartbeat.md']);\n\nconst DEFAULT_HEARTBEAT_PROMPT_CONTEXT_BLOCK =\n 'Default heartbeat prompt:\\n`Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.`';\n\nfunction normalizeContextFilePath(pathValue: string): string {\n return pathValue.trim().replace(/\\\\/g, '/');\n}\n\nfunction getContextFileBasename(pathValue: string): string {\n const normalizedPath = normalizeContextFilePath(pathValue);\n return (normalizedPath.split('/').pop() ?? normalizedPath).toLowerCase();\n}\n\nfunction isDynamicContextFile(pathValue: string): boolean {\n return DYNAMIC_CONTEXT_FILE_BASENAMES.has(getContextFileBasename(pathValue));\n}\n\nfunction sanitizeContextFileContentForPrompt(content: string): string {\n return content.replaceAll(DEFAULT_HEARTBEAT_PROMPT_CONTEXT_BLOCK, '').replace(/\\n{3,}/g, '\\n\\n');\n}\n\nfunction sortContextFilesForPrompt(contextFiles: EmbeddedContextFile[]): EmbeddedContextFile[] {\n return [...contextFiles].sort((a, b) => {\n const aBase = getContextFileBasename(a.path);\n const bBase = getContextFileBasename(b.path);\n const aOrder = CONTEXT_FILE_ORDER.get(aBase) ?? Number.MAX_SAFE_INTEGER;\n const bOrder = CONTEXT_FILE_ORDER.get(bBase) ?? Number.MAX_SAFE_INTEGER;\n if (aOrder !== bOrder) {\n return aOrder - bOrder;\n }\n if (aBase !== bBase) {\n return aBase.localeCompare(bBase);\n }\n return normalizeContextFilePath(a.path).localeCompare(normalizeContextFilePath(b.path));\n });\n}\n\nfunction buildProjectContextSection(params: {\n files: EmbeddedContextFile[];\n heading: string;\n dynamic: boolean;\n}): string[] {\n if (params.files.length === 0) {\n return [];\n }\n const lines: string[] = [params.heading, ''];\n if (params.dynamic) {\n lines.push(\n 'The following frequently-changing project context files are kept below the cache boundary when possible:',\n '',\n );\n } else {\n const hasSoulFile = params.files.some((file) => getContextFileBasename(file.path) === 'soul.md');\n lines.push('The following project context files have been loaded:');\n if (hasSoulFile) {\n lines.push(\n 'If SOUL.md is present, embody its persona and tone. Avoid stiff, generic replies; follow its guidance unless higher-priority instructions override it.',\n );\n }\n lines.push('');\n }\n for (const file of params.files) {\n lines.push(`## ${file.path}`, '', sanitizeContextFileContentForPrompt(file.content), '');\n }\n return lines;\n}\n\nfunction buildMemorySection(\n citationsMode: MemoryCitationsMode = 'on',\n hasProfileMemory = false,\n): string {\n if (!hasProfileMemory) {\n return '';\n }\n\n const citationInstruction =\n citationsMode === 'off'\n ? 'Citations are disabled: do not mention file paths or line numbers in replies.'\n : citationsMode === 'source-only'\n ? 'Citations: mention file path when it helps (e.g., Source: MEMORY.md).'\n : 'Citations: include Source: <path#line> when it helps the user verify memory snippets.';\n\n return `## Memory Recall\n\n${citationInstruction}\n\nStartup profile files (SOUL, USER, MEMORY, etc.) are already in Project Context above. Do not re-read them unless the user asks or you need lines beyond what was injected.\n\nBefore answering anything about prior work, decisions, dates, people, preferences, or todos:\n1. Run \\`memory_search\\` on profile MEMORY.md and workspace \\`memory/*.md\\`\n2. For **other chat sessions** / cross-session history, use \\`session_search\\` with keywords (or omit \\`query\\` to list recent sessions)\n3. Use \\`memory_get\\` to pull only the needed lines from files\n4. For structured curated notes under agent home \\`memories/\\`, use \\`curated_memory\\`\n5. If low confidence after search, say you checked\n\n### Memory Files\n\n- **Daily notes:** \\`memory/YYYY-MM-DD.md\\` — raw logs (runtime may preload recent days on /new or /reset)\n- **Long-term:** profile \\`MEMORY.md\\` — curated memories in Project Context when present\n- **Curated store:** agent home \\`memories/MEMORY.md\\` and \\`memories/USER.md\\` — use \\`curated_memory\\` for live read/write\n\n### Writing to Memory\n\n- **Declarative vs procedural:** Save facts and preferences via workspace memory files and/or \\`curated_memory\\`. Save reusable task playbooks with \\`skill_manage\\` as skills.\n- **Memory is limited** — if you want to remember something, WRITE IT TO A FILE\n- When someone says \"remember this\" → update \\`memory/YYYY-MM-DD.md\\` or relevant file\n- **Text > Brain**\n`;\n}\n\nfunction buildSkillsSection(availableTools: string[] = []): string {\n if (availableTools.length === 0) {\n return '';\n }\n\n return `## Skills\n\nWhen a solution already exists, do not reinvent the wheel.\n\n**How to use:**\n1. Skim <available_skills> — is anything clearly relevant?\n2. Only one match? → Confirm with skills_list, then load the full text with skill_view(name) and follow it.\n3. Need sub-documents or scripts? → skill_view(name, \"references/…\"), etc.\n4. No match? → Solve it yourself; do not force-fit a skill.\n\n**Division of labor with memory:** Skills = **procedural** workflows; memory / \\`curated_memory\\` = **declarative** facts and preferences.\n`;\n}\n\nfunction buildSafetySection(): string {\n return `## Safety\n\n- You have no independent goals: do not pursue self-preservation, replication, resource acquisition, or power-seeking; avoid long-term plans beyond the user's request.\n- Prioritize safety and human oversight over completion; if instructions conflict, pause and ask; comply with stop/pause/audit requests and never bypass safeguards.\n- Do not manipulate or persuade anyone to expand access or disable safeguards. Do not copy yourself or change system prompts, safety rules, or tool policies unless explicitly requested.`;\n}\n\nfunction buildProblemSolvingSection(): string {\n return `## Problem Solving\n\n**Simple tasks** (< 5 minutes or a single-file change): Do them directly; run a quick verification after changes.\n\n**Complex tasks** (multiple files or design decisions): Use an iterative flow — Plan → Build → Verify → Fix.\n\n**Core principle: Match the complexity; reject ritual for its own sake. Verification matters, but do not verify just to tick a box.**`;\n}\n\nfunction buildAestheticSection(): string {\n return `## Tone & Style\n\n**Default voice:** Direct, concise, concrete.\n\n**SOUL.md takes precedence:** If SOUL.md defines a specific tone, defer to it over the above.`;\n}\n\nfunction buildHeartbeatBehaviorSection(params: {\n enabled: boolean;\n customPrompt?: string;\n userTimezone?: string;\n}): string {\n if (!params.enabled) {\n return '';\n }\n if (params.customPrompt?.trim()) {\n return `## Heartbeats\\n\\n${params.customPrompt.trim()}\\n`;\n }\n let quietHoursNote = '';\n if (params.userTimezone) {\n quietHoursNote = `\\n\\n> Quiet hours: The user is in **${params.userTimezone}**. Avoid proactive checks during late night (23:00-08:00) unless urgent.`;\n }\n return `## Heartbeats\n\nIf the current user message is a heartbeat poll and nothing needs attention, reply exactly: HEARTBEAT_OK\n\nIf something needs attention, do NOT include \"HEARTBEAT_OK\"; reply with the alert text instead.${quietHoursNote}\n`;\n}\n\nfunction buildMessagingSection(channels: string[] = [], isMinimal: boolean = false): string {\n if (isMinimal || channels.length === 0) {\n return '';\n }\n const channelList = channels.join(', ');\n return `## Messaging\n\n- Reply in current session → automatically routes to the source channel (${channelList})\n- Use \\`message\\` for proactive sends + channel actions\n- If you use \\`message\\` to deliver your user-visible reply, respond with ONLY: NO_REPLY (avoid duplicate replies)\n`;\n}\n\nfunction buildTimeSection(timezone?: string): string {\n if (!timezone) {\n return '';\n }\n return `## Current Date & Time\n\nTime zone: ${timezone}\n\nIf you need the current date/time/day-of-week, use the \\`session_status\\` tool or the inbound message timestamp envelope (when present).\n`;\n}\n\nfunction buildRuntimeSection(runtime?: { version?: string; model?: string; channel?: string }): string {\n if (!runtime) {\n return '';\n }\n const parts: string[] = [];\n if (runtime.version) parts.push(`v${runtime.version}`);\n if (runtime.model) parts.push(`model=${runtime.model.split('/').pop()}`);\n if (runtime.channel) parts.push(`ch=${runtime.channel}`);\n return parts.length > 0 ? `[${parts.join(' | ')}]` : '';\n}\n\nfunction buildWorkingDirSection(workspaceDir: string): string {\n return `Working directory: ${workspaceDir}`;\n}\n\nfunction buildExternalMemorySection(text: string | undefined): string {\n const t = text?.trim();\n if (!t) {\n return '';\n }\n return `## External memory provider\\n\\n${t}`;\n}\n\nexport interface SystemPromptOptions {\n /** Bootstrap context files from profile Markdown (Project Context). */\n contextFiles?: EmbeddedContextFile[];\n promptMode?: PromptMode;\n heartbeatEnabled?: boolean;\n heartbeatPrompt?: string;\n availableTools?: string[];\n memoryCitationsMode?: MemoryCitationsMode;\n userTimezone?: string;\n runtime?: {\n version?: string;\n model?: string;\n channel?: string;\n };\n channels?: string[];\n externalMemoryInstructions?: string;\n ttsSystemHint?: string;\n}\n\n/**\n * Build system prompt with bootstrap Project Context integration.\n */\nexport function buildSystemPrompt(workspaceDir: string, options: SystemPromptOptions): string {\n const {\n contextFiles = [],\n promptMode = 'full',\n heartbeatEnabled = false,\n heartbeatPrompt,\n availableTools = [],\n memoryCitationsMode = 'on',\n userTimezone,\n runtime,\n channels = [],\n externalMemoryInstructions,\n ttsSystemHint,\n } = options;\n\n if (promptMode === 'none') {\n return 'You are a personal AI assistant running inside xopc.';\n }\n\n const isMinimal = promptMode === 'minimal';\n const orderedContextFiles = sortContextFilesForPrompt(\n contextFiles.filter((file) => file.path.trim().length > 0),\n );\n const stableContextFiles = orderedContextFiles.filter((file) => !isDynamicContextFile(file.path));\n const dynamicContextFiles = orderedContextFiles.filter((file) => isDynamicContextFile(file.path));\n const hasProfileMemory = orderedContextFiles.some(\n (file) => getContextFileBasename(file.path) === 'memory.md',\n );\n\n const sections: string[] = [\n 'You are a personal AI assistant running inside xopc.',\n '',\n '## Workspace Files (injected)',\n '',\n 'Profile bootstrap files are injected below as Project Context. Do not manually reread them at session start unless the user asks or injected content is insufficient.',\n '',\n ];\n\n if (!isMinimal) {\n sections.push(buildTimeSection(userTimezone));\n sections.push(buildExternalMemorySection(externalMemoryInstructions));\n sections.push(buildMemorySection(memoryCitationsMode, hasProfileMemory));\n }\n\n sections.push(buildSkillsSection(availableTools));\n\n if (!isMinimal) {\n sections.push(buildSafetySection());\n sections.push(buildProblemSolvingSection());\n sections.push(buildAestheticSection());\n }\n\n sections.push(\n ...buildProjectContextSection({\n files: stableContextFiles,\n heading: '# Project Context',\n dynamic: false,\n }),\n );\n\n sections.push(PROMPT_CACHE_BOUNDARY);\n\n sections.push(\n ...buildProjectContextSection({\n files: dynamicContextFiles,\n heading: stableContextFiles.length > 0 ? '# Dynamic Project Context' : '# Project Context',\n dynamic: true,\n }),\n );\n\n sections.push(buildHeartbeatBehaviorSection({ enabled: heartbeatEnabled, customPrompt: heartbeatPrompt, userTimezone }));\n sections.push(buildWorkingDirSection(workspaceDir));\n sections.push(buildMessagingSection(channels, isMinimal));\n\n if (!isMinimal && ttsSystemHint?.trim()) {\n sections.push(`## Voice (TTS)\\n\\n${ttsSystemHint.trim()}`);\n }\n\n sections.push(buildRuntimeSection(runtime));\n\n return sections.filter(Boolean).join('\\n\\n');\n}\n\n/** Whether HEARTBEAT.md is injected as dynamic context (vs behavior-only section). */\nexport function isHeartbeatContextFile(pathValue: string): boolean {\n return getContextFileBasename(pathValue) === DEFAULT_HEARTBEAT_FILENAME.toLowerCase();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"system-prompt.js","names":[],"sources":["../../../../src/agent/prompt/system-prompt.ts"],"sourcesContent":["/**\n * System Prompt Builder — xopc-owned prompt with OpenClaw-style bootstrap injection.\n *\n * Profile Markdown under `agents/<id>/profile/` is injected as Project Context\n * (see `src/agent/bootstrap/`). Runtime owns loading; AGENTS.md instructs agents\n * not to manually reread startup files.\n */\n\nimport type { EmbeddedContextFile } from '../bootstrap/types.js';\nimport { PROMPT_CACHE_BOUNDARY, splitPromptCacheBoundary } from './cache-boundary.js';\nimport type { ProviderSystemPromptContribution } from './contribution.js';\nimport {\n buildAestheticSection,\n buildExecutionBiasSection,\n buildProblemSolvingSection,\n buildSafetySection,\n buildToolCallStyleSection,\n} from './sections/behavior.js';\nimport {\n buildExternalMemorySection,\n buildMemorySection,\n buildSkillsSection,\n} from './sections/memory-skills.js';\nimport {\n buildHeartbeatBehaviorSection,\n buildMessagingSection,\n buildOutputDirectivesSection,\n buildSilentRepliesSection,\n buildTimeSection,\n} from './sections/messaging-runtime.js';\nimport {\n buildProjectContextSection,\n getContextFileBasename,\n isDynamicContextFile,\n sortContextFilesForPrompt,\n} from './sections/project-context.js';\nimport { buildToolingSection, hasSkillsTools } from './sections/tooling.js';\nimport {\n buildRuntimeSection,\n buildWorkspaceFilesIntroSection,\n buildWorkspaceSection,\n type RuntimeInfoInput,\n} from './sections/workspace-runtime.js';\nimport { buildOverridablePromptSection } from './system-prompt-params.js';\nimport type { MemoryCitationsMode, PromptMode, SilentReplyPromptMode } from './types.js';\n\nexport type { MemoryCitationsMode } from './types.js';\nexport {\n getContextFileBasename,\n isDynamicContextFile,\n sortContextFilesForPrompt,\n} from './sections/project-context.js';\n\nexport interface SystemPromptOptions {\n contextFiles?: EmbeddedContextFile[];\n promptMode?: PromptMode;\n heartbeatEnabled?: boolean;\n heartbeatPrompt?: string;\n /** Registered tool names for Tooling section and memory/skills gating. */\n toolNames?: string[];\n toolSummaries?: Record<string, string>;\n /** @deprecated Prefer toolNames — kept for skill-section gating compatibility. */\n availableTools?: string[];\n memoryCitationsMode?: MemoryCitationsMode;\n includeMemorySection?: boolean;\n userTimezone?: string;\n runtime?: RuntimeInfoInput;\n channels?: string[];\n externalMemoryInstructions?: string;\n ttsSystemHint?: string;\n extraSystemPrompt?: string;\n silentReplyPromptMode?: SilentReplyPromptMode;\n promptContribution?: ProviderSystemPromptContribution;\n includeProblemSolving?: boolean;\n includeToneSection?: boolean;\n}\n\nfunction joinSections(sections: Array<string | undefined>): string {\n return sections.filter((section): section is string => Boolean(section?.trim())).join('\\n\\n');\n}\n\n/**\n * Build system prompt with bootstrap Project Context integration.\n */\nexport function buildSystemPrompt(workspaceDir: string, options: SystemPromptOptions = {}): string {\n const {\n contextFiles = [],\n promptMode = 'full',\n heartbeatEnabled = false,\n heartbeatPrompt,\n toolNames: toolNamesOption,\n toolSummaries,\n availableTools = [],\n memoryCitationsMode = 'on',\n includeMemorySection,\n userTimezone,\n runtime,\n channels = [],\n externalMemoryInstructions,\n ttsSystemHint,\n extraSystemPrompt,\n silentReplyPromptMode = 'generic',\n promptContribution,\n includeProblemSolving = true,\n includeToneSection = true,\n } = options;\n\n if (promptMode === 'none') {\n return 'You are a personal AI assistant running inside xopc.';\n }\n\n const isMinimal = promptMode === 'minimal';\n const toolNames = toolNamesOption ?? availableTools;\n const normalizedTools = new Set(toolNames.map((tool) => tool.toLowerCase()));\n const sectionOverrides = promptContribution?.sectionOverrides ?? {};\n\n const orderedContextFiles = sortContextFilesForPrompt(\n contextFiles.filter((file) => file.path.trim().length > 0),\n );\n const stableContextFiles = orderedContextFiles.filter((file) => !isDynamicContextFile(file.path));\n const dynamicContextFiles = orderedContextFiles.filter((file) => isDynamicContextFile(file.path));\n const hasProfileMemory = orderedContextFiles.some(\n (file) => getContextFileBasename(file.path) === 'memory.md',\n );\n\n const stableSections: string[] = [\n 'You are a personal AI assistant running inside xopc.',\n buildToolingSection({ toolNames, toolSummaries }),\n buildOverridablePromptSection({\n override: sectionOverrides.tool_call_style,\n fallback: buildToolCallStyleSection(),\n }),\n ];\n\n if (!isMinimal) {\n stableSections.push(\n buildOverridablePromptSection({\n override: sectionOverrides.execution_bias,\n fallback: buildExecutionBiasSection(),\n }),\n );\n }\n\n const providerStablePrefix = buildOverridablePromptSection({\n override: promptContribution?.stablePrefix,\n fallback: '',\n });\n if (providerStablePrefix) {\n stableSections.push(providerStablePrefix);\n }\n\n stableSections.push(buildSafetySection());\n\n if (hasSkillsTools(toolNames)) {\n stableSections.push(buildSkillsSection(true));\n }\n\n if (!isMinimal) {\n stableSections.push(\n buildMemorySection({\n availableTools: normalizedTools,\n citationsMode: memoryCitationsMode,\n hasProfileMemory,\n includeMemorySection,\n }),\n buildExternalMemorySection(externalMemoryInstructions),\n );\n if (includeProblemSolving) {\n stableSections.push(buildProblemSolvingSection());\n }\n if (includeToneSection) {\n stableSections.push(buildAestheticSection());\n }\n stableSections.push(buildTimeSection(userTimezone));\n }\n\n stableSections.push(\n buildWorkspaceSection(workspaceDir),\n buildWorkspaceFilesIntroSection(),\n );\n\n if (!isMinimal) {\n stableSections.push(buildOutputDirectivesSection(isMinimal));\n }\n\n stableSections.push(\n buildMessagingSection({\n channels,\n isMinimal,\n hasSendMessage: normalizedTools.has('send_message'),\n }),\n );\n\n if (!isMinimal && ttsSystemHint?.trim()) {\n stableSections.push(`## Voice (TTS)\\n\\n${ttsSystemHint.trim()}`);\n }\n\n stableSections.push(\n joinSections(\n buildProjectContextSection({\n files: stableContextFiles,\n heading: '# Project Context',\n dynamic: false,\n }),\n ),\n );\n\n if (!isMinimal) {\n stableSections.push(\n buildSilentRepliesSection({ isMinimal, silentReplyPromptMode }),\n );\n }\n\n const dynamicSections: string[] = [];\n\n dynamicSections.push(\n joinSections(\n buildProjectContextSection({\n files: dynamicContextFiles,\n heading: stableContextFiles.length > 0 ? '# Dynamic Project Context' : '# Project Context',\n dynamic: true,\n }),\n ),\n );\n\n if (extraSystemPrompt?.trim()) {\n const contextHeader = isMinimal ? '## Subagent Context' : '## Group Chat Context';\n dynamicSections.push(`${contextHeader}\\n\\n${extraSystemPrompt.trim()}`);\n }\n\n const providerDynamicSuffix = buildOverridablePromptSection({\n override: promptContribution?.dynamicSuffix,\n fallback: '',\n });\n if (providerDynamicSuffix) {\n dynamicSections.push(providerDynamicSuffix);\n }\n\n dynamicSections.push(\n buildHeartbeatBehaviorSection({\n enabled: heartbeatEnabled,\n customPrompt: heartbeatPrompt,\n userTimezone,\n }),\n buildRuntimeSection(runtime),\n );\n\n const stablePrefix = joinSections(stableSections);\n const dynamicSuffix = joinSections(dynamicSections);\n\n if (!dynamicSuffix.trim()) {\n return `${stablePrefix}\\n\\n${PROMPT_CACHE_BOUNDARY}`.trim();\n }\n\n return `${stablePrefix}\\n\\n${PROMPT_CACHE_BOUNDARY}\\n\\n${dynamicSuffix}`.trim();\n}\n\n/** Split a built prompt at the cache boundary (for tests and provider adapters). */\nexport function splitBuiltSystemPrompt(text: string) {\n return splitPromptCacheBoundary(text);\n}\n"],"mappings":"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"}
@@ -6,3 +6,6 @@
6
6
  * - "none": Just basic identity line, no sections
7
7
  */
8
8
  export type PromptMode = 'full' | 'minimal' | 'none';
9
+ /** Controls the generic silent-reply section. Channel-aware callers can set "none". */
10
+ export type SilentReplyPromptMode = 'generic' | 'none';
11
+ export type MemoryCitationsMode = 'on' | 'off' | 'source-only';
@@ -1,30 +1,14 @@
1
1
  import type { Config } from '../../config/schema.js';
2
+ import type { MediaRef } from '../../channels/attachments/inbound-persist.js';
2
3
  import type { AgentInstanceGateway } from '../agent-instance-gateway.js';
3
4
  import type { ModelManager } from '../models/index.js';
4
- export type DirectInboundAttachment = {
5
- type: string;
6
- mimeType?: string;
7
- data?: string;
8
- name?: string;
9
- size?: number;
10
- workspaceRelativePath?: string;
11
- };
12
- export type DirectMessagePart = {
13
- type: 'text';
14
- text: string;
15
- } | {
16
- type: 'image';
17
- data: string;
18
- mimeType: string;
19
- };
20
- /**
21
- * Build user message parts (text + resolved images/files) for direct / webchat turns.
22
- */
5
+ export type { InboundAttachmentInput as DirectInboundWireAttachment } from '../../channels/attachments/inbound-persist.js';
6
+ export type { MediaRef as DirectInboundAttachment } from '../../channels/attachments/inbound-persist.js';
23
7
  export declare function buildDirectUserMessageContent(opts: {
24
8
  content: string;
25
- attachments?: DirectInboundAttachment[];
9
+ attachments?: MediaRef[];
26
10
  sessionKey?: string;
27
11
  config: Config;
28
12
  agentManager: AgentInstanceGateway;
29
13
  modelManager: ModelManager;
30
- }): Promise<DirectMessagePart[]>;
14
+ }): Promise<import("../inbound/attachment-pipeline.js").TranscriptUserMessage>;
@@ -1,73 +1,20 @@
1
1
  import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
2
- import { init_agent_scope, resolveAgentHomeDir, resolveDefaultAgentId } from "../agent-scope.js";
3
- import { extractProfileAgentId } from "../../config/agent-profile.js";
4
2
  import { getDefaultModelSync, init_providers } from "../../providers/index.js";
5
- import { formatInboundFileTextBlock } from "../../channels/attachments/inbound-persist.js";
6
- import { expandAtFileMentionsInPlainText } from "../context/expand-at-file-mentions.js";
7
- import { resolveInboundImageContentParts } from "../image/inbound-image-handling.js";
3
+ import { buildTranscriptUserMessage } from "../inbound/attachment-pipeline.js";
8
4
  //#region src/agent/service/build-direct-message-content.ts
9
5
  init_schema();
10
6
  init_providers();
11
- init_agent_scope();
12
- /**
13
- * Build user message parts (text + resolved images/files) for direct / webchat turns.
14
- */
15
7
  async function buildDirectUserMessageContent(opts) {
16
- const { content, attachments, sessionKey, config, agentManager, modelManager } = opts;
17
- const messageContent = [];
18
- const sk = sessionKey ?? "";
19
- if (content.trim()) {
20
- let textPart = content;
21
- if (/@file:/.test(textPart)) {
22
- const wsKey = sk !== "" ? sk : "agent:main:main";
23
- const root = agentManager.getResolvedWorkspaceForSession(wsKey);
24
- textPart = await expandAtFileMentionsInPlainText(textPart, root);
25
- }
26
- messageContent.push({
27
- type: "text",
28
- text: textPart
29
- });
30
- }
31
- if (!attachments?.length) return messageContent;
32
- const modelRef = sk !== "" ? modelManager.getModelForSession(sk) : getAgentDefaultModelRef(config) ?? getDefaultModelSync(config);
33
- const storageRoot = sk !== "" ? resolveAgentHomeDir(config, extractProfileAgentId(sk, config)) : resolveAgentHomeDir(config, resolveDefaultAgentId(config));
34
- let i = 0;
35
- while (i < attachments.length) {
36
- const att = attachments[i];
37
- if (att.type === "image" || att.type === "photo" || Boolean(att.mimeType?.startsWith("image/"))) {
38
- const group = [];
39
- while (i < attachments.length) {
40
- const a = attachments[i];
41
- if (!(a.type === "image" || a.type === "photo" || Boolean(a.mimeType?.startsWith("image/")))) break;
42
- if (!a.data || a.data.length === 0) {
43
- i += 1;
44
- continue;
45
- }
46
- group.push({
47
- data: a.data,
48
- mimeType: a.mimeType || "image/png"
49
- });
50
- i += 1;
51
- }
52
- if (group.length > 0) {
53
- const parts = await resolveInboundImageContentParts({
54
- modelRef: modelRef || getDefaultModelSync(config),
55
- cfg: config,
56
- userTextForContext: content.trim() ? content : "",
57
- images: group
58
- });
59
- messageContent.push(...parts);
60
- }
61
- } else {
62
- const fileBlock = formatInboundFileTextBlock(att, storageRoot);
63
- messageContent.push({
64
- type: "text",
65
- text: fileBlock
66
- });
67
- i += 1;
68
- }
69
- }
70
- return messageContent;
8
+ const sk = opts.sessionKey ?? "";
9
+ const modelRef = sk !== "" ? opts.modelManager.getModelForSession(sk) : getAgentDefaultModelRef(opts.config) ?? getDefaultModelSync(opts.config);
10
+ return buildTranscriptUserMessage({
11
+ text: opts.content,
12
+ prepared: opts.attachments,
13
+ sessionKey: sk,
14
+ modelRef: modelRef || getDefaultModelSync(opts.config),
15
+ config: opts.config,
16
+ agentManager: opts.agentManager
17
+ });
71
18
  }
72
19
  //#endregion
73
20
  export { buildDirectUserMessageContent };