@ouro.bot/cli 0.1.0-alpha.92 → 0.1.0-alpha.921
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 +5826 -16
- package/deploy/unraid/Dockerfile +58 -0
- package/deploy/unraid/README.txt +2997 -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-butler-upgrade.mjs +1254 -0
- package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
- package/deploy/unraid/sanctuary-replay-gate.mjs +1564 -0
- package/deploy/unraid/sanctuary-safe-rename.py +24 -0
- package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2086 -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/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 +2231 -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 +33 -0
- package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +27 -0
- package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +22 -0
- package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
- package/deploy/unraid/sanctuary.ouro/tool-profiles.json +232 -0
- package/deploy/unraid/sanctuary.xml +30 -0
- package/dist/a2a/card.js +57 -0
- package/dist/a2a/client.js +250 -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 +93 -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 +110 -0
- package/dist/a2a/mission-result-wire.js +196 -0
- package/dist/a2a/onboarding.js +133 -0
- package/dist/a2a/operator-trust.js +382 -0
- package/dist/a2a/outbox-client.js +57 -0
- package/dist/a2a/outbox-store.js +188 -0
- package/dist/a2a/outbox-wire.js +95 -0
- package/dist/a2a/pin-store.js +132 -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 +113 -0
- package/dist/a2a/seen-ledger.js +120 -0
- package/dist/a2a/server.js +771 -0
- package/dist/a2a/task-store.js +69 -0
- package/dist/a2a/transport.js +45 -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/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/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 +111 -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 +174 -131
- package/dist/heart/context-loss-gauntlet.js +387 -0
- package/dist/heart/context-loss-sentinel.js +1159 -0
- package/dist/heart/core.js +2364 -578
- 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 +283 -3
- package/dist/heart/daemon/agent-home.js +319 -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 +197 -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 +876 -0
- package/dist/heart/daemon/cli-desk.js +322 -0
- package/dist/heart/daemon/cli-exec.js +9199 -0
- package/dist/heart/daemon/cli-help.js +735 -0
- package/dist/heart/daemon/cli-parse.js +3211 -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 +171 -0
- package/dist/heart/daemon/container-spec-auditor.js +235 -0
- package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
- package/dist/heart/daemon/daemon-cli.js +29 -2350
- package/dist/heart/daemon/daemon-entry.js +953 -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 +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 +5 -2
- 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 +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 +281 -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 +1267 -0
- package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
- package/dist/heart/daemon/sanctuary-bundle-migration.js +730 -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 +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 +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 +733 -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 +1516 -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 +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 +230 -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 +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 +272 -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 +83 -16
- 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 +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 +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 +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/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 +607 -0
- package/dist/heart/runtime-cwd.js +87 -0
- package/dist/heart/sense-truth.js +24 -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/shelf-claims.js +78 -0
- package/dist/heart/shepherd-config.js +113 -0
- package/dist/heart/source-grounding.js +297 -0
- package/dist/heart/start-of-turn-packet.js +372 -0
- package/dist/heart/steward-policy.js +656 -0
- package/dist/heart/streaming.js +609 -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.js +726 -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/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-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 +307 -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 +330 -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 +1085 -198
- 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 +1201 -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 +174 -32
- 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 +968 -20
- package/dist/repertoire/house-sweep.js +469 -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 +46 -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 +699 -0
- package/dist/repertoire/tools-attachments.js +322 -0
- package/dist/repertoire/tools-awaiting.js +872 -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 +995 -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-escalation.js +84 -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-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 +496 -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 +1133 -0
- package/dist/repertoire/tools-shell.js +149 -0
- package/dist/repertoire/tools-shepherd.js +262 -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 +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 +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 +514 -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 +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 +132 -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} +379 -41
- 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 +3878 -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 +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 +601 -304
- 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 +1158 -204
- package/dist/senses/private-runtime-worker.js +859 -0
- package/dist/senses/private-runtime.js +1627 -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 +104 -0
- package/dist/senses/sanctuary-health.js +422 -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 +259 -0
- package/dist/senses/sanctuary-media-optimization.js +514 -0
- package/dist/senses/sanctuary-runtime.js +369 -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 +793 -0
- package/dist/senses/shepherd/client.js +196 -0
- package/dist/senses/shepherd/cmux.js +352 -0
- package/dist/senses/shepherd/herdr.js +315 -0
- package/dist/senses/shepherd/host.js +14 -0
- package/dist/senses/shepherd/judge.js +137 -0
- package/dist/senses/shepherd/owner-notice.js +251 -0
- package/dist/senses/shepherd/redact.js +66 -0
- package/dist/senses/shepherd/returns.js +79 -0
- package/dist/senses/shepherd/sense.js +310 -0
- package/dist/senses/shepherd/terminal-process.js +99 -0
- package/dist/senses/shepherd-entry.js +78 -0
- package/dist/senses/surface-tool.js +109 -0
- package/dist/senses/teams-entry.js +68 -8
- package/dist/senses/teams.js +598 -233
- 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 +900 -0
- package/dist/senses/telegram-entry.js +83 -0
- package/dist/senses/telegram-handoff.js +80 -0
- package/dist/senses/telegram.js +2405 -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 +121 -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 +8100 -0
- package/package.json +74 -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 -362
- 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,382 @@
|
|
|
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.TrustDirectoryError = exports.TRUST_DIR_ENV = exports.OPERATOR_TRUST_ROOT = void 0;
|
|
37
|
+
exports.overrideTrustRootForTests = overrideTrustRootForTests;
|
|
38
|
+
exports.agentNameFromRoot = agentNameFromRoot;
|
|
39
|
+
exports.operatorTrustDir = operatorTrustDir;
|
|
40
|
+
exports.operatorTrustFile = operatorTrustFile;
|
|
41
|
+
exports.readGrantFile = readGrantFile;
|
|
42
|
+
exports.overrideFchownForTests = overrideFchownForTests;
|
|
43
|
+
exports.ensureTrustDirectory = ensureTrustDirectory;
|
|
44
|
+
exports.overrideDirectoryFlushForTests = overrideDirectoryFlushForTests;
|
|
45
|
+
exports.overrideLockTimeoutForTests = overrideLockTimeoutForTests;
|
|
46
|
+
exports.withTrustedWriteLock = withTrustedWriteLock;
|
|
47
|
+
exports.writeTrustedFile = writeTrustedFile;
|
|
48
|
+
exports.describeGrantFile = describeGrantFile;
|
|
49
|
+
const node_crypto_1 = require("node:crypto");
|
|
50
|
+
const fs = __importStar(require("node:fs"));
|
|
51
|
+
const os = __importStar(require("node:os"));
|
|
52
|
+
const path = __importStar(require("node:path"));
|
|
53
|
+
const runtime_1 = require("../nerves/runtime");
|
|
54
|
+
const trusted_files_1 = require("./trusted-files");
|
|
55
|
+
/**
|
|
56
|
+
* Operator-set grants live in a trust directory outside the agent bundle: `/etc/ouro/trust/<agent>/` by default, or
|
|
57
|
+
* `<OURO_OPERATOR_TRUST_DIR>/<agent>/` when that variable replaces the trust root. The agent's own uid cannot write there, and the bundle's recursive
|
|
58
|
+
* `chown` during an in-place upgrade cannot reach it. A file in it counts only when the whole chain above it passes
|
|
59
|
+
* the trusted-files check (real directories, root-owned, closed to group and other writes, up to `/`).
|
|
60
|
+
*/
|
|
61
|
+
exports.OPERATOR_TRUST_ROOT = "/etc/ouro/trust";
|
|
62
|
+
exports.TRUST_DIR_ENV = "OURO_OPERATOR_TRUST_DIR";
|
|
63
|
+
let trustRoot = exports.OPERATOR_TRUST_ROOT;
|
|
64
|
+
/** Tests keep trust directories under their private temp root instead of `/etc`. Refused outside a test runner. */
|
|
65
|
+
function overrideTrustRootForTests(root) {
|
|
66
|
+
if (process.env.VITEST === undefined)
|
|
67
|
+
throw new Error("overrideTrustRootForTests is for tests only");
|
|
68
|
+
trustRoot = root ?? exports.OPERATOR_TRUST_ROOT;
|
|
69
|
+
}
|
|
70
|
+
/** The agent a bundle root belongs to: `~/AgentBundles/sanctuary.ouro` is `sanctuary`. */
|
|
71
|
+
function agentNameFromRoot(agentRoot) {
|
|
72
|
+
return path.basename(agentRoot).replace(/\.ouro$/u, "");
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The real path of `target`, resolved once. The deepest ancestor that exists is resolved through every symlink and the rest of
|
|
76
|
+
* the (not yet created) tail is appended, so a configured `/etc/ouro/trust` becomes `/private/etc/ouro/trust` on macOS and the
|
|
77
|
+
* ancestor check then walks the directories the grants actually sit in.
|
|
78
|
+
*/
|
|
79
|
+
function resolveReal(target) {
|
|
80
|
+
const tail = [];
|
|
81
|
+
for (let current = path.resolve(target);; current = path.dirname(current)) {
|
|
82
|
+
try {
|
|
83
|
+
return path.join(fs.realpathSync(current), ...tail);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
/* v8 ignore next -- the filesystem root always resolves, so this loop never runs out of ancestors @preserve */
|
|
87
|
+
if (path.dirname(current) === current)
|
|
88
|
+
return path.resolve(target);
|
|
89
|
+
tail.unshift(path.basename(current));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Where this agent's operator-set grants live: `<trust root>/<agent>`. `OURO_OPERATOR_TRUST_DIR` replaces the trust root
|
|
95
|
+
* (`/etc/ouro/trust`) and keeps the per-agent subdirectory, so one setting serves every agent on the host.
|
|
96
|
+
*/
|
|
97
|
+
function operatorTrustDir(agentRoot) {
|
|
98
|
+
const override = process.env[exports.TRUST_DIR_ENV];
|
|
99
|
+
const root = override && override.trim().length > 0 ? override : trustRoot;
|
|
100
|
+
return path.join(resolveReal(root), agentNameFromRoot(agentRoot));
|
|
101
|
+
}
|
|
102
|
+
function operatorTrustFile(agentRoot, fileName) {
|
|
103
|
+
return path.join(operatorTrustDir(agentRoot), fileName);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Reads `{ schemaVersion: 1, grants: { <friendId>: entry } }` from the trust directory. A file that is not trusted, not
|
|
107
|
+
* JSON or not this shape is `untrusted` and holds no grants; a missing file is `missing`. Within a trusted file, an
|
|
108
|
+
* entry that fails `valid` is dropped and its friend id is listed in `ignored`.
|
|
109
|
+
*/
|
|
110
|
+
function readGrantFile(agentRoot, fileName, valid) {
|
|
111
|
+
const raw = (0, trusted_files_1.inspectTrustedJson)(operatorTrustFile(agentRoot, fileName));
|
|
112
|
+
if (raw.state === "missing")
|
|
113
|
+
return { state: "missing", grants: {}, ignored: [] };
|
|
114
|
+
if (raw.state === "untrusted")
|
|
115
|
+
return { state: "untrusted", reason: raw.reason, grants: {}, ignored: [] };
|
|
116
|
+
const file = raw.value;
|
|
117
|
+
const grants = file?.grants;
|
|
118
|
+
if (!file || typeof file !== "object" || file.schemaVersion !== 1 || !grants || typeof grants !== "object" || Array.isArray(grants)) {
|
|
119
|
+
return { state: "untrusted", reason: "file is not { schemaVersion: 1, grants: {...} }", grants: {}, ignored: [] };
|
|
120
|
+
}
|
|
121
|
+
const kept = {};
|
|
122
|
+
const ignored = [];
|
|
123
|
+
for (const [friendId, entry] of Object.entries(grants)) {
|
|
124
|
+
if (valid(entry))
|
|
125
|
+
kept[friendId] = entry;
|
|
126
|
+
else
|
|
127
|
+
ignored.push(friendId);
|
|
128
|
+
}
|
|
129
|
+
return { state: "trusted", grants: kept, ignored };
|
|
130
|
+
}
|
|
131
|
+
/** Why the operator command refused to write. The message says what to fix. */
|
|
132
|
+
class TrustDirectoryError extends Error {
|
|
133
|
+
}
|
|
134
|
+
exports.TrustDirectoryError = TrustDirectoryError;
|
|
135
|
+
const isRoot = () => process.geteuid?.() === 0;
|
|
136
|
+
let fchownHook;
|
|
137
|
+
/** Tests are not root, so they watch ownership changes instead of making them. Refused outside a test runner. */
|
|
138
|
+
function overrideFchownForTests(hook) {
|
|
139
|
+
if (process.env.VITEST === undefined)
|
|
140
|
+
throw new Error("overrideFchownForTests is for tests only");
|
|
141
|
+
fchownHook = hook;
|
|
142
|
+
}
|
|
143
|
+
/* v8 ignore start -- the real fchown only succeeds as root; tests watch the hook instead @preserve */
|
|
144
|
+
function chownToRoot(fd) {
|
|
145
|
+
if (fchownHook)
|
|
146
|
+
fchownHook(fd, 0, 0);
|
|
147
|
+
else
|
|
148
|
+
fs.fchownSync(fd, 0, 0);
|
|
149
|
+
}
|
|
150
|
+
/* v8 ignore stop */
|
|
151
|
+
/**
|
|
152
|
+
* Makes sure the trust directory exists and is trusted. A missing directory is created root-owned 0755, one component
|
|
153
|
+
* at a time, but only below an ancestor that is already trusted. An existing directory (or ancestor) that is not
|
|
154
|
+
* trusted is refused: the command never takes ownership of something the agent could have made.
|
|
155
|
+
*/
|
|
156
|
+
function ensureTrustDirectory(dir) {
|
|
157
|
+
const missing = [];
|
|
158
|
+
let base = path.resolve(dir);
|
|
159
|
+
for (;;) {
|
|
160
|
+
const result = (0, trusted_files_1.inspectTrustedDirectory)(base);
|
|
161
|
+
if (result.state === "trusted")
|
|
162
|
+
break;
|
|
163
|
+
if (result.state === "untrusted")
|
|
164
|
+
throw new TrustDirectoryError(`refusing to write: ${base} is not trusted (${result.reason}). Fix its owner and mode as root; this command never takes ownership of an existing directory.`);
|
|
165
|
+
missing.push(base);
|
|
166
|
+
base = path.dirname(base);
|
|
167
|
+
}
|
|
168
|
+
for (const next of missing.reverse()) {
|
|
169
|
+
fs.mkdirSync(next, { mode: 0o755 });
|
|
170
|
+
const fd = fs.openSync(next, fs.constants.O_RDONLY | fs.constants.O_DIRECTORY | fs.constants.O_NOFOLLOW);
|
|
171
|
+
try {
|
|
172
|
+
if (isRoot())
|
|
173
|
+
chownToRoot(fd);
|
|
174
|
+
fs.fchmodSync(fd, 0o755);
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
fs.closeSync(fd);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/** Flushes a directory's entries to disk, so a rename or a new file in it survives a crash. */
|
|
182
|
+
function fsyncDirectory(dir) {
|
|
183
|
+
const fd = fs.openSync(dir, fs.constants.O_RDONLY | fs.constants.O_DIRECTORY | fs.constants.O_NOFOLLOW);
|
|
184
|
+
try {
|
|
185
|
+
fs.fsyncSync(fd);
|
|
186
|
+
directoryFlushHook?.(dir);
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
fs.closeSync(fd);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
let directoryFlushHook;
|
|
193
|
+
/** Tests watch directory flushes (the ESM fs namespace cannot be spied on). Refused outside a test runner. */
|
|
194
|
+
function overrideDirectoryFlushForTests(hook) {
|
|
195
|
+
if (process.env.VITEST === undefined)
|
|
196
|
+
throw new Error("overrideDirectoryFlushForTests is for tests only");
|
|
197
|
+
directoryFlushHook = hook;
|
|
198
|
+
}
|
|
199
|
+
const LOCK_FILE = ".lock";
|
|
200
|
+
const LOCK_STALE_MS = 2 * 60_000;
|
|
201
|
+
/** A lock written by another host or pid namespace (a different hostname in its body) cannot be checked for a live holder, so it is only taken over after this long. */
|
|
202
|
+
const LOCK_FOREIGN_STALE_MS = 60 * 60_000;
|
|
203
|
+
let lockTimeoutMs = 5000;
|
|
204
|
+
let lockWaitHook;
|
|
205
|
+
let beforeReclaimHook;
|
|
206
|
+
/** Tests shorten the wait for a held lock, can act while it waits, and can act between judging a lock stale and reclaiming it. Refused outside a test runner. */
|
|
207
|
+
function overrideLockTimeoutForTests(timeoutMs, onWait, onBeforeReclaim) {
|
|
208
|
+
if (process.env.VITEST === undefined)
|
|
209
|
+
throw new Error("overrideLockTimeoutForTests is for tests only");
|
|
210
|
+
lockTimeoutMs = timeoutMs ?? 5000;
|
|
211
|
+
lockWaitHook = onWait;
|
|
212
|
+
beforeReclaimHook = onBeforeReclaim;
|
|
213
|
+
}
|
|
214
|
+
/** How long ago `file` was last written; a file that is gone counts as brand new, so nobody treats it as stale. */
|
|
215
|
+
function ageMs(file) {
|
|
216
|
+
try {
|
|
217
|
+
return Date.now() - fs.lstatSync(file).mtimeMs;
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
return 0;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const lockBody = () => `pid ${process.pid} host ${os.hostname()} at ${new Date().toISOString()}\n`;
|
|
224
|
+
/** True when a process with this pid exists on this host. EPERM means it exists but is someone else's. */
|
|
225
|
+
function processAlive(pid) {
|
|
226
|
+
try {
|
|
227
|
+
process.kill(pid, 0);
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
return error.code !== "ESRCH";
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Whether `lock` was left by a writer that is gone. Age alone is not enough: a slow writer can hold the lock for longer than two
|
|
236
|
+
* minutes. So a lock older than that is stale only when the pid in its body is no longer running on this host. A body that cannot be
|
|
237
|
+
* read as `pid N host H at T` names no holder at all, and a lock from another host or pid namespace cannot be checked, so it waits
|
|
238
|
+
* out a much longer age.
|
|
239
|
+
*/
|
|
240
|
+
function lockIsStale(lock) {
|
|
241
|
+
const age = ageMs(lock);
|
|
242
|
+
if (age <= LOCK_STALE_MS)
|
|
243
|
+
return false;
|
|
244
|
+
let held = null;
|
|
245
|
+
try {
|
|
246
|
+
held = /^pid (\d+) host (\S+) at /.exec(fs.readFileSync(lock, "utf8"));
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
if (!held)
|
|
252
|
+
return true;
|
|
253
|
+
if (held[2] !== os.hostname())
|
|
254
|
+
return age > LOCK_FOREIGN_STALE_MS;
|
|
255
|
+
return !processAlive(Number(held[1]));
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Removes a lock that looked stale, but only while holding a second exclusive file (`.lock.reclaim`) and only after looking again:
|
|
259
|
+
* two writers that both judged the same lock stale cannot then each delete it, which would let the second delete the fresh lock
|
|
260
|
+
* the first had just taken. A reclaim file that is itself stale belongs to a writer that died and is removed.
|
|
261
|
+
*/
|
|
262
|
+
function reclaimStaleLock(lock) {
|
|
263
|
+
const guard = `${lock}.reclaim`;
|
|
264
|
+
try {
|
|
265
|
+
createExclusive(guard, lockBody());
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
if (ageMs(guard) > LOCK_STALE_MS)
|
|
269
|
+
fs.rmSync(guard, { force: true });
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
if (lockIsStale(lock))
|
|
274
|
+
fs.rmSync(lock, { force: true });
|
|
275
|
+
}
|
|
276
|
+
finally {
|
|
277
|
+
fs.rmSync(guard, { force: true });
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function sleepSync(ms) {
|
|
281
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Runs a read-modify-write of the trust files under an exclusive lock file in the trust directory, so two grant commands
|
|
285
|
+
* cannot both read the old file and then overwrite each other. The lock is created with O_EXCL and records the writer's pid and host;
|
|
286
|
+
* a lock older than two minutes whose writer is no longer running is taken over. A lock that stays held past the wait names the file to remove.
|
|
287
|
+
*/
|
|
288
|
+
function withTrustedWriteLock(agentRoot, fn) {
|
|
289
|
+
const dir = operatorTrustDir(agentRoot);
|
|
290
|
+
ensureTrustDirectory(dir);
|
|
291
|
+
const lock = path.join(dir, LOCK_FILE);
|
|
292
|
+
const deadline = Date.now() + lockTimeoutMs;
|
|
293
|
+
for (;;) {
|
|
294
|
+
try {
|
|
295
|
+
createExclusive(lock, lockBody());
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
if (error.code !== "EEXIST")
|
|
300
|
+
throw error;
|
|
301
|
+
if (lockIsStale(lock)) {
|
|
302
|
+
beforeReclaimHook?.();
|
|
303
|
+
reclaimStaleLock(lock);
|
|
304
|
+
}
|
|
305
|
+
if (Date.now() >= deadline)
|
|
306
|
+
throw new TrustDirectoryError(`refusing to write: another grant command is writing to ${dir} (lock file ${lock}). If none is running, remove that file and retry. Nothing was written.`);
|
|
307
|
+
lockWaitHook?.();
|
|
308
|
+
sleepSync(25);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
try {
|
|
312
|
+
return fn();
|
|
313
|
+
}
|
|
314
|
+
finally {
|
|
315
|
+
fs.rmSync(lock, { force: true });
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
/** Creates `file` exclusively (never through a link or over anything), owned by root with mode 0644 when run as root, and fsyncs it. */
|
|
319
|
+
function createExclusive(file, body) {
|
|
320
|
+
const fd = fs.openSync(file, fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_NOFOLLOW, 0o600);
|
|
321
|
+
try {
|
|
322
|
+
if (isRoot())
|
|
323
|
+
chownToRoot(fd);
|
|
324
|
+
fs.fchmodSync(fd, 0o644);
|
|
325
|
+
fs.writeFileSync(fd, body);
|
|
326
|
+
fs.fsyncSync(fd);
|
|
327
|
+
}
|
|
328
|
+
finally {
|
|
329
|
+
fs.closeSync(fd);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
function rawBytes(file) {
|
|
333
|
+
let fd;
|
|
334
|
+
try {
|
|
335
|
+
fd = fs.openSync(file, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
|
|
336
|
+
return fs.fstatSync(fd).isFile() ? fs.readFileSync(fd) : null;
|
|
337
|
+
}
|
|
338
|
+
catch {
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
finally {
|
|
342
|
+
if (fd !== undefined)
|
|
343
|
+
fs.closeSync(fd);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Replaces one file in the trust directory. The previous bytes are kept beside it as a timestamped backup, created the
|
|
348
|
+
* same safe way. The new file is written to an exclusive random temporary name, owned and moded through its descriptor,
|
|
349
|
+
* fsynced and renamed into place, so a reader never sees a half-written file and nothing already on disk is followed.
|
|
350
|
+
*/
|
|
351
|
+
function writeTrustedFile(agentRoot, fileName, body, now) {
|
|
352
|
+
const dir = operatorTrustDir(agentRoot);
|
|
353
|
+
ensureTrustDirectory(dir);
|
|
354
|
+
const file = path.join(dir, fileName);
|
|
355
|
+
const previous = rawBytes(file);
|
|
356
|
+
let backup = null;
|
|
357
|
+
if (previous) {
|
|
358
|
+
backup = `${file}.bak-${now.toISOString().replace(/[:.]/gu, "-")}`;
|
|
359
|
+
createExclusive(backup, previous);
|
|
360
|
+
fsyncDirectory(dir);
|
|
361
|
+
}
|
|
362
|
+
const tmp = path.join(dir, `.${fileName}.${(0, node_crypto_1.randomBytes)(8).toString("hex")}.tmp`);
|
|
363
|
+
try {
|
|
364
|
+
createExclusive(tmp, body);
|
|
365
|
+
fs.renameSync(tmp, file);
|
|
366
|
+
fsyncDirectory(dir);
|
|
367
|
+
}
|
|
368
|
+
catch (error) {
|
|
369
|
+
fs.rmSync(tmp, { force: true });
|
|
370
|
+
throw error;
|
|
371
|
+
}
|
|
372
|
+
(0, runtime_1.emitNervesEvent)({ component: "senses", event: "senses.a2a_trust_file_written", message: "wrote an operator-set trust file", meta: { file, backedUp: backup !== null } });
|
|
373
|
+
return { backup };
|
|
374
|
+
}
|
|
375
|
+
/** A short human line about the file's state for `list` output and warnings. */
|
|
376
|
+
function describeGrantFile(view, file) {
|
|
377
|
+
if (view.state === "trusted")
|
|
378
|
+
return `trusted: ${file}`;
|
|
379
|
+
if (view.state === "missing")
|
|
380
|
+
return `not present: ${file}`;
|
|
381
|
+
return `NOT TRUSTED: ${file} (${view.reason}); no grant in it is honoured`;
|
|
382
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.callOutboxMethod = callOutboxMethod;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const a2a_client_1 = require("@ouro.bot/friends/a2a-client");
|
|
6
|
+
const client_1 = require("./client");
|
|
7
|
+
const outbox_wire_1 = require("./outbox-wire");
|
|
8
|
+
const sealed_chat_1 = require("./sealed-chat");
|
|
9
|
+
const runtime_1 = require("../nerves/runtime");
|
|
10
|
+
/**
|
|
11
|
+
* Calls one outbox method on an A2A agent as a verified friend. The request is sealed to the agent's card DID and
|
|
12
|
+
* signed by `identity`, and the reply is opened only if it was sealed by that same card key, so neither direction
|
|
13
|
+
* travels in plaintext. Throws with the agent's refusal text when the agent answers with a JSON-RPC error.
|
|
14
|
+
*/
|
|
15
|
+
async function callOutboxMethod(input) {
|
|
16
|
+
const fetchImpl = input.fetchImpl ?? fetch;
|
|
17
|
+
const sodium = input.sodium ?? await (0, a2a_client_1.ready)();
|
|
18
|
+
const card = await (0, client_1.fetchA2AAgentCard)(input.cardUrl, fetchImpl);
|
|
19
|
+
const peerDid = (0, client_1.cardDid)(card);
|
|
20
|
+
if (!peerDid)
|
|
21
|
+
throw new Error(`A2A card ${input.cardUrl} serves no DID; outbox calls need one`);
|
|
22
|
+
const parsed = (0, a2a_client_1.parseDidKey)(peerDid);
|
|
23
|
+
if (!parsed || !(0, a2a_client_1.verifyCardDidBinding)({ card: { did: peerDid, url: input.cardUrl }, did: peerDid, didDoc: null })) {
|
|
24
|
+
throw new Error(`A2A card↔DID binding failed for ${peerDid}`);
|
|
25
|
+
}
|
|
26
|
+
const endpointUrl = (0, client_1.endpointForCard)(card);
|
|
27
|
+
const conversationId = (0, node_crypto_1.randomUUID)();
|
|
28
|
+
const sealed = (0, sealed_chat_1.sealChatMessage)({
|
|
29
|
+
sodium, from: input.identity, recipientDid: peerDid, recipientEd25519Pub: parsed.ed25519Pub,
|
|
30
|
+
text: (0, outbox_wire_1.encodeOutboxCommand)(input.method, input.params), conversationId,
|
|
31
|
+
});
|
|
32
|
+
const request = {
|
|
33
|
+
jsonrpc: "2.0", id: (0, node_crypto_1.randomUUID)(), method: input.method,
|
|
34
|
+
params: { message: { kind: "message", role: "ROLE_USER", messageId: (0, node_crypto_1.randomUUID)(), contextId: conversationId, parts: sealed.parts } },
|
|
35
|
+
};
|
|
36
|
+
(0, runtime_1.emitNervesEvent)({ component: "channels", event: "channel.a2a_outbox_call_start", message: "calling an A2A outbox method", meta: { endpointUrl, peerDid, method: input.method } });
|
|
37
|
+
const rpc = await (0, client_1.postJsonRpc)(endpointUrl, request, fetchImpl);
|
|
38
|
+
if ("error" in rpc)
|
|
39
|
+
throw new Error(`A2A error ${rpc.error.code}: ${rpc.error.message}`);
|
|
40
|
+
const reply = rpc.result;
|
|
41
|
+
if (!reply || !Array.isArray(reply.parts))
|
|
42
|
+
throw new Error("A2A outbox call returned no reply message");
|
|
43
|
+
const opened = await (0, sealed_chat_1.openChatMessage)({ sodium, self: input.identity, message: reply, senderDid: peerDid, senderEd25519Pub: parsed.ed25519Pub });
|
|
44
|
+
if (!opened.ok)
|
|
45
|
+
throw new Error(`A2A outbox reply rejected: ${opened.reason}`);
|
|
46
|
+
let result;
|
|
47
|
+
try {
|
|
48
|
+
result = JSON.parse(opened.text);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
throw new Error("A2A outbox reply was not JSON");
|
|
52
|
+
}
|
|
53
|
+
if (!result || typeof result !== "object" || Array.isArray(result))
|
|
54
|
+
throw new Error("A2A outbox reply was not a JSON object");
|
|
55
|
+
(0, runtime_1.emitNervesEvent)({ component: "channels", event: "channel.a2a_outbox_call_end", message: "received an A2A outbox reply", meta: { endpointUrl, peerDid, method: input.method } });
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
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.FileOutboxStore = exports.OUTBOX_LIST_MAX_CHARS = exports.OUTBOX_LIST_MAX_LIMIT = exports.OUTBOX_LIST_DEFAULT_LIMIT = exports.OUTBOX_MAX_BODY_CHARS = exports.OUTBOX_MAX_ENTRIES = void 0;
|
|
37
|
+
exports.isOutboxEntryId = isOutboxEntryId;
|
|
38
|
+
exports.outboxRoot = outboxRoot;
|
|
39
|
+
const node_crypto_1 = require("node:crypto");
|
|
40
|
+
const fs = __importStar(require("node:fs"));
|
|
41
|
+
const path = __importStar(require("node:path"));
|
|
42
|
+
const file_lock_1 = require("../heart/file-lock");
|
|
43
|
+
const runtime_1 = require("../nerves/runtime");
|
|
44
|
+
exports.OUTBOX_MAX_ENTRIES = 500;
|
|
45
|
+
exports.OUTBOX_MAX_BODY_CHARS = 6_000;
|
|
46
|
+
exports.OUTBOX_LIST_DEFAULT_LIMIT = 20;
|
|
47
|
+
exports.OUTBOX_LIST_MAX_LIMIT = 50;
|
|
48
|
+
/** One listing reply is a single sealed message of at most 16,000 characters, so a listing stops filling well before that. */
|
|
49
|
+
exports.OUTBOX_LIST_MAX_CHARS = 12_000;
|
|
50
|
+
const FRIEND_ID = /^[A-Za-z0-9][A-Za-z0-9._-]*$/u;
|
|
51
|
+
const ENTRY_ID = /^\d{13}-[0-9a-f]{6}$/u;
|
|
52
|
+
function isOutboxEntryId(value) {
|
|
53
|
+
return typeof value === "string" && ENTRY_ID.test(value);
|
|
54
|
+
}
|
|
55
|
+
function entryDir(agentRoot, friendId) {
|
|
56
|
+
if (!FRIEND_ID.test(friendId))
|
|
57
|
+
throw new Error("outbox friend id is invalid");
|
|
58
|
+
return path.join(agentRoot, "state", "outbox", friendId);
|
|
59
|
+
}
|
|
60
|
+
function outboxRoot(agentRoot) {
|
|
61
|
+
return path.join(agentRoot, "state", "outbox");
|
|
62
|
+
}
|
|
63
|
+
function readEntry(file) {
|
|
64
|
+
try {
|
|
65
|
+
const parsed = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
66
|
+
if (!isOutboxEntryId(parsed.id) || typeof parsed.kind !== "string" || typeof parsed.createdAt !== "string" || typeof parsed.body !== "string")
|
|
67
|
+
return null;
|
|
68
|
+
return { id: parsed.id, kind: parsed.kind, createdAt: parsed.createdAt, body: parsed.body, ...(parsed.meta ? { meta: parsed.meta } : {}) };
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function sortedIds(dir) {
|
|
75
|
+
let names;
|
|
76
|
+
try {
|
|
77
|
+
names = fs.readdirSync(dir);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
return names.filter((name) => name.endsWith(".json") && isOutboxEntryId(name.slice(0, -5))).map((name) => name.slice(0, -5)).sort();
|
|
83
|
+
}
|
|
84
|
+
class FileOutboxStore {
|
|
85
|
+
agentRoot;
|
|
86
|
+
constructor(agentRoot) {
|
|
87
|
+
this.agentRoot = agentRoot;
|
|
88
|
+
}
|
|
89
|
+
/** Adds one entry for `friendId`. The oldest entries beyond the cap are dropped so a peer that never reads cannot fill the disk. */
|
|
90
|
+
append(friendId, input, now = Date.now()) {
|
|
91
|
+
const dir = entryDir(this.agentRoot, friendId);
|
|
92
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
93
|
+
const id = `${String(now).padStart(13, "0")}-${(0, node_crypto_1.randomBytes)(3).toString("hex")}`;
|
|
94
|
+
const entry = {
|
|
95
|
+
id,
|
|
96
|
+
kind: input.kind,
|
|
97
|
+
createdAt: new Date(now).toISOString(),
|
|
98
|
+
body: input.body.slice(0, exports.OUTBOX_MAX_BODY_CHARS),
|
|
99
|
+
...(input.meta ? { meta: input.meta } : {}),
|
|
100
|
+
};
|
|
101
|
+
const file = path.join(dir, `${id}.json`);
|
|
102
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
103
|
+
fs.writeFileSync(tmp, `${JSON.stringify(entry, null, 2)}\n`, { mode: 0o600 });
|
|
104
|
+
fs.renameSync(tmp, file);
|
|
105
|
+
const ids = sortedIds(dir);
|
|
106
|
+
const evicted = ids.slice(0, Math.max(0, ids.length - exports.OUTBOX_MAX_ENTRIES));
|
|
107
|
+
for (const stale of evicted)
|
|
108
|
+
fs.rmSync(path.join(dir, `${stale}.json`), { force: true });
|
|
109
|
+
if (evicted.length > 0) {
|
|
110
|
+
(0, runtime_1.emitNervesEvent)({
|
|
111
|
+
level: "warn",
|
|
112
|
+
component: "senses",
|
|
113
|
+
event: "senses.a2a_outbox_evicted",
|
|
114
|
+
message: "a peer outbox is full, so its oldest unread entries were dropped",
|
|
115
|
+
meta: { friendId, evicted: evicted.length, oldestDropped: evicted[0], cap: exports.OUTBOX_MAX_ENTRIES },
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
(0, runtime_1.emitNervesEvent)({
|
|
119
|
+
component: "senses",
|
|
120
|
+
event: "senses.a2a_outbox_appended",
|
|
121
|
+
message: "queued a message in a peer outbox",
|
|
122
|
+
meta: { friendId, entryId: id, kind: input.kind },
|
|
123
|
+
});
|
|
124
|
+
return entry;
|
|
125
|
+
}
|
|
126
|
+
/** Like `append`, but a second call with the same `dedupeKey` while the first entry is still unacked returns that entry, so a retried delivery cannot double-post. */
|
|
127
|
+
async appendOnce(friendId, dedupeKey, input, now = Date.now()) {
|
|
128
|
+
const dir = entryDir(this.agentRoot, friendId);
|
|
129
|
+
// The check and the append happen under one cross-process lock, so two senses retrying the same delivery cannot both miss it.
|
|
130
|
+
return (0, file_lock_1.withFileLock)(path.join(this.agentRoot, "state", "outbox", ".locks"), `once-${friendId}`, () => {
|
|
131
|
+
for (const id of sortedIds(dir)) {
|
|
132
|
+
const entry = readEntry(path.join(dir, `${id}.json`));
|
|
133
|
+
if (entry?.meta?.dedupeKey === dedupeKey)
|
|
134
|
+
return entry;
|
|
135
|
+
}
|
|
136
|
+
return this.append(friendId, { ...input, meta: { ...input.meta, dedupeKey } }, now);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/** Entries after `since` (exclusive), oldest first, within the count and size limits. */
|
|
140
|
+
list(friendId, options = {}) {
|
|
141
|
+
const dir = entryDir(this.agentRoot, friendId);
|
|
142
|
+
const limit = Math.min(Math.max(1, Math.floor(options.limit ?? exports.OUTBOX_LIST_DEFAULT_LIMIT)), exports.OUTBOX_LIST_MAX_LIMIT);
|
|
143
|
+
const since = options.since ?? "";
|
|
144
|
+
const ids = sortedIds(dir).filter((id) => id > since);
|
|
145
|
+
const entries = [];
|
|
146
|
+
let chars = 0;
|
|
147
|
+
let more = false;
|
|
148
|
+
for (const id of ids) {
|
|
149
|
+
const entry = readEntry(path.join(dir, `${id}.json`));
|
|
150
|
+
if (!entry)
|
|
151
|
+
continue;
|
|
152
|
+
const size = JSON.stringify(entry).length;
|
|
153
|
+
if (entries.length >= limit || (entries.length > 0 && chars + size > exports.OUTBOX_LIST_MAX_CHARS)) {
|
|
154
|
+
more = true;
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
entries.push(entry);
|
|
158
|
+
chars += size;
|
|
159
|
+
}
|
|
160
|
+
return { entries, nextCursor: entries.length > 0 ? entries[entries.length - 1].id : null, more };
|
|
161
|
+
}
|
|
162
|
+
/** Removes the named entries from this friend's outbox only; ids that are malformed or not there come back as unknown. */
|
|
163
|
+
ack(friendId, ids) {
|
|
164
|
+
const dir = entryDir(this.agentRoot, friendId);
|
|
165
|
+
const acked = [];
|
|
166
|
+
const unknown = [];
|
|
167
|
+
for (const id of ids) {
|
|
168
|
+
const file = isOutboxEntryId(id) ? path.join(dir, `${id}.json`) : null;
|
|
169
|
+
if (file && fs.existsSync(file)) {
|
|
170
|
+
fs.rmSync(file, { force: true });
|
|
171
|
+
acked.push(id);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
unknown.push(id);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (acked.length > 0) {
|
|
178
|
+
(0, runtime_1.emitNervesEvent)({
|
|
179
|
+
component: "senses",
|
|
180
|
+
event: "senses.a2a_outbox_acked",
|
|
181
|
+
message: "a peer cleared entries from its outbox",
|
|
182
|
+
meta: { friendId, count: acked.length },
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
return { acked, unknown };
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
exports.FileOutboxStore = FileOutboxStore;
|