@symerian/symi 3.0.17 → 3.0.19

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 (259) hide show
  1. package/dist/{audio-preflight-CBDFctZN.js → audio-preflight-BfmZbg4Y.js} +4 -4
  2. package/dist/{audio-preflight-gsZSpG-6.js → audio-preflight-DcuC-liM.js} +4 -4
  3. package/dist/build-info.json +3 -3
  4. package/dist/bundled/boot-md/handler.js +8 -8
  5. package/dist/bundled/session-memory/handler.js +7 -7
  6. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  7. package/dist/{chrome-nPMY1XTJ.js → chrome-Bo7cbvFK.js} +5 -5
  8. package/dist/{chrome-BjVab8gM.js → chrome-DYp18Q0t.js} +5 -5
  9. package/dist/{deliver-D-QFqm31.js → deliver-ChSIbiMM.js} +1 -1
  10. package/dist/{deliver-B4-bcot9.js → deliver-DEgRQM4J.js} +1 -1
  11. package/dist/extensionAPI.js +7 -7
  12. package/dist/{image-CDwtQjmt.js → image-Bx-hvoNJ.js} +1 -1
  13. package/dist/{image-CcS-vzTA.js → image-CQl_mjWk.js} +1 -1
  14. package/dist/llm-slug-generator.js +7 -7
  15. package/dist/{manager-BnEdHzmO.js → manager-D_pn0urG.js} +1 -1
  16. package/dist/{manager-09r0qPze.js → manager-YQxK2t0C.js} +1 -1
  17. package/dist/{pi-embedded-CWsY69-4.js → pi-embedded-CLw_ZzEZ.js} +16 -16
  18. package/dist/{pi-embedded-helpers-BBMy-lqr.js → pi-embedded-helpers-B5I53aw6.js} +4 -4
  19. package/dist/{pi-embedded-helpers-ChEYbgVj.js → pi-embedded-helpers-sUAEIC9X.js} +4 -4
  20. package/dist/plugin-sdk/{accounts-BfyWsC_i.js → accounts-CWFytwbR.js} +3 -3
  21. package/dist/plugin-sdk/{active-listener-DcJW7xAT.js → active-listener-BkZ4jHrL.js} +2 -2
  22. package/dist/plugin-sdk/{agent-scope-ChbGV6of.js → agent-scope-C9gfY_Gk.js} +2 -2
  23. package/dist/plugin-sdk/{audio-preflight-D3GtNLqW.js → audio-preflight-HKbdzXLZ.js} +21 -21
  24. package/dist/plugin-sdk/{bindings-CN2Qmefj.js → bindings-BaKIqPPy.js} +2 -2
  25. package/dist/plugin-sdk/{channel-web-DTyqujjA.js → channel-web-D5nWiTH1.js} +18 -18
  26. package/dist/plugin-sdk/{chrome-BKzAKr3K.js → chrome-klTSnz-9.js} +3 -3
  27. package/dist/plugin-sdk/{chunk-DhDkBujV.js → chunk-BbrYSny_.js} +1 -1
  28. package/dist/plugin-sdk/{command-format-CVrYFyZS.js → command-format-BN6tyZt6.js} +1 -1
  29. package/dist/plugin-sdk/{commands-registry-17yfZkHZ.js → commands-registry-CTzKKtY6.js} +4 -4
  30. package/dist/plugin-sdk/{config-7wk65zKC.js → config-Crv2qEdJ.js} +9 -9
  31. package/dist/plugin-sdk/{consolidate-exbAW0ml.js → consolidate-DT1QH65Q.js} +2 -2
  32. package/dist/plugin-sdk/{deliver-TxAcw7J5.js → deliver-7rOvAlrc.js} +12 -12
  33. package/dist/plugin-sdk/{diagnostic-Debx4frd.js → diagnostic-0nsxhWp7.js} +1 -1
  34. package/dist/plugin-sdk/{fs-safe-wBYbAkJF.js → fs-safe-DfWYBeWF.js} +1 -1
  35. package/dist/plugin-sdk/{gemini-auth-7U2pm2Ky.js → gemini-auth-C0N0_u49.js} +1 -1
  36. package/dist/plugin-sdk/{image-BtDVmYA5.js → image-WOSl2apK.js} +4 -4
  37. package/dist/plugin-sdk/index.js +43 -43
  38. package/dist/plugin-sdk/{ir-CKMvRrGW.js → ir-9J84MTls.js} +4 -4
  39. package/dist/plugin-sdk/{local-roots-c_gaPs01.js → local-roots-OLRDbvyY.js} +3 -3
  40. package/dist/plugin-sdk/{login-DUym1Jy0.js → login-C7x4q0i2.js} +7 -7
  41. package/dist/plugin-sdk/{login-qr-B-WBdvrX.js → login-qr-Dv5_MoAW.js} +9 -9
  42. package/dist/plugin-sdk/{manager-B71SCzos.js → manager-C83tK17x.js} +8 -8
  43. package/dist/plugin-sdk/{manifest-registry-Dnic6Chh.js → manifest-registry-CJMV-PI7.js} +1 -1
  44. package/dist/plugin-sdk/{markdown-tables-Dur7OTlM.js → markdown-tables-DXNKz5y_.js} +1 -1
  45. package/dist/plugin-sdk/{message-channel-BrAhJJV_.js → message-channel-aGy1HbQQ.js} +1 -1
  46. package/dist/plugin-sdk/{model-selection-B9qaVQSJ.js → model-selection-C-3-tpe7.js} +4 -4
  47. package/dist/plugin-sdk/{outbound-DB1wDM8b.js → outbound-DquCeSy5.js} +6 -6
  48. package/dist/plugin-sdk/{pi-auth-json-ZO118hoy.js → pi-auth-json-D9PDCXGn.js} +1 -1
  49. package/dist/plugin-sdk/{pi-embedded-helpers-s_U0Un7j.js → pi-embedded-helpers-D3ygfH7l.js} +16 -16
  50. package/dist/plugin-sdk/{plugins-DF81oSaI.js → plugins-DOwnSg9D.js} +4 -4
  51. package/dist/plugin-sdk/{pw-ai-CTwP02uv.js → pw-ai-rlengLjb.js} +8 -8
  52. package/dist/plugin-sdk/{qmd-manager-CBaSGant.js → qmd-manager-BzxFjRFa.js} +4 -4
  53. package/dist/plugin-sdk/{registry-CZVURNhF.js → registry-5iFfixlB.js} +2 -2
  54. package/dist/plugin-sdk/{replies-hwRbkU3z.js → replies-BXOzO_H5.js} +7 -7
  55. package/dist/plugin-sdk/{reply-prefix-CaXmzZlx.js → reply-prefix-INAKTqCU.js} +1 -1
  56. package/dist/plugin-sdk/{resolve-outbound-target-fxVSOBmk.js → resolve-outbound-target-DvbxHtqp.js} +2 -2
  57. package/dist/plugin-sdk/{resolve-route-ClCyiOeu.js → resolve-route-URXlY3AK.js} +3 -3
  58. package/dist/plugin-sdk/{runner-Cq5jvwQ7.js → runner-Bv0_DWoH.js} +9 -9
  59. package/dist/plugin-sdk/{session-B_TkB65Y.js → session-C3r8l7ou.js} +4 -4
  60. package/dist/plugin-sdk/{skill-commands-0LF9HTGr.js → skill-commands-KjLUGIdZ.js} +5 -5
  61. package/dist/plugin-sdk/{skills-BIT_O7J0.js → skills-BrsD4L5c.js} +7 -7
  62. package/dist/plugin-sdk/{sqlite-Bx5Y5U5X.js → sqlite-CjW7ME1H.js} +1 -1
  63. package/dist/plugin-sdk/{subsystem-CXqYeDy-.js → subsystem-DcOg1xJr.js} +1 -1
  64. package/dist/plugin-sdk/{synthesis-DtsYAj1E.js → synthesis-CY7YAasV.js} +38 -38
  65. package/dist/plugin-sdk/{target-errors-B8mokOeH.js → target-errors-BVWJGWFq.js} +2 -2
  66. package/dist/plugin-sdk/{thinking-Ca0DhqzO.js → thinking-CtsTDPOi.js} +3 -3
  67. package/dist/plugin-sdk/{tokens-CvlONEqh.js → tokens-8lqOTZCB.js} +1 -1
  68. package/dist/plugin-sdk/{tool-images-DpBaWEHT.js → tool-images-Cl_rGIUZ.js} +2 -2
  69. package/dist/plugin-sdk/{tool-loop-detection-BOvUFa0f.js → tool-loop-detection-Da4WUT_P.js} +2 -2
  70. package/dist/plugin-sdk/{unified-runner-CnM7lyNd.js → unified-runner-nwMnsZyj.js} +60 -60
  71. package/dist/plugin-sdk/web-BlweOZDp.js +54 -0
  72. package/dist/plugin-sdk/{whatsapp-actions-CvnfsFJm.js → whatsapp-actions-DpfaGYs7.js} +21 -21
  73. package/dist/{pw-ai-BW8_KeDf.js → pw-ai-BqxJG-Wh.js} +1 -1
  74. package/dist/{pw-ai-j9IE1K0-.js → pw-ai-C-NSGye0.js} +1 -1
  75. package/dist/{runner-8ALr2UII.js → runner-COGFTeDw.js} +1 -1
  76. package/dist/{runner-C4-9kFdR.js → runner-DhCi2lT1.js} +1 -1
  77. package/dist/{synthesis-Cph3LhA1.js → synthesis-CXZu24Vx.js} +7 -7
  78. package/dist/{synthesis-Cus0A2dL.js → synthesis-DrPxcMlQ.js} +7 -7
  79. package/dist/{unified-runner-CX80YMTk.js → unified-runner-iByUazvW.js} +16 -16
  80. package/dist/{web-ChozvJ7I.js → web-EsMQBIYf.js} +7 -7
  81. package/dist/{web-DFlsbXmQ.js → web-PPg5y6xI.js} +7 -7
  82. package/package.json +1 -1
  83. package/dist/plugin-sdk/web-CIPJBHAU.js +0 -54
  84. package/extensions/copilot-proxy/README.md +0 -24
  85. package/extensions/copilot-proxy/index.ts +0 -154
  86. package/extensions/copilot-proxy/node_modules/.bin/symi +0 -21
  87. package/extensions/copilot-proxy/package.json +0 -15
  88. package/extensions/copilot-proxy/symi.plugin.json +0 -9
  89. package/extensions/device-pair/index.ts +0 -642
  90. package/extensions/device-pair/symi.plugin.json +0 -20
  91. package/extensions/diagnostics-otel/index.ts +0 -15
  92. package/extensions/diagnostics-otel/node_modules/.bin/acorn +0 -21
  93. package/extensions/diagnostics-otel/node_modules/.bin/symi +0 -21
  94. package/extensions/diagnostics-otel/package.json +0 -27
  95. package/extensions/diagnostics-otel/src/service.test.ts +0 -290
  96. package/extensions/diagnostics-otel/src/service.ts +0 -666
  97. package/extensions/diagnostics-otel/symi.plugin.json +0 -8
  98. package/extensions/google-antigravity-auth/README.md +0 -24
  99. package/extensions/google-antigravity-auth/index.ts +0 -424
  100. package/extensions/google-antigravity-auth/node_modules/.bin/symi +0 -21
  101. package/extensions/google-antigravity-auth/package.json +0 -15
  102. package/extensions/google-antigravity-auth/symi.plugin.json +0 -9
  103. package/extensions/google-gemini-cli-auth/README.md +0 -35
  104. package/extensions/google-gemini-cli-auth/index.ts +0 -75
  105. package/extensions/google-gemini-cli-auth/node_modules/.bin/symi +0 -21
  106. package/extensions/google-gemini-cli-auth/oauth.test.ts +0 -162
  107. package/extensions/google-gemini-cli-auth/oauth.ts +0 -636
  108. package/extensions/google-gemini-cli-auth/package.json +0 -15
  109. package/extensions/google-gemini-cli-auth/symi.plugin.json +0 -9
  110. package/extensions/learning-loop/index.ts +0 -159
  111. package/extensions/learning-loop/node_modules/.bin/symi +0 -21
  112. package/extensions/learning-loop/package.json +0 -18
  113. package/extensions/learning-loop/src/analytics/gateway-methods.ts +0 -230
  114. package/extensions/learning-loop/src/analytics/metrics-aggregator.ts +0 -153
  115. package/extensions/learning-loop/src/capture/run-tracker.ts +0 -181
  116. package/extensions/learning-loop/src/capture/serializer.ts +0 -74
  117. package/extensions/learning-loop/src/db.ts +0 -583
  118. package/extensions/learning-loop/src/feedback/explicit-feedback.ts +0 -58
  119. package/extensions/learning-loop/src/feedback/implicit-signals.ts +0 -89
  120. package/extensions/learning-loop/src/graph/edge-inference.ts +0 -189
  121. package/extensions/learning-loop/src/graph/graph-retrieval.ts +0 -144
  122. package/extensions/learning-loop/src/graph/graph-store.ts +0 -183
  123. package/extensions/learning-loop/src/hooks.ts +0 -244
  124. package/extensions/learning-loop/src/injection/cache.ts +0 -73
  125. package/extensions/learning-loop/src/injection/context-injector.ts +0 -104
  126. package/extensions/learning-loop/src/injection/prompt-builder.ts +0 -43
  127. package/extensions/learning-loop/src/learning/embedding-bridge.ts +0 -54
  128. package/extensions/learning-loop/src/learning/learning-extractor.ts +0 -217
  129. package/extensions/learning-loop/src/learning/learning-store.ts +0 -158
  130. package/extensions/learning-loop/src/learning/retrieval.ts +0 -87
  131. package/extensions/learning-loop/src/math/confidence-intervals.ts +0 -62
  132. package/extensions/learning-loop/src/math/ewma.ts +0 -51
  133. package/extensions/learning-loop/src/math/weighted-scorer.ts +0 -42
  134. package/extensions/learning-loop/src/schema.ts +0 -176
  135. package/extensions/learning-loop/src/scoring/normalization.ts +0 -32
  136. package/extensions/learning-loop/src/scoring/quality-engine.ts +0 -78
  137. package/extensions/learning-loop/src/scoring/signal-extractors.ts +0 -155
  138. package/extensions/learning-loop/src/test/context-injector.test.ts +0 -142
  139. package/extensions/learning-loop/src/test/fixes.test.ts +0 -1286
  140. package/extensions/learning-loop/src/test/graph.test.ts +0 -711
  141. package/extensions/learning-loop/src/test/integration.test.ts +0 -312
  142. package/extensions/learning-loop/src/test/learning-store.test.ts +0 -191
  143. package/extensions/learning-loop/src/test/math.test.ts +0 -148
  144. package/extensions/learning-loop/src/test/quality-engine.test.ts +0 -231
  145. package/extensions/learning-loop/src/test/run-tracker.test.ts +0 -143
  146. package/extensions/learning-loop/src/types.ts +0 -281
  147. package/extensions/learning-loop/symi.plugin.json +0 -46
  148. package/extensions/llm-task/README.md +0 -97
  149. package/extensions/llm-task/index.ts +0 -6
  150. package/extensions/llm-task/package.json +0 -12
  151. package/extensions/llm-task/src/llm-task-tool.test.ts +0 -138
  152. package/extensions/llm-task/src/llm-task-tool.ts +0 -249
  153. package/extensions/llm-task/symi.plugin.json +0 -21
  154. package/extensions/memory-lancedb/config.ts +0 -161
  155. package/extensions/memory-lancedb/index.test.ts +0 -330
  156. package/extensions/memory-lancedb/index.ts +0 -670
  157. package/extensions/memory-lancedb/node_modules/.bin/arrow2csv +0 -21
  158. package/extensions/memory-lancedb/node_modules/.bin/openai +0 -21
  159. package/extensions/memory-lancedb/node_modules/.bin/symi +0 -21
  160. package/extensions/memory-lancedb/package.json +0 -20
  161. package/extensions/memory-lancedb/symi.plugin.json +0 -71
  162. package/extensions/minimax-portal-auth/README.md +0 -33
  163. package/extensions/minimax-portal-auth/index.ts +0 -161
  164. package/extensions/minimax-portal-auth/node_modules/.bin/symi +0 -21
  165. package/extensions/minimax-portal-auth/oauth.ts +0 -247
  166. package/extensions/minimax-portal-auth/package.json +0 -15
  167. package/extensions/minimax-portal-auth/symi.plugin.json +0 -9
  168. package/extensions/model-equalizer/index.ts +0 -80
  169. package/extensions/model-equalizer/skills/model-equalizer/SKILL.md +0 -58
  170. package/extensions/model-equalizer/src/detection.ts +0 -62
  171. package/extensions/model-equalizer/src/enhancer.ts +0 -63
  172. package/extensions/model-equalizer/src/test/detection.test.ts +0 -218
  173. package/extensions/model-equalizer/src/test/enhancer.test.ts +0 -137
  174. package/extensions/model-equalizer/src/test/integration.test.ts +0 -185
  175. package/extensions/model-equalizer/src/types.ts +0 -24
  176. package/extensions/model-equalizer/symi.plugin.json +0 -12
  177. package/extensions/phone-control/index.ts +0 -421
  178. package/extensions/phone-control/symi.plugin.json +0 -10
  179. package/extensions/pipeline/README.md +0 -75
  180. package/extensions/pipeline/SKILL.md +0 -97
  181. package/extensions/pipeline/index.ts +0 -18
  182. package/extensions/pipeline/package.json +0 -11
  183. package/extensions/pipeline/src/pipeline-tool.test.ts +0 -345
  184. package/extensions/pipeline/src/pipeline-tool.ts +0 -266
  185. package/extensions/pipeline/src/windows-spawn.test.ts +0 -148
  186. package/extensions/pipeline/src/windows-spawn.ts +0 -193
  187. package/extensions/pipeline/symi.plugin.json +0 -10
  188. package/extensions/qwen-portal-auth/README.md +0 -24
  189. package/extensions/qwen-portal-auth/index.ts +0 -134
  190. package/extensions/qwen-portal-auth/oauth.ts +0 -190
  191. package/extensions/qwen-portal-auth/symi.plugin.json +0 -9
  192. package/extensions/talk-voice/index.ts +0 -150
  193. package/extensions/talk-voice/symi.plugin.json +0 -10
  194. package/extensions/thread-ownership/index.test.ts +0 -180
  195. package/extensions/thread-ownership/index.ts +0 -133
  196. package/extensions/thread-ownership/symi.plugin.json +0 -28
  197. package/skills/1password/SKILL.md +0 -71
  198. package/skills/1password/references/cli-examples.md +0 -29
  199. package/skills/1password/references/get-started.md +0 -17
  200. package/skills/apple-notes/SKILL.md +0 -78
  201. package/skills/apple-reminders/SKILL.md +0 -119
  202. package/skills/bear-notes/SKILL.md +0 -108
  203. package/skills/blogwatcher/SKILL.md +0 -70
  204. package/skills/blucli/SKILL.md +0 -48
  205. package/skills/bluebubbles/SKILL.md +0 -132
  206. package/skills/camsnap/SKILL.md +0 -46
  207. package/skills/canvas/SKILL.md +0 -204
  208. package/skills/connect-email/SKILL.md +0 -142
  209. package/skills/document-generation/SKILL.md +0 -83
  210. package/skills/eightctl/SKILL.md +0 -51
  211. package/skills/food-order/SKILL.md +0 -49
  212. package/skills/gemini/SKILL.md +0 -44
  213. package/skills/gh-issues/SKILL.md +0 -865
  214. package/skills/gifgrep/SKILL.md +0 -80
  215. package/skills/github/SKILL.md +0 -164
  216. package/skills/gog/SKILL.md +0 -117
  217. package/skills/goplaces/SKILL.md +0 -53
  218. package/skills/healthcheck/SKILL.md +0 -246
  219. package/skills/himalaya/SKILL.md +0 -258
  220. package/skills/himalaya/references/configuration.md +0 -184
  221. package/skills/himalaya/references/message-composition.md +0 -199
  222. package/skills/imsg/SKILL.md +0 -122
  223. package/skills/long-task/SKILL.md +0 -58
  224. package/skills/long-task/scripts/detach-task.sh +0 -187
  225. package/skills/nano-banana-pro/SKILL.md +0 -59
  226. package/skills/nano-banana-pro/scripts/generate_image.py +0 -184
  227. package/skills/nano-pdf/SKILL.md +0 -39
  228. package/skills/notion/SKILL.md +0 -173
  229. package/skills/obsidian/SKILL.md +0 -82
  230. package/skills/openai-image-gen/SKILL.md +0 -90
  231. package/skills/openai-image-gen/scripts/gen.py +0 -240
  232. package/skills/openai-whisper/SKILL.md +0 -39
  233. package/skills/openai-whisper-api/SKILL.md +0 -53
  234. package/skills/openai-whisper-api/scripts/transcribe.sh +0 -85
  235. package/skills/openhue/SKILL.md +0 -113
  236. package/skills/oracle/SKILL.md +0 -126
  237. package/skills/ordercli/SKILL.md +0 -79
  238. package/skills/peekaboo/SKILL.md +0 -191
  239. package/skills/reactions-extensive/SKILL.md +0 -30
  240. package/skills/reactions-minimal/SKILL.md +0 -31
  241. package/skills/safe-edit/SKILL.md +0 -51
  242. package/skills/sag/SKILL.md +0 -88
  243. package/skills/sherpa-onnx-tts/SKILL.md +0 -104
  244. package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +0 -178
  245. package/skills/songsee/SKILL.md +0 -50
  246. package/skills/sonoscli/SKILL.md +0 -66
  247. package/skills/spotify-player/SKILL.md +0 -65
  248. package/skills/symihub/SKILL.md +0 -78
  249. package/skills/things-mac/SKILL.md +0 -87
  250. package/skills/tmux/SKILL.md +0 -153
  251. package/skills/tmux/scripts/find-sessions.sh +0 -112
  252. package/skills/tmux/scripts/wait-for-text.sh +0 -83
  253. package/skills/trello/SKILL.md +0 -96
  254. package/skills/video-frames/SKILL.md +0 -47
  255. package/skills/video-frames/scripts/frame.sh +0 -81
  256. package/skills/voice-call/SKILL.md +0 -46
  257. package/skills/wacli/SKILL.md +0 -73
  258. package/skills/weather/SKILL.md +0 -113
  259. package/skills/xurl/SKILL.md +0 -462
