@ouro.bot/cli 0.1.0-alpha.62 → 0.1.0-alpha.637
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 +4087 -13
- package/dist/arc/attention-types.js +8 -0
- package/dist/arc/cares.js +144 -0
- package/dist/arc/episodes.js +118 -0
- package/dist/arc/evolution.js +487 -0
- package/dist/arc/intentions.js +134 -0
- package/dist/arc/json-store.js +117 -0
- package/dist/arc/obligations.js +270 -0
- package/dist/arc/packets.js +288 -0
- package/dist/arc/presence.js +185 -0
- package/dist/arc/task-lifecycle.js +57 -0
- package/dist/heart/active-work.js +860 -43
- package/dist/heart/agent-entry.js +69 -3
- package/dist/heart/attachments/image-normalize.js +194 -0
- package/dist/heart/attachments/materialize.js +97 -0
- package/dist/heart/attachments/originals.js +88 -0
- package/dist/heart/attachments/render.js +29 -0
- package/dist/heart/attachments/sources/bluebubbles.js +156 -0
- package/dist/heart/attachments/sources/cli-local-file.js +78 -0
- package/dist/heart/attachments/sources/index.js +16 -0
- package/dist/heart/attachments/store.js +103 -0
- package/dist/heart/attachments/types.js +93 -0
- package/dist/heart/auth/auth-flow.js +479 -0
- package/dist/heart/awaiting/await-alert.js +146 -0
- package/dist/heart/awaiting/await-expiry.js +108 -0
- package/dist/heart/awaiting/await-loader.js +91 -0
- package/dist/heart/awaiting/await-parser.js +141 -0
- package/dist/heart/awaiting/await-runtime-state.js +100 -0
- package/dist/heart/awaiting/await-scheduler.js +377 -0
- package/dist/heart/background-operations.js +281 -0
- package/dist/heart/bridges/manager.js +137 -17
- package/dist/heart/bridges/store.js +14 -2
- package/dist/heart/bundle-state.js +168 -0
- package/dist/heart/commitments.js +135 -0
- package/dist/heart/config-registry.js +322 -0
- package/dist/heart/config.js +114 -119
- package/dist/heart/core.js +1028 -248
- 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-desk.js +322 -0
- package/dist/heart/daemon/cli-exec.js +7468 -0
- package/dist/heart/daemon/cli-help.js +505 -0
- package/dist/heart/daemon/cli-parse.js +1554 -0
- package/dist/heart/daemon/cli-render-doctor.js +57 -0
- package/dist/heart/daemon/cli-render.js +763 -0
- package/dist/heart/daemon/cli-types.js +8 -0
- package/dist/heart/daemon/connect-bay.js +323 -0
- package/dist/heart/daemon/daemon-cli.js +29 -1700
- package/dist/heart/daemon/daemon-entry.js +485 -2
- package/dist/heart/daemon/daemon-health.js +176 -0
- package/dist/heart/daemon/daemon-rollup.js +57 -0
- package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
- package/dist/heart/daemon/daemon-tombstone.js +236 -0
- package/dist/heart/daemon/daemon.js +906 -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 +873 -0
- package/dist/heart/daemon/health-monitor.js +122 -1
- package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
- package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
- package/dist/heart/daemon/http-health-probe.js +80 -0
- package/dist/heart/daemon/human-command-screens.js +234 -0
- package/dist/heart/daemon/human-readiness.js +114 -0
- package/dist/heart/daemon/inner-status.js +89 -0
- package/dist/heart/daemon/interactive-repair.js +394 -0
- package/dist/heart/daemon/launchd.js +37 -8
- package/dist/heart/daemon/log-tailer.js +79 -10
- package/dist/heart/daemon/logs-prune.js +110 -0
- package/dist/heart/daemon/mcp-canary.js +297 -0
- package/dist/heart/daemon/migrate-to-desk.js +848 -0
- package/dist/heart/daemon/os-cron-deps.js +135 -0
- package/dist/heart/daemon/os-cron.js +14 -12
- package/dist/heart/daemon/ouro-bot-entry.js +4 -2
- package/dist/heart/daemon/ouro-entry.js +3 -1
- package/dist/heart/daemon/plugin-cli.js +432 -0
- package/dist/heart/daemon/process-manager.js +501 -35
- 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 +11 -3
- package/dist/heart/daemon/runtime-metadata.js +2 -30
- package/dist/heart/daemon/safe-mode.js +161 -0
- package/dist/heart/daemon/sense-manager.js +493 -38
- package/dist/heart/daemon/session-id-resolver.js +131 -0
- package/dist/heart/daemon/skill-management-installer.js +22 -9
- package/dist/heart/daemon/socket-client.js +158 -11
- package/dist/heart/daemon/stale-bundle-prune.js +96 -0
- package/dist/heart/daemon/startup-tui.js +330 -0
- package/dist/heart/daemon/task-scheduler.js +117 -39
- package/dist/heart/daemon/terminal-ui.js +499 -0
- package/dist/heart/daemon/thoughts.js +229 -17
- package/dist/heart/daemon/up-progress.js +366 -0
- package/dist/heart/daemon/vault-items.js +56 -0
- package/dist/heart/delegation.js +1 -4
- package/dist/heart/habits/habit-migration.js +189 -0
- package/dist/heart/habits/habit-parser.js +140 -0
- package/dist/heart/habits/habit-runtime-state.js +100 -0
- package/dist/heart/habits/habit-scheduler.js +372 -0
- package/dist/heart/{daemon → hatch}/hatch-flow.js +32 -56
- package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
- package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
- package/dist/heart/{daemon → hatch}/specialist-tools.js +37 -14
- package/dist/heart/identity.js +168 -57
- package/dist/heart/kept-notes.js +357 -0
- package/dist/heart/kicks.js +1 -1
- package/dist/heart/machine-identity.js +161 -0
- package/dist/heart/mail-import-discovery.js +353 -0
- package/dist/heart/mailbox/mailbox-http-hooks.js +66 -0
- package/dist/heart/mailbox/mailbox-http-response.js +7 -0
- package/dist/heart/mailbox/mailbox-http-routes.js +246 -0
- package/dist/heart/mailbox/mailbox-http-static.js +103 -0
- package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
- package/dist/heart/mailbox/mailbox-http.js +99 -0
- package/dist/heart/mailbox/mailbox-read.js +31 -0
- package/dist/heart/mailbox/mailbox-types.js +27 -0
- package/dist/heart/mailbox/mailbox-view.js +197 -0
- package/dist/heart/mailbox/readers/agent-machine.js +418 -0
- package/dist/heart/mailbox/readers/continuity-readers.js +319 -0
- package/dist/heart/mailbox/readers/mail.js +375 -0
- package/dist/heart/mailbox/readers/runtime-readers.js +756 -0
- package/dist/heart/mailbox/readers/sessions.js +232 -0
- package/dist/heart/mailbox/readers/shared.js +111 -0
- package/dist/heart/mcp/mcp-server.js +692 -0
- package/dist/heart/migrate-config.js +100 -0
- package/dist/heart/model-capabilities.js +19 -0
- package/dist/heart/orientation-frame.js +217 -0
- package/dist/heart/platform.js +81 -0
- package/dist/heart/provider-attempt.js +134 -0
- package/dist/heart/provider-binding-resolver.js +272 -0
- package/dist/heart/provider-credentials.js +425 -0
- package/dist/heart/provider-failover.js +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 +23 -11
- package/dist/heart/providers/error-classification.js +127 -0
- package/dist/heart/providers/github-copilot.js +145 -0
- package/dist/heart/providers/minimax-vlm.js +189 -0
- package/dist/heart/providers/minimax.js +26 -8
- package/dist/heart/providers/openai-codex.js +55 -40
- package/dist/heart/runtime-capability-check.js +170 -0
- package/dist/heart/runtime-credentials.js +367 -0
- package/dist/heart/runtime-cwd.js +87 -0
- package/dist/heart/sense-truth.js +13 -4
- package/dist/heart/session-activity.js +48 -24
- package/dist/heart/session-events.js +1163 -0
- package/dist/heart/session-playback-cli-main.js +5 -0
- package/dist/heart/session-playback-cli.js +36 -0
- package/dist/heart/session-playback.js +231 -0
- package/dist/heart/session-stats-cli-main.js +5 -0
- package/dist/heart/session-stats.js +182 -0
- package/dist/heart/session-transcript.js +133 -0
- package/dist/heart/start-of-turn-packet.js +345 -0
- package/dist/heart/streaming.js +44 -27
- package/dist/heart/structured-output.js +196 -0
- package/dist/heart/sync-classification.js +176 -0
- package/dist/heart/sync.js +449 -0
- package/dist/heart/target-resolution.js +9 -5
- package/dist/heart/tempo.js +93 -0
- package/dist/heart/temporal-view.js +41 -0
- package/dist/heart/timeouts.js +101 -0
- package/dist/heart/tool-activity-callbacks.js +59 -0
- package/dist/heart/tool-description.js +143 -0
- package/dist/heart/tool-friction.js +55 -0
- package/dist/heart/tool-loop.js +200 -0
- package/dist/heart/turn-context.js +389 -0
- package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
- package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
- package/dist/heart/versioning/ouro-path-installer.js +426 -0
- package/dist/heart/versioning/ouro-version-manager.js +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-9-AxCxuB.js +61 -0
- package/dist/mailbox-ui/assets/index-CWzt267f.css +1 -0
- package/dist/mailbox-ui/index.html +15 -0
- package/dist/mailroom/attention.js +167 -0
- package/dist/mailroom/autonomy.js +209 -0
- package/dist/mailroom/blob-store.js +715 -0
- package/dist/mailroom/body-cache.js +61 -0
- package/dist/mailroom/core.js +788 -0
- package/dist/mailroom/entry.js +160 -0
- package/dist/mailroom/file-store.js +568 -0
- package/dist/mailroom/mbox-import.js +393 -0
- package/dist/mailroom/migration.js +164 -0
- package/dist/mailroom/outbound.js +380 -0
- package/dist/mailroom/policy.js +263 -0
- package/dist/mailroom/reader.js +233 -0
- package/dist/mailroom/search-cache.js +334 -0
- package/dist/mailroom/search-relevance.js +319 -0
- package/dist/mailroom/smtp-ingress.js +176 -0
- package/dist/mailroom/source-state.js +176 -0
- package/dist/mailroom/thread.js +109 -0
- package/dist/mailroom/travel-extract.js +89 -0
- package/dist/mind/bundle-manifest.js +14 -1
- package/dist/mind/context.js +251 -101
- package/dist/mind/desk-section.js +310 -0
- package/dist/mind/diary-integrity.js +60 -0
- package/dist/mind/{memory.js → diary.js} +68 -76
- package/dist/mind/embedding-provider.js +60 -0
- package/dist/mind/file-state.js +179 -0
- package/dist/mind/friends/channel.js +39 -0
- package/dist/mind/friends/resolver.js +54 -2
- package/dist/mind/friends/store-file.js +48 -4
- package/dist/mind/friends/types.js +2 -2
- package/dist/mind/journal-index.js +162 -0
- package/dist/mind/note-search.js +268 -0
- package/dist/mind/obligation-steering.js +221 -0
- package/dist/mind/pending.js +6 -1
- package/dist/mind/prompt-refresh.js +3 -2
- package/dist/mind/prompt.js +1075 -146
- package/dist/mind/provenance-trust.js +26 -0
- package/dist/mind/scrutiny.js +173 -0
- package/dist/nerves/cli-logging.js +7 -1
- package/dist/nerves/coverage/audit-rules.js +15 -6
- package/dist/nerves/coverage/audit.js +28 -2
- package/dist/nerves/coverage/cli.js +1 -1
- package/dist/nerves/coverage/contract.js +5 -5
- package/dist/nerves/coverage/file-completeness.js +139 -5
- package/dist/nerves/event-buffer.js +111 -0
- package/dist/nerves/index.js +224 -4
- package/dist/nerves/observation.js +20 -0
- package/dist/nerves/redact.js +79 -0
- package/dist/nerves/review/cli-main.js +5 -0
- package/dist/nerves/review/cli.js +156 -0
- package/dist/nerves/review/core.js +152 -0
- package/dist/nerves/runtime.js +5 -1
- package/dist/repertoire/ado-client.js +15 -56
- package/dist/repertoire/ado-semantic.js +16 -10
- package/dist/repertoire/api-client.js +97 -0
- package/dist/repertoire/bitwarden-store.js +1040 -0
- package/dist/repertoire/bundle-templates.js +72 -0
- package/dist/repertoire/bw-installer.js +180 -0
- package/dist/repertoire/coding/codex-jsonl.js +64 -0
- package/dist/repertoire/coding/context-pack.js +331 -0
- package/dist/repertoire/coding/feedback.js +197 -30
- package/dist/repertoire/coding/manager.js +166 -10
- package/dist/repertoire/coding/spawner.js +55 -9
- package/dist/repertoire/coding/tools.js +219 -7
- package/dist/repertoire/commerce-errors.js +109 -0
- package/dist/repertoire/commerce-self-test.js +156 -0
- package/dist/repertoire/credential-access.js +178 -0
- package/dist/repertoire/desk/classifier.js +362 -0
- package/dist/repertoire/duffel-client.js +185 -0
- package/dist/repertoire/github-client.js +14 -55
- package/dist/repertoire/graph-client.js +11 -52
- package/dist/repertoire/guardrails.js +385 -0
- package/dist/repertoire/mcp-client.js +295 -0
- package/dist/repertoire/mcp-manager.js +403 -0
- package/dist/repertoire/mcp-tools.js +83 -0
- package/dist/repertoire/plugin-mcp.js +175 -0
- package/dist/repertoire/plugins.js +253 -0
- package/dist/repertoire/shell-sessions.js +133 -0
- package/dist/repertoire/skills.js +48 -4
- package/dist/repertoire/stripe-client.js +131 -0
- package/dist/repertoire/tool-results.js +29 -0
- package/dist/repertoire/tools-attachments.js +317 -0
- package/dist/repertoire/tools-awaiting.js +372 -0
- package/dist/repertoire/tools-base.js +59 -1082
- package/dist/repertoire/tools-bluebubbles.js +2 -0
- package/dist/repertoire/tools-bridge.js +144 -0
- package/dist/repertoire/tools-bundle.js +993 -0
- package/dist/repertoire/tools-config.js +186 -0
- package/dist/repertoire/tools-continuity.js +252 -0
- package/dist/repertoire/tools-credential.js +383 -0
- package/dist/repertoire/tools-evolution.js +527 -0
- package/dist/repertoire/tools-files.js +344 -0
- package/dist/repertoire/tools-flight.js +227 -0
- package/dist/repertoire/tools-flow.js +119 -0
- package/dist/repertoire/tools-github.js +3 -8
- package/dist/repertoire/tools-mail.js +1975 -0
- package/dist/repertoire/tools-notes.js +438 -0
- package/dist/repertoire/tools-obligations.js +143 -0
- package/dist/repertoire/tools-orientation.js +31 -0
- package/dist/repertoire/tools-record.js +464 -0
- package/dist/repertoire/tools-runtime.js +150 -0
- package/dist/repertoire/tools-session.js +766 -0
- package/dist/repertoire/tools-shell.js +120 -0
- package/dist/repertoire/tools-stripe.js +182 -0
- package/dist/repertoire/tools-surface.js +344 -0
- package/dist/repertoire/tools-teams.js +12 -39
- package/dist/repertoire/tools-travel.js +125 -0
- package/dist/repertoire/tools-trip.js +982 -0
- package/dist/repertoire/tools-user-profile.js +146 -0
- package/dist/repertoire/tools-vault.js +40 -0
- package/dist/repertoire/tools-voice.js +145 -0
- package/dist/repertoire/tools.js +215 -103
- package/dist/repertoire/travel-api-client.js +360 -0
- package/dist/repertoire/user-profile.js +131 -0
- package/dist/repertoire/vault-setup.js +246 -0
- package/dist/repertoire/vault-unlock.js +594 -0
- package/dist/scripts/claude-code-hook.js +41 -0
- package/dist/scripts/claude-code-stop-hook.js +47 -0
- package/dist/senses/attention-queue.js +186 -0
- package/dist/senses/await-turn-message.js +58 -0
- package/dist/senses/bluebubbles/active-turns.js +216 -0
- package/dist/senses/bluebubbles/attachment-cache.js +53 -0
- package/dist/senses/bluebubbles/attachment-download.js +137 -0
- package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
- package/dist/senses/bluebubbles/entry.js +77 -0
- package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
- package/dist/senses/bluebubbles/index.js +2737 -0
- package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
- package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
- package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
- package/dist/senses/bluebubbles/processed-log.js +133 -0
- package/dist/senses/bluebubbles/replay.js +137 -0
- package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
- package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
- package/dist/senses/bluebubbles-meta-guard.js +40 -0
- package/dist/senses/cli/bracketed-paste.js +82 -0
- package/dist/senses/cli/image-paste.js +287 -0
- package/dist/senses/cli/image-ref-navigation.js +75 -0
- package/dist/senses/cli/ink-app.js +156 -0
- package/dist/senses/cli/inline-diff.js +64 -0
- package/dist/senses/cli/input-keys.js +174 -0
- package/dist/senses/cli/kill-ring.js +86 -0
- package/dist/senses/cli/message-list.js +51 -0
- package/dist/senses/cli/ouro-tui.js +607 -0
- package/dist/senses/cli/spinner-imperative.js +135 -0
- package/dist/senses/cli/spinner.js +101 -0
- package/dist/senses/cli/status-line.js +60 -0
- package/dist/senses/cli/streaming-markdown.js +526 -0
- package/dist/senses/cli/tool-display.js +85 -0
- package/dist/senses/cli/tool-render.js +85 -0
- package/dist/senses/cli/tui-store.js +240 -0
- package/dist/senses/cli/virtual-list.js +35 -0
- package/dist/senses/cli-entry.js +60 -8
- package/dist/senses/cli-layout.js +100 -0
- package/dist/senses/cli.js +517 -204
- package/dist/senses/commands.js +66 -3
- package/dist/senses/habit-turn-message.js +108 -0
- package/dist/senses/inner-dialog-worker.js +254 -22
- package/dist/senses/inner-dialog.js +505 -40
- package/dist/senses/mail-entry.js +66 -0
- package/dist/senses/mail.js +379 -0
- package/dist/senses/pipeline.js +666 -181
- package/dist/senses/proactive-content-guard.js +51 -0
- package/dist/senses/shared-turn.js +393 -0
- package/dist/senses/surface-tool.js +108 -0
- package/dist/senses/teams-entry.js +60 -8
- package/dist/senses/teams.js +388 -98
- package/dist/senses/trust-gate.js +100 -5
- package/dist/senses/voice/audio-playback.js +237 -0
- package/dist/senses/voice/audio-routing.js +119 -0
- package/dist/senses/voice/elevenlabs.js +202 -0
- package/dist/senses/voice/floor-control.js +431 -0
- package/dist/senses/voice/floor-controller.js +115 -0
- package/dist/senses/voice/golden-path.js +116 -0
- package/dist/senses/voice/index.js +29 -0
- package/dist/senses/voice/meeting.js +113 -0
- package/dist/senses/voice/outbound.js +190 -0
- package/dist/senses/voice/phone.js +33 -0
- package/dist/senses/voice/playback.js +139 -0
- package/dist/senses/voice/realtime-eval.js +496 -0
- package/dist/senses/voice/realtime-trace.js +531 -0
- package/dist/senses/voice/transcript.js +70 -0
- package/dist/senses/voice/turn.js +191 -0
- package/dist/senses/voice/twilio-phone-runtime.js +807 -0
- package/dist/senses/voice/twilio-phone.js +5079 -0
- package/dist/senses/voice/types.js +2 -0
- package/dist/senses/voice/whisper.js +161 -0
- package/dist/senses/voice-entry.js +81 -0
- package/dist/senses/voice-realtime-eval-command.js +99 -0
- package/dist/senses/voice-realtime-eval-entry.js +21 -0
- package/dist/senses/voice-twilio-entry.js +87 -0
- package/dist/trips/core.js +138 -0
- package/dist/trips/store.js +265 -0
- package/dist/util/frontmatter.js +53 -0
- package/package.json +48 -8
- package/skills/agent-commerce.md +106 -0
- package/skills/browser-navigation.md +117 -0
- package/skills/commerce-setup-guide.md +116 -0
- package/skills/commerce-setup.md +84 -0
- package/skills/configure-dev-tools.md +99 -0
- package/skills/travel-planning.md +138 -0
- package/dist/heart/daemon/auth-flow.js +0 -351
- package/dist/heart/daemon/ouro-path-installer.js +0 -178
- package/dist/heart/safe-workspace.js +0 -228
- package/dist/heart/session-recall.js +0 -116
- package/dist/mind/associative-recall.js +0 -209
- package/dist/repertoire/tasks/board.js +0 -134
- package/dist/repertoire/tasks/index.js +0 -224
- package/dist/repertoire/tasks/lifecycle.js +0 -80
- package/dist/repertoire/tasks/middleware.js +0 -65
- package/dist/repertoire/tasks/parser.js +0 -173
- package/dist/repertoire/tasks/scanner.js +0 -132
- package/dist/repertoire/tasks/transitions.js +0 -144
- package/dist/senses/bluebubbles-entry.js +0 -13
- package/dist/senses/bluebubbles.js +0 -1177
- package/dist/senses/debug-activity.js +0 -148
- package/subagents/README.md +0 -7
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
- /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
- /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
- /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
- /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
- /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
- /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
|
@@ -41,6 +41,10 @@ exports.readTaskFile = readTaskFile;
|
|
|
41
41
|
exports.buildTaskTriggeredMessage = buildTaskTriggeredMessage;
|
|
42
42
|
exports.deriveResumeCheckpoint = deriveResumeCheckpoint;
|
|
43
43
|
exports.innerDialogSessionPath = innerDialogSessionPath;
|
|
44
|
+
exports.enrichDelegatedFromWithBridge = enrichDelegatedFromWithBridge;
|
|
45
|
+
exports.routeDelegatedCompletion = routeDelegatedCompletion;
|
|
46
|
+
exports.buildParseErrorNudge = buildParseErrorNudge;
|
|
47
|
+
exports.buildHeldReturnWakeMessage = buildHeldReturnWakeMessage;
|
|
44
48
|
exports.runInnerDialogTurn = runInnerDialogTurn;
|
|
45
49
|
const fs = __importStar(require("fs"));
|
|
46
50
|
const path = __importStar(require("path"));
|
|
@@ -49,8 +53,13 @@ const core_1 = require("../heart/core");
|
|
|
49
53
|
const identity_1 = require("../heart/identity");
|
|
50
54
|
const context_1 = require("../mind/context");
|
|
51
55
|
const prompt_1 = require("../mind/prompt");
|
|
56
|
+
const mcp_manager_1 = require("../repertoire/mcp-manager");
|
|
57
|
+
const tools_1 = require("../repertoire/tools");
|
|
52
58
|
const bundle_manifest_1 = require("../mind/bundle-manifest");
|
|
53
59
|
const pending_1 = require("../mind/pending");
|
|
60
|
+
const obligations_1 = require("../arc/obligations");
|
|
61
|
+
const attention_queue_1 = require("./attention-queue");
|
|
62
|
+
const packets_1 = require("../arc/packets");
|
|
54
63
|
const channel_1 = require("../mind/friends/channel");
|
|
55
64
|
const trust_gate_1 = require("./trust-gate");
|
|
56
65
|
const tokens_1 = require("../mind/friends/tokens");
|
|
@@ -60,6 +69,15 @@ const runtime_1 = require("../nerves/runtime");
|
|
|
60
69
|
const manager_1 = require("../heart/bridges/manager");
|
|
61
70
|
const session_activity_1 = require("../heart/session-activity");
|
|
62
71
|
const bluebubbles_1 = require("./bluebubbles");
|
|
72
|
+
const habit_turn_message_1 = require("./habit-turn-message");
|
|
73
|
+
const await_turn_message_1 = require("./await-turn-message");
|
|
74
|
+
const await_parser_1 = require("../heart/awaiting/await-parser");
|
|
75
|
+
const await_runtime_state_1 = require("../heart/awaiting/await-runtime-state");
|
|
76
|
+
const journal_index_1 = require("../mind/journal-index");
|
|
77
|
+
const habit_parser_1 = require("../heart/habits/habit-parser");
|
|
78
|
+
const habit_runtime_state_1 = require("../heart/habits/habit-runtime-state");
|
|
79
|
+
const cadence_1 = require("../heart/daemon/cadence");
|
|
80
|
+
const daemon_health_1 = require("../heart/daemon/daemon-health");
|
|
63
81
|
const DEFAULT_INNER_DIALOG_INSTINCTS = [
|
|
64
82
|
{
|
|
65
83
|
id: "heartbeat_checkin",
|
|
@@ -98,23 +116,31 @@ function buildNonCanonicalCleanupNudge(nonCanonicalPaths) {
|
|
|
98
116
|
}
|
|
99
117
|
return [
|
|
100
118
|
"## canonical cleanup nudge",
|
|
101
|
-
"I found non-canonical files in my bundle. I should distill anything valuable into
|
|
119
|
+
"I found non-canonical files in my bundle. I should distill anything valuable into my diary and remove these files.",
|
|
102
120
|
...listed,
|
|
103
121
|
].join("\n");
|
|
104
122
|
}
|
|
123
|
+
function displayCheckpoint(checkpoint) {
|
|
124
|
+
const trimmed = checkpoint?.trim();
|
|
125
|
+
if (!trimmed || trimmed === "no prior checkpoint recorded") {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
return trimmed;
|
|
129
|
+
}
|
|
105
130
|
function buildInstinctUserMessage(instincts, _reason, state) {
|
|
106
131
|
const active = instincts.find((instinct) => instinct.enabled !== false) ?? DEFAULT_INNER_DIALOG_INSTINCTS[0];
|
|
107
|
-
const checkpoint = state.checkpoint
|
|
132
|
+
const checkpoint = displayCheckpoint(state.checkpoint);
|
|
108
133
|
const lines = [active.prompt];
|
|
109
134
|
if (checkpoint) {
|
|
110
|
-
lines.push(`\nlast
|
|
135
|
+
lines.push(`\nlast checkpoint: ${checkpoint}`);
|
|
111
136
|
}
|
|
112
137
|
return lines.join("\n");
|
|
113
138
|
}
|
|
114
139
|
function readTaskFile(agentRoot, taskId) {
|
|
115
|
-
// Task files live in collection subdirectories (one-shots, ongoing
|
|
140
|
+
// Task files live in collection subdirectories (one-shots, ongoing).
|
|
116
141
|
// Try each collection, then fall back to root tasks/ for legacy layout.
|
|
117
|
-
|
|
142
|
+
// Habits are no longer in tasks/ — they live at bundle root habits/.
|
|
143
|
+
const collections = ["one-shots", "ongoing", ""];
|
|
118
144
|
for (const collection of collections) {
|
|
119
145
|
try {
|
|
120
146
|
return fs.readFileSync(path.join(agentRoot, "tasks", collection, `${taskId}.md`), "utf8").trim();
|
|
@@ -133,8 +159,9 @@ function buildTaskTriggeredMessage(taskId, taskContent, checkpoint) {
|
|
|
133
159
|
else {
|
|
134
160
|
lines.push("", `## task: ${taskId}`, "(task file not found)");
|
|
135
161
|
}
|
|
136
|
-
|
|
137
|
-
|
|
162
|
+
const renderedCheckpoint = displayCheckpoint(checkpoint);
|
|
163
|
+
if (renderedCheckpoint) {
|
|
164
|
+
lines.push("", `last checkpoint: ${renderedCheckpoint}`);
|
|
138
165
|
}
|
|
139
166
|
return lines.join("\n");
|
|
140
167
|
}
|
|
@@ -157,31 +184,129 @@ function contentToText(content) {
|
|
|
157
184
|
.join("\n");
|
|
158
185
|
return text.trim();
|
|
159
186
|
}
|
|
160
|
-
function
|
|
161
|
-
const
|
|
162
|
-
if (!lastAssistant)
|
|
163
|
-
return "no prior checkpoint recorded";
|
|
164
|
-
const assistantText = contentToText(lastAssistant.content);
|
|
187
|
+
function checkpointTextFromAssistantContent(content) {
|
|
188
|
+
const assistantText = contentToText(content);
|
|
165
189
|
if (!assistantText)
|
|
166
|
-
return
|
|
167
|
-
const
|
|
190
|
+
return null;
|
|
191
|
+
const cleanedLines = assistantText
|
|
168
192
|
.split("\n")
|
|
169
|
-
.map((line) => line.trim())
|
|
193
|
+
.map((line) => line.replace(/<\/?think>/gi, "").trim())
|
|
194
|
+
.filter((line) => line.length > 0);
|
|
195
|
+
const explicitCheckpoint = cleanedLines
|
|
170
196
|
.find((line) => /^checkpoint\s*:/i.test(line));
|
|
171
197
|
if (explicitCheckpoint) {
|
|
172
198
|
const parsed = explicitCheckpoint.replace(/^checkpoint\s*:\s*/i, "").trim();
|
|
173
|
-
return parsed ||
|
|
199
|
+
return parsed || null;
|
|
174
200
|
}
|
|
175
|
-
const firstLine =
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
201
|
+
const firstLine = cleanedLines[0];
|
|
202
|
+
return firstLine ?? null;
|
|
203
|
+
}
|
|
204
|
+
function truncateCheckpointText(text) {
|
|
205
|
+
if (text.length <= 220)
|
|
206
|
+
return text;
|
|
207
|
+
return `${text.slice(0, 217)}...`;
|
|
208
|
+
}
|
|
209
|
+
function parseToolArguments(argumentsValue) {
|
|
210
|
+
if (!argumentsValue)
|
|
211
|
+
return {};
|
|
212
|
+
try {
|
|
213
|
+
const parsed = JSON.parse(argumentsValue);
|
|
214
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
215
|
+
? parsed
|
|
216
|
+
: {};
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
return {};
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
function toolArgumentText(args, keys) {
|
|
223
|
+
for (const key of keys) {
|
|
224
|
+
const value = args[key];
|
|
225
|
+
if (typeof value === "string" && value.trim()) {
|
|
226
|
+
return value.trim();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return "";
|
|
230
|
+
}
|
|
231
|
+
function summarizeToolAction(name, argumentsValue) {
|
|
232
|
+
if (!name)
|
|
233
|
+
return null;
|
|
234
|
+
const args = parseToolArguments(argumentsValue);
|
|
235
|
+
if (name === "surface") {
|
|
236
|
+
const message = toolArgumentText(args, ["message", "text", "content"]);
|
|
237
|
+
return message ? `surfaced: ${message}` : null;
|
|
238
|
+
}
|
|
239
|
+
if (name === "ponder") {
|
|
240
|
+
const thought = toolArgumentText(args, ["summary", "question", "topic", "prompt"]);
|
|
241
|
+
return thought ? `pondered: ${thought}` : null;
|
|
242
|
+
}
|
|
243
|
+
if (name === "diary_write") {
|
|
244
|
+
const note = toolArgumentText(args, ["text", "content", "note", "entry"]);
|
|
245
|
+
return note ? `diary: ${note}` : null;
|
|
246
|
+
}
|
|
247
|
+
if (name === "let_go") {
|
|
248
|
+
const reason = toolArgumentText(args, ["reason", "note", "status"]);
|
|
249
|
+
return reason ? `let go: ${reason}` : null;
|
|
250
|
+
}
|
|
251
|
+
if (name === "rest") {
|
|
252
|
+
const note = toolArgumentText(args, ["note", "status"]);
|
|
253
|
+
return note ? `rested: ${note}` : null;
|
|
254
|
+
}
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
function extractToolFunction(toolCall) {
|
|
258
|
+
if (!toolCall || typeof toolCall !== "object" || !("function" in toolCall))
|
|
259
|
+
return null;
|
|
260
|
+
const maybeFunction = toolCall.function;
|
|
261
|
+
if (!maybeFunction || typeof maybeFunction !== "object")
|
|
262
|
+
return null;
|
|
263
|
+
const name = "name" in maybeFunction && typeof maybeFunction.name === "string"
|
|
264
|
+
? maybeFunction.name
|
|
265
|
+
: undefined;
|
|
266
|
+
const argumentsValue = "arguments" in maybeFunction && typeof maybeFunction.arguments === "string"
|
|
267
|
+
? maybeFunction.arguments
|
|
268
|
+
: undefined;
|
|
269
|
+
return { name, arguments: argumentsValue };
|
|
270
|
+
}
|
|
271
|
+
function checkpointTextFromAssistantToolCalls(message) {
|
|
272
|
+
if (message.role !== "assistant" || !Array.isArray(message.tool_calls))
|
|
273
|
+
return null;
|
|
274
|
+
for (let i = message.tool_calls.length - 1; i >= 0; i--) {
|
|
275
|
+
const toolFunction = extractToolFunction(message.tool_calls[i]);
|
|
276
|
+
const summary = summarizeToolAction(toolFunction?.name, toolFunction?.arguments);
|
|
277
|
+
if (summary)
|
|
278
|
+
return summary;
|
|
279
|
+
}
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
function latestRestStatus(messages) {
|
|
283
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
284
|
+
const message = messages[i];
|
|
285
|
+
if (message.role !== "assistant" || !Array.isArray(message.tool_calls))
|
|
286
|
+
continue;
|
|
287
|
+
for (let j = message.tool_calls.length - 1; j >= 0; j--) {
|
|
288
|
+
const toolFunction = extractToolFunction(message.tool_calls[j]);
|
|
289
|
+
if (toolFunction?.name !== "rest")
|
|
290
|
+
continue;
|
|
291
|
+
const status = parseToolArguments(toolFunction.arguments).status;
|
|
292
|
+
return typeof status === "string" && status.trim() ? status.trim() : undefined;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return undefined;
|
|
296
|
+
}
|
|
297
|
+
function deriveResumeCheckpoint(messages) {
|
|
298
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
299
|
+
const message = messages[i];
|
|
300
|
+
if (message.role !== "assistant")
|
|
301
|
+
continue;
|
|
302
|
+
const textCheckpoint = checkpointTextFromAssistantContent(message.content);
|
|
303
|
+
if (textCheckpoint)
|
|
304
|
+
return truncateCheckpointText(textCheckpoint);
|
|
305
|
+
const toolCheckpoint = checkpointTextFromAssistantToolCalls(message);
|
|
306
|
+
if (toolCheckpoint)
|
|
307
|
+
return truncateCheckpointText(toolCheckpoint);
|
|
308
|
+
}
|
|
309
|
+
return "no prior checkpoint recorded";
|
|
185
310
|
}
|
|
186
311
|
function extractAssistantPreview(messages, maxLength = 120) {
|
|
187
312
|
const lastAssistant = [...messages].reverse().find((m) => m.role === "assistant");
|
|
@@ -247,6 +372,7 @@ function writeInnerDialogRuntimeState(sessionFilePath, state) {
|
|
|
247
372
|
});
|
|
248
373
|
}
|
|
249
374
|
}
|
|
375
|
+
/* v8 ignore start -- routing helpers: called from routing functions which are integration paths @preserve */
|
|
250
376
|
function writePendingEnvelope(pendingDir, message) {
|
|
251
377
|
fs.mkdirSync(pendingDir, { recursive: true });
|
|
252
378
|
const fileName = `${message.timestamp}-${Math.random().toString(36).slice(2, 10)}.json`;
|
|
@@ -258,6 +384,8 @@ function sessionMatchesActivity(activity, session) {
|
|
|
258
384
|
&& activity.channel === session.channel
|
|
259
385
|
&& activity.key === session.key;
|
|
260
386
|
}
|
|
387
|
+
/* v8 ignore stop */
|
|
388
|
+
/* v8 ignore start -- routing: delivery now inline via surface tool; routing functions preserved for reuse @preserve */
|
|
261
389
|
function resolveBridgePreferredSession(delegatedFrom, sessionActivity) {
|
|
262
390
|
if (!delegatedFrom.bridgeId)
|
|
263
391
|
return null;
|
|
@@ -277,15 +405,82 @@ async function tryDeliverDelegatedCompletion(target, outboundEnvelope) {
|
|
|
277
405
|
friendId: target.friendId,
|
|
278
406
|
sessionKey: target.key,
|
|
279
407
|
text: outboundEnvelope.content,
|
|
408
|
+
intent: "explicit_cross_chat",
|
|
280
409
|
});
|
|
281
410
|
return result.delivered;
|
|
282
411
|
}
|
|
412
|
+
function enrichDelegatedFromWithBridge(delegatedFrom) {
|
|
413
|
+
if (delegatedFrom.bridgeId) {
|
|
414
|
+
return delegatedFrom;
|
|
415
|
+
}
|
|
416
|
+
const bridgeManager = (0, manager_1.createBridgeManager)();
|
|
417
|
+
const originBridges = bridgeManager.findBridgesForSession({
|
|
418
|
+
friendId: delegatedFrom.friendId,
|
|
419
|
+
channel: delegatedFrom.channel,
|
|
420
|
+
key: delegatedFrom.key,
|
|
421
|
+
});
|
|
422
|
+
const activeBridge = originBridges.find((b) => b.lifecycle === "active");
|
|
423
|
+
if (activeBridge) {
|
|
424
|
+
return { ...delegatedFrom, bridgeId: activeBridge.id };
|
|
425
|
+
}
|
|
426
|
+
return delegatedFrom;
|
|
427
|
+
}
|
|
428
|
+
function advanceObligationQuietly(agentName, obligationId, update) {
|
|
429
|
+
if (!obligationId)
|
|
430
|
+
return;
|
|
431
|
+
try {
|
|
432
|
+
(0, obligations_1.advanceReturnObligation)(agentName, obligationId, update);
|
|
433
|
+
/* v8 ignore start -- best-effort: obligation fs errors must never block return routing @preserve */
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
// swallowed
|
|
437
|
+
}
|
|
438
|
+
/* v8 ignore stop */
|
|
439
|
+
}
|
|
283
440
|
async function routeDelegatedCompletion(agentRoot, agentName, completion, drainedPending, timestamp) {
|
|
284
441
|
const delegated = (drainedPending ?? []).find((message) => message.delegatedFrom);
|
|
285
442
|
if (!delegated?.delegatedFrom || !completion?.answer?.trim()) {
|
|
286
443
|
return;
|
|
287
444
|
}
|
|
288
|
-
const delegatedFrom = delegated.delegatedFrom;
|
|
445
|
+
const delegatedFrom = enrichDelegatedFromWithBridge(delegated.delegatedFrom);
|
|
446
|
+
const obligationId = delegated.obligationId;
|
|
447
|
+
// Advance any inner return obligations from queued -> running (they were drained this turn).
|
|
448
|
+
// drainedPending is guaranteed non-null here (we found delegated above).
|
|
449
|
+
for (const msg of drainedPending) {
|
|
450
|
+
if (msg.obligationId) {
|
|
451
|
+
advanceObligationQuietly(agentName, msg.obligationId, {
|
|
452
|
+
status: "running",
|
|
453
|
+
startedAt: timestamp,
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
if (delegated.obligationStatus === "pending") {
|
|
458
|
+
// Fulfill the persistent obligation in the store
|
|
459
|
+
try {
|
|
460
|
+
const pending = (0, obligations_1.findPendingObligationForOrigin)(agentRoot, {
|
|
461
|
+
friendId: delegatedFrom.friendId,
|
|
462
|
+
channel: delegatedFrom.channel,
|
|
463
|
+
key: delegatedFrom.key,
|
|
464
|
+
});
|
|
465
|
+
/* v8 ignore next 2 -- obligation fulfillment tested via obligations.test.ts; integration requires real disk state @preserve */
|
|
466
|
+
if (pending) {
|
|
467
|
+
(0, obligations_1.fulfillObligation)(agentRoot, pending.id);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
catch {
|
|
471
|
+
/* v8 ignore next -- defensive: obligation store read failure should not break delivery @preserve */
|
|
472
|
+
}
|
|
473
|
+
(0, runtime_1.emitNervesEvent)({
|
|
474
|
+
event: "senses.obligation_fulfilled",
|
|
475
|
+
component: "senses",
|
|
476
|
+
message: "obligation fulfilled via delegated completion",
|
|
477
|
+
meta: {
|
|
478
|
+
friendId: delegatedFrom.friendId,
|
|
479
|
+
channel: delegatedFrom.channel,
|
|
480
|
+
key: delegatedFrom.key,
|
|
481
|
+
},
|
|
482
|
+
});
|
|
483
|
+
}
|
|
289
484
|
const outboundEnvelope = {
|
|
290
485
|
from: agentName,
|
|
291
486
|
friendId: delegatedFrom.friendId,
|
|
@@ -294,36 +489,62 @@ async function routeDelegatedCompletion(agentRoot, agentName, completion, draine
|
|
|
294
489
|
content: completion.answer.trim(),
|
|
295
490
|
timestamp,
|
|
296
491
|
delegatedFrom,
|
|
492
|
+
...(obligationId ? { obligationId } : {}),
|
|
297
493
|
};
|
|
298
494
|
const sessionActivity = (0, session_activity_1.listSessionActivity)({
|
|
299
495
|
sessionsDir: path.join(agentRoot, "state", "sessions"),
|
|
300
496
|
friendsDir: path.join(agentRoot, "friends"),
|
|
301
497
|
agentName,
|
|
302
498
|
});
|
|
499
|
+
// Priority 1: Bridge-preferred session (if delegation was within a bridge).
|
|
303
500
|
const bridgeTarget = resolveBridgePreferredSession(delegatedFrom, sessionActivity);
|
|
304
501
|
if (bridgeTarget) {
|
|
305
502
|
if (await tryDeliverDelegatedCompletion(bridgeTarget, outboundEnvelope)) {
|
|
503
|
+
advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "bridge-session" });
|
|
306
504
|
return;
|
|
307
505
|
}
|
|
308
506
|
writePendingEnvelope((0, pending_1.getPendingDir)(agentName, bridgeTarget.friendId, bridgeTarget.channel, bridgeTarget.key), outboundEnvelope);
|
|
507
|
+
advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "bridge-session" });
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
// Priority 1.5: Direct return to originating session (ponder without bridge).
|
|
511
|
+
// When delegatedFrom has specific channel+key, route directly there instead of searching for freshest.
|
|
512
|
+
if (delegatedFrom.channel && delegatedFrom.key && delegatedFrom.channel !== "inner") {
|
|
513
|
+
const directTarget = sessionActivity.find((a) => a.friendId === delegatedFrom.friendId && a.channel === delegatedFrom.channel && a.key === delegatedFrom.key);
|
|
514
|
+
if (directTarget) {
|
|
515
|
+
if (await tryDeliverDelegatedCompletion(directTarget, outboundEnvelope)) {
|
|
516
|
+
advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "direct-originator" });
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
// Even if session isn't in activity list (might have ended), queue to its pending dir
|
|
521
|
+
writePendingEnvelope((0, pending_1.getPendingDir)(agentName, delegatedFrom.friendId, delegatedFrom.channel, delegatedFrom.key), outboundEnvelope);
|
|
522
|
+
advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "direct-originator" });
|
|
309
523
|
return;
|
|
310
524
|
}
|
|
311
|
-
|
|
525
|
+
// Priority 2: Freshest active friend session.
|
|
526
|
+
// For BB, prefer DM sessions (;-;) over group chats (;+;) — proactive outreach should never land in groups.
|
|
527
|
+
const allFriendSessions = (0, session_activity_1.listSessionActivity)({
|
|
312
528
|
sessionsDir: path.join(agentRoot, "state", "sessions"),
|
|
313
529
|
friendsDir: path.join(agentRoot, "friends"),
|
|
314
530
|
agentName,
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
if (freshest
|
|
531
|
+
}).filter((s) => s.friendId === delegatedFrom.friendId && s.channel !== "inner");
|
|
532
|
+
const bbDm = allFriendSessions.find((s) => s.channel === "bluebubbles" && s.key.includes(";-;"));
|
|
533
|
+
const freshest = bbDm ?? allFriendSessions.find((s) => s.channel !== "bluebubbles" || s.key.includes(";-;")) ?? allFriendSessions[0];
|
|
534
|
+
if (freshest) {
|
|
319
535
|
if (await tryDeliverDelegatedCompletion(freshest, outboundEnvelope)) {
|
|
536
|
+
advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "freshest-session" });
|
|
320
537
|
return;
|
|
321
538
|
}
|
|
322
539
|
writePendingEnvelope((0, pending_1.getPendingDir)(agentName, freshest.friendId, freshest.channel, freshest.key), outboundEnvelope);
|
|
540
|
+
advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "freshest-session" });
|
|
323
541
|
return;
|
|
324
542
|
}
|
|
543
|
+
// Priority 3: Deferred return queue.
|
|
325
544
|
writePendingEnvelope((0, pending_1.getDeferredReturnDir)(agentName, delegatedFrom.friendId), outboundEnvelope);
|
|
545
|
+
advanceObligationQuietly(agentName, obligationId, { status: "deferred", returnedAt: timestamp, returnTarget: "deferred" });
|
|
326
546
|
}
|
|
547
|
+
/* v8 ignore stop */
|
|
327
548
|
// Self-referencing friend record for inner dialog (agent talking to itself).
|
|
328
549
|
// No real friend to resolve -- this satisfies the pipeline's friend resolver contract.
|
|
329
550
|
function createSelfFriend(agentName) {
|
|
@@ -350,12 +571,67 @@ function createNoOpFriendStore() {
|
|
|
350
571
|
findByExternalId: async () => null,
|
|
351
572
|
};
|
|
352
573
|
}
|
|
574
|
+
function buildParseErrorNudge(parseErrors) {
|
|
575
|
+
if (parseErrors.length === 0)
|
|
576
|
+
return "";
|
|
577
|
+
const lines = parseErrors.map((e) => `I noticed my habit file \`${e.file}\` has invalid frontmatter — I should fix it. (${e.error})`);
|
|
578
|
+
return lines.join("\n");
|
|
579
|
+
}
|
|
580
|
+
function buildHeldReturnWakeMessage() {
|
|
581
|
+
return [
|
|
582
|
+
"held return work arrived; use the current held-work frame above as the authority for this turn.",
|
|
583
|
+
"Older checkpoints, rest summaries, transcript memories, completed returns, and repeated probes are historical context, not evidence about what is waiting now.",
|
|
584
|
+
"Return only the requested result; do not add commentary about prior attempts, old loops, or completed probes.",
|
|
585
|
+
"Return each listed item with surface(delegationId=...) before resting or settling.",
|
|
586
|
+
].join("\n");
|
|
587
|
+
}
|
|
588
|
+
function buildAlsoDueLine(agentRoot, currentHabitName, now) {
|
|
589
|
+
const habitsDir = path.join(agentRoot, "habits");
|
|
590
|
+
let files;
|
|
591
|
+
try {
|
|
592
|
+
files = fs.readdirSync(habitsDir);
|
|
593
|
+
}
|
|
594
|
+
catch {
|
|
595
|
+
return "";
|
|
596
|
+
}
|
|
597
|
+
const nowMs = now().getTime();
|
|
598
|
+
const alsoDue = [];
|
|
599
|
+
for (const file of files) {
|
|
600
|
+
if (!file.endsWith(".md"))
|
|
601
|
+
continue;
|
|
602
|
+
const stem = file.replace(/\.md$/, "");
|
|
603
|
+
if (stem === currentHabitName)
|
|
604
|
+
continue;
|
|
605
|
+
try {
|
|
606
|
+
const content = fs.readFileSync(path.join(habitsDir, file), "utf-8");
|
|
607
|
+
const habit = (0, habit_runtime_state_1.applyHabitRuntimeState)(agentRoot, (0, habit_parser_1.parseHabitFile)(content, path.join(habitsDir, file)));
|
|
608
|
+
if (habit.status !== "active" || !habit.cadence)
|
|
609
|
+
continue;
|
|
610
|
+
const cadenceMs = (0, cadence_1.parseCadenceToMs)(habit.cadence);
|
|
611
|
+
if (cadenceMs === null)
|
|
612
|
+
continue;
|
|
613
|
+
if (habit.lastRun === null) {
|
|
614
|
+
alsoDue.push(stem);
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
const lastRunMs = new Date(habit.lastRun).getTime();
|
|
618
|
+
if (nowMs - lastRunMs >= cadenceMs) {
|
|
619
|
+
alsoDue.push(stem);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
catch {
|
|
623
|
+
// skip unreadable habits
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
if (alsoDue.length === 0)
|
|
627
|
+
return "";
|
|
628
|
+
return `also due: ${alsoDue.join(", ")}`;
|
|
629
|
+
}
|
|
353
630
|
async function runInnerDialogTurn(options) {
|
|
354
631
|
const now = options?.now ?? (() => new Date());
|
|
355
|
-
const reason = options?.reason ?? "
|
|
632
|
+
const reason = options?.reason ?? "instinct";
|
|
356
633
|
const sessionFilePath = innerDialogSessionPath();
|
|
357
634
|
const agentName = (0, identity_1.getAgentName)();
|
|
358
|
-
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
359
635
|
writeInnerDialogRuntimeState(sessionFilePath, {
|
|
360
636
|
status: "running",
|
|
361
637
|
reason,
|
|
@@ -370,8 +646,14 @@ async function runInnerDialogTurn(options) {
|
|
|
370
646
|
resting: false,
|
|
371
647
|
lastHeartbeatAt: now().toISOString(),
|
|
372
648
|
};
|
|
649
|
+
const pendingDir = (0, pending_1.getInnerDialogPendingDir)(agentName);
|
|
650
|
+
const shouldUseHeldReturnWake = !options?.taskId && reason !== "habit" && reason !== "await"
|
|
651
|
+
? (0, obligations_1.listActiveReturnObligations)(agentName).length > 0
|
|
652
|
+
: false;
|
|
373
653
|
// ── Adapter concern: build user message ──────────────────────────
|
|
374
654
|
let userContent;
|
|
655
|
+
let habitTools;
|
|
656
|
+
let habitParsedSuccessfully = false;
|
|
375
657
|
if (existingMessages.length === 0) {
|
|
376
658
|
// Fresh session: bootstrap message with non-canonical cleanup nudge
|
|
377
659
|
const aspirations = readAspirations((0, identity_1.getAgentRoot)());
|
|
@@ -391,32 +673,173 @@ async function runInnerDialogTurn(options) {
|
|
|
391
673
|
const taskContent = readTaskFile((0, identity_1.getAgentRoot)(), options.taskId);
|
|
392
674
|
userContent = buildTaskTriggeredMessage(options.taskId, taskContent, state.checkpoint);
|
|
393
675
|
}
|
|
676
|
+
else if (reason === "habit" && options?.habitName) {
|
|
677
|
+
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
678
|
+
const habitName = options.habitName;
|
|
679
|
+
const habitFilePath = path.join(agentRoot, "habits", `${habitName}.md`);
|
|
680
|
+
// Read and parse the habit file
|
|
681
|
+
let habitBody;
|
|
682
|
+
let habitTitle = habitName;
|
|
683
|
+
let habitLastRun = null;
|
|
684
|
+
try {
|
|
685
|
+
const habitContent = fs.readFileSync(habitFilePath, "utf-8");
|
|
686
|
+
const parsed = (0, habit_runtime_state_1.applyHabitRuntimeState)(agentRoot, (0, habit_parser_1.parseHabitFile)(habitContent, habitFilePath));
|
|
687
|
+
habitBody = parsed.body || undefined;
|
|
688
|
+
habitTitle = parsed.title || habitName;
|
|
689
|
+
habitLastRun = parsed.lastRun;
|
|
690
|
+
habitTools = parsed.tools;
|
|
691
|
+
}
|
|
692
|
+
catch {
|
|
693
|
+
// Habit file missing or unreadable
|
|
694
|
+
}
|
|
695
|
+
// If the habit file couldn't be read at all (no body, no title parsed), error message
|
|
696
|
+
if (habitBody === undefined && habitTitle === habitName) {
|
|
697
|
+
userContent = `habit "${habitName}" could not be read (file not found or unreadable). check habits/${habitName}.md exists.`;
|
|
698
|
+
}
|
|
699
|
+
else {
|
|
700
|
+
habitParsedSuccessfully = true;
|
|
701
|
+
// Unified path: gather context for ALL habits (heartbeat included)
|
|
702
|
+
const obligations = (0, obligations_1.listActiveReturnObligations)(agentName);
|
|
703
|
+
const nowMs = now().getTime();
|
|
704
|
+
const staleObligations = obligations.map((o) => ({
|
|
705
|
+
friendName: o.origin.friendId,
|
|
706
|
+
content: o.delegatedContent,
|
|
707
|
+
stalenessMs: nowMs - o.createdAt,
|
|
708
|
+
}));
|
|
709
|
+
const alsoDue = buildAlsoDueLine(agentRoot, habitName, now);
|
|
710
|
+
// Degraded state (best-effort: never crash)
|
|
711
|
+
let degradedComponents = [];
|
|
712
|
+
try {
|
|
713
|
+
const health = (0, daemon_health_1.readHealth)((0, daemon_health_1.getDefaultHealthPath)());
|
|
714
|
+
if (health && health.degraded.length > 0) {
|
|
715
|
+
degradedComponents = health.degraded.map((d) => ({ component: d.component, reason: d.reason }));
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
catch {
|
|
719
|
+
// Best-effort: missing file or parse error -> empty array, no crash
|
|
720
|
+
}
|
|
721
|
+
userContent = (0, habit_turn_message_1.buildHabitTurnMessage)({
|
|
722
|
+
habitName,
|
|
723
|
+
habitTitle,
|
|
724
|
+
habitBody,
|
|
725
|
+
lastRun: habitLastRun,
|
|
726
|
+
checkpoint: displayCheckpoint(state.checkpoint),
|
|
727
|
+
alsoDue: alsoDue || undefined,
|
|
728
|
+
staleObligations,
|
|
729
|
+
parseErrors: options?.parseErrors ?? [],
|
|
730
|
+
degradedComponents,
|
|
731
|
+
now,
|
|
732
|
+
});
|
|
733
|
+
// Piggyback journal embedding indexing (best-effort, fire-and-forget)
|
|
734
|
+
const journalDir = path.join(agentRoot, "journal");
|
|
735
|
+
/* v8 ignore start -- journal indexing piggyback: embedding provider may not be available; tested via journal-index unit tests @preserve */
|
|
736
|
+
void (0, journal_index_1.indexJournalFiles)(journalDir, path.join(journalDir, ".index.json"), {
|
|
737
|
+
embed: async () => [],
|
|
738
|
+
}).catch(() => {
|
|
739
|
+
// swallowed: indexing failure must never block habit turn
|
|
740
|
+
});
|
|
741
|
+
/* v8 ignore stop */
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
else if (reason === "await" && options?.awaitName) {
|
|
745
|
+
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
746
|
+
const awaitName = options.awaitName;
|
|
747
|
+
const awaitFilePath = path.join(agentRoot, "awaiting", `${awaitName}.md`);
|
|
748
|
+
let awaitBody;
|
|
749
|
+
let condition = null;
|
|
750
|
+
let lastCheckedAt = null;
|
|
751
|
+
let lastObservation = null;
|
|
752
|
+
let checkedCount = 0;
|
|
753
|
+
let awaitFound = false;
|
|
754
|
+
try {
|
|
755
|
+
const awaitContent = fs.readFileSync(awaitFilePath, "utf-8");
|
|
756
|
+
const parsed = (0, await_runtime_state_1.applyAwaitRuntimeState)(agentRoot, (0, await_parser_1.parseAwaitFile)(awaitContent, awaitFilePath));
|
|
757
|
+
awaitFound = true;
|
|
758
|
+
awaitBody = parsed.body || undefined;
|
|
759
|
+
condition = parsed.condition;
|
|
760
|
+
lastCheckedAt = parsed.last_checked ?? null;
|
|
761
|
+
lastObservation = parsed.last_observation ?? null;
|
|
762
|
+
checkedCount = parsed.checked_count ?? 0;
|
|
763
|
+
}
|
|
764
|
+
catch {
|
|
765
|
+
// file missing — fall through to error message
|
|
766
|
+
}
|
|
767
|
+
if (!awaitFound || !condition) {
|
|
768
|
+
userContent = `await "${awaitName}" could not be read (file not found or no condition). check awaiting/${awaitName}.md.`;
|
|
769
|
+
}
|
|
770
|
+
else {
|
|
771
|
+
userContent = (0, await_turn_message_1.buildAwaitTurnMessage)({
|
|
772
|
+
awaitName,
|
|
773
|
+
condition,
|
|
774
|
+
body: awaitBody,
|
|
775
|
+
lastCheckedAt,
|
|
776
|
+
lastObservation,
|
|
777
|
+
checkedCount,
|
|
778
|
+
checkpoint: displayCheckpoint(state.checkpoint),
|
|
779
|
+
now,
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
}
|
|
394
783
|
else {
|
|
395
784
|
userContent = buildInstinctUserMessage(instincts, reason, state);
|
|
396
785
|
}
|
|
397
786
|
}
|
|
787
|
+
if (shouldUseHeldReturnWake) {
|
|
788
|
+
userContent = buildHeldReturnWakeMessage();
|
|
789
|
+
}
|
|
398
790
|
const userMessage = { role: "user", content: userContent };
|
|
399
791
|
// ── Session loader: wraps existing session logic ──────────────────
|
|
400
792
|
const innerCapabilities = (0, channel_1.getChannelCapabilities)("inner");
|
|
401
|
-
const pendingDir = (0, pending_1.getInnerDialogPendingDir)(agentName);
|
|
402
793
|
const selfFriend = createSelfFriend(agentName);
|
|
403
794
|
const selfContext = { friend: selfFriend, channel: innerCapabilities };
|
|
795
|
+
const mcpManager = await (0, mcp_manager_1.getSharedMcpManager)() ?? undefined;
|
|
796
|
+
// ── Habit tool enforcement ───────────────────────────────────────
|
|
797
|
+
let habitToolsResolved;
|
|
798
|
+
if (habitTools !== undefined) {
|
|
799
|
+
const fullTools = (0, tools_1.getToolsForChannel)(innerCapabilities);
|
|
800
|
+
habitToolsResolved = fullTools.filter((t) => habitTools.includes(t.function.name));
|
|
801
|
+
(0, runtime_1.emitNervesEvent)({
|
|
802
|
+
event: "habit.tools_restricted",
|
|
803
|
+
component: "senses",
|
|
804
|
+
message: "habit running with restricted tools",
|
|
805
|
+
meta: {
|
|
806
|
+
habitName: options?.habitName,
|
|
807
|
+
declared: habitTools,
|
|
808
|
+
resolved: habitToolsResolved.map((t) => t.function.name),
|
|
809
|
+
},
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
else if (reason === "habit" && options?.habitName && habitParsedSuccessfully) {
|
|
813
|
+
(0, runtime_1.emitNervesEvent)({
|
|
814
|
+
event: "habit.tools_unrestricted",
|
|
815
|
+
component: "senses",
|
|
816
|
+
message: "habit running with full tool repertoire",
|
|
817
|
+
meta: { habitName: options.habitName },
|
|
818
|
+
});
|
|
819
|
+
}
|
|
404
820
|
const sessionLoader = {
|
|
405
821
|
loadOrCreate: async () => {
|
|
406
822
|
if (existingMessages.length > 0) {
|
|
407
|
-
return {
|
|
823
|
+
return {
|
|
824
|
+
messages: existingMessages,
|
|
825
|
+
sessionPath: sessionFilePath,
|
|
826
|
+
structuredOutputs: loaded?.structuredOutputs,
|
|
827
|
+
};
|
|
408
828
|
}
|
|
409
829
|
// Fresh session: build system prompt
|
|
410
830
|
const systemPrompt = await (0, prompt_1.buildSystem)("inner", { toolChoiceRequired: true });
|
|
411
831
|
return {
|
|
412
|
-
messages: [{ role: "system", content: systemPrompt }],
|
|
832
|
+
messages: [{ role: "system", content: (0, prompt_1.flattenSystemPrompt)(systemPrompt) }],
|
|
413
833
|
sessionPath: sessionFilePath,
|
|
834
|
+
structuredOutputs: [],
|
|
414
835
|
};
|
|
415
836
|
},
|
|
416
837
|
};
|
|
417
838
|
// ── Call shared pipeline ──────────────────────────────────────────
|
|
418
839
|
const callbacks = createInnerDialogCallbacks();
|
|
419
840
|
const traceId = (0, nerves_1.createTraceId)();
|
|
841
|
+
// Attention queue: built when pending messages are drained, shared with tool context
|
|
842
|
+
let attentionQueue = [];
|
|
420
843
|
const result = await (0, pipeline_1.handleInboundTurn)({
|
|
421
844
|
channel: "inner",
|
|
422
845
|
sessionKey: "dialog",
|
|
@@ -431,16 +854,56 @@ async function runInnerDialogTurn(options) {
|
|
|
431
854
|
enforceTrustGate: trust_gate_1.enforceTrustGate,
|
|
432
855
|
drainPending: pending_1.drainPending,
|
|
433
856
|
runAgent: core_1.runAgent,
|
|
434
|
-
postTurn:
|
|
857
|
+
postTurn: (turnMessages, sessionPathArg, usage, hooks, state) => {
|
|
858
|
+
const prepared = (0, context_1.postTurnTrim)(turnMessages, usage, hooks);
|
|
859
|
+
(0, context_1.deferPostTurnPersist)(sessionPathArg, prepared, usage, state);
|
|
860
|
+
},
|
|
435
861
|
accumulateFriendTokens: tokens_1.accumulateFriendTokens,
|
|
436
862
|
signal: options?.signal,
|
|
863
|
+
/* v8 ignore start -- attention queue: callback invoked by pipeline during pending drain; tested via attention-queue unit tests @preserve */
|
|
864
|
+
onPendingDrained: (drained) => {
|
|
865
|
+
const outstandingObligations = (0, obligations_1.listActiveReturnObligations)(agentName);
|
|
866
|
+
const builtAttentionQueue = (0, attention_queue_1.buildAttentionQueue)({
|
|
867
|
+
drainedPending: drained,
|
|
868
|
+
outstandingObligations,
|
|
869
|
+
friendNameResolver: (friendId) => {
|
|
870
|
+
try {
|
|
871
|
+
const raw = fs.readFileSync(path.join((0, identity_1.getAgentRoot)(agentName), "friends", friendId + ".json"), "utf-8");
|
|
872
|
+
const parsed = JSON.parse(raw);
|
|
873
|
+
return typeof parsed.name === "string" ? parsed.name : null;
|
|
874
|
+
}
|
|
875
|
+
catch {
|
|
876
|
+
return null;
|
|
877
|
+
}
|
|
878
|
+
},
|
|
879
|
+
packetResolver: (packetId) => {
|
|
880
|
+
try {
|
|
881
|
+
return (0, packets_1.readPonderPacket)((0, identity_1.getAgentRoot)(agentName), packetId);
|
|
882
|
+
}
|
|
883
|
+
catch {
|
|
884
|
+
return null;
|
|
885
|
+
}
|
|
886
|
+
},
|
|
887
|
+
});
|
|
888
|
+
attentionQueue.splice(0, attentionQueue.length, ...builtAttentionQueue);
|
|
889
|
+
const attentionFrame = (0, attention_queue_1.buildAttentionQueueStatusFrame)(attentionQueue);
|
|
890
|
+
return attentionFrame ? [attentionFrame] : [];
|
|
891
|
+
},
|
|
892
|
+
/* v8 ignore stop */
|
|
437
893
|
runAgentOptions: {
|
|
438
894
|
traceId,
|
|
439
895
|
toolChoiceRequired: true,
|
|
440
|
-
|
|
896
|
+
mcpManager,
|
|
897
|
+
...(habitToolsResolved !== undefined && { tools: habitToolsResolved }),
|
|
898
|
+
toolContext: {
|
|
899
|
+
signin: async () => undefined,
|
|
900
|
+
delegatedOrigins: attentionQueue,
|
|
901
|
+
},
|
|
441
902
|
},
|
|
442
903
|
});
|
|
443
|
-
|
|
904
|
+
// Post-turn routeDelegatedCompletion removed: delivery is now inline via surface tool.
|
|
905
|
+
// settle in inner dialog produces no CompletionMetadata, so routeDelegatedCompletion
|
|
906
|
+
// would be a no-op. The routing infrastructure is reused by the surface handler.
|
|
444
907
|
const resultMessages = result.messages ?? [];
|
|
445
908
|
const assistantPreview = extractAssistantPreview(resultMessages);
|
|
446
909
|
const toolCalls = extractToolCallNames(resultMessages);
|
|
@@ -466,6 +929,8 @@ async function runInnerDialogTurn(options) {
|
|
|
466
929
|
usage: result.usage,
|
|
467
930
|
sessionPath: result.sessionPath ?? sessionFilePath,
|
|
468
931
|
completion: result.completion,
|
|
932
|
+
turnOutcome: result.turnOutcome,
|
|
933
|
+
restStatus: latestRestStatus(resultMessages),
|
|
469
934
|
};
|
|
470
935
|
}
|
|
471
936
|
finally {
|