@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,97 +0,0 @@
1
- # LLM Task (plugin)
2
-
3
- Adds an **optional** agent tool `llm-task` for running **JSON-only** LLM tasks
4
- (drafting, summarizing, classifying) with optional JSON Schema validation.
5
-
6
- Designed to be called from workflow engines (for example, Pipeline via
7
- `symi.invoke --each`) without adding new Symi code per workflow.
8
-
9
- ## Enable
10
-
11
- 1. Enable the plugin:
12
-
13
- ```json
14
- {
15
- "plugins": {
16
- "entries": {
17
- "llm-task": { "enabled": true }
18
- }
19
- }
20
- }
21
- ```
22
-
23
- 2. Allowlist the tool (it is registered with `optional: true`):
24
-
25
- ```json
26
- {
27
- "agents": {
28
- "list": [
29
- {
30
- "id": "main",
31
- "tools": { "allow": ["llm-task"] }
32
- }
33
- ]
34
- }
35
- }
36
- ```
37
-
38
- ## Config (optional)
39
-
40
- ```json
41
- {
42
- "plugins": {
43
- "entries": {
44
- "llm-task": {
45
- "enabled": true,
46
- "config": {
47
- "defaultProvider": "openai-codex",
48
- "defaultModel": "gpt-5.2",
49
- "defaultAuthProfileId": "main",
50
- "allowedModels": ["openai-codex/gpt-5.2"],
51
- "maxTokens": 800,
52
- "timeoutMs": 30000
53
- }
54
- }
55
- }
56
- }
57
- }
58
- ```
59
-
60
- `allowedModels` is an allowlist of `provider/model` strings. If set, any request
61
- outside the list is rejected.
62
-
63
- ## Tool API
64
-
65
- ### Parameters
66
-
67
- - `prompt` (string, required)
68
- - `input` (any, optional)
69
- - `schema` (object, optional JSON Schema)
70
- - `provider` (string, optional)
71
- - `model` (string, optional)
72
- - `authProfileId` (string, optional)
73
- - `temperature` (number, optional)
74
- - `maxTokens` (number, optional)
75
- - `timeoutMs` (number, optional)
76
-
77
- ### Output
78
-
79
- Returns `details.json` containing the parsed JSON (and validates against
80
- `schema` when provided).
81
-
82
- ## Notes
83
-
84
- - The tool is **JSON-only** and instructs the model to output only JSON
85
- (no code fences, no commentary).
86
- - No tools are exposed to the model for this run.
87
- - Side effects should be handled outside this tool (for example, approvals in
88
- Pipeline) before calling tools that send messages/emails.
89
-
90
- ## Bundled extension note
91
-
92
- This extension depends on Symi internal modules (the embedded agent runner).
93
- It is intended to ship as a **bundled** Symi extension (like `pipeline`) and
94
- be enabled via `plugins.entries` + tool allowlists.
95
-
96
- It is **not** currently designed to be copied into
97
- `~/.symi/extensions` as a standalone plugin directory.
@@ -1,6 +0,0 @@
1
- import type { AnyAgentTool, SymiPluginApi } from "../../src/plugins/types.js";
2
- import { createLlmTaskTool } from "./src/llm-task-tool.js";
3
-
4
- export default function register(api: SymiPluginApi) {
5
- api.registerTool(createLlmTaskTool(api) as unknown as AnyAgentTool, { optional: true });
6
- }
@@ -1,12 +0,0 @@
1
- {
2
- "name": "@symi/llm-task",
3
- "version": "3.0.9",
4
- "private": true,
5
- "description": "Symi JSON-only LLM task plugin",
6
- "type": "module",
7
- "symi": {
8
- "extensions": [
9
- "./index.ts"
10
- ]
11
- }
12
- }
@@ -1,138 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
-
3
- vi.mock("../../../src/agents/pi-embedded-runner.js", () => {
4
- return {
5
- runEmbeddedPiAgent: vi.fn(async () => ({
6
- meta: { startedAt: Date.now() },
7
- payloads: [{ text: "{}" }],
8
- })),
9
- };
10
- });
11
-
12
- import { runEmbeddedPiAgent } from "../../../src/agents/pi-embedded-runner.js";
13
- import { createLlmTaskTool } from "./llm-task-tool.js";
14
-
15
- // oxlint-disable-next-line typescript/no-explicit-any
16
- function fakeApi(overrides: any = {}) {
17
- return {
18
- id: "llm-task",
19
- name: "llm-task",
20
- source: "test",
21
- config: {
22
- agents: { defaults: { workspace: "/tmp", model: { primary: "openai-codex/gpt-5.2" } } },
23
- },
24
- pluginConfig: {},
25
- runtime: { version: "test" },
26
- logger: { debug() {}, info() {}, warn() {}, error() {} },
27
- registerTool() {},
28
- ...overrides,
29
- };
30
- }
31
-
32
- describe("llm-task tool (json-only)", () => {
33
- beforeEach(() => vi.clearAllMocks());
34
-
35
- it("returns parsed json", async () => {
36
- // oxlint-disable-next-line typescript/no-explicit-any
37
- (runEmbeddedPiAgent as any).mockResolvedValueOnce({
38
- meta: {},
39
- payloads: [{ text: JSON.stringify({ foo: "bar" }) }],
40
- });
41
- const tool = createLlmTaskTool(fakeApi());
42
- const res = await tool.execute("id", { prompt: "return foo" });
43
- // oxlint-disable-next-line typescript/no-explicit-any
44
- expect((res as any).details.json).toEqual({ foo: "bar" });
45
- });
46
-
47
- it("strips fenced json", async () => {
48
- // oxlint-disable-next-line typescript/no-explicit-any
49
- (runEmbeddedPiAgent as any).mockResolvedValueOnce({
50
- meta: {},
51
- payloads: [{ text: '```json\n{"ok":true}\n```' }],
52
- });
53
- const tool = createLlmTaskTool(fakeApi());
54
- const res = await tool.execute("id", { prompt: "return ok" });
55
- // oxlint-disable-next-line typescript/no-explicit-any
56
- expect((res as any).details.json).toEqual({ ok: true });
57
- });
58
-
59
- it("validates schema", async () => {
60
- // oxlint-disable-next-line typescript/no-explicit-any
61
- (runEmbeddedPiAgent as any).mockResolvedValueOnce({
62
- meta: {},
63
- payloads: [{ text: JSON.stringify({ foo: "bar" }) }],
64
- });
65
- const tool = createLlmTaskTool(fakeApi());
66
- const schema = {
67
- type: "object",
68
- properties: { foo: { type: "string" } },
69
- required: ["foo"],
70
- additionalProperties: false,
71
- };
72
- const res = await tool.execute("id", { prompt: "return foo", schema });
73
- // oxlint-disable-next-line typescript/no-explicit-any
74
- expect((res as any).details.json).toEqual({ foo: "bar" });
75
- });
76
-
77
- it("throws on invalid json", async () => {
78
- // oxlint-disable-next-line typescript/no-explicit-any
79
- (runEmbeddedPiAgent as any).mockResolvedValueOnce({
80
- meta: {},
81
- payloads: [{ text: "not-json" }],
82
- });
83
- const tool = createLlmTaskTool(fakeApi());
84
- await expect(tool.execute("id", { prompt: "x" })).rejects.toThrow(/invalid json/i);
85
- });
86
-
87
- it("throws on schema mismatch", async () => {
88
- // oxlint-disable-next-line typescript/no-explicit-any
89
- (runEmbeddedPiAgent as any).mockResolvedValueOnce({
90
- meta: {},
91
- payloads: [{ text: JSON.stringify({ foo: 1 }) }],
92
- });
93
- const tool = createLlmTaskTool(fakeApi());
94
- const schema = { type: "object", properties: { foo: { type: "string" } }, required: ["foo"] };
95
- await expect(tool.execute("id", { prompt: "x", schema })).rejects.toThrow(/match schema/i);
96
- });
97
-
98
- it("passes provider/model overrides to embedded runner", async () => {
99
- // oxlint-disable-next-line typescript/no-explicit-any
100
- (runEmbeddedPiAgent as any).mockResolvedValueOnce({
101
- meta: {},
102
- payloads: [{ text: JSON.stringify({ ok: true }) }],
103
- });
104
- const tool = createLlmTaskTool(fakeApi());
105
- await tool.execute("id", { prompt: "x", provider: "anthropic", model: "claude-4-sonnet" });
106
- // oxlint-disable-next-line typescript/no-explicit-any
107
- const call = (runEmbeddedPiAgent as any).mock.calls[0]?.[0];
108
- expect(call.provider).toBe("anthropic");
109
- expect(call.model).toBe("claude-4-sonnet");
110
- });
111
-
112
- it("enforces allowedModels", async () => {
113
- // oxlint-disable-next-line typescript/no-explicit-any
114
- (runEmbeddedPiAgent as any).mockResolvedValueOnce({
115
- meta: {},
116
- payloads: [{ text: JSON.stringify({ ok: true }) }],
117
- });
118
- const tool = createLlmTaskTool(
119
- fakeApi({ pluginConfig: { allowedModels: ["openai-codex/gpt-5.2"] } }),
120
- );
121
- await expect(
122
- tool.execute("id", { prompt: "x", provider: "anthropic", model: "claude-4-sonnet" }),
123
- ).rejects.toThrow(/not allowed/i);
124
- });
125
-
126
- it("disables tools for embedded run", async () => {
127
- // oxlint-disable-next-line typescript/no-explicit-any
128
- (runEmbeddedPiAgent as any).mockResolvedValueOnce({
129
- meta: {},
130
- payloads: [{ text: JSON.stringify({ ok: true }) }],
131
- });
132
- const tool = createLlmTaskTool(fakeApi());
133
- await tool.execute("id", { prompt: "x" });
134
- // oxlint-disable-next-line typescript/no-explicit-any
135
- const call = (runEmbeddedPiAgent as any).mock.calls[0]?.[0];
136
- expect(call.disableTools).toBe(true);
137
- });
138
- });
@@ -1,249 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import os from "node:os";
3
- import path from "node:path";
4
- import { Type } from "@sinclair/typebox";
5
- import Ajv from "ajv";
6
- // NOTE: This extension is intended to be bundled with Symi.
7
- // When running from source (tests/dev), Symi internals live under src/.
8
- // When running from a built install, internals live under dist/ (no src/ tree).
9
- // So we resolve internal imports dynamically with src-first, dist-fallback.
10
- import type { SymiPluginApi } from "../../../src/plugins/types.js";
11
-
12
- type RunEmbeddedPiAgentFn = (params: Record<string, unknown>) => Promise<unknown>;
13
-
14
- async function loadRunEmbeddedPiAgent(): Promise<RunEmbeddedPiAgentFn> {
15
- // Source checkout (tests/dev)
16
- try {
17
- const mod = await import("../../../src/agents/pi-embedded-runner.js");
18
- // oxlint-disable-next-line typescript/no-explicit-any
19
- if (typeof (mod as any).runEmbeddedPiAgent === "function") {
20
- // oxlint-disable-next-line typescript/no-explicit-any
21
- return (mod as any).runEmbeddedPiAgent;
22
- }
23
- } catch {
24
- // ignore
25
- }
26
-
27
- // Bundled install (built)
28
- const mod = await import("../../../src/agents/pi-embedded-runner.js");
29
- if (typeof mod.runEmbeddedPiAgent !== "function") {
30
- throw new Error("Internal error: runEmbeddedPiAgent not available");
31
- }
32
- return mod.runEmbeddedPiAgent as RunEmbeddedPiAgentFn;
33
- }
34
-
35
- function stripCodeFences(s: string): string {
36
- const trimmed = s.trim();
37
- const m = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i);
38
- if (m) {
39
- return (m[1] ?? "").trim();
40
- }
41
- return trimmed;
42
- }
43
-
44
- function collectText(payloads: Array<{ text?: string; isError?: boolean }> | undefined): string {
45
- const texts = (payloads ?? [])
46
- .filter((p) => !p.isError && typeof p.text === "string")
47
- .map((p) => p.text ?? "");
48
- return texts.join("\n").trim();
49
- }
50
-
51
- function toModelKey(provider?: string, model?: string): string | undefined {
52
- const p = provider?.trim();
53
- const m = model?.trim();
54
- if (!p || !m) {
55
- return undefined;
56
- }
57
- return `${p}/${m}`;
58
- }
59
-
60
- type PluginCfg = {
61
- defaultProvider?: string;
62
- defaultModel?: string;
63
- defaultAuthProfileId?: string;
64
- allowedModels?: string[];
65
- maxTokens?: number;
66
- timeoutMs?: number;
67
- };
68
-
69
- export function createLlmTaskTool(api: SymiPluginApi) {
70
- return {
71
- name: "llm-task",
72
- label: "LLM Task",
73
- description:
74
- "Run a generic JSON-only LLM task and return schema-validated JSON. Designed for orchestration from Pipeline workflows via symi.invoke.",
75
- parameters: Type.Object({
76
- prompt: Type.String({ description: "Task instruction for the LLM." }),
77
- input: Type.Optional(Type.Unknown({ description: "Optional input payload for the task." })),
78
- schema: Type.Optional(
79
- Type.Unknown({ description: "Optional JSON Schema to validate the returned JSON." }),
80
- ),
81
- provider: Type.Optional(
82
- Type.String({ description: "Provider override (e.g. openai-codex, anthropic)." }),
83
- ),
84
- model: Type.Optional(Type.String({ description: "Model id override." })),
85
- authProfileId: Type.Optional(Type.String({ description: "Auth profile override." })),
86
- temperature: Type.Optional(Type.Number({ description: "Best-effort temperature override." })),
87
- maxTokens: Type.Optional(Type.Number({ description: "Best-effort maxTokens override." })),
88
- timeoutMs: Type.Optional(Type.Number({ description: "Timeout for the LLM run." })),
89
- }),
90
-
91
- async execute(_id: string, params: Record<string, unknown>) {
92
- const prompt = typeof params.prompt === "string" ? params.prompt : "";
93
- if (!prompt.trim()) {
94
- throw new Error("prompt required");
95
- }
96
-
97
- const pluginCfg = (api.pluginConfig ?? {}) as PluginCfg;
98
-
99
- const primary = api.config?.agents?.defaults?.model?.primary;
100
- const primaryProvider = typeof primary === "string" ? primary.split("/")[0] : undefined;
101
- const primaryModel =
102
- typeof primary === "string" ? primary.split("/").slice(1).join("/") : undefined;
103
-
104
- const provider =
105
- (typeof params.provider === "string" && params.provider.trim()) ||
106
- (typeof pluginCfg.defaultProvider === "string" && pluginCfg.defaultProvider.trim()) ||
107
- primaryProvider ||
108
- undefined;
109
-
110
- const model =
111
- (typeof params.model === "string" && params.model.trim()) ||
112
- (typeof pluginCfg.defaultModel === "string" && pluginCfg.defaultModel.trim()) ||
113
- primaryModel ||
114
- undefined;
115
-
116
- const authProfileId =
117
- // oxlint-disable-next-line typescript/no-explicit-any
118
- (typeof (params as any).authProfileId === "string" &&
119
- // oxlint-disable-next-line typescript/no-explicit-any
120
- (params as any).authProfileId.trim()) ||
121
- (typeof pluginCfg.defaultAuthProfileId === "string" &&
122
- pluginCfg.defaultAuthProfileId.trim()) ||
123
- undefined;
124
-
125
- const modelKey = toModelKey(provider, model);
126
- if (!provider || !model || !modelKey) {
127
- throw new Error(
128
- `provider/model could not be resolved (provider=${String(provider ?? "")}, model=${String(model ?? "")})`,
129
- );
130
- }
131
-
132
- const allowed = Array.isArray(pluginCfg.allowedModels) ? pluginCfg.allowedModels : undefined;
133
- if (allowed && allowed.length > 0 && !allowed.includes(modelKey)) {
134
- throw new Error(
135
- `Model not allowed by llm-task plugin config: ${modelKey}. Allowed models: ${allowed.join(", ")}`,
136
- );
137
- }
138
-
139
- const timeoutMs =
140
- (typeof params.timeoutMs === "number" && params.timeoutMs > 0
141
- ? params.timeoutMs
142
- : undefined) ||
143
- (typeof pluginCfg.timeoutMs === "number" && pluginCfg.timeoutMs > 0
144
- ? pluginCfg.timeoutMs
145
- : undefined) ||
146
- 30_000;
147
-
148
- const streamParams = {
149
- temperature: typeof params.temperature === "number" ? params.temperature : undefined,
150
- maxTokens:
151
- typeof params.maxTokens === "number"
152
- ? params.maxTokens
153
- : typeof pluginCfg.maxTokens === "number"
154
- ? pluginCfg.maxTokens
155
- : undefined,
156
- };
157
-
158
- // oxlint-disable-next-line typescript/no-explicit-any
159
- const input = (params as any).input as unknown;
160
- let inputJson: string;
161
- try {
162
- inputJson = JSON.stringify(input ?? null, null, 2);
163
- } catch {
164
- throw new Error("input must be JSON-serializable");
165
- }
166
-
167
- const system = [
168
- "You are a JSON-only function.",
169
- "Return ONLY a valid JSON value.",
170
- "Do not wrap in markdown fences.",
171
- "Do not include commentary.",
172
- "Do not call tools.",
173
- ].join(" ");
174
-
175
- const fullPrompt = `${system}\n\nTASK:\n${prompt}\n\nINPUT_JSON:\n${inputJson}\n`;
176
-
177
- let tmpDir: string | null = null;
178
- try {
179
- tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "symi-llm-task-"));
180
- const sessionId = `llm-task-${Date.now()}`;
181
- const sessionFile = path.join(tmpDir, "session.json");
182
-
183
- const runEmbeddedPiAgent = await loadRunEmbeddedPiAgent();
184
-
185
- const result = await runEmbeddedPiAgent({
186
- sessionId,
187
- sessionFile,
188
- workspaceDir: api.config?.agents?.defaults?.workspace ?? process.cwd(),
189
- config: api.config,
190
- prompt: fullPrompt,
191
- timeoutMs,
192
- runId: `llm-task-${Date.now()}`,
193
- provider,
194
- model,
195
- authProfileId,
196
- authProfileIdSource: authProfileId ? "user" : "auto",
197
- streamParams,
198
- disableTools: true,
199
- });
200
-
201
- // oxlint-disable-next-line typescript/no-explicit-any
202
- const text = collectText((result as any).payloads);
203
- if (!text) {
204
- throw new Error("LLM returned empty output");
205
- }
206
-
207
- const raw = stripCodeFences(text);
208
- let parsed: unknown;
209
- try {
210
- parsed = JSON.parse(raw);
211
- } catch {
212
- throw new Error("LLM returned invalid JSON");
213
- }
214
-
215
- // oxlint-disable-next-line typescript/no-explicit-any
216
- const schema = (params as any).schema as unknown;
217
- if (schema && typeof schema === "object" && !Array.isArray(schema)) {
218
- const ajv = new Ajv.default({ allErrors: true, strict: false });
219
- // oxlint-disable-next-line typescript/no-explicit-any
220
- const validate = ajv.compile(schema as any);
221
- const ok = validate(parsed);
222
- if (!ok) {
223
- const msg =
224
- validate.errors
225
- ?.map(
226
- (e: { instancePath?: string; message?: string }) =>
227
- `${e.instancePath || "<root>"} ${e.message || "invalid"}`,
228
- )
229
- .join("; ") ?? "invalid";
230
- throw new Error(`LLM JSON did not match schema: ${msg}`);
231
- }
232
- }
233
-
234
- return {
235
- content: [{ type: "text", text: JSON.stringify(parsed, null, 2) }],
236
- details: { json: parsed, provider, model },
237
- };
238
- } finally {
239
- if (tmpDir) {
240
- try {
241
- await fs.rm(tmpDir, { recursive: true, force: true });
242
- } catch {
243
- // ignore
244
- }
245
- }
246
- }
247
- },
248
- };
249
- }
@@ -1,21 +0,0 @@
1
- {
2
- "id": "llm-task",
3
- "name": "LLM Task",
4
- "description": "Generic JSON-only LLM tool for structured tasks callable from workflows.",
5
- "configSchema": {
6
- "type": "object",
7
- "additionalProperties": false,
8
- "properties": {
9
- "defaultProvider": { "type": "string" },
10
- "defaultModel": { "type": "string" },
11
- "defaultAuthProfileId": { "type": "string" },
12
- "allowedModels": {
13
- "type": "array",
14
- "items": { "type": "string" },
15
- "description": "Allowlist of provider/model keys like openai-codex/gpt-5.2."
16
- },
17
- "maxTokens": { "type": "number" },
18
- "timeoutMs": { "type": "number" }
19
- }
20
- }
21
- }
@@ -1,161 +0,0 @@
1
- import fs from "node:fs";
2
- import { homedir } from "node:os";
3
- import { join } from "node:path";
4
-
5
- export type MemoryConfig = {
6
- embedding: {
7
- provider: "openai";
8
- model?: string;
9
- apiKey: string;
10
- };
11
- dbPath?: string;
12
- autoCapture?: boolean;
13
- autoRecall?: boolean;
14
- captureMaxChars?: number;
15
- };
16
-
17
- export const MEMORY_CATEGORIES = ["preference", "fact", "decision", "entity", "other"] as const;
18
- export type MemoryCategory = (typeof MEMORY_CATEGORIES)[number];
19
-
20
- const DEFAULT_MODEL = "text-embedding-3-small";
21
- export const DEFAULT_CAPTURE_MAX_CHARS = 500;
22
- const LEGACY_STATE_DIRS: string[] = [];
23
-
24
- function resolveDefaultDbPath(): string {
25
- const home = homedir();
26
- const preferred = join(home, ".symi", "memory", "lancedb");
27
- try {
28
- if (fs.existsSync(preferred)) {
29
- return preferred;
30
- }
31
- } catch {
32
- // best-effort
33
- }
34
-
35
- for (const legacy of LEGACY_STATE_DIRS) {
36
- const candidate = join(home, legacy, "memory", "lancedb");
37
- try {
38
- if (fs.existsSync(candidate)) {
39
- return candidate;
40
- }
41
- } catch {
42
- // best-effort
43
- }
44
- }
45
-
46
- return preferred;
47
- }
48
-
49
- const DEFAULT_DB_PATH = resolveDefaultDbPath();
50
-
51
- const EMBEDDING_DIMENSIONS: Record<string, number> = {
52
- "text-embedding-3-small": 1536,
53
- "text-embedding-3-large": 3072,
54
- };
55
-
56
- function assertAllowedKeys(value: Record<string, unknown>, allowed: string[], label: string) {
57
- const unknown = Object.keys(value).filter((key) => !allowed.includes(key));
58
- if (unknown.length === 0) {
59
- return;
60
- }
61
- throw new Error(`${label} has unknown keys: ${unknown.join(", ")}`);
62
- }
63
-
64
- export function vectorDimsForModel(model: string): number {
65
- const dims = EMBEDDING_DIMENSIONS[model];
66
- if (!dims) {
67
- throw new Error(`Unsupported embedding model: ${model}`);
68
- }
69
- return dims;
70
- }
71
-
72
- function resolveEnvVars(value: string): string {
73
- return value.replace(/\$\{([^}]+)\}/g, (_, envVar) => {
74
- const envValue = process.env[envVar];
75
- if (!envValue) {
76
- throw new Error(`Environment variable ${envVar} is not set`);
77
- }
78
- return envValue;
79
- });
80
- }
81
-
82
- function resolveEmbeddingModel(embedding: Record<string, unknown>): string {
83
- const model = typeof embedding.model === "string" ? embedding.model : DEFAULT_MODEL;
84
- vectorDimsForModel(model);
85
- return model;
86
- }
87
-
88
- export const memoryConfigSchema = {
89
- parse(value: unknown): MemoryConfig {
90
- if (!value || typeof value !== "object" || Array.isArray(value)) {
91
- throw new Error("memory config required");
92
- }
93
- const cfg = value as Record<string, unknown>;
94
- assertAllowedKeys(
95
- cfg,
96
- ["embedding", "dbPath", "autoCapture", "autoRecall", "captureMaxChars"],
97
- "memory config",
98
- );
99
-
100
- const embedding = cfg.embedding as Record<string, unknown> | undefined;
101
- if (!embedding || typeof embedding.apiKey !== "string") {
102
- throw new Error("embedding.apiKey is required");
103
- }
104
- assertAllowedKeys(embedding, ["apiKey", "model"], "embedding config");
105
-
106
- const model = resolveEmbeddingModel(embedding);
107
-
108
- const captureMaxChars =
109
- typeof cfg.captureMaxChars === "number" ? Math.floor(cfg.captureMaxChars) : undefined;
110
- if (
111
- typeof captureMaxChars === "number" &&
112
- (captureMaxChars < 100 || captureMaxChars > 10_000)
113
- ) {
114
- throw new Error("captureMaxChars must be between 100 and 10000");
115
- }
116
-
117
- return {
118
- embedding: {
119
- provider: "openai",
120
- model,
121
- apiKey: resolveEnvVars(embedding.apiKey),
122
- },
123
- dbPath: typeof cfg.dbPath === "string" ? cfg.dbPath : DEFAULT_DB_PATH,
124
- autoCapture: cfg.autoCapture === true,
125
- autoRecall: cfg.autoRecall !== false,
126
- captureMaxChars: captureMaxChars ?? DEFAULT_CAPTURE_MAX_CHARS,
127
- };
128
- },
129
- uiHints: {
130
- "embedding.apiKey": {
131
- label: "OpenAI API Key",
132
- sensitive: true,
133
- placeholder: "sk-proj-...",
134
- help: "API key for OpenAI embeddings (or use ${OPENAI_API_KEY})",
135
- },
136
- "embedding.model": {
137
- label: "Embedding Model",
138
- placeholder: DEFAULT_MODEL,
139
- help: "OpenAI embedding model to use",
140
- },
141
- dbPath: {
142
- label: "Database Path",
143
- placeholder: "~/.symi/memory/lancedb",
144
- advanced: true,
145
- },
146
- autoCapture: {
147
- label: "Auto-Capture",
148
- help: "Automatically capture important information from conversations",
149
- },
150
- autoRecall: {
151
- label: "Auto-Recall",
152
- help: "Automatically inject relevant memories into context",
153
- },
154
- captureMaxChars: {
155
- label: "Capture Max Chars",
156
- help: "Maximum message length eligible for auto-capture",
157
- advanced: true,
158
- placeholder: String(DEFAULT_CAPTURE_MAX_CHARS),
159
- },
160
- },
161
- };