@ouro.bot/cli 0.1.0-alpha.83 → 0.1.0-alpha.831
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +154 -23
- package/RepairGuide.ouro/agent.json +5 -0
- package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
- package/RepairGuide.ouro/psyche/SOUL.md +55 -0
- package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
- package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
- package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
- package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
- package/assets/bluebubbles-host +264 -0
- package/assets/sanctuary-host-launcher.sh +16 -0
- package/changelog.json +5308 -16
- package/deploy/unraid/Dockerfile +54 -0
- package/deploy/unraid/README.txt +2983 -0
- package/deploy/unraid/audit-container-spec.sh +4 -0
- package/deploy/unraid/container-runtime.json +1 -0
- package/deploy/unraid/docker-man-template-transaction.mjs +711 -0
- package/deploy/unraid/docker-man-template-xml.cjs +105 -0
- package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
- package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
- package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
- package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
- package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
- package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
- package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
- package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
- package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
- package/deploy/unraid/sanctuary-authority-installation.json +36 -0
- package/deploy/unraid/sanctuary-authority-service.sh +30 -0
- package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
- package/deploy/unraid/sanctuary-safe-rename.py +24 -0
- package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2084 -0
- package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
- package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
- package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
- package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
- package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
- package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
- package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +795 -0
- package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
- package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
- package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
- package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +15 -0
- package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +25 -0
- package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +15 -0
- package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
- package/deploy/unraid/sanctuary.ouro/tool-profiles.json +135 -0
- package/deploy/unraid/sanctuary.xml +28 -0
- package/dist/a2a/card.js +57 -0
- package/dist/a2a/client.js +180 -0
- package/dist/a2a/config.js +50 -0
- package/dist/a2a/delegation-stores.js +56 -0
- package/dist/a2a/did-resolution.js +93 -0
- package/dist/a2a/identity.js +170 -0
- package/dist/a2a/inbound-share.js +107 -0
- package/dist/a2a/mission-result-wire.js +196 -0
- package/dist/a2a/onboarding.js +115 -0
- package/dist/a2a/pin-store.js +132 -0
- package/dist/a2a/seen-ledger.js +120 -0
- package/dist/a2a/server.js +604 -0
- package/dist/a2a/task-store.js +69 -0
- package/dist/a2a/transport.js +45 -0
- package/dist/a2a/types.js +3 -0
- package/dist/arc/attention-types.js +8 -0
- package/dist/arc/cares.js +360 -0
- package/dist/arc/episodes.js +118 -0
- package/dist/arc/evolution.js +490 -0
- package/dist/arc/flight-recorder.js +1034 -0
- package/dist/arc/intentions.js +134 -0
- package/dist/arc/json-store.js +117 -0
- package/dist/arc/obligations.js +386 -0
- package/dist/arc/packets.js +336 -0
- package/dist/arc/presence.js +185 -0
- package/dist/arc/task-lifecycle.js +57 -0
- package/dist/commerce/store.js +755 -0
- package/dist/commerce/types.js +3 -0
- package/dist/heart/active-work.js +798 -40
- package/dist/heart/agent-entry.js +252 -3
- package/dist/heart/approval-files.js +113 -0
- package/dist/heart/approval-store.js +960 -0
- package/dist/heart/attachments/image-normalize.js +194 -0
- package/dist/heart/attachments/materialize.js +97 -0
- package/dist/heart/attachments/originals.js +88 -0
- package/dist/heart/attachments/render.js +29 -0
- package/dist/heart/attachments/sources/bluebubbles.js +156 -0
- package/dist/heart/attachments/sources/cli-local-file.js +78 -0
- package/dist/heart/attachments/sources/index.js +18 -0
- package/dist/heart/attachments/sources/telegram.js +71 -0
- package/dist/heart/attachments/store.js +132 -0
- package/dist/heart/attachments/types.js +93 -0
- package/dist/heart/auth/auth-flow.js +495 -0
- package/dist/heart/autonomy-budget.js +478 -0
- package/dist/heart/awaiting/await-alert.js +148 -0
- package/dist/heart/awaiting/await-expiry.js +143 -0
- package/dist/heart/awaiting/await-loader.js +91 -0
- package/dist/heart/awaiting/await-parser.js +149 -0
- package/dist/heart/awaiting/await-runtime-state.js +111 -0
- package/dist/heart/awaiting/await-scheduler.js +382 -0
- package/dist/heart/background-operations.js +281 -0
- package/dist/heart/bridges/manager.js +137 -17
- package/dist/heart/bridges/store.js +14 -2
- package/dist/heart/bundle-state.js +168 -0
- package/dist/heart/commitments.js +44 -18
- package/dist/heart/config-registry.js +331 -0
- package/dist/heart/config.js +174 -131
- package/dist/heart/context-loss-gauntlet.js +387 -0
- package/dist/heart/context-loss-sentinel.js +1157 -0
- package/dist/heart/core.js +2169 -581
- package/dist/heart/cross-chat-delivery.js +9 -22
- package/dist/heart/daemon/agent-config-check.js +451 -0
- package/dist/heart/daemon/agent-discovery.js +185 -3
- package/dist/heart/daemon/agent-service.js +542 -0
- package/dist/heart/daemon/agentic-repair.js +547 -0
- package/dist/heart/daemon/await-private-wake.js +59 -0
- package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
- package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
- package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
- package/dist/heart/daemon/bluebubbles-host.js +273 -0
- package/dist/heart/daemon/boot-sync-probe.js +197 -0
- package/dist/heart/daemon/cadence.js +180 -0
- package/dist/heart/daemon/cli-defaults.js +854 -0
- package/dist/heart/daemon/cli-desk.js +322 -0
- package/dist/heart/daemon/cli-exec.js +8822 -0
- package/dist/heart/daemon/cli-help.js +716 -0
- package/dist/heart/daemon/cli-parse.js +2771 -0
- package/dist/heart/daemon/cli-render-doctor.js +57 -0
- package/dist/heart/daemon/cli-render.js +777 -0
- package/dist/heart/daemon/cli-types.js +8 -0
- package/dist/heart/daemon/connect-bay.js +323 -0
- package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
- package/dist/heart/daemon/container-healthcheck.js +112 -0
- package/dist/heart/daemon/container-runtime.js +97 -0
- package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
- package/dist/heart/daemon/container-spec-auditor.js +229 -0
- package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
- package/dist/heart/daemon/daemon-cli.js +29 -2349
- package/dist/heart/daemon/daemon-entry.js +930 -11
- package/dist/heart/daemon/daemon-health.js +186 -0
- package/dist/heart/daemon/daemon-rollup.js +57 -0
- package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
- package/dist/heart/daemon/daemon-tombstone.js +236 -0
- package/dist/heart/daemon/daemon.js +2084 -105
- package/dist/heart/daemon/dns-workflow.js +394 -0
- package/dist/heart/daemon/doctor-types.js +8 -0
- package/dist/heart/daemon/doctor.js +1755 -0
- package/dist/heart/daemon/freshness.js +345 -0
- package/dist/heart/daemon/habit-private-wake.js +61 -0
- package/dist/heart/daemon/health-monitor.js +142 -11
- package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
- package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
- package/dist/heart/daemon/http-health-probe.js +80 -0
- package/dist/heart/daemon/human-command-screens.js +234 -0
- package/dist/heart/daemon/human-readiness.js +114 -0
- package/dist/heart/daemon/inner-status.js +78 -0
- package/dist/heart/daemon/interactive-repair.js +394 -0
- package/dist/heart/daemon/launchd.js +37 -8
- package/dist/heart/daemon/log-tailer.js +79 -10
- package/dist/heart/daemon/logs-prune.js +132 -0
- package/dist/heart/daemon/mcp-canary.js +524 -0
- package/dist/heart/daemon/message-router.js +65 -5
- package/dist/heart/daemon/migrate-to-desk.js +848 -0
- package/dist/heart/daemon/os-cron-deps.js +135 -0
- package/dist/heart/daemon/os-cron.js +22 -14
- package/dist/heart/daemon/ouro-bot-entry.js +4 -2
- package/dist/heart/daemon/ouro-entry.js +3 -1
- package/dist/heart/daemon/plugin-cli.js +432 -0
- package/dist/heart/daemon/process-manager.js +733 -61
- package/dist/heart/daemon/provider-discovery.js +137 -0
- package/dist/heart/daemon/provider-ping-progress.js +83 -0
- package/dist/heart/daemon/prunable-bundle.js +144 -0
- package/dist/heart/daemon/pulse.js +511 -0
- package/dist/heart/daemon/readiness-repair.js +365 -0
- package/dist/heart/daemon/run-hooks.js +2 -0
- package/dist/heart/daemon/runtime-logging.js +47 -14
- package/dist/heart/daemon/runtime-metadata.js +2 -30
- package/dist/heart/daemon/runtime-mode.js +13 -2
- package/dist/heart/daemon/safe-mode.js +161 -0
- package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
- package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
- package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
- package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
- package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
- package/dist/heart/daemon/sanctuary-authority-epoch.js +256 -0
- package/dist/heart/daemon/sanctuary-authority-installation.js +140 -0
- package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
- package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +819 -0
- package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
- package/dist/heart/daemon/sanctuary-bundle-migration.js +729 -0
- package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
- package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +494 -0
- package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
- package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
- package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
- package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
- package/dist/heart/daemon/sanctuary-package-management.js +103 -0
- package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
- package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
- package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +445 -0
- package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
- package/dist/heart/daemon/sanctuary-telegram-authority-service.js +630 -0
- package/dist/heart/daemon/sense-manager.js +699 -48
- package/dist/heart/daemon/session-id-resolver.js +131 -0
- package/dist/heart/daemon/skill-management-installer.js +1 -1
- package/dist/heart/daemon/socket-client.js +180 -12
- package/dist/heart/daemon/stale-bundle-prune.js +113 -0
- package/dist/heart/daemon/startup-tui.js +339 -0
- package/dist/heart/daemon/supercronic-supervisor.js +282 -0
- package/dist/heart/daemon/task-scheduler.js +117 -39
- package/dist/heart/daemon/terminal-ui.js +499 -0
- package/dist/heart/daemon/thoughts.js +138 -54
- package/dist/heart/daemon/up-progress.js +366 -0
- package/dist/heart/daemon/vault-items.js +56 -0
- package/dist/heart/delegation.js +1 -4
- package/dist/heart/external-events/router.js +1430 -0
- package/dist/heart/frontend-approval-runtime.js +506 -0
- package/dist/heart/frontend-journal.js +215 -0
- package/dist/heart/frontend-session-service.js +237 -0
- package/dist/heart/frontend-socket-client.js +164 -0
- package/dist/heart/frontend-socket.js +400 -0
- package/dist/heart/habits/habit-cancel.js +810 -0
- package/dist/heart/habits/habit-lifecycle.js +1327 -0
- package/dist/heart/habits/habit-migration.js +194 -0
- package/dist/heart/habits/habit-parser.js +278 -0
- package/dist/heart/habits/habit-runtime-state.js +93 -0
- package/dist/heart/habits/habit-scheduler.js +653 -0
- package/dist/heart/habits/habit-session-summary.js +318 -0
- package/dist/heart/habits/habit-session.js +636 -0
- package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
- package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
- package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
- package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
- package/dist/heart/identity.js +196 -59
- package/dist/heart/kept-notes.js +289 -0
- package/dist/heart/kicks.js +1 -1
- package/dist/heart/machine-identity.js +161 -0
- package/dist/heart/mail-import-discovery.js +356 -0
- package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
- package/dist/heart/mailbox/mailbox-http-response.js +7 -0
- package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
- package/dist/heart/mailbox/mailbox-http-static.js +103 -0
- package/dist/heart/mailbox/mailbox-http-transport.js +129 -0
- package/dist/heart/mailbox/mailbox-http.js +99 -0
- package/dist/heart/mailbox/mailbox-read.js +39 -0
- package/dist/heart/mailbox/mailbox-types.js +27 -0
- package/dist/heart/mailbox/mailbox-view.js +197 -0
- package/dist/heart/mailbox/readers/agent-machine.js +428 -0
- package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
- package/dist/heart/mailbox/readers/mail.js +375 -0
- package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
- package/dist/heart/mailbox/readers/sessions.js +231 -0
- package/dist/heart/mailbox/readers/shared.js +111 -0
- package/dist/heart/mcp/mcp-server.js +696 -0
- package/dist/heart/migrate-config.js +100 -0
- package/dist/heart/model-capabilities.js +11 -0
- package/dist/heart/orientation-frame.js +345 -0
- package/dist/heart/platform.js +81 -0
- package/dist/heart/primitives.js +1 -1
- package/dist/heart/private-runtime/decision-renderer.js +158 -0
- package/dist/heart/private-runtime/index.js +18 -0
- package/dist/heart/private-runtime/ledger.js +221 -0
- package/dist/heart/private-runtime/policy.js +252 -0
- package/dist/heart/private-runtime/types.js +2 -0
- package/dist/heart/progress-story.js +1 -1
- package/dist/heart/provider-attempt.js +137 -0
- package/dist/heart/provider-binding-resolver.js +273 -0
- package/dist/heart/provider-credentials.js +449 -0
- package/dist/heart/provider-failover.js +311 -0
- package/dist/heart/provider-models.js +96 -0
- package/dist/heart/provider-ping.js +265 -0
- package/dist/heart/provider-readiness-cache.js +119 -0
- package/dist/heart/provider-visibility.js +188 -0
- package/dist/heart/providers/anthropic-token.js +131 -0
- package/dist/heart/providers/anthropic.js +173 -60
- package/dist/heart/providers/azure.js +23 -11
- package/dist/heart/providers/error-classification.js +127 -0
- package/dist/heart/providers/github-copilot.js +34 -38
- package/dist/heart/providers/minimax-vlm.js +189 -0
- package/dist/heart/providers/minimax.js +26 -8
- package/dist/heart/providers/openai-codex-token.js +349 -0
- package/dist/heart/providers/openai-codex.js +55 -40
- package/dist/heart/providers/openai-compatible.js +177 -0
- package/dist/heart/run-ledger.js +247 -0
- package/dist/heart/runtime-capability-check.js +170 -0
- package/dist/heart/runtime-credentials.js +607 -0
- package/dist/heart/runtime-cwd.js +87 -0
- package/dist/heart/sense-truth.js +22 -4
- package/dist/heart/session-activity.js +92 -24
- package/dist/heart/session-events.js +1504 -0
- package/dist/heart/session-playback-cli-main.js +5 -0
- package/dist/heart/session-playback-cli.js +36 -0
- package/dist/heart/session-playback.js +231 -0
- package/dist/heart/session-redaction-repair-cli-main.js +31 -0
- package/dist/heart/session-redaction-repair.js +552 -0
- package/dist/heart/session-stats-cli-main.js +5 -0
- package/dist/heart/session-stats.js +183 -0
- package/dist/heart/session-transcript.js +133 -0
- package/dist/heart/start-of-turn-packet.js +372 -0
- package/dist/heart/steward-policy.js +618 -0
- package/dist/heart/streaming.js +604 -207
- package/dist/heart/structured-output.js +196 -0
- package/dist/heart/sync-classification.js +176 -0
- package/dist/heart/sync.js +449 -0
- package/dist/heart/target-resolution.js +11 -7
- package/dist/heart/tempo.js +93 -0
- package/dist/heart/temporal-view.js +41 -0
- package/dist/heart/timeouts.js +101 -0
- package/dist/heart/tool-activity-callbacks.js +59 -0
- package/dist/heart/tool-approval.js +382 -0
- package/dist/heart/tool-description.js +155 -0
- package/dist/heart/tool-friction.js +55 -0
- package/dist/heart/tool-loop.js +200 -0
- package/dist/heart/turn-context.js +482 -0
- package/dist/heart/turn-execution-lease.js +30 -0
- package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
- package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
- package/dist/heart/versioning/ouro-path-installer.js +432 -0
- package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
- package/dist/heart/versioning/ouro-version-manager.js +409 -0
- package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
- package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
- package/dist/heart/versioning/update-hooks.js +154 -0
- package/dist/heart/versioning/version-intent.js +114 -0
- package/dist/heart/work-card.js +380 -0
- package/dist/mailbox-ui/assets/index-Cyv4mw3Y.js +1 -0
- package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
- package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
- package/dist/mailbox-ui/index.html +16 -0
- package/dist/mailroom/attention.js +167 -0
- package/dist/mailroom/autonomy.js +209 -0
- package/dist/mailroom/blob-store.js +889 -0
- package/dist/mailroom/body-cache.js +61 -0
- package/dist/mailroom/cache-sync-cli.js +58 -0
- package/dist/mailroom/core.js +803 -0
- package/dist/mailroom/entry.js +160 -0
- package/dist/mailroom/file-store.js +568 -0
- package/dist/mailroom/hosted-cache-sync.js +384 -0
- package/dist/mailroom/mbox-import.js +393 -0
- package/dist/mailroom/migration.js +164 -0
- package/dist/mailroom/outbound.js +380 -0
- package/dist/mailroom/policy.js +263 -0
- package/dist/mailroom/reader.js +292 -0
- package/dist/mailroom/search-cache.js +513 -0
- package/dist/mailroom/search-relevance.js +319 -0
- package/dist/mailroom/smtp-ingress.js +176 -0
- package/dist/mailroom/source-state.js +176 -0
- package/dist/mailroom/thread.js +109 -0
- package/dist/mailroom/travel-extract.js +89 -0
- package/dist/mind/bundle-manifest.js +24 -2
- package/dist/mind/context.js +309 -111
- package/dist/mind/desk-section.js +362 -0
- package/dist/mind/diary-integrity.js +60 -0
- package/dist/mind/{memory.js → diary.js} +68 -77
- package/dist/mind/embedding-provider.js +60 -0
- package/dist/mind/file-state.js +179 -0
- package/dist/mind/{associative-recall.js → note-search.js} +47 -58
- package/dist/mind/obligation-steering.js +199 -3
- package/dist/mind/pending.js +36 -10
- package/dist/mind/prompt-budget.js +479 -0
- package/dist/mind/prompt-refresh.js +3 -2
- package/dist/mind/prompt.js +1050 -189
- package/dist/mind/provenance-trust.js +26 -0
- package/dist/mind/record-paths.js +312 -0
- package/dist/mind/scrutiny.js +173 -0
- package/dist/mind/session-transaction.js +564 -0
- package/dist/nerves/cli-logging.js +7 -1
- package/dist/nerves/coverage/audit-rules.js +15 -6
- package/dist/nerves/coverage/audit.js +28 -2
- package/dist/nerves/coverage/cli.js +1 -1
- package/dist/nerves/coverage/contract.js +5 -5
- package/dist/nerves/coverage/file-completeness.js +139 -5
- package/dist/nerves/coverage/run-artifacts.js +55 -35
- package/dist/nerves/coverage/source-scanner.js +4 -4
- package/dist/nerves/event-buffer.js +111 -0
- package/dist/nerves/index.js +293 -9
- package/dist/nerves/observation.js +20 -0
- package/dist/nerves/redact.js +79 -0
- package/dist/nerves/review/cli-main.js +5 -0
- package/dist/nerves/review/cli.js +156 -0
- package/dist/nerves/review/core.js +159 -0
- package/dist/nerves/runtime.js +17 -1
- package/dist/repertoire/ado-client.js +15 -56
- package/dist/repertoire/ado-semantic.js +16 -10
- package/dist/repertoire/api-client.js +97 -0
- package/dist/repertoire/bitwarden-store.js +1045 -0
- package/dist/repertoire/bundle-templates.js +71 -0
- package/dist/repertoire/bw-installer.js +180 -0
- package/dist/repertoire/coding/codex-jsonl.js +64 -0
- package/dist/repertoire/coding/context-pack.js +331 -0
- package/dist/repertoire/coding/feedback.js +174 -32
- package/dist/repertoire/coding/index.js +15 -3
- package/dist/repertoire/coding/manager.js +159 -10
- package/dist/repertoire/coding/spawner.js +58 -11
- package/dist/repertoire/coding/tools.js +221 -15
- package/dist/repertoire/coding/workbench-client.js +272 -0
- package/dist/repertoire/coding/workbench-manager.js +346 -0
- package/dist/repertoire/commerce-errors.js +109 -0
- package/dist/repertoire/commerce-self-test.js +156 -0
- package/dist/repertoire/credential-access.js +178 -0
- package/dist/repertoire/desk/classifier.js +362 -0
- package/dist/repertoire/duffel-client.js +185 -0
- package/dist/repertoire/github-client.js +14 -55
- package/dist/repertoire/graph-client.js +11 -52
- package/dist/repertoire/guardrails.js +811 -18
- package/dist/repertoire/mcp-client.js +44 -3
- package/dist/repertoire/mcp-manager.js +427 -139
- package/dist/repertoire/mcp-tools.js +124 -0
- package/dist/repertoire/plugin-mcp.js +175 -0
- package/dist/repertoire/plugins.js +253 -0
- package/dist/repertoire/relationship-authorization.js +322 -0
- package/dist/repertoire/shell-sessions.js +134 -0
- package/dist/repertoire/skills.js +48 -4
- package/dist/repertoire/stripe-client.js +131 -0
- package/dist/repertoire/tool-arguments.js +170 -0
- package/dist/repertoire/tool-results.js +29 -0
- package/dist/repertoire/tools-a2a.js +699 -0
- package/dist/repertoire/tools-attachments.js +322 -0
- package/dist/repertoire/tools-awaiting.js +575 -0
- package/dist/repertoire/tools-base.js +77 -1138
- package/dist/repertoire/tools-bluebubbles.js +2 -0
- package/dist/repertoire/tools-bridge.js +144 -0
- package/dist/repertoire/tools-bundle.js +993 -0
- package/dist/repertoire/tools-commerce.js +253 -0
- package/dist/repertoire/tools-config.js +186 -0
- package/dist/repertoire/tools-continuity.js +575 -0
- package/dist/repertoire/tools-credential.js +383 -0
- package/dist/repertoire/tools-evolution.js +527 -0
- package/dist/repertoire/tools-files.js +344 -0
- package/dist/repertoire/tools-flight.js +290 -0
- package/dist/repertoire/tools-flow.js +119 -0
- package/dist/repertoire/tools-github.js +3 -8
- package/dist/repertoire/tools-habits.js +103 -0
- package/dist/repertoire/tools-mail.js +1828 -0
- package/dist/repertoire/tools-notes.js +485 -0
- package/dist/repertoire/tools-obligations.js +182 -0
- package/dist/repertoire/tools-orientation.js +31 -0
- package/dist/repertoire/tools-record.js +482 -0
- package/dist/repertoire/tools-rsvp.js +139 -0
- package/dist/repertoire/tools-runtime.js +150 -0
- package/dist/repertoire/tools-sanctuary-host.js +202 -0
- package/dist/repertoire/tools-session.js +1133 -0
- package/dist/repertoire/tools-shell.js +149 -0
- package/dist/repertoire/tools-steward-policy.js +119 -0
- package/dist/repertoire/tools-stripe.js +224 -0
- package/dist/repertoire/tools-surface.js +369 -0
- package/dist/repertoire/tools-teams.js +12 -39
- package/dist/repertoire/tools-telegram-contacts.js +37 -0
- package/dist/repertoire/tools-travel.js +125 -0
- package/dist/repertoire/tools-trip.js +982 -0
- package/dist/repertoire/tools-unraid.js +531 -0
- package/dist/repertoire/tools-user-profile.js +146 -0
- package/dist/repertoire/tools-vault.js +40 -0
- package/dist/repertoire/tools-voice.js +145 -0
- package/dist/repertoire/tools.js +494 -148
- package/dist/repertoire/travel-api-client.js +360 -0
- package/dist/repertoire/unraid-client.js +155 -0
- package/dist/repertoire/unraid-restart.js +339 -0
- package/dist/repertoire/user-profile.js +131 -0
- package/dist/repertoire/vault-setup.js +246 -0
- package/dist/repertoire/vault-unlock.js +628 -0
- package/dist/rsvp/aisleplanner-client.js +354 -0
- package/dist/rsvp/cli.js +926 -0
- package/dist/rsvp/config.js +327 -0
- package/dist/rsvp/cutover.js +433 -0
- package/dist/rsvp/diagnostics.js +232 -0
- package/dist/rsvp/diff-renderer.js +176 -0
- package/dist/rsvp/habit-policy.js +110 -0
- package/dist/rsvp/habit-stage.js +123 -0
- package/dist/rsvp/incident-bundle.js +97 -0
- package/dist/rsvp/migration.js +204 -0
- package/dist/rsvp/native-habit-runner.js +630 -0
- package/dist/rsvp/outbound-state.js +628 -0
- package/dist/rsvp/query.js +118 -0
- package/dist/rsvp/replay.js +233 -0
- package/dist/rsvp/snapshot.js +232 -0
- package/dist/rsvp/spend-ledger.js +175 -0
- package/dist/scripts/claude-code-hook.js +41 -0
- package/dist/scripts/claude-code-stop-hook.js +47 -0
- package/dist/senses/a2a-entry.js +115 -0
- package/dist/senses/acp-server.js +386 -0
- package/dist/senses/attention-queue.js +186 -0
- package/dist/senses/await-turn-message.js +58 -0
- package/dist/senses/bluebubbles/active-turns.js +216 -0
- package/dist/senses/bluebubbles/attachment-cache.js +53 -0
- package/dist/senses/bluebubbles/attachment-download.js +137 -0
- package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +355 -40
- package/dist/senses/bluebubbles/context-packet.js +207 -0
- package/dist/senses/bluebubbles/context-smoke.js +144 -0
- package/dist/senses/bluebubbles/entry.js +90 -0
- package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
- package/dist/senses/bluebubbles/index.js +3841 -0
- package/dist/senses/bluebubbles/latest-turn.js +311 -0
- package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
- package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
- package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
- package/dist/senses/bluebubbles/outbound-state.js +308 -0
- package/dist/senses/bluebubbles/processed-log.js +133 -0
- package/dist/senses/bluebubbles/reaction-policy.js +47 -0
- package/dist/senses/bluebubbles/replay.js +284 -0
- package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
- package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
- package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
- package/dist/senses/bluebubbles/webhook-registration.js +228 -0
- package/dist/senses/bluebubbles-meta-guard.js +39 -0
- package/dist/senses/cli/bracketed-paste.js +82 -0
- package/dist/senses/cli/image-paste.js +287 -0
- package/dist/senses/cli/image-ref-navigation.js +75 -0
- package/dist/senses/cli/ink-app.js +156 -0
- package/dist/senses/cli/inline-diff.js +64 -0
- package/dist/senses/cli/input-keys.js +174 -0
- package/dist/senses/cli/kill-ring.js +86 -0
- package/dist/senses/cli/message-list.js +51 -0
- package/dist/senses/cli/ouro-tui.js +607 -0
- package/dist/senses/cli/spinner-imperative.js +135 -0
- package/dist/senses/cli/spinner.js +101 -0
- package/dist/senses/cli/status-line.js +60 -0
- package/dist/senses/cli/streaming-markdown.js +526 -0
- package/dist/senses/cli/tool-display.js +85 -0
- package/dist/senses/cli/tool-render.js +85 -0
- package/dist/senses/cli/tui-store.js +241 -0
- package/dist/senses/cli/virtual-list.js +35 -0
- package/dist/senses/cli-entry.js +60 -8
- package/dist/senses/cli.js +604 -320
- package/dist/senses/commands.js +66 -3
- package/dist/senses/context-packet-ledger.js +371 -0
- package/dist/senses/context-packets.js +154 -0
- package/dist/senses/habit-lifecycle-guard.js +24 -0
- package/dist/senses/habit-turn-message.js +160 -0
- package/dist/senses/ingress-evidence.js +2 -0
- package/dist/senses/mail-entry.js +66 -0
- package/dist/senses/mail.js +524 -0
- package/dist/senses/pipeline.js +1115 -204
- package/dist/senses/private-runtime-worker.js +859 -0
- package/dist/senses/private-runtime.js +1517 -0
- package/dist/senses/proactive-content-guard.js +51 -0
- package/dist/senses/root-host-approval-port.js +345 -0
- package/dist/senses/root-host-approval-runtime.js +393 -0
- package/dist/senses/sanctuary-authority-resident.js +102 -0
- package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
- package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
- package/dist/senses/sanctuary-grounding.js +118 -0
- package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
- package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
- package/dist/senses/sanctuary-health-runner.js +100 -0
- package/dist/senses/sanctuary-health.js +408 -0
- package/dist/senses/sanctuary-install-state-contract.js +126 -0
- package/dist/senses/sanctuary-interactive-control.js +410 -0
- package/dist/senses/sanctuary-media-catalog-contract.js +297 -0
- package/dist/senses/sanctuary-media-optimization.js +514 -0
- package/dist/senses/sanctuary-runtime.js +340 -0
- package/dist/senses/sanctuary-sab.js +85 -0
- package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
- package/dist/senses/shared-turn.js +772 -0
- package/dist/senses/surface-tool.js +109 -0
- package/dist/senses/teams-entry.js +60 -8
- package/dist/senses/teams.js +519 -218
- package/dist/senses/telegram-admission.js +718 -0
- package/dist/senses/telegram-approval-runtime.js +793 -0
- package/dist/senses/telegram-attachments.js +186 -0
- package/dist/senses/telegram-audit-ledger.js +220 -0
- package/dist/senses/telegram-authority-transport.js +231 -0
- package/dist/senses/telegram-client.js +1749 -0
- package/dist/senses/telegram-effect-adapter.js +896 -0
- package/dist/senses/telegram-entry.js +83 -0
- package/dist/senses/telegram.js +2324 -0
- package/dist/senses/trust-gate.js +104 -9
- package/dist/senses/voice/audio-playback.js +237 -0
- package/dist/senses/voice/audio-routing.js +119 -0
- package/dist/senses/voice/elevenlabs.js +202 -0
- package/dist/senses/voice/floor-control.js +431 -0
- package/dist/senses/voice/floor-controller.js +115 -0
- package/dist/senses/voice/golden-path.js +116 -0
- package/dist/senses/voice/index.js +29 -0
- package/dist/senses/voice/meeting.js +113 -0
- package/dist/senses/voice/outbound.js +190 -0
- package/dist/senses/voice/phone.js +33 -0
- package/dist/senses/voice/playback.js +139 -0
- package/dist/senses/voice/realtime-eval.js +496 -0
- package/dist/senses/voice/realtime-trace.js +531 -0
- package/dist/senses/voice/transcript.js +70 -0
- package/dist/senses/voice/turn.js +191 -0
- package/dist/senses/voice/twilio-phone-runtime.js +807 -0
- package/dist/senses/voice/twilio-phone.js +5031 -0
- package/dist/senses/voice/types.js +2 -0
- package/dist/senses/voice/whisper.js +161 -0
- package/dist/senses/voice-entry.js +81 -0
- package/dist/senses/voice-realtime-eval-command.js +99 -0
- package/dist/senses/voice-realtime-eval-entry.js +21 -0
- package/dist/senses/voice-twilio-entry.js +87 -0
- package/dist/trips/core.js +138 -0
- package/dist/trips/store.js +265 -0
- package/dist/util/frontmatter.js +69 -0
- package/npm-shrinkwrap.json +8138 -0
- package/package.json +72 -13
- package/skills/agent-commerce.md +113 -0
- package/skills/browser-navigation.md +117 -0
- package/skills/commerce-setup-guide.md +116 -0
- package/skills/commerce-setup.md +84 -0
- package/skills/configure-dev-tools.md +99 -0
- package/skills/travel-planning.md +138 -0
- package/dist/heart/daemon/auth-flow.js +0 -430
- package/dist/heart/daemon/ouro-path-installer.js +0 -260
- package/dist/heart/daemon/ouro-version-manager.js +0 -171
- package/dist/heart/daemon/update-hooks.js +0 -138
- package/dist/heart/obligations.js +0 -191
- package/dist/heart/safe-workspace.js +0 -228
- package/dist/heart/session-recall.js +0 -116
- package/dist/mind/friends/channel.js +0 -84
- package/dist/mind/friends/group-context.js +0 -144
- package/dist/mind/friends/resolver.js +0 -84
- package/dist/mind/friends/store-file.js +0 -190
- package/dist/mind/friends/store.js +0 -4
- package/dist/mind/friends/tokens.js +0 -26
- package/dist/mind/friends/trust-explanation.js +0 -74
- package/dist/mind/friends/types.js +0 -29
- package/dist/repertoire/tasks/board.js +0 -134
- package/dist/repertoire/tasks/index.js +0 -224
- package/dist/repertoire/tasks/lifecycle.js +0 -80
- package/dist/repertoire/tasks/middleware.js +0 -65
- package/dist/repertoire/tasks/parser.js +0 -173
- package/dist/repertoire/tasks/scanner.js +0 -132
- package/dist/repertoire/tasks/transitions.js +0 -144
- package/dist/senses/bluebubbles-entry.js +0 -13
- package/dist/senses/bluebubbles.js +0 -1181
- package/dist/senses/debug-activity.js +0 -154
- package/dist/senses/inner-dialog-worker.js +0 -90
- package/dist/senses/inner-dialog.js +0 -525
- package/subagents/README.md +0 -7
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
- /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
- /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
- /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
- /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
- /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
|
@@ -0,0 +1,699 @@
|
|
|
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.a2aToolDefinitions = void 0;
|
|
37
|
+
const path = __importStar(require("node:path"));
|
|
38
|
+
const identity_1 = require("../heart/identity");
|
|
39
|
+
const runtime_credentials_1 = require("../heart/runtime-credentials");
|
|
40
|
+
const friends_1 = require("@ouro.bot/friends");
|
|
41
|
+
const a2a_client_1 = require("@ouro.bot/friends/a2a-client");
|
|
42
|
+
const runtime_1 = require("../nerves/runtime");
|
|
43
|
+
const client_1 = require("../a2a/client");
|
|
44
|
+
const onboarding_1 = require("../a2a/onboarding");
|
|
45
|
+
const identity_2 = require("../a2a/identity");
|
|
46
|
+
const transport_1 = require("../a2a/transport");
|
|
47
|
+
const delegation_stores_1 = require("../a2a/delegation-stores");
|
|
48
|
+
const mission_result_wire_1 = require("../a2a/mission-result-wire");
|
|
49
|
+
const outboundTaskTokens = new Map();
|
|
50
|
+
function tokenKey(ctx, friendId, taskId) {
|
|
51
|
+
return `${ctx?.agentRoot ?? "ambient"}\n${friendId}\n${taskId}`;
|
|
52
|
+
}
|
|
53
|
+
function rememberTaskToken(ctx, friendId, task) {
|
|
54
|
+
/* v8 ignore next -- defensive metadata-shape guard; protocol tasks from Ouro servers always use object metadata @preserve */
|
|
55
|
+
const token = task.metadata?.a2a && typeof task.metadata.a2a === "object" && !Array.isArray(task.metadata.a2a)
|
|
56
|
+
? task.metadata.a2a.accessToken
|
|
57
|
+
: undefined;
|
|
58
|
+
if (typeof token === "string" && token.trim()) {
|
|
59
|
+
outboundTaskTokens.set(tokenKey(ctx, friendId, task.id), token.trim());
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function rememberedTaskToken(ctx, friendId, taskId) {
|
|
63
|
+
return outboundTaskTokens.get(tokenKey(ctx, friendId, taskId));
|
|
64
|
+
}
|
|
65
|
+
function redactTaskToken(task) {
|
|
66
|
+
const a2a = task.metadata?.a2a;
|
|
67
|
+
if (!a2a || typeof a2a !== "object" || Array.isArray(a2a) || !("accessToken" in a2a))
|
|
68
|
+
return task;
|
|
69
|
+
const { accessToken: _accessToken, ...safeA2A } = a2a;
|
|
70
|
+
return {
|
|
71
|
+
...task,
|
|
72
|
+
metadata: {
|
|
73
|
+
...task.metadata,
|
|
74
|
+
a2a: safeA2A,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function storeFor(ctx) {
|
|
79
|
+
if (ctx?.friendStore)
|
|
80
|
+
return ctx.friendStore;
|
|
81
|
+
/* v8 ignore next -- no-agentRoot fallback depends on process argv; normal tool calls inject agentRoot @preserve */
|
|
82
|
+
if (ctx?.agentRoot)
|
|
83
|
+
return new friends_1.FileFriendStore(path.join(ctx.agentRoot, "friends"));
|
|
84
|
+
return new friends_1.FileFriendStore(path.join((0, identity_1.getAgentRoot)(), "friends"));
|
|
85
|
+
}
|
|
86
|
+
function requireTrustedRequester(ctx) {
|
|
87
|
+
if (!ctx?.context?.friend?.id)
|
|
88
|
+
return "no friend context — cannot use A2A tools.";
|
|
89
|
+
if (!(0, friends_1.isTrustedLevel)(ctx.context.friend.trustLevel))
|
|
90
|
+
return "A2A tools require friend or family trust.";
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
function isA2APeer(friend) {
|
|
94
|
+
return friend.kind === "agent" && friend.externalIds.some((id) => id.provider === "a2a-agent");
|
|
95
|
+
}
|
|
96
|
+
function agentNameFromRoot(agentRoot) {
|
|
97
|
+
if (!agentRoot)
|
|
98
|
+
return undefined;
|
|
99
|
+
const base = path.basename(agentRoot);
|
|
100
|
+
return base.endsWith(".ouro") ? base.slice(0, -".ouro".length) : undefined;
|
|
101
|
+
}
|
|
102
|
+
function textField(record, key) {
|
|
103
|
+
const value = record?.[key];
|
|
104
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
105
|
+
}
|
|
106
|
+
function localA2ACardUrl(agentRoot) {
|
|
107
|
+
const agentName = agentNameFromRoot(agentRoot);
|
|
108
|
+
if (!agentName)
|
|
109
|
+
return undefined;
|
|
110
|
+
const result = (0, runtime_credentials_1.readMachineRuntimeCredentialConfig)(agentName);
|
|
111
|
+
if (!result.ok)
|
|
112
|
+
return undefined;
|
|
113
|
+
const a2a = result.config.a2a;
|
|
114
|
+
if (!a2a || typeof a2a !== "object" || Array.isArray(a2a))
|
|
115
|
+
return undefined;
|
|
116
|
+
const publicUrl = textField(a2a, "publicUrl");
|
|
117
|
+
return publicUrl ? `${publicUrl.replace(/\/+$/, "")}/.well-known/agent-card.json` : undefined;
|
|
118
|
+
}
|
|
119
|
+
async function resolveA2AEndpoint(friend) {
|
|
120
|
+
const metadata = friend.agentMeta?.a2a;
|
|
121
|
+
if (metadata?.endpointUrl) {
|
|
122
|
+
return { endpointUrl: metadata.endpointUrl, agentId: metadata.agentId, peerName: friend.name };
|
|
123
|
+
}
|
|
124
|
+
if (metadata?.cardUrl) {
|
|
125
|
+
const card = await (0, client_1.fetchA2AAgentCard)(metadata.cardUrl);
|
|
126
|
+
const endpointUrl = (0, client_1.endpointForCard)(card);
|
|
127
|
+
/* v8 ignore next -- fetchA2AAgentCard rejects cards without a usable endpoint before tools see them @preserve */
|
|
128
|
+
if (!endpointUrl)
|
|
129
|
+
throw new Error("A2A card has no JSONRPC endpoint");
|
|
130
|
+
/* v8 ignore next -- empty card names are invalid in practice; friend-name fallback is defensive @preserve */
|
|
131
|
+
const peerName = card.name || friend.name;
|
|
132
|
+
return { endpointUrl, agentId: metadata.agentId ?? endpointUrl, peerName };
|
|
133
|
+
}
|
|
134
|
+
const external = friend.externalIds.find((id) => id.provider === "a2a-agent");
|
|
135
|
+
if (external?.externalId?.startsWith("http")) {
|
|
136
|
+
const card = await (0, client_1.fetchA2AAgentCard)(external.externalId);
|
|
137
|
+
const endpointUrl = (0, client_1.endpointForCard)(card);
|
|
138
|
+
/* v8 ignore next -- fetchA2AAgentCard rejects cards without a usable endpoint before tools see them @preserve */
|
|
139
|
+
if (!endpointUrl)
|
|
140
|
+
throw new Error("A2A card has no JSONRPC endpoint");
|
|
141
|
+
/* v8 ignore next -- empty card names are invalid in practice; friend-name fallback is defensive @preserve */
|
|
142
|
+
const peerName = card.name || friend.name;
|
|
143
|
+
return { endpointUrl, agentId: external.externalId, peerName };
|
|
144
|
+
}
|
|
145
|
+
throw new Error("A2A peer has no endpointUrl or cardUrl in agentMeta.a2a");
|
|
146
|
+
}
|
|
147
|
+
/** The management sense the current turn arrived through, defaulting to a non-`local`
|
|
148
|
+
* value when unknown so the owner-only gate fails CLOSED on an unexpected origin. */
|
|
149
|
+
function senseTypeOf(ctx) {
|
|
150
|
+
/* v8 ignore next -- in-turn tool calls always carry a resolved channel context; the open-default fail-closed fallback is defensive @preserve */
|
|
151
|
+
return ctx?.context?.channel?.senseType ?? "open";
|
|
152
|
+
}
|
|
153
|
+
/** The pinned DID a peer record carries (its durable A2A identity), or undefined for a
|
|
154
|
+
* legacy (non-DID-keyed) peer. */
|
|
155
|
+
function peerDid(peer) {
|
|
156
|
+
const did = peer.agentMeta?.a2a?.did;
|
|
157
|
+
return typeof did === "string" && did.trim() ? did.trim() : undefined;
|
|
158
|
+
}
|
|
159
|
+
/** Locate an imported delegation by its correlation `requestId` across all missions:
|
|
160
|
+
* who delegated it (`fromAgentId`) + which local mission (`missionId`). The delegation
|
|
161
|
+
* lives under `importedDelegations[fromAgentId][requestId]` — what the inbound bridge
|
|
162
|
+
* quarantined. Returns undefined when no mission carries that requestId. */
|
|
163
|
+
function findImportedDelegation(missions, requestId) {
|
|
164
|
+
for (const mission of missions) {
|
|
165
|
+
for (const [fromAgentId, byRequest] of Object.entries(mission.importedDelegations ?? {})) {
|
|
166
|
+
if (byRequest[requestId])
|
|
167
|
+
return { fromAgentId, missionId: mission.id };
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Seal an arbitrary friends plaintext envelope to a DID-keyed peer and deliver it over
|
|
174
|
+
* the `direct` rung via friends' `sendShare`. `sendShare` builds the SAME SealedEnvelope
|
|
175
|
+
* regardless of rung, `wrapInDataPart`-wraps it, and calls the transport itself; the
|
|
176
|
+
* recipient X25519 is derived from the peer's pinned did:key. Throws when the peer's DID
|
|
177
|
+
* is unparseable (cannot seal) or the rung is unreachable.
|
|
178
|
+
*/
|
|
179
|
+
async function sealEnvelopeToPeer(input) {
|
|
180
|
+
const parsed = (0, a2a_client_1.parseDidKey)(input.did);
|
|
181
|
+
if (!parsed)
|
|
182
|
+
throw new Error(`cannot seal: peer DID is not a parseable did:key (${input.did})`);
|
|
183
|
+
const reachability = (0, a2a_client_1.resolveReachability)(input.peer.agentMeta?.a2a, input.peer.agentMeta?.mailbox);
|
|
184
|
+
if (reachability.rung === "unreachable") {
|
|
185
|
+
throw new Error("cannot seal: peer has no reachable A2A endpoint");
|
|
186
|
+
}
|
|
187
|
+
(0, runtime_1.emitNervesEvent)({
|
|
188
|
+
component: "channels",
|
|
189
|
+
event: "channel.a2a_outbound_seal",
|
|
190
|
+
message: "sealing outbound A2A envelope to a DID-keyed peer",
|
|
191
|
+
meta: { selfDid: input.self.did, peerDid: input.did, rung: reachability.rung, friendsKind: input.friendsKind },
|
|
192
|
+
});
|
|
193
|
+
const result = await (0, a2a_client_1.sendShare)({
|
|
194
|
+
sodium: input.sodium,
|
|
195
|
+
transport: (0, transport_1.makeA2ATransport)(),
|
|
196
|
+
fromIdentity: input.self,
|
|
197
|
+
toPeer: { a2a: input.peer.agentMeta?.a2a },
|
|
198
|
+
recipientDid: input.did,
|
|
199
|
+
recipientX25519Pub: (0, a2a_client_1.keyAgreementFromDidKey)({ sodium: input.sodium, ed25519Pub: parsed.ed25519Pub }),
|
|
200
|
+
plaintextEnvelope: input.envelope,
|
|
201
|
+
friendsKind: input.friendsKind,
|
|
202
|
+
});
|
|
203
|
+
/* v8 ignore next 3 -- unreachable behind the resolveReachability pre-check above: sendShare only returns ok:false on the SAME `unreachable` plan we already rejected; a redundant guard. @preserve */
|
|
204
|
+
if (!result.ok) {
|
|
205
|
+
throw new Error(`sealed send failed (${result.reason})`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Seal an outbound free-text message to a DID-keyed peer over the `direct` rung. The
|
|
210
|
+
* text rides a minimal `coordination` envelope (`intent:"offer"`, the text as `note`) —
|
|
211
|
+
* the kind the Slice-1 inbound bridge verifies (signed sender DID) and turns into a
|
|
212
|
+
* peer turn.
|
|
213
|
+
*/
|
|
214
|
+
async function sealAndSendToPeer(input) {
|
|
215
|
+
const sodium = await (0, a2a_client_1.ready)();
|
|
216
|
+
const self = await (0, identity_2.loadSelfA2AIdentity)({ agentName: input.agentName, sodium });
|
|
217
|
+
const envelope = {
|
|
218
|
+
subject: { missionKey: `dm:${self.did}:${input.did}`, title: "Direct message" },
|
|
219
|
+
fromAgentId: self.did,
|
|
220
|
+
intent: "offer",
|
|
221
|
+
note: input.message,
|
|
222
|
+
issuedAt: new Date().toISOString(),
|
|
223
|
+
};
|
|
224
|
+
await sealEnvelopeToPeer({
|
|
225
|
+
self: { did: self.did, keyId: self.keyId, ed25519Priv: self.ed25519Priv },
|
|
226
|
+
sodium, peer: input.peer, did: input.did, envelope, friendsKind: "coordination",
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
exports.a2aToolDefinitions = [
|
|
230
|
+
{
|
|
231
|
+
tool: {
|
|
232
|
+
type: "function",
|
|
233
|
+
function: {
|
|
234
|
+
name: "connect_to",
|
|
235
|
+
description: "Owner-only: link an A2A agent (by its agent-card URL) into your fleet as a family-trusted, DID-keyed peer. Reachable only from your own local/CLI management sense — not exposed to network peers.",
|
|
236
|
+
parameters: {
|
|
237
|
+
type: "object",
|
|
238
|
+
properties: {
|
|
239
|
+
card_url: { type: "string", description: "The agent-card URL of the agent to connect to (its /.well-known/agent-card.json)." },
|
|
240
|
+
name: { type: "string", description: "Optional display name for the linked peer (defaults to the card name)." },
|
|
241
|
+
},
|
|
242
|
+
required: ["card_url"],
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
handler: async (args, ctx) => {
|
|
247
|
+
(0, runtime_1.emitNervesEvent)({
|
|
248
|
+
component: "repertoire",
|
|
249
|
+
event: "repertoire.tool_connect_to",
|
|
250
|
+
message: "connect_to invoked",
|
|
251
|
+
meta: { tool: "connect_to" },
|
|
252
|
+
});
|
|
253
|
+
const guard = requireTrustedRequester(ctx);
|
|
254
|
+
if (guard)
|
|
255
|
+
return guard;
|
|
256
|
+
// OWNER-ONLY GATE (fail-closed): authorizeConnect commits ONLY on the `local`
|
|
257
|
+
// (owner stdio/CLI) management sense. Any network/group/internal sense
|
|
258
|
+
// downgrades — refused BEFORE any card fetch or record write, so this tool is
|
|
259
|
+
// never reachable as a general in-turn capability a network peer could exercise.
|
|
260
|
+
// No `membership` is computed (roster auto-family is OUT of scope), so a `closed`
|
|
261
|
+
// sense ALSO downgrades — never a blanket-allow without the real roster verifier.
|
|
262
|
+
const senseType = senseTypeOf(ctx);
|
|
263
|
+
const authorization = (0, friends_1.authorizeConnect)({ senseType });
|
|
264
|
+
if (authorization.decision !== "commit") {
|
|
265
|
+
(0, runtime_1.emitNervesEvent)({
|
|
266
|
+
component: "repertoire",
|
|
267
|
+
event: "repertoire.tool_connect_to_refused",
|
|
268
|
+
message: "connect_to refused (non-owner management sense)",
|
|
269
|
+
meta: { tool: "connect_to", senseType, reason: authorization.reason },
|
|
270
|
+
});
|
|
271
|
+
return `connect_to is available only from your own local management sense (the CLI you launched). This sense (${senseType}) is not permitted to link agents.`;
|
|
272
|
+
}
|
|
273
|
+
const agentName = agentNameFromRoot(ctx?.agentRoot);
|
|
274
|
+
// ONE store for both halves — the DID-keyed onboarding write and the
|
|
275
|
+
// connectAgents resolve/link MUST point at the same store, or the link can't
|
|
276
|
+
// resolve the record the onboarding just wrote.
|
|
277
|
+
const store = storeFor(ctx);
|
|
278
|
+
try {
|
|
279
|
+
// 1) DID-keyed onboarding (the footgun fix): fetch the card, verify the
|
|
280
|
+
// card↔DID binding, and write the record keyed on the verified DID. This
|
|
281
|
+
// is what makes the peer resolvable BY DID for connectAgents below (and for
|
|
282
|
+
// the inbound resolve path). A mis-bound card throws here → no link.
|
|
283
|
+
const onboarded = await (0, onboarding_1.onboardA2APeer)({
|
|
284
|
+
/* v8 ignore next -- in-turn connect_to always carries an agentRoot; the ambient-name fallback is defensive @preserve */
|
|
285
|
+
agentName: agentName ?? "ouro-agent",
|
|
286
|
+
cardUrl: args.card_url,
|
|
287
|
+
trustLevel: "family",
|
|
288
|
+
...(args.name ? { name: args.name } : {}),
|
|
289
|
+
store,
|
|
290
|
+
});
|
|
291
|
+
const did = onboarded.agentMeta?.a2a?.did;
|
|
292
|
+
// onboardA2APeer always sets a2a.agentId (== the DID when DID-keyed, else the
|
|
293
|
+
// card URL), so this is the resolvable handle connectAgents disambiguates on.
|
|
294
|
+
/* v8 ignore next -- upsertAgentPeer always writes a2a.agentId; the record-id fallback guards a future store-shape regression @preserve */
|
|
295
|
+
const peerHandle = onboarded.agentMeta?.a2a?.agentId ?? onboarded.id;
|
|
296
|
+
// 2) The authority-gated link + control-plane audit. connectAgents re-runs the
|
|
297
|
+
// `local` gate, resolves the just-written record (by DID when present, else
|
|
298
|
+
// by its agent-peer handle), links at family, and records action:"connect".
|
|
299
|
+
const result = await (0, friends_1.connectAgents)(store, {
|
|
300
|
+
peer: did ? { did } : { agentId: peerHandle },
|
|
301
|
+
senseType,
|
|
302
|
+
trustLevel: "family",
|
|
303
|
+
}, { actor: "owner:local", originSense: senseType });
|
|
304
|
+
/* v8 ignore next 3 -- onboardA2APeer wrote a DID/agentId-keyed record, so connectAgents always resolves it (ok:true); this guards a future store-shape regression @preserve */
|
|
305
|
+
if (!result.ok) {
|
|
306
|
+
return `connect_to could not complete the link (${result.status}).`;
|
|
307
|
+
}
|
|
308
|
+
return `connected ${result.record.name} (${did ?? result.record.id}) at family trust.`;
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
return `connect_to error: ${error instanceof Error ? error.message : /* v8 ignore next -- defensive non-Error failures @preserve */ String(error)}`;
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
summaryKeys: ["card_url", "name"],
|
|
315
|
+
riskProfile: { mutates: "durable_state_write", risk: "high", reason: "links a new agent peer into the friend model at family trust" },
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
tool: {
|
|
319
|
+
type: "function",
|
|
320
|
+
function: {
|
|
321
|
+
name: "a2a_list_peers",
|
|
322
|
+
description: "List onboarded A2A agent peers from the friend model. Requires friend or family trust.",
|
|
323
|
+
parameters: {
|
|
324
|
+
type: "object",
|
|
325
|
+
properties: {},
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
handler: async (_args, ctx) => {
|
|
330
|
+
(0, runtime_1.emitNervesEvent)({
|
|
331
|
+
component: "repertoire",
|
|
332
|
+
event: "repertoire.tool_a2a_list_peers",
|
|
333
|
+
message: "a2a_list_peers invoked",
|
|
334
|
+
meta: { tool: "a2a_list_peers" },
|
|
335
|
+
});
|
|
336
|
+
const guard = requireTrustedRequester(ctx);
|
|
337
|
+
if (guard)
|
|
338
|
+
return guard;
|
|
339
|
+
const store = storeFor(ctx);
|
|
340
|
+
const listAll = store.listAll;
|
|
341
|
+
if (!listAll)
|
|
342
|
+
return "friend store does not support listing.";
|
|
343
|
+
const peers = (await listAll.call(store)).filter(isA2APeer);
|
|
344
|
+
return JSON.stringify(peers.map((peer) => ({
|
|
345
|
+
id: peer.id,
|
|
346
|
+
name: peer.name,
|
|
347
|
+
trustLevel: peer.trustLevel ?? "friend",
|
|
348
|
+
endpointUrl: peer.agentMeta?.a2a?.endpointUrl,
|
|
349
|
+
cardUrl: peer.agentMeta?.a2a?.cardUrl,
|
|
350
|
+
})), null, 2);
|
|
351
|
+
},
|
|
352
|
+
summaryKeys: [],
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
tool: {
|
|
356
|
+
type: "function",
|
|
357
|
+
function: {
|
|
358
|
+
name: "a2a_send_message",
|
|
359
|
+
description: "Send a message to a trusted A2A agent peer. The target peer must be an agent friend at friend/family trust.",
|
|
360
|
+
parameters: {
|
|
361
|
+
type: "object",
|
|
362
|
+
properties: {
|
|
363
|
+
friend_id: { type: "string", description: "Friend record ID for the A2A agent peer." },
|
|
364
|
+
message: { type: "string", description: "Message or task request to send." },
|
|
365
|
+
session_key: { type: "string", description: "Optional A2A context/session key." },
|
|
366
|
+
},
|
|
367
|
+
required: ["friend_id", "message"],
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
handler: async (args, ctx) => {
|
|
372
|
+
(0, runtime_1.emitNervesEvent)({
|
|
373
|
+
component: "repertoire",
|
|
374
|
+
event: "repertoire.tool_a2a_send_message",
|
|
375
|
+
message: "a2a_send_message invoked",
|
|
376
|
+
meta: { tool: "a2a_send_message", friendId: args.friend_id },
|
|
377
|
+
});
|
|
378
|
+
const guard = requireTrustedRequester(ctx);
|
|
379
|
+
if (guard)
|
|
380
|
+
return guard;
|
|
381
|
+
const peer = await storeFor(ctx).get(args.friend_id);
|
|
382
|
+
if (!peer || !isA2APeer(peer))
|
|
383
|
+
return `A2A peer not found: ${args.friend_id}`;
|
|
384
|
+
if (!(0, friends_1.isTrustedLevel)(peer.trustLevel))
|
|
385
|
+
return "target A2A peer must be friend or family trust before outbound messages.";
|
|
386
|
+
// ROUTING (explicit, no impl judgment): a DID-keyed peer → seal+sign via
|
|
387
|
+
// sendShare over the direct rung (E2E, verified-DID inbound). A legacy peer
|
|
388
|
+
// with no pinned DID → the existing text send, byte-for-byte unchanged.
|
|
389
|
+
const did = peerDid(peer);
|
|
390
|
+
if (did) {
|
|
391
|
+
try {
|
|
392
|
+
await sealAndSendToPeer({
|
|
393
|
+
/* v8 ignore next -- in-turn a2a_send_message always carries a bundle agentRoot; the ambient-name fallback is defensive @preserve */
|
|
394
|
+
agentName: agentNameFromRoot(ctx?.agentRoot) ?? "ouro-agent",
|
|
395
|
+
peer,
|
|
396
|
+
did,
|
|
397
|
+
message: args.message,
|
|
398
|
+
});
|
|
399
|
+
return `sealed message delivered to ${peer.name} (${did}) over the direct rung.`;
|
|
400
|
+
}
|
|
401
|
+
catch (error) {
|
|
402
|
+
return `A2A sealed send error: ${error instanceof Error ? error.message : /* v8 ignore next -- defensive non-Error transport failures @preserve */ String(error)}`;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
try {
|
|
406
|
+
const endpoint = await resolveA2AEndpoint(peer);
|
|
407
|
+
const task = await (0, client_1.sendA2AMessage)({
|
|
408
|
+
endpointUrl: endpoint.endpointUrl,
|
|
409
|
+
message: args.message,
|
|
410
|
+
senderAgentId: agentNameFromRoot(ctx?.agentRoot) ?? "ouro-agent",
|
|
411
|
+
senderName: agentNameFromRoot(ctx?.agentRoot) ?? "Ouro agent",
|
|
412
|
+
senderCardUrl: localA2ACardUrl(ctx?.agentRoot),
|
|
413
|
+
sessionKey: args.session_key,
|
|
414
|
+
});
|
|
415
|
+
rememberTaskToken(ctx, peer.id, task);
|
|
416
|
+
return JSON.stringify(redactTaskToken(task), null, 2);
|
|
417
|
+
}
|
|
418
|
+
catch (error) {
|
|
419
|
+
return `A2A send error: ${error instanceof Error ? error.message : /* v8 ignore next -- defensive non-Error transport failures */ String(error)}`;
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
summaryKeys: ["friend_id", "session_key"],
|
|
423
|
+
riskProfile: { mutates: "external_side_effect", risk: "high", reason: "sends a message to a remote agent peer" },
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
tool: {
|
|
427
|
+
type: "function",
|
|
428
|
+
function: {
|
|
429
|
+
name: "a2a_get_task",
|
|
430
|
+
description: "Fetch a task from a trusted A2A agent peer.",
|
|
431
|
+
parameters: {
|
|
432
|
+
type: "object",
|
|
433
|
+
properties: {
|
|
434
|
+
friend_id: { type: "string", description: "Friend record ID for the A2A agent peer." },
|
|
435
|
+
task_id: { type: "string", description: "Remote A2A task ID." },
|
|
436
|
+
access_token: { type: "string", description: "Optional task access token from an external A2A response; omitted for tasks sent through a2a_send_message because Ouro stores it out of transcript." },
|
|
437
|
+
},
|
|
438
|
+
required: ["friend_id", "task_id"],
|
|
439
|
+
},
|
|
440
|
+
},
|
|
441
|
+
},
|
|
442
|
+
handler: async (args, ctx) => {
|
|
443
|
+
(0, runtime_1.emitNervesEvent)({
|
|
444
|
+
component: "repertoire",
|
|
445
|
+
event: "repertoire.tool_a2a_get_task",
|
|
446
|
+
message: "a2a_get_task invoked",
|
|
447
|
+
meta: { tool: "a2a_get_task", friendId: args.friend_id, taskId: args.task_id },
|
|
448
|
+
});
|
|
449
|
+
const guard = requireTrustedRequester(ctx);
|
|
450
|
+
if (guard)
|
|
451
|
+
return guard;
|
|
452
|
+
const peer = await storeFor(ctx).get(args.friend_id);
|
|
453
|
+
if (!peer || !isA2APeer(peer))
|
|
454
|
+
return `A2A peer not found: ${args.friend_id}`;
|
|
455
|
+
if (!(0, friends_1.isTrustedLevel)(peer.trustLevel))
|
|
456
|
+
return "target A2A peer must be friend or family trust before task lookup.";
|
|
457
|
+
try {
|
|
458
|
+
const endpoint = await resolveA2AEndpoint(peer);
|
|
459
|
+
const task = await (0, client_1.getA2ATask)({
|
|
460
|
+
endpointUrl: endpoint.endpointUrl,
|
|
461
|
+
taskId: args.task_id,
|
|
462
|
+
accessToken: args.access_token ?? rememberedTaskToken(ctx, peer.id, args.task_id),
|
|
463
|
+
senderAgentId: agentNameFromRoot(ctx?.agentRoot) ?? "ouro-agent",
|
|
464
|
+
senderName: agentNameFromRoot(ctx?.agentRoot) ?? "Ouro agent",
|
|
465
|
+
senderCardUrl: localA2ACardUrl(ctx?.agentRoot),
|
|
466
|
+
});
|
|
467
|
+
rememberTaskToken(ctx, peer.id, task);
|
|
468
|
+
return JSON.stringify(redactTaskToken(task), null, 2);
|
|
469
|
+
}
|
|
470
|
+
catch (error) {
|
|
471
|
+
return `A2A task error: ${error instanceof Error ? error.message : /* v8 ignore next -- defensive non-Error transport failures */ String(error)}`;
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
summaryKeys: ["friend_id", "task_id"],
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
tool: {
|
|
478
|
+
type: "function",
|
|
479
|
+
function: {
|
|
480
|
+
name: "coordinate",
|
|
481
|
+
description: "Delegate a task to a trusted (friend/family) A2A agent peer over a named shared mission. Mints a correlation requestId, records your first-party delegation, and seals the coordination to the peer over the direct rung. The peer reads it via its quarantined imported delegations and returns a result with send_result.",
|
|
482
|
+
parameters: {
|
|
483
|
+
type: "object",
|
|
484
|
+
properties: {
|
|
485
|
+
friend_id: { type: "string", description: "Friend record ID for the A2A agent peer to delegate to." },
|
|
486
|
+
mission_key: { type: "string", description: "The shared mission join key both agents can name (e.g. a stable project key)." },
|
|
487
|
+
mission_title: { type: "string", description: "Human title for the mission (used when first creating it)." },
|
|
488
|
+
task_summary: { type: "string", description: "What the peer is being asked to do." },
|
|
489
|
+
task_details: { type: "string", description: "Optional fuller description of the task." },
|
|
490
|
+
},
|
|
491
|
+
required: ["friend_id", "mission_key", "mission_title", "task_summary"],
|
|
492
|
+
},
|
|
493
|
+
},
|
|
494
|
+
},
|
|
495
|
+
handler: async (args, ctx) => {
|
|
496
|
+
(0, runtime_1.emitNervesEvent)({
|
|
497
|
+
component: "repertoire",
|
|
498
|
+
event: "repertoire.tool_coordinate",
|
|
499
|
+
message: "coordinate invoked",
|
|
500
|
+
meta: { tool: "coordinate", friendId: args.friend_id, missionKey: args.mission_key },
|
|
501
|
+
});
|
|
502
|
+
const guard = requireTrustedRequester(ctx);
|
|
503
|
+
if (guard)
|
|
504
|
+
return guard;
|
|
505
|
+
const peer = await storeFor(ctx).get(args.friend_id);
|
|
506
|
+
if (!peer || !isA2APeer(peer))
|
|
507
|
+
return `A2A peer not found: ${args.friend_id}`;
|
|
508
|
+
if (!(0, friends_1.isTrustedLevel)(peer.trustLevel))
|
|
509
|
+
return "target A2A peer must be friend or family trust before delegating.";
|
|
510
|
+
const did = peerDid(peer);
|
|
511
|
+
if (!did)
|
|
512
|
+
return "coordinate requires a DID-keyed peer (connect_to it first to pin its did:key).";
|
|
513
|
+
/* v8 ignore next -- in-turn coordinate always carries a bundle agentRoot; the ambient-name fallback is defensive (same pattern as connect_to) @preserve */
|
|
514
|
+
const agentName = agentNameFromRoot(ctx?.agentRoot) ?? "ouro-agent";
|
|
515
|
+
const store = storeFor(ctx);
|
|
516
|
+
/* v8 ignore next -- in-turn tool calls always carry an agentRoot; the getAgentRoot() ambient fallback depends on process argv (same pattern as storeFor) @preserve */
|
|
517
|
+
const { missionStore, grantStore } = (0, delegation_stores_1.delegationStoresFor)(ctx?.agentRoot ?? (0, identity_1.getAgentRoot)());
|
|
518
|
+
try {
|
|
519
|
+
const sodium = await (0, a2a_client_1.ready)();
|
|
520
|
+
const self = await (0, identity_2.loadSelfA2AIdentity)({ agentName, sodium });
|
|
521
|
+
// Ensure the local mission exists (first-party), then prepare the coordination:
|
|
522
|
+
// mints the requestId + records the first-party delegation (assignee = the peer).
|
|
523
|
+
const mission = await (0, friends_1.recordMission)(missionStore, { missionKey: args.mission_key, title: args.mission_title });
|
|
524
|
+
const prepared = await (0, friends_1.prepareCoordination)(missionStore, store, grantStore, {
|
|
525
|
+
missionId: mission.id,
|
|
526
|
+
toAgentId: did,
|
|
527
|
+
intent: "request",
|
|
528
|
+
selfAgentId: self.did,
|
|
529
|
+
task: { summary: args.task_summary, ...(args.task_details ? { details: args.task_details } : {}) },
|
|
530
|
+
});
|
|
531
|
+
/* v8 ignore next 3 -- unreachable for a trusted DID-keyed peer: recordMission guarantees the mission exists (no not_found) and the isTrustedLevel guard above guarantees trust≥friend, which the tiered consent default always approves (no no_consent). Defensive only. @preserve */
|
|
532
|
+
if (!prepared.ok) {
|
|
533
|
+
return `coordinate refused (${prepared.status}).`;
|
|
534
|
+
}
|
|
535
|
+
const requestId = prepared.envelope.task?.requestId;
|
|
536
|
+
// Seal + send the coordination envelope to the peer over direct.
|
|
537
|
+
await sealEnvelopeToPeer({
|
|
538
|
+
self: { did: self.did, keyId: self.keyId, ed25519Priv: self.ed25519Priv },
|
|
539
|
+
sodium, peer, did,
|
|
540
|
+
envelope: prepared.envelope,
|
|
541
|
+
friendsKind: "coordination",
|
|
542
|
+
});
|
|
543
|
+
(0, runtime_1.emitNervesEvent)({
|
|
544
|
+
component: "repertoire",
|
|
545
|
+
event: "repertoire.tool_coordinate_sent",
|
|
546
|
+
message: "coordination delegated + sealed to peer",
|
|
547
|
+
meta: { tool: "coordinate", peerDid: did, missionKey: args.mission_key, requestId },
|
|
548
|
+
});
|
|
549
|
+
return `coordinated: delegated "${args.task_summary}" to ${peer.name} on mission ${args.mission_key} (requestId ${requestId}).`;
|
|
550
|
+
}
|
|
551
|
+
catch (error) {
|
|
552
|
+
return `coordinate error: ${error instanceof Error ? error.message : /* v8 ignore next -- defensive non-Error failures @preserve */ String(error)}`;
|
|
553
|
+
}
|
|
554
|
+
},
|
|
555
|
+
summaryKeys: ["friend_id", "mission_key"],
|
|
556
|
+
riskProfile: { mutates: "external_side_effect", risk: "high", reason: "delegates a task to a remote agent peer" },
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
tool: {
|
|
560
|
+
type: "function",
|
|
561
|
+
function: {
|
|
562
|
+
name: "list_delegations",
|
|
563
|
+
description: "List delegations other agents have sent you (quarantined imported delegations). Each entry names the requesting agent, the mission, the correlation requestId, and the task summary. Use this to see what work peers have asked you to do, then send_result when done.",
|
|
564
|
+
parameters: { type: "object", properties: {} },
|
|
565
|
+
},
|
|
566
|
+
},
|
|
567
|
+
handler: async (_args, ctx) => {
|
|
568
|
+
(0, runtime_1.emitNervesEvent)({
|
|
569
|
+
component: "repertoire",
|
|
570
|
+
event: "repertoire.tool_list_delegations",
|
|
571
|
+
message: "list_delegations invoked",
|
|
572
|
+
meta: { tool: "list_delegations" },
|
|
573
|
+
});
|
|
574
|
+
const guard = requireTrustedRequester(ctx);
|
|
575
|
+
if (guard)
|
|
576
|
+
return guard;
|
|
577
|
+
/* v8 ignore next -- in-turn tool calls always carry an agentRoot; the getAgentRoot() ambient fallback depends on process argv (same pattern as storeFor) @preserve */
|
|
578
|
+
const { missionStore } = (0, delegation_stores_1.delegationStoresFor)(ctx?.agentRoot ?? (0, identity_1.getAgentRoot)());
|
|
579
|
+
/* v8 ignore next -- FileMissionStore always implements listAll; the [] fallback guards a future store-shape regression @preserve */
|
|
580
|
+
const missions = missionStore.listAll ? await missionStore.listAll() : [];
|
|
581
|
+
const rows = [];
|
|
582
|
+
for (const mission of missions) {
|
|
583
|
+
for (const [fromAgentId, byRequest] of Object.entries(mission.importedDelegations ?? {})) {
|
|
584
|
+
for (const [requestId, delegation] of Object.entries(byRequest)) {
|
|
585
|
+
rows.push({
|
|
586
|
+
requestId,
|
|
587
|
+
fromAgentId,
|
|
588
|
+
missionKey: mission.missionKey,
|
|
589
|
+
missionTitle: mission.title,
|
|
590
|
+
summary: delegation.task.summary,
|
|
591
|
+
...(delegation.task.details ? { details: delegation.task.details } : {}),
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return JSON.stringify(rows, null, 2);
|
|
597
|
+
},
|
|
598
|
+
summaryKeys: [],
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
tool: {
|
|
602
|
+
type: "function",
|
|
603
|
+
function: {
|
|
604
|
+
name: "send_result",
|
|
605
|
+
description: "Return a result for a delegation another agent sent you (by its requestId, from list_delegations). Seals the result and delivers it back to the delegating agent over the direct rung; they import it (assignee/correlation-gated). Deliver-back is explicit — do the work in your turn, then call this.",
|
|
606
|
+
parameters: {
|
|
607
|
+
type: "object",
|
|
608
|
+
properties: {
|
|
609
|
+
request_id: { type: "string", description: "The delegation correlation requestId (from list_delegations)." },
|
|
610
|
+
summary: { type: "string", description: "A summary of the result/deliverable." },
|
|
611
|
+
artifact: { type: "string", description: "Optional artifact reference (e.g. a PR or document URL)." },
|
|
612
|
+
},
|
|
613
|
+
required: ["request_id", "summary"],
|
|
614
|
+
},
|
|
615
|
+
},
|
|
616
|
+
},
|
|
617
|
+
handler: async (args, ctx) => {
|
|
618
|
+
(0, runtime_1.emitNervesEvent)({
|
|
619
|
+
component: "repertoire",
|
|
620
|
+
event: "repertoire.tool_send_result",
|
|
621
|
+
message: "send_result invoked",
|
|
622
|
+
meta: { tool: "send_result", requestId: args.request_id },
|
|
623
|
+
});
|
|
624
|
+
const guard = requireTrustedRequester(ctx);
|
|
625
|
+
if (guard)
|
|
626
|
+
return guard;
|
|
627
|
+
const store = storeFor(ctx);
|
|
628
|
+
/* v8 ignore next -- in-turn tool calls always carry an agentRoot; the getAgentRoot() ambient fallback depends on process argv (same pattern as storeFor) @preserve */
|
|
629
|
+
const { missionStore, grantStore } = (0, delegation_stores_1.delegationStoresFor)(ctx?.agentRoot ?? (0, identity_1.getAgentRoot)());
|
|
630
|
+
// Find the imported delegation this result answers (who delegated + which mission).
|
|
631
|
+
/* v8 ignore next -- FileMissionStore always implements listAll; the [] fallback guards a future store-shape regression @preserve */
|
|
632
|
+
const missions = missionStore.listAll ? await missionStore.listAll() : [];
|
|
633
|
+
const found = findImportedDelegation(missions, args.request_id);
|
|
634
|
+
if (!found)
|
|
635
|
+
return `no imported delegation found for requestId ${args.request_id} (check list_delegations).`;
|
|
636
|
+
// The delegator (the recipient of the result) must be a trusted, reachable,
|
|
637
|
+
// DID-keyed peer in our store.
|
|
638
|
+
const delegator = await (0, friends_1.findFriendByDid)(store, found.fromAgentId);
|
|
639
|
+
if (!delegator || !isA2APeer(delegator))
|
|
640
|
+
return `delegating peer not found for ${found.fromAgentId}.`;
|
|
641
|
+
if (!(0, friends_1.isTrustedLevel)(delegator.trustLevel))
|
|
642
|
+
return "delegating peer must be friend or family trust to return a result.";
|
|
643
|
+
const delegatorDid = peerDid(delegator);
|
|
644
|
+
/* v8 ignore next -- unreachable: findFriendByDid matched this record BY its DID (via resolveAgentIdentity, which omits empty DIDs), so a2a.did is always present here. Defensive. @preserve */
|
|
645
|
+
if (!delegatorDid)
|
|
646
|
+
return "delegating peer is not DID-keyed (cannot seal the result).";
|
|
647
|
+
const parsedDelegator = (0, a2a_client_1.parseDidKey)(delegatorDid);
|
|
648
|
+
if (!parsedDelegator)
|
|
649
|
+
return `cannot seal: delegating peer DID is unparseable (${delegatorDid}).`;
|
|
650
|
+
const endpointUrl = delegator.agentMeta?.a2a?.endpointUrl;
|
|
651
|
+
if (!endpointUrl)
|
|
652
|
+
return "delegating peer has no reachable A2A endpoint to return the result to.";
|
|
653
|
+
/* v8 ignore next -- in-turn send_result always carries a bundle agentRoot; the ambient-name fallback is defensive (same pattern as connect_to) @preserve */
|
|
654
|
+
const agentName = agentNameFromRoot(ctx?.agentRoot) ?? "ouro-agent";
|
|
655
|
+
try {
|
|
656
|
+
const sodium = await (0, a2a_client_1.ready)();
|
|
657
|
+
const self = await (0, identity_2.loadSelfA2AIdentity)({ agentName, sodium });
|
|
658
|
+
// prepareMissionResult records the result first-party (results[requestId]) +
|
|
659
|
+
// returns the MissionResultEnvelope (consent-gated: trust ≥ friend recipient).
|
|
660
|
+
const prepared = await (0, friends_1.prepareMissionResult)(missionStore, store, grantStore, {
|
|
661
|
+
missionId: found.missionId,
|
|
662
|
+
toAgentId: delegatorDid,
|
|
663
|
+
requestId: args.request_id,
|
|
664
|
+
selfAgentId: self.did,
|
|
665
|
+
result: { summary: args.summary, ...(args.artifact ? { artifact: args.artifact } : {}) },
|
|
666
|
+
});
|
|
667
|
+
/* v8 ignore next 3 -- unreachable for a trusted DID-keyed delegator: the mission exists (it carried the imported delegation we matched) and the isTrustedLevel guard guarantees trust≥friend, which the tiered consent default approves. Defensive only. @preserve */
|
|
668
|
+
if (!prepared.ok) {
|
|
669
|
+
return `send_result refused (${prepared.status}).`;
|
|
670
|
+
}
|
|
671
|
+
// HARNESS-OWNED RESULT WIRE: seal the envelope (reusing the seal crypto), wrap
|
|
672
|
+
// it in the mission_result-tagged DataPart, and POST it to the delegator over
|
|
673
|
+
// direct. The inbound side routes it to importMissionResult (NOT receiveShare).
|
|
674
|
+
const sealed = (0, a2a_client_1.sealEnvelope)({
|
|
675
|
+
sodium,
|
|
676
|
+
envelope: prepared.envelope,
|
|
677
|
+
friendsKind: "coordination",
|
|
678
|
+
fromIdentity: { did: self.did, keyId: self.keyId, ed25519Priv: self.ed25519Priv },
|
|
679
|
+
recipientDid: delegatorDid,
|
|
680
|
+
recipientX25519Pub: (0, a2a_client_1.keyAgreementFromDidKey)({ sodium, ed25519Pub: parsedDelegator.ed25519Pub }),
|
|
681
|
+
});
|
|
682
|
+
const message = (0, mission_result_wire_1.wrapMissionResultDataPart)({ sealedEnvelope: sealed, recipientDid: delegatorDid });
|
|
683
|
+
(0, runtime_1.emitNervesEvent)({
|
|
684
|
+
component: "channels",
|
|
685
|
+
event: "channel.a2a_result_send",
|
|
686
|
+
message: "delivering sealed mission result over the direct rung",
|
|
687
|
+
meta: { selfDid: self.did, toDid: delegatorDid, requestId: args.request_id },
|
|
688
|
+
});
|
|
689
|
+
await (0, client_1.postA2AMessageEnvelope)({ endpointUrl, message });
|
|
690
|
+
return `result sent to ${delegator.name} (${delegatorDid}) for requestId ${args.request_id}.`;
|
|
691
|
+
}
|
|
692
|
+
catch (error) {
|
|
693
|
+
return `send_result error: ${error instanceof Error ? error.message : /* v8 ignore next -- defensive non-Error failures @preserve */ String(error)}`;
|
|
694
|
+
}
|
|
695
|
+
},
|
|
696
|
+
summaryKeys: ["request_id"],
|
|
697
|
+
riskProfile: { mutates: "external_side_effect", risk: "high", reason: "returns a result to a remote agent peer" },
|
|
698
|
+
},
|
|
699
|
+
];
|