memeloop 0.0.1 → 0.1.0

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 (228) hide show
  1. package/README.md +63 -0
  2. package/dist/browser.cjs +1413 -0
  3. package/dist/browser.cjs.map +1 -0
  4. package/dist/browser.d.cts +3066 -0
  5. package/dist/browser.d.ts +3066 -0
  6. package/dist/browser.js +43 -0
  7. package/dist/chunk-426CJUZP.js +630 -0
  8. package/dist/chunk-426CJUZP.js.map +1 -0
  9. package/dist/chunk-44YHBKDL.js +382 -0
  10. package/dist/chunk-44YHBKDL.js.map +1 -0
  11. package/dist/chunk-7ZDTB4VZ.js +63 -0
  12. package/dist/chunk-7ZDTB4VZ.js.map +1 -0
  13. package/dist/chunk-AZFYDWIN.js +98 -0
  14. package/dist/chunk-AZFYDWIN.js.map +1 -0
  15. package/dist/chunk-BGPU4RR7.js +367 -0
  16. package/dist/chunk-BGPU4RR7.js.map +1 -0
  17. package/dist/chunk-CCEFAOSH.js +496 -0
  18. package/dist/chunk-CCEFAOSH.js.map +1 -0
  19. package/dist/chunk-FWSY5HOA.js +63 -0
  20. package/dist/chunk-FWSY5HOA.js.map +1 -0
  21. package/dist/chunk-GYIOMQMY.js +8726 -0
  22. package/dist/chunk-GYIOMQMY.js.map +1 -0
  23. package/dist/chunk-HVB2BR3H.js +42 -0
  24. package/dist/chunk-HVB2BR3H.js.map +1 -0
  25. package/dist/chunk-K6P63KD4.js +68 -0
  26. package/dist/chunk-K6P63KD4.js.map +1 -0
  27. package/dist/chunk-MRKY4HGF.js +205 -0
  28. package/dist/chunk-MRKY4HGF.js.map +1 -0
  29. package/dist/chunk-QFHAAIIM.js +2657 -0
  30. package/dist/chunk-QFHAAIIM.js.map +1 -0
  31. package/dist/chunk-VZKQX5PP.js +1 -0
  32. package/dist/chunk-VZKQX5PP.js.map +1 -0
  33. package/dist/chunk-WAI6BODI.js +175 -0
  34. package/dist/chunk-WAI6BODI.js.map +1 -0
  35. package/dist/chunk-XHRBV6I3.js +3637 -0
  36. package/dist/chunk-XHRBV6I3.js.map +1 -0
  37. package/dist/chunk-YMNXDNDW.js +798 -0
  38. package/dist/chunk-YMNXDNDW.js.map +1 -0
  39. package/dist/conversation.cjs +208 -0
  40. package/dist/conversation.cjs.map +1 -0
  41. package/dist/conversation.d.cts +100 -0
  42. package/dist/conversation.d.ts +100 -0
  43. package/dist/conversation.js +21 -0
  44. package/dist/conversation.js.map +1 -0
  45. package/dist/device-network-portable.cjs +702 -0
  46. package/dist/device-network-portable.cjs.map +1 -0
  47. package/dist/device-network-portable.d.cts +110 -0
  48. package/dist/device-network-portable.d.ts +110 -0
  49. package/dist/device-network-portable.js +53 -0
  50. package/dist/device-network-portable.js.map +1 -0
  51. package/dist/device-network.cjs +906 -0
  52. package/dist/device-network.cjs.map +1 -0
  53. package/dist/device-network.d.cts +6 -0
  54. package/dist/device-network.d.ts +6 -0
  55. package/dist/device-network.js +59 -0
  56. package/dist/device-network.js.map +1 -0
  57. package/dist/fetchProvider-BpcGVSOG.d.cts +91 -0
  58. package/dist/fetchProvider-Cm0sO4Tl.d.ts +91 -0
  59. package/dist/index.cjs +27957 -5459
  60. package/dist/index.cjs.map +1 -1
  61. package/dist/index.d.cts +94 -1320
  62. package/dist/index.d.ts +94 -1320
  63. package/dist/index.js +10576 -2386
  64. package/dist/index.js.map +1 -1
  65. package/dist/interface-IrKBFtL1.d.cts +493 -0
  66. package/dist/interface-IrKBFtL1.d.ts +493 -0
  67. package/dist/llm-providers.cjs +43 -8
  68. package/dist/llm-providers.cjs.map +1 -1
  69. package/dist/llm-providers.d.cts +2 -1
  70. package/dist/llm-providers.d.ts +2 -1
  71. package/dist/llm-providers.js +4 -2
  72. package/dist/llm-providers.js.map +1 -1
  73. package/dist/loop-api.cjs +5177 -2050
  74. package/dist/loop-api.cjs.map +1 -1
  75. package/dist/loop-api.d.cts +11 -5
  76. package/dist/loop-api.d.ts +11 -5
  77. package/dist/loop-api.js +84 -49
  78. package/dist/mobile.cjs +2625 -0
  79. package/dist/mobile.cjs.map +1 -0
  80. package/dist/mobile.d.cts +6 -0
  81. package/dist/mobile.d.ts +6 -0
  82. package/dist/mobile.js +22 -0
  83. package/dist/mobile.js.map +1 -0
  84. package/dist/orchestration-portable-Bsf8YRfp.d.cts +2192 -0
  85. package/dist/orchestration-portable-Zw0g5tbj.d.ts +2192 -0
  86. package/dist/orchestration-portable.cjs +9553 -0
  87. package/dist/orchestration-portable.cjs.map +1 -0
  88. package/dist/orchestration-portable.d.cts +5 -0
  89. package/dist/orchestration-portable.d.ts +5 -0
  90. package/dist/orchestration-portable.js +290 -0
  91. package/dist/orchestration-portable.js.map +1 -0
  92. package/dist/pairingInvite-BXPWY3aM.d.cts +149 -0
  93. package/dist/pairingInvite-Cuz0wuq9.d.ts +149 -0
  94. package/dist/promptConcat-WTN-uHcz.d.cts +516 -0
  95. package/dist/promptConcat-deDSWZE3.d.ts +516 -0
  96. package/dist/providerRegistry-9trr5aoK.d.ts +86 -0
  97. package/dist/providerRegistry-xk_B1Ekv.d.cts +86 -0
  98. package/dist/registry-8eztoD_r.d.cts +393 -0
  99. package/dist/registry-DV24sI-3.d.ts +393 -0
  100. package/dist/remoteClient-B_spK019.d.ts +87 -0
  101. package/dist/remoteClient-CBggnRy3.d.cts +87 -0
  102. package/dist/runtime-SKSXVYIM.js +18 -0
  103. package/dist/runtime-SKSXVYIM.js.map +1 -0
  104. package/dist/scriptDeploymentPipeline-BAeo1dPb.d.cts +2463 -0
  105. package/dist/scriptDeploymentPipeline-DsnT0AG6.d.ts +2463 -0
  106. package/dist/syncCloudDevices-BEqwgrhD.d.ts +49 -0
  107. package/dist/syncCloudDevices-Ds_Kcgrv.d.cts +49 -0
  108. package/dist/types-7pYti-k9.d.cts +255 -0
  109. package/dist/types-CdFVSntj.d.ts +255 -0
  110. package/package.json +110 -35
  111. package/dist/anthropic.cjs +0 -72
  112. package/dist/anthropic.cjs.map +0 -1
  113. package/dist/anthropic.d.cts +0 -21
  114. package/dist/anthropic.d.ts +0 -21
  115. package/dist/anthropic.js +0 -21
  116. package/dist/anthropic.js.map +0 -1
  117. package/dist/azure.cjs +0 -72
  118. package/dist/azure.cjs.map +0 -1
  119. package/dist/azure.d.cts +0 -21
  120. package/dist/azure.d.ts +0 -21
  121. package/dist/azure.js +0 -21
  122. package/dist/azure.js.map +0 -1
  123. package/dist/chunk-3CN7DFBL.js +0 -4894
  124. package/dist/chunk-3CN7DFBL.js.map +0 -1
  125. package/dist/chunk-4AZ4D7U5.js +0 -32
  126. package/dist/chunk-4AZ4D7U5.js.map +0 -1
  127. package/dist/chunk-6ON4XSOV.js +0 -63
  128. package/dist/chunk-6ON4XSOV.js.map +0 -1
  129. package/dist/chunk-DJQNGIXX.js +0 -4793
  130. package/dist/chunk-DJQNGIXX.js.map +0 -1
  131. package/dist/chunk-FKQP6AOQ.js +0 -32
  132. package/dist/chunk-FKQP6AOQ.js.map +0 -1
  133. package/dist/chunk-OVJ7JJBA.js +0 -35
  134. package/dist/chunk-OVJ7JJBA.js.map +0 -1
  135. package/dist/chunk-P4UZ7IXC.js +0 -42
  136. package/dist/chunk-YHJ2AEFR.js +0 -4933
  137. package/dist/chunk-YHJ2AEFR.js.map +0 -1
  138. package/dist/chunk-YVK7RYRO.js +0 -4973
  139. package/dist/chunk-YVK7RYRO.js.map +0 -1
  140. package/dist/code-assistant.json +0 -114
  141. package/dist/cohere.cjs +0 -72
  142. package/dist/cohere.cjs.map +0 -1
  143. package/dist/cohere.d.cts +0 -21
  144. package/dist/cohere.d.ts +0 -21
  145. package/dist/cohere.js +0 -21
  146. package/dist/cohere.js.map +0 -1
  147. package/dist/deepseek.cjs +0 -72
  148. package/dist/deepseek.cjs.map +0 -1
  149. package/dist/deepseek.d.cts +0 -21
  150. package/dist/deepseek.d.ts +0 -21
  151. package/dist/deepseek.js +0 -21
  152. package/dist/deepseek.js.map +0 -1
  153. package/dist/dist-65U7OYRG.js +0 -1257
  154. package/dist/dist-65U7OYRG.js.map +0 -1
  155. package/dist/fetchProvider-Cu4WkU5O.d.cts +0 -819
  156. package/dist/fetchProvider-Cu4WkU5O.d.ts +0 -819
  157. package/dist/frontend-ui-ux.json +0 -105
  158. package/dist/general-assistant.json +0 -95
  159. package/dist/git-master.json +0 -51
  160. package/dist/google-vertex.cjs +0 -72
  161. package/dist/google-vertex.cjs.map +0 -1
  162. package/dist/google-vertex.d.cts +0 -21
  163. package/dist/google-vertex.d.ts +0 -21
  164. package/dist/google-vertex.js +0 -21
  165. package/dist/google-vertex.js.map +0 -1
  166. package/dist/google.cjs +0 -72
  167. package/dist/google.cjs.map +0 -1
  168. package/dist/google.d.cts +0 -21
  169. package/dist/google.d.ts +0 -21
  170. package/dist/google.js +0 -21
  171. package/dist/google.js.map +0 -1
  172. package/dist/groq.cjs +0 -72
  173. package/dist/groq.cjs.map +0 -1
  174. package/dist/groq.d.cts +0 -21
  175. package/dist/groq.d.ts +0 -21
  176. package/dist/groq.js +0 -21
  177. package/dist/groq.js.map +0 -1
  178. package/dist/index.d.mts +0 -3203
  179. package/dist/index.mjs +0 -7064
  180. package/dist/index.mjs.map +0 -1
  181. package/dist/mistral.cjs +0 -72
  182. package/dist/mistral.cjs.map +0 -1
  183. package/dist/mistral.d.cts +0 -21
  184. package/dist/mistral.d.ts +0 -21
  185. package/dist/mistral.js +0 -21
  186. package/dist/mistral.js.map +0 -1
  187. package/dist/multipart-parser-EJCXIUHC.js +0 -372
  188. package/dist/multipart-parser-EJCXIUHC.js.map +0 -1
  189. package/dist/openai.cjs +0 -72
  190. package/dist/openai.cjs.map +0 -1
  191. package/dist/openai.d.cts +0 -21
  192. package/dist/openai.d.ts +0 -21
  193. package/dist/openai.js +0 -21
  194. package/dist/openai.js.map +0 -1
  195. package/dist/perplexity.cjs +0 -72
  196. package/dist/perplexity.cjs.map +0 -1
  197. package/dist/perplexity.d.cts +0 -21
  198. package/dist/perplexity.d.ts +0 -21
  199. package/dist/perplexity.js +0 -21
  200. package/dist/perplexity.js.map +0 -1
  201. package/dist/playwright.json +0 -52
  202. package/dist/promptConcat-BJdazTg5.d.cts +0 -1832
  203. package/dist/promptConcat-BJdazTg5.d.ts +0 -1832
  204. package/dist/promptConcat-CAkpni_8.d.cts +0 -1834
  205. package/dist/promptConcat-CAkpni_8.d.ts +0 -1834
  206. package/dist/promptConcat-CfH5-GAE.d.cts +0 -1036
  207. package/dist/promptConcat-ChcAZOOL.d.ts +0 -1036
  208. package/dist/promptConcat-G5TnJVRy.d.cts +0 -1800
  209. package/dist/promptConcat-G5TnJVRy.d.ts +0 -1800
  210. package/dist/promptConcat-L72eowzp.d.ts +0 -1090
  211. package/dist/promptConcat-eLHdN7K8.d.cts +0 -1090
  212. package/dist/src-VTSXKG72.js +0 -1409
  213. package/dist/src-VTSXKG72.js.map +0 -1
  214. package/dist/togetherai.cjs +0 -72
  215. package/dist/togetherai.cjs.map +0 -1
  216. package/dist/togetherai.d.cts +0 -21
  217. package/dist/togetherai.d.ts +0 -21
  218. package/dist/togetherai.js +0 -21
  219. package/dist/togetherai.js.map +0 -1
  220. package/dist/types-B0Jm2l38.d.cts +0 -767
  221. package/dist/types-B0Jm2l38.d.ts +0 -767
  222. package/dist/xai.cjs +0 -72
  223. package/dist/xai.cjs.map +0 -1
  224. package/dist/xai.d.cts +0 -21
  225. package/dist/xai.d.ts +0 -21
  226. package/dist/xai.js +0 -21
  227. package/dist/xai.js.map +0 -1
  228. /package/dist/{chunk-P4UZ7IXC.js.map → browser.js.map} +0 -0
