@ouro.bot/cli 0.1.0-alpha.23 → 0.1.0-alpha.231

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.
Files changed (241) hide show
  1. package/README.md +187 -191
  2. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
  3. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +1 -1
  4. package/changelog.json +1408 -1
  5. package/dist/arc/attention-types.js +8 -0
  6. package/dist/arc/cares.js +140 -0
  7. package/dist/arc/episodes.js +119 -0
  8. package/dist/arc/intentions.js +133 -0
  9. package/dist/arc/json-store.js +120 -0
  10. package/dist/arc/obligations.js +237 -0
  11. package/dist/arc/presence.js +185 -0
  12. package/dist/heart/active-work.js +832 -0
  13. package/dist/heart/agent-entry.js +37 -2
  14. package/dist/heart/auth/auth-flow.js +447 -0
  15. package/dist/heart/bridges/manager.js +358 -0
  16. package/dist/heart/bridges/state-machine.js +135 -0
  17. package/dist/heart/bridges/store.js +123 -0
  18. package/dist/heart/commitments.js +111 -0
  19. package/dist/heart/config-registry.js +305 -0
  20. package/dist/heart/config.js +63 -30
  21. package/dist/heart/core.js +601 -145
  22. package/dist/heart/cross-chat-delivery.js +131 -0
  23. package/dist/heart/daemon/agent-config-check.js +149 -0
  24. package/dist/heart/daemon/agent-discovery.js +81 -0
  25. package/dist/heart/daemon/agent-service.js +360 -0
  26. package/dist/heart/daemon/cadence.js +70 -0
  27. package/dist/heart/daemon/cli-defaults.js +557 -0
  28. package/dist/heart/daemon/cli-exec.js +1847 -0
  29. package/dist/heart/daemon/cli-parse.js +759 -0
  30. package/dist/heart/daemon/cli-render.js +316 -0
  31. package/dist/heart/daemon/cli-types.js +8 -0
  32. package/dist/heart/daemon/daemon-cli.js +29 -1163
  33. package/dist/heart/daemon/daemon-entry.js +202 -4
  34. package/dist/heart/daemon/daemon-health.js +136 -0
  35. package/dist/heart/daemon/daemon-runtime-sync.js +153 -12
  36. package/dist/heart/daemon/daemon-tombstone.js +123 -0
  37. package/dist/heart/daemon/daemon.js +489 -20
  38. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  39. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  40. package/dist/heart/daemon/inner-status.js +89 -0
  41. package/dist/heart/daemon/launchd.js +39 -8
  42. package/dist/heart/daemon/log-tailer.js +4 -3
  43. package/dist/heart/daemon/message-router.js +17 -8
  44. package/dist/heart/daemon/os-cron-deps.js +134 -0
  45. package/dist/heart/daemon/ouro-bot-entry.js +1 -1
  46. package/dist/heart/daemon/process-manager.js +123 -0
  47. package/dist/heart/daemon/run-hooks.js +2 -0
  48. package/dist/heart/daemon/runtime-logging.js +58 -15
  49. package/dist/heart/daemon/runtime-metadata.js +101 -0
  50. package/dist/heart/daemon/runtime-mode.js +67 -0
  51. package/dist/heart/daemon/safe-mode.js +161 -0
  52. package/dist/heart/daemon/sense-manager.js +72 -3
  53. package/dist/heart/daemon/session-id-resolver.js +131 -0
  54. package/dist/heart/daemon/skill-management-installer.js +94 -0
  55. package/dist/heart/daemon/socket-client.js +201 -0
  56. package/dist/heart/daemon/task-scheduler.js +3 -25
  57. package/dist/heart/daemon/thoughts.js +507 -0
  58. package/dist/heart/delegation.js +62 -0
  59. package/dist/heart/habits/habit-migration.js +181 -0
  60. package/dist/heart/habits/habit-parser.js +119 -0
  61. package/dist/heart/habits/habit-scheduler.js +369 -0
  62. package/dist/heart/{daemon → hatch}/hatch-flow.js +29 -119
  63. package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
  64. package/dist/heart/{daemon → hatch}/specialist-prompt.js +10 -7
  65. package/dist/heart/{daemon → hatch}/specialist-tools.js +49 -3
  66. package/dist/heart/identity.js +144 -55
  67. package/dist/heart/kicks.js +2 -20
  68. package/dist/heart/mcp/mcp-server.js +608 -0
  69. package/dist/heart/migrate-config.js +127 -0
  70. package/dist/heart/model-capabilities.js +48 -0
  71. package/dist/heart/outlook/outlook-http.js +439 -0
  72. package/dist/heart/outlook/outlook-read.js +1618 -0
  73. package/dist/heart/outlook/outlook-render.js +1032 -0
  74. package/dist/heart/outlook/outlook-types.js +7 -0
  75. package/dist/heart/outlook/outlook-view.js +194 -0
  76. package/dist/heart/progress-story.js +42 -0
  77. package/dist/heart/provider-failover.js +88 -0
  78. package/dist/heart/provider-ping.js +162 -0
  79. package/dist/heart/providers/anthropic-token.js +163 -0
  80. package/dist/heart/providers/anthropic.js +187 -41
  81. package/dist/heart/providers/azure.js +116 -10
  82. package/dist/heart/providers/github-copilot.js +157 -0
  83. package/dist/heart/providers/minimax.js +33 -3
  84. package/dist/heart/providers/openai-codex.js +51 -16
  85. package/dist/heart/session-activity.js +172 -0
  86. package/dist/heart/session-recall.js +216 -0
  87. package/dist/heart/start-of-turn-packet.js +330 -0
  88. package/dist/heart/streaming.js +36 -27
  89. package/dist/heart/sync.js +217 -0
  90. package/dist/heart/target-resolution.js +127 -0
  91. package/dist/heart/tempo.js +93 -0
  92. package/dist/heart/temporal-view.js +41 -0
  93. package/dist/heart/tool-activity-callbacks.js +36 -0
  94. package/dist/heart/tool-description.js +135 -0
  95. package/dist/heart/tool-loop.js +200 -0
  96. package/dist/heart/turn-context.js +358 -0
  97. package/dist/heart/turn-coordinator.js +28 -0
  98. package/dist/heart/versioning/ouro-bot-global-installer.js +128 -0
  99. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  100. package/dist/heart/{daemon → versioning}/ouro-path-installer.js +78 -35
  101. package/dist/heart/versioning/ouro-version-manager.js +171 -0
  102. package/dist/heart/{daemon → versioning}/staged-restart.js +30 -6
  103. package/dist/heart/{daemon → versioning}/update-checker.js +9 -1
  104. package/dist/heart/{daemon → versioning}/update-hooks.js +20 -2
  105. package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +41 -3
  106. package/dist/mind/associative-recall.js +126 -66
  107. package/dist/mind/bundle-manifest.js +8 -1
  108. package/dist/mind/context.js +125 -14
  109. package/dist/mind/{memory.js → diary.js} +73 -96
  110. package/dist/mind/embedding-provider.js +60 -0
  111. package/dist/mind/file-state.js +179 -0
  112. package/dist/mind/first-impressions.js +16 -2
  113. package/dist/mind/friends/channel.js +56 -0
  114. package/dist/mind/friends/group-context.js +144 -0
  115. package/dist/mind/friends/store-file.js +58 -3
  116. package/dist/mind/friends/trust-explanation.js +74 -0
  117. package/dist/mind/friends/types.js +8 -0
  118. package/dist/mind/journal-index.js +161 -0
  119. package/dist/mind/obligation-steering.js +221 -0
  120. package/dist/mind/pending.js +76 -9
  121. package/dist/mind/phrases.js +1 -0
  122. package/dist/mind/prompt.js +779 -109
  123. package/dist/mind/scrutiny.js +173 -0
  124. package/dist/mind/token-estimate.js +8 -12
  125. package/dist/nerves/coverage/audit.js +1 -1
  126. package/dist/nerves/coverage/file-completeness.js +47 -5
  127. package/dist/nerves/coverage/run-artifacts.js +1 -1
  128. package/dist/nerves/event-buffer.js +111 -0
  129. package/dist/nerves/index.js +64 -4
  130. package/dist/nerves/observation.js +20 -0
  131. package/dist/nerves/runtime.js +5 -1
  132. package/dist/outlook-ui/assets/index-Ck8agNeO.js +61 -0
  133. package/dist/outlook-ui/assets/index-LwChZTgL.css +1 -0
  134. package/dist/outlook-ui/index.html +15 -0
  135. package/dist/repertoire/ado-client.js +15 -56
  136. package/dist/repertoire/ado-semantic.js +11 -5
  137. package/dist/repertoire/api-client.js +97 -0
  138. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  139. package/dist/repertoire/coding/context-pack.js +330 -0
  140. package/dist/repertoire/coding/feedback.js +197 -30
  141. package/dist/repertoire/coding/manager.js +149 -2
  142. package/dist/repertoire/coding/spawner.js +55 -9
  143. package/dist/repertoire/coding/tools.js +170 -7
  144. package/dist/repertoire/credential-access.js +449 -0
  145. package/dist/repertoire/github-client.js +14 -55
  146. package/dist/repertoire/graph-client.js +11 -52
  147. package/dist/repertoire/guardrails.js +342 -0
  148. package/dist/repertoire/mcp-client.js +254 -0
  149. package/dist/repertoire/mcp-manager.js +251 -0
  150. package/dist/repertoire/shell-sessions.js +133 -0
  151. package/dist/repertoire/skills.js +14 -23
  152. package/dist/repertoire/tasks/board.js +43 -5
  153. package/dist/repertoire/tasks/fix.js +182 -0
  154. package/dist/repertoire/tasks/index.js +28 -10
  155. package/dist/repertoire/tasks/lifecycle.js +2 -2
  156. package/dist/repertoire/tasks/parser.js +3 -2
  157. package/dist/repertoire/tasks/scanner.js +194 -37
  158. package/dist/repertoire/tasks/transitions.js +11 -28
  159. package/dist/repertoire/tools-base.js +35 -771
  160. package/dist/repertoire/tools-bluebubbles.js +94 -0
  161. package/dist/repertoire/tools-bridge.js +141 -0
  162. package/dist/repertoire/tools-config.js +266 -0
  163. package/dist/repertoire/tools-continuity.js +248 -0
  164. package/dist/repertoire/tools-credential.js +184 -0
  165. package/dist/repertoire/tools-files.js +342 -0
  166. package/dist/repertoire/tools-flow.js +62 -0
  167. package/dist/repertoire/tools-github.js +1 -6
  168. package/dist/repertoire/tools-memory.js +347 -0
  169. package/dist/repertoire/tools-session.js +739 -0
  170. package/dist/repertoire/tools-shell.js +120 -0
  171. package/dist/repertoire/tools-surface.js +243 -0
  172. package/dist/repertoire/tools-teams.js +12 -59
  173. package/dist/repertoire/tools-travel.js +125 -0
  174. package/dist/repertoire/tools.js +132 -124
  175. package/dist/repertoire/travel-api-client.js +214 -0
  176. package/dist/scripts/claude-code-hook.js +41 -0
  177. package/dist/scripts/claude-code-stop-hook.js +47 -0
  178. package/dist/senses/attention-queue.js +97 -0
  179. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +109 -10
  180. package/dist/senses/bluebubbles/entry.js +13 -0
  181. package/dist/senses/bluebubbles/inbound-log.js +109 -0
  182. package/dist/senses/bluebubbles/index.js +1374 -0
  183. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +119 -24
  184. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +13 -5
  185. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +46 -6
  186. package/dist/senses/bluebubbles/runtime-state.js +109 -0
  187. package/dist/senses/bluebubbles/session-cleanup.js +72 -0
  188. package/dist/senses/cli/adapter.js +274 -0
  189. package/dist/senses/cli/ink-app.js +156 -0
  190. package/dist/senses/cli/inline-diff.js +64 -0
  191. package/dist/senses/cli/message-list.js +51 -0
  192. package/dist/senses/cli/ouro-tui.js +358 -0
  193. package/dist/senses/cli/spinner-imperative.js +135 -0
  194. package/dist/senses/cli/spinner.js +101 -0
  195. package/dist/senses/cli/status-line.js +60 -0
  196. package/dist/senses/cli/streaming-markdown.js +526 -0
  197. package/dist/senses/cli/tool-display.js +83 -0
  198. package/dist/senses/cli/tool-render.js +85 -0
  199. package/dist/senses/cli/tui-store.js +198 -0
  200. package/dist/senses/cli/virtual-list.js +35 -0
  201. package/dist/senses/cli-entry.js +1 -1
  202. package/dist/senses/cli-layout.js +187 -0
  203. package/dist/senses/cli.js +503 -244
  204. package/dist/senses/commands.js +65 -1
  205. package/dist/senses/continuity.js +94 -0
  206. package/dist/senses/habit-turn-message.js +108 -0
  207. package/dist/senses/inner-dialog-worker.js +112 -19
  208. package/dist/senses/inner-dialog.js +594 -85
  209. package/dist/senses/pipeline.js +559 -0
  210. package/dist/senses/shared-turn.js +196 -0
  211. package/dist/senses/surface-tool.js +68 -0
  212. package/dist/senses/teams.js +667 -120
  213. package/dist/senses/trust-gate.js +112 -2
  214. package/package.json +12 -6
  215. package/skills/browser-navigation.md +110 -0
  216. package/skills/configure-dev-tools.md +81 -0
  217. package/skills/travel-planning.md +138 -0
  218. package/dist/heart/daemon/subagent-installer.js +0 -134
  219. package/dist/senses/bluebubbles-entry.js +0 -11
  220. package/dist/senses/bluebubbles.js +0 -421
  221. package/dist/senses/debug-activity.js +0 -107
  222. package/subagents/README.md +0 -73
  223. package/subagents/work-doer.md +0 -235
  224. package/subagents/work-merger.md +0 -618
  225. package/subagents/work-planner.md +0 -382
  226. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  227. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  228. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  229. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  230. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  231. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  232. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  233. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  234. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  235. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  236. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  237. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +0 -0
  238. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  239. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  240. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  241. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createToolActivityCallbacks = createToolActivityCallbacks;
