openclaw-multi-auto 1.6.2 → 1.6.6

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 (182) hide show
  1. package/dist/{accounts-L9ByEpnP.js → accounts-C9HcPI9h.js} +2 -2
  2. package/dist/{accounts-BOzyfwW4.js → accounts-C_lW3Ag9.js} +2 -2
  3. package/dist/{accounts-yfBeCZtS.js → accounts-Tgelvk0C.js} +17 -17
  4. package/dist/{active-listener-D1yqT1cw.js → active-listener-BEdprTkn.js} +2 -2
  5. package/dist/{api-key-rotation-DtsNS2Nb.js → api-key-rotation-BJpKWXy0.js} +2 -2
  6. package/dist/{audio-preflight-DoPfNXDz.js → audio-preflight-BMvgEQ5j.js} +32 -32
  7. package/dist/{audio-transcription-runner-CzjuH3uL.js → audio-transcription-runner-gLFfz8fr.js} +12 -12
  8. package/dist/{audit-membership-runtime-DWyHWAHM.js → audit-membership-runtime-Dntemq07.js} +4 -4
  9. package/dist/build-info.json +3 -3
  10. package/dist/bundled/boot-md/handler.js +51 -51
  11. package/dist/bundled/bootstrap-extra-files/handler.js +6 -6
  12. package/dist/bundled/command-logger/handler.js +2 -2
  13. package/dist/bundled/session-memory/handler.js +51 -51
  14. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  15. package/dist/{channel-activity-xHOMiarp.js → channel-activity-BDnjYF7B.js} +3 -3
  16. package/dist/{chrome-DlhJHqj8.js → chrome-DxxEKrY7.js} +26 -26
  17. package/dist/{commands-registry-V1zZ5pPC.js → commands-registry-D5qXbFJn.js} +4 -4
  18. package/dist/{deliver-CApVJA_l.js → deliver-DbdywYJE.js} +21 -21
  19. package/dist/deliver-runtime-BFs7iAZF.js +36 -0
  20. package/dist/deps-send-discord.runtime-DZUccI6Z.js +26 -0
  21. package/dist/deps-send-imessage.runtime-CF3OpoqY.js +25 -0
  22. package/dist/deps-send-signal.runtime-Cw4-ozeO.js +24 -0
  23. package/dist/deps-send-slack.runtime-BDsDhS1P.js +22 -0
  24. package/dist/deps-send-telegram.runtime-D_4xVasO.js +27 -0
  25. package/dist/deps-send-whatsapp.runtime-DK8jqd14.js +60 -0
  26. package/dist/{diagnostic-Bn4PZjMZ.js → diagnostic-Co6Kghr-.js} +2 -2
  27. package/dist/{errors-CCLeFWAg.js → errors-xt401nuk.js} +1 -1
  28. package/dist/{fetch-BlJWzEP6.js → fetch-DuraYswo.js} +5 -5
  29. package/dist/{fetch-guard-ChYBwfiy.js → fetch-guard-DWr0d00H.js} +2 -2
  30. package/dist/{frontmatter-CvaMP376.js → frontmatter-BkTfEZ93.js} +3 -3
  31. package/dist/{fs-safe-0jAo_Whb.js → fs-safe-CTYUrIgQ.js} +4 -4
  32. package/dist/{github-copilot-token-D13V9YBz.js → github-copilot-token-BDioPmd6.js} +7 -7
  33. package/dist/{image-B3Mz7N5I.js → image-eT7Y-nP5.js} +6 -6
  34. package/dist/{image-ops-CehkHxmW.js → image-ops-BuUnEOE0.js} +2 -2
  35. package/dist/image-runtime-BcAK3n8a.js +29 -0
  36. package/dist/{ir-DAP-B-Xw.js → ir-B83looB-.js} +8 -8
  37. package/dist/{legacy-names-TyzbVqa_.js → legacy-names-DOC03BkU.js} +1 -1
  38. package/dist/llm-slug-generator.js +51 -51
  39. package/dist/{logger-DMZQQtxK.js → logger-BfjWMCSD.js} +7 -7
  40. package/dist/{login-DiCctRo1.js → login-CrIwcrVI.js} +5 -5
  41. package/dist/{login-qr-MUbXgjtd.js → login-qr-BpPDZdl_.js} +10 -10
  42. package/dist/{manager-BW_NSIMl.js → manager-1bvuGrNR.js} +13 -13
  43. package/dist/manager-runtime-FO1Sx3W8.js +18 -0
  44. package/dist/{model-selection-idoqPmw0.js → model-selection-Dna0Gz1k.js} +43 -43
  45. package/dist/{outbound-C2kanETZ.js → outbound-ChDjtuD6.js} +6 -6
  46. package/dist/{outbound-attachment-DBrYWX8h.js → outbound-attachment-DqHlD21U.js} +2 -2
  47. package/dist/{path-alias-guards-DqXRZmsL.js → path-alias-guards-BzvdLvTI.js} +1 -1
  48. package/dist/{paths-CCxysrzL.js → paths-Bkr-BCxW.js} +4 -4
  49. package/dist/{paths-C6TxBCvO.js → paths-Cvc9EM8Y.js} +5 -5
  50. package/dist/{pi-embedded-bcjMe3wj.js → pi-embedded-BQQa91aA.js} +167 -167
  51. package/dist/{pi-embedded-helpers-D5yyGEvA.js → pi-embedded-helpers-CLXm10bV.js} +52 -52
  52. package/dist/{plugin-sdk/pi-model-discovery-v-XPUOOf.js → pi-model-discovery-Dymwdjt0.js} +2 -2
  53. package/dist/pi-model-discovery-runtime-BeY4EUPp.js +11 -0
  54. package/dist/{pi-tools.before-tool-call.runtime-BuLxSyx9.js → pi-tools.before-tool-call.runtime-Cwab_5W1.js} +9 -9
  55. package/dist/plugin-sdk/compat.js +50 -50
  56. package/dist/plugin-sdk/discord.js +6 -6
  57. package/dist/plugin-sdk/slack.js +2 -2
  58. package/dist/{plugins-CWkRQYDj.js → plugins-4Rj4OjLY.js} +11 -11
  59. package/dist/{proxy-env-Cq5gdrbj.js → proxy-env-DlmzDx8x.js} +1 -1
  60. package/dist/{proxy-fetch-CCjEYbFm.js → proxy-fetch-B2pEfjbR.js} +1 -1
  61. package/dist/{pw-ai-CDQDCfUa.js → pw-ai-DNMjFMqH.js} +14 -14
  62. package/dist/{qmd-manager-BsYsO9Ii.js → qmd-manager-BtIKUaO9.js} +10 -10
  63. package/dist/{query-expansion-DtLc3wjL.js → query-expansion-CX-1fS52.js} +6 -6
  64. package/dist/{plugin-sdk/redact-DjVX-1N3.js → redact-COik8ET1.js} +1 -1
  65. package/dist/{run-with-concurrency-D_ZpbgEG.js → run-with-concurrency-BgYfgkXT.js} +4 -4
  66. package/dist/runtime-whatsapp-login.runtime-DUb55byQ.js +13 -0
  67. package/dist/runtime-whatsapp-outbound.runtime-Bii_xSfI.js +22 -0
  68. package/dist/{send-Dx2RkUOZ.js → send-6lz6rNVP.js} +6 -6
  69. package/dist/{send-vmONuVgL.js → send-BHTiZcH3.js} +26 -26
  70. package/dist/{send-Bj776ESJ.js → send-L7gRiwyd.js} +7 -7
  71. package/dist/{send-DcxmcFi_.js → send-PE6cwoTe.js} +8 -8
  72. package/dist/{send-BQERFNyo.js → send-dfu6_rgf.js} +5 -5
  73. package/dist/{session-A4QhBRvH.js → session-D8ImowSs.js} +8 -8
  74. package/dist/{skill-commands-CMzBZKG2.js → skill-commands-DNqJ-kwn.js} +9 -9
  75. package/dist/{skills-CE_iqvM5.js → skills-7ODkHQYp.js} +22 -22
  76. package/dist/slash-commands.runtime-CVw6566g.js +16 -0
  77. package/dist/slash-dispatch.runtime-B9Ygtzi4.js +56 -0
  78. package/dist/slash-skill-commands.runtime-DxZ4z5h6.js +20 -0
  79. package/dist/{store--eR1R_UX.js → store-D89wDcz9.js} +2 -2
  80. package/dist/subagent-registry-runtime-DL1Wv7nA.js +56 -0
  81. package/dist/{subsystem-Di1z8l0Z.js → subsystem-B45WV3qB.js} +14 -14
  82. package/dist/{tables-d739Y1xW.js → tables-mE4cJBN2.js} +1 -1
  83. package/dist/{plugin-sdk/target-errors-Blia4S69.js → target-errors-mnlwhAjP.js} +2 -2
  84. package/dist/{thinking-DXYisHiZ.js → thinking-BeGmb5k6.js} +7 -7
  85. package/dist/{tokens-DxnY9ui_.js → tokens-q32vI39c.js} +1 -1
  86. package/dist/{tool-images-2cBx1W8h.js → tool-images-RZdHiZcG.js} +2 -2
  87. package/dist/{web-NWKn8ABz.js → web-Btj-e8kN.js} +55 -55
  88. package/dist/{whatsapp-actions-iEArE_Ez.js → whatsapp-actions-BHbJJyqw.js} +21 -21
  89. package/dist/{workspace-CUVC6GX1.js → workspace-U-DyR64O.js} +20 -20
  90. package/package.json +1 -1
  91. package/scripts/create-instance.sh +93 -96
  92. package/dist/deliver-runtime-D1z-h5eg.js +0 -36
  93. package/dist/deps-send-discord.runtime-DnbhTFX9.js +0 -26
  94. package/dist/deps-send-imessage.runtime-BOiQ6mDx.js +0 -25
  95. package/dist/deps-send-signal.runtime-CTcl388M.js +0 -24
  96. package/dist/deps-send-slack.runtime-CCqBz4Kg.js +0 -22
  97. package/dist/deps-send-telegram.runtime-DGSKTCpH.js +0 -27
  98. package/dist/deps-send-whatsapp.runtime-Dz_4fi2D.js +0 -60
  99. package/dist/image-runtime-DWjhow2W.js +0 -29
  100. package/dist/manager-runtime-BN6VevdC.js +0 -18
  101. package/dist/pi-model-discovery-BGgOlX8N.js +0 -134
  102. package/dist/pi-model-discovery-runtime-Bwmi4Ev8.js +0 -11
  103. package/dist/plugin-sdk/accounts-CJWOBzwB.js +0 -35
  104. package/dist/plugin-sdk/accounts-DP1-L-QS.js +0 -288
  105. package/dist/plugin-sdk/accounts-DZhWlEg3.js +0 -46
  106. package/dist/plugin-sdk/active-listener-B_sLJTXM.js +0 -50
  107. package/dist/plugin-sdk/api-key-rotation-BRE4X2tf.js +0 -181
  108. package/dist/plugin-sdk/audio-preflight-DGEUDxxR.js +0 -69
  109. package/dist/plugin-sdk/audio-transcription-runner-DkoPNPYt.js +0 -2176
  110. package/dist/plugin-sdk/audit-membership-runtime-DSBHHw7o.js +0 -58
  111. package/dist/plugin-sdk/channel-activity-F3d0yUwy.js +0 -94
  112. package/dist/plugin-sdk/channel-web-QF7EpjeP.js +0 -2256
  113. package/dist/plugin-sdk/chrome-BXoCyCkY.js +0 -2415
  114. package/dist/plugin-sdk/commands-registry-t7cXBTfN.js +0 -1125
  115. package/dist/plugin-sdk/config-BkEnz2Po.js +0 -17913
  116. package/dist/plugin-sdk/deliver-B6AG_l67.js +0 -1694
  117. package/dist/plugin-sdk/deliver-runtime-D585kJZc.js +0 -32
  118. package/dist/plugin-sdk/deps-send-discord.runtime-a_OKY2js.js +0 -23
  119. package/dist/plugin-sdk/deps-send-imessage.runtime-Baxy9TD4.js +0 -22
  120. package/dist/plugin-sdk/deps-send-signal.runtime-BwXoCrFl.js +0 -21
  121. package/dist/plugin-sdk/deps-send-slack.runtime-CLmKjgso.js +0 -19
  122. package/dist/plugin-sdk/deps-send-telegram.runtime-BKfdBKnZ.js +0 -24
  123. package/dist/plugin-sdk/deps-send-whatsapp.runtime-BOTwkbx_.js +0 -57
  124. package/dist/plugin-sdk/diagnostic-CsP-lEkI.js +0 -319
  125. package/dist/plugin-sdk/errors-DaiAM-yU.js +0 -54
  126. package/dist/plugin-sdk/fetch-guard-DETCcJzQ.js +0 -156
  127. package/dist/plugin-sdk/fs-safe-B8y811FR.js +0 -352
  128. package/dist/plugin-sdk/image-DjTEkYZE.js +0 -2310
  129. package/dist/plugin-sdk/image-ops-BSiMpAw4.js +0 -584
  130. package/dist/plugin-sdk/image-runtime-6xPp8m5a.js +0 -25
  131. package/dist/plugin-sdk/ir-DQ7_HbvK.js +0 -1296
  132. package/dist/plugin-sdk/local-roots-BUP4YBmR.js +0 -186
  133. package/dist/plugin-sdk/logger-CZY9KIoY.js +0 -1163
  134. package/dist/plugin-sdk/login-BxEKLlCo.js +0 -57
  135. package/dist/plugin-sdk/login-qr-BQIpMPr9.js +0 -320
  136. package/dist/plugin-sdk/manager-I6KbPihW.js +0 -3917
  137. package/dist/plugin-sdk/manager-runtime-CFfYYWIQ.js +0 -15
  138. package/dist/plugin-sdk/outbound-NS6UHnB6.js +0 -212
  139. package/dist/plugin-sdk/outbound-attachment-Dy6fyf6H.js +0 -19
  140. package/dist/plugin-sdk/path-alias-guards-DBjLbIX_.js +0 -43
  141. package/dist/plugin-sdk/paths-vTM3Lh3X.js +0 -166
  142. package/dist/plugin-sdk/pi-embedded-helpers-1R1gu7eX.js +0 -9627
  143. package/dist/plugin-sdk/pi-model-discovery-runtime-Do9o-dUd.js +0 -8
  144. package/dist/plugin-sdk/pi-tools.before-tool-call.runtime-D4sFsIks.js +0 -354
  145. package/dist/plugin-sdk/plugins-DeBZB9l_.js +0 -864
  146. package/dist/plugin-sdk/proxy-fetch-ChxOhWF4.js +0 -38
  147. package/dist/plugin-sdk/pw-ai-DEOmCSSC.js +0 -1938
  148. package/dist/plugin-sdk/qmd-manager-HyYKoEch.js +0 -1448
  149. package/dist/plugin-sdk/query-expansion-CeyKUeDW.js +0 -1011
  150. package/dist/plugin-sdk/reply-DAo_Jt8K.js +0 -97916
  151. package/dist/plugin-sdk/resolve-outbound-target-B42qgQS9.js +0 -40
  152. package/dist/plugin-sdk/run-with-concurrency-Bt_ks0Qa.js +0 -1994
  153. package/dist/plugin-sdk/runtime-whatsapp-login.runtime-B6W989eF.js +0 -10
  154. package/dist/plugin-sdk/runtime-whatsapp-outbound.runtime-c_GDFy37.js +0 -19
  155. package/dist/plugin-sdk/send-CQpMudwO.js +0 -2587
  156. package/dist/plugin-sdk/send-DQHLzVyO.js +0 -414
  157. package/dist/plugin-sdk/send-DTB24bEF.js +0 -3135
  158. package/dist/plugin-sdk/send-DfHadjZ_.js +0 -503
  159. package/dist/plugin-sdk/send-XXlW2iny.js +0 -540
  160. package/dist/plugin-sdk/session-6TF6MyaC.js +0 -169
  161. package/dist/plugin-sdk/skill-commands-CkGeFUMl.js +0 -342
  162. package/dist/plugin-sdk/skills-CBkHBYPq.js +0 -1428
  163. package/dist/plugin-sdk/slash-commands.runtime-CxliuGaP.js +0 -13
  164. package/dist/plugin-sdk/slash-dispatch.runtime-DFaeYlJQ.js +0 -52
  165. package/dist/plugin-sdk/slash-skill-commands.runtime-0M0OLCxq.js +0 -16
  166. package/dist/plugin-sdk/ssrf-cFtplYtS.js +0 -202
  167. package/dist/plugin-sdk/store-5nyxY3WU.js +0 -81
  168. package/dist/plugin-sdk/subagent-registry-runtime-DCtmDwna.js +0 -52
  169. package/dist/plugin-sdk/tables-C47P4GTN.js +0 -55
  170. package/dist/plugin-sdk/thinking-Bo2eosVa.js +0 -1206
  171. package/dist/plugin-sdk/tokens-DgNRBwIg.js +0 -52
  172. package/dist/plugin-sdk/tool-images-Gk_-0y2N.js +0 -274
  173. package/dist/plugin-sdk/web-CVxZbXyH.js +0 -56
  174. package/dist/plugin-sdk/whatsapp-actions-Bw0H9g-n.js +0 -80
  175. package/dist/redact-ClbcYG1J.js +0 -319
  176. package/dist/runtime-whatsapp-login.runtime-IeylZEl4.js +0 -13
  177. package/dist/runtime-whatsapp-outbound.runtime-ClBRuLsq.js +0 -22
  178. package/dist/slash-commands.runtime-Cpn2tYW4.js +0 -16
  179. package/dist/slash-dispatch.runtime-CWbpp23S.js +0 -56
  180. package/dist/slash-skill-commands.runtime-DKMvvdDW.js +0 -20
  181. package/dist/subagent-registry-runtime-DEVpAaAP.js +0 -56
  182. package/dist/target-errors-CBI2Ga0y.js +0 -195
