@ouro.bot/cli 0.1.0-alpha.38 → 0.1.0-alpha.381

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 (331) hide show
  1. package/README.md +109 -14
  2. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
  3. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  4. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  5. package/changelog.json +2303 -2
  6. package/dist/arc/attention-types.js +8 -0
  7. package/dist/arc/cares.js +140 -0
  8. package/dist/arc/episodes.js +117 -0
  9. package/dist/arc/intentions.js +133 -0
  10. package/dist/arc/json-store.js +117 -0
  11. package/dist/arc/obligations.js +237 -0
  12. package/dist/arc/packets.js +193 -0
  13. package/dist/arc/presence.js +185 -0
  14. package/dist/arc/task-lifecycle.js +65 -0
  15. package/dist/heart/active-work.js +832 -0
  16. package/dist/heart/agent-entry.js +58 -3
  17. package/dist/heart/attachments/image-normalize.js +194 -0
  18. package/dist/heart/attachments/materialize.js +97 -0
  19. package/dist/heart/attachments/originals.js +88 -0
  20. package/dist/heart/attachments/render.js +29 -0
  21. package/dist/heart/attachments/sources/adapter.js +2 -0
  22. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  23. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  24. package/dist/heart/attachments/sources/index.js +16 -0
  25. package/dist/heart/attachments/store.js +103 -0
  26. package/dist/heart/attachments/types.js +93 -0
  27. package/dist/heart/auth/auth-flow.js +378 -0
  28. package/dist/heart/bridges/manager.js +358 -0
  29. package/dist/heart/bridges/state-machine.js +135 -0
  30. package/dist/heart/bridges/store.js +123 -0
  31. package/dist/heart/bundle-state.js +168 -0
  32. package/dist/heart/commitments.js +111 -0
  33. package/dist/heart/config-registry.js +304 -0
  34. package/dist/heart/config.js +111 -128
  35. package/dist/heart/core.js +803 -259
  36. package/dist/heart/cross-chat-delivery.js +131 -0
  37. package/dist/heart/daemon/agent-config-check.js +376 -0
  38. package/dist/heart/daemon/agent-discovery.js +79 -3
  39. package/dist/heart/daemon/agent-service.js +360 -0
  40. package/dist/heart/daemon/agentic-repair.js +205 -0
  41. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  42. package/dist/heart/daemon/cadence.js +70 -0
  43. package/dist/heart/daemon/cli-defaults.js +560 -0
  44. package/dist/heart/daemon/cli-exec.js +3220 -0
  45. package/dist/heart/daemon/cli-help.js +319 -0
  46. package/dist/heart/daemon/cli-parse.js +1060 -0
  47. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  48. package/dist/heart/daemon/cli-render.js +560 -0
  49. package/dist/heart/daemon/cli-types.js +8 -0
  50. package/dist/heart/daemon/daemon-cli.js +29 -1498
  51. package/dist/heart/daemon/daemon-entry.js +356 -3
  52. package/dist/heart/daemon/daemon-health.js +141 -0
  53. package/dist/heart/daemon/daemon-runtime-sync.js +157 -12
  54. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  55. package/dist/heart/daemon/daemon.js +774 -58
  56. package/dist/heart/daemon/doctor-types.js +8 -0
  57. package/dist/heart/daemon/doctor.js +419 -0
  58. package/dist/heart/daemon/health-monitor.js +79 -1
  59. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  60. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  61. package/dist/heart/daemon/http-health-probe.js +80 -0
  62. package/dist/heart/daemon/inner-status.js +89 -0
  63. package/dist/heart/daemon/interactive-repair.js +182 -0
  64. package/dist/heart/daemon/launchd.js +46 -9
  65. package/dist/heart/daemon/log-tailer.js +82 -12
  66. package/dist/heart/daemon/logs-prune.js +105 -0
  67. package/dist/heart/daemon/message-router.js +17 -8
  68. package/dist/heart/daemon/os-cron-deps.js +134 -0
  69. package/dist/heart/daemon/ouro-bot-entry.js +1 -1
  70. package/dist/heart/daemon/process-manager.js +201 -0
  71. package/dist/heart/daemon/provider-discovery.js +137 -0
  72. package/dist/heart/daemon/pulse.js +475 -0
  73. package/dist/heart/daemon/run-hooks.js +2 -0
  74. package/dist/heart/daemon/runtime-logging.js +67 -16
  75. package/dist/heart/daemon/runtime-metadata.js +73 -0
  76. package/dist/heart/daemon/runtime-mode.js +67 -0
  77. package/dist/heart/daemon/safe-mode.js +161 -0
  78. package/dist/heart/daemon/sense-manager.js +119 -30
  79. package/dist/heart/daemon/session-id-resolver.js +131 -0
  80. package/dist/heart/daemon/skill-management-installer.js +94 -0
  81. package/dist/heart/daemon/socket-client.js +307 -0
  82. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  83. package/dist/heart/daemon/startup-tui.js +237 -0
  84. package/dist/heart/daemon/task-scheduler.js +3 -25
  85. package/dist/heart/daemon/thoughts.js +510 -0
  86. package/dist/heart/daemon/up-progress.js +135 -0
  87. package/dist/heart/delegation.js +62 -0
  88. package/dist/heart/habits/habit-migration.js +181 -0
  89. package/dist/heart/habits/habit-parser.js +140 -0
  90. package/dist/heart/habits/habit-scheduler.js +371 -0
  91. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -126
  92. package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
  93. package/dist/heart/{daemon → hatch}/specialist-prompt.js +10 -8
  94. package/dist/heart/{daemon → hatch}/specialist-tools.js +30 -10
  95. package/dist/heart/identity.js +153 -65
  96. package/dist/heart/kept-notes.js +357 -0
  97. package/dist/heart/kicks.js +2 -20
  98. package/dist/heart/machine-identity.js +161 -0
  99. package/dist/heart/mcp/mcp-server.js +653 -0
  100. package/dist/heart/migrate-config.js +100 -0
  101. package/dist/heart/model-capabilities.js +59 -0
  102. package/dist/heart/outlook/outlook-http-hooks.js +64 -0
  103. package/dist/heart/outlook/outlook-http-response.js +7 -0
  104. package/dist/heart/outlook/outlook-http-routes.js +232 -0
  105. package/dist/heart/outlook/outlook-http-static.js +99 -0
  106. package/dist/heart/outlook/outlook-http-transport.js +116 -0
  107. package/dist/heart/outlook/outlook-http.js +99 -0
  108. package/dist/heart/outlook/outlook-read.js +28 -0
  109. package/dist/heart/outlook/outlook-types.js +27 -0
  110. package/dist/heart/outlook/outlook-view.js +195 -0
  111. package/dist/heart/outlook/readers/agent-machine.js +359 -0
  112. package/dist/heart/outlook/readers/continuity-readers.js +332 -0
  113. package/dist/heart/outlook/readers/runtime-readers.js +660 -0
  114. package/dist/heart/outlook/readers/sessions.js +232 -0
  115. package/dist/heart/outlook/readers/shared.js +111 -0
  116. package/dist/heart/platform.js +81 -0
  117. package/dist/heart/progress-story.js +42 -0
  118. package/dist/heart/provider-attempt.js +133 -0
  119. package/dist/heart/provider-binding-resolver.js +239 -0
  120. package/dist/heart/provider-credentials.js +379 -0
  121. package/dist/heart/provider-failover.js +266 -0
  122. package/dist/heart/provider-models.js +81 -0
  123. package/dist/heart/provider-ping.js +237 -0
  124. package/dist/heart/provider-state.js +216 -0
  125. package/dist/heart/provider-visibility.js +186 -0
  126. package/dist/heart/providers/anthropic-token.js +131 -0
  127. package/dist/heart/providers/anthropic.js +193 -55
  128. package/dist/heart/providers/azure.js +103 -12
  129. package/dist/heart/providers/error-classification.js +63 -0
  130. package/dist/heart/providers/github-copilot.js +145 -0
  131. package/dist/heart/providers/minimax-vlm.js +189 -0
  132. package/dist/heart/providers/minimax.js +29 -7
  133. package/dist/heart/providers/openai-codex.js +39 -29
  134. package/dist/heart/runtime-credentials.js +181 -0
  135. package/dist/heart/session-activity.js +190 -0
  136. package/dist/heart/session-events.js +855 -0
  137. package/dist/heart/session-transcript.js +167 -0
  138. package/dist/heart/start-of-turn-packet.js +345 -0
  139. package/dist/heart/streaming.js +36 -27
  140. package/dist/heart/sync.js +332 -0
  141. package/dist/heart/target-resolution.js +127 -0
  142. package/dist/heart/tempo.js +93 -0
  143. package/dist/heart/temporal-view.js +41 -0
  144. package/dist/heart/tool-activity-callbacks.js +36 -0
  145. package/dist/heart/tool-description.js +135 -0
  146. package/dist/heart/tool-friction.js +55 -0
  147. package/dist/heart/tool-loop.js +200 -0
  148. package/dist/heart/turn-context.js +351 -0
  149. package/dist/heart/turn-coordinator.js +28 -0
  150. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +1 -1
  151. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  152. package/dist/heart/versioning/ouro-path-installer.js +301 -0
  153. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  154. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  155. package/dist/heart/{daemon → versioning}/update-checker.js +12 -2
  156. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  157. package/dist/mind/bundle-manifest.js +7 -1
  158. package/dist/mind/context.js +141 -94
  159. package/dist/mind/diary-integrity.js +60 -0
  160. package/dist/mind/{memory.js → diary.js} +84 -96
  161. package/dist/mind/embedding-provider.js +60 -0
  162. package/dist/mind/file-state.js +179 -0
  163. package/dist/mind/first-impressions.js +14 -1
  164. package/dist/mind/friends/channel.js +48 -0
  165. package/dist/mind/friends/group-context.js +144 -0
  166. package/dist/mind/friends/resolver.js +38 -1
  167. package/dist/mind/friends/store-file.js +39 -3
  168. package/dist/mind/friends/trust-explanation.js +74 -0
  169. package/dist/mind/friends/types.js +9 -1
  170. package/dist/mind/journal-index.js +161 -0
  171. package/dist/mind/note-search.js +268 -0
  172. package/dist/mind/obligation-steering.js +221 -0
  173. package/dist/mind/pending.js +74 -7
  174. package/dist/mind/prompt-refresh.js +3 -2
  175. package/dist/mind/prompt.js +966 -183
  176. package/dist/mind/provenance-trust.js +26 -0
  177. package/dist/mind/scrutiny.js +173 -0
  178. package/dist/mind/token-estimate.js +8 -12
  179. package/dist/nerves/cli-logging.js +7 -1
  180. package/dist/nerves/coverage/audit-rules.js +15 -6
  181. package/dist/nerves/coverage/audit.js +28 -2
  182. package/dist/nerves/coverage/cli.js +1 -1
  183. package/dist/nerves/coverage/file-completeness.js +83 -5
  184. package/dist/nerves/coverage/run-artifacts.js +1 -1
  185. package/dist/nerves/event-buffer.js +111 -0
  186. package/dist/nerves/index.js +224 -4
  187. package/dist/nerves/observation.js +20 -0
  188. package/dist/nerves/redact.js +79 -0
  189. package/dist/nerves/runtime.js +5 -1
  190. package/dist/outlook-ui/assets/index-BAcU08c-.css +1 -0
  191. package/dist/outlook-ui/assets/index-D7l3l4vY.js +61 -0
  192. package/dist/outlook-ui/index.html +15 -0
  193. package/dist/repertoire/ado-client.js +15 -56
  194. package/dist/repertoire/ado-semantic.js +11 -10
  195. package/dist/repertoire/api-client.js +97 -0
  196. package/dist/repertoire/bitwarden-store.js +365 -0
  197. package/dist/repertoire/bundle-templates.js +72 -0
  198. package/dist/repertoire/bw-installer.js +79 -0
  199. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  200. package/dist/repertoire/coding/context-pack.js +330 -0
  201. package/dist/repertoire/coding/feedback.js +197 -30
  202. package/dist/repertoire/coding/manager.js +158 -9
  203. package/dist/repertoire/coding/spawner.js +55 -9
  204. package/dist/repertoire/coding/tools.js +170 -7
  205. package/dist/repertoire/commerce-errors.js +109 -0
  206. package/dist/repertoire/commerce-self-test.js +156 -0
  207. package/dist/repertoire/credential-access.js +107 -0
  208. package/dist/repertoire/duffel-client.js +185 -0
  209. package/dist/repertoire/github-client.js +14 -55
  210. package/dist/repertoire/graph-client.js +11 -52
  211. package/dist/repertoire/guardrails.js +371 -0
  212. package/dist/repertoire/mcp-client.js +255 -0
  213. package/dist/repertoire/mcp-manager.js +305 -0
  214. package/dist/repertoire/mcp-tools.js +63 -0
  215. package/dist/repertoire/shell-sessions.js +133 -0
  216. package/dist/repertoire/skills.js +15 -24
  217. package/dist/repertoire/stripe-client.js +131 -0
  218. package/dist/repertoire/tasks/board.js +43 -5
  219. package/dist/repertoire/tasks/fix.js +182 -0
  220. package/dist/repertoire/tasks/index.js +28 -10
  221. package/dist/repertoire/tasks/lifecycle.js +2 -2
  222. package/dist/repertoire/tasks/parser.js +3 -2
  223. package/dist/repertoire/tasks/scanner.js +194 -37
  224. package/dist/repertoire/tasks/transitions.js +16 -79
  225. package/dist/repertoire/tool-results.js +29 -0
  226. package/dist/repertoire/tools-attachments.js +317 -0
  227. package/dist/repertoire/tools-base.js +42 -690
  228. package/dist/repertoire/tools-bluebubbles.js +1 -0
  229. package/dist/repertoire/tools-bridge.js +141 -0
  230. package/dist/repertoire/tools-bundle.js +984 -0
  231. package/dist/repertoire/tools-config.js +185 -0
  232. package/dist/repertoire/tools-continuity.js +248 -0
  233. package/dist/repertoire/tools-credential.js +182 -0
  234. package/dist/repertoire/tools-files.js +342 -0
  235. package/dist/repertoire/tools-flight.js +224 -0
  236. package/dist/repertoire/tools-flow.js +105 -0
  237. package/dist/repertoire/tools-github.js +1 -7
  238. package/dist/repertoire/tools-notes.js +376 -0
  239. package/dist/repertoire/tools-session.js +739 -0
  240. package/dist/repertoire/tools-shell.js +120 -0
  241. package/dist/repertoire/tools-stripe.js +180 -0
  242. package/dist/repertoire/tools-surface.js +243 -0
  243. package/dist/repertoire/tools-teams.js +12 -62
  244. package/dist/repertoire/tools-travel.js +125 -0
  245. package/dist/repertoire/tools-user-profile.js +144 -0
  246. package/dist/repertoire/tools-vault.js +40 -0
  247. package/dist/repertoire/tools.js +144 -120
  248. package/dist/repertoire/travel-api-client.js +360 -0
  249. package/dist/repertoire/user-profile.js +118 -0
  250. package/dist/repertoire/vault-setup.js +241 -0
  251. package/dist/repertoire/vault-unlock.js +364 -0
  252. package/dist/scripts/claude-code-hook.js +41 -0
  253. package/dist/scripts/claude-code-stop-hook.js +47 -0
  254. package/dist/senses/attention-queue.js +116 -0
  255. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  256. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  257. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +260 -9
  258. package/dist/senses/bluebubbles/entry.js +70 -0
  259. package/dist/senses/bluebubbles/inbound-log.js +113 -0
  260. package/dist/senses/bluebubbles/index.js +1620 -0
  261. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  262. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +43 -12
  263. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +46 -6
  264. package/dist/senses/bluebubbles/replay.js +129 -0
  265. package/dist/senses/bluebubbles/runtime-state.js +109 -0
  266. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  267. package/dist/senses/cli/bracketed-paste.js +82 -0
  268. package/dist/senses/cli/image-paste.js +287 -0
  269. package/dist/senses/cli/image-ref-navigation.js +75 -0
  270. package/dist/senses/cli/ink-app.js +156 -0
  271. package/dist/senses/cli/inline-diff.js +64 -0
  272. package/dist/senses/cli/input-keys.js +174 -0
  273. package/dist/senses/cli/kill-ring.js +86 -0
  274. package/dist/senses/cli/message-list.js +51 -0
  275. package/dist/senses/cli/ouro-tui.js +605 -0
  276. package/dist/senses/cli/spinner-imperative.js +135 -0
  277. package/dist/senses/cli/spinner.js +101 -0
  278. package/dist/senses/cli/status-line.js +60 -0
  279. package/dist/senses/cli/streaming-markdown.js +526 -0
  280. package/dist/senses/cli/tool-display.js +83 -0
  281. package/dist/senses/cli/tool-render.js +85 -0
  282. package/dist/senses/cli/tui-store.js +240 -0
  283. package/dist/senses/cli/virtual-list.js +35 -0
  284. package/dist/senses/cli-entry.js +60 -8
  285. package/dist/senses/cli-layout.js +187 -0
  286. package/dist/senses/cli.js +574 -254
  287. package/dist/senses/commands.js +66 -3
  288. package/dist/senses/continuity.js +94 -0
  289. package/dist/senses/habit-turn-message.js +108 -0
  290. package/dist/senses/inner-dialog-worker.js +112 -19
  291. package/dist/senses/inner-dialog.js +630 -82
  292. package/dist/senses/pipeline.js +602 -0
  293. package/dist/senses/proactive-content-guard.js +51 -0
  294. package/dist/senses/shared-turn.js +205 -0
  295. package/dist/senses/surface-tool.js +68 -0
  296. package/dist/senses/teams-entry.js +60 -8
  297. package/dist/senses/teams.js +585 -231
  298. package/dist/senses/trust-gate.js +112 -2
  299. package/package.json +28 -7
  300. package/skills/agent-commerce.md +106 -0
  301. package/skills/browser-navigation.md +110 -0
  302. package/skills/commerce-setup-guide.md +116 -0
  303. package/skills/commerce-setup.md +84 -0
  304. package/skills/configure-dev-tools.md +101 -0
  305. package/skills/travel-planning.md +134 -0
  306. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  307. package/dist/heart/daemon/subagent-installer.js +0 -134
  308. package/dist/mind/associative-recall.js +0 -197
  309. package/dist/senses/bluebubbles-entry.js +0 -11
  310. package/dist/senses/bluebubbles.js +0 -736
  311. package/dist/senses/debug-activity.js +0 -127
  312. package/subagents/README.md +0 -60
  313. package/subagents/work-doer.md +0 -235
  314. package/subagents/work-merger.md +0 -618
  315. package/subagents/work-planner.md +0 -382
  316. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  317. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  318. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  319. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  320. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  321. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  322. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  323. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  324. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  325. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  326. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  327. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  328. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  329. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  330. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  331. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -1,736 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.handleBlueBubblesEvent = handleBlueBubblesEvent;