4
+ const tool_description_1 = require("./tool-description");
5
+ const runtime_1 = require("../nerves/runtime");
6
+ function createToolActivityCallbacks(options) {
7
+ (0, runtime_1.emitNervesEvent)({
8
+ component: "engine",
9
+ event: "engine.tool_activity_callbacks_created",
10
+ message: "tool activity callbacks initialized",
11
+ meta: {},
12
+ });
13
+ // Track the last description so we can reference it in END messages
14
+ let lastDescription = null;
15
+ return {
16
+ onToolStart(name, args) {
17
+ const description = (0, tool_description_1.humanReadableToolDescription)(name, args);
18
+ if (description === null)
19
+ return; // hidden tool (settle, rest, descend)
20
+ lastDescription = description;
21
+ options.onDescription(description);
22
+ },
23
+ onToolEnd(name, summary, success) {
24
+ const desc = lastDescription ?? name;
25
+ // Strip trailing "..." from description for the result line
26
+ const cleanDesc = desc.endsWith("...") ? desc.slice(0, -3) : desc;
27
+ if (!success) {
28
+ options.onFailure(`\u2717 ${cleanDesc} — ${summary}`);
29
+ return;
30
+ }
31
+ if (options.isDebug()) {
32
+ options.onResult(`\u2713 ${cleanDesc}`);
33
+ }
34
+ },
35
+ };
36
+ }
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.humanReadableToolDescription = humanReadableToolDescription;
4
+ const runtime_1 = require("../nerves/runtime");
5
+ function basename(filePath) {
6
+ const idx = filePath.lastIndexOf("/");
7
+ return idx >= 0 ? filePath.slice(idx + 1) : filePath;
8
+ }
9
+ function truncate(text, max) {
10
+ if (text.length <= max)
11
+ return text;
12
+ // Cut at last space before maxLen to avoid mid-word truncation
13
+ const slice = text.slice(0, max - 1);
14
+ const lastSpace = slice.lastIndexOf(" ");
15
+ if (lastSpace > 0)
16
+ return text.slice(0, lastSpace) + "\u2026";
17
+ // No space found (single long word) — hard truncate
18
+ return slice + "\u2026";
19
+ }
20
+ const TOOL_DESCRIPTIONS = {
21
+ // File operations
22
+ shell: (args) => {
23
+ const cmd = args.command;
24
+ if (!cmd)
25
+ return "running a command...";
26
+ return `running ${truncate(cmd, 50)}...`;
27
+ },
28
+ read_file: (args) => {
29
+ const fp = args.path || args.file_path;
30
+ if (!fp)
31
+ return "reading a file...";
32
+ return `reading ${basename(fp)}...`;
33
+ },
34
+ write_file: (args) => {
35
+ const fp = args.path || args.file_path;
36
+ if (!fp)
37
+ return "writing a file...";
38
+ return `writing ${basename(fp)}...`;
39
+ },
40
+ edit_file: (args) => {
41
+ const fp = args.path || args.file_path;
42
+ if (!fp)
43
+ return "editing a file...";
44
+ return `editing ${basename(fp)}...`;
45
+ },
46
+ glob: (args) => {
47
+ const p = args.pattern;
48
+ if (!p)
49
+ return "searching for files...";
50
+ return `searching for ${truncate(p, 40)}...`;
51
+ },
52
+ grep: (args) => {
53
+ const p = args.pattern;
54
+ if (!p)
55
+ return "searching code...";
56
+ return `searching code for '${truncate(p, 40)}'...`;
57
+ },
58
+ // Memory and knowledge
59
+ recall: (args) => {
60
+ const q = args.query;
61
+ if (!q)
62
+ return "searching memory...";
63
+ return `searching memory for '${truncate(q, 40)}'...`;
64
+ },
65
+ diary_write: (args) => {
66
+ const about = args.about;
67
+ return about ? `noting something about ${truncate(about, 30)}...` : "noting something down...";
68
+ },
69
+ save_friend_note: () => "making a note about you...",
70
+ get_friend_note: () => "checking my notes...",
71
+ load_skill: (args) => {
72
+ const name = args.name || args.skill;
73
+ return name ? `loading ${name} skill...` : "loading a skill...";
74
+ },
75
+ // Session and context
76
+ query_session: (args) => {
77
+ const mode = args.mode;
78
+ if (mode === "search")
79
+ return `searching session for '${truncate(args.query || "", 30)}'...`;
80
+ if (mode === "status")
81
+ return "checking inner dialog status...";
82
+ return "checking session history...";
83
+ },
84
+ web_search: (args) => {
85
+ const q = args.query;
86
+ return q ? `searching the web for '${truncate(q, 35)}'...` : "searching the web...";
87
+ },
88
+ coding_spawn: (args) => {
89
+ const runner = args.runner;
90
+ return runner ? `starting ${runner} coding session...` : "starting coding session...";
91
+ },
92
+ coding_status: () => "checking coding sessions...",
93
+ coding_tail: () => "reading coding output...",
94
+ coding_kill: () => "stopping coding session...",
95
+ bridge_manage: () => "managing conversation bridge...",
96
+ // Communication
97
+ send_message: (args) => {
98
+ const to = args.to;
99
+ return to ? `sending a message to ${to}...` : "sending a message...";
100
+ },
101
+ surface: () => "sharing a thought...",
102
+ // Metacognitive (agent's inner life)
103
+ ponder: (args) => {
104
+ const thought = args.thought;
105
+ return thought ? `thinking about ${truncate(thought, 40)}...` : "thinking deeper...";
106
+ },
107
+ observe: () => null,
108
+ claude: () => "reasoning...",
109
+ set_reasoning_effort: (args) => {
110
+ const level = args.level;
111
+ return level ? `setting thinking depth to ${level}...` : "adjusting thinking depth...";
112
+ },
113
+ // Hidden — these ARE the response or end-of-turn
114
+ settle: () => null,
115
+ rest: () => null,
116
+ descend: () => null,
117
+ };
118
+ function humanReadableToolDescription(name, args) {
119
+ (0, runtime_1.emitNervesEvent)({
120
+ component: "engine",
121
+ event: "engine.tool_description",
122
+ message: "generated human-readable tool description",
123
+ meta: { tool: name },
124
+ });
125
+ const builder = TOOL_DESCRIPTIONS[name];
126
+ if (builder)
127
+ return builder(args);
128
+ // MCP tools: mcp__server__toolname — extract last segment
129
+ if (name.startsWith("mcp__")) {
130
+ const parts = name.split("__");
131
+ const toolName = parts[parts.length - 1];
132
+ return `using ${toolName}...`;
133
+ }
134
+ return `using ${name}...`;
135
+ }
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.GLOBAL_CIRCUIT_BREAKER_LIMIT = exports.PING_PONG_WINDOW = exports.GENERIC_REPEAT_LIMIT = exports.POLL_NO_PROGRESS_LIMIT = exports.TOOL_LOOP_HISTORY_LIMIT = void 0;
37
+ exports.createToolLoopState = createToolLoopState;
38
+ exports.recordToolOutcome = recordToolOutcome;
39
+ exports.detectToolLoop = detectToolLoop;
40
+ const crypto = __importStar(require("crypto"));
41
+ const runtime_1 = require("../nerves/runtime");
42
+ exports.TOOL_LOOP_HISTORY_LIMIT = 30;
43
+ exports.POLL_NO_PROGRESS_LIMIT = 3;
44
+ exports.GENERIC_REPEAT_LIMIT = 4;
45
+ exports.PING_PONG_WINDOW = 6;
46
+ exports.GLOBAL_CIRCUIT_BREAKER_LIMIT = 24;
47
+ function stableStringify(value) {
48
+ if (value === null || typeof value !== "object") {
49
+ return JSON.stringify(value);
50
+ }
51
+ /* v8 ignore next -- stableStringify currently receives only objects/strings from normalized loop inputs @preserve */
52
+ if (Array.isArray(value)) {
53
+ return `[${value.map((entry) => stableStringify(entry)).join(",")}]`;
54
+ }
55
+ const record = value;
56
+ return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`).join(",")}}`;
57
+ }
58
+ function digest(value) {
59
+ return crypto.createHash("sha256").update(stableStringify(value)).digest("hex");
60
+ }
61
+ function normalizeArgs(toolName, args) {
62
+ if (toolName === "query_active_work") {
63
+ return { toolName };
64
+ }
65
+ if (toolName === "coding_status" || toolName === "coding_tail") {
66
+ return {
67
+ toolName,
68
+ sessionId: args.sessionId ?? "",
69
+ };
70
+ }
71
+ if (toolName === "query_session") {
72
+ return {
73
+ toolName,
74
+ mode: args.mode ?? "",
75
+ friendId: args.friendId ?? "",
76
+ channel: args.channel ?? "",
77
+ key: args.key ?? "",
78
+ query: args.query ?? "",
79
+ };
80
+ }
81
+ return {
82
+ toolName,
83
+ args,
84
+ };
85
+ }
86
+ function normalizeOutcome(result, success) {
87
+ return {
88
+ success,
89
+ result: result.replace(/\s+/g, " ").trim(),
90
+ };
91
+ }
92
+ function isKnownPollTool(toolName, args) {
93
+ return toolName === "query_active_work"
94
+ || toolName === "coding_status"
95
+ || toolName === "coding_tail"
96
+ || (toolName === "query_session" && (args.mode ?? "").trim() === "status");
97
+ }
98
+ function emitDetection(detector, toolName, count, message, pairedToolName) {
99
+ (0, runtime_1.emitNervesEvent)({
100
+ level: "warn",
101
+ component: "engine",
102
+ event: "engine.tool_loop_detected",
103
+ message: "tool loop guard detected repeated non-progress work",
104
+ meta: {
105
+ detector,
106
+ toolName,
107
+ count,
108
+ pairedToolName: pairedToolName ?? null,
109
+ },
110
+ });
111
+ return {
112
+ stuck: true,
113
+ detector,
114
+ count,
115
+ message,
116
+ pairedToolName,
117
+ };
118
+ }
119
+ function countTrailingRepeats(history, toolName, callHash) {
120
+ let count = 0;
121
+ let outcomeHash;
122
+ for (let index = history.length - 1; index >= 0; index--) {
123
+ const record = history[index];
124
+ if (record.toolName !== toolName || record.callHash !== callHash) {
125
+ break;
126
+ }
127
+ if (!outcomeHash) {
128
+ outcomeHash = record.outcomeHash;
129
+ }
130
+ if (record.outcomeHash !== outcomeHash) {
131
+ break;
132
+ }
133
+ count += 1;
134
+ }
135
+ return { count, outcomeHash };
136
+ }
137
+ function detectPingPong(history, toolName, callHash) {
138
+ if (history.length < exports.PING_PONG_WINDOW) {
139
+ return { stuck: false };
140
+ }
141
+ const recent = history.slice(-exports.PING_PONG_WINDOW);
142
+ const first = recent[0];
143
+ const second = recent[1];
144
+ if (!first.isKnownPoll || !second.isKnownPoll) {
145
+ return { stuck: false };
146
+ }
147
+ if (first.toolName === second.toolName && first.callHash === second.callHash) {
148
+ return { stuck: false };
149
+ }
150
+ for (let index = 0; index < recent.length; index++) {
151
+ const expected = index % 2 === 0 ? first : second;
152
+ const actual = recent[index];
153
+ if (actual.toolName !== expected.toolName
154
+ || actual.callHash !== expected.callHash
155
+ || actual.outcomeHash !== expected.outcomeHash) {
156
+ return { stuck: false };
157
+ }
158
+ }
159
+ const matchesPair = (toolName === first.toolName && callHash === first.callHash)
160
+ || (toolName === second.toolName && callHash === second.callHash);
161
+ if (!matchesPair) {
162
+ return { stuck: false };
163
+ }
164
+ const pairedToolName = toolName === first.toolName ? second.toolName : first.toolName;
165
+ return emitDetection("ping_pong", toolName, exports.PING_PONG_WINDOW, `repeated ${first.toolName}/${second.toolName} polling is not changing. stop cycling between status checks and either act on the current state, change approach, or answer truthfully with what is known.`, pairedToolName);
166
+ }
167
+ function createToolLoopState() {
168
+ return { history: [] };
169
+ }
170
+ function recordToolOutcome(state, toolName, args, result, success) {
171
+ state.history.push({
172
+ toolName,
173
+ callHash: digest(normalizeArgs(toolName, args)),
174
+ outcomeHash: digest(normalizeOutcome(result, success)),
175
+ isKnownPoll: isKnownPollTool(toolName, args),
176
+ });
177
+ if (state.history.length > exports.TOOL_LOOP_HISTORY_LIMIT) {
178
+ state.history.splice(0, state.history.length - exports.TOOL_LOOP_HISTORY_LIMIT);
179
+ }
180
+ }
181
+ // Tools that must never be blocked by the circuit breaker.
182
+ // settle = end the turn, surface = deliver results outward.
183
+ // ponder = continue thinking (inner dialog) or hand off to inner dialog (outer).
184
+ // rest = end inner dialog turn (added in Unit 8b).
185
+ // Blocking these traps the agent: it can think all it wants but can never speak or stop.
186
+ const CIRCUIT_BREAKER_EXEMPT = new Set(["settle", "surface", "ponder", "rest"]);
187
+ function detectToolLoop(state, toolName, args) {
188
+ if (state.history.length >= exports.GLOBAL_CIRCUIT_BREAKER_LIMIT && !CIRCUIT_BREAKER_EXEMPT.has(toolName)) {
189
+ return emitDetection("global_circuit_breaker", toolName, state.history.length, `this turn has already made ${state.history.length} tool calls. stop thrashing, use the current evidence, and either change approach or answer truthfully with the best grounded status.`);
190
+ }
191
+ const callHash = digest(normalizeArgs(toolName, args));
192
+ const trailing = countTrailingRepeats(state.history, toolName, callHash);
193
+ if (isKnownPollTool(toolName, args) && trailing.count >= exports.POLL_NO_PROGRESS_LIMIT) {
194
+ return emitDetection("known_poll_no_progress", toolName, trailing.count, `repeated ${toolName} calls have returned the same state ${trailing.count} times. stop polling and either act on the current state, wait for a meaningful change, or answer truthfully with what is known.`);
195
+ }
196
+ if (trailing.count >= exports.GENERIC_REPEAT_LIMIT) {
197
+ return emitDetection("generic_repeat", toolName, trailing.count, `repeating ${toolName} with the same inputs is not producing new information. change approach, use the evidence already gathered, or answer truthfully with what is known.`);
198
+ }
199
+ return detectPingPong(state.history, toolName, callHash);
200
+ }