@ouro.bot/cli 0.1.0-alpha.56 → 0.1.0-alpha.560
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 +3596 -0
- package/dist/arc/attention-types.js +8 -0
- package/dist/arc/cares.js +140 -0
- package/dist/arc/episodes.js +117 -0
- package/dist/arc/intentions.js +133 -0
- package/dist/arc/json-store.js +117 -0
- package/dist/arc/obligations.js +237 -0
- package/dist/arc/packets.js +193 -0
- package/dist/arc/presence.js +185 -0
- package/dist/arc/task-lifecycle.js +65 -0
- package/dist/heart/active-work.js +837 -26
- package/dist/heart/agent-entry.js +58 -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/adapter.js +2 -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/background-operations.js +281 -0
- package/dist/heart/bundle-state.js +168 -0
- package/dist/heart/commitments.js +111 -0
- package/dist/heart/config-registry.js +322 -0
- package/dist/heart/config.js +114 -118
- package/dist/heart/core.js +913 -246
- 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 +776 -0
- package/dist/heart/daemon/cli-exec.js +7457 -0
- package/dist/heart/daemon/cli-help.js +498 -0
- package/dist/heart/daemon/cli-parse.js +1592 -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 -1698
- package/dist/heart/daemon/daemon-entry.js +387 -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 +796 -71
- package/dist/heart/daemon/dns-workflow.js +394 -0
- package/dist/heart/daemon/doctor-types.js +8 -0
- package/dist/heart/daemon/doctor.js +826 -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 +82 -12
- package/dist/heart/daemon/logs-prune.js +110 -0
- package/dist/heart/daemon/mcp-canary.js +297 -0
- package/dist/heart/daemon/message-router.js +2 -2
- 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/process-manager.js +375 -33
- 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 +67 -16
- package/dist/heart/daemon/runtime-metadata.js +3 -31
- package/dist/heart/daemon/safe-mode.js +161 -0
- package/dist/heart/daemon/sense-manager.js +389 -38
- package/dist/heart/daemon/session-id-resolver.js +131 -0
- package/dist/heart/daemon/skill-management-installer.js +94 -0
- 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 +3 -25
- package/dist/heart/daemon/terminal-ui.js +499 -0
- package/dist/heart/daemon/thoughts.js +162 -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 -1
- 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 +35 -12
- package/dist/heart/identity.js +203 -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 +195 -0
- package/dist/heart/mailbox/readers/agent-machine.js +382 -0
- package/dist/heart/mailbox/readers/continuity-readers.js +338 -0
- package/dist/heart/mailbox/readers/mail.js +362 -0
- package/dist/heart/mailbox/readers/runtime-readers.js +651 -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 +683 -0
- package/dist/heart/migrate-config.js +100 -0
- package/dist/heart/model-capabilities.js +19 -0
- package/dist/heart/platform.js +81 -0
- package/dist/heart/provider-attempt.js +134 -0
- package/dist/heart/provider-binding-resolver.js +267 -0
- package/dist/heart/provider-credentials.js +425 -0
- package/dist/heart/provider-failover.js +301 -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 +97 -13
- 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.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 +43 -22
- package/dist/heart/session-events.js +1149 -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 +243 -0
- package/dist/heart/start-of-turn-packet.js +345 -0
- package/dist/heart/streaming.js +44 -27
- 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 +139 -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 +295 -0
- package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
- package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
- package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
- package/dist/mailbox-ui/assets/index-B-461hes.js +61 -0
- package/dist/mailbox-ui/assets/index-BPr5vNuM.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 +674 -0
- package/dist/mailroom/body-cache.js +61 -0
- package/dist/mailroom/core.js +720 -0
- package/dist/mailroom/entry.js +160 -0
- package/dist/mailroom/file-store.js +430 -0
- package/dist/mailroom/mbox-import.js +383 -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 +256 -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 +7 -1
- package/dist/mind/context.js +165 -101
- package/dist/mind/diary-integrity.js +60 -0
- package/dist/mind/{memory.js → diary.js} +62 -75
- 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 +39 -3
- package/dist/mind/friends/types.js +2 -2
- package/dist/mind/journal-index.js +161 -0
- package/dist/mind/note-search.js +268 -0
- package/dist/mind/obligation-steering.js +221 -0
- package/dist/mind/pending.js +4 -0
- package/dist/mind/prompt-refresh.js +3 -2
- package/dist/mind/prompt.js +1011 -123
- 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 +129 -5
- package/dist/nerves/coverage/run-artifacts.js +1 -1
- 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 +11 -10
- package/dist/repertoire/api-client.js +97 -0
- package/dist/repertoire/bitwarden-store.js +963 -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 +330 -0
- package/dist/repertoire/coding/feedback.js +197 -30
- package/dist/repertoire/coding/manager.js +158 -9
- package/dist/repertoire/coding/spawner.js +55 -9
- package/dist/repertoire/coding/tools.js +170 -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/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 +396 -0
- package/dist/repertoire/mcp-client.js +295 -0
- package/dist/repertoire/mcp-manager.js +362 -0
- package/dist/repertoire/mcp-tools.js +63 -0
- package/dist/repertoire/shell-sessions.js +133 -0
- package/dist/repertoire/skills.js +15 -24
- package/dist/repertoire/stripe-client.js +131 -0
- package/dist/repertoire/tasks/board.js +31 -5
- package/dist/repertoire/tasks/fix.js +182 -0
- package/dist/repertoire/tasks/index.js +16 -4
- package/dist/repertoire/tasks/lifecycle.js +2 -2
- package/dist/repertoire/tasks/parser.js +3 -2
- package/dist/repertoire/tasks/scanner.js +194 -37
- package/dist/repertoire/tasks/transitions.js +16 -78
- package/dist/repertoire/tool-results.js +29 -0
- package/dist/repertoire/tools-attachments.js +317 -0
- package/dist/repertoire/tools-base.js +47 -1075
- package/dist/repertoire/tools-bluebubbles.js +1 -0
- package/dist/repertoire/tools-bridge.js +142 -0
- package/dist/repertoire/tools-bundle.js +984 -0
- package/dist/repertoire/tools-config.js +185 -0
- package/dist/repertoire/tools-continuity.js +248 -0
- package/dist/repertoire/tools-credential.js +381 -0
- package/dist/repertoire/tools-files.js +342 -0
- package/dist/repertoire/tools-flight.js +224 -0
- package/dist/repertoire/tools-flow.js +119 -0
- package/dist/repertoire/tools-github.js +1 -7
- package/dist/repertoire/tools-mail.js +1857 -0
- package/dist/repertoire/tools-notes.js +421 -0
- package/dist/repertoire/tools-session.js +750 -0
- package/dist/repertoire/tools-shell.js +120 -0
- package/dist/repertoire/tools-stripe.js +180 -0
- package/dist/repertoire/tools-surface.js +243 -0
- package/dist/repertoire/tools-teams.js +9 -39
- package/dist/repertoire/tools-travel.js +125 -0
- package/dist/repertoire/tools-trip.js +604 -0
- package/dist/repertoire/tools-user-profile.js +144 -0
- package/dist/repertoire/tools-vault.js +40 -0
- package/dist/repertoire/tools.js +108 -100
- 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 +116 -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 +2305 -0
- package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
- 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/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 +187 -0
- package/dist/senses/cli.js +520 -209
- package/dist/senses/commands.js +66 -3
- package/dist/senses/habit-turn-message.js +108 -0
- package/dist/senses/inner-dialog-worker.js +175 -21
- package/dist/senses/inner-dialog.js +330 -27
- package/dist/senses/mail-entry.js +66 -0
- package/dist/senses/mail.js +379 -0
- package/dist/senses/pipeline.js +549 -181
- package/dist/senses/proactive-content-guard.js +51 -0
- package/dist/senses/shared-turn.js +248 -0
- package/dist/senses/surface-tool.js +68 -0
- package/dist/senses/teams-entry.js +60 -8
- package/dist/senses/teams.js +387 -98
- package/dist/senses/trust-gate.js +100 -5
- package/dist/senses/voice/elevenlabs.js +125 -0
- package/dist/senses/voice/index.js +22 -0
- package/dist/senses/voice/transcript.js +70 -0
- package/dist/senses/voice/turn.js +85 -0
- package/dist/senses/voice/types.js +2 -0
- package/dist/senses/voice/whisper.js +133 -0
- package/dist/senses/voice-entry.js +80 -0
- package/dist/trips/core.js +138 -0
- package/dist/trips/store.js +146 -0
- package/package.json +38 -7
- 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 +101 -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/subagent-installer.js +0 -166
- package/dist/heart/session-recall.js +0 -116
- package/dist/mind/associative-recall.js +0 -209
- 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 -86
- package/subagents/work-doer.md +0 -237
- package/subagents/work-merger.md +0 -618
- package/subagents/work-planner.md +0 -390
- /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/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,342 @@
|
|
|
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.fileToolDefinitions = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const fg = __importStar(require("fast-glob"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const identity_1 = require("../heart/identity");
|
|
41
|
+
const file_state_1 = require("../mind/file-state");
|
|
42
|
+
const scrutiny_1 = require("../mind/scrutiny");
|
|
43
|
+
const tools_base_1 = require("./tools-base");
|
|
44
|
+
function resolveLocalToolPath(targetPath) {
|
|
45
|
+
if (!path.isAbsolute(targetPath)) {
|
|
46
|
+
return path.resolve((0, identity_1.getRepoRoot)(), targetPath);
|
|
47
|
+
}
|
|
48
|
+
return targetPath;
|
|
49
|
+
}
|
|
50
|
+
function buildContextDiff(lines, changeStart, changeEnd, contextSize = 3) {
|
|
51
|
+
const start = Math.max(0, changeStart - contextSize);
|
|
52
|
+
const end = Math.min(lines.length, changeEnd + contextSize);
|
|
53
|
+
const result = [];
|
|
54
|
+
for (let i = start; i < end; i++) {
|
|
55
|
+
const lineNum = i + 1;
|
|
56
|
+
const prefix = (i >= changeStart && i < changeEnd) ? ">" : " ";
|
|
57
|
+
result.push(`${prefix} ${lineNum} | ${lines[i]}`);
|
|
58
|
+
}
|
|
59
|
+
return result.join("\n");
|
|
60
|
+
}
|
|
61
|
+
exports.fileToolDefinitions = [
|
|
62
|
+
{
|
|
63
|
+
tool: {
|
|
64
|
+
type: "function",
|
|
65
|
+
function: {
|
|
66
|
+
name: "read_file",
|
|
67
|
+
description: "Read file contents. Results include line numbers. Use offset/limit for large files -- don't read the whole thing if you only need a section. Use this tool before editing any file. When reading code, read enough context to understand the surrounding logic, not just the target line.",
|
|
68
|
+
parameters: {
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: {
|
|
71
|
+
path: { type: "string" },
|
|
72
|
+
offset: { type: "number", description: "1-based line number to start reading from" },
|
|
73
|
+
limit: { type: "number", description: "maximum number of lines to return" },
|
|
74
|
+
},
|
|
75
|
+
required: ["path"],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
handler: (a) => {
|
|
80
|
+
const resolvedPath = resolveLocalToolPath(a.path);
|
|
81
|
+
const content = fs.readFileSync(resolvedPath, "utf-8");
|
|
82
|
+
tools_base_1.editFileReadTracker.add(resolvedPath);
|
|
83
|
+
const offset = a.offset ? parseInt(a.offset, 10) : undefined;
|
|
84
|
+
const limit = a.limit ? parseInt(a.limit, 10) : undefined;
|
|
85
|
+
// Record in file state cache for staleness detection
|
|
86
|
+
try {
|
|
87
|
+
const mtime = fs.statSync(resolvedPath).mtimeMs;
|
|
88
|
+
const readContent = (offset === undefined && limit === undefined)
|
|
89
|
+
? content
|
|
90
|
+
: content.split("\n").slice(offset ? offset - 1 : 0, limit !== undefined ? (offset ? offset - 1 : 0) + limit : undefined).join("\n");
|
|
91
|
+
file_state_1.fileStateCache.record(resolvedPath, readContent, mtime, offset, limit);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// stat failed -- skip cache recording
|
|
95
|
+
}
|
|
96
|
+
if (offset === undefined && limit === undefined)
|
|
97
|
+
return content;
|
|
98
|
+
const lines = content.split("\n");
|
|
99
|
+
const start = offset ? offset - 1 : 0;
|
|
100
|
+
const end = limit !== undefined ? start + limit : lines.length;
|
|
101
|
+
return lines.slice(start, end).join("\n");
|
|
102
|
+
},
|
|
103
|
+
summaryKeys: ["path"],
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
tool: {
|
|
107
|
+
type: "function",
|
|
108
|
+
function: {
|
|
109
|
+
name: "write_file",
|
|
110
|
+
description: "Prefer this tool for creating new files or fully replacing existing ones. You MUST read an existing file with read_file before overwriting it. Prefer edit_file for modifying existing files -- it only sends the diff. Do not create documentation files (*.md, README) by default; only do so when explicitly asked or when documentation is clearly part of the requested change.",
|
|
111
|
+
parameters: {
|
|
112
|
+
type: "object",
|
|
113
|
+
properties: { path: { type: "string" }, content: { type: "string" } },
|
|
114
|
+
required: ["path", "content"],
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
handler: (a) => {
|
|
119
|
+
const resolvedPath = resolveLocalToolPath(a.path);
|
|
120
|
+
fs.mkdirSync(path.dirname(resolvedPath), { recursive: true });
|
|
121
|
+
fs.writeFileSync(resolvedPath, a.content, "utf-8");
|
|
122
|
+
(0, scrutiny_1.trackModifiedFile)(resolvedPath);
|
|
123
|
+
const scrutiny = (0, scrutiny_1.getPostImplementationScrutiny)((0, scrutiny_1.getModifiedFileCount)());
|
|
124
|
+
/* v8 ignore next -- scrutiny appendix branch depends on session-level file count @preserve */
|
|
125
|
+
return scrutiny ? `ok\n\n${scrutiny}` : "ok";
|
|
126
|
+
},
|
|
127
|
+
summaryKeys: ["path"],
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
tool: {
|
|
131
|
+
type: "function",
|
|
132
|
+
function: {
|
|
133
|
+
name: "edit_file",
|
|
134
|
+
description: "Surgically edit a file by replacing an exact string. The file MUST have been read via read_file first -- this tool will reject the call otherwise. old_string must match EXACTLY ONE location in the file -- if it matches zero or multiple, the edit fails. To fix: provide more surrounding context to make the match unique. Preserve exact indentation (tabs/spaces) from the file. Prefer this over write_file for modifications -- it only sends the diff.",
|
|
135
|
+
parameters: {
|
|
136
|
+
type: "object",
|
|
137
|
+
properties: {
|
|
138
|
+
path: { type: "string" },
|
|
139
|
+
old_string: { type: "string" },
|
|
140
|
+
new_string: { type: "string" },
|
|
141
|
+
},
|
|
142
|
+
required: ["path", "old_string", "new_string"],
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
handler: (a) => {
|
|
147
|
+
const resolvedPath = resolveLocalToolPath(a.path);
|
|
148
|
+
if (!tools_base_1.editFileReadTracker.has(resolvedPath)) {
|
|
149
|
+
return `error: you must read the file with read_file before editing it. call read_file on ${a.path} first.`;
|
|
150
|
+
}
|
|
151
|
+
// Check staleness before editing
|
|
152
|
+
const stalenessCheck = file_state_1.fileStateCache.isStale(resolvedPath);
|
|
153
|
+
let content;
|
|
154
|
+
try {
|
|
155
|
+
content = fs.readFileSync(resolvedPath, "utf-8");
|
|
156
|
+
}
|
|
157
|
+
catch (e) {
|
|
158
|
+
return `error: could not read file: ${e instanceof Error ? e.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(e)}`;
|
|
159
|
+
}
|
|
160
|
+
// Count occurrences
|
|
161
|
+
const occurrences = [];
|
|
162
|
+
let searchFrom = 0;
|
|
163
|
+
while (true) {
|
|
164
|
+
const idx = content.indexOf(a.old_string, searchFrom);
|
|
165
|
+
if (idx === -1)
|
|
166
|
+
break;
|
|
167
|
+
occurrences.push(idx);
|
|
168
|
+
searchFrom = idx + 1;
|
|
169
|
+
}
|
|
170
|
+
if (occurrences.length === 0) {
|
|
171
|
+
return `error: old_string not found in ${a.path}`;
|
|
172
|
+
}
|
|
173
|
+
if (occurrences.length > 1) {
|
|
174
|
+
return `error: old_string is ambiguous -- found ${occurrences.length} matches in ${a.path}. provide more context to make the match unique.`;
|
|
175
|
+
}
|
|
176
|
+
// Single unique match -- replace
|
|
177
|
+
const idx = occurrences[0];
|
|
178
|
+
const updated = content.slice(0, idx) + a.new_string + content.slice(idx + a.old_string.length);
|
|
179
|
+
fs.writeFileSync(resolvedPath, updated, "utf-8");
|
|
180
|
+
// Update file state cache with new content
|
|
181
|
+
try {
|
|
182
|
+
const newMtime = fs.statSync(resolvedPath).mtimeMs;
|
|
183
|
+
file_state_1.fileStateCache.record(resolvedPath, updated, newMtime);
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
// stat failed -- skip cache update
|
|
187
|
+
}
|
|
188
|
+
// Build contextual diff
|
|
189
|
+
const lines = updated.split("\n");
|
|
190
|
+
const prefixLines = content.slice(0, idx).split("\n");
|
|
191
|
+
const changeStartLine = prefixLines.length - 1;
|
|
192
|
+
const newStringLines = a.new_string.split("\n");
|
|
193
|
+
const changeEndLine = changeStartLine + newStringLines.length;
|
|
194
|
+
const diffResult = buildContextDiff(lines, changeStartLine, changeEndLine);
|
|
195
|
+
// Track modified file and compute scrutiny appendix
|
|
196
|
+
(0, scrutiny_1.trackModifiedFile)(resolvedPath);
|
|
197
|
+
const scrutiny = (0, scrutiny_1.getPostImplementationScrutiny)((0, scrutiny_1.getModifiedFileCount)());
|
|
198
|
+
// Append staleness warning if detected (do not block -- TTFA)
|
|
199
|
+
/* v8 ignore start -- staleness+diff+scrutiny combo not exercised in integration tests @preserve */
|
|
200
|
+
if (stalenessCheck.stale) {
|
|
201
|
+
const base = `${diffResult}\n\n⚠️ warning: file changed externally since last read -- re-read recommended`;
|
|
202
|
+
return scrutiny ? `${base}\n\n${scrutiny}` : base;
|
|
203
|
+
}
|
|
204
|
+
/* v8 ignore stop */
|
|
205
|
+
/* v8 ignore next -- scrutiny appendix branch depends on session-level file count @preserve */
|
|
206
|
+
return scrutiny ? `${diffResult}\n\n${scrutiny}` : diffResult;
|
|
207
|
+
},
|
|
208
|
+
summaryKeys: ["path"],
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
tool: {
|
|
212
|
+
type: "function",
|
|
213
|
+
function: {
|
|
214
|
+
name: "glob",
|
|
215
|
+
description: "Find files matching a glob pattern, sorted alphabetically. Use this instead of shell commands like `find` or `ls`. For broad exploratory searches that would require multiple rounds of globbing and grepping, consider using claude or coding_spawn.",
|
|
216
|
+
parameters: {
|
|
217
|
+
type: "object",
|
|
218
|
+
properties: {
|
|
219
|
+
pattern: { type: "string", description: "glob pattern (e.g. **/*.ts)" },
|
|
220
|
+
cwd: { type: "string", description: "directory to search from (defaults to process.cwd())" },
|
|
221
|
+
},
|
|
222
|
+
required: ["pattern"],
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
handler: (a) => {
|
|
227
|
+
const cwd = a.cwd ? resolveLocalToolPath(a.cwd) : process.cwd();
|
|
228
|
+
const matches = fg.globSync(a.pattern, { cwd, dot: true });
|
|
229
|
+
return matches.sort().join("\n");
|
|
230
|
+
},
|
|
231
|
+
summaryKeys: ["pattern", "cwd"],
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
tool: {
|
|
235
|
+
type: "function",
|
|
236
|
+
function: {
|
|
237
|
+
name: "grep",
|
|
238
|
+
description: "Search file contents for lines matching a regex pattern. Searches recursively in directories. Use this instead of shell commands like `grep` or `rg`. Returns matching lines with file path and line numbers. Use context_lines for surrounding context. Use include to filter file types (e.g., '*.ts').",
|
|
239
|
+
parameters: {
|
|
240
|
+
type: "object",
|
|
241
|
+
properties: {
|
|
242
|
+
pattern: { type: "string", description: "regex pattern to search for" },
|
|
243
|
+
path: { type: "string", description: "file or directory to search" },
|
|
244
|
+
context_lines: { type: "number", description: "number of surrounding context lines (default 0)" },
|
|
245
|
+
include: { type: "string", description: "glob filter to limit searched files (e.g. *.ts)" },
|
|
246
|
+
},
|
|
247
|
+
required: ["pattern", "path"],
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
handler: (a) => {
|
|
252
|
+
const targetPath = resolveLocalToolPath(a.path);
|
|
253
|
+
const regex = new RegExp(a.pattern);
|
|
254
|
+
const contextLines = parseInt(a.context_lines || "0", 10);
|
|
255
|
+
const includeGlob = a.include || undefined;
|
|
256
|
+
function searchFile(filePath) {
|
|
257
|
+
let content;
|
|
258
|
+
try {
|
|
259
|
+
content = fs.readFileSync(filePath, "utf-8");
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
return [];
|
|
263
|
+
}
|
|
264
|
+
const lines = content.split("\n");
|
|
265
|
+
const matchIndices = new Set();
|
|
266
|
+
for (let i = 0; i < lines.length; i++) {
|
|
267
|
+
if (regex.test(lines[i])) {
|
|
268
|
+
matchIndices.add(i);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (matchIndices.size === 0)
|
|
272
|
+
return [];
|
|
273
|
+
const outputIndices = new Set();
|
|
274
|
+
for (const idx of matchIndices) {
|
|
275
|
+
const start = Math.max(0, idx - contextLines);
|
|
276
|
+
const end = Math.min(lines.length - 1, idx + contextLines);
|
|
277
|
+
for (let i = start; i <= end; i++) {
|
|
278
|
+
outputIndices.add(i);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
const sortedIndices = [...outputIndices].sort((a, b) => a - b);
|
|
282
|
+
const results = [];
|
|
283
|
+
for (const idx of sortedIndices) {
|
|
284
|
+
const lineNum = idx + 1;
|
|
285
|
+
if (matchIndices.has(idx)) {
|
|
286
|
+
results.push(`${filePath}:${lineNum}: ${lines[idx]}`);
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
results.push(`-${filePath}:${lineNum}: ${lines[idx]}`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return results;
|
|
293
|
+
}
|
|
294
|
+
function collectFiles(dirPath) {
|
|
295
|
+
const files = [];
|
|
296
|
+
function walk(dir) {
|
|
297
|
+
let entries;
|
|
298
|
+
try {
|
|
299
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
for (const entry of entries) {
|
|
305
|
+
const fullPath = path.join(dir, entry.name);
|
|
306
|
+
if (entry.isDirectory()) {
|
|
307
|
+
walk(fullPath);
|
|
308
|
+
}
|
|
309
|
+
else if (entry.isFile()) {
|
|
310
|
+
files.push(fullPath);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
walk(dirPath);
|
|
315
|
+
return files.sort();
|
|
316
|
+
}
|
|
317
|
+
function matchesGlob(filePath, glob) {
|
|
318
|
+
const escaped = glob
|
|
319
|
+
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
|
|
320
|
+
.replace(/\*/g, ".*")
|
|
321
|
+
.replace(/\?/g, ".");
|
|
322
|
+
return new RegExp(`(^|/)${escaped}$`).test(filePath);
|
|
323
|
+
}
|
|
324
|
+
const stat = fs.statSync(targetPath, { throwIfNoEntry: false });
|
|
325
|
+
if (!stat)
|
|
326
|
+
return "";
|
|
327
|
+
if (stat.isFile()) {
|
|
328
|
+
return searchFile(targetPath).join("\n");
|
|
329
|
+
}
|
|
330
|
+
let files = collectFiles(targetPath);
|
|
331
|
+
if (includeGlob) {
|
|
332
|
+
files = files.filter((f) => matchesGlob(f, includeGlob));
|
|
333
|
+
}
|
|
334
|
+
const allResults = [];
|
|
335
|
+
for (const file of files) {
|
|
336
|
+
allResults.push(...searchFile(file));
|
|
337
|
+
}
|
|
338
|
+
return allResults.join("\n");
|
|
339
|
+
},
|
|
340
|
+
summaryKeys: ["pattern", "path", "include"],
|
|
341
|
+
},
|
|
342
|
+
];
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.flightToolDefinitions = void 0;
|
|
4
|
+
exports.resetDuffelClient = resetDuffelClient;
|
|
5
|
+
const duffel_client_1 = require("./duffel-client");
|
|
6
|
+
const user_profile_1 = require("./user-profile");
|
|
7
|
+
const credential_access_1 = require("./credential-access");
|
|
8
|
+
const runtime_1 = require("../nerves/runtime");
|
|
9
|
+
// Lazy-initialized Duffel client singleton
|
|
10
|
+
let _duffelClient = null;
|
|
11
|
+
async function getDuffelClient() {
|
|
12
|
+
if (!_duffelClient) {
|
|
13
|
+
_duffelClient = await (0, duffel_client_1.createDuffelClient)();
|
|
14
|
+
}
|
|
15
|
+
return _duffelClient;
|
|
16
|
+
}
|
|
17
|
+
function requireFamilyContext(ctx) {
|
|
18
|
+
if (!ctx?.context?.friend?.id) {
|
|
19
|
+
return "no friend context — cannot access flight tools.";
|
|
20
|
+
}
|
|
21
|
+
if (ctx.context.friend.trustLevel !== "family") {
|
|
22
|
+
return "booking and cancellation require family trust level.";
|
|
23
|
+
}
|
|
24
|
+
return { friendId: ctx.context.friend.id };
|
|
25
|
+
}
|
|
26
|
+
function requireFriendContext(ctx) {
|
|
27
|
+
if (!ctx?.context?.friend?.id) {
|
|
28
|
+
return "no friend context — cannot search flights.";
|
|
29
|
+
}
|
|
30
|
+
return { friendId: ctx.context.friend.id };
|
|
31
|
+
}
|
|
32
|
+
exports.flightToolDefinitions = [
|
|
33
|
+
{
|
|
34
|
+
tool: {
|
|
35
|
+
type: "function",
|
|
36
|
+
function: {
|
|
37
|
+
name: "flight_search",
|
|
38
|
+
description: "Search for flights between two airports. Returns available offers with prices.",
|
|
39
|
+
parameters: {
|
|
40
|
+
type: "object",
|
|
41
|
+
properties: {
|
|
42
|
+
origin: { type: "string", description: "Origin airport IATA code (e.g. 'SFO')" },
|
|
43
|
+
destination: { type: "string", description: "Destination airport IATA code (e.g. 'JFK')" },
|
|
44
|
+
departure_date: { type: "string", description: "Departure date (YYYY-MM-DD)" },
|
|
45
|
+
return_date: { type: "string", description: "Return date for round trips (optional)" },
|
|
46
|
+
passengers: { type: "string", description: "Number of adult passengers (default '1')" },
|
|
47
|
+
cabin_class: { type: "string", description: "Cabin class: economy, premium_economy, business, first" },
|
|
48
|
+
},
|
|
49
|
+
required: ["origin", "destination", "departure_date"],
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
handler: async (args, ctx) => {
|
|
54
|
+
(0, runtime_1.emitNervesEvent)({
|
|
55
|
+
component: "repertoire",
|
|
56
|
+
event: "repertoire.tool_flight_search",
|
|
57
|
+
message: "flight_search invoked",
|
|
58
|
+
meta: { tool: "flight_search", origin: args.origin, destination: args.destination },
|
|
59
|
+
});
|
|
60
|
+
const guard = requireFriendContext(ctx);
|
|
61
|
+
if (typeof guard === "string")
|
|
62
|
+
return guard;
|
|
63
|
+
try {
|
|
64
|
+
const client = await getDuffelClient();
|
|
65
|
+
const passengerCount = parseInt(args.passengers || "1", 10);
|
|
66
|
+
const passengers = Array.from({ length: passengerCount }, () => ({ type: "adult" }));
|
|
67
|
+
const offers = await client.searchFlights({
|
|
68
|
+
origin: args.origin,
|
|
69
|
+
destination: args.destination,
|
|
70
|
+
departureDate: args.departure_date,
|
|
71
|
+
returnDate: args.return_date,
|
|
72
|
+
passengers,
|
|
73
|
+
cabinClass: args.cabin_class,
|
|
74
|
+
});
|
|
75
|
+
if (offers.length === 0) {
|
|
76
|
+
return "no flights found for those criteria.";
|
|
77
|
+
}
|
|
78
|
+
return JSON.stringify(offers, null, 2);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
/* v8 ignore next -- defensive @preserve */
|
|
82
|
+
return `flight search error: ${err instanceof Error ? err.message : String(err)}`;
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
summaryKeys: ["origin", "destination", "departure_date"],
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
tool: {
|
|
89
|
+
type: "function",
|
|
90
|
+
function: {
|
|
91
|
+
name: "flight_hold",
|
|
92
|
+
description: "Hold a flight offer for a short period before committing to book. Not all airlines support holds.",
|
|
93
|
+
parameters: {
|
|
94
|
+
type: "object",
|
|
95
|
+
properties: {
|
|
96
|
+
offer_id: { type: "string", description: "The Duffel offer ID to hold" },
|
|
97
|
+
},
|
|
98
|
+
required: ["offer_id"],
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
handler: async (args, ctx) => {
|
|
103
|
+
(0, runtime_1.emitNervesEvent)({
|
|
104
|
+
component: "repertoire",
|
|
105
|
+
event: "repertoire.tool_flight_hold",
|
|
106
|
+
message: "flight_hold invoked",
|
|
107
|
+
meta: { tool: "flight_hold", offerId: args.offer_id },
|
|
108
|
+
});
|
|
109
|
+
const guard = requireFamilyContext(ctx);
|
|
110
|
+
if (typeof guard === "string")
|
|
111
|
+
return guard;
|
|
112
|
+
// Hold functionality would call Duffel's offer hold API.
|
|
113
|
+
// For pre-build, we return a structured acknowledgment.
|
|
114
|
+
return JSON.stringify({
|
|
115
|
+
status: "hold_requested",
|
|
116
|
+
offerId: args.offer_id,
|
|
117
|
+
message: "Hold requested. Confirm or cancel before the hold expires.",
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
summaryKeys: ["offer_id"],
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
tool: {
|
|
124
|
+
type: "function",
|
|
125
|
+
function: {
|
|
126
|
+
name: "flight_book",
|
|
127
|
+
description: "Book a flight. Pulls passenger name/DOB/passport from the user's profile. Creates a virtual card, books the flight, then deactivates the card. Requires family trust level.",
|
|
128
|
+
parameters: {
|
|
129
|
+
type: "object",
|
|
130
|
+
properties: {
|
|
131
|
+
offer_id: { type: "string", description: "The Duffel offer ID to book" },
|
|
132
|
+
amount: { type: "string", description: "Expected total amount in dollars" },
|
|
133
|
+
currency: { type: "string", description: "Currency code (e.g. 'usd')" },
|
|
134
|
+
},
|
|
135
|
+
required: ["offer_id", "amount", "currency"],
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
handler: async (args, ctx) => {
|
|
140
|
+
(0, runtime_1.emitNervesEvent)({
|
|
141
|
+
component: "repertoire",
|
|
142
|
+
event: "repertoire.tool_flight_book",
|
|
143
|
+
message: "flight_book invoked",
|
|
144
|
+
meta: { tool: "flight_book", offerId: args.offer_id },
|
|
145
|
+
});
|
|
146
|
+
const guard = requireFamilyContext(ctx);
|
|
147
|
+
if (typeof guard === "string")
|
|
148
|
+
return guard;
|
|
149
|
+
try {
|
|
150
|
+
const store = (0, credential_access_1.getCredentialStore)();
|
|
151
|
+
// Get passenger data from profile
|
|
152
|
+
const legalName = await (0, user_profile_1.getUserProfileField)(guard.friendId, "legalName", store);
|
|
153
|
+
if (!legalName) {
|
|
154
|
+
return "passenger profile not found — please store your profile first using user_profile_store.";
|
|
155
|
+
}
|
|
156
|
+
const dateOfBirth = await (0, user_profile_1.getUserProfileField)(guard.friendId, "dateOfBirth", store);
|
|
157
|
+
const passport = await (0, user_profile_1.getUserProfileField)(guard.friendId, "passport", store);
|
|
158
|
+
const client = await getDuffelClient();
|
|
159
|
+
const result = await client.createOrder({
|
|
160
|
+
offerId: args.offer_id,
|
|
161
|
+
passengers: [{
|
|
162
|
+
type: "adult",
|
|
163
|
+
givenName: legalName.first,
|
|
164
|
+
familyName: legalName.last,
|
|
165
|
+
/* v8 ignore next -- reason @preserve */
|
|
166
|
+
dateOfBirth: dateOfBirth ?? "1990-01-01",
|
|
167
|
+
passportNumber: passport?.number,
|
|
168
|
+
passportCountry: passport?.country,
|
|
169
|
+
passportExpiry: passport?.expiry,
|
|
170
|
+
}],
|
|
171
|
+
amount: parseFloat(args.amount),
|
|
172
|
+
currency: args.currency,
|
|
173
|
+
});
|
|
174
|
+
return JSON.stringify(result, null, 2);
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
/* v8 ignore next -- defensive @preserve */
|
|
178
|
+
return `booking error: ${err instanceof Error ? err.message : String(err)}`;
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
summaryKeys: ["offer_id", "amount"],
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
tool: {
|
|
185
|
+
type: "function",
|
|
186
|
+
function: {
|
|
187
|
+
name: "flight_cancel",
|
|
188
|
+
description: "Cancel a flight booking. Not all bookings are cancellable. Requires family trust level.",
|
|
189
|
+
parameters: {
|
|
190
|
+
type: "object",
|
|
191
|
+
properties: {
|
|
192
|
+
order_id: { type: "string", description: "The Duffel order ID to cancel" },
|
|
193
|
+
},
|
|
194
|
+
required: ["order_id"],
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
handler: async (args, ctx) => {
|
|
199
|
+
(0, runtime_1.emitNervesEvent)({
|
|
200
|
+
component: "repertoire",
|
|
201
|
+
event: "repertoire.tool_flight_cancel",
|
|
202
|
+
message: "flight_cancel invoked",
|
|
203
|
+
meta: { tool: "flight_cancel", orderId: args.order_id },
|
|
204
|
+
});
|
|
205
|
+
const guard = requireFamilyContext(ctx);
|
|
206
|
+
if (typeof guard === "string")
|
|
207
|
+
return guard;
|
|
208
|
+
try {
|
|
209
|
+
const client = await getDuffelClient();
|
|
210
|
+
const result = await client.cancelOrder(args.order_id);
|
|
211
|
+
return JSON.stringify(result, null, 2);
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
/* v8 ignore next -- defensive @preserve */
|
|
215
|
+
return `cancellation error: ${err instanceof Error ? err.message : String(err)}`;
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
summaryKeys: ["order_id"],
|
|
219
|
+
},
|
|
220
|
+
];
|
|
221
|
+
/** Reset the Duffel client singleton (for testing). */
|
|
222
|
+
function resetDuffelClient() {
|
|
223
|
+
_duffelClient = null;
|
|
224
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.restTool = exports.speakTool = exports.settleTool = exports.observeTool = exports.ponderTool = void 0;
|
|
4
|
+
exports.ponderTool = {
|
|
5
|
+
type: "function",
|
|
6
|
+
function: {
|
|
7
|
+
name: "ponder",
|
|
8
|
+
description: "create or revise a typed ponder packet so i don't lose the plot while i keep working. use this for harness friction, research, or reflection that should survive the current turn. ponder does not end the turn, does not defer the response by itself, and may be followed by more tools before i settle or rest. Don't ponder trivial questions.",
|
|
9
|
+
parameters: {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
action: {
|
|
13
|
+
type: "string",
|
|
14
|
+
enum: ["create", "revise"],
|
|
15
|
+
description: "create a new packet or revise an existing drafting packet.",
|
|
16
|
+
},
|
|
17
|
+
kind: {
|
|
18
|
+
type: "string",
|
|
19
|
+
enum: ["harness_friction", "research", "reflection"],
|
|
20
|
+
description: "the packet kind. determines the SOP the inner session should follow.",
|
|
21
|
+
},
|
|
22
|
+
packet_id: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "required for action=revise. the packet to revise in place.",
|
|
25
|
+
},
|
|
26
|
+
follows_packet_id: {
|
|
27
|
+
type: "string",
|
|
28
|
+
description: "optional follow-up linkage when a new packet grows out of an earlier one.",
|
|
29
|
+
},
|
|
30
|
+
objective: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description: "the durable objective for this packet.",
|
|
33
|
+
},
|
|
34
|
+
summary: {
|
|
35
|
+
type: "string",
|
|
36
|
+
description: "brief factual summary of the work object or friction being preserved.",
|
|
37
|
+
},
|
|
38
|
+
success_criteria: {
|
|
39
|
+
type: "string",
|
|
40
|
+
description: "newline-delimited success criteria bullets.",
|
|
41
|
+
},
|
|
42
|
+
payload_json: {
|
|
43
|
+
type: "string",
|
|
44
|
+
description: "JSON object string with packet-specific structured details. use {} when empty.",
|
|
45
|
+
},
|
|
46
|
+
thought: {
|
|
47
|
+
type: "string",
|
|
48
|
+
description: "deprecated compatibility field. legacy thought text is normalized into a reflection packet.",
|
|
49
|
+
},
|
|
50
|
+
say: {
|
|
51
|
+
type: "string",
|
|
52
|
+
description: "deprecated compatibility field. retained for migration only; it no longer controls deferral or silence.",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
exports.observeTool = {
|
|
59
|
+
type: "function",
|
|
60
|
+
function: {
|
|
61
|
+
name: "observe",
|
|
62
|
+
description: "absorb what happened without responding — the moment doesn't call for words. must be the only tool call in the turn.",
|
|
63
|
+
parameters: {
|
|
64
|
+
type: "object",
|
|
65
|
+
properties: {
|
|
66
|
+
reason: { type: "string", description: "brief reason for staying silent (for logging)" },
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
exports.settleTool = {
|
|
72
|
+
type: "function",
|
|
73
|
+
function: {
|
|
74
|
+
name: "settle",
|
|
75
|
+
description: "deliver your response and end your turn — this hands control back to the user. only settle when your work is complete, you're genuinely blocked, or the user asked a direct question that needs an answer now. do not settle with status updates mid-task. if you're settling with 'I'll look into that,' you probably should be using a tool instead.",
|
|
76
|
+
parameters: {
|
|
77
|
+
type: "object",
|
|
78
|
+
properties: {
|
|
79
|
+
answer: { type: "string" },
|
|
80
|
+
intent: { type: "string", enum: ["complete", "blocked", "direct_reply"] },
|
|
81
|
+
},
|
|
82
|
+
required: ["answer"],
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
exports.speakTool = {
|
|
87
|
+
type: "function",
|
|
88
|
+
function: {
|
|
89
|
+
name: "speak",
|
|
90
|
+
description: "i speak to send words to my friend mid-turn without ending it. for progress, acknowledgment, or phase-boundary updates during heavy work. i settle when my work is done or i need a reply. speak is one-way: my friend cannot steer me mid-turn after i speak.",
|
|
91
|
+
parameters: {
|
|
92
|
+
type: "object",
|
|
93
|
+
properties: {
|
|
94
|
+
message: { type: "string", description: "the words i'm sending to my friend right now" },
|
|
95
|
+
},
|
|
96
|
+
required: ["message"],
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
exports.restTool = {
|
|
101
|
+
type: "function",
|
|
102
|
+
function: {
|
|
103
|
+
name: "rest",
|
|
104
|
+
description: "end an inner-session turn when i'm done thinking. rest remains the explicit terminal move for the inner session and must be the only tool call in the turn. on idle heartbeat turns, use status=HEARTBEAT_OK.",
|
|
105
|
+
parameters: {
|
|
106
|
+
type: "object",
|
|
107
|
+
properties: {
|
|
108
|
+
status: {
|
|
109
|
+
type: "string",
|
|
110
|
+
description: "optional rest status. use HEARTBEAT_OK when the heartbeat fires and there is nothing to do.",
|
|
111
|
+
},
|
|
112
|
+
note: {
|
|
113
|
+
type: "string",
|
|
114
|
+
description: "optional brief note about why i'm resting.",
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
};
|