@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
package/dist/senses/pipeline.js
CHANGED
|
@@ -4,58 +4,300 @@
|
|
|
4
4
|
// resolve friend -> trust gate -> load session -> drain pending -> runAgent -> postTurn -> token accumulation.
|
|
5
5
|
//
|
|
6
6
|
// Transport-level concerns (BB API calls, Teams cards, readline) stay in sense adapters.
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
7
40
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.emitObligationTransitionEpisodes = emitObligationTransitionEpisodes;
|
|
8
42
|
exports.handleInboundTurn = handleInboundTurn;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
9
45
|
const runtime_1 = require("../nerves/runtime");
|
|
46
|
+
const commands_1 = require("./commands");
|
|
10
47
|
const continuity_1 = require("./continuity");
|
|
11
48
|
const manager_1 = require("../heart/bridges/manager");
|
|
12
49
|
const identity_1 = require("../heart/identity");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
50
|
+
const auth_flow_1 = require("../heart/auth/auth-flow");
|
|
51
|
+
const socket_client_1 = require("../heart/daemon/socket-client");
|
|
15
52
|
const active_work_1 = require("../heart/active-work");
|
|
16
53
|
const delegation_1 = require("../heart/delegation");
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
54
|
+
const obligations_1 = require("../arc/obligations");
|
|
55
|
+
const provider_failover_1 = require("../heart/provider-failover");
|
|
56
|
+
const tempo_1 = require("../heart/tempo");
|
|
57
|
+
const temporal_view_1 = require("../heart/temporal-view");
|
|
58
|
+
const start_of_turn_packet_1 = require("../heart/start-of-turn-packet");
|
|
59
|
+
const bundle_state_1 = require("../heart/bundle-state");
|
|
60
|
+
const sync_1 = require("../heart/sync");
|
|
61
|
+
const config_1 = require("../heart/config");
|
|
62
|
+
const session_events_1 = require("../heart/session-events");
|
|
63
|
+
const presence_1 = require("../arc/presence");
|
|
64
|
+
const episodes_1 = require("../arc/episodes");
|
|
65
|
+
const turn_context_1 = require("../heart/turn-context");
|
|
66
|
+
const provider_visibility_1 = require("../heart/provider-visibility");
|
|
67
|
+
/**
|
|
68
|
+
* Emit episodes for obligation state transitions detected during a turn.
|
|
69
|
+
* Exported for direct testability (avoids v8 coverage merge issues in multi-file test suites).
|
|
70
|
+
*/
|
|
71
|
+
function emitObligationTransitionEpisodes(agentRoot, preTurnObligationIds, postTurnObligations, preTurnObligations) {
|
|
72
|
+
const postTurnObligationIds = new Set(postTurnObligations.map((ob) => `${ob.id}:${ob.status}`));
|
|
73
|
+
for (const key of preTurnObligationIds) {
|
|
74
|
+
if (!postTurnObligationIds.has(key)) {
|
|
75
|
+
const [obId] = key.split(":");
|
|
76
|
+
const matchedOb = postTurnObligations.find((ob) => ob.id === obId) ?? preTurnObligations.find((ob) => ob.id === obId);
|
|
77
|
+
(0, episodes_1.emitEpisode)(agentRoot, {
|
|
78
|
+
kind: "obligation_shift",
|
|
79
|
+
summary: `obligation "${matchedOb?.content ?? obId}" status changed`,
|
|
80
|
+
whyItMattered: "obligation state transition detected during turn",
|
|
81
|
+
relatedEntities: [`obligation:${obId}`],
|
|
82
|
+
salience: "medium",
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function providerLaneForChannel(channel) {
|
|
88
|
+
return channel === "inner" ? "inner" : "outward";
|
|
89
|
+
}
|
|
90
|
+
function resolveCurrentFailoverBinding(agentName, lane) {
|
|
91
|
+
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
92
|
+
const { config: agentConfig } = (0, auth_flow_1.readAgentConfigForAgent)(agentName, path.dirname(agentRoot));
|
|
93
|
+
const fallback = lane === "inner" ? agentConfig.agentFacing : agentConfig.humanFacing;
|
|
94
|
+
return { provider: fallback.provider, model: fallback.model };
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Apply an agent-driven failover switch to agent.json, but only after
|
|
98
|
+
* re-pinging the candidate. The inventory ping that produced the candidate
|
|
99
|
+
* may be stale by the time the agent replies — without this preflight, a
|
|
100
|
+
* "switch to <provider>" reply can move the lane onto an unreachable provider.
|
|
101
|
+
*
|
|
102
|
+
* Returns:
|
|
103
|
+
* { ok: true } — preflight passed, state mutated
|
|
104
|
+
* { ok: false, refused } — preflight failed, state untouched, caller should
|
|
105
|
+
* surface the refusal to the agent
|
|
106
|
+
* Throws on disk errors only (caught by caller as before).
|
|
107
|
+
*/
|
|
108
|
+
async function writeFailoverAgentConfigSwitch(agentName, action) {
|
|
109
|
+
const validation = await (0, provider_failover_1.validateFailoverSwitchCandidate)(agentName, { provider: action.provider, model: action.model });
|
|
110
|
+
if (!validation.ok) {
|
|
111
|
+
return { ok: false, refused: true, classification: validation.classification, message: validation.message };
|
|
112
|
+
}
|
|
113
|
+
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
114
|
+
const { configPath, config } = (0, auth_flow_1.readAgentConfigForAgent)(agentName, path.dirname(agentRoot));
|
|
115
|
+
const facingKey = action.lane === "inner" ? "agentFacing" : "humanFacing";
|
|
116
|
+
const nextConfig = {
|
|
117
|
+
...config,
|
|
118
|
+
[facingKey]: {
|
|
119
|
+
...config[facingKey],
|
|
120
|
+
provider: action.provider,
|
|
121
|
+
model: action.model,
|
|
32
122
|
},
|
|
33
|
-
actionRequired: [],
|
|
34
|
-
unresolvedDependencies: [],
|
|
35
|
-
activeSessions: [],
|
|
36
|
-
activeBridges: [],
|
|
37
123
|
};
|
|
124
|
+
fs.writeFileSync(configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, "utf-8");
|
|
125
|
+
return { ok: true };
|
|
38
126
|
}
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
127
|
+
function formatFailoverSwitchLabel(action) {
|
|
128
|
+
const provenance = (0, provider_failover_1.formatCredentialProvenanceLabel)(action);
|
|
129
|
+
return `${action.provider} (${action.model}${provenance ? `; ${provenance}` : ""})`;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Build the operational refusal context message handed back to the agent when
|
|
133
|
+
* a failover switch is rejected by the preflight ping. Slugger-tested format:
|
|
134
|
+
* lead with the refusal + reason, restate the lane that's still standing, then
|
|
135
|
+
* list remaining ready alternatives so the next turn doesn't have to re-enter
|
|
136
|
+
* discovery mode.
|
|
137
|
+
*/
|
|
138
|
+
function buildFailoverSwitchRefusedMessage(pendingContext, refusedAction, refusal) {
|
|
139
|
+
const refusedLabel = formatFailoverSwitchLabel(refusedAction);
|
|
140
|
+
const remaining = pendingContext.readyProviders.filter((candidate) => candidate.provider !== refusedAction.provider);
|
|
141
|
+
const alternativesLine = remaining.length > 0
|
|
142
|
+
? `available verified alternatives right now: ${remaining.map((c) => `${c.provider} (${c.model})`).join(", ")}.`
|
|
143
|
+
: "no other verified alternatives are ready right now.";
|
|
144
|
+
const nextMove = remaining.length > 0
|
|
145
|
+
? `next move: reply "switch to <provider>" picking one of the alternatives above, or tell the user you cannot continue and why.`
|
|
146
|
+
: `next move: ask the operator to repair credentials for ${refusedAction.provider} (or another provider), or tell the user you cannot continue and why.`;
|
|
147
|
+
return [
|
|
148
|
+
`[provider switch refused: tried to switch ${refusedAction.lane} lane to ${refusedLabel}.`,
|
|
149
|
+
`reason: preflight ping failed (${refusal.classification}: ${refusal.message}).`,
|
|
150
|
+
`current lane unchanged: ${pendingContext.currentProvider} / ${pendingContext.currentModel} on the ${pendingContext.currentLane} lane.`,
|
|
151
|
+
alternativesLine,
|
|
152
|
+
nextMove + "]",
|
|
153
|
+
].join(" ");
|
|
154
|
+
}
|
|
155
|
+
function prependTurnSections(message, sections) {
|
|
156
|
+
/* v8 ignore next -- defensive: only user messages with non-empty sections reach here @preserve */
|
|
157
|
+
if (message.role !== "user" || sections.length === 0)
|
|
158
|
+
return message;
|
|
159
|
+
const prefix = sections.join("\n\n");
|
|
160
|
+
/* v8 ignore start -- defensive: multipart content branch; non-string user messages are rare @preserve */
|
|
161
|
+
if (typeof message.content === "string") {
|
|
51
162
|
return {
|
|
52
|
-
|
|
53
|
-
|
|
163
|
+
...message,
|
|
164
|
+
content: `${prefix}\n\n${message.content}`,
|
|
54
165
|
};
|
|
55
166
|
}
|
|
167
|
+
return {
|
|
168
|
+
...message,
|
|
169
|
+
content: [
|
|
170
|
+
{ type: "text", text: `${prefix}\n\n` },
|
|
171
|
+
...message.content,
|
|
172
|
+
],
|
|
173
|
+
};
|
|
174
|
+
/* v8 ignore stop */
|
|
56
175
|
}
|
|
57
176
|
// ── Pipeline ──────────────────────────────────────────────────────
|
|
177
|
+
let _lastSessionKey = null;
|
|
58
178
|
async function handleInboundTurn(input) {
|
|
179
|
+
// Reset session-scoped state when the session changes
|
|
180
|
+
const sessionKey = `${input.channel}/${input.sessionKey ?? "session"}`;
|
|
181
|
+
if (sessionKey !== _lastSessionKey) {
|
|
182
|
+
_lastSessionKey = sessionKey;
|
|
183
|
+
// Reset file-state cache and scrutiny tracking for the new session
|
|
184
|
+
const { fileStateCache } = await Promise.resolve().then(() => __importStar(require("../mind/file-state")));
|
|
185
|
+
const { resetSessionModifiedFiles } = await Promise.resolve().then(() => __importStar(require("../mind/scrutiny")));
|
|
186
|
+
fileStateCache.clear();
|
|
187
|
+
resetSessionModifiedFiles();
|
|
188
|
+
}
|
|
189
|
+
// Step 0: Check for pending failover reply
|
|
190
|
+
if (input.failoverState?.pending) {
|
|
191
|
+
const userText = input.messages
|
|
192
|
+
.filter((m) => m.role === "user")
|
|
193
|
+
.map((m) => typeof m.content === "string" ? m.content : /* v8 ignore next -- defensive: multipart content fallback @preserve */ "")
|
|
194
|
+
.join(" ")
|
|
195
|
+
.trim();
|
|
196
|
+
const pendingContext = input.failoverState.pending;
|
|
197
|
+
const failoverAction = (0, provider_failover_1.handleFailoverReply)(userText, pendingContext);
|
|
198
|
+
const failoverAgentName = pendingContext.agentName;
|
|
199
|
+
input.failoverState.pending = null; // always clear before acting
|
|
200
|
+
if (failoverAction.action === "switch") {
|
|
201
|
+
let switchOutcome = null;
|
|
202
|
+
try {
|
|
203
|
+
switchOutcome = await writeFailoverAgentConfigSwitch(failoverAgentName, failoverAction);
|
|
204
|
+
/* v8 ignore start -- defensive: write failure during provider switch @preserve */
|
|
205
|
+
}
|
|
206
|
+
catch (switchError) {
|
|
207
|
+
(0, runtime_1.emitNervesEvent)({
|
|
208
|
+
level: "error",
|
|
209
|
+
component: "senses",
|
|
210
|
+
event: "senses.failover_switch_error",
|
|
211
|
+
message: `failed to switch ${failoverAction.lane} provider lane to ${failoverAction.provider}`,
|
|
212
|
+
meta: { agentName: failoverAgentName, lane: failoverAction.lane, provider: failoverAction.provider, model: failoverAction.model, error: switchError instanceof Error ? switchError.message : String(switchError) },
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
/* v8 ignore stop */
|
|
216
|
+
if (switchOutcome?.ok) {
|
|
217
|
+
(0, runtime_1.emitNervesEvent)({
|
|
218
|
+
component: "senses",
|
|
219
|
+
event: "senses.failover_switch",
|
|
220
|
+
message: `switched ${failoverAction.lane} provider lane to ${failoverAction.provider} via failover`,
|
|
221
|
+
meta: {
|
|
222
|
+
agentName: failoverAgentName,
|
|
223
|
+
lane: failoverAction.lane,
|
|
224
|
+
provider: failoverAction.provider,
|
|
225
|
+
model: failoverAction.model,
|
|
226
|
+
credentialRevision: failoverAction.credentialRevision,
|
|
227
|
+
source: failoverAction.source,
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
// Replace "switch to <provider>" with a context message for the agent.
|
|
231
|
+
// The session already has the user's original question from the failed turn.
|
|
232
|
+
// The agent needs to know what happened so it can respond appropriately.
|
|
233
|
+
const newProviderLabel = formatFailoverSwitchLabel(failoverAction);
|
|
234
|
+
input.messages = [{
|
|
235
|
+
role: "user",
|
|
236
|
+
content: `[provider switch: ${pendingContext.errorSummary}. switched ${failoverAction.lane} lane to ${newProviderLabel}. your conversation history is intact — respond to the user's last message.]`,
|
|
237
|
+
}];
|
|
238
|
+
input.switchedProvider = failoverAction.provider;
|
|
239
|
+
}
|
|
240
|
+
else if (switchOutcome && !switchOutcome.ok) {
|
|
241
|
+
// Preflight refused the switch — the candidate provider is not actually
|
|
242
|
+
// reachable right now. Keep the existing lane intact and tell the agent
|
|
243
|
+
// what happened so it can pick something else next turn.
|
|
244
|
+
(0, runtime_1.emitNervesEvent)({
|
|
245
|
+
level: "warn",
|
|
246
|
+
component: "senses",
|
|
247
|
+
event: "senses.failover_switch_refused",
|
|
248
|
+
message: `refused failover switch of ${failoverAction.lane} lane to ${failoverAction.provider}: ${switchOutcome.message}`,
|
|
249
|
+
meta: {
|
|
250
|
+
agentName: failoverAgentName,
|
|
251
|
+
lane: failoverAction.lane,
|
|
252
|
+
provider: failoverAction.provider,
|
|
253
|
+
model: failoverAction.model,
|
|
254
|
+
classification: switchOutcome.classification,
|
|
255
|
+
error: switchOutcome.message,
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
input.messages = [{
|
|
259
|
+
role: "user",
|
|
260
|
+
content: buildFailoverSwitchRefusedMessage(pendingContext, failoverAction, switchOutcome),
|
|
261
|
+
}];
|
|
262
|
+
}
|
|
263
|
+
// Switch failed OR succeeded — either way, fall through to normal processing.
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
// Step 0b: Slash command interception (before friend resolution / agent turn)
|
|
267
|
+
{
|
|
268
|
+
const firstUserMsg = input.messages.find((m) => m.role === "user");
|
|
269
|
+
const userText = firstUserMsg
|
|
270
|
+
? (typeof firstUserMsg.content === "string"
|
|
271
|
+
? firstUserMsg.content
|
|
272
|
+
: Array.isArray(firstUserMsg.content)
|
|
273
|
+
? firstUserMsg.content.find((p) => p.type === "text")?.text ?? ""
|
|
274
|
+
: /* v8 ignore next -- defensive: content is always string or array @preserve */ "")
|
|
275
|
+
: "";
|
|
276
|
+
const parsed = (0, commands_1.parseSlashCommand)(userText);
|
|
277
|
+
if (parsed) {
|
|
278
|
+
const registry = (0, commands_1.getSharedCommandRegistry)();
|
|
279
|
+
const dispatchResult = registry.dispatch(parsed.command, { channel: input.channel });
|
|
280
|
+
if (dispatchResult.handled && dispatchResult.result) {
|
|
281
|
+
(0, runtime_1.emitNervesEvent)({
|
|
282
|
+
component: "senses",
|
|
283
|
+
event: "senses.pipeline_command",
|
|
284
|
+
message: `slash command intercepted: /${parsed.command}`,
|
|
285
|
+
meta: { command: parsed.command, channel: input.channel },
|
|
286
|
+
});
|
|
287
|
+
if (dispatchResult.result.message) {
|
|
288
|
+
input.callbacks.onTextChunk(dispatchResult.result.message);
|
|
289
|
+
}
|
|
290
|
+
// Return a minimal result — no agent turn, no session write
|
|
291
|
+
const resolvedContext = await input.friendResolver.resolve();
|
|
292
|
+
return {
|
|
293
|
+
resolvedContext,
|
|
294
|
+
gateResult: { allowed: true },
|
|
295
|
+
turnOutcome: "command",
|
|
296
|
+
commandAction: dispatchResult.result.action,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
59
301
|
// Step 1: Resolve friend
|
|
60
302
|
const resolvedContext = await input.friendResolver.resolve();
|
|
61
303
|
(0, runtime_1.emitNervesEvent)({
|
|
@@ -101,6 +343,7 @@ async function handleInboundTurn(input) {
|
|
|
101
343
|
// Step 3: Load/create session
|
|
102
344
|
const session = await input.sessionLoader.loadOrCreate();
|
|
103
345
|
const sessionMessages = session.messages;
|
|
346
|
+
const sessionEvents = session.events ?? [];
|
|
104
347
|
let mustResolveBeforeHandoff = (0, continuity_1.resolveMustResolveBeforeHandoff)(session.state?.mustResolveBeforeHandoff === true, input.continuityIngressTexts);
|
|
105
348
|
const lastFriendActivityAt = input.channel === "inner"
|
|
106
349
|
? session.state?.lastFriendActivityAt
|
|
@@ -115,164 +358,289 @@ async function handleInboundTurn(input) {
|
|
|
115
358
|
key: input.sessionKey ?? "session",
|
|
116
359
|
sessionPath: session.sessionPath,
|
|
117
360
|
};
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
const bridgeContext = (0, manager_1.formatBridgeContext)(activeBridges) || undefined;
|
|
124
|
-
let sessionActivity = [];
|
|
361
|
+
const currentSessionTiming = (0, session_events_1.describeCurrentSessionTiming)(sessionEvents);
|
|
362
|
+
// Step 3b: Pre-turn sync pull (opt-in) — MUST happen before any continuity state reads
|
|
363
|
+
// so that obligations, episodes, cares, etc. reflect the latest remote state.
|
|
364
|
+
let syncFailure;
|
|
365
|
+
let syncConfig = { enabled: false, remote: "origin" };
|
|
125
366
|
try {
|
|
126
|
-
|
|
127
|
-
sessionActivity = (0, session_activity_1.listSessionActivity)({
|
|
128
|
-
sessionsDir: `${agentRoot}/state/sessions`,
|
|
129
|
-
friendsDir: `${agentRoot}/friends`,
|
|
130
|
-
agentName: (0, identity_1.getAgentName)(),
|
|
131
|
-
currentSession: {
|
|
132
|
-
friendId: currentSession.friendId,
|
|
133
|
-
channel: currentSession.channel,
|
|
134
|
-
key: currentSession.key,
|
|
135
|
-
},
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
catch {
|
|
139
|
-
sessionActivity = [];
|
|
367
|
+
syncConfig = (0, config_1.getSyncConfig)();
|
|
140
368
|
}
|
|
141
|
-
|
|
369
|
+
catch { /* config not available */ }
|
|
370
|
+
// Wrap the turn body in try/finally so postTurnPush always runs — even on
|
|
371
|
+
// error or early-return failover paths.
|
|
142
372
|
try {
|
|
143
|
-
|
|
373
|
+
/* v8 ignore start -- sync-enabled branches tested in sync.test.ts, pipeline tests mock at module boundary @preserve */
|
|
374
|
+
if (syncConfig.enabled) {
|
|
375
|
+
const pullResult = (0, sync_1.preTurnPull)((0, identity_1.getAgentRoot)(), syncConfig);
|
|
376
|
+
if (!pullResult.ok) {
|
|
377
|
+
syncFailure = pullResult.error;
|
|
378
|
+
}
|
|
379
|
+
// Check for pending-sync from a prior failed push
|
|
380
|
+
if (!syncFailure) {
|
|
381
|
+
const pendingSyncPath = path.join((0, identity_1.getAgentRoot)(), "state", "pending-sync.json");
|
|
382
|
+
try {
|
|
383
|
+
if (fs.existsSync(pendingSyncPath)) {
|
|
384
|
+
const pendingSync = JSON.parse(fs.readFileSync(pendingSyncPath, "utf-8"));
|
|
385
|
+
syncFailure = `prior sync push failed: ${pendingSync.error ?? "unknown"}`;
|
|
386
|
+
fs.unlinkSync(pendingSyncPath);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
catch {
|
|
390
|
+
// Ignore read errors for pending-sync
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
/* v8 ignore stop */
|
|
395
|
+
// Build the turn context snapshot — centralizes all state reads
|
|
396
|
+
const ctx = await (0, turn_context_1.buildTurnContext)({
|
|
397
|
+
currentSession,
|
|
398
|
+
channel: input.channel,
|
|
399
|
+
friendStore: input.friendStore,
|
|
400
|
+
});
|
|
401
|
+
// Propagate sync failure from pre-turn pull
|
|
402
|
+
ctx.syncFailure = syncFailure;
|
|
403
|
+
const { activeBridges, sessionActivity, pendingObligations, codingSessions, otherCodingSessions, backgroundOperations } = ctx;
|
|
404
|
+
const bridgeContext = (0, manager_1.formatBridgeContext)(activeBridges) || undefined;
|
|
405
|
+
const activeWorkFrame = (0, active_work_1.buildActiveWorkFrame)({
|
|
406
|
+
currentSession,
|
|
407
|
+
currentObligation,
|
|
408
|
+
mustResolveBeforeHandoff,
|
|
409
|
+
inner: ctx.innerWorkState,
|
|
410
|
+
bridges: activeBridges,
|
|
411
|
+
codingSessions,
|
|
412
|
+
backgroundOperations,
|
|
413
|
+
otherCodingSessions,
|
|
414
|
+
pendingObligations,
|
|
415
|
+
taskBoard: ctx.taskBoard,
|
|
416
|
+
friendActivity: sessionActivity,
|
|
417
|
+
targetCandidates: ctx.targetCandidates,
|
|
418
|
+
innerReturnObligations: ctx.returnObligations,
|
|
419
|
+
});
|
|
420
|
+
const delegationDecision = (0, delegation_1.decideDelegation)({
|
|
421
|
+
channel: input.channel,
|
|
422
|
+
ingressTexts: input.continuityIngressTexts ?? [],
|
|
423
|
+
activeWork: activeWorkFrame,
|
|
424
|
+
mustResolveBeforeHandoff,
|
|
425
|
+
});
|
|
426
|
+
// Step 4: Drain deferred friend returns, then ordinary per-session pending.
|
|
427
|
+
const deferredReturns = input.channel === "inner"
|
|
428
|
+
? []
|
|
429
|
+
: (input.drainDeferredReturns?.(resolvedContext.friend.id) ?? []);
|
|
430
|
+
const sessionPending = input.drainPending(input.pendingDir);
|
|
431
|
+
const pending = [...deferredReturns, ...sessionPending];
|
|
432
|
+
// Assemble messages: session messages + pending + inbound user messages
|
|
433
|
+
// NOTE: live world-state checkpoint and pending messages are rendered via buildSystem (system prompt sections)
|
|
434
|
+
const extraPrefixSections = input.onPendingDrained?.(pending) ?? [];
|
|
435
|
+
// extraPrefixSections from onPendingDrained still prepend to user message (e.g., inner dialog wakes)
|
|
436
|
+
if (extraPrefixSections.length > 0 && input.messages.length > 0) {
|
|
437
|
+
input.messages[0] = prependTurnSections(input.messages[0], extraPrefixSections);
|
|
438
|
+
}
|
|
439
|
+
// Append user messages from the inbound turn
|
|
440
|
+
for (const msg of input.messages) {
|
|
441
|
+
(0, session_events_1.stampIngressTime)(msg);
|
|
442
|
+
sessionMessages.push(msg);
|
|
443
|
+
}
|
|
444
|
+
// Step 4b: Continuity pipeline — derive tempo, build start-of-turn packet, snapshot obligations
|
|
445
|
+
let renderedStartOfTurnPacket;
|
|
446
|
+
const preTurnObligationIds = new Set(pendingObligations.map((ob) => `${ob.id}:${ob.status}`));
|
|
447
|
+
try {
|
|
144
448
|
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
449
|
+
const agentName = (0, identity_1.getAgentName)();
|
|
450
|
+
const { recentEpisodes, activeCares } = ctx;
|
|
451
|
+
const tempoState = (0, tempo_1.deriveTempo)({
|
|
452
|
+
activeSessions: sessionActivity.length + 1,
|
|
453
|
+
openObligations: pendingObligations.length,
|
|
454
|
+
recentEpisodeCount: recentEpisodes.length,
|
|
455
|
+
lastActivityAgeMs: sessionActivity.length > 0
|
|
456
|
+
? Date.now() - new Date(sessionActivity[0].lastActivityAt).getTime()
|
|
457
|
+
: 0,
|
|
458
|
+
hasBlockers: false, // obligations use specific statuses, not "blocked"
|
|
459
|
+
highSalienceEpisodes: recentEpisodes.filter((ep) => ep.salience === "high" || ep.salience === "critical").length,
|
|
460
|
+
activeCareCount: activeCares.length,
|
|
461
|
+
atRiskCareCount: activeCares.filter((c) => c.currentRisk != null).length,
|
|
462
|
+
});
|
|
463
|
+
const temporalView = (0, temporal_view_1.buildTemporalView)(agentRoot, {
|
|
464
|
+
tempo: tempoState.mode,
|
|
465
|
+
preloaded: {
|
|
466
|
+
recentEpisodes,
|
|
467
|
+
activeObligations: pendingObligations,
|
|
468
|
+
activeCares,
|
|
153
469
|
},
|
|
154
|
-
friendStore: input.friendStore,
|
|
155
470
|
});
|
|
471
|
+
const startOfTurnPacket = (0, start_of_turn_packet_1.buildStartOfTurnPacket)(temporalView, {
|
|
472
|
+
canonicalObligations: {
|
|
473
|
+
primary: activeWorkFrame.primaryObligation,
|
|
474
|
+
all: activeWorkFrame.pendingObligations,
|
|
475
|
+
},
|
|
476
|
+
currentSessionTiming,
|
|
477
|
+
});
|
|
478
|
+
/* v8 ignore next 3 -- syncFailure propagation tested in sync.test.ts @preserve */
|
|
479
|
+
if (syncFailure) {
|
|
480
|
+
startOfTurnPacket.syncFailure = syncFailure;
|
|
481
|
+
}
|
|
482
|
+
if (ctx.providerVisibility) {
|
|
483
|
+
startOfTurnPacket.providerSelection = (0, provider_visibility_1.formatAgentProviderVisibilityForStartOfTurn)(ctx.providerVisibility);
|
|
484
|
+
}
|
|
485
|
+
// Structured bundle state detection — surfaces discrete issues the
|
|
486
|
+
// agent can remediate via the bundle_* tools. Runs independently of
|
|
487
|
+
// syncFailure so the two signals coexist during the transition away
|
|
488
|
+
// from the legacy free-form syncFailure string. Always assigned; the
|
|
489
|
+
// packet renderer's empty-filter handles the empty-array case without
|
|
490
|
+
// a separate branch here.
|
|
491
|
+
startOfTurnPacket.bundleState = (0, bundle_state_1.detectBundleState)(agentRoot);
|
|
492
|
+
const capabilities = (0, start_of_turn_packet_1.buildCapabilitiesSection)(agentRoot);
|
|
493
|
+
if (capabilities) {
|
|
494
|
+
startOfTurnPacket.capabilities = capabilities;
|
|
495
|
+
}
|
|
496
|
+
renderedStartOfTurnPacket = (0, start_of_turn_packet_1.renderStartOfTurnPacket)(startOfTurnPacket);
|
|
497
|
+
if (!renderedStartOfTurnPacket)
|
|
498
|
+
renderedStartOfTurnPacket = undefined;
|
|
499
|
+
// Update self-presence
|
|
500
|
+
const presence = (0, presence_1.derivePresence)(agentRoot, agentName, {
|
|
501
|
+
activeSessions: sessionActivity.length + 1,
|
|
502
|
+
openObligations: pendingObligations.length,
|
|
503
|
+
activeBridges: activeBridges.length,
|
|
504
|
+
codingLanes: codingSessions.length,
|
|
505
|
+
currentTempo: tempoState.mode,
|
|
506
|
+
});
|
|
507
|
+
(0, presence_1.writePresence)(agentRoot, agentName, presence);
|
|
156
508
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
509
|
+
catch (continuityError) {
|
|
510
|
+
(0, runtime_1.emitNervesEvent)({
|
|
511
|
+
level: "warn",
|
|
512
|
+
component: "senses",
|
|
513
|
+
event: "senses.continuity_error",
|
|
514
|
+
message: "continuity pipeline failed, continuing without start-of-turn packet",
|
|
515
|
+
meta: { error: continuityError instanceof Error ? continuityError.message : String(continuityError) },
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
// Step 5: runAgent
|
|
519
|
+
const existingToolContext = input.runAgentOptions?.toolContext;
|
|
520
|
+
const runAgentOptions = {
|
|
521
|
+
...input.runAgentOptions,
|
|
522
|
+
bridgeContext,
|
|
523
|
+
activeWorkFrame,
|
|
524
|
+
delegationDecision,
|
|
525
|
+
startOfTurnPacket: renderedStartOfTurnPacket,
|
|
526
|
+
pendingMessages: pending.length > 0 ? pending.map((msg) => ({ from: msg.from, content: msg.content })) : undefined,
|
|
527
|
+
currentSessionKey: currentSession.key,
|
|
528
|
+
currentObligation,
|
|
529
|
+
mustResolveBeforeHandoff,
|
|
530
|
+
setMustResolveBeforeHandoff: (value) => {
|
|
531
|
+
mustResolveBeforeHandoff = value;
|
|
532
|
+
},
|
|
533
|
+
// Pre-read state from TurnContext for prompt assembly
|
|
534
|
+
daemonRunning: ctx.daemonRunning,
|
|
535
|
+
senseStatusLines: ctx.senseStatusLines,
|
|
536
|
+
bundleMeta: ctx.bundleMeta,
|
|
537
|
+
daemonHealth: ctx.daemonHealth,
|
|
538
|
+
journalFiles: ctx.journalFiles,
|
|
539
|
+
...(ctx.providerVisibility ? { providerVisibility: ctx.providerVisibility } : {}),
|
|
540
|
+
toolContext: {
|
|
541
|
+
/* v8 ignore next -- default no-op signin satisfies interface; real signin injected by sense adapter @preserve */
|
|
542
|
+
signin: async () => undefined,
|
|
543
|
+
...existingToolContext,
|
|
544
|
+
context: resolvedContext,
|
|
545
|
+
friendStore: input.friendStore,
|
|
546
|
+
currentSession,
|
|
547
|
+
activeBridges,
|
|
548
|
+
},
|
|
549
|
+
};
|
|
550
|
+
const result = await input.runAgent(sessionMessages, input.callbacks, input.channel, input.signal, runAgentOptions);
|
|
551
|
+
// Step 5b: Failover on terminal error
|
|
552
|
+
if (result.outcome === "errored" && input.failoverState) {
|
|
168
553
|
try {
|
|
169
|
-
|
|
554
|
+
const agentName = (0, identity_1.getAgentName)();
|
|
555
|
+
const currentLane = providerLaneForChannel(input.channel);
|
|
556
|
+
const currentBinding = resolveCurrentFailoverBinding(agentName, currentLane);
|
|
557
|
+
const currentProvider = currentBinding.provider;
|
|
558
|
+
/* v8 ignore next -- defensive: errorClassification always set when errored @preserve */
|
|
559
|
+
const classification = result.errorClassification ?? "unknown";
|
|
560
|
+
const inventory = await (0, provider_failover_1.runMachineProviderFailoverInventory)(agentName, currentProvider);
|
|
561
|
+
const failoverContext = (0, provider_failover_1.buildFailoverContext)(
|
|
562
|
+
/* v8 ignore next -- defensive: error always set when errored @preserve */
|
|
563
|
+
result.error?.message ?? "unknown error", classification, currentProvider, currentBinding.model, agentName, inventory, {}, { currentLane });
|
|
564
|
+
input.failoverState.pending = failoverContext;
|
|
565
|
+
input.postTurn(sessionMessages, session.sessionPath, result.usage);
|
|
566
|
+
return {
|
|
567
|
+
resolvedContext,
|
|
568
|
+
gateResult,
|
|
569
|
+
usage: result.usage,
|
|
570
|
+
turnOutcome: result.outcome,
|
|
571
|
+
sessionPath: session.sessionPath,
|
|
572
|
+
messages: sessionMessages,
|
|
573
|
+
drainedPending: pending,
|
|
574
|
+
failoverMessage: failoverContext.userMessage,
|
|
575
|
+
};
|
|
576
|
+
/* v8 ignore start -- failover catch: tested via pipeline failover sequence throws test but v8 under-reports catch coverage @preserve */
|
|
170
577
|
}
|
|
171
|
-
catch {
|
|
172
|
-
|
|
578
|
+
catch (failoverError) {
|
|
579
|
+
(0, runtime_1.emitNervesEvent)({
|
|
580
|
+
level: "warn",
|
|
581
|
+
component: "senses",
|
|
582
|
+
event: "senses.failover_error",
|
|
583
|
+
message: "failover sequence failed, falling through",
|
|
584
|
+
meta: { error: failoverError instanceof Error ? failoverError.message : String(failoverError) },
|
|
585
|
+
});
|
|
173
586
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
.
|
|
195
|
-
|
|
196
|
-
//
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
],
|
|
213
|
-
};
|
|
214
|
-
}
|
|
587
|
+
/* v8 ignore stop */
|
|
588
|
+
}
|
|
589
|
+
// Step 5c: Emit episodes for obligation state transitions
|
|
590
|
+
try {
|
|
591
|
+
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
592
|
+
const postTurnObligations = (0, obligations_1.readPendingObligations)(agentRoot);
|
|
593
|
+
emitObligationTransitionEpisodes(agentRoot, preTurnObligationIds, postTurnObligations, pendingObligations);
|
|
594
|
+
}
|
|
595
|
+
catch {
|
|
596
|
+
// Episode emission is non-fatal
|
|
597
|
+
}
|
|
598
|
+
// Step 6: postTurn
|
|
599
|
+
const continuingState = {
|
|
600
|
+
...(mustResolveBeforeHandoff ? { mustResolveBeforeHandoff: true } : {}),
|
|
601
|
+
...(typeof lastFriendActivityAt === "string" ? { lastFriendActivityAt } : {}),
|
|
602
|
+
};
|
|
603
|
+
const nextState = result.outcome === "settled" || result.outcome === "blocked" || result.outcome === "superseded" || result.outcome === "observed"
|
|
604
|
+
? (typeof lastFriendActivityAt === "string"
|
|
605
|
+
? { lastFriendActivityAt }
|
|
606
|
+
: undefined)
|
|
607
|
+
: (Object.keys(continuingState).length > 0 ? continuingState : undefined);
|
|
608
|
+
input.postTurn(sessionMessages, session.sessionPath, result.usage, undefined, nextState);
|
|
609
|
+
// Step 7: Token accumulation
|
|
610
|
+
await input.accumulateFriendTokens(input.friendStore, resolvedContext.friend.id, result.usage);
|
|
611
|
+
(0, runtime_1.emitNervesEvent)({
|
|
612
|
+
component: "senses",
|
|
613
|
+
event: "senses.pipeline_end",
|
|
614
|
+
message: "inbound turn pipeline completed",
|
|
615
|
+
meta: {
|
|
616
|
+
channel: input.channel,
|
|
617
|
+
friendId: resolvedContext.friend.id,
|
|
618
|
+
},
|
|
619
|
+
});
|
|
620
|
+
// DRY cross-session awareness: notify inner dialog that activity happened on another channel
|
|
621
|
+
// Inner dialog's next checkpoint will include this session's state
|
|
622
|
+
if (input.channel !== "inner") {
|
|
623
|
+
try {
|
|
624
|
+
(0, socket_client_1.requestInnerWake)((0, identity_1.getAgentName)()).catch(/* v8 ignore next */ () => { });
|
|
215
625
|
}
|
|
626
|
+
catch { /* getAgentName may fail in test environments */ }
|
|
216
627
|
}
|
|
628
|
+
return {
|
|
629
|
+
resolvedContext,
|
|
630
|
+
gateResult,
|
|
631
|
+
usage: result.usage,
|
|
632
|
+
turnOutcome: result.outcome,
|
|
633
|
+
completion: result.completion,
|
|
634
|
+
sessionPath: session.sessionPath,
|
|
635
|
+
messages: sessionMessages,
|
|
636
|
+
drainedPending: pending,
|
|
637
|
+
...(input.switchedProvider ? { switchedProvider: input.switchedProvider } : {}),
|
|
638
|
+
};
|
|
217
639
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
640
|
+
finally {
|
|
641
|
+
// Step 6b: Post-turn sync push (opt-in, git-status-based discovery).
|
|
642
|
+
if (syncConfig.enabled) {
|
|
643
|
+
(0, sync_1.postTurnPush)((0, identity_1.getAgentRoot)(), syncConfig);
|
|
644
|
+
}
|
|
221
645
|
}
|
|
222
|
-
// Step 5: runAgent
|
|
223
|
-
const existingToolContext = input.runAgentOptions?.toolContext;
|
|
224
|
-
const runAgentOptions = {
|
|
225
|
-
...input.runAgentOptions,
|
|
226
|
-
bridgeContext,
|
|
227
|
-
activeWorkFrame,
|
|
228
|
-
delegationDecision,
|
|
229
|
-
currentSessionKey: currentSession.key,
|
|
230
|
-
currentObligation,
|
|
231
|
-
mustResolveBeforeHandoff,
|
|
232
|
-
setMustResolveBeforeHandoff: (value) => {
|
|
233
|
-
mustResolveBeforeHandoff = value;
|
|
234
|
-
},
|
|
235
|
-
toolContext: {
|
|
236
|
-
/* v8 ignore next -- default no-op signin satisfies interface; real signin injected by sense adapter @preserve */
|
|
237
|
-
signin: async () => undefined,
|
|
238
|
-
...existingToolContext,
|
|
239
|
-
context: resolvedContext,
|
|
240
|
-
friendStore: input.friendStore,
|
|
241
|
-
currentSession,
|
|
242
|
-
activeBridges,
|
|
243
|
-
},
|
|
244
|
-
};
|
|
245
|
-
const result = await input.runAgent(sessionMessages, input.callbacks, input.channel, input.signal, runAgentOptions);
|
|
246
|
-
// Step 6: postTurn
|
|
247
|
-
const continuingState = {
|
|
248
|
-
...(mustResolveBeforeHandoff ? { mustResolveBeforeHandoff: true } : {}),
|
|
249
|
-
...(typeof lastFriendActivityAt === "string" ? { lastFriendActivityAt } : {}),
|
|
250
|
-
};
|
|
251
|
-
const nextState = result.outcome === "complete" || result.outcome === "blocked" || result.outcome === "superseded"
|
|
252
|
-
? (typeof lastFriendActivityAt === "string"
|
|
253
|
-
? { lastFriendActivityAt }
|
|
254
|
-
: undefined)
|
|
255
|
-
: (Object.keys(continuingState).length > 0 ? continuingState : undefined);
|
|
256
|
-
input.postTurn(sessionMessages, session.sessionPath, result.usage, undefined, nextState);
|
|
257
|
-
// Step 7: Token accumulation
|
|
258
|
-
await input.accumulateFriendTokens(input.friendStore, resolvedContext.friend.id, result.usage);
|
|
259
|
-
(0, runtime_1.emitNervesEvent)({
|
|
260
|
-
component: "senses",
|
|
261
|
-
event: "senses.pipeline_end",
|
|
262
|
-
message: "inbound turn pipeline completed",
|
|
263
|
-
meta: {
|
|
264
|
-
channel: input.channel,
|
|
265
|
-
friendId: resolvedContext.friend.id,
|
|
266
|
-
},
|
|
267
|
-
});
|
|
268
|
-
return {
|
|
269
|
-
resolvedContext,
|
|
270
|
-
gateResult,
|
|
271
|
-
usage: result.usage,
|
|
272
|
-
turnOutcome: result.outcome,
|
|
273
|
-
completion: result.completion,
|
|
274
|
-
sessionPath: session.sessionPath,
|
|
275
|
-
messages: sessionMessages,
|
|
276
|
-
drainedPending: pending,
|
|
277
|
-
};
|
|
278
646
|
}
|