@ouro.bot/cli 0.1.0-alpha.99 → 0.1.0-alpha.991
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +171 -23
- package/RepairGuide.ouro/agent.json +5 -0
- package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
- package/RepairGuide.ouro/psyche/SOUL.md +55 -0
- package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
- package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
- package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
- package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
- package/assets/bluebubbles-host +264 -0
- package/assets/sanctuary-host-launcher.sh +16 -0
- package/changelog.json +6257 -16
- package/deploy/unraid/Dockerfile +71 -0
- package/deploy/unraid/INSTALL.md +64 -0
- package/deploy/unraid/README.txt +3032 -0
- package/deploy/unraid/audit-container-spec.sh +4 -0
- package/deploy/unraid/container-runtime.json +1 -0
- package/deploy/unraid/credit-gateway.md +95 -0
- package/deploy/unraid/docker-man-template-transaction.mjs +727 -0
- package/deploy/unraid/docker-man-template-xml.cjs +105 -0
- package/deploy/unraid/github_known_hosts +3 -0
- package/deploy/unraid/install.sh +274 -0
- package/deploy/unraid/migrate-sanctuary-bundle.mjs +63 -0
- package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
- package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
- package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
- package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
- package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
- package/deploy/unraid/ouro-sync-ssh +98 -0
- package/deploy/unraid/ouro-sync.sudoers +3 -0
- package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
- package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
- package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
- package/deploy/unraid/sanctuary-authority-installation.json +36 -0
- package/deploy/unraid/sanctuary-authority-service.sh +30 -0
- package/deploy/unraid/sanctuary-butler-upgrade.mjs +1523 -0
- package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
- package/deploy/unraid/sanctuary-replay-gate.mjs +2467 -0
- package/deploy/unraid/sanctuary-safe-rename.py +24 -0
- package/deploy/unraid/sanctuary-sync-cutover.sh +1039 -0
- package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2088 -0
- package/deploy/unraid/sanctuary-unit16-run.sh +570 -0
- package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
- package/deploy/unraid/sanctuary.ouro/agent.json +67 -0
- package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
- package/deploy/unraid/sanctuary.ouro/awaiting/house-care-sweep.md +17 -0
- package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
- package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
- package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +2255 -0
- package/deploy/unraid/sanctuary.ouro/product/PRODUCT.md +13 -0
- package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
- package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
- package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +7 -0
- package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +7 -0
- package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +15 -0
- package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +3 -0
- package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
- package/deploy/unraid/sanctuary.ouro/tool-profiles.json +234 -0
- package/deploy/unraid/sanctuary.xml +30 -0
- package/dist/a2a/card.js +57 -0
- package/dist/a2a/client.js +290 -0
- package/dist/a2a/config.js +50 -0
- package/dist/a2a/delegated-command-grants.js +93 -0
- package/dist/a2a/delegated-command.js +197 -0
- package/dist/a2a/delegation-stores.js +56 -0
- package/dist/a2a/did-resolution.js +205 -0
- package/dist/a2a/escalation-grants.js +84 -0
- package/dist/a2a/escalation-wiring.js +60 -0
- package/dist/a2a/identity.js +258 -0
- package/dist/a2a/inbound-share.js +131 -0
- package/dist/a2a/mission-result-wire.js +265 -0
- package/dist/a2a/onboarding.js +133 -0
- package/dist/a2a/operator-trust.js +399 -0
- package/dist/a2a/outbox-client.js +59 -0
- package/dist/a2a/outbox-store.js +188 -0
- package/dist/a2a/outbox-wire.js +106 -0
- package/dist/a2a/pin-store.js +167 -0
- package/dist/a2a/refusals.js +53 -0
- package/dist/a2a/relay-client.js +106 -0
- package/dist/a2a/relay-config-vault.js +64 -0
- package/dist/a2a/relay-contacts.js +120 -0
- package/dist/a2a/relay-inbox.js +360 -0
- package/dist/a2a/relay-retirements.js +89 -0
- package/dist/a2a/replay-grant-holders.js +33 -0
- package/dist/a2a/replay-harness.js +188 -0
- package/dist/a2a/resolution-proof.js +53 -0
- package/dist/a2a/sealed-chat.js +114 -0
- package/dist/a2a/seen-ledger.js +214 -0
- package/dist/a2a/server.js +808 -0
- package/dist/a2a/task-store.js +69 -0
- package/dist/a2a/transport.js +100 -0
- package/dist/a2a/trust-commands.js +203 -0
- package/dist/a2a/trusted-files.js +185 -0
- package/dist/a2a/types.js +3 -0
- package/dist/arc/attention-types.js +8 -0
- package/dist/arc/cares.js +360 -0
- package/dist/arc/episodes.js +118 -0
- package/dist/arc/evolution.js +490 -0
- package/dist/arc/flight-recorder.js +1034 -0
- package/dist/arc/intentions.js +134 -0
- package/dist/arc/json-store.js +117 -0
- package/dist/arc/obligations.js +386 -0
- package/dist/arc/packets.js +336 -0
- package/dist/arc/presence.js +185 -0
- package/dist/arc/task-lifecycle.js +57 -0
- package/dist/commerce/store.js +755 -0
- package/dist/commerce/types.js +3 -0
- package/dist/gateway/keys.js +117 -0
- package/dist/gateway/server.js +429 -0
- package/dist/heart/active-work.js +798 -40
- package/dist/heart/agent-entry.js +252 -3
- package/dist/heart/approval-files.js +113 -0
- package/dist/heart/approval-store.js +960 -0
- package/dist/heart/attachments/image-normalize.js +201 -0
- package/dist/heart/attachments/materialize.js +97 -0
- package/dist/heart/attachments/originals.js +88 -0
- package/dist/heart/attachments/render.js +29 -0
- package/dist/heart/attachments/sources/bluebubbles.js +156 -0
- package/dist/heart/attachments/sources/cli-local-file.js +78 -0
- package/dist/heart/attachments/sources/index.js +18 -0
- package/dist/heart/attachments/sources/telegram.js +71 -0
- package/dist/heart/attachments/store.js +132 -0
- package/dist/heart/attachments/types.js +93 -0
- package/dist/heart/auth/auth-flow.js +511 -0
- package/dist/heart/autonomy-budget.js +478 -0
- package/dist/heart/awaiting/a2a-await-delivery.js +109 -0
- package/dist/heart/awaiting/await-alert.js +152 -0
- package/dist/heart/awaiting/await-expiry.js +143 -0
- package/dist/heart/awaiting/await-loader.js +91 -0
- package/dist/heart/awaiting/await-parser.js +152 -0
- package/dist/heart/awaiting/await-runtime-state.js +130 -0
- package/dist/heart/awaiting/await-scheduler.js +391 -0
- package/dist/heart/background-operations.js +281 -0
- package/dist/heart/bluebubbles-host-account.js +78 -0
- package/dist/heart/bridges/manager.js +137 -17
- package/dist/heart/bridges/store.js +14 -2
- package/dist/heart/bundle-state.js +168 -0
- package/dist/heart/commitments.js +44 -18
- package/dist/heart/config-registry.js +331 -0
- package/dist/heart/config.js +179 -131
- package/dist/heart/context-loss-gauntlet.js +387 -0
- package/dist/heart/context-loss-sentinel.js +1204 -0
- package/dist/heart/core.js +2378 -586
- package/dist/heart/cross-chat-delivery.js +9 -22
- package/dist/heart/daemon/agent-config-check.js +474 -0
- package/dist/heart/daemon/agent-discovery.js +287 -3
- package/dist/heart/daemon/agent-home.js +355 -0
- package/dist/heart/daemon/agent-service.js +542 -0
- package/dist/heart/daemon/agentic-repair.js +547 -0
- package/dist/heart/daemon/await-private-wake.js +59 -0
- package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
- package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
- package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
- package/dist/heart/daemon/bluebubbles-host.js +273 -0
- package/dist/heart/daemon/boot-sync-probe.js +223 -0
- package/dist/heart/daemon/cadence.js +180 -0
- package/dist/heart/daemon/cli-arg-redaction.js +26 -0
- package/dist/heart/daemon/cli-defaults.js +881 -0
- package/dist/heart/daemon/cli-desk.js +331 -0
- package/dist/heart/daemon/cli-exec.js +9339 -0
- package/dist/heart/daemon/cli-help.js +766 -0
- package/dist/heart/daemon/cli-parse.js +3343 -0
- package/dist/heart/daemon/cli-render-doctor.js +57 -0
- package/dist/heart/daemon/cli-render.js +819 -0
- package/dist/heart/daemon/cli-types.js +8 -0
- package/dist/heart/daemon/connect-bay.js +323 -0
- package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
- package/dist/heart/daemon/container-healthcheck.js +112 -0
- package/dist/heart/daemon/container-runtime.js +97 -0
- package/dist/heart/daemon/container-spec-auditor-main.js +187 -0
- package/dist/heart/daemon/container-spec-auditor.js +257 -0
- package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
- package/dist/heart/daemon/daemon-cli.js +29 -2373
- package/dist/heart/daemon/daemon-entry.js +975 -11
- package/dist/heart/daemon/daemon-health.js +186 -0
- package/dist/heart/daemon/daemon-rollup.js +57 -0
- package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
- package/dist/heart/daemon/daemon-tombstone.js +236 -0
- package/dist/heart/daemon/daemon.js +2110 -104
- package/dist/heart/daemon/desk-admin.js +420 -0
- package/dist/heart/daemon/dns-workflow.js +394 -0
- package/dist/heart/daemon/doctor-types.js +8 -0
- package/dist/heart/daemon/doctor.js +1766 -0
- package/dist/heart/daemon/freshness.js +345 -0
- package/dist/heart/daemon/habit-private-wake.js +61 -0
- package/dist/heart/daemon/health-monitor.js +154 -11
- package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
- package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
- package/dist/heart/daemon/http-health-probe.js +80 -0
- package/dist/heart/daemon/human-command-screens.js +234 -0
- package/dist/heart/daemon/human-readiness.js +114 -0
- package/dist/heart/daemon/inner-status.js +78 -0
- package/dist/heart/daemon/interactive-repair.js +394 -0
- package/dist/heart/daemon/launchd.js +37 -8
- package/dist/heart/daemon/log-tailer.js +79 -10
- package/dist/heart/daemon/logs-prune.js +132 -0
- package/dist/heart/daemon/mcp-canary.js +524 -0
- package/dist/heart/daemon/message-router.js +65 -5
- package/dist/heart/daemon/migrate-to-desk.js +848 -0
- package/dist/heart/daemon/os-cron-deps.js +135 -0
- package/dist/heart/daemon/os-cron.js +22 -14
- package/dist/heart/daemon/ouro-bot-entry.js +6 -3
- package/dist/heart/daemon/ouro-entry.js +9 -3
- package/dist/heart/daemon/plugin-cli.js +432 -0
- package/dist/heart/daemon/process-manager.js +760 -61
- package/dist/heart/daemon/provider-discovery.js +137 -0
- package/dist/heart/daemon/provider-ping-progress.js +83 -0
- package/dist/heart/daemon/prunable-bundle.js +144 -0
- package/dist/heart/daemon/pulse.js +511 -0
- package/dist/heart/daemon/readiness-repair.js +365 -0
- package/dist/heart/daemon/run-hooks.js +2 -0
- package/dist/heart/daemon/runtime-logging.js +47 -14
- package/dist/heart/daemon/runtime-metadata.js +2 -30
- package/dist/heart/daemon/runtime-mode.js +13 -2
- package/dist/heart/daemon/safe-mode.js +161 -0
- package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2662 -0
- package/dist/heart/daemon/sanctuary-acceptance-harness.js +1832 -0
- package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
- package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +956 -0
- package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
- package/dist/heart/daemon/sanctuary-authority-epoch.js +291 -0
- package/dist/heart/daemon/sanctuary-authority-installation.js +161 -0
- package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
- package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +1332 -0
- package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
- package/dist/heart/daemon/sanctuary-bundle-migration.js +974 -0
- package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
- package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +493 -0
- package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
- package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
- package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
- package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
- package/dist/heart/daemon/sanctuary-package-management.js +113 -0
- package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
- package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
- package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +475 -0
- package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
- package/dist/heart/daemon/sanctuary-telegram-authority-service.js +676 -0
- package/dist/heart/daemon/sense-manager.js +786 -48
- package/dist/heart/daemon/session-id-resolver.js +131 -0
- package/dist/heart/daemon/skill-management-installer.js +1 -1
- package/dist/heart/daemon/socket-client.js +180 -12
- package/dist/heart/daemon/stale-bundle-prune.js +113 -0
- package/dist/heart/daemon/startup-tui.js +339 -0
- package/dist/heart/daemon/supercronic-supervisor.js +282 -0
- package/dist/heart/daemon/task-scheduler.js +117 -39
- package/dist/heart/daemon/terminal-ui.js +503 -0
- package/dist/heart/daemon/thoughts.js +138 -54
- package/dist/heart/daemon/up-progress.js +366 -0
- package/dist/heart/daemon/vault-items.js +56 -0
- package/dist/heart/delegation.js +1 -4
- package/dist/heart/external-events/router.js +1531 -0
- package/dist/heart/failure-reports.js +336 -0
- package/dist/heart/file-lock.js +109 -0
- package/dist/heart/frontend-approval-runtime.js +506 -0
- package/dist/heart/frontend-journal.js +215 -0
- package/dist/heart/frontend-session-service.js +271 -0
- package/dist/heart/frontend-socket-client.js +173 -0
- package/dist/heart/frontend-socket.js +434 -0
- package/dist/heart/frontend-turn-errors.js +20 -0
- package/dist/heart/habits/habit-cancel.js +810 -0
- package/dist/heart/habits/habit-lifecycle.js +1327 -0
- package/dist/heart/habits/habit-migration.js +194 -0
- package/dist/heart/habits/habit-parser.js +278 -0
- package/dist/heart/habits/habit-runtime-state.js +93 -0
- package/dist/heart/habits/habit-scheduler.js +653 -0
- package/dist/heart/habits/habit-session-summary.js +318 -0
- package/dist/heart/habits/habit-session.js +636 -0
- package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
- package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
- package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
- package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
- package/dist/heart/identity.js +239 -59
- package/dist/heart/kept-notes.js +289 -0
- package/dist/heart/kicks.js +1 -1
- package/dist/heart/machine-identity.js +175 -0
- package/dist/heart/mail-import-discovery.js +356 -0
- package/dist/heart/mailbox/mailbox-http-hooks.js +99 -0
- package/dist/heart/mailbox/mailbox-http-response.js +7 -0
- package/dist/heart/mailbox/mailbox-http-routes.js +406 -0
- package/dist/heart/mailbox/mailbox-http-static.js +103 -0
- package/dist/heart/mailbox/mailbox-http-transport.js +272 -0
- package/dist/heart/mailbox/mailbox-http.js +99 -0
- package/dist/heart/mailbox/mailbox-read.js +41 -0
- package/dist/heart/mailbox/mailbox-supervision.js +131 -0
- package/dist/heart/mailbox/mailbox-types.js +27 -0
- package/dist/heart/mailbox/mailbox-view.js +197 -0
- package/dist/heart/mailbox/readers/agent-machine.js +428 -0
- package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
- package/dist/heart/mailbox/readers/mail.js +375 -0
- package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
- package/dist/heart/mailbox/readers/sessions.js +231 -0
- package/dist/heart/mailbox/readers/shared.js +111 -0
- package/dist/heart/mcp/mcp-server.js +760 -0
- package/dist/heart/migrate-config.js +100 -0
- package/dist/heart/model-capabilities.js +83 -16
- package/dist/heart/orientation-frame.js +376 -0
- package/dist/heart/platform.js +81 -0
- package/dist/heart/primitives.js +1 -1
- package/dist/heart/private-runtime/decision-renderer.js +158 -0
- package/dist/heart/private-runtime/index.js +18 -0
- package/dist/heart/private-runtime/ledger.js +221 -0
- package/dist/heart/private-runtime/policy.js +260 -0
- package/dist/heart/private-runtime/types.js +2 -0
- package/dist/heart/progress-story.js +1 -1
- package/dist/heart/provider-attempt.js +137 -0
- package/dist/heart/provider-binding-resolver.js +273 -0
- package/dist/heart/provider-credentials.js +449 -0
- package/dist/heart/provider-failover.js +311 -0
- package/dist/heart/provider-models.js +96 -0
- package/dist/heart/provider-ping.js +266 -0
- package/dist/heart/provider-readiness-cache.js +119 -0
- package/dist/heart/provider-visibility.js +188 -0
- package/dist/heart/providers/anthropic-token.js +131 -0
- package/dist/heart/providers/anthropic.js +248 -67
- package/dist/heart/providers/azure.js +23 -11
- package/dist/heart/providers/error-classification.js +129 -0
- package/dist/heart/providers/github-copilot.js +38 -39
- package/dist/heart/providers/minimax-vlm.js +189 -0
- package/dist/heart/providers/minimax.js +26 -8
- package/dist/heart/providers/openai-codex-token.js +349 -0
- package/dist/heart/providers/openai-codex.js +55 -40
- package/dist/heart/providers/openai-compatible.js +177 -0
- package/dist/heart/reach-channel.js +85 -0
- package/dist/heart/reply-style.js +52 -0
- package/dist/heart/run-ledger.js +247 -0
- package/dist/heart/runtime-capability-check.js +170 -0
- package/dist/heart/runtime-credentials.js +608 -0
- package/dist/heart/runtime-cwd.js +87 -0
- package/dist/heart/sense-truth.js +24 -4
- package/dist/heart/session-activity.js +94 -24
- package/dist/heart/session-events.js +1521 -0
- package/dist/heart/session-playback-cli-main.js +5 -0
- package/dist/heart/session-playback-cli.js +36 -0
- package/dist/heart/session-playback.js +231 -0
- package/dist/heart/session-redaction-repair-cli-main.js +31 -0
- package/dist/heart/session-redaction-repair.js +552 -0
- package/dist/heart/session-stats-cli-main.js +5 -0
- package/dist/heart/session-stats.js +183 -0
- package/dist/heart/session-transcript.js +133 -0
- package/dist/heart/shelf-claims.js +78 -0
- package/dist/heart/shepherd/custody-types.js +2 -0
- package/dist/heart/shepherd/mandates.js +352 -0
- package/dist/heart/shepherd/operation-commands.js +19 -0
- package/dist/heart/shepherd/operations.js +135 -0
- package/dist/heart/shepherd/supervision.js +114 -0
- package/dist/heart/shepherd/types.js +2 -0
- package/dist/heart/shepherd-config.js +123 -0
- package/dist/heart/source-grounding.js +313 -0
- package/dist/heart/start-of-turn-packet.js +372 -0
- package/dist/heart/steward-policy.js +656 -0
- package/dist/heart/streaming.js +631 -207
- package/dist/heart/structured-output.js +196 -0
- package/dist/heart/sync-classification.js +176 -0
- package/dist/heart/sync-health.js +152 -0
- package/dist/heart/sync-lock.js +431 -0
- package/dist/heart/sync.js +1579 -0
- package/dist/heart/target-resolution.js +11 -7
- package/dist/heart/tempo.js +93 -0
- package/dist/heart/temporal-view.js +41 -0
- package/dist/heart/timeouts.js +101 -0
- package/dist/heart/tool-activity-callbacks.js +59 -0
- package/dist/heart/tool-approval.js +382 -0
- package/dist/heart/tool-description.js +155 -0
- package/dist/heart/tool-friction.js +55 -0
- package/dist/heart/tool-loop.js +206 -0
- package/dist/heart/tool-output-budget.js +41 -0
- package/dist/heart/turn-context.js +496 -0
- package/dist/heart/turn-execution-lease.js +30 -0
- package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
- package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +3 -2
- package/dist/heart/versioning/ouro-path-installer.js +432 -0
- package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
- package/dist/heart/versioning/ouro-version-manager.js +432 -0
- package/dist/heart/versioning/release-sources.js +173 -0
- package/dist/heart/versioning/self-update-defaults.js +294 -0
- package/dist/heart/versioning/self-update.js +196 -0
- package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
- package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
- package/dist/heart/versioning/update-hooks.js +154 -0
- package/dist/heart/versioning/update-state.js +126 -0
- package/dist/heart/versioning/updater-launchd.js +150 -0
- package/dist/heart/versioning/version-intent.js +114 -0
- package/dist/heart/work-card.js +380 -0
- package/dist/mailbox-ui/assets/index-Dbska1tZ.js +1 -0
- package/dist/mailbox-ui/assets/index-DsiKaPyH.css +1 -0
- package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
- package/dist/mailbox-ui/index.html +16 -0
- package/dist/mailroom/attention.js +167 -0
- package/dist/mailroom/autonomy.js +209 -0
- package/dist/mailroom/blob-store.js +889 -0
- package/dist/mailroom/body-cache.js +61 -0
- package/dist/mailroom/cache-sync-cli.js +58 -0
- package/dist/mailroom/core.js +803 -0
- package/dist/mailroom/entry.js +160 -0
- package/dist/mailroom/file-store.js +568 -0
- package/dist/mailroom/hosted-cache-sync.js +384 -0
- package/dist/mailroom/mbox-import.js +393 -0
- package/dist/mailroom/migration.js +164 -0
- package/dist/mailroom/outbound.js +380 -0
- package/dist/mailroom/policy.js +263 -0
- package/dist/mailroom/reader.js +292 -0
- package/dist/mailroom/search-cache.js +513 -0
- package/dist/mailroom/search-relevance.js +319 -0
- package/dist/mailroom/smtp-ingress.js +176 -0
- package/dist/mailroom/source-state.js +176 -0
- package/dist/mailroom/thread.js +109 -0
- package/dist/mailroom/travel-extract.js +89 -0
- package/dist/mind/bundle-manifest.js +25 -2
- package/dist/mind/context.js +328 -139
- package/dist/mind/desk-section.js +362 -0
- package/dist/mind/diary-integrity.js +60 -0
- package/dist/mind/{memory.js → diary.js} +68 -77
- package/dist/mind/embedding-provider.js +60 -0
- package/dist/mind/file-state.js +179 -0
- package/dist/mind/friend-link-codes.js +209 -0
- package/dist/mind/friend-merge.js +336 -0
- package/dist/mind/house-names.js +43 -0
- package/dist/mind/{associative-recall.js → note-search.js} +47 -58
- package/dist/mind/obligation-steering.js +199 -3
- package/dist/mind/outbound-record.js +168 -0
- package/dist/mind/pending.js +36 -10
- package/dist/mind/prompt-budget.js +479 -0
- package/dist/mind/prompt-refresh.js +3 -2
- package/dist/mind/prompt.js +1222 -203
- package/dist/mind/provenance-trust.js +26 -0
- package/dist/mind/record-paths.js +312 -0
- package/dist/mind/scrutiny.js +173 -0
- package/dist/mind/session-transaction.js +622 -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 +143 -5
- package/dist/nerves/coverage/run-artifacts.js +55 -35
- package/dist/nerves/coverage/source-scanner.js +4 -4
- package/dist/nerves/event-buffer.js +111 -0
- package/dist/nerves/index.js +293 -9
- package/dist/nerves/observation.js +20 -0
- package/dist/nerves/redact.js +79 -0
- package/dist/nerves/review/cli-main.js +5 -0
- package/dist/nerves/review/cli.js +156 -0
- package/dist/nerves/review/core.js +159 -0
- package/dist/nerves/runtime.js +17 -1
- package/dist/repertoire/ado-client.js +15 -56
- package/dist/repertoire/ado-semantic.js +16 -10
- package/dist/repertoire/api-client.js +97 -0
- package/dist/repertoire/bitwarden-store.js +1199 -0
- package/dist/repertoire/bundle-templates.js +71 -0
- package/dist/repertoire/bw-installer.js +231 -0
- package/dist/repertoire/coding/codex-jsonl.js +64 -0
- package/dist/repertoire/coding/context-pack.js +331 -0
- package/dist/repertoire/coding/feedback.js +146 -34
- package/dist/repertoire/coding/index.js +15 -3
- package/dist/repertoire/coding/manager.js +159 -10
- package/dist/repertoire/coding/spawner.js +40 -11
- package/dist/repertoire/coding/tools.js +182 -18
- package/dist/repertoire/coding/workbench-client.js +272 -0
- package/dist/repertoire/coding/workbench-manager.js +346 -0
- package/dist/repertoire/commerce-errors.js +109 -0
- package/dist/repertoire/commerce-self-test.js +156 -0
- package/dist/repertoire/credential-access.js +183 -0
- package/dist/repertoire/desk/classifier.js +362 -0
- package/dist/repertoire/duffel-client.js +185 -0
- package/dist/repertoire/github-client.js +14 -55
- package/dist/repertoire/graph-client.js +11 -52
- package/dist/repertoire/guardrails.js +1480 -22
- package/dist/repertoire/house-sweep.js +471 -0
- package/dist/repertoire/mcp-client.js +58 -5
- package/dist/repertoire/mcp-manager.js +427 -139
- package/dist/repertoire/mcp-tools.js +132 -0
- package/dist/repertoire/mcp-write-guard.js +46 -0
- package/dist/repertoire/plugin-mcp.js +175 -0
- package/dist/repertoire/plugins.js +253 -0
- package/dist/repertoire/relationship-authorization.js +322 -0
- package/dist/repertoire/sanctuary-container-policy.js +50 -0
- package/dist/repertoire/shell-sessions.js +134 -0
- package/dist/repertoire/skills.js +48 -4
- package/dist/repertoire/stripe-client.js +131 -0
- package/dist/repertoire/tool-arguments.js +182 -0
- package/dist/repertoire/tool-results.js +29 -0
- package/dist/repertoire/tools-a2a.js +742 -0
- package/dist/repertoire/tools-attachments.js +322 -0
- package/dist/repertoire/tools-awaiting.js +897 -0
- package/dist/repertoire/tools-base.js +83 -1168
- package/dist/repertoire/tools-bluebubbles.js +2 -0
- package/dist/repertoire/tools-bridge.js +144 -0
- package/dist/repertoire/tools-bundle.js +917 -0
- package/dist/repertoire/tools-commerce.js +253 -0
- package/dist/repertoire/tools-config.js +186 -0
- package/dist/repertoire/tools-continuity.js +588 -0
- package/dist/repertoire/tools-credential.js +383 -0
- package/dist/repertoire/tools-escalation.js +84 -0
- package/dist/repertoire/tools-evolution.js +527 -0
- package/dist/repertoire/tools-files.js +362 -0
- package/dist/repertoire/tools-flight.js +290 -0
- package/dist/repertoire/tools-flow.js +119 -0
- package/dist/repertoire/tools-friend-link.js +57 -0
- package/dist/repertoire/tools-github.js +3 -8
- package/dist/repertoire/tools-habits.js +103 -0
- package/dist/repertoire/tools-house-care.js +174 -0
- package/dist/repertoire/tools-mail.js +1828 -0
- package/dist/repertoire/tools-notes.js +501 -0
- package/dist/repertoire/tools-obligations.js +182 -0
- package/dist/repertoire/tools-orientation.js +31 -0
- package/dist/repertoire/tools-record.js +482 -0
- package/dist/repertoire/tools-rsvp.js +139 -0
- package/dist/repertoire/tools-runtime.js +238 -0
- package/dist/repertoire/tools-sanctuary-host.js +202 -0
- package/dist/repertoire/tools-session.js +1141 -0
- package/dist/repertoire/tools-shell.js +154 -0
- package/dist/repertoire/tools-shepherd-guidance.js +171 -0
- package/dist/repertoire/tools-shepherd.js +325 -0
- package/dist/repertoire/tools-steward-policy.js +147 -0
- package/dist/repertoire/tools-stripe.js +224 -0
- package/dist/repertoire/tools-surface.js +369 -0
- package/dist/repertoire/tools-teams.js +50 -39
- package/dist/repertoire/tools-telegram-contacts.js +37 -0
- package/dist/repertoire/tools-travel.js +125 -0
- package/dist/repertoire/tools-trip.js +982 -0
- package/dist/repertoire/tools-unraid.js +556 -0
- package/dist/repertoire/tools-user-profile.js +146 -0
- package/dist/repertoire/tools-vault.js +40 -0
- package/dist/repertoire/tools-voice-local.js +198 -0
- package/dist/repertoire/tools-voice.js +145 -0
- package/dist/repertoire/tools.js +523 -156
- package/dist/repertoire/travel-api-client.js +360 -0
- package/dist/repertoire/unraid-client.js +155 -0
- package/dist/repertoire/unraid-restart.js +339 -0
- package/dist/repertoire/user-profile.js +131 -0
- package/dist/repertoire/vault-setup.js +246 -0
- package/dist/repertoire/vault-unlock.js +686 -0
- package/dist/rsvp/aisleplanner-client.js +354 -0
- package/dist/rsvp/cli.js +936 -0
- package/dist/rsvp/config.js +327 -0
- package/dist/rsvp/cutover.js +453 -0
- package/dist/rsvp/diagnostics.js +232 -0
- package/dist/rsvp/diff-renderer.js +176 -0
- package/dist/rsvp/habit-policy.js +110 -0
- package/dist/rsvp/habit-stage.js +123 -0
- package/dist/rsvp/incident-bundle.js +97 -0
- package/dist/rsvp/migration.js +204 -0
- package/dist/rsvp/native-habit-runner.js +630 -0
- package/dist/rsvp/outbound-state.js +628 -0
- package/dist/rsvp/query.js +118 -0
- package/dist/rsvp/replay.js +233 -0
- package/dist/rsvp/snapshot.js +232 -0
- package/dist/rsvp/spend-ledger.js +175 -0
- package/dist/scripts/claude-code-hook.js +41 -0
- package/dist/scripts/claude-code-stop-hook.js +47 -0
- package/dist/senses/a2a-entry.js +140 -0
- package/dist/senses/acp-server.js +386 -0
- package/dist/senses/attention-queue.js +186 -0
- package/dist/senses/await-turn-message.js +65 -0
- package/dist/senses/bluebubbles/active-turns.js +216 -0
- package/dist/senses/bluebubbles/attachment-cache.js +53 -0
- package/dist/senses/bluebubbles/attachment-download.js +137 -0
- package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +393 -43
- package/dist/senses/bluebubbles/context-packet.js +207 -0
- package/dist/senses/bluebubbles/context-smoke.js +144 -0
- package/dist/senses/bluebubbles/entry.js +90 -0
- package/dist/senses/bluebubbles/host-account-verifier.js +88 -0
- package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
- package/dist/senses/bluebubbles/index.js +4054 -0
- package/dist/senses/bluebubbles/latest-turn.js +311 -0
- package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
- package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
- package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
- package/dist/senses/bluebubbles/outbound-state.js +335 -0
- package/dist/senses/bluebubbles/processed-log.js +133 -0
- package/dist/senses/bluebubbles/reaction-policy.js +47 -0
- package/dist/senses/bluebubbles/replay.js +284 -0
- package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
- package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
- package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
- package/dist/senses/bluebubbles/webhook-registration.js +257 -0
- package/dist/senses/bluebubbles-meta-guard.js +39 -0
- package/dist/senses/cli/bracketed-paste.js +82 -0
- package/dist/senses/cli/image-paste.js +287 -0
- package/dist/senses/cli/image-ref-navigation.js +75 -0
- package/dist/senses/cli/ink-app.js +156 -0
- package/dist/senses/cli/inline-diff.js +64 -0
- package/dist/senses/cli/input-keys.js +174 -0
- package/dist/senses/cli/kill-ring.js +86 -0
- package/dist/senses/cli/message-list.js +51 -0
- package/dist/senses/cli/ouro-tui.js +607 -0
- package/dist/senses/cli/spinner-imperative.js +135 -0
- package/dist/senses/cli/spinner.js +101 -0
- package/dist/senses/cli/status-line.js +60 -0
- package/dist/senses/cli/streaming-markdown.js +526 -0
- package/dist/senses/cli/tool-display.js +85 -0
- package/dist/senses/cli/tool-render.js +85 -0
- package/dist/senses/cli/tui-store.js +241 -0
- package/dist/senses/cli/virtual-list.js +35 -0
- package/dist/senses/cli-entry.js +60 -8
- package/dist/senses/cli.js +570 -309
- package/dist/senses/commands.js +66 -3
- package/dist/senses/context-packet-ledger.js +371 -0
- package/dist/senses/context-packets.js +154 -0
- package/dist/senses/habit-lifecycle-guard.js +24 -0
- package/dist/senses/habit-turn-message.js +160 -0
- package/dist/senses/ingress-evidence.js +2 -0
- package/dist/senses/mail-entry.js +66 -0
- package/dist/senses/mail.js +524 -0
- package/dist/senses/pipeline.js +1192 -204
- package/dist/senses/private-runtime-worker.js +857 -0
- package/dist/senses/private-runtime.js +1622 -0
- package/dist/senses/proactive-content-guard.js +51 -0
- package/dist/senses/root-host-approval-port.js +345 -0
- package/dist/senses/root-host-approval-runtime.js +393 -0
- package/dist/senses/sanctuary-authority-resident.js +102 -0
- package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
- package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
- package/dist/senses/sanctuary-grounding.js +118 -0
- package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
- package/dist/senses/sanctuary-health-acceptance-probe.js +786 -0
- package/dist/senses/sanctuary-health-runner.js +106 -0
- package/dist/senses/sanctuary-health.js +442 -0
- package/dist/senses/sanctuary-house.js +97 -0
- package/dist/senses/sanctuary-install-state-contract.js +169 -0
- package/dist/senses/sanctuary-interactive-control.js +410 -0
- package/dist/senses/sanctuary-media-catalog-contract.js +268 -0
- package/dist/senses/sanctuary-media-optimization.js +517 -0
- package/dist/senses/sanctuary-runtime.js +390 -0
- package/dist/senses/sanctuary-sab.js +85 -0
- package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
- package/dist/senses/shared-turn.js +832 -0
- package/dist/senses/shepherd/agent-presentation.js +88 -0
- package/dist/senses/shepherd/attention-page.js +166 -0
- package/dist/senses/shepherd/attention-sidebar.js +76 -0
- package/dist/senses/shepherd/attention.js +295 -0
- package/dist/senses/shepherd/checkin-config.js +76 -0
- package/dist/senses/shepherd/checkin-store.js +386 -0
- package/dist/senses/shepherd/client.js +196 -0
- package/dist/senses/shepherd/cmux.js +483 -0
- package/dist/senses/shepherd/composer.js +336 -0
- package/dist/senses/shepherd/copilot-app.js +648 -0
- package/dist/senses/shepherd/feedback-reply.js +108 -0
- package/dist/senses/shepherd/feedback-source.js +20 -0
- package/dist/senses/shepherd/feedback-store.js +331 -0
- package/dist/senses/shepherd/feedback-submit.js +182 -0
- package/dist/senses/shepherd/feedback-worker.js +208 -0
- package/dist/senses/shepherd/guidance.js +273 -0
- package/dist/senses/shepherd/herdr.js +427 -0
- package/dist/senses/shepherd/host.js +17 -0
- package/dist/senses/shepherd/human-decision-guard.js +29 -0
- package/dist/senses/shepherd/judge-evaluation-command.js +183 -0
- package/dist/senses/shepherd/judge-evaluation-entry.js +13 -0
- package/dist/senses/shepherd/judge-evaluation.js +155 -0
- package/dist/senses/shepherd/judge.js +210 -0
- package/dist/senses/shepherd/notice-outbox.js +262 -0
- package/dist/senses/shepherd/observation-publisher.js +320 -0
- package/dist/senses/shepherd/operations-defaults.js +86 -0
- package/dist/senses/shepherd/operations.js +159 -0
- package/dist/senses/shepherd/owner-notice.js +489 -0
- package/dist/senses/shepherd/prompt-state.js +60 -0
- package/dist/senses/shepherd/recovery.js +543 -0
- package/dist/senses/shepherd/redact.js +66 -0
- package/dist/senses/shepherd/returns.js +79 -0
- package/dist/senses/shepherd/sense.js +849 -0
- package/dist/senses/shepherd/shepherd-judge-corpus-v1.json +170 -0
- package/dist/senses/shepherd/surface.js +123 -0
- package/dist/senses/shepherd/target-binding.js +13 -0
- package/dist/senses/shepherd/terminal-process.js +147 -0
- package/dist/senses/shepherd-entry.js +98 -0
- package/dist/senses/surface-tool.js +109 -0
- package/dist/senses/teams-entry.js +68 -8
- package/dist/senses/teams-image.js +119 -0
- package/dist/senses/teams.js +998 -337
- package/dist/senses/telegram-admission.js +718 -0
- package/dist/senses/telegram-approval-runtime.js +793 -0
- package/dist/senses/telegram-attachments.js +186 -0
- package/dist/senses/telegram-audit-ledger.js +220 -0
- package/dist/senses/telegram-authority-transport.js +231 -0
- package/dist/senses/telegram-client.js +1755 -0
- package/dist/senses/telegram-effect-adapter.js +904 -0
- package/dist/senses/telegram-entry.js +83 -0
- package/dist/senses/telegram-handoff.js +154 -0
- package/dist/senses/telegram.js +2474 -0
- package/dist/senses/trust-gate.js +104 -9
- package/dist/senses/voice/audio-playback.js +237 -0
- package/dist/senses/voice/audio-routing.js +119 -0
- package/dist/senses/voice/call-auth.js +250 -0
- package/dist/senses/voice/elevenlabs.js +202 -0
- package/dist/senses/voice/floor-control.js +431 -0
- package/dist/senses/voice/floor-controller.js +115 -0
- package/dist/senses/voice/golden-path.js +116 -0
- package/dist/senses/voice/index.js +29 -0
- package/dist/senses/voice/local-audio-control.js +344 -0
- package/dist/senses/voice/local-audio-devices.js +516 -0
- package/dist/senses/voice/local-audio-disclosure.js +174 -0
- package/dist/senses/voice/local-audio-identity.js +103 -0
- package/dist/senses/voice/local-audio-join.js +325 -0
- package/dist/senses/voice/local-audio-mute.js +199 -0
- package/dist/senses/voice/local-audio-notify.js +124 -0
- package/dist/senses/voice/local-audio-prompts.js +116 -0
- package/dist/senses/voice/local-audio-transport.js +427 -0
- package/dist/senses/voice/local-audio.js +281 -0
- package/dist/senses/voice/local-media-stream.js +145 -0
- package/dist/senses/voice/meeting.js +113 -0
- package/dist/senses/voice/outbound.js +190 -0
- package/dist/senses/voice/phone.js +33 -0
- package/dist/senses/voice/playback.js +139 -0
- package/dist/senses/voice/process-guards.js +51 -0
- package/dist/senses/voice/realtime-eval.js +496 -0
- package/dist/senses/voice/realtime-tool-schema.js +195 -0
- package/dist/senses/voice/realtime-trace.js +531 -0
- package/dist/senses/voice/transcript.js +70 -0
- package/dist/senses/voice/turn.js +191 -0
- package/dist/senses/voice/twilio-phone-runtime.js +836 -0
- package/dist/senses/voice/twilio-phone.js +5454 -0
- package/dist/senses/voice/types.js +2 -0
- package/dist/senses/voice/whisper.js +161 -0
- package/dist/senses/voice-entry.js +83 -0
- package/dist/senses/voice-realtime-eval-command.js +99 -0
- package/dist/senses/voice-realtime-eval-entry.js +21 -0
- package/dist/senses/voice-twilio-entry.js +87 -0
- package/dist/trips/core.js +138 -0
- package/dist/trips/store.js +265 -0
- package/dist/util/frontmatter.js +69 -0
- package/npm-shrinkwrap.json +8342 -0
- package/package.json +76 -13
- package/skills/agent-commerce.md +113 -0
- package/skills/browser-navigation.md +117 -0
- package/skills/commerce-setup-guide.md +116 -0
- package/skills/commerce-setup.md +84 -0
- package/skills/configure-dev-tools.md +99 -0
- package/skills/travel-planning.md +138 -0
- package/dist/heart/daemon/auth-flow.js +0 -430
- package/dist/heart/daemon/ouro-path-installer.js +0 -260
- package/dist/heart/daemon/ouro-version-manager.js +0 -171
- package/dist/heart/daemon/update-hooks.js +0 -138
- package/dist/heart/obligations.js +0 -191
- package/dist/heart/safe-workspace.js +0 -381
- package/dist/heart/session-recall.js +0 -116
- package/dist/mind/friends/channel.js +0 -84
- package/dist/mind/friends/group-context.js +0 -144
- package/dist/mind/friends/resolver.js +0 -84
- package/dist/mind/friends/store-file.js +0 -190
- package/dist/mind/friends/store.js +0 -4
- package/dist/mind/friends/tokens.js +0 -26
- package/dist/mind/friends/trust-explanation.js +0 -74
- package/dist/mind/friends/types.js +0 -29
- package/dist/repertoire/tasks/board.js +0 -134
- package/dist/repertoire/tasks/index.js +0 -224
- package/dist/repertoire/tasks/lifecycle.js +0 -80
- package/dist/repertoire/tasks/middleware.js +0 -65
- package/dist/repertoire/tasks/parser.js +0 -173
- package/dist/repertoire/tasks/scanner.js +0 -132
- package/dist/repertoire/tasks/transitions.js +0 -144
- package/dist/senses/bluebubbles-entry.js +0 -13
- package/dist/senses/bluebubbles.js +0 -1181
- package/dist/senses/debug-activity.js +0 -154
- package/dist/senses/inner-dialog-worker.js +0 -90
- package/dist/senses/inner-dialog.js +0 -525
- package/subagents/README.md +0 -7
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
- /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
- /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
- /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
- /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
- /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
package/dist/senses/cli.js
CHANGED
|
@@ -33,9 +33,10 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.MarkdownStreamer = exports.InputController = exports.Spinner = exports.StreamingWordWrapper = exports.wrapCliText = exports.formatEchoedInputSummary = void 0;
|
|
36
|
+
exports.InputQueue = exports.MarkdownStreamer = exports.InputController = exports.Spinner = exports.StreamingWordWrapper = exports.wrapCliText = exports.formatEchoedInputSummary = void 0;
|
|
37
37
|
exports.formatPendingPrefix = formatPendingPrefix;
|
|
38
38
|
exports.getCliContinuityIngressTexts = getCliContinuityIngressTexts;
|
|
39
|
+
exports.formatTimeAgo = formatTimeAgo;
|
|
39
40
|
exports.writeCliAsyncAssistantMessage = writeCliAsyncAssistantMessage;
|
|
40
41
|
exports.pauseActiveSpinner = pauseActiveSpinner;
|
|
41
42
|
exports.resumeActiveSpinner = resumeActiveSpinner;
|
|
@@ -55,25 +56,27 @@ const prompt_1 = require("../mind/prompt");
|
|
|
55
56
|
const phrases_1 = require("../mind/phrases");
|
|
56
57
|
const format_1 = require("../mind/format");
|
|
57
58
|
const config_1 = require("../heart/config");
|
|
59
|
+
const session_events_1 = require("../heart/session-events");
|
|
58
60
|
const context_1 = require("../mind/context");
|
|
59
61
|
const pending_1 = require("../mind/pending");
|
|
60
62
|
const commands_1 = require("./commands");
|
|
61
63
|
const identity_1 = require("../heart/identity");
|
|
62
64
|
const mcp_manager_1 = require("../repertoire/mcp-manager");
|
|
63
65
|
const nerves_1 = require("../nerves");
|
|
64
|
-
const
|
|
65
|
-
const resolver_1 = require("../mind/friends/resolver");
|
|
66
|
-
const tokens_1 = require("../mind/friends/tokens");
|
|
66
|
+
const friends_1 = require("@ouro.bot/friends");
|
|
67
67
|
const cli_logging_1 = require("../nerves/cli-logging");
|
|
68
68
|
const runtime_1 = require("../nerves/runtime");
|
|
69
69
|
const trust_gate_1 = require("./trust-gate");
|
|
70
70
|
const pipeline_1 = require("./pipeline");
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const update_hooks_1 = require("../heart/daemon/update-hooks");
|
|
71
|
+
const session_transaction_1 = require("../mind/session-transaction");
|
|
72
|
+
const update_hooks_1 = require("../heart/versioning/update-hooks");
|
|
74
73
|
const bundle_meta_1 = require("../heart/daemon/hooks/bundle-meta");
|
|
74
|
+
const agent_config_v2_1 = require("../heart/daemon/hooks/agent-config-v2");
|
|
75
75
|
const bundle_manifest_1 = require("../mind/bundle-manifest");
|
|
76
76
|
const cli_layout_1 = require("./cli-layout");
|
|
77
|
+
const image_paste_1 = require("./cli/image-paste");
|
|
78
|
+
const spinner_imperative_1 = require("./cli/spinner-imperative");
|
|
79
|
+
const tool_display_1 = require("./cli/tool-display");
|
|
77
80
|
var cli_layout_2 = require("./cli-layout");
|
|
78
81
|
Object.defineProperty(exports, "formatEchoedInputSummary", { enumerable: true, get: function () { return cli_layout_2.formatEchoedInputSummary; } });
|
|
79
82
|
Object.defineProperty(exports, "wrapCliText", { enumerable: true, get: function () { return cli_layout_2.wrapCliText; } });
|
|
@@ -81,13 +84,13 @@ Object.defineProperty(exports, "StreamingWordWrapper", { enumerable: true, get:
|
|
|
81
84
|
/**
|
|
82
85
|
* Format pending messages as content-prefix strings for injection into
|
|
83
86
|
* the next user message. Self-messages (from === agentName) become
|
|
84
|
-
* `[
|
|
87
|
+
* `[private-runtime note: {content}]`, inter-agent messages become
|
|
85
88
|
* `[message from {name}: {content}]`.
|
|
86
89
|
*/
|
|
87
90
|
function formatPendingPrefix(messages, agentName) {
|
|
88
91
|
return messages
|
|
89
92
|
.map((msg) => msg.from === agentName
|
|
90
|
-
? `[
|
|
93
|
+
? `[private-runtime note: ${msg.content}]`
|
|
91
94
|
: `[message from ${msg.from}: ${msg.content}]`)
|
|
92
95
|
.join("\n");
|
|
93
96
|
}
|
|
@@ -95,7 +98,21 @@ function getCliContinuityIngressTexts(input) {
|
|
|
95
98
|
const trimmed = input.trim();
|
|
96
99
|
return trimmed ? [trimmed] : [];
|
|
97
100
|
}
|
|
98
|
-
|
|
101
|
+
/* v8 ignore start -- cosmetic time formatting @preserve */
|
|
102
|
+
function formatTimeAgo(date) {
|
|
103
|
+
const seconds = Math.floor((Date.now() - date.getTime()) / 1000);
|
|
104
|
+
if (seconds < 60)
|
|
105
|
+
return "just now";
|
|
106
|
+
const minutes = Math.floor(seconds / 60);
|
|
107
|
+
if (minutes < 60)
|
|
108
|
+
return `${minutes}m ago`;
|
|
109
|
+
const hours = Math.floor(minutes / 60);
|
|
110
|
+
if (hours < 24)
|
|
111
|
+
return `${hours}h ago`;
|
|
112
|
+
const days = Math.floor(hours / 24);
|
|
113
|
+
return `${days}d ago`;
|
|
114
|
+
}
|
|
115
|
+
const CLI_PROMPT = "\x1b[36m) \x1b[0m";
|
|
99
116
|
function writeCliAsyncAssistantMessage(rl, message, stdout = process.stdout) {
|
|
100
117
|
const rlInt = rl;
|
|
101
118
|
const currentLine = rlInt.line ?? "";
|
|
@@ -118,82 +135,9 @@ function pauseActiveSpinner() { _activeSpinner?.pause(); }
|
|
|
118
135
|
function resumeActiveSpinner() { _activeSpinner?.resume(); }
|
|
119
136
|
/* v8 ignore stop */
|
|
120
137
|
function setActiveSpinner(s) { _activeSpinner = s; }
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
125
|
-
i = 0;
|
|
126
|
-
iv = null;
|
|
127
|
-
piv = null;
|
|
128
|
-
msg = "";
|
|
129
|
-
phrases = null;
|
|
130
|
-
lastPhrase = "";
|
|
131
|
-
stopped = false;
|
|
132
|
-
constructor(m = "working", phrases) {
|
|
133
|
-
this.msg = m;
|
|
134
|
-
if (phrases && phrases.length > 0)
|
|
135
|
-
this.phrases = phrases;
|
|
136
|
-
}
|
|
137
|
-
start() {
|
|
138
|
-
this.stopped = false;
|
|
139
|
-
process.stderr.write("\r\x1b[K");
|
|
140
|
-
this.spin();
|
|
141
|
-
this.iv = setInterval(() => this.spin(), 80);
|
|
142
|
-
if (this.phrases) {
|
|
143
|
-
this.piv = setInterval(() => this.rotatePhrase(), 1500);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
spin() {
|
|
147
|
-
// Guard: clearInterval can't prevent already-dequeued callbacks
|
|
148
|
-
/* v8 ignore next -- race guard: timer callback fires after stop() @preserve */
|
|
149
|
-
if (this.stopped)
|
|
150
|
-
return;
|
|
151
|
-
process.stderr.write(`\r\x1b[K${this.frames[this.i]} ${this.msg}... `);
|
|
152
|
-
this.i = (this.i + 1) % this.frames.length;
|
|
153
|
-
}
|
|
154
|
-
rotatePhrase() {
|
|
155
|
-
/* v8 ignore next -- race guard: timer callback fires after stop() @preserve */
|
|
156
|
-
if (this.stopped)
|
|
157
|
-
return;
|
|
158
|
-
const next = (0, phrases_1.pickPhrase)(this.phrases, this.lastPhrase);
|
|
159
|
-
this.lastPhrase = next;
|
|
160
|
-
this.msg = next;
|
|
161
|
-
}
|
|
162
|
-
/* v8 ignore start -- pause/resume: exercised at runtime via log sink coordination @preserve */
|
|
163
|
-
/** Clear the spinner line temporarily so other output can print cleanly. */
|
|
164
|
-
pause() {
|
|
165
|
-
if (this.stopped)
|
|
166
|
-
return;
|
|
167
|
-
process.stderr.write("\r\x1b[K");
|
|
168
|
-
}
|
|
169
|
-
/** Restore the spinner line after a pause. */
|
|
170
|
-
resume() {
|
|
171
|
-
if (this.stopped)
|
|
172
|
-
return;
|
|
173
|
-
this.spin();
|
|
174
|
-
}
|
|
175
|
-
/* v8 ignore stop */
|
|
176
|
-
stop(ok) {
|
|
177
|
-
this.stopped = true;
|
|
178
|
-
if (this.iv) {
|
|
179
|
-
clearInterval(this.iv);
|
|
180
|
-
this.iv = null;
|
|
181
|
-
}
|
|
182
|
-
if (this.piv) {
|
|
183
|
-
clearInterval(this.piv);
|
|
184
|
-
this.piv = null;
|
|
185
|
-
}
|
|
186
|
-
process.stderr.write("\r\x1b[K");
|
|
187
|
-
/* v8 ignore next -- ok parameter currently unused by callers @preserve */
|
|
188
|
-
if (ok)
|
|
189
|
-
process.stderr.write(`\x1b[32m\u2713\x1b[0m ${ok}\n`);
|
|
190
|
-
}
|
|
191
|
-
fail(msg) {
|
|
192
|
-
this.stop();
|
|
193
|
-
process.stderr.write(`\x1b[31m\u2717\x1b[0m ${msg}\n`);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
exports.Spinner = Spinner;
|
|
138
|
+
// Re-export ImperativeSpinner as Spinner for backward compatibility
|
|
139
|
+
var spinner_imperative_2 = require("./cli/spinner-imperative");
|
|
140
|
+
Object.defineProperty(exports, "Spinner", { enumerable: true, get: function () { return spinner_imperative_2.ImperativeSpinner; } });
|
|
197
141
|
// Input controller: pauses readline during model/tool execution.
|
|
198
142
|
// Does NOT touch raw mode — readline with terminal:true manages raw mode
|
|
199
143
|
// internally. Touching it causes ^C to be echoed by the terminal driver.
|
|
@@ -367,6 +311,7 @@ function createCliCallbacks() {
|
|
|
367
311
|
const streamer = new MarkdownStreamer();
|
|
368
312
|
const wrapper = new cli_layout_1.StreamingWordWrapper();
|
|
369
313
|
return {
|
|
314
|
+
settleOutputMode: "final_only",
|
|
370
315
|
onModelStart: () => {
|
|
371
316
|
currentSpinner?.stop();
|
|
372
317
|
setSpinner(null);
|
|
@@ -376,20 +321,20 @@ function createCliCallbacks() {
|
|
|
376
321
|
const phrases = (0, phrases_1.getPhrases)();
|
|
377
322
|
const pool = hadToolRun ? phrases.followup : phrases.thinking;
|
|
378
323
|
const first = (0, phrases_1.pickPhrase)(pool);
|
|
379
|
-
setSpinner(new
|
|
324
|
+
setSpinner(new spinner_imperative_1.ImperativeSpinner(first, pool));
|
|
380
325
|
currentSpinner.start();
|
|
381
326
|
},
|
|
382
327
|
onModelStreamStart: () => {
|
|
383
328
|
// No-op: content callbacks (onTextChunk, onReasoningChunk) handle
|
|
384
329
|
// stopping the spinner. onModelStreamStart fires too early and
|
|
385
|
-
// doesn't fire at all for
|
|
330
|
+
// doesn't fire at all for settle tool streaming.
|
|
386
331
|
},
|
|
387
332
|
onClearText: () => {
|
|
388
333
|
streamer.reset();
|
|
389
334
|
wrapper.reset();
|
|
390
335
|
},
|
|
391
336
|
onTextChunk: (text) => {
|
|
392
|
-
// Stop spinner if still running —
|
|
337
|
+
// Stop spinner if still running — settle streaming and Anthropic
|
|
393
338
|
// tool-only responses bypass onModelStreamStart, so the spinner would
|
|
394
339
|
// otherwise keep running (and its \r writes overwrite response text).
|
|
395
340
|
if (currentSpinner) {
|
|
@@ -406,11 +351,20 @@ function createCliCallbacks() {
|
|
|
406
351
|
/* v8 ignore stop */
|
|
407
352
|
textDirty = text.length > 0 && !text.endsWith("\n");
|
|
408
353
|
},
|
|
354
|
+
flushNow: () => {
|
|
355
|
+
// CLI flushes immediately on each onTextChunk; nothing buffered to push.
|
|
356
|
+
},
|
|
409
357
|
onReasoningChunk: (_text) => {
|
|
410
358
|
// Keep reasoning private in the CLI surface. The spinner continues to
|
|
411
359
|
// represent active thinking until actual tool or answer output arrives.
|
|
412
360
|
},
|
|
413
361
|
onToolStart: (_name, _args) => {
|
|
362
|
+
// speak is flow-control: its visible output is the message itself (delivered
|
|
363
|
+
// via onTextChunk/flushNow). Do NOT start a tool spinner — that would write
|
|
364
|
+
// a "running speak..." phrase to stderr right before the actual message
|
|
365
|
+
// arrives, which is the visual churn the user explicitly does not want.
|
|
366
|
+
if (_name === "speak")
|
|
367
|
+
return;
|
|
414
368
|
// Stop the model-start spinner: when the model returns only tool calls
|
|
415
369
|
// (no content/reasoning), onModelStreamStart never fires, so the old
|
|
416
370
|
// spinner's intervals would leak.
|
|
@@ -423,16 +377,14 @@ function createCliCallbacks() {
|
|
|
423
377
|
}
|
|
424
378
|
const toolPhrases = (0, phrases_1.getPhrases)().tool;
|
|
425
379
|
const first = (0, phrases_1.pickPhrase)(toolPhrases);
|
|
426
|
-
setSpinner(new
|
|
380
|
+
setSpinner(new spinner_imperative_1.ImperativeSpinner(first, toolPhrases));
|
|
427
381
|
currentSpinner.start();
|
|
428
382
|
hadToolRun = true;
|
|
429
383
|
},
|
|
430
384
|
onToolEnd: (name, argSummary, success) => {
|
|
431
385
|
currentSpinner?.stop();
|
|
432
386
|
setSpinner(null);
|
|
433
|
-
|
|
434
|
-
const color = success ? "\x1b[32m" : "\x1b[31m";
|
|
435
|
-
process.stderr.write(`${color}${msg}\x1b[0m\n`);
|
|
387
|
+
(0, tool_display_1.writeToolEnd)(name, argSummary, success);
|
|
436
388
|
},
|
|
437
389
|
onError: (error, severity) => {
|
|
438
390
|
if (severity === "transient") {
|
|
@@ -508,29 +460,227 @@ async function* createDebouncedLines(source, debounceMs) {
|
|
|
508
460
|
yield lines.join("\n");
|
|
509
461
|
}
|
|
510
462
|
}
|
|
463
|
+
/**
|
|
464
|
+
* Async queue that bridges push-based Ink input to pull-based async iteration.
|
|
465
|
+
* Input from Ink's onSubmit callback is pushed; the business logic loop awaits via for-await.
|
|
466
|
+
*/
|
|
467
|
+
class InputQueue {
|
|
468
|
+
queue = [];
|
|
469
|
+
resolve = null;
|
|
470
|
+
done = false;
|
|
471
|
+
push(input) {
|
|
472
|
+
if (this.done)
|
|
473
|
+
return;
|
|
474
|
+
if (this.resolve) {
|
|
475
|
+
const r = this.resolve;
|
|
476
|
+
this.resolve = null;
|
|
477
|
+
r({ value: input, done: false });
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
this.queue.push(input);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
close() {
|
|
484
|
+
this.done = true;
|
|
485
|
+
if (this.resolve) {
|
|
486
|
+
const r = this.resolve;
|
|
487
|
+
this.resolve = null;
|
|
488
|
+
r({ value: undefined, done: true });
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
/** Drain all buffered items, leaving any pending async awaiter untouched. */
|
|
492
|
+
drainAll() {
|
|
493
|
+
const items = [...this.queue];
|
|
494
|
+
this.queue = [];
|
|
495
|
+
return items;
|
|
496
|
+
}
|
|
497
|
+
[Symbol.asyncIterator]() {
|
|
498
|
+
return {
|
|
499
|
+
next: () => {
|
|
500
|
+
if (this.queue.length > 0) {
|
|
501
|
+
return Promise.resolve({ value: this.queue.shift(), done: false });
|
|
502
|
+
}
|
|
503
|
+
if (this.done) {
|
|
504
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
505
|
+
}
|
|
506
|
+
return new Promise((resolve) => {
|
|
507
|
+
this.resolve = resolve;
|
|
508
|
+
});
|
|
509
|
+
},
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
exports.InputQueue = InputQueue;
|
|
511
514
|
async function runCliSession(options) {
|
|
512
515
|
/* v8 ignore start -- integration: runCliSession is interactive, tested via E2E @preserve */
|
|
513
|
-
const pasteDebounceMs = options.pasteDebounceMs ?? 50;
|
|
514
516
|
const registry = (0, commands_1.createCommandRegistry)();
|
|
515
517
|
if (!options.disableCommands) {
|
|
516
518
|
(0, commands_1.registerDefaultCommands)(registry);
|
|
517
519
|
}
|
|
518
520
|
const messages = options.messages
|
|
519
|
-
?? [{ role: "system", content: await (0, prompt_1.buildSystem)("cli") }];
|
|
520
|
-
|
|
521
|
-
const
|
|
521
|
+
?? [{ role: "system", content: (0, prompt_1.flattenSystemPrompt)(await (0, prompt_1.buildSystem)("cli")) }];
|
|
522
|
+
// ─── Rendering: TUI (Ink + Static) for TTY, imperative for tests/pipes ───
|
|
523
|
+
const useTui = !options._testInputSource && process.stdin.isTTY === true;
|
|
522
524
|
let currentAbort = null;
|
|
523
|
-
const history = [];
|
|
524
525
|
let closed = false;
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
526
|
+
// eslint-disable-next-line prefer-const -- set by onImageMap callback during input
|
|
527
|
+
let pendingImages = null;
|
|
528
|
+
let cliCallbacks;
|
|
529
|
+
let tuiStore = null;
|
|
530
|
+
let inkRef = null;
|
|
531
|
+
const inputQueue = useTui ? new InputQueue() : null;
|
|
532
|
+
let rl = null;
|
|
533
|
+
if (useTui) {
|
|
534
|
+
try {
|
|
535
|
+
const [ink, React, tuiMod, storeMod] = await Promise.all([
|
|
536
|
+
Promise.resolve().then(() => __importStar(require("ink"))),
|
|
537
|
+
Promise.resolve().then(() => __importStar(require("react"))),
|
|
538
|
+
Promise.resolve().then(() => __importStar(require("./cli/ouro-tui"))),
|
|
539
|
+
Promise.resolve().then(() => __importStar(require("./cli/tui-store"))),
|
|
540
|
+
]);
|
|
541
|
+
const { OuroTui } = tuiMod;
|
|
542
|
+
const { TuiStore, createTuiCallbacks } = storeMod;
|
|
543
|
+
tuiStore = new TuiStore();
|
|
544
|
+
cliCallbacks = createTuiCallbacks(tuiStore);
|
|
545
|
+
// Seed input history from previous session (for up/down arrows) — NOT display
|
|
546
|
+
const prevUserMsgs = messages
|
|
547
|
+
.filter((msg) => msg.role === "user" && typeof msg.content === "string")
|
|
548
|
+
.map(msg => msg.content);
|
|
549
|
+
tuiStore.seedHistory(prevUserMsgs);
|
|
550
|
+
// Show session resume context: last 2 exchanges as normal messages
|
|
551
|
+
if (messages.length > 1) {
|
|
552
|
+
const userAssistantMsgs = messages.filter((m) => (m.role === "user" || m.role === "assistant") && typeof m.content === "string" && m.content.trim().length > 0);
|
|
553
|
+
// Extract last 2 exchanges (up to 4 messages)
|
|
554
|
+
const lastExchanges = [];
|
|
555
|
+
for (let i = userAssistantMsgs.length - 1; i >= 0 && lastExchanges.length < 4; i--) {
|
|
556
|
+
lastExchanges.unshift({ role: userAssistantMsgs[i].role, content: userAssistantMsgs[i].content });
|
|
557
|
+
}
|
|
558
|
+
tuiStore.addResumeMessages(lastExchanges);
|
|
559
|
+
}
|
|
560
|
+
// Compute resumeInfo for header banner
|
|
561
|
+
const resumeInfo = messages.length > 1
|
|
562
|
+
? {
|
|
563
|
+
messageCount: messages.filter(m => m.role === "user" || m.role === "assistant").length,
|
|
564
|
+
timeAgo: options.lastActivityAt ? formatTimeAgo(new Date(options.lastActivityAt)) : "unknown",
|
|
565
|
+
}
|
|
566
|
+
: undefined;
|
|
567
|
+
// Ctrl-C state machine (Claude Code behavior):
|
|
568
|
+
// During generation: abort current request
|
|
569
|
+
// Idle with text: clear input
|
|
570
|
+
// Idle empty (first): warn
|
|
571
|
+
// Idle empty (second): exit
|
|
572
|
+
let ctrlCWarned = false;
|
|
573
|
+
let ctrlCTimer = null;
|
|
574
|
+
const handleCtrlC = (hasInput) => {
|
|
575
|
+
if (currentAbort) {
|
|
576
|
+
currentAbort.abort();
|
|
577
|
+
ctrlCWarned = false;
|
|
578
|
+
return "abort";
|
|
579
|
+
}
|
|
580
|
+
if (hasInput) {
|
|
581
|
+
ctrlCWarned = false;
|
|
582
|
+
return "clear";
|
|
583
|
+
}
|
|
584
|
+
if (ctrlCWarned) {
|
|
585
|
+
ctrlCWarned = false;
|
|
586
|
+
if (ctrlCTimer) {
|
|
587
|
+
clearTimeout(ctrlCTimer);
|
|
588
|
+
ctrlCTimer = null;
|
|
589
|
+
}
|
|
590
|
+
closed = true;
|
|
591
|
+
inputQueue.close();
|
|
592
|
+
return "exit";
|
|
593
|
+
}
|
|
594
|
+
ctrlCWarned = true;
|
|
595
|
+
// Reset after 2 seconds — must press twice within window
|
|
596
|
+
ctrlCTimer = setTimeout(() => { ctrlCWarned = false; }, 2000);
|
|
597
|
+
return "warn";
|
|
598
|
+
};
|
|
599
|
+
// TUI root: subscribes to store, passes props to OuroTui
|
|
600
|
+
// Elapsed timer is local React state (no store.notify overhead)
|
|
601
|
+
const storeRef = tuiStore;
|
|
602
|
+
function TuiRoot() {
|
|
603
|
+
const [, forceUpdate] = React.useState(0);
|
|
604
|
+
const [elapsed, setElapsed] = React.useState(0);
|
|
605
|
+
React.useEffect(() => storeRef.subscribe(() => {
|
|
606
|
+
forceUpdate((n) => n + 1);
|
|
607
|
+
// Reset ctrlC warning on any state change (new turn, etc.)
|
|
608
|
+
}), []);
|
|
609
|
+
React.useEffect(() => {
|
|
610
|
+
const iv = setInterval(() => setElapsed(storeRef.getElapsed()), 1000);
|
|
611
|
+
return () => clearInterval(iv);
|
|
612
|
+
}, []);
|
|
613
|
+
return React.createElement(OuroTui, {
|
|
614
|
+
agentName: options.agentName,
|
|
615
|
+
model: (0, identity_1.loadAgentConfig)().humanFacing?.model ?? "",
|
|
616
|
+
completedMessages: storeRef.completedMessages,
|
|
617
|
+
inputHistory: storeRef.inputHistory,
|
|
618
|
+
queuedInputs: storeRef.queuedInputs,
|
|
619
|
+
live: storeRef.live,
|
|
620
|
+
elapsedSeconds: elapsed,
|
|
621
|
+
contextPercent: 0,
|
|
622
|
+
onSubmit: (text) => { ctrlCWarned = false; inputQueue.push(text); storeRef.enqueueInput(text); },
|
|
623
|
+
onCtrlC: handleCtrlC,
|
|
624
|
+
onPopQueue: () => { const items = storeRef.popAllQueuedForEditing(); inputQueue.drainAll(); return items; },
|
|
625
|
+
headerShown: storeRef.headerShown,
|
|
626
|
+
cwd: process.cwd().replace(process.env.HOME ?? "", "~"),
|
|
627
|
+
resumeInfo,
|
|
628
|
+
onImageMap: (images) => { pendingImages = images; },
|
|
629
|
+
onHistoryAdd: (text) => { storeRef.addToHistoryOnly(text); },
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
inkRef = ink.render(React.createElement(TuiRoot), { exitOnCtrlC: false, patchConsole: false });
|
|
633
|
+
}
|
|
634
|
+
catch (err) {
|
|
635
|
+
// Ink failed to load (CJS compat, missing deps, etc.) — fall through to imperative
|
|
636
|
+
(0, runtime_1.emitNervesEvent)({
|
|
637
|
+
component: "senses",
|
|
638
|
+
event: "senses.tui_fallback",
|
|
639
|
+
message: `TUI failed to load, falling back to imperative: ${err instanceof Error ? err.message : String(err)}`,
|
|
640
|
+
meta: {},
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
// Fallback to imperative callbacks if TUI didn't initialize
|
|
645
|
+
if (!tuiStore) {
|
|
646
|
+
cliCallbacks = createCliCallbacks();
|
|
647
|
+
if (options.banner !== false) {
|
|
648
|
+
const bannerText = typeof options.banner === "string"
|
|
649
|
+
? options.banner
|
|
650
|
+
: `${options.agentName} (type /commands for help)`;
|
|
651
|
+
// eslint-disable-next-line no-console -- terminal UX: startup banner
|
|
652
|
+
console.log(`\n${bannerText}\n`);
|
|
653
|
+
}
|
|
532
654
|
}
|
|
533
|
-
|
|
655
|
+
// Display helpers: route to TUI store or imperative stderr/stdout
|
|
656
|
+
const display = {
|
|
657
|
+
error: (msg) => {
|
|
658
|
+
if (tuiStore)
|
|
659
|
+
tuiStore.setError(msg);
|
|
660
|
+
else
|
|
661
|
+
process.stderr.write(`\x1b[31m${msg}\x1b[0m\n`);
|
|
662
|
+
},
|
|
663
|
+
warn: (msg) => {
|
|
664
|
+
if (tuiStore)
|
|
665
|
+
tuiStore.setError(msg); // TUI shows warnings as errors (amber color handled in component)
|
|
666
|
+
else
|
|
667
|
+
process.stderr.write(`\x1b[33m${msg}\x1b[0m\n`);
|
|
668
|
+
},
|
|
669
|
+
text: (msg) => {
|
|
670
|
+
if (tuiStore)
|
|
671
|
+
tuiStore.appendText(msg);
|
|
672
|
+
else
|
|
673
|
+
process.stdout.write(`${msg}\n`);
|
|
674
|
+
},
|
|
675
|
+
suppressInput: () => {
|
|
676
|
+
if (tuiStore)
|
|
677
|
+
tuiStore.suppressInput();
|
|
678
|
+
},
|
|
679
|
+
restoreInput: () => {
|
|
680
|
+
if (tuiStore)
|
|
681
|
+
tuiStore.restoreInput();
|
|
682
|
+
},
|
|
683
|
+
};
|
|
534
684
|
const effectiveToolContext = {
|
|
535
685
|
signin: options.toolContext?.signin ?? (async () => undefined),
|
|
536
686
|
...options.toolContext,
|
|
@@ -542,7 +692,7 @@ async function runCliSession(options) {
|
|
|
542
692
|
};
|
|
543
693
|
messages.push(assistantMessage);
|
|
544
694
|
await options.onAsyncAssistantMessage?.(messages, assistantMessage);
|
|
545
|
-
|
|
695
|
+
display.text(message);
|
|
546
696
|
await options.toolContext?.codingFeedback?.send(message);
|
|
547
697
|
},
|
|
548
698
|
},
|
|
@@ -557,8 +707,6 @@ async function runCliSession(options) {
|
|
|
557
707
|
if (name === options.exitOnToolCall) {
|
|
558
708
|
exitToolResult = result;
|
|
559
709
|
exitToolFired = true;
|
|
560
|
-
// Abort immediately so the model doesn't generate more output
|
|
561
|
-
// (e.g. reasoning about calling final_answer after complete_adoption)
|
|
562
710
|
currentAbort?.abort();
|
|
563
711
|
}
|
|
564
712
|
return result;
|
|
@@ -566,28 +714,6 @@ async function runCliSession(options) {
|
|
|
566
714
|
: resolvedExecTool;
|
|
567
715
|
// Resolve toolChoiceRequired: use explicit option if set, else fall back to toggle
|
|
568
716
|
const getEffectiveToolChoiceRequired = () => options.toolChoiceRequired !== undefined ? options.toolChoiceRequired : (0, commands_1.getToolChoiceRequired)();
|
|
569
|
-
// Ctrl-C at the input prompt: clear line or warn/exit
|
|
570
|
-
rl.on("SIGINT", () => {
|
|
571
|
-
const rlInt = rl;
|
|
572
|
-
const currentLine = rlInt.line || "";
|
|
573
|
-
const result = handleSigint(rl, currentLine);
|
|
574
|
-
if (result === "clear") {
|
|
575
|
-
rlInt.line = "";
|
|
576
|
-
rlInt.cursor = 0;
|
|
577
|
-
process.stdout.write(`\r\x1b[K${CLI_PROMPT}`);
|
|
578
|
-
}
|
|
579
|
-
else if (result === "warn") {
|
|
580
|
-
rlInt.line = "";
|
|
581
|
-
rlInt.cursor = 0;
|
|
582
|
-
process.stdout.write("\r\x1b[K");
|
|
583
|
-
process.stderr.write("press Ctrl-C again to exit\n");
|
|
584
|
-
process.stdout.write(CLI_PROMPT);
|
|
585
|
-
}
|
|
586
|
-
else {
|
|
587
|
-
rl.close();
|
|
588
|
-
}
|
|
589
|
-
});
|
|
590
|
-
const debouncedLines = (source) => createDebouncedLines(source, pasteDebounceMs);
|
|
591
717
|
(0, runtime_1.emitNervesEvent)({
|
|
592
718
|
component: "senses",
|
|
593
719
|
event: "senses.cli_session_start",
|
|
@@ -600,7 +726,7 @@ async function runCliSession(options) {
|
|
|
600
726
|
if (options.autoFirstTurn && messages.length > 0 && messages[messages.length - 1]?.role === "user") {
|
|
601
727
|
currentAbort = new AbortController();
|
|
602
728
|
const traceId = (0, nerves_1.createTraceId)();
|
|
603
|
-
|
|
729
|
+
display.suppressInput();
|
|
604
730
|
let result;
|
|
605
731
|
try {
|
|
606
732
|
result = await (0, core_1.runAgent)(messages, cliCallbacks, options.skipSystemPromptRefresh ? undefined : "cli", currentAbort.signal, {
|
|
@@ -612,138 +738,185 @@ async function runCliSession(options) {
|
|
|
612
738
|
});
|
|
613
739
|
}
|
|
614
740
|
catch (err) {
|
|
615
|
-
// AbortError (Ctrl-C) -- silently continue to prompt
|
|
616
|
-
// All other errors: show the user what happened
|
|
617
741
|
if (!(err instanceof DOMException && err.name === "AbortError")) {
|
|
618
|
-
|
|
742
|
+
display.error(err instanceof Error ? err.message : String(err));
|
|
619
743
|
}
|
|
620
744
|
}
|
|
621
745
|
cliCallbacks.flushMarkdown();
|
|
622
|
-
|
|
746
|
+
display.restoreInput();
|
|
623
747
|
currentAbort = null;
|
|
624
748
|
if (exitToolFired) {
|
|
625
749
|
exitReason = "tool_exit";
|
|
626
|
-
|
|
750
|
+
closed = true;
|
|
627
751
|
}
|
|
628
752
|
else {
|
|
629
753
|
const lastMsg = messages[messages.length - 1];
|
|
630
754
|
if (lastMsg?.role === "assistant" && !(typeof lastMsg.content === "string" ? lastMsg.content : "").trim()) {
|
|
631
|
-
|
|
755
|
+
display.warn("(empty response)");
|
|
632
756
|
}
|
|
633
|
-
process.stdout.write("\n\n");
|
|
634
757
|
if (options.onTurnEnd) {
|
|
635
758
|
await options.onTurnEnd(messages, result ?? { usage: undefined });
|
|
636
759
|
}
|
|
637
760
|
}
|
|
638
761
|
}
|
|
639
|
-
if (!exitToolFired) {
|
|
640
|
-
process.stdout.write(CLI_PROMPT);
|
|
641
|
-
}
|
|
642
762
|
try {
|
|
643
|
-
for
|
|
763
|
+
// Input source: TUI queue for Ink, test source for tests, readline fallback
|
|
764
|
+
let inputSource;
|
|
765
|
+
let inputCtrl = null;
|
|
766
|
+
if (tuiStore && inputQueue) {
|
|
767
|
+
// TUI path: input comes from Ink's onSubmit → InputQueue
|
|
768
|
+
inputSource = inputQueue;
|
|
769
|
+
}
|
|
770
|
+
else if (options._testInputSource) {
|
|
771
|
+
inputSource = options._testInputSource;
|
|
772
|
+
}
|
|
773
|
+
else {
|
|
774
|
+
// Imperative fallback: readline
|
|
775
|
+
const isTTY = process.stdin.isTTY === true;
|
|
776
|
+
rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: isTTY });
|
|
777
|
+
inputCtrl = new InputController(rl);
|
|
778
|
+
inputSource = rl;
|
|
779
|
+
process.stdout.write(CLI_PROMPT);
|
|
780
|
+
}
|
|
781
|
+
for await (const input of inputSource) {
|
|
644
782
|
if (closed)
|
|
645
783
|
break;
|
|
646
|
-
if (!input.trim())
|
|
647
|
-
process.stdout.write(CLI_PROMPT);
|
|
784
|
+
if (!input.trim())
|
|
648
785
|
continue;
|
|
649
|
-
|
|
786
|
+
// Remove from TUI queue display as the agent picks up this message
|
|
787
|
+
tuiStore?.dequeueInput(input);
|
|
650
788
|
// Optional input gate (e.g. trust gate in main)
|
|
651
789
|
if (options.onInput) {
|
|
652
790
|
const gate = options.onInput(input);
|
|
653
791
|
if (!gate.allowed) {
|
|
654
792
|
if (gate.reply) {
|
|
655
|
-
|
|
793
|
+
display.text(gate.reply);
|
|
656
794
|
}
|
|
657
795
|
if (closed)
|
|
658
796
|
break;
|
|
659
|
-
process.stdout.write(CLI_PROMPT);
|
|
660
797
|
continue;
|
|
661
798
|
}
|
|
662
799
|
}
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
if (
|
|
669
|
-
|
|
800
|
+
await options.onTurnStart?.(messages);
|
|
801
|
+
try {
|
|
802
|
+
// Check for slash commands (legacy path only — pipeline handles commands for runTurn path)
|
|
803
|
+
if (!options.runTurn) {
|
|
804
|
+
const parsed = (0, commands_1.parseSlashCommand)(input);
|
|
805
|
+
if (parsed) {
|
|
806
|
+
const dispatchResult = registry.dispatch(parsed.command, { channel: "cli" });
|
|
807
|
+
if (dispatchResult.handled && dispatchResult.result) {
|
|
808
|
+
if (dispatchResult.result.action === "exit") {
|
|
809
|
+
break;
|
|
810
|
+
}
|
|
811
|
+
else if (dispatchResult.result.action === "response") {
|
|
812
|
+
display.text(dispatchResult.result.message || "");
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
670
816
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
817
|
+
}
|
|
818
|
+
// Track user message in TUI for display
|
|
819
|
+
if (tuiStore)
|
|
820
|
+
tuiStore.addUserMessage(input);
|
|
821
|
+
currentAbort = new AbortController();
|
|
822
|
+
if (tuiStore)
|
|
823
|
+
tuiStore.suppressInput();
|
|
824
|
+
inputCtrl?.suppress(() => { currentAbort?.abort(); });
|
|
825
|
+
// Resolve pending image content before the turn executes
|
|
826
|
+
let contentParts = null;
|
|
827
|
+
const currentImages = pendingImages;
|
|
828
|
+
if (currentImages && currentImages.size > 0) {
|
|
829
|
+
contentParts = await (0, image_paste_1.resolveImageContent)(input, currentImages);
|
|
830
|
+
pendingImages = null;
|
|
831
|
+
}
|
|
832
|
+
let result;
|
|
833
|
+
try {
|
|
834
|
+
if (options.runTurn) {
|
|
835
|
+
// Pipeline-based turn: the runTurn callback handles user message assembly,
|
|
836
|
+
// pending drain, trust gate, runAgent, postTurn, and token accumulation.
|
|
837
|
+
result = await options.runTurn(messages, input, cliCallbacks, currentAbort.signal, effectiveToolContext, contentParts ?? undefined);
|
|
838
|
+
// Handle pipeline-intercepted commands with loop-control side effects
|
|
839
|
+
if (result?.turnOutcome === "command") {
|
|
840
|
+
if (result.commandAction === "exit") {
|
|
841
|
+
break;
|
|
842
|
+
}
|
|
843
|
+
// For "response" commands: the pipeline already emitted the response via onTextChunk
|
|
844
|
+
cliCallbacks.flushMarkdown();
|
|
845
|
+
continue;
|
|
846
|
+
}
|
|
679
847
|
}
|
|
680
|
-
else
|
|
681
|
-
//
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
848
|
+
else {
|
|
849
|
+
// Legacy path: inline runAgent (used by serpent guide and tests)
|
|
850
|
+
const prefix = options.getContentPrefix?.();
|
|
851
|
+
const userContent = contentParts
|
|
852
|
+
? contentParts
|
|
853
|
+
: (prefix ? `${prefix}\n\n${input}` : input);
|
|
854
|
+
const userMsg = { role: "user", content: userContent };
|
|
855
|
+
(0, session_events_1.stampIngressTime)(userMsg);
|
|
856
|
+
messages.push(userMsg);
|
|
857
|
+
const traceId = (0, nerves_1.createTraceId)();
|
|
858
|
+
result = await (0, core_1.runAgent)(messages, cliCallbacks, options.skipSystemPromptRefresh ? undefined : "cli", currentAbort.signal, {
|
|
859
|
+
toolChoiceRequired: getEffectiveToolChoiceRequired(),
|
|
860
|
+
traceId,
|
|
861
|
+
tools: options.tools,
|
|
862
|
+
execTool: wrappedExecTool,
|
|
863
|
+
toolContext: effectiveToolContext,
|
|
864
|
+
});
|
|
685
865
|
}
|
|
686
866
|
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
addHistory(history, input);
|
|
692
|
-
currentAbort = new AbortController();
|
|
693
|
-
ctrl.suppress(() => currentAbort.abort());
|
|
694
|
-
let result;
|
|
695
|
-
try {
|
|
696
|
-
if (options.runTurn) {
|
|
697
|
-
// Pipeline-based turn: the runTurn callback handles user message assembly,
|
|
698
|
-
// pending drain, trust gate, runAgent, postTurn, and token accumulation.
|
|
699
|
-
result = await options.runTurn(messages, input, cliCallbacks, currentAbort.signal, effectiveToolContext);
|
|
867
|
+
catch (err) {
|
|
868
|
+
if (!(err instanceof DOMException && err.name === "AbortError")) {
|
|
869
|
+
display.error(err instanceof Error ? err.message : String(err));
|
|
870
|
+
}
|
|
700
871
|
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
});
|
|
872
|
+
cliCallbacks.flushMarkdown();
|
|
873
|
+
if (!tuiStore)
|
|
874
|
+
process.stdout.write("\n"); // ensure response ends with newline before prompt (imperative only)
|
|
875
|
+
if (tuiStore)
|
|
876
|
+
tuiStore.restoreInput();
|
|
877
|
+
inputCtrl?.restore();
|
|
878
|
+
currentAbort = null;
|
|
879
|
+
// Check if exit tool was fired during this turn
|
|
880
|
+
if (exitToolFired) {
|
|
881
|
+
exitReason = "tool_exit";
|
|
882
|
+
break;
|
|
713
883
|
}
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
884
|
+
// Safety net: never silently swallow an empty response
|
|
885
|
+
const lastMsg = messages[messages.length - 1];
|
|
886
|
+
if (lastMsg?.role === "assistant" && !(typeof lastMsg.content === "string" ? lastMsg.content : "").trim()) {
|
|
887
|
+
display.warn("(empty response)");
|
|
888
|
+
}
|
|
889
|
+
// Post-turn hook (session persistence, pending drain, prompt refresh, etc.)
|
|
890
|
+
if (options.onTurnEnd) {
|
|
891
|
+
await options.onTurnEnd(messages, result ?? { usage: undefined });
|
|
720
892
|
}
|
|
721
893
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
currentAbort = null;
|
|
725
|
-
// Check if exit tool was fired during this turn
|
|
726
|
-
if (exitToolFired) {
|
|
727
|
-
exitReason = "tool_exit";
|
|
728
|
-
break;
|
|
729
|
-
}
|
|
730
|
-
// Safety net: never silently swallow an empty response
|
|
731
|
-
const lastMsg = messages[messages.length - 1];
|
|
732
|
-
if (lastMsg?.role === "assistant" && !(typeof lastMsg.content === "string" ? lastMsg.content : "").trim()) {
|
|
733
|
-
process.stderr.write("\x1b[33m(empty response)\x1b[0m\n");
|
|
734
|
-
}
|
|
735
|
-
process.stdout.write("\n\n");
|
|
736
|
-
// Post-turn hook (session persistence, pending drain, prompt refresh, etc.)
|
|
737
|
-
if (options.onTurnEnd) {
|
|
738
|
-
await options.onTurnEnd(messages, result ?? { usage: undefined });
|
|
894
|
+
finally {
|
|
895
|
+
await options.onTurnFinish?.();
|
|
739
896
|
}
|
|
740
897
|
if (closed)
|
|
741
898
|
break;
|
|
742
|
-
process.stdout.write(CLI_PROMPT);
|
|
743
899
|
}
|
|
744
900
|
}
|
|
745
901
|
finally {
|
|
746
|
-
rl
|
|
902
|
+
rl?.close();
|
|
903
|
+
if (inkRef) {
|
|
904
|
+
// Suppress React "state update on unmounted component" warnings during cleanup.
|
|
905
|
+
// Ink's useInput hook fires after unmount — this is harmless but noisy.
|
|
906
|
+
// This also covers the SerpentGuide exitOnToolCall path, which aborts the
|
|
907
|
+
// current request and breaks out of the loop into this finally block.
|
|
908
|
+
// eslint-disable-next-line no-console -- intentional console.warn/error override for cleanup
|
|
909
|
+
const origWarn = console.warn;
|
|
910
|
+
const origError = console.error; // eslint-disable-line no-console
|
|
911
|
+
// eslint-disable-next-line no-console -- suppress React unmount warnings
|
|
912
|
+
console.warn = (...args) => { if (typeof args[0] === "string" && args[0].includes("Can't perform a React state update"))
|
|
913
|
+
return; origWarn.apply(console, args); };
|
|
914
|
+
// eslint-disable-next-line no-console -- suppress React unmount warnings
|
|
915
|
+
console.error = (...args) => { if (typeof args[0] === "string" && args[0].includes("Can't perform a React state update"))
|
|
916
|
+
return; origError.apply(console, args); };
|
|
917
|
+
inkRef.unmount();
|
|
918
|
+
setTimeout(() => { console.warn = origWarn; console.error = origError; }, 100); // eslint-disable-line no-console
|
|
919
|
+
}
|
|
747
920
|
if (options.banner !== false) {
|
|
748
921
|
// eslint-disable-next-line no-console -- terminal UX: goodbye
|
|
749
922
|
console.log("bye");
|
|
@@ -756,20 +929,35 @@ async function main(agentName, options) {
|
|
|
756
929
|
if (agentName)
|
|
757
930
|
(0, identity_1.setAgentName)(agentName);
|
|
758
931
|
const pasteDebounceMs = options?.pasteDebounceMs ?? 50;
|
|
932
|
+
// Safety net: process-level SIGINT handler ensures Ctrl+C always exits,
|
|
933
|
+
// even when Ink's event loop is blocked by expensive renders.
|
|
934
|
+
/* v8 ignore start -- process signal handler @preserve */
|
|
935
|
+
let sigintCount = 0;
|
|
936
|
+
const sigintHandler = () => {
|
|
937
|
+
sigintCount++;
|
|
938
|
+
if (sigintCount >= 2)
|
|
939
|
+
process.exit(1);
|
|
940
|
+
};
|
|
941
|
+
if (!options?._testInputSource) {
|
|
942
|
+
process.on("SIGINT", sigintHandler);
|
|
943
|
+
}
|
|
944
|
+
/* v8 ignore stop */
|
|
759
945
|
// Register spinner hooks so log output clears the spinner before printing
|
|
760
946
|
(0, nerves_1.registerSpinnerHooks)(pauseActiveSpinner, resumeActiveSpinner);
|
|
761
947
|
// Fallback: apply pending updates for daemon-less direct CLI usage
|
|
762
948
|
(0, update_hooks_1.registerUpdateHook)(bundle_meta_1.bundleMetaHook);
|
|
949
|
+
(0, update_hooks_1.registerUpdateHook)(agent_config_v2_1.agentConfigV2Hook);
|
|
763
950
|
await (0, update_hooks_1.applyPendingUpdates)((0, identity_1.getAgentBundlesRoot)(), (0, bundle_manifest_1.getPackageVersion)());
|
|
764
951
|
// Fail fast if provider is misconfigured (triggers human-readable error + exit)
|
|
765
|
-
(0, core_1.getProvider)();
|
|
952
|
+
(0, core_1.getProvider)("human");
|
|
766
953
|
// Resolve context kernel (identity + channel) for CLI
|
|
767
|
-
const
|
|
768
|
-
const
|
|
954
|
+
const currentAgentName = (0, identity_1.getAgentName)();
|
|
955
|
+
const owner = { agentName: currentAgentName, agentRoot: (0, identity_1.getAgentRoot)(currentAgentName) };
|
|
956
|
+
const friendsPath = path.join(owner.agentRoot, "friends");
|
|
957
|
+
const friendStore = new friends_1.FileFriendStore(friendsPath);
|
|
769
958
|
const username = os.userInfo().username;
|
|
770
|
-
const
|
|
771
|
-
const
|
|
772
|
-
const resolver = new resolver_1.FriendResolver(friendStore, {
|
|
959
|
+
const localExternalId = username;
|
|
960
|
+
const resolver = new friends_1.FriendResolver(friendStore, {
|
|
773
961
|
provider: "local",
|
|
774
962
|
externalId: localExternalId,
|
|
775
963
|
displayName: username,
|
|
@@ -783,94 +971,167 @@ async function main(agentName, options) {
|
|
|
783
971
|
sinks: agentConfig.logging?.sinks,
|
|
784
972
|
});
|
|
785
973
|
const sessPath = (0, config_1.sessionPath)(friendId, "cli", "session");
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
}
|
|
796
|
-
throw error;
|
|
797
|
-
/* v8 ignore stop */
|
|
798
|
-
}
|
|
799
|
-
// Load existing session or start fresh
|
|
800
|
-
const existing = (0, context_1.loadSession)(sessPath);
|
|
801
|
-
let sessionState = existing?.state;
|
|
802
|
-
const mcpManager = await (0, mcp_manager_1.getSharedMcpManager)() ?? undefined;
|
|
803
|
-
const sessionMessages = existing?.messages && existing.messages.length > 0
|
|
804
|
-
? existing.messages
|
|
805
|
-
: [{ role: "system", content: await (0, prompt_1.buildSystem)("cli", { mcpManager }, resolvedContext) }];
|
|
974
|
+
const acquireTurnLease = options?._acquireSessionTurnLease ?? session_transaction_1.acquireSessionTurnLease;
|
|
975
|
+
let sessionTurnLease = null;
|
|
976
|
+
let pendingPersists = [];
|
|
977
|
+
let existing = null;
|
|
978
|
+
let sessionState;
|
|
979
|
+
let sessionEvents = [];
|
|
980
|
+
const sessionMessages = [
|
|
981
|
+
{ role: "system", content: (0, prompt_1.flattenSystemPrompt)(await (0, prompt_1.buildSystem)("cli", {}, resolvedContext)) },
|
|
982
|
+
];
|
|
806
983
|
// Per-turn pipeline input: CLI capabilities and pending dir
|
|
807
|
-
const cliCapabilities = (0,
|
|
808
|
-
const currentAgentName = (0, identity_1.getAgentName)();
|
|
984
|
+
const cliCapabilities = (0, friends_1.getChannelCapabilities)("cli");
|
|
809
985
|
const pendingDir = (0, pending_1.getPendingDir)(currentAgentName, friendId, "cli", "session");
|
|
810
|
-
const summarize = (0, core_1.createSummarize)();
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
messages
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
986
|
+
const summarize = (0, core_1.createSummarize)("human");
|
|
987
|
+
const cliFailoverState = { pending: null };
|
|
988
|
+
await runCliSession({
|
|
989
|
+
agentName: currentAgentName,
|
|
990
|
+
pasteDebounceMs,
|
|
991
|
+
messages: sessionMessages,
|
|
992
|
+
lastActivityAt: sessionState?.lastFriendActivityAt,
|
|
993
|
+
_testInputSource: options?._testInputSource,
|
|
994
|
+
onTurnStart: async (messages) => {
|
|
995
|
+
sessionTurnLease = await acquireTurnLease(sessPath);
|
|
996
|
+
try {
|
|
997
|
+
pendingPersists = [];
|
|
998
|
+
existing = (0, context_1.loadSession)(sessPath);
|
|
999
|
+
sessionState = existing?.state;
|
|
1000
|
+
sessionEvents = existing?.events ?? [];
|
|
1001
|
+
const loadedMessages = existing?.messages && existing.messages.length > 0
|
|
1002
|
+
? existing.messages
|
|
1003
|
+
: [{ role: "system", content: (0, prompt_1.flattenSystemPrompt)(await (0, prompt_1.buildSystem)("cli", {}, resolvedContext)) }];
|
|
1004
|
+
(0, core_1.repairOrphanedToolCalls)(loadedMessages);
|
|
1005
|
+
messages.splice(0, messages.length, ...loadedMessages);
|
|
1006
|
+
}
|
|
1007
|
+
catch (error) {
|
|
1008
|
+
const lease = sessionTurnLease;
|
|
1009
|
+
sessionTurnLease = null;
|
|
1010
|
+
await lease.release();
|
|
1011
|
+
throw error;
|
|
1012
|
+
}
|
|
1013
|
+
},
|
|
1014
|
+
onTurnFinish: async () => {
|
|
1015
|
+
try {
|
|
1016
|
+
await Promise.all(pendingPersists);
|
|
1017
|
+
}
|
|
1018
|
+
finally {
|
|
1019
|
+
const lease = sessionTurnLease;
|
|
1020
|
+
sessionTurnLease = null;
|
|
1021
|
+
await lease.release();
|
|
1022
|
+
}
|
|
1023
|
+
},
|
|
1024
|
+
onAsyncAssistantMessage: async (messages, _assistantMessage) => {
|
|
1025
|
+
const prepared = (0, context_1.postTurnTrim)(messages);
|
|
1026
|
+
const events = (0, context_1.postTurnPersist)(sessPath, prepared, undefined, sessionState, sessionTurnLease ?? undefined);
|
|
1027
|
+
/* v8 ignore next -- defensive: postTurnPersist always returns events in practice @preserve */
|
|
1028
|
+
sessionEvents = events.length > 0 ? events : sessionEvents;
|
|
1029
|
+
},
|
|
1030
|
+
runTurn: async (messages, userInput, callbacks, signal, toolContext, userContent) => {
|
|
1031
|
+
// Run the full per-turn pipeline: resolve -> gate -> session -> drain -> runAgent -> postTurn -> tokens
|
|
1032
|
+
// User message passed via input.messages so the pipeline can prepend pending messages to it.
|
|
1033
|
+
const failoverState = cliFailoverState;
|
|
1034
|
+
// Capture terminal errors instead of displaying immediately — the failover
|
|
1035
|
+
// message replaces the raw error if failover triggers successfully.
|
|
1036
|
+
let capturedTerminalError = null;
|
|
1037
|
+
/* v8 ignore start -- failover-aware callback wrapper: tested via pipeline integration @preserve */
|
|
1038
|
+
const failoverAwareCallbacks = {
|
|
1039
|
+
...callbacks,
|
|
1040
|
+
// Save session after each tool result for crash recovery (deferred to avoid blocking)
|
|
1041
|
+
onToolResult: (turnMessages) => {
|
|
1042
|
+
const prepared = (0, context_1.postTurnTrim)(turnMessages);
|
|
1043
|
+
pendingPersists.push((0, context_1.deferPostTurnPersist)(sessPath, prepared, undefined, sessionState, sessionTurnLease ?? undefined));
|
|
1044
|
+
},
|
|
1045
|
+
onError: (error, severity) => {
|
|
1046
|
+
if (severity === "terminal" && failoverState) {
|
|
1047
|
+
capturedTerminalError = error;
|
|
1048
|
+
callbacks.onError(new Error(""), "transient");
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
callbacks.onError(error, severity);
|
|
1052
|
+
},
|
|
1053
|
+
};
|
|
1054
|
+
/* v8 ignore stop */
|
|
1055
|
+
const result = await (0, pipeline_1.handleInboundTurn)({
|
|
1056
|
+
channel: "cli",
|
|
1057
|
+
sessionKey: "session",
|
|
1058
|
+
capabilities: cliCapabilities,
|
|
1059
|
+
messages: [{ role: "user", content: userContent ?? userInput }],
|
|
1060
|
+
continuityIngressTexts: getCliContinuityIngressTexts(userInput),
|
|
1061
|
+
callbacks: failoverAwareCallbacks,
|
|
1062
|
+
sessionTurnLease: sessionTurnLease,
|
|
1063
|
+
friendResolver: { resolve: () => Promise.resolve(resolvedContext) },
|
|
1064
|
+
sessionLoader: {
|
|
1065
|
+
loadOrCreate: () => Promise.resolve({
|
|
1066
|
+
messages,
|
|
1067
|
+
sessionPath: sessPath,
|
|
1068
|
+
state: sessionState,
|
|
1069
|
+
events: sessionEvents,
|
|
1070
|
+
structuredOutputs: existing?.structuredOutputs,
|
|
846
1071
|
}),
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
1072
|
+
},
|
|
1073
|
+
pendingDir,
|
|
1074
|
+
friendStore,
|
|
1075
|
+
provider: "local",
|
|
1076
|
+
externalId: localExternalId,
|
|
1077
|
+
enforceTrustGate: trust_gate_1.enforceTrustGate,
|
|
1078
|
+
drainPending: pending_1.drainPending,
|
|
1079
|
+
drainDeferredReturns: (deferredFriendId) => (0, pending_1.drainDeferredReturns)(currentAgentName, deferredFriendId),
|
|
1080
|
+
runAgent: async (msgs, cb, channel, sig, opts) => (0, core_1.runAgent)(msgs, cb, channel, sig, {
|
|
1081
|
+
...opts,
|
|
1082
|
+
mcpManager: opts?.hardDisableTools ? undefined : await (0, mcp_manager_1.getSharedMcpManager)(owner) ?? undefined,
|
|
1083
|
+
toolContext: {
|
|
1084
|
+
/* v8 ignore next -- default no-op signin; pipeline provides the real one @preserve */
|
|
1085
|
+
signin: async () => undefined,
|
|
1086
|
+
...opts?.toolContext,
|
|
1087
|
+
...owner,
|
|
1088
|
+
summarize,
|
|
850
1089
|
},
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
1090
|
+
}),
|
|
1091
|
+
postTurn: (turnMessages, sessionPathArg, usage, hooks, state) => {
|
|
1092
|
+
// Trim synchronously (mutates turnMessages for next turn),
|
|
1093
|
+
// then defer envelope build + disk I/O to avoid blocking the TUI.
|
|
1094
|
+
const prepared = (0, context_1.postTurnTrim)(turnMessages, usage, hooks);
|
|
1095
|
+
sessionState = state;
|
|
1096
|
+
const persist = (0, context_1.deferPostTurnPersist)(sessionPathArg, prepared, usage, state, sessionTurnLease ?? undefined).then((events) => {
|
|
1097
|
+
/* v8 ignore next -- defensive: deferPostTurnPersist always resolves events in practice @preserve */
|
|
1098
|
+
sessionEvents = events.length > 0 ? events : sessionEvents;
|
|
1099
|
+
});
|
|
1100
|
+
pendingPersists.push(persist);
|
|
1101
|
+
},
|
|
1102
|
+
accumulateFriendTokens: friends_1.accumulateFriendTokens,
|
|
1103
|
+
signal,
|
|
1104
|
+
runAgentOptions: {
|
|
1105
|
+
toolChoiceRequired: (0, commands_1.getToolChoiceRequired)(),
|
|
1106
|
+
traceId: (0, nerves_1.createTraceId)(),
|
|
1107
|
+
toolContext,
|
|
1108
|
+
},
|
|
1109
|
+
failoverState,
|
|
1110
|
+
});
|
|
1111
|
+
/* v8 ignore start -- failover display: tested via pipeline integration tests @preserve */
|
|
1112
|
+
if (result.failoverMessage) {
|
|
1113
|
+
// Failover handled it — show the actionable message instead of the raw error
|
|
1114
|
+
process.stdout.write(`\x1b[33m${result.failoverMessage}\x1b[0m\n`);
|
|
1115
|
+
}
|
|
1116
|
+
else if (capturedTerminalError) {
|
|
1117
|
+
// Failover didn't trigger (no failoverState, or sequence failed) — show the raw error
|
|
1118
|
+
process.stderr.write(`\x1b[31m${(0, format_1.formatError)(capturedTerminalError)}\x1b[0m\n`);
|
|
1119
|
+
}
|
|
1120
|
+
/* v8 ignore stop */
|
|
1121
|
+
// Handle gate rejection: display auto-reply if present
|
|
1122
|
+
if (!result.gateResult.allowed) {
|
|
1123
|
+
if ("autoReply" in result.gateResult && result.gateResult.autoReply) {
|
|
1124
|
+
process.stdout.write(`${result.gateResult.autoReply}\n`);
|
|
865
1125
|
}
|
|
866
|
-
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
1126
|
+
}
|
|
1127
|
+
return { usage: result.usage, turnOutcome: result.turnOutcome, commandAction: result.commandAction };
|
|
1128
|
+
},
|
|
1129
|
+
});
|
|
1130
|
+
// Force exit: lingering handles (Ink cleanup timers, MCP connections) keep the
|
|
1131
|
+
// event loop alive after the interactive session ends. This is safe because all
|
|
1132
|
+
// session persistence has already completed in the finally block above.
|
|
1133
|
+
/* v8 ignore next -- process.exit not callable in vitest @preserve */
|
|
1134
|
+
if (!options?._testInputSource)
|
|
1135
|
+
process.exit(0);
|
|
876
1136
|
}
|
|
1137
|
+
// CI trigger
|