@@ -1,8 +0,0 @@
1
- import "./run-with-concurrency-Bt_ks0Qa.js";
2
- import "./paths-MKyEVmEb.js";
3
- import "./github-copilot-token-D5fdS6xD.js";
4
- import "./config-BkEnz2Po.js";
5
- import "./logger-CZY9KIoY.js";
6
- import { n as discoverModels, t as discoverAuthStorage } from "./pi-model-discovery-v-XPUOOf.js";
7
-
8
- export { discoverAuthStorage, discoverModels };
@@ -1,354 +0,0 @@
1
- import "./run-with-concurrency-Bt_ks0Qa.js";
2
- import "./paths-MKyEVmEb.js";
3
- import "./github-copilot-token-D5fdS6xD.js";
4
- import "./config-BkEnz2Po.js";
5
- import { P as isPlainObject, a as createSubsystemLogger } from "./logger-CZY9KIoY.js";
6
- import { p as getDiagnosticSessionState, s as logToolLoopAction } from "./diagnostic-CsP-lEkI.js";
7
- import { createHash } from "node:crypto";
8
-
9
- //#region src/agents/tool-loop-detection.ts
10
- const log = createSubsystemLogger("agents/loop-detection");
11
- const TOOL_CALL_HISTORY_SIZE = 30;
12
- const WARNING_THRESHOLD = 10;
13
- const CRITICAL_THRESHOLD = 20;
14
- const GLOBAL_CIRCUIT_BREAKER_THRESHOLD = 30;
15
- const DEFAULT_LOOP_DETECTION_CONFIG = {
16
- enabled: false,
17
- historySize: TOOL_CALL_HISTORY_SIZE,
18
- warningThreshold: WARNING_THRESHOLD,
19
- criticalThreshold: CRITICAL_THRESHOLD,
20
- globalCircuitBreakerThreshold: GLOBAL_CIRCUIT_BREAKER_THRESHOLD,
21
- detectors: {
22
- genericRepeat: true,
23
- knownPollNoProgress: true,
24
- pingPong: true
25
- }
26
- };
27
- function asPositiveInt(value, fallback) {
28
- if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) return fallback;
29
- return value;
30
- }
31
- function resolveLoopDetectionConfig(config) {
32
- let warningThreshold = asPositiveInt(config?.warningThreshold, DEFAULT_LOOP_DETECTION_CONFIG.warningThreshold);
33
- let criticalThreshold = asPositiveInt(config?.criticalThreshold, DEFAULT_LOOP_DETECTION_CONFIG.criticalThreshold);
34
- let globalCircuitBreakerThreshold = asPositiveInt(config?.globalCircuitBreakerThreshold, DEFAULT_LOOP_DETECTION_CONFIG.globalCircuitBreakerThreshold);
35
- if (criticalThreshold <= warningThreshold) criticalThreshold = warningThreshold + 1;
36
- if (globalCircuitBreakerThreshold <= criticalThreshold) globalCircuitBreakerThreshold = criticalThreshold + 1;
37
- return {
38
- enabled: config?.enabled ?? DEFAULT_LOOP_DETECTION_CONFIG.enabled,
39
- historySize: asPositiveInt(config?.historySize, DEFAULT_LOOP_DETECTION_CONFIG.historySize),
40
- warningThreshold,
41
- criticalThreshold,
42
- globalCircuitBreakerThreshold,
43
- detectors: {
44
- genericRepeat: config?.detectors?.genericRepeat ?? DEFAULT_LOOP_DETECTION_CONFIG.detectors.genericRepeat,
45
- knownPollNoProgress: config?.detectors?.knownPollNoProgress ?? DEFAULT_LOOP_DETECTION_CONFIG.detectors.knownPollNoProgress,
46
- pingPong: config?.detectors?.pingPong ?? DEFAULT_LOOP_DETECTION_CONFIG.detectors.pingPong
47
- }
48
- };
49
- }
50
- /**
51
- * Hash a tool call for pattern matching.
52
- * Uses tool name + deterministic JSON serialization digest of params.
53
- */
54
- function hashToolCall(toolName, params) {
55
- return `${toolName}:${digestStable(params)}`;
56
- }
57
- function stableStringify(value) {
58
- if (value === null || typeof value !== "object") return JSON.stringify(value);
59
- if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
60
- const obj = value;
61
- return `{${Object.keys(obj).toSorted().map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`).join(",")}}`;
62
- }
63
- function digestStable(value) {
64
- const serialized = stableStringifyFallback(value);
65
- return createHash("sha256").update(serialized).digest("hex");
66
- }
67
- function stableStringifyFallback(value) {
68
- try {
69
- return stableStringify(value);
70
- } catch {
71
- if (value === null || value === void 0) return `${value}`;
72
- if (typeof value === "string") return value;
73
- if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return `${value}`;
74
- if (value instanceof Error) return `${value.name}:${value.message}`;
75
- return Object.prototype.toString.call(value);
76
- }
77
- }
78
- function isKnownPollToolCall(toolName, params) {
79
- if (toolName === "command_status") return true;
80
- if (toolName !== "process" || !isPlainObject(params)) return false;
81
- const action = params.action;
82
- return action === "poll" || action === "log";
83
- }
84
- function extractTextContent(result) {
85
- if (!isPlainObject(result) || !Array.isArray(result.content)) return "";
86
- return result.content.filter((entry) => isPlainObject(entry) && typeof entry.type === "string" && typeof entry.text === "string").map((entry) => entry.text).join("\n").trim();
87
- }
88
- function formatErrorForHash(error) {
89
- if (error instanceof Error) return error.message || error.name;
90
- if (typeof error === "string") return error;
91
- if (typeof error === "number" || typeof error === "boolean" || typeof error === "bigint") return `${error}`;
92
- return stableStringify(error);
93
- }
94
- function hashToolOutcome(toolName, params, result, error) {
95
- if (error !== void 0) return `error:${digestStable(formatErrorForHash(error))}`;
96
- if (!isPlainObject(result)) return result === void 0 ? void 0 : digestStable(result);
97
- const details = isPlainObject(result.details) ? result.details : {};
98
- const text = extractTextContent(result);
99
- if (isKnownPollToolCall(toolName, params) && toolName === "process" && isPlainObject(params)) {
100
- const action = params.action;
101
- if (action === "poll") return digestStable({
102
- action,
103
- status: details.status,
104
- exitCode: details.exitCode ?? null,
105
- exitSignal: details.exitSignal ?? null,
106
- aggregated: details.aggregated ?? null,
107
- text
108
- });
109
- if (action === "log") return digestStable({
110
- action,
111
- status: details.status,
112
- totalLines: details.totalLines ?? null,
113
- totalChars: details.totalChars ?? null,
114
- truncated: details.truncated ?? null,
115
- exitCode: details.exitCode ?? null,
116
- exitSignal: details.exitSignal ?? null,
117
- text
118
- });
119
- }
120
- return digestStable({
121
- details,
122
- text
123
- });
124
- }
125
- function getNoProgressStreak(history, toolName, argsHash) {
126
- let streak = 0;
127
- let latestResultHash;
128
- for (let i = history.length - 1; i >= 0; i -= 1) {
129
- const record = history[i];
130
- if (!record || record.toolName !== toolName || record.argsHash !== argsHash) continue;
131
- if (typeof record.resultHash !== "string" || !record.resultHash) continue;
132
- if (!latestResultHash) {
133
- latestResultHash = record.resultHash;
134
- streak = 1;
135
- continue;
136
- }
137
- if (record.resultHash !== latestResultHash) break;
138
- streak += 1;
139
- }
140
- return {
141
- count: streak,
142
- latestResultHash
143
- };
144
- }
145
- function getPingPongStreak(history, currentSignature) {
146
- const last = history.at(-1);
147
- if (!last) return {
148
- count: 0,
149
- noProgressEvidence: false
150
- };
151
- let otherSignature;
152
- let otherToolName;
153
- for (let i = history.length - 2; i >= 0; i -= 1) {
154
- const call = history[i];
155
- if (!call) continue;
156
- if (call.argsHash !== last.argsHash) {
157
- otherSignature = call.argsHash;
158
- otherToolName = call.toolName;
159
- break;
160
- }
161
- }
162
- if (!otherSignature || !otherToolName) return {
163
- count: 0,
164
- noProgressEvidence: false
165
- };
166
- let alternatingTailCount = 0;
167
- for (let i = history.length - 1; i >= 0; i -= 1) {
168
- const call = history[i];
169
- if (!call) continue;
170
- const expected = alternatingTailCount % 2 === 0 ? last.argsHash : otherSignature;
171
- if (call.argsHash !== expected) break;
172
- alternatingTailCount += 1;
173
- }
174
- if (alternatingTailCount < 2) return {
175
- count: 0,
176
- noProgressEvidence: false
177
- };
178
- if (currentSignature !== otherSignature) return {
179
- count: 0,
180
- noProgressEvidence: false
181
- };
182
- const tailStart = Math.max(0, history.length - alternatingTailCount);
183
- let firstHashA;
184
- let firstHashB;
185
- let noProgressEvidence = true;
186
- for (let i = tailStart; i < history.length; i += 1) {
187
- const call = history[i];
188
- if (!call) continue;
189
- if (!call.resultHash) {
190
- noProgressEvidence = false;
191
- break;
192
- }
193
- if (call.argsHash === last.argsHash) {
194
- if (!firstHashA) firstHashA = call.resultHash;
195
- else if (firstHashA !== call.resultHash) {
196
- noProgressEvidence = false;
197
- break;
198
- }
199
- continue;
200
- }
201
- if (call.argsHash === otherSignature) {
202
- if (!firstHashB) firstHashB = call.resultHash;
203
- else if (firstHashB !== call.resultHash) {
204
- noProgressEvidence = false;
205
- break;
206
- }
207
- continue;
208
- }
209
- noProgressEvidence = false;
210
- break;
211
- }
212
- if (!firstHashA || !firstHashB) noProgressEvidence = false;
213
- return {
214
- count: alternatingTailCount + 1,
215
- pairedToolName: last.toolName,
216
- pairedSignature: last.argsHash,
217
- noProgressEvidence
218
- };
219
- }
220
- function canonicalPairKey(signatureA, signatureB) {
221
- return [signatureA, signatureB].toSorted().join("|");
222
- }
223
- /**
224
- * Detect if an agent is stuck in a repetitive tool call loop.
225
- * Checks if the same tool+params combination has been called excessively.
226
- */
227
- function detectToolCallLoop(state, toolName, params, config) {
228
- const resolvedConfig = resolveLoopDetectionConfig(config);
229
- if (!resolvedConfig.enabled) return { stuck: false };
230
- const history = state.toolCallHistory ?? [];
231
- const currentHash = hashToolCall(toolName, params);
232
- const noProgress = getNoProgressStreak(history, toolName, currentHash);
233
- const noProgressStreak = noProgress.count;
234
- const knownPollTool = isKnownPollToolCall(toolName, params);
235
- const pingPong = getPingPongStreak(history, currentHash);
236
- if (noProgressStreak >= resolvedConfig.globalCircuitBreakerThreshold) {
237
- log.error(`Global circuit breaker triggered: ${toolName} repeated ${noProgressStreak} times with no progress`);
238
- return {
239
- stuck: true,
240
- level: "critical",
241
- detector: "global_circuit_breaker",
242
- count: noProgressStreak,
243
- message: `CRITICAL: ${toolName} has repeated identical no-progress outcomes ${noProgressStreak} times. Session execution blocked by global circuit breaker to prevent runaway loops.`,
244
- warningKey: `global:${toolName}:${currentHash}:${noProgress.latestResultHash ?? "none"}`
245
- };
246
- }
247
- if (knownPollTool && resolvedConfig.detectors.knownPollNoProgress && noProgressStreak >= resolvedConfig.criticalThreshold) {
248
- log.error(`Critical polling loop detected: ${toolName} repeated ${noProgressStreak} times`);
249
- return {
250
- stuck: true,
251
- level: "critical",
252
- detector: "known_poll_no_progress",
253
- count: noProgressStreak,
254
- message: `CRITICAL: Called ${toolName} with identical arguments and no progress ${noProgressStreak} times. This appears to be a stuck polling loop. Session execution blocked to prevent resource waste.`,
255
- warningKey: `poll:${toolName}:${currentHash}:${noProgress.latestResultHash ?? "none"}`
256
- };
257
- }
258
- if (knownPollTool && resolvedConfig.detectors.knownPollNoProgress && noProgressStreak >= resolvedConfig.warningThreshold) {
259
- log.warn(`Polling loop warning: ${toolName} repeated ${noProgressStreak} times`);
260
- return {
261
- stuck: true,
262
- level: "warning",
263
- detector: "known_poll_no_progress",
264
- count: noProgressStreak,
265
- message: `WARNING: You have called ${toolName} ${noProgressStreak} times with identical arguments and no progress. Stop polling and either (1) increase wait time between checks, or (2) report the task as failed if the process is stuck.`,
266
- warningKey: `poll:${toolName}:${currentHash}:${noProgress.latestResultHash ?? "none"}`
267
- };
268
- }
269
- const pingPongWarningKey = pingPong.pairedSignature ? `pingpong:${canonicalPairKey(currentHash, pingPong.pairedSignature)}` : `pingpong:${toolName}:${currentHash}`;
270
- if (resolvedConfig.detectors.pingPong && pingPong.count >= resolvedConfig.criticalThreshold && pingPong.noProgressEvidence) {
271
- log.error(`Critical ping-pong loop detected: alternating calls count=${pingPong.count} currentTool=${toolName}`);
272
- return {
273
- stuck: true,
274
- level: "critical",
275
- detector: "ping_pong",
276
- count: pingPong.count,
277
- message: `CRITICAL: You are alternating between repeated tool-call patterns (${pingPong.count} consecutive calls) with no progress. This appears to be a stuck ping-pong loop. Session execution blocked to prevent resource waste.`,
278
- pairedToolName: pingPong.pairedToolName,
279
- warningKey: pingPongWarningKey
280
- };
281
- }
282
- if (resolvedConfig.detectors.pingPong && pingPong.count >= resolvedConfig.warningThreshold) {
283
- log.warn(`Ping-pong loop warning: alternating calls count=${pingPong.count} currentTool=${toolName}`);
284
- return {
285
- stuck: true,
286
- level: "warning",
287
- detector: "ping_pong",
288
- count: pingPong.count,
289
- message: `WARNING: You are alternating between repeated tool-call patterns (${pingPong.count} consecutive calls). This looks like a ping-pong loop; stop retrying and report the task as failed.`,
290
- pairedToolName: pingPong.pairedToolName,
291
- warningKey: pingPongWarningKey
292
- };
293
- }
294
- const recentCount = history.filter((h) => h.toolName === toolName && h.argsHash === currentHash).length;
295
- if (!knownPollTool && resolvedConfig.detectors.genericRepeat && recentCount >= resolvedConfig.warningThreshold) {
296
- log.warn(`Loop warning: ${toolName} called ${recentCount} times with identical arguments`);
297
- return {
298
- stuck: true,
299
- level: "warning",
300
- detector: "generic_repeat",
301
- count: recentCount,
302
- message: `WARNING: You have called ${toolName} ${recentCount} times with identical arguments. If this is not making progress, stop retrying and report the task as failed.`,
303
- warningKey: `generic:${toolName}:${currentHash}`
304
- };
305
- }
306
- return { stuck: false };
307
- }
308
- /**
309
- * Record a tool call in the session's history for loop detection.
310
- * Maintains sliding window of last N calls.
311
- */
312
- function recordToolCall(state, toolName, params, toolCallId, config) {
313
- const resolvedConfig = resolveLoopDetectionConfig(config);
314
- if (!state.toolCallHistory) state.toolCallHistory = [];
315
- state.toolCallHistory.push({
316
- toolName,
317
- argsHash: hashToolCall(toolName, params),
318
- toolCallId,
319
- timestamp: Date.now()
320
- });
321
- if (state.toolCallHistory.length > resolvedConfig.historySize) state.toolCallHistory.shift();
322
- }
323
- /**
324
- * Record a completed tool call outcome so loop detection can identify no-progress repeats.
325
- */
326
- function recordToolCallOutcome(state, params) {
327
- const resolvedConfig = resolveLoopDetectionConfig(params.config);
328
- const resultHash = hashToolOutcome(params.toolName, params.toolParams, params.result, params.error);
329
- if (!resultHash) return;
330
- if (!state.toolCallHistory) state.toolCallHistory = [];
331
- const argsHash = hashToolCall(params.toolName, params.toolParams);
332
- let matched = false;
333
- for (let i = state.toolCallHistory.length - 1; i >= 0; i -= 1) {
334
- const call = state.toolCallHistory[i];
335
- if (!call) continue;
336
- if (params.toolCallId && call.toolCallId !== params.toolCallId) continue;
337
- if (call.toolName !== params.toolName || call.argsHash !== argsHash) continue;
338
- if (call.resultHash !== void 0) continue;
339
- call.resultHash = resultHash;
340
- matched = true;
341
- break;
342
- }
343
- if (!matched) state.toolCallHistory.push({
344
- toolName: params.toolName,
345
- argsHash,
346
- toolCallId: params.toolCallId,
347
- resultHash,
348
- timestamp: Date.now()
349
- });
350
- if (state.toolCallHistory.length > resolvedConfig.historySize) state.toolCallHistory.splice(0, state.toolCallHistory.length - resolvedConfig.historySize);
351
- }
352
-
353
- //#endregion
354
- export { detectToolCallLoop, getDiagnosticSessionState, logToolLoopAction, recordToolCall, recordToolCallOutcome };