@ouro.bot/cli 0.1.0-alpha.62 → 0.1.0-alpha.637

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 (432) 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 +4087 -13
  13. package/dist/arc/attention-types.js +8 -0
  14. package/dist/arc/cares.js +144 -0
  15. package/dist/arc/episodes.js +118 -0
  16. package/dist/arc/evolution.js +487 -0
  17. package/dist/arc/intentions.js +134 -0
  18. package/dist/arc/json-store.js +117 -0
  19. package/dist/arc/obligations.js +270 -0
  20. package/dist/arc/packets.js +288 -0
  21. package/dist/arc/presence.js +185 -0
  22. package/dist/arc/task-lifecycle.js +57 -0
  23. package/dist/heart/active-work.js +860 -43
  24. package/dist/heart/agent-entry.js +69 -3
  25. package/dist/heart/attachments/image-normalize.js +194 -0
  26. package/dist/heart/attachments/materialize.js +97 -0
  27. package/dist/heart/attachments/originals.js +88 -0
  28. package/dist/heart/attachments/render.js +29 -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/awaiting/await-alert.js +146 -0
  36. package/dist/heart/awaiting/await-expiry.js +108 -0
  37. package/dist/heart/awaiting/await-loader.js +91 -0
  38. package/dist/heart/awaiting/await-parser.js +141 -0
  39. package/dist/heart/awaiting/await-runtime-state.js +100 -0
  40. package/dist/heart/awaiting/await-scheduler.js +377 -0
  41. package/dist/heart/background-operations.js +281 -0
  42. package/dist/heart/bridges/manager.js +137 -17
  43. package/dist/heart/bridges/store.js +14 -2
  44. package/dist/heart/bundle-state.js +168 -0
  45. package/dist/heart/commitments.js +135 -0
  46. package/dist/heart/config-registry.js +322 -0
  47. package/dist/heart/config.js +114 -119
  48. package/dist/heart/core.js +1028 -248
  49. package/dist/heart/cross-chat-delivery.js +3 -18
  50. package/dist/heart/daemon/agent-config-check.js +419 -0
  51. package/dist/heart/daemon/agent-discovery.js +102 -3
  52. package/dist/heart/daemon/agent-service.js +522 -0
  53. package/dist/heart/daemon/agentic-repair.js +547 -0
  54. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  55. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  56. package/dist/heart/daemon/cadence.js +70 -0
  57. package/dist/heart/daemon/cli-defaults.js +776 -0
  58. package/dist/heart/daemon/cli-desk.js +322 -0
  59. package/dist/heart/daemon/cli-exec.js +7468 -0
  60. package/dist/heart/daemon/cli-help.js +505 -0
  61. package/dist/heart/daemon/cli-parse.js +1554 -0
  62. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  63. package/dist/heart/daemon/cli-render.js +763 -0
  64. package/dist/heart/daemon/cli-types.js +8 -0
  65. package/dist/heart/daemon/connect-bay.js +323 -0
  66. package/dist/heart/daemon/daemon-cli.js +29 -1700
  67. package/dist/heart/daemon/daemon-entry.js +485 -2
  68. package/dist/heart/daemon/daemon-health.js +176 -0
  69. package/dist/heart/daemon/daemon-rollup.js +57 -0
  70. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  71. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  72. package/dist/heart/daemon/daemon.js +906 -71
  73. package/dist/heart/daemon/dns-workflow.js +394 -0
  74. package/dist/heart/daemon/doctor-types.js +8 -0
  75. package/dist/heart/daemon/doctor.js +873 -0
  76. package/dist/heart/daemon/health-monitor.js +122 -1
  77. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  78. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  79. package/dist/heart/daemon/http-health-probe.js +80 -0
  80. package/dist/heart/daemon/human-command-screens.js +234 -0
  81. package/dist/heart/daemon/human-readiness.js +114 -0
  82. package/dist/heart/daemon/inner-status.js +89 -0
  83. package/dist/heart/daemon/interactive-repair.js +394 -0
  84. package/dist/heart/daemon/launchd.js +37 -8
  85. package/dist/heart/daemon/log-tailer.js +79 -10
  86. package/dist/heart/daemon/logs-prune.js +110 -0
  87. package/dist/heart/daemon/mcp-canary.js +297 -0
  88. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  89. package/dist/heart/daemon/os-cron-deps.js +135 -0
  90. package/dist/heart/daemon/os-cron.js +14 -12
  91. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  92. package/dist/heart/daemon/ouro-entry.js +3 -1
  93. package/dist/heart/daemon/plugin-cli.js +432 -0
  94. package/dist/heart/daemon/process-manager.js +501 -35
  95. package/dist/heart/daemon/provider-discovery.js +137 -0
  96. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  97. package/dist/heart/daemon/pulse.js +475 -0
  98. package/dist/heart/daemon/readiness-repair.js +365 -0
  99. package/dist/heart/daemon/run-hooks.js +2 -0
  100. package/dist/heart/daemon/runtime-logging.js +11 -3
  101. package/dist/heart/daemon/runtime-metadata.js +2 -30
  102. package/dist/heart/daemon/safe-mode.js +161 -0
  103. package/dist/heart/daemon/sense-manager.js +493 -38
  104. package/dist/heart/daemon/session-id-resolver.js +131 -0
  105. package/dist/heart/daemon/skill-management-installer.js +22 -9
  106. package/dist/heart/daemon/socket-client.js +158 -11
  107. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  108. package/dist/heart/daemon/startup-tui.js +330 -0
  109. package/dist/heart/daemon/task-scheduler.js +117 -39
  110. package/dist/heart/daemon/terminal-ui.js +499 -0
  111. package/dist/heart/daemon/thoughts.js +229 -17
  112. package/dist/heart/daemon/up-progress.js +366 -0
  113. package/dist/heart/daemon/vault-items.js +56 -0
  114. package/dist/heart/delegation.js +1 -4
  115. package/dist/heart/habits/habit-migration.js +189 -0
  116. package/dist/heart/habits/habit-parser.js +140 -0
  117. package/dist/heart/habits/habit-runtime-state.js +100 -0
  118. package/dist/heart/habits/habit-scheduler.js +372 -0
  119. package/dist/heart/{daemon → hatch}/hatch-flow.js +32 -56
  120. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  121. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  122. package/dist/heart/{daemon → hatch}/specialist-tools.js +37 -14
  123. package/dist/heart/identity.js +168 -57
  124. package/dist/heart/kept-notes.js +357 -0
  125. package/dist/heart/kicks.js +1 -1
  126. package/dist/heart/machine-identity.js +161 -0
  127. package/dist/heart/mail-import-discovery.js +353 -0
  128. package/dist/heart/mailbox/mailbox-http-hooks.js +66 -0
  129. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  130. package/dist/heart/mailbox/mailbox-http-routes.js +246 -0
  131. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  132. package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
  133. package/dist/heart/mailbox/mailbox-http.js +99 -0
  134. package/dist/heart/mailbox/mailbox-read.js +31 -0
  135. package/dist/heart/mailbox/mailbox-types.js +27 -0
  136. package/dist/heart/mailbox/mailbox-view.js +197 -0
  137. package/dist/heart/mailbox/readers/agent-machine.js +418 -0
  138. package/dist/heart/mailbox/readers/continuity-readers.js +319 -0
  139. package/dist/heart/mailbox/readers/mail.js +375 -0
  140. package/dist/heart/mailbox/readers/runtime-readers.js +756 -0
  141. package/dist/heart/mailbox/readers/sessions.js +232 -0
  142. package/dist/heart/mailbox/readers/shared.js +111 -0
  143. package/dist/heart/mcp/mcp-server.js +692 -0
  144. package/dist/heart/migrate-config.js +100 -0
  145. package/dist/heart/model-capabilities.js +19 -0
  146. package/dist/heart/orientation-frame.js +217 -0
  147. package/dist/heart/platform.js +81 -0
  148. package/dist/heart/provider-attempt.js +134 -0
  149. package/dist/heart/provider-binding-resolver.js +272 -0
  150. package/dist/heart/provider-credentials.js +425 -0
  151. package/dist/heart/provider-failover.js +301 -0
  152. package/dist/heart/provider-models.js +81 -0
  153. package/dist/heart/provider-ping.js +262 -0
  154. package/dist/heart/provider-readiness-cache.js +40 -0
  155. package/dist/heart/provider-visibility.js +188 -0
  156. package/dist/heart/providers/anthropic-token.js +131 -0
  157. package/dist/heart/providers/anthropic.js +139 -52
  158. package/dist/heart/providers/azure.js +23 -11
  159. package/dist/heart/providers/error-classification.js +127 -0
  160. package/dist/heart/providers/github-copilot.js +145 -0
  161. package/dist/heart/providers/minimax-vlm.js +189 -0
  162. package/dist/heart/providers/minimax.js +26 -8
  163. package/dist/heart/providers/openai-codex.js +55 -40
  164. package/dist/heart/runtime-capability-check.js +170 -0
  165. package/dist/heart/runtime-credentials.js +367 -0
  166. package/dist/heart/runtime-cwd.js +87 -0
  167. package/dist/heart/sense-truth.js +13 -4
  168. package/dist/heart/session-activity.js +48 -24
  169. package/dist/heart/session-events.js +1163 -0
  170. package/dist/heart/session-playback-cli-main.js +5 -0
  171. package/dist/heart/session-playback-cli.js +36 -0
  172. package/dist/heart/session-playback.js +231 -0
  173. package/dist/heart/session-stats-cli-main.js +5 -0
  174. package/dist/heart/session-stats.js +182 -0
  175. package/dist/heart/session-transcript.js +133 -0
  176. package/dist/heart/start-of-turn-packet.js +345 -0
  177. package/dist/heart/streaming.js +44 -27
  178. package/dist/heart/structured-output.js +196 -0
  179. package/dist/heart/sync-classification.js +176 -0
  180. package/dist/heart/sync.js +449 -0
  181. package/dist/heart/target-resolution.js +9 -5
  182. package/dist/heart/tempo.js +93 -0
  183. package/dist/heart/temporal-view.js +41 -0
  184. package/dist/heart/timeouts.js +101 -0
  185. package/dist/heart/tool-activity-callbacks.js +59 -0
  186. package/dist/heart/tool-description.js +143 -0
  187. package/dist/heart/tool-friction.js +55 -0
  188. package/dist/heart/tool-loop.js +200 -0
  189. package/dist/heart/turn-context.js +389 -0
  190. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  191. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  192. package/dist/heart/versioning/ouro-path-installer.js +426 -0
  193. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  194. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  195. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  196. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  197. package/dist/mailbox-ui/assets/index-9-AxCxuB.js +61 -0
  198. package/dist/mailbox-ui/assets/index-CWzt267f.css +1 -0
  199. package/dist/mailbox-ui/index.html +15 -0
  200. package/dist/mailroom/attention.js +167 -0
  201. package/dist/mailroom/autonomy.js +209 -0
  202. package/dist/mailroom/blob-store.js +715 -0
  203. package/dist/mailroom/body-cache.js +61 -0
  204. package/dist/mailroom/core.js +788 -0
  205. package/dist/mailroom/entry.js +160 -0
  206. package/dist/mailroom/file-store.js +568 -0
  207. package/dist/mailroom/mbox-import.js +393 -0
  208. package/dist/mailroom/migration.js +164 -0
  209. package/dist/mailroom/outbound.js +380 -0
  210. package/dist/mailroom/policy.js +263 -0
  211. package/dist/mailroom/reader.js +233 -0
  212. package/dist/mailroom/search-cache.js +334 -0
  213. package/dist/mailroom/search-relevance.js +319 -0
  214. package/dist/mailroom/smtp-ingress.js +176 -0
  215. package/dist/mailroom/source-state.js +176 -0
  216. package/dist/mailroom/thread.js +109 -0
  217. package/dist/mailroom/travel-extract.js +89 -0
  218. package/dist/mind/bundle-manifest.js +14 -1
  219. package/dist/mind/context.js +251 -101
  220. package/dist/mind/desk-section.js +310 -0
  221. package/dist/mind/diary-integrity.js +60 -0
  222. package/dist/mind/{memory.js → diary.js} +68 -76
  223. package/dist/mind/embedding-provider.js +60 -0
  224. package/dist/mind/file-state.js +179 -0
  225. package/dist/mind/friends/channel.js +39 -0
  226. package/dist/mind/friends/resolver.js +54 -2
  227. package/dist/mind/friends/store-file.js +48 -4
  228. package/dist/mind/friends/types.js +2 -2
  229. package/dist/mind/journal-index.js +162 -0
  230. package/dist/mind/note-search.js +268 -0
  231. package/dist/mind/obligation-steering.js +221 -0
  232. package/dist/mind/pending.js +6 -1
  233. package/dist/mind/prompt-refresh.js +3 -2
  234. package/dist/mind/prompt.js +1075 -146
  235. package/dist/mind/provenance-trust.js +26 -0
  236. package/dist/mind/scrutiny.js +173 -0
  237. package/dist/nerves/cli-logging.js +7 -1
  238. package/dist/nerves/coverage/audit-rules.js +15 -6
  239. package/dist/nerves/coverage/audit.js +28 -2
  240. package/dist/nerves/coverage/cli.js +1 -1
  241. package/dist/nerves/coverage/contract.js +5 -5
  242. package/dist/nerves/coverage/file-completeness.js +139 -5
  243. package/dist/nerves/event-buffer.js +111 -0
  244. package/dist/nerves/index.js +224 -4
  245. package/dist/nerves/observation.js +20 -0
  246. package/dist/nerves/redact.js +79 -0
  247. package/dist/nerves/review/cli-main.js +5 -0
  248. package/dist/nerves/review/cli.js +156 -0
  249. package/dist/nerves/review/core.js +152 -0
  250. package/dist/nerves/runtime.js +5 -1
  251. package/dist/repertoire/ado-client.js +15 -56
  252. package/dist/repertoire/ado-semantic.js +16 -10
  253. package/dist/repertoire/api-client.js +97 -0
  254. package/dist/repertoire/bitwarden-store.js +1040 -0
  255. package/dist/repertoire/bundle-templates.js +72 -0
  256. package/dist/repertoire/bw-installer.js +180 -0
  257. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  258. package/dist/repertoire/coding/context-pack.js +331 -0
  259. package/dist/repertoire/coding/feedback.js +197 -30
  260. package/dist/repertoire/coding/manager.js +166 -10
  261. package/dist/repertoire/coding/spawner.js +55 -9
  262. package/dist/repertoire/coding/tools.js +219 -7
  263. package/dist/repertoire/commerce-errors.js +109 -0
  264. package/dist/repertoire/commerce-self-test.js +156 -0
  265. package/dist/repertoire/credential-access.js +178 -0
  266. package/dist/repertoire/desk/classifier.js +362 -0
  267. package/dist/repertoire/duffel-client.js +185 -0
  268. package/dist/repertoire/github-client.js +14 -55
  269. package/dist/repertoire/graph-client.js +11 -52
  270. package/dist/repertoire/guardrails.js +385 -0
  271. package/dist/repertoire/mcp-client.js +295 -0
  272. package/dist/repertoire/mcp-manager.js +403 -0
  273. package/dist/repertoire/mcp-tools.js +83 -0
  274. package/dist/repertoire/plugin-mcp.js +175 -0
  275. package/dist/repertoire/plugins.js +253 -0
  276. package/dist/repertoire/shell-sessions.js +133 -0
  277. package/dist/repertoire/skills.js +48 -4
  278. package/dist/repertoire/stripe-client.js +131 -0
  279. package/dist/repertoire/tool-results.js +29 -0
  280. package/dist/repertoire/tools-attachments.js +317 -0
  281. package/dist/repertoire/tools-awaiting.js +372 -0
  282. package/dist/repertoire/tools-base.js +59 -1082
  283. package/dist/repertoire/tools-bluebubbles.js +2 -0
  284. package/dist/repertoire/tools-bridge.js +144 -0
  285. package/dist/repertoire/tools-bundle.js +993 -0
  286. package/dist/repertoire/tools-config.js +186 -0
  287. package/dist/repertoire/tools-continuity.js +252 -0
  288. package/dist/repertoire/tools-credential.js +383 -0
  289. package/dist/repertoire/tools-evolution.js +527 -0
  290. package/dist/repertoire/tools-files.js +344 -0
  291. package/dist/repertoire/tools-flight.js +227 -0
  292. package/dist/repertoire/tools-flow.js +119 -0
  293. package/dist/repertoire/tools-github.js +3 -8
  294. package/dist/repertoire/tools-mail.js +1975 -0
  295. package/dist/repertoire/tools-notes.js +438 -0
  296. package/dist/repertoire/tools-obligations.js +143 -0
  297. package/dist/repertoire/tools-orientation.js +31 -0
  298. package/dist/repertoire/tools-record.js +464 -0
  299. package/dist/repertoire/tools-runtime.js +150 -0
  300. package/dist/repertoire/tools-session.js +766 -0
  301. package/dist/repertoire/tools-shell.js +120 -0
  302. package/dist/repertoire/tools-stripe.js +182 -0
  303. package/dist/repertoire/tools-surface.js +344 -0
  304. package/dist/repertoire/tools-teams.js +12 -39
  305. package/dist/repertoire/tools-travel.js +125 -0
  306. package/dist/repertoire/tools-trip.js +982 -0
  307. package/dist/repertoire/tools-user-profile.js +146 -0
  308. package/dist/repertoire/tools-vault.js +40 -0
  309. package/dist/repertoire/tools-voice.js +145 -0
  310. package/dist/repertoire/tools.js +215 -103
  311. package/dist/repertoire/travel-api-client.js +360 -0
  312. package/dist/repertoire/user-profile.js +131 -0
  313. package/dist/repertoire/vault-setup.js +246 -0
  314. package/dist/repertoire/vault-unlock.js +594 -0
  315. package/dist/scripts/claude-code-hook.js +41 -0
  316. package/dist/scripts/claude-code-stop-hook.js +47 -0
  317. package/dist/senses/attention-queue.js +186 -0
  318. package/dist/senses/await-turn-message.js +58 -0
  319. package/dist/senses/bluebubbles/active-turns.js +216 -0
  320. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  321. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  322. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  323. package/dist/senses/bluebubbles/entry.js +77 -0
  324. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  325. package/dist/senses/bluebubbles/index.js +2737 -0
  326. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  327. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  328. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  329. package/dist/senses/bluebubbles/processed-log.js +133 -0
  330. package/dist/senses/bluebubbles/replay.js +137 -0
  331. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  332. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  333. package/dist/senses/bluebubbles-meta-guard.js +40 -0
  334. package/dist/senses/cli/bracketed-paste.js +82 -0
  335. package/dist/senses/cli/image-paste.js +287 -0
  336. package/dist/senses/cli/image-ref-navigation.js +75 -0
  337. package/dist/senses/cli/ink-app.js +156 -0
  338. package/dist/senses/cli/inline-diff.js +64 -0
  339. package/dist/senses/cli/input-keys.js +174 -0
  340. package/dist/senses/cli/kill-ring.js +86 -0
  341. package/dist/senses/cli/message-list.js +51 -0
  342. package/dist/senses/cli/ouro-tui.js +607 -0
  343. package/dist/senses/cli/spinner-imperative.js +135 -0
  344. package/dist/senses/cli/spinner.js +101 -0
  345. package/dist/senses/cli/status-line.js +60 -0
  346. package/dist/senses/cli/streaming-markdown.js +526 -0
  347. package/dist/senses/cli/tool-display.js +85 -0
  348. package/dist/senses/cli/tool-render.js +85 -0
  349. package/dist/senses/cli/tui-store.js +240 -0
  350. package/dist/senses/cli/virtual-list.js +35 -0
  351. package/dist/senses/cli-entry.js +60 -8
  352. package/dist/senses/cli-layout.js +100 -0
  353. package/dist/senses/cli.js +517 -204
  354. package/dist/senses/commands.js +66 -3
  355. package/dist/senses/habit-turn-message.js +108 -0
  356. package/dist/senses/inner-dialog-worker.js +254 -22
  357. package/dist/senses/inner-dialog.js +505 -40
  358. package/dist/senses/mail-entry.js +66 -0
  359. package/dist/senses/mail.js +379 -0
  360. package/dist/senses/pipeline.js +666 -181
  361. package/dist/senses/proactive-content-guard.js +51 -0
  362. package/dist/senses/shared-turn.js +393 -0
  363. package/dist/senses/surface-tool.js +108 -0
  364. package/dist/senses/teams-entry.js +60 -8
  365. package/dist/senses/teams.js +388 -98
  366. package/dist/senses/trust-gate.js +100 -5
  367. package/dist/senses/voice/audio-playback.js +237 -0
  368. package/dist/senses/voice/audio-routing.js +119 -0
  369. package/dist/senses/voice/elevenlabs.js +202 -0
  370. package/dist/senses/voice/floor-control.js +431 -0
  371. package/dist/senses/voice/floor-controller.js +115 -0
  372. package/dist/senses/voice/golden-path.js +116 -0
  373. package/dist/senses/voice/index.js +29 -0
  374. package/dist/senses/voice/meeting.js +113 -0
  375. package/dist/senses/voice/outbound.js +190 -0
  376. package/dist/senses/voice/phone.js +33 -0
  377. package/dist/senses/voice/playback.js +139 -0
  378. package/dist/senses/voice/realtime-eval.js +496 -0
  379. package/dist/senses/voice/realtime-trace.js +531 -0
  380. package/dist/senses/voice/transcript.js +70 -0
  381. package/dist/senses/voice/turn.js +191 -0
  382. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  383. package/dist/senses/voice/twilio-phone.js +5079 -0
  384. package/dist/senses/voice/types.js +2 -0
  385. package/dist/senses/voice/whisper.js +161 -0
  386. package/dist/senses/voice-entry.js +81 -0
  387. package/dist/senses/voice-realtime-eval-command.js +99 -0
  388. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  389. package/dist/senses/voice-twilio-entry.js +87 -0
  390. package/dist/trips/core.js +138 -0
  391. package/dist/trips/store.js +265 -0
  392. package/dist/util/frontmatter.js +53 -0
  393. package/package.json +48 -8
  394. package/skills/agent-commerce.md +106 -0
  395. package/skills/browser-navigation.md +117 -0
  396. package/skills/commerce-setup-guide.md +116 -0
  397. package/skills/commerce-setup.md +84 -0
  398. package/skills/configure-dev-tools.md +99 -0
  399. package/skills/travel-planning.md +138 -0
  400. package/dist/heart/daemon/auth-flow.js +0 -351
  401. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  402. package/dist/heart/safe-workspace.js +0 -228
  403. package/dist/heart/session-recall.js +0 -116
  404. package/dist/mind/associative-recall.js +0 -209
  405. package/dist/repertoire/tasks/board.js +0 -134
  406. package/dist/repertoire/tasks/index.js +0 -224
  407. package/dist/repertoire/tasks/lifecycle.js +0 -80
  408. package/dist/repertoire/tasks/middleware.js +0 -65
  409. package/dist/repertoire/tasks/parser.js +0 -173
  410. package/dist/repertoire/tasks/scanner.js +0 -132
  411. package/dist/repertoire/tasks/transitions.js +0 -144
  412. package/dist/senses/bluebubbles-entry.js +0 -13
  413. package/dist/senses/bluebubbles.js +0 -1177
  414. package/dist/senses/debug-activity.js +0 -148
  415. package/subagents/README.md +0 -7
  416. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  417. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  418. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  419. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  420. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  421. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  422. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  423. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  424. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  425. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  426. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  427. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  428. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  429. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  430. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  431. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  432. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ /**
3
+ * Shared OpenAI embedding provider.
4
+ *
5
+ * Both diary.ts and note-search.ts need to call the OpenAI embeddings
6
+ * API. This module provides the shared implementation so neither duplicates
7
+ * the fetch logic.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.OpenAIEmbeddingProvider = void 0;
11
+ exports.createDefaultEmbeddingProvider = createDefaultEmbeddingProvider;
12
+ const config_1 = require("../heart/config");
13
+ const runtime_1 = require("../nerves/runtime");
14
+ const DEFAULT_EMBEDDING_MODEL = "text-embedding-3-small";
15
+ class OpenAIEmbeddingProvider {
16
+ apiKey;
17
+ model;
18
+ constructor(apiKey, model = DEFAULT_EMBEDDING_MODEL) {
19
+ this.apiKey = apiKey;
20
+ this.model = model;
21
+ }
22
+ async embed(texts) {
23
+ const response = await fetch("https://api.openai.com/v1/embeddings", {
24
+ method: "POST",
25
+ headers: {
26
+ Authorization: `Bearer ${this.apiKey}`,
27
+ "Content-Type": "application/json",
28
+ },
29
+ body: JSON.stringify({
30
+ model: this.model,
31
+ input: texts,
32
+ }),
33
+ });
34
+ if (!response.ok) {
35
+ throw new Error(`embedding request failed: ${response.status} ${response.statusText}`);
36
+ }
37
+ const payload = (await response.json());
38
+ if (!payload.data || payload.data.length !== texts.length) {
39
+ throw new Error("embedding response missing expected vectors");
40
+ }
41
+ return payload.data.map((entry) => entry.embedding);
42
+ }
43
+ }
44
+ exports.OpenAIEmbeddingProvider = OpenAIEmbeddingProvider;
45
+ /**
46
+ * Create a default embedding provider from the configured API key.
47
+ * Returns null if no key is configured.
48
+ */
49
+ function createDefaultEmbeddingProvider() {
50
+ const apiKey = (0, config_1.getOpenAIEmbeddingsApiKey)().trim();
51
+ if (!apiKey)
52
+ return null;
53
+ (0, runtime_1.emitNervesEvent)({
54
+ component: "mind",
55
+ event: "mind.embedding_provider_created",
56
+ message: "default embedding provider created",
57
+ meta: { model: DEFAULT_EMBEDDING_MODEL },
58
+ });
59
+ return new OpenAIEmbeddingProvider(apiKey);
60
+ }
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fileStateCache = exports.FileStateCache = void 0;
4
+ exports.contentHash = contentHash;
5
+ const crypto_1 = require("crypto");
6
+ const fs_1 = require("fs");
7
+ const runtime_1 = require("../nerves/runtime");
8
+ /** Compute sha256 hex hash of content */
9
+ function contentHash(content) {
10
+ return (0, crypto_1.createHash)("sha256").update(content).digest("hex");
11
+ }
12
+ /**
13
+ * Session-scoped LRU cache tracking file reads.
14
+ * Stores content hashes (not full content) to limit stored content.
15
+ * Keyed by absolute file path.
16
+ *
17
+ * Also maintains a separate snapshot list for future rewind support.
18
+ * Snapshots are indexed by content hash and linked to conversation messages.
19
+ */
20
+ class FileStateCache {
21
+ entries;
22
+ maxSize;
23
+ snapshots = [];
24
+ maxSnapshots = 100;
25
+ constructor(maxSize = 50) {
26
+ this.entries = new Map();
27
+ this.maxSize = maxSize;
28
+ }
29
+ /**
30
+ * Record a file read. Computes content hash and stores metadata.
31
+ */
32
+ record(filePath, content, mtime, offset, limit, messageId) {
33
+ // If key already exists, delete it so re-insertion moves it to end (most recent)
34
+ if (this.entries.has(filePath)) {
35
+ this.entries.delete(filePath);
36
+ }
37
+ const hash = contentHash(content);
38
+ const fullRead = offset === undefined && limit === undefined;
39
+ this.entries.set(filePath, {
40
+ hash,
41
+ mtime,
42
+ offset: fullRead ? undefined : offset,
43
+ limit: fullRead ? undefined : limit,
44
+ fullRead,
45
+ recordedAt: Date.now(),
46
+ messageId,
47
+ });
48
+ (0, runtime_1.emitNervesEvent)({
49
+ component: "mind",
50
+ event: "mind.file_state.record",
51
+ message: "recorded file state",
52
+ meta: { path: filePath, hash, fullRead },
53
+ });
54
+ // Evict LRU (first entry in Map iteration order) if over capacity
55
+ if (this.entries.size > this.maxSize) {
56
+ const firstKey = this.entries.keys().next().value;
57
+ this.entries.delete(firstKey);
58
+ }
59
+ }
60
+ /**
61
+ * Get the cached state for a file path. Also promotes it in LRU order.
62
+ */
63
+ get(filePath) {
64
+ const entry = this.entries.get(filePath);
65
+ if (entry === undefined)
66
+ return undefined;
67
+ // Promote to most-recently-used by re-inserting
68
+ this.entries.delete(filePath);
69
+ this.entries.set(filePath, entry);
70
+ (0, runtime_1.emitNervesEvent)({
71
+ component: "mind",
72
+ event: "mind.file_state.get",
73
+ message: "retrieved file state",
74
+ meta: { path: filePath, hash: entry.hash },
75
+ });
76
+ return entry;
77
+ }
78
+ /**
79
+ * Check if a file has been modified since the last recorded read.
80
+ * Uses mtime as primary signal, content hash as fallback for cloud sync / touch scenarios.
81
+ * Returns { stale: false } if the path is not in cache or the file cannot be stat'd.
82
+ */
83
+ isStale(filePath) {
84
+ const entry = this.entries.get(filePath);
85
+ if (entry === undefined)
86
+ return { stale: false };
87
+ let currentMtime;
88
+ try {
89
+ currentMtime = (0, fs_1.statSync)(filePath).mtimeMs;
90
+ }
91
+ catch {
92
+ // File doesn't exist or can't be stat'd -- no basis for staleness
93
+ return { stale: false };
94
+ }
95
+ // Fast path: mtime unchanged means not stale
96
+ if (currentMtime === entry.mtime)
97
+ return { stale: false };
98
+ // mtime differs -- check content hash as fallback (handles touch / cloud sync)
99
+ try {
100
+ const currentContent = (0, fs_1.readFileSync)(filePath, "utf-8");
101
+ const currentHash = contentHash(currentContent);
102
+ if (currentHash === entry.hash)
103
+ return { stale: false };
104
+ (0, runtime_1.emitNervesEvent)({
105
+ component: "mind",
106
+ event: "mind.file_state.stale_detected",
107
+ message: "file staleness detected",
108
+ meta: { path: filePath, previousHash: entry.hash, currentHash },
109
+ });
110
+ return { stale: true, reason: `file modified since last read (mtime and content differ)` };
111
+ }
112
+ catch {
113
+ // Can't read file -- treat as not stale (file may have been deleted)
114
+ return { stale: false };
115
+ }
116
+ }
117
+ /**
118
+ * Create a pre-edit snapshot of the current cache state for a file.
119
+ * Snapshots are stored separately from the LRU cache for future rewind support.
120
+ * Returns undefined if the path is not in cache.
121
+ */
122
+ snapshot(filePath) {
123
+ const entry = this.entries.get(filePath);
124
+ if (entry === undefined)
125
+ return undefined;
126
+ const snap = {
127
+ filePath,
128
+ hash: entry.hash,
129
+ mtime: entry.mtime,
130
+ messageId: entry.messageId,
131
+ createdAt: Date.now(),
132
+ };
133
+ this.snapshots.push(snap);
134
+ (0, runtime_1.emitNervesEvent)({
135
+ component: "mind",
136
+ event: "mind.file_state.snapshot_created",
137
+ message: "created file state snapshot",
138
+ meta: { path: filePath, hash: snap.hash },
139
+ });
140
+ // Evict oldest snapshots if over capacity
141
+ if (this.snapshots.length > this.maxSnapshots) {
142
+ this.snapshots = this.snapshots.slice(this.snapshots.length - this.maxSnapshots);
143
+ }
144
+ return snap;
145
+ }
146
+ /**
147
+ * Get all snapshots in creation order.
148
+ */
149
+ getSnapshots() {
150
+ return this.snapshots;
151
+ }
152
+ /**
153
+ * Look up a snapshot by content hash. Returns the first match.
154
+ */
155
+ lookupSnapshotByHash(hash) {
156
+ return this.snapshots.find(s => s.hash === hash);
157
+ }
158
+ /**
159
+ * Clear all snapshots.
160
+ */
161
+ clearSnapshots() {
162
+ this.snapshots = [];
163
+ }
164
+ /**
165
+ * Clear all cached entries (does not clear snapshots).
166
+ */
167
+ clear() {
168
+ (0, runtime_1.emitNervesEvent)({
169
+ component: "mind",
170
+ event: "mind.file_state.clear",
171
+ message: "cleared file state cache",
172
+ meta: { entryCount: this.entries.size },
173
+ });
174
+ this.entries.clear();
175
+ }
176
+ }
177
+ exports.FileStateCache = FileStateCache;
178
+ /** Session-scoped singleton instance used by tool handlers */
179
+ exports.fileStateCache = new FileStateCache();
@@ -2,10 +2,22 @@
2
2
  // Channel capabilities -- hardcoded const map keyed by channel identifier.
