@ouro.bot/cli 0.1.0-alpha.83 → 0.1.0-alpha.831
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.
- package/LICENSE +21 -0
- package/README.md +154 -23
- package/RepairGuide.ouro/agent.json +5 -0
- package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
- package/RepairGuide.ouro/psyche/SOUL.md +55 -0
- package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
- package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
- package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
- package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
- package/assets/bluebubbles-host +264 -0
- package/assets/sanctuary-host-launcher.sh +16 -0
- package/changelog.json +5308 -16
- package/deploy/unraid/Dockerfile +54 -0
- package/deploy/unraid/README.txt +2983 -0
- package/deploy/unraid/audit-container-spec.sh +4 -0
- package/deploy/unraid/container-runtime.json +1 -0
- package/deploy/unraid/docker-man-template-transaction.mjs +711 -0
- package/deploy/unraid/docker-man-template-xml.cjs +105 -0
- package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
- package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
- package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
- package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
- package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
- package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
- package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
- package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
- package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
- package/deploy/unraid/sanctuary-authority-installation.json +36 -0
- package/deploy/unraid/sanctuary-authority-service.sh +30 -0
- package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
- package/deploy/unraid/sanctuary-safe-rename.py +24 -0
- package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2084 -0
- package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
- package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
- package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
- package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
- package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
- package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
- package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +795 -0
- package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
- package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
- package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
- package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +15 -0
- package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +25 -0
- package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +15 -0
- package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
- package/deploy/unraid/sanctuary.ouro/tool-profiles.json +135 -0
- package/deploy/unraid/sanctuary.xml +28 -0
- package/dist/a2a/card.js +57 -0
- package/dist/a2a/client.js +180 -0
- package/dist/a2a/config.js +50 -0
- package/dist/a2a/delegation-stores.js +56 -0
- package/dist/a2a/did-resolution.js +93 -0
- package/dist/a2a/identity.js +170 -0
- package/dist/a2a/inbound-share.js +107 -0
- package/dist/a2a/mission-result-wire.js +196 -0
- package/dist/a2a/onboarding.js +115 -0
- package/dist/a2a/pin-store.js +132 -0
- package/dist/a2a/seen-ledger.js +120 -0
- package/dist/a2a/server.js +604 -0
- package/dist/a2a/task-store.js +69 -0
- package/dist/a2a/transport.js +45 -0
- package/dist/a2a/types.js +3 -0
- package/dist/arc/attention-types.js +8 -0
- package/dist/arc/cares.js +360 -0
- package/dist/arc/episodes.js +118 -0
- package/dist/arc/evolution.js +490 -0
- package/dist/arc/flight-recorder.js +1034 -0
- package/dist/arc/intentions.js +134 -0
- package/dist/arc/json-store.js +117 -0
- package/dist/arc/obligations.js +386 -0
- package/dist/arc/packets.js +336 -0
- package/dist/arc/presence.js +185 -0
- package/dist/arc/task-lifecycle.js +57 -0
- package/dist/commerce/store.js +755 -0
- package/dist/commerce/types.js +3 -0
- package/dist/heart/active-work.js +798 -40
- package/dist/heart/agent-entry.js +252 -3
- package/dist/heart/approval-files.js +113 -0
- package/dist/heart/approval-store.js +960 -0
- package/dist/heart/attachments/image-normalize.js +194 -0
- package/dist/heart/attachments/materialize.js +97 -0
- package/dist/heart/attachments/originals.js +88 -0
- package/dist/heart/attachments/render.js +29 -0
- package/dist/heart/attachments/sources/bluebubbles.js +156 -0
- package/dist/heart/attachments/sources/cli-local-file.js +78 -0
- package/dist/heart/attachments/sources/index.js +18 -0
- package/dist/heart/attachments/sources/telegram.js +71 -0
- package/dist/heart/attachments/store.js +132 -0
- package/dist/heart/attachments/types.js +93 -0
- package/dist/heart/auth/auth-flow.js +495 -0
- package/dist/heart/autonomy-budget.js +478 -0
- package/dist/heart/awaiting/await-alert.js +148 -0
- package/dist/heart/awaiting/await-expiry.js +143 -0
- package/dist/heart/awaiting/await-loader.js +91 -0
- package/dist/heart/awaiting/await-parser.js +149 -0
- package/dist/heart/awaiting/await-runtime-state.js +111 -0
- package/dist/heart/awaiting/await-scheduler.js +382 -0
- package/dist/heart/background-operations.js +281 -0
- package/dist/heart/bridges/manager.js +137 -17
- package/dist/heart/bridges/store.js +14 -2
- package/dist/heart/bundle-state.js +168 -0
- package/dist/heart/commitments.js +44 -18
- package/dist/heart/config-registry.js +331 -0
- package/dist/heart/config.js +174 -131
- package/dist/heart/context-loss-gauntlet.js +387 -0
- package/dist/heart/context-loss-sentinel.js +1157 -0
- package/dist/heart/core.js +2169 -581
- package/dist/heart/cross-chat-delivery.js +9 -22
- package/dist/heart/daemon/agent-config-check.js +451 -0
- package/dist/heart/daemon/agent-discovery.js +185 -3
- package/dist/heart/daemon/agent-service.js +542 -0
- package/dist/heart/daemon/agentic-repair.js +547 -0
- package/dist/heart/daemon/await-private-wake.js +59 -0
- package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
- package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
- package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
- package/dist/heart/daemon/bluebubbles-host.js +273 -0
- package/dist/heart/daemon/boot-sync-probe.js +197 -0
- package/dist/heart/daemon/cadence.js +180 -0
- package/dist/heart/daemon/cli-defaults.js +854 -0
- package/dist/heart/daemon/cli-desk.js +322 -0
- package/dist/heart/daemon/cli-exec.js +8822 -0
- package/dist/heart/daemon/cli-help.js +716 -0
- package/dist/heart/daemon/cli-parse.js +2771 -0
- package/dist/heart/daemon/cli-render-doctor.js +57 -0
- package/dist/heart/daemon/cli-render.js +777 -0
- package/dist/heart/daemon/cli-types.js +8 -0
- package/dist/heart/daemon/connect-bay.js +323 -0
- package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
- package/dist/heart/daemon/container-healthcheck.js +112 -0
- package/dist/heart/daemon/container-runtime.js +97 -0
- package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
- package/dist/heart/daemon/container-spec-auditor.js +229 -0
- package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
- package/dist/heart/daemon/daemon-cli.js +29 -2349
- package/dist/heart/daemon/daemon-entry.js +930 -11
- package/dist/heart/daemon/daemon-health.js +186 -0
- package/dist/heart/daemon/daemon-rollup.js +57 -0
- package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
- package/dist/heart/daemon/daemon-tombstone.js +236 -0
- package/dist/heart/daemon/daemon.js +2084 -105
- package/dist/heart/daemon/dns-workflow.js +394 -0
- package/dist/heart/daemon/doctor-types.js +8 -0
- package/dist/heart/daemon/doctor.js +1755 -0
- package/dist/heart/daemon/freshness.js +345 -0
- package/dist/heart/daemon/habit-private-wake.js +61 -0
- package/dist/heart/daemon/health-monitor.js +142 -11
- package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
- package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
- package/dist/heart/daemon/http-health-probe.js +80 -0
- package/dist/heart/daemon/human-command-screens.js +234 -0
- package/dist/heart/daemon/human-readiness.js +114 -0
- package/dist/heart/daemon/inner-status.js +78 -0
- package/dist/heart/daemon/interactive-repair.js +394 -0
- package/dist/heart/daemon/launchd.js +37 -8
- package/dist/heart/daemon/log-tailer.js +79 -10
- package/dist/heart/daemon/logs-prune.js +132 -0
- package/dist/heart/daemon/mcp-canary.js +524 -0
- package/dist/heart/daemon/message-router.js +65 -5
- package/dist/heart/daemon/migrate-to-desk.js +848 -0
- package/dist/heart/daemon/os-cron-deps.js +135 -0
- package/dist/heart/daemon/os-cron.js +22 -14
- package/dist/heart/daemon/ouro-bot-entry.js +4 -2
- package/dist/heart/daemon/ouro-entry.js +3 -1
- package/dist/heart/daemon/plugin-cli.js +432 -0
- package/dist/heart/daemon/process-manager.js +733 -61
- package/dist/heart/daemon/provider-discovery.js +137 -0
- package/dist/heart/daemon/provider-ping-progress.js +83 -0
- package/dist/heart/daemon/prunable-bundle.js +144 -0
- package/dist/heart/daemon/pulse.js +511 -0
- package/dist/heart/daemon/readiness-repair.js +365 -0
- package/dist/heart/daemon/run-hooks.js +2 -0
- package/dist/heart/daemon/runtime-logging.js +47 -14
- package/dist/heart/daemon/runtime-metadata.js +2 -30
- package/dist/heart/daemon/runtime-mode.js +13 -2
- package/dist/heart/daemon/safe-mode.js +161 -0
- package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
- package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
- package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
- package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
- package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
- package/dist/heart/daemon/sanctuary-authority-epoch.js +256 -0
- package/dist/heart/daemon/sanctuary-authority-installation.js +140 -0
- package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
- package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +819 -0
- package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
- package/dist/heart/daemon/sanctuary-bundle-migration.js +729 -0
- package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
- package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +494 -0
- package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
- package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
- package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
- package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
- package/dist/heart/daemon/sanctuary-package-management.js +103 -0
- package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
- package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
- package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +445 -0
- package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
- package/dist/heart/daemon/sanctuary-telegram-authority-service.js +630 -0
- package/dist/heart/daemon/sense-manager.js +699 -48
- package/dist/heart/daemon/session-id-resolver.js +131 -0
- package/dist/heart/daemon/skill-management-installer.js +1 -1
- package/dist/heart/daemon/socket-client.js +180 -12
- package/dist/heart/daemon/stale-bundle-prune.js +113 -0
- package/dist/heart/daemon/startup-tui.js +339 -0
- package/dist/heart/daemon/supercronic-supervisor.js +282 -0
- package/dist/heart/daemon/task-scheduler.js +117 -39
- package/dist/heart/daemon/terminal-ui.js +499 -0
- package/dist/heart/daemon/thoughts.js +138 -54
- package/dist/heart/daemon/up-progress.js +366 -0
- package/dist/heart/daemon/vault-items.js +56 -0
- package/dist/heart/delegation.js +1 -4
- package/dist/heart/external-events/router.js +1430 -0
- package/dist/heart/frontend-approval-runtime.js +506 -0
- package/dist/heart/frontend-journal.js +215 -0
- package/dist/heart/frontend-session-service.js +237 -0
- package/dist/heart/frontend-socket-client.js +164 -0
- package/dist/heart/frontend-socket.js +400 -0
- package/dist/heart/habits/habit-cancel.js +810 -0
- package/dist/heart/habits/habit-lifecycle.js +1327 -0
- package/dist/heart/habits/habit-migration.js +194 -0
- package/dist/heart/habits/habit-parser.js +278 -0
- package/dist/heart/habits/habit-runtime-state.js +93 -0
- package/dist/heart/habits/habit-scheduler.js +653 -0
- package/dist/heart/habits/habit-session-summary.js +318 -0
- package/dist/heart/habits/habit-session.js +636 -0
- package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
- package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
- package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
- package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
- package/dist/heart/identity.js +196 -59
- package/dist/heart/kept-notes.js +289 -0
- package/dist/heart/kicks.js +1 -1
- package/dist/heart/machine-identity.js +161 -0
- package/dist/heart/mail-import-discovery.js +356 -0
- package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
- package/dist/heart/mailbox/mailbox-http-response.js +7 -0
- package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
- package/dist/heart/mailbox/mailbox-http-static.js +103 -0
- package/dist/heart/mailbox/mailbox-http-transport.js +129 -0
- package/dist/heart/mailbox/mailbox-http.js +99 -0
- package/dist/heart/mailbox/mailbox-read.js +39 -0
- package/dist/heart/mailbox/mailbox-types.js +27 -0
- package/dist/heart/mailbox/mailbox-view.js +197 -0
- package/dist/heart/mailbox/readers/agent-machine.js +428 -0
- package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
- package/dist/heart/mailbox/readers/mail.js +375 -0
- package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
- package/dist/heart/mailbox/readers/sessions.js +231 -0
- package/dist/heart/mailbox/readers/shared.js +111 -0
- package/dist/heart/mcp/mcp-server.js +696 -0
- package/dist/heart/migrate-config.js +100 -0
- package/dist/heart/model-capabilities.js +11 -0
- package/dist/heart/orientation-frame.js +345 -0
- package/dist/heart/platform.js +81 -0
- package/dist/heart/primitives.js +1 -1
- package/dist/heart/private-runtime/decision-renderer.js +158 -0
- package/dist/heart/private-runtime/index.js +18 -0
- package/dist/heart/private-runtime/ledger.js +221 -0
- package/dist/heart/private-runtime/policy.js +252 -0
- package/dist/heart/private-runtime/types.js +2 -0
- package/dist/heart/progress-story.js +1 -1
- package/dist/heart/provider-attempt.js +137 -0
- package/dist/heart/provider-binding-resolver.js +273 -0
- package/dist/heart/provider-credentials.js +449 -0
- package/dist/heart/provider-failover.js +311 -0
- package/dist/heart/provider-models.js +96 -0
- package/dist/heart/provider-ping.js +265 -0
- package/dist/heart/provider-readiness-cache.js +119 -0
- package/dist/heart/provider-visibility.js +188 -0
- package/dist/heart/providers/anthropic-token.js +131 -0
- package/dist/heart/providers/anthropic.js +173 -60
- package/dist/heart/providers/azure.js +23 -11
- package/dist/heart/providers/error-classification.js +127 -0
- package/dist/heart/providers/github-copilot.js +34 -38
- package/dist/heart/providers/minimax-vlm.js +189 -0
- package/dist/heart/providers/minimax.js +26 -8
- package/dist/heart/providers/openai-codex-token.js +349 -0
- package/dist/heart/providers/openai-codex.js +55 -40
- package/dist/heart/providers/openai-compatible.js +177 -0
- package/dist/heart/run-ledger.js +247 -0
- package/dist/heart/runtime-capability-check.js +170 -0
- package/dist/heart/runtime-credentials.js +607 -0
- package/dist/heart/runtime-cwd.js +87 -0
- package/dist/heart/sense-truth.js +22 -4
- package/dist/heart/session-activity.js +92 -24
- package/dist/heart/session-events.js +1504 -0
- package/dist/heart/session-playback-cli-main.js +5 -0
- package/dist/heart/session-playback-cli.js +36 -0
- package/dist/heart/session-playback.js +231 -0
- package/dist/heart/session-redaction-repair-cli-main.js +31 -0
- package/dist/heart/session-redaction-repair.js +552 -0
- package/dist/heart/session-stats-cli-main.js +5 -0
- package/dist/heart/session-stats.js +183 -0
- package/dist/heart/session-transcript.js +133 -0
- package/dist/heart/start-of-turn-packet.js +372 -0
- package/dist/heart/steward-policy.js +618 -0
- package/dist/heart/streaming.js +604 -207
- package/dist/heart/structured-output.js +196 -0
- package/dist/heart/sync-classification.js +176 -0
- package/dist/heart/sync.js +449 -0
- package/dist/heart/target-resolution.js +11 -7
- package/dist/heart/tempo.js +93 -0
- package/dist/heart/temporal-view.js +41 -0
- package/dist/heart/timeouts.js +101 -0
- package/dist/heart/tool-activity-callbacks.js +59 -0
- package/dist/heart/tool-approval.js +382 -0
- package/dist/heart/tool-description.js +155 -0
- package/dist/heart/tool-friction.js +55 -0
- package/dist/heart/tool-loop.js +200 -0
- package/dist/heart/turn-context.js +482 -0
- package/dist/heart/turn-execution-lease.js +30 -0
- package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
- package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
- package/dist/heart/versioning/ouro-path-installer.js +432 -0
- package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
- package/dist/heart/versioning/ouro-version-manager.js +409 -0
- package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
- package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
- package/dist/heart/versioning/update-hooks.js +154 -0
- package/dist/heart/versioning/version-intent.js +114 -0
- package/dist/heart/work-card.js +380 -0
- package/dist/mailbox-ui/assets/index-Cyv4mw3Y.js +1 -0
- package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
- package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
- package/dist/mailbox-ui/index.html +16 -0
- package/dist/mailroom/attention.js +167 -0
- package/dist/mailroom/autonomy.js +209 -0
- package/dist/mailroom/blob-store.js +889 -0
- package/dist/mailroom/body-cache.js +61 -0
- package/dist/mailroom/cache-sync-cli.js +58 -0
- package/dist/mailroom/core.js +803 -0
- package/dist/mailroom/entry.js +160 -0
- package/dist/mailroom/file-store.js +568 -0
- package/dist/mailroom/hosted-cache-sync.js +384 -0
- package/dist/mailroom/mbox-import.js +393 -0
- package/dist/mailroom/migration.js +164 -0
- package/dist/mailroom/outbound.js +380 -0
- package/dist/mailroom/policy.js +263 -0
- package/dist/mailroom/reader.js +292 -0
- package/dist/mailroom/search-cache.js +513 -0
- package/dist/mailroom/search-relevance.js +319 -0
- package/dist/mailroom/smtp-ingress.js +176 -0
- package/dist/mailroom/source-state.js +176 -0
- package/dist/mailroom/thread.js +109 -0
- package/dist/mailroom/travel-extract.js +89 -0
- package/dist/mind/bundle-manifest.js +24 -2
- package/dist/mind/context.js +309 -111
- package/dist/mind/desk-section.js +362 -0
- package/dist/mind/diary-integrity.js +60 -0
- package/dist/mind/{memory.js → diary.js} +68 -77
- package/dist/mind/embedding-provider.js +60 -0
- package/dist/mind/file-state.js +179 -0
- package/dist/mind/{associative-recall.js → note-search.js} +47 -58
- package/dist/mind/obligation-steering.js +199 -3
- package/dist/mind/pending.js +36 -10
- package/dist/mind/prompt-budget.js +479 -0
- package/dist/mind/prompt-refresh.js +3 -2
- package/dist/mind/prompt.js +1050 -189
- package/dist/mind/provenance-trust.js +26 -0
- package/dist/mind/record-paths.js +312 -0
- package/dist/mind/scrutiny.js +173 -0
- package/dist/mind/session-transaction.js +564 -0
- package/dist/nerves/cli-logging.js +7 -1
- package/dist/nerves/coverage/audit-rules.js +15 -6
- package/dist/nerves/coverage/audit.js +28 -2
- package/dist/nerves/coverage/cli.js +1 -1
- package/dist/nerves/coverage/contract.js +5 -5
- package/dist/nerves/coverage/file-completeness.js +139 -5
- package/dist/nerves/coverage/run-artifacts.js +55 -35
- package/dist/nerves/coverage/source-scanner.js +4 -4
- package/dist/nerves/event-buffer.js +111 -0
- package/dist/nerves/index.js +293 -9
- package/dist/nerves/observation.js +20 -0
- package/dist/nerves/redact.js +79 -0
- package/dist/nerves/review/cli-main.js +5 -0
- package/dist/nerves/review/cli.js +156 -0
- package/dist/nerves/review/core.js +159 -0
- package/dist/nerves/runtime.js +17 -1
- package/dist/repertoire/ado-client.js +15 -56
- package/dist/repertoire/ado-semantic.js +16 -10
- package/dist/repertoire/api-client.js +97 -0
- package/dist/repertoire/bitwarden-store.js +1045 -0
- package/dist/repertoire/bundle-templates.js +71 -0
- package/dist/repertoire/bw-installer.js +180 -0
- package/dist/repertoire/coding/codex-jsonl.js +64 -0
- package/dist/repertoire/coding/context-pack.js +331 -0
- package/dist/repertoire/coding/feedback.js +174 -32
- package/dist/repertoire/coding/index.js +15 -3
- package/dist/repertoire/coding/manager.js +159 -10
- package/dist/repertoire/coding/spawner.js +58 -11
- package/dist/repertoire/coding/tools.js +221 -15
- package/dist/repertoire/coding/workbench-client.js +272 -0
- package/dist/repertoire/coding/workbench-manager.js +346 -0
- package/dist/repertoire/commerce-errors.js +109 -0
- package/dist/repertoire/commerce-self-test.js +156 -0
- package/dist/repertoire/credential-access.js +178 -0
- package/dist/repertoire/desk/classifier.js +362 -0
- package/dist/repertoire/duffel-client.js +185 -0
- package/dist/repertoire/github-client.js +14 -55
- package/dist/repertoire/graph-client.js +11 -52
- package/dist/repertoire/guardrails.js +811 -18
- package/dist/repertoire/mcp-client.js +44 -3
- package/dist/repertoire/mcp-manager.js +427 -139
- package/dist/repertoire/mcp-tools.js +124 -0
- package/dist/repertoire/plugin-mcp.js +175 -0
- package/dist/repertoire/plugins.js +253 -0
- package/dist/repertoire/relationship-authorization.js +322 -0
- package/dist/repertoire/shell-sessions.js +134 -0
- package/dist/repertoire/skills.js +48 -4
- package/dist/repertoire/stripe-client.js +131 -0
- package/dist/repertoire/tool-arguments.js +170 -0
- package/dist/repertoire/tool-results.js +29 -0
- package/dist/repertoire/tools-a2a.js +699 -0
- package/dist/repertoire/tools-attachments.js +322 -0
- package/dist/repertoire/tools-awaiting.js +575 -0
- package/dist/repertoire/tools-base.js +77 -1138
- package/dist/repertoire/tools-bluebubbles.js +2 -0
- package/dist/repertoire/tools-bridge.js +144 -0
- package/dist/repertoire/tools-bundle.js +993 -0
- package/dist/repertoire/tools-commerce.js +253 -0
- package/dist/repertoire/tools-config.js +186 -0
- package/dist/repertoire/tools-continuity.js +575 -0
- package/dist/repertoire/tools-credential.js +383 -0
- package/dist/repertoire/tools-evolution.js +527 -0
- package/dist/repertoire/tools-files.js +344 -0
- package/dist/repertoire/tools-flight.js +290 -0
- package/dist/repertoire/tools-flow.js +119 -0
- package/dist/repertoire/tools-github.js +3 -8
- package/dist/repertoire/tools-habits.js +103 -0
- package/dist/repertoire/tools-mail.js +1828 -0
- package/dist/repertoire/tools-notes.js +485 -0
- package/dist/repertoire/tools-obligations.js +182 -0
- package/dist/repertoire/tools-orientation.js +31 -0
- package/dist/repertoire/tools-record.js +482 -0
- package/dist/repertoire/tools-rsvp.js +139 -0
- package/dist/repertoire/tools-runtime.js +150 -0
- package/dist/repertoire/tools-sanctuary-host.js +202 -0
- package/dist/repertoire/tools-session.js +1133 -0
- package/dist/repertoire/tools-shell.js +149 -0
- package/dist/repertoire/tools-steward-policy.js +119 -0
- package/dist/repertoire/tools-stripe.js +224 -0
- package/dist/repertoire/tools-surface.js +369 -0
- package/dist/repertoire/tools-teams.js +12 -39
- package/dist/repertoire/tools-telegram-contacts.js +37 -0
- package/dist/repertoire/tools-travel.js +125 -0
- package/dist/repertoire/tools-trip.js +982 -0
- package/dist/repertoire/tools-unraid.js +531 -0
- package/dist/repertoire/tools-user-profile.js +146 -0
- package/dist/repertoire/tools-vault.js +40 -0
- package/dist/repertoire/tools-voice.js +145 -0
- package/dist/repertoire/tools.js +494 -148
- package/dist/repertoire/travel-api-client.js +360 -0
- package/dist/repertoire/unraid-client.js +155 -0
- package/dist/repertoire/unraid-restart.js +339 -0
- package/dist/repertoire/user-profile.js +131 -0
- package/dist/repertoire/vault-setup.js +246 -0
- package/dist/repertoire/vault-unlock.js +628 -0
- package/dist/rsvp/aisleplanner-client.js +354 -0
- package/dist/rsvp/cli.js +926 -0
- package/dist/rsvp/config.js +327 -0
- package/dist/rsvp/cutover.js +433 -0
- package/dist/rsvp/diagnostics.js +232 -0
- package/dist/rsvp/diff-renderer.js +176 -0
- package/dist/rsvp/habit-policy.js +110 -0
- package/dist/rsvp/habit-stage.js +123 -0
- package/dist/rsvp/incident-bundle.js +97 -0
- package/dist/rsvp/migration.js +204 -0
- package/dist/rsvp/native-habit-runner.js +630 -0
- package/dist/rsvp/outbound-state.js +628 -0
- package/dist/rsvp/query.js +118 -0
- package/dist/rsvp/replay.js +233 -0
- package/dist/rsvp/snapshot.js +232 -0
- package/dist/rsvp/spend-ledger.js +175 -0
- package/dist/scripts/claude-code-hook.js +41 -0
- package/dist/scripts/claude-code-stop-hook.js +47 -0
- package/dist/senses/a2a-entry.js +115 -0
- package/dist/senses/acp-server.js +386 -0
- package/dist/senses/attention-queue.js +186 -0
- package/dist/senses/await-turn-message.js +58 -0
- package/dist/senses/bluebubbles/active-turns.js +216 -0
- package/dist/senses/bluebubbles/attachment-cache.js +53 -0
- package/dist/senses/bluebubbles/attachment-download.js +137 -0
- package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +355 -40
- package/dist/senses/bluebubbles/context-packet.js +207 -0
- package/dist/senses/bluebubbles/context-smoke.js +144 -0
- package/dist/senses/bluebubbles/entry.js +90 -0
- package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
- package/dist/senses/bluebubbles/index.js +3841 -0
- package/dist/senses/bluebubbles/latest-turn.js +311 -0
- package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
- package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
- package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
- package/dist/senses/bluebubbles/outbound-state.js +308 -0
- package/dist/senses/bluebubbles/processed-log.js +133 -0
- package/dist/senses/bluebubbles/reaction-policy.js +47 -0
- package/dist/senses/bluebubbles/replay.js +284 -0
- package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
- package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
- package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
- package/dist/senses/bluebubbles/webhook-registration.js +228 -0
- package/dist/senses/bluebubbles-meta-guard.js +39 -0
- package/dist/senses/cli/bracketed-paste.js +82 -0
- package/dist/senses/cli/image-paste.js +287 -0
- package/dist/senses/cli/image-ref-navigation.js +75 -0
- package/dist/senses/cli/ink-app.js +156 -0
- package/dist/senses/cli/inline-diff.js +64 -0
- package/dist/senses/cli/input-keys.js +174 -0
- package/dist/senses/cli/kill-ring.js +86 -0
- package/dist/senses/cli/message-list.js +51 -0
- package/dist/senses/cli/ouro-tui.js +607 -0
- package/dist/senses/cli/spinner-imperative.js +135 -0
- package/dist/senses/cli/spinner.js +101 -0
- package/dist/senses/cli/status-line.js +60 -0
- package/dist/senses/cli/streaming-markdown.js +526 -0
- package/dist/senses/cli/tool-display.js +85 -0
- package/dist/senses/cli/tool-render.js +85 -0
- package/dist/senses/cli/tui-store.js +241 -0
- package/dist/senses/cli/virtual-list.js +35 -0
- package/dist/senses/cli-entry.js +60 -8
- package/dist/senses/cli.js +604 -320
- package/dist/senses/commands.js +66 -3
- package/dist/senses/context-packet-ledger.js +371 -0
- package/dist/senses/context-packets.js +154 -0
- package/dist/senses/habit-lifecycle-guard.js +24 -0
- package/dist/senses/habit-turn-message.js +160 -0
- package/dist/senses/ingress-evidence.js +2 -0
- package/dist/senses/mail-entry.js +66 -0
- package/dist/senses/mail.js +524 -0
- package/dist/senses/pipeline.js +1115 -204
- package/dist/senses/private-runtime-worker.js +859 -0
- package/dist/senses/private-runtime.js +1517 -0
- package/dist/senses/proactive-content-guard.js +51 -0
- package/dist/senses/root-host-approval-port.js +345 -0
- package/dist/senses/root-host-approval-runtime.js +393 -0
- package/dist/senses/sanctuary-authority-resident.js +102 -0
- package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
- package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
- package/dist/senses/sanctuary-grounding.js +118 -0
- package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
- package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
- package/dist/senses/sanctuary-health-runner.js +100 -0
- package/dist/senses/sanctuary-health.js +408 -0
- package/dist/senses/sanctuary-install-state-contract.js +126 -0
- package/dist/senses/sanctuary-interactive-control.js +410 -0
- package/dist/senses/sanctuary-media-catalog-contract.js +297 -0
- package/dist/senses/sanctuary-media-optimization.js +514 -0
- package/dist/senses/sanctuary-runtime.js +340 -0
- package/dist/senses/sanctuary-sab.js +85 -0
- package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
- package/dist/senses/shared-turn.js +772 -0
- package/dist/senses/surface-tool.js +109 -0
- package/dist/senses/teams-entry.js +60 -8
- package/dist/senses/teams.js +519 -218
- package/dist/senses/telegram-admission.js +718 -0
- package/dist/senses/telegram-approval-runtime.js +793 -0
- package/dist/senses/telegram-attachments.js +186 -0
- package/dist/senses/telegram-audit-ledger.js +220 -0
- package/dist/senses/telegram-authority-transport.js +231 -0
- package/dist/senses/telegram-client.js +1749 -0
- package/dist/senses/telegram-effect-adapter.js +896 -0
- package/dist/senses/telegram-entry.js +83 -0
- package/dist/senses/telegram.js +2324 -0
- package/dist/senses/trust-gate.js +104 -9
- package/dist/senses/voice/audio-playback.js +237 -0
- package/dist/senses/voice/audio-routing.js +119 -0
- package/dist/senses/voice/elevenlabs.js +202 -0
- package/dist/senses/voice/floor-control.js +431 -0
- package/dist/senses/voice/floor-controller.js +115 -0
- package/dist/senses/voice/golden-path.js +116 -0
- package/dist/senses/voice/index.js +29 -0
- package/dist/senses/voice/meeting.js +113 -0
- package/dist/senses/voice/outbound.js +190 -0
- package/dist/senses/voice/phone.js +33 -0
- package/dist/senses/voice/playback.js +139 -0
- package/dist/senses/voice/realtime-eval.js +496 -0
- package/dist/senses/voice/realtime-trace.js +531 -0
- package/dist/senses/voice/transcript.js +70 -0
- package/dist/senses/voice/turn.js +191 -0
- package/dist/senses/voice/twilio-phone-runtime.js +807 -0
- package/dist/senses/voice/twilio-phone.js +5031 -0
- package/dist/senses/voice/types.js +2 -0
- package/dist/senses/voice/whisper.js +161 -0
- package/dist/senses/voice-entry.js +81 -0
- package/dist/senses/voice-realtime-eval-command.js +99 -0
- package/dist/senses/voice-realtime-eval-entry.js +21 -0
- package/dist/senses/voice-twilio-entry.js +87 -0
- package/dist/trips/core.js +138 -0
- package/dist/trips/store.js +265 -0
- package/dist/util/frontmatter.js +69 -0
- package/npm-shrinkwrap.json +8138 -0
- package/package.json +72 -13
- package/skills/agent-commerce.md +113 -0
- package/skills/browser-navigation.md +117 -0
- package/skills/commerce-setup-guide.md +116 -0
- package/skills/commerce-setup.md +84 -0
- package/skills/configure-dev-tools.md +99 -0
- package/skills/travel-planning.md +138 -0
- package/dist/heart/daemon/auth-flow.js +0 -430
- package/dist/heart/daemon/ouro-path-installer.js +0 -260
- package/dist/heart/daemon/ouro-version-manager.js +0 -171
- package/dist/heart/daemon/update-hooks.js +0 -138
- package/dist/heart/obligations.js +0 -191
- package/dist/heart/safe-workspace.js +0 -228
- package/dist/heart/session-recall.js +0 -116
- package/dist/mind/friends/channel.js +0 -84
- package/dist/mind/friends/group-context.js +0 -144
- package/dist/mind/friends/resolver.js +0 -84
- package/dist/mind/friends/store-file.js +0 -190
- package/dist/mind/friends/store.js +0 -4
- package/dist/mind/friends/tokens.js +0 -26
- package/dist/mind/friends/trust-explanation.js +0 -74
- package/dist/mind/friends/types.js +0 -29
- package/dist/repertoire/tasks/board.js +0 -134
- package/dist/repertoire/tasks/index.js +0 -224
- package/dist/repertoire/tasks/lifecycle.js +0 -80
- package/dist/repertoire/tasks/middleware.js +0 -65
- package/dist/repertoire/tasks/parser.js +0 -173
- package/dist/repertoire/tasks/scanner.js +0 -132
- package/dist/repertoire/tasks/transitions.js +0 -144
- package/dist/senses/bluebubbles-entry.js +0 -13
- package/dist/senses/bluebubbles.js +0 -1181
- package/dist/senses/debug-activity.js +0 -154
- package/dist/senses/inner-dialog-worker.js +0 -90
- package/dist/senses/inner-dialog.js +0 -525
- package/subagents/README.md +0 -7
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
- /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
- /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
- /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
- /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
- /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BlueBubblesIgnoredEventError = void 0;
|
|
4
|
+
exports.describeBlueBubblesReaction = describeBlueBubblesReaction;
|
|
5
|
+
exports.renderBlueBubblesReactionText = renderBlueBubblesReactionText;
|
|
3
6
|
exports.normalizeBlueBubblesEvent = normalizeBlueBubblesEvent;
|
|
4
|
-
const runtime_1 = require("
|
|
7
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
8
|
+
const render_1 = require("../../heart/attachments/render");
|
|
9
|
+
const bluebubbles_1 = require("../../heart/attachments/sources/bluebubbles");
|
|
10
|
+
const IGNORABLE_GUIDLESS_EVENT_TYPES = new Set([
|
|
11
|
+
"chat-read-status-changed",
|
|
12
|
+
]);
|
|
13
|
+
class BlueBubblesIgnoredEventError extends Error {
|
|
14
|
+
eventType;
|
|
15
|
+
constructor(eventType, message) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = "BlueBubblesIgnoredEventError";
|
|
18
|
+
this.eventType = eventType;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.BlueBubblesIgnoredEventError = BlueBubblesIgnoredEventError;
|
|
5
22
|
function asRecord(value) {
|
|
6
23
|
return value && typeof value === "object" && !Array.isArray(value)
|
|
7
24
|
? value
|
|
@@ -75,9 +92,11 @@ function buildChatRef(data, threadOriginatorGuid) {
|
|
|
75
92
|
}
|
|
76
93
|
function extractSender(data, chat) {
|
|
77
94
|
const handle = asRecord(data.handle) ?? asRecord(data.sender) ?? null;
|
|
78
|
-
const
|
|
95
|
+
const observedRawId = readString(handle, "address") ??
|
|
79
96
|
readString(handle, "id") ??
|
|
80
|
-
readString(data, "senderId")
|
|
97
|
+
readString(data, "senderId");
|
|
98
|
+
const observed = typeof observedRawId === "string" && observedRawId.trim().length > 0;
|
|
99
|
+
const rawId = observedRawId ??
|
|
81
100
|
chat.chatIdentifier ??
|
|
82
101
|
chat.chatGuid ??
|
|
83
102
|
"unknown";
|
|
@@ -88,6 +107,7 @@ function extractSender(data, chat) {
|
|
|
88
107
|
externalId,
|
|
89
108
|
rawId,
|
|
90
109
|
displayName,
|
|
110
|
+
observed,
|
|
91
111
|
};
|
|
92
112
|
}
|
|
93
113
|
function extractAttachments(data) {
|
|
@@ -107,18 +127,14 @@ function extractAttachments(data) {
|
|
|
107
127
|
function formatAttachmentText(attachments) {
|
|
108
128
|
if (attachments.length === 0)
|
|
109
129
|
return "";
|
|
130
|
+
const renderable = attachments
|
|
131
|
+
.filter((attachment) => typeof attachment.guid === "string" && attachment.guid.trim().length > 0)
|
|
132
|
+
.map((attachment) => (0, bluebubbles_1.buildBlueBubblesAttachmentRecord)(attachment));
|
|
133
|
+
if (renderable.length > 0) {
|
|
134
|
+
return (0, render_1.renderAttachmentBlock)(renderable);
|
|
135
|
+
}
|
|
110
136
|
const [first] = attachments;
|
|
111
|
-
|
|
112
|
-
const label = mime.startsWith("image/")
|
|
113
|
-
? "image attachment"
|
|
114
|
-
: mime.startsWith("audio/")
|
|
115
|
-
? "audio attachment"
|
|
116
|
-
: "attachment";
|
|
117
|
-
const name = first.transferName ? `: ${first.transferName}` : "";
|
|
118
|
-
const dimensions = typeof first.width === "number" && typeof first.height === "number" && first.width > 0 && first.height > 0
|
|
119
|
-
? ` (${first.width}x${first.height})`
|
|
120
|
-
: "";
|
|
121
|
-
return `[${label}${name}${dimensions}]`;
|
|
137
|
+
return `[attachment: ${first.transferName?.trim() || "unknown"}]`;
|
|
122
138
|
}
|
|
123
139
|
function formatMessageText(data, attachments) {
|
|
124
140
|
const text = readString(data, "text")?.trim() ?? "";
|
|
@@ -127,16 +143,91 @@ function formatMessageText(data, attachments) {
|
|
|
127
143
|
if (balloonBundleId === "com.apple.messages.URLBalloonProvider") {
|
|
128
144
|
return `${text}\n[link preview attached]`;
|
|
129
145
|
}
|
|
146
|
+
// B2 fix: when text and attachments both exist, append the attachment
|
|
147
|
+
// marker so downstream senses can see the guid/filename. Previously the
|
|
148
|
+
// marker was dropped whenever text was non-empty, which hid images from
|
|
149
|
+
// the agent when the user captioned a screenshot.
|
|
150
|
+
if (attachments.length > 0) {
|
|
151
|
+
return `${text}\n${formatAttachmentText(attachments)}`;
|
|
152
|
+
}
|
|
130
153
|
return text;
|
|
131
154
|
}
|
|
132
155
|
return formatAttachmentText(attachments);
|
|
133
156
|
}
|
|
134
157
|
function normalizeReactionName(value) {
|
|
158
|
+
// chat.db stores associated_message_type as an integer; BlueBubbles forwards it
|
|
159
|
+
// as either the integer, its decimal string, or a name ("love", "-love").
|
|
160
|
+
if (typeof value === "number") {
|
|
161
|
+
return Number.isFinite(value) && value !== 0 ? String(value) : undefined;
|
|
162
|
+
}
|
|
135
163
|
if (typeof value !== "string")
|
|
136
164
|
return undefined;
|
|
137
165
|
const trimmed = value.trim();
|
|
138
166
|
return trimmed ? trimmed.toLowerCase() : undefined;
|
|
139
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* iMessage tapbacks: associated_message_type 2000-2006 add a tapback, 3000-3006
|
|
170
|
+
* remove the same tapback. BlueBubbles may send either the code or the name.
|
|
171
|
+
*/
|
|
172
|
+
const REACTION_VOCABULARY = [
|
|
173
|
+
{ code: 2000, name: "love", verb: "loved", noun: "love" },
|
|
174
|
+
{ code: 2001, name: "like", verb: "liked", noun: "like" },
|
|
175
|
+
{ code: 2002, name: "dislike", verb: "disliked", noun: "dislike" },
|
|
176
|
+
{ code: 2003, name: "laugh", verb: "laughed at", noun: "laugh" },
|
|
177
|
+
{ code: 2004, name: "emphasize", verb: "emphasized", noun: "emphasis" },
|
|
178
|
+
{ code: 2005, name: "question", verb: "questioned", noun: "question" },
|
|
179
|
+
{ code: 2006, name: "custom", verb: "reacted with custom emoji to", noun: "custom emoji" },
|
|
180
|
+
];
|
|
181
|
+
const REACTION_EXCERPT_MAX_LENGTH = 80;
|
|
182
|
+
function describeBlueBubblesReaction(raw, rawTransportValue = raw) {
|
|
183
|
+
const stripped = raw.startsWith("-") ? raw.slice(1) : raw;
|
|
184
|
+
const code = /^\d+$/.test(stripped) ? Number(stripped) : undefined;
|
|
185
|
+
const removal = raw.startsWith("-") || (code !== undefined && code >= 3000 && code < 4000);
|
|
186
|
+
const action = removal ? "remove" : "add";
|
|
187
|
+
const entry = REACTION_VOCABULARY.find((candidate) => candidate.name === stripped || candidate.code === code || candidate.code + 1000 === code);
|
|
188
|
+
const canonicalValue = entry?.name ?? "unknown";
|
|
189
|
+
if (!entry)
|
|
190
|
+
return { raw, rawTransportValue, canonicalValue, action };
|
|
191
|
+
return {
|
|
192
|
+
raw,
|
|
193
|
+
rawTransportValue,
|
|
194
|
+
canonicalValue,
|
|
195
|
+
action,
|
|
196
|
+
verb: entry.verb,
|
|
197
|
+
noun: entry.noun,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function reactionExcerpt(text) {
|
|
201
|
+
return text.length > REACTION_EXCERPT_MAX_LENGTH
|
|
202
|
+
? `${text.slice(0, REACTION_EXCERPT_MAX_LENGTH - 3)}...`
|
|
203
|
+
: text;
|
|
204
|
+
}
|
|
205
|
+
function reactionTargetPhrase(target) {
|
|
206
|
+
const text = target.text?.trim();
|
|
207
|
+
if (text) {
|
|
208
|
+
const owner = target.fromMe === true ? "your" : target.fromMe === false ? "their" : "a";
|
|
209
|
+
return `${owner} message: "${reactionExcerpt(text)}"`;
|
|
210
|
+
}
|
|
211
|
+
// Never hand the agent a bare "reacted with love" stub — say plainly that the
|
|
212
|
+
// referent is missing so it can ask instead of guessing what was approved.
|
|
213
|
+
return target.guid
|
|
214
|
+
? `an unidentified message (target guid ${target.guid}; its text could not be resolved)`
|
|
215
|
+
: "an unidentified message (the reaction carried no target message reference)";
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Render a reaction as speech the agent can act on: what the tapback was, whether
|
|
219
|
+
* it was added or removed, and which message it points at.
|
|
220
|
+
*/
|
|
221
|
+
function renderBlueBubblesReactionText(reaction, target) {
|
|
222
|
+
const phrase = reactionTargetPhrase(target);
|
|
223
|
+
if (reaction.action === "remove") {
|
|
224
|
+
const noun = reaction.noun ?? reaction.raw.replace(/^-/, "");
|
|
225
|
+
return `removed their ${noun} reaction from ${phrase}`;
|
|
226
|
+
}
|
|
227
|
+
return reaction.verb
|
|
228
|
+
? `${reaction.verb} ${phrase}`
|
|
229
|
+
: `reacted with ${reaction.raw} to ${phrase}`;
|
|
230
|
+
}
|
|
140
231
|
function stripPartPrefix(guid) {
|
|
141
232
|
if (!guid)
|
|
142
233
|
return undefined;
|
|
@@ -144,10 +235,10 @@ function stripPartPrefix(guid) {
|
|
|
144
235
|
const marker = trimmed.lastIndexOf("/");
|
|
145
236
|
return marker >= 0 ? trimmed.slice(marker + 1) : trimmed;
|
|
146
237
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
238
|
+
// Reactions never reach here: `detectMutationType` returns "reaction" only when a
|
|
239
|
+
// reaction name was decoded, and that same name produces the descriptor the caller
|
|
240
|
+
// renders with `renderBlueBubblesReactionText` instead.
|
|
241
|
+
function buildMutationText(mutationType, data) {
|
|
151
242
|
if (mutationType === "edit") {
|
|
152
243
|
const editedText = readString(data, "text")?.trim() ?? "";
|
|
153
244
|
return editedText ? `edited message: ${editedText}` : "edited a message";
|
|
@@ -164,17 +255,35 @@ function detectMutationType(eventType, data, reactionName) {
|
|
|
164
255
|
if (reactionName)
|
|
165
256
|
return "reaction";
|
|
166
257
|
if (eventType === "updated-message") {
|
|
167
|
-
if (readNumber(data, "dateRetracted"))
|
|
258
|
+
if (readNumber(data, "dateRetracted") !== undefined)
|
|
168
259
|
return "unsend";
|
|
169
|
-
if (readNumber(data, "dateEdited"))
|
|
260
|
+
if (readNumber(data, "dateEdited") !== undefined)
|
|
170
261
|
return "edit";
|
|
171
|
-
if (readNumber(data, "dateRead"))
|
|
262
|
+
if (readNumber(data, "dateRead") !== undefined)
|
|
172
263
|
return "read";
|
|
173
|
-
if (readBoolean(data, "isDelivered") || readNumber(data, "dateDelivered"))
|
|
264
|
+
if (readBoolean(data, "isDelivered") || readNumber(data, "dateDelivered") !== undefined)
|
|
174
265
|
return "delivery";
|
|
175
266
|
}
|
|
176
267
|
return null;
|
|
177
268
|
}
|
|
269
|
+
function readProviderRevision(data) {
|
|
270
|
+
const value = data.revision;
|
|
271
|
+
if (typeof value !== "string" && typeof value !== "number")
|
|
272
|
+
return undefined;
|
|
273
|
+
const normalized = String(value).trim();
|
|
274
|
+
return normalized || undefined;
|
|
275
|
+
}
|
|
276
|
+
function mutationEffectiveTimestamp(mutationType, data) {
|
|
277
|
+
if (mutationType === "reaction")
|
|
278
|
+
return readNumber(data, "dateCreated");
|
|
279
|
+
if (mutationType === "edit")
|
|
280
|
+
return readNumber(data, "dateEdited");
|
|
281
|
+
if (mutationType === "unsend")
|
|
282
|
+
return readNumber(data, "dateRetracted");
|
|
283
|
+
if (mutationType === "read")
|
|
284
|
+
return readNumber(data, "dateRead");
|
|
285
|
+
return readNumber(data, "dateDelivered");
|
|
286
|
+
}
|
|
178
287
|
function normalizeBlueBubblesEvent(payload) {
|
|
179
288
|
const envelope = asRecord(payload);
|
|
180
289
|
const eventType = readString(envelope, "type")?.trim() ?? "";
|
|
@@ -198,16 +307,33 @@ function normalizeBlueBubblesEvent(payload) {
|
|
|
198
307
|
message: "ignored bluebubbles payload without guid",
|
|
199
308
|
meta: { eventType },
|
|
200
309
|
});
|
|
310
|
+
if (IGNORABLE_GUIDLESS_EVENT_TYPES.has(eventType)) {
|
|
311
|
+
throw new BlueBubblesIgnoredEventError(eventType, `Ignored BlueBubbles event '${eventType}' without data.guid`);
|
|
312
|
+
}
|
|
201
313
|
throw new Error("BlueBubbles payload is missing data.guid");
|
|
202
314
|
}
|
|
203
315
|
const threadOriginatorGuid = readString(data, "threadOriginatorGuid")?.trim() || undefined;
|
|
204
316
|
const chat = buildChatRef(data, threadOriginatorGuid);
|
|
205
317
|
const sender = extractSender(data, chat);
|
|
206
318
|
const timestamp = readNumber(data, "dateCreated") ?? Date.now();
|
|
207
|
-
const fromMe = readBoolean(data, "isFromMe") ??
|
|
319
|
+
const fromMe = readBoolean(data, "isFromMe") ?? null;
|
|
208
320
|
const attachments = extractAttachments(data);
|
|
209
321
|
const reactionName = normalizeReactionName(data.associatedMessageType);
|
|
322
|
+
const reaction = reactionName
|
|
323
|
+
? describeBlueBubblesReaction(reactionName, String(data.associatedMessageType))
|
|
324
|
+
: undefined;
|
|
325
|
+
const targetMessageGuid = reaction
|
|
326
|
+
? stripPartPrefix(readString(data, "associatedMessageGuid"))
|
|
327
|
+
: undefined;
|
|
210
328
|
const mutationType = detectMutationType(eventType, data, reactionName);
|
|
329
|
+
const revision = mutationType ? readProviderRevision(data) : undefined;
|
|
330
|
+
const effectiveTimestamp = mutationType
|
|
331
|
+
? mutationEffectiveTimestamp(mutationType, data)
|
|
332
|
+
: undefined;
|
|
333
|
+
const editedText = mutationType === "edit" ? readString(data, "text") : undefined;
|
|
334
|
+
const retractionTimestamp = mutationType === "unsend"
|
|
335
|
+
? readNumber(data, "dateRetracted")
|
|
336
|
+
: undefined;
|
|
211
337
|
const requiresRepair = (readBoolean(data, "hasPayloadData") ?? false) ||
|
|
212
338
|
attachments.length > 0 ||
|
|
213
339
|
eventType === "updated-message";
|
|
@@ -217,16 +343,21 @@ function normalizeBlueBubblesEvent(payload) {
|
|
|
217
343
|
eventType,
|
|
218
344
|
mutationType,
|
|
219
345
|
messageGuid,
|
|
220
|
-
targetMessageGuid
|
|
221
|
-
? stripPartPrefix(readString(data, "associatedMessageGuid"))
|
|
222
|
-
: undefined,
|
|
346
|
+
targetMessageGuid,
|
|
223
347
|
timestamp,
|
|
224
348
|
fromMe,
|
|
225
349
|
sender,
|
|
226
350
|
chat,
|
|
227
351
|
shouldNotifyAgent: mutationType === "reaction" || mutationType === "edit" || mutationType === "unsend",
|
|
228
|
-
textForAgent:
|
|
352
|
+
textForAgent: reaction
|
|
353
|
+
? renderBlueBubblesReactionText(reaction, { guid: targetMessageGuid })
|
|
354
|
+
: buildMutationText(mutationType, data),
|
|
229
355
|
requiresRepair,
|
|
356
|
+
...(reaction ? { reaction } : {}),
|
|
357
|
+
...(editedText !== undefined ? { editedText } : {}),
|
|
358
|
+
...(revision ? { revision } : {}),
|
|
359
|
+
...(effectiveTimestamp !== undefined ? { effectiveTimestamp } : {}),
|
|
360
|
+
...(retractionTimestamp !== undefined ? { retractionTimestamp } : {}),
|
|
230
361
|
}
|
|
231
362
|
: {
|
|
232
363
|
kind: "message",
|
|
@@ -236,7 +367,7 @@ function normalizeBlueBubblesEvent(payload) {
|
|
|
236
367
|
fromMe,
|
|
237
368
|
sender,
|
|
238
369
|
chat,
|
|
239
|
-
text: readString(data, "text")
|
|
370
|
+
text: readString(data, "text") ?? "",
|
|
240
371
|
textForAgent: formatMessageText(data, attachments),
|
|
241
372
|
attachments,
|
|
242
373
|
balloonBundleId: readString(data, "balloonBundleId")?.trim() || undefined,
|
|
@@ -35,12 +35,13 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.getBlueBubblesMutationLogPath = getBlueBubblesMutationLogPath;
|
|
37
37
|
exports.recordBlueBubblesMutation = recordBlueBubblesMutation;
|
|
38
|
+
exports.listRecordedBlueBubblesMutations = listRecordedBlueBubblesMutations;
|
|
38
39
|
exports.listBlueBubblesRecoveryCandidates = listBlueBubblesRecoveryCandidates;
|
|
39
40
|
const fs = __importStar(require("node:fs"));
|
|
40
41
|
const path = __importStar(require("node:path"));
|
|
41
|
-
const runtime_1 = require("
|
|
42
|
-
const identity_1 = require("
|
|
43
|
-
const config_1 = require("
|
|
42
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
43
|
+
const identity_1 = require("../../heart/identity");
|
|
44
|
+
const config_1 = require("../../heart/config");
|
|
44
45
|
function getBlueBubblesMutationLogPath(agentName, sessionKey) {
|
|
45
46
|
return path.join((0, identity_1.getAgentRoot)(agentName), "state", "senses", "bluebubbles", "mutations", `${(0, config_1.sanitizeKey)(sessionKey)}.ndjson`);
|
|
46
47
|
}
|
|
@@ -73,7 +74,7 @@ function recordBlueBubblesMutation(agentName, event) {
|
|
|
73
74
|
});
|
|
74
75
|
return filePath;
|
|
75
76
|
}
|
|
76
|
-
function
|
|
77
|
+
function readBlueBubblesMutationRows(agentName) {
|
|
77
78
|
const rootDir = path.join((0, identity_1.getAgentRoot)(agentName), "state", "senses", "bluebubbles", "mutations");
|
|
78
79
|
let files;
|
|
79
80
|
try {
|
|
@@ -82,7 +83,7 @@ function listBlueBubblesRecoveryCandidates(agentName) {
|
|
|
82
83
|
catch {
|
|
83
84
|
return [];
|
|
84
85
|
}
|
|
85
|
-
const
|
|
86
|
+
const entries = [];
|
|
86
87
|
for (const file of files.filter((entry) => entry.endsWith(".ndjson")).sort()) {
|
|
87
88
|
const filePath = path.join(rootDir, file);
|
|
88
89
|
let raw = "";
|
|
@@ -98,19 +99,29 @@ function listBlueBubblesRecoveryCandidates(agentName) {
|
|
|
98
99
|
continue;
|
|
99
100
|
try {
|
|
100
101
|
const entry = JSON.parse(trimmed);
|
|
101
|
-
if (typeof entry.messageGuid !== "string"
|
|
102
|
-
|| !entry.messageGuid.trim()
|
|
103
|
-
|| entry.fromMe
|
|
104
|
-
|| entry.shouldNotifyAgent
|
|
105
|
-
|| (entry.mutationType !== "read" && entry.mutationType !== "delivery")) {
|
|
102
|
+
if (typeof entry.messageGuid !== "string" || !entry.messageGuid.trim())
|
|
106
103
|
continue;
|
|
107
|
-
|
|
108
|
-
deduped.set(entry.messageGuid, entry);
|
|
104
|
+
entries.push(entry);
|
|
109
105
|
}
|
|
110
106
|
catch {
|
|
111
|
-
//
|
|
107
|
+
// Keep malformed legacy rows inert while retaining readable audit rows.
|
|
112
108
|
}
|
|
113
109
|
}
|
|
114
110
|
}
|
|
111
|
+
return entries;
|
|
112
|
+
}
|
|
113
|
+
function listRecordedBlueBubblesMutations(agentName) {
|
|
114
|
+
return readBlueBubblesMutationRows(agentName).filter((entry) => (typeof entry.sessionKey === "string" && entry.sessionKey.trim().length > 0));
|
|
115
|
+
}
|
|
116
|
+
function listBlueBubblesRecoveryCandidates(agentName) {
|
|
117
|
+
const deduped = new Map();
|
|
118
|
+
for (const entry of readBlueBubblesMutationRows(agentName)) {
|
|
119
|
+
if (entry.fromMe !== false
|
|
120
|
+
|| entry.shouldNotifyAgent
|
|
121
|
+
|| (entry.mutationType !== "read" && entry.mutationType !== "delivery")) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
deduped.set(entry.messageGuid, entry);
|
|
125
|
+
}
|
|
115
126
|
return [...deduped.values()].sort((left, right) => left.recordedAt.localeCompare(right.recordedAt));
|
|
116
127
|
}
|
|
@@ -0,0 +1,308 @@
|
|
|
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.BLUEBUBBLES_OUTBOUND_STATE_POLICY_VERSION = void 0;
|
|
37
|
+
exports.blueBubblesOutboundRecordPath = blueBubblesOutboundRecordPath;
|
|
38
|
+
exports.buildBlueBubblesRouteProof = buildBlueBubblesRouteProof;
|
|
39
|
+
exports.buildBlueBubblesAttachmentProof = buildBlueBubblesAttachmentProof;
|
|
40
|
+
exports.readBlueBubblesOutboundRecord = readBlueBubblesOutboundRecord;
|
|
41
|
+
exports.readBlueBubblesOutboundRecordByIdempotencyKey = readBlueBubblesOutboundRecordByIdempotencyKey;
|
|
42
|
+
exports.reserveBlueBubblesOutbound = reserveBlueBubblesOutbound;
|
|
43
|
+
exports.markBlueBubblesOutboundAccepted = markBlueBubblesOutboundAccepted;
|
|
44
|
+
exports.markBlueBubblesOutboundEnqueued = markBlueBubblesOutboundEnqueued;
|
|
45
|
+
exports.markBlueBubblesOutboundLocalVisible = markBlueBubblesOutboundLocalVisible;
|
|
46
|
+
exports.markBlueBubblesOutboundDelivered = markBlueBubblesOutboundDelivered;
|
|
47
|
+
exports.markBlueBubblesOutboundFailed = markBlueBubblesOutboundFailed;
|
|
48
|
+
exports.markBlueBubblesOutboundPendingManualVerification = markBlueBubblesOutboundPendingManualVerification;
|
|
49
|
+
const fs = __importStar(require("node:fs"));
|
|
50
|
+
const path = __importStar(require("node:path"));
|
|
51
|
+
const node_crypto_1 = require("node:crypto");
|
|
52
|
+
const runtime_1 = require("../../nerves/runtime");
|
|
53
|
+
exports.BLUEBUBBLES_OUTBOUND_STATE_POLICY_VERSION = "bluebubbles-outbound-state/v1";
|
|
54
|
+
function sha256Hex(input) {
|
|
55
|
+
return (0, node_crypto_1.createHash)("sha256").update(input).digest("hex");
|
|
56
|
+
}
|
|
57
|
+
function hash(input) {
|
|
58
|
+
return `sha256:${sha256Hex(canonicalJson(input))}`;
|
|
59
|
+
}
|
|
60
|
+
function canonicalJson(value) {
|
|
61
|
+
if (Array.isArray(value))
|
|
62
|
+
return `[${value.map((entry) => canonicalJson(entry)).join(",")}]`;
|
|
63
|
+
if (value && typeof value === "object") {
|
|
64
|
+
const record = value;
|
|
65
|
+
return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(",")}}`;
|
|
66
|
+
}
|
|
67
|
+
return JSON.stringify(value);
|
|
68
|
+
}
|
|
69
|
+
function nowIso(input) {
|
|
70
|
+
return input ?? new Date().toISOString();
|
|
71
|
+
}
|
|
72
|
+
function recordIdFor(idempotencyKey) {
|
|
73
|
+
return `bbout_${sha256Hex(`bluebubbles-outbound:${idempotencyKey}`).slice(0, 32)}`;
|
|
74
|
+
}
|
|
75
|
+
function normalizeText(value) {
|
|
76
|
+
return value.trim().replace(/\s+/g, " ");
|
|
77
|
+
}
|
|
78
|
+
function endpointOrigin(serverUrl) {
|
|
79
|
+
const parsed = new URL(serverUrl);
|
|
80
|
+
return parsed.origin;
|
|
81
|
+
}
|
|
82
|
+
function blueBubblesOutboundDir(agentRoot) {
|
|
83
|
+
return path.join(agentRoot, "state", "bluebubbles", "outbound");
|
|
84
|
+
}
|
|
85
|
+
function blueBubblesOutboundRecordPath(agentRoot, recordId) {
|
|
86
|
+
return path.join(blueBubblesOutboundDir(agentRoot), `${recordId}.json`);
|
|
87
|
+
}
|
|
88
|
+
function buildBlueBubblesRouteProof(chat) {
|
|
89
|
+
const participantHandles = [...chat.participantHandles].sort();
|
|
90
|
+
const base = {
|
|
91
|
+
chatGuid: chat.chatGuid?.trim() || null,
|
|
92
|
+
chatIdentifier: chat.chatIdentifier?.trim() || null,
|
|
93
|
+
sendTarget: chat.sendTarget,
|
|
94
|
+
sessionKey: chat.sessionKey,
|
|
95
|
+
isGroup: chat.isGroup,
|
|
96
|
+
participantHandles,
|
|
97
|
+
};
|
|
98
|
+
return {
|
|
99
|
+
chatGuid: base.chatGuid,
|
|
100
|
+
chatIdentifier: base.chatIdentifier,
|
|
101
|
+
sendTarget: base.sendTarget,
|
|
102
|
+
sessionKey: base.sessionKey,
|
|
103
|
+
isGroup: base.isGroup,
|
|
104
|
+
participantHandlesHash: hash(participantHandles),
|
|
105
|
+
routeHash: hash(base),
|
|
106
|
+
rawParticipantHandlesStored: false,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function buildBlueBubblesAttachmentProof(input) {
|
|
110
|
+
const proof = {
|
|
111
|
+
endpointOrigin: endpointOrigin(input.serverUrl),
|
|
112
|
+
accountId: input.accountId?.trim() || null,
|
|
113
|
+
};
|
|
114
|
+
return {
|
|
115
|
+
...proof,
|
|
116
|
+
identityHash: hash(proof),
|
|
117
|
+
secretStored: false,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function buildRecord(input) {
|
|
121
|
+
const createdAt = nowIso(input.now);
|
|
122
|
+
const idempotencyKey = input.idempotencyKey.trim();
|
|
123
|
+
const text = normalizeText(input.text);
|
|
124
|
+
return {
|
|
125
|
+
schemaVersion: 1,
|
|
126
|
+
policyVersion: exports.BLUEBUBBLES_OUTBOUND_STATE_POLICY_VERSION,
|
|
127
|
+
recordId: recordIdFor(idempotencyKey),
|
|
128
|
+
idempotencyKey,
|
|
129
|
+
idempotencyHash: hash(idempotencyKey),
|
|
130
|
+
status: "reserved",
|
|
131
|
+
createdAt,
|
|
132
|
+
updatedAt: createdAt,
|
|
133
|
+
tempGuid: input.tempGuid.trim(),
|
|
134
|
+
routeProof: buildBlueBubblesRouteProof(input.chat),
|
|
135
|
+
attachmentProof: buildBlueBubblesAttachmentProof(input.attachment),
|
|
136
|
+
textHash: hash(text),
|
|
137
|
+
textLength: text.length,
|
|
138
|
+
...(input.replyToMessageGuid?.trim() ? { replyToMessageGuidHash: hash(input.replyToMessageGuid.trim()) } : {}),
|
|
139
|
+
contentStored: false,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function writeJsonAtomic(filePath, value) {
|
|
143
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
144
|
+
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
145
|
+
fs.writeFileSync(tmp, `${JSON.stringify(value, null, 2)}\n`, "utf-8");
|
|
146
|
+
fs.renameSync(tmp, filePath);
|
|
147
|
+
}
|
|
148
|
+
function readJson(filePath) {
|
|
149
|
+
if (!fs.existsSync(filePath))
|
|
150
|
+
return null;
|
|
151
|
+
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
152
|
+
}
|
|
153
|
+
function isOutboundRecord(value) {
|
|
154
|
+
const row = value;
|
|
155
|
+
return !!row
|
|
156
|
+
&& row.schemaVersion === 1
|
|
157
|
+
&& row.policyVersion === exports.BLUEBUBBLES_OUTBOUND_STATE_POLICY_VERSION
|
|
158
|
+
&& typeof row.recordId === "string"
|
|
159
|
+
&& typeof row.idempotencyKey === "string"
|
|
160
|
+
&& typeof row.idempotencyHash === "string"
|
|
161
|
+
&& typeof row.status === "string"
|
|
162
|
+
&& typeof row.createdAt === "string"
|
|
163
|
+
&& typeof row.updatedAt === "string"
|
|
164
|
+
&& typeof row.tempGuid === "string"
|
|
165
|
+
&& typeof row.textHash === "string"
|
|
166
|
+
&& typeof row.textLength === "number"
|
|
167
|
+
&& row.contentStored === false;
|
|
168
|
+
}
|
|
169
|
+
function readBlueBubblesOutboundRecord(agentRoot, recordId) {
|
|
170
|
+
try {
|
|
171
|
+
const parsed = readJson(blueBubblesOutboundRecordPath(agentRoot, recordId));
|
|
172
|
+
return isOutboundRecord(parsed) ? parsed : null;
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function readBlueBubblesOutboundRecordByIdempotencyKey(agentRoot, idempotencyKey) {
|
|
179
|
+
return readBlueBubblesOutboundRecord(agentRoot, recordIdFor(idempotencyKey.trim()));
|
|
180
|
+
}
|
|
181
|
+
function writeBlueBubblesOutboundRecord(agentRoot, record) {
|
|
182
|
+
writeJsonAtomic(blueBubblesOutboundRecordPath(agentRoot, record.recordId), record);
|
|
183
|
+
return record;
|
|
184
|
+
}
|
|
185
|
+
function identityMatches(left, right) {
|
|
186
|
+
return left.routeProof.routeHash === right.routeProof.routeHash
|
|
187
|
+
&& left.attachmentProof.identityHash === right.attachmentProof.identityHash
|
|
188
|
+
&& left.textHash === right.textHash
|
|
189
|
+
&& left.replyToMessageGuidHash === right.replyToMessageGuidHash;
|
|
190
|
+
}
|
|
191
|
+
function emitDuplicate(record) {
|
|
192
|
+
(0, runtime_1.emitNervesEvent)({
|
|
193
|
+
level: "warn",
|
|
194
|
+
component: "senses",
|
|
195
|
+
event: "senses.bluebubbles_outbound_duplicate",
|
|
196
|
+
message: "duplicate bluebubbles outbound reservation suppressed",
|
|
197
|
+
meta: { recordId: record.recordId, status: record.status },
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
function markPendingManualVerification(agentRoot, record, decidedAt, reason) {
|
|
201
|
+
const updated = writeBlueBubblesOutboundRecord(agentRoot, {
|
|
202
|
+
...record,
|
|
203
|
+
status: "pending-manual-verification",
|
|
204
|
+
updatedAt: decidedAt,
|
|
205
|
+
manualVerificationReason: reason,
|
|
206
|
+
});
|
|
207
|
+
(0, runtime_1.emitNervesEvent)({
|
|
208
|
+
level: "warn",
|
|
209
|
+
component: "senses",
|
|
210
|
+
event: "senses.bluebubbles_outbound_pending_manual_verification",
|
|
211
|
+
message: "bluebubbles outbound requires manual verification",
|
|
212
|
+
meta: { recordId: updated.recordId, reason },
|
|
213
|
+
});
|
|
214
|
+
return updated;
|
|
215
|
+
}
|
|
216
|
+
function reserveBlueBubblesOutbound(input) {
|
|
217
|
+
const record = buildRecord(input);
|
|
218
|
+
const filePath = blueBubblesOutboundRecordPath(input.agentRoot, record.recordId);
|
|
219
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
220
|
+
try {
|
|
221
|
+
const fd = fs.openSync(filePath, "wx");
|
|
222
|
+
try {
|
|
223
|
+
fs.writeFileSync(fd, `${JSON.stringify(record, null, 2)}\n`, "utf-8");
|
|
224
|
+
}
|
|
225
|
+
finally {
|
|
226
|
+
fs.closeSync(fd);
|
|
227
|
+
}
|
|
228
|
+
(0, runtime_1.emitNervesEvent)({
|
|
229
|
+
component: "senses",
|
|
230
|
+
event: "senses.bluebubbles_outbound_reserved",
|
|
231
|
+
message: "reserved bluebubbles outbound idempotency key",
|
|
232
|
+
meta: { recordId: record.recordId, textLength: record.textLength },
|
|
233
|
+
});
|
|
234
|
+
return { status: "reserved", record };
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
/* v8 ignore next -- non-EEXIST filesystem failures are rethrown fail-closed; hard to trigger portably after mkdir succeeds @preserve */
|
|
238
|
+
if (!isNodeFileExistsError(error))
|
|
239
|
+
throw error;
|
|
240
|
+
const existing = readBlueBubblesOutboundRecord(input.agentRoot, record.recordId);
|
|
241
|
+
if (!existing)
|
|
242
|
+
throw new Error(`bluebubbles outbound reservation is unreadable: ${record.recordId}`);
|
|
243
|
+
if (identityMatches(existing, record)) {
|
|
244
|
+
emitDuplicate(existing);
|
|
245
|
+
return { status: "duplicate", record: existing };
|
|
246
|
+
}
|
|
247
|
+
const updated = markPendingManualVerification(input.agentRoot, existing, nowIso(input.now), "identity-proof-mismatch");
|
|
248
|
+
return { status: "pending-manual-verification", reason: "identity-proof-mismatch", record: updated };
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
function isNodeFileExistsError(error) {
|
|
252
|
+
return typeof error === "object" && error !== null && error.code === "EEXIST";
|
|
253
|
+
}
|
|
254
|
+
function updateStatus(agentRoot, recordId, status, updatedAt, patch) {
|
|
255
|
+
const existing = readBlueBubblesOutboundRecord(agentRoot, recordId);
|
|
256
|
+
if (!existing)
|
|
257
|
+
throw new Error(`bluebubbles outbound record not found: ${recordId}`);
|
|
258
|
+
const updated = writeBlueBubblesOutboundRecord(agentRoot, {
|
|
259
|
+
...existing,
|
|
260
|
+
...patch,
|
|
261
|
+
status,
|
|
262
|
+
updatedAt,
|
|
263
|
+
});
|
|
264
|
+
(0, runtime_1.emitNervesEvent)({
|
|
265
|
+
component: "senses",
|
|
266
|
+
event: "senses.bluebubbles_outbound_state_changed",
|
|
267
|
+
message: "bluebubbles outbound state changed",
|
|
268
|
+
meta: { recordId, status },
|
|
269
|
+
});
|
|
270
|
+
return updated;
|
|
271
|
+
}
|
|
272
|
+
function markBlueBubblesOutboundAccepted(input) {
|
|
273
|
+
return updateStatus(input.agentRoot, input.recordId, "accepted", input.acceptedAt, {
|
|
274
|
+
acceptedAt: input.acceptedAt,
|
|
275
|
+
...(input.messageGuid?.trim() ? { messageGuid: input.messageGuid.trim() } : {}),
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
function markBlueBubblesOutboundEnqueued(input) {
|
|
279
|
+
return updateStatus(input.agentRoot, input.recordId, "enqueued", input.enqueuedAt, {
|
|
280
|
+
enqueuedAt: input.enqueuedAt,
|
|
281
|
+
messageGuid: input.messageGuid.trim(),
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
function markBlueBubblesOutboundLocalVisible(input) {
|
|
285
|
+
return updateStatus(input.agentRoot, input.recordId, "local-visible", input.visibleAt, {
|
|
286
|
+
localVisibleAt: input.visibleAt,
|
|
287
|
+
messageGuid: input.messageGuid.trim(),
|
|
288
|
+
...(input.tempGuid?.trim() ? { tempGuid: input.tempGuid.trim() } : {}),
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
function markBlueBubblesOutboundDelivered(input) {
|
|
292
|
+
return updateStatus(input.agentRoot, input.recordId, "delivered", input.deliveredAt, {
|
|
293
|
+
deliveredAt: input.deliveredAt,
|
|
294
|
+
...(input.messageGuid?.trim() ? { messageGuid: input.messageGuid.trim() } : {}),
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
function markBlueBubblesOutboundFailed(input) {
|
|
298
|
+
return updateStatus(input.agentRoot, input.recordId, "failed", input.failedAt, {
|
|
299
|
+
failedAt: input.failedAt,
|
|
300
|
+
failureReason: input.reason.slice(0, 500),
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
function markBlueBubblesOutboundPendingManualVerification(input) {
|
|
304
|
+
const existing = readBlueBubblesOutboundRecord(input.agentRoot, input.recordId);
|
|
305
|
+
if (!existing)
|
|
306
|
+
throw new Error(`bluebubbles outbound record not found: ${input.recordId}`);
|
|
307
|
+
return markPendingManualVerification(input.agentRoot, existing, input.decidedAt, input.reason);
|
|
308
|
+
}
|