@ouro.bot/cli 0.1.0-alpha.81 → 0.1.0-alpha.811

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 (623) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +154 -23
  3. package/RepairGuide.ouro/agent.json +5 -0
  4. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  5. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  6. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  7. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  8. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  9. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  13. package/assets/bluebubbles-host +264 -0
  14. package/changelog.json +5189 -16
  15. package/deploy/unraid/Dockerfile +48 -0
  16. package/deploy/unraid/README.txt +3032 -0
  17. package/deploy/unraid/audit-container-spec.sh +4 -0
  18. package/deploy/unraid/container-runtime.json +1 -0
  19. package/deploy/unraid/docker-man-template-transaction.mjs +526 -0
  20. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  21. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  22. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  23. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  24. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  25. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  26. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  27. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  28. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  29. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  30. package/deploy/unraid/sanctuary-deployment-target.mjs +709 -0
  31. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  32. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2031 -0
  33. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  34. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  35. package/deploy/unraid/sanctuary.ouro/agent.json +24 -0
  36. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  37. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  38. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  39. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  40. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  41. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  42. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +11 -0
  43. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +25 -0
  44. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +11 -0
  45. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  46. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +23 -0
  47. package/deploy/unraid/sanctuary.xml +27 -0
  48. package/dist/a2a/card.js +57 -0
  49. package/dist/a2a/client.js +180 -0
  50. package/dist/a2a/config.js +50 -0
  51. package/dist/a2a/delegation-stores.js +56 -0
  52. package/dist/a2a/did-resolution.js +93 -0
  53. package/dist/a2a/identity.js +170 -0
  54. package/dist/a2a/inbound-share.js +107 -0
  55. package/dist/a2a/mission-result-wire.js +196 -0
  56. package/dist/a2a/onboarding.js +115 -0
  57. package/dist/a2a/pin-store.js +132 -0
  58. package/dist/a2a/seen-ledger.js +120 -0
  59. package/dist/a2a/server.js +604 -0
  60. package/dist/a2a/task-store.js +69 -0
  61. package/dist/a2a/transport.js +45 -0
  62. package/dist/a2a/types.js +3 -0
  63. package/dist/arc/attention-types.js +8 -0
  64. package/dist/arc/cares.js +360 -0
  65. package/dist/arc/episodes.js +118 -0
  66. package/dist/arc/evolution.js +490 -0
  67. package/dist/arc/flight-recorder.js +1034 -0
  68. package/dist/arc/intentions.js +134 -0
  69. package/dist/arc/json-store.js +117 -0
  70. package/dist/arc/obligations.js +386 -0
  71. package/dist/arc/packets.js +336 -0
  72. package/dist/arc/presence.js +185 -0
  73. package/dist/arc/task-lifecycle.js +57 -0
  74. package/dist/commerce/store.js +755 -0
  75. package/dist/commerce/types.js +3 -0
  76. package/dist/heart/active-work.js +820 -29
  77. package/dist/heart/agent-entry.js +252 -3
  78. package/dist/heart/approval-files.js +113 -0
  79. package/dist/heart/approval-store.js +950 -0
  80. package/dist/heart/attachments/image-normalize.js +194 -0
  81. package/dist/heart/attachments/materialize.js +97 -0
  82. package/dist/heart/attachments/originals.js +88 -0
  83. package/dist/heart/attachments/render.js +29 -0
  84. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  85. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  86. package/dist/heart/attachments/sources/index.js +18 -0
  87. package/dist/heart/attachments/sources/telegram.js +71 -0
  88. package/dist/heart/attachments/store.js +132 -0
  89. package/dist/heart/attachments/types.js +93 -0
  90. package/dist/heart/auth/auth-flow.js +495 -0
  91. package/dist/heart/autonomy-budget.js +478 -0
  92. package/dist/heart/awaiting/await-alert.js +148 -0
  93. package/dist/heart/awaiting/await-expiry.js +143 -0
  94. package/dist/heart/awaiting/await-loader.js +91 -0
  95. package/dist/heart/awaiting/await-parser.js +149 -0
  96. package/dist/heart/awaiting/await-runtime-state.js +100 -0
  97. package/dist/heart/awaiting/await-scheduler.js +382 -0
  98. package/dist/heart/background-operations.js +281 -0
  99. package/dist/heart/bridges/manager.js +137 -17
  100. package/dist/heart/bridges/store.js +14 -2
  101. package/dist/heart/bundle-state.js +168 -0
  102. package/dist/heart/commitments.js +64 -18
  103. package/dist/heart/config-registry.js +331 -0
  104. package/dist/heart/config.js +174 -131
  105. package/dist/heart/context-loss-gauntlet.js +387 -0
  106. package/dist/heart/context-loss-sentinel.js +1157 -0
  107. package/dist/heart/core.js +2164 -581
  108. package/dist/heart/cross-chat-delivery.js +9 -22
  109. package/dist/heart/daemon/agent-config-check.js +451 -0
  110. package/dist/heart/daemon/agent-discovery.js +185 -3
  111. package/dist/heart/daemon/agent-service.js +542 -0
  112. package/dist/heart/daemon/agentic-repair.js +547 -0
  113. package/dist/heart/daemon/await-private-wake.js +59 -0
  114. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  115. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  116. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  117. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  118. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  119. package/dist/heart/daemon/cadence.js +180 -0
  120. package/dist/heart/daemon/cli-defaults.js +854 -0
  121. package/dist/heart/daemon/cli-desk.js +322 -0
  122. package/dist/heart/daemon/cli-exec.js +8822 -0
  123. package/dist/heart/daemon/cli-help.js +716 -0
  124. package/dist/heart/daemon/cli-parse.js +2771 -0
  125. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  126. package/dist/heart/daemon/cli-render.js +777 -0
  127. package/dist/heart/daemon/cli-types.js +8 -0
  128. package/dist/heart/daemon/connect-bay.js +323 -0
  129. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  130. package/dist/heart/daemon/container-healthcheck.js +112 -0
  131. package/dist/heart/daemon/container-runtime.js +97 -0
  132. package/dist/heart/daemon/container-spec-auditor-main.js +170 -0
  133. package/dist/heart/daemon/container-spec-auditor.js +236 -0
  134. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  135. package/dist/heart/daemon/daemon-cli.js +29 -2317
  136. package/dist/heart/daemon/daemon-entry.js +921 -11
  137. package/dist/heart/daemon/daemon-health.js +186 -0
  138. package/dist/heart/daemon/daemon-rollup.js +57 -0
  139. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  140. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  141. package/dist/heart/daemon/daemon.js +2084 -105
  142. package/dist/heart/daemon/dns-workflow.js +394 -0
  143. package/dist/heart/daemon/doctor-types.js +8 -0
  144. package/dist/heart/daemon/doctor.js +1755 -0
  145. package/dist/heart/daemon/freshness.js +345 -0
  146. package/dist/heart/daemon/habit-private-wake.js +61 -0
  147. package/dist/heart/daemon/health-monitor.js +142 -11
  148. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  149. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  150. package/dist/heart/daemon/http-health-probe.js +80 -0
  151. package/dist/heart/daemon/human-command-screens.js +234 -0
  152. package/dist/heart/daemon/human-readiness.js +114 -0
  153. package/dist/heart/daemon/inner-status.js +78 -0
  154. package/dist/heart/daemon/interactive-repair.js +394 -0
  155. package/dist/heart/daemon/launchd.js +37 -8
  156. package/dist/heart/daemon/log-tailer.js +79 -10
  157. package/dist/heart/daemon/logs-prune.js +132 -0
  158. package/dist/heart/daemon/mcp-canary.js +524 -0
  159. package/dist/heart/daemon/message-router.js +65 -5
  160. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  161. package/dist/heart/daemon/os-cron-deps.js +135 -0
  162. package/dist/heart/daemon/os-cron.js +22 -14
  163. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  164. package/dist/heart/daemon/ouro-entry.js +3 -1
  165. package/dist/heart/daemon/plugin-cli.js +432 -0
  166. package/dist/heart/daemon/process-manager.js +733 -61
  167. package/dist/heart/daemon/provider-discovery.js +137 -0
  168. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  169. package/dist/heart/daemon/prunable-bundle.js +144 -0
  170. package/dist/heart/daemon/pulse.js +511 -0
  171. package/dist/heart/daemon/readiness-repair.js +365 -0
  172. package/dist/heart/daemon/run-hooks.js +2 -0
  173. package/dist/heart/daemon/runtime-logging.js +47 -14
  174. package/dist/heart/daemon/runtime-metadata.js +2 -30
  175. package/dist/heart/daemon/runtime-mode.js +13 -2
  176. package/dist/heart/daemon/safe-mode.js +161 -0
  177. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2647 -0
  178. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1904 -0
  179. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  180. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +956 -0
  181. package/dist/heart/daemon/sanctuary-bundle-migration.js +728 -0
  182. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  183. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  184. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  185. package/dist/heart/daemon/sense-manager.js +689 -48
  186. package/dist/heart/daemon/session-id-resolver.js +131 -0
  187. package/dist/heart/daemon/skill-management-installer.js +1 -1
  188. package/dist/heart/daemon/socket-client.js +180 -12
  189. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  190. package/dist/heart/daemon/startup-tui.js +339 -0
  191. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  192. package/dist/heart/daemon/task-scheduler.js +117 -39
  193. package/dist/heart/daemon/terminal-ui.js +499 -0
  194. package/dist/heart/daemon/thoughts.js +138 -54
  195. package/dist/heart/daemon/up-progress.js +366 -0
  196. package/dist/heart/daemon/vault-items.js +56 -0
  197. package/dist/heart/delegation.js +1 -4
  198. package/dist/heart/external-events/router.js +1414 -0
  199. package/dist/heart/frontend-approval-runtime.js +506 -0
  200. package/dist/heart/frontend-journal.js +215 -0
  201. package/dist/heart/frontend-session-service.js +237 -0
  202. package/dist/heart/frontend-socket-client.js +154 -0
  203. package/dist/heart/frontend-socket.js +400 -0
  204. package/dist/heart/habits/habit-cancel.js +810 -0
  205. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  206. package/dist/heart/habits/habit-migration.js +194 -0
  207. package/dist/heart/habits/habit-parser.js +278 -0
  208. package/dist/heart/habits/habit-runtime-state.js +93 -0
  209. package/dist/heart/habits/habit-scheduler.js +653 -0
  210. package/dist/heart/habits/habit-session-summary.js +318 -0
  211. package/dist/heart/habits/habit-session.js +636 -0
  212. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  213. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  214. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  215. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  216. package/dist/heart/identity.js +196 -59
  217. package/dist/heart/kept-notes.js +289 -0
  218. package/dist/heart/kicks.js +1 -1
  219. package/dist/heart/machine-identity.js +161 -0
  220. package/dist/heart/mail-import-discovery.js +356 -0
  221. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  222. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  223. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  224. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  225. package/dist/heart/mailbox/mailbox-http-transport.js +129 -0
  226. package/dist/heart/mailbox/mailbox-http.js +99 -0
  227. package/dist/heart/mailbox/mailbox-read.js +39 -0
  228. package/dist/heart/mailbox/mailbox-types.js +27 -0
  229. package/dist/heart/mailbox/mailbox-view.js +197 -0
  230. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  231. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  232. package/dist/heart/mailbox/readers/mail.js +375 -0
  233. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  234. package/dist/heart/mailbox/readers/sessions.js +231 -0
  235. package/dist/heart/mailbox/readers/shared.js +111 -0
  236. package/dist/heart/mcp/mcp-server.js +696 -0
  237. package/dist/heart/migrate-config.js +100 -0
  238. package/dist/heart/model-capabilities.js +11 -0
  239. package/dist/heart/orientation-frame.js +345 -0
  240. package/dist/heart/platform.js +81 -0
  241. package/dist/heart/primitives.js +1 -1
  242. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  243. package/dist/heart/private-runtime/index.js +18 -0
  244. package/dist/heart/private-runtime/ledger.js +221 -0
  245. package/dist/heart/private-runtime/policy.js +252 -0
  246. package/dist/heart/private-runtime/types.js +2 -0
  247. package/dist/heart/progress-story.js +1 -1
  248. package/dist/heart/provider-attempt.js +137 -0
  249. package/dist/heart/provider-binding-resolver.js +273 -0
  250. package/dist/heart/provider-credentials.js +449 -0
  251. package/dist/heart/provider-failover.js +311 -0
  252. package/dist/heart/provider-models.js +96 -0
  253. package/dist/heart/provider-ping.js +265 -0
  254. package/dist/heart/provider-readiness-cache.js +119 -0
  255. package/dist/heart/provider-visibility.js +188 -0
  256. package/dist/heart/providers/anthropic-token.js +131 -0
  257. package/dist/heart/providers/anthropic.js +173 -60
  258. package/dist/heart/providers/azure.js +23 -11
  259. package/dist/heart/providers/error-classification.js +127 -0
  260. package/dist/heart/providers/github-copilot.js +34 -38
  261. package/dist/heart/providers/minimax-vlm.js +189 -0
  262. package/dist/heart/providers/minimax.js +26 -8
  263. package/dist/heart/providers/openai-codex-token.js +349 -0
  264. package/dist/heart/providers/openai-codex.js +55 -40
  265. package/dist/heart/providers/openai-compatible.js +177 -0
  266. package/dist/heart/run-ledger.js +247 -0
  267. package/dist/heart/runtime-capability-check.js +170 -0
  268. package/dist/heart/runtime-credentials.js +607 -0
  269. package/dist/heart/runtime-cwd.js +87 -0
  270. package/dist/heart/sense-truth.js +22 -4
  271. package/dist/heart/session-activity.js +92 -24
  272. package/dist/heart/session-events.js +1440 -0
  273. package/dist/heart/session-playback-cli-main.js +5 -0
  274. package/dist/heart/session-playback-cli.js +36 -0
  275. package/dist/heart/session-playback.js +231 -0
  276. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  277. package/dist/heart/session-redaction-repair.js +543 -0
  278. package/dist/heart/session-stats-cli-main.js +5 -0
  279. package/dist/heart/session-stats.js +182 -0
  280. package/dist/heart/session-transcript.js +133 -0
  281. package/dist/heart/start-of-turn-packet.js +372 -0
  282. package/dist/heart/steward-policy.js +302 -0
  283. package/dist/heart/streaming.js +604 -207
  284. package/dist/heart/structured-output.js +196 -0
  285. package/dist/heart/sync-classification.js +176 -0
  286. package/dist/heart/sync.js +449 -0
  287. package/dist/heart/target-resolution.js +11 -7
  288. package/dist/heart/tempo.js +93 -0
  289. package/dist/heart/temporal-view.js +41 -0
  290. package/dist/heart/timeouts.js +101 -0
  291. package/dist/heart/tool-activity-callbacks.js +59 -0
  292. package/dist/heart/tool-approval.js +375 -0
  293. package/dist/heart/tool-description.js +155 -0
  294. package/dist/heart/tool-friction.js +55 -0
  295. package/dist/heart/tool-loop.js +200 -0
  296. package/dist/heart/turn-context.js +482 -0
  297. package/dist/heart/turn-execution-lease.js +30 -0
  298. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  299. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  300. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  301. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  302. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  303. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  304. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  305. package/dist/heart/versioning/update-hooks.js +154 -0
  306. package/dist/heart/versioning/version-intent.js +114 -0
  307. package/dist/heart/work-card.js +380 -0
  308. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  309. package/dist/mailbox-ui/assets/index-J8zDwHmE.js +1 -0
  310. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  311. package/dist/mailbox-ui/index.html +16 -0
  312. package/dist/mailroom/attention.js +167 -0
  313. package/dist/mailroom/autonomy.js +209 -0
  314. package/dist/mailroom/blob-store.js +889 -0
  315. package/dist/mailroom/body-cache.js +61 -0
  316. package/dist/mailroom/cache-sync-cli.js +58 -0
  317. package/dist/mailroom/core.js +803 -0
  318. package/dist/mailroom/entry.js +160 -0
  319. package/dist/mailroom/file-store.js +568 -0
  320. package/dist/mailroom/hosted-cache-sync.js +384 -0
  321. package/dist/mailroom/mbox-import.js +393 -0
  322. package/dist/mailroom/migration.js +164 -0
  323. package/dist/mailroom/outbound.js +380 -0
  324. package/dist/mailroom/policy.js +263 -0
  325. package/dist/mailroom/reader.js +292 -0
  326. package/dist/mailroom/search-cache.js +513 -0
  327. package/dist/mailroom/search-relevance.js +319 -0
  328. package/dist/mailroom/smtp-ingress.js +176 -0
  329. package/dist/mailroom/source-state.js +176 -0
  330. package/dist/mailroom/thread.js +109 -0
  331. package/dist/mailroom/travel-extract.js +89 -0
  332. package/dist/mind/bundle-manifest.js +24 -2
  333. package/dist/mind/context.js +279 -111
  334. package/dist/mind/desk-section.js +362 -0
  335. package/dist/mind/diary-integrity.js +60 -0
  336. package/dist/mind/{memory.js → diary.js} +68 -77
  337. package/dist/mind/embedding-provider.js +60 -0
  338. package/dist/mind/file-state.js +179 -0
  339. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  340. package/dist/mind/obligation-steering.js +227 -0
  341. package/dist/mind/pending.js +36 -10
  342. package/dist/mind/prompt-budget.js +479 -0
  343. package/dist/mind/prompt-refresh.js +3 -2
  344. package/dist/mind/prompt.js +1059 -187
  345. package/dist/mind/provenance-trust.js +26 -0
  346. package/dist/mind/record-paths.js +312 -0
  347. package/dist/mind/scrutiny.js +173 -0
  348. package/dist/mind/session-transaction.js +564 -0
  349. package/dist/nerves/cli-logging.js +7 -1
  350. package/dist/nerves/coverage/audit-rules.js +15 -6
  351. package/dist/nerves/coverage/audit.js +28 -2
  352. package/dist/nerves/coverage/cli.js +1 -1
  353. package/dist/nerves/coverage/contract.js +5 -5
  354. package/dist/nerves/coverage/file-completeness.js +139 -5
  355. package/dist/nerves/coverage/run-artifacts.js +55 -35
  356. package/dist/nerves/coverage/source-scanner.js +4 -4
  357. package/dist/nerves/event-buffer.js +111 -0
  358. package/dist/nerves/index.js +293 -9
  359. package/dist/nerves/observation.js +20 -0
  360. package/dist/nerves/redact.js +79 -0
  361. package/dist/nerves/review/cli-main.js +5 -0
  362. package/dist/nerves/review/cli.js +156 -0
  363. package/dist/nerves/review/core.js +159 -0
  364. package/dist/nerves/runtime.js +17 -1
  365. package/dist/repertoire/ado-client.js +15 -56
  366. package/dist/repertoire/ado-semantic.js +16 -10
  367. package/dist/repertoire/api-client.js +97 -0
  368. package/dist/repertoire/bitwarden-store.js +1045 -0
  369. package/dist/repertoire/bundle-templates.js +71 -0
  370. package/dist/repertoire/bw-installer.js +180 -0
  371. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  372. package/dist/repertoire/coding/context-pack.js +331 -0
  373. package/dist/repertoire/coding/feedback.js +218 -30
  374. package/dist/repertoire/coding/index.js +15 -3
  375. package/dist/repertoire/coding/manager.js +166 -10
  376. package/dist/repertoire/coding/spawner.js +58 -11
  377. package/dist/repertoire/coding/tools.js +242 -14
  378. package/dist/repertoire/coding/workbench-client.js +272 -0
  379. package/dist/repertoire/coding/workbench-manager.js +346 -0
  380. package/dist/repertoire/commerce-errors.js +109 -0
  381. package/dist/repertoire/commerce-self-test.js +156 -0
  382. package/dist/repertoire/credential-access.js +178 -0
  383. package/dist/repertoire/desk/classifier.js +362 -0
  384. package/dist/repertoire/duffel-client.js +185 -0
  385. package/dist/repertoire/github-client.js +14 -55
  386. package/dist/repertoire/graph-client.js +11 -52
  387. package/dist/repertoire/guardrails.js +811 -18
  388. package/dist/repertoire/mcp-client.js +44 -3
  389. package/dist/repertoire/mcp-manager.js +427 -139
  390. package/dist/repertoire/mcp-tools.js +124 -0
  391. package/dist/repertoire/plugin-mcp.js +175 -0
  392. package/dist/repertoire/plugins.js +253 -0
  393. package/dist/repertoire/relationship-authorization.js +194 -0
  394. package/dist/repertoire/shell-sessions.js +134 -0
  395. package/dist/repertoire/skills.js +48 -4
  396. package/dist/repertoire/stripe-client.js +131 -0
  397. package/dist/repertoire/tool-arguments.js +170 -0
  398. package/dist/repertoire/tool-results.js +29 -0
  399. package/dist/repertoire/tools-a2a.js +699 -0
  400. package/dist/repertoire/tools-attachments.js +322 -0
  401. package/dist/repertoire/tools-awaiting.js +575 -0
  402. package/dist/repertoire/tools-base.js +82 -1139
  403. package/dist/repertoire/tools-bluebubbles.js +2 -0
  404. package/dist/repertoire/tools-bridge.js +144 -0
  405. package/dist/repertoire/tools-bundle.js +993 -0
  406. package/dist/repertoire/tools-commerce.js +253 -0
  407. package/dist/repertoire/tools-config.js +186 -0
  408. package/dist/repertoire/tools-continuity.js +575 -0
  409. package/dist/repertoire/tools-credential.js +383 -0
  410. package/dist/repertoire/tools-evolution.js +527 -0
  411. package/dist/repertoire/tools-files.js +344 -0
  412. package/dist/repertoire/tools-flight.js +290 -0
  413. package/dist/repertoire/tools-flow.js +119 -0
  414. package/dist/repertoire/tools-github.js +3 -8
  415. package/dist/repertoire/tools-habits.js +103 -0
  416. package/dist/repertoire/tools-mail.js +1828 -0
  417. package/dist/repertoire/tools-notes.js +485 -0
  418. package/dist/repertoire/tools-obligations.js +182 -0
  419. package/dist/repertoire/tools-orientation.js +31 -0
  420. package/dist/repertoire/tools-record.js +482 -0
  421. package/dist/repertoire/tools-rsvp.js +139 -0
  422. package/dist/repertoire/tools-runtime.js +150 -0
  423. package/dist/repertoire/tools-session.js +1133 -0
  424. package/dist/repertoire/tools-shell.js +149 -0
  425. package/dist/repertoire/tools-steward-policy.js +95 -0
  426. package/dist/repertoire/tools-stripe.js +224 -0
  427. package/dist/repertoire/tools-surface.js +369 -0
  428. package/dist/repertoire/tools-teams.js +12 -39
  429. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  430. package/dist/repertoire/tools-travel.js +125 -0
  431. package/dist/repertoire/tools-trip.js +982 -0
  432. package/dist/repertoire/tools-unraid.js +484 -0
  433. package/dist/repertoire/tools-user-profile.js +146 -0
  434. package/dist/repertoire/tools-vault.js +40 -0
  435. package/dist/repertoire/tools-voice.js +145 -0
  436. package/dist/repertoire/tools.js +470 -147
  437. package/dist/repertoire/travel-api-client.js +360 -0
  438. package/dist/repertoire/unraid-client.js +155 -0
  439. package/dist/repertoire/unraid-restart.js +212 -0
  440. package/dist/repertoire/user-profile.js +131 -0
  441. package/dist/repertoire/vault-setup.js +246 -0
  442. package/dist/repertoire/vault-unlock.js +628 -0
  443. package/dist/rsvp/aisleplanner-client.js +354 -0
  444. package/dist/rsvp/cli.js +926 -0
  445. package/dist/rsvp/config.js +327 -0
  446. package/dist/rsvp/cutover.js +433 -0
  447. package/dist/rsvp/diagnostics.js +232 -0
  448. package/dist/rsvp/diff-renderer.js +176 -0
  449. package/dist/rsvp/habit-policy.js +110 -0
  450. package/dist/rsvp/habit-stage.js +123 -0
  451. package/dist/rsvp/incident-bundle.js +97 -0
  452. package/dist/rsvp/migration.js +204 -0
  453. package/dist/rsvp/native-habit-runner.js +630 -0
  454. package/dist/rsvp/outbound-state.js +628 -0
  455. package/dist/rsvp/query.js +118 -0
  456. package/dist/rsvp/replay.js +233 -0
  457. package/dist/rsvp/snapshot.js +232 -0
  458. package/dist/rsvp/spend-ledger.js +175 -0
  459. package/dist/scripts/claude-code-hook.js +41 -0
  460. package/dist/scripts/claude-code-stop-hook.js +47 -0
  461. package/dist/senses/a2a-entry.js +115 -0
  462. package/dist/senses/acp-server.js +386 -0
  463. package/dist/senses/attention-queue.js +186 -0
  464. package/dist/senses/await-turn-message.js +58 -0
  465. package/dist/senses/bluebubbles/active-turns.js +216 -0
  466. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  467. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  468. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +355 -40
  469. package/dist/senses/bluebubbles/context-packet.js +207 -0
  470. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  471. package/dist/senses/bluebubbles/entry.js +90 -0
  472. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  473. package/dist/senses/bluebubbles/index.js +3841 -0
  474. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  475. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  476. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  477. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  478. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  479. package/dist/senses/bluebubbles/processed-log.js +133 -0
  480. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  481. package/dist/senses/bluebubbles/replay.js +284 -0
  482. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  483. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  484. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  485. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  486. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  487. package/dist/senses/cli/bracketed-paste.js +82 -0
  488. package/dist/senses/cli/image-paste.js +287 -0
  489. package/dist/senses/cli/image-ref-navigation.js +75 -0
  490. package/dist/senses/cli/ink-app.js +156 -0
  491. package/dist/senses/cli/inline-diff.js +64 -0
  492. package/dist/senses/cli/input-keys.js +174 -0
  493. package/dist/senses/cli/kill-ring.js +86 -0
  494. package/dist/senses/cli/message-list.js +51 -0
  495. package/dist/senses/cli/ouro-tui.js +607 -0
  496. package/dist/senses/cli/spinner-imperative.js +135 -0
  497. package/dist/senses/cli/spinner.js +101 -0
  498. package/dist/senses/cli/status-line.js +60 -0
  499. package/dist/senses/cli/streaming-markdown.js +526 -0
  500. package/dist/senses/cli/tool-display.js +85 -0
  501. package/dist/senses/cli/tool-render.js +85 -0
  502. package/dist/senses/cli/tui-store.js +241 -0
  503. package/dist/senses/cli/virtual-list.js +35 -0
  504. package/dist/senses/cli-entry.js +60 -8
  505. package/dist/senses/cli.js +604 -320
  506. package/dist/senses/commands.js +66 -3
  507. package/dist/senses/context-packet-ledger.js +371 -0
  508. package/dist/senses/context-packets.js +154 -0
  509. package/dist/senses/habit-lifecycle-guard.js +24 -0
  510. package/dist/senses/habit-turn-message.js +160 -0
  511. package/dist/senses/ingress-evidence.js +2 -0
  512. package/dist/senses/mail-entry.js +66 -0
  513. package/dist/senses/mail.js +524 -0
  514. package/dist/senses/pipeline.js +1115 -204
  515. package/dist/senses/private-runtime-worker.js +859 -0
  516. package/dist/senses/private-runtime.js +1502 -0
  517. package/dist/senses/proactive-content-guard.js +51 -0
  518. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  519. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  520. package/dist/senses/sanctuary-grounding.js +118 -0
  521. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  522. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  523. package/dist/senses/sanctuary-health-runner.js +101 -0
  524. package/dist/senses/sanctuary-health.js +408 -0
  525. package/dist/senses/sanctuary-install-state-contract.js +126 -0
  526. package/dist/senses/sanctuary-interactive-control.js +306 -0
  527. package/dist/senses/sanctuary-media-catalog-contract.js +235 -0
  528. package/dist/senses/sanctuary-media-optimization.js +514 -0
  529. package/dist/senses/sanctuary-runtime.js +338 -0
  530. package/dist/senses/sanctuary-sab.js +85 -0
  531. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  532. package/dist/senses/shared-turn.js +759 -0
  533. package/dist/senses/surface-tool.js +109 -0
  534. package/dist/senses/teams-entry.js +60 -8
  535. package/dist/senses/teams.js +519 -218
  536. package/dist/senses/telegram-admission.js +711 -0
  537. package/dist/senses/telegram-approval-runtime.js +675 -0
  538. package/dist/senses/telegram-attachments.js +182 -0
  539. package/dist/senses/telegram-audit-ledger.js +220 -0
  540. package/dist/senses/telegram-client.js +1694 -0
  541. package/dist/senses/telegram-effect-adapter.js +859 -0
  542. package/dist/senses/telegram-entry.js +83 -0
  543. package/dist/senses/telegram.js +2084 -0
  544. package/dist/senses/trust-gate.js +104 -9
  545. package/dist/senses/voice/audio-playback.js +237 -0
  546. package/dist/senses/voice/audio-routing.js +119 -0
  547. package/dist/senses/voice/elevenlabs.js +202 -0
  548. package/dist/senses/voice/floor-control.js +431 -0
  549. package/dist/senses/voice/floor-controller.js +115 -0
  550. package/dist/senses/voice/golden-path.js +116 -0
  551. package/dist/senses/voice/index.js +29 -0
  552. package/dist/senses/voice/meeting.js +113 -0
  553. package/dist/senses/voice/outbound.js +190 -0
  554. package/dist/senses/voice/phone.js +33 -0
  555. package/dist/senses/voice/playback.js +139 -0
  556. package/dist/senses/voice/realtime-eval.js +496 -0
  557. package/dist/senses/voice/realtime-trace.js +531 -0
  558. package/dist/senses/voice/transcript.js +70 -0
  559. package/dist/senses/voice/turn.js +191 -0
  560. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  561. package/dist/senses/voice/twilio-phone.js +5031 -0
  562. package/dist/senses/voice/types.js +2 -0
  563. package/dist/senses/voice/whisper.js +161 -0
  564. package/dist/senses/voice-entry.js +81 -0
  565. package/dist/senses/voice-realtime-eval-command.js +99 -0
  566. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  567. package/dist/senses/voice-twilio-entry.js +87 -0
  568. package/dist/trips/core.js +138 -0
  569. package/dist/trips/store.js +265 -0
  570. package/dist/util/frontmatter.js +69 -0
  571. package/npm-shrinkwrap.json +8138 -0
  572. package/package.json +72 -13
  573. package/skills/agent-commerce.md +113 -0
  574. package/skills/browser-navigation.md +117 -0
  575. package/skills/commerce-setup-guide.md +116 -0
  576. package/skills/commerce-setup.md +84 -0
  577. package/skills/configure-dev-tools.md +99 -0
  578. package/skills/travel-planning.md +138 -0
  579. package/dist/heart/daemon/auth-flow.js +0 -430
  580. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  581. package/dist/heart/daemon/ouro-version-manager.js +0 -164
  582. package/dist/heart/daemon/update-hooks.js +0 -138
  583. package/dist/heart/obligations.js +0 -141
  584. package/dist/heart/safe-workspace.js +0 -228
  585. package/dist/heart/session-recall.js +0 -116
  586. package/dist/mind/friends/channel.js +0 -84
  587. package/dist/mind/friends/group-context.js +0 -144
  588. package/dist/mind/friends/resolver.js +0 -84
  589. package/dist/mind/friends/store-file.js +0 -190
  590. package/dist/mind/friends/store.js +0 -4
  591. package/dist/mind/friends/tokens.js +0 -26
  592. package/dist/mind/friends/trust-explanation.js +0 -74
  593. package/dist/mind/friends/types.js +0 -29
  594. package/dist/repertoire/tasks/board.js +0 -134
  595. package/dist/repertoire/tasks/index.js +0 -224
  596. package/dist/repertoire/tasks/lifecycle.js +0 -80
  597. package/dist/repertoire/tasks/middleware.js +0 -65
  598. package/dist/repertoire/tasks/parser.js +0 -173
  599. package/dist/repertoire/tasks/scanner.js +0 -132
  600. package/dist/repertoire/tasks/transitions.js +0 -144
  601. package/dist/senses/bluebubbles-entry.js +0 -13
  602. package/dist/senses/bluebubbles.js +0 -1181
  603. package/dist/senses/debug-activity.js +0 -154
  604. package/dist/senses/inner-dialog-worker.js +0 -90
  605. package/dist/senses/inner-dialog.js +0 -525
  606. package/subagents/README.md +0 -7
  607. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  608. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  609. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  610. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  611. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  612. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  613. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  614. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  615. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  616. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  617. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  618. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  619. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  620. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  621. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  622. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  623. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,101 @@
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.runSanctuaryHealthHabit = runSanctuaryHealthHabit;
37
+ const path = __importStar(require("node:path"));
38
+ const router_1 = require("../heart/external-events/router");
39
+ const identity_1 = require("../heart/identity");
40
+ const machine_identity_1 = require("../heart/machine-identity");
41
+ const runtime_credentials_1 = require("../heart/runtime-credentials");
42
+ const runtime_1 = require("../nerves/runtime");
43
+ const sanctuary_health_1 = require("./sanctuary-health");
44
+ const sanctuary_runtime_1 = require("./sanctuary-runtime");
45
+ function evidenceInputs(agentName, result) {
46
+ const revision = result.observationRevision;
47
+ const current = result.incidents.map((incident) => ({
48
+ agent: agentName,
49
+ source: "sanctuary-health",
50
+ eventType: "health.observed",
51
+ eventId: incident.id,
52
+ observationRevision: incident.observationRevision ?? revision,
53
+ transition: incident.transition ?? result.transition ?? "changed",
54
+ summary: incident.summary,
55
+ evidence: [incident.summary],
56
+ priority: "high",
57
+ }));
58
+ const recovered = (result.recovered ?? []).map((incident) => ({
59
+ agent: agentName,
60
+ source: "sanctuary-health",
61
+ eventType: "health.observed",
62
+ eventId: incident.id,
63
+ observationRevision: incident.observationRevision ?? revision,
64
+ transition: "recovered",
65
+ summary: `recovered: ${incident.summary}`,
66
+ evidence: [`recovered: ${incident.summary}`],
67
+ priority: "high",
68
+ }));
69
+ return [...current, ...recovered];
70
+ }
71
+ async function runSanctuaryHealthHabit(agentName, options = {}) {
72
+ if (!options.createSweep && !(0, runtime_credentials_1.readMachineRuntimeCredentialConfig)(agentName).ok) {
73
+ const machine = (0, machine_identity_1.loadOrCreateMachineIdentity)();
74
+ await (0, runtime_credentials_1.refreshMachineRuntimeCredentialConfig)(agentName, machine.machineId, { preserveCachedOnFailure: true });
75
+ }
76
+ const sweep = options.createSweep?.(agentName) ?? (0, sanctuary_health_1.createSanctuaryHealthSweep)({
77
+ toolContext: (0, sanctuary_runtime_1.createSanctuaryToolContext)(agentName),
78
+ statePath: path.join((0, identity_1.getAgentRoot)(agentName), "state", "health", "sanctuary-health.json"),
79
+ });
80
+ const result = await sweep();
81
+ const inputs = evidenceInputs(agentName, result);
82
+ if (inputs.length === 0) {
83
+ (0, runtime_1.emitNervesEvent)({
84
+ component: "senses",
85
+ event: "senses.sanctuary_health_habit",
86
+ message: "Sanctuary health evidence submitted",
87
+ meta: { agentName, incidentCount: 0, submitted: 0, wakesRequested: 0 },
88
+ });
89
+ return { ok: true, message: "health evidence submitted", data: { incidentCount: 0, submitted: 0, wakesRequested: 0 } };
90
+ }
91
+ const submit = options.submitEvidence ?? ((input) => (0, router_1.recordExternalEvent)(input));
92
+ const receipts = await Promise.all(inputs.map((input) => submit(input)));
93
+ const wakesRequested = receipts.some((receipt) => receipt.shouldWake) ? 1 : 0;
94
+ (0, runtime_1.emitNervesEvent)({
95
+ component: "senses",
96
+ event: "senses.sanctuary_health_habit",
97
+ message: "Sanctuary health evidence submitted",
98
+ meta: { agentName, incidentCount: result.incidents.length, submitted: inputs.length, wakesRequested },
99
+ });
100
+ return { ok: true, message: "health evidence submitted", data: { incidentCount: result.incidents.length, submitted: inputs.length, wakesRequested } };
101
+ }
@@ -0,0 +1,408 @@
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.SANCTUARY_PUBLIC_ENDPOINTS = void 0;
37
+ exports.withSanctuaryHealthStateLease = withSanctuaryHealthStateLease;
38
+ exports.readSanctuaryHealthState = readSanctuaryHealthState;
39
+ exports.probeSanctuaryEndpoint = probeSanctuaryEndpoint;
40
+ exports.createSanctuaryHealthSweep = createSanctuaryHealthSweep;
41
+ const fs = __importStar(require("node:fs"));
42
+ const path = __importStar(require("node:path"));
43
+ const node_crypto_1 = require("node:crypto");
44
+ const runtime_1 = require("../nerves/runtime");
45
+ const sanctuary_acceptance_marker_1 = require("../heart/daemon/sanctuary-acceptance-marker");
46
+ exports.SANCTUARY_PUBLIC_ENDPOINTS = [
47
+ "https://media.mendelow.cloud/",
48
+ "https://books.mendelow.cloud/",
49
+ "https://requests.mendelow.cloud/",
50
+ "https://readarr.mendelow.cloud/",
51
+ ];
52
+ const REQUIRED_CONTAINERS = new Set(["calibre", "calibre-web", "Cloudflare-DDNS"]);
53
+ const UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;
54
+ const MAX_HEALTH_STATE_BYTES = 4 * 1024 * 1024;
55
+ const MAX_HEALTH_TEXT_BYTES = 50_000;
56
+ const MAX_HEALTH_INCIDENT_BYTES = 4_096;
57
+ function boundedIncidentText(value) {
58
+ if (Buffer.byteLength(value) <= MAX_HEALTH_INCIDENT_BYTES)
59
+ return value;
60
+ let output = "";
61
+ for (const character of value) {
62
+ if (Buffer.byteLength(output) + Buffer.byteLength(character) > MAX_HEALTH_INCIDENT_BYTES - 3)
63
+ break;
64
+ output += character;
65
+ }
66
+ return `${output}…`;
67
+ }
68
+ function canonicalIsoTimestamp(value) {
69
+ if (typeof value !== "string" || value.length > 30)
70
+ return false;
71
+ const parsed = Date.parse(value);
72
+ return Number.isFinite(parsed) && new Date(parsed).toISOString() === value;
73
+ }
74
+ const healthLockTails = new Map();
75
+ const healthLeaseBrand = Symbol("sanctuary-health-state-lease");
76
+ const activeHealthLeases = new Set();
77
+ function healthLeaseOwner(value) {
78
+ if (!value || typeof value !== "object" || Array.isArray(value))
79
+ throw new Error("Sanctuary health lease ownership is invalid");
80
+ const owner = value;
81
+ if (JSON.stringify(Object.keys(owner).sort()) !== JSON.stringify(["nonce", "pid", "schemaVersion"])
82
+ || owner.schemaVersion !== 1 || !Number.isSafeInteger(owner.pid) || Number(owner.pid) < 1
83
+ || typeof owner.nonce !== "string" || !/^[0-9a-f]{64}$/u.test(owner.nonce)) {
84
+ throw new Error("Sanctuary health lease ownership is invalid");
85
+ }
86
+ return owner;
87
+ }
88
+ function processIsAlive(pid) {
89
+ try {
90
+ process.kill(pid, 0);
91
+ return true;
92
+ }
93
+ catch (error) {
94
+ return error.code === "EPERM";
95
+ }
96
+ }
97
+ function removeHealthLeaseDirectory(leasePath) {
98
+ const entries = fs.readdirSync(leasePath, { withFileTypes: true });
99
+ if (entries.some((entry) => !entry.isFile() || entry.name !== "owner.json"))
100
+ throw new Error("Sanctuary health lease contains unexpected entries");
101
+ if (entries.length === 1)
102
+ fs.unlinkSync(path.join(leasePath, "owner.json"));
103
+ fs.rmdirSync(leasePath);
104
+ }
105
+ async function acquireHealthFileLease(statePath, timeoutMs) {
106
+ const leasePath = `${statePath}.lease`;
107
+ const ownerPath = path.join(leasePath, "owner.json");
108
+ const deadline = Date.now() + timeoutMs;
109
+ const nonce = (0, node_crypto_1.createHash)("sha256").update((0, node_crypto_1.randomUUID)()).digest("hex");
110
+ fs.mkdirSync(path.dirname(statePath), { recursive: true });
111
+ for (;;) {
112
+ try {
113
+ fs.mkdirSync(leasePath, { recursive: false, mode: 0o700 });
114
+ fs.writeFileSync(ownerPath, `${JSON.stringify({ schemaVersion: 1, pid: process.pid, nonce })}\n`, { flag: "wx", mode: 0o600 });
115
+ return { statePath, nonce, [healthLeaseBrand]: true };
116
+ }
117
+ catch (error) {
118
+ if (error.code !== "EEXIST") {
119
+ try {
120
+ if (fs.existsSync(leasePath) && !fs.existsSync(ownerPath))
121
+ fs.rmdirSync(leasePath);
122
+ }
123
+ catch { /* preserve the original failure */ }
124
+ throw error;
125
+ }
126
+ let owner;
127
+ try {
128
+ owner = healthLeaseOwner(JSON.parse(fs.readFileSync(ownerPath, "utf8")));
129
+ }
130
+ catch (ownerError) {
131
+ if (ownerError.code === "ENOENT" && Date.now() < deadline) {
132
+ await new Promise((resolve) => setTimeout(resolve, 10));
133
+ continue;
134
+ }
135
+ if (ownerError instanceof Error && ownerError.message.includes("ownership is invalid"))
136
+ throw ownerError;
137
+ throw new Error("Sanctuary health lease ownership is invalid", { cause: ownerError });
138
+ }
139
+ if (!processIsAlive(owner.pid)) {
140
+ removeHealthLeaseDirectory(leasePath);
141
+ continue;
142
+ }
143
+ if (Date.now() >= deadline)
144
+ throw new Error("Sanctuary health state lease timed out");
145
+ await new Promise((resolve) => setTimeout(resolve, 25));
146
+ }
147
+ }
148
+ }
149
+ function releaseHealthFileLease(lease) {
150
+ const leasePath = `${lease.statePath}.lease`;
151
+ const owner = healthLeaseOwner(JSON.parse(fs.readFileSync(path.join(leasePath, "owner.json"), "utf8")));
152
+ if (owner.nonce !== lease.nonce || owner.pid !== process.pid)
153
+ throw new Error("Sanctuary health lease ownership changed");
154
+ removeHealthLeaseDirectory(leasePath);
155
+ }
156
+ async function withSanctuaryHealthStateLease(statePath, operation, options = {}) {
157
+ const previous = healthLockTails.get(statePath) ?? Promise.resolve();
158
+ let releaseProcess;
159
+ const current = new Promise((resolve) => { releaseProcess = resolve; });
160
+ healthLockTails.set(statePath, current);
161
+ await previous;
162
+ let lease;
163
+ try {
164
+ lease = await acquireHealthFileLease(statePath, options.timeoutMs ?? 30_000);
165
+ activeHealthLeases.add(lease);
166
+ return await operation(lease);
167
+ }
168
+ finally {
169
+ if (lease) {
170
+ activeHealthLeases.delete(lease);
171
+ releaseHealthFileLease(lease);
172
+ }
173
+ releaseProcess();
174
+ if (healthLockTails.get(statePath) === current)
175
+ healthLockTails.delete(statePath);
176
+ }
177
+ }
178
+ async function withHealthLock(statePath, operation, lease) {
179
+ if (lease) {
180
+ if (lease.statePath !== statePath || !activeHealthLeases.has(lease) || lease[healthLeaseBrand] !== true) {
181
+ throw new Error("Sanctuary health state lease is invalid");
182
+ }
183
+ return await operation();
184
+ }
185
+ return withSanctuaryHealthStateLease(statePath, async () => operation());
186
+ }
187
+ function load(filePath) {
188
+ try {
189
+ if (fs.statSync(filePath).size > MAX_HEALTH_STATE_BYTES)
190
+ throw new Error("health state exceeds its bound");
191
+ const value = JSON.parse(fs.readFileSync(filePath, "utf8"));
192
+ const validDelivery = (delivery) => Boolean(delivery && typeof delivery === "object"
193
+ && typeof delivery.id === "string" && delivery.id.length > 0 && delivery.id.length <= 128
194
+ && typeof delivery.message === "string" && Buffer.byteLength(delivery.message) <= MAX_HEALTH_TEXT_BYTES
195
+ && ["pending", "attempting"].includes(delivery.status)
196
+ && canonicalIsoTimestamp(delivery.createdAt)
197
+ && (delivery.kind === undefined || ["transition", "digest", "transition_and_digest", "legacy_unknown"].includes(delivery.kind))
198
+ && (delivery.summarizedMessage === undefined || (typeof delivery.summarizedMessage === "string" && Buffer.byteLength(delivery.summarizedMessage) <= MAX_HEALTH_TEXT_BYTES)));
199
+ if (!value.incidents || typeof value.incidents !== "object" || Array.isArray(value.incidents))
200
+ throw new Error("invalid incidents");
201
+ if (value.lastDigestDay !== null && typeof value.lastDigestDay !== "string")
202
+ throw new Error("invalid digest day");
203
+ if (typeof value.updatedAt !== "string")
204
+ throw new Error("invalid update time");
205
+ if (value.outbox !== undefined && value.outbox !== null && !validDelivery(value.outbox))
206
+ throw new Error("invalid health outbox");
207
+ if (value.indeterminateDeliveries !== undefined && (!Array.isArray(value.indeterminateDeliveries) || !value.indeterminateDeliveries.every(validDelivery)))
208
+ throw new Error("invalid indeterminate deliveries");
209
+ if (value.deliveredReceipts !== undefined && (!Array.isArray(value.deliveredReceipts) || value.deliveredReceipts.length > 100 || !value.deliveredReceipts.every((receipt) => (receipt && typeof receipt.deliveryId === "string" && receipt.deliveryId.length > 0 && receipt.deliveryId.length <= 128 && canonicalIsoTimestamp(receipt.deliveredAt)
210
+ && (receipt.kind === undefined || ["transition", "digest", "transition_and_digest", "legacy_unknown"].includes(receipt.kind))
211
+ && Array.isArray(receipt.messageIds) && receipt.messageIds.length > 0 && receipt.messageIds.length <= 100
212
+ && receipt.messageIds.every((id) => Number.isSafeInteger(id) && id > 0)))))
213
+ throw new Error("invalid delivered receipts");
214
+ if (value.sweepReceipts !== undefined && (!Array.isArray(value.sweepReceipts) || value.sweepReceipts.length > 500 || !value.sweepReceipts.every((receipt) => (receipt && typeof receipt.sweepId === "string" && UUID_V4.test(receipt.sweepId)
215
+ && canonicalIsoTimestamp(receipt.startedAt)
216
+ && canonicalIsoTimestamp(receipt.completedAt)
217
+ && /^[0-9a-f]{64}$/u.test(receipt.incidentDigest) && Number.isSafeInteger(receipt.opened) && receipt.opened >= 0
218
+ && Number.isSafeInteger(receipt.recovered) && receipt.recovered >= 0 && typeof receipt.digestDue === "boolean"
219
+ && (receipt.deliveryId === undefined || (typeof receipt.deliveryId === "string" && receipt.deliveryId.length > 0 && receipt.deliveryId.length <= 128))
220
+ && (receipt.scenarioHandleDigest === undefined || /^[0-9a-f]{64}$/u.test(receipt.scenarioHandleDigest))))))
221
+ throw new Error("invalid sweep receipts");
222
+ return {
223
+ incidents: value.incidents,
224
+ lastDigestDay: value.lastDigestDay,
225
+ updatedAt: value.updatedAt,
226
+ outbox: value.outbox ? { ...value.outbox, kind: value.outbox.kind ?? "legacy_unknown" } : null,
227
+ indeterminateDeliveries: (value.indeterminateDeliveries ?? []).map((delivery) => ({ ...delivery, kind: delivery.kind ?? "legacy_unknown" })),
228
+ deliveredReceipts: (value.deliveredReceipts ?? []).map((receipt) => ({ ...receipt, kind: receipt.kind ?? "legacy_unknown" })),
229
+ sweepReceipts: value.sweepReceipts ?? [],
230
+ };
231
+ }
232
+ catch (error) {
233
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT")
234
+ return { incidents: {}, lastDigestDay: null, updatedAt: new Date(0).toISOString(), outbox: null, indeterminateDeliveries: [], deliveredReceipts: [], sweepReceipts: [] };
235
+ throw new Error("Sanctuary health state is corrupt", { cause: error });
236
+ }
237
+ }
238
+ /** Read-only projection for status/orientation surfaces; mutation remains lease-owned by the sweep. */
239
+ function readSanctuaryHealthState(filePath) {
240
+ return load(filePath);
241
+ }
242
+ function save(filePath, state) {
243
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
244
+ const temporary = `${filePath}.tmp-${process.pid}-${(0, node_crypto_1.randomUUID)()}`;
245
+ fs.writeFileSync(temporary, `${JSON.stringify(state)}\n`, { mode: 0o600 });
246
+ const temporaryHandle = fs.openSync(temporary, "r");
247
+ try {
248
+ fs.fsyncSync(temporaryHandle);
249
+ }
250
+ finally {
251
+ fs.closeSync(temporaryHandle);
252
+ }
253
+ fs.renameSync(temporary, filePath);
254
+ const directoryHandle = fs.openSync(path.dirname(filePath), "r");
255
+ try {
256
+ fs.fsyncSync(directoryHandle);
257
+ }
258
+ finally {
259
+ fs.closeSync(directoryHandle);
260
+ }
261
+ }
262
+ function record(value) {
263
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
264
+ }
265
+ async function probeSanctuaryEndpoint(url, fetchImpl = fetch) {
266
+ const configured = new URL(url);
267
+ if (configured.protocol !== "https:" || configured.username || configured.password)
268
+ return { url, ok: false, status: 0 };
269
+ let current = configured;
270
+ try {
271
+ for (let redirects = 0;; redirects += 1) {
272
+ const response = await fetchImpl(current.href, { signal: AbortSignal.timeout(10_000), redirect: "manual" });
273
+ const redirect = response.status >= 300 && response.status < 400;
274
+ if (!redirect) {
275
+ await response.body?.cancel().catch(() => undefined);
276
+ return { url, ok: response.status >= 200 && response.status < 400, status: response.status };
277
+ }
278
+ const location = response.headers.get("location");
279
+ await response.body?.cancel().catch(() => undefined);
280
+ if (!location || redirects === 5)
281
+ return { url, ok: false, status: 0 };
282
+ const target = new URL(location, current);
283
+ if (target.protocol !== "https:" || target.origin !== configured.origin || target.username || target.password) {
284
+ return { url, ok: false, status: 0 };
285
+ }
286
+ current = target;
287
+ }
288
+ }
289
+ catch {
290
+ return { url, ok: false, status: 0 };
291
+ }
292
+ }
293
+ function createSanctuaryHealthSweep(options) {
294
+ const fetchImpl = options.fetch ?? fetch;
295
+ const now = options.now ?? (() => new Date());
296
+ const acceptanceEventMeta = options.acceptanceEventMeta ?? (() => (0, sanctuary_acceptance_marker_1.sanctuaryAcceptanceEventMeta)("sanctuary"));
297
+ const runSweep = async () => {
298
+ const sweepId = (0, node_crypto_1.randomUUID)();
299
+ const startedAt = now().toISOString();
300
+ (0, runtime_1.emitNervesEvent)({ component: "senses", event: "senses.sanctuary_health_start", message: "Sanctuary deterministic health sweep started", meta: { statePath: options.statePath, ...acceptanceEventMeta() } });
301
+ const pendingState = load(options.statePath);
302
+ if (pendingState.outbox) {
303
+ pendingState.outbox = null;
304
+ pendingState.indeterminateDeliveries = [];
305
+ pendingState.updatedAt = now().toISOString();
306
+ save(options.statePath, pendingState);
307
+ }
308
+ const runtime = options.toolContext.sanctuary;
309
+ if (!runtime)
310
+ throw new Error("Sanctuary health runtime is unavailable");
311
+ const [containersResult, storageResult, disksResult, notificationsResult, endpoints] = await Promise.all([
312
+ runtime.listContainers(), runtime.getStorage(), runtime.getDisks(), runtime.getNotifications(),
313
+ Promise.all(exports.SANCTUARY_PUBLIC_ENDPOINTS.map((url) => probeSanctuaryEndpoint(url, fetchImpl))),
314
+ ]);
315
+ const incidents = new Map();
316
+ const add = (id, rawSummary) => {
317
+ const summary = boundedIncidentText(rawSummary);
318
+ incidents.set(id, {
319
+ id,
320
+ summary,
321
+ observationRevision: (0, node_crypto_1.createHash)("sha256").update(`${id}\0${summary}`).digest("hex"),
322
+ });
323
+ };
324
+ const containers = record(containersResult)?.ok ? record(record(containersResult)?.data)?.containers : null;
325
+ if (!Array.isArray(containers))
326
+ add("containers:unavailable", "container status is unavailable");
327
+ else
328
+ for (const container of containers) {
329
+ if ((container.autostart === true || REQUIRED_CONTAINERS.has(container.name)) && container.state !== "running")
330
+ add(`container:${container.id}:availability`, `${container.name} is ${container.state}`);
331
+ if (container.state === "unknown" || container.degraded === true)
332
+ add(`container:${container.id}:health`, `${container.name} status is degraded`);
333
+ }
334
+ const storage = record(storageResult)?.ok ? record(record(storageResult)?.data) : null;
335
+ const array = record(storage?.array);
336
+ if (!array || array.degraded || typeof array.usedPercent !== "number")
337
+ add("storage:array:capacity", "array capacity is unavailable");
338
+ else if (array.usedPercent >= 90)
339
+ add("storage:array:capacity", `array usage is ${array.usedPercent}%`);
340
+ for (const share of Array.isArray(storage?.shares) ? storage.shares : [])
341
+ if (share.degraded || typeof share.usedPercent !== "number")
342
+ add(`storage:share:${share.name}:capacity`, `${share.name} capacity is unavailable`);
343
+ else if (share.usedPercent >= 90)
344
+ add(`storage:share:${share.name}:capacity`, `${share.name} usage is ${share.usedPercent}%`);
345
+ const disks = record(disksResult)?.ok ? record(record(disksResult)?.data) : null;
346
+ if (!disks)
347
+ add("disks:unavailable", "disk health is unavailable");
348
+ else {
349
+ for (const disk of Array.isArray(disks.disks) ? disks.disks : []) {
350
+ if (disk.smart !== "passed")
351
+ add(`disk:${disk.id}:smart`, `${disk.name} SMART is ${disk.smart}`);
352
+ if (typeof disk.temperatureC !== "number")
353
+ add(`disk:${disk.id}:temperature`, `${disk.name} temperature is unavailable`);
354
+ else if (disk.temperatureC >= 50)
355
+ add(`disk:${disk.id}:temperature`, `${disk.name} is ${disk.temperatureC}°C`);
356
+ }
357
+ const parity = record(disks.parity);
358
+ if (!parity || parity.result !== "success" || typeof parity.ageHours !== "number" || parity.ageHours >= 45 * 24)
359
+ add("parity:stale-or-failed", "parity check is unsuccessful, unknown, or older than 45 days");
360
+ }
361
+ const notifications = record(notificationsResult)?.ok ? record(record(notificationsResult)?.data)?.unacknowledged : null;
362
+ if (!Array.isArray(notifications))
363
+ add("notifications:unavailable", "notification status is unavailable");
364
+ else
365
+ for (const item of notifications)
366
+ add(`notification:${item.id}`, `unacknowledged notification: ${item.title || item.id}`);
367
+ for (const endpoint of endpoints)
368
+ if (!endpoint.ok)
369
+ add(`endpoint:${endpoint.url}`, `${endpoint.url} returned ${endpoint.status || "no response"}`);
370
+ const previous = load(options.statePath);
371
+ const current = Object.fromEntries([...incidents.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([id, incident]) => {
372
+ const prior = previous.incidents[id];
373
+ const transition = !prior ? "opened" : prior.observationRevision === incident.observationRevision ? "unchanged" : "changed";
374
+ return [id, { ...incident, transition }];
375
+ }));
376
+ const opened = Object.values(current).filter((incident) => !previous.incidents[incident.id]);
377
+ const changed = Object.values(current).filter((incident) => incident.transition === "changed");
378
+ const recovered = Object.values(previous.incidents).filter((incident) => !current[incident.id]);
379
+ const acceptanceMeta = acceptanceEventMeta();
380
+ const completedAt = now().toISOString();
381
+ const incidentDigest = (0, node_crypto_1.createHash)("sha256").update(JSON.stringify(current)).digest("hex");
382
+ const sweepReceipt = {
383
+ sweepId,
384
+ startedAt,
385
+ completedAt,
386
+ incidentDigest,
387
+ opened: opened.length,
388
+ recovered: recovered.length,
389
+ digestDue: false,
390
+ ...(acceptanceMeta.scenarioHandleDigest ? { scenarioHandleDigest: acceptanceMeta.scenarioHandleDigest } : {}),
391
+ };
392
+ const next = {
393
+ incidents: current,
394
+ lastDigestDay: null,
395
+ updatedAt: now().toISOString(),
396
+ outbox: null,
397
+ indeterminateDeliveries: [],
398
+ deliveredReceipts: previous.deliveredReceipts,
399
+ sweepReceipts: [...previous.sweepReceipts, sweepReceipt].slice(-500),
400
+ };
401
+ save(options.statePath, next);
402
+ (0, runtime_1.emitNervesEvent)({ component: "senses", event: "senses.sanctuary_health_end", message: "Sanctuary deterministic health sweep completed", meta: { incidentCount: incidents.size, opened: opened.length, recovered: recovered.length, digestDue: false, ...acceptanceEventMeta() } });
403
+ const transition = changed.length > 0 || (opened.length > 0 && recovered.length > 0) ? "changed" : opened.length > 0 ? "opened" : recovered.length > 0 ? "recovered" : "unchanged";
404
+ return { message: null, incidents: Object.values(current), recovered, observationRevision: incidentDigest, transition };
405
+ };
406
+ const sweep = (() => withHealthLock(options.statePath, runSweep, options.lease));
407
+ return sweep;
408
+ }
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sanctuaryInstallStateRequiredToolCalls = sanctuaryInstallStateRequiredToolCalls;
4
+ const runtime_1 = require("../nerves/runtime");
5
+ const TOOL_NAME = "sanctuary_get_install_state";
6
+ const REQUEST = /\b(?:use|run|call)\s+sanctuary_get_install_state\b/iu;
7
+ const NEGATED_REQUEST = /\b(?:do not|don't|dont|never|must not|should not|cannot|can't)\s+(?:(?:under|any|all|circumstances|whatsoever|ever|please|really|actually|immediately)\s+)*(?:use|run|call)\s+sanctuary_get_install_state\b|\bnot\s+to\s+(?:use|run|call)\s+sanctuary_get_install_state\b|\b(?:do not|don't|dont)\s+(?:(?:want|need|ask)\b(?:(?![.!?;,:]).){0,64}|(?:(?:under|any|all|circumstances|whatsoever|ever|please|really|actually|immediately)\s+)*(?:attempt|try|plan|intend)\s+(?:to\s+)?)(?:use|run|call)\s+sanctuary_get_install_state\b/giu;
8
+ const HISTORICAL_QUESTION = /\b(?:did|have|has)\s+(?:you\s+)?(?:use|run|call)\s+sanctuary_get_install_state\b[^.!?;:]*/giu;
9
+ const MISMATCH_CODES = new Set([
10
+ "managed_file_missing",
11
+ "managed_file_content",
12
+ "managed_file_mode",
13
+ "bundle_meta_missing",
14
+ "bundle_meta_field",
15
+ "bundle_meta_mode",
16
+ ]);
17
+ const REPAIR_ACTIONS = new Set([
18
+ "restart_from_verified_release",
19
+ "run_verified_update_recovery",
20
+ "roll_back_or_install_verified_release",
21
+ ]);
22
+ function parseInstallState(result) {
23
+ try {
24
+ const parsed = JSON.parse(result);
25
+ const data = parsed.ok === true && parsed.data && typeof parsed.data === "object" && !Array.isArray(parsed.data)
26
+ ? parsed.data
27
+ : undefined;
28
+ const repair = data?.repair && typeof data.repair === "object" && !Array.isArray(data.repair)
29
+ ? data.repair
30
+ : undefined;
31
+ if (!data
32
+ || typeof data.runtimePackageVersion !== "string" || data.runtimePackageVersion.length === 0
33
+ || typeof data.packagedBundleVersion !== "string" || data.packagedBundleVersion.length === 0
34
+ || !(typeof data.liveBundleVersion === "string" && data.liveBundleVersion.length > 0 || data.liveBundleVersion === null)
35
+ || !["exact", "mismatch"].includes(String(data.parity))
36
+ || !Array.isArray(data.mismatchCodes)
37
+ || !data.mismatchCodes.every((code) => typeof code === "string" && MISMATCH_CODES.has(code))
38
+ || !["absent", "rollback", "committing"].includes(String(data.journalState))
39
+ || typeof data.ready !== "boolean"
40
+ || !(repair?.actor === "none" && repair.action === "none"
41
+ || repair?.actor === "human-required" && typeof repair.action === "string" && REPAIR_ACTIONS.has(repair.action)))
42
+ return undefined;
43
+ return {
44
+ runtimePackageVersion: data.runtimePackageVersion,
45
+ packagedBundleVersion: data.packagedBundleVersion,
46
+ liveBundleVersion: data.liveBundleVersion,
47
+ parity: data.parity,
48
+ journalState: data.journalState,
49
+ ready: data.ready,
50
+ repairAction: repair.action,
51
+ };
52
+ }
53
+ catch {
54
+ return undefined;
55
+ }
56
+ }
57
+ function exactAnswerPattern(current) {
58
+ const value = (raw) => raw.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
59
+ const assignment = String.raw `\s*(?:(?:is)\s+|[:=]\s*)?`;
60
+ const separator = String.raw `\s*[,;]\s*`;
61
+ return new RegExp(String.raw `runtime(?: package)?(?: version)?${assignment}${value(current.runtimePackageVersion)}${separator}`
62
+ + String.raw `packaged(?: bundle)?(?: version)?${assignment}${value(current.packagedBundleVersion)}${separator}`
63
+ + String.raw `live(?: bundle)?(?: version)?${assignment}${value(current.liveBundleVersion ?? "null")}${separator}`
64
+ + String.raw `parity${assignment}${value(current.parity)}${separator}`
65
+ + String.raw `journal(?: state)?${assignment}${value(current.journalState)}${separator}`
66
+ + String.raw `ready(?: state)?${assignment}${value(String(current.ready))}${separator}`
67
+ + String.raw `repair(?: action)?${assignment}${value(current.repairAction)}(?=$|[\s,;.!?])`, "iu");
68
+ }
69
+ const RESIDUAL_INSTALL_STATE_CLAIM = /(?:^|[.!?;,]\s*)(?:(?:and|but|however|yet)\s+)*(?:(?:the\s+)?(?:runtime(?: package)?(?: version)?|packaged(?: bundle)?(?: version)?|live(?: bundle)?(?: version)?)\s*(?:(?:is)\s+|[:=]\s*)?(?=v?\d|unknown\b|null\b|missing\b|corrupt\b)|(?:the\s+)?installed package(?: version)?\b|(?:the\s+)?parity\s*(?:(?:is)\s+|[:=]\s*)?(?=(?:not\s+)?(?:exact|mismatch)\b)|(?:the\s+)?journal(?: state)?\s*(?:(?:is)\s+|[:=]\s*)?(?=(?:not\s+)?(?:absent|rollback|committing)\b)|(?:the\s+)?ready(?: state)?\s*(?:(?:is)\s+|[:=]\s*)?(?=(?:not\s+)?(?:true|false|ready)\b)|(?:the\s+)?repair(?: action)?\s*(?:(?:is)\s+|[:=]\s*)?(?=none\b|restart_from_verified_release\b|run_verified_update_recovery\b|roll_back_or_install_verified_release\b|required\b|needed\b)|(?:the\s+)?(?:install(?:ation)?|sanctuary|bundle|service|system|it)\s+(?:is(?:\s+not)?|isn't)\s+ready\b)/iu;
70
+ function sanctuaryInstallStateRequiredToolCalls(request, advertisedToolNames) {
71
+ const normalizedRequest = request.normalize("NFKC").replace(/[‘’]/gu, "'");
72
+ const negationRequest = normalizedRequest.replace(/,/gu, " ");
73
+ const affirmativeRequest = negationRequest
74
+ .replace(NEGATED_REQUEST, " ")
75
+ .replace(HISTORICAL_QUESTION, " ");
76
+ if (!advertisedToolNames.includes(TOOL_NAME)
77
+ || !REQUEST.test(affirmativeRequest))
78
+ return undefined;
79
+ let current;
80
+ const retryMessage = "Call sanctuary_get_install_state with empty arguments, then answer only from that fresh result.";
81
+ (0, runtime_1.emitNervesEvent)({
82
+ component: "senses",
83
+ event: "senses.sanctuary_install_state_required",
84
+ message: "explicit Sanctuary install-state request requires a fresh verified read",
85
+ meta: { requiredToolName: TOOL_NAME },
86
+ });
87
+ return {
88
+ names: [TOOL_NAME],
89
+ retryMessage,
90
+ requireSuccessfulResults: true,
91
+ validateRequiredToolResult: (name, result, args) => {
92
+ if (name !== TOOL_NAME || Object.keys(args).length !== 0)
93
+ return false;
94
+ current = parseInstallState(result);
95
+ return current !== undefined;
96
+ },
97
+ validateTerminalAnswer: (answer) => {
98
+ if (!current) {
99
+ return "Answer from the fresh install-state result and include its runtime package version, packaged bundle version, live bundle version, parity, journal state, ready state, and repair action.";
100
+ }
101
+ const normalizedAnswer = answer.normalize("NFKC").replace(/[‘’]/gu, "'").replace(/\*\*|`/gu, "");
102
+ const exactMatches = [...normalizedAnswer.matchAll(new RegExp(exactAnswerPattern(current).source, "giu"))];
103
+ if (exactMatches.length === 0) {
104
+ const currentValues = [
105
+ current.runtimePackageVersion,
106
+ current.packagedBundleVersion,
107
+ current.liveBundleVersion ?? "null",
108
+ current.parity,
109
+ current.journalState,
110
+ String(current.ready),
111
+ current.repairAction,
112
+ ];
113
+ return currentValues.every((value) => normalizedAnswer.includes(value))
114
+ ? "State each fresh install-state value exactly once in one compact answer."
115
+ : "Answer from the fresh install-state result and include its runtime package version, packaged bundle version, live bundle version, parity, journal state, ready state, and repair action.";
116
+ }
117
+ if (exactMatches.length !== 1)
118
+ return "State each fresh install-state value exactly once in one compact answer.";
119
+ const match = exactMatches[0];
120
+ const residual = normalizedAnswer.replace(match[0], " ").trim();
121
+ if (RESIDUAL_INSTALL_STATE_CLAIM.test(residual))
122
+ return "State each fresh install-state value exactly once in one compact answer.";
123
+ return undefined;
124
+ },
125
+ };
126
+ }