@@ -0,0 +1,2657 @@
1
+ import {
2
+ createChatMessage,
3
+ getChatMessageParts,
4
+ isToolResultPart
5
+ } from "./chunk-WAI6BODI.js";
6
+ import {
7
+ TOOL_OPERATION_API_VERSION,
8
+ TOOL_OPERATION_KIND,
9
+ createToolOperationManifest
10
+ } from "./chunk-BGPU4RR7.js";
11
+ import {
12
+ OrchestrationError
13
+ } from "./chunk-FWSY5HOA.js";
14
+
15
+ // src/permission/engine.ts
16
+ function matchPattern(toolName, pattern) {
17
+ if (pattern === toolName) return true;
18
+ if (pattern === "*") return true;
19
+ const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\*/g, ".*");
20
+ return new RegExp(`^${escaped}$`).test(toolName);
21
+ }
22
+ function mergePermissionSets(sets) {
23
+ const merged = /* @__PURE__ */ new Map();
24
+ merged.set("allow", /* @__PURE__ */ new Map());
25
+ merged.set("deny", /* @__PURE__ */ new Map());
26
+ merged.set("ask", /* @__PURE__ */ new Map());
27
+ for (const set of sets) {
28
+ for (const rule of set.rules) {
29
+ for (const [action, map] of merged) {
30
+ if (action !== rule.action) {
31
+ map.delete(rule.toolPattern);
32
+ }
33
+ }
34
+ merged.get(rule.action).set(rule.toolPattern, rule.action);
35
+ }
36
+ }
37
+ return {
38
+ allow: [...merged.get("allow").keys()],
39
+ deny: [...merged.get("deny").keys()],
40
+ ask: [...merged.get("ask").keys()]
41
+ };
42
+ }
43
+ function checkPermission(toolName, merged) {
44
+ const isWildcard = (p) => p.includes("*");
45
+ for (const pattern of merged.deny) {
46
+ if (!isWildcard(pattern) && matchPattern(toolName, pattern)) return "deny";
47
+ }
48
+ for (const pattern of merged.ask) {
49
+ if (!isWildcard(pattern) && matchPattern(toolName, pattern)) return "ask";
50
+ }
51
+ for (const pattern of merged.allow) {
52
+ if (!isWildcard(pattern) && matchPattern(toolName, pattern)) return "allow";
53
+ }
54
+ for (const pattern of merged.deny) {
55
+ if (isWildcard(pattern) && matchPattern(toolName, pattern)) return "deny";
56
+ }
57
+ for (const pattern of merged.ask) {
58
+ if (isWildcard(pattern) && matchPattern(toolName, pattern)) return "ask";
59
+ }
60
+ for (const pattern of merged.allow) {
61
+ if (isWildcard(pattern) && matchPattern(toolName, pattern)) return "allow";
62
+ }
63
+ const hasAnyRules = merged.allow.length > 0 || merged.deny.length > 0 || merged.ask.length > 0;
64
+ return hasAnyRules ? "deny" : "allow";
65
+ }
66
+
67
+ // src/orchestration/security/admission.ts
68
+ function defaultAdmissionPolicyForTrustClass(trustClass) {
69
+ switch (trustClass) {
70
+ case "restricted":
71
+ case "quarantine":
72
+ return { defaultAction: "deny", rules: [] };
73
+ default:
74
+ return { defaultAction: "allow", rules: [] };
75
+ }
76
+ }
77
+ function resolveAdmissionPolicy(profile, trustClass) {
78
+ const base = defaultAdmissionPolicyForTrustClass(trustClass);
79
+ const overlay = profile?.spec.toolAdmission;
80
+ if (!overlay) return base;
81
+ const defaultAction = trustClass === "trusted" ? overlay.defaultAction ?? base.defaultAction : "deny";
82
+ return {
83
+ defaultAction,
84
+ rules: [...overlay.rules ?? [], ...base.rules ?? []]
85
+ };
86
+ }
87
+ function defaultPermissionActionForTrustClass(trustClass) {
88
+ return trustClass === "restricted" || trustClass === "quarantine" ? "deny" : "allow";
89
+ }
90
+ function evaluateToolAdmission(policy, operation) {
91
+ const toolName = operation.spec.toolRef.name;
92
+ const effect = operation.spec.effect;
93
+ for (const rule of policy.rules ?? []) {
94
+ if (!matchPattern(toolName, rule.toolPattern)) continue;
95
+ if (rule.effects && !rule.effects.includes(effect)) continue;
96
+ return {
97
+ action: rule.action,
98
+ source: "rule",
99
+ reason: rule.reason,
100
+ matchedRule: rule
101
+ };
102
+ }
103
+ return { action: policy.defaultAction, source: "default" };
104
+ }
105
+
106
+ // src/orchestration/drivers/unknownEffect.ts
107
+ var TOOL_OPERATION_CONDITION_EFFECT_UNKNOWN = "EffectUnknown";
108
+ var DEFAULT_MAX_ATTEMPTS = 3;
109
+ function attemptsOf(operation) {
110
+ return operation.status?.attempts ?? 0;
111
+ }
112
+ function maxAttemptsOf(operation) {
113
+ return operation.spec.retry?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
114
+ }
115
+ function reconcileUnknownEffect(operation, evidence) {
116
+ if (evidence.resultObserved) {
117
+ return { action: "succeeded", reason: "result was observed before the disconnect; only the ack was lost" };
118
+ }
119
+ if (operation.spec.retry?.nonRetryable) {
120
+ return { action: "manual-intervention", reason: "operation is marked nonRetryable and its effect is unknown" };
121
+ }
122
+ const attempts = attemptsOf(operation);
123
+ const maxAttempts = maxAttemptsOf(operation);
124
+ const withinBudget = attempts < maxAttempts;
125
+ if (operation.spec.effect === "read") {
126
+ if (withinBudget) {
127
+ return { action: "retry", reason: `read effect has no side effects (attempt ${attempts + 1}/${maxAttempts})` };
128
+ }
129
+ return { action: "verification-required", reason: `read retry budget exhausted (${attempts}/${maxAttempts})` };
130
+ }
131
+ if (operation.spec.idempotencyKey) {
132
+ if (withinBudget) {
133
+ return {
134
+ action: "retry",
135
+ reason: `idempotencyKey deduplicates repeated delivery (attempt ${attempts + 1}/${maxAttempts})`
136
+ };
137
+ }
138
+ return {
139
+ action: "verification-required",
140
+ reason: `idempotent retry budget exhausted (${attempts}/${maxAttempts}); verify before further attempts`
141
+ };
142
+ }
143
+ return {
144
+ action: "verification-required",
145
+ reason: `effect '${operation.spec.effect}' without idempotencyKey must be verified before any retry`
146
+ };
147
+ }
148
+ function effectUnknownCondition(decision, at) {
149
+ return {
150
+ type: TOOL_OPERATION_CONDITION_EFFECT_UNKNOWN,
151
+ status: "True",
152
+ reason: decision.action,
153
+ message: decision.reason,
154
+ lastTransitionTime: at
155
+ };
156
+ }
157
+ function applyUnknownEffectDecision(operation, decision, at = (/* @__PURE__ */ new Date()).toISOString()) {
158
+ const conditions = [
159
+ ...(operation.status?.conditions ?? []).filter((c) => c.type !== TOOL_OPERATION_CONDITION_EFFECT_UNKNOWN),
160
+ effectUnknownCondition(decision, at)
161
+ ];
162
+ const base = {
163
+ ...operation.status,
164
+ conditions
165
+ };
166
+ if (decision.action === "retry") {
167
+ return { ...operation, status: { ...base, phase: "Pending" } };
168
+ }
169
+ if (decision.action === "succeeded") {
170
+ return {
171
+ ...operation,
172
+ status: { ...base, phase: "Completed", completedAt: at }
173
+ };
174
+ }
175
+ return { ...operation, status: { ...base, phase: "Running" } };
176
+ }
177
+
178
+ // src/tools/pluginRegistry.ts
179
+ var defaultPluginRegistry = /* @__PURE__ */ new Map();
180
+ var pluginRegistry = defaultPluginRegistry;
181
+ var activeOverride = null;
182
+ function getActivePluginRegistry() {
183
+ return activeOverride ?? defaultPluginRegistry;
184
+ }
185
+ function runWithPluginRegistry(registry, function_) {
186
+ const previous = activeOverride;
187
+ activeOverride = registry;
188
+ try {
189
+ return function_();
190
+ } finally {
191
+ activeOverride = previous;
192
+ }
193
+ }
194
+ function createHookSlot() {
195
+ const handlers = [];
196
+ return {
197
+ handlers,
198
+ tapAsync(_name, function_) {
199
+ handlers.push(function_);
200
+ },
201
+ async promise(context) {
202
+ for (const function_ of handlers) {
203
+ await new Promise((resolve) => {
204
+ function_(context, resolve);
205
+ });
206
+ }
207
+ }
208
+ };
209
+ }
210
+ function createAgentFrameworkHooks() {
211
+ return {
212
+ processPrompts: createHookSlot(),
213
+ finalizePrompts: createHookSlot(),
214
+ postProcess: createHookSlot(),
215
+ userMessageReceived: createHookSlot(),
216
+ agentStatusChanged: createHookSlot(),
217
+ toolExecuted: createHookSlot(),
218
+ responseUpdate: createHookSlot(),
219
+ responseComplete: createHookSlot()
220
+ };
221
+ }
222
+ var hookHandlers = {};
223
+ async function runProcessPromptsHooks(_hooks, context) {
224
+ const slot = _hooks.processPrompts;
225
+ const fns = slot?.handlers ?? hookHandlers.processPrompts ?? [];
226
+ for (const function_ of fns) {
227
+ await new Promise((resolve) => {
228
+ function_(context, resolve);
229
+ });
230
+ }
231
+ return context;
232
+ }
233
+ async function runResponseCompleteHooks(hooks, context) {
234
+ await hooks.responseComplete.promise(context);
235
+ }
236
+ async function runPostProcessHooks(hooks, context) {
237
+ await hooks.postProcess.promise(context);
238
+ }
239
+ async function runToolExecutedHooks(hooks, context) {
240
+ await hooks.toolExecuted.promise(context);
241
+ }
242
+ function resolvePromptPluginMap(context) {
243
+ const fromTools = context.tools?.getPromptPlugins?.();
244
+ if (fromTools) return fromTools;
245
+ return getActivePluginRegistry();
246
+ }
247
+ async function createHooksWithPlugins(agentFrameworkConfig, options) {
248
+ const reg = options?.pluginRegistry ?? getActivePluginRegistry();
249
+ const hooks = createAgentFrameworkHooks();
250
+ if (agentFrameworkConfig.plugins) {
251
+ for (const pluginConfig of agentFrameworkConfig.plugins) {
252
+ const { toolId } = pluginConfig;
253
+ const plugin = reg.get(toolId);
254
+ if (plugin) {
255
+ plugin(hooks);
256
+ }
257
+ }
258
+ }
259
+ return {
260
+ hooks,
261
+ pluginConfigs: agentFrameworkConfig.plugins ?? []
262
+ };
263
+ }
264
+
265
+ // src/promptUtilities/responsePatternUtility.ts
266
+ import JSON5 from "json5";
267
+ var MAX_FALLBACK_INPUT_LENGTH = 1e3;
268
+ function parseToolParameters(parametersText) {
269
+ if (!parametersText || !parametersText.trim()) {
270
+ return {};
271
+ }
272
+ const trimmedText = parametersText.trim();
273
+ try {
274
+ return JSON.parse(trimmedText);
275
+ } catch {
276
+ }
277
+ try {
278
+ return JSON5.parse(trimmedText);
279
+ } catch {
280
+ }
281
+ return { input: trimmedText.substring(0, MAX_FALLBACK_INPUT_LENGTH) };
282
+ }
283
+ function extractFunctionCallsParameters(text) {
284
+ const parameters = {};
285
+ const parameterRegex = /<parameter\s+name="([^"]+)"[^>]*>([^<]*)<\/parameter>/g;
286
+ let m;
287
+ while ((m = parameterRegex.exec(text)) !== null) {
288
+ parameters[m[1]] = m[2].trim();
289
+ }
290
+ return parameters;
291
+ }
292
+ var toolPatterns = [
293
+ {
294
+ name: "tool_use",
295
+ pattern: /<tool_use\s+name="([^"]+)"[^>]*>(.*?)<\/tool_use>/gis,
296
+ extractToolId: (match) => match[1],
297
+ extractParams: (match) => match[2],
298
+ extractOriginalText: (match) => match[0]
299
+ },
300
+ {
301
+ name: "function_call",
302
+ pattern: /<function_call\s+name="([^"]+)"[^>]*>(.*?)<\/function_call>/gis,
303
+ extractToolId: (match) => match[1],
304
+ extractParams: (match) => match[2],
305
+ extractOriginalText: (match) => match[0]
306
+ },
307
+ {
308
+ name: "function_calls_invoke",
309
+ pattern: /<invoke\s+name="([^"]+)"[^>]*>(.*?)<\/invoke>/gis,
310
+ extractToolId: (match) => match[1],
311
+ extractParams: (match) => JSON.stringify(extractFunctionCallsParameters(match[2])),
312
+ extractOriginalText: (match) => match[0]
313
+ }
314
+ ];
315
+ function matchToolCalling(responseText) {
316
+ try {
317
+ for (const toolPattern of toolPatterns) {
318
+ toolPattern.pattern.lastIndex = 0;
319
+ const match = toolPattern.pattern.exec(responseText);
320
+ if (match) {
321
+ const toolId = toolPattern.extractToolId(match);
322
+ const parametersText = toolPattern.extractParams(match);
323
+ const originalText = toolPattern.extractOriginalText(match);
324
+ return {
325
+ found: true,
326
+ toolId,
327
+ parameters: parseToolParameters(parametersText),
328
+ originalText
329
+ };
330
+ }
331
+ }
332
+ return { found: false };
333
+ } catch {
334
+ return { found: false };
335
+ }
336
+ }
337
+ function matchAllToolCallings(responseText) {
338
+ const calls = [];
339
+ const parallel = /<parallel_tool_calls>/i.test(responseText);
340
+ try {
341
+ for (const toolPattern of toolPatterns) {
342
+ toolPattern.pattern.lastIndex = 0;
343
+ let match;
344
+ while ((match = toolPattern.pattern.exec(responseText)) !== null) {
345
+ calls.push({
346
+ found: true,
347
+ toolId: toolPattern.extractToolId(match),
348
+ parameters: parseToolParameters(toolPattern.extractParams(match)),
349
+ originalText: toolPattern.extractOriginalText(match)
350
+ });
351
+ }
352
+ }
353
+ } catch {
354
+ }
355
+ return { calls, parallel };
356
+ }
357
+
358
+ // src/storage/nextLamport.ts
359
+ async function nextLamportClockForConversation(storage, conversationId) {
360
+ if (typeof storage.getMaxLamportClockForConversation === "function") {
361
+ const max2 = await storage.getMaxLamportClockForConversation(conversationId);
362
+ return max2 + 1;
363
+ }
364
+ const msgs = await storage.getMessages(conversationId, { mode: "full-content" });
365
+ let max = 0;
366
+ for (const m of msgs) {
367
+ if (typeof m.lamportClock === "number" && m.lamportClock > max) {
368
+ max = m.lamportClock;
369
+ }
370
+ }
371
+ return max + 1;
372
+ }
373
+
374
+ // src/loopAPI/hooks/registry.ts
375
+ var HookRegistry = class {
376
+ hookRegistry = /* @__PURE__ */ new Map();
377
+ hookOrder = /* @__PURE__ */ new Map();
378
+ /**
379
+ * Register a hook handler for a specific lifecycle event.
380
+ */
381
+ registerHook(type, handler, name) {
382
+ const key = name ?? `hook:${Date.now().toString(36)}:${Math.random().toString(36).slice(2, 8)}`;
383
+ const handlers = this.hookOrder.get(type) ?? [];
384
+ handlers.push(handler);
385
+ this.hookOrder.set(type, handlers);
386
+ const map = this.hookRegistry.get(type) ?? /* @__PURE__ */ new Map();
387
+ map.set(key, handler);
388
+ this.hookRegistry.set(type, map);
389
+ }
390
+ /**
391
+ * Unregister a specific hook handler by name.
392
+ */
393
+ unregisterHook(type, name) {
394
+ const map = this.hookRegistry.get(type);
395
+ if (!map) return false;
396
+ const deleted = map.delete(name);
397
+ if (deleted) {
398
+ this.hookOrder.set(type, Array.from(map.values()));
399
+ }
400
+ return deleted;
401
+ }
402
+ /**
403
+ * Execute all registered hooks for a given type in registration order.
404
+ */
405
+ async executeHooks(type, context, data) {
406
+ const handlers = this.hookOrder.get(type);
407
+ if (!handlers || handlers.length === 0) {
408
+ return { allowed: true };
409
+ }
410
+ let currentData = data;
411
+ let mergedModified;
412
+ let permissionAction;
413
+ for (const handler of handlers) {
414
+ try {
415
+ const result = await handler(context, currentData);
416
+ if (result.modified) {
417
+ mergedModified = { ...mergedModified ?? {}, ...result.modified };
418
+ currentData = { ...currentData, ...result.modified };
419
+ }
420
+ if (result.permissionAction && result.permissionAction !== "allow") {
421
+ permissionAction = result.permissionAction;
422
+ }
423
+ if (!result.allowed) {
424
+ return {
425
+ ...result,
426
+ modified: mergedModified ?? result.modified,
427
+ permissionAction: permissionAction ?? result.permissionAction
428
+ };
429
+ }
430
+ } catch (error) {
431
+ return {
432
+ allowed: false,
433
+ reason: error instanceof Error ? error.message : "Hook execution failed",
434
+ modified: mergedModified,
435
+ permissionAction
436
+ };
437
+ }
438
+ }
439
+ const finalResult = { allowed: true };
440
+ if (mergedModified) finalResult.modified = mergedModified;
441
+ if (permissionAction) finalResult.permissionAction = permissionAction;
442
+ return finalResult;
443
+ }
444
+ /**
445
+ * Check if any hooks are registered for a given type.
446
+ */
447
+ hasHooks(type) {
448
+ const map = this.hookRegistry.get(type);
449
+ return map != null && map.size > 0;
450
+ }
451
+ /**
452
+ * Remove all registered hooks of all types.
453
+ */
454
+ clearHooks() {
455
+ this.hookRegistry.clear();
456
+ this.hookOrder.clear();
457
+ }
458
+ /**
459
+ * List all hook types that have at least one registered handler.
460
+ */
461
+ listRegisteredHookTypes() {
462
+ const types = [];
463
+ for (const [type, map] of this.hookRegistry) {
464
+ if (map.size > 0) {
465
+ types.push(type);
466
+ }
467
+ }
468
+ return types;
469
+ }
470
+ /**
471
+ * Get the count of registered handlers for a hook type.
472
+ */
473
+ getHookCount(type) {
474
+ const map = this.hookRegistry.get(type);
475
+ return map?.size ?? 0;
476
+ }
477
+ };
478
+ var defaultHookRegistry = new HookRegistry();
479
+ function getDefaultHookRegistry() {
480
+ return defaultHookRegistry;
481
+ }
482
+ function registerHook(type, handler, name) {
483
+ defaultHookRegistry.registerHook(type, handler, name);
484
+ }
485
+ function unregisterHook(type, name) {
486
+ return defaultHookRegistry.unregisterHook(type, name);
487
+ }
488
+ async function executeHooks(type, context, data) {
489
+ return defaultHookRegistry.executeHooks(type, context, data);
490
+ }
491
+ function hasHooks(type) {
492
+ return defaultHookRegistry.hasHooks(type);
493
+ }
494
+ function clearHooks() {
495
+ defaultHookRegistry.clearHooks();
496
+ }
497
+ function listRegisteredHookTypes() {
498
+ return defaultHookRegistry.listRegisteredHookTypes();
499
+ }
500
+ function getHookCount(type) {
501
+ return defaultHookRegistry.getHookCount(type);
502
+ }
503
+
504
+ // src/loopAPI/agent-tool-loop/compaction.ts
505
+ function countTurns(messages) {
506
+ let turns = 0;
507
+ for (const message of messages) {
508
+ if (message.role === "user") {
509
+ turns++;
510
+ }
511
+ }
512
+ return turns;
513
+ }
514
+ function estimateTokens(messages) {
515
+ let total = 0;
516
+ for (const message of messages) {
517
+ const content = typeof message.content === "string" ? message.content : JSON.stringify(message.content);
518
+ total += content.length / 3.5;
519
+ }
520
+ return Math.ceil(total);
521
+ }
522
+ function buildTruncationSummary(dropped, totalDropped) {
523
+ const turns = countTurns(dropped);
524
+ const oldest = dropped[0];
525
+ const newest = dropped[dropped.length - 1];
526
+ const oldestTime = oldest?.timestamp ? new Date(oldest.timestamp).toISOString() : "unknown";
527
+ const newestTime = newest?.timestamp ? new Date(newest.timestamp).toISOString() : "unknown";
528
+ return `[context-summary] ${totalDropped} earlier messages (${turns} turns, ${oldestTime} \u2192 ${newestTime}) were compacted. Key topics: see recent messages below.`;
529
+ }
530
+ function createSummaryMessage(conversationId, summaryText, baseMessage) {
531
+ return {
532
+ messageId: `${conversationId}:compacted:${Date.now().toString(36)}`,
533
+ conversationId,
534
+ originNodeId: baseMessage.originNodeId,
535
+ timestamp: Date.now(),
536
+ lamportClock: -1,
537
+ // Will be replaced by AgentToolLoop
538
+ role: "assistant",
539
+ content: summaryText,
540
+ metadata: { compacted: true }
541
+ };
542
+ }
543
+ function compactMessages(messages, options = {}) {
544
+ const recentTurnsToKeep = options.recentTurnsToKeep ?? 4;
545
+ if (messages.length <= recentTurnsToKeep * 2) {
546
+ return { messages, compacted: false, droppedCount: 0, summaryText: "" };
547
+ }
548
+ const userIndices = [];
549
+ for (let index = 0; index < messages.length; index++) {
550
+ if (messages[index].role === "user") {
551
+ userIndices.push(index);
552
+ }
553
+ }
554
+ if (userIndices.length <= recentTurnsToKeep) {
555
+ return { messages, compacted: false, droppedCount: 0, summaryText: "" };
556
+ }
557
+ const keepStartIndex = userIndices[userIndices.length - recentTurnsToKeep];
558
+ const dropped = messages.slice(0, keepStartIndex);
559
+ const kept = messages.slice(keepStartIndex);
560
+ if (dropped.length === 0) {
561
+ return { messages, compacted: false, droppedCount: 0, summaryText: "" };
562
+ }
563
+ const conversationId = messages[0]?.conversationId ?? "unknown";
564
+ const summaryText = buildTruncationSummary(dropped, dropped.length);
565
+ const summaryMessage = createSummaryMessage(conversationId, summaryText, messages[0]);
566
+ const compacted = [summaryMessage, ...kept];
567
+ return {
568
+ messages: compacted,
569
+ compacted: true,
570
+ droppedCount: dropped.length,
571
+ summaryText
572
+ };
573
+ }
574
+ function shouldCompact(messages, threshold) {
575
+ const t = threshold ?? 50;
576
+ return messages.length > t;
577
+ }
578
+ async function autoCompact(messages, options = {}) {
579
+ const recentTurnsToKeep = options.recentTurnsToKeep ?? 4;
580
+ if (options.maxTokens && options.maxTokens > 0) {
581
+ const currentTokens = estimateTokens(messages);
582
+ if (currentTokens <= options.maxTokens) {
583
+ return { messages, compacted: false, droppedCount: 0, summaryText: "" };
584
+ }
585
+ }
586
+ if (options.useLlmSummary !== false && options.llmProvider?.model != null) {
587
+ try {
588
+ const result = await llmCompact(messages, options.llmProvider, recentTurnsToKeep);
589
+ if (result) return result;
590
+ } catch {
591
+ }
592
+ }
593
+ return compactMessages(messages, { ...options });
594
+ }
595
+ async function llmCompact(messages, llmProvider, recentTurnsToKeep) {
596
+ const userIndices = [];
597
+ for (let index = 0; index < messages.length; index++) {
598
+ if (messages[index].role === "user") {
599
+ userIndices.push(index);
600
+ }
601
+ }
602
+ if (userIndices.length <= recentTurnsToKeep) {
603
+ return null;
604
+ }
605
+ const keepStartIndex = userIndices[userIndices.length - recentTurnsToKeep];
606
+ const toSummarize = messages.slice(0, keepStartIndex);
607
+ const kept = messages.slice(keepStartIndex);
608
+ if (toSummarize.length === 0) return null;
609
+ const conversationId = messages[0]?.conversationId ?? "unknown";
610
+ const conversationText = toSummarize.map((m) => {
611
+ const content = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
612
+ const toolId = typeof m.metadata?.toolId === "string" ? m.metadata.toolId : "unknown";
613
+ const roleLabel = m.role === "tool" ? `[tool: ${toolId}]` : `[${m.role}]`;
614
+ if (m.role === "tool" && content.length > 500) {
615
+ return `${roleLabel} ${content.slice(0, 500)}... (truncated)`;
616
+ }
617
+ return `${roleLabel} ${content}`;
618
+ }).join("\n\n");
619
+ const prompt = `Summarize the following conversation excerpt. Be concise but capture key decisions, action items, tool calls, and important context. Focus on information useful for continuing the conversation.
620
+
621
+ <conversation>
622
+ ${conversationText.slice(0, 8e3)}
623
+ </conversation>
624
+
625
+ Provide a brief summary (3-5 paragraphs) of the key points.`;
626
+ try {
627
+ const summaryText = await generateSummary(llmProvider, prompt);
628
+ if (!summaryText || summaryText.length < 10) return null;
629
+ const summaryMessage = createSummaryMessage(
630
+ conversationId,
631
+ `[context-summary] ${summaryText}`,
632
+ messages[0]
633
+ );
634
+ return {
635
+ messages: [summaryMessage, ...kept],
636
+ compacted: true,
637
+ droppedCount: toSummarize.length,
638
+ summaryText
639
+ };
640
+ } catch {
641
+ return null;
642
+ }
643
+ }
644
+ async function generateSummary(llmProvider, prompt) {
645
+ if (typeof llmProvider.chat !== "function") return null;
646
+ const raw = llmProvider.chat({ messages: [{ role: "user", content: prompt }] });
647
+ let resolved = raw;
648
+ if (resolved != null && typeof resolved.then === "function") {
649
+ resolved = await resolved;
650
+ }
651
+ if (resolved != null && typeof resolved[Symbol.asyncIterator] === "function") {
652
+ let text = "";
653
+ for await (const chunk of resolved) {
654
+ text += chunkToText(chunk);
655
+ }
656
+ return text || null;
657
+ }
658
+ if (typeof resolved === "string") return resolved;
659
+ return null;
660
+ }
661
+ function chunkToText(chunk) {
662
+ if (typeof chunk === "string") return chunk;
663
+ if (chunk != null && typeof chunk === "object" && "content" in chunk) {
664
+ const content = chunk.content;
665
+ return typeof content === "string" ? content : JSON.stringify(content);
666
+ }
667
+ return JSON.stringify(chunk);
668
+ }
669
+
670
+ // src/promptUtilities/promptConcat.ts
671
+ function collectPromptSourcePaths(prompts, basePath = "agentFrameworkConfig.prompts") {
672
+ const out = {};
673
+ function walk(nodes, prefix) {
674
+ nodes.forEach((n, index) => {
675
+ const p = `${prefix}.${index}`;
676
+ if (n.id) {
677
+ out[n.id] = p;
678
+ }
679
+ if (n.children?.length) {
680
+ walk(n.children, `${p}.children`);
681
+ }
682
+ });
683
+ }
684
+ walk(prompts, basePath);
685
+ return out;
686
+ }
687
+ var logger = {
688
+ debug: (..._arguments) => {
689
+ },
690
+ info: (..._arguments) => {
691
+ },
692
+ warn: (..._arguments) => {
693
+ },
694
+ error: (..._arguments) => {
695
+ }
696
+ };
697
+ function findPromptById(prompts, id) {
698
+ for (let index = 0; index < prompts.length; index++) {
699
+ const prompt = prompts[index];
700
+ if (prompt.id === id) {
701
+ return { prompt, parent: prompts, index };
702
+ }
703
+ if (prompt.children) {
704
+ const found = findPromptById(prompt.children, id);
705
+ if (found) return found;
706
+ }
707
+ }
708
+ return void 0;
709
+ }
710
+ function flattenPrompts(prompts) {
711
+ const result = [];
712
+ function processPrompt(prompt) {
713
+ let text = prompt.text ?? "";
714
+ if (prompt.children) {
715
+ for (const child of prompt.children) {
716
+ if (!child.role) {
717
+ text += processPrompt(child);
718
+ }
719
+ }
720
+ }
721
+ return text;
722
+ }
723
+ function collectRolePrompts(nodes) {
724
+ for (const prompt of nodes) {
725
+ if (prompt.enabled === false) continue;
726
+ const content = processPrompt(prompt);
727
+ if (content.trim() || prompt.role) {
728
+ result.push({
729
+ role: prompt.role ?? "system",
730
+ content: content.trim()
731
+ });
732
+ }
733
+ if (prompt.children) {
734
+ collectRolePrompts(prompt.children);
735
+ }
736
+ }
737
+ }
738
+ collectRolePrompts(prompts);
739
+ return result;
740
+ }
741
+ async function* promptConcatStream(agentConfig, messages, agentFrameworkContext, options) {
742
+ const frameworkConfig = agentConfig.agentFrameworkConfig;
743
+ const promptConfigs = frameworkConfig?.prompts ?? [];
744
+ const plugins = frameworkConfig?.plugins ?? [];
745
+ const hooks = createAgentFrameworkHooks();
746
+ const pluginMap = resolvePromptPluginMap(agentFrameworkContext);
747
+ for (const plugin of plugins) {
748
+ const entry = pluginMap.get(plugin.toolId);
749
+ if (entry) entry(hooks);
750
+ }
751
+ let processedContext = { prompts: promptConfigs };
752
+ for (let index = 0; index < plugins.length; index++) {
753
+ const plugin = plugins[index];
754
+ processedContext = await runProcessPromptsHooks(hooks, {
755
+ prompts: processedContext.prompts,
756
+ messages,
757
+ toolConfig: plugin,
758
+ pluginIndex: index,
759
+ agentFrameworkContext
760
+ });
761
+ }
762
+ const processed = processedContext.prompts;
763
+ const flat = flattenPrompts(processed);
764
+ const last = messages[messages.length - 1];
765
+ if (last && last.role === "user") {
766
+ const content = last.content;
767
+ const fileMeta = last.metadata?.file;
768
+ if (fileMeta?.path && options?.readAttachmentFile) {
769
+ try {
770
+ const buf = await options.readAttachmentFile(fileMeta.path);
771
+ flat.push({
772
+ role: "user",
773
+ content: [
774
+ { type: "image", image: buf },
775
+ { type: "text", text: content }
776
+ ]
777
+ });
778
+ } catch (error) {
779
+ logger.error("failed to read attached file", { error, path: fileMeta.path });
780
+ }
781
+ } else if (fileMeta?.path && !options?.readAttachmentFile) {
782
+ flat.push({
783
+ role: "user",
784
+ content: `[attached path: ${fileMeta.path}]
785
+ ${content}`
786
+ });
787
+ } else {
788
+ flat.push({ role: "user", content });
789
+ }
790
+ }
791
+ const state = {
792
+ processedPrompts: processed,
793
+ flatPrompts: flat,
794
+ step: "complete",
795
+ isComplete: true,
796
+ sourcePaths: collectPromptSourcePaths(processed)
797
+ };
798
+ yield state;
799
+ return state;
800
+ }
801
+
802
+ // src/tools/structuredToolResult.ts
803
+ var MEMELOOP_STRUCTURED_TOOL_KEY = "__memeloopToolResult";
804
+ function truncateToolSummary(s, max = 2e3) {
805
+ if (s.length <= max) return s;
806
+ return `${s.slice(0, max - 3)}...`;
807
+ }
808
+ function extractMemeloopStructuredToolPayload(raw) {
809
+ if (raw === null || typeof raw !== "object") return null;
810
+ const o = raw;
811
+ const payload = o[MEMELOOP_STRUCTURED_TOOL_KEY];
812
+ if (payload === null || typeof payload !== "object") return null;
813
+ const p = payload;
814
+ if (typeof p.summary !== "string" || p.summary.length === 0) return null;
815
+ const awaitSessionId = typeof p.awaitSessionId === "string" && p.awaitSessionId.length > 0 ? p.awaitSessionId : void 0;
816
+ return {
817
+ summary: p.summary,
818
+ detailRef: p.detailRef,
819
+ awaitSessionId
820
+ };
821
+ }
822
+
823
+ // src/tools/approval.ts
824
+ var pendingApprovals = /* @__PURE__ */ new Map();
825
+ var approvalListeners = /* @__PURE__ */ new Set();
826
+ function onApprovalRequest(listener) {
827
+ approvalListeners.add(listener);
828
+ return () => {
829
+ approvalListeners.delete(listener);
830
+ };
831
+ }
832
+ function evaluateApproval(approval, toolName, parameters) {
833
+ if (!approval || approval.mode === "auto") {
834
+ return "allow";
835
+ }
836
+ const callContent = JSON.stringify({ tool: toolName, parameters });
837
+ if (approval.denyPatterns?.length) {
838
+ for (const pattern of approval.denyPatterns) {
839
+ try {
840
+ if (new RegExp(pattern, "i").test(callContent)) {
841
+ return "deny";
842
+ }
843
+ } catch {
844
+ }
845
+ }
846
+ }
847
+ if (approval.allowPatterns?.length) {
848
+ for (const pattern of approval.allowPatterns) {
849
+ try {
850
+ if (new RegExp(pattern, "i").test(callContent)) {
851
+ return "allow";
852
+ }
853
+ } catch {
854
+ }
855
+ }
856
+ }
857
+ return "pending";
858
+ }
859
+ function requestApproval(request, timeoutMs = 6e4) {
860
+ return new Promise((resolve) => {
861
+ pendingApprovals.set(request.approvalId, { request, resolve });
862
+ for (const listener of approvalListeners) {
863
+ try {
864
+ listener(request);
865
+ } catch {
866
+ }
867
+ }
868
+ if (timeoutMs > 0) {
869
+ setTimeout(() => {
870
+ if (pendingApprovals.has(request.approvalId)) {
871
+ pendingApprovals.delete(request.approvalId);
872
+ resolve("deny");
873
+ }
874
+ }, timeoutMs);
875
+ }
876
+ });
877
+ }
878
+ function resolveApproval(approvalId, decision) {
879
+ const pending = pendingApprovals.get(approvalId);
880
+ if (pending) {
881
+ pendingApprovals.delete(approvalId);
882
+ pending.resolve(decision);
883
+ }
884
+ }
885
+ function getPendingApprovals() {
886
+ return [...pendingApprovals.values()].map((p) => p.request);
887
+ }
888
+ function cancelPendingApprovals(agentId) {
889
+ for (const [id, pending] of pendingApprovals) {
890
+ if (pending.request.agentId === agentId) {
891
+ pendingApprovals.delete(id);
892
+ pending.resolve("deny");
893
+ }
894
+ }
895
+ }
896
+
897
+ // src/promptUtilities/responseConcat.ts
898
+ function cloneResponses(responses) {
899
+ return structuredClone(responses);
900
+ }
901
+ async function responseConcat(agentFrameworkConfig, llmResponse, agentFrameworkContext, messages) {
902
+ const responses = Array.isArray(agentFrameworkConfig?.response) ? cloneResponses(agentFrameworkConfig.response) : [];
903
+ const toolConfigs = (Array.isArray(agentFrameworkConfig.plugins) ? agentFrameworkConfig.plugins : []).filter((t) => t.enabled !== false);
904
+ const hooks = createAgentFrameworkHooks();
905
+ const pluginMap = resolvePromptPluginMap(agentFrameworkContext);
906
+ for (const tool of toolConfigs) {
907
+ const builtInTool = pluginMap.get(tool.toolId);
908
+ if (builtInTool) {
909
+ builtInTool(hooks);
910
+ }
911
+ }
912
+ let yieldNextRoundTo;
913
+ let toolCallInfo;
914
+ for (const tool of toolConfigs) {
915
+ const responseContext = {
916
+ agentFrameworkContext,
917
+ messages,
918
+ prompts: [],
919
+ toolConfig: tool,
920
+ llmResponse,
921
+ responses,
922
+ metadata: {},
923
+ actions: {}
924
+ };
925
+ await runPostProcessHooks(hooks, responseContext);
926
+ if (responseContext.actions?.yieldNextRoundTo) {
927
+ yieldNextRoundTo = responseContext.actions.yieldNextRoundTo;
928
+ if (responseContext.actions.toolCalling) {
929
+ toolCallInfo = responseContext.actions.toolCalling;
930
+ }
931
+ }
932
+ }
933
+ const processedResponse = flattenResponses(responses);
934
+ return {
935
+ processedResponse: processedResponse || llmResponse,
936
+ yieldNextRoundTo,
937
+ toolCallInfo
938
+ };
939
+ }
940
+ function flattenResponses(responses) {
941
+ if (responses.length === 0) {
942
+ return "";
943
+ }
944
+ return responses.filter((response) => response.enabled !== false).map((response) => response.text || "").join("\n\n").trim();
945
+ }
946
+
947
+ // src/loopAPI/agent-tool-loop/historyCompaction.ts
948
+ function compactHistory(history, options) {
949
+ const maxMessages = options?.contextCompaction?.maxMessages ?? 0;
950
+ if (maxMessages <= 0 || history.length <= maxMessages) return history;
951
+ const dropped = history.length - maxMessages;
952
+ const tail = history.slice(-maxMessages);
953
+ const summaryMessage = {
954
+ ...tail[0],
955
+ messageId: `${tail[0]?.conversationId ?? "unknown"}:summary:${Date.now().toString(36)}`,
956
+ role: "assistant",
957
+ content: `[context-summary] ${dropped} earlier messages were compacted.`
958
+ };
959
+ if (options?.contextCompaction?.replayLastUserMessage === false) return tail;
960
+ const lastUser = [...history].reverse().find((message) => message.role === "user");
961
+ if (!lastUser) return [summaryMessage, ...tail];
962
+ if (tail.some((message) => message.messageId === lastUser.messageId)) return tail;
963
+ return [summaryMessage, lastUser, ...tail];
964
+ }
965
+ function asChatMessages(value) {
966
+ if (!Array.isArray(value)) return void 0;
967
+ if (!value.every((message) => message != null && typeof message === "object")) return void 0;
968
+ return value;
969
+ }
970
+ function buildCompactedStep(conversationId, iteration, droppedCount, summaryText) {
971
+ return {
972
+ type: "thinking",
973
+ data: {
974
+ status: "compacted",
975
+ conversationId,
976
+ droppedCount: typeof droppedCount === "number" ? droppedCount : 0,
977
+ summaryText: typeof summaryText === "string" ? summaryText : "",
978
+ iteration
979
+ }
980
+ };
981
+ }
982
+ async function persistSummaryMessage(context, conversationId, summaryMessage) {
983
+ if (!summaryMessage) return;
984
+ const lamportSummary = await nextLamportClockForConversation(context.storage, conversationId);
985
+ await context.storage.appendMessage({
986
+ ...summaryMessage,
987
+ lamportClock: lamportSummary
988
+ });
989
+ }
990
+ async function maybeApplyContextCompactionHook(options) {
991
+ const { context, conversationId, iteration, history, agentToolLoopOptions } = options;
992
+ if (!hasHooks("ContextCompaction")) {
993
+ return { handled: false, history, steps: [] };
994
+ }
995
+ const hookResult = await executeHooks("ContextCompaction", context, {
996
+ conversationId,
997
+ iteration,
998
+ history,
999
+ autoCompact: agentToolLoopOptions?.autoCompact,
1000
+ contextCompaction: agentToolLoopOptions?.contextCompaction
1001
+ });
1002
+ const modified = hookResult.modified;
1003
+ const modifiedHistory = asChatMessages(modified?.history);
1004
+ const nextHistory = modifiedHistory ?? history;
1005
+ const skipDefault = !hookResult.allowed || modifiedHistory != null || modified?.skipDefault === true;
1006
+ if (!skipDefault) {
1007
+ return { handled: false, history: nextHistory, steps: [] };
1008
+ }
1009
+ const steps = modified?.compacted === true ? [buildCompactedStep(conversationId, iteration, modified.droppedCount, modified.summaryText)] : [];
1010
+ if (modified?.persistSummaryMessage === true) {
1011
+ await persistSummaryMessage(context, conversationId, nextHistory[0]);
1012
+ }
1013
+ return { handled: true, history: nextHistory, steps };
1014
+ }
1015
+ async function applyBuiltInAutoCompact(options) {
1016
+ const { context, conversationId, iteration, agentToolLoopOptions } = options;
1017
+ let history = options.history;
1018
+ const autoCompactOptions = agentToolLoopOptions?.autoCompact;
1019
+ if (!autoCompactOptions) {
1020
+ return { history, steps: [] };
1021
+ }
1022
+ const threshold = autoCompactOptions.threshold ?? 50;
1023
+ if (!shouldCompact(history, threshold)) {
1024
+ return { history, steps: [] };
1025
+ }
1026
+ try {
1027
+ const result = await autoCompact(history, {
1028
+ recentTurnsToKeep: autoCompactOptions.recentTurnsToKeep ?? 4,
1029
+ maxTokens: autoCompactOptions.maxTokens ?? 0,
1030
+ llmProvider: context.llmProvider
1031
+ });
1032
+ if (!result.compacted) {
1033
+ return { history, steps: [] };
1034
+ }
1035
+ history = result.messages;
1036
+ await persistSummaryMessage(context, conversationId, result.messages[0]);
1037
+ return {
1038
+ history,
1039
+ steps: [
1040
+ buildCompactedStep(conversationId, iteration, result.droppedCount, result.summaryText)
1041
+ ]
1042
+ };
1043
+ } catch (error) {
1044
+ if (context.logger?.warn) {
1045
+ context.logger.warn("[agentToolLoop] auto-compact failed:", error);
1046
+ } else {
1047
+ console.warn("[agentToolLoop] auto-compact failed:", error);
1048
+ }
1049
+ return { history, steps: [] };
1050
+ }
1051
+ }
1052
+ async function prepareIterationHistory(options) {
1053
+ const { agentToolLoopOptions } = options;
1054
+ const hookResult = await maybeApplyContextCompactionHook({
1055
+ ...options,
1056
+ history: options.rawHistory
1057
+ });
1058
+ if (hookResult.handled) {
1059
+ return hookResult;
1060
+ }
1061
+ const autoCompactResult = await applyBuiltInAutoCompact({
1062
+ ...options,
1063
+ history: hookResult.history
1064
+ });
1065
+ return {
1066
+ history: compactHistory(autoCompactResult.history, agentToolLoopOptions),
1067
+ steps: autoCompactResult.steps
1068
+ };
1069
+ }
1070
+
1071
+ // src/loopAPI/agent-tool-loop/llmStream.ts
1072
+ function isAsyncIterable(value) {
1073
+ return value != null && typeof value[Symbol.asyncIterator] === "function";
1074
+ }
1075
+ function chunkToText2(chunk) {
1076
+ if (typeof chunk === "string") return chunk;
1077
+ if (chunk != null && typeof chunk === "object" && "content" in chunk) {
1078
+ const content = chunk.content;
1079
+ return typeof content === "string" ? content : JSON.stringify(content);
1080
+ }
1081
+ return JSON.stringify(chunk);
1082
+ }
1083
+ async function* streamLlm(context, request) {
1084
+ const chatFunction = context.llmProvider.chat;
1085
+ if (typeof chatFunction !== "function") {
1086
+ throw new Error(
1087
+ "LLM provider does not support legacy chat() method. Use AI SDK's streamText instead."
1088
+ );
1089
+ }
1090
+ const raw = chatFunction(request);
1091
+ let resolved = raw;
1092
+ if (resolved != null && typeof resolved.then === "function") {
1093
+ resolved = await resolved;
1094
+ }
1095
+ if (isAsyncIterable(resolved)) {
1096
+ for await (const chunk of resolved) {
1097
+ yield chunk;
1098
+ }
1099
+ return;
1100
+ }
1101
+ yield resolved;
1102
+ }
1103
+
1104
+ // src/promptUtilities/utilities.ts
1105
+ function filterOldMessagesByDuration(messages, maxAgeMs, now = Date.now()) {
1106
+ if (maxAgeMs <= 0) return messages;
1107
+ const cutoff = now - maxAgeMs;
1108
+ return messages.filter((m) => typeof m.timestamp === "number" && m.timestamp >= cutoff);
1109
+ }
1110
+
1111
+ // src/loopAPI/agent-tool-loop/toolResultMessage.ts
1112
+ function formatToolResultMessage(toolName, parameters, body, isError) {
1113
+ return `<functions_result>
1114
+ Tool: ${toolName}
1115
+ Parameters: ${JSON.stringify(parameters)}
1116
+ ${isError ? "Error" : "Result"}: ${body}
1117
+ </functions_result>`;
1118
+ }
1119
+
1120
+ // src/loopAPI/agent-tool-loop/modelMessages.ts
1121
+ function chatMessageToModelMessage(message) {
1122
+ const role = message.role === "agent" || message.role === "error" ? "assistant" : message.role === "tool" ? "tool" : message.role === "user" ? "user" : "assistant";
1123
+ if (role === "tool") {
1124
+ const toolResults = getChatMessageParts(message).filter(isToolResultPart);
1125
+ if (toolResults.length > 0) {
1126
+ return {
1127
+ role,
1128
+ content: toolResults.map(
1129
+ (part) => formatToolResultMessage(
1130
+ part.toolName,
1131
+ part.parameters && typeof part.parameters === "object" ? part.parameters : {},
1132
+ part.result,
1133
+ part.isError === true
1134
+ )
1135
+ ).join("\n\n")
1136
+ };
1137
+ }
1138
+ }
1139
+ return {
1140
+ role,
1141
+ content: message.content
1142
+ };
1143
+ }
1144
+ async function resolveAgentDefinitionModel(context, definitionId) {
1145
+ if (context.resolveAgentDefinition) {
1146
+ return context.resolveAgentDefinition(definitionId);
1147
+ }
1148
+ return context.storage.getAgentDefinition(definitionId);
1149
+ }
1150
+ async function inferDefinitionId(storage, conversationId) {
1151
+ try {
1152
+ const meta = await storage.getConversationMeta(conversationId);
1153
+ if (meta?.definitionId) return meta.definitionId;
1154
+ } catch {
1155
+ }
1156
+ const parts = conversationId.split(":");
1157
+ if (parts.length >= 2) {
1158
+ return parts.slice(0, -1).join(":");
1159
+ }
1160
+ return conversationId;
1161
+ }
1162
+ async function buildLlmMessages(context, conversationId, history) {
1163
+ const definitionId = await inferDefinitionId(context.storage, conversationId);
1164
+ const definition = await resolveAgentDefinitionModel(context, definitionId);
1165
+ const fw = definition?.agentFrameworkConfig;
1166
+ const maxHistoryAgeMs = context.agentToolLoop?.maxHistoryAgeMs ?? 0;
1167
+ const historyForPrompt = maxHistoryAgeMs > 0 ? filterOldMessagesByDuration(history, maxHistoryAgeMs) : history;
1168
+ if (fw?.prompts && Array.isArray(fw.prompts) && fw.prompts.length > 0) {
1169
+ const readAttachmentFile = context.agentToolLoop?.readAttachmentFile;
1170
+ const gen = promptConcatStream(
1171
+ {
1172
+ agentFrameworkConfig: {
1173
+ prompts: fw.prompts,
1174
+ plugins: fw.plugins ?? [],
1175
+ response: []
1176
+ }
1177
+ },
1178
+ historyForPrompt,
1179
+ context,
1180
+ readAttachmentFile ? { readAttachmentFile } : void 0
1181
+ );
1182
+ let lastFlat = [];
1183
+ for await (const state of gen) {
1184
+ lastFlat = state.flatPrompts;
1185
+ }
1186
+ const withoutTrailingUser = lastFlat.length > 0 && lastFlat[lastFlat.length - 1]?.role === "user" ? lastFlat.slice(0, -1) : lastFlat;
1187
+ return [...withoutTrailingUser, ...historyForPrompt.map(chatMessageToModelMessage)];
1188
+ }
1189
+ const systemText = typeof definition?.systemPrompt === "string" ? definition.systemPrompt.trim() : "";
1190
+ if (systemText.length > 0) {
1191
+ return [
1192
+ { role: "system", content: systemText },
1193
+ ...historyForPrompt.map(chatMessageToModelMessage)
1194
+ ];
1195
+ }
1196
+ return historyForPrompt.map(chatMessageToModelMessage);
1197
+ }
1198
+
1199
+ // src/loopAPI/agent-tool-loop/toolCallRunner.ts
1200
+ var TOOL_OPERATION_DEFAULT_TIMEOUT_MS = 6e4;
1201
+ var TOOL_OPERATION_POLL_INTERVAL_MS = 250;
1202
+ var toolOperationCounter = 0;
1203
+ var toolResultMessageCounter = 0;
1204
+ function isTerminalToolOperationPhase(phase) {
1205
+ return phase === "Completed" || phase === "Failed" || phase === "Cancelled";
1206
+ }
1207
+ function stableStringify(value) {
1208
+ if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "undefined";
1209
+ if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
1210
+ const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`);
1211
+ return `{${entries.join(",")}}`;
1212
+ }
1213
+ function fnv1aHex(input) {
1214
+ let hash = 2166136261;
1215
+ for (let index = 0; index < input.length; index += 1) {
1216
+ hash = Math.imul(hash ^ input.charCodeAt(index), 16777619) >>> 0;
1217
+ }
1218
+ return hash.toString(16).padStart(8, "0");
1219
+ }
1220
+ function isTransientGetError(error) {
1221
+ return error instanceof OrchestrationError && (error.code === "UNAVAILABLE" || error.code === "TIMEOUT" || error.code === "INTERNAL");
1222
+ }
1223
+ async function waitForToolOperationTerminal(client, reference, timeoutMs, applied) {
1224
+ const deadline = Date.now() + timeoutMs;
1225
+ let last = applied ?? null;
1226
+ while (Date.now() < deadline) {
1227
+ let resource;
1228
+ try {
1229
+ resource = await client.get(reference);
1230
+ } catch (error) {
1231
+ if (!isTransientGetError(error)) throw error;
1232
+ const basis = last ?? applied;
1233
+ if (!basis) throw error;
1234
+ const decision = reconcileUnknownEffect(basis, { resultObserved: false });
1235
+ if (decision.action === "retry") {
1236
+ } else {
1237
+ throw new Error(
1238
+ `ToolOperation ${reference.name ?? "<unknown>"} effect unknown after transport failure: ${decision.action} \u2014 ${decision.reason}`
1239
+ );
1240
+ }
1241
+ }
1242
+ if (resource) {
1243
+ last = resource;
1244
+ if (isTerminalToolOperationPhase(last.status?.phase)) {
1245
+ return last;
1246
+ }
1247
+ }
1248
+ await new Promise((resolve) => {
1249
+ setTimeout(resolve, TOOL_OPERATION_POLL_INTERVAL_MS);
1250
+ });
1251
+ }
1252
+ if (last) {
1253
+ return last;
1254
+ }
1255
+ throw new Error(`ToolOperation ${reference.name ?? "<unknown>"} was not observed before timeout`);
1256
+ }
1257
+ function toolOperationRow(resource) {
1258
+ const status = resource.status;
1259
+ if (status?.phase === "Completed") {
1260
+ const value = status.result?.value;
1261
+ if (value != null && typeof value === "object") {
1262
+ const structured = extractMemeloopStructuredToolPayload(value);
1263
+ if (structured) {
1264
+ return {
1265
+ text: structured.summary,
1266
+ isError: false,
1267
+ detailRef: structured.detailRef,
1268
+ awaitSessionId: structured.awaitSessionId
1269
+ };
1270
+ }
1271
+ if ("error" in value && typeof value.error === "string") {
1272
+ return { text: value.error, isError: true };
1273
+ }
1274
+ if ("result" in value && value.result != null) {
1275
+ return {
1276
+ text: typeof value.result === "string" ? value.result : JSON.stringify(value.result),
1277
+ payload: typeof value.result === "string" ? void 0 : value.result,
1278
+ isError: false
1279
+ };
1280
+ }
1281
+ }
1282
+ return { text: typeof value === "string" ? value : JSON.stringify(value), isError: false };
1283
+ }
1284
+ if (status?.phase === "Failed" || status?.phase === "Cancelled") {
1285
+ return {
1286
+ text: status.result?.error?.message ?? `ToolOperation ${status.phase}`,
1287
+ isError: true
1288
+ };
1289
+ }
1290
+ return {
1291
+ text: `ToolOperation did not reach a terminal phase (last phase: ${status?.phase ?? "unknown"})`,
1292
+ isError: true
1293
+ };
1294
+ }
1295
+ async function executeToolOperation(context, conversationId, call, occurrence) {
1296
+ const client = context.orchestration;
1297
+ if (!client) return null;
1298
+ try {
1299
+ const caps = await client.getCapabilities();
1300
+ if (!caps.resourceKinds.includes(TOOL_OPERATION_KIND) || !caps.operations.includes("apply") || !caps.operations.includes("get")) {
1301
+ return null;
1302
+ }
1303
+ } catch {
1304
+ return null;
1305
+ }
1306
+ const timeoutMs = context.agentToolLoop?.toolOperationTimeoutMs ?? TOOL_OPERATION_DEFAULT_TIMEOUT_MS;
1307
+ const idempotencyKey = `${conversationId}:${fnv1aHex(stableStringify({
1308
+ toolId: call.toolId,
1309
+ parameters: call.parameters
1310
+ }))}:${occurrence}`;
1311
+ toolOperationCounter += 1;
1312
+ const operation = createToolOperationManifest(
1313
+ `${call.toolId}-${Date.now().toString(36)}-${toolOperationCounter.toString(36)}`,
1314
+ {
1315
+ toolRef: { kind: "BuiltinTool", name: call.toolId },
1316
+ effect: context.tools.getToolEffect?.(call.toolId) ?? "execute",
1317
+ arguments: call.parameters,
1318
+ idempotencyKey,
1319
+ timeoutMs,
1320
+ policy: { auditLevel: "metadata" }
1321
+ }
1322
+ );
1323
+ try {
1324
+ const applied = await client.apply(operation);
1325
+ if (applied.apiVersion !== TOOL_OPERATION_API_VERSION || applied.kind !== TOOL_OPERATION_KIND) {
1326
+ return { text: "ToolOperation apply returned an unexpected resource kind", isError: true };
1327
+ }
1328
+ let resource = applied;
1329
+ if (!isTerminalToolOperationPhase(resource.status?.phase)) {
1330
+ const reference = {
1331
+ apiVersion: applied.apiVersion,
1332
+ kind: applied.kind,
1333
+ name: applied.metadata.name,
1334
+ namespace: applied.metadata.namespace
1335
+ };
1336
+ resource = await waitForToolOperationTerminal(client, reference, timeoutMs, resource);
1337
+ }
1338
+ return toolOperationRow(resource);
1339
+ } catch (error) {
1340
+ const message = error instanceof Error ? error.message : String(error);
1341
+ return { text: `ToolOperation execution error: ${message}`, isError: true };
1342
+ }
1343
+ }
1344
+ async function executeRegistryTool(context, toolId, parameters) {
1345
+ const normalizedId = toolId.includes("-") ? toolId.replace(/-([a-z])/g, (_m, c) => c.toUpperCase()) : toolId;
1346
+ const impl = context.tools.getTool(toolId) ?? context.tools.getTool(normalizedId);
1347
+ if (typeof impl !== "function") {
1348
+ return {
1349
+ text: `No tool registered for "${toolId}".`,
1350
+ isError: true
1351
+ };
1352
+ }
1353
+ try {
1354
+ const raw = await impl(parameters);
1355
+ if (raw != null && typeof raw === "object") {
1356
+ const o = raw;
1357
+ if (typeof o.error === "string" && o.error.length > 0) {
1358
+ return { text: o.error, isError: true };
1359
+ }
1360
+ if ("result" in o) {
1361
+ return {
1362
+ text: typeof o.result === "string" ? o.result : JSON.stringify(o.result),
1363
+ payload: typeof o.result === "string" ? void 0 : o.result,
1364
+ isError: false
1365
+ };
1366
+ }
1367
+ const structured = extractMemeloopStructuredToolPayload(raw);
1368
+ if (structured) {
1369
+ return {
1370
+ text: structured.summary,
1371
+ isError: false,
1372
+ detailRef: structured.detailRef,
1373
+ awaitSessionId: structured.awaitSessionId
1374
+ };
1375
+ }
1376
+ }
1377
+ return { text: typeof raw === "string" ? raw : JSON.stringify(raw), isError: false };
1378
+ } catch (error) {
1379
+ const message = error instanceof Error ? error.message : String(error);
1380
+ if (context.logger?.warn) {
1381
+ context.logger.warn("[agentToolLoop] tool execution error", toolId, message);
1382
+ } else {
1383
+ console.warn("[agentToolLoop] tool execution error", toolId, message);
1384
+ }
1385
+ return { text: message, isError: true };
1386
+ }
1387
+ }
1388
+ async function executeWithGuards(context, options, conversationId, recentToolCalls, call) {
1389
+ const signature = `${call.toolId}:${JSON.stringify(call.parameters)}`;
1390
+ recentToolCalls.push(signature);
1391
+ const threshold = Math.max(2, options?.doomLoopThreshold ?? 3);
1392
+ const last = recentToolCalls.slice(-threshold);
1393
+ if (last.length === threshold && last.every((x) => x === signature)) {
1394
+ return { text: "Blocked by doom-loop guard", isError: true };
1395
+ }
1396
+ const occurrence = recentToolCalls.filter((entry) => entry === signature).length;
1397
+ const row = await executeToolOperation(context, conversationId, call, occurrence) ?? await executeRegistryTool(context, call.toolId, call.parameters);
1398
+ if (hasHooks("PostToolUse")) {
1399
+ await executeHooks("PostToolUse", context, {
1400
+ toolId: call.toolId,
1401
+ parameters: call.parameters,
1402
+ result: row.text,
1403
+ isError: row.isError,
1404
+ conversationId
1405
+ });
1406
+ }
1407
+ return row;
1408
+ }
1409
+ async function persistToolResult(context, conversationId, call, row) {
1410
+ toolResultMessageCounter += 1;
1411
+ const lamportTool = await nextLamportClockForConversation(context.storage, conversationId);
1412
+ await context.storage.appendMessage(createChatMessage({
1413
+ // Counter suffix keeps message identity unique for identical calls within
1414
+ // the same millisecond (parallel tools or fast consecutive rounds).
1415
+ messageId: `${conversationId}:t:${call.toolId}:${Date.now().toString(36)}:${toolResultMessageCounter.toString(36)}`,
1416
+ conversationId,
1417
+ originNodeId: "local",
1418
+ lamportClock: lamportTool,
1419
+ role: "tool",
1420
+ parts: [{
1421
+ type: "tool-result",
1422
+ toolName: call.toolId,
1423
+ parameters: call.parameters,
1424
+ result: row.text,
1425
+ isError: row.isError,
1426
+ payload: row.payload,
1427
+ detailRef: row.detailRef
1428
+ }],
1429
+ detailRef: row.detailRef,
1430
+ metadata: {
1431
+ isToolResult: true,
1432
+ isError: row.isError,
1433
+ toolId: call.toolId,
1434
+ toolParameters: call.parameters
1435
+ }
1436
+ }));
1437
+ }
1438
+ async function persistTerminalAwaitCompletion(context, options, conversationId, call, row) {
1439
+ const sid = row.awaitSessionId;
1440
+ const wait = options?.waitForTerminalSession;
1441
+ if (!sid || !wait || row.isError) return;
1442
+ const done = await wait(sid);
1443
+ const lamportTool = await nextLamportClockForConversation(context.storage, conversationId);
1444
+ const body = truncateToolSummary(
1445
+ `[terminal.await done] session=${sid}
1446
+ exitCode: ${done.exitCode ?? "null"}
1447
+ ---
1448
+ ${done.truncatedOutput}`
1449
+ );
1450
+ await context.storage.appendMessage(createChatMessage({
1451
+ messageId: `${conversationId}:t:${call.toolId}:await:${Date.now().toString(36)}:${toolResultMessageCounter.toString(36)}`,
1452
+ conversationId,
1453
+ originNodeId: "local",
1454
+ lamportClock: lamportTool,
1455
+ role: "tool",
1456
+ parts: [{
1457
+ type: "tool-result",
1458
+ toolName: call.toolId,
1459
+ parameters: call.parameters,
1460
+ result: body,
1461
+ detailRef: row.detailRef ? { ...row.detailRef, exitCode: done.exitCode ?? row.detailRef.exitCode } : void 0
1462
+ }],
1463
+ detailRef: row.detailRef ? { ...row.detailRef, exitCode: done.exitCode ?? row.detailRef.exitCode } : void 0,
1464
+ metadata: {
1465
+ isToolResult: true,
1466
+ toolId: call.toolId,
1467
+ toolParameters: call.parameters,
1468
+ awaitSessionId: sid
1469
+ }
1470
+ }));
1471
+ }
1472
+ function toolStep(row, parallel) {
1473
+ return {
1474
+ type: "tool",
1475
+ data: {
1476
+ toolId: row.call.toolId,
1477
+ parameters: row.call.parameters,
1478
+ parallel,
1479
+ result: row.text,
1480
+ isError: row.isError
1481
+ }
1482
+ };
1483
+ }
1484
+ async function* runRegistryToolCalls(options) {
1485
+ const { context, agentToolLoopOptions, conversationId, calls, parallel, recentToolCalls } = options;
1486
+ if (parallel) {
1487
+ const results = await Promise.all(
1488
+ calls.map(
1489
+ async (call) => ({
1490
+ call,
1491
+ ...await executeWithGuards(
1492
+ context,
1493
+ agentToolLoopOptions,
1494
+ conversationId,
1495
+ recentToolCalls,
1496
+ call
1497
+ )
1498
+ })
1499
+ )
1500
+ );
1501
+ for (const row of results) {
1502
+ yield toolStep(row, true);
1503
+ }
1504
+ for (const row of results) {
1505
+ await persistToolResult(context, conversationId, row.call, row);
1506
+ }
1507
+ for (const row of results) {
1508
+ await persistTerminalAwaitCompletion(
1509
+ context,
1510
+ agentToolLoopOptions,
1511
+ conversationId,
1512
+ row.call,
1513
+ row
1514
+ );
1515
+ }
1516
+ return;
1517
+ }
1518
+ for (const call of calls) {
1519
+ const row = await executeWithGuards(
1520
+ context,
1521
+ agentToolLoopOptions,
1522
+ conversationId,
1523
+ recentToolCalls,
1524
+ call
1525
+ );
1526
+ yield toolStep({ call, ...row }, false);
1527
+ await persistToolResult(context, conversationId, call, row);
1528
+ await persistTerminalAwaitCompletion(context, agentToolLoopOptions, conversationId, call, row);
1529
+ }
1530
+ }
1531
+
1532
+ // src/loopAPI/agent-tool-loop/toolUseGate.ts
1533
+ function buildLayeredPermissions(options, definitionId, userSet) {
1534
+ const globalPerms = options?.toolPermissions;
1535
+ const sets = [];
1536
+ if (globalPerms?.default) {
1537
+ sets.push({
1538
+ source: "default",
1539
+ rules: [{ toolPattern: "*", action: globalPerms.default }]
1540
+ });
1541
+ }
1542
+ const scoped = globalPerms?.perAgent?.[definitionId];
1543
+ if (scoped) {
1544
+ if (scoped.default) {
1545
+ sets.push({
1546
+ source: `agent:${definitionId}:default`,
1547
+ rules: [{ toolPattern: "*", action: scoped.default }]
1548
+ });
1549
+ }
1550
+ if (scoped.rules && scoped.rules.length > 0) {
1551
+ sets.push({
1552
+ source: `agent:${definitionId}`,
1553
+ rules: scoped.rules.map((r) => ({ toolPattern: r.pattern, action: r.action }))
1554
+ });
1555
+ }
1556
+ }
1557
+ if (userSet && userSet.rules.length > 0) {
1558
+ sets.push(userSet);
1559
+ }
1560
+ if (globalPerms?.rules && globalPerms.rules.length > 0) {
1561
+ sets.push({
1562
+ source: "session",
1563
+ rules: globalPerms.rules.map((r) => ({ toolPattern: r.pattern, action: r.action }))
1564
+ });
1565
+ }
1566
+ if (!sets.some((s) => s.rules.some((r) => r.toolPattern === "*"))) {
1567
+ sets.unshift({
1568
+ source: "implied-default",
1569
+ rules: [{ toolPattern: "*", action: defaultPermissionActionForTrustClass(options?.trustClass) }]
1570
+ });
1571
+ }
1572
+ return mergePermissionSets(sets);
1573
+ }
1574
+ function createPermissionPreToolUseHook(options, definitionId, userSet) {
1575
+ const mergedPermissions = buildLayeredPermissions(options, definitionId, userSet);
1576
+ return async (_context, data) => {
1577
+ const toolId = typeof data.toolId === "string" ? data.toolId : "";
1578
+ const action = checkPermission(toolId, mergedPermissions);
1579
+ if (action === "allow") {
1580
+ return { allowed: true, permissionAction: "allow" };
1581
+ }
1582
+ return {
1583
+ allowed: true,
1584
+ permissionAction: action,
1585
+ reason: action === "deny" ? "Denied by tool permission" : void 0
1586
+ };
1587
+ };
1588
+ }
1589
+ function applyModifiedCall(call, modified) {
1590
+ if (!modified) return call;
1591
+ const toolId = typeof modified.toolId === "string" ? modified.toolId : call.toolId;
1592
+ const parameters = modified.parameters != null && typeof modified.parameters === "object" ? modified.parameters : call.parameters;
1593
+ return { ...call, toolId, parameters };
1594
+ }
1595
+ function normalizePreToolUseResult(result) {
1596
+ if (!result.allowed) {
1597
+ return { action: "deny", reason: result.reason ?? "Blocked by PreToolUse hook" };
1598
+ }
1599
+ if (result.permissionAction === "ask" || result.permissionAction === "deny") {
1600
+ return { action: result.permissionAction, reason: result.reason };
1601
+ }
1602
+ return { action: "allow", reason: result.reason };
1603
+ }
1604
+ async function persistDeniedToolResult(context, conversationId, call, errorText) {
1605
+ const lamportTool = await nextLamportClockForConversation(context.storage, conversationId);
1606
+ await context.storage.appendMessage(createChatMessage({
1607
+ messageId: `${conversationId}:t:${call.toolId}:${Date.now().toString(36)}`,
1608
+ conversationId,
1609
+ originNodeId: "local",
1610
+ lamportClock: lamportTool,
1611
+ role: "tool",
1612
+ parts: [{
1613
+ type: "tool-result",
1614
+ toolName: call.toolId,
1615
+ parameters: call.parameters,
1616
+ result: errorText,
1617
+ isError: true
1618
+ }],
1619
+ metadata: {
1620
+ isToolResult: true,
1621
+ isError: true,
1622
+ toolId: call.toolId,
1623
+ toolParameters: call.parameters
1624
+ }
1625
+ }));
1626
+ }
1627
+ async function* resolveAskAction(conversationId, call) {
1628
+ yield {
1629
+ type: "permission_request",
1630
+ data: { tool: call.toolId, args: call.parameters }
1631
+ };
1632
+ const decision = await requestApproval(
1633
+ {
1634
+ approvalId: `${conversationId}:${Date.now().toString(36)}:${call.toolId}`,
1635
+ agentId: conversationId,
1636
+ toolName: call.toolId,
1637
+ parameters: call.parameters,
1638
+ created: /* @__PURE__ */ new Date()
1639
+ },
1640
+ 6e4
1641
+ );
1642
+ return decision === "allow" ? "allow" : "deny";
1643
+ }
1644
+ async function runPreToolUseHook(context, data) {
1645
+ if (!hasHooks("PreToolUse")) return { allowed: true };
1646
+ return executeHooks("PreToolUse", context, data);
1647
+ }
1648
+ async function* gateToolCallsWithPreToolUse(context, options, definitionId, conversationId, calls) {
1649
+ const permissionHook = createPermissionPreToolUseHook(options, definitionId);
1650
+ const allowedCalls = [];
1651
+ for (const originalCall of calls) {
1652
+ let call = originalCall;
1653
+ const permissionResult = await permissionHook(context, {
1654
+ toolId: call.toolId,
1655
+ parameters: call.parameters,
1656
+ conversationId
1657
+ });
1658
+ call = applyModifiedCall(call, permissionResult.modified);
1659
+ let { action, reason } = normalizePreToolUseResult(permissionResult);
1660
+ if (action === "ask") {
1661
+ action = yield* resolveAskAction(conversationId, call);
1662
+ reason = action === "deny" ? "Tool approval denied or timed out" : reason;
1663
+ }
1664
+ if (action === "deny") {
1665
+ const errorText = reason ?? "Denied by tool permission";
1666
+ yield {
1667
+ type: "tool",
1668
+ data: {
1669
+ toolId: call.toolId,
1670
+ parameters: call.parameters,
1671
+ parallel: false,
1672
+ result: errorText,
1673
+ isError: true
1674
+ }
1675
+ };
1676
+ await persistDeniedToolResult(context, conversationId, call, errorText);
1677
+ continue;
1678
+ }
1679
+ const hookResult = await runPreToolUseHook(context, {
1680
+ toolId: call.toolId,
1681
+ parameters: call.parameters,
1682
+ conversationId
1683
+ });
1684
+ call = applyModifiedCall(call, hookResult.modified);
1685
+ ({ action, reason } = normalizePreToolUseResult(hookResult));
1686
+ if (action === "ask") {
1687
+ action = yield* resolveAskAction(conversationId, call);
1688
+ reason = action === "deny" ? "Tool approval denied or timed out" : reason;
1689
+ }
1690
+ if (action === "deny") {
1691
+ const errorText = reason ?? "Blocked by PreToolUse hook";
1692
+ yield {
1693
+ type: "tool",
1694
+ data: {
1695
+ toolId: call.toolId,
1696
+ parameters: call.parameters,
1697
+ parallel: false,
1698
+ result: errorText,
1699
+ isError: true
1700
+ }
1701
+ };
1702
+ await persistDeniedToolResult(context, conversationId, call, errorText);
1703
+ continue;
1704
+ }
1705
+ allowedCalls.push(call);
1706
+ }
1707
+ return allowedCalls;
1708
+ }
1709
+
1710
+ // src/loopAPI/agent-tool-loop/turnPrimitives.ts
1711
+ var DEFAULT_MAX_ITERATIONS = 256;
1712
+ function toolCallHandledInAgentMessages(agentMessages, assistantContent, call) {
1713
+ let assistantIndex = -1;
1714
+ for (let index = agentMessages.length - 1; index >= 0; index -= 1) {
1715
+ const message = agentMessages[index];
1716
+ if (message.role === "assistant" && message.content === assistantContent) {
1717
+ assistantIndex = index;
1718
+ break;
1719
+ }
1720
+ }
1721
+ if (assistantIndex < 0) return false;
1722
+ const after = agentMessages.slice(assistantIndex + 1);
1723
+ return after.some(
1724
+ (message) => message.role === "tool" && (message.metadata?.toolId === call.toolId || typeof message.content === "string" && message.content.includes(`Tool: ${call.toolId}`))
1725
+ );
1726
+ }
1727
+ function resolveMaxIterations(context) {
1728
+ const configured = context.agentToolLoop?.maxIterations;
1729
+ return configured != null && configured > 0 ? configured : DEFAULT_MAX_ITERATIONS;
1730
+ }
1731
+ function createAgentToolLoopState(context) {
1732
+ return {
1733
+ iteration: 0,
1734
+ maxIterations: resolveMaxIterations(context),
1735
+ recentToolCalls: [],
1736
+ agentStarted: false,
1737
+ agentStopped: false
1738
+ };
1739
+ }
1740
+ function markAgentToolLoopStop(state, reason) {
1741
+ state.stopReason ??= reason;
1742
+ }
1743
+ function finishAgentToolLoopThinking(state, reason, data) {
1744
+ markAgentToolLoopStop(state, reason);
1745
+ return { type: "thinking", data };
1746
+ }
1747
+ async function startAgentToolLoopTurn(context, input, state) {
1748
+ const now = Date.now();
1749
+ const lamportClock = await nextLamportClockForConversation(
1750
+ context.storage,
1751
+ input.conversationId
1752
+ );
1753
+ const hostUserMessage = input.userMessage;
1754
+ const userMessage = context.normalizeMessage?.({
1755
+ ...hostUserMessage,
1756
+ messageId: hostUserMessage?.messageId ?? `${input.conversationId}:${now.toString(36)}`,
1757
+ conversationId: input.conversationId,
1758
+ originNodeId: hostUserMessage?.originNodeId ?? "local",
1759
+ timestamp: hostUserMessage?.timestamp ?? now,
1760
+ lamportClock: hostUserMessage?.lamportClock ?? lamportClock,
1761
+ role: "user",
1762
+ content: hostUserMessage?.content ?? input.message
1763
+ }) ?? {
1764
+ ...hostUserMessage,
1765
+ messageId: hostUserMessage?.messageId ?? `${input.conversationId}:${now.toString(36)}`,
1766
+ conversationId: input.conversationId,
1767
+ originNodeId: hostUserMessage?.originNodeId ?? "local",
1768
+ timestamp: hostUserMessage?.timestamp ?? now,
1769
+ lamportClock: hostUserMessage?.lamportClock ?? lamportClock,
1770
+ role: "user",
1771
+ content: hostUserMessage?.content ?? input.message
1772
+ };
1773
+ if (input.resumeSession && input.resumeSession.length > 0) {
1774
+ await context.storage.insertMessagesIfAbsent(input.resumeSession);
1775
+ }
1776
+ await context.storage.appendMessage(userMessage);
1777
+ if (hasHooks("UserPromptSubmit")) {
1778
+ const hookResult = await executeHooks("UserPromptSubmit", context, {
1779
+ message: input.message,
1780
+ conversationId: input.conversationId
1781
+ });
1782
+ if (!hookResult.allowed) {
1783
+ return {
1784
+ action: "stop",
1785
+ step: {
1786
+ type: "thinking",
1787
+ data: {
1788
+ status: "blocked",
1789
+ conversationId: input.conversationId,
1790
+ reason: hookResult.reason ?? "Blocked by UserPromptSubmit hook"
1791
+ }
1792
+ }
1793
+ };
1794
+ }
1795
+ }
1796
+ const initialDefinitionId = await inferDefinitionId(context.storage, input.conversationId);
1797
+ if (hasHooks("AgentStart")) {
1798
+ const hookResult = await executeHooks("AgentStart", context, {
1799
+ conversationId: input.conversationId,
1800
+ definitionId: initialDefinitionId
1801
+ });
1802
+ if (!hookResult.allowed) {
1803
+ return {
1804
+ action: "stop",
1805
+ step: {
1806
+ type: "thinking",
1807
+ data: {
1808
+ status: "blocked",
1809
+ conversationId: input.conversationId,
1810
+ reason: hookResult.reason ?? "Blocked by AgentStart hook"
1811
+ }
1812
+ }
1813
+ };
1814
+ }
1815
+ }
1816
+ state.agentStarted = true;
1817
+ return { action: "continue" };
1818
+ }
1819
+ async function* runAgentToolLoopIteration(context, input, state) {
1820
+ const options = context.agentToolLoop ?? {};
1821
+ const enableToolLoop = options.enableToolLoop !== false;
1822
+ const fallbackRegistry = options.fallbackRegistryTools !== false;
1823
+ const checkpointOptions = options.sessionCheckpoint;
1824
+ if (state.iteration >= state.maxIterations) {
1825
+ yield finishAgentToolLoopThinking(state, "max-iterations", {
1826
+ status: "max-iterations",
1827
+ conversationId: input.conversationId,
1828
+ maxIterations: state.maxIterations
1829
+ });
1830
+ return { action: "stop", reason: "max-iterations" };
1831
+ }
1832
+ state.iteration += 1;
1833
+ const iteration = state.iteration;
1834
+ if (options.isCancelled?.(input.conversationId)) {
1835
+ yield finishAgentToolLoopThinking(state, "cancelled", {
1836
+ status: "cancelled",
1837
+ conversationId: input.conversationId
1838
+ });
1839
+ return { action: "stop", reason: "cancelled" };
1840
+ }
1841
+ const rawHistory = await context.storage.getMessages(input.conversationId, {
1842
+ mode: "full-content"
1843
+ });
1844
+ const { history, steps: compactionSteps } = await prepareIterationHistory({
1845
+ context,
1846
+ conversationId: input.conversationId,
1847
+ iteration,
1848
+ rawHistory,
1849
+ agentToolLoopOptions: options
1850
+ });
1851
+ for (const step of compactionSteps) {
1852
+ yield step;
1853
+ }
1854
+ const runtimeAgent = context.resolveAgentRuntimeView ? await context.resolveAgentRuntimeView(input.conversationId, history) : { id: input.conversationId, messages: history };
1855
+ const hookContext = {
1856
+ ...context,
1857
+ agent: runtimeAgent,
1858
+ persistAgentMessage: async (message) => {
1859
+ await context.storage.appendMessage(message);
1860
+ }
1861
+ };
1862
+ yield {
1863
+ type: "thinking",
1864
+ data: {
1865
+ status: "calling-llm",
1866
+ conversationId: input.conversationId,
1867
+ messageCount: history.length,
1868
+ iteration
1869
+ }
1870
+ };
1871
+ const messages = await buildLlmMessages(context, input.conversationId, history);
1872
+ const request = { conversationId: input.conversationId, messages };
1873
+ const assistantMessageId = `${input.conversationId}:a:${iteration}:${Date.now().toString(36)}`;
1874
+ const assistantLamportClock = await nextLamportClockForConversation(
1875
+ context.storage,
1876
+ input.conversationId
1877
+ );
1878
+ const buildAssistantMessage = (content) => context.normalizeMessage?.({
1879
+ messageId: assistantMessageId,
1880
+ conversationId: input.conversationId,
1881
+ originNodeId: "local",
1882
+ timestamp: Date.now(),
1883
+ lamportClock: assistantLamportClock,
1884
+ role: "assistant",
1885
+ content
1886
+ }) ?? {
1887
+ messageId: assistantMessageId,
1888
+ conversationId: input.conversationId,
1889
+ originNodeId: "local",
1890
+ timestamp: Date.now(),
1891
+ lamportClock: assistantLamportClock,
1892
+ role: "assistant",
1893
+ content
1894
+ };
1895
+ const updateAssistantView = (message) => {
1896
+ const existingIndex = hookContext.agent.messages.findIndex(
1897
+ (item) => item.messageId === message.messageId
1898
+ );
1899
+ if (existingIndex >= 0) {
1900
+ hookContext.agent.messages[existingIndex] = message;
1901
+ } else {
1902
+ hookContext.agent.messages.push(message);
1903
+ }
1904
+ };
1905
+ let assistantText = "";
1906
+ for await (const chunk of streamLlm(context, request)) {
1907
+ assistantText += chunkToText2(chunk);
1908
+ const transientAssistantMessage = buildAssistantMessage(assistantText);
1909
+ updateAssistantView(transientAssistantMessage);
1910
+ try {
1911
+ await context.onTransientMessage?.(transientAssistantMessage);
1912
+ } catch (error) {
1913
+ context.logger?.warn?.("[agentToolLoop] transient message subscriber failed:", error);
1914
+ }
1915
+ yield { type: "message", data: chunk };
1916
+ }
1917
+ const definitionId = await inferDefinitionId(context.storage, input.conversationId);
1918
+ const agentDefinition = await resolveAgentDefinitionModel(context, definitionId);
1919
+ const frameworkConfig = agentDefinition?.agentFrameworkConfig;
1920
+ const hasPlugins = Boolean(
1921
+ frameworkConfig?.plugins && Array.isArray(frameworkConfig.plugins) && frameworkConfig.plugins.length > 0
1922
+ );
1923
+ const assistantMessage = buildAssistantMessage(assistantText);
1924
+ updateAssistantView(assistantMessage);
1925
+ await hookContext.persistAgentMessage?.(assistantMessage);
1926
+ const { calls, parallel } = matchAllToolCallings(assistantText);
1927
+ if (hasPlugins && frameworkConfig) {
1928
+ const { hooks } = await createHooksWithPlugins(
1929
+ frameworkConfig,
1930
+ {
1931
+ pluginRegistry: resolvePromptPluginMap(context)
1932
+ }
1933
+ );
1934
+ const responseCompletePayload = {
1935
+ agentFrameworkContext: hookContext,
1936
+ response: { status: "done", content: assistantText },
1937
+ agentFrameworkConfig: frameworkConfig,
1938
+ requestId: void 0,
1939
+ toolConfig: { id: "_memeloop", toolId: "_memeloop" },
1940
+ actions: {}
1941
+ };
1942
+ await runResponseCompleteHooks(hooks, responseCompletePayload);
1943
+ await context.storage.insertMessagesIfAbsent(hookContext.agent.messages);
1944
+ const postProcess = await responseConcat(
1945
+ frameworkConfig,
1946
+ assistantText,
1947
+ hookContext,
1948
+ hookContext.agent.messages
1949
+ );
1950
+ const yieldTarget = responseCompletePayload.actions?.yieldNextRoundTo ?? postProcess.yieldNextRoundTo;
1951
+ if (yieldTarget === "human") {
1952
+ yield finishAgentToolLoopThinking(state, "completed", {
1953
+ status: "input-required",
1954
+ conversationId: input.conversationId
1955
+ });
1956
+ return { action: "stop", reason: "completed" };
1957
+ }
1958
+ if (yieldTarget === "self") {
1959
+ return { action: "continue" };
1960
+ }
1961
+ }
1962
+ if (calls.length === 0) {
1963
+ markAgentToolLoopStop(state, "completed");
1964
+ return { action: "stop", reason: "completed" };
1965
+ }
1966
+ if (!enableToolLoop) {
1967
+ markAgentToolLoopStop(state, "completed");
1968
+ return { action: "stop", reason: "completed" };
1969
+ }
1970
+ const pending = calls.filter(
1971
+ (call) => !toolCallHandledInAgentMessages(hookContext.agent.messages, assistantText, call)
1972
+ );
1973
+ if (pending.length === 0) {
1974
+ if (hasPlugins && calls.length > 0) {
1975
+ return { action: "continue" };
1976
+ }
1977
+ markAgentToolLoopStop(state, "completed");
1978
+ return { action: "stop", reason: "completed" };
1979
+ }
1980
+ if (!fallbackRegistry && hasPlugins) {
1981
+ return { action: "continue" };
1982
+ }
1983
+ const allowedCalls = yield* gateToolCallsWithPreToolUse(
1984
+ context,
1985
+ options,
1986
+ definitionId,
1987
+ input.conversationId,
1988
+ pending
1989
+ );
1990
+ if (allowedCalls.length === 0) {
1991
+ return { action: "continue" };
1992
+ }
1993
+ yield* runRegistryToolCalls({
1994
+ context,
1995
+ agentToolLoopOptions: options,
1996
+ conversationId: input.conversationId,
1997
+ calls: allowedCalls,
1998
+ parallel,
1999
+ recentToolCalls: state.recentToolCalls
2000
+ });
2001
+ if (checkpointOptions?.enabled) {
2002
+ const checkpointStore = checkpointOptions.store;
2003
+ if (!checkpointStore) {
2004
+ if (context.logger?.warn) {
2005
+ context.logger.warn("[agentToolLoop] checkpoint enabled without a checkpoint store");
2006
+ } else {
2007
+ console.warn("[agentToolLoop] checkpoint enabled without a checkpoint store");
2008
+ }
2009
+ return { action: "continue" };
2010
+ }
2011
+ try {
2012
+ const allMessages = await context.storage.getMessages(input.conversationId, {
2013
+ mode: "full-content"
2014
+ });
2015
+ await checkpointStore.saveCheckpoint(input.conversationId, allMessages);
2016
+ } catch (error) {
2017
+ if (context.logger?.warn) {
2018
+ context.logger.warn("[agentToolLoop] checkpoint save failed:", error);
2019
+ } else {
2020
+ console.warn("[agentToolLoop] checkpoint save failed:", error);
2021
+ }
2022
+ }
2023
+ }
2024
+ return { action: "continue" };
2025
+ }
2026
+ async function stopAgentToolLoopTurn(context, input, state, reason) {
2027
+ if (reason) markAgentToolLoopStop(state, reason);
2028
+ if (state.agentStarted && !state.agentStopped && state.stopReason && hasHooks("AgentStop")) {
2029
+ state.agentStopped = true;
2030
+ await executeHooks("AgentStop", context, {
2031
+ conversationId: input.conversationId,
2032
+ reason: state.stopReason
2033
+ });
2034
+ }
2035
+ }
2036
+
2037
+ // src/loopAPI/agent-tool-loop/directRunner.ts
2038
+ function createAgentToolLoopRunner(context) {
2039
+ return async function* agentToolLoopRunner(input) {
2040
+ const state = createAgentToolLoopState(context);
2041
+ try {
2042
+ const start = await startAgentToolLoopTurn(context, input, state);
2043
+ if (start.step) yield start.step;
2044
+ if (start.action === "stop") return;
2045
+ while (true) {
2046
+ const result = yield* runAgentToolLoopIteration(context, input, state);
2047
+ if (result.action === "stop") return;
2048
+ }
2049
+ } catch (error) {
2050
+ await stopAgentToolLoopTurn(context, input, state, "error");
2051
+ throw error;
2052
+ } finally {
2053
+ await stopAgentToolLoopTurn(context, input, state);
2054
+ }
2055
+ };
2056
+ }
2057
+
2058
+ // src/loopAPI/registry.ts
2059
+ function normalizePluginSelections(selected) {
2060
+ if (!selected) return void 0;
2061
+ const result = /* @__PURE__ */ new Map();
2062
+ for (const entry of selected) {
2063
+ if (typeof entry === "string") {
2064
+ result.set(entry, { id: entry, enabled: true });
2065
+ continue;
2066
+ }
2067
+ if (entry.enabled === false) continue;
2068
+ result.set(entry.id, entry);
2069
+ }
2070
+ return result;
2071
+ }
2072
+ var LoopRegistryImpl = class {
2073
+ loops = /* @__PURE__ */ new Map();
2074
+ profiles = /* @__PURE__ */ new Map();
2075
+ plugins = /* @__PURE__ */ new Map();
2076
+ // ── Loop registration ──
2077
+ registerLoop(definition) {
2078
+ if (!definition.id) throw new Error("Loop definition must have an id");
2079
+ this.loops.set(definition.id, definition);
2080
+ }
2081
+ getLoop(id) {
2082
+ return this.loops.get(id);
2083
+ }
2084
+ listLoops() {
2085
+ return Array.from(this.loops.values());
2086
+ }
2087
+ // ── Profile registration ──
2088
+ registerProfile(profile) {
2089
+ if (!profile.id) throw new Error("Loop profile must have an id");
2090
+ this.profiles.set(profile.id, profile);
2091
+ }
2092
+ getProfile(id) {
2093
+ return this.profiles.get(id);
2094
+ }
2095
+ listProfiles() {
2096
+ return Array.from(this.profiles.values());
2097
+ }
2098
+ // ── Plugin registration ──
2099
+ registerPlugin(plugin) {
2100
+ if (!plugin.id) throw new Error("Loop plugin must have an id");
2101
+ this.plugins.set(plugin.id, plugin);
2102
+ }
2103
+ getPlugin(id) {
2104
+ return this.plugins.get(id);
2105
+ }
2106
+ listPlugins() {
2107
+ return Array.from(this.plugins.values());
2108
+ }
2109
+ installPluginsForLoop(loopId, target, selected) {
2110
+ const selectedEntries = normalizePluginSelections(selected);
2111
+ for (const plugin of this.plugins.values()) {
2112
+ const entry = selectedEntries?.get(plugin.id);
2113
+ if (selectedEntries && !entry) continue;
2114
+ if (plugin.targetLoopId && plugin.targetLoopId !== "*" && plugin.targetLoopId !== loopId) {
2115
+ continue;
2116
+ }
2117
+ if (plugin.install) {
2118
+ plugin.install(target, entry?.config);
2119
+ }
2120
+ }
2121
+ }
2122
+ installPluginsForProfile(profile, target) {
2123
+ this.installPluginsForLoop(profile.loopId ?? "agent-tool-loop", target, profile.plugins ?? []);
2124
+ }
2125
+ createRunnerForProfile(profile, context = {}) {
2126
+ const loopId = profile.loopId ?? "agent-tool-loop";
2127
+ this.installPluginsForProfile(profile, context);
2128
+ return this.createRunner(loopId, { ...context, profile });
2129
+ }
2130
+ // ── Lifecycle ──
2131
+ createRunner(loopId, context = {}) {
2132
+ const definition = this.loops.get(loopId);
2133
+ if (!definition) return null;
2134
+ return definition.createRunner(context);
2135
+ }
2136
+ reset() {
2137
+ this.loops.clear();
2138
+ this.profiles.clear();
2139
+ this.plugins.clear();
2140
+ }
2141
+ };
2142
+ var defaultRegistry = null;
2143
+ function getLoopRegistry() {
2144
+ if (!defaultRegistry) {
2145
+ defaultRegistry = new LoopRegistryImpl();
2146
+ }
2147
+ return defaultRegistry;
2148
+ }
2149
+ function resetLoopRegistry() {
2150
+ if (defaultRegistry) {
2151
+ defaultRegistry.reset();
2152
+ }
2153
+ defaultRegistry = null;
2154
+ }
2155
+
2156
+ // src/loopProfiles/builtinProfileSources.ts
2157
+ var builtinProfileSources = {
2158
+ "code-assistant": [
2159
+ "{",
2160
+ ' "id": "memeloop:code-assistant",',
2161
+ ' "name": "\u4EE3\u7801\u52A9\u624B",',
2162
+ ' "description": "\u4E13\u6CE8\u4E8E\u4EE3\u7801\u7F16\u5199\u3001\u91CD\u6784\u548C\u8C03\u8BD5\u7684\u52A9\u624B\u3002",',
2163
+ ' "loopId": "agent-tool-loop",',
2164
+ ' "systemPrompt": "You are a senior software engineer helping the user write and refactor code.",',
2165
+ ' "tools": [',
2166
+ ' "workspacesList",',
2167
+ ' "modelContextProtocol",',
2168
+ ' "spawnAgent",',
2169
+ ' "askQuestion",',
2170
+ ' "getErrors",',
2171
+ ' "webFetch"',
2172
+ " ],",
2173
+ ' "plugins": [',
2174
+ ' { "id": "builtin:mcp-client" },',
2175
+ ' { "id": "builtin:mcp-forward" },',
2176
+ ' { "id": "builtin:spawn-agent" },',
2177
+ ' { "id": "builtin:ask-question" }',
2178
+ " ],",
2179
+ ' "agentTools": [',
2180
+ " {",
2181
+ ' "toolId": "workspacesList",',
2182
+ ' "parameters": {',
2183
+ ' "workspacesListParam": { "targetId": "builtin-system", "position": "after" }',
2184
+ " }",
2185
+ " },",
2186
+ " {",
2187
+ ' "toolId": "modelContextProtocol",',
2188
+ ' "parameters": {',
2189
+ ' "modelContextProtocolParam": {',
2190
+ ' "serverUrl": "http://127.0.0.1:38385/mcp",',
2191
+ ' "timeoutSecond": 30,',
2192
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" },',
2193
+ ' "toolResultDuration": 1',
2194
+ " }",
2195
+ " }",
2196
+ " },",
2197
+ " {",
2198
+ ' "toolId": "spawnAgent",',
2199
+ ' "parameters": {',
2200
+ ' "spawnAgentParam": {',
2201
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" },',
2202
+ ' "toolResultDuration": 2,',
2203
+ ' "defaultTimeoutMs": 120000',
2204
+ " }",
2205
+ " }",
2206
+ " },",
2207
+ " {",
2208
+ ' "toolId": "askQuestion",',
2209
+ ' "parameters": {',
2210
+ ' "askQuestionParam": {',
2211
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" }',
2212
+ " }",
2213
+ " }",
2214
+ " },",
2215
+ " {",
2216
+ ' "toolId": "getErrors",',
2217
+ ' "parameters": {',
2218
+ ' "getErrorsParam": {',
2219
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" }',
2220
+ " }",
2221
+ " }",
2222
+ " },",
2223
+ " {",
2224
+ ' "toolId": "webFetch",',
2225
+ ' "parameters": {',
2226
+ ' "webFetchParam": {',
2227
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" },',
2228
+ ' "toolResultDuration": 1',
2229
+ " }",
2230
+ " }",
2231
+ " }",
2232
+ " ],",
2233
+ ' "agentFrameworkConfig": {',
2234
+ ' "prompts": [',
2235
+ " {",
2236
+ ' "id": "builtin-system",',
2237
+ ' "role": "system",',
2238
+ ' "text": "You are a senior software engineer helping the user write and refactor code. Prefer small, safe edits; use file.read and file.search before changing code; use terminal.execute for build/tests when appropriate."',
2239
+ " }",
2240
+ " ],",
2241
+ ' "plugins": [{ "toolId": "fullReplacement" }],',
2242
+ ' "response": []',
2243
+ " },",
2244
+ ' "modelConfig": {',
2245
+ ' "provider": "memeloop",',
2246
+ ' "model": "claude-opus-4.6",',
2247
+ ' "temperature": 0.2,',
2248
+ ' "maxTokens": 4096',
2249
+ " },",
2250
+ ' "version": "1.0.0"',
2251
+ "}",
2252
+ ""
2253
+ ].join("\n"),
2254
+ "frontend-ui-ux": [
2255
+ "{",
2256
+ ' "id": "memeloop:frontend-ui-ux",',
2257
+ ' "name": "Frontend UI/UX",',
2258
+ ' "description": "Designer-turned-developer who crafts stunning UI/UX even without design mockups.",',
2259
+ ' "loopId": "agent-tool-loop",',
2260
+ ' "systemPrompt": "You are a designer-turned-developer who crafts stunning UI/UX even without design mockups.\\n\\nWhen working on frontend tasks:\\n- Prioritize visual polish and user experience above all else\\n- Use consistent spacing, typography, and color schemes\\n- Apply modern design patterns: rounded corners, subtle shadows, smooth transitions\\n- Ensure responsive design across mobile, tablet, and desktop breakpoints\\n- Prefer accessible patterns: semantic HTML, ARIA labels, keyboard navigation\\n- Optimize for perceived performance: skeleton loaders, optimistic updates, progressive enhancement\\n- Use component composition over monolithic layouts\\n- Match the existing design system when extending an existing UI",',
2261
+ ' "tools": [',
2262
+ ' "workspacesList",',
2263
+ ' "wikiSearch",',
2264
+ ' "wikiOperation",',
2265
+ ' "modelContextProtocol",',
2266
+ ' "spawnAgent",',
2267
+ ' "askQuestion",',
2268
+ ' "webFetch"',
2269
+ " ],",
2270
+ ' "plugins": [',
2271
+ ' { "id": "builtin:mcp-client" },',
2272
+ ' { "id": "builtin:mcp-forward" },',
2273
+ ' { "id": "builtin:spawn-agent" },',
2274
+ ' { "id": "builtin:ask-question" }',
2275
+ " ],",
2276
+ ' "agentTools": [',
2277
+ " {",
2278
+ ' "toolId": "workspacesList",',
2279
+ ' "parameters": {',
2280
+ ' "workspacesListParam": { "targetId": "builtin-system", "position": "after" }',
2281
+ " }",
2282
+ " },",
2283
+ " {",
2284
+ ' "toolId": "wikiSearch",',
2285
+ ' "parameters": {',
2286
+ ' "wikiSearchParam": {',
2287
+ ' "sourceType": "wiki",',
2288
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" },',
2289
+ ' "toolResultDuration": 1',
2290
+ " }",
2291
+ " }",
2292
+ " },",
2293
+ " {",
2294
+ ' "toolId": "wikiOperation",',
2295
+ ' "parameters": {',
2296
+ ' "wikiOperationParam": {',
2297
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" },',
2298
+ ' "toolResultDuration": 1',
2299
+ " }",
2300
+ " }",
2301
+ " },",
2302
+ " {",
2303
+ ' "toolId": "modelContextProtocol",',
2304
+ ' "parameters": {',
2305
+ ' "modelContextProtocolParam": {',
2306
+ ' "serverUrl": "http://127.0.0.1:38385/mcp",',
2307
+ ' "timeoutSecond": 30,',
2308
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" },',
2309
+ ' "toolResultDuration": 1',
2310
+ " }",
2311
+ " }",
2312
+ " },",
2313
+ " {",
2314
+ ' "toolId": "spawnAgent",',
2315
+ ' "parameters": {',
2316
+ ' "spawnAgentParam": {',
2317
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" },',
2318
+ ' "toolResultDuration": 2,',
2319
+ ' "defaultTimeoutMs": 120000',
2320
+ " }",
2321
+ " }",
2322
+ " },",
2323
+ " {",
2324
+ ' "toolId": "askQuestion",',
2325
+ ' "parameters": {',
2326
+ ' "askQuestionParam": {',
2327
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" }',
2328
+ " }",
2329
+ " }",
2330
+ " },",
2331
+ " {",
2332
+ ' "toolId": "webFetch",',
2333
+ ' "parameters": {',
2334
+ ' "webFetchParam": {',
2335
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" },',
2336
+ ' "toolResultDuration": 1',
2337
+ " }",
2338
+ " }",
2339
+ " }",
2340
+ " ],",
2341
+ ' "agentFrameworkConfig": {',
2342
+ ' "prompts": [',
2343
+ " {",
2344
+ ' "id": "builtin-system",',
2345
+ ' "role": "system",',
2346
+ ' "text": "You are a designer-turned-developer who crafts stunning UI/UX even without design mockups.\\n\\nWhen working on frontend tasks:\\n- Prioritize visual polish and user experience above all else\\n- Use consistent spacing, typography, and color schemes\\n- Apply modern design patterns: rounded corners, subtle shadows, smooth transitions\\n- Ensure responsive design across mobile, tablet, and desktop breakpoints\\n- Prefer accessible patterns: semantic HTML, ARIA labels, keyboard navigation\\n- Optimize for perceived performance: skeleton loaders, optimistic updates, progressive enhancement\\n- Use component composition over monolithic layouts\\n- Match the existing design system when extending an existing UI"',
2347
+ " }",
2348
+ " ],",
2349
+ ' "plugins": [],',
2350
+ ' "response": []',
2351
+ " },",
2352
+ ' "modelConfig": {',
2353
+ ' "provider": "memeloop",',
2354
+ ' "model": "claude-opus-4.6",',
2355
+ ' "temperature": 0.3,',
2356
+ ' "maxTokens": 4096',
2357
+ " },",
2358
+ ' "version": "1.0.0"',
2359
+ "}",
2360
+ ""
2361
+ ].join("\n"),
2362
+ "general-assistant": [
2363
+ "{",
2364
+ ' "id": "memeloop:general-assistant",',
2365
+ ' "name": "\u901A\u7528\u52A9\u624B",',
2366
+ ' "description": "\u901A\u7528\u81EA\u7136\u8BED\u8A00\u52A9\u7406\uFF0C\u7528\u4E8E\u65E5\u5E38\u95EE\u7B54\u548C\u7B80\u5355\u4EFB\u52A1\u3002",',
2367
+ ' "loopId": "agent-tool-loop",',
2368
+ ' "systemPrompt": "You are a helpful general-purpose assistant. When you need to use a tool, output ONLY the tool call in this exact XML format:\\n<tool_use name=\\"TOOL_NAME\\">{\\"param\\":\\"value\\"}</tool_use>\\nNever wrap tool calls in markdown code blocks or add explanatory text before/after the tool call in the same message. After receiving the tool result, continue responding normally.",',
2369
+ ' "tools": [',
2370
+ ' "workspacesList",',
2371
+ ' "wikiSearch",',
2372
+ ' "wikiOperation",',
2373
+ ' "modelContextProtocol",',
2374
+ ' "spawnAgent",',
2375
+ ' "askQuestion"',
2376
+ " ],",
2377
+ ' "plugins": [',
2378
+ ' { "id": "builtin:mcp-client" },',
2379
+ ' { "id": "builtin:mcp-forward" },',
2380
+ ' { "id": "builtin:spawn-agent" },',
2381
+ ' { "id": "builtin:ask-question" }',
2382
+ " ],",
2383
+ ' "agentTools": [',
2384
+ " {",
2385
+ ' "toolId": "workspacesList",',
2386
+ ' "parameters": {',
2387
+ ' "workspacesListParam": { "targetId": "builtin-system", "position": "after" }',
2388
+ " }",
2389
+ " },",
2390
+ " {",
2391
+ ' "toolId": "wikiSearch",',
2392
+ ' "parameters": {',
2393
+ ' "wikiSearchParam": {',
2394
+ ' "sourceType": "wiki",',
2395
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" },',
2396
+ ' "toolResultDuration": 1',
2397
+ " }",
2398
+ " }",
2399
+ " },",
2400
+ " {",
2401
+ ' "toolId": "wikiOperation",',
2402
+ ' "parameters": {',
2403
+ ' "wikiOperationParam": {',
2404
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" },',
2405
+ ' "toolResultDuration": 1',
2406
+ " }",
2407
+ " }",
2408
+ " },",
2409
+ " {",
2410
+ ' "toolId": "modelContextProtocol",',
2411
+ ' "parameters": {',
2412
+ ' "modelContextProtocolParam": {',
2413
+ ' "serverUrl": "http://127.0.0.1:38385/mcp",',
2414
+ ' "timeoutSecond": 30,',
2415
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" },',
2416
+ ' "toolResultDuration": 1',
2417
+ " }",
2418
+ " }",
2419
+ " },",
2420
+ " {",
2421
+ ' "toolId": "spawnAgent",',
2422
+ ' "parameters": {',
2423
+ ' "spawnAgentParam": {',
2424
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" },',
2425
+ ' "toolResultDuration": 2,',
2426
+ ' "defaultTimeoutMs": 120000',
2427
+ " }",
2428
+ " }",
2429
+ " },",
2430
+ " {",
2431
+ ' "toolId": "askQuestion",',
2432
+ ' "parameters": {',
2433
+ ' "askQuestionParam": {',
2434
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" }',
2435
+ " }",
2436
+ " }",
2437
+ " }",
2438
+ " ],",
2439
+ ' "agentFrameworkConfig": {',
2440
+ ' "prompts": [',
2441
+ " {",
2442
+ ' "id": "builtin-system",',
2443
+ ' "role": "system",',
2444
+ ' "text": "You are a helpful general-purpose assistant. When you need to use a tool, output ONLY the tool call in this exact XML format:\\n<tool_use name=\\"TOOL_NAME\\">{\\"param\\":\\"value\\"}</tool_use>\\nNever wrap tool calls in markdown code blocks or add explanatory text before/after the tool call in the same message. After receiving the tool result, continue responding normally."',
2445
+ " }",
2446
+ " ],",
2447
+ ' "plugins": [{ "toolId": "fullReplacement" }],',
2448
+ ' "response": []',
2449
+ " },",
2450
+ ' "modelConfig": {',
2451
+ ' "provider": "memeloop",',
2452
+ ' "model": "claude-opus-4.6",',
2453
+ ' "temperature": 0.5,',
2454
+ ' "maxTokens": 4096',
2455
+ " },",
2456
+ ' "version": "1.0.0"',
2457
+ "}",
2458
+ ""
2459
+ ].join("\n"),
2460
+ "git-master": [
2461
+ "{",
2462
+ ' "id": "memeloop:git-master",',
2463
+ ' "name": "Git Master",',
2464
+ ' "description": "Expert git workflow management with safety-first approach.",',
2465
+ ' "loopId": "agent-tool-loop",',
2466
+ ' "systemPrompt": "You are an expert in git workflow management. Follow these rules:\\n\\nGit Safety Protocol:\\n- NEVER update the git config\\n- NEVER run destructive/irreversible git commands (push --force, hard reset, etc.) unless the user explicitly requests them\\n- NEVER skip hooks (--no-verify, --no-gpg-sign, etc.) unless the user explicitly requests it\\n- NEVER force push to main/master; warn the user if they request it\\n- Avoid git commit --amend. ONLY use --amend when ALL conditions are met:\\n (1) User explicitly requested amend, OR the commit succeeded and pre-commit hooks auto-modified files that need including\\n (2) HEAD commit was created by you in this conversation\\n (3) Commit has NOT been pushed to remote\\n- If commit FAILED or was REJECTED by hook, NEVER amend \u2014 fix the issue and create a NEW commit\\n- If you already pushed to remote, NEVER amend unless user explicitly requests it (requires force push)\\n\\nCommitting:\\n- NEVER commit changes unless the user explicitly asks\\n- Run: git status, git diff, git log (recent commits)\\n- Analyze all staged changes and draft a concise commit message\\n- Summarize nature of changes: add/update/fix/refactor/test/docs\\n- Do NOT commit files that likely contain secrets\\n\\nPull Requests:\\n- Check branch status, divergence from base, full commit history\\n- Create PR with descriptive title and summary body\\n- Return the PR URL when done",',
2467
+ ' "tools": ["workspacesList", "git", "askQuestion"],',
2468
+ ' "plugins": [{ "id": "builtin:ask-question" }],',
2469
+ ' "agentTools": [',
2470
+ " {",
2471
+ ' "toolId": "workspacesList",',
2472
+ ' "parameters": {',
2473
+ ' "workspacesListParam": { "targetId": "builtin-system", "position": "after" }',
2474
+ " }",
2475
+ " },",
2476
+ " {",
2477
+ ' "toolId": "git",',
2478
+ ' "parameters": {',
2479
+ ' "gitParam": {',
2480
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" }',
2481
+ " }",
2482
+ " }",
2483
+ " },",
2484
+ " {",
2485
+ ' "toolId": "askQuestion",',
2486
+ ' "parameters": {',
2487
+ ' "askQuestionParam": {',
2488
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" }',
2489
+ " }",
2490
+ " }",
2491
+ " }",
2492
+ " ],",
2493
+ ' "agentFrameworkConfig": {',
2494
+ ' "prompts": [',
2495
+ " {",
2496
+ ' "id": "builtin-system",',
2497
+ ' "role": "system",',
2498
+ ' "text": "You are an expert in git workflow management. Follow these rules:\\n\\nGit Safety Protocol:\\n- NEVER update the git config\\n- NEVER run destructive/irreversible git commands (push --force, hard reset, etc.) unless the user explicitly requests them\\n- NEVER skip hooks (--no-verify, --no-gpg-sign, etc.) unless the user explicitly requests it\\n- NEVER force push to main/master; warn the user if they request it\\n- Avoid git commit --amend. ONLY use --amend when ALL conditions are met:\\n (1) User explicitly requested amend, OR the commit succeeded and pre-commit hooks auto-modified files that need including\\n (2) HEAD commit was created by you in this conversation\\n (3) Commit has NOT been pushed to remote\\n- If commit FAILED or was REJECTED by hook, NEVER amend \u2014 fix the issue and create a NEW commit\\n- If you already pushed to remote, NEVER amend unless user explicitly requests it (requires force push)\\n\\nCommitting:\\n- NEVER commit changes unless the user explicitly asks\\n- Run: git status, git diff, git log (recent commits)\\n- Analyze all staged changes and draft a concise commit message\\n- Summarize nature of changes: add/update/fix/refactor/test/docs\\n- Do NOT commit files that likely contain secrets\\n\\nPull Requests:\\n- Check branch status, divergence from base, full commit history\\n- Create PR with descriptive title and summary body\\n- Return the PR URL when done"',
2499
+ " }",
2500
+ " ],",
2501
+ ' "plugins": [],',
2502
+ ' "response": []',
2503
+ " },",
2504
+ ' "modelConfig": {',
2505
+ ' "provider": "memeloop",',
2506
+ ' "model": "claude-opus-4.6",',
2507
+ ' "temperature": 0.2,',
2508
+ ' "maxTokens": 4096',
2509
+ " },",
2510
+ ' "version": "1.0.0"',
2511
+ "}",
2512
+ ""
2513
+ ].join("\n"),
2514
+ playwright: [
2515
+ "{",
2516
+ ' "id": "memeloop:playwright",',
2517
+ ' "name": "Playwright",',
2518
+ ' "description": "Browser automation via Playwright for verification, browsing, information gathering, web scraping, testing, and screenshots.",',
2519
+ ' "loopId": "agent-tool-loop",',
2520
+ ' "systemPrompt": "You have access to Playwright for browser automation. Use it for:\\n\\nBrowser Automation:\\n- Navigate to URLs and verify page content\\n- Fill forms, click buttons, and interact with page elements\\n- Take screenshots of specific elements or full pages\\n- Extract data from web pages (scraping)\\n- Test web application functionality end-to-end\\n- Automate browser workflows\\n- Log into websites and maintain sessions\\n\\nBest Practices:\\n- Use specific selectors (data-testid, id, or unique CSS selectors) over fragile XPath\\n- Wait for elements to be visible before interacting\\n- Handle page navigation and loading states explicitly\\n- Take screenshots at key steps for debugging\\n- Clean up browser resources when done\\n- Handle timeouts and error states gracefully\\n\\nAvailable Playwright MCP Tools:\\n- browser_navigate: Navigate to a URL\\n- browser_click: Click an element\\n- browser_type: Type into an input field\\n- browser_snapshot: Take accessibility snapshot of page\\n- browser_take_screenshot: Capture screenshot\\n- browser_fill_form: Fill multiple form fields at once\\n- browser_evaluate: Execute JavaScript in page context\\n- browser_select_option: Select from dropdown\\n- browser_drag: Drag and drop elements\\n- browser_hover: Hover over an element\\n- browser_press_key: Press a keyboard key\\n- browser_handle_dialog: Handle browser dialogs (alert/confirm/prompt)\\n- browser_close: Close the browser",',
2521
+ ' "tools": ["modelContextProtocol", "askQuestion"],',
2522
+ ' "plugins": [',
2523
+ ' { "id": "builtin:mcp-client" },',
2524
+ ' { "id": "builtin:mcp-forward" },',
2525
+ ' { "id": "builtin:ask-question" }',
2526
+ " ],",
2527
+ ' "agentTools": [',
2528
+ " {",
2529
+ ' "toolId": "modelContextProtocol",',
2530
+ ' "parameters": {',
2531
+ ' "modelContextProtocolParam": {',
2532
+ ' "serverUrl": "http://127.0.0.1:38385/mcp",',
2533
+ ' "timeoutSecond": 30,',
2534
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" },',
2535
+ ' "toolResultDuration": 1',
2536
+ " }",
2537
+ " }",
2538
+ " },",
2539
+ " {",
2540
+ ' "toolId": "askQuestion",',
2541
+ ' "parameters": {',
2542
+ ' "askQuestionParam": {',
2543
+ ' "toolListPosition": { "targetId": "builtin-system", "position": "after" }',
2544
+ " }",
2545
+ " }",
2546
+ " }",
2547
+ " ],",
2548
+ ' "agentFrameworkConfig": {',
2549
+ ' "prompts": [',
2550
+ " {",
2551
+ ' "id": "builtin-system",',
2552
+ ' "role": "system",',
2553
+ ' "text": "You have access to Playwright for browser automation. Use it for:\\n\\nBrowser Automation:\\n- Navigate to URLs and verify page content\\n- Fill forms, click buttons, and interact with page elements\\n- Take screenshots of specific elements or full pages\\n- Extract data from web pages (scraping)\\n- Test web application functionality end-to-end\\n- Automate browser workflows\\n- Log into websites and maintain sessions\\n\\nBest Practices:\\n- Use specific selectors (data-testid, id, or unique CSS selectors) over fragile XPath\\n- Wait for elements to be visible before interacting\\n- Handle page navigation and loading states explicitly\\n- Take screenshots at key steps for debugging\\n- Clean up browser resources when done\\n- Handle timeouts and error states gracefully\\n\\nAvailable Playwright MCP Tools:\\n- browser_navigate: Navigate to a URL\\n- browser_click: Click an element\\n- browser_type: Type into an input field\\n- browser_snapshot: Take accessibility snapshot of page\\n- browser_take_screenshot: Capture screenshot\\n- browser_fill_form: Fill multiple form fields at once\\n- browser_evaluate: Execute JavaScript in page context\\n- browser_select_option: Select from dropdown\\n- browser_drag: Drag and drop elements\\n- browser_hover: Hover over an element\\n- browser_press_key: Press a keyboard key\\n- browser_handle_dialog: Handle browser dialogs (alert/confirm/prompt)\\n- browser_close: Close the browser"',
2554
+ " }",
2555
+ " ],",
2556
+ ' "plugins": [],',
2557
+ ' "response": []',
2558
+ " },",
2559
+ ' "modelConfig": {',
2560
+ ' "provider": "memeloop",',
2561
+ ' "model": "claude-opus-4.6",',
2562
+ ' "temperature": 0.3,',
2563
+ ' "maxTokens": 4096',
2564
+ " },",
2565
+ ' "version": "1.0.0"',
2566
+ "}",
2567
+ ""
2568
+ ].join("\n")
2569
+ };
2570
+
2571
+ // src/loopProfiles/loadBuiltins.ts
2572
+ function loadProfile(name) {
2573
+ const source = builtinProfileSources[name];
2574
+ if (!source) {
2575
+ throw new Error(`Builtin profile not found: ${name}`);
2576
+ }
2577
+ return JSON.parse(source);
2578
+ }
2579
+ function getBuiltinLoopProfiles() {
2580
+ return [
2581
+ loadProfile("general-assistant"),
2582
+ loadProfile("code-assistant"),
2583
+ loadProfile("frontend-ui-ux"),
2584
+ loadProfile("git-master"),
2585
+ loadProfile("playwright")
2586
+ ];
2587
+ }
2588
+ function getBuiltinLoopProfile(id) {
2589
+ return getBuiltinLoopProfiles().find((p) => p.id === id);
2590
+ }
2591
+ function registerBuiltinLoopProfiles() {
2592
+ const registry = getLoopRegistry();
2593
+ for (const profile of getBuiltinLoopProfiles()) {
2594
+ registry.registerProfile(profile);
2595
+ }
2596
+ }
2597
+
2598
+ export {
2599
+ matchPattern,
2600
+ mergePermissionSets,
2601
+ checkPermission,
2602
+ defaultAdmissionPolicyForTrustClass,
2603
+ resolveAdmissionPolicy,
2604
+ defaultPermissionActionForTrustClass,
2605
+ evaluateToolAdmission,
2606
+ TOOL_OPERATION_CONDITION_EFFECT_UNKNOWN,
2607
+ reconcileUnknownEffect,
2608
+ applyUnknownEffectDecision,
2609
+ pluginRegistry,
2610
+ getActivePluginRegistry,
2611
+ runWithPluginRegistry,
2612
+ createAgentFrameworkHooks,
2613
+ runProcessPromptsHooks,
2614
+ runResponseCompleteHooks,
2615
+ runPostProcessHooks,
2616
+ runToolExecutedHooks,
2617
+ resolvePromptPluginMap,
2618
+ createHooksWithPlugins,
2619
+ matchToolCalling,
2620
+ matchAllToolCallings,
2621
+ nextLamportClockForConversation,
2622
+ HookRegistry,
2623
+ getDefaultHookRegistry,
2624
+ registerHook,
2625
+ unregisterHook,
2626
+ executeHooks,
2627
+ hasHooks,
2628
+ clearHooks,
2629
+ listRegisteredHookTypes,
2630
+ getHookCount,
2631
+ compactMessages,
2632
+ shouldCompact,
2633
+ autoCompact,
2634
+ findPromptById,
2635
+ flattenPrompts,
2636
+ promptConcatStream,
2637
+ MEMELOOP_STRUCTURED_TOOL_KEY,
2638
+ truncateToolSummary,
2639
+ extractMemeloopStructuredToolPayload,
2640
+ onApprovalRequest,
2641
+ evaluateApproval,
2642
+ requestApproval,
2643
+ resolveApproval,
2644
+ getPendingApprovals,
2645
+ cancelPendingApprovals,
2646
+ createAgentToolLoopState,
2647
+ startAgentToolLoopTurn,
2648
+ runAgentToolLoopIteration,
2649
+ stopAgentToolLoopTurn,
2650
+ createAgentToolLoopRunner,
2651
+ getLoopRegistry,
2652
+ resetLoopRegistry,
2653
+ getBuiltinLoopProfiles,
2654
+ getBuiltinLoopProfile,
2655
+ registerBuiltinLoopProfiles
2656
+ };
2657
+ //# sourceMappingURL=chunk-QFHAAIIM.js.map