@ouro.bot/cli 0.1.0-alpha.99 → 0.1.0-alpha.991
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 +171 -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 +6257 -16
- package/deploy/unraid/Dockerfile +71 -0
- package/deploy/unraid/INSTALL.md +64 -0
- package/deploy/unraid/README.txt +3032 -0
- package/deploy/unraid/audit-container-spec.sh +4 -0
- package/deploy/unraid/container-runtime.json +1 -0
- package/deploy/unraid/credit-gateway.md +95 -0
- package/deploy/unraid/docker-man-template-transaction.mjs +727 -0
- package/deploy/unraid/docker-man-template-xml.cjs +105 -0
- package/deploy/unraid/github_known_hosts +3 -0
- package/deploy/unraid/install.sh +274 -0
- package/deploy/unraid/migrate-sanctuary-bundle.mjs +63 -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/ouro-sync-ssh +98 -0
- package/deploy/unraid/ouro-sync.sudoers +3 -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-butler-upgrade.mjs +1523 -0
- package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
- package/deploy/unraid/sanctuary-replay-gate.mjs +2467 -0
- package/deploy/unraid/sanctuary-safe-rename.py +24 -0
- package/deploy/unraid/sanctuary-sync-cutover.sh +1039 -0
- package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2088 -0
- package/deploy/unraid/sanctuary-unit16-run.sh +570 -0
- package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
- package/deploy/unraid/sanctuary.ouro/agent.json +67 -0
- package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
- package/deploy/unraid/sanctuary.ouro/awaiting/house-care-sweep.md +17 -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 +2255 -0
- package/deploy/unraid/sanctuary.ouro/product/PRODUCT.md +13 -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 +7 -0
- package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +7 -0
- package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +15 -0
- package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +3 -0
- package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
- package/deploy/unraid/sanctuary.ouro/tool-profiles.json +234 -0
- package/deploy/unraid/sanctuary.xml +30 -0
- package/dist/a2a/card.js +57 -0
- package/dist/a2a/client.js +290 -0
- package/dist/a2a/config.js +50 -0
- package/dist/a2a/delegated-command-grants.js +93 -0
- package/dist/a2a/delegated-command.js +197 -0
- package/dist/a2a/delegation-stores.js +56 -0
- package/dist/a2a/did-resolution.js +205 -0
- package/dist/a2a/escalation-grants.js +84 -0
- package/dist/a2a/escalation-wiring.js +60 -0
- package/dist/a2a/identity.js +258 -0
- package/dist/a2a/inbound-share.js +131 -0
- package/dist/a2a/mission-result-wire.js +265 -0
- package/dist/a2a/onboarding.js +133 -0
- package/dist/a2a/operator-trust.js +399 -0
- package/dist/a2a/outbox-client.js +59 -0
- package/dist/a2a/outbox-store.js +188 -0
- package/dist/a2a/outbox-wire.js +106 -0
- package/dist/a2a/pin-store.js +167 -0
- package/dist/a2a/refusals.js +53 -0
- package/dist/a2a/relay-client.js +106 -0
- package/dist/a2a/relay-config-vault.js +64 -0
- package/dist/a2a/relay-contacts.js +120 -0
- package/dist/a2a/relay-inbox.js +360 -0
- package/dist/a2a/relay-retirements.js +89 -0
- package/dist/a2a/replay-grant-holders.js +33 -0
- package/dist/a2a/replay-harness.js +188 -0
- package/dist/a2a/resolution-proof.js +53 -0
- package/dist/a2a/sealed-chat.js +114 -0
- package/dist/a2a/seen-ledger.js +214 -0
- package/dist/a2a/server.js +808 -0
- package/dist/a2a/task-store.js +69 -0
- package/dist/a2a/transport.js +100 -0
- package/dist/a2a/trust-commands.js +203 -0
- package/dist/a2a/trusted-files.js +185 -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/gateway/keys.js +117 -0
- package/dist/gateway/server.js +429 -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 +201 -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 +511 -0
- package/dist/heart/autonomy-budget.js +478 -0
- package/dist/heart/awaiting/a2a-await-delivery.js +109 -0
- package/dist/heart/awaiting/await-alert.js +152 -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 +152 -0
- package/dist/heart/awaiting/await-runtime-state.js +130 -0
- package/dist/heart/awaiting/await-scheduler.js +391 -0
- package/dist/heart/background-operations.js +281 -0
- package/dist/heart/bluebubbles-host-account.js +78 -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 +179 -131
- package/dist/heart/context-loss-gauntlet.js +387 -0
- package/dist/heart/context-loss-sentinel.js +1204 -0
- package/dist/heart/core.js +2378 -586
- package/dist/heart/cross-chat-delivery.js +9 -22
- package/dist/heart/daemon/agent-config-check.js +474 -0
- package/dist/heart/daemon/agent-discovery.js +287 -3
- package/dist/heart/daemon/agent-home.js +355 -0
- 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 +223 -0
- package/dist/heart/daemon/cadence.js +180 -0
- package/dist/heart/daemon/cli-arg-redaction.js +26 -0
- package/dist/heart/daemon/cli-defaults.js +881 -0
- package/dist/heart/daemon/cli-desk.js +331 -0
- package/dist/heart/daemon/cli-exec.js +9339 -0
- package/dist/heart/daemon/cli-help.js +766 -0
- package/dist/heart/daemon/cli-parse.js +3343 -0
- package/dist/heart/daemon/cli-render-doctor.js +57 -0
- package/dist/heart/daemon/cli-render.js +819 -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 +187 -0
- package/dist/heart/daemon/container-spec-auditor.js +257 -0
- package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
- package/dist/heart/daemon/daemon-cli.js +29 -2373
- package/dist/heart/daemon/daemon-entry.js +975 -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 +2110 -104
- package/dist/heart/daemon/desk-admin.js +420 -0
- package/dist/heart/daemon/dns-workflow.js +394 -0
- package/dist/heart/daemon/doctor-types.js +8 -0
- package/dist/heart/daemon/doctor.js +1766 -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 +154 -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 +6 -3
- package/dist/heart/daemon/ouro-entry.js +9 -3
- package/dist/heart/daemon/plugin-cli.js +432 -0
- package/dist/heart/daemon/process-manager.js +760 -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 +2662 -0
- package/dist/heart/daemon/sanctuary-acceptance-harness.js +1832 -0
- package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
- package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +956 -0
- package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
- package/dist/heart/daemon/sanctuary-authority-epoch.js +291 -0
- package/dist/heart/daemon/sanctuary-authority-installation.js +161 -0
- package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
- package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +1332 -0
- package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
- package/dist/heart/daemon/sanctuary-bundle-migration.js +974 -0
- package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
- package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +493 -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 +113 -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 +475 -0
- package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
- package/dist/heart/daemon/sanctuary-telegram-authority-service.js +676 -0
- package/dist/heart/daemon/sense-manager.js +786 -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 +503 -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 +1531 -0
- package/dist/heart/failure-reports.js +336 -0
- package/dist/heart/file-lock.js +109 -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 +271 -0
- package/dist/heart/frontend-socket-client.js +173 -0
- package/dist/heart/frontend-socket.js +434 -0
- package/dist/heart/frontend-turn-errors.js +20 -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 +239 -59
- package/dist/heart/kept-notes.js +289 -0
- package/dist/heart/kicks.js +1 -1
- package/dist/heart/machine-identity.js +175 -0
- package/dist/heart/mail-import-discovery.js +356 -0
- package/dist/heart/mailbox/mailbox-http-hooks.js +99 -0
- package/dist/heart/mailbox/mailbox-http-response.js +7 -0
- package/dist/heart/mailbox/mailbox-http-routes.js +406 -0
- package/dist/heart/mailbox/mailbox-http-static.js +103 -0
- package/dist/heart/mailbox/mailbox-http-transport.js +272 -0
- package/dist/heart/mailbox/mailbox-http.js +99 -0
- package/dist/heart/mailbox/mailbox-read.js +41 -0
- package/dist/heart/mailbox/mailbox-supervision.js +131 -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 +760 -0
- package/dist/heart/migrate-config.js +100 -0
- package/dist/heart/model-capabilities.js +83 -16
- package/dist/heart/orientation-frame.js +376 -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 +260 -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 +266 -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 +248 -67
- package/dist/heart/providers/azure.js +23 -11
- package/dist/heart/providers/error-classification.js +129 -0
- package/dist/heart/providers/github-copilot.js +38 -39
- 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/reach-channel.js +85 -0
- package/dist/heart/reply-style.js +52 -0
- package/dist/heart/run-ledger.js +247 -0
- package/dist/heart/runtime-capability-check.js +170 -0
- package/dist/heart/runtime-credentials.js +608 -0
- package/dist/heart/runtime-cwd.js +87 -0
- package/dist/heart/sense-truth.js +24 -4
- package/dist/heart/session-activity.js +94 -24
- package/dist/heart/session-events.js +1521 -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/shelf-claims.js +78 -0
- package/dist/heart/shepherd/custody-types.js +2 -0
- package/dist/heart/shepherd/mandates.js +352 -0
- package/dist/heart/shepherd/operation-commands.js +19 -0
- package/dist/heart/shepherd/operations.js +135 -0
- package/dist/heart/shepherd/supervision.js +114 -0
- package/dist/heart/shepherd/types.js +2 -0
- package/dist/heart/shepherd-config.js +123 -0
- package/dist/heart/source-grounding.js +313 -0
- package/dist/heart/start-of-turn-packet.js +372 -0
- package/dist/heart/steward-policy.js +656 -0
- package/dist/heart/streaming.js +631 -207
- package/dist/heart/structured-output.js +196 -0
- package/dist/heart/sync-classification.js +176 -0
- package/dist/heart/sync-health.js +152 -0
- package/dist/heart/sync-lock.js +431 -0
- package/dist/heart/sync.js +1579 -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 +206 -0
- package/dist/heart/tool-output-budget.js +41 -0
- package/dist/heart/turn-context.js +496 -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 +3 -2
- 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 +432 -0
- package/dist/heart/versioning/release-sources.js +173 -0
- package/dist/heart/versioning/self-update-defaults.js +294 -0
- package/dist/heart/versioning/self-update.js +196 -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/update-state.js +126 -0
- package/dist/heart/versioning/updater-launchd.js +150 -0
- package/dist/heart/versioning/version-intent.js +114 -0
- package/dist/heart/work-card.js +380 -0
- package/dist/mailbox-ui/assets/index-Dbska1tZ.js +1 -0
- package/dist/mailbox-ui/assets/index-DsiKaPyH.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 +25 -2
- package/dist/mind/context.js +328 -139
- 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/friend-link-codes.js +209 -0
- package/dist/mind/friend-merge.js +336 -0
- package/dist/mind/house-names.js +43 -0
- package/dist/mind/{associative-recall.js → note-search.js} +47 -58
- package/dist/mind/obligation-steering.js +199 -3
- package/dist/mind/outbound-record.js +168 -0
- 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 +1222 -203
- 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 +622 -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 +143 -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 +1199 -0
- package/dist/repertoire/bundle-templates.js +71 -0
- package/dist/repertoire/bw-installer.js +231 -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 +146 -34
- package/dist/repertoire/coding/index.js +15 -3
- package/dist/repertoire/coding/manager.js +159 -10
- package/dist/repertoire/coding/spawner.js +40 -11
- package/dist/repertoire/coding/tools.js +182 -18
- 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 +183 -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 +1480 -22
- package/dist/repertoire/house-sweep.js +471 -0
- package/dist/repertoire/mcp-client.js +58 -5
- package/dist/repertoire/mcp-manager.js +427 -139
- package/dist/repertoire/mcp-tools.js +132 -0
- package/dist/repertoire/mcp-write-guard.js +46 -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/sanctuary-container-policy.js +50 -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 +182 -0
- package/dist/repertoire/tool-results.js +29 -0
- package/dist/repertoire/tools-a2a.js +742 -0
- package/dist/repertoire/tools-attachments.js +322 -0
- package/dist/repertoire/tools-awaiting.js +897 -0
- package/dist/repertoire/tools-base.js +83 -1168
- package/dist/repertoire/tools-bluebubbles.js +2 -0
- package/dist/repertoire/tools-bridge.js +144 -0
- package/dist/repertoire/tools-bundle.js +917 -0
- package/dist/repertoire/tools-commerce.js +253 -0
- package/dist/repertoire/tools-config.js +186 -0
- package/dist/repertoire/tools-continuity.js +588 -0
- package/dist/repertoire/tools-credential.js +383 -0
- package/dist/repertoire/tools-escalation.js +84 -0
- package/dist/repertoire/tools-evolution.js +527 -0
- package/dist/repertoire/tools-files.js +362 -0
- package/dist/repertoire/tools-flight.js +290 -0
- package/dist/repertoire/tools-flow.js +119 -0
- package/dist/repertoire/tools-friend-link.js +57 -0
- package/dist/repertoire/tools-github.js +3 -8
- package/dist/repertoire/tools-habits.js +103 -0
- package/dist/repertoire/tools-house-care.js +174 -0
- package/dist/repertoire/tools-mail.js +1828 -0
- package/dist/repertoire/tools-notes.js +501 -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 +238 -0
- package/dist/repertoire/tools-sanctuary-host.js +202 -0
- package/dist/repertoire/tools-session.js +1141 -0
- package/dist/repertoire/tools-shell.js +154 -0
- package/dist/repertoire/tools-shepherd-guidance.js +171 -0
- package/dist/repertoire/tools-shepherd.js +325 -0
- package/dist/repertoire/tools-steward-policy.js +147 -0
- package/dist/repertoire/tools-stripe.js +224 -0
- package/dist/repertoire/tools-surface.js +369 -0
- package/dist/repertoire/tools-teams.js +50 -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 +556 -0
- package/dist/repertoire/tools-user-profile.js +146 -0
- package/dist/repertoire/tools-vault.js +40 -0
- package/dist/repertoire/tools-voice-local.js +198 -0
- package/dist/repertoire/tools-voice.js +145 -0
- package/dist/repertoire/tools.js +523 -156
- 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 +686 -0
- package/dist/rsvp/aisleplanner-client.js +354 -0
- package/dist/rsvp/cli.js +936 -0
- package/dist/rsvp/config.js +327 -0
- package/dist/rsvp/cutover.js +453 -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 +140 -0
- package/dist/senses/acp-server.js +386 -0
- package/dist/senses/attention-queue.js +186 -0
- package/dist/senses/await-turn-message.js +65 -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} +393 -43
- 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/host-account-verifier.js +88 -0
- package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
- package/dist/senses/bluebubbles/index.js +4054 -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 +335 -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 +257 -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 +570 -309
- 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 +1192 -204
- package/dist/senses/private-runtime-worker.js +857 -0
- package/dist/senses/private-runtime.js +1622 -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 +786 -0
- package/dist/senses/sanctuary-health-runner.js +106 -0
- package/dist/senses/sanctuary-health.js +442 -0
- package/dist/senses/sanctuary-house.js +97 -0
- package/dist/senses/sanctuary-install-state-contract.js +169 -0
- package/dist/senses/sanctuary-interactive-control.js +410 -0
- package/dist/senses/sanctuary-media-catalog-contract.js +268 -0
- package/dist/senses/sanctuary-media-optimization.js +517 -0
- package/dist/senses/sanctuary-runtime.js +390 -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 +832 -0
- package/dist/senses/shepherd/agent-presentation.js +88 -0
- package/dist/senses/shepherd/attention-page.js +166 -0
- package/dist/senses/shepherd/attention-sidebar.js +76 -0
- package/dist/senses/shepherd/attention.js +295 -0
- package/dist/senses/shepherd/checkin-config.js +76 -0
- package/dist/senses/shepherd/checkin-store.js +386 -0
- package/dist/senses/shepherd/client.js +196 -0
- package/dist/senses/shepherd/cmux.js +483 -0
- package/dist/senses/shepherd/composer.js +336 -0
- package/dist/senses/shepherd/copilot-app.js +648 -0
- package/dist/senses/shepherd/feedback-reply.js +108 -0
- package/dist/senses/shepherd/feedback-source.js +20 -0
- package/dist/senses/shepherd/feedback-store.js +331 -0
- package/dist/senses/shepherd/feedback-submit.js +182 -0
- package/dist/senses/shepherd/feedback-worker.js +208 -0
- package/dist/senses/shepherd/guidance.js +273 -0
- package/dist/senses/shepherd/herdr.js +427 -0
- package/dist/senses/shepherd/host.js +17 -0
- package/dist/senses/shepherd/human-decision-guard.js +29 -0
- package/dist/senses/shepherd/judge-evaluation-command.js +183 -0
- package/dist/senses/shepherd/judge-evaluation-entry.js +13 -0
- package/dist/senses/shepherd/judge-evaluation.js +155 -0
- package/dist/senses/shepherd/judge.js +210 -0
- package/dist/senses/shepherd/notice-outbox.js +262 -0
- package/dist/senses/shepherd/observation-publisher.js +320 -0
- package/dist/senses/shepherd/operations-defaults.js +86 -0
- package/dist/senses/shepherd/operations.js +159 -0
- package/dist/senses/shepherd/owner-notice.js +489 -0
- package/dist/senses/shepherd/prompt-state.js +60 -0
- package/dist/senses/shepherd/recovery.js +543 -0
- package/dist/senses/shepherd/redact.js +66 -0
- package/dist/senses/shepherd/returns.js +79 -0
- package/dist/senses/shepherd/sense.js +849 -0
- package/dist/senses/shepherd/shepherd-judge-corpus-v1.json +170 -0
- package/dist/senses/shepherd/surface.js +123 -0
- package/dist/senses/shepherd/target-binding.js +13 -0
- package/dist/senses/shepherd/terminal-process.js +147 -0
- package/dist/senses/shepherd-entry.js +98 -0
- package/dist/senses/surface-tool.js +109 -0
- package/dist/senses/teams-entry.js +68 -8
- package/dist/senses/teams-image.js +119 -0
- package/dist/senses/teams.js +998 -337
- 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 +1755 -0
- package/dist/senses/telegram-effect-adapter.js +904 -0
- package/dist/senses/telegram-entry.js +83 -0
- package/dist/senses/telegram-handoff.js +154 -0
- package/dist/senses/telegram.js +2474 -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/call-auth.js +250 -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/local-audio-control.js +344 -0
- package/dist/senses/voice/local-audio-devices.js +516 -0
- package/dist/senses/voice/local-audio-disclosure.js +174 -0
- package/dist/senses/voice/local-audio-identity.js +103 -0
- package/dist/senses/voice/local-audio-join.js +325 -0
- package/dist/senses/voice/local-audio-mute.js +199 -0
- package/dist/senses/voice/local-audio-notify.js +124 -0
- package/dist/senses/voice/local-audio-prompts.js +116 -0
- package/dist/senses/voice/local-audio-transport.js +427 -0
- package/dist/senses/voice/local-audio.js +281 -0
- package/dist/senses/voice/local-media-stream.js +145 -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/process-guards.js +51 -0
- package/dist/senses/voice/realtime-eval.js +496 -0
- package/dist/senses/voice/realtime-tool-schema.js +195 -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 +836 -0
- package/dist/senses/voice/twilio-phone.js +5454 -0
- package/dist/senses/voice/types.js +2 -0
- package/dist/senses/voice/whisper.js +161 -0
- package/dist/senses/voice-entry.js +83 -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 +8342 -0
- package/package.json +76 -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 -381
- 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
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RELAY_MAX_PER_TICK = exports.RELAY_MAX_BACKOFF_MS = exports.RELAY_POLL_INTERVAL_MS = void 0;
|
|
4
|
+
exports.memoryRelayRetirements = memoryRelayRetirements;
|
|
5
|
+
exports.ensureRelayRegistration = ensureRelayRegistration;
|
|
6
|
+
exports.rebuildRelayedMessage = rebuildRelayedMessage;
|
|
7
|
+
exports.drainRelayInbox = drainRelayInbox;
|
|
8
|
+
exports.retirePreviousRegistrations = retirePreviousRegistrations;
|
|
9
|
+
exports.startRelayInbox = startRelayInbox;
|
|
10
|
+
const node_crypto_1 = require("node:crypto");
|
|
11
|
+
const runtime_1 = require("../nerves/runtime");
|
|
12
|
+
const relay_client_1 = require("./relay-client");
|
|
13
|
+
const refusals_1 = require("./refusals");
|
|
14
|
+
const seen_ledger_1 = require("./seen-ledger");
|
|
15
|
+
const registrationKey = (registration) => `${registration.relayUrl}\n${registration.handle}`;
|
|
16
|
+
const sameRegistration = (a, b) => registrationKey(a) === registrationKey(b);
|
|
17
|
+
/** Retirement records kept in memory only (the default, and for tests). */
|
|
18
|
+
function memoryRelayRetirements() {
|
|
19
|
+
const records = new Map();
|
|
20
|
+
return {
|
|
21
|
+
read: (registration) => ({ ...records.get(registrationKey(registration)) }),
|
|
22
|
+
write: (registration, record) => { records.set(registrationKey(registration), { ...record }); },
|
|
23
|
+
clear: (registration) => { records.delete(registrationKey(registration)); },
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
exports.RELAY_POLL_INTERVAL_MS = 30_000;
|
|
27
|
+
exports.RELAY_MAX_BACKOFF_MS = 5 * 60_000;
|
|
28
|
+
exports.RELAY_MAX_PER_TICK = 20;
|
|
29
|
+
function errorText(error) {
|
|
30
|
+
/* v8 ignore next -- the relay client and the vault only throw Error instances @preserve */
|
|
31
|
+
return error instanceof Error ? error.message : String(error);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Make sure this agent holds a registration on the configured relay, registering when there is none, when the relay
|
|
35
|
+
* URL changed, or when the operator supplied an invite token. Returns the registration to poll, or null.
|
|
36
|
+
*/
|
|
37
|
+
async function ensureRelayRegistration(input) {
|
|
38
|
+
const config = await input.config.read();
|
|
39
|
+
const url = config.url;
|
|
40
|
+
const current = config.registration;
|
|
41
|
+
if (!url)
|
|
42
|
+
return null;
|
|
43
|
+
if (current && current.relayUrl === url && !config.inviteToken)
|
|
44
|
+
return current;
|
|
45
|
+
const handle = config.pendingRegistration?.relayUrl === url
|
|
46
|
+
? config.pendingRegistration.handle
|
|
47
|
+
: current?.relayUrl === url ? current.handle : (0, node_crypto_1.randomBytes)(16).toString("hex");
|
|
48
|
+
try {
|
|
49
|
+
await input.config.write({ pendingRegistration: { relayUrl: url, handle } });
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_config_write_failed", message: "could not record the pending relay registration; a retry may pick a new handle", meta: { handle, error: errorText(error) } });
|
|
53
|
+
}
|
|
54
|
+
let grant;
|
|
55
|
+
try {
|
|
56
|
+
grant = await (0, relay_client_1.relayRegister)({ url, handle, did: input.did, agentCard: { name: input.agentName, did: input.did }, inviteToken: config.inviteToken, fetchImpl: input.fetchImpl });
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_register_failed", message: "relay registration failed; offline messages wait until it succeeds", meta: { relayUrl: url, error: errorText(error) } });
|
|
60
|
+
// Keep using a registration that still exists (the old relay, or the same relay before a rotation).
|
|
61
|
+
return current ?? null;
|
|
62
|
+
}
|
|
63
|
+
const registration = { relayUrl: url, handle, inboxAuth: grant.inboxAuth, sendCredential: grant.sendCredential };
|
|
64
|
+
const moved = current !== undefined && current.relayUrl !== url;
|
|
65
|
+
try {
|
|
66
|
+
// Re-read so an invite token the operator set meanwhile survives. A move never waits for older relays: each one
|
|
67
|
+
// moved away from joins the list and is retired on its own.
|
|
68
|
+
const latest = await input.config.read();
|
|
69
|
+
await input.config.write({
|
|
70
|
+
registration,
|
|
71
|
+
pendingRegistration: undefined,
|
|
72
|
+
...(latest.inviteToken !== undefined && latest.inviteToken === config.inviteToken ? { inviteToken: undefined } : {}),
|
|
73
|
+
...(moved ? { previousRegistrations: [...(latest.previousRegistrations ?? []).filter((r) => !sameRegistration(r, current)), current] } : {}),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
(0, runtime_1.emitNervesEvent)({ level: "error", component: "channels", event: "channel.a2a_relay_config_write_failed", message: "registered at the relay but could not save the credentials; they last only until this process stops", meta: { relayUrl: url, handle, error: errorText(error) } });
|
|
78
|
+
}
|
|
79
|
+
return registration;
|
|
80
|
+
}
|
|
81
|
+
/** The single DataPart of a queued message, rebuilt into a fresh message so nothing else the relay added survives. */
|
|
82
|
+
function rebuildRelayedMessage(queued) {
|
|
83
|
+
const raw = queued;
|
|
84
|
+
if (!raw || typeof raw !== "object" || typeof raw.messageId !== "string" || !Array.isArray(raw.parts) || raw.parts.length !== 1)
|
|
85
|
+
return null;
|
|
86
|
+
const part = raw.parts[0];
|
|
87
|
+
if (!part || part.kind !== "data" || !part.data || typeof part.data !== "object")
|
|
88
|
+
return null;
|
|
89
|
+
const nonce = part.data.sealed?.n;
|
|
90
|
+
return {
|
|
91
|
+
message: { kind: "message", role: "agent", messageId: raw.messageId, parts: [{ kind: "data", data: part.data }] },
|
|
92
|
+
...(typeof nonce === "string" ? { nonce } : {}),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Pull up to `RELAY_MAX_PER_TICK` queued messages and run each through `handle`, one at a time. A message is acked
|
|
97
|
+
* once handled or refused for good; it stays queued after a retryable refusal, and after a throw that came before
|
|
98
|
+
* friends verified it (its seal nonce is not in the seen ledger). A throw ends the pass and asks for back-off.
|
|
99
|
+
*/
|
|
100
|
+
async function drainRelayInbox(input) {
|
|
101
|
+
const { registration } = input;
|
|
102
|
+
const call = { url: registration.relayUrl, handle: registration.handle, inboxAuth: registration.inboxAuth, fetchImpl: input.fetchImpl };
|
|
103
|
+
let queued;
|
|
104
|
+
try {
|
|
105
|
+
queued = await (0, relay_client_1.relayPull)(call);
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (error instanceof relay_client_1.RelayHttpError && error.status === 401) {
|
|
109
|
+
(0, runtime_1.emitNervesEvent)({ level: "error", component: "channels", event: "channel.a2a_relay_unauthorized", message: "the relay no longer accepts this agent's inbox credential; polling stopped. To register again, set a new a2a.relay.inviteToken and restart the A2A sense", meta: { relayUrl: registration.relayUrl } });
|
|
110
|
+
return "stop";
|
|
111
|
+
}
|
|
112
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_pull_failed", message: "could not pull the relay inbox", meta: { relayUrl: registration.relayUrl, error: errorText(error) } });
|
|
113
|
+
return "backoff";
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
return await deliverQueued(call, queued, input);
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_ack_failed", message: "could not ack a relayed message; it may be delivered again and is then refused as a replay", meta: { relayUrl: registration.relayUrl, error: errorText(error) } });
|
|
120
|
+
return "backoff";
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/** Run up to `RELAY_MAX_PER_TICK` pulled messages through `handle`, acking each one done. A failed ack throws. */
|
|
124
|
+
async function deliverQueued(call, queued, input) {
|
|
125
|
+
for (const item of queued.slice(0, exports.RELAY_MAX_PER_TICK)) {
|
|
126
|
+
const rebuilt = rebuildRelayedMessage(item.message);
|
|
127
|
+
if (!rebuilt) {
|
|
128
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_message_dropped", message: "dropped a relayed message that is not a single sealed data part", meta: { queueId: item.queueId } });
|
|
129
|
+
await (0, relay_client_1.relayAck)({ ...call, queueId: item.queueId });
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
let response;
|
|
133
|
+
try {
|
|
134
|
+
response = await input.handle({ jsonrpc: "2.0", id: item.queueId, method: "message/send", params: { message: rebuilt.message } });
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
const verified = rebuilt.nonce !== undefined && input.seen(rebuilt.nonce);
|
|
138
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_message_failed", message: verified ? "a relayed message failed after it was verified; it cannot run again, so it is acked" : "a relayed message failed before it was verified; it stays queued", meta: { queueId: item.queueId, error: errorText(error) } });
|
|
139
|
+
if (verified)
|
|
140
|
+
await (0, relay_client_1.relayAck)({ ...call, queueId: item.queueId });
|
|
141
|
+
return "backoff";
|
|
142
|
+
}
|
|
143
|
+
const refusal = "error" in response ? response.error.message : undefined;
|
|
144
|
+
// A receive refusal that can pass on a later try (refusals.ts marks it retry: a copy being handled right now) stays
|
|
145
|
+
// queued. Any other answer is final and is acked, including errors that merely carry `retry` (a delegated-command
|
|
146
|
+
// refusal is already marked seen, so a retry could only come back as a replay).
|
|
147
|
+
if ("error" in response && (0, refusals_1.isRetryableReceiveRefusal)(response.error.data)) {
|
|
148
|
+
(0, runtime_1.emitNervesEvent)({ component: "channels", event: "channel.a2a_relay_message_deferred", message: "a relayed message was refused for now; it stays queued", meta: { queueId: item.queueId, refusal } });
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
await (0, relay_client_1.relayAck)({ ...call, queueId: item.queueId });
|
|
152
|
+
(0, runtime_1.emitNervesEvent)({ component: "channels", event: "channel.a2a_relay_message_delivered", message: refusal ? "a relayed message was refused and acked" : "delivered a relayed message", meta: { queueId: item.queueId, ...(refusal ? { refusal } : {}) } });
|
|
153
|
+
}
|
|
154
|
+
return "ok";
|
|
155
|
+
}
|
|
156
|
+
/** The relay itself (its own JSON error) says it does not know this registration: it was deregistered or lost. */
|
|
157
|
+
function forgottenByRelay(error) {
|
|
158
|
+
return error instanceof relay_client_1.RelayHttpError && error.fromRelay && (error.status === 401 || error.status === 404);
|
|
159
|
+
}
|
|
160
|
+
function attempt(what, fn) {
|
|
161
|
+
try {
|
|
162
|
+
fn();
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_retirement_record_failed", message: `could not ${what} the local record of a relay retirement`, meta: { error: errorText(error) } });
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const ENVELOPE_MAX_AGE_DAYS = seen_ledger_1.MAX_ENVELOPE_AGE_MS / (24 * 60 * 60 * 1000);
|
|
171
|
+
async function tellOwnerLost(previous, why, input) {
|
|
172
|
+
if (!input.notifyOwner)
|
|
173
|
+
return;
|
|
174
|
+
const noticeId = `a2a-relay-gone-${(0, node_crypto_1.createHash)("sha256").update(registrationKey(previous)).digest("hex").slice(0, 16)}`;
|
|
175
|
+
const text = `I moved to a new relay for messages that arrive while I'm offline, but ${why}, so any messages still waiting there are lost. Anyone who sent one will need to send it again; new messages reach me through the new relay or directly.`;
|
|
176
|
+
await input.notifyOwner({ noticeId, text }).catch((error) => {
|
|
177
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_owner_notice_failed", message: "could not tell the owner that the previous relay was gone", meta: { relayUrl: previous.relayUrl, error: errorText(error) } });
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* One previous registration at its relay: drain the old inbox until a pull comes back empty, then deregister
|
|
182
|
+
* (deregistering deletes whatever is still queued). Returns "retired" once that is done or the relay is gone, and
|
|
183
|
+
* "kept" to try again at the next start.
|
|
184
|
+
*
|
|
185
|
+
* Gone means either the relay's own JSON 401 or 404 (it no longer knows this registration), or attempts failing in any
|
|
186
|
+
* other way (refused connection, DNS, 5xx, TLS, timeout, an answer that is not the relay's) with no successful pull or
|
|
187
|
+
* deregistration for longer than `MAX_ENVELOPE_AGE_MS`: anything queued there that long could no longer be accepted
|
|
188
|
+
* anyway. A successful pull or deregistration restarts that clock. The owner is told messages were lost only when
|
|
189
|
+
* this run saw the old inbox holding messages it could not drain, or the relay stayed unreachable past the window.
|
|
190
|
+
*/
|
|
191
|
+
async function retireAtRelay(previous, input, retirements, now) {
|
|
192
|
+
let record = {};
|
|
193
|
+
attempt("read", () => { record = retirements.read(previous); });
|
|
194
|
+
if (record.retired)
|
|
195
|
+
return "retired";
|
|
196
|
+
const save = (next) => {
|
|
197
|
+
record = next;
|
|
198
|
+
attempt("save", () => retirements.write(previous, next));
|
|
199
|
+
};
|
|
200
|
+
const inbox = { url: previous.relayUrl, handle: previous.handle, inboxAuth: previous.inboxAuth, fetchImpl: input.fetchImpl, timeoutMs: input.relayTimeoutMs };
|
|
201
|
+
const progressed = () => { if (record.firstFailedAt !== undefined)
|
|
202
|
+
save({}); };
|
|
203
|
+
let holding = false;
|
|
204
|
+
try {
|
|
205
|
+
let queued = await (0, relay_client_1.relayPull)(inbox);
|
|
206
|
+
progressed();
|
|
207
|
+
while (queued.length > 0) {
|
|
208
|
+
holding = true;
|
|
209
|
+
if (await deliverQueued(inbox, queued, input) === "backoff")
|
|
210
|
+
return "kept";
|
|
211
|
+
const after = await (0, relay_client_1.relayPull)(inbox);
|
|
212
|
+
if (after.length >= queued.length) {
|
|
213
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_previous_kept", message: "the previous relay still holds messages this agent cannot handle yet; it is kept and tried again at the next start", meta: { relayUrl: previous.relayUrl, queued: after.length } });
|
|
214
|
+
return "kept";
|
|
215
|
+
}
|
|
216
|
+
queued = after;
|
|
217
|
+
}
|
|
218
|
+
holding = false;
|
|
219
|
+
await (0, relay_client_1.relayDeregister)(inbox);
|
|
220
|
+
save({ retired: true });
|
|
221
|
+
return "retired";
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
if (forgottenByRelay(error)) {
|
|
225
|
+
// Recorded before the owner is told, so a crash after the notice does not send it twice.
|
|
226
|
+
save({ retired: true });
|
|
227
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_previous_gone", message: "the previous relay no longer knows this agent; its registration is retired", meta: { relayUrl: previous.relayUrl, reason: error.message, lost: holding } });
|
|
228
|
+
if (holding)
|
|
229
|
+
await tellOwnerLost(previous, `my old relay (${new URL(previous.relayUrl).host}) no longer knows me`, input);
|
|
230
|
+
return "retired";
|
|
231
|
+
}
|
|
232
|
+
const firstFailedAt = record.firstFailedAt ?? now;
|
|
233
|
+
if (record.firstFailedAt === undefined)
|
|
234
|
+
save({ firstFailedAt });
|
|
235
|
+
if (now - firstFailedAt > seen_ledger_1.MAX_ENVELOPE_AGE_MS) {
|
|
236
|
+
save({ retired: true });
|
|
237
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_previous_gone", message: `the previous relay has failed every attempt for more than ${ENVELOPE_MAX_AGE_DAYS} days; its registration is retired, and anything still queued there is lost`, meta: { relayUrl: previous.relayUrl, reason: errorText(error), lost: true, firstFailedAt: new Date(firstFailedAt).toISOString() } });
|
|
238
|
+
await tellOwnerLost(previous, `my old relay (${new URL(previous.relayUrl).host}) couldn't be reached for more than ${ENVELOPE_MAX_AGE_DAYS} days`, input);
|
|
239
|
+
return "retired";
|
|
240
|
+
}
|
|
241
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_previous_retire_failed", message: `could not retire the registration on the previous relay this time; it is tried again at each start, and retired anyway once attempts have failed for more than ${ENVELOPE_MAX_AGE_DAYS} days in a row`, meta: { relayUrl: previous.relayUrl, error: errorText(error), firstFailedAt: new Date(firstFailedAt).toISOString() } });
|
|
242
|
+
return "kept";
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Retire each registration on a relay the operator moved away from (see `retireAtRelay`), then remove the retired ones
|
|
247
|
+
* from the vault. Returns "pending" when that vault write failed (the records say they are retired, so the next try
|
|
248
|
+
* repeats only the write), "kept" when some registration is still waiting, "retired" when all are gone from the vault,
|
|
249
|
+
* and "none" when there were none. `finishOnly` skips the relays and repeats only the vault write. Never throws.
|
|
250
|
+
*/
|
|
251
|
+
async function retirePreviousRegistrations(input) {
|
|
252
|
+
const retirements = input.retirements ?? memoryRelayRetirements();
|
|
253
|
+
let previous;
|
|
254
|
+
try {
|
|
255
|
+
previous = (await input.config.read()).previousRegistrations ?? [];
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_previous_read_failed", message: "could not read the relay settings, so previous relays are not retired this time; the relay inbox keeps running, and retiring is tried again at the next start", meta: { error: errorText(error) } });
|
|
259
|
+
return "kept";
|
|
260
|
+
}
|
|
261
|
+
if (previous.length === 0)
|
|
262
|
+
return "none";
|
|
263
|
+
const now = (input.now ?? Date.now)();
|
|
264
|
+
const done = [];
|
|
265
|
+
for (const registration of previous) {
|
|
266
|
+
let finished = false;
|
|
267
|
+
if (input.finishOnly)
|
|
268
|
+
attempt("read", () => { finished = retirements.read(registration).retired === true; });
|
|
269
|
+
else
|
|
270
|
+
finished = await retireAtRelay(registration, input, retirements, now) === "retired";
|
|
271
|
+
if (finished)
|
|
272
|
+
done.push(registration);
|
|
273
|
+
}
|
|
274
|
+
if (done.length === 0)
|
|
275
|
+
return "kept";
|
|
276
|
+
try {
|
|
277
|
+
const latest = (await input.config.read()).previousRegistrations ?? [];
|
|
278
|
+
const remaining = latest.filter((registration) => !done.some((gone) => sameRegistration(gone, registration)));
|
|
279
|
+
await input.config.write({ previousRegistrations: remaining.length > 0 ? remaining : undefined });
|
|
280
|
+
}
|
|
281
|
+
catch (error) {
|
|
282
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_previous_retire_pending", message: "a previous relay registration is retired, but removing it from the vault failed; the vault write is tried again at the next poll and at each start", meta: { relayUrls: done.map((registration) => registration.relayUrl), error: errorText(error) } });
|
|
283
|
+
return "pending";
|
|
284
|
+
}
|
|
285
|
+
for (const registration of done) {
|
|
286
|
+
attempt("remove", () => retirements.clear(registration));
|
|
287
|
+
(0, runtime_1.emitNervesEvent)({ component: "channels", event: "channel.a2a_relay_previous_retired", message: "removed the registration on a previous relay", meta: { relayUrl: registration.relayUrl } });
|
|
288
|
+
}
|
|
289
|
+
return done.length < previous.length ? "kept" : "retired";
|
|
290
|
+
}
|
|
291
|
+
const DEFAULT_TIMERS = {
|
|
292
|
+
set: (fn, ms) => setTimeout(fn, ms).unref(),
|
|
293
|
+
clear: (timer) => clearTimeout(timer),
|
|
294
|
+
};
|
|
295
|
+
/** Register (moving to a new relay when the operator set one), retire the relays moved away from, then poll every 30 s, backing off (doubling to 5 minutes) after a failure. */
|
|
296
|
+
function startRelayInbox(input) {
|
|
297
|
+
const interval = input.intervalMs ?? exports.RELAY_POLL_INTERVAL_MS;
|
|
298
|
+
const timers = input.timers ?? DEFAULT_TIMERS;
|
|
299
|
+
const retirements = input.retirements ?? memoryRelayRetirements();
|
|
300
|
+
let registration = null;
|
|
301
|
+
let stopped = false;
|
|
302
|
+
let delay = interval;
|
|
303
|
+
let timer;
|
|
304
|
+
let running;
|
|
305
|
+
let retirePending = false;
|
|
306
|
+
const retire = async (finishOnly) => {
|
|
307
|
+
retirePending = await retirePreviousRegistrations({ ...input, retirements, finishOnly }) === "pending";
|
|
308
|
+
};
|
|
309
|
+
const tick = () => {
|
|
310
|
+
// One pass at a time: a manual tick during a timed pass waits for it instead of handling the same messages twice.
|
|
311
|
+
running ??= (async () => {
|
|
312
|
+
if (retirePending)
|
|
313
|
+
await retire(true);
|
|
314
|
+
if (!registration)
|
|
315
|
+
return "stop";
|
|
316
|
+
const result = await drainRelayInbox({ registration, handle: input.handle, seen: input.seen, fetchImpl: input.fetchImpl });
|
|
317
|
+
if (result === "stop")
|
|
318
|
+
registration = null;
|
|
319
|
+
return result;
|
|
320
|
+
})().finally(() => { running = undefined; });
|
|
321
|
+
return running;
|
|
322
|
+
};
|
|
323
|
+
const schedule = () => {
|
|
324
|
+
if (stopped || !registration)
|
|
325
|
+
return;
|
|
326
|
+
timer = timers.set(() => {
|
|
327
|
+
void tick().then((result) => {
|
|
328
|
+
delay = result === "backoff" ? Math.min(Math.max(delay, interval) * 2, exports.RELAY_MAX_BACKOFF_MS) : interval;
|
|
329
|
+
schedule();
|
|
330
|
+
});
|
|
331
|
+
}, delay);
|
|
332
|
+
};
|
|
333
|
+
const ready = (async () => {
|
|
334
|
+
// Register first: a move never waits for the relays before it, which are then retired, each on its own clock.
|
|
335
|
+
try {
|
|
336
|
+
registration = await ensureRelayRegistration(input);
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_relay_start_failed", message: "could not read the relay configuration; the relay inbox is off", meta: { error: errorText(error) } });
|
|
340
|
+
registration = null;
|
|
341
|
+
}
|
|
342
|
+
await retire(false);
|
|
343
|
+
if (!registration || stopped)
|
|
344
|
+
return;
|
|
345
|
+
(0, runtime_1.emitNervesEvent)({ component: "channels", event: "channel.a2a_relay_inbox_started", message: "polling the A2A relay inbox", meta: { relayUrl: registration.relayUrl, intervalMs: interval } });
|
|
346
|
+
const first = await tick();
|
|
347
|
+
delay = first === "backoff" ? interval * 2 : interval;
|
|
348
|
+
schedule();
|
|
349
|
+
})();
|
|
350
|
+
return {
|
|
351
|
+
ready,
|
|
352
|
+
registration: () => registration,
|
|
353
|
+
tick,
|
|
354
|
+
stop: () => {
|
|
355
|
+
stopped = true;
|
|
356
|
+
if (timer !== undefined)
|
|
357
|
+
timers.clear(timer);
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
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.fileRelayRetirements = fileRelayRetirements;
|
|
37
|
+
const node_crypto_1 = require("node:crypto");
|
|
38
|
+
const fs = __importStar(require("node:fs"));
|
|
39
|
+
const path = __importStar(require("node:path"));
|
|
40
|
+
const runtime_1 = require("../nerves/runtime");
|
|
41
|
+
function markerKey(registration) {
|
|
42
|
+
return (0, node_crypto_1.createHash)("sha256").update(`${registration.relayUrl}\n${registration.handle}`).digest("hex");
|
|
43
|
+
}
|
|
44
|
+
function recordFrom(value) {
|
|
45
|
+
const raw = value;
|
|
46
|
+
return {
|
|
47
|
+
...(typeof raw?.firstFailedAt === "number" && Number.isFinite(raw.firstFailedAt) ? { firstFailedAt: raw.firstFailedAt } : {}),
|
|
48
|
+
...(raw?.retired === true ? { retired: true } : {}),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The retirement record of each previous relay registration (when attempts on it first failed, and whether it is done
|
|
53
|
+
* at the relay), kept on disk under `state/a2a/relay-retired/` so it survives a restart. A record holds no
|
|
54
|
+
* credentials, only the relay URL and handle, under a name hashed from both; it is written 0600 to a temporary name and
|
|
55
|
+
* renamed into place. Records are also kept in memory, so a failed disk write still holds until the process stops.
|
|
56
|
+
*/
|
|
57
|
+
function fileRelayRetirements(agentRoot) {
|
|
58
|
+
const dir = path.join(agentRoot, "state", "a2a", "relay-retired");
|
|
59
|
+
const cache = new Map();
|
|
60
|
+
const file = (key) => path.join(dir, `${key}.json`);
|
|
61
|
+
return {
|
|
62
|
+
read: (registration) => {
|
|
63
|
+
const key = markerKey(registration);
|
|
64
|
+
const cached = cache.get(key);
|
|
65
|
+
if (cached)
|
|
66
|
+
return { ...cached };
|
|
67
|
+
try {
|
|
68
|
+
return recordFrom(JSON.parse(fs.readFileSync(file(key), "utf8")));
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return {};
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
write: (registration, record) => {
|
|
75
|
+
const key = markerKey(registration);
|
|
76
|
+
cache.set(key, { ...record });
|
|
77
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
78
|
+
const temp = `${file(key)}.${(0, node_crypto_1.randomBytes)(6).toString("hex")}.tmp`;
|
|
79
|
+
fs.writeFileSync(temp, `${JSON.stringify({ relayUrl: registration.relayUrl, handle: registration.handle, ...record, updatedAt: new Date().toISOString() })}\n`, { mode: 0o600 });
|
|
80
|
+
fs.renameSync(temp, file(key));
|
|
81
|
+
(0, runtime_1.emitNervesEvent)({ component: "channels", event: "channel.a2a_relay_retirement_recorded", message: record.retired ? "an old relay registration is retired" : "an old relay registration is still being retired", meta: { relayUrl: registration.relayUrl, retired: record.retired === true } });
|
|
82
|
+
},
|
|
83
|
+
clear: (registration) => {
|
|
84
|
+
const key = markerKey(registration);
|
|
85
|
+
cache.delete(key);
|
|
86
|
+
fs.rmSync(file(key), { force: true });
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.REPLAY_GRANT_HOLDERS_FILE = void 0;
|
|
4
|
+
exports.isReplayGrantHolder = isReplayGrantHolder;
|
|
5
|
+
const runtime_1 = require("../nerves/runtime");
|
|
6
|
+
const operator_trust_1 = require("./operator-trust");
|
|
7
|
+
/**
|
|
8
|
+
* The friends the replay gate provisioned as replay peers, kept by the gate itself as root inside the operator trust directory
|
|
9
|
+
* (`replay-identities.json`, `{ schemaVersion: 1, grants: { <friend id>: { who, name, did } } }`). A grant for one of them must
|
|
10
|
+
* carry an expiry (and so must every grant when this file is present but cannot be trusted), so a permanent grant can never be left behind by a replay run. This list is the authority for that rule: the
|
|
11
|
+
* bundle's own replay registry and a grant's free-text source are the agent's to edit and decide nothing here.
|
|
12
|
+
*/
|
|
13
|
+
exports.REPLAY_GRANT_HOLDERS_FILE = "replay-identities.json";
|
|
14
|
+
function validHolder(value) {
|
|
15
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
16
|
+
return false;
|
|
17
|
+
const holder = value;
|
|
18
|
+
return typeof holder.who === "string" && typeof holder.name === "string" && typeof holder.did === "string";
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* True when a grant with no expiry for this friend must be refused. That is the case for a friend the list names, for an entry in the list
|
|
22
|
+
* that is malformed (its id is read from the file but its content is not trusted), and for every friend when the list is present but
|
|
23
|
+
* untrusted or malformed: a list the Butler cannot rely on must never let a permanent replay grant through. A list that does not exist
|
|
24
|
+
* yet (no replay gate has run) names nobody.
|
|
25
|
+
*/
|
|
26
|
+
function isReplayGrantHolder(agentRoot, friendId) {
|
|
27
|
+
const view = (0, operator_trust_1.readGrantFile)(agentRoot, exports.REPLAY_GRANT_HOLDERS_FILE, validHolder);
|
|
28
|
+
if (view.state === "untrusted") {
|
|
29
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "senses", event: "senses.a2a_replay_list_untrusted", message: "the replay list is present but cannot be trusted, so no grant without an expiry is honoured", meta: { file: exports.REPLAY_GRANT_HOLDERS_FILE } });
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
return Object.prototype.hasOwnProperty.call(view.grants, friendId) || view.ignored.includes(friendId);
|
|
33
|
+
}
|