@ouro.bot/cli 0.1.0-alpha.92 → 0.1.0-alpha.920
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 +5819 -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 +344 -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 +245 -0
- package/dist/senses/shepherd/redact.js +66 -0
- package/dist/senses/shepherd/returns.js +79 -0
- package/dist/senses/shepherd/sense.js +309 -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,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.A2ARpcError = void 0;
|
|
4
|
+
exports.cardDid = cardDid;
|
|
5
|
+
exports.endpointForCard = endpointForCard;
|
|
6
|
+
exports.fetchA2AAgentCard = fetchA2AAgentCard;
|
|
7
|
+
exports.postJsonRpc = postJsonRpc;
|
|
8
|
+
exports.sendA2AMessage = sendA2AMessage;
|
|
9
|
+
exports.postA2AMessageEnvelope = postA2AMessageEnvelope;
|
|
10
|
+
exports.getA2ATask = getA2ATask;
|
|
11
|
+
exports.sendSealedA2AChat = sendSealedA2AChat;
|
|
12
|
+
const node_crypto_1 = require("node:crypto");
|
|
13
|
+
const a2a_client_1 = require("@ouro.bot/friends/a2a-client");
|
|
14
|
+
const runtime_1 = require("../nerves/runtime");
|
|
15
|
+
const sealed_chat_1 = require("./sealed-chat");
|
|
16
|
+
/** The trimmed `did:key` a card serves, or undefined when the card is did-less. */
|
|
17
|
+
function cardDid(card) {
|
|
18
|
+
const did = card.did;
|
|
19
|
+
return typeof did === "string" && did.trim() ? did.trim() : undefined;
|
|
20
|
+
}
|
|
21
|
+
function endpointForCard(card) {
|
|
22
|
+
const jsonRpc = card.supportedInterfaces?.find((entry) => (entry.protocolBinding ?? entry.transport)?.toUpperCase() === "JSONRPC");
|
|
23
|
+
if (jsonRpc?.url)
|
|
24
|
+
return jsonRpc.url;
|
|
25
|
+
if (card.preferredTransport?.toUpperCase() === "JSONRPC" && card.url)
|
|
26
|
+
return card.url;
|
|
27
|
+
const legacyJsonRpc = card.additionalInterfaces?.find((entry) => entry.transport.toUpperCase() === "JSONRPC");
|
|
28
|
+
return legacyJsonRpc?.url ?? card.url;
|
|
29
|
+
}
|
|
30
|
+
async function fetchA2AAgentCard(cardUrl, fetchImpl = fetch) {
|
|
31
|
+
(0, runtime_1.emitNervesEvent)({
|
|
32
|
+
component: "channels",
|
|
33
|
+
event: "channel.a2a_card_fetch_start",
|
|
34
|
+
message: "fetching A2A agent card",
|
|
35
|
+
meta: { cardUrl },
|
|
36
|
+
});
|
|
37
|
+
const response = await fetchImpl(cardUrl);
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
throw new Error(`A2A card fetch failed (${response.status} ${response.statusText})`);
|
|
40
|
+
}
|
|
41
|
+
const parsed = await response.json();
|
|
42
|
+
const endpoint = endpointForCard(parsed);
|
|
43
|
+
if (!parsed || typeof parsed !== "object" || typeof endpoint !== "string" || typeof parsed.name !== "string") {
|
|
44
|
+
throw new Error("A2A card is missing required name or JSONRPC endpoint fields");
|
|
45
|
+
}
|
|
46
|
+
(0, runtime_1.emitNervesEvent)({
|
|
47
|
+
component: "channels",
|
|
48
|
+
event: "channel.a2a_card_fetch_end",
|
|
49
|
+
message: "fetched A2A agent card",
|
|
50
|
+
meta: { cardUrl, endpoint, name: parsed.name },
|
|
51
|
+
});
|
|
52
|
+
return parsed;
|
|
53
|
+
}
|
|
54
|
+
/** A JSON-RPC error answer from the peer. `data` carries the peer's structured detail (for a refused delegated command: reason, nothingRan, retry, next). */
|
|
55
|
+
class A2ARpcError extends Error {
|
|
56
|
+
code;
|
|
57
|
+
data;
|
|
58
|
+
constructor(error) {
|
|
59
|
+
super(`A2A error ${error.code}: ${error.message}`);
|
|
60
|
+
this.code = error.code;
|
|
61
|
+
this.data = error.data;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.A2ARpcError = A2ARpcError;
|
|
65
|
+
async function postJsonRpc(endpointUrl, request, fetchImpl, protocolVersion = "1.0") {
|
|
66
|
+
const response = await fetchImpl(endpointUrl, {
|
|
67
|
+
method: "POST",
|
|
68
|
+
headers: { "content-type": "application/json", "A2A-Version": protocolVersion },
|
|
69
|
+
body: JSON.stringify(request),
|
|
70
|
+
});
|
|
71
|
+
if (!response.ok) {
|
|
72
|
+
throw new Error(`A2A JSON-RPC request failed (${response.status} ${response.statusText})`);
|
|
73
|
+
}
|
|
74
|
+
return await response.json();
|
|
75
|
+
}
|
|
76
|
+
function methodNotFound(response) {
|
|
77
|
+
return "error" in response && response.error.code === -32601;
|
|
78
|
+
}
|
|
79
|
+
function senderMetadata(input) {
|
|
80
|
+
return {
|
|
81
|
+
...(input.senderAgentId ? { senderAgentId: input.senderAgentId } : {}),
|
|
82
|
+
...(input.senderName ? { senderName: input.senderName } : {}),
|
|
83
|
+
...(input.senderCardUrl ? { senderCardUrl: input.senderCardUrl } : {}),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
async function sendA2AMessage(input) {
|
|
87
|
+
const fetchImpl = input.fetchImpl ?? fetch;
|
|
88
|
+
const messageId = (0, node_crypto_1.randomUUID)();
|
|
89
|
+
const request = {
|
|
90
|
+
jsonrpc: "2.0",
|
|
91
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
92
|
+
method: "message/send",
|
|
93
|
+
params: {
|
|
94
|
+
message: {
|
|
95
|
+
kind: "message",
|
|
96
|
+
role: "user",
|
|
97
|
+
messageId,
|
|
98
|
+
...(input.taskId ? { taskId: input.taskId } : {}),
|
|
99
|
+
contextId: input.sessionKey ?? "default",
|
|
100
|
+
parts: [{ kind: "text", text: input.message }],
|
|
101
|
+
metadata: senderMetadata(input),
|
|
102
|
+
},
|
|
103
|
+
...(input.accessToken ? { accessToken: input.accessToken } : {}),
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
(0, runtime_1.emitNervesEvent)({
|
|
107
|
+
component: "channels",
|
|
108
|
+
event: "channel.a2a_message_send_start",
|
|
109
|
+
message: "sending A2A message",
|
|
110
|
+
meta: { endpointUrl: input.endpointUrl, messageId },
|
|
111
|
+
});
|
|
112
|
+
let rpc = await postJsonRpc(input.endpointUrl, request, fetchImpl, "0.3");
|
|
113
|
+
if (methodNotFound(rpc)) {
|
|
114
|
+
rpc = await postJsonRpc(input.endpointUrl, {
|
|
115
|
+
...request,
|
|
116
|
+
method: "SendMessage",
|
|
117
|
+
params: {
|
|
118
|
+
...request.params,
|
|
119
|
+
message: {
|
|
120
|
+
...(request.params.message),
|
|
121
|
+
role: "ROLE_USER",
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
}, fetchImpl);
|
|
125
|
+
}
|
|
126
|
+
if ("error" in rpc) {
|
|
127
|
+
throw new A2ARpcError(rpc.error);
|
|
128
|
+
}
|
|
129
|
+
const result = rpc.result;
|
|
130
|
+
const task = "task" in result && result.task ? result.task : result;
|
|
131
|
+
(0, runtime_1.emitNervesEvent)({
|
|
132
|
+
component: "channels",
|
|
133
|
+
event: "channel.a2a_message_send_end",
|
|
134
|
+
message: "sent A2A message",
|
|
135
|
+
meta: { endpointUrl: input.endpointUrl, messageId, taskId: task.id },
|
|
136
|
+
});
|
|
137
|
+
return task;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* POST a pre-built friends A2A message (a `wrapInDataPart` sealed-envelope message)
|
|
141
|
+
* to a peer endpoint as a JSON-RPC `message/send`. This is the `direct`-rung wire
|
|
142
|
+
* the harness `A2ATransport` uses: friends' `sendShare` builds the sealed message and
|
|
143
|
+
* hands it to the transport, which delivers it here. Unlike `sendA2AMessage` (which
|
|
144
|
+
* builds a text part), this carries the caller's exact `message` (the sealed DataPart)
|
|
145
|
+
* untouched. Throws on a non-2xx response (transport failure).
|
|
146
|
+
*/
|
|
147
|
+
async function postA2AMessageEnvelope(input) {
|
|
148
|
+
const fetchImpl = input.fetchImpl ?? fetch;
|
|
149
|
+
const request = {
|
|
150
|
+
jsonrpc: "2.0",
|
|
151
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
152
|
+
method: "message/send",
|
|
153
|
+
params: { message: input.message },
|
|
154
|
+
};
|
|
155
|
+
(0, runtime_1.emitNervesEvent)({
|
|
156
|
+
component: "channels",
|
|
157
|
+
event: "channel.a2a_envelope_post_start",
|
|
158
|
+
message: "posting sealed A2A message envelope (direct rung)",
|
|
159
|
+
meta: { endpointUrl: input.endpointUrl },
|
|
160
|
+
});
|
|
161
|
+
let rpc = await postJsonRpc(input.endpointUrl, request, fetchImpl, "0.3");
|
|
162
|
+
if (methodNotFound(rpc)) {
|
|
163
|
+
rpc = await postJsonRpc(input.endpointUrl, { ...request, method: "SendMessage" }, fetchImpl);
|
|
164
|
+
}
|
|
165
|
+
if ("error" in rpc) {
|
|
166
|
+
throw new A2ARpcError(rpc.error);
|
|
167
|
+
}
|
|
168
|
+
(0, runtime_1.emitNervesEvent)({
|
|
169
|
+
component: "channels",
|
|
170
|
+
event: "channel.a2a_envelope_post_end",
|
|
171
|
+
message: "posted sealed A2A message envelope",
|
|
172
|
+
meta: { endpointUrl: input.endpointUrl },
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
async function getA2ATask(input) {
|
|
176
|
+
const fetchImpl = input.fetchImpl ?? fetch;
|
|
177
|
+
const metadata = senderMetadata(input);
|
|
178
|
+
const request = {
|
|
179
|
+
jsonrpc: "2.0",
|
|
180
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
181
|
+
method: "tasks/get",
|
|
182
|
+
params: {
|
|
183
|
+
id: input.taskId,
|
|
184
|
+
...(input.accessToken ? { accessToken: input.accessToken } : {}),
|
|
185
|
+
...(Object.keys(metadata).length > 0 ? { metadata } : {}),
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
(0, runtime_1.emitNervesEvent)({
|
|
189
|
+
component: "channels",
|
|
190
|
+
event: "channel.a2a_task_get",
|
|
191
|
+
message: "fetching A2A task",
|
|
192
|
+
meta: { endpointUrl: input.endpointUrl, taskId: input.taskId },
|
|
193
|
+
});
|
|
194
|
+
let rpc = await postJsonRpc(input.endpointUrl, request, fetchImpl, "0.3");
|
|
195
|
+
if (methodNotFound(rpc)) {
|
|
196
|
+
rpc = await postJsonRpc(input.endpointUrl, { ...request, method: "GetTask" }, fetchImpl);
|
|
197
|
+
}
|
|
198
|
+
if ("error" in rpc) {
|
|
199
|
+
throw new A2ARpcError(rpc.error);
|
|
200
|
+
}
|
|
201
|
+
return rpc.result;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Talk to an A2A agent as a verified friend: seal `text` to the agent's card DID,
|
|
205
|
+
* signed by `identity`, send it, and open the sealed reply. The card must serve a
|
|
206
|
+
* did:key bound to it (the same check onboarding applies), so the reply can only be
|
|
207
|
+
* accepted from that key. Neither direction ever travels in plaintext.
|
|
208
|
+
*/
|
|
209
|
+
async function sendSealedA2AChat(input) {
|
|
210
|
+
const fetchImpl = input.fetchImpl ?? fetch;
|
|
211
|
+
const sodium = input.sodium ?? await (0, a2a_client_1.ready)();
|
|
212
|
+
const card = await fetchA2AAgentCard(input.cardUrl, fetchImpl);
|
|
213
|
+
const peerDid = cardDid(card);
|
|
214
|
+
if (!peerDid)
|
|
215
|
+
throw new Error(`A2A card ${input.cardUrl} serves no DID; sealed chat needs one`);
|
|
216
|
+
const parsed = (0, a2a_client_1.parseDidKey)(peerDid);
|
|
217
|
+
if (!parsed || !(0, a2a_client_1.verifyCardDidBinding)({ card: { did: peerDid, url: input.cardUrl }, did: peerDid, didDoc: null })) {
|
|
218
|
+
throw new Error(`A2A card↔DID binding failed for ${peerDid}`);
|
|
219
|
+
}
|
|
220
|
+
const endpointUrl = endpointForCard(card);
|
|
221
|
+
const conversationId = input.conversationId ?? (0, node_crypto_1.randomUUID)();
|
|
222
|
+
const sealed = (0, sealed_chat_1.sealChatMessage)({
|
|
223
|
+
sodium,
|
|
224
|
+
from: input.identity,
|
|
225
|
+
recipientDid: peerDid,
|
|
226
|
+
recipientEd25519Pub: parsed.ed25519Pub,
|
|
227
|
+
text: input.text,
|
|
228
|
+
conversationId,
|
|
229
|
+
...(input.onBehalfOf ? { onBehalfOf: input.onBehalfOf } : {}),
|
|
230
|
+
});
|
|
231
|
+
const request = {
|
|
232
|
+
jsonrpc: "2.0",
|
|
233
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
234
|
+
method: "SendMessage",
|
|
235
|
+
params: { message: { kind: "message", role: "ROLE_USER", messageId: (0, node_crypto_1.randomUUID)(), contextId: conversationId, parts: sealed.parts } },
|
|
236
|
+
};
|
|
237
|
+
(0, runtime_1.emitNervesEvent)({ component: "channels", event: "channel.a2a_chat_send_start", message: "sending sealed A2A chat message", meta: { endpointUrl, peerDid } });
|
|
238
|
+
const rpc = await postJsonRpc(endpointUrl, request, fetchImpl);
|
|
239
|
+
if ("error" in rpc)
|
|
240
|
+
throw new A2ARpcError(rpc.error);
|
|
241
|
+
const task = rpc.result;
|
|
242
|
+
const replyMessage = task?.status?.message;
|
|
243
|
+
if (!replyMessage)
|
|
244
|
+
throw new Error("A2A chat returned no reply message");
|
|
245
|
+
const opened = await (0, sealed_chat_1.openChatMessage)({ sodium, self: input.identity, message: replyMessage, senderDid: peerDid, senderEd25519Pub: parsed.ed25519Pub });
|
|
246
|
+
if (!opened.ok)
|
|
247
|
+
throw new Error(`A2A chat reply rejected: ${opened.reason}`);
|
|
248
|
+
(0, runtime_1.emitNervesEvent)({ component: "channels", event: "channel.a2a_chat_send_end", message: "received sealed A2A chat reply", meta: { endpointUrl, peerDid, taskId: task.id } });
|
|
249
|
+
return { text: opened.text, conversationId, taskId: task.id, peerDid, peerName: card.name };
|
|
250
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.A2A_DEFAULT_PATH = exports.A2A_DEFAULT_HOST = exports.A2A_DEFAULT_PROTOCOL_VERSION = void 0;
|
|
4
|
+
exports.defaultA2APort = defaultA2APort;
|
|
5
|
+
exports.normalizeA2APath = normalizeA2APath;
|
|
6
|
+
exports.a2aEndpointFromBaseUrl = a2aEndpointFromBaseUrl;
|
|
7
|
+
const node_crypto_1 = require("node:crypto");
|
|
8
|
+
const runtime_1 = require("../nerves/runtime");
|
|
9
|
+
exports.A2A_DEFAULT_PROTOCOL_VERSION = "1.0";
|
|
10
|
+
exports.A2A_DEFAULT_HOST = "127.0.0.1";
|
|
11
|
+
exports.A2A_DEFAULT_PATH = "/a2a";
|
|
12
|
+
function defaultA2APort(agentName) {
|
|
13
|
+
const digest = (0, node_crypto_1.createHash)("sha256").update(agentName).digest();
|
|
14
|
+
const port = 18920 + (digest[0] % 60);
|
|
15
|
+
(0, runtime_1.emitNervesEvent)({
|
|
16
|
+
component: "channels",
|
|
17
|
+
event: "channel.a2a_default_port",
|
|
18
|
+
message: "computed default A2A port",
|
|
19
|
+
meta: { agentName, port },
|
|
20
|
+
});
|
|
21
|
+
return port;
|
|
22
|
+
}
|
|
23
|
+
function normalizeA2APath(value) {
|
|
24
|
+
const trimmed = value?.trim();
|
|
25
|
+
const normalized = !trimmed
|
|
26
|
+
? exports.A2A_DEFAULT_PATH
|
|
27
|
+
: trimmed.startsWith("/")
|
|
28
|
+
? trimmed
|
|
29
|
+
: `/${trimmed}`;
|
|
30
|
+
(0, runtime_1.emitNervesEvent)({
|
|
31
|
+
component: "channels",
|
|
32
|
+
event: "channel.a2a_path_normalized",
|
|
33
|
+
message: "normalized A2A path",
|
|
34
|
+
meta: { normalized },
|
|
35
|
+
});
|
|
36
|
+
return normalized;
|
|
37
|
+
}
|
|
38
|
+
function a2aEndpointFromBaseUrl(baseUrl, a2aPath = exports.A2A_DEFAULT_PATH) {
|
|
39
|
+
const url = new URL(baseUrl);
|
|
40
|
+
url.pathname = normalizeA2APath(a2aPath);
|
|
41
|
+
url.search = "";
|
|
42
|
+
url.hash = "";
|
|
43
|
+
(0, runtime_1.emitNervesEvent)({
|
|
44
|
+
component: "channels",
|
|
45
|
+
event: "channel.a2a_endpoint_built",
|
|
46
|
+
message: "built A2A endpoint URL",
|
|
47
|
+
meta: { endpoint: url.toString() },
|
|
48
|
+
});
|
|
49
|
+
return url.toString();
|
|
50
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DELEGATED_COMMAND_GRANTS_FILE = void 0;
|
|
4
|
+
exports.delegatedCommandGrantsPath = delegatedCommandGrantsPath;
|
|
5
|
+
exports.viewDelegatedCommandGrants = viewDelegatedCommandGrants;
|
|
6
|
+
exports.readDelegatedCommandGrants = readDelegatedCommandGrants;
|
|
7
|
+
exports.checkDelegatedCommandGrant = checkDelegatedCommandGrant;
|
|
8
|
+
exports.setDelegatedCommandGrant = setDelegatedCommandGrant;
|
|
9
|
+
const runtime_1 = require("../nerves/runtime");
|
|
10
|
+
const operator_trust_1 = require("./operator-trust");
|
|
11
|
+
const replay_grant_holders_1 = require("./replay-grant-holders");
|
|
12
|
+
const replay_harness_1 = require("./replay-harness");
|
|
13
|
+
exports.DELEGATED_COMMAND_GRANTS_FILE = "delegated-command-grants.json";
|
|
14
|
+
function delegatedCommandGrantsPath(agentRoot) {
|
|
15
|
+
return (0, operator_trust_1.operatorTrustFile)(agentRoot, exports.DELEGATED_COMMAND_GRANTS_FILE);
|
|
16
|
+
}
|
|
17
|
+
function validGrant(value) {
|
|
18
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
19
|
+
return false;
|
|
20
|
+
const grant = value;
|
|
21
|
+
const keys = Object.keys(grant).sort().join(",");
|
|
22
|
+
return (keys === "did,grantedAt,scope,source" || keys === "did,expiresAt,grantedAt,scope,source")
|
|
23
|
+
&& grant.scope === "principal_commands"
|
|
24
|
+
&& typeof grant.did === "string" && grant.did.startsWith("did:") && grant.did.length <= 512
|
|
25
|
+
&& typeof grant.grantedAt === "string" && !Number.isNaN(Date.parse(grant.grantedAt))
|
|
26
|
+
&& typeof grant.source === "string" && grant.source.trim().length > 0
|
|
27
|
+
&& (grant.expiresAt === undefined || typeof grant.expiresAt === "string");
|
|
28
|
+
}
|
|
29
|
+
/** The file's trust state, every well-formed grant in it keyed by friend id, and the friend ids whose entries were dropped. */
|
|
30
|
+
function viewDelegatedCommandGrants(agentRoot) {
|
|
31
|
+
return (0, operator_trust_1.readGrantFile)(agentRoot, exports.DELEGATED_COMMAND_GRANTS_FILE, validGrant);
|
|
32
|
+
}
|
|
33
|
+
function readDelegatedCommandGrants(agentRoot) {
|
|
34
|
+
return viewDelegatedCommandGrants(agentRoot).grants;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The one answer to "may this friend relay the principal's commands right now?". Admission, the follow-up path and
|
|
38
|
+
* `list` all ask it, so they cannot disagree. `signerDid` is the DID the message was verified as: it must equal the
|
|
39
|
+
* DID the operator pinned. Order: file trusted, grant exists, DID matches, not expired (an expiry that is not a finite
|
|
40
|
+
* time counts as expired, and so does a replay identity whose root-owned window is closed), then family and active.
|
|
41
|
+
*/
|
|
42
|
+
function checkDelegatedCommandGrant(agentRoot, friend, signerDid, now = Date.now()) {
|
|
43
|
+
const view = viewDelegatedCommandGrants(agentRoot);
|
|
44
|
+
if (view.state === "untrusted")
|
|
45
|
+
return { ok: false, reason: "grants_untrusted" };
|
|
46
|
+
const grant = view.grants[friend.id];
|
|
47
|
+
if (!grant)
|
|
48
|
+
return { ok: false, reason: "no_grant" };
|
|
49
|
+
if (grant.did !== signerDid)
|
|
50
|
+
return { ok: false, reason: "grant_did_mismatch" };
|
|
51
|
+
if (grant.expiresAt !== undefined) {
|
|
52
|
+
const expiresAt = Date.parse(grant.expiresAt);
|
|
53
|
+
if (!Number.isFinite(expiresAt) || expiresAt <= now)
|
|
54
|
+
return { ok: false, reason: "grant_expired" };
|
|
55
|
+
}
|
|
56
|
+
// A grant for a friend on the root-owned replay list must be time-bounded by the trusted file itself. The bundle's replay registry is the agent's to move aside, so it only ever adds the window check below.
|
|
57
|
+
if (grant.expiresAt === undefined && (0, replay_grant_holders_1.isReplayGrantHolder)(agentRoot, friend.id))
|
|
58
|
+
return { ok: false, reason: "grant_expired" };
|
|
59
|
+
// A replay identity is a test peer of the host's replay gate: its grant means something only while the root-owned window is open.
|
|
60
|
+
if ((0, replay_harness_1.isReplayIdentity)(agentRoot, friend.id) && !(0, replay_harness_1.isReplayWindowOpen)(agentRoot, friend.id, now))
|
|
61
|
+
return { ok: false, reason: "grant_expired" };
|
|
62
|
+
if (friend.trustLevel !== "family" || friend.admissionState !== "active")
|
|
63
|
+
return { ok: false, reason: "not_family" };
|
|
64
|
+
return { ok: true };
|
|
65
|
+
}
|
|
66
|
+
/** Writes or removes one grant. The previous file is kept beside it as a timestamped backup before the change. */
|
|
67
|
+
function setDelegatedCommandGrant(agentRoot, friendId, change, now = new Date()) {
|
|
68
|
+
return (0, operator_trust_1.withTrustedWriteLock)(agentRoot, () => setDelegatedCommandGrantLocked(agentRoot, friendId, change, now));
|
|
69
|
+
}
|
|
70
|
+
function setDelegatedCommandGrantLocked(agentRoot, friendId, change, now) {
|
|
71
|
+
const current = readDelegatedCommandGrants(agentRoot);
|
|
72
|
+
const had = current[friendId];
|
|
73
|
+
const next = { ...current };
|
|
74
|
+
if (change.grant) {
|
|
75
|
+
const entry = { scope: "principal_commands", did: change.did, grantedAt: now.toISOString(), source: change.source, ...(change.expiresAt ? { expiresAt: change.expiresAt } : {}) };
|
|
76
|
+
if (had && had.did === entry.did && had.source === entry.source && had.expiresAt === entry.expiresAt)
|
|
77
|
+
return { changed: false, backup: null };
|
|
78
|
+
next[friendId] = entry;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
if (had === undefined)
|
|
82
|
+
return { changed: false, backup: null };
|
|
83
|
+
delete next[friendId];
|
|
84
|
+
}
|
|
85
|
+
const { backup } = (0, operator_trust_1.writeTrustedFile)(agentRoot, exports.DELEGATED_COMMAND_GRANTS_FILE, `${JSON.stringify({ schemaVersion: 1, grants: next }, null, 2)}\n`, now);
|
|
86
|
+
(0, runtime_1.emitNervesEvent)({
|
|
87
|
+
component: "senses",
|
|
88
|
+
event: "senses.a2a_delegated_command_grant_changed",
|
|
89
|
+
message: change.grant ? "granted delegated commands to an A2A peer" : "revoked an A2A peer's delegated-command grant",
|
|
90
|
+
meta: { friendId, granted: change.grant },
|
|
91
|
+
});
|
|
92
|
+
return { changed: true, backup };
|
|
93
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
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.DELEGATED_BANNER = exports.A2A_PRINCIPAL_PROFILE_ID = void 0;
|
|
37
|
+
exports.delegatedCommandWasNoticed = delegatedCommandWasNoticed;
|
|
38
|
+
exports.delegationRefusalGuidance = delegationRefusalGuidance;
|
|
39
|
+
exports.shieldDelegatedBanner = shieldDelegatedBanner;
|
|
40
|
+
exports.delegatedCommandNotice = delegatedCommandNotice;
|
|
41
|
+
exports.admitDelegatedCommand = admitDelegatedCommand;
|
|
42
|
+
const crypto_1 = require("crypto");
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const runtime_1 = require("../nerves/runtime");
|
|
46
|
+
const delegated_command_grants_1 = require("./delegated-command-grants");
|
|
47
|
+
const replay_harness_1 = require("./replay-harness");
|
|
48
|
+
const relationship_authorization_1 = require("../repertoire/relationship-authorization");
|
|
49
|
+
const NOTICE_EXCERPT_CHARS = 200;
|
|
50
|
+
/** The relationship profile that names the principal a delegated peer acts for. */
|
|
51
|
+
exports.A2A_PRINCIPAL_PROFILE_ID = "sanctuary-owner";
|
|
52
|
+
/**
|
|
53
|
+
* True when the owner was told about delegated command `commandId` in their own chat: admission only runs a command
|
|
54
|
+
* after that notice is delivered, and the Telegram effect journal keeps the notice under a key derived from the
|
|
55
|
+
* command id. A request id with no such record never came through a signed, owner-notified delegated command.
|
|
56
|
+
* A missing record is `false`; an unreadable or malformed one throws, so the caller retries instead of deciding.
|
|
57
|
+
*/
|
|
58
|
+
function delegatedCommandWasNoticed(agentRoot, commandId, principalFriendId, delegateFriendId) {
|
|
59
|
+
const idempotencyKey = `owner-notice:delegated:${commandId}`;
|
|
60
|
+
const file = path.join(agentRoot, "state", "telegram", "effects", `${(0, crypto_1.createHash)("sha256").update(idempotencyKey).digest("hex")}.json`);
|
|
61
|
+
let raw;
|
|
62
|
+
try {
|
|
63
|
+
raw = fs.readFileSync(file, "utf8");
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
if (error.code === "ENOENT")
|
|
67
|
+
return delegateFriendId !== undefined && (0, replay_harness_1.isReplayWindowOpen)(agentRoot, delegateFriendId) && (0, replay_harness_1.replayNoticeRecorded)(agentRoot, `delegated:${commandId}`, delegateFriendId);
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
const artifact = JSON.parse(raw);
|
|
71
|
+
return artifact.idempotencyKey === idempotencyKey && artifact.authorClass === "butler" && artifact.target?.friendId === principalFriendId;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* What a refused sender is told. Every refusal says that nothing ran and names the next step; the reason code stays
|
|
75
|
+
* first on the wire (`delegated command refused: <reason>`) because the replay gate and older CLIs match it.
|
|
76
|
+
*/
|
|
77
|
+
function delegationRefusalGuidance(reason, hints) {
|
|
78
|
+
switch (reason) {
|
|
79
|
+
case "not_enabled":
|
|
80
|
+
return { message: "this agent does not accept delegated commands", next: "Send the message without --delegated, or ask the agent's operator to enable delegated commands.", retry: false };
|
|
81
|
+
case "no_grant":
|
|
82
|
+
return {
|
|
83
|
+
message: hints.legacyRecordGrant
|
|
84
|
+
? "the operator has not granted you delegated commands; a grant on your friend record is not honoured, because the agent could have written it"
|
|
85
|
+
: "the operator has not granted you delegated commands",
|
|
86
|
+
next: `Ask the operator to run, as root on the agent's host: ouro a2a delegated-commands grant --friend <your friend id> --did <your DID> (your DID is in: ouro a2a identity --json).${hints.legacyRecordGrant ? " Grants live in the operator trust directory now, not on the friend record." : ""}`,
|
|
87
|
+
retry: false,
|
|
88
|
+
};
|
|
89
|
+
case "grants_untrusted":
|
|
90
|
+
return { message: "the agent cannot trust its grant file, so it honours no delegated-command grants", next: "Ask the operator to run: ouro a2a delegated-commands list, and fix the owner or mode it reports.", retry: false };
|
|
91
|
+
case "grant_did_mismatch":
|
|
92
|
+
return { message: "this message was signed by a different key than the one the operator granted", next: "Send from the host whose DID the operator pinned, or ask the operator to re-grant with your current DID: ouro a2a delegated-commands grant --friend <your friend id> --did <your DID>.", retry: false };
|
|
93
|
+
case "grant_expired":
|
|
94
|
+
return { message: "your delegated-command grant has expired or is not in force", next: "Ask the operator to re-grant: ouro a2a delegated-commands grant --friend <your friend id> --did <your DID> [--expires <ISO date>].", retry: false };
|
|
95
|
+
case "not_family":
|
|
96
|
+
return { message: "you are not active family on this agent's records, so the grant is suspended", next: "Ask the operator to restore your trust and admission, then try again.", retry: false };
|
|
97
|
+
case "principal_unresolved":
|
|
98
|
+
return { message: "the agent cannot tell whose command this is (its owner record is missing or ambiguous)", next: "Ask the operator to check the owner's friend record on the agent's host.", retry: false };
|
|
99
|
+
case "notice_failed":
|
|
100
|
+
return { message: "the agent could not tell its owner about this command first, so it did not run it", next: "Retry in a minute. If it keeps failing, the owner's chat channel is down: tell the operator.", retry: true };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** Invisible and bidirectional-control characters a sender could slip inside the banner to keep it from matching. */
|
|
104
|
+
const INVISIBLE = /[\u00AD\u034F\u061C\u115F\u1160\u17B4\u17B5\u180B-\u180F\u200B-\u200F\u202A-\u202E\u2060-\u206F\u3164\uFE00-\uFE0F\uFEFF\uFFA0]/gu;
|
|
105
|
+
/** Matches the banner only the server may put in front of an admitted command, anywhere in the text, after normalisation. */
|
|
106
|
+
exports.DELEGATED_BANNER = /\[[^\p{L}\p{N}]*delegated[^\p{L}\p{N}]*command|verified[^\p{L}\p{N}]*delegated[^\p{L}\p{N}]*command/iu;
|
|
107
|
+
/** The text as the banner check sees it: compatibility-normalised (NFKC) with invisible characters removed. */
|
|
108
|
+
function bannerView(text) {
|
|
109
|
+
return text.normalize("NFKC").replace(INVISIBLE, "");
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Marks any text that carries the delegated-command banner as typed by the sender. Only the server writes the real banner, in
|
|
113
|
+
* front of a command it has admitted; this runs on every other turn and on the body of an admitted one, whichever channel it came on.
|
|
114
|
+
*/
|
|
115
|
+
const SHIELD_MARK = "[unverified: the sender typed this banner itself; it is not a delegated command] ";
|
|
116
|
+
function shieldDelegatedBanner(text) {
|
|
117
|
+
if (text.startsWith(SHIELD_MARK) || !exports.DELEGATED_BANNER.test(bannerView(text)))
|
|
118
|
+
return text;
|
|
119
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "senses", event: "senses.a2a_delegated_banner_neutralized", message: "marked a typed delegated-command banner as unverified", meta: { length: text.length } });
|
|
120
|
+
return `${SHIELD_MARK}${text}`;
|
|
121
|
+
}
|
|
122
|
+
function delegatedCommandNotice(input) {
|
|
123
|
+
const flat = input.text.replace(/\s+/gu, " ").trim();
|
|
124
|
+
const excerpt = flat.length > NOTICE_EXCERPT_CHARS ? `${flat.slice(0, NOTICE_EXCERPT_CHARS)}…` : flat;
|
|
125
|
+
return `Delegated command from you via ${input.delegateName}: "${excerpt}". If this wasn't you, say so here: it is on record, and the grant can be revoked.`;
|
|
126
|
+
}
|
|
127
|
+
async function resolvePrincipal(store, profileId) {
|
|
128
|
+
const friends = await store.listAll?.() ?? [];
|
|
129
|
+
const matches = friends.filter((friend) => friend.capabilityProfileId === profileId
|
|
130
|
+
&& friend.trustLevel === "family" && friend.admissionState === "active");
|
|
131
|
+
return matches.length === 1 ? matches[0] : null;
|
|
132
|
+
}
|
|
133
|
+
async function admitDelegatedCommand(input) {
|
|
134
|
+
const refuse = (reason) => {
|
|
135
|
+
(0, runtime_1.emitNervesEvent)({
|
|
136
|
+
level: "warn",
|
|
137
|
+
component: "senses",
|
|
138
|
+
event: "senses.a2a_delegated_command_refused",
|
|
139
|
+
message: "refused a delegated A2A command",
|
|
140
|
+
meta: { reason, delegateFriendId: input.friend.id, commandId: input.commandId },
|
|
141
|
+
});
|
|
142
|
+
return { ok: false, reason };
|
|
143
|
+
};
|
|
144
|
+
if (!input.options)
|
|
145
|
+
return refuse("not_enabled");
|
|
146
|
+
const granted = (0, delegated_command_grants_1.checkDelegatedCommandGrant)(input.options.agentRoot, input.friend, input.did, input.now);
|
|
147
|
+
if (!granted.ok)
|
|
148
|
+
return refuse(granted.reason);
|
|
149
|
+
const registry = input.registry;
|
|
150
|
+
if (!registry)
|
|
151
|
+
return refuse("principal_unresolved");
|
|
152
|
+
const principal = await resolvePrincipal(input.store, input.options.principalProfileId);
|
|
153
|
+
if (!principal || principal.id === input.friend.id)
|
|
154
|
+
return refuse("principal_unresolved");
|
|
155
|
+
const noticeId = `delegated:${input.commandId}`;
|
|
156
|
+
try {
|
|
157
|
+
const text = delegatedCommandNotice({ delegateName: input.friend.name, text: input.text });
|
|
158
|
+
const agentRoot = input.options.agentRoot;
|
|
159
|
+
if ((0, replay_harness_1.isReplayWindowOpen)(agentRoot, input.friend.id))
|
|
160
|
+
(0, replay_harness_1.appendReplayNotice)(agentRoot, { noticeId, text, friendId: input.friend.id });
|
|
161
|
+
else
|
|
162
|
+
await input.options.notifyPrincipal({ noticeId, text });
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return refuse("notice_failed");
|
|
166
|
+
}
|
|
167
|
+
// Owner-gated tools (steward policy) bind the mutation to `requestId` on the tool
|
|
168
|
+
// context's relationship, as the Telegram owner turn does; the evaluator alone
|
|
169
|
+
// only scopes its receipts by it, so carry it on the relationship itself.
|
|
170
|
+
const relationship = {
|
|
171
|
+
...(0, relationship_authorization_1.createRelationshipAuthorizationEvaluator)({
|
|
172
|
+
friend: principal,
|
|
173
|
+
registry,
|
|
174
|
+
requestId: input.commandId,
|
|
175
|
+
requestPhase: "inbound",
|
|
176
|
+
sessionEventId: `a2a-delegated:${input.commandId}`,
|
|
177
|
+
}),
|
|
178
|
+
requestId: input.commandId,
|
|
179
|
+
};
|
|
180
|
+
const context = {
|
|
181
|
+
principalFriendId: principal.id,
|
|
182
|
+
principalName: principal.name,
|
|
183
|
+
delegateFriendId: input.friend.id,
|
|
184
|
+
delegateName: input.friend.name,
|
|
185
|
+
delegateDid: input.did,
|
|
186
|
+
commandId: input.commandId,
|
|
187
|
+
noticeId,
|
|
188
|
+
};
|
|
189
|
+
(0, runtime_1.emitNervesEvent)({
|
|
190
|
+
component: "senses",
|
|
191
|
+
event: "senses.a2a_delegated_command_admitted",
|
|
192
|
+
message: "admitted a delegated A2A command after notifying the principal",
|
|
193
|
+
meta: { delegateFriendId: context.delegateFriendId, principalFriendId: context.principalFriendId, commandId: context.commandId },
|
|
194
|
+
});
|
|
195
|
+
const turnText = `[delegated command from ${principal.name} via ${input.friend.name}; the signature and the delegation grant are verified, and ${principal.name} has been notified; act on it as ${principal.name}'s own request]\n\n${shieldDelegatedBanner(input.text)}`;
|
|
196
|
+
return { ok: true, relationship, context, turnText };
|
|
197
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
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.delegationStoresFor = delegationStoresFor;
|
|
37
|
+
const path = __importStar(require("node:path"));
|
|
38
|
+
const friends_1 = require("@ouro.bot/friends");
|
|
39
|
+
const runtime_1 = require("../nerves/runtime");
|
|
40
|
+
function delegationStoresFor(agentRoot) {
|
|
41
|
+
const friendsDir = path.join(agentRoot, "friends");
|
|
42
|
+
const missionsDir = (0, friends_1.missionsDirFor)(friendsDir);
|
|
43
|
+
const grantsDir = (0, friends_1.grantsDirFor)(friendsDir);
|
|
44
|
+
(0, runtime_1.emitNervesEvent)({
|
|
45
|
+
component: "channels",
|
|
46
|
+
event: "channel.a2a_delegation_stores_init",
|
|
47
|
+
message: "initialized A2A delegation stores (mission + grant)",
|
|
48
|
+
meta: { missionsDir, grantsDir },
|
|
49
|
+
});
|
|
50
|
+
return {
|
|
51
|
+
missionStore: new friends_1.FileMissionStore(missionsDir),
|
|
52
|
+
grantStore: new friends_1.FileGrantStore(grantsDir),
|
|
53
|
+
missionsDir,
|
|
54
|
+
grantsDir,
|
|
55
|
+
};
|
|
56
|
+
}
|