3
3
  // Pure lookup, no I/O, cannot fail. Unknown channel gets minimal defaults.
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.channelToFacing = channelToFacing;
5
6
  exports.getChannelCapabilities = getChannelCapabilities;
6
7
  exports.isRemoteChannel = isRemoteChannel;
7
8
  exports.getAlwaysOnSenseNames = getAlwaysOnSenseNames;
8
9
  const runtime_1 = require("../../nerves/runtime");
10
+ const AGENT_FACING_CHANNELS = new Set(["inner", "mcp"]);
11
+ function channelToFacing(channel) {
12
+ const facing = channel && AGENT_FACING_CHANNELS.has(channel) ? "agent" : "human";
13
+ (0, runtime_1.emitNervesEvent)({
14
+ component: "channels",
15
+ event: "channel.facing_lookup",
16
+ message: "channel facing lookup",
17
+ meta: { channel: channel ?? "undefined", facing },
18
+ });
19
+ return facing;
20
+ }
9
21
  const CHANNEL_CAPABILITIES = {
10
22
  cli: {
11
23
  channel: "cli",
@@ -34,6 +46,24 @@ const CHANNEL_CAPABILITIES = {
34
46
  supportsRichCards: false,
35
47
  maxMessageLength: Infinity,
36
48
  },
49
+ mail: {
50
+ channel: "mail",
51
+ senseType: "open",
52
+ availableIntegrations: [],
53
+ supportsMarkdown: false,
54
+ supportsStreaming: false,
55
+ supportsRichCards: false,
56
+ maxMessageLength: Infinity,
57
+ },
58
+ voice: {
59
+ channel: "voice",
60
+ senseType: "local",
61
+ availableIntegrations: [],
62
+ supportsMarkdown: false,
63
+ supportsStreaming: true,
64
+ supportsRichCards: false,
65
+ maxMessageLength: Infinity,
66
+ },
37
67
  inner: {
38
68
  channel: "inner",
39
69
  senseType: "internal",
@@ -43,6 +73,15 @@ const CHANNEL_CAPABILITIES = {
43
73
  supportsRichCards: false,
44
74
  maxMessageLength: Infinity,
45
75
  },
76
+ mcp: {
77
+ channel: "mcp",
78
+ senseType: "local",
79
+ availableIntegrations: [],
80
+ supportsMarkdown: true,
81
+ supportsStreaming: false,
82
+ supportsRichCards: false,
83
+ maxMessageLength: Infinity,
84
+ },
46
85
  };
47
86
  const DEFAULT_CAPABILITIES = {
48
87
  channel: "cli",
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  // FriendResolver -- resolves external identity into a FriendRecord + channel capabilities.
3
3
  // Created per-request (per-incoming-message), per-friend.
4
- // Replaces the old ContextResolver: no authority checker, no separate memory resolution.
4
+ // Replaces the old ContextResolver: no authority checker, no separate note resolution.
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.FriendResolver = void 0;
7
7
  const crypto_1 = require("crypto");
@@ -31,6 +31,43 @@ class FriendResolver {
31
31
  }
32
32
  if (existing)
33
33
  return existing;
34
+ // Migration: local provider previously used "${username}@${hostname}" format.
35
+ // If no exact match, try finding a friend with old-format external ID.
36
+ /* v8 ignore start -- migration path: only fires when legacy hostname-format friend exists @preserve */
37
+ if (this.params.provider === "local" && !this.params.externalId.includes("@")) {
38
+ try {
39
+ const all = typeof this.store.listAll === "function" ? await this.store.listAll() : [];
40
+ /* v8 ignore start -- migration path: only fires when legacy hostname-format friend exists @preserve */
41
+ const migrationMatch = all.find((f) => f.externalIds.some((eid) => eid.provider === "local" && eid.externalId.startsWith(this.params.externalId + "@")));
42
+ if (migrationMatch) {
43
+ const now = new Date().toISOString();
44
+ migrationMatch.externalIds.push({
45
+ provider: this.params.provider,
46
+ externalId: this.params.externalId,
47
+ linkedAt: now,
48
+ });
49
+ migrationMatch.updatedAt = now;
50
+ try {
51
+ await this.store.put(migrationMatch.id, migrationMatch);
52
+ }
53
+ catch {
54
+ // best-effort persist
55
+ }
56
+ (0, runtime_1.emitNervesEvent)({
57
+ component: "friends",
58
+ event: "friends.local_id_migrated",
59
+ message: `migrated local friend identity from hostname format to username-only`,
60
+ meta: { friendId: migrationMatch.id, newExternalId: this.params.externalId },
61
+ });
62
+ return migrationMatch;
63
+ }
64
+ /* v8 ignore stop */
65
+ }
66
+ catch {
67
+ // fall through to create new
68
+ }
69
+ }
70
+ /* v8 ignore stop */
34
71
  // First encounter -- create new FriendRecord
35
72
  const now = new Date().toISOString();
36
73
  const externalId = {
@@ -50,6 +87,21 @@ class FriendResolver {
50
87
  hasAnyFriends = false;
51
88
  }
52
89
  const isFirstImprint = !hasAnyFriends;
90
+ // BlueBubbles group chats route through here as `imessage-handle` with an
91
+ // externalId of the form `group:any;+;<chatHash>`. When the harness auto-
92
+ // creates the group friend at stranger trust, we mark the record so that
93
+ // the trust gate can surface the relationship for explicit acknowledgment
94
+ // later instead of letting messages accumulate silently.
95
+ const isImessageGroup = this.params.provider === "imessage-handle" &&
96
+ typeof this.params.externalId === "string" &&
97
+ this.params.externalId.startsWith("group:");
98
+ const notes = {};
99
+ if (this.params.displayName !== "Unknown") {
100
+ notes.name = { value: this.params.displayName, savedAt: now };
101
+ }
102
+ if (isImessageGroup && !isFirstImprint) {
103
+ notes.autoCreatedGroup = { value: "true", savedAt: now };
104
+ }
53
105
  const friend = {
54
106
  id: (0, crypto_1.randomUUID)(),
55
107
  name: this.params.displayName,
@@ -59,7 +111,7 @@ class FriendResolver {
59
111
  externalIds: [externalId],
60
112
  tenantMemberships,
61
113
  toolPreferences: {},
62
- notes: this.params.displayName !== "Unknown" ? { name: { value: this.params.displayName, savedAt: now } } : {},
114
+ notes,
63
115
  totalTokens: 0,
64
116
  createdAt: now,
65
117
  updatedAt: now,
@@ -39,6 +39,7 @@ exports.FileFriendStore = void 0;
39
39
  const fs = __importStar(require("fs"));
40
40
  const fsPromises = __importStar(require("fs/promises"));
41
41
  const path = __importStar(require("path"));
42
+ const session_events_1 = require("../../heart/session-events");
42
43
  const runtime_1 = require("../../nerves/runtime");
43
44
  const DEFAULT_ROLE = "friend";
44
45
  const DEFAULT_TRUST_LEVEL = "friend";
@@ -55,10 +56,29 @@ class FileFriendStore {
55
56
  });
56
57
  }
57
58
  async get(id) {
59
+ // Direct UUID lookup
58
60
  const record = await this.readJson(path.join(this.friendsPath, `${id}.json`));
59
- if (!record)
60
- return null;
61
- return this.normalize(record);
61
+ if (record)
62
+ return this.normalize(record);
63
+ // Fallback: if id is a name (not UUID), scan for matching friend
64
+ /* v8 ignore start -- name fallback: exercised by live proactive sends @preserve */
65
+ try {
66
+ const entries = await fsPromises.readdir(this.friendsPath);
67
+ for (const entry of entries) {
68
+ if (!entry.endsWith(".json"))
69
+ continue;
70
+ const raw = await this.readJson(path.join(this.friendsPath, entry));
71
+ if (!raw)
72
+ continue;
73
+ const normalized = this.normalize(raw);
74
+ if (normalized.name?.toLowerCase() === id.toLowerCase()) {
75
+ return normalized;
76
+ }
77
+ }
78
+ }
79
+ catch { /* directory unreadable — return null */ }
80
+ /* v8 ignore stop */
81
+ return null;
62
82
  }
63
83
  async put(id, record) {
64
84
  await this.writeJson(path.join(this.friendsPath, `${id}.json`), this.normalize(record));
@@ -127,6 +147,8 @@ class FileFriendStore {
127
147
  trustLevel === "stranger"
128
148
  ? trustLevel
129
149
  : DEFAULT_TRUST_LEVEL;
150
+ const kind = raw.kind === "human" || raw.kind === "agent" ? raw.kind : "human";
151
+ const agentMeta = kind === "agent" ? this.normalizeAgentMeta(raw.agentMeta) : undefined;
130
152
  return {
131
153
  id: raw.id,
132
154
  name: raw.name,
@@ -153,6 +175,21 @@ class FileFriendStore {
153
175
  createdAt: typeof raw.createdAt === "string" ? raw.createdAt : new Date().toISOString(),
154
176
  updatedAt: typeof raw.updatedAt === "string" ? raw.updatedAt : new Date().toISOString(),
155
177
  schemaVersion: typeof raw.schemaVersion === "number" ? raw.schemaVersion : 1,
178
+ kind,
179
+ agentMeta,
180
+ };
181
+ }
182
+ normalizeAgentMeta(raw) {
183
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
184
+ return undefined;
185
+ const meta = raw;
186
+ if (typeof meta.bundleName !== "string")
187
+ return undefined;
188
+ return {
189
+ bundleName: meta.bundleName,
190
+ familiarity: typeof meta.familiarity === "number" ? meta.familiarity : 0,
191
+ sharedMissions: Array.isArray(meta.sharedMissions) ? meta.sharedMissions : [],
192
+ outcomes: Array.isArray(meta.outcomes) ? meta.outcomes : [],
156
193
  };
157
194
  }
158
195
  async readJson(filePath) {
@@ -174,7 +211,14 @@ class FileFriendStore {
174
211
  }
175
212
  }
176
213
  async writeJson(filePath, data) {
177
- await fsPromises.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
214
+ const notes = Object.fromEntries(Object.entries(data.notes).map(([key, note]) => [
215
+ key,
216
+ {
217
+ ...note,
218
+ value: (0, session_events_1.capStructuredRecordString)(note.value),
219
+ },
220
+ ]));
221
+ await fsPromises.writeFile(filePath, JSON.stringify({ ...data, notes }, null, 2), "utf-8");
178
222
  }
179
223
  async removeFile(filePath) {
180
224
  try {
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  // Context kernel type definitions.
3
- // FriendRecord (merged identity + memory), channel capabilities, and resolved context.
3
+ // FriendRecord (merged identity + notes), channel capabilities, and resolved context.
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.TRUSTED_LEVELS = void 0;
6
6
  exports.isIdentityProvider = isIdentityProvider;
7
7
  exports.isIntegration = isIntegration;
8
8
  exports.isTrustedLevel = isTrustedLevel;
9
9
  const runtime_1 = require("../../nerves/runtime");
10
- const IDENTITY_PROVIDERS = new Set(["aad", "local", "teams-conversation", "imessage-handle"]);
10
+ const IDENTITY_PROVIDERS = new Set(["aad", "local", "teams-conversation", "imessage-handle", "email-address"]);
11
11
  function isIdentityProvider(value) {
12
12
  (0, runtime_1.emitNervesEvent)({
13
13
  component: "friends",
@@ -0,0 +1,162 @@
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.indexJournalFiles = indexJournalFiles;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const session_events_1 = require("../heart/session-events");
40
+ const runtime_1 = require("../nerves/runtime");
41
+ const TEXT_EXTENSIONS = new Set([".md", ".txt"]);
42
+ const PREVIEW_CHAR_LIMIT = 500;
43
+ function readExistingIndex(indexPath) {
44
+ try {
45
+ const raw = fs.readFileSync(indexPath, "utf8");
46
+ const parsed = JSON.parse(raw);
47
+ if (!Array.isArray(parsed))
48
+ return [];
49
+ return parsed;
50
+ }
51
+ catch {
52
+ return [];
53
+ }
54
+ }
55
+ function extractPreview(content) {
56
+ const trimmed = content.trim();
57
+ if (!trimmed)
58
+ return "";
59
+ return trimmed.split("\n")[0].replace(/^#+\s*/, "").trim();
60
+ }
61
+ async function indexJournalFiles(journalDir, indexPath, embedProvider) {
62
+ // Read existing index
63
+ const existingIndex = readExistingIndex(indexPath);
64
+ const indexMap = new Map();
65
+ for (const entry of existingIndex) {
66
+ indexMap.set(entry.filename, entry);
67
+ }
68
+ // Scan journal dir for text files
69
+ let dirEntries;
70
+ try {
71
+ dirEntries = fs.readdirSync(journalDir, { withFileTypes: true });
72
+ }
73
+ catch {
74
+ (0, runtime_1.emitNervesEvent)({
75
+ component: "mind",
76
+ event: "mind.journal_index_scan",
77
+ message: "journal dir not found or unreadable",
78
+ meta: { journalDir },
79
+ });
80
+ return 0;
81
+ }
82
+ const textFiles = dirEntries.filter((entry) => {
83
+ if (!entry.isFile())
84
+ return false;
85
+ if (entry.name.startsWith("."))
86
+ return false;
87
+ const ext = path.extname(entry.name).toLowerCase();
88
+ return TEXT_EXTENSIONS.has(ext);
89
+ });
90
+ if (textFiles.length === 0) {
91
+ (0, runtime_1.emitNervesEvent)({
92
+ component: "mind",
93
+ event: "mind.journal_index_scan",
94
+ message: "no text files found in journal",
95
+ meta: { journalDir },
96
+ });
97
+ return 0;
98
+ }
99
+ let newlyIndexed = 0;
100
+ for (const file of textFiles) {
101
+ const filePath = path.join(journalDir, file.name);
102
+ let stat;
103
+ try {
104
+ stat = fs.statSync(filePath);
105
+ }
106
+ catch {
107
+ /* v8 ignore next -- filesystem race: file deleted between readdir and stat @preserve */
108
+ continue;
109
+ }
110
+ // Check if already indexed with same mtime
111
+ const existing = indexMap.get(file.name);
112
+ if (existing && existing.mtime === stat.mtimeMs) {
113
+ continue;
114
+ }
115
+ // Read content for embedding
116
+ let content;
117
+ try {
118
+ content = fs.readFileSync(filePath, "utf8");
119
+ }
120
+ catch {
121
+ /* v8 ignore next -- filesystem race: file deleted between stat and read @preserve */
122
+ continue;
123
+ }
124
+ const preview = (0, session_events_1.capStructuredRecordString)(extractPreview(content));
125
+ const embedText = content.slice(0, PREVIEW_CHAR_LIMIT);
126
+ // Generate embedding
127
+ let embedding;
128
+ try {
129
+ const vectors = await embedProvider.embed([embedText]);
130
+ embedding = vectors[0] ?? [];
131
+ }
132
+ catch {
133
+ (0, runtime_1.emitNervesEvent)({
134
+ level: "warn",
135
+ component: "mind",
136
+ event: "mind.journal_embedding_error",
137
+ message: "embedding failed for journal file",
138
+ meta: { filename: file.name },
139
+ });
140
+ embedding = [];
141
+ }
142
+ indexMap.set(file.name, {
143
+ filename: file.name,
144
+ embedding,
145
+ mtime: stat.mtimeMs,
146
+ preview,
147
+ });
148
+ newlyIndexed++;
149
+ }
150
+ // Write updated index back
151
+ if (newlyIndexed > 0) {
152
+ const updatedIndex = Array.from(indexMap.values());
153
+ fs.writeFileSync(indexPath, JSON.stringify(updatedIndex, null, 2), "utf8");
154
+ }
155
+ (0, runtime_1.emitNervesEvent)({
156
+ component: "mind",
157
+ event: "mind.journal_index_complete",
158
+ message: "journal indexing complete",
159
+ meta: { journalDir, newlyIndexed, total: indexMap.size },
160
+ });
161
+ return newlyIndexed;
162
+ }