@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,666 +0,0 @@
1
- import { metrics, trace, SpanStatusCode } from "@opentelemetry/api";
2
- import type { SeverityNumber } from "@opentelemetry/api-logs";
3
- import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
4
- import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
5
- import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
6
- import { resourceFromAttributes } from "@opentelemetry/resources";
7
- import { BatchLogRecordProcessor, LoggerProvider } from "@opentelemetry/sdk-logs";
8
- import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
9
- import { NodeSDK } from "@opentelemetry/sdk-node";
10
- import { ParentBasedSampler, TraceIdRatioBasedSampler } from "@opentelemetry/sdk-trace-base";
11
- import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
12
- import type { DiagnosticEventPayload, SymiPluginService } from "symi/plugin-sdk";
13
- import { onDiagnosticEvent, registerLogTransport } from "symi/plugin-sdk";
14
-
15
- const DEFAULT_SERVICE_NAME = "symi";
16
-
17
- function normalizeEndpoint(endpoint?: string): string | undefined {
18
- const trimmed = endpoint?.trim();
19
- return trimmed ? trimmed.replace(/\/+$/, "") : undefined;
20
- }
21
-
22
- function resolveOtelUrl(endpoint: string | undefined, path: string): string | undefined {
23
- if (!endpoint) {
24
- return undefined;
25
- }
26
- const endpointWithoutQueryOrFragment = endpoint.split(/[?#]/, 1)[0] ?? endpoint;
27
- if (/\/v1\/(?:traces|metrics|logs)$/i.test(endpointWithoutQueryOrFragment)) {
28
- return endpoint;
29
- }
30
- return `${endpoint}/${path}`;
31
- }
32
-
33
- function resolveSampleRate(value: number | undefined): number | undefined {
34
- if (typeof value !== "number" || !Number.isFinite(value)) {
35
- return undefined;
36
- }
37
- if (value < 0 || value > 1) {
38
- return undefined;
39
- }
40
- return value;
41
- }
42
-
43
- function formatError(err: unknown): string {
44
- if (err instanceof Error) {
45
- return err.stack ?? err.message;
46
- }
47
- if (typeof err === "string") {
48
- return err;
49
- }
50
- try {
51
- return JSON.stringify(err);
52
- } catch {
53
- return String(err);
54
- }
55
- }
56
-
57
- export function createDiagnosticsOtelService(): SymiPluginService {
58
- let sdk: NodeSDK | null = null;
59
- let logProvider: LoggerProvider | null = null;
60
- let stopLogTransport: (() => void) | null = null;
61
- let unsubscribe: (() => void) | null = null;
62
-
63
- return {
64
- id: "diagnostics-otel",
65
- async start(ctx) {
66
- const cfg = ctx.config.diagnostics;
67
- const otel = cfg?.otel;
68
- if (!cfg?.enabled || !otel?.enabled) {
69
- return;
70
- }
71
-
72
- const protocol = otel.protocol ?? process.env.OTEL_EXPORTER_OTLP_PROTOCOL ?? "http/protobuf";
73
- if (protocol !== "http/protobuf") {
74
- ctx.logger.warn(`diagnostics-otel: unsupported protocol ${protocol}`);
75
- return;
76
- }
77
-
78
- const endpoint = normalizeEndpoint(otel.endpoint ?? process.env.OTEL_EXPORTER_OTLP_ENDPOINT);
79
- const headers = otel.headers ?? undefined;
80
- const serviceName =
81
- otel.serviceName?.trim() || process.env.OTEL_SERVICE_NAME || DEFAULT_SERVICE_NAME;
82
- const sampleRate = resolveSampleRate(otel.sampleRate);
83
-
84
- const tracesEnabled = otel.traces !== false;
85
- const metricsEnabled = otel.metrics !== false;
86
- const logsEnabled = otel.logs === true;
87
- if (!tracesEnabled && !metricsEnabled && !logsEnabled) {
88
- return;
89
- }
90
-
91
- const resource = resourceFromAttributes({
92
- [ATTR_SERVICE_NAME]: serviceName,
93
- });
94
-
95
- const traceUrl = resolveOtelUrl(endpoint, "v1/traces");
96
- const metricUrl = resolveOtelUrl(endpoint, "v1/metrics");
97
- const logUrl = resolveOtelUrl(endpoint, "v1/logs");
98
- const traceExporter = tracesEnabled
99
- ? new OTLPTraceExporter({
100
- ...(traceUrl ? { url: traceUrl } : {}),
101
- ...(headers ? { headers } : {}),
102
- })
103
- : undefined;
104
-
105
- const metricExporter = metricsEnabled
106
- ? new OTLPMetricExporter({
107
- ...(metricUrl ? { url: metricUrl } : {}),
108
- ...(headers ? { headers } : {}),
109
- })
110
- : undefined;
111
-
112
- const metricReader = metricExporter
113
- ? new PeriodicExportingMetricReader({
114
- exporter: metricExporter,
115
- ...(typeof otel.flushIntervalMs === "number"
116
- ? { exportIntervalMillis: Math.max(1000, otel.flushIntervalMs) }
117
- : {}),
118
- })
119
- : undefined;
120
-
121
- if (tracesEnabled || metricsEnabled) {
122
- sdk = new NodeSDK({
123
- resource,
124
- ...(traceExporter ? { traceExporter } : {}),
125
- ...(metricReader ? { metricReader } : {}),
126
- ...(sampleRate !== undefined
127
- ? {
128
- sampler: new ParentBasedSampler({
129
- root: new TraceIdRatioBasedSampler(sampleRate),
130
- }),
131
- }
132
- : {}),
133
- });
134
-
135
- try {
136
- await sdk.start();
137
- } catch (err) {
138
- ctx.logger.error(`diagnostics-otel: failed to start SDK: ${formatError(err)}`);
139
- throw err;
140
- }
141
- }
142
-
143
- const logSeverityMap: Record<string, SeverityNumber> = {
144
- TRACE: 1 as SeverityNumber,
145
- DEBUG: 5 as SeverityNumber,
146
- INFO: 9 as SeverityNumber,
147
- WARN: 13 as SeverityNumber,
148
- ERROR: 17 as SeverityNumber,
149
- FATAL: 21 as SeverityNumber,
150
- };
151
-
152
- const meter = metrics.getMeter("symi");
153
- const tracer = trace.getTracer("symi");
154
-
155
- const tokensCounter = meter.createCounter("symi.tokens", {
156
- unit: "1",
157
- description: "Token usage by type",
158
- });
159
- const costCounter = meter.createCounter("symi.cost.usd", {
160
- unit: "1",
161
- description: "Estimated model cost (USD)",
162
- });
163
- const durationHistogram = meter.createHistogram("symi.run.duration_ms", {
164
- unit: "ms",
165
- description: "Agent run duration",
166
- });
167
- const contextHistogram = meter.createHistogram("symi.context.tokens", {
168
- unit: "1",
169
- description: "Context window size and usage",
170
- });
171
- const webhookReceivedCounter = meter.createCounter("symi.webhook.received", {
172
- unit: "1",
173
- description: "Webhook requests received",
174
- });
175
- const webhookErrorCounter = meter.createCounter("symi.webhook.error", {
176
- unit: "1",
177
- description: "Webhook processing errors",
178
- });
179
- const webhookDurationHistogram = meter.createHistogram("symi.webhook.duration_ms", {
180
- unit: "ms",
181
- description: "Webhook processing duration",
182
- });
183
- const messageQueuedCounter = meter.createCounter("symi.message.queued", {
184
- unit: "1",
185
- description: "Messages queued for processing",
186
- });
187
- const messageProcessedCounter = meter.createCounter("symi.message.processed", {
188
- unit: "1",
189
- description: "Messages processed by outcome",
190
- });
191
- const messageDurationHistogram = meter.createHistogram("symi.message.duration_ms", {
192
- unit: "ms",
193
- description: "Message processing duration",
194
- });
195
- const queueDepthHistogram = meter.createHistogram("symi.queue.depth", {
196
- unit: "1",
197
- description: "Queue depth on enqueue/dequeue",
198
- });
199
- const queueWaitHistogram = meter.createHistogram("symi.queue.wait_ms", {
200
- unit: "ms",
201
- description: "Queue wait time before execution",
202
- });
203
- const laneEnqueueCounter = meter.createCounter("symi.queue.lane.enqueue", {
204
- unit: "1",
205
- description: "Command queue lane enqueue events",
206
- });
207
- const laneDequeueCounter = meter.createCounter("symi.queue.lane.dequeue", {
208
- unit: "1",
209
- description: "Command queue lane dequeue events",
210
- });
211
- const sessionStateCounter = meter.createCounter("symi.session.state", {
212
- unit: "1",
213
- description: "Session state transitions",
214
- });
215
- const sessionStuckCounter = meter.createCounter("symi.session.stuck", {
216
- unit: "1",
217
- description: "Sessions stuck in processing",
218
- });
219
- const sessionStuckAgeHistogram = meter.createHistogram("symi.session.stuck_age_ms", {
220
- unit: "ms",
221
- description: "Age of stuck sessions",
222
- });
223
- const runAttemptCounter = meter.createCounter("symi.run.attempt", {
224
- unit: "1",
225
- description: "Run attempts",
226
- });
227
-
228
- if (logsEnabled) {
229
- const logExporter = new OTLPLogExporter({
230
- ...(logUrl ? { url: logUrl } : {}),
231
- ...(headers ? { headers } : {}),
232
- });
233
- const logProcessor = new BatchLogRecordProcessor(
234
- logExporter,
235
- typeof otel.flushIntervalMs === "number"
236
- ? { scheduledDelayMillis: Math.max(1000, otel.flushIntervalMs) }
237
- : {},
238
- );
239
- logProvider = new LoggerProvider({
240
- resource,
241
- processors: [logProcessor],
242
- });
243
- const otelLogger = logProvider.getLogger("symi");
244
-
245
- stopLogTransport = registerLogTransport((logObj) => {
246
- try {
247
- const safeStringify = (value: unknown) => {
248
- try {
249
- return JSON.stringify(value);
250
- } catch {
251
- return String(value);
252
- }
253
- };
254
- const meta = (logObj as Record<string, unknown>)._meta as
255
- | {
256
- logLevelName?: string;
257
- date?: Date;
258
- name?: string;
259
- parentNames?: string[];
260
- path?: {
261
- filePath?: string;
262
- fileLine?: string;
263
- fileColumn?: string;
264
- filePathWithLine?: string;
265
- method?: string;
266
- };
267
- }
268
- | undefined;
269
- const logLevelName = meta?.logLevelName ?? "INFO";
270
- const severityNumber = logSeverityMap[logLevelName] ?? (9 as SeverityNumber);
271
-
272
- const numericArgs = Object.entries(logObj)
273
- .filter(([key]) => /^\d+$/.test(key))
274
- .toSorted((a, b) => Number(a[0]) - Number(b[0]))
275
- .map(([, value]) => value);
276
-
277
- let bindings: Record<string, unknown> | undefined;
278
- if (typeof numericArgs[0] === "string" && numericArgs[0].trim().startsWith("{")) {
279
- try {
280
- const parsed = JSON.parse(numericArgs[0]);
281
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
282
- bindings = parsed as Record<string, unknown>;
283
- numericArgs.shift();
284
- }
285
- } catch {
286
- // ignore malformed json bindings
287
- }
288
- }
289
-
290
- let message = "";
291
- if (numericArgs.length > 0 && typeof numericArgs[numericArgs.length - 1] === "string") {
292
- message = String(numericArgs.pop());
293
- } else if (numericArgs.length === 1) {
294
- message = safeStringify(numericArgs[0]);
295
- numericArgs.length = 0;
296
- }
297
- if (!message) {
298
- message = "log";
299
- }
300
-
301
- const attributes: Record<string, string | number | boolean> = {
302
- "symi.log.level": logLevelName,
303
- };
304
- if (meta?.name) {
305
- attributes["symi.logger"] = meta.name;
306
- }
307
- if (meta?.parentNames?.length) {
308
- attributes["symi.logger.parents"] = meta.parentNames.join(".");
309
- }
310
- if (bindings) {
311
- for (const [key, value] of Object.entries(bindings)) {
312
- if (
313
- typeof value === "string" ||
314
- typeof value === "number" ||
315
- typeof value === "boolean"
316
- ) {
317
- attributes[`symi.${key}`] = value;
318
- } else if (value != null) {
319
- attributes[`symi.${key}`] = safeStringify(value);
320
- }
321
- }
322
- }
323
- if (numericArgs.length > 0) {
324
- attributes["symi.log.args"] = safeStringify(numericArgs);
325
- }
326
- if (meta?.path?.filePath) {
327
- attributes["code.filepath"] = meta.path.filePath;
328
- }
329
- if (meta?.path?.fileLine) {
330
- attributes["code.lineno"] = Number(meta.path.fileLine);
331
- }
332
- if (meta?.path?.method) {
333
- attributes["code.function"] = meta.path.method;
334
- }
335
- if (meta?.path?.filePathWithLine) {
336
- attributes["symi.code.location"] = meta.path.filePathWithLine;
337
- }
338
-
339
- otelLogger.emit({
340
- body: message,
341
- severityText: logLevelName,
342
- severityNumber,
343
- attributes,
344
- timestamp: meta?.date ?? new Date(),
345
- });
346
- } catch (err) {
347
- ctx.logger.error(`diagnostics-otel: log transport failed: ${formatError(err)}`);
348
- }
349
- });
350
- }
351
-
352
- const spanWithDuration = (
353
- name: string,
354
- attributes: Record<string, string | number>,
355
- durationMs?: number,
356
- ) => {
357
- const startTime =
358
- typeof durationMs === "number" ? Date.now() - Math.max(0, durationMs) : undefined;
359
- const span = tracer.startSpan(name, {
360
- attributes,
361
- ...(startTime ? { startTime } : {}),
362
- });
363
- return span;
364
- };
365
-
366
- const recordModelUsage = (evt: Extract<DiagnosticEventPayload, { type: "model.usage" }>) => {
367
- const attrs = {
368
- "symi.channel": evt.channel ?? "unknown",
369
- "symi.provider": evt.provider ?? "unknown",
370
- "symi.model": evt.model ?? "unknown",
371
- };
372
-
373
- const usage = evt.usage;
374
- if (usage.input) {
375
- tokensCounter.add(usage.input, { ...attrs, "symi.token": "input" });
376
- }
377
- if (usage.output) {
378
- tokensCounter.add(usage.output, { ...attrs, "symi.token": "output" });
379
- }
380
- if (usage.cacheRead) {
381
- tokensCounter.add(usage.cacheRead, { ...attrs, "symi.token": "cache_read" });
382
- }
383
- if (usage.cacheWrite) {
384
- tokensCounter.add(usage.cacheWrite, { ...attrs, "symi.token": "cache_write" });
385
- }
386
- if (usage.promptTokens) {
387
- tokensCounter.add(usage.promptTokens, { ...attrs, "symi.token": "prompt" });
388
- }
389
- if (usage.total) {
390
- tokensCounter.add(usage.total, { ...attrs, "symi.token": "total" });
391
- }
392
-
393
- if (evt.costUsd) {
394
- costCounter.add(evt.costUsd, attrs);
395
- }
396
- if (evt.durationMs) {
397
- durationHistogram.record(evt.durationMs, attrs);
398
- }
399
- if (evt.context?.limit) {
400
- contextHistogram.record(evt.context.limit, {
401
- ...attrs,
402
- "symi.context": "limit",
403
- });
404
- }
405
- if (evt.context?.used) {
406
- contextHistogram.record(evt.context.used, {
407
- ...attrs,
408
- "symi.context": "used",
409
- });
410
- }
411
-
412
- if (!tracesEnabled) {
413
- return;
414
- }
415
- const spanAttrs: Record<string, string | number> = {
416
- ...attrs,
417
- "symi.sessionKey": evt.sessionKey ?? "",
418
- "symi.sessionId": evt.sessionId ?? "",
419
- "symi.tokens.input": usage.input ?? 0,
420
- "symi.tokens.output": usage.output ?? 0,
421
- "symi.tokens.cache_read": usage.cacheRead ?? 0,
422
- "symi.tokens.cache_write": usage.cacheWrite ?? 0,
423
- "symi.tokens.total": usage.total ?? 0,
424
- };
425
-
426
- const span = spanWithDuration("symi.model.usage", spanAttrs, evt.durationMs);
427
- span.end();
428
- };
429
-
430
- const recordWebhookReceived = (
431
- evt: Extract<DiagnosticEventPayload, { type: "webhook.received" }>,
432
- ) => {
433
- const attrs = {
434
- "symi.channel": evt.channel ?? "unknown",
435
- "symi.webhook": evt.updateType ?? "unknown",
436
- };
437
- webhookReceivedCounter.add(1, attrs);
438
- };
439
-
440
- const recordWebhookProcessed = (
441
- evt: Extract<DiagnosticEventPayload, { type: "webhook.processed" }>,
442
- ) => {
443
- const attrs = {
444
- "symi.channel": evt.channel ?? "unknown",
445
- "symi.webhook": evt.updateType ?? "unknown",
446
- };
447
- if (typeof evt.durationMs === "number") {
448
- webhookDurationHistogram.record(evt.durationMs, attrs);
449
- }
450
- if (!tracesEnabled) {
451
- return;
452
- }
453
- const spanAttrs: Record<string, string | number> = { ...attrs };
454
- if (evt.chatId !== undefined) {
455
- spanAttrs["symi.chatId"] = String(evt.chatId);
456
- }
457
- const span = spanWithDuration("symi.webhook.processed", spanAttrs, evt.durationMs);
458
- span.end();
459
- };
460
-
461
- const recordWebhookError = (
462
- evt: Extract<DiagnosticEventPayload, { type: "webhook.error" }>,
463
- ) => {
464
- const attrs = {
465
- "symi.channel": evt.channel ?? "unknown",
466
- "symi.webhook": evt.updateType ?? "unknown",
467
- };
468
- webhookErrorCounter.add(1, attrs);
469
- if (!tracesEnabled) {
470
- return;
471
- }
472
- const spanAttrs: Record<string, string | number> = {
473
- ...attrs,
474
- "symi.error": evt.error,
475
- };
476
- if (evt.chatId !== undefined) {
477
- spanAttrs["symi.chatId"] = String(evt.chatId);
478
- }
479
- const span = tracer.startSpan("symi.webhook.error", {
480
- attributes: spanAttrs,
481
- });
482
- span.setStatus({ code: SpanStatusCode.ERROR, message: evt.error });
483
- span.end();
484
- };
485
-
486
- const recordMessageQueued = (
487
- evt: Extract<DiagnosticEventPayload, { type: "message.queued" }>,
488
- ) => {
489
- const attrs = {
490
- "symi.channel": evt.channel ?? "unknown",
491
- "symi.source": evt.source ?? "unknown",
492
- };
493
- messageQueuedCounter.add(1, attrs);
494
- if (typeof evt.queueDepth === "number") {
495
- queueDepthHistogram.record(evt.queueDepth, attrs);
496
- }
497
- };
498
-
499
- const recordMessageProcessed = (
500
- evt: Extract<DiagnosticEventPayload, { type: "message.processed" }>,
501
- ) => {
502
- const attrs = {
503
- "symi.channel": evt.channel ?? "unknown",
504
- "symi.outcome": evt.outcome ?? "unknown",
505
- };
506
- messageProcessedCounter.add(1, attrs);
507
- if (typeof evt.durationMs === "number") {
508
- messageDurationHistogram.record(evt.durationMs, attrs);
509
- }
510
- if (!tracesEnabled) {
511
- return;
512
- }
513
- const spanAttrs: Record<string, string | number> = { ...attrs };
514
- if (evt.sessionKey) {
515
- spanAttrs["symi.sessionKey"] = evt.sessionKey;
516
- }
517
- if (evt.sessionId) {
518
- spanAttrs["symi.sessionId"] = evt.sessionId;
519
- }
520
- if (evt.chatId !== undefined) {
521
- spanAttrs["symi.chatId"] = String(evt.chatId);
522
- }
523
- if (evt.messageId !== undefined) {
524
- spanAttrs["symi.messageId"] = String(evt.messageId);
525
- }
526
- if (evt.reason) {
527
- spanAttrs["symi.reason"] = evt.reason;
528
- }
529
- const span = spanWithDuration("symi.message.processed", spanAttrs, evt.durationMs);
530
- if (evt.outcome === "error") {
531
- span.setStatus({ code: SpanStatusCode.ERROR, message: evt.error });
532
- }
533
- span.end();
534
- };
535
-
536
- const recordLaneEnqueue = (
537
- evt: Extract<DiagnosticEventPayload, { type: "queue.lane.enqueue" }>,
538
- ) => {
539
- const attrs = { "symi.lane": evt.lane };
540
- laneEnqueueCounter.add(1, attrs);
541
- queueDepthHistogram.record(evt.queueSize, attrs);
542
- };
543
-
544
- const recordLaneDequeue = (
545
- evt: Extract<DiagnosticEventPayload, { type: "queue.lane.dequeue" }>,
546
- ) => {
547
- const attrs = { "symi.lane": evt.lane };
548
- laneDequeueCounter.add(1, attrs);
549
- queueDepthHistogram.record(evt.queueSize, attrs);
550
- if (typeof evt.waitMs === "number") {
551
- queueWaitHistogram.record(evt.waitMs, attrs);
552
- }
553
- };
554
-
555
- const recordSessionState = (
556
- evt: Extract<DiagnosticEventPayload, { type: "session.state" }>,
557
- ) => {
558
- const attrs: Record<string, string> = { "symi.state": evt.state };
559
- if (evt.reason) {
560
- attrs["symi.reason"] = evt.reason;
561
- }
562
- sessionStateCounter.add(1, attrs);
563
- };
564
-
565
- const recordSessionStuck = (
566
- evt: Extract<DiagnosticEventPayload, { type: "session.stuck" }>,
567
- ) => {
568
- const attrs: Record<string, string> = { "symi.state": evt.state };
569
- sessionStuckCounter.add(1, attrs);
570
- if (typeof evt.ageMs === "number") {
571
- sessionStuckAgeHistogram.record(evt.ageMs, attrs);
572
- }
573
- if (!tracesEnabled) {
574
- return;
575
- }
576
- const spanAttrs: Record<string, string | number> = { ...attrs };
577
- if (evt.sessionKey) {
578
- spanAttrs["symi.sessionKey"] = evt.sessionKey;
579
- }
580
- if (evt.sessionId) {
581
- spanAttrs["symi.sessionId"] = evt.sessionId;
582
- }
583
- spanAttrs["symi.queueDepth"] = evt.queueDepth ?? 0;
584
- spanAttrs["symi.ageMs"] = evt.ageMs;
585
- const span = tracer.startSpan("symi.session.stuck", { attributes: spanAttrs });
586
- span.setStatus({ code: SpanStatusCode.ERROR, message: "session stuck" });
587
- span.end();
588
- };
589
-
590
- const recordRunAttempt = (evt: Extract<DiagnosticEventPayload, { type: "run.attempt" }>) => {
591
- runAttemptCounter.add(1, { "symi.attempt": evt.attempt });
592
- };
593
-
594
- const recordHeartbeat = (
595
- evt: Extract<DiagnosticEventPayload, { type: "diagnostic.heartbeat" }>,
596
- ) => {
597
- queueDepthHistogram.record(evt.queued, { "symi.channel": "heartbeat" });
598
- };
599
-
600
- unsubscribe = onDiagnosticEvent((evt: DiagnosticEventPayload) => {
601
- try {
602
- switch (evt.type) {
603
- case "model.usage":
604
- recordModelUsage(evt);
605
- return;
606
- case "webhook.received":
607
- recordWebhookReceived(evt);
608
- return;
609
- case "webhook.processed":
610
- recordWebhookProcessed(evt);
611
- return;
612
- case "webhook.error":
613
- recordWebhookError(evt);
614
- return;
615
- case "message.queued":
616
- recordMessageQueued(evt);
617
- return;
618
- case "message.processed":
619
- recordMessageProcessed(evt);
620
- return;
621
- case "queue.lane.enqueue":
622
- recordLaneEnqueue(evt);
623
- return;
624
- case "queue.lane.dequeue":
625
- recordLaneDequeue(evt);
626
- return;
627
- case "session.state":
628
- recordSessionState(evt);
629
- return;
630
- case "session.stuck":
631
- recordSessionStuck(evt);
632
- return;
633
- case "run.attempt":
634
- recordRunAttempt(evt);
635
- return;
636
- case "diagnostic.heartbeat":
637
- recordHeartbeat(evt);
638
- return;
639
- }
640
- } catch (err) {
641
- ctx.logger.error(
642
- `diagnostics-otel: event handler failed (${evt.type}): ${formatError(err)}`,
643
- );
644
- }
645
- });
646
-
647
- if (logsEnabled) {
648
- ctx.logger.info("diagnostics-otel: logs exporter enabled (OTLP/HTTP)");
649
- }
650
- },
651
- async stop() {
652
- unsubscribe?.();
653
- unsubscribe = null;
654
- stopLogTransport?.();
655
- stopLogTransport = null;
656
- if (logProvider) {
657
- await logProvider.shutdown().catch(() => undefined);
658
- logProvider = null;
659
- }
660
- if (sdk) {
661
- await sdk.shutdown().catch(() => undefined);
662
- sdk = null;
663
- }
664
- },
665
- } satisfies SymiPluginService;
666
- }
@@ -1,8 +0,0 @@
1
- {
2
- "id": "diagnostics-otel",
3
- "configSchema": {
4
- "type": "object",
5
- "additionalProperties": false,
6
- "properties": {}
7
- }
8
- }
@@ -1,24 +0,0 @@
1
- # Google Antigravity Auth (Symi plugin)
2
-
3
- OAuth provider plugin for **Google Antigravity** (Cloud Code Assist).
4
-
5
- ## Enable
6
-
7
- Bundled plugins are disabled by default. Enable this one:
8
-
9
- ```bash
10
- symi plugins enable google-antigravity-auth
11
- ```
12
-
13
- Restart the Gateway after enabling.
14
-
15
- ## Authenticate
16
-
17
- ```bash
18
- symi models auth login --provider google-antigravity --set-default
19
- ```
20
-
21
- ## Notes
22
-
23
- - Antigravity uses Google Cloud project quotas.
24
- - If requests fail, ensure Gemini for Google Cloud is enabled.