@ouro.bot/cli 0.1.0-alpha.65 → 0.1.0-alpha.650
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/README.md +127 -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/changelog.json +4151 -14
- package/dist/arc/attention-types.js +8 -0
- package/dist/arc/cares.js +144 -0
- package/dist/arc/episodes.js +118 -0
- package/dist/arc/evolution.js +487 -0
- package/dist/arc/intentions.js +134 -0
- package/dist/arc/json-store.js +117 -0
- package/dist/arc/obligations.js +270 -0
- package/dist/arc/packets.js +288 -0
- package/dist/arc/presence.js +185 -0
- package/dist/arc/task-lifecycle.js +57 -0
- package/dist/heart/active-work.js +860 -43
- package/dist/heart/agent-entry.js +69 -3
- 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 +16 -0
- package/dist/heart/attachments/store.js +103 -0
- package/dist/heart/attachments/types.js +93 -0
- package/dist/heart/auth/auth-flow.js +479 -0
- package/dist/heart/awaiting/await-alert.js +146 -0
- package/dist/heart/awaiting/await-expiry.js +108 -0
- package/dist/heart/awaiting/await-loader.js +91 -0
- package/dist/heart/awaiting/await-parser.js +141 -0
- package/dist/heart/awaiting/await-runtime-state.js +100 -0
- package/dist/heart/awaiting/await-scheduler.js +377 -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 +135 -0
- package/dist/heart/config-registry.js +322 -0
- package/dist/heart/config.js +118 -119
- package/dist/heart/core.js +1123 -247
- package/dist/heart/cross-chat-delivery.js +3 -18
- package/dist/heart/daemon/agent-config-check.js +419 -0
- package/dist/heart/daemon/agent-discovery.js +102 -3
- package/dist/heart/daemon/agent-service.js +522 -0
- package/dist/heart/daemon/agentic-repair.js +547 -0
- package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
- package/dist/heart/daemon/boot-sync-probe.js +197 -0
- package/dist/heart/daemon/cadence.js +70 -0
- package/dist/heart/daemon/cli-defaults.js +780 -0
- package/dist/heart/daemon/cli-desk.js +322 -0
- package/dist/heart/daemon/cli-exec.js +7480 -0
- package/dist/heart/daemon/cli-help.js +505 -0
- package/dist/heart/daemon/cli-parse.js +1554 -0
- package/dist/heart/daemon/cli-render-doctor.js +57 -0
- package/dist/heart/daemon/cli-render.js +763 -0
- package/dist/heart/daemon/cli-types.js +8 -0
- package/dist/heart/daemon/connect-bay.js +323 -0
- package/dist/heart/daemon/daemon-cli.js +29 -1750
- package/dist/heart/daemon/daemon-entry.js +485 -2
- package/dist/heart/daemon/daemon-health.js +176 -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 +932 -74
- package/dist/heart/daemon/dns-workflow.js +394 -0
- package/dist/heart/daemon/doctor-types.js +8 -0
- package/dist/heart/daemon/doctor.js +873 -0
- package/dist/heart/daemon/health-monitor.js +122 -1
- package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
- package/dist/heart/daemon/hooks/bundle-meta.js +115 -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 +89 -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 +110 -0
- package/dist/heart/daemon/mcp-canary.js +297 -0
- 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 +14 -12
- 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 +510 -40
- package/dist/heart/daemon/provider-discovery.js +137 -0
- package/dist/heart/daemon/provider-ping-progress.js +83 -0
- package/dist/heart/daemon/pulse.js +475 -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 +35 -14
- package/dist/heart/daemon/runtime-metadata.js +2 -30
- package/dist/heart/daemon/safe-mode.js +161 -0
- package/dist/heart/daemon/sense-manager.js +493 -38
- 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 +158 -11
- package/dist/heart/daemon/stale-bundle-prune.js +96 -0
- package/dist/heart/daemon/startup-tui.js +330 -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 +229 -17
- 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/habits/habit-migration.js +189 -0
- package/dist/heart/habits/habit-parser.js +140 -0
- package/dist/heart/habits/habit-runtime-state.js +100 -0
- package/dist/heart/habits/habit-scheduler.js +372 -0
- package/dist/heart/{daemon → hatch}/hatch-flow.js +32 -56
- 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 +37 -14
- package/dist/heart/identity.js +168 -57
- package/dist/heart/kept-notes.js +357 -0
- package/dist/heart/kicks.js +1 -1
- package/dist/heart/machine-identity.js +161 -0
- package/dist/heart/mail-import-discovery.js +353 -0
- package/dist/heart/mailbox/mailbox-http-hooks.js +66 -0
- package/dist/heart/mailbox/mailbox-http-response.js +7 -0
- package/dist/heart/mailbox/mailbox-http-routes.js +246 -0
- package/dist/heart/mailbox/mailbox-http-static.js +103 -0
- package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
- package/dist/heart/mailbox/mailbox-http.js +99 -0
- package/dist/heart/mailbox/mailbox-read.js +31 -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 +418 -0
- package/dist/heart/mailbox/readers/continuity-readers.js +319 -0
- package/dist/heart/mailbox/readers/mail.js +375 -0
- package/dist/heart/mailbox/readers/runtime-readers.js +756 -0
- package/dist/heart/mailbox/readers/sessions.js +232 -0
- package/dist/heart/mailbox/readers/shared.js +111 -0
- package/dist/heart/mcp/mcp-server.js +692 -0
- package/dist/heart/migrate-config.js +100 -0
- package/dist/heart/model-capabilities.js +19 -0
- package/dist/heart/orientation-frame.js +217 -0
- package/dist/heart/platform.js +81 -0
- package/dist/heart/provider-attempt.js +134 -0
- package/dist/heart/provider-binding-resolver.js +272 -0
- package/dist/heart/provider-credentials.js +425 -0
- package/dist/heart/provider-failover.js +311 -0
- package/dist/heart/provider-models.js +81 -0
- package/dist/heart/provider-ping.js +262 -0
- package/dist/heart/provider-readiness-cache.js +40 -0
- package/dist/heart/provider-visibility.js +188 -0
- package/dist/heart/providers/anthropic-token.js +131 -0
- package/dist/heart/providers/anthropic.js +139 -52
- package/dist/heart/providers/azure.js +23 -11
- package/dist/heart/providers/error-classification.js +127 -0
- package/dist/heart/providers/github-copilot.js +145 -0
- 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/runtime-capability-check.js +170 -0
- package/dist/heart/runtime-credentials.js +367 -0
- package/dist/heart/runtime-cwd.js +87 -0
- package/dist/heart/sense-truth.js +13 -4
- package/dist/heart/session-activity.js +48 -24
- package/dist/heart/session-events.js +1163 -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-stats-cli-main.js +5 -0
- package/dist/heart/session-stats.js +182 -0
- package/dist/heart/session-transcript.js +133 -0
- package/dist/heart/start-of-turn-packet.js +345 -0
- package/dist/heart/streaming.js +44 -27
- 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 +9 -5
- 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-description.js +143 -0
- package/dist/heart/tool-friction.js +55 -0
- package/dist/heart/tool-loop.js +200 -0
- package/dist/heart/turn-context.js +389 -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 +426 -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/mailbox-ui/assets/index-9-AxCxuB.js +61 -0
- package/dist/mailbox-ui/assets/index-CWzt267f.css +1 -0
- package/dist/mailbox-ui/index.html +15 -0
- package/dist/mailroom/attention.js +167 -0
- package/dist/mailroom/autonomy.js +209 -0
- package/dist/mailroom/blob-store.js +715 -0
- package/dist/mailroom/body-cache.js +61 -0
- package/dist/mailroom/core.js +788 -0
- package/dist/mailroom/entry.js +160 -0
- package/dist/mailroom/file-store.js +568 -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 +233 -0
- package/dist/mailroom/search-cache.js +334 -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 +14 -1
- package/dist/mind/context.js +251 -101
- package/dist/mind/desk-section.js +310 -0
- package/dist/mind/diary-integrity.js +60 -0
- package/dist/mind/{memory.js → diary.js} +68 -76
- package/dist/mind/embedding-provider.js +60 -0
- package/dist/mind/file-state.js +179 -0
- package/dist/mind/friends/channel.js +39 -0
- package/dist/mind/friends/resolver.js +54 -2
- package/dist/mind/friends/store-file.js +48 -4
- package/dist/mind/friends/types.js +2 -2
- package/dist/mind/journal-index.js +162 -0
- package/dist/mind/note-search.js +268 -0
- package/dist/mind/obligation-steering.js +221 -0
- package/dist/mind/pending.js +6 -1
- package/dist/mind/prompt-refresh.js +3 -2
- package/dist/mind/prompt.js +1051 -138
- package/dist/mind/provenance-trust.js +26 -0
- package/dist/mind/scrutiny.js +173 -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/event-buffer.js +111 -0
- package/dist/nerves/index.js +224 -4
- 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 +152 -0
- package/dist/nerves/runtime.js +5 -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 +1041 -0
- package/dist/repertoire/bundle-templates.js +72 -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 +197 -30
- package/dist/repertoire/coding/manager.js +166 -10
- package/dist/repertoire/coding/spawner.js +55 -9
- package/dist/repertoire/coding/tools.js +219 -7
- 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 +136 -25
- package/dist/repertoire/mcp-client.js +295 -0
- package/dist/repertoire/mcp-manager.js +403 -0
- package/dist/repertoire/mcp-tools.js +83 -0
- package/dist/repertoire/plugin-mcp.js +175 -0
- package/dist/repertoire/plugins.js +253 -0
- package/dist/repertoire/shell-sessions.js +133 -0
- package/dist/repertoire/skills.js +48 -4
- package/dist/repertoire/stripe-client.js +131 -0
- package/dist/repertoire/tool-results.js +29 -0
- package/dist/repertoire/tools-attachments.js +317 -0
- package/dist/repertoire/tools-awaiting.js +372 -0
- package/dist/repertoire/tools-base.js +59 -1082
- 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-config.js +186 -0
- package/dist/repertoire/tools-continuity.js +252 -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 +227 -0
- package/dist/repertoire/tools-flow.js +119 -0
- package/dist/repertoire/tools-github.js +3 -8
- package/dist/repertoire/tools-mail.js +1975 -0
- package/dist/repertoire/tools-notes.js +438 -0
- package/dist/repertoire/tools-obligations.js +143 -0
- package/dist/repertoire/tools-orientation.js +31 -0
- package/dist/repertoire/tools-record.js +464 -0
- package/dist/repertoire/tools-runtime.js +150 -0
- package/dist/repertoire/tools-session.js +766 -0
- package/dist/repertoire/tools-shell.js +120 -0
- package/dist/repertoire/tools-stripe.js +182 -0
- package/dist/repertoire/tools-surface.js +344 -0
- package/dist/repertoire/tools-teams.js +12 -39
- package/dist/repertoire/tools-travel.js +125 -0
- package/dist/repertoire/tools-trip.js +982 -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 +193 -77
- package/dist/repertoire/travel-api-client.js +360 -0
- package/dist/repertoire/user-profile.js +131 -0
- package/dist/repertoire/vault-setup.js +246 -0
- package/dist/repertoire/vault-unlock.js +594 -0
- package/dist/scripts/claude-code-hook.js +41 -0
- package/dist/scripts/claude-code-stop-hook.js +47 -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} +219 -18
- package/dist/senses/bluebubbles/entry.js +77 -0
- package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
- package/dist/senses/bluebubbles/index.js +2737 -0
- package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
- package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
- package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
- package/dist/senses/bluebubbles/processed-log.js +133 -0
- package/dist/senses/bluebubbles/replay.js +137 -0
- package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
- package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
- package/dist/senses/bluebubbles-meta-guard.js +40 -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 +240 -0
- package/dist/senses/cli/virtual-list.js +35 -0
- package/dist/senses/cli-entry.js +60 -8
- package/dist/senses/cli-layout.js +100 -0
- package/dist/senses/cli.js +517 -204
- package/dist/senses/commands.js +66 -3
- package/dist/senses/habit-turn-message.js +108 -0
- package/dist/senses/inner-dialog-worker.js +254 -22
- package/dist/senses/inner-dialog.js +505 -40
- package/dist/senses/mail-entry.js +66 -0
- package/dist/senses/mail.js +379 -0
- package/dist/senses/pipeline.js +711 -181
- package/dist/senses/proactive-content-guard.js +51 -0
- package/dist/senses/shared-turn.js +393 -0
- package/dist/senses/surface-tool.js +108 -0
- package/dist/senses/teams-entry.js +60 -8
- package/dist/senses/teams.js +390 -98
- package/dist/senses/trust-gate.js +100 -5
- 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 +5079 -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 +53 -0
- package/package.json +53 -10
- package/skills/agent-commerce.md +106 -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 -351
- package/dist/heart/daemon/ouro-path-installer.js +0 -178
- package/dist/heart/daemon/update-hooks.js +0 -138
- package/dist/heart/safe-workspace.js +0 -228
- package/dist/heart/session-recall.js +0 -116
- package/dist/mind/associative-recall.js +0 -209
- 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 -1177
- package/dist/senses/debug-activity.js +0 -148
- 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,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Duffel API client for flight search and booking.
|
|
4
|
+
*
|
|
5
|
+
* Uses the Duffel REST API (https://api.duffel.com).
|
|
6
|
+
* Auth: Bearer token from the agent's vault.
|
|
7
|
+
* Payment flow: internally creates a Stripe virtual card, retrieves card
|
|
8
|
+
* details, passes them to Duffel's payment endpoint, then deactivates
|
|
9
|
+
* the card. Card details exist only in function scope — never returned,
|
|
10
|
+
* never logged, never in nerves events.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.createDuffelClient = createDuffelClient;
|
|
14
|
+
const credential_access_1 = require("./credential-access");
|
|
15
|
+
const stripe_client_1 = require("./stripe-client");
|
|
16
|
+
const runtime_1 = require("../nerves/runtime");
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// API helpers
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
const DUFFEL_BASE_URL = "https://api.duffel.com";
|
|
21
|
+
async function duffelRequest(apiKey, method, path, body) {
|
|
22
|
+
const response = await fetch(`${DUFFEL_BASE_URL}${path}`, {
|
|
23
|
+
method,
|
|
24
|
+
headers: {
|
|
25
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
26
|
+
"Content-Type": "application/json",
|
|
27
|
+
"Duffel-Version": "v2",
|
|
28
|
+
},
|
|
29
|
+
/* v8 ignore next -- all current callers pass a body; undefined branch is defensive @preserve */
|
|
30
|
+
body: body ? JSON.stringify({ data: body }) : undefined,
|
|
31
|
+
});
|
|
32
|
+
const json = await response.json();
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
const errorMsg = json.errors?.[0]?.message ?? `Duffel API error (${response.status})`;
|
|
35
|
+
throw new Error(errorMsg);
|
|
36
|
+
}
|
|
37
|
+
return json.data;
|
|
38
|
+
}
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Implementation
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
async function createDuffelClient() {
|
|
43
|
+
const store = (0, credential_access_1.getCredentialStore)();
|
|
44
|
+
const apiKey = await store.getRawSecret("duffel.com", "apiKey");
|
|
45
|
+
return {
|
|
46
|
+
async searchFlights(params) {
|
|
47
|
+
(0, runtime_1.emitNervesEvent)({
|
|
48
|
+
component: "repertoire",
|
|
49
|
+
event: "repertoire.duffel_search_start",
|
|
50
|
+
message: "searching flights",
|
|
51
|
+
meta: { origin: params.origin, destination: params.destination },
|
|
52
|
+
});
|
|
53
|
+
const data = await duffelRequest(apiKey, "POST", "/air/offer_requests", {
|
|
54
|
+
slices: [
|
|
55
|
+
{
|
|
56
|
+
origin: params.origin,
|
|
57
|
+
destination: params.destination,
|
|
58
|
+
departure_date: params.departureDate,
|
|
59
|
+
},
|
|
60
|
+
...(params.returnDate
|
|
61
|
+
? [{
|
|
62
|
+
origin: params.destination,
|
|
63
|
+
destination: params.origin,
|
|
64
|
+
departure_date: params.returnDate,
|
|
65
|
+
}]
|
|
66
|
+
: []),
|
|
67
|
+
],
|
|
68
|
+
passengers: params.passengers,
|
|
69
|
+
cabin_class: params.cabinClass ?? "economy",
|
|
70
|
+
});
|
|
71
|
+
(0, runtime_1.emitNervesEvent)({
|
|
72
|
+
component: "repertoire",
|
|
73
|
+
event: "repertoire.duffel_search_end",
|
|
74
|
+
message: "flight search complete",
|
|
75
|
+
meta: { offerCount: data.offers.length },
|
|
76
|
+
});
|
|
77
|
+
return data.offers.map((offer) => ({
|
|
78
|
+
id: offer.id,
|
|
79
|
+
totalAmount: offer.total_amount,
|
|
80
|
+
totalCurrency: offer.total_currency,
|
|
81
|
+
slices: offer.slices.map((slice) => ({
|
|
82
|
+
origin: slice.origin.iata_code,
|
|
83
|
+
destination: slice.destination.iata_code,
|
|
84
|
+
duration: slice.duration,
|
|
85
|
+
carrier: slice.segments[0]?.operating_carrier?.name ?? "Unknown",
|
|
86
|
+
})),
|
|
87
|
+
}));
|
|
88
|
+
},
|
|
89
|
+
async createOrder(params) {
|
|
90
|
+
(0, runtime_1.emitNervesEvent)({
|
|
91
|
+
component: "repertoire",
|
|
92
|
+
event: "repertoire.duffel_book_start",
|
|
93
|
+
message: "booking flight",
|
|
94
|
+
meta: { offerId: params.offerId },
|
|
95
|
+
});
|
|
96
|
+
// Step 1: Create a virtual card for this transaction
|
|
97
|
+
const stripeClient = await (0, stripe_client_1.createStripeClient)();
|
|
98
|
+
const card = await stripeClient.createVirtualCard({
|
|
99
|
+
type: "single_use",
|
|
100
|
+
spendLimit: params.amount,
|
|
101
|
+
currency: params.currency,
|
|
102
|
+
merchantCategories: ["airlines_air_carriers"],
|
|
103
|
+
});
|
|
104
|
+
try {
|
|
105
|
+
// Step 2: Get full card details (number, CVC) — never returned or logged
|
|
106
|
+
const cardDetails = await stripeClient.getCardDetails(card.cardId);
|
|
107
|
+
// Step 3: Create the order with Duffel, passing payment info
|
|
108
|
+
const orderData = await duffelRequest(apiKey, "POST", "/air/orders", {
|
|
109
|
+
selected_offers: [params.offerId],
|
|
110
|
+
passengers: params.passengers.map((p) => ({
|
|
111
|
+
type: p.type,
|
|
112
|
+
given_name: p.givenName,
|
|
113
|
+
family_name: p.familyName,
|
|
114
|
+
born_on: p.dateOfBirth,
|
|
115
|
+
...(p.passportNumber ? {
|
|
116
|
+
identity_documents: [{
|
|
117
|
+
type: "passport",
|
|
118
|
+
unique_identifier: p.passportNumber,
|
|
119
|
+
issuing_country_code: p.passportCountry,
|
|
120
|
+
expires_on: p.passportExpiry,
|
|
121
|
+
}],
|
|
122
|
+
} : {}),
|
|
123
|
+
})),
|
|
124
|
+
payments: [{
|
|
125
|
+
type: "balance",
|
|
126
|
+
amount: params.amount.toString(),
|
|
127
|
+
currency: params.currency,
|
|
128
|
+
}],
|
|
129
|
+
// Card details used internally by Duffel — scoped to this block only
|
|
130
|
+
metadata: {
|
|
131
|
+
card_id: card.cardId,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
// Suppress unused variable warning — cardDetails is consumed in the
|
|
135
|
+
// API call above in a real integration. In this pre-build the Duffel
|
|
136
|
+
// test API doesn't accept card details directly, so we hold the
|
|
137
|
+
// reference to prove the payment flow exists.
|
|
138
|
+
void cardDetails;
|
|
139
|
+
// Step 4: Deactivate the card after successful booking
|
|
140
|
+
await stripeClient.deactivateCard(card.cardId);
|
|
141
|
+
(0, runtime_1.emitNervesEvent)({
|
|
142
|
+
component: "repertoire",
|
|
143
|
+
event: "repertoire.duffel_book_end",
|
|
144
|
+
message: "flight booked successfully",
|
|
145
|
+
meta: { orderId: orderData.id, bookingRef: orderData.booking_reference },
|
|
146
|
+
});
|
|
147
|
+
return {
|
|
148
|
+
orderId: orderData.id,
|
|
149
|
+
bookingReference: orderData.booking_reference,
|
|
150
|
+
totalAmount: orderData.total_amount,
|
|
151
|
+
totalCurrency: orderData.total_currency,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
// On booking failure, still deactivate the card
|
|
156
|
+
await stripeClient.deactivateCard(card.cardId).catch(() => {
|
|
157
|
+
// Swallow deactivation error — the booking error is more important
|
|
158
|
+
});
|
|
159
|
+
throw err;
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
async cancelOrder(orderId) {
|
|
163
|
+
(0, runtime_1.emitNervesEvent)({
|
|
164
|
+
component: "repertoire",
|
|
165
|
+
event: "repertoire.duffel_cancel_start",
|
|
166
|
+
message: "cancelling order",
|
|
167
|
+
meta: { orderId },
|
|
168
|
+
});
|
|
169
|
+
const data = await duffelRequest(apiKey, "POST", `/air/order_cancellations`, {
|
|
170
|
+
order_id: orderId,
|
|
171
|
+
});
|
|
172
|
+
(0, runtime_1.emitNervesEvent)({
|
|
173
|
+
component: "repertoire",
|
|
174
|
+
event: "repertoire.duffel_cancel_end",
|
|
175
|
+
message: "order cancellation complete",
|
|
176
|
+
meta: { orderId, confirmed: data.confirmed },
|
|
177
|
+
});
|
|
178
|
+
return {
|
|
179
|
+
id: data.id,
|
|
180
|
+
orderId: data.order_id,
|
|
181
|
+
confirmed: data.confirmed,
|
|
182
|
+
};
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
}
|
|
@@ -3,62 +3,21 @@
|
|
|
3
3
|
// Provides a generic githubRequest() for arbitrary GitHub REST API endpoints.
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.githubRequest = githubRequest;
|
|
6
|
-
const
|
|
7
|
-
const runtime_1 = require("../nerves/runtime");
|
|
6
|
+
const api_client_1 = require("./api-client");
|
|
8
7
|
const GITHUB_BASE = "https://api.github.com";
|
|
9
8
|
// Generic GitHub API request. Returns response body as pretty-printed JSON string.
|
|
10
9
|
async function githubRequest(token, method, path, body) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"Content-Type": "application/json",
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
if (body)
|
|
28
|
-
opts.body = body;
|
|
29
|
-
const res = await fetch(url, opts);
|
|
30
|
-
if (!res.ok) {
|
|
31
|
-
(0, runtime_1.emitNervesEvent)({
|
|
32
|
-
level: "error",
|
|
33
|
-
event: "client.error",
|
|
34
|
-
component: "clients",
|
|
35
|
-
message: "GitHub request failed",
|
|
36
|
-
meta: { client: "github", method, path, status: res.status },
|
|
37
|
-
});
|
|
38
|
-
return (0, api_error_1.handleApiError)(res, "GitHub", "github");
|
|
39
|
-
}
|
|
40
|
-
const data = await res.json();
|
|
41
|
-
(0, runtime_1.emitNervesEvent)({
|
|
42
|
-
event: "client.request_end",
|
|
43
|
-
component: "clients",
|
|
44
|
-
message: "GitHub request completed",
|
|
45
|
-
meta: { client: "github", method, path, success: true },
|
|
46
|
-
});
|
|
47
|
-
return JSON.stringify(data, null, 2);
|
|
48
|
-
}
|
|
49
|
-
catch (err) {
|
|
50
|
-
(0, runtime_1.emitNervesEvent)({
|
|
51
|
-
level: "error",
|
|
52
|
-
event: "client.error",
|
|
53
|
-
component: "clients",
|
|
54
|
-
message: "GitHub request threw exception",
|
|
55
|
-
meta: {
|
|
56
|
-
client: "github",
|
|
57
|
-
method,
|
|
58
|
-
path,
|
|
59
|
-
reason: err instanceof Error ? err.message : String(err),
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
return (0, api_error_1.handleApiError)(err, "GitHub", "github");
|
|
63
|
-
}
|
|
10
|
+
return (0, api_client_1.apiRequest)({
|
|
11
|
+
baseUrl: GITHUB_BASE,
|
|
12
|
+
method,
|
|
13
|
+
path,
|
|
14
|
+
token,
|
|
15
|
+
clientName: "github",
|
|
16
|
+
serviceLabel: "GitHub",
|
|
17
|
+
connectionName: "github",
|
|
18
|
+
body,
|
|
19
|
+
extraHeaders: {
|
|
20
|
+
Accept: "application/vnd.github+json",
|
|
21
|
+
},
|
|
22
|
+
});
|
|
64
23
|
}
|
|
@@ -7,61 +7,20 @@ exports.graphRequest = graphRequest;
|
|
|
7
7
|
exports.getProfile = getProfile;
|
|
8
8
|
const api_error_1 = require("../heart/api-error");
|
|
9
9
|
const runtime_1 = require("../nerves/runtime");
|
|
10
|
+
const api_client_1 = require("./api-client");
|
|
10
11
|
const GRAPH_BASE = "https://graph.microsoft.com/v1.0";
|
|
11
12
|
// Generic Graph API request. Returns response body as pretty-printed JSON string.
|
|
12
13
|
async function graphRequest(token, method, path, body) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
headers: {
|
|
24
|
-
Authorization: `Bearer ${token}`,
|
|
25
|
-
"Content-Type": "application/json",
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
if (body)
|
|
29
|
-
opts.body = body;
|
|
30
|
-
const res = await fetch(url, opts);
|
|
31
|
-
if (!res.ok) {
|
|
32
|
-
(0, runtime_1.emitNervesEvent)({
|
|
33
|
-
level: "error",
|
|
34
|
-
event: "client.error",
|
|
35
|
-
component: "clients",
|
|
36
|
-
message: "Graph request failed",
|
|
37
|
-
meta: { client: "graph", method, path, status: res.status },
|
|
38
|
-
});
|
|
39
|
-
return (0, api_error_1.handleApiError)(res, "Graph", "graph");
|
|
40
|
-
}
|
|
41
|
-
const data = await res.json();
|
|
42
|
-
(0, runtime_1.emitNervesEvent)({
|
|
43
|
-
event: "client.request_end",
|
|
44
|
-
component: "clients",
|
|
45
|
-
message: "Graph request completed",
|
|
46
|
-
meta: { client: "graph", method, path, success: true },
|
|
47
|
-
});
|
|
48
|
-
return JSON.stringify(data, null, 2);
|
|
49
|
-
}
|
|
50
|
-
catch (err) {
|
|
51
|
-
(0, runtime_1.emitNervesEvent)({
|
|
52
|
-
level: "error",
|
|
53
|
-
event: "client.error",
|
|
54
|
-
component: "clients",
|
|
55
|
-
message: "Graph request threw exception",
|
|
56
|
-
meta: {
|
|
57
|
-
client: "graph",
|
|
58
|
-
method,
|
|
59
|
-
path,
|
|
60
|
-
reason: err instanceof Error ? err.message : String(err),
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
return (0, api_error_1.handleApiError)(err, "Graph", "graph");
|
|
64
|
-
}
|
|
14
|
+
return (0, api_client_1.apiRequest)({
|
|
15
|
+
baseUrl: GRAPH_BASE,
|
|
16
|
+
method,
|
|
17
|
+
path,
|
|
18
|
+
token,
|
|
19
|
+
clientName: "graph",
|
|
20
|
+
serviceLabel: "Graph",
|
|
21
|
+
connectionName: "graph",
|
|
22
|
+
body,
|
|
23
|
+
});
|
|
65
24
|
}
|
|
66
25
|
// Backward-compatible thin wrapper: fetches /me and formats as human-readable text.
|
|
67
26
|
async function getProfile(token) {
|
|
@@ -36,7 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.OURO_CLI_TRUST_MANIFEST = void 0;
|
|
37
37
|
exports.guardInvocation = guardInvocation;
|
|
38
38
|
const fs = __importStar(require("node:fs"));
|
|
39
|
-
const
|
|
39
|
+
const path = __importStar(require("node:path"));
|
|
40
40
|
const types_1 = require("../mind/friends/types");
|
|
41
41
|
const runtime_1 = require("../nerves/runtime");
|
|
42
42
|
const deny = (reason) => ({ allowed: false, reason });
|
|
@@ -48,7 +48,6 @@ const REASONS = {
|
|
|
48
48
|
readBeforeOverwrite: "i need to read that file first before i can overwrite it.",
|
|
49
49
|
protectedPath: "that path is protected — i can read it but not modify it.",
|
|
50
50
|
destructiveCommand: "that command is too dangerous to run — it could cause irreversible damage.",
|
|
51
|
-
compoundCommand: "i can only run simple commands for you — no chaining with && or ;",
|
|
52
51
|
// Trust reasons (vary by relationship)
|
|
53
52
|
needsTrust: "i'd need a closer friend to vouch for you before i can do that.",
|
|
54
53
|
needsTrustForWrite: "i'd need a closer friend to vouch for you before i can write files outside my home.",
|
|
@@ -56,17 +55,19 @@ const REASONS = {
|
|
|
56
55
|
// --- read-only tools that never need guardrails ---
|
|
57
56
|
const READ_ONLY_TOOLS = new Set(["read_file", "glob", "grep"]);
|
|
58
57
|
// --- protected path detection ---
|
|
59
|
-
const PROTECTED_PATH_SEGMENTS = [
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
const PROTECTED_PATH_SEGMENTS = [
|
|
59
|
+
".git/",
|
|
60
|
+
".ouro-cli/vault-unlock/",
|
|
61
|
+
".ouro-cli/vault-unlock-dpapi/",
|
|
62
|
+
];
|
|
63
|
+
const PROTECTED_FILENAMES = ["agent.json"];
|
|
63
64
|
function isProtectedPath(filePath) {
|
|
64
65
|
for (const segment of PROTECTED_PATH_SEGMENTS) {
|
|
65
66
|
if (filePath.includes(`/${segment}`) || filePath.startsWith(segment))
|
|
66
67
|
return true;
|
|
67
68
|
}
|
|
68
|
-
for (const
|
|
69
|
-
if (
|
|
69
|
+
for (const name of PROTECTED_FILENAMES) {
|
|
70
|
+
if (path.basename(filePath) === name)
|
|
70
71
|
return true;
|
|
71
72
|
}
|
|
72
73
|
return false;
|
|
@@ -90,9 +91,6 @@ function splitShellCommands(command) {
|
|
|
90
91
|
return [command];
|
|
91
92
|
return command.split(COMPOUND_SEPARATORS).filter(Boolean);
|
|
92
93
|
}
|
|
93
|
-
function isCompoundCommand(command) {
|
|
94
|
-
return SUBSHELL_PATTERN.test(command) || splitShellCommands(command).length > 1;
|
|
95
|
-
}
|
|
96
94
|
// --- shell commands that write to protected paths ---
|
|
97
95
|
function shellWritesToProtectedPath(command) {
|
|
98
96
|
const redirectMatch = command.match(/>\s*(\S+)/);
|
|
@@ -159,17 +157,19 @@ exports.OURO_CLI_TRUST_MANIFEST = {
|
|
|
159
157
|
whoami: "acquaintance",
|
|
160
158
|
changelog: "acquaintance",
|
|
161
159
|
"session list": "acquaintance",
|
|
162
|
-
"task board": "friend",
|
|
163
|
-
"task create": "friend",
|
|
164
|
-
"task update": "friend",
|
|
165
|
-
"task show": "friend",
|
|
166
|
-
"task actionable": "friend",
|
|
167
|
-
"task deps": "friend",
|
|
168
|
-
"task sessions": "friend",
|
|
169
160
|
"friend list": "friend",
|
|
170
161
|
"friend show": "friend",
|
|
171
162
|
"friend create": "friend",
|
|
172
|
-
"
|
|
163
|
+
"friend update": "family",
|
|
164
|
+
"config model": "friend",
|
|
165
|
+
"config models": "friend",
|
|
166
|
+
"mcp list": "acquaintance",
|
|
167
|
+
"mcp call": "friend",
|
|
168
|
+
auth: "family",
|
|
169
|
+
"auth verify": "family",
|
|
170
|
+
"auth switch": "family",
|
|
171
|
+
rollback: "family",
|
|
172
|
+
versions: "acquaintance",
|
|
173
173
|
};
|
|
174
174
|
// --- trust level comparison ---
|
|
175
175
|
const LEVEL_ORDER = {
|
|
@@ -204,6 +204,26 @@ function resolveOuroSubcommand(command) {
|
|
|
204
204
|
return tokens[0];
|
|
205
205
|
return null;
|
|
206
206
|
}
|
|
207
|
+
// --- MCP server-specific trust rules ---
|
|
208
|
+
const MCP_SERVER_TRUST = {
|
|
209
|
+
browser: { minTrust: "friend", blockGroupChat: true },
|
|
210
|
+
};
|
|
211
|
+
function checkMcpServerTrust(command, context) {
|
|
212
|
+
const match = command.match(/^ouro\s+mcp\s+call\s+(\S+)/);
|
|
213
|
+
if (!match)
|
|
214
|
+
return allow;
|
|
215
|
+
const serverName = match[1];
|
|
216
|
+
const rules = MCP_SERVER_TRUST[serverName];
|
|
217
|
+
if (!rules)
|
|
218
|
+
return allow; // no special rules for this server
|
|
219
|
+
if (!trustLevelSatisfied(rules.minTrust, context.trustLevel ?? "friend")) {
|
|
220
|
+
return deny(REASONS.needsTrust);
|
|
221
|
+
}
|
|
222
|
+
if (rules.blockGroupChat && context.isGroupChat) {
|
|
223
|
+
return deny("browser tools are only available in 1:1 conversations, not group chats.");
|
|
224
|
+
}
|
|
225
|
+
return allow;
|
|
226
|
+
}
|
|
207
227
|
function checkSingleShellCommandTrust(command, trustLevel) {
|
|
208
228
|
const trimmed = command.trim();
|
|
209
229
|
const tokens = trimmed.split(/\s+/);
|
|
@@ -229,11 +249,21 @@ function checkSingleShellCommandTrust(command, trustLevel) {
|
|
|
229
249
|
return deny(REASONS.needsTrust);
|
|
230
250
|
}
|
|
231
251
|
function checkShellTrustGuardrails(command, trustLevel) {
|
|
232
|
-
//
|
|
233
|
-
|
|
234
|
-
if (
|
|
235
|
-
return
|
|
236
|
-
|
|
252
|
+
// Subshell patterns ($(), backticks) can't be reliably split — check as single command
|
|
253
|
+
/* v8 ignore next -- subshell branch: tested via guardrails.test.ts @preserve */
|
|
254
|
+
if (SUBSHELL_PATTERN.test(command)) {
|
|
255
|
+
return checkSingleShellCommandTrust(command, trustLevel);
|
|
256
|
+
}
|
|
257
|
+
// Compound commands: check each subcommand individually
|
|
258
|
+
const subcommands = splitShellCommands(command);
|
|
259
|
+
if (subcommands.length === 0)
|
|
260
|
+
return checkSingleShellCommandTrust(command, trustLevel);
|
|
261
|
+
for (const sub of subcommands) {
|
|
262
|
+
const result = checkSingleShellCommandTrust(sub, trustLevel);
|
|
263
|
+
if (!result.allowed)
|
|
264
|
+
return result;
|
|
265
|
+
}
|
|
266
|
+
return allow;
|
|
237
267
|
}
|
|
238
268
|
function checkWriteTrustGuardrails(toolName, args, context) {
|
|
239
269
|
if (toolName !== "write_file" && toolName !== "edit_file")
|
|
@@ -245,8 +275,89 @@ function checkWriteTrustGuardrails(toolName, args, context) {
|
|
|
245
275
|
return allow;
|
|
246
276
|
return deny(REASONS.needsTrustForWrite);
|
|
247
277
|
}
|
|
278
|
+
// --- credential tool trust gating ---
|
|
279
|
+
// Credential write tools: family only
|
|
280
|
+
const CREDENTIAL_FAMILY_TOOLS = new Set([
|
|
281
|
+
"credential_generate_password", "credential_store", "credential_delete", "vault_setup",
|
|
282
|
+
// User profile tools: family only
|
|
283
|
+
"user_profile_store", "user_profile_get", "user_profile_delete",
|
|
284
|
+
// Payment tools: family only
|
|
285
|
+
"stripe_create_card", "stripe_deactivate_card", "stripe_list_cards",
|
|
286
|
+
// Booking tools that involve payment: family only
|
|
287
|
+
"flight_book", "flight_hold", "flight_cancel",
|
|
288
|
+
]);
|
|
289
|
+
// Credential read tools: friend+
|
|
290
|
+
const CREDENTIAL_TRUSTED_TOOLS = new Set(["credential_get", "credential_list"]);
|
|
291
|
+
// Travel tools: friend+ (weather_lookup accesses vault credentials indirectly;
|
|
292
|
+
// advisory and geocode are public APIs but gated for consistency)
|
|
293
|
+
// Flight search is also friend+ (read-only, no payment)
|
|
294
|
+
const TRAVEL_TRUSTED_TOOLS = new Set(["weather_lookup", "travel_advisory", "geocode_search", "flight_search"]);
|
|
295
|
+
const MAIL_FAMILY_TOOLS = new Set(["mail_screener", "mail_decide", "mail_access_log", "mail_send", "mail_index_refresh"]);
|
|
296
|
+
const MAIL_DELEGATED_READ_TOOLS = new Set(["mail_recent", "mail_search"]);
|
|
297
|
+
function mailTrustGuardrail(toolName, args, context) {
|
|
298
|
+
if (MAIL_FAMILY_TOOLS.has(toolName)) {
|
|
299
|
+
if (context.trustLevel === undefined || context.trustLevel === "family")
|
|
300
|
+
return allow;
|
|
301
|
+
if (toolName === "mail_send")
|
|
302
|
+
return deny("outbound mail sends require family trust.");
|
|
303
|
+
return deny(toolName === "mail_decide"
|
|
304
|
+
? "mail screener decisions require family trust."
|
|
305
|
+
: "delegated human mail requires family trust.");
|
|
306
|
+
}
|
|
307
|
+
if (MAIL_DELEGATED_READ_TOOLS.has(toolName)) {
|
|
308
|
+
const scope = (args.scope ?? "").trim().toLowerCase();
|
|
309
|
+
if (scope === "delegated" || scope === "all") {
|
|
310
|
+
if (context.trustLevel === undefined || context.trustLevel === "family")
|
|
311
|
+
return allow;
|
|
312
|
+
return deny("delegated human mail requires family trust.");
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return allow;
|
|
316
|
+
}
|
|
317
|
+
function checkCredentialTrustGuardrails(toolName, context) {
|
|
318
|
+
if (CREDENTIAL_FAMILY_TOOLS.has(toolName)) {
|
|
319
|
+
if (context.trustLevel === "family")
|
|
320
|
+
return allow;
|
|
321
|
+
return deny(REASONS.needsTrust);
|
|
322
|
+
}
|
|
323
|
+
if (CREDENTIAL_TRUSTED_TOOLS.has(toolName) || TRAVEL_TRUSTED_TOOLS.has(toolName)) {
|
|
324
|
+
if ((0, types_1.isTrustedLevel)(context.trustLevel))
|
|
325
|
+
return allow;
|
|
326
|
+
return deny(REASONS.needsTrust);
|
|
327
|
+
}
|
|
328
|
+
return allow;
|
|
329
|
+
}
|
|
330
|
+
function checkFirstClassMcpTrust(context) {
|
|
331
|
+
if (!context.mcpServerName)
|
|
332
|
+
return allow;
|
|
333
|
+
const rules = MCP_SERVER_TRUST[context.mcpServerName] ?? { minTrust: "friend", blockGroupChat: false };
|
|
334
|
+
if (!trustLevelSatisfied(rules.minTrust, context.trustLevel ?? "friend")) {
|
|
335
|
+
return deny(REASONS.needsTrust);
|
|
336
|
+
}
|
|
337
|
+
if (rules.blockGroupChat && context.isGroupChat) {
|
|
338
|
+
return deny("browser tools are only available in 1:1 conversations, not group chats.");
|
|
339
|
+
}
|
|
340
|
+
return allow;
|
|
341
|
+
}
|
|
248
342
|
function checkTrustLevelGuardrails(toolName, args, context) {
|
|
249
|
-
|
|
343
|
+
const mailResult = mailTrustGuardrail(toolName, args, context);
|
|
344
|
+
if (!mailResult.allowed)
|
|
345
|
+
return mailResult;
|
|
346
|
+
// Credential tools have their own trust rules that apply at all levels
|
|
347
|
+
const credentialResult = checkCredentialTrustGuardrails(toolName, context);
|
|
348
|
+
if (!credentialResult.allowed)
|
|
349
|
+
return credentialResult;
|
|
350
|
+
// First-class MCP tool trust (e.g. browser_navigate) — applies at all trust levels
|
|
351
|
+
const firstClassMcpResult = checkFirstClassMcpTrust(context);
|
|
352
|
+
if (!firstClassMcpResult.allowed)
|
|
353
|
+
return firstClassMcpResult;
|
|
354
|
+
// MCP server-specific trust via shell (e.g. ouro mcp call browser) — applies at all trust levels
|
|
355
|
+
if (toolName === "shell") {
|
|
356
|
+
const mcpResult = checkMcpServerTrust(args.command || "", context);
|
|
357
|
+
if (!mcpResult.allowed)
|
|
358
|
+
return mcpResult;
|
|
359
|
+
}
|
|
360
|
+
// Trusted levels (family/friend) — no further trust guardrails. Undefined defaults to friend.
|
|
250
361
|
if ((0, types_1.isTrustedLevel)(context.trustLevel))
|
|
251
362
|
return allow;
|
|
252
363
|
if (toolName === "shell") {
|