@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,176 +0,0 @@
1
- /**
2
- * SQLite schema for the learning loop extension.
3
- * All tables use WAL mode for concurrent read/write performance.
4
- */
5
-
6
- import type { DatabaseSync } from "node:sqlite";
7
-
8
- export function initializeSchema(db: DatabaseSync): void {
9
- db.exec("PRAGMA journal_mode = WAL");
10
- db.exec("PRAGMA busy_timeout = 5000");
11
- db.exec("PRAGMA synchronous = NORMAL");
12
-
13
- db.exec(`
14
- CREATE TABLE IF NOT EXISTS runs (
15
- run_id TEXT PRIMARY KEY,
16
- session_id TEXT NOT NULL,
17
- session_key TEXT NOT NULL,
18
- agent_id TEXT NOT NULL,
19
- provider TEXT NOT NULL,
20
- model TEXT NOT NULL,
21
- prompt_hash TEXT NOT NULL,
22
- prompt_length INTEGER NOT NULL DEFAULT 0,
23
- response_length INTEGER NOT NULL DEFAULT 0,
24
- response_tool_call_count INTEGER NOT NULL DEFAULT 0,
25
- usage_input INTEGER NOT NULL DEFAULT 0,
26
- usage_output INTEGER NOT NULL DEFAULT 0,
27
- usage_cache_read INTEGER NOT NULL DEFAULT 0,
28
- usage_cache_write INTEGER NOT NULL DEFAULT 0,
29
- usage_total INTEGER NOT NULL DEFAULT 0,
30
- success INTEGER NOT NULL DEFAULT 0,
31
- error TEXT,
32
- duration_ms INTEGER NOT NULL DEFAULT 0,
33
- quality_score REAL,
34
- algorithm_version INTEGER,
35
- started_at INTEGER NOT NULL,
36
- completed_at INTEGER NOT NULL
37
- )
38
- `);
39
-
40
- db.exec(`
41
- CREATE TABLE IF NOT EXISTS tool_calls (
42
- id INTEGER PRIMARY KEY AUTOINCREMENT,
43
- run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
44
- tool_name TEXT NOT NULL,
45
- duration_ms INTEGER,
46
- success INTEGER NOT NULL DEFAULT 1,
47
- error TEXT,
48
- param_hash TEXT NOT NULL
49
- )
50
- `);
51
-
52
- db.exec(`
53
- CREATE TABLE IF NOT EXISTS quality_signals (
54
- id INTEGER PRIMARY KEY AUTOINCREMENT,
55
- run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
56
- signal_name TEXT NOT NULL,
57
- value REAL NOT NULL,
58
- confidence REAL NOT NULL,
59
- weight REAL NOT NULL
60
- )
61
- `);
62
-
63
- db.exec(`
64
- CREATE TABLE IF NOT EXISTS learnings (
65
- id TEXT PRIMARY KEY,
66
- run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
67
- category TEXT NOT NULL,
68
- content TEXT NOT NULL,
69
- embedding TEXT,
70
- confidence REAL NOT NULL DEFAULT 0.5,
71
- applied_count INTEGER NOT NULL DEFAULT 0,
72
- created_at INTEGER NOT NULL,
73
- updated_at INTEGER NOT NULL
74
- )
75
- `);
76
-
77
- db.exec(`
78
- CREATE TABLE IF NOT EXISTS feedback (
79
- id TEXT PRIMARY KEY,
80
- run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
81
- source TEXT NOT NULL,
82
- score REAL NOT NULL,
83
- created_at INTEGER NOT NULL
84
- )
85
- `);
86
-
87
- db.exec(`
88
- CREATE TABLE IF NOT EXISTS metrics_buckets (
89
- provider TEXT NOT NULL,
90
- model TEXT NOT NULL,
91
- bucket_hour TEXT NOT NULL,
92
- run_count INTEGER NOT NULL DEFAULT 0,
93
- success_count INTEGER NOT NULL DEFAULT 0,
94
- quality_sum REAL NOT NULL DEFAULT 0,
95
- quality_sum_sq REAL NOT NULL DEFAULT 0,
96
- latency_sum REAL NOT NULL DEFAULT 0,
97
- latency_sum_sq REAL NOT NULL DEFAULT 0,
98
- token_input_sum INTEGER NOT NULL DEFAULT 0,
99
- token_output_sum INTEGER NOT NULL DEFAULT 0,
100
- PRIMARY KEY (provider, model, bucket_hour)
101
- )
102
- `);
103
-
104
- db.exec(`
105
- CREATE TABLE IF NOT EXISTS ewma_state (
106
- provider TEXT NOT NULL,
107
- model TEXT NOT NULL,
108
- metric TEXT NOT NULL,
109
- value REAL NOT NULL DEFAULT 0,
110
- count INTEGER NOT NULL DEFAULT 0,
111
- PRIMARY KEY (provider, model, metric)
112
- )
113
- `);
114
-
115
- // --- Graph tables ---
116
-
117
- db.exec(`
118
- CREATE TABLE IF NOT EXISTS learning_edges (
119
- id INTEGER PRIMARY KEY AUTOINCREMENT,
120
- source_id TEXT NOT NULL,
121
- target_id TEXT NOT NULL,
122
- edge_type TEXT NOT NULL CHECK(edge_type IN ('T','S','C','U','X','R')),
123
- weight REAL NOT NULL DEFAULT 1.0,
124
- created_at INTEGER NOT NULL,
125
- UNIQUE(source_id, target_id, edge_type)
126
- )
127
- `);
128
-
129
- db.exec(`
130
- CREATE TABLE IF NOT EXISTS centrality_scores (
131
- learning_id TEXT PRIMARY KEY,
132
- score REAL NOT NULL DEFAULT 0.0,
133
- updated_at INTEGER NOT NULL
134
- )
135
- `);
136
-
137
- // Indexes for efficient queries
138
- db.exec(`CREATE INDEX IF NOT EXISTS idx_runs_provider_model ON runs(provider, model)`);
139
- db.exec(`CREATE INDEX IF NOT EXISTS idx_runs_completed_at ON runs(completed_at)`);
140
- db.exec(`CREATE INDEX IF NOT EXISTS idx_runs_quality_score ON runs(quality_score)`);
141
- db.exec(`CREATE INDEX IF NOT EXISTS idx_tool_calls_run_id ON tool_calls(run_id)`);
142
- db.exec(`CREATE INDEX IF NOT EXISTS idx_quality_signals_run_id ON quality_signals(run_id)`);
143
- db.exec(`CREATE INDEX IF NOT EXISTS idx_learnings_run_id ON learnings(run_id)`);
144
- db.exec(`CREATE INDEX IF NOT EXISTS idx_learnings_category ON learnings(category)`);
145
- db.exec(`CREATE INDEX IF NOT EXISTS idx_feedback_run_id ON feedback(run_id)`);
146
- db.exec(`CREATE INDEX IF NOT EXISTS idx_edges_source ON learning_edges(source_id)`);
147
- db.exec(`CREATE INDEX IF NOT EXISTS idx_edges_target ON learning_edges(target_id)`);
148
- db.exec(`CREATE INDEX IF NOT EXISTS idx_edges_type ON learning_edges(edge_type)`);
149
-
150
- // FTS5 virtual table for text search over learnings
151
- db.exec(`
152
- CREATE VIRTUAL TABLE IF NOT EXISTS learnings_fts USING fts5(
153
- content,
154
- content='learnings',
155
- content_rowid='rowid'
156
- )
157
- `);
158
-
159
- // Triggers to keep FTS in sync
160
- db.exec(`
161
- CREATE TRIGGER IF NOT EXISTS learnings_ai AFTER INSERT ON learnings BEGIN
162
- INSERT INTO learnings_fts(rowid, content) VALUES (new.rowid, new.content);
163
- END
164
- `);
165
- db.exec(`
166
- CREATE TRIGGER IF NOT EXISTS learnings_ad AFTER DELETE ON learnings BEGIN
167
- INSERT INTO learnings_fts(learnings_fts, rowid, content) VALUES('delete', old.rowid, old.content);
168
- END
169
- `);
170
- db.exec(`
171
- CREATE TRIGGER IF NOT EXISTS learnings_au AFTER UPDATE ON learnings BEGIN
172
- INSERT INTO learnings_fts(learnings_fts, rowid, content) VALUES('delete', old.rowid, old.content);
173
- INSERT INTO learnings_fts(rowid, content) VALUES (new.rowid, new.content);
174
- END
175
- `);
176
- }
@@ -1,32 +0,0 @@
1
- /**
2
- * Signal normalization and combination.
3
- * Wraps the weighted scorer with signal-specific logic.
4
- */
5
-
6
- import { computeWeightedScore } from "../math/weighted-scorer.js";
7
- import type { QualitySignal, QualityScore } from "../types.js";
8
- import { ALGORITHM_VERSION } from "../types.js";
9
-
10
- /**
11
- * Combine quality signals into a single score using confidence-weighted
12
- * arithmetic mean.
13
- *
14
- * Formula: score = sum(w_i * c_i * s_i) / sum(w_i * c_i)
15
- *
16
- * Complexity: O(k) where k = number of signals (5)
17
- */
18
- export function combineSignals(signals: QualitySignal[]): QualityScore {
19
- const score = computeWeightedScore(
20
- signals.map((s) => ({
21
- value: s.value,
22
- weight: s.weight,
23
- confidence: s.confidence,
24
- })),
25
- );
26
-
27
- return {
28
- score,
29
- signals,
30
- algorithmVersion: ALGORITHM_VERSION,
31
- };
32
- }
@@ -1,78 +0,0 @@
1
- /**
2
- * Quality scoring engine.
3
- * Orchestrates signal extraction, EWMA updates, and score combination.
4
- * Purely mathematical, deterministic, zero LLM calls.
5
- */
6
-
7
- import type { DatabaseManager } from "../db.js";
8
- import type { CompletedRun, LearningLoopConfig, QualityScore, FeedbackRecord } from "../types.js";
9
- import { combineSignals } from "./normalization.js";
10
- import {
11
- extractTaskCompletion,
12
- extractToolEfficiency,
13
- extractResponseAppropriateness,
14
- extractLatencyRelative,
15
- extractUserFeedback,
16
- } from "./signal-extractors.js";
17
-
18
- export type QualityEngine = ReturnType<typeof createQualityEngine>;
19
-
20
- export function createQualityEngine(params: { config: LearningLoopConfig; db: DatabaseManager }) {
21
- const { config, db } = params;
22
- const weights = config.scoring.weights;
23
-
24
- /**
25
- * Score a completed run. Updates EWMA state for latency tracking.
26
- *
27
- * @param run - The completed run to score
28
- * @param feedback - Optional feedback (explicit or implicit)
29
- * @returns Quality score with all signal breakdowns
30
- */
31
- function scoreRun(
32
- run: CompletedRun,
33
- feedback?: { source: "explicit" | "implicit"; score: number },
34
- ): QualityScore {
35
- // Get EWMA state for latency comparison
36
- const ewmaState = db.getEwmaState(run.provider, run.model, "latency");
37
-
38
- // Extract all five signals
39
- const signals = [
40
- extractTaskCompletion(run, weights.taskCompletion),
41
- extractToolEfficiency(run, weights.toolEfficiency),
42
- extractResponseAppropriateness(run, weights.responseAppropriateLength),
43
- extractLatencyRelative(run, weights.latencyRelative, ewmaState),
44
- extractUserFeedback(weights.userFeedback, feedback),
45
- ];
46
-
47
- // Update EWMA for latency after scoring
48
- db.updateEwmaState(run.provider, run.model, "latency", run.durationMs);
49
-
50
- return combineSignals(signals);
51
- }
52
-
53
- /**
54
- * Re-score a run with new feedback (e.g., when implicit or explicit feedback arrives later).
55
- */
56
- function rescoreWithFeedback(
57
- run: CompletedRun,
58
- feedback: { source: "explicit" | "implicit"; score: number },
59
- ): QualityScore {
60
- // Re-extract all signals with the feedback
61
- const ewmaState = db.getEwmaState(run.provider, run.model, "latency");
62
-
63
- const signals = [
64
- extractTaskCompletion(run, weights.taskCompletion),
65
- extractToolEfficiency(run, weights.toolEfficiency),
66
- extractResponseAppropriateness(run, weights.responseAppropriateLength),
67
- extractLatencyRelative(run, weights.latencyRelative, ewmaState),
68
- extractUserFeedback(weights.userFeedback, feedback),
69
- ];
70
-
71
- return combineSignals(signals);
72
- }
73
-
74
- return {
75
- scoreRun,
76
- rescoreWithFeedback,
77
- };
78
- }
@@ -1,155 +0,0 @@
1
- /**
2
- * Five independent signal extraction functions.
3
- * Each returns a value in [0, 1] and a confidence in [0, 1].
4
- * All are deterministic and require zero LLM calls.
5
- */
6
-
7
- import { type EWMAState, getEWMAValue } from "../math/ewma.js";
8
- import type { CompletedRun, QualitySignal, ScoringWeights } from "../types.js";
9
-
10
- /**
11
- * Signal 1: Task Completion
12
- *
13
- * success && !error => 1.0
14
- * success && error => 0.5 (partial success with warnings)
15
- * fail => 0.0
16
- *
17
- * Confidence: always 1.0 (deterministic from agent_end)
18
- * Complexity: O(1)
19
- */
20
- export function extractTaskCompletion(run: CompletedRun, weight: number): QualitySignal {
21
- let value: number;
22
- if (run.success && !run.error) {
23
- value = 1.0;
24
- } else if (run.success && run.error) {
25
- value = 0.5;
26
- } else {
27
- value = 0.0;
28
- }
29
-
30
- return { name: "taskCompletion", value, confidence: 1.0, weight };
31
- }
32
-
33
- /**
34
- * Signal 2: Tool Efficiency
35
- *
36
- * Formula: 1.0 - 0.6*(errors/total) - 0.4*(redundant/total)
37
- * Redundant = consecutive calls with same tool+paramHash (likely retries of the same thing)
38
- *
39
- * Confidence: scales with tool call count (min 0.3 for 1 call, 1.0 for 5+)
40
- * Complexity: O(T) where T = number of tool calls
41
- */
42
- export function extractToolEfficiency(run: CompletedRun, weight: number): QualitySignal {
43
- const total = run.toolCalls.length;
44
- if (total === 0) {
45
- return { name: "toolEfficiency", value: 1.0, confidence: 0.3, weight };
46
- }
47
-
48
- let errors = 0;
49
- let redundant = 0;
50
-
51
- for (let i = 0; i < total; i++) {
52
- const tc = run.toolCalls[i]!;
53
- if (!tc.success) errors++;
54
-
55
- if (i > 0) {
56
- const prev = run.toolCalls[i - 1]!;
57
- if (tc.toolName === prev.toolName && tc.paramHash === prev.paramHash) {
58
- redundant++;
59
- }
60
- }
61
- }
62
-
63
- const value = Math.max(0, 1.0 - 0.6 * (errors / total) - 0.4 * (redundant / total));
64
- const confidence = Math.min(1.0, 0.3 + 0.7 * Math.min(1, (total - 1) / 4));
65
-
66
- return { name: "toolEfficiency", value, confidence, weight };
67
- }
68
-
69
- /**
70
- * Signal 3: Response Appropriateness (length)
71
- *
72
- * Log-normal penalty around a target ratio of response/prompt.
73
- * Formula: exp(-0.5 * (ln(ratio) / sigma)^2)
74
- *
75
- * The target ratio is 1.0 (response length ~ prompt length).
76
- * sigma = 1.5 allows wide variance before heavy penalty.
77
- *
78
- * Confidence: 0.5 (weak signal, length is a rough proxy)
79
- * Complexity: O(1)
80
- */
81
- export function extractResponseAppropriateness(run: CompletedRun, weight: number): QualitySignal {
82
- if (run.promptLength === 0 || run.responseLength === 0) {
83
- return { name: "responseAppropriateLength", value: 0.5, confidence: 0.3, weight };
84
- }
85
-
86
- const ratio = run.responseLength / run.promptLength;
87
- const sigma = 1.5;
88
- const lnRatio = Math.log(ratio);
89
- const value = Math.exp(-0.5 * (lnRatio / sigma) ** 2);
90
-
91
- return { name: "responseAppropriateLength", value, confidence: 0.5, weight };
92
- }
93
-
94
- /**
95
- * Signal 4: Latency Relative
96
- *
97
- * Compares this run's duration against the per-model EWMA.
98
- * Formula: min(1.0, ewma / duration)
99
- *
100
- * If the run is faster than average, score = 1.0.
101
- * If slower, score degrades linearly.
102
- *
103
- * Confidence: scales with EWMA observation count (0.3 for <3, 0.7 for 3-10, 1.0 for 10+)
104
- * Complexity: O(1)
105
- */
106
- export function extractLatencyRelative(
107
- run: CompletedRun,
108
- weight: number,
109
- ewmaState: EWMAState,
110
- ): QualitySignal {
111
- if (run.durationMs <= 0) {
112
- return { name: "latencyRelative", value: 1.0, confidence: 0.3, weight };
113
- }
114
-
115
- const ewmaValue = getEWMAValue(ewmaState, run.durationMs);
116
- const value = Math.min(1.0, ewmaValue / run.durationMs);
117
-
118
- let confidence: number;
119
- if (ewmaState.count < 3) confidence = 0.3;
120
- else if (ewmaState.count < 10) confidence = 0.7;
121
- else confidence = 1.0;
122
-
123
- return { name: "latencyRelative", value, confidence, weight };
124
- }
125
-
126
- /**
127
- * Signal 5: User Feedback
128
- *
129
- * Explicit: 1-5 rating mapped to [0, 1] via (score - 1) / 4
130
- * Implicit: re-ask = 0.0, topic change = 1.0, continuation = 0.5
131
- * No feedback: returns confidence 0 (signal is excluded from combination)
132
- *
133
- * Complexity: O(1)
134
- */
135
- export function extractUserFeedback(
136
- weight: number,
137
- feedback?: { source: "explicit" | "implicit"; score: number },
138
- ): QualitySignal {
139
- if (!feedback) {
140
- return { name: "userFeedback", value: 0.5, confidence: 0.0, weight };
141
- }
142
-
143
- let value: number;
144
- let confidence: number;
145
-
146
- if (feedback.source === "explicit") {
147
- value = Math.max(0, Math.min(1, (feedback.score - 1) / 4));
148
- confidence = 1.0;
149
- } else {
150
- value = Math.max(0, Math.min(1, feedback.score));
151
- confidence = 0.6;
152
- }
153
-
154
- return { name: "userFeedback", value, confidence, weight };
155
- }
@@ -1,142 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { createLRUCache } from "../injection/cache.js";
3
- import { formatLearningsContext } from "../injection/prompt-builder.js";
4
- import type { RetrievalResult } from "../learning/retrieval.js";
5
- import type { LearningLoopConfig } from "../types.js";
6
-
7
- describe("LRU Cache", () => {
8
- it("should return undefined for missing keys", () => {
9
- const cache = createLRUCache<string>();
10
- expect(cache.get("nonexistent")).toBeUndefined();
11
- });
12
-
13
- it("should store and retrieve values", () => {
14
- const cache = createLRUCache<string>();
15
- cache.set("key1", "value1");
16
- expect(cache.get("key1")).toBe("value1");
17
- });
18
-
19
- it("should evict oldest entries when at capacity", () => {
20
- const cache = createLRUCache<string>(2);
21
- cache.set("a", "1");
22
- cache.set("b", "2");
23
- cache.set("c", "3"); // evicts "a"
24
- expect(cache.get("a")).toBeUndefined();
25
- expect(cache.get("b")).toBe("2");
26
- expect(cache.get("c")).toBe("3");
27
- });
28
-
29
- it("should expire entries after TTL", () => {
30
- const cache = createLRUCache<string>(10, 1); // 1ms TTL
31
- cache.set("key", "value");
32
- // Wait for TTL (synchronous, but Date.now() should advance)
33
- const start = Date.now();
34
- while (Date.now() - start < 5) {
35
- // busy wait
36
- }
37
- expect(cache.get("key")).toBeUndefined();
38
- });
39
-
40
- it("should track hit rate", () => {
41
- const cache = createLRUCache<string>();
42
- cache.set("a", "1");
43
- cache.get("a"); // hit
44
- cache.get("b"); // miss
45
- const stats = cache.getStats();
46
- expect(stats.hits).toBe(1);
47
- expect(stats.misses).toBe(1);
48
- expect(stats.hitRate).toBeCloseTo(0.5, 5);
49
- });
50
-
51
- it("should refresh LRU order on access", () => {
52
- const cache = createLRUCache<string>(2);
53
- cache.set("a", "1");
54
- cache.set("b", "2");
55
- cache.get("a"); // refresh "a"
56
- cache.set("c", "3"); // evicts "b" (oldest)
57
- expect(cache.get("a")).toBe("1");
58
- expect(cache.get("b")).toBeUndefined();
59
- });
60
-
61
- it("should clear all entries and reset stats", () => {
62
- const cache = createLRUCache<string>();
63
- cache.set("a", "1");
64
- cache.get("a");
65
- cache.clear();
66
- expect(cache.get("a")).toBeUndefined();
67
- expect(cache.getStats().hits).toBe(0);
68
- });
69
- });
70
-
71
- describe("Prompt Builder", () => {
72
- const config: LearningLoopConfig = {
73
- capture: { embedPrompts: false, maxRuns: 10000 },
74
- scoring: {
75
- weights: {
76
- taskCompletion: 0.35,
77
- toolEfficiency: 0.25,
78
- responseAppropriateLength: 0.1,
79
- latencyRelative: 0.1,
80
- userFeedback: 0.2,
81
- },
82
- },
83
- injection: { maxLearnings: 5, minRelevance: 0.3, maxTokens: 500, cacheTtlMs: 60000 },
84
- decay: { halfLifeDays: 30 },
85
- };
86
-
87
- it("should return empty string for no results", () => {
88
- expect(formatLearningsContext([], config)).toBe("");
89
- });
90
-
91
- it("should format learnings with category tags", () => {
92
- const results: RetrievalResult[] = [
93
- {
94
- learning: {
95
- id: "lrn-1",
96
- runId: "run-1",
97
- category: "tool_pattern",
98
- content: "Use search before read",
99
- embedding: null,
100
- confidence: 0.8,
101
- appliedCount: 3,
102
- createdAt: Date.now(),
103
- updatedAt: Date.now(),
104
- },
105
- score: 0.9,
106
- decayedScore: 0.85,
107
- },
108
- ];
109
-
110
- const context = formatLearningsContext(results, config);
111
- expect(context).toContain("<learnings>");
112
- expect(context).toContain("</learnings>");
113
- expect(context).toContain("[tool_pattern]");
114
- expect(context).toContain("Use search before read");
115
- });
116
-
117
- it("should respect maxTokens limit", () => {
118
- const longContent = "A".repeat(5000);
119
- const results: RetrievalResult[] = [
120
- {
121
- learning: {
122
- id: "lrn-1",
123
- runId: "run-1",
124
- category: "tool_pattern",
125
- content: longContent,
126
- embedding: null,
127
- confidence: 0.8,
128
- appliedCount: 0,
129
- createdAt: Date.now(),
130
- updatedAt: Date.now(),
131
- },
132
- score: 0.9,
133
- decayedScore: 0.85,
134
- },
135
- ];
136
-
137
- const smallConfig = { ...config, injection: { ...config.injection, maxTokens: 50 } };
138
- const context = formatLearningsContext(results, smallConfig);
139
- // Should be empty because the single learning exceeds maxTokens
140
- expect(context).toBe("");
141
- });
142
- });