@ouro.bot/cli 0.1.0-alpha.58 → 0.1.0-alpha.580

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 (404) hide show
  1. package/README.md +127 -23
  2. package/RepairGuide.ouro/agent.json +5 -0
  3. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  4. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  5. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  6. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  7. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  8. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  9. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  12. package/changelog.json +3738 -0
  13. package/dist/arc/attention-types.js +8 -0
  14. package/dist/arc/cares.js +140 -0
  15. package/dist/arc/episodes.js +117 -0
  16. package/dist/arc/intentions.js +133 -0
  17. package/dist/arc/json-store.js +117 -0
  18. package/dist/arc/obligations.js +237 -0
  19. package/dist/arc/packets.js +193 -0
  20. package/dist/arc/presence.js +185 -0
  21. package/dist/arc/task-lifecycle.js +65 -0
  22. package/dist/heart/active-work.js +837 -26
  23. package/dist/heart/agent-entry.js +69 -3
  24. package/dist/heart/attachments/image-normalize.js +194 -0
  25. package/dist/heart/attachments/materialize.js +97 -0
  26. package/dist/heart/attachments/originals.js +88 -0
  27. package/dist/heart/attachments/render.js +29 -0
  28. package/dist/heart/attachments/sources/adapter.js +2 -0
  29. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  30. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  31. package/dist/heart/attachments/sources/index.js +16 -0
  32. package/dist/heart/attachments/store.js +103 -0
  33. package/dist/heart/attachments/types.js +93 -0
  34. package/dist/heart/auth/auth-flow.js +479 -0
  35. package/dist/heart/background-operations.js +281 -0
  36. package/dist/heart/bundle-state.js +168 -0
  37. package/dist/heart/commitments.js +111 -0
  38. package/dist/heart/config-registry.js +322 -0
  39. package/dist/heart/config.js +114 -118
  40. package/dist/heart/core.js +909 -246
  41. package/dist/heart/cross-chat-delivery.js +3 -18
  42. package/dist/heart/daemon/agent-config-check.js +419 -0
  43. package/dist/heart/daemon/agent-discovery.js +102 -3
  44. package/dist/heart/daemon/agent-service.js +522 -0
  45. package/dist/heart/daemon/agentic-repair.js +547 -0
  46. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  47. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  48. package/dist/heart/daemon/cadence.js +70 -0
  49. package/dist/heart/daemon/cli-defaults.js +776 -0
  50. package/dist/heart/daemon/cli-exec.js +7559 -0
  51. package/dist/heart/daemon/cli-help.js +498 -0
  52. package/dist/heart/daemon/cli-parse.js +1592 -0
  53. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  54. package/dist/heart/daemon/cli-render.js +763 -0
  55. package/dist/heart/daemon/cli-types.js +8 -0
  56. package/dist/heart/daemon/connect-bay.js +323 -0
  57. package/dist/heart/daemon/daemon-cli.js +29 -1703
  58. package/dist/heart/daemon/daemon-entry.js +387 -2
  59. package/dist/heart/daemon/daemon-health.js +176 -0
  60. package/dist/heart/daemon/daemon-rollup.js +57 -0
  61. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  62. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  63. package/dist/heart/daemon/daemon.js +816 -71
  64. package/dist/heart/daemon/dns-workflow.js +394 -0
  65. package/dist/heart/daemon/doctor-types.js +8 -0
  66. package/dist/heart/daemon/doctor.js +826 -0
  67. package/dist/heart/daemon/health-monitor.js +122 -1
  68. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  69. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  70. package/dist/heart/daemon/http-health-probe.js +80 -0
  71. package/dist/heart/daemon/human-command-screens.js +234 -0
  72. package/dist/heart/daemon/human-readiness.js +114 -0
  73. package/dist/heart/daemon/inner-status.js +89 -0
  74. package/dist/heart/daemon/interactive-repair.js +394 -0
  75. package/dist/heart/daemon/launchd.js +37 -8
  76. package/dist/heart/daemon/log-tailer.js +82 -12
  77. package/dist/heart/daemon/logs-prune.js +110 -0
  78. package/dist/heart/daemon/mcp-canary.js +297 -0
  79. package/dist/heart/daemon/message-router.js +2 -2
  80. package/dist/heart/daemon/os-cron-deps.js +135 -0
  81. package/dist/heart/daemon/os-cron.js +14 -12
  82. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  83. package/dist/heart/daemon/ouro-entry.js +3 -1
  84. package/dist/heart/daemon/process-manager.js +375 -33
  85. package/dist/heart/daemon/provider-discovery.js +137 -0
  86. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  87. package/dist/heart/daemon/pulse.js +475 -0
  88. package/dist/heart/daemon/readiness-repair.js +365 -0
  89. package/dist/heart/daemon/run-hooks.js +2 -0
  90. package/dist/heart/daemon/runtime-logging.js +30 -6
  91. package/dist/heart/daemon/runtime-metadata.js +3 -31
  92. package/dist/heart/daemon/safe-mode.js +161 -0
  93. package/dist/heart/daemon/sense-manager.js +462 -38
  94. package/dist/heart/daemon/session-id-resolver.js +131 -0
  95. package/dist/heart/daemon/skill-management-installer.js +94 -0
  96. package/dist/heart/daemon/socket-client.js +158 -11
  97. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  98. package/dist/heart/daemon/startup-tui.js +330 -0
  99. package/dist/heart/daemon/task-scheduler.js +3 -25
  100. package/dist/heart/daemon/terminal-ui.js +499 -0
  101. package/dist/heart/daemon/thoughts.js +162 -17
  102. package/dist/heart/daemon/up-progress.js +366 -0
  103. package/dist/heart/daemon/vault-items.js +56 -0
  104. package/dist/heart/delegation.js +1 -1
  105. package/dist/heart/habits/habit-migration.js +189 -0
  106. package/dist/heart/habits/habit-parser.js +140 -0
  107. package/dist/heart/habits/habit-runtime-state.js +100 -0
  108. package/dist/heart/habits/habit-scheduler.js +372 -0
  109. package/dist/heart/{daemon → hatch}/hatch-flow.js +32 -56
  110. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  111. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  112. package/dist/heart/{daemon → hatch}/specialist-tools.js +35 -12
  113. package/dist/heart/identity.js +203 -57
  114. package/dist/heart/kept-notes.js +357 -0
  115. package/dist/heart/kicks.js +1 -1
  116. package/dist/heart/machine-identity.js +161 -0
  117. package/dist/heart/mail-import-discovery.js +353 -0
  118. package/dist/heart/mailbox/mailbox-http-hooks.js +66 -0
  119. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  120. package/dist/heart/mailbox/mailbox-http-routes.js +246 -0
  121. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  122. package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
  123. package/dist/heart/mailbox/mailbox-http.js +99 -0
  124. package/dist/heart/mailbox/mailbox-read.js +31 -0
  125. package/dist/heart/mailbox/mailbox-types.js +27 -0
  126. package/dist/heart/mailbox/mailbox-view.js +195 -0
  127. package/dist/heart/mailbox/readers/agent-machine.js +382 -0
  128. package/dist/heart/mailbox/readers/continuity-readers.js +338 -0
  129. package/dist/heart/mailbox/readers/mail.js +362 -0
  130. package/dist/heart/mailbox/readers/runtime-readers.js +651 -0
  131. package/dist/heart/mailbox/readers/sessions.js +232 -0
  132. package/dist/heart/mailbox/readers/shared.js +111 -0
  133. package/dist/heart/mcp/mcp-server.js +656 -0
  134. package/dist/heart/migrate-config.js +100 -0
  135. package/dist/heart/model-capabilities.js +19 -0
  136. package/dist/heart/platform.js +81 -0
  137. package/dist/heart/provider-attempt.js +134 -0
  138. package/dist/heart/provider-binding-resolver.js +267 -0
  139. package/dist/heart/provider-credentials.js +425 -0
  140. package/dist/heart/provider-failover.js +301 -0
  141. package/dist/heart/provider-models.js +81 -0
  142. package/dist/heart/provider-ping.js +262 -0
  143. package/dist/heart/provider-readiness-cache.js +40 -0
  144. package/dist/heart/provider-visibility.js +188 -0
  145. package/dist/heart/providers/anthropic-token.js +131 -0
  146. package/dist/heart/providers/anthropic.js +139 -52
  147. package/dist/heart/providers/azure.js +97 -13
  148. package/dist/heart/providers/error-classification.js +127 -0
  149. package/dist/heart/providers/github-copilot.js +145 -0
  150. package/dist/heart/providers/minimax-vlm.js +189 -0
  151. package/dist/heart/providers/minimax.js +26 -8
  152. package/dist/heart/providers/openai-codex.js +55 -40
  153. package/dist/heart/runtime-capability-check.js +170 -0
  154. package/dist/heart/runtime-credentials.js +367 -0
  155. package/dist/heart/runtime-cwd.js +87 -0
  156. package/dist/heart/sense-truth.js +13 -4
  157. package/dist/heart/session-activity.js +43 -22
  158. package/dist/heart/session-events.js +1149 -0
  159. package/dist/heart/session-playback-cli-main.js +5 -0
  160. package/dist/heart/session-playback-cli.js +36 -0
  161. package/dist/heart/session-playback.js +231 -0
  162. package/dist/heart/session-stats-cli-main.js +5 -0
  163. package/dist/heart/session-stats.js +182 -0
  164. package/dist/heart/session-transcript.js +243 -0
  165. package/dist/heart/start-of-turn-packet.js +345 -0
  166. package/dist/heart/streaming.js +44 -27
  167. package/dist/heart/sync-classification.js +176 -0
  168. package/dist/heart/sync.js +449 -0
  169. package/dist/heart/target-resolution.js +9 -5
  170. package/dist/heart/tempo.js +93 -0
  171. package/dist/heart/temporal-view.js +41 -0
  172. package/dist/heart/timeouts.js +101 -0
  173. package/dist/heart/tool-activity-callbacks.js +59 -0
  174. package/dist/heart/tool-description.js +143 -0
  175. package/dist/heart/tool-friction.js +55 -0
  176. package/dist/heart/tool-loop.js +200 -0
  177. package/dist/heart/turn-context.js +421 -0
  178. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  179. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  180. package/dist/heart/versioning/ouro-path-installer.js +426 -0
  181. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  182. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  183. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  184. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  185. package/dist/mailbox-ui/assets/index-B-461hes.js +61 -0
  186. package/dist/mailbox-ui/assets/index-BPr5vNuM.css +1 -0
  187. package/dist/mailbox-ui/index.html +15 -0
  188. package/dist/mailroom/attention.js +167 -0
  189. package/dist/mailroom/autonomy.js +209 -0
  190. package/dist/mailroom/blob-store.js +674 -0
  191. package/dist/mailroom/body-cache.js +61 -0
  192. package/dist/mailroom/core.js +720 -0
  193. package/dist/mailroom/entry.js +160 -0
  194. package/dist/mailroom/file-store.js +430 -0
  195. package/dist/mailroom/mbox-import.js +383 -0
  196. package/dist/mailroom/outbound.js +380 -0
  197. package/dist/mailroom/policy.js +263 -0
  198. package/dist/mailroom/reader.js +233 -0
  199. package/dist/mailroom/search-cache.js +256 -0
  200. package/dist/mailroom/search-relevance.js +319 -0
  201. package/dist/mailroom/smtp-ingress.js +176 -0
  202. package/dist/mailroom/source-state.js +176 -0
  203. package/dist/mailroom/thread.js +109 -0
  204. package/dist/mailroom/travel-extract.js +89 -0
  205. package/dist/mind/bundle-manifest.js +7 -1
  206. package/dist/mind/context.js +165 -101
  207. package/dist/mind/diary-integrity.js +60 -0
  208. package/dist/mind/{memory.js → diary.js} +62 -75
  209. package/dist/mind/embedding-provider.js +60 -0
  210. package/dist/mind/file-state.js +179 -0
  211. package/dist/mind/friends/channel.js +39 -0
  212. package/dist/mind/friends/resolver.js +54 -2
  213. package/dist/mind/friends/store-file.js +39 -3
  214. package/dist/mind/friends/types.js +2 -2
  215. package/dist/mind/journal-index.js +161 -0
  216. package/dist/mind/note-search.js +268 -0
  217. package/dist/mind/obligation-steering.js +221 -0
  218. package/dist/mind/pending.js +4 -0
  219. package/dist/mind/prompt-refresh.js +3 -2
  220. package/dist/mind/prompt.js +1039 -135
  221. package/dist/mind/provenance-trust.js +26 -0
  222. package/dist/mind/scrutiny.js +173 -0
  223. package/dist/nerves/cli-logging.js +7 -1
  224. package/dist/nerves/coverage/audit-rules.js +15 -6
  225. package/dist/nerves/coverage/audit.js +28 -2
  226. package/dist/nerves/coverage/cli.js +1 -1
  227. package/dist/nerves/coverage/contract.js +5 -5
  228. package/dist/nerves/coverage/file-completeness.js +129 -5
  229. package/dist/nerves/coverage/run-artifacts.js +1 -1
  230. package/dist/nerves/event-buffer.js +111 -0
  231. package/dist/nerves/index.js +224 -4
  232. package/dist/nerves/observation.js +20 -0
  233. package/dist/nerves/redact.js +79 -0
  234. package/dist/nerves/review/cli-main.js +5 -0
  235. package/dist/nerves/review/cli.js +156 -0
  236. package/dist/nerves/review/core.js +152 -0
  237. package/dist/nerves/runtime.js +5 -1
  238. package/dist/repertoire/ado-client.js +15 -56
  239. package/dist/repertoire/ado-semantic.js +11 -10
  240. package/dist/repertoire/api-client.js +97 -0
  241. package/dist/repertoire/bitwarden-store.js +997 -0
  242. package/dist/repertoire/bundle-templates.js +72 -0
  243. package/dist/repertoire/bw-installer.js +180 -0
  244. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  245. package/dist/repertoire/coding/context-pack.js +330 -0
  246. package/dist/repertoire/coding/feedback.js +197 -30
  247. package/dist/repertoire/coding/manager.js +158 -9
  248. package/dist/repertoire/coding/spawner.js +55 -9
  249. package/dist/repertoire/coding/tools.js +170 -7
  250. package/dist/repertoire/commerce-errors.js +109 -0
  251. package/dist/repertoire/commerce-self-test.js +156 -0
  252. package/dist/repertoire/credential-access.js +178 -0
  253. package/dist/repertoire/duffel-client.js +185 -0
  254. package/dist/repertoire/github-client.js +14 -55
  255. package/dist/repertoire/graph-client.js +11 -52
  256. package/dist/repertoire/guardrails.js +396 -0
  257. package/dist/repertoire/mcp-client.js +295 -0
  258. package/dist/repertoire/mcp-manager.js +362 -0
  259. package/dist/repertoire/mcp-tools.js +63 -0
  260. package/dist/repertoire/shell-sessions.js +133 -0
  261. package/dist/repertoire/skills.js +15 -24
  262. package/dist/repertoire/stripe-client.js +131 -0
  263. package/dist/repertoire/tasks/board.js +31 -5
  264. package/dist/repertoire/tasks/fix.js +182 -0
  265. package/dist/repertoire/tasks/index.js +16 -4
  266. package/dist/repertoire/tasks/lifecycle.js +2 -2
  267. package/dist/repertoire/tasks/parser.js +3 -2
  268. package/dist/repertoire/tasks/scanner.js +194 -37
  269. package/dist/repertoire/tasks/transitions.js +16 -78
  270. package/dist/repertoire/tool-results.js +29 -0
  271. package/dist/repertoire/tools-attachments.js +317 -0
  272. package/dist/repertoire/tools-base.js +47 -1075
  273. package/dist/repertoire/tools-bluebubbles.js +1 -0
  274. package/dist/repertoire/tools-bridge.js +142 -0
  275. package/dist/repertoire/tools-bundle.js +984 -0
  276. package/dist/repertoire/tools-config.js +185 -0
  277. package/dist/repertoire/tools-continuity.js +248 -0
  278. package/dist/repertoire/tools-credential.js +381 -0
  279. package/dist/repertoire/tools-files.js +342 -0
  280. package/dist/repertoire/tools-flight.js +224 -0
  281. package/dist/repertoire/tools-flow.js +119 -0
  282. package/dist/repertoire/tools-github.js +1 -7
  283. package/dist/repertoire/tools-mail.js +1857 -0
  284. package/dist/repertoire/tools-notes.js +421 -0
  285. package/dist/repertoire/tools-session.js +809 -0
  286. package/dist/repertoire/tools-shell.js +120 -0
  287. package/dist/repertoire/tools-stripe.js +180 -0
  288. package/dist/repertoire/tools-surface.js +345 -0
  289. package/dist/repertoire/tools-teams.js +9 -39
  290. package/dist/repertoire/tools-travel.js +125 -0
  291. package/dist/repertoire/tools-trip.js +604 -0
  292. package/dist/repertoire/tools-user-profile.js +144 -0
  293. package/dist/repertoire/tools-vault.js +40 -0
  294. package/dist/repertoire/tools-voice.js +144 -0
  295. package/dist/repertoire/tools.js +115 -103
  296. package/dist/repertoire/travel-api-client.js +360 -0
  297. package/dist/repertoire/user-profile.js +131 -0
  298. package/dist/repertoire/vault-setup.js +246 -0
  299. package/dist/repertoire/vault-unlock.js +594 -0
  300. package/dist/scripts/claude-code-hook.js +41 -0
  301. package/dist/scripts/claude-code-stop-hook.js +47 -0
  302. package/dist/senses/attention-queue.js +116 -0
  303. package/dist/senses/bluebubbles/active-turns.js +216 -0
  304. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  305. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  306. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  307. package/dist/senses/bluebubbles/entry.js +77 -0
  308. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  309. package/dist/senses/bluebubbles/index.js +2420 -0
  310. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  311. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  312. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  313. package/dist/senses/bluebubbles/processed-log.js +133 -0
  314. package/dist/senses/bluebubbles/replay.js +137 -0
  315. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  316. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  317. package/dist/senses/bluebubbles-meta-guard.js +40 -0
  318. package/dist/senses/cli/bracketed-paste.js +82 -0
  319. package/dist/senses/cli/image-paste.js +287 -0
  320. package/dist/senses/cli/image-ref-navigation.js +75 -0
  321. package/dist/senses/cli/ink-app.js +156 -0
  322. package/dist/senses/cli/inline-diff.js +64 -0
  323. package/dist/senses/cli/input-keys.js +174 -0
  324. package/dist/senses/cli/kill-ring.js +86 -0
  325. package/dist/senses/cli/message-list.js +51 -0
  326. package/dist/senses/cli/ouro-tui.js +607 -0
  327. package/dist/senses/cli/spinner-imperative.js +135 -0
  328. package/dist/senses/cli/spinner.js +101 -0
  329. package/dist/senses/cli/status-line.js +60 -0
  330. package/dist/senses/cli/streaming-markdown.js +526 -0
  331. package/dist/senses/cli/tool-display.js +85 -0
  332. package/dist/senses/cli/tool-render.js +85 -0
  333. package/dist/senses/cli/tui-store.js +240 -0
  334. package/dist/senses/cli/virtual-list.js +35 -0
  335. package/dist/senses/cli-entry.js +60 -8
  336. package/dist/senses/cli-layout.js +100 -0
  337. package/dist/senses/cli.js +516 -204
  338. package/dist/senses/commands.js +66 -3
  339. package/dist/senses/habit-turn-message.js +108 -0
  340. package/dist/senses/inner-dialog-worker.js +175 -21
  341. package/dist/senses/inner-dialog.js +330 -27
  342. package/dist/senses/mail-entry.js +66 -0
  343. package/dist/senses/mail.js +379 -0
  344. package/dist/senses/pipeline.js +654 -181
  345. package/dist/senses/proactive-content-guard.js +51 -0
  346. package/dist/senses/shared-turn.js +392 -0
  347. package/dist/senses/surface-tool.js +70 -0
  348. package/dist/senses/teams-entry.js +60 -8
  349. package/dist/senses/teams.js +387 -98
  350. package/dist/senses/trust-gate.js +100 -5
  351. package/dist/senses/voice/audio-playback.js +237 -0
  352. package/dist/senses/voice/audio-routing.js +119 -0
  353. package/dist/senses/voice/elevenlabs.js +202 -0
  354. package/dist/senses/voice/golden-path.js +116 -0
  355. package/dist/senses/voice/index.js +28 -0
  356. package/dist/senses/voice/meeting.js +113 -0
  357. package/dist/senses/voice/outbound.js +190 -0
  358. package/dist/senses/voice/phone.js +33 -0
  359. package/dist/senses/voice/playback.js +139 -0
  360. package/dist/senses/voice/transcript.js +70 -0
  361. package/dist/senses/voice/turn.js +191 -0
  362. package/dist/senses/voice/twilio-phone-runtime.js +755 -0
  363. package/dist/senses/voice/twilio-phone.js +4484 -0
  364. package/dist/senses/voice/types.js +2 -0
  365. package/dist/senses/voice/whisper.js +161 -0
  366. package/dist/senses/voice-entry.js +81 -0
  367. package/dist/senses/voice-twilio-entry.js +87 -0
  368. package/dist/trips/core.js +138 -0
  369. package/dist/trips/store.js +146 -0
  370. package/package.json +40 -7
  371. package/skills/agent-commerce.md +106 -0
  372. package/skills/browser-navigation.md +117 -0
  373. package/skills/commerce-setup-guide.md +116 -0
  374. package/skills/commerce-setup.md +84 -0
  375. package/skills/configure-dev-tools.md +99 -0
  376. package/skills/travel-planning.md +138 -0
  377. package/dist/heart/daemon/auth-flow.js +0 -351
  378. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  379. package/dist/heart/daemon/subagent-installer.js +0 -166
  380. package/dist/heart/session-recall.js +0 -116
  381. package/dist/mind/associative-recall.js +0 -209
  382. package/dist/senses/bluebubbles-entry.js +0 -13
  383. package/dist/senses/bluebubbles.js +0 -1177
  384. package/dist/senses/debug-activity.js +0 -148
  385. package/subagents/README.md +0 -86
  386. package/subagents/work-doer.md +0 -237
  387. package/subagents/work-merger.md +0 -618
  388. package/subagents/work-planner.md +0 -390
  389. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  390. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  391. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  392. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  393. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  394. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  395. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  396. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  397. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  398. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  399. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  400. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  401. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  402. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  403. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  404. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,809 @@
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.sessionToolDefinitions = void 0;
37
+ exports.renderInnerProgressStatus = renderInnerProgressStatus;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const config_1 = require("../heart/config");
41
+ const identity_1 = require("../heart/identity");
42
+ const runtime_1 = require("../nerves/runtime");
43
+ const socket_client_1 = require("../heart/daemon/socket-client");
44
+ const thoughts_1 = require("../heart/daemon/thoughts");
45
+ const manager_1 = require("../heart/bridges/manager");
46
+ const session_transcript_1 = require("../heart/session-transcript");
47
+ const session_activity_1 = require("../heart/session-activity");
48
+ const active_work_1 = require("../heart/active-work");
49
+ const coding_1 = require("./coding");
50
+ const tasks_1 = require("./tasks");
51
+ const pending_1 = require("../mind/pending");
52
+ const obligations_1 = require("../arc/obligations");
53
+ const progress_story_1 = require("../heart/progress-story");
54
+ const cross_chat_delivery_1 = require("../heart/cross-chat-delivery");
55
+ const mail_import_discovery_1 = require("../heart/mail-import-discovery");
56
+ const outbound_1 = require("../senses/voice/outbound");
57
+ const NO_SESSION_FOUND_MESSAGE = "no session found for that friend/channel/key combination.";
58
+ const EMPTY_SESSION_MESSAGE = "session exists but has no non-system messages.";
59
+ async function summarizeSessionTailSafely(options) {
60
+ try {
61
+ return await (0, session_transcript_1.summarizeSessionTail)(options);
62
+ }
63
+ catch (error) {
64
+ if (options.summarize) {
65
+ (0, runtime_1.emitNervesEvent)({
66
+ component: "daemon",
67
+ event: "daemon.session_tail_summary_summary_fallback",
68
+ message: "session tail summarization failed; using raw transcript",
69
+ meta: {
70
+ friendId: options.friendId,
71
+ channel: options.channel,
72
+ key: options.key,
73
+ error: error instanceof Error ? error.message : String(error),
74
+ },
75
+ });
76
+ try {
77
+ return await (0, session_transcript_1.summarizeSessionTail)({
78
+ ...options,
79
+ summarize: undefined,
80
+ });
81
+ /* v8 ignore start -- defensive: session tail fallback @preserve */
82
+ }
83
+ catch {
84
+ return { kind: "missing" };
85
+ }
86
+ /* v8 ignore stop */
87
+ }
88
+ return { kind: "missing" };
89
+ }
90
+ }
91
+ async function searchSessionSafely(options) {
92
+ try {
93
+ return await (0, session_transcript_1.searchSessionTranscript)(options);
94
+ }
95
+ catch {
96
+ return { kind: "missing" };
97
+ }
98
+ }
99
+ function normalizeProgressOutcome(text) {
100
+ const trimmed = text.trim();
101
+ /* v8 ignore next -- defensive: normalizeProgressOutcome null branch @preserve */
102
+ if (!trimmed || trimmed === "nothing yet" || trimmed === "nothing recent") {
103
+ return null;
104
+ }
105
+ if (trimmed.startsWith("\"") && trimmed.endsWith("\"") && trimmed.length >= 2) {
106
+ return trimmed.slice(1, -1);
107
+ }
108
+ return trimmed;
109
+ }
110
+ function writePendingEnvelope(queueDir, message) {
111
+ fs.mkdirSync(queueDir, { recursive: true });
112
+ const fileName = `${message.timestamp}-${Math.random().toString(36).slice(2, 10)}.json`;
113
+ const filePath = path.join(queueDir, fileName);
114
+ fs.writeFileSync(filePath, JSON.stringify(message, null, 2));
115
+ }
116
+ function renderCrossChatDeliveryStatus(target, result) {
117
+ const phase = result.status === "delivered_now"
118
+ ? "completed"
119
+ : result.status === "queued_for_later"
120
+ ? "queued"
121
+ : result.status === "blocked"
122
+ ? "blocked"
123
+ : "errored";
124
+ const lead = result.status === "delivered_now"
125
+ ? "delivered now"
126
+ : result.status === "queued_for_later"
127
+ ? "queued for later"
128
+ : result.status === "blocked"
129
+ ? "blocked"
130
+ : "failed";
131
+ return (0, progress_story_1.renderProgressStory)((0, progress_story_1.buildProgressStory)({
132
+ scope: "shared-work",
133
+ phase,
134
+ objective: `message to ${target}`,
135
+ outcomeText: `${lead}\n${result.detail}`,
136
+ }));
137
+ }
138
+ async function deliverVoiceChannelMessage(request, agentName, initialAudio) {
139
+ const result = await (0, outbound_1.placeTrustedFriendVoiceOutboundCall)({
140
+ agentName,
141
+ agentRoot: (0, identity_1.getAgentRoot)(),
142
+ friendId: request.friendId,
143
+ reason: request.content,
144
+ ...(initialAudio ? { initialAudio } : {}),
145
+ });
146
+ if (result.status === "placed") {
147
+ return {
148
+ status: "delivered_now",
149
+ detail: result.detail,
150
+ };
151
+ }
152
+ return {
153
+ status: result.status,
154
+ detail: result.detail,
155
+ };
156
+ }
157
+ /* v8 ignore start -- voice initial-audio parsing is exercised by voice transport tests; session tool keeps a thin argument adapter @preserve */
158
+ function parseVoiceInitialAudio(args) {
159
+ const source = args.voiceAudioSource === "url" || args.voiceAudioSource === "file" || args.voiceAudioSource === "tone"
160
+ ? args.voiceAudioSource
161
+ : undefined;
162
+ const hasAudioHint = Boolean(source
163
+ || args.voiceAudioUrl?.trim()
164
+ || args.voiceAudioPath?.trim()
165
+ || args.voiceAudioLabel?.trim()
166
+ || args.voiceAudioToneHz?.trim()
167
+ || args.voiceAudioDurationMs?.trim());
168
+ if (!hasAudioHint)
169
+ return undefined;
170
+ const toneHz = args.voiceAudioToneHz?.trim() ? Number(args.voiceAudioToneHz) : undefined;
171
+ const durationMs = args.voiceAudioDurationMs?.trim() ? Number(args.voiceAudioDurationMs) : undefined;
172
+ return {
173
+ source: source ?? "tone",
174
+ ...(args.voiceAudioUrl?.trim() ? { url: args.voiceAudioUrl.trim() } : {}),
175
+ ...(args.voiceAudioPath?.trim() ? { path: args.voiceAudioPath.trim() } : {}),
176
+ ...(args.voiceAudioLabel?.trim() ? { label: args.voiceAudioLabel.trim() } : {}),
177
+ ...(Number.isFinite(toneHz) ? { toneHz } : {}),
178
+ ...(Number.isFinite(durationMs) ? { durationMs } : {}),
179
+ };
180
+ }
181
+ /* v8 ignore stop */
182
+ function emptyTaskBoard() {
183
+ return {
184
+ compact: "",
185
+ full: "",
186
+ byStatus: {
187
+ drafting: [],
188
+ processing: [],
189
+ validating: [],
190
+ collaborating: [],
191
+ paused: [],
192
+ blocked: [],
193
+ done: [],
194
+ cancelled: [],
195
+ },
196
+ issues: [],
197
+ actionRequired: [],
198
+ unresolvedDependencies: [],
199
+ activeSessions: [],
200
+ activeBridges: [],
201
+ };
202
+ }
203
+ function isLiveCodingSessionStatus(status) {
204
+ return status === "spawning"
205
+ || status === "running"
206
+ || status === "waiting_input"
207
+ || status === "stalled";
208
+ }
209
+ function readActiveWorkInnerState() {
210
+ const defaultJob = {
211
+ status: "idle",
212
+ content: null,
213
+ origin: null,
214
+ mode: "reflect",
215
+ obligationStatus: null,
216
+ surfacedResult: null,
217
+ queuedAt: null,
218
+ startedAt: null,
219
+ surfacedAt: null,
220
+ };
221
+ try {
222
+ const agentRoot = (0, identity_1.getAgentRoot)();
223
+ const pendingDir = (0, pending_1.getInnerDialogPendingDir)((0, identity_1.getAgentName)());
224
+ const sessionPath = (0, thoughts_1.getInnerDialogSessionPath)(agentRoot);
225
+ const { pendingMessages, turns, runtimeState } = (0, thoughts_1.readInnerDialogRawData)(sessionPath, pendingDir);
226
+ const dialogStatus = (0, thoughts_1.deriveInnerDialogStatus)(pendingMessages, turns, runtimeState);
227
+ const job = (0, thoughts_1.deriveInnerJob)(pendingMessages, turns, runtimeState);
228
+ const storeObligationPending = (0, obligations_1.readPendingObligations)(agentRoot).length > 0;
229
+ return {
230
+ status: dialogStatus.processing === "started" ? "running" : "idle",
231
+ hasPending: dialogStatus.queue !== "clear",
232
+ origin: dialogStatus.origin,
233
+ contentSnippet: dialogStatus.contentSnippet,
234
+ obligationPending: dialogStatus.obligationPending || storeObligationPending,
235
+ job,
236
+ };
237
+ }
238
+ catch {
239
+ return {
240
+ status: "idle",
241
+ hasPending: false,
242
+ job: defaultJob,
243
+ };
244
+ }
245
+ }
246
+ async function buildToolActiveWorkFrame(ctx) {
247
+ const currentSession = ctx?.currentSession
248
+ ? {
249
+ friendId: ctx.currentSession.friendId,
250
+ channel: ctx.currentSession.channel,
251
+ key: ctx.currentSession.key,
252
+ sessionPath: (0, config_1.resolveSessionPath)(ctx.currentSession.friendId, ctx.currentSession.channel, ctx.currentSession.key),
253
+ }
254
+ : null;
255
+ const agentRoot = (0, identity_1.getAgentRoot)();
256
+ const bridges = currentSession
257
+ ? (0, manager_1.createBridgeManager)().findBridgesForSession({
258
+ friendId: currentSession.friendId,
259
+ channel: currentSession.channel,
260
+ key: currentSession.key,
261
+ })
262
+ : [];
263
+ let friendActivity = [];
264
+ try {
265
+ friendActivity = (0, session_activity_1.listSessionActivity)({
266
+ sessionsDir: `${agentRoot}/state/sessions`,
267
+ friendsDir: `${agentRoot}/friends`,
268
+ agentName: (0, identity_1.getAgentName)(),
269
+ currentSession,
270
+ });
271
+ }
272
+ catch {
273
+ friendActivity = [];
274
+ }
275
+ const pendingObligations = (() => {
276
+ try {
277
+ return (0, obligations_1.readPendingObligations)(agentRoot);
278
+ }
279
+ catch {
280
+ return [];
281
+ }
282
+ })();
283
+ let codingSessions = [];
284
+ let otherCodingSessions = [];
285
+ try {
286
+ const liveCodingSessions = (0, coding_1.getCodingSessionManager)()
287
+ .listSessions()
288
+ .filter((session) => isLiveCodingSessionStatus(session.status) && Boolean(session.originSession));
289
+ if (currentSession) {
290
+ codingSessions = liveCodingSessions.filter((session) => session.originSession?.friendId === currentSession.friendId
291
+ && session.originSession.channel === currentSession.channel
292
+ && session.originSession.key === currentSession.key);
293
+ otherCodingSessions = liveCodingSessions.filter((session) => !(session.originSession?.friendId === currentSession.friendId
294
+ && session.originSession.channel === currentSession.channel
295
+ && session.originSession.key === currentSession.key));
296
+ }
297
+ else {
298
+ codingSessions = [];
299
+ otherCodingSessions = liveCodingSessions;
300
+ }
301
+ }
302
+ catch {
303
+ codingSessions = [];
304
+ otherCodingSessions = [];
305
+ }
306
+ const currentObligation = currentSession
307
+ ? pendingObligations.find((obligation) => obligation.status !== "fulfilled"
308
+ && obligation.origin.friendId === currentSession.friendId
309
+ && obligation.origin.channel === currentSession.channel
310
+ && obligation.origin.key === currentSession.key)?.content ?? null
311
+ : null;
312
+ const backgroundOperations = (0, mail_import_discovery_1.listVisibleBackgroundOperations)({
313
+ agentName: (0, identity_1.getAgentName)(),
314
+ agentRoot,
315
+ repoRoot: process.cwd(),
316
+ homeDir: process.env.HOME,
317
+ nowMs: Date.now(),
318
+ limit: 5,
319
+ });
320
+ return (0, active_work_1.buildActiveWorkFrame)({
321
+ currentSession,
322
+ currentObligation,
323
+ mustResolveBeforeHandoff: false,
324
+ inner: readActiveWorkInnerState(),
325
+ bridges,
326
+ codingSessions,
327
+ backgroundOperations,
328
+ otherCodingSessions,
329
+ pendingObligations,
330
+ taskBoard: (() => {
331
+ try {
332
+ return (0, tasks_1.getTaskModule)().getBoard();
333
+ }
334
+ catch {
335
+ return emptyTaskBoard();
336
+ }
337
+ })(),
338
+ friendActivity,
339
+ targetCandidates: [],
340
+ });
341
+ }
342
+ function findDelegatingBridgeId(ctx) {
343
+ const currentSession = ctx?.currentSession;
344
+ if (!currentSession)
345
+ return undefined;
346
+ return ctx?.activeBridges?.find((bridge) => bridge.lifecycle === "active"
347
+ && bridge.attachedSessions.some((session) => session.friendId === currentSession.friendId
348
+ && session.channel === currentSession.channel
349
+ && session.key === currentSession.key))?.id;
350
+ }
351
+ function renderInnerProgressStatus(status) {
352
+ if (status.processing === "pending") {
353
+ return "i've queued this thought for private attention. it'll come up when my inner dialog is free.";
354
+ }
355
+ if (status.processing === "started") {
356
+ return "i'm working through this privately right now.";
357
+ }
358
+ // processed / completed
359
+ if (status.surfaced && status.surfaced !== "nothing recent" && status.surfaced !== "no outward result") {
360
+ return `i thought about this privately and came to something: ${status.surfaced}`;
361
+ }
362
+ return "i thought about this privately. i'll bring it back when the time is right.";
363
+ }
364
+ exports.sessionToolDefinitions = [
365
+ {
366
+ tool: {
367
+ type: "function",
368
+ function: {
369
+ name: "query_active_work",
370
+ description: "read the current live world-state across visible sessions, coding lanes, inner work, and return obligations. use this instead of piecing status together from separate session and coding tools.",
371
+ parameters: {
372
+ type: "object",
373
+ properties: {},
374
+ },
375
+ },
376
+ },
377
+ handler: async (_args, ctx) => {
378
+ const frame = await buildToolActiveWorkFrame(ctx);
379
+ return `this is my current top-level live world-state.\nanswer whole-self status questions from this before drilling into individual sessions.\n\n${(0, active_work_1.formatActiveWorkFrame)(frame)}`;
380
+ },
381
+ },
382
+ {
383
+ tool: {
384
+ type: "function",
385
+ function: {
386
+ name: "query_session",
387
+ description: "inspect another session. use transcript for recent context, status for self/inner progress, or search to find older history by query.",
388
+ parameters: {
389
+ type: "object",
390
+ properties: {
391
+ friendId: { type: "string", description: "the friend UUID (or 'self')" },
392
+ channel: { type: "string", description: "the channel: cli, teams, bluebubbles, voice, inner, or mcp" },
393
+ key: { type: "string", description: "session key (defaults to 'session')" },
394
+ messageCount: { type: "string", description: "how many recent messages to return (default 20)" },
395
+ mode: {
396
+ type: "string",
397
+ enum: ["transcript", "status", "search"],
398
+ description: "transcript (default), lightweight status for self/inner checks, or search for older history",
399
+ },
400
+ query: { type: "string", description: "required when mode=search; search term for older session history" },
401
+ },
402
+ required: ["friendId", "channel"],
403
+ },
404
+ },
405
+ },
406
+ handler: async (args, ctx) => {
407
+ let friendId = args.friendId;
408
+ const channel = args.channel;
409
+ const key = args.key || "session";
410
+ const count = parseInt(args.messageCount || "20", 10);
411
+ const mode = args.mode || "transcript";
412
+ // Resolve friend name -> UUID if not already a UUID or "self"
413
+ if (friendId && friendId !== "self" && !/^[0-9a-f]{8}-[0-9a-f]{4}-/.test(friendId) && ctx?.friendStore?.listAll) {
414
+ const allFriends = await ctx.friendStore.listAll();
415
+ const match = allFriends.find(f => f.name.toLowerCase() === friendId.toLowerCase());
416
+ if (match) {
417
+ friendId = match.id;
418
+ }
419
+ }
420
+ if (mode === "status") {
421
+ if (friendId !== "self" || channel !== "inner") {
422
+ return "status mode is only available for self/inner dialog.";
423
+ }
424
+ const sessionPath = (0, thoughts_1.getInnerDialogSessionPath)((0, identity_1.getAgentRoot)());
425
+ const pendingDir = (0, pending_1.getInnerDialogPendingDir)((0, identity_1.getAgentName)());
426
+ return renderInnerProgressStatus((0, thoughts_1.readInnerDialogStatus)(sessionPath, pendingDir));
427
+ }
428
+ if (mode === "search") {
429
+ const query = (args.query || "").trim();
430
+ if (!query) {
431
+ return "search mode requires a non-empty query.";
432
+ }
433
+ const search = await searchSessionSafely({
434
+ sessionPath: (0, config_1.resolveSessionPath)(friendId, channel, key),
435
+ friendId,
436
+ channel,
437
+ key,
438
+ query,
439
+ });
440
+ if (search.kind === "missing") {
441
+ return NO_SESSION_FOUND_MESSAGE;
442
+ }
443
+ if (search.kind === "empty") {
444
+ return EMPTY_SESSION_MESSAGE;
445
+ }
446
+ if (search.kind === "no_match") {
447
+ return `no matches for "${search.query}" in that session.\n\n${search.snapshot}`;
448
+ }
449
+ return [
450
+ `history search: "${search.query}"`,
451
+ search.snapshot,
452
+ ...search.matches.map((match, index) => `match ${index + 1}\n${match}`),
453
+ ].join("\n\n");
454
+ }
455
+ const sessFile = (0, config_1.resolveSessionPath)(friendId, channel, key);
456
+ const sessionTail = await summarizeSessionTailSafely({
457
+ sessionPath: sessFile,
458
+ friendId,
459
+ channel,
460
+ key,
461
+ messageCount: count,
462
+ trustLevel: ctx?.context?.friend?.trustLevel,
463
+ summarize: ctx?.summarize,
464
+ archiveFallback: true,
465
+ });
466
+ if (sessionTail.kind === "missing") {
467
+ return NO_SESSION_FOUND_MESSAGE;
468
+ }
469
+ if (sessionTail.kind === "empty") {
470
+ return EMPTY_SESSION_MESSAGE;
471
+ }
472
+ return sessionTail.summary;
473
+ },
474
+ },
475
+ {
476
+ tool: {
477
+ type: "function",
478
+ function: {
479
+ name: "send_message",
480
+ description: "send a message to a friend's session. when the request is explicitly authorized from a trusted live chat, the harness will try to deliver immediately; otherwise it reports truthful queued/block/failure state.",
481
+ parameters: {
482
+ type: "object",
483
+ properties: {
484
+ friendId: { type: "string", description: "the friend UUID (or 'self')" },
485
+ channel: { type: "string", description: "the channel: cli, teams, bluebubbles, voice, inner, or mcp. channel=voice intentionally starts a live phone call to a trusted friend through the Voice sense." },
486
+ key: { type: "string", description: "session key (defaults to 'session')" },
487
+ content: { type: "string", description: "the message content to send" },
488
+ voiceAudioSource: { type: "string", enum: ["tone", "url", "file"], description: "optional initial non-speech audio to play after the opening greeting when channel=voice" },
489
+ voiceAudioUrl: { type: "string", description: "short audio URL for voiceAudioSource=url" },
490
+ voiceAudioPath: { type: "string", description: "local audio file path for voiceAudioSource=file" },
491
+ voiceAudioLabel: { type: "string", description: "short label for the initial voice audio" },
492
+ voiceAudioToneHz: { type: "number", description: "tone frequency for voiceAudioSource=tone" },
493
+ voiceAudioDurationMs: { type: "number", description: "initial audio duration in milliseconds" },
494
+ },
495
+ required: ["friendId", "channel", "content"],
496
+ },
497
+ },
498
+ },
499
+ handler: async (args, ctx) => {
500
+ let friendId = args.friendId;
501
+ const channel = args.channel;
502
+ const key = args.key || "session";
503
+ const content = args.content;
504
+ const voiceInitialAudio = channel === "voice" ? parseVoiceInitialAudio(args) : undefined;
505
+ const now = Date.now();
506
+ const agentName = (0, identity_1.getAgentName)();
507
+ // Resolve friend name → UUID if needed
508
+ /* v8 ignore start -- name resolution: reads real filesystem, tested via live integration @preserve */
509
+ if (friendId !== "self") {
510
+ const originalFriendId = friendId;
511
+ try {
512
+ const agentRoot = (0, identity_1.getAgentRoot)();
513
+ const sessionsDir = path.join(agentRoot, "state", "sessions");
514
+ const friendsDir = path.join(agentRoot, "friends");
515
+ const sessionDirExists = fs.existsSync(path.join(sessionsDir, friendId));
516
+ if (!sessionDirExists) {
517
+ const friendFiles = fs.readdirSync(friendsDir).filter((f) => f.endsWith(".json"));
518
+ for (const file of friendFiles) {
519
+ const raw = fs.readFileSync(path.join(friendsDir, file), "utf-8");
520
+ const record = JSON.parse(raw);
521
+ if (record.name?.toLowerCase() === friendId.toLowerCase() && record.id) {
522
+ friendId = record.id;
523
+ break;
524
+ }
525
+ }
526
+ (0, runtime_1.emitNervesEvent)({
527
+ component: "repertoire",
528
+ event: "repertoire.send_message_name_resolve",
529
+ message: friendId !== originalFriendId ? "resolved friend name to UUID" : "friend name resolution failed",
530
+ meta: { original: originalFriendId, resolved: friendId, friendsDir, fileCount: friendFiles.length },
531
+ });
532
+ }
533
+ }
534
+ catch (err) {
535
+ (0, runtime_1.emitNervesEvent)({
536
+ level: "warn",
537
+ component: "repertoire",
538
+ event: "repertoire.send_message_name_resolve_error",
539
+ message: "friend name resolution threw",
540
+ meta: { friendId: originalFriendId, error: err instanceof Error ? err.message : String(err) },
541
+ });
542
+ }
543
+ }
544
+ /* v8 ignore stop */
545
+ // Self-routing: messages to "self" always go to inner dialog pending dir,
546
+ // regardless of the channel or key the agent specified.
547
+ const isSelf = friendId === "self";
548
+ const pendingDir = isSelf
549
+ ? (0, pending_1.getInnerDialogPendingDir)(agentName)
550
+ : (0, pending_1.getPendingDir)(agentName, friendId, channel, key);
551
+ const delegatingBridgeId = findDelegatingBridgeId(ctx);
552
+ const delegatedFrom = isSelf
553
+ && ctx?.currentSession
554
+ && !(ctx.currentSession.friendId === "self" && ctx.currentSession.channel === "inner")
555
+ ? {
556
+ friendId: ctx.currentSession.friendId,
557
+ channel: ctx.currentSession.channel,
558
+ key: ctx.currentSession.key,
559
+ ...(delegatingBridgeId ? { bridgeId: delegatingBridgeId } : {}),
560
+ }
561
+ : undefined;
562
+ const obligationId = delegatedFrom ? (0, obligations_1.generateObligationId)(now) : undefined;
563
+ const envelope = {
564
+ from: agentName,
565
+ friendId,
566
+ channel,
567
+ key,
568
+ content,
569
+ timestamp: now,
570
+ ...(delegatedFrom ? { delegatedFrom, obligationStatus: "pending" } : {}),
571
+ ...(obligationId ? { obligationId } : {}),
572
+ };
573
+ if (isSelf) {
574
+ writePendingEnvelope(pendingDir, envelope);
575
+ if (delegatedFrom) {
576
+ try {
577
+ (0, obligations_1.createObligation)((0, identity_1.getAgentRoot)(), {
578
+ origin: {
579
+ friendId: delegatedFrom.friendId,
580
+ channel: delegatedFrom.channel,
581
+ key: delegatedFrom.key,
582
+ },
583
+ ...(delegatedFrom.bridgeId ? { bridgeId: delegatedFrom.bridgeId } : {}),
584
+ content,
585
+ });
586
+ }
587
+ catch {
588
+ /* v8 ignore next -- defensive: obligation store write failure should not break send_message @preserve */
589
+ }
590
+ /* v8 ignore next -- obligationId always set when delegatedFrom is set (see generateObligationId above) @preserve */
591
+ if (obligationId) {
592
+ (0, obligations_1.createReturnObligation)(agentName, {
593
+ id: obligationId,
594
+ origin: delegatedFrom,
595
+ status: "queued",
596
+ delegatedContent: content.length > 120 ? `${content.slice(0, 117)}...` : content,
597
+ createdAt: now,
598
+ });
599
+ }
600
+ (0, runtime_1.emitNervesEvent)({
601
+ event: "repertoire.obligation_created",
602
+ component: "repertoire",
603
+ message: "obligation created for inner dialog delegation",
604
+ meta: {
605
+ friendId: delegatedFrom.friendId,
606
+ channel: delegatedFrom.channel,
607
+ key: delegatedFrom.key,
608
+ },
609
+ });
610
+ }
611
+ let wakeResponse = null;
612
+ try {
613
+ wakeResponse = await (0, socket_client_1.requestInnerWake)(agentName);
614
+ }
615
+ catch {
616
+ wakeResponse = null;
617
+ }
618
+ if (!wakeResponse?.ok) {
619
+ const { runInnerDialogTurn } = await Promise.resolve().then(() => __importStar(require("../senses/inner-dialog")));
620
+ if (ctx?.context?.channel.channel === "inner") {
621
+ queueMicrotask(() => {
622
+ void runInnerDialogTurn({ reason: "instinct" });
623
+ });
624
+ return renderInnerProgressStatus({
625
+ queue: "queued to inner/dialog",
626
+ wake: "inline scheduled",
627
+ processing: "pending",
628
+ surfaced: "nothing yet",
629
+ });
630
+ }
631
+ else {
632
+ const turnResult = await runInnerDialogTurn({ reason: "instinct" });
633
+ const surfacedPreview = normalizeProgressOutcome((0, thoughts_1.formatSurfacedValue)((0, thoughts_1.extractThoughtResponseFromMessages)(turnResult?.messages ?? [])));
634
+ return (0, progress_story_1.renderProgressStory)((0, progress_story_1.buildProgressStory)({
635
+ scope: "inner-delegation",
636
+ phase: "completed",
637
+ objective: "queued to inner/dialog",
638
+ outcomeText: `wake: inline fallback\n${surfacedPreview}`,
639
+ }));
640
+ }
641
+ }
642
+ return renderInnerProgressStatus({
643
+ queue: "queued to inner/dialog",
644
+ wake: "daemon requested",
645
+ processing: "pending",
646
+ surfaced: "nothing yet",
647
+ });
648
+ }
649
+ // Resolve BB session key if using default — agents don't know the real session key
650
+ /* v8 ignore start -- BB session key resolution: reads real filesystem @preserve */
651
+ let resolvedKey = key;
652
+ if (channel === "bluebubbles" && key === "session") {
653
+ try {
654
+ const agentRoot = (0, identity_1.getAgentRoot)();
655
+ const bbDir = path.join(agentRoot, "state", "sessions", friendId, "bluebubbles");
656
+ if (fs.existsSync(bbDir)) {
657
+ const files = fs.readdirSync(bbDir).filter((f) => f.endsWith(".json"));
658
+ // Only use DM sessions (;-;) for proactive delivery — never group chats (;+;)
659
+ const dmFile = files.find((f) => f.includes(";-;"));
660
+ if (dmFile) {
661
+ resolvedKey = dmFile.replace(/\.json$/, "");
662
+ }
663
+ }
664
+ }
665
+ catch { /* continue with default key */ }
666
+ }
667
+ /* v8 ignore stop */
668
+ const deliveryResult = await (0, cross_chat_delivery_1.deliverCrossChatMessage)({
669
+ friendId,
670
+ channel,
671
+ key: resolvedKey,
672
+ content,
673
+ intent: ctx?.currentSession && ctx.currentSession.friendId !== "self"
674
+ ? "explicit_cross_chat"
675
+ : "generic_outreach",
676
+ ...(ctx?.currentSession && ctx.currentSession.friendId !== "self"
677
+ ? {
678
+ authorizingSession: {
679
+ friendId: ctx.currentSession.friendId,
680
+ channel: ctx.currentSession.channel,
681
+ key: ctx.currentSession.key,
682
+ trustLevel: ctx?.context?.friend?.trustLevel,
683
+ },
684
+ }
685
+ : {}),
686
+ }, {
687
+ agentName,
688
+ queuePending: (message) => writePendingEnvelope(pendingDir, message),
689
+ deliverers: {
690
+ bluebubbles: async (request) => {
691
+ const { sendProactiveBlueBubblesMessageToSession } = await Promise.resolve().then(() => __importStar(require("../senses/bluebubbles")));
692
+ const result = await sendProactiveBlueBubblesMessageToSession({
693
+ friendId: request.friendId,
694
+ sessionKey: request.key,
695
+ text: request.content,
696
+ intent: request.intent,
697
+ authorizingSession: request.authorizingSession,
698
+ });
699
+ if (result.delivered) {
700
+ return {
701
+ status: "delivered_now",
702
+ detail: "sent to the active bluebubbles chat now",
703
+ };
704
+ }
705
+ if (result.reason === "missing_target") {
706
+ return {
707
+ status: "blocked",
708
+ detail: "bluebubbles could not resolve a routable target for that session",
709
+ };
710
+ }
711
+ if (result.reason === "blocked_meta_content") {
712
+ return {
713
+ status: "blocked",
714
+ detail: "blocked: contains internal meta markers",
715
+ };
716
+ }
717
+ if (result.reason === "send_error") {
718
+ return {
719
+ status: "failed",
720
+ detail: "bluebubbles send failed",
721
+ };
722
+ }
723
+ return {
724
+ status: "unavailable",
725
+ detail: "live delivery unavailable right now; queued for the next active turn",
726
+ };
727
+ },
728
+ teams: async (request) => {
729
+ if (!ctx?.botApi) {
730
+ return {
731
+ status: "unavailable",
732
+ detail: "live delivery unavailable right now; queued for the next active turn",
733
+ };
734
+ }
735
+ const { sendProactiveTeamsMessageToSession } = await Promise.resolve().then(() => __importStar(require("../senses/teams")));
736
+ const result = await sendProactiveTeamsMessageToSession({
737
+ friendId: request.friendId,
738
+ sessionKey: request.key,
739
+ text: request.content,
740
+ intent: request.intent,
741
+ authorizingSession: request.authorizingSession,
742
+ }, {
743
+ botApi: ctx.botApi,
744
+ });
745
+ if (result.delivered) {
746
+ return {
747
+ status: "delivered_now",
748
+ detail: "sent to the active teams chat now",
749
+ };
750
+ }
751
+ if (result.reason === "missing_target") {
752
+ return {
753
+ status: "blocked",
754
+ detail: "teams could not resolve a routable target for that session",
755
+ };
756
+ }
757
+ if (result.reason === "send_error") {
758
+ return {
759
+ status: "failed",
760
+ detail: "teams send failed",
761
+ };
762
+ }
763
+ return {
764
+ status: "unavailable",
765
+ detail: "live delivery unavailable right now; queued for the next active turn",
766
+ };
767
+ },
768
+ voice: async (request) => deliverVoiceChannelMessage(request, agentName, voiceInitialAudio),
769
+ },
770
+ });
771
+ return renderCrossChatDeliveryStatus(`${friendId} on ${channel}/${key}`, deliveryResult);
772
+ },
773
+ },
774
+ {
775
+ tool: {
776
+ type: "function",
777
+ function: {
778
+ name: "set_reasoning_effort",
779
+ description: "adjust your own reasoning depth for subsequent turns. use higher effort for complex analysis, lower for simple tasks.",
780
+ parameters: {
781
+ type: "object",
782
+ properties: {
783
+ level: { type: "string", description: "the reasoning effort level to set" },
784
+ },
785
+ required: ["level"],
786
+ },
787
+ },
788
+ },
789
+ handler: (args, ctx) => {
790
+ if (!ctx?.supportedReasoningEfforts || !ctx.setReasoningEffort) {
791
+ return "reasoning effort adjustment is not available in this context.";
792
+ }
793
+ const level = (args.level || "").trim();
794
+ if (!ctx.supportedReasoningEfforts.includes(level)) {
795
+ return `invalid reasoning effort level "${level}". accepted levels: ${ctx.supportedReasoningEfforts.join(", ")}`;
796
+ }
797
+ ctx.setReasoningEffort(level);
798
+ (0, runtime_1.emitNervesEvent)({
799
+ component: "repertoire",
800
+ event: "repertoire.reasoning_effort_changed",
801
+ message: `reasoning effort set to ${level}`,
802
+ meta: { level },
803
+ });
804
+ return `reasoning effort set to "${level}".`;
805
+ },
806
+ requiredCapability: "reasoning-effort",
807
+ summaryKeys: ["level"],
808
+ },
809
+ ];