@pikku/core 0.11.1 → 0.12.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 (363) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/crypto-utils.d.ts +2 -0
  3. package/dist/crypto-utils.js +78 -0
  4. package/dist/errors/error-handler.js +3 -3
  5. package/dist/errors/errors.d.ts +8 -0
  6. package/dist/errors/errors.js +16 -0
  7. package/dist/errors/index.d.ts +0 -1
  8. package/dist/errors/index.js +0 -1
  9. package/dist/function/function-runner.d.ts +10 -3
  10. package/dist/function/function-runner.js +136 -31
  11. package/dist/function/functions.types.d.ts +35 -12
  12. package/dist/function/functions.types.js +16 -6
  13. package/dist/function/index.d.ts +2 -2
  14. package/dist/function/index.js +1 -2
  15. package/dist/handle-error.js +1 -10
  16. package/dist/index.d.ts +30 -24
  17. package/dist/index.js +19 -27
  18. package/dist/middleware/auth-apikey.d.ts +1 -1
  19. package/dist/middleware/auth-apikey.js +3 -3
  20. package/dist/middleware/auth-bearer.d.ts +1 -1
  21. package/dist/middleware/auth-bearer.js +3 -6
  22. package/dist/middleware/auth-cookie.d.ts +1 -1
  23. package/dist/middleware/auth-cookie.js +6 -8
  24. package/dist/middleware/cors.d.ts +46 -0
  25. package/dist/middleware/cors.js +73 -0
  26. package/dist/middleware/index.d.ts +5 -3
  27. package/dist/middleware/index.js +5 -3
  28. package/dist/middleware/remote-auth.d.ts +5 -0
  29. package/dist/middleware/remote-auth.js +55 -0
  30. package/dist/middleware/timeout.d.ts +1 -1
  31. package/dist/middleware-runner.d.ts +3 -14
  32. package/dist/middleware-runner.js +14 -16
  33. package/dist/permissions.d.ts +3 -86
  34. package/dist/permissions.js +20 -80
  35. package/dist/pikku-state.d.ts +33 -104
  36. package/dist/pikku-state.js +150 -66
  37. package/dist/schema.d.ts +8 -6
  38. package/dist/schema.js +31 -18
  39. package/dist/services/ai-agent-runner-service.d.ts +24 -0
  40. package/dist/services/ai-agent-runner-service.js +1 -0
  41. package/dist/services/ai-run-state-service.d.ts +13 -0
  42. package/dist/services/ai-run-state-service.js +1 -0
  43. package/dist/services/ai-storage-service.d.ts +18 -0
  44. package/dist/services/ai-storage-service.js +1 -0
  45. package/dist/services/deployment-service.d.ts +19 -0
  46. package/dist/services/deployment-service.js +1 -0
  47. package/dist/services/gopass-secrets.d.ts +47 -0
  48. package/dist/services/gopass-secrets.js +94 -0
  49. package/dist/services/in-memory-trigger-service.d.ts +23 -0
  50. package/dist/services/in-memory-trigger-service.js +50 -0
  51. package/dist/services/in-memory-workflow-service.d.ts +59 -0
  52. package/dist/services/in-memory-workflow-service.js +287 -0
  53. package/dist/services/index.d.ts +25 -11
  54. package/dist/services/index.js +10 -13
  55. package/dist/services/local-secrets.d.ts +23 -0
  56. package/dist/services/local-secrets.js +45 -0
  57. package/dist/services/local-variables.d.ts +5 -0
  58. package/dist/services/local-variables.js +18 -0
  59. package/dist/services/scheduler-service.d.ts +21 -1
  60. package/dist/services/scheduler-service.js +14 -0
  61. package/dist/services/schema-service.d.ts +6 -0
  62. package/dist/services/scoped-secret-service.d.ts +16 -0
  63. package/dist/services/scoped-secret-service.js +35 -0
  64. package/dist/services/secret-service.d.ts +25 -4
  65. package/dist/services/trigger-service.d.ts +23 -0
  66. package/dist/services/trigger-service.js +1 -0
  67. package/dist/services/typed-secret-service.d.ts +30 -0
  68. package/dist/services/typed-secret-service.js +40 -0
  69. package/dist/services/typed-variables-service.d.ts +27 -0
  70. package/dist/services/typed-variables-service.js +46 -0
  71. package/dist/services/user-session-service.d.ts +13 -0
  72. package/dist/services/user-session-service.js +17 -0
  73. package/dist/services/variables-service.d.ts +5 -0
  74. package/dist/services/workflow-service.d.ts +43 -0
  75. package/dist/services/workflow-service.js +1 -0
  76. package/dist/types/core.types.d.ts +54 -10
  77. package/dist/types/core.types.js +7 -0
  78. package/dist/types/state.types.d.ts +127 -0
  79. package/dist/types/state.types.js +1 -0
  80. package/dist/utils.d.ts +10 -1
  81. package/dist/utils.js +60 -3
  82. package/dist/version.d.ts +6 -0
  83. package/dist/version.js +19 -0
  84. package/dist/wirings/ai-agent/ai-agent-memory.d.ts +29 -0
  85. package/dist/wirings/ai-agent/ai-agent-memory.js +199 -0
  86. package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +9 -0
  87. package/dist/wirings/ai-agent/ai-agent-model-config.js +36 -0
  88. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +60 -0
  89. package/dist/wirings/ai-agent/ai-agent-prepare.js +312 -0
  90. package/dist/wirings/ai-agent/ai-agent-registry.d.ts +15 -0
  91. package/dist/wirings/ai-agent/ai-agent-registry.js +47 -0
  92. package/dist/wirings/ai-agent/ai-agent-runner.d.ts +3 -0
  93. package/dist/wirings/ai-agent/ai-agent-runner.js +96 -0
  94. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +11 -0
  95. package/dist/wirings/ai-agent/ai-agent-stream.js +503 -0
  96. package/dist/wirings/ai-agent/ai-agent.types.d.ts +254 -0
  97. package/dist/wirings/ai-agent/ai-agent.types.js +1 -0
  98. package/dist/wirings/ai-agent/index.d.ts +5 -0
  99. package/dist/wirings/ai-agent/index.js +4 -0
  100. package/dist/wirings/channel/channel-common.d.ts +7 -4
  101. package/dist/wirings/channel/channel-common.js +15 -8
  102. package/dist/wirings/channel/channel-handler.js +13 -4
  103. package/dist/wirings/channel/channel-middleware-runner.d.ts +9 -0
  104. package/dist/wirings/channel/channel-middleware-runner.js +73 -0
  105. package/dist/wirings/channel/channel-runner.js +12 -12
  106. package/dist/wirings/channel/channel.types.d.ts +5 -1
  107. package/dist/wirings/channel/define-channel-routes.d.ts +21 -0
  108. package/dist/wirings/channel/define-channel-routes.js +23 -0
  109. package/dist/wirings/channel/index.d.ts +10 -8
  110. package/dist/wirings/channel/index.js +7 -8
  111. package/dist/wirings/channel/local/index.d.ts +3 -3
  112. package/dist/wirings/channel/local/index.js +3 -3
  113. package/dist/wirings/channel/local/local-channel-runner.js +18 -6
  114. package/dist/wirings/channel/log-channels.js +1 -1
  115. package/dist/wirings/channel/serverless/index.d.ts +1 -1
  116. package/dist/wirings/channel/serverless/index.js +1 -1
  117. package/dist/wirings/channel/serverless/serverless-channel-runner.js +17 -6
  118. package/dist/wirings/cli/channel/cli-channel-runner.js +3 -2
  119. package/dist/wirings/cli/channel/index.d.ts +1 -1
  120. package/dist/wirings/cli/channel/index.js +1 -1
  121. package/dist/wirings/cli/cli-runner.d.ts +1 -1
  122. package/dist/wirings/cli/cli-runner.js +22 -18
  123. package/dist/wirings/cli/cli.types.d.ts +7 -6
  124. package/dist/wirings/cli/define-cli-commands.d.ts +19 -0
  125. package/dist/wirings/cli/define-cli-commands.js +20 -0
  126. package/dist/wirings/cli/index.d.ts +2 -3
  127. package/dist/wirings/cli/index.js +1 -3
  128. package/dist/wirings/http/http-routes.d.ts +69 -0
  129. package/dist/wirings/http/http-routes.js +139 -0
  130. package/dist/wirings/http/http-runner.d.ts +2 -2
  131. package/dist/wirings/http/http-runner.js +62 -27
  132. package/dist/wirings/http/http.types.d.ts +77 -24
  133. package/dist/wirings/http/index.d.ts +5 -4
  134. package/dist/wirings/http/index.js +4 -3
  135. package/dist/wirings/http/log-http-routes.js +1 -1
  136. package/dist/wirings/http/routers/path-to-regex.js +2 -2
  137. package/dist/wirings/mcp/index.d.ts +4 -3
  138. package/dist/wirings/mcp/index.js +3 -3
  139. package/dist/wirings/mcp/mcp-runner.d.ts +1 -3
  140. package/dist/wirings/mcp/mcp-runner.js +42 -56
  141. package/dist/wirings/mcp/mcp.types.d.ts +3 -3
  142. package/dist/wirings/node/index.d.ts +2 -0
  143. package/dist/wirings/node/index.js +1 -0
  144. package/dist/wirings/node/node.types.d.ts +20 -0
  145. package/dist/wirings/node/node.types.js +1 -0
  146. package/dist/wirings/oauth2/index.d.ts +3 -0
  147. package/dist/wirings/oauth2/index.js +2 -0
  148. package/dist/wirings/oauth2/oauth2-client.d.ts +47 -0
  149. package/dist/wirings/oauth2/oauth2-client.js +267 -0
  150. package/dist/wirings/oauth2/oauth2.types.d.ts +65 -0
  151. package/dist/wirings/oauth2/oauth2.types.js +4 -0
  152. package/dist/wirings/oauth2/wire-oauth2-credential.d.ts +20 -0
  153. package/dist/wirings/oauth2/wire-oauth2-credential.js +21 -0
  154. package/dist/wirings/queue/index.d.ts +2 -2
  155. package/dist/wirings/queue/index.js +1 -1
  156. package/dist/wirings/queue/queue-runner.d.ts +7 -0
  157. package/dist/wirings/queue/queue-runner.js +23 -12
  158. package/dist/wirings/queue/queue.types.d.ts +8 -2
  159. package/dist/wirings/rpc/index.d.ts +1 -1
  160. package/dist/wirings/rpc/index.js +1 -1
  161. package/dist/wirings/rpc/rpc-runner.d.ts +40 -13
  162. package/dist/wirings/rpc/rpc-runner.js +191 -25
  163. package/dist/wirings/rpc/rpc-types.d.ts +15 -4
  164. package/dist/wirings/scheduler/index.d.ts +3 -3
  165. package/dist/wirings/scheduler/index.js +2 -3
  166. package/dist/wirings/scheduler/log-schedulers.js +1 -1
  167. package/dist/wirings/scheduler/scheduler-runner.d.ts +5 -0
  168. package/dist/wirings/scheduler/scheduler-runner.js +28 -10
  169. package/dist/wirings/secret/index.d.ts +3 -0
  170. package/dist/wirings/secret/index.js +2 -0
  171. package/dist/wirings/secret/secret.types.d.ts +27 -0
  172. package/dist/wirings/secret/secret.types.js +1 -0
  173. package/dist/wirings/secret/validate-secret-definitions.d.ts +6 -0
  174. package/dist/wirings/secret/validate-secret-definitions.js +55 -0
  175. package/dist/wirings/trigger/index.d.ts +3 -0
  176. package/dist/wirings/trigger/index.js +2 -0
  177. package/dist/wirings/trigger/pikku-trigger-service.d.ts +26 -0
  178. package/dist/wirings/trigger/pikku-trigger-service.js +75 -0
  179. package/dist/wirings/trigger/trigger-runner.d.ts +42 -0
  180. package/dist/wirings/trigger/trigger-runner.js +85 -0
  181. package/dist/wirings/trigger/trigger.types.d.ts +130 -0
  182. package/dist/wirings/trigger/trigger.types.js +40 -0
  183. package/dist/wirings/variable/index.d.ts +3 -0
  184. package/dist/wirings/variable/index.js +2 -0
  185. package/dist/wirings/variable/validate-variable-definitions.d.ts +6 -0
  186. package/dist/wirings/variable/validate-variable-definitions.js +45 -0
  187. package/dist/wirings/variable/variable.types.d.ts +18 -0
  188. package/dist/wirings/variable/variable.types.js +1 -0
  189. package/dist/wirings/workflow/dsl/index.d.ts +5 -0
  190. package/dist/wirings/workflow/dsl/index.js +4 -0
  191. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +292 -0
  192. package/dist/wirings/workflow/dsl/workflow-dsl.types.js +5 -0
  193. package/dist/wirings/workflow/dsl/workflow-runner.d.ts +5 -0
  194. package/dist/wirings/workflow/dsl/workflow-runner.js +23 -0
  195. package/dist/wirings/workflow/graph/graph-node.d.ts +117 -0
  196. package/dist/wirings/workflow/graph/graph-node.js +58 -0
  197. package/dist/wirings/workflow/graph/graph-runner.d.ts +9 -0
  198. package/dist/wirings/workflow/graph/graph-runner.js +540 -0
  199. package/dist/wirings/workflow/graph/index.d.ts +4 -0
  200. package/dist/wirings/workflow/graph/index.js +3 -0
  201. package/dist/wirings/workflow/graph/template.d.ts +15 -0
  202. package/dist/wirings/workflow/graph/template.js +27 -0
  203. package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +15 -0
  204. package/dist/wirings/workflow/graph/wire-workflow-graph.js +8 -0
  205. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +82 -0
  206. package/dist/wirings/workflow/graph/workflow-graph.types.js +15 -0
  207. package/dist/wirings/workflow/index.d.ts +7 -12
  208. package/dist/wirings/workflow/index.js +8 -11
  209. package/dist/wirings/workflow/pikku-workflow-service.d.ts +114 -10
  210. package/dist/wirings/workflow/pikku-workflow-service.js +386 -115
  211. package/dist/wirings/workflow/workflow-helpers.d.ts +36 -0
  212. package/dist/wirings/workflow/workflow-helpers.js +38 -0
  213. package/dist/wirings/workflow/workflow-utils.d.ts +1 -0
  214. package/dist/wirings/workflow/workflow-utils.js +1 -0
  215. package/dist/wirings/workflow/workflow.types.d.ts +83 -214
  216. package/package.json +13 -6
  217. package/run-tests.sh +4 -1
  218. package/src/crypto-utils.ts +99 -0
  219. package/src/errors/error-handler.ts +3 -3
  220. package/src/errors/errors.ts +17 -0
  221. package/src/errors/index.ts +0 -1
  222. package/src/factory-functions.test.ts +42 -2
  223. package/src/function/function-runner.test.ts +5 -12
  224. package/src/function/function-runner.ts +195 -40
  225. package/src/function/functions.types.ts +66 -14
  226. package/src/function/index.ts +5 -2
  227. package/src/handle-error.ts +2 -10
  228. package/src/index.ts +106 -27
  229. package/src/middleware/auth-apikey.test.ts +15 -12
  230. package/src/middleware/auth-apikey.ts +3 -3
  231. package/src/middleware/auth-bearer.test.ts +17 -14
  232. package/src/middleware/auth-bearer.ts +25 -27
  233. package/src/middleware/auth-cookie.test.ts +16 -13
  234. package/src/middleware/auth-cookie.ts +6 -8
  235. package/src/middleware/cors.ts +96 -0
  236. package/src/middleware/index.ts +5 -3
  237. package/src/middleware/remote-auth.ts +68 -0
  238. package/src/middleware-runner.test.ts +122 -0
  239. package/src/middleware-runner.ts +24 -17
  240. package/src/permissions.test.ts +102 -86
  241. package/src/permissions.ts +32 -93
  242. package/src/pikku-state.ts +168 -201
  243. package/src/run-tests-script.test.ts +49 -0
  244. package/src/schema.ts +50 -18
  245. package/src/services/ai-agent-runner-service.ts +29 -0
  246. package/src/services/ai-run-state-service.ts +20 -0
  247. package/src/services/ai-storage-service.ts +39 -0
  248. package/src/services/deployment-service.ts +22 -0
  249. package/src/services/gopass-secrets.ts +95 -0
  250. package/src/services/in-memory-trigger-service.ts +68 -0
  251. package/src/services/in-memory-workflow-service.ts +395 -0
  252. package/src/services/index.ts +49 -14
  253. package/src/services/local-secrets.ts +51 -0
  254. package/src/services/local-variables.ts +22 -0
  255. package/src/services/scheduler-service.ts +29 -1
  256. package/src/services/schema-service.ts +7 -0
  257. package/src/services/scoped-secret-service.ts +41 -0
  258. package/src/services/secret-service.ts +25 -4
  259. package/src/services/trigger-service.ts +38 -0
  260. package/src/services/typed-secret-service.ts +70 -0
  261. package/src/services/typed-variables-service.ts +81 -0
  262. package/src/services/user-session-service.ts +23 -0
  263. package/src/services/variables-service.ts +5 -0
  264. package/src/services/workflow-service.ts +94 -0
  265. package/src/types/core.types.ts +82 -8
  266. package/src/types/state.types.ts +169 -0
  267. package/src/utils.ts +74 -5
  268. package/src/version.test.ts +80 -0
  269. package/src/version.ts +25 -0
  270. package/src/wirings/ai-agent/ai-agent-memory.ts +300 -0
  271. package/src/wirings/ai-agent/ai-agent-model-config.ts +43 -0
  272. package/src/wirings/ai-agent/ai-agent-prepare.ts +470 -0
  273. package/src/wirings/ai-agent/ai-agent-registry.test.ts +37 -0
  274. package/src/wirings/ai-agent/ai-agent-registry.ts +82 -0
  275. package/src/wirings/ai-agent/ai-agent-runner.test.ts +75 -0
  276. package/src/wirings/ai-agent/ai-agent-runner.ts +137 -0
  277. package/src/wirings/ai-agent/ai-agent-stream.test.ts +246 -0
  278. package/src/wirings/ai-agent/ai-agent-stream.ts +774 -0
  279. package/src/wirings/ai-agent/ai-agent.types.ts +273 -0
  280. package/src/wirings/ai-agent/index.ts +28 -0
  281. package/src/wirings/channel/channel-common.ts +32 -19
  282. package/src/wirings/channel/channel-handler.ts +18 -5
  283. package/src/wirings/channel/channel-middleware-runner.ts +119 -0
  284. package/src/wirings/channel/channel-runner.ts +14 -15
  285. package/src/wirings/channel/channel.types.ts +17 -1
  286. package/src/wirings/channel/define-channel-routes.ts +25 -0
  287. package/src/wirings/channel/index.ts +23 -8
  288. package/src/wirings/channel/local/index.ts +3 -3
  289. package/src/wirings/channel/local/local-channel-runner.test.ts +47 -2
  290. package/src/wirings/channel/local/local-channel-runner.ts +22 -6
  291. package/src/wirings/channel/log-channels.ts +1 -1
  292. package/src/wirings/channel/serverless/index.ts +5 -1
  293. package/src/wirings/channel/serverless/serverless-channel-runner.ts +22 -6
  294. package/src/wirings/cli/channel/cli-channel-runner.ts +4 -3
  295. package/src/wirings/cli/channel/index.ts +1 -1
  296. package/src/wirings/cli/cli-runner.test.ts +28 -28
  297. package/src/wirings/cli/cli-runner.ts +27 -19
  298. package/src/wirings/cli/cli.types.ts +12 -11
  299. package/src/wirings/cli/command-parser.test.ts +8 -8
  300. package/src/wirings/cli/define-cli-commands.ts +24 -0
  301. package/src/wirings/cli/index.ts +10 -4
  302. package/src/wirings/http/http-routes.test.ts +322 -0
  303. package/src/wirings/http/http-routes.ts +198 -0
  304. package/src/wirings/http/http-runner.test.ts +5 -5
  305. package/src/wirings/http/http-runner.ts +80 -29
  306. package/src/wirings/http/http.types.ts +121 -23
  307. package/src/wirings/http/index.ts +16 -4
  308. package/src/wirings/http/log-http-routes.ts +1 -1
  309. package/src/wirings/http/routers/path-to-regex.test.ts +30 -19
  310. package/src/wirings/http/routers/path-to-regex.ts +2 -2
  311. package/src/wirings/mcp/index.ts +27 -3
  312. package/src/wirings/mcp/mcp-endpoint-registry.test.ts +3 -3
  313. package/src/wirings/mcp/mcp-runner.ts +56 -67
  314. package/src/wirings/mcp/mcp.types.ts +3 -3
  315. package/src/wirings/node/index.ts +2 -0
  316. package/src/wirings/node/node.types.ts +23 -0
  317. package/src/wirings/oauth2/index.ts +3 -0
  318. package/src/wirings/oauth2/oauth2-client.test.ts +929 -0
  319. package/src/wirings/oauth2/oauth2-client.ts +335 -0
  320. package/src/wirings/oauth2/oauth2.types.ts +69 -0
  321. package/src/wirings/oauth2/wire-oauth2-credential.ts +23 -0
  322. package/src/wirings/queue/index.ts +14 -2
  323. package/src/wirings/queue/queue-runner.test.ts +115 -73
  324. package/src/wirings/queue/queue-runner.ts +39 -13
  325. package/src/wirings/queue/queue.types.ts +12 -2
  326. package/src/wirings/rpc/index.ts +1 -1
  327. package/src/wirings/rpc/rpc-runner.ts +270 -34
  328. package/src/wirings/rpc/rpc-types.ts +21 -4
  329. package/src/wirings/scheduler/index.ts +7 -4
  330. package/src/wirings/scheduler/log-schedulers.ts +1 -1
  331. package/src/wirings/scheduler/scheduler-runner.test.ts +97 -53
  332. package/src/wirings/scheduler/scheduler-runner.ts +50 -10
  333. package/src/wirings/secret/index.ts +9 -0
  334. package/src/wirings/secret/secret.types.ts +32 -0
  335. package/src/wirings/secret/validate-secret-definitions.ts +82 -0
  336. package/src/wirings/trigger/index.ts +10 -0
  337. package/src/wirings/trigger/pikku-trigger-service.ts +134 -0
  338. package/src/wirings/trigger/trigger-runner.ts +138 -0
  339. package/src/wirings/trigger/trigger.types.ts +178 -0
  340. package/src/wirings/variable/index.ts +8 -0
  341. package/src/wirings/variable/validate-variable-definitions.ts +69 -0
  342. package/src/wirings/variable/variable.types.ts +22 -0
  343. package/src/wirings/workflow/dsl/index.ts +31 -0
  344. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +320 -0
  345. package/src/wirings/workflow/dsl/workflow-runner.ts +28 -0
  346. package/src/wirings/workflow/graph/graph-node.ts +222 -0
  347. package/src/wirings/workflow/graph/graph-runner.test.ts +495 -0
  348. package/src/wirings/workflow/graph/graph-runner.ts +816 -0
  349. package/src/wirings/workflow/graph/index.ts +14 -0
  350. package/src/wirings/workflow/graph/template.ts +42 -0
  351. package/src/wirings/workflow/graph/wire-workflow-graph.ts +29 -0
  352. package/src/wirings/workflow/graph/workflow-graph.types.ts +104 -0
  353. package/src/wirings/workflow/index.ts +64 -26
  354. package/src/wirings/workflow/pikku-workflow-service.test.ts +212 -0
  355. package/src/wirings/workflow/pikku-workflow-service.ts +571 -136
  356. package/src/wirings/workflow/workflow-helpers.ts +79 -0
  357. package/src/wirings/workflow/workflow-utils.ts +0 -0
  358. package/src/wirings/workflow/workflow.types.ts +123 -279
  359. package/tsconfig.tsbuildinfo +1 -1
  360. package/dist/wirings/workflow/workflow-runner.d.ts +0 -34
  361. package/dist/wirings/workflow/workflow-runner.js +0 -65
  362. package/src/function/function-runner.ts.bak +0 -188
  363. package/src/wirings/workflow/workflow-runner.ts +0 -72