37
- exports.createBlueBubblesWebhookHandler = createBlueBubblesWebhookHandler;
38
- exports.drainAndSendPendingBlueBubbles = drainAndSendPendingBlueBubbles;
39
- exports.startBlueBubblesApp = startBlueBubblesApp;
40
- const fs = __importStar(require("node:fs"));
41
- const http = __importStar(require("node:http"));
42
- const path = __importStar(require("node:path"));
43
- const core_1 = require("../heart/core");
44
- const config_1 = require("../heart/config");
45
- const identity_1 = require("../heart/identity");
46
- const context_1 = require("../mind/context");
47
- const tokens_1 = require("../mind/friends/tokens");
48
- const resolver_1 = require("../mind/friends/resolver");
49
- const store_file_1 = require("../mind/friends/store-file");
50
- const prompt_1 = require("../mind/prompt");
51
- const phrases_1 = require("../mind/phrases");
52
- const runtime_1 = require("../nerves/runtime");
53
- const bluebubbles_model_1 = require("./bluebubbles-model");
54
- const bluebubbles_client_1 = require("./bluebubbles-client");
55
- const bluebubbles_mutation_log_1 = require("./bluebubbles-mutation-log");
56
- const bluebubbles_session_cleanup_1 = require("./bluebubbles-session-cleanup");
57
- const debug_activity_1 = require("./debug-activity");
58
- const defaultDeps = {
59
- getAgentName: identity_1.getAgentName,
60
- buildSystem: prompt_1.buildSystem,
61
- runAgent: core_1.runAgent,
62
- loadSession: context_1.loadSession,
63
- postTurn: context_1.postTurn,
64
- sessionPath: config_1.sessionPath,
65
- accumulateFriendTokens: tokens_1.accumulateFriendTokens,
66
- createClient: () => (0, bluebubbles_client_1.createBlueBubblesClient)(),
67
- recordMutation: bluebubbles_mutation_log_1.recordBlueBubblesMutation,
68
- createFriendStore: () => new store_file_1.FileFriendStore(path.join((0, identity_1.getAgentRoot)(), "friends")),
69
- createFriendResolver: (store, params) => new resolver_1.FriendResolver(store, params),
70
- createServer: http.createServer,
71
- };
72
- function resolveFriendParams(event) {
73
- if (event.chat.isGroup) {
74
- const groupKey = event.chat.chatGuid ?? event.chat.chatIdentifier ?? event.sender.externalId;
75
- return {
76
- provider: "imessage-handle",
77
- externalId: `group:${groupKey}`,
78
- displayName: event.chat.displayName ?? "Unknown Group",
79
- channel: "bluebubbles",
80
- };
81
- }
82
- return {
83
- provider: "imessage-handle",
84
- externalId: event.sender.externalId || event.sender.rawId,
85
- displayName: event.sender.displayName || "Unknown",
86
- channel: "bluebubbles",
87
- };
88
- }
89
- function extractMessageText(content) {
90
- if (typeof content === "string")
91
- return content;
92
- if (!Array.isArray(content))
93
- return "";
94
- return content
95
- .map((part) => {
96
- if (part && typeof part === "object" && "type" in part && part.type === "text" && typeof part.text === "string") {
97
- return part.text;
98
- }
99
- return "";
100
- })
101
- .filter(Boolean)
102
- .join("\n");
103
- }
104
- function extractHistoricalLaneSummary(messages) {
105
- const seen = new Set();
106
- const summaries = [];
107
- for (let index = messages.length - 1; index >= 0; index--) {
108
- const message = messages[index];
109
- if (message.role !== "user")
110
- continue;
111
- const text = extractMessageText(message.content);
112
- if (!text)
113
- continue;
114
- const firstLine = text.split("\n")[0].trim();
115
- const threadMatch = firstLine.match(/thread id: ([^\]|]+)/i);
116
- const laneKey = threadMatch
117
- ? `thread:${threadMatch[1].trim()}`
118
- : /top[-_]level/i.test(firstLine)
119
- ? "top_level"
120
- : null;
121
- if (!laneKey || seen.has(laneKey))
122
- continue;
123
- seen.add(laneKey);
124
- const snippet = text
125
- .split("\n")
126
- .slice(1)
127
- .map((line) => line.trim())
128
- .find(Boolean)
129
- ?.slice(0, 80) ?? "(no recent text)";
130
- summaries.push({
131
- key: laneKey,
132
- label: laneKey === "top_level" ? "top_level" : laneKey,
133
- snippet,
134
- });
135
- if (summaries.length >= 5)
136
- break;
137
- }
138
- return summaries;
139
- }
140
- function buildConversationScopePrefix(event, existingMessages) {
141
- if (event.kind !== "message") {
142
- return "";
143
- }
144
- const summaries = extractHistoricalLaneSummary(existingMessages);
145
- const lines = [];
146
- if (event.threadOriginatorGuid?.trim()) {
147
- lines.push(`[conversation scope: existing chat trunk | current inbound lane: thread | current thread id: ${event.threadOriginatorGuid.trim()} | default outbound target for this turn: current_lane]`);
148
- }
149
- else {
150
- lines.push("[conversation scope: existing chat trunk | current inbound lane: top_level | default outbound target for this turn: top_level]");
151
- }
152
- if (summaries.length > 0) {
153
- lines.push("[recent active lanes]");
154
- for (const summary of summaries) {
155
- lines.push(`- ${summary.label}: ${summary.snippet}`);
156
- }
157
- }
158
- if (event.threadOriginatorGuid?.trim() || summaries.some((summary) => summary.key.startsWith("thread:"))) {
159
- lines.push("[routing control: use bluebubbles_set_reply_target with target=top_level to widen back out, or target=thread plus a listed thread id to route into a specific active thread]");
160
- }
161
- return lines.join("\n");
162
- }
163
- function buildInboundText(event, existingMessages) {
164
- const metadataPrefix = buildConversationScopePrefix(event, existingMessages);
165
- const baseText = event.repairNotice?.trim()
166
- ? `${event.textForAgent}\n[${event.repairNotice.trim()}]`
167
- : event.textForAgent;
168
- if (!event.chat.isGroup) {
169
- return metadataPrefix ? `${metadataPrefix}\n${baseText}` : baseText;
170
- }
171
- const scopedText = metadataPrefix ? `${metadataPrefix}\n${baseText}` : baseText;
172
- if (event.kind === "mutation") {
173
- return `${event.sender.displayName} ${scopedText}`;
174
- }
175
- return `${event.sender.displayName}: ${scopedText}`;
176
- }
177
- function buildInboundContent(event, existingMessages) {
178
- const text = buildInboundText(event, existingMessages);
179
- if (event.kind !== "message" || !event.inputPartsForAgent || event.inputPartsForAgent.length === 0) {
180
- return text;
181
- }
182
- return [
183
- { type: "text", text },
184
- ...event.inputPartsForAgent,
185
- ];
186
- }
187
- function createReplyTargetController(event) {
188
- const defaultTargetLabel = event.kind === "message" && event.threadOriginatorGuid?.trim() ? "current_lane" : "top_level";
189
- let selection = event.kind === "message" && event.threadOriginatorGuid?.trim()
190
- ? { target: "current_lane" }
191
- : { target: "top_level" };
192
- return {
193
- getReplyToMessageGuid() {
194
- if (event.kind !== "message")
195
- return undefined;
196
- if (selection.target === "top_level")
197
- return undefined;
198
- if (selection.target === "thread")
199
- return selection.threadOriginatorGuid.trim();
200
- return event.threadOriginatorGuid?.trim() ? event.messageGuid : undefined;
201
- },
202
- setSelection(next) {
203
- selection = next;
204
- if (next.target === "top_level") {
205
- return "bluebubbles reply target override: top_level";
206
- }
207
- if (next.target === "thread") {
208
- return `bluebubbles reply target override: thread:${next.threadOriginatorGuid}`;
209
- }
210
- return `bluebubbles reply target: using default for this turn (${defaultTargetLabel})`;
211
- },
212
- };
213
- }
214
- function emitBlueBubblesMarkReadWarning(chat, error) {
215
- (0, runtime_1.emitNervesEvent)({
216
- level: "warn",
217
- component: "senses",
218
- event: "senses.bluebubbles_mark_read_error",
219
- message: "failed to mark bluebubbles chat as read",
220
- meta: {
221
- chatGuid: chat.chatGuid ?? null,
222
- reason: error instanceof Error ? error.message : String(error),
223
- },
224
- });
225
- }
226
- function createBlueBubblesCallbacks(client, chat, replyTarget) {
227
- let textBuffer = "";
228
- const phrases = (0, phrases_1.getPhrases)();
229
- const activity = (0, debug_activity_1.createDebugActivityController)({
230
- thinkingPhrases: phrases.thinking,
231
- followupPhrases: phrases.followup,
232
- startTypingOnModelStart: true,
233
- suppressInitialModelStatus: true,
234
- suppressFollowupPhraseStatus: true,
235
- transport: {
236
- sendStatus: async (text) => {
237
- const sent = await client.sendText({
238
- chat,
239
- text,
240
- replyToMessageGuid: replyTarget.getReplyToMessageGuid(),
241
- });
242
- return sent.messageGuid;
243
- },
244
- editStatus: async (_messageGuid, text) => {
245
- await client.sendText({
246
- chat,
247
- text,
248
- replyToMessageGuid: replyTarget.getReplyToMessageGuid(),
249
- });
250
- },
251
- setTyping: async (active) => {
252
- if (!active) {
253
- await client.setTyping(chat, false);
254
- return;
255
- }
256
- const [markReadResult, typingResult] = await Promise.allSettled([
257
- client.markChatRead(chat),
258
- client.setTyping(chat, true),
259
- ]);
260
- if (markReadResult.status === "rejected") {
261
- emitBlueBubblesMarkReadWarning(chat, markReadResult.reason);
262
- }
263
- if (typingResult.status === "rejected") {
264
- throw typingResult.reason;
265
- }
266
- },
267
- },
268
- onTransportError: (operation, error) => {
269
- (0, runtime_1.emitNervesEvent)({
270
- level: "warn",
271
- component: "senses",
272
- event: "senses.bluebubbles_activity_error",
273
- message: "bluebubbles activity transport failed",
274
- meta: {
275
- operation,
276
- reason: error instanceof Error ? error.message : String(error),
277
- },
278
- });
279
- },
280
- });
281
- return {
282
- onModelStart() {
283
- activity.onModelStart();
284
- (0, runtime_1.emitNervesEvent)({
285
- component: "senses",
286
- event: "senses.bluebubbles_turn_start",
287
- message: "bluebubbles turn started",
288
- meta: { chatGuid: chat.chatGuid ?? null },
289
- });
290
- },
291
- onModelStreamStart() {
292
- (0, runtime_1.emitNervesEvent)({
293
- component: "senses",
294
- event: "senses.bluebubbles_stream_start",
295
- message: "bluebubbles non-streaming response started",
296
- meta: {},
297
- });
298
- },
299
- onTextChunk(text) {
300
- activity.onTextChunk(text);
301
- textBuffer += text;
302
- },
303
- onReasoningChunk(_text) { },
304
- onToolStart(name, _args) {
305
- activity.onToolStart(name, _args);
306
- (0, runtime_1.emitNervesEvent)({
307
- component: "senses",
308
- event: "senses.bluebubbles_tool_start",
309
- message: "bluebubbles tool execution started",
310
- meta: { name },
311
- });
312
- },
313
- onToolEnd(name, summary, success) {
314
- activity.onToolEnd(name, summary, success);
315
- (0, runtime_1.emitNervesEvent)({
316
- component: "senses",
317
- event: "senses.bluebubbles_tool_end",
318
- message: "bluebubbles tool execution completed",
319
- meta: { name, success, summary },
320
- });
321
- },
322
- onError(error, severity) {
323
- activity.onError(error);
324
- (0, runtime_1.emitNervesEvent)({
325
- level: severity === "terminal" ? "error" : "warn",
326
- component: "senses",
327
- event: "senses.bluebubbles_turn_error",
328
- message: "bluebubbles turn callback error",
329
- meta: { severity, reason: error.message },
330
- });
331
- },
332
- onClearText() {
333
- textBuffer = "";
334
- },
335
- async flush() {
336
- await activity.drain();
337
- const trimmed = textBuffer.trim();
338
- if (!trimmed) {
339
- await activity.finish();
340
- return;
341
- }
342
- textBuffer = "";
343
- await activity.finish();
344
- await client.sendText({
345
- chat,
346
- text: trimmed,
347
- replyToMessageGuid: replyTarget.getReplyToMessageGuid(),
348
- });
349
- },
350
- async finish() {
351
- await activity.finish();
352
- },
353
- };
354
- }
355
- async function readRequestBody(req) {
356
- let body = "";
357
- for await (const chunk of req) {
358
- body += chunk.toString();
359
- }
360
- return body;
361
- }
362
- function writeJson(res, statusCode, payload) {
363
- res.statusCode = statusCode;
364
- res.setHeader("Content-Type", "application/json; charset=utf-8");
365
- res.end(JSON.stringify(payload));
366
- }
367
- function isWebhookPasswordValid(url, expectedPassword) {
368
- const provided = url.searchParams.get("password");
369
- return !provided || provided === expectedPassword;
370
- }
371
- async function handleBlueBubblesEvent(payload, deps = {}) {
372
- const resolvedDeps = { ...defaultDeps, ...deps };
373
- const client = resolvedDeps.createClient();
374
- const event = await client.repairEvent((0, bluebubbles_model_1.normalizeBlueBubblesEvent)(payload));
375
- if (event.fromMe) {
376
- (0, runtime_1.emitNervesEvent)({
377
- component: "senses",
378
- event: "senses.bluebubbles_from_me_ignored",
379
- message: "ignored from-me bluebubbles event",
380
- meta: {
381
- messageGuid: event.messageGuid,
382
- kind: event.kind,
383
- },
384
- });
385
- return { handled: true, notifiedAgent: false, kind: event.kind, reason: "from_me" };
386
- }
387
- if (event.kind === "mutation") {
388
- try {
389
- resolvedDeps.recordMutation(resolvedDeps.getAgentName(), event);
390
- }
391
- catch (error) {
392
- (0, runtime_1.emitNervesEvent)({
393
- level: "error",
394
- component: "senses",
395
- event: "senses.bluebubbles_mutation_log_error",
396
- message: "failed recording bluebubbles mutation sidecar",
397
- meta: {
398
- messageGuid: event.messageGuid,
399
- mutationType: event.mutationType,
400
- reason: error instanceof Error ? error.message : String(error),
401
- },
402
- });
403
- }
404
- }
405
- if (event.kind === "mutation" && !event.shouldNotifyAgent) {
406
- (0, runtime_1.emitNervesEvent)({
407
- component: "senses",
408
- event: "senses.bluebubbles_state_mutation_recorded",
409
- message: "recorded non-notify bluebubbles mutation",
410
- meta: {
411
- messageGuid: event.messageGuid,
412
- mutationType: event.mutationType,
413
- },
414
- });
415
- return { handled: true, notifiedAgent: false, kind: event.kind, reason: "mutation_state_only" };
416
- }
417
- const store = resolvedDeps.createFriendStore();
418
- const resolver = resolvedDeps.createFriendResolver(store, resolveFriendParams(event));
419
- const context = await resolver.resolve();
420
- const replyTarget = createReplyTargetController(event);
421
- const toolContext = {
422
- signin: async () => undefined,
423
- friendStore: store,
424
- summarize: (0, core_1.createSummarize)(),
425
- context,
426
- bluebubblesReplyTarget: {
427
- setSelection: (selection) => replyTarget.setSelection(selection),
428
- },
429
- codingFeedback: {
430
- send: async (message) => {
431
- await client.sendText({
432
- chat: event.chat,
433
- text: message,
434
- replyToMessageGuid: replyTarget.getReplyToMessageGuid(),
435
- });
436
- },
437
- },
438
- };
439
- const friendId = context.friend.id;
440
- const sessPath = resolvedDeps.sessionPath(friendId, "bluebubbles", event.chat.sessionKey);
441
- try {
442
- (0, bluebubbles_session_cleanup_1.findObsoleteBlueBubblesThreadSessions)(sessPath);
443
- }
444
- catch (error) {
445
- (0, runtime_1.emitNervesEvent)({
446
- level: "warn",
447
- component: "senses",
448
- event: "senses.bluebubbles_thread_lane_cleanup_error",
449
- message: "failed to inspect obsolete bluebubbles thread-lane sessions",
450
- meta: {
451
- sessionPath: sessPath,
452
- reason: error instanceof Error ? error.message : String(error),
453
- },
454
- });
455
- }
456
- const existing = resolvedDeps.loadSession(sessPath);
457
- const messages = existing?.messages && existing.messages.length > 0
458
- ? existing.messages
459
- : [{ role: "system", content: await resolvedDeps.buildSystem("bluebubbles", undefined, context) }];
460
- messages.push({ role: "user", content: buildInboundContent(event, existing?.messages ?? messages) });
461
- const callbacks = createBlueBubblesCallbacks(client, event.chat, replyTarget);
462
- const controller = new AbortController();
463
- const agentOptions = {
464
- toolContext,
465
- };
466
- try {
467
- const result = await resolvedDeps.runAgent(messages, callbacks, "bluebubbles", controller.signal, agentOptions);
468
- await callbacks.flush();
469
- resolvedDeps.postTurn(messages, sessPath, result.usage);
470
- await resolvedDeps.accumulateFriendTokens(store, friendId, result.usage);
471
- (0, runtime_1.emitNervesEvent)({
472
- component: "senses",
473
- event: "senses.bluebubbles_turn_end",
474
- message: "bluebubbles event handled",
475
- meta: {
476
- messageGuid: event.messageGuid,
477
- kind: event.kind,
478
- sessionKey: event.chat.sessionKey,
479
- },
480
- });
481
- return {
482
- handled: true,
483
- notifiedAgent: true,
484
- kind: event.kind,
485
- };
486
- }
487
- finally {
488
- await callbacks.finish();
489
- }
490
- }
491
- function createBlueBubblesWebhookHandler(deps = {}) {
492
- return async (req, res) => {
493
- const url = new URL(req.url ?? "/", "http://127.0.0.1");
494
- const channelConfig = (0, config_1.getBlueBubblesChannelConfig)();
495
- const runtimeConfig = (0, config_1.getBlueBubblesConfig)();
496
- if (url.pathname !== channelConfig.webhookPath) {
497
- writeJson(res, 404, { error: "Not found" });
498
- return;
499
- }
500
- if (req.method !== "POST") {
501
- writeJson(res, 405, { error: "Method not allowed" });
502
- return;
503
- }
504
- if (!isWebhookPasswordValid(url, runtimeConfig.password)) {
505
- writeJson(res, 401, { error: "Unauthorized" });
506
- return;
507
- }
508
- let payload;
509
- try {
510
- const rawBody = await readRequestBody(req);
511
- payload = JSON.parse(rawBody);
512
- }
513
- catch (error) {
514
- (0, runtime_1.emitNervesEvent)({
515
- level: "warn",
516
- component: "senses",
517
- event: "senses.bluebubbles_webhook_bad_json",
518
- message: "failed to parse bluebubbles webhook body",
519
- meta: {
520
- reason: error instanceof Error ? error.message : String(error),
521
- },
522
- });
523
- writeJson(res, 400, { error: "Invalid JSON body" });
524
- return;
525
- }
526
- try {
527
- const result = await handleBlueBubblesEvent(payload, deps);
528
- writeJson(res, 200, result);
529
- }
530
- catch (error) {
531
- (0, runtime_1.emitNervesEvent)({
532
- level: "error",
533
- component: "senses",
534
- event: "senses.bluebubbles_webhook_error",
535
- message: "bluebubbles webhook handling failed",
536
- meta: {
537
- reason: error instanceof Error ? error.message : String(error),
538
- },
539
- });
540
- writeJson(res, 500, {
541
- error: error instanceof Error ? error.message : String(error),
542
- });
543
- }
544
- };
545
- }
546
- const PROACTIVE_SEND_ALLOWED_TRUST = new Set(["family", "friend"]);
547
- function findImessageHandle(friend) {
548
- for (const ext of friend.externalIds) {
549
- if (ext.provider === "imessage-handle" && !ext.externalId.startsWith("group:")) {
550
- return ext.externalId;
551
- }
552
- }
553
- return undefined;
554
- }
555
- function scanPendingBlueBubblesFiles(pendingRoot) {
556
- const results = [];
557
- let friendIds;
558
- try {
559
- friendIds = fs.readdirSync(pendingRoot);
560
- }
561
- catch {
562
- return results;
563
- }
564
- for (const friendId of friendIds) {
565
- const bbDir = path.join(pendingRoot, friendId, "bluebubbles");
566
- let keys;
567
- try {
568
- keys = fs.readdirSync(bbDir);
569
- }
570
- catch {
571
- continue;
572
- }
573
- for (const key of keys) {
574
- const keyDir = path.join(bbDir, key);
575
- let files;
576
- try {
577
- files = fs.readdirSync(keyDir);
578
- }
579
- catch {
580
- continue;
581
- }
582
- for (const file of files.filter((f) => f.endsWith(".json")).sort()) {
583
- const filePath = path.join(keyDir, file);
584
- try {
585
- const content = fs.readFileSync(filePath, "utf-8");
586
- results.push({ friendId, key, filePath, content });
587
- }
588
- catch {
589
- // skip unreadable files
590
- }
591
- }
592
- }
593
- }
594
- return results;
595
- }
596
- async function drainAndSendPendingBlueBubbles(deps = {}, pendingRoot) {
597
- const resolvedDeps = { ...defaultDeps, ...deps };
598
- const root = pendingRoot ?? path.join((0, identity_1.getAgentRoot)(), "state", "pending");
599
- const client = resolvedDeps.createClient();
600
- const store = resolvedDeps.createFriendStore();
601
- const pendingFiles = scanPendingBlueBubblesFiles(root);
602
- const result = { sent: 0, skipped: 0, failed: 0 };
603
- for (const { friendId, filePath, content } of pendingFiles) {
604
- let parsed;
605
- try {
606
- parsed = JSON.parse(content);
607
- }
608
- catch {
609
- result.failed++;
610
- try {
611
- fs.unlinkSync(filePath);
612
- }
613
- catch { /* ignore */ }
614
- continue;
615
- }
616
- const messageText = typeof parsed.content === "string" ? parsed.content : "";
617
- if (!messageText.trim()) {
618
- result.skipped++;
619
- try {
620
- fs.unlinkSync(filePath);
621
- }
622
- catch { /* ignore */ }
623
- continue;
624
- }
625
- let friend;
626
- try {
627
- friend = await store.get(friendId);
628
- }
629
- catch {
630
- friend = null;
631
- }
632
- if (!friend) {
633
- result.skipped++;
634
- try {
635
- fs.unlinkSync(filePath);
636
- }
637
- catch { /* ignore */ }
638
- (0, runtime_1.emitNervesEvent)({
639
- level: "warn",
640
- component: "senses",
641
- event: "senses.bluebubbles_proactive_no_friend",
642
- message: "proactive send skipped: friend not found",
643
- meta: { friendId },
644
- });
645
- continue;
646
- }
647
- if (!PROACTIVE_SEND_ALLOWED_TRUST.has(friend.trustLevel ?? "stranger")) {
648
- result.skipped++;
649
- try {
650
- fs.unlinkSync(filePath);
651
- }
652
- catch { /* ignore */ }
653
- (0, runtime_1.emitNervesEvent)({
654
- component: "senses",
655
- event: "senses.bluebubbles_proactive_trust_skip",
656
- message: "proactive send skipped: trust level not allowed",
657
- meta: { friendId, trustLevel: friend.trustLevel ?? "unknown" },
658
- });
659
- continue;
660
- }
661
- const handle = findImessageHandle(friend);
662
- if (!handle) {
663
- result.skipped++;
664
- try {
665
- fs.unlinkSync(filePath);
666
- }
667
- catch { /* ignore */ }
668
- (0, runtime_1.emitNervesEvent)({
669
- level: "warn",
670
- component: "senses",
671
- event: "senses.bluebubbles_proactive_no_handle",
672
- message: "proactive send skipped: no iMessage handle found",
673
- meta: { friendId },
674
- });
675
- continue;
676
- }
677
- const chat = {
678
- chatIdentifier: handle,
679
- isGroup: false,
680
- sessionKey: friendId,
681
- sendTarget: { kind: "chat_identifier", value: handle },
682
- };
683
- try {
684
- await client.sendText({ chat, text: messageText });
685
- result.sent++;
686
- try {
687
- fs.unlinkSync(filePath);
688
- }
689
- catch { /* ignore */ }
690
- (0, runtime_1.emitNervesEvent)({
691
- component: "senses",
692
- event: "senses.bluebubbles_proactive_sent",
693
- message: "proactive bluebubbles message sent",
694
- meta: { friendId, handle },
695
- });
696
- }
697
- catch (error) {
698
- result.failed++;
699
- (0, runtime_1.emitNervesEvent)({
700
- level: "error",
701
- component: "senses",
702
- event: "senses.bluebubbles_proactive_send_error",
703
- message: "proactive bluebubbles send failed",
704
- meta: {
705
- friendId,
706
- handle,
707
- reason: error instanceof Error ? error.message : String(error),
708
- },
709
- });
710
- }
711
- }
712
- if (result.sent > 0 || result.skipped > 0 || result.failed > 0) {
713
- (0, runtime_1.emitNervesEvent)({
714
- component: "senses",
715
- event: "senses.bluebubbles_proactive_drain_complete",
716
- message: "bluebubbles proactive drain complete",
717
- meta: { sent: result.sent, skipped: result.skipped, failed: result.failed },
718
- });
719
- }
720
- return result;
721
- }
722
- function startBlueBubblesApp(deps = {}) {
723
- const resolvedDeps = { ...defaultDeps, ...deps };
724
- resolvedDeps.createClient();
725
- const channelConfig = (0, config_1.getBlueBubblesChannelConfig)();
726
- const server = resolvedDeps.createServer(createBlueBubblesWebhookHandler(deps));
727
- server.listen(channelConfig.port, () => {
728
- (0, runtime_1.emitNervesEvent)({
729
- component: "channels",
730
- event: "channel.app_started",
731
- message: "BlueBubbles sense started",
732
- meta: { port: channelConfig.port, webhookPath: channelConfig.webhookPath },
733
- });
734
- });
735
- return server;
736
- }