@@ -1,244 +0,0 @@
1
- /**
2
- * Hook registration for the learning loop plugin.
3
- *
4
- * | Priority | Hook | Role |
5
- * |----------|---------------------|-----------------------------------------|
6
- * | 200 | before_prompt_build | Inject learnings (runs first) |
7
- * | 100 | llm_input | Capture run start metadata |
8
- * | 100 | llm_output | Capture usage + response data |
9
- * | 100 | after_tool_call | Capture tool call traces |
10
- * | 100 | subagent_ended | Capture subagent outcomes |
11
- * | 50 | agent_end | Score run, extract learnings, persist |
12
- * | 50 | message_received | Detect implicit feedback |
13
- */
14
-
15
- import { hashText } from "../../../src/memory/internal.js";
16
- import type { SymiPluginApi, PluginLogger } from "../../../src/plugins/types.js";
17
- import type { MetricsAggregator } from "./analytics/metrics-aggregator.js";
18
- import type { RunTracker } from "./capture/run-tracker.js";
19
- import { normalizeCompletedRun, reconstructCompletedRun } from "./capture/serializer.js";
20
- import type { DatabaseManager } from "./db.js";
21
- import type { ImplicitSignals } from "./feedback/implicit-signals.js";
22
- import type { EdgeInference } from "./graph/edge-inference.js";
23
- import type { ContextInjector } from "./injection/context-injector.js";
24
- import type { LearningExtractor } from "./learning/learning-extractor.js";
25
- import type { LearningStore } from "./learning/learning-store.js";
26
- import type { QualityEngine } from "./scoring/quality-engine.js";
27
- import type { LearningLoopConfig } from "./types.js";
28
-
29
- export function registerHooks(
30
- api: SymiPluginApi,
31
- deps: {
32
- config: LearningLoopConfig;
33
- logger: PluginLogger;
34
- db: DatabaseManager;
35
- tracker: RunTracker;
36
- qualityEngine: QualityEngine;
37
- learningStore: LearningStore;
38
- extractor: LearningExtractor;
39
- injector: ContextInjector;
40
- metrics: MetricsAggregator;
41
- implicit: ImplicitSignals;
42
- edgeInference?: EdgeInference;
43
- },
44
- ) {
45
- const {
46
- config,
47
- logger,
48
- db,
49
- tracker,
50
- qualityEngine,
51
- learningStore,
52
- extractor,
53
- injector,
54
- metrics,
55
- implicit,
56
- edgeInference,
57
- } = deps;
58
-
59
- // -----------------------------------------------------------------------
60
- // before_prompt_build (priority 200) -- Inject learnings
61
- // -----------------------------------------------------------------------
62
- api.on(
63
- "before_prompt_build",
64
- async (event, ctx) => {
65
- try {
66
- const context = await injector.getContext(event.prompt);
67
- if (context) {
68
- return { prependContext: context };
69
- }
70
- } catch (err) {
71
- logger.warn(`[learning-loop] before_prompt_build failed: ${String(err)}`);
72
- }
73
- return undefined;
74
- },
75
- { priority: 200 },
76
- );
77
-
78
- // -----------------------------------------------------------------------
79
- // llm_input (priority 100) -- Capture run start metadata
80
- // -----------------------------------------------------------------------
81
- api.on(
82
- "llm_input",
83
- (event, ctx) => {
84
- try {
85
- tracker.onLlmInput({
86
- runId: event.runId,
87
- sessionId: event.sessionId,
88
- provider: event.provider,
89
- model: event.model,
90
- prompt: event.prompt,
91
- sessionKey: ctx.sessionKey,
92
- agentId: ctx.agentId,
93
- });
94
-
95
- // Record prompt for implicit feedback analysis
96
- implicit.recordPrompt(event.runId, event.prompt);
97
- } catch (err) {
98
- logger.warn(`[learning-loop] llm_input handler failed: ${String(err)}`);
99
- }
100
- },
101
- { priority: 100 },
102
- );
103
-
104
- // -----------------------------------------------------------------------
105
- // llm_output (priority 100) -- Capture usage + response data
106
- // -----------------------------------------------------------------------
107
- api.on(
108
- "llm_output",
109
- (event, ctx) => {
110
- try {
111
- tracker.onLlmOutput({
112
- runId: event.runId,
113
- sessionId: event.sessionId,
114
- assistantTexts: event.assistantTexts,
115
- usage: event.usage,
116
- });
117
- } catch (err) {
118
- logger.warn(`[learning-loop] llm_output handler failed: ${String(err)}`);
119
- }
120
- },
121
- { priority: 100 },
122
- );
123
-
124
- // -----------------------------------------------------------------------
125
- // after_tool_call (priority 100) -- Capture tool call traces
126
- // -----------------------------------------------------------------------
127
- api.on(
128
- "after_tool_call",
129
- (event, ctx) => {
130
- try {
131
- tracker.onToolCall({
132
- toolName: event.toolName,
133
- durationMs: event.durationMs,
134
- success: !event.error,
135
- error: event.error,
136
- paramHash: hashText(JSON.stringify(event.params)),
137
- sessionKey: ctx.sessionKey,
138
- });
139
- } catch (err) {
140
- logger.warn(`[learning-loop] after_tool_call handler failed: ${String(err)}`);
141
- }
142
- },
143
- { priority: 100 },
144
- );
145
-
146
- // -----------------------------------------------------------------------
147
- // subagent_ended (priority 100) -- Capture subagent outcomes
148
- // -----------------------------------------------------------------------
149
- api.on(
150
- "subagent_ended",
151
- (event, ctx) => {
152
- // Subagent outcomes are tracked as metadata; no separate storage needed.
153
- // The parent agent's agent_end will finalize the run.
154
- },
155
- { priority: 100 },
156
- );
157
-
158
- // -----------------------------------------------------------------------
159
- // agent_end (priority 50) -- Score run, extract learnings, persist
160
- // -----------------------------------------------------------------------
161
- api.on(
162
- "agent_end",
163
- async (event, ctx) => {
164
- try {
165
- const completedRaw = tracker.finalize({
166
- sessionKey: ctx.sessionKey,
167
- agentId: ctx.agentId,
168
- sessionId: ctx.sessionId,
169
- success: event.success,
170
- error: event.error,
171
- durationMs: event.durationMs,
172
- });
173
-
174
- if (!completedRaw) return;
175
-
176
- const completed = normalizeCompletedRun(completedRaw);
177
-
178
- // Score the run
179
- const score = qualityEngine.scoreRun(completed);
180
-
181
- // Persist run with score
182
- db.insertRun(completed, score);
183
-
184
- // Update metrics bucket
185
- metrics.recordRun(completed, score);
186
-
187
- // Track which learnings were injected into this run
188
- injector.trackRunAppliedIds(completed.runId);
189
- const appliedIds = injector.getAppliedIds(completed.runId);
190
-
191
- // Extract learnings (async: embeds content if bridge is available)
192
- const extractedIds = await extractor.extract(completed, score);
193
-
194
- // Infer graph edges from run scoring
195
- if (edgeInference) {
196
- edgeInference.onRunScored(completed.runId, appliedIds, extractedIds);
197
- }
198
-
199
- // Prune old runs if needed (learnings are preserved with run_id='__pruned__')
200
- db.pruneOldRuns(config.capture.maxRuns);
201
-
202
- // Prune genuinely stale learnings (unapplied, low-confidence, >90 days old)
203
- db.pruneStaleLearnings(90 * 24 * 60 * 60 * 1000);
204
-
205
- logger.debug?.(
206
- `[learning-loop] run ${completed.runId}: score=${score.score.toFixed(3)} ` +
207
- `(${completed.provider}/${completed.model}, ${completed.toolCalls.length} tool calls)`,
208
- );
209
- } catch (err) {
210
- logger.warn(`[learning-loop] agent_end handler failed: ${String(err)}`);
211
- }
212
- },
213
- { priority: 50 },
214
- );
215
-
216
- // -----------------------------------------------------------------------
217
- // message_received (priority 50) -- Detect implicit feedback
218
- // -----------------------------------------------------------------------
219
- api.on(
220
- "message_received",
221
- (event, ctx) => {
222
- try {
223
- const feedback = implicit.analyzeMessage(event.content, event.timestamp ?? Date.now());
224
-
225
- // Close the feedback loop: rescore the associated run
226
- if (feedback) {
227
- const runRow = db.getRun(feedback.runId);
228
- if (runRow) {
229
- const toolCalls = db.getToolCalls(feedback.runId);
230
- const completedRun = reconstructCompletedRun(runRow, toolCalls);
231
- const newScore = qualityEngine.rescoreWithFeedback(completedRun, {
232
- source: feedback.source as "explicit" | "implicit",
233
- score: feedback.score,
234
- });
235
- db.updateRunScore(feedback.runId, newScore.score);
236
- }
237
- }
238
- } catch (err) {
239
- logger.warn(`[learning-loop] message_received handler failed: ${String(err)}`);
240
- }
241
- },
242
- { priority: 50 },
243
- );
244
- }
@@ -1,73 +0,0 @@
1
- /**
2
- * LRU cache for context injection results.
3
- * Target: >85% hit rate, O(1) lookup.
4
- */
5
-
6
- export type CacheEntry<T> = {
7
- value: T;
8
- expiresAt: number;
9
- };
10
-
11
- export type LRUCache<T> = ReturnType<typeof createLRUCache<T>>;
12
-
13
- export function createLRUCache<T>(maxSize: number = 128, ttlMs: number = 60_000) {
14
- const cache = new Map<string, CacheEntry<T>>();
15
- let hits = 0;
16
- let misses = 0;
17
-
18
- function get(key: string): T | undefined {
19
- const entry = cache.get(key);
20
- if (!entry) {
21
- misses++;
22
- return undefined;
23
- }
24
-
25
- if (Date.now() > entry.expiresAt) {
26
- cache.delete(key);
27
- misses++;
28
- return undefined;
29
- }
30
-
31
- // Move to end (most recently used) by re-inserting
32
- cache.delete(key);
33
- cache.set(key, entry);
34
- hits++;
35
- return entry.value;
36
- }
37
-
38
- function set(key: string, value: T): void {
39
- // Evict oldest if at capacity
40
- if (cache.size >= maxSize) {
41
- const oldest = cache.keys().next().value;
42
- if (oldest !== undefined) {
43
- cache.delete(oldest);
44
- }
45
- }
46
-
47
- cache.set(key, {
48
- value,
49
- expiresAt: Date.now() + ttlMs,
50
- });
51
- }
52
-
53
- function invalidate(key: string): void {
54
- cache.delete(key);
55
- }
56
-
57
- function clear(): void {
58
- cache.clear();
59
- hits = 0;
60
- misses = 0;
61
- }
62
-
63
- function getHitRate(): number {
64
- const total = hits + misses;
65
- return total === 0 ? 0 : hits / total;
66
- }
67
-
68
- function getStats(): { size: number; hits: number; misses: number; hitRate: number } {
69
- return { size: cache.size, hits, misses, hitRate: getHitRate() };
70
- }
71
-
72
- return { get, set, invalidate, clear, getHitRate, getStats };
73
- }
@@ -1,104 +0,0 @@
1
- /**
2
- * Context injection for before_prompt_build hook.
3
- *
4
- * On each prompt build:
5
- * 1. Hash prompt -> check LRU cache (target >85% hit rate, O(1))
6
- * 2. Cache miss: query learnings via cosine similarity or FTS5 fallback
7
- * 3. Apply temporal decay and MMR rerank for diversity
8
- * 4. Format top N as <learnings> context block
9
- * 5. Return { prependContext }
10
- */
11
-
12
- import { hashText } from "../../../../src/memory/internal.js";
13
- import type { DatabaseManager } from "../db.js";
14
- import type { GraphRetrieval } from "../graph/graph-retrieval.js";
15
- import type { EmbeddingBridge } from "../learning/embedding-bridge.js";
16
- import type { LearningStore } from "../learning/learning-store.js";
17
- import { retrieveLearnings, type RetrievalResult } from "../learning/retrieval.js";
18
- import type { LearningLoopConfig, RunId } from "../types.js";
19
- import { createLRUCache } from "./cache.js";
20
- import { formatLearningsContext } from "./prompt-builder.js";
21
-
22
- export type ContextInjector = ReturnType<typeof createContextInjector>;
23
-
24
- export function createContextInjector(params: {
25
- db: DatabaseManager;
26
- learningStore: LearningStore;
27
- config: LearningLoopConfig;
28
- embeddingBridge?: EmbeddingBridge;
29
- graphRetrieval?: GraphRetrieval;
30
- }) {
31
- const { db, learningStore, config, embeddingBridge, graphRetrieval } = params;
32
- const cache = createLRUCache<string>(128, config.injection.cacheTtlMs);
33
- const appliedIdsMap = new Map<RunId, string[]>();
34
- let lastAppliedIds: string[] = [];
35
-
36
- /**
37
- * Generate context to prepend to the agent prompt.
38
- * Returns empty string if no relevant learnings exist.
39
- */
40
- async function getContext(prompt: string): Promise<string> {
41
- const promptKey = hashText(prompt);
42
-
43
- // Check cache first
44
- const cached = cache.get(promptKey);
45
- if (cached !== undefined) return cached;
46
-
47
- // Get query embedding if bridge is available
48
- let queryEmbedding: number[] | null = null;
49
- if (embeddingBridge?.available()) {
50
- queryEmbedding = await embeddingBridge.embed(prompt);
51
- }
52
-
53
- // Retrieve relevant learnings
54
- const results = retrieveLearnings({
55
- learningStore,
56
- config,
57
- queryEmbedding,
58
- queryText: prompt,
59
- graphRetrieval,
60
- });
61
-
62
- // Record applications and track applied IDs
63
- const appliedIds: string[] = [];
64
- for (const result of results) {
65
- learningStore.recordApplication(result.learning.id);
66
- appliedIds.push(result.learning.id);
67
- }
68
- lastAppliedIds = appliedIds;
69
-
70
- // Format context
71
- const context = formatLearningsContext(results, config);
72
-
73
- // Cache result
74
- cache.set(promptKey, context);
75
-
76
- return context;
77
- }
78
-
79
- /**
80
- * Associate the most recently injected learning IDs with a run ID.
81
- */
82
- function trackRunAppliedIds(runId: RunId): void {
83
- if (lastAppliedIds.length > 0) {
84
- appliedIdsMap.set(runId, [...lastAppliedIds]);
85
- }
86
- }
87
-
88
- /**
89
- * Get the learning IDs that were injected into a specific run.
90
- */
91
- function getAppliedIds(runId: RunId): string[] {
92
- return appliedIdsMap.get(runId) ?? [];
93
- }
94
-
95
- function getCacheStats() {
96
- return cache.getStats();
97
- }
98
-
99
- function clearCache(): void {
100
- cache.clear();
101
- }
102
-
103
- return { getContext, trackRunAppliedIds, getAppliedIds, getCacheStats, clearCache };
104
- }
@@ -1,43 +0,0 @@
1
- /**
2
- * Format retrieved learnings into context text for prompt injection.
3
- */
4
-
5
- import type { RetrievalResult } from "../learning/retrieval.js";
6
- import type { LearningLoopConfig } from "../types.js";
7
-
8
- /**
9
- * Format learnings into a context block that will be prepended to the agent prompt.
10
- *
11
- * Respects maxTokens by estimating token count (chars / 4) and truncating.
12
- * Returns empty string if no learnings pass the threshold.
13
- */
14
- export function formatLearningsContext(
15
- results: RetrievalResult[],
16
- config: LearningLoopConfig,
17
- ): string {
18
- if (results.length === 0) return "";
19
-
20
- const maxTokens = config.injection.maxTokens;
21
- const lines: string[] = [];
22
- let estimatedTokens = 0;
23
-
24
- // Header
25
- const header = "<learnings>";
26
- const footer = "</learnings>";
27
- estimatedTokens += (header.length + footer.length) / 4;
28
-
29
- for (const result of results) {
30
- const contested = result.contested ? " [CONTESTED]" : "";
31
- const line = `- [${result.learning.category}] ${result.learning.content}${contested}`;
32
- const lineTokens = line.length / 4;
33
-
34
- if (estimatedTokens + lineTokens > maxTokens) break;
35
-
36
- lines.push(line);
37
- estimatedTokens += lineTokens;
38
- }
39
-
40
- if (lines.length === 0) return "";
41
-
42
- return `${header}\n${lines.join("\n")}\n${footer}`;
43
- }
@@ -1,54 +0,0 @@
1
- /**
2
- * Bridge to the existing embedding provider system.
3
- * Uses the same multi-provider system (OpenAI, Gemini, Voyage, local ONNX)
4
- * that the memory system uses.
5
- */
6
-
7
- import type { EmbeddingProvider } from "../../../../src/memory/embeddings.js";
8
- import type { PluginLogger } from "../../../../src/plugins/types.js";
9
-
10
- export type EmbeddingBridge = {
11
- embed: (text: string) => Promise<number[] | null>;
12
- embedBatch: (texts: string[]) => Promise<Array<number[] | null>>;
13
- available: () => boolean;
14
- };
15
-
16
- /**
17
- * Create an embedding bridge that wraps an existing EmbeddingProvider.
18
- * If no provider is available, embed() returns null gracefully.
19
- */
20
- export function createEmbeddingBridge(params: {
21
- provider: EmbeddingProvider | null;
22
- logger: PluginLogger;
23
- }): EmbeddingBridge {
24
- const { provider, logger } = params;
25
-
26
- async function embed(text: string): Promise<number[] | null> {
27
- if (!provider) return null;
28
-
29
- try {
30
- return await provider.embedQuery(text);
31
- } catch (err) {
32
- logger.warn(`[learning-loop] embedding failed: ${String(err)}`);
33
- return null;
34
- }
35
- }
36
-
37
- async function embedBatch(texts: string[]): Promise<Array<number[] | null>> {
38
- if (!provider) return texts.map(() => null);
39
-
40
- try {
41
- const results = await provider.embedBatch(texts);
42
- return results;
43
- } catch (err) {
44
- logger.warn(`[learning-loop] batch embedding failed: ${String(err)}`);
45
- return texts.map(() => null);
46
- }
47
- }
48
-
49
- function available(): boolean {
50
- return provider !== null;
51
- }
52
-
53
- return { embed, embedBatch, available };
54
- }