@@ -0,0 +1,169 @@
1
+ import { PikkuError, ErrorDetails } from '../errors/error-handler.js'
2
+ import {
3
+ CorePikkuFunctionConfig,
4
+ CorePermissionGroup,
5
+ CorePikkuPermission,
6
+ } from '../function/functions.types.js'
7
+ import { CorePikkuTriggerFunctionConfig } from '../wirings/trigger/trigger.types.js'
8
+ import { CoreChannel, ChannelsMeta } from '../wirings/channel/channel.types.js'
9
+ import { CLIMeta, CLIProgramState } from '../wirings/cli/cli.types.js'
10
+ import {
11
+ HTTPMethod,
12
+ CoreHTTPFunctionWiring,
13
+ HTTPWiringsMeta,
14
+ } from '../wirings/http/http.types.js'
15
+ import {
16
+ CoreMCPResource,
17
+ MCPResourceMeta,
18
+ MCPToolMeta,
19
+ CoreMCPPrompt,
20
+ MCPPromptMeta,
21
+ } from '../wirings/mcp/mcp.types.js'
22
+ import { CoreAIAgent, AIAgentMeta } from '../wirings/ai-agent/ai-agent.types.js'
23
+ import {
24
+ CoreQueueWorker,
25
+ QueueWorkersMeta,
26
+ } from '../wirings/queue/queue.types.js'
27
+ import {
28
+ CoreScheduledTask,
29
+ ScheduledTasksMeta,
30
+ } from '../wirings/scheduler/scheduler.types.js'
31
+ import {
32
+ CoreWorkflow,
33
+ WorkflowsRuntimeMeta,
34
+ } from '../wirings/workflow/workflow.types.js'
35
+ import {
36
+ CoreTrigger,
37
+ CoreTriggerSource,
38
+ TriggerMeta,
39
+ TriggerSourceMeta,
40
+ } from '../wirings/trigger/trigger.types.js'
41
+ import {
42
+ FunctionsMeta,
43
+ CorePikkuMiddleware,
44
+ CorePikkuMiddlewareGroup,
45
+ CreateConfig,
46
+ CreateSingletonServices,
47
+ CreateWireServices,
48
+ CoreConfig,
49
+ CoreSingletonServices,
50
+ CoreServices,
51
+ CoreUserSession,
52
+ } from './core.types.js'
53
+ import type { CorePikkuChannelMiddleware } from '../wirings/channel/channel.types.js'
54
+
55
+ /**
56
+ * State structure for an individual package
57
+ */
58
+ export interface PikkuPackageState {
59
+ function: {
60
+ meta: FunctionsMeta
61
+ functions: Map<string, CorePikkuFunctionConfig<any, any>>
62
+ }
63
+ rpc: {
64
+ meta: Record<string, string>
65
+ files: Map<
66
+ string,
67
+ {
68
+ exportedName: string
69
+ path: string
70
+ }
71
+ >
72
+ /** Maps namespace aliases to package config (e.g., 'ext' -> { package: '@pikku/...', rpcEndpoint: '...' }) */
73
+ externalPackages: Map<string, { package: string; rpcEndpoint?: string }>
74
+ }
75
+ http: {
76
+ middleware: Map<string, CorePikkuMiddleware<any, any>[]>
77
+ permissions: Map<string, CorePermissionGroup | CorePikkuPermission[]>
78
+ routes: Map<HTTPMethod, Map<string, CoreHTTPFunctionWiring<any, any, any>>>
79
+ meta: HTTPWiringsMeta
80
+ }
81
+ channel: {
82
+ channels: Map<string, CoreChannel<any, any>>
83
+ meta: ChannelsMeta
84
+ }
85
+ scheduler: {
86
+ tasks: Map<string, CoreScheduledTask>
87
+ meta: ScheduledTasksMeta
88
+ }
89
+ queue: {
90
+ registrations: Map<string, CoreQueueWorker>
91
+ meta: QueueWorkersMeta
92
+ }
93
+ workflows: {
94
+ registrations: Map<string, CoreWorkflow>
95
+ meta: WorkflowsRuntimeMeta
96
+ }
97
+ trigger: {
98
+ functions: Map<string, CorePikkuTriggerFunctionConfig<any, any>>
99
+ triggers: Map<string, CoreTrigger>
100
+ triggerSources: Map<string, CoreTriggerSource>
101
+ meta: TriggerMeta
102
+ sourceMeta: TriggerSourceMeta
103
+ }
104
+ mcp: {
105
+ resources: Map<string, CoreMCPResource>
106
+ resourcesMeta: MCPResourceMeta
107
+ toolsMeta: MCPToolMeta
108
+ prompts: Map<string, CoreMCPPrompt>
109
+ promptsMeta: MCPPromptMeta
110
+ }
111
+ agent: {
112
+ agents: Map<string, CoreAIAgent>
113
+ agentsMeta: AIAgentMeta
114
+ }
115
+ cli: {
116
+ meta: CLIMeta | Record<string, any> // Backward compatible with old published CLI format
117
+ programs: Record<string, CLIProgramState>
118
+ }
119
+ middleware: {
120
+ tagGroup: Record<string, CorePikkuMiddlewareGroup>
121
+ httpGroup: Record<string, CorePikkuMiddlewareGroup>
122
+ }
123
+ channelMiddleware: {
124
+ tagGroup: Record<string, CorePikkuChannelMiddleware[]>
125
+ }
126
+ permissions: {
127
+ tagGroup: Record<string, CorePermissionGroup | CorePikkuPermission[]>
128
+ httpGroup: Record<string, CorePermissionGroup | CorePikkuPermission[]>
129
+ }
130
+ misc: {
131
+ errors: Map<PikkuError, ErrorDetails>
132
+ schemas: Map<string, any>
133
+ middleware: Record<string, CorePikkuMiddleware[]>
134
+ channelMiddleware: Record<string, CorePikkuChannelMiddleware[]>
135
+ permissions: Record<string, CorePermissionGroup | CorePikkuPermission[]>
136
+ }
137
+ models: {
138
+ config: {
139
+ models?: Record<
140
+ string,
141
+ string | { model: string; temperature?: number; maxSteps?: number }
142
+ >
143
+ agentDefaults?: { temperature?: number; maxSteps?: number }
144
+ agentOverrides?: Record<
145
+ string,
146
+ { model?: string; temperature?: number; maxSteps?: number }
147
+ >
148
+ } | null
149
+ }
150
+ package: {
151
+ /** Service factory functions for external packages */
152
+ factories: {
153
+ createConfig?: CreateConfig<CoreConfig>
154
+ createSingletonServices?: CreateSingletonServices<
155
+ CoreConfig,
156
+ CoreSingletonServices
157
+ >
158
+ createWireServices?: CreateWireServices<
159
+ CoreSingletonServices,
160
+ CoreServices,
161
+ CoreUserSession
162
+ >
163
+ } | null
164
+ /** Cached singleton services for this package */
165
+ singletonServices: CoreSingletonServices | null
166
+ /** Absolute path to this package's .pikku directory */
167
+ metaDir: string | null
168
+ }
169
+ }
package/src/utils.ts CHANGED
@@ -1,14 +1,12 @@
1
1
  import { Logger } from './services/logger.js'
2
+ import { CoreSingletonServices, WireServices } from './types/core.types.js'
2
3
 
3
- // TODO: WireServices probably needs it's own type
4
- // but is an issue for the future and will be tackled
5
- // with dependency injection
6
4
  export const closeWireServices = async (
7
5
  logger: Logger,
8
- wireServices: Record<string, any>
6
+ wireServices: WireServices
9
7
  ) => {
10
8
  await Promise.all(
11
- Object.values(wireServices).map(async (service) => {
9
+ Object.values(wireServices).map(async (service: any) => {
12
10
  if (service?.close) {
13
11
  try {
14
12
  await service.close()
@@ -39,6 +37,23 @@ export const isSerializable = (data: any): boolean => {
39
37
  )
40
38
  }
41
39
 
40
+ export const getTagGroups = <T>(
41
+ tagGroups: Record<string, T>,
42
+ tag: string
43
+ ): T[] => {
44
+ const results: T[] = []
45
+ const exact = tagGroups[tag]
46
+ if (exact) results.push(exact)
47
+ let colonIdx = tag.lastIndexOf(':')
48
+ while (colonIdx !== -1) {
49
+ const parent = tag.slice(0, colonIdx)
50
+ const group = tagGroups[parent]
51
+ if (group) results.push(group)
52
+ colonIdx = parent.lastIndexOf(':')
53
+ }
54
+ return results
55
+ }
56
+
42
57
  const EMPTY_ARRAY = Object.freeze([])
43
58
 
44
59
  export const freezeDedupe = <T>(
@@ -57,3 +72,57 @@ export const freezeDedupe = <T>(
57
72
  }
58
73
  return Object.freeze(out)
59
74
  }
75
+
76
+ /**
77
+ * Stop a single service by calling its stop method if it exists
78
+ */
79
+ const stopService = async (
80
+ logger: Logger,
81
+ name: string,
82
+ service: any
83
+ ): Promise<void> => {
84
+ const stop = service?.stop
85
+ if (stop) {
86
+ logger.info(`Stopping singleton service: ${name}`)
87
+ try {
88
+ await stop.call(service)
89
+ } catch (e: any) {
90
+ logger.error(`Error stopping service ${name}:`, e)
91
+ }
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Stop all singleton services, including external package services.
97
+ * External package services are stopped first, then the parent services.
98
+ *
99
+ * @param singletonServices - The parent singleton services to stop
100
+ */
101
+ export const stopSingletonServices = async (
102
+ singletonServices: CoreSingletonServices
103
+ ): Promise<void> => {
104
+ const logger = singletonServices.logger
105
+
106
+ // First, stop all external package singleton services
107
+ if (globalThis.pikkuState) {
108
+ for (const [packageName, packageState] of globalThis.pikkuState) {
109
+ // Skip main package - we handle it separately
110
+ if (packageName === '__main__') continue
111
+
112
+ const packageServices = packageState.package?.singletonServices
113
+ if (packageServices) {
114
+ logger.info(`Stopping singleton services for package: ${packageName}`)
115
+ for (const [name, service] of Object.entries(packageServices)) {
116
+ await stopService(logger, `${packageName}/${name}`, service)
117
+ }
118
+ // Clear the cached services
119
+ packageState.package.singletonServices = null
120
+ }
121
+ }
122
+ }
123
+
124
+ // Then stop the parent singleton services
125
+ for (const [name, service] of Object.entries(singletonServices)) {
126
+ await stopService(logger, name, service)
127
+ }
128
+ }
@@ -0,0 +1,80 @@
1
+ import { strict as assert } from 'assert'
2
+ import { describe, test } from 'node:test'
3
+ import {
4
+ formatVersionedId,
5
+ parseVersionedId,
6
+ isVersionedId,
7
+ } from './version.js'
8
+
9
+ describe('formatVersionedId', () => {
10
+ test('formats base name with version', () => {
11
+ assert.strictEqual(formatVersionedId('createUser', 1), 'createUser@v1')
12
+ assert.strictEqual(formatVersionedId('createUser', 2), 'createUser@v2')
13
+ assert.strictEqual(formatVersionedId('createUser', 10), 'createUser@v10')
14
+ })
15
+
16
+ test('handles namespaced base names', () => {
17
+ assert.strictEqual(
18
+ formatVersionedId('pkg:createUser', 3),
19
+ 'pkg:createUser@v3'
20
+ )
21
+ })
22
+ })
23
+
24
+ describe('parseVersionedId', () => {
25
+ test('parses versioned IDs', () => {
26
+ assert.deepStrictEqual(parseVersionedId('createUser@v1'), {
27
+ baseName: 'createUser',
28
+ version: 1,
29
+ })
30
+ assert.deepStrictEqual(parseVersionedId('createUser@v2'), {
31
+ baseName: 'createUser',
32
+ version: 2,
33
+ })
34
+ assert.deepStrictEqual(parseVersionedId('createUser@v10'), {
35
+ baseName: 'createUser',
36
+ version: 10,
37
+ })
38
+ })
39
+
40
+ test('returns null version for unversioned IDs', () => {
41
+ assert.deepStrictEqual(parseVersionedId('createUser'), {
42
+ baseName: 'createUser',
43
+ version: null,
44
+ })
45
+ })
46
+
47
+ test('returns null version for invalid version suffix', () => {
48
+ assert.deepStrictEqual(parseVersionedId('createUser@vx'), {
49
+ baseName: 'createUser@vx',
50
+ version: null,
51
+ })
52
+ assert.deepStrictEqual(parseVersionedId('createUser@v0'), {
53
+ baseName: 'createUser@v0',
54
+ version: null,
55
+ })
56
+ assert.deepStrictEqual(parseVersionedId('createUser@v-1'), {
57
+ baseName: 'createUser@v-1',
58
+ version: null,
59
+ })
60
+ })
61
+
62
+ test('handles namespaced versioned IDs', () => {
63
+ assert.deepStrictEqual(parseVersionedId('pkg:createUser@v3'), {
64
+ baseName: 'pkg:createUser',
65
+ version: 3,
66
+ })
67
+ })
68
+ })
69
+
70
+ describe('isVersionedId', () => {
71
+ test('returns true for versioned IDs', () => {
72
+ assert.strictEqual(isVersionedId('createUser@v1'), true)
73
+ assert.strictEqual(isVersionedId('createUser@v99'), true)
74
+ })
75
+
76
+ test('returns false for unversioned IDs', () => {
77
+ assert.strictEqual(isVersionedId('createUser'), false)
78
+ assert.strictEqual(isVersionedId('createUser@vx'), false)
79
+ })
80
+ })
package/src/version.ts ADDED
@@ -0,0 +1,25 @@
1
+ const VERSION_SEPARATOR = '@v'
2
+
3
+ export function formatVersionedId(baseName: string, version: number): string {
4
+ return `${baseName}${VERSION_SEPARATOR}${version}`
5
+ }
6
+
7
+ export function parseVersionedId(id: string): {
8
+ baseName: string
9
+ version: number | null
10
+ } {
11
+ const idx = id.lastIndexOf(VERSION_SEPARATOR)
12
+ if (idx === -1) {
13
+ return { baseName: id, version: null }
14
+ }
15
+ const versionStr = id.slice(idx + VERSION_SEPARATOR.length)
16
+ const version = Number(versionStr)
17
+ if (!Number.isInteger(version) || version < 1) {
18
+ return { baseName: id, version: null }
19
+ }
20
+ return { baseName: id.slice(0, idx), version }
21
+ }
22
+
23
+ export function isVersionedId(id: string): boolean {
24
+ return parseVersionedId(id).version !== null
25
+ }
@@ -0,0 +1,300 @@
1
+ import { randomUUID } from 'crypto'
2
+ import type { CoreSingletonServices } from '../../types/core.types.js'
3
+ import type {
4
+ CoreAIAgent,
5
+ AIAgentMemoryConfig,
6
+ AIAgentInput,
7
+ AIMessage,
8
+ } from './ai-agent.types.js'
9
+ import type { AIStorageService } from '../../services/ai-storage-service.js'
10
+ import type { Logger } from '../../services/logger.js'
11
+ import type { SchemaService } from '../../services/schema-service.js'
12
+
13
+ export function resolveMemoryServices(
14
+ agent: CoreAIAgent,
15
+ singletonServices: CoreSingletonServices
16
+ ): {
17
+ storage: AIStorageService | undefined
18
+ } {
19
+ const memoryConfig = agent.memory
20
+ const storage = memoryConfig?.storage
21
+ ? (singletonServices as any)[memoryConfig.storage]
22
+ : singletonServices.aiStorage
23
+ return { storage }
24
+ }
25
+
26
+ export function deepMergeWorkingMemory(
27
+ existing: Record<string, unknown>,
28
+ updates: Record<string, unknown>
29
+ ): Record<string, unknown> {
30
+ const result = { ...existing }
31
+ for (const key of Object.keys(updates)) {
32
+ const value = updates[key]
33
+ if (value === null) {
34
+ delete result[key]
35
+ } else if (
36
+ typeof value === 'object' &&
37
+ !Array.isArray(value) &&
38
+ typeof result[key] === 'object' &&
39
+ result[key] !== null &&
40
+ !Array.isArray(result[key])
41
+ ) {
42
+ result[key] = deepMergeWorkingMemory(
43
+ result[key] as Record<string, unknown>,
44
+ value as Record<string, unknown>
45
+ )
46
+ } else {
47
+ result[key] = value
48
+ }
49
+ }
50
+ return result
51
+ }
52
+
53
+ export function buildWorkingMemoryPrompt(
54
+ currentState: Record<string, unknown> | null,
55
+ jsonSchema?: Record<string, unknown>
56
+ ): string {
57
+ const parts: string[] = []
58
+
59
+ if (jsonSchema?.properties) {
60
+ const props = jsonSchema.properties as Record<
61
+ string,
62
+ { type?: string; description?: string }
63
+ >
64
+ const fieldLines = Object.entries(props).map(([name, def]) => {
65
+ const type = def.type ?? 'unknown'
66
+ const desc = def.description ? ` - ${def.description}` : ''
67
+ return ` - ${name} (${type})${desc}`
68
+ })
69
+ if (fieldLines.length > 0) {
70
+ parts.push(`Working memory fields:\n${fieldLines.join('\n')}`)
71
+ }
72
+ }
73
+
74
+ if (currentState && Object.keys(currentState).length > 0) {
75
+ parts.push(`Current working memory:\n${JSON.stringify(currentState)}`)
76
+ } else {
77
+ parts.push('Current working memory: (empty)')
78
+ }
79
+
80
+ parts.push(
81
+ 'When you learn new information, output a partial JSON update in <working_memory> tags. ' +
82
+ 'Only include changed fields. Set a field to null to delete it.'
83
+ )
84
+
85
+ return parts.join('\n\n')
86
+ }
87
+
88
+ export async function loadContextMessages(
89
+ memoryConfig: AIAgentMemoryConfig | undefined,
90
+ storage: AIStorageService | undefined,
91
+ input: AIAgentInput,
92
+ workingMemoryJsonSchema?: Record<string, unknown>
93
+ ): Promise<AIMessage[]> {
94
+ const contextMessages: AIMessage[] = []
95
+
96
+ if (memoryConfig?.workingMemory && storage) {
97
+ const workingMem = await storage.getWorkingMemory(input.threadId, 'thread')
98
+ const prompt = buildWorkingMemoryPrompt(workingMem, workingMemoryJsonSchema)
99
+ contextMessages.push({
100
+ id: `wm-${randomUUID()}`,
101
+ role: 'system',
102
+ content: prompt,
103
+ createdAt: new Date(),
104
+ })
105
+ }
106
+
107
+ return contextMessages
108
+ }
109
+
110
+ export async function saveMessages(
111
+ storage: AIStorageService | undefined,
112
+ threadId: string,
113
+ resourceId: string,
114
+ memoryConfig: AIAgentMemoryConfig | undefined,
115
+ userMessage: AIMessage,
116
+ result: {
117
+ text: string
118
+ steps: {
119
+ toolCalls?: {
120
+ name: string
121
+ args: Record<string, unknown>
122
+ result: string
123
+ }[]
124
+ }[]
125
+ },
126
+ options?: {
127
+ workingMemoryJsonSchema?: Record<string, unknown>
128
+ workingMemorySchemaName?: string | null
129
+ logger?: Logger
130
+ schemaService?: SchemaService
131
+ }
132
+ ): Promise<string> {
133
+ let responseText = result.text
134
+
135
+ if (storage) {
136
+ const newMessages: AIMessage[] = [userMessage]
137
+
138
+ for (const step of result.steps) {
139
+ if (step.toolCalls?.length) {
140
+ newMessages.push({
141
+ id: randomUUID(),
142
+ role: 'assistant',
143
+ toolCalls: step.toolCalls.map((tc) => ({
144
+ id: randomUUID(),
145
+ name: tc.name,
146
+ args: tc.args,
147
+ })),
148
+ createdAt: new Date(),
149
+ })
150
+ newMessages.push({
151
+ id: randomUUID(),
152
+ role: 'tool',
153
+ toolResults: step.toolCalls.map((tc) => ({
154
+ id: randomUUID(),
155
+ name: tc.name,
156
+ result: tc.result,
157
+ })),
158
+ createdAt: new Date(),
159
+ })
160
+ }
161
+ }
162
+
163
+ newMessages.push({
164
+ id: randomUUID(),
165
+ role: 'assistant',
166
+ content: responseText,
167
+ createdAt: new Date(),
168
+ })
169
+
170
+ await storage.saveMessages(threadId, newMessages)
171
+
172
+ if (memoryConfig?.workingMemory) {
173
+ const parsed = parseWorkingMemory(responseText)
174
+ if (parsed) {
175
+ const existing =
176
+ (await storage.getWorkingMemory(threadId, 'thread')) ?? {}
177
+ const merged = deepMergeWorkingMemory(existing, parsed)
178
+
179
+ if (options?.schemaService && options?.workingMemorySchemaName) {
180
+ try {
181
+ await options.schemaService.validateSchema(
182
+ options.workingMemorySchemaName,
183
+ merged
184
+ )
185
+ } catch (err) {
186
+ options.logger?.warn(
187
+ `Working memory validation failed: ${err instanceof Error ? err.message : String(err)}`
188
+ )
189
+ }
190
+ }
191
+
192
+ await storage.saveWorkingMemory(threadId, 'thread', merged)
193
+ responseText = stripWorkingMemoryTags(responseText)
194
+ }
195
+ }
196
+ }
197
+
198
+ return responseText
199
+ }
200
+
201
+ export function trimMessages(
202
+ messages: AIMessage[],
203
+ maxTokenBudget: number = 100000
204
+ ): AIMessage[] {
205
+ const sanitized = sanitizeToolMessages(messages)
206
+
207
+ let estimatedTokens = 0
208
+ const result: AIMessage[] = []
209
+
210
+ for (let i = sanitized.length - 1; i >= 0; i--) {
211
+ const msg = sanitized[i]
212
+ const msgTokens = estimateTokens(msg)
213
+ if (estimatedTokens + msgTokens > maxTokenBudget && result.length > 0) {
214
+ break
215
+ }
216
+ estimatedTokens += msgTokens
217
+ result.unshift(msg)
218
+ }
219
+
220
+ if (
221
+ result.length > 0 &&
222
+ result[0].role !== 'user' &&
223
+ result[0].role !== 'system'
224
+ ) {
225
+ const firstUserIdx = result.findIndex(
226
+ (m) => m.role === 'user' || m.role === 'system'
227
+ )
228
+ if (firstUserIdx > 0) {
229
+ return result.slice(firstUserIdx)
230
+ }
231
+ }
232
+
233
+ return result
234
+ }
235
+
236
+ function sanitizeToolMessages(messages: AIMessage[]): AIMessage[] {
237
+ const result: AIMessage[] = []
238
+
239
+ for (let i = 0; i < messages.length; i++) {
240
+ const msg = messages[i]
241
+
242
+ if (msg.role === 'assistant' && msg.toolCalls?.length) {
243
+ const next = messages[i + 1]
244
+ if (!next || next.role !== 'tool' || !next.toolResults?.length) {
245
+ if (msg.content) {
246
+ result.push({ ...msg, toolCalls: undefined })
247
+ }
248
+ continue
249
+ }
250
+
251
+ const toolCallIds = new Set(msg.toolCalls.map((tc) => tc.id))
252
+ const resultIds = new Set(next.toolResults.map((tr) => tr.id))
253
+ const allMatched = [...toolCallIds].every((id) => resultIds.has(id))
254
+
255
+ if (!allMatched) {
256
+ if (msg.content) {
257
+ result.push({ ...msg, toolCalls: undefined })
258
+ }
259
+ result.push({
260
+ ...next,
261
+ toolResults:
262
+ next.toolResults.filter((tr) => !toolCallIds.has(tr.id)) ||
263
+ undefined,
264
+ })
265
+ i++
266
+ continue
267
+ }
268
+ }
269
+
270
+ result.push(msg)
271
+ }
272
+
273
+ return result.filter(
274
+ (m) => m.role !== 'tool' || (m.toolResults && m.toolResults.length > 0)
275
+ )
276
+ }
277
+
278
+ function estimateTokens(msg: AIMessage): number {
279
+ let chars = 0
280
+ if (msg.content) chars += msg.content.length
281
+ if (msg.toolCalls) chars += JSON.stringify(msg.toolCalls).length
282
+ if (msg.toolResults) chars += JSON.stringify(msg.toolResults).length
283
+ return Math.ceil(chars / 4)
284
+ }
285
+
286
+ export function parseWorkingMemory(
287
+ text: string
288
+ ): Record<string, unknown> | null {
289
+ const match = text.match(/<working_memory>([\s\S]*?)<\/working_memory>/)
290
+ if (!match) return null
291
+ try {
292
+ return JSON.parse(match[1].trim())
293
+ } catch {
294
+ return null
295
+ }
296
+ }
297
+
298
+ export function stripWorkingMemoryTags(text: string): string {
299
+ return text.replace(/<working_memory>[\s\S]*?<\/working_memory>/g, '').trim()
300
+ }