@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,217 +0,0 @@
1
- /**
2
- * Deterministic pattern extraction from scored runs.
3
- * No LLM calls -- all patterns are derived from mathematical analysis
4
- * of run history and tool call traces.
5
- */
6
-
7
- import type { DatabaseManager } from "../db.js";
8
- import type { EdgeInference } from "../graph/edge-inference.js";
9
- import { getEWMAValue } from "../math/ewma.js";
10
- import type {
11
- CompletedRun,
12
- QualityScore,
13
- LearningLoopConfig,
14
- LearningCategory,
15
- RunRow,
16
- } from "../types.js";
17
- import type { EmbeddingBridge } from "./embedding-bridge.js";
18
- import type { LearningStore } from "./learning-store.js";
19
-
20
- export type LearningExtractor = ReturnType<typeof createLearningExtractor>;
21
-
22
- type ExtractedLearning = {
23
- category: LearningCategory;
24
- content: string;
25
- confidence: number;
26
- };
27
-
28
- export function createLearningExtractor(params: {
29
- db: DatabaseManager;
30
- learningStore: LearningStore;
31
- config: LearningLoopConfig;
32
- edgeInference?: EdgeInference;
33
- embeddingBridge?: EmbeddingBridge;
34
- }) {
35
- const { db, learningStore, config, edgeInference, embeddingBridge } = params;
36
-
37
- /**
38
- * Extract learnings from a completed, scored run.
39
- * Returns the IDs of newly created learnings.
40
- */
41
- async function extract(run: CompletedRun, score: QualityScore): Promise<string[]> {
42
- const learnings: ExtractedLearning[] = [];
43
-
44
- learnings.push(...extractToolPatterns(run, score));
45
- learnings.push(...extractErrorRecovery(run));
46
- learnings.push(...extractModelAffinity(run, score));
47
- learnings.push(...extractAntiPatterns(run));
48
-
49
- // Batch-embed all learning contents if bridge is available
50
- const contents = learnings.map((l) => l.content);
51
- const embeddings =
52
- embeddingBridge && contents.length > 0
53
- ? await embeddingBridge.embedBatch(contents)
54
- : contents.map(() => null);
55
-
56
- const ids: string[] = [];
57
- for (let i = 0; i < learnings.length; i++) {
58
- const learning = learnings[i]!;
59
- const id = learningStore.addLearning({
60
- runId: run.runId,
61
- category: learning.category,
62
- content: learning.content,
63
- embedding: embeddings[i] ?? null,
64
- confidence: learning.confidence,
65
- });
66
- if (id) {
67
- ids.push(id);
68
- // Infer graph edges for the newly created learning
69
- if (edgeInference) {
70
- const record = learningStore.getLearning(id);
71
- if (record) {
72
- edgeInference.onLearningCreated(record, run.runId);
73
- }
74
- }
75
- }
76
- }
77
-
78
- return ids;
79
- }
80
-
81
- /**
82
- * Tool Pattern: Same tool set (order-independent) succeeds 3+ times with score >= 0.7.
83
- * Uses Jaccard similarity >= 0.8 on tool sets instead of exact sequence matching.
84
- */
85
- function extractToolPatterns(run: CompletedRun, score: QualityScore): ExtractedLearning[] {
86
- if (score.score < 0.7 || run.toolCalls.length < 2) return [];
87
-
88
- const toolSet = new Set(run.toolCalls.map((tc) => tc.toolName));
89
-
90
- const recentRuns = db.getRunsByModel(run.provider, run.model, 50);
91
- let matchCount = 0;
92
-
93
- for (const prevRow of recentRuns) {
94
- if (prevRow.run_id === run.runId) continue;
95
- if ((prevRow.quality_score ?? 0) < 0.7) continue;
96
-
97
- const prevToolCalls = db.getToolCalls(prevRow.run_id);
98
- const prevToolSet = new Set(prevToolCalls.map((tc) => tc.tool_name));
99
-
100
- // Jaccard similarity on tool sets
101
- const intersection = [...toolSet].filter((t) => prevToolSet.has(t)).length;
102
- const union = new Set([...toolSet, ...prevToolSet]).size;
103
- const jaccard = union > 0 ? intersection / union : 0;
104
-
105
- if (jaccard >= 0.8) matchCount++;
106
- }
107
-
108
- if (matchCount < 2) return []; // Need 3+ total (including current)
109
-
110
- const uniqueTools = [...toolSet].sort();
111
- return [
112
- {
113
- category: "tool_pattern",
114
- content: `Tool combination [${uniqueTools.join(", ")}] is effective for tasks handled by ${run.provider}/${run.model}. Used successfully ${matchCount + 1} times.`,
115
- confidence: Math.min(1.0, 0.5 + matchCount * 0.1),
116
- },
117
- ];
118
- }
119
-
120
- /**
121
- * Error Recovery: Tool error followed by successful retry with different params
122
- */
123
- function extractErrorRecovery(run: CompletedRun): ExtractedLearning[] {
124
- const results: ExtractedLearning[] = [];
125
-
126
- for (let i = 1; i < run.toolCalls.length; i++) {
127
- const prev = run.toolCalls[i - 1]!;
128
- const curr = run.toolCalls[i]!;
129
-
130
- if (
131
- !prev.success &&
132
- curr.success &&
133
- prev.toolName === curr.toolName &&
134
- prev.paramHash !== curr.paramHash
135
- ) {
136
- results.push({
137
- category: "error_recovery",
138
- content: `Tool "${prev.toolName}" failed with "${prev.error ?? "unknown error"}", retry with different parameters succeeded.`,
139
- confidence: 0.7,
140
- });
141
- }
142
- }
143
-
144
- return results;
145
- }
146
-
147
- /**
148
- * Model Affinity: Model's EWMA quality > global mean + 1 std dev
149
- */
150
- function extractModelAffinity(run: CompletedRun, score: QualityScore): ExtractedLearning[] {
151
- const leaderboard = db.getModelLeaderboard();
152
- if (leaderboard.length < 2) return [];
153
-
154
- const globalSum = leaderboard.reduce((s, m) => s + m.avgQuality, 0);
155
- const globalMean = globalSum / leaderboard.length;
156
- const variance =
157
- leaderboard.reduce((s, m) => s + (m.avgQuality - globalMean) ** 2, 0) / leaderboard.length;
158
- const stdDev = Math.sqrt(variance);
159
-
160
- if (stdDev === 0) return [];
161
-
162
- const modelEntry = leaderboard.find(
163
- (m) => m.provider === run.provider && m.model === run.model,
164
- );
165
- if (!modelEntry || modelEntry.runCount < 5) return [];
166
-
167
- if (modelEntry.avgQuality > globalMean + stdDev) {
168
- return [
169
- {
170
- category: "model_affinity",
171
- content: `Model ${run.provider}/${run.model} performs above average (quality: ${modelEntry.avgQuality.toFixed(3)} vs global mean: ${globalMean.toFixed(3)}).`,
172
- confidence: Math.min(1.0, 0.5 + modelEntry.runCount * 0.02),
173
- },
174
- ];
175
- }
176
-
177
- return [];
178
- }
179
-
180
- /**
181
- * Anti-Pattern: Tool error rate > 50% over 5+ runs
182
- */
183
- function extractAntiPatterns(run: CompletedRun): ExtractedLearning[] {
184
- const results: ExtractedLearning[] = [];
185
-
186
- // Aggregate tool error rates from recent runs
187
- const recentRuns = db.getRecentRuns(50);
188
- const toolStats = new Map<string, { total: number; errors: number; lastError: string }>();
189
-
190
- for (const row of recentRuns) {
191
- const toolCalls = db.getToolCalls(row.run_id);
192
- for (const tc of toolCalls) {
193
- const stat = toolStats.get(tc.tool_name) ?? { total: 0, errors: 0, lastError: "" };
194
- stat.total++;
195
- if (!tc.success) {
196
- stat.errors++;
197
- stat.lastError = tc.error ?? "unknown error";
198
- }
199
- toolStats.set(tc.tool_name, stat);
200
- }
201
- }
202
-
203
- for (const [toolName, stat] of toolStats) {
204
- if (stat.total >= 5 && stat.errors / stat.total > 0.5) {
205
- results.push({
206
- category: "anti_pattern",
207
- content: `Tool "${toolName}" has a high error rate (${stat.errors}/${stat.total} = ${((stat.errors / stat.total) * 100).toFixed(0)}%). Common error: "${stat.lastError}".`,
208
- confidence: Math.min(1.0, 0.5 + stat.total * 0.02),
209
- });
210
- }
211
- }
212
-
213
- return results;
214
- }
215
-
216
- return { extract };
217
- }
@@ -1,158 +0,0 @@
1
- /**
2
- * CRUD operations for learning records.
3
- * Handles storage, retrieval, deduplication, and embedding management.
4
- */
5
-
6
- import crypto from "node:crypto";
7
- import { buildFtsQuery } from "../../../../src/memory/hybrid.js";
8
- import { cosineSimilarity } from "../../../../src/memory/internal.js";
9
- import type { DatabaseManager } from "../db.js";
10
- import type { GraphStore } from "../graph/graph-store.js";
11
- import type { LearningRecord, LearningRow, LearningCategory } from "../types.js";
12
-
13
- export type LearningStore = ReturnType<typeof createLearningStore>;
14
-
15
- const DEDUP_THRESHOLD = 0.92;
16
-
17
- function rowToRecord(row: LearningRow): LearningRecord {
18
- return {
19
- id: row.id,
20
- runId: row.run_id,
21
- category: row.category as LearningCategory,
22
- content: row.content,
23
- embedding: row.embedding ? (JSON.parse(row.embedding) as number[]) : null,
24
- confidence: row.confidence,
25
- appliedCount: row.applied_count,
26
- createdAt: row.created_at,
27
- updatedAt: row.updated_at,
28
- };
29
- }
30
-
31
- export function createLearningStore(params: { db: DatabaseManager; graphStore?: GraphStore }) {
32
- const { db, graphStore } = params;
33
-
34
- function generateId(): string {
35
- return `lrn_${Date.now()}_${crypto.randomBytes(4).toString("hex")}`;
36
- }
37
-
38
- /**
39
- * Check if a learning with similar content already exists.
40
- * Uses cosine similarity on embeddings if available, otherwise exact match.
41
- */
42
- function isDuplicate(content: string, embedding: number[] | null): boolean {
43
- if (!embedding) {
44
- // Fallback: check exact content match
45
- const all = db.getAllLearnings(500);
46
- return all.some((row) => row.content === content);
47
- }
48
-
49
- // Check cosine similarity against existing embeddings
50
- const all = db.getAllLearnings(500);
51
- for (const row of all) {
52
- if (!row.embedding) continue;
53
- const existing = JSON.parse(row.embedding) as number[];
54
- if (cosineSimilarity(embedding, existing) >= DEDUP_THRESHOLD) {
55
- return true;
56
- }
57
- }
58
-
59
- return false;
60
- }
61
-
62
- /**
63
- * Add a new learning record, with deduplication.
64
- * Returns the learning ID if created, or null if deduplicated.
65
- */
66
- function addLearning(params: {
67
- runId: string;
68
- category: LearningCategory;
69
- content: string;
70
- embedding: number[] | null;
71
- confidence: number;
72
- }): string | null {
73
- if (isDuplicate(params.content, params.embedding)) {
74
- return null;
75
- }
76
-
77
- const now = Date.now();
78
- const record: LearningRecord = {
79
- id: generateId(),
80
- runId: params.runId,
81
- category: params.category,
82
- content: params.content,
83
- embedding: params.embedding,
84
- confidence: params.confidence,
85
- appliedCount: 0,
86
- createdAt: now,
87
- updatedAt: now,
88
- };
89
-
90
- db.insertLearning(record);
91
- return record.id;
92
- }
93
-
94
- function getLearning(id: string): LearningRecord | null {
95
- const row = db.getLearning(id);
96
- return row ? rowToRecord(row) : null;
97
- }
98
-
99
- function listLearnings(opts?: { category?: LearningCategory; limit?: number }): LearningRecord[] {
100
- const rows = opts?.category
101
- ? db.getLearningsByCategory(opts.category, opts.limit ?? 100)
102
- : db.getAllLearnings(opts?.limit ?? 100);
103
- return rows.map(rowToRecord);
104
- }
105
-
106
- function searchByText(query: string, limit: number = 20): LearningRecord[] {
107
- const ftsQuery = buildFtsQuery(query);
108
- if (!ftsQuery) return [];
109
-
110
- const rows = db.searchLearningsFts(ftsQuery, limit);
111
- return rows.map(rowToRecord);
112
- }
113
-
114
- /**
115
- * Retrieve learnings by vector similarity.
116
- * Falls back to FTS if no embeddings are available.
117
- */
118
- function searchByVector(
119
- queryEmbedding: number[],
120
- limit: number = 10,
121
- minScore: number = 0.3,
122
- ): Array<LearningRecord & { score: number }> {
123
- const all = db.getAllLearnings(1000);
124
- const results: Array<LearningRecord & { score: number }> = [];
125
-
126
- for (const row of all) {
127
- if (!row.embedding) continue;
128
- const embedding = JSON.parse(row.embedding) as number[];
129
- const score = cosineSimilarity(queryEmbedding, embedding);
130
- if (score >= minScore) {
131
- results.push({ ...rowToRecord(row), score });
132
- }
133
- }
134
-
135
- results.sort((a, b) => b.score - a.score);
136
- return results.slice(0, limit);
137
- }
138
-
139
- function recordApplication(id: string): void {
140
- db.incrementAppliedCount(id);
141
- }
142
-
143
- function removeLearning(id: string): void {
144
- graphStore?.removeEdgesFor(id);
145
- db.deleteLearning(id);
146
- }
147
-
148
- return {
149
- addLearning,
150
- getLearning,
151
- listLearnings,
152
- searchByText,
153
- searchByVector,
154
- recordApplication,
155
- removeLearning,
156
- isDuplicate,
157
- };
158
- }
@@ -1,87 +0,0 @@
1
- /**
2
- * Learning retrieval for context injection.
3
- * Supports vector similarity search with FTS5 fallback.
4
- */
5
-
6
- import { mmrRerank, type MMRItem } from "../../../../src/memory/mmr.js";
7
- import { calculateTemporalDecayMultiplier } from "../../../../src/memory/temporal-decay.js";
8
- import type { GraphRetrieval } from "../graph/graph-retrieval.js";
9
- import type { LearningRecord, LearningLoopConfig } from "../types.js";
10
- import type { LearningStore } from "./learning-store.js";
11
-
12
- export type RetrievalResult = {
13
- learning: LearningRecord;
14
- score: number;
15
- decayedScore: number;
16
- contested?: boolean;
17
- };
18
-
19
- /**
20
- * Retrieve relevant learnings for a given query.
21
- *
22
- * 1. Vector search (if embedding available) or FTS fallback
23
- * 2. Apply temporal decay
24
- * 3. MMR rerank for diversity
25
- * 4. Return top N
26
- */
27
- export function retrieveLearnings(params: {
28
- learningStore: LearningStore;
29
- config: LearningLoopConfig;
30
- queryEmbedding: number[] | null;
31
- queryText: string;
32
- limit?: number;
33
- graphRetrieval?: GraphRetrieval;
34
- }): RetrievalResult[] {
35
- const { learningStore, config, queryEmbedding, queryText, graphRetrieval } = params;
36
- const limit = params.limit ?? config.injection.maxLearnings;
37
- const minRelevance = config.injection.minRelevance;
38
- const halfLifeDays = config.decay.halfLifeDays;
39
- const nowMs = Date.now();
40
-
41
- // Step 1: Retrieve candidates
42
- let candidates: Array<LearningRecord & { score: number }>;
43
-
44
- if (queryEmbedding) {
45
- candidates = learningStore.searchByVector(queryEmbedding, limit * 3, minRelevance * 0.5);
46
- } else {
47
- // FTS fallback
48
- const textResults = learningStore.searchByText(queryText, limit * 3);
49
- candidates = textResults.map((r, i) => ({
50
- ...r,
51
- score: 1.0 - i * (0.8 / Math.max(1, textResults.length)),
52
- }));
53
- }
54
-
55
- if (candidates.length === 0) return [];
56
-
57
- // Step 2: Apply temporal decay
58
- const DAY_MS = 24 * 60 * 60 * 1000;
59
- const withDecay = candidates.map((c) => {
60
- const ageInDays = (nowMs - c.updatedAt) / DAY_MS;
61
- const decayMultiplier = calculateTemporalDecayMultiplier({ ageInDays, halfLifeDays });
62
- const decayedScore = c.score * decayMultiplier;
63
- return { learning: c, score: c.score, decayedScore };
64
- });
65
-
66
- // Filter by minimum relevance after decay
67
- const filtered = withDecay.filter((r) => r.decayedScore >= minRelevance);
68
- if (filtered.length === 0) return [];
69
-
70
- // Step 3: Graph expansion (if available)
71
- if (graphRetrieval) {
72
- return graphRetrieval.expandWithGraph(filtered, limit);
73
- }
74
-
75
- // Step 4: MMR rerank for diversity
76
- const mmrItems: (MMRItem & { original: RetrievalResult })[] = filtered.map((r) => ({
77
- id: r.learning.id,
78
- score: r.decayedScore,
79
- content: r.learning.content,
80
- original: r,
81
- }));
82
-
83
- const reranked = mmrRerank(mmrItems, { enabled: true, lambda: 0.7 });
84
-
85
- // Step 5: Take top N
86
- return reranked.slice(0, limit).map((item) => item.original);
87
- }
@@ -1,62 +0,0 @@
1
- /**
2
- * Wilson Score Interval for binomial proportions.
3
- *
4
- * Provides a confidence interval for a proportion derived from a binomial
5
- * distribution. Used to rank learnings by confidence: items with more
6
- * observations and higher success rates rank higher.
7
- *
8
- * Formula (lower bound, 95% CI):
9
- * (p + z^2/(2n) - z * sqrt(p*(1-p)/n + z^2/(4n^2))) / (1 + z^2/n)
10
- *
11
- * Complexity: O(1)
12
- */
13
-
14
- const Z_95 = 1.96;
15
-
16
- /**
17
- * Compute the lower bound of the Wilson score interval.
18
- *
19
- * @param successes - Number of positive outcomes
20
- * @param total - Total number of trials
21
- * @param z - Z-score for confidence level (default: 1.96 for 95%)
22
- * @returns Lower bound of the confidence interval in [0, 1]
23
- */
24
- export function wilsonScoreLowerBound(successes: number, total: number, z: number = Z_95): number {
25
- if (total <= 0) return 0;
26
-
27
- const p = successes / total;
28
- const z2 = z * z;
29
- const denominator = 1 + z2 / total;
30
-
31
- const numerator =
32
- p + z2 / (2 * total) - z * Math.sqrt((p * (1 - p)) / total + z2 / (4 * total * total));
33
-
34
- return Math.max(0, Math.min(1, numerator / denominator));
35
- }
36
-
37
- /**
38
- * Compute both bounds of the Wilson score interval.
39
- *
40
- * @param successes - Number of positive outcomes
41
- * @param total - Total number of trials
42
- * @param z - Z-score for confidence level (default: 1.96 for 95%)
43
- * @returns [lowerBound, upperBound] each in [0, 1]
44
- */
45
- export function wilsonScoreInterval(
46
- successes: number,
47
- total: number,
48
- z: number = Z_95,
49
- ): [number, number] {
50
- if (total <= 0) return [0, 0];
51
-
52
- const p = successes / total;
53
- const z2 = z * z;
54
- const denominator = 1 + z2 / total;
55
- const center = p + z2 / (2 * total);
56
- const spread = z * Math.sqrt((p * (1 - p)) / total + z2 / (4 * total * total));
57
-
58
- const lower = Math.max(0, (center - spread) / denominator);
59
- const upper = Math.min(1, (center + spread) / denominator);
60
-
61
- return [lower, upper];
62
- }
@@ -1,51 +0,0 @@
1
- /**
2
- * Exponentially Weighted Moving Average (EWMA).
3
- *
4
- * Maintains a running weighted average where recent observations
5
- * contribute more than older ones. O(1) per update.
6
- *
7
- * Formula: S_t = alpha * x_t + (1 - alpha) * S_{t-1}
8
- */
9
-
10
- export type EWMAState = {
11
- value: number;
12
- count: number;
13
- };
14
-
15
- const DEFAULT_ALPHA = 0.1;
16
-
17
- export function createEWMA(alpha: number = DEFAULT_ALPHA): EWMAState {
18
- return { value: 0, count: 0 };
19
- }
20
-
21
- /**
22
- * Update EWMA with a new observation. Returns a new state (immutable).
23
- * First observation initializes directly; subsequent observations use exponential weighting.
24
- *
25
- * Complexity: O(1)
26
- */
27
- export function updateEWMA(
28
- state: EWMAState,
29
- observation: number,
30
- alpha: number = DEFAULT_ALPHA,
31
- ): EWMAState {
32
- if (!Number.isFinite(observation)) return state;
33
-
34
- const clampedAlpha = Math.max(0, Math.min(1, alpha));
35
-
36
- if (state.count === 0) {
37
- return { value: observation, count: 1 };
38
- }
39
-
40
- return {
41
- value: clampedAlpha * observation + (1 - clampedAlpha) * state.value,
42
- count: state.count + 1,
43
- };
44
- }
45
-
46
- /**
47
- * Get the current EWMA value, or a fallback if no observations exist.
48
- */
49
- export function getEWMAValue(state: EWMAState, fallback: number = 0): number {
50
- return state.count === 0 ? fallback : state.value;
51
- }
@@ -1,42 +0,0 @@
1
- /**
2
- * Confidence-weighted arithmetic mean combiner.
3
- *
4
- * Combines multiple independent signals into a single score, where each
5
- * signal contributes proportionally to its weight AND confidence.
6
- *
7
- * Formula: score = sum(w_i * c_i * s_i) / sum(w_i * c_i)
8
- *
9
- * Complexity: O(k) where k = number of signals
10
- */
11
-
12
- export type WeightedSignal = {
13
- value: number;
14
- weight: number;
15
- confidence: number;
16
- };
17
-
18
- /**
19
- * Compute a confidence-weighted score from multiple signals.
20
- *
21
- * @param signals - Array of signals with value in [0,1], weight > 0, confidence in [0,1]
22
- * @returns Combined score in [0, 1], or 0 if no valid signals
23
- */
24
- export function computeWeightedScore(signals: WeightedSignal[]): number {
25
- let numerator = 0;
26
- let denominator = 0;
27
-
28
- for (const signal of signals) {
29
- if (signal.confidence <= 0 || signal.weight <= 0) continue;
30
- if (!Number.isFinite(signal.value)) continue;
31
-
32
- const clampedValue = Math.max(0, Math.min(1, signal.value));
33
- const clampedConfidence = Math.max(0, Math.min(1, signal.confidence));
34
- const effectiveWeight = signal.weight * clampedConfidence;
35
-
36
- numerator += effectiveWeight * clampedValue;
37
- denominator += effectiveWeight;
38
- }
39
-
40
- if (denominator === 0) return 0;
41
- return numerator / denominator;
42
- }