@ouro.bot/cli 0.1.0-alpha.5 → 0.1.0-alpha.500
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 +226 -183
- package/SerpentGuide.ouro/agent.json +82 -0
- package/SerpentGuide.ouro/psyche/SOUL.md +25 -0
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +2 -2
- package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
- package/assets/ouroboros.png +0 -0
- package/changelog.json +3418 -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 +989 -0
- 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 +426 -0
- package/dist/heart/background-operations.js +281 -0
- package/dist/heart/bridges/manager.js +358 -0
- package/dist/heart/bridges/state-machine.js +135 -0
- package/dist/heart/bridges/store.js +123 -0
- package/dist/heart/bundle-state.js +168 -0
- package/dist/heart/commitments.js +111 -0
- package/dist/heart/config-registry.js +304 -0
- package/dist/heart/config.js +193 -130
- package/dist/heart/core.js +1010 -261
- package/dist/heart/cross-chat-delivery.js +131 -0
- package/dist/heart/daemon/agent-config-check.js +490 -0
- package/dist/heart/daemon/agent-discovery.js +157 -0
- package/dist/heart/daemon/agent-service.js +360 -0
- package/dist/heart/daemon/agentic-repair.js +216 -0
- package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
- package/dist/heart/daemon/cadence.js +70 -0
- package/dist/heart/daemon/cli-defaults.js +640 -0
- package/dist/heart/daemon/cli-exec.js +7239 -0
- package/dist/heart/daemon/cli-help.js +493 -0
- package/dist/heart/daemon/cli-parse.js +1533 -0
- package/dist/heart/daemon/cli-render-doctor.js +57 -0
- package/dist/heart/daemon/cli-render.js +561 -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 +30 -697
- package/dist/heart/daemon/daemon-entry.js +359 -8
- package/dist/heart/daemon/daemon-health.js +141 -0
- package/dist/heart/daemon/daemon-runtime-sync.js +268 -0
- package/dist/heart/daemon/daemon-tombstone.js +236 -0
- package/dist/heart/daemon/daemon.js +813 -19
- package/dist/heart/daemon/dns-workflow.js +394 -0
- package/dist/heart/daemon/doctor-types.js +8 -0
- package/dist/heart/daemon/doctor.js +615 -0
- package/dist/heart/daemon/health-monitor.js +92 -1
- package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
- package/dist/heart/daemon/hooks/bundle-meta.js +206 -0
- 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 +171 -0
- package/dist/heart/daemon/log-tailer.js +82 -12
- package/dist/heart/daemon/logs-prune.js +110 -0
- package/dist/heart/daemon/message-router.js +17 -8
- package/dist/heart/daemon/os-cron-deps.js +134 -0
- 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 +215 -1
- 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 +39 -0
- package/dist/heart/daemon/runtime-logging.js +67 -16
- package/dist/heart/daemon/runtime-metadata.js +191 -0
- package/dist/heart/daemon/runtime-mode.js +67 -0
- package/dist/heart/daemon/safe-mode.js +161 -0
- package/dist/heart/daemon/sense-manager.js +431 -0
- 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 +307 -0
- package/dist/heart/daemon/stale-bundle-prune.js +96 -0
- package/dist/heart/daemon/startup-tui.js +264 -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 +524 -0
- package/dist/heart/daemon/up-progress.js +366 -0
- package/dist/heart/daemon/vault-items.js +56 -0
- package/dist/heart/delegation.js +62 -0
- 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-animation.js +10 -3
- package/dist/heart/{daemon → hatch}/hatch-flow.js +54 -136
- package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
- package/dist/heart/hatch/specialist-orchestrator.js +129 -0
- package/dist/heart/hatch/specialist-prompt.js +102 -0
- package/dist/heart/hatch/specialist-tools.js +306 -0
- package/dist/heart/identity.js +274 -61
- package/dist/heart/kept-notes.js +357 -0
- package/dist/heart/kicks.js +2 -20
- package/dist/heart/machine-identity.js +161 -0
- package/dist/heart/mail-import-discovery.js +353 -0
- package/dist/heart/mcp/mcp-server.js +653 -0
- package/dist/heart/migrate-config.js +100 -0
- package/dist/heart/model-capabilities.js +59 -0
- package/dist/heart/outlook/outlook-http-hooks.js +66 -0
- package/dist/heart/outlook/outlook-http-response.js +7 -0
- package/dist/heart/outlook/outlook-http-routes.js +244 -0
- package/dist/heart/outlook/outlook-http-static.js +103 -0
- package/dist/heart/outlook/outlook-http-transport.js +116 -0
- package/dist/heart/outlook/outlook-http.js +99 -0
- package/dist/heart/outlook/outlook-read.js +31 -0
- package/dist/heart/outlook/outlook-types.js +27 -0
- package/dist/heart/outlook/outlook-view.js +195 -0
- package/dist/heart/outlook/readers/agent-machine.js +382 -0
- package/dist/heart/outlook/readers/continuity-readers.js +336 -0
- package/dist/heart/outlook/readers/mail.js +362 -0
- package/dist/heart/outlook/readers/runtime-readers.js +644 -0
- package/dist/heart/outlook/readers/sessions.js +232 -0
- package/dist/heart/outlook/readers/shared.js +111 -0
- package/dist/heart/platform.js +81 -0
- package/dist/heart/progress-story.js +42 -0
- package/dist/heart/provider-attempt.js +134 -0
- package/dist/heart/provider-binding-resolver.js +255 -0
- package/dist/heart/provider-credentials.js +424 -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-state.js +216 -0
- package/dist/heart/provider-visibility.js +188 -0
- package/dist/heart/providers/anthropic-token.js +131 -0
- package/dist/heart/providers/anthropic.js +202 -50
- package/dist/heart/providers/azure.js +104 -13
- package/dist/heart/providers/error-classification.js +63 -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 +29 -7
- package/dist/heart/providers/openai-codex.js +63 -39
- package/dist/heart/runtime-capability-check.js +170 -0
- package/dist/heart/runtime-credentials.js +260 -0
- package/dist/heart/sense-truth.js +68 -0
- package/dist/heart/session-activity.js +190 -0
- package/dist/heart/session-events.js +1089 -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-transcript.js +167 -0
- package/dist/heart/start-of-turn-packet.js +345 -0
- package/dist/heart/streaming.js +129 -34
- package/dist/heart/sync.js +332 -0
- package/dist/heart/target-resolution.js +127 -0
- package/dist/heart/tempo.js +93 -0
- package/dist/heart/temporal-view.js +41 -0
- package/dist/heart/tool-activity-callbacks.js +36 -0
- package/dist/heart/tool-description.js +135 -0
- package/dist/heart/tool-friction.js +55 -0
- package/dist/heart/tool-loop.js +200 -0
- package/dist/heart/turn-context.js +372 -0
- package/dist/heart/turn-coordinator.js +28 -0
- package/dist/heart/versioning/ouro-bot-global-installer.js +128 -0
- package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
- package/dist/heart/versioning/ouro-path-installer.js +425 -0
- package/dist/heart/{daemon → versioning}/ouro-uti.js +11 -2
- package/dist/heart/versioning/ouro-version-manager.js +295 -0
- package/dist/heart/versioning/staged-restart.js +146 -0
- package/dist/heart/versioning/update-checker.js +115 -0
- package/dist/heart/versioning/update-hooks.js +142 -0
- package/dist/heart/versioning/wrapper-publish-guard.js +86 -0
- package/dist/mailroom/attention.js +167 -0
- package/dist/mailroom/autonomy.js +209 -0
- package/dist/mailroom/blob-store.js +606 -0
- package/dist/mailroom/core.js +672 -0
- package/dist/mailroom/entry.js +160 -0
- package/dist/mailroom/file-store.js +426 -0
- package/dist/mailroom/mbox-import.js +382 -0
- package/dist/mailroom/outbound.js +380 -0
- package/dist/mailroom/policy.js +263 -0
- package/dist/mailroom/reader.js +219 -0
- package/dist/mailroom/search-cache.js +182 -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 +77 -1
- package/dist/mind/context.js +173 -94
- package/dist/mind/diary-integrity.js +60 -0
- package/dist/mind/{memory.js → diary.js} +84 -96
- package/dist/mind/embedding-provider.js +60 -0
- package/dist/mind/file-state.js +179 -0
- package/dist/mind/first-impressions.js +16 -2
- package/dist/mind/friends/channel.js +73 -0
- package/dist/mind/friends/group-context.js +144 -0
- package/dist/mind/friends/resolver.js +54 -2
- package/dist/mind/friends/store-file.js +58 -3
- package/dist/mind/friends/trust-explanation.js +74 -0
- package/dist/mind/friends/types.js +10 -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 +76 -9
- package/dist/mind/phrases.js +1 -0
- package/dist/mind/prompt-refresh.js +3 -2
- package/dist/mind/prompt.js +1144 -117
- package/dist/mind/provenance-trust.js +26 -0
- package/dist/mind/scrutiny.js +173 -0
- package/dist/mind/token-estimate.js +8 -12
- package/dist/nerves/cli-logging.js +22 -3
- 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 +101 -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/runtime.js +5 -1
- package/dist/outlook-ui/assets/index-BPr5vNuM.css +1 -0
- package/dist/outlook-ui/assets/index-Cm51CY9W.js +61 -0
- package/dist/outlook-ui/index.html +15 -0
- package/dist/repertoire/ado-client.js +17 -56
- package/dist/repertoire/ado-semantic.js +11 -10
- package/dist/repertoire/api-client.js +97 -0
- package/dist/repertoire/bitwarden-store.js +774 -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 +301 -0
- package/dist/repertoire/coding/index.js +4 -1
- package/dist/repertoire/coding/manager.js +220 -13
- package/dist/repertoire/coding/spawner.js +58 -12
- package/dist/repertoire/coding/tools.js +209 -7
- package/dist/repertoire/commerce-errors.js +109 -0
- package/dist/repertoire/commerce-self-test.js +156 -0
- package/dist/repertoire/credential-access.js +111 -0
- package/dist/repertoire/data/ado-endpoints.json +188 -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 +255 -0
- package/dist/repertoire/mcp-manager.js +305 -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 +43 -5
- package/dist/repertoire/tasks/fix.js +182 -0
- package/dist/repertoire/tasks/index.js +39 -13
- 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 -79
- package/dist/repertoire/tool-results.js +29 -0
- package/dist/repertoire/tools-attachments.js +317 -0
- package/dist/repertoire/tools-base.js +49 -707
- package/dist/repertoire/tools-bluebubbles.js +94 -0
- package/dist/repertoire/tools-bridge.js +141 -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 +105 -0
- package/dist/repertoire/tools-github.js +1 -7
- package/dist/repertoire/tools-mail.js +1377 -0
- package/dist/repertoire/tools-notes.js +376 -0
- package/dist/repertoire/tools-session.js +749 -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 +64 -61
- package/dist/repertoire/tools-travel.js +125 -0
- package/dist/repertoire/tools-trip.js +356 -0
- package/dist/repertoire/tools-user-profile.js +144 -0
- package/dist/repertoire/tools-vault.js +40 -0
- package/dist/repertoire/tools.js +149 -98
- 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 +561 -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/attachment-cache.js +53 -0
- package/dist/senses/bluebubbles/attachment-download.js +137 -0
- package/dist/senses/bluebubbles/client.js +685 -0
- package/dist/senses/bluebubbles/entry.js +73 -0
- package/dist/senses/bluebubbles/inbound-log.js +126 -0
- package/dist/senses/bluebubbles/index.js +1881 -0
- package/dist/senses/bluebubbles/media.js +389 -0
- package/dist/senses/bluebubbles/model.js +282 -0
- package/dist/senses/bluebubbles/mutation-log.js +116 -0
- package/dist/senses/bluebubbles/processed-log.js +111 -0
- package/dist/senses/bluebubbles/replay.js +129 -0
- package/dist/senses/bluebubbles/runtime-state.js +109 -0
- package/dist/senses/bluebubbles/session-cleanup.js +72 -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 +605 -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 +83 -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 +768 -264
- package/dist/senses/commands.js +66 -3
- package/dist/senses/continuity.js +94 -0
- package/dist/senses/habit-turn-message.js +108 -0
- package/dist/senses/inner-dialog-worker.js +199 -16
- package/dist/senses/inner-dialog.js +640 -91
- package/dist/senses/mail-entry.js +66 -0
- package/dist/senses/mail.js +379 -0
- package/dist/senses/pipeline.js +665 -0
- 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 +844 -197
- package/dist/senses/trust-gate.js +207 -2
- package/dist/trips/core.js +138 -0
- package/dist/trips/store.js +146 -0
- package/package.json +47 -6
- 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/AdoptionSpecialist.ouro/agent.json +0 -20
- package/AdoptionSpecialist.ouro/psyche/SOUL.md +0 -22
- package/dist/heart/daemon/specialist-orchestrator.js +0 -160
- package/dist/heart/daemon/specialist-prompt.js +0 -40
- package/dist/heart/daemon/specialist-session.js +0 -142
- package/dist/heart/daemon/specialist-tools.js +0 -128
- package/dist/heart/daemon/subagent-installer.js +0 -125
- package/dist/inner-worker-entry.js +0 -4
- package/dist/mind/associative-recall.js +0 -197
- package/subagents/README.md +0 -73
- package/subagents/work-doer.md +0 -233
- package/subagents/work-merger.md +0 -624
- package/subagents/work-planner.md +0 -373
- /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/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/senses/commands.js
CHANGED
|
@@ -3,7 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createCommandRegistry = createCommandRegistry;
|
|
4
4
|
exports.getToolChoiceRequired = getToolChoiceRequired;
|
|
5
5
|
exports.resetToolChoiceRequired = resetToolChoiceRequired;
|
|
6
|
+
exports.getDebugMode = getDebugMode;
|
|
7
|
+
exports.resetDebugMode = resetDebugMode;
|
|
6
8
|
exports.registerDefaultCommands = registerDefaultCommands;
|
|
9
|
+
exports.getSharedCommandRegistry = getSharedCommandRegistry;
|
|
10
|
+
exports.resetSharedCommandRegistry = resetSharedCommandRegistry;
|
|
7
11
|
exports.parseSlashCommand = parseSlashCommand;
|
|
8
12
|
const identity_1 = require("../heart/identity");
|
|
9
13
|
const runtime_1 = require("../nerves/runtime");
|
|
@@ -21,7 +25,7 @@ function createCommandRegistry() {
|
|
|
21
25
|
},
|
|
22
26
|
dispatch(name, ctx) {
|
|
23
27
|
const cmd = commands.get(name);
|
|
24
|
-
if (!cmd)
|
|
28
|
+
if (!cmd || !cmd.channels.includes(ctx.channel))
|
|
25
29
|
return { handled: false };
|
|
26
30
|
return { handled: true, result: cmd.handler(ctx) };
|
|
27
31
|
},
|
|
@@ -35,6 +39,14 @@ function getToolChoiceRequired() {
|
|
|
35
39
|
function resetToolChoiceRequired() {
|
|
36
40
|
_toolChoiceRequired = false;
|
|
37
41
|
}
|
|
42
|
+
// Module-level toggle for debug mode
|
|
43
|
+
let _debugMode = false;
|
|
44
|
+
function getDebugMode() {
|
|
45
|
+
return _debugMode;
|
|
46
|
+
}
|
|
47
|
+
function resetDebugMode() {
|
|
48
|
+
_debugMode = false;
|
|
49
|
+
}
|
|
38
50
|
function registerDefaultCommands(registry) {
|
|
39
51
|
(0, runtime_1.emitNervesEvent)({
|
|
40
52
|
event: "repertoire.load_start",
|
|
@@ -51,7 +63,7 @@ function registerDefaultCommands(registry) {
|
|
|
51
63
|
registry.register({
|
|
52
64
|
name: "new",
|
|
53
65
|
description: "start a new conversation",
|
|
54
|
-
channels: ["
|
|
66
|
+
channels: ["teams"],
|
|
55
67
|
handler: () => ({ action: "new" }),
|
|
56
68
|
});
|
|
57
69
|
registry.register({
|
|
@@ -60,10 +72,36 @@ function registerDefaultCommands(registry) {
|
|
|
60
72
|
channels: ["cli", "teams"],
|
|
61
73
|
handler: (ctx) => {
|
|
62
74
|
const cmds = registry.list(ctx.channel);
|
|
63
|
-
const lines = cmds.map((c) => `/${c.name}
|
|
75
|
+
const lines = cmds.map((c) => `/${c.name} \u2014 ${c.description}`);
|
|
64
76
|
return { action: "response", message: lines.join("\n") };
|
|
65
77
|
},
|
|
66
78
|
});
|
|
79
|
+
registry.register({
|
|
80
|
+
name: "help",
|
|
81
|
+
description: "show keyboard shortcuts and tips",
|
|
82
|
+
channels: ["cli"],
|
|
83
|
+
/* v8 ignore start -- integration: /help command tested via E2E @preserve */
|
|
84
|
+
handler: () => ({
|
|
85
|
+
action: "response",
|
|
86
|
+
message: [
|
|
87
|
+
"Keyboard shortcuts:",
|
|
88
|
+
" Ctrl-C abort current generation / clear input / exit (twice within 2s)",
|
|
89
|
+
" Escape clear input",
|
|
90
|
+
" ↑ / ↓ browse input history (includes previous sessions)",
|
|
91
|
+
" Option+← / → jump between words",
|
|
92
|
+
" Ctrl+A / E jump to start / end of line",
|
|
93
|
+
" Option+Delete delete word backward",
|
|
94
|
+
" Option+D delete word forward",
|
|
95
|
+
" Alt+Enter insert newline (multi-line input)",
|
|
96
|
+
"",
|
|
97
|
+
"Commands:",
|
|
98
|
+
" /help this help",
|
|
99
|
+
" /commands list all commands",
|
|
100
|
+
" /exit quit",
|
|
101
|
+
].join("\n"),
|
|
102
|
+
}),
|
|
103
|
+
/* v8 ignore stop */
|
|
104
|
+
});
|
|
67
105
|
registry.register({
|
|
68
106
|
name: "tool-required",
|
|
69
107
|
description: "toggle tool_choice required mode (forces tool calls)",
|
|
@@ -73,6 +111,20 @@ function registerDefaultCommands(registry) {
|
|
|
73
111
|
return { action: "response", message: `tool-required mode: ${_toolChoiceRequired ? "ON" : "OFF"}` };
|
|
74
112
|
},
|
|
75
113
|
});
|
|
114
|
+
registry.register({
|
|
115
|
+
name: "debug",
|
|
116
|
+
description: "toggle debug mode — see more detail about what I'm doing",
|
|
117
|
+
channels: ["cli", "teams", "bluebubbles", "mail", "mcp"],
|
|
118
|
+
handler: () => {
|
|
119
|
+
_debugMode = !_debugMode;
|
|
120
|
+
return {
|
|
121
|
+
action: "response",
|
|
122
|
+
message: _debugMode
|
|
123
|
+
? "debug mode on — you'll see more detail about what I'm doing"
|
|
124
|
+
: "debug mode off — back to clean output",
|
|
125
|
+
};
|
|
126
|
+
},
|
|
127
|
+
});
|
|
76
128
|
(0, runtime_1.emitNervesEvent)({
|
|
77
129
|
event: "repertoire.load_end",
|
|
78
130
|
component: "repertoire",
|
|
@@ -80,6 +132,17 @@ function registerDefaultCommands(registry) {
|
|
|
80
132
|
meta: {},
|
|
81
133
|
});
|
|
82
134
|
}
|
|
135
|
+
let _sharedRegistry = null;
|
|
136
|
+
function getSharedCommandRegistry() {
|
|
137
|
+
if (!_sharedRegistry) {
|
|
138
|
+
_sharedRegistry = createCommandRegistry();
|
|
139
|
+
registerDefaultCommands(_sharedRegistry);
|
|
140
|
+
}
|
|
141
|
+
return _sharedRegistry;
|
|
142
|
+
}
|
|
143
|
+
function resetSharedCommandRegistry() {
|
|
144
|
+
_sharedRegistry = null;
|
|
145
|
+
}
|
|
83
146
|
function parseSlashCommand(input) {
|
|
84
147
|
const trimmed = input.trim();
|
|
85
148
|
if (!trimmed.startsWith("/"))
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeContinuityClauses = normalizeContinuityClauses;
|
|
4
|
+
exports.resolveMustResolveBeforeHandoff = resolveMustResolveBeforeHandoff;
|
|
5
|
+
exports.classifySteeringFollowUpEffect = classifySteeringFollowUpEffect;
|
|
6
|
+
const runtime_1 = require("../nerves/runtime");
|
|
7
|
+
const NO_HANDOFF_CLAUSES = new Set([
|
|
8
|
+
"dont return control until complete or blocked",
|
|
9
|
+
"do not return control until complete or blocked",
|
|
10
|
+
"dont hand back control until complete or blocked",
|
|
11
|
+
"do not hand back control until complete or blocked",
|
|
12
|
+
"keep going until youre done",
|
|
13
|
+
"keep going until you are done",
|
|
14
|
+
"keep working until youre done",
|
|
15
|
+
"keep working until you are done",
|
|
16
|
+
"dont stop until youre done",
|
|
17
|
+
"do not stop until youre done",
|
|
18
|
+
"only come back if blocked",
|
|
19
|
+
"only return if blocked",
|
|
20
|
+
"only respond if blocked",
|
|
21
|
+
"work autonomously on this",
|
|
22
|
+
"work on this autonomously",
|
|
23
|
+
"handle this autonomously",
|
|
24
|
+
]);
|
|
25
|
+
const CANCEL_SUPERSEDE_CLAUSES = new Set([
|
|
26
|
+
"stop",
|
|
27
|
+
"cancel that",
|
|
28
|
+
"cancel this",
|
|
29
|
+
"never mind",
|
|
30
|
+
"nevermind",
|
|
31
|
+
"forget it",
|
|
32
|
+
"ignore that",
|
|
33
|
+
"ignore this",
|
|
34
|
+
"hold off",
|
|
35
|
+
"ill take it from here",
|
|
36
|
+
"i will take it from here",
|
|
37
|
+
"lets do something else",
|
|
38
|
+
"stop working on that",
|
|
39
|
+
"stop working on this",
|
|
40
|
+
"dont do that",
|
|
41
|
+
"do not do that",
|
|
42
|
+
]);
|
|
43
|
+
function normalizeContinuityClauses(text) {
|
|
44
|
+
return text
|
|
45
|
+
.toLowerCase()
|
|
46
|
+
.split(/[\n.!?;]+/)
|
|
47
|
+
.map((clause) => clause.replace(/[^a-z\s]/g, "").replace(/\s+/g, " ").trim())
|
|
48
|
+
.filter(Boolean);
|
|
49
|
+
}
|
|
50
|
+
function resolveMustResolveBeforeHandoff(initialValue, ingressTexts) {
|
|
51
|
+
let current = initialValue;
|
|
52
|
+
for (const text of ingressTexts ?? []) {
|
|
53
|
+
for (const clause of normalizeContinuityClauses(text)) {
|
|
54
|
+
if (CANCEL_SUPERSEDE_CLAUSES.has(clause)) {
|
|
55
|
+
current = false;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (NO_HANDOFF_CLAUSES.has(clause)) {
|
|
59
|
+
current = true;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
(0, runtime_1.emitNervesEvent)({
|
|
64
|
+
component: "senses",
|
|
65
|
+
event: "senses.continuity_state_resolved",
|
|
66
|
+
message: "resolved continuity handoff state from ingress text",
|
|
67
|
+
meta: {
|
|
68
|
+
initialValue,
|
|
69
|
+
finalValue: current,
|
|
70
|
+
ingressCount: ingressTexts?.length ?? 0,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
return current;
|
|
74
|
+
}
|
|
75
|
+
function classifySteeringFollowUpEffect(text) {
|
|
76
|
+
const clauses = normalizeContinuityClauses(text);
|
|
77
|
+
let effect = "none";
|
|
78
|
+
if (clauses.some((clause) => CANCEL_SUPERSEDE_CLAUSES.has(clause))) {
|
|
79
|
+
effect = "clear_and_supersede";
|
|
80
|
+
}
|
|
81
|
+
else if (clauses.some((clause) => NO_HANDOFF_CLAUSES.has(clause))) {
|
|
82
|
+
effect = "set_no_handoff";
|
|
83
|
+
}
|
|
84
|
+
(0, runtime_1.emitNervesEvent)({
|
|
85
|
+
component: "senses",
|
|
86
|
+
event: "senses.continuity_follow_up_classified",
|
|
87
|
+
message: "classified steering follow-up continuity effect",
|
|
88
|
+
meta: {
|
|
89
|
+
effect,
|
|
90
|
+
clauseCount: clauses.length,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
return effect;
|
|
94
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildHabitTurnMessage = buildHabitTurnMessage;
|
|
4
|
+
const runtime_1 = require("../nerves/runtime");
|
|
5
|
+
function formatElapsed(ms) {
|
|
6
|
+
const minutes = Math.floor(ms / 60000);
|
|
7
|
+
if (minutes < 60) {
|
|
8
|
+
return `${minutes} ${minutes === 1 ? "minute" : "minutes"}`;
|
|
9
|
+
}
|
|
10
|
+
const hours = Math.floor(minutes / 60);
|
|
11
|
+
return `${hours} ${hours === 1 ? "hour" : "hours"}`;
|
|
12
|
+
}
|
|
13
|
+
function buildHabitTurnMessage(options) {
|
|
14
|
+
const { habitName, habitTitle, habitBody, lastRun, checkpoint, alsoDue, staleObligations, parseErrors, degradedComponents, now, } = options;
|
|
15
|
+
const hasBody = habitBody !== undefined && habitBody !== "";
|
|
16
|
+
// First beat: lastRun is null
|
|
17
|
+
if (lastRun === null) {
|
|
18
|
+
// Cold start: no checkpoint, no body — bare awareness
|
|
19
|
+
if (!checkpoint && !hasBody) {
|
|
20
|
+
(0, runtime_1.emitNervesEvent)({
|
|
21
|
+
component: "senses",
|
|
22
|
+
event: "senses.habit_turn_message_built",
|
|
23
|
+
message: "habit turn message built (cold start)",
|
|
24
|
+
meta: { habitName, coldStart: true },
|
|
25
|
+
});
|
|
26
|
+
return "...time passing. anything stirring?";
|
|
27
|
+
}
|
|
28
|
+
if (!hasBody) {
|
|
29
|
+
// First beat with no body: nudge
|
|
30
|
+
const sections = [
|
|
31
|
+
`your ${habitTitle} fired but has no instructions \u2014 add a body to \`habits/${habitName}.md\``,
|
|
32
|
+
];
|
|
33
|
+
appendTrailingExtras(sections, alsoDue, staleObligations, parseErrors, degradedComponents);
|
|
34
|
+
(0, runtime_1.emitNervesEvent)({
|
|
35
|
+
component: "senses",
|
|
36
|
+
event: "senses.habit_turn_message_built",
|
|
37
|
+
message: "habit turn message built (first beat, no body)",
|
|
38
|
+
meta: { habitName, firstBeat: true, hasBody: false },
|
|
39
|
+
});
|
|
40
|
+
return sections.join("\n\n");
|
|
41
|
+
}
|
|
42
|
+
const sections = [
|
|
43
|
+
`your ${habitTitle} is alive. this is its first breath.`,
|
|
44
|
+
habitBody,
|
|
45
|
+
];
|
|
46
|
+
appendTrailingExtras(sections, alsoDue, staleObligations, parseErrors, degradedComponents);
|
|
47
|
+
(0, runtime_1.emitNervesEvent)({
|
|
48
|
+
component: "senses",
|
|
49
|
+
event: "senses.habit_turn_message_built",
|
|
50
|
+
message: "habit turn message built (first beat)",
|
|
51
|
+
meta: { habitName, firstBeat: true },
|
|
52
|
+
});
|
|
53
|
+
return sections.join("\n\n");
|
|
54
|
+
}
|
|
55
|
+
// Normal turn
|
|
56
|
+
const sections = [];
|
|
57
|
+
// 1. Checkpoint
|
|
58
|
+
if (checkpoint) {
|
|
59
|
+
sections.push(`you were thinking about ${checkpoint}.`);
|
|
60
|
+
}
|
|
61
|
+
// 2. Elapsed time
|
|
62
|
+
const nowMs = now().getTime();
|
|
63
|
+
const lastRunMs = new Date(lastRun).getTime();
|
|
64
|
+
const elapsed = nowMs - lastRunMs;
|
|
65
|
+
sections.push(`${formatElapsed(elapsed)} have passed.`);
|
|
66
|
+
// 3. Body or no-body nudge
|
|
67
|
+
if (hasBody) {
|
|
68
|
+
sections.push(habitBody);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
sections.push(`your ${habitTitle} fired but has no instructions \u2014 add a body to \`habits/${habitName}.md\``);
|
|
72
|
+
}
|
|
73
|
+
// 4-7. Trailing extras
|
|
74
|
+
appendTrailingExtras(sections, alsoDue, staleObligations, parseErrors, degradedComponents);
|
|
75
|
+
(0, runtime_1.emitNervesEvent)({
|
|
76
|
+
component: "senses",
|
|
77
|
+
event: "senses.habit_turn_message_built",
|
|
78
|
+
message: "habit turn message built",
|
|
79
|
+
meta: {
|
|
80
|
+
habitName,
|
|
81
|
+
hasCheckpoint: !!checkpoint,
|
|
82
|
+
hasBody: hasBody,
|
|
83
|
+
staleObligationCount: staleObligations.length,
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
return sections.join("\n\n");
|
|
87
|
+
}
|
|
88
|
+
function appendTrailingExtras(sections, alsoDue, staleObligations, parseErrors, degradedComponents) {
|
|
89
|
+
// 4. Also-due
|
|
90
|
+
if (alsoDue) {
|
|
91
|
+
sections.push(alsoDue);
|
|
92
|
+
}
|
|
93
|
+
// 5. Stale obligations
|
|
94
|
+
if (staleObligations.length > 0) {
|
|
95
|
+
const lines = staleObligations.map((o) => `[internal] obligation: ${o.friendName} — waiting ${formatElapsed(o.stalenessMs)}`);
|
|
96
|
+
sections.push(lines.join("\n"));
|
|
97
|
+
}
|
|
98
|
+
// 6. Parse errors
|
|
99
|
+
if (parseErrors.length > 0) {
|
|
100
|
+
const lines = parseErrors.map((e) => `I noticed my habit file \`${e.file}\` has invalid frontmatter \u2014 I should fix it. (${e.error})`);
|
|
101
|
+
sections.push(lines.join("\n"));
|
|
102
|
+
}
|
|
103
|
+
// 7. Degraded state
|
|
104
|
+
if (degradedComponents.length > 0) {
|
|
105
|
+
const reasons = degradedComponents.map((d) => `${d.component}: ${d.reason}`).join("; ");
|
|
106
|
+
sections.push(`[note: my scheduling is degraded: ${reasons}]`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -1,30 +1,201 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.HABIT_RECURSION_BURST_THRESHOLD = exports.HABIT_RECURSION_BURST_WINDOW_MS = exports.HABIT_RECURSION_MIN_INTERVAL_MS = exports.MAX_CONSECUTIVE_INSTINCT_TURNS = void 0;
|
|
3
37
|
exports.createInnerDialogWorker = createInnerDialogWorker;
|
|
4
38
|
exports.startInnerDialogWorker = startInnerDialogWorker;
|
|
39
|
+
const path = __importStar(require("path"));
|
|
5
40
|
const inner_dialog_1 = require("./inner-dialog");
|
|
6
41
|
const runtime_1 = require("../nerves/runtime");
|
|
7
|
-
|
|
42
|
+
const identity_1 = require("../heart/identity");
|
|
43
|
+
const pending_1 = require("../mind/pending");
|
|
44
|
+
const habit_runtime_state_1 = require("../heart/habits/habit-runtime-state");
|
|
45
|
+
/**
|
|
46
|
+
* Cap on consecutive `instinct` follow-on turns triggered by `hasPendingWork()`
|
|
47
|
+
* with no externally-queued work in between. Without this cap, a turn that
|
|
48
|
+
* writes anything back into the inner-dialog pending dir as a side effect of
|
|
49
|
+
* processing (e.g. a surface tool routing a response) puts the worker into
|
|
50
|
+
* a self-sustaining loop where the next turn's drain produces another write,
|
|
51
|
+
* and so on. Real workflows rarely chain more than 2–3 instinct turns; an
|
|
52
|
+
* external trigger (habit, poke, chat) resets the counter so legitimate
|
|
53
|
+
* follow-on work is unaffected.
|
|
54
|
+
*
|
|
55
|
+
* Three feels right: legitimate cascading follow-ups (e.g. processing a
|
|
56
|
+
* batch of delegated returns) get through; a true self-loop caps fast.
|
|
57
|
+
*/
|
|
58
|
+
exports.MAX_CONSECUTIVE_INSTINCT_TURNS = 3;
|
|
59
|
+
/**
|
|
60
|
+
* Habit recursion detector thresholds. The instinct cap above protects
|
|
61
|
+
* against pending-dir self-loops; this protects against the *external*
|
|
62
|
+
* IPC self-loop where heartbeat-shaped messages get re-issued faster
|
|
63
|
+
* than their cadence — e.g. a hook misconfigured to repost on every
|
|
64
|
+
* heartbeat, a daemon retry storm, or a stuck timer firing back-to-back.
|
|
65
|
+
*
|
|
66
|
+
* MIN_INTERVAL_MS — two of the same habit within this window is suspect
|
|
67
|
+
* regardless of cadence (no realistic habit fires every few seconds).
|
|
68
|
+
* BURST_THRESHOLD over BURST_WINDOW_MS catches slower runaways that stay
|
|
69
|
+
* just under MIN_INTERVAL_MS.
|
|
70
|
+
*
|
|
71
|
+
* Detection is observation-only: it emits warn-level nerves events, it
|
|
72
|
+
* does not drop the message. An operator (or follow-up auto-recovery)
|
|
73
|
+
* decides what to do with the signal.
|
|
74
|
+
*/
|
|
75
|
+
exports.HABIT_RECURSION_MIN_INTERVAL_MS = 5_000;
|
|
76
|
+
exports.HABIT_RECURSION_BURST_WINDOW_MS = 60_000;
|
|
77
|
+
exports.HABIT_RECURSION_BURST_THRESHOLD = 5;
|
|
78
|
+
function createInnerDialogWorker(runTurn = (options) => (0, inner_dialog_1.runInnerDialogTurn)(options), hasPendingWork = () => (0, pending_1.hasPendingMessages)((0, pending_1.getInnerDialogPendingDir)((0, identity_1.getAgentName)())), nowSource = () => Date.now()) {
|
|
8
79
|
let running = false;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
80
|
+
const queue = [];
|
|
81
|
+
const lastFireByHabit = new Map();
|
|
82
|
+
const recentHabitFires = [];
|
|
83
|
+
function recordHabitFireForRecursion(habitName) {
|
|
84
|
+
const now = nowSource();
|
|
85
|
+
const previous = lastFireByHabit.get(habitName);
|
|
86
|
+
if (previous !== undefined) {
|
|
87
|
+
const intervalMs = now - previous;
|
|
88
|
+
if (intervalMs < exports.HABIT_RECURSION_MIN_INTERVAL_MS) {
|
|
89
|
+
(0, runtime_1.emitNervesEvent)({
|
|
90
|
+
level: "warn",
|
|
91
|
+
component: "senses",
|
|
92
|
+
event: "senses.habit_recursion_suspected",
|
|
93
|
+
message: "habit fired suspiciously fast after the previous fire — possible self-recursion or duplicate dispatch",
|
|
94
|
+
meta: {
|
|
95
|
+
habitName,
|
|
96
|
+
intervalMs,
|
|
97
|
+
thresholdMs: exports.HABIT_RECURSION_MIN_INTERVAL_MS,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}
|
|
15
101
|
}
|
|
16
|
-
|
|
102
|
+
lastFireByHabit.set(habitName, now);
|
|
103
|
+
recentHabitFires.push(now);
|
|
104
|
+
while (recentHabitFires.length > 0 && now - recentHabitFires[0] > exports.HABIT_RECURSION_BURST_WINDOW_MS) {
|
|
105
|
+
recentHabitFires.shift();
|
|
106
|
+
}
|
|
107
|
+
if (recentHabitFires.length >= exports.HABIT_RECURSION_BURST_THRESHOLD) {
|
|
17
108
|
(0, runtime_1.emitNervesEvent)({
|
|
18
|
-
level: "
|
|
109
|
+
level: "warn",
|
|
19
110
|
component: "senses",
|
|
20
|
-
event: "senses.
|
|
21
|
-
message: "
|
|
111
|
+
event: "senses.habit_recursion_burst",
|
|
112
|
+
message: "habit messages arriving in a burst — possible runaway loop",
|
|
22
113
|
meta: {
|
|
23
|
-
|
|
24
|
-
|
|
114
|
+
count: recentHabitFires.length,
|
|
115
|
+
windowMs: exports.HABIT_RECURSION_BURST_WINDOW_MS,
|
|
116
|
+
thresholdCount: exports.HABIT_RECURSION_BURST_THRESHOLD,
|
|
117
|
+
lastHabitName: habitName,
|
|
25
118
|
},
|
|
26
119
|
});
|
|
27
120
|
}
|
|
121
|
+
}
|
|
122
|
+
async function run(reason, taskId, habitName) {
|
|
123
|
+
if (running) {
|
|
124
|
+
queue.push({ reason, taskId, habitName });
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
running = true;
|
|
128
|
+
try {
|
|
129
|
+
let nextReason = reason;
|
|
130
|
+
let nextTaskId = taskId;
|
|
131
|
+
let nextHabitName = habitName;
|
|
132
|
+
let consecutiveInstinctTurns = reason === "instinct" ? 1 : 0;
|
|
133
|
+
do {
|
|
134
|
+
try {
|
|
135
|
+
await runTurn({ reason: nextReason, taskId: nextTaskId, habitName: nextHabitName });
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
(0, runtime_1.emitNervesEvent)({
|
|
139
|
+
level: "error",
|
|
140
|
+
component: "senses",
|
|
141
|
+
event: "senses.inner_dialog_worker_error",
|
|
142
|
+
message: "inner dialog worker turn failed",
|
|
143
|
+
meta: {
|
|
144
|
+
reason: nextReason,
|
|
145
|
+
error: error instanceof Error ? error.message : String(error),
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
// Record lastRun after a habit turn without dirtying the tracked habit file.
|
|
150
|
+
if (nextReason === "habit" && nextHabitName) {
|
|
151
|
+
try {
|
|
152
|
+
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
153
|
+
(0, habit_runtime_state_1.recordHabitRun)(agentRoot, nextHabitName, new Date().toISOString(), {
|
|
154
|
+
definitionPath: path.join(agentRoot, "habits", `${nextHabitName}.md`),
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// Habit file/state may be unavailable during the turn — skip gracefully
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Drain queue first. Externally-queued work resets the instinct cap
|
|
162
|
+
// because a real outside trigger arrived between turns.
|
|
163
|
+
if (queue.length > 0) {
|
|
164
|
+
const next = queue.shift();
|
|
165
|
+
nextReason = next.reason;
|
|
166
|
+
nextTaskId = next.taskId;
|
|
167
|
+
nextHabitName = next.habitName;
|
|
168
|
+
consecutiveInstinctTurns = nextReason === "instinct" ? consecutiveInstinctTurns + 1 : 0;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
// Then check hasPendingWork fallback. This is the loop site: any
|
|
172
|
+
// tool that writes to the inner-dialog pending dir during a turn
|
|
173
|
+
// would cause hasPendingWork() to be true here, producing a
|
|
174
|
+
// self-sustaining "instinct" loop with no external input. Cap it.
|
|
175
|
+
if (hasPendingWork()) {
|
|
176
|
+
if (consecutiveInstinctTurns >= exports.MAX_CONSECUTIVE_INSTINCT_TURNS) {
|
|
177
|
+
(0, runtime_1.emitNervesEvent)({
|
|
178
|
+
level: "warn",
|
|
179
|
+
component: "senses",
|
|
180
|
+
event: "senses.inner_dialog_worker_instinct_loop_capped",
|
|
181
|
+
message: "inner dialog worker stopped chaining instinct turns; pending work remains for next external trigger",
|
|
182
|
+
meta: {
|
|
183
|
+
consecutiveInstinctTurns,
|
|
184
|
+
cap: exports.MAX_CONSECUTIVE_INSTINCT_TURNS,
|
|
185
|
+
lastReason: nextReason,
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
consecutiveInstinctTurns += 1;
|
|
191
|
+
nextReason = "instinct";
|
|
192
|
+
nextTaskId = undefined;
|
|
193
|
+
nextHabitName = undefined;
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
break;
|
|
197
|
+
} while (true);
|
|
198
|
+
}
|
|
28
199
|
finally {
|
|
29
200
|
running = false;
|
|
30
201
|
}
|
|
@@ -33,12 +204,24 @@ function createInnerDialogWorker(runTurn = (options) => (0, inner_dialog_1.runIn
|
|
|
33
204
|
if (!message || typeof message !== "object")
|
|
34
205
|
return;
|
|
35
206
|
const maybeMessage = message;
|
|
207
|
+
if (maybeMessage.type === "habit") {
|
|
208
|
+
/* v8 ignore next -- defensive fallback: live habit dispatch always sets habitName @preserve */
|
|
209
|
+
const habitName = maybeMessage.habitName ?? "(unnamed)";
|
|
210
|
+
recordHabitFireForRecursion(habitName);
|
|
211
|
+
await run("habit", undefined, maybeMessage.habitName);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
36
214
|
if (maybeMessage.type === "heartbeat") {
|
|
37
|
-
|
|
215
|
+
// Backward compatibility: heartbeat -> habit/heartbeat
|
|
216
|
+
recordHabitFireForRecursion("heartbeat");
|
|
217
|
+
await run("habit", undefined, "heartbeat");
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (maybeMessage.type === "poke") {
|
|
221
|
+
await run("instinct", maybeMessage.taskId);
|
|
38
222
|
return;
|
|
39
223
|
}
|
|
40
|
-
if (maybeMessage.type === "
|
|
41
|
-
maybeMessage.type === "chat" ||
|
|
224
|
+
if (maybeMessage.type === "chat" ||
|
|
42
225
|
maybeMessage.type === "message") {
|
|
43
226
|
await run("instinct");
|
|
44
227
|
return;
|