@agent-native/core 0.133.2 → 0.134.0

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 (213) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +62 -0
  3. package/corpus/core/docs/content/observability.mdx +41 -1
  4. package/corpus/core/docs/content/tracking.mdx +25 -0
  5. package/corpus/core/package.json +1 -1
  6. package/corpus/core/src/agent/run-manager.ts +7 -0
  7. package/corpus/core/src/client/agent-chat-adapter.ts +10 -0
  8. package/corpus/core/src/client/analytics.ts +105 -1
  9. package/corpus/core/src/client/use-action.ts +6 -0
  10. package/corpus/core/src/deploy/build.ts +38 -1
  11. package/corpus/core/src/observability/posthog-ai.ts +294 -0
  12. package/corpus/core/src/observability/routes.ts +29 -6
  13. package/corpus/core/src/observability/traces.ts +287 -12
  14. package/corpus/core/src/observability/types.ts +11 -0
  15. package/corpus/core/src/secrets/register-framework-secrets.ts +16 -0
  16. package/corpus/core/src/server/agent-run-context.ts +21 -0
  17. package/corpus/core/src/server/capture-error.ts +8 -0
  18. package/corpus/core/src/server/core-routes-plugin.ts +75 -4
  19. package/corpus/core/src/server/deploy-environment.ts +57 -0
  20. package/corpus/core/src/server/error-noise-filter.ts +268 -0
  21. package/corpus/core/src/server/posthog-config.ts +75 -0
  22. package/corpus/core/src/server/request-context.ts +6 -0
  23. package/corpus/core/src/server/sentry-config.ts +4 -8
  24. package/corpus/core/src/server/sentry-plugin.ts +13 -29
  25. package/corpus/core/src/server/sentry.ts +13 -156
  26. package/corpus/core/src/server/ssr-handler.ts +6 -1
  27. package/corpus/core/src/shared/mcp-embed-headers.ts +1 -1
  28. package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +36 -10
  29. package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +55 -1
  30. package/corpus/core/src/tracking/error-capture.ts +44 -109
  31. package/corpus/core/src/tracking/index.ts +11 -0
  32. package/corpus/core/src/tracking/posthog-exception.ts +305 -0
  33. package/corpus/core/src/tracking/providers.ts +91 -14
  34. package/corpus/core/src/tracking/redaction.ts +105 -0
  35. package/corpus/templates/content/actions/_batch-utils.ts +33 -0
  36. package/corpus/templates/content/actions/_builder-cms-read-client.ts +173 -81
  37. package/corpus/templates/content/actions/_content-files.ts +31 -21
  38. package/corpus/templates/content/actions/_database-source-utils.ts +653 -155
  39. package/corpus/templates/content/actions/_database-utils.ts +535 -41
  40. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +291 -240
  41. package/corpus/templates/content/actions/add-database-item.ts +15 -1
  42. package/corpus/templates/content/actions/attach-content-database-source.ts +156 -58
  43. package/corpus/templates/content/actions/bind-content-database-source-field.ts +2 -2
  44. package/corpus/templates/content/actions/cancel-prepared-builder-source-update.ts +4 -1
  45. package/corpus/templates/content/actions/delete-database-items.ts +8 -2
  46. package/corpus/templates/content/actions/disconnect-content-database-source.ts +2 -2
  47. package/corpus/templates/content/actions/duplicate-database-item.ts +15 -1
  48. package/corpus/templates/content/actions/duplicate-database-items.ts +19 -1
  49. package/corpus/templates/content/actions/execute-builder-source-execution.ts +2 -1
  50. package/corpus/templates/content/actions/get-content-database.ts +12 -64
  51. package/corpus/templates/content/actions/move-database-item.ts +4 -1
  52. package/corpus/templates/content/actions/prepare-builder-source-execution.ts +1 -1
  53. package/corpus/templates/content/actions/prepare-builder-source-review.ts +4 -8
  54. package/corpus/templates/content/actions/preview-content-database-source-attach.ts +92 -0
  55. package/corpus/templates/content/actions/process-builder-body-hydration.ts +2 -1
  56. package/corpus/templates/content/actions/query-content-database-items.ts +64 -0
  57. package/corpus/templates/content/actions/refresh-content-database-source.ts +7 -0
  58. package/corpus/templates/content/actions/review-content-database-source-change-set.ts +1 -1
  59. package/corpus/templates/content/actions/set-content-database-source-write-mode.ts +1 -1
  60. package/corpus/templates/content/actions/stage-builder-revision.ts +1 -1
  61. package/corpus/templates/content/actions/update-content-database-personal-view.ts +29 -3
  62. package/corpus/templates/content/actions/update-content-database-view.ts +1 -1
  63. package/corpus/templates/content/actions/validate-builder-source-execution.ts +1 -1
  64. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +3 -22
  65. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +267 -105
  66. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +82 -1
  67. package/corpus/templates/content/app/hooks/use-content-database.ts +285 -24
  68. package/corpus/templates/content/app/hooks/use-document-properties.ts +7 -6
  69. package/corpus/templates/content/app/i18n-data.ts +10 -0
  70. package/corpus/templates/content/changelog/2026-07-29-large-databases-keep-useful-rows-visible.md +6 -0
  71. package/corpus/templates/content/changelog/2026-07-30-builder-source-columns-now-appear-immediately-when-connected.md +6 -0
  72. package/corpus/templates/content/changelog/2026-07-30-large-builder-backed-tables-show-useful-rows-sooner-and-fini.md +6 -0
  73. package/corpus/templates/content/changelog/2026-08-01-large-builder-databases-now-show-rows-immediately-and-finish.md +6 -0
  74. package/corpus/templates/content/parity/matrix.md +2 -1
  75. package/corpus/templates/content/parity/matrix.ts +25 -0
  76. package/corpus/templates/content/shared/api.ts +54 -4
  77. package/corpus/templates/content/shared/database-query.ts +359 -0
  78. package/dist/agent/run-manager.d.ts.map +1 -1
  79. package/dist/agent/run-manager.js +7 -0
  80. package/dist/agent/run-manager.js.map +1 -1
  81. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  82. package/dist/client/agent-chat-adapter.js +12 -0
  83. package/dist/client/agent-chat-adapter.js.map +1 -1
  84. package/dist/client/analytics.d.ts +8 -0
  85. package/dist/client/analytics.d.ts.map +1 -1
  86. package/dist/client/analytics.js +95 -1
  87. package/dist/client/analytics.js.map +1 -1
  88. package/dist/client/use-action.d.ts.map +1 -1
  89. package/dist/client/use-action.js +6 -0
  90. package/dist/client/use-action.js.map +1 -1
  91. package/dist/collab/routes.d.ts +1 -1
  92. package/dist/collab/struct-routes.d.ts +1 -1
  93. package/dist/deploy/build.d.ts.map +1 -1
  94. package/dist/deploy/build.js +38 -1
  95. package/dist/deploy/build.js.map +1 -1
  96. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  97. package/dist/notifications/routes.d.ts +3 -3
  98. package/dist/observability/posthog-ai.d.ts +126 -0
  99. package/dist/observability/posthog-ai.d.ts.map +1 -0
  100. package/dist/observability/posthog-ai.js +190 -0
  101. package/dist/observability/posthog-ai.js.map +1 -0
  102. package/dist/observability/routes.d.ts +1 -1
  103. package/dist/observability/routes.d.ts.map +1 -1
  104. package/dist/observability/routes.js +26 -6
  105. package/dist/observability/routes.js.map +1 -1
  106. package/dist/observability/traces.d.ts +9 -0
  107. package/dist/observability/traces.d.ts.map +1 -1
  108. package/dist/observability/traces.js +219 -10
  109. package/dist/observability/traces.js.map +1 -1
  110. package/dist/observability/types.d.ts +10 -0
  111. package/dist/observability/types.d.ts.map +1 -1
  112. package/dist/observability/types.js +1 -0
  113. package/dist/observability/types.js.map +1 -1
  114. package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
  115. package/dist/secrets/register-framework-secrets.js +14 -0
  116. package/dist/secrets/register-framework-secrets.js.map +1 -1
  117. package/dist/server/agent-run-context.d.ts +8 -0
  118. package/dist/server/agent-run-context.d.ts.map +1 -1
  119. package/dist/server/agent-run-context.js +18 -0
  120. package/dist/server/agent-run-context.js.map +1 -1
  121. package/dist/server/capture-error.d.ts +8 -0
  122. package/dist/server/capture-error.d.ts.map +1 -1
  123. package/dist/server/capture-error.js.map +1 -1
  124. package/dist/server/core-routes-plugin.d.ts +0 -23
  125. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  126. package/dist/server/core-routes-plugin.js +71 -7
  127. package/dist/server/core-routes-plugin.js.map +1 -1
  128. package/dist/server/deploy-environment.d.ts +17 -0
  129. package/dist/server/deploy-environment.d.ts.map +1 -0
  130. package/dist/server/deploy-environment.js +47 -0
  131. package/dist/server/deploy-environment.js.map +1 -0
  132. package/dist/server/error-noise-filter.d.ts +80 -0
  133. package/dist/server/error-noise-filter.d.ts.map +1 -0
  134. package/dist/server/error-noise-filter.js +173 -0
  135. package/dist/server/error-noise-filter.js.map +1 -0
  136. package/dist/server/posthog-config.d.ts +28 -0
  137. package/dist/server/posthog-config.d.ts.map +1 -0
  138. package/dist/server/posthog-config.js +53 -0
  139. package/dist/server/posthog-config.js.map +1 -0
  140. package/dist/server/request-context.d.ts +6 -0
  141. package/dist/server/request-context.d.ts.map +1 -1
  142. package/dist/server/request-context.js.map +1 -1
  143. package/dist/server/sentry-config.d.ts +1 -0
  144. package/dist/server/sentry-config.d.ts.map +1 -1
  145. package/dist/server/sentry-config.js +3 -1
  146. package/dist/server/sentry-config.js.map +1 -1
  147. package/dist/server/sentry-plugin.d.ts.map +1 -1
  148. package/dist/server/sentry-plugin.js +12 -27
  149. package/dist/server/sentry-plugin.js.map +1 -1
  150. package/dist/server/sentry.d.ts.map +1 -1
  151. package/dist/server/sentry.js +8 -124
  152. package/dist/server/sentry.js.map +1 -1
  153. package/dist/server/ssr-handler.d.ts.map +1 -1
  154. package/dist/server/ssr-handler.js +6 -1
  155. package/dist/server/ssr-handler.js.map +1 -1
  156. package/dist/shared/mcp-embed-headers.d.ts +1 -1
  157. package/dist/shared/mcp-embed-headers.d.ts.map +1 -1
  158. package/dist/shared/mcp-embed-headers.js +1 -1
  159. package/dist/shared/mcp-embed-headers.js.map +1 -1
  160. package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +36 -10
  161. package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +55 -1
  162. package/dist/tracking/error-capture.d.ts +7 -0
  163. package/dist/tracking/error-capture.d.ts.map +1 -1
  164. package/dist/tracking/error-capture.js +10 -73
  165. package/dist/tracking/error-capture.js.map +1 -1
  166. package/dist/tracking/index.d.ts +1 -0
  167. package/dist/tracking/index.d.ts.map +1 -1
  168. package/dist/tracking/index.js +1 -0
  169. package/dist/tracking/index.js.map +1 -1
  170. package/dist/tracking/posthog-exception.d.ts +103 -0
  171. package/dist/tracking/posthog-exception.d.ts.map +1 -0
  172. package/dist/tracking/posthog-exception.js +181 -0
  173. package/dist/tracking/posthog-exception.js.map +1 -0
  174. package/dist/tracking/providers.d.ts +14 -0
  175. package/dist/tracking/providers.d.ts.map +1 -1
  176. package/dist/tracking/providers.js +63 -11
  177. package/dist/tracking/providers.js.map +1 -1
  178. package/dist/tracking/redaction.d.ts +25 -0
  179. package/dist/tracking/redaction.d.ts.map +1 -0
  180. package/dist/tracking/redaction.js +85 -0
  181. package/dist/tracking/redaction.js.map +1 -0
  182. package/docs/content/observability.mdx +41 -1
  183. package/docs/content/tracking.mdx +25 -0
  184. package/package.json +1 -1
  185. package/src/agent/run-manager.ts +7 -0
  186. package/src/client/agent-chat-adapter.ts +10 -0
  187. package/src/client/analytics.ts +105 -1
  188. package/src/client/use-action.ts +6 -0
  189. package/src/deploy/build.ts +38 -1
  190. package/src/observability/posthog-ai.ts +294 -0
  191. package/src/observability/routes.ts +29 -6
  192. package/src/observability/traces.ts +287 -12
  193. package/src/observability/types.ts +11 -0
  194. package/src/secrets/register-framework-secrets.ts +16 -0
  195. package/src/server/agent-run-context.ts +21 -0
  196. package/src/server/capture-error.ts +8 -0
  197. package/src/server/core-routes-plugin.ts +75 -4
  198. package/src/server/deploy-environment.ts +57 -0
  199. package/src/server/error-noise-filter.ts +268 -0
  200. package/src/server/posthog-config.ts +75 -0
  201. package/src/server/request-context.ts +6 -0
  202. package/src/server/sentry-config.ts +4 -8
  203. package/src/server/sentry-plugin.ts +13 -29
  204. package/src/server/sentry.ts +13 -156
  205. package/src/server/ssr-handler.ts +6 -1
  206. package/src/shared/mcp-embed-headers.ts +1 -1
  207. package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +36 -10
  208. package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +55 -1
  209. package/src/tracking/error-capture.ts +44 -109
  210. package/src/tracking/index.ts +11 -0
  211. package/src/tracking/posthog-exception.ts +305 -0
  212. package/src/tracking/providers.ts +91 -14
  213. package/src/tracking/redaction.ts +105 -0
@@ -1 +1 @@
1
- {"version":3,"file":"traces.js","sourceRoot":"","sources":["../../src/observability/traces.ts"],"names":[],"mappings":"AAKA,OAAO,EAAkB,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAEpE,OAAO,EAAE,4BAA4B,EAAE,MAAM,YAAY,CAAC;AAE1D,SAAS,MAAM;IACb,OAAO,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AACxE,CAAC;AAED,SAAS,qBAAqB,CAC5B,UAA8B,EAC9B,KAAa;IAEb,MAAM,MAAM,GAAG,UAAU,EAAE,IAAI,EAAE,CAAC;IAClC,IAAI,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACzE,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,WAAW,CAAC;IACxD,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IACrD,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IAClD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAa;IAC1C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;AAC9D,CAAC;AAED,MAAM,iCAAiC,GAAG,EAAE,CAAC;AAC7C,MAAM,6BAA6B,GAAG,GAAG,CAAC;AAC1C,MAAM,0BAA0B,GAC9B,wIAAwI,CAAC;AAW3I,SAAS,wBAAwB,CAAC,KAAa;IAC7C,OAAO,KAAK,CAAC,MAAM,GAAG,6BAA6B;QACjD,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,6BAA6B,CAAC,GAAG;QACrD,CAAC,CAAC,KAAK,CAAC;AACZ,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAa;IAC3C,MAAM,cAAc,GAClB,8FAA8F,CAAC;IACjG,MAAM,iBAAiB,GAAG,eAAe,cAAc,6BAA6B,CAAC;IACrF,OAAO,KAAK;SACT,OAAO,CACN,IAAI,MAAM,CACR,GAAG,iBAAiB,sCAAsC,EAC1D,IAAI,CACL,EACD,cAAc,CACf;SACA,OAAO,CACN,IAAI,MAAM,CAAC,GAAG,iBAAiB,qBAAqB,EAAE,IAAI,CAAC,EAC3D,cAAc,CACf;SACA,OAAO,CAAC,kCAAkC,EAAE,YAAY,CAAC;SACzD,OAAO,CAAC,0BAA0B,EAAE,YAAY,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,8BAA8B,CAAC,IAgDvC;IACC,MAAM,QAAQ,GAAG,qBAAqB,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACpE,MAAM,OAAO,GACX,IAAI,CAAC,aAAa,KAAK,SAAS;QAC9B,CAAC,CAAC,qBAAqB,CAAC,IAAI,CAAC,aAAa,CAAC;QAC3C,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,WAAW,GACf,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS;QAC/D,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY;QACtC,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,IAAI,SAAS,CAAC;IAC7C,MAAM,UAAU,GAA4B;QAC1C,GAAG,0BAA0B,EAAE;QAC/B,MAAM,EAAE,qBAAqB;QAC7B,SAAS,EAAE,UAAU;QACrB,MAAM,EAAE,IAAI,CAAC,KAAK;QAClB,SAAS,EAAE,IAAI,CAAC,QAAQ;QACxB,cAAc,EAAE,IAAI,CAAC,YAAY;QACjC,OAAO,EAAE,IAAI,CAAC,SAAS;QACvB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,QAAQ;QACR,YAAY,EAAE,IAAI,CAAC,WAAW;QAC9B,aAAa,EAAE,IAAI,CAAC,YAAY;QAChC,YAAY,EAAE,WAAW;QACzB,iBAAiB,EAAE,IAAI,CAAC,eAAe;QACvC,kBAAkB,EAAE,IAAI,CAAC,gBAAgB;QACzC,eAAe,EAAE,IAAI,CAAC,aAAa;QACnC,QAAQ,EAAE,OAAO;QACjB,WAAW,EAAE,IAAI,CAAC,UAAU;QAC5B,sBAAsB,EAAE,IAAI,CAAC,YAAY;QACzC,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,UAAU,EAAE,IAAI,CAAC,SAAS;QAC1B,gBAAgB,EAAE,IAAI,CAAC,eAAe;QACtC,YAAY,EAAE,IAAI,CAAC,WAAW;QAC9B,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,eAAe,EAAE,IAAI,CAAC,cAAc;QACpC,cAAc,EAAE,IAAI,CAAC,eAAe,EAAE,KAAK;QAC3C,aAAa,EACX,IAAI,CAAC,eAAe,EAAE,KAAK,KAAK,QAAQ;YACxC,IAAI,CAAC,eAAe,EAAE,KAAK,KAAK,gBAAgB;YAC9C,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI;YAC3B,CAAC,CAAC,SAAS;QACf,kBAAkB,EAChB,IAAI,CAAC,eAAe,EAAE,KAAK,KAAK,QAAQ;YACtC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS;YAChC,CAAC,CAAC,SAAS;QACf,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QAC7C,mBAAmB,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ;QAC9C,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,SAAS;QACtC,WAAW,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM;QACpC,aAAa,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW;QAC3C,cAAc,EAAE,IAAI,CAAC,UAAU,EAAE,YAAY;QAC7C,sBAAsB,EAAE,IAAI,CAAC,oBAAoB;QACjD,UAAU,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE;QAClD,aAAa,EAAE,IAAI,CAAC,SAAS;QAC7B,YAAY,EAAE,IAAI,CAAC,KAAK;QACxB,cAAc,EAAE,IAAI,CAAC,QAAQ,IAAI,SAAS;QAC1C,WAAW,EAAE,IAAI,CAAC,SAAS;QAC3B,aAAa,EAAE,WAAW;QAC1B,aAAa,EAAE,IAAI,CAAC,YAAY;QAChC,SAAS,EAAE,IAAI,CAAC,KAAK;QACrB,YAAY,EAAE,QAAQ;QACtB,gBAAgB,EAAE,IAAI,CAAC,WAAW;QAClC,iBAAiB,EAAE,IAAI,CAAC,YAAY;QACpC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI;QAC/D,YAAY,EAAE,IAAI,CAAC,MAAM,KAAK,OAAO;QACrC,SAAS,EAAE,KAAK;QAChB,2BAA2B,EAAE,IAAI,CAAC,eAAe;QACjD,+BAA+B,EAAE,IAAI,CAAC,gBAAgB;QACtD,iBAAiB,EAAE,CAAC;QACpB,kBAAkB,EAAE,OAAO;KAC5B,CAAC;IACF,IAAI,IAAI,CAAC,qBAAqB,EAAE,MAAM,EAAE,CAAC;QACvC,UAAU,CAAC,cAAc,GAAG,IAAI,CAAC,qBAAqB;aACnD,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC;aAC5C,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,UAAU,CAAC,mBAAmB,GAAG,IAAI,CAAC,qBAAqB;aACxD,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;aACzC,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,IAAI,IAAI,CAAC,qBAAqB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5C,UAAU,CAAC,aAAa,GAAG,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;YACtE,UAAU,CAAC,kBAAkB,GAAG,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1E,CAAC;IACH,CAAC;IACD,IAAI,KAAK;QAAE,UAAU,CAAC,aAAa,GAAG,KAAK,CAAC;IAE5C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1C,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,SAAS;YAAE,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI,CAAC;QACH,KAAK,MAAM,CAAC,yBAAyB,CAAC;aACnC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;YAClB,KAAK,CAAC,gBAAgB,EAAE,UAAU,EAAE;gBAClC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,SAAS;aACjC,CAAC,CAAC;QACL,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;IACnE,CAAC;AACH,CAAC;AAED;;;;;;2BAM2B;AAC3B,MAAM,uBAAuB,GAC3B,uGAAuG,CAAC;AAE1G;;;wEAGwE;AACxE,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,OAAO,UAAU,CAAC,KAAK,EAAE,IAAI,OAAO,EAAU,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,UAAU,CAAC,KAAc,EAAE,IAAqB;IACvD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC9D,IAAI,IAAI,CAAC,GAAG,CAAC,KAAe,CAAC;QAAE,OAAO,YAAY,CAAC;IACnD,IAAI,CAAC,GAAG,CAAC,KAAe,CAAC,CAAC;IAC1B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;QACtE,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACpC,GAAG,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB;IAC1C,IAAI,MAAM,GAAwC,IAAI,CAAC;IACvD,IAAI,CAAC;QACH,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAC5D,MAAM,GAAG,CAAC,MAAM,UAAU,CACxB,sBAAsB,CACvB,CAAwC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,MAAM,EAAE,8BAA8B,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC1E,OAAO;QACL,GAAG,4BAA4B;QAC/B,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC;QACjB,GAAG,8BAA8B,CAAC,MAAM,CAAC;KAC1C,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IA4DzC;IACC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC5B,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC;IAC9B,MAAM,wBAAwB,GAC5B,MAAM,CAAC,wBAAwB,IAAI,IAAI,CAAC,cAAc,IAAI,QAAQ,IAAI,MAAM;QAC1E,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;aACjB,IAAI,CAAC,CAAC,EAAE,8BAA8B,EAAE,EAAE,EAAE,CAC3C,8BAA8B,CAAC,QAAQ,EAAE;YACvC,MAAM;YACN,YAAY,EAAE,KAAK;SACpB,CAAC,CACH;aACA,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;QACtB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B,0EAA0E;IAC1E,2EAA2E;IAC3E,2EAA2E;IAC3E,yEAAyE;IACzE,oDAAoD;IACpD,MAAM,kBAAkB,GAAG,cAAc,CAAC,WAAW,EAAE;QACrD,cAAc,EAAE,KAAK;QACrB,iBAAiB,EAAE,QAAQ,IAAI,SAAS;QACxC,eAAe,EAAE,MAAM,IAAI,SAAS;QACpC,aAAa,EAAE,QAAQ,CAAC,KAAK;QAC7B,8BAA8B,EAAE,IAAI,CAAC,oBAAoB;QACzD,qBAAqB,EACnB,IAAI,CAAC,qBAAqB,EAAE,MAAM,KAAK,CAAC;YACtC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,YAAY;YAC5C,CAAC,CAAC,SAAS;QACf,0BAA0B,EACxB,IAAI,CAAC,qBAAqB,EAAE,MAAM,KAAK,CAAC;YACtC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,SAAS;YACzC,CAAC,CAAC,SAAS;KAChB,CAAC,CAAC;IAEH,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,IAAI,qBAAqB,GAAG,CAAC,CAAC;IAC9B,oEAAoE;IACpE,MAAM,YAAY,GAAG,IAAI,GAAG,EAWzB,CAAC;IACJ,4EAA4E;IAC5E,8EAA8E;IAC9E,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAoB,CAAC;IACvD,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtD,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAA8B,CAAC;IAElE,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,wEAAwE;IACxE,gDAAgD;IAChD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAa,CAAC;IAC/C,IAAI,KAAiC,CAAC;IACtC,IAAI,SAAS,GAAwB,SAAS,CAAC;IAC/C,IAAI,YAAY,GAAkB,IAAI,CAAC;IACvC,IAAI,WAAW,GAAmC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC;IACxE,IAAI,eAA6C,CAAC;IAElD,MAAM,mBAAmB,GAAG,CAAC,OAAyB,EAAQ,EAAE;QAC9D,eAAe,GAAG,OAAO,CAAC;QAC1B,IAAI,OAAO,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;YAClC,SAAS,GAAG,SAAS,CAAC;YACtB,YAAY,GAAG,IAAI,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,SAAS,GAAG,OAAO,CAAC;YACpB,YAAY;gBACV,OAAO,CAAC,KAAK,KAAK,UAAU;oBAC1B,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,IAAI,yBAAyB,CAAC;oBAChD,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;QACxB,CAAC;QACD,WAAW,GAAG;YACZ,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC;YACtB,cAAc,EAAE,OAAO,CAAC,KAAK;YAC7B,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,QAAQ;gBAC5B,CAAC,CAAC,EAAE,kBAAkB,EAAE,OAAO,CAAC,SAAS,EAAE;gBAC3C,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;QACF,IAAI,CAAC;YACH,QAAQ,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;QACvD,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,CAAC,KAAqB,EAAQ,EAAE;QACvD,IAAI,CAAC;YACH,qEAAqE;YACrE,wEAAwE;YACxE,uEAAuE;YACvE,yEAAyE;YACzE,qEAAqE;YACrE,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACpD,SAAS,GAAG,SAAS,CAAC;gBACtB,YAAY,GAAG,IAAI,CAAC;YACtB,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAClC,SAAS,GAAG,OAAO,CAAC;gBACpB,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC;YAC7B,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBACrC,SAAS,GAAG,OAAO,CAAC;gBACpB,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC;YAC9B,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBACvC,SAAS,GAAG,OAAO,CAAC;gBACpB,YAAY,GAAG,iCAAiC,CAAC;YACnD,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;gBAC5C,SAAS,GAAG,OAAO,CAAC;gBACpB,YAAY,GAAG,iBAAiB,CAAC;YACnC,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAChC,MAAM,OAAO,GAAG,qBAAqB,EAAE,CAAC;gBACxC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;gBACrB,iEAAiE;gBACjE,oEAAoE;gBACpE,qEAAqE;gBACrE,uEAAuE;gBACvE,MAAM,KAAK,GAaP;oBACF,MAAM,EAAE,GAAG;oBACX,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACzC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;oBACnB,QAAQ,EAAE,KAAK,CAAC,IAAI;oBACpB,KAAK,EAAE,KAAK,CAAC,KAAK;oBAClB,QAAQ,EAAE,IAAI;iBACf,CAAC;gBACF,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBACjC,IAAI,KAAK,CAAC,EAAE;oBAAE,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;gBACzD,KAAK,cAAc,CAAC,WAAW,EAAE;oBAC/B,WAAW,EAAE,KAAK,CAAC,IAAI;iBACxB,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;oBACf,IAAI,CAAC,IAAI;wBAAE,OAAO;oBAClB,sEAAsE;oBACtE,+DAA+D;oBAC/D,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;wBACpB,YAAY,CAAC,IAAI,EAAE;4BACjB,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM;4BAC9B,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,YAAY;yBAC3C,CAAC,CAAC;oBACL,CAAC;yBAAM,CAAC;wBACN,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;wBACtB,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBAC9B,CAAC;gBACH,CAAC,CAAC,CAAC;gBACH,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACjD,IAAI,KAAK;oBAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;;oBAC1B,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;YACrD,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBACtC,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACjD,MAAM,aAAa,GAAG,KAAK,CAAC,EAAE;oBAC5B,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBACnC,CAAC,CAAC,SAAS,CAAC;gBACd,MAAM,gBAAgB,GACpB,KAAK,CAAC,EAAE,IAAI,aAAa,KAAK,SAAS,IAAI,KAAK;oBAC9C,CAAC,CAAC,KAAK,CAAC,SAAS,CACb,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,CACpD;oBACH,CAAC,CAAC,CAAC,CAAC,CAAC;gBACT,MAAM,OAAO,GACX,aAAa;oBACb,CAAC,KAAK,CAAC,EAAE;wBACP,CAAC,CAAC,gBAAgB,IAAI,CAAC;4BACrB,CAAC,CAAC,KAAK,EAAE,CAAC,gBAAgB,CAAC;4BAC3B,CAAC,CAAC,SAAS;wBACb,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBACtB,MAAM,OAAO,GACX,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAChE,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;oBAC1B,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;oBAC7B,IAAI,OAAO,EAAE,MAAM;wBAAE,mBAAmB,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;oBAChE,IAAI,CAAC,aAAa,KAAK,SAAS,IAAI,gBAAgB,IAAI,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC;wBACpE,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;wBAC1C,IAAI,UAAU,IAAI,CAAC;4BAAE,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;oBACnD,CAAC;oBACD,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;wBAC7B,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC1C,CAAC;gBACD,aAAa,EAAE,CAAC;gBAEhB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAE9B,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC;gBAC7C,MAAM,OAAO,GACX,OAAO,KAAK,CAAC,OAAO,KAAK,SAAS;oBAChC,CAAC,CAAC,KAAK,CAAC,OAAO;oBACf,CAAC,CAAC,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ;wBAChC,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;4BAC/B,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC;gBACnD,IAAI,OAAO;oBAAE,WAAW,EAAE,CAAC;;oBACtB,eAAe,EAAE,CAAC;gBAEvB,IACE,OAAO,KAAK,SAAS;oBACrB,OAAO,GAAG,iCAAiC;oBAC3C,OAAO,EACP,CAAC;oBACD,mBAAmB,CAAC,GAAG,CAAC,OAAO,EAAE;wBAC/B,IAAI,EAAE,OAAO,CAAC,QAAQ;wBACtB,iBAAiB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC;wBAC1D,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;wBACtD,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;wBACrC,WAAW,EAAE,CAAC,OAAO;4BACnB,CAAC,CAAC,IAAI;4BACN,CAAC,CAAC,aAAa;gCACb,CAAC,CAAC,YAAY;gCACd,CAAC,CAAC,uBAAuB;wBAC7B,aAAa,EACX,OAAO,IAAI,MAAM,CAAC,kBAAkB;4BAClC,CAAC,CAAC,wBAAwB,CAAC,sBAAsB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;4BAChE,CAAC,CAAC,SAAS;qBAChB,CAAC,CAAC;gBACL,CAAC;gBAED,uEAAuE;gBACvE,oEAAoE;gBACpE,MAAM,aAAa,GAAG;oBACpB,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAwB;oBAC9D,YAAY,EAAE,OAAO,CAAC,CAAC,CAAE,KAAK,CAAC,MAAiB,CAAC,CAAC,CAAC,IAAI;iBACxD,CAAC;gBACF,IAAI,OAAO,EAAE,QAAQ,EAAE,CAAC;oBACtB,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;oBAC3C,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE;wBAC7B,MAAM,EAAE,aAAa,CAAC,MAAM;wBAC5B,YAAY,EAAE,aAAa,CAAC,YAAY;wBACxC,UAAU,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,IAAI,EAAE;qBACxC,CAAC,CAAC;gBACL,CAAC;qBAAM,IAAI,OAAO,EAAE,CAAC;oBACnB,OAAO,CAAC,SAAS,GAAG,aAAa,CAAC;gBACpC,CAAC;gBAED,MAAM,IAAI,GAAc;oBACtB,EAAE,EAAE,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE;oBAC/B,KAAK;oBACL,QAAQ;oBACR,MAAM;oBACN,YAAY;oBACZ,QAAQ,EAAE,WAAW;oBACrB,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,WAAW,EAAE,CAAC;oBACd,YAAY,EAAE,CAAC;oBACf,eAAe,EAAE,CAAC;oBAClB,gBAAgB,EAAE,CAAC;oBACnB,aAAa,EAAE,CAAC;oBAChB,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;oBACnE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;oBACrC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;oBAC3C,QAAQ,EACN,MAAM,CAAC,eAAe,IAAI,OAAO;wBAC/B,CAAC,CAAC,yDAAyD;4BACzD,sDAAsD;4BACtD,uDAAuD;4BACvD,oCAAoC;4BACpC;gCACE,KAAK,EAAE,qBAAqB,CAAC,OAAO,CAAC,KAAK,CAGzC;6BACF;wBACH,CAAC,CAAC,IAAI;oBACV,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;iBACtB,CAAC;gBACF,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QAEV,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,YAAY,CAAC;YACzB,GAAG,QAAQ;YACX,KAAK;YACL,IAAI,EAAE,gBAAgB;YACtB,SAAS,EAAE,mBAAmB;SAC/B,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;QACzD,SAAS,GAAG,cAAc,EAAE,MAAM,IAAI,OAAO,CAAC;QAC9C,YAAY;YACV,cAAc,EAAE,YAAY,KAAK,SAAS;gBACxC,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC/B,CAAC,CAAC,cAAc,CAAC,YAAY,CAAC;QAClC,MAAM,aAAa,GAAG,cAAc,EAAE,QAAQ,IAAI,IAAI,CAAC;QACvD,WAAW;YACT,WAAW,IAAI,aAAa;gBAC1B,CAAC,CAAC,EAAE,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,EAAE;gBACtD,CAAC,CAAC,IAAI,CAAC;QACX,MAAM,GAAG,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC1B,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,CAAC;QAE1C,IAAI,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAC1B,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,SAAS,GAAG,OAAO,CAAC;gBACpB,YAAY,KAAK,6CAA6C,CAAC;YACjE,CAAC;YACD,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,YAAY,EAAE,CAAC;gBAC9C,aAAa,IAAI,CAAC,CAAC;gBACnB,WAAW,IAAI,CAAC,CAAC;gBACjB,MAAM,kBAAkB,GAAG,yCAAyC,CAAC;gBACrE,IAAI,OAAO,GAAG,iCAAiC,EAAE,CAAC;oBAChD,mBAAmB,CAAC,GAAG,CAAC,OAAO,EAAE;wBAC/B,IAAI,EAAE,OAAO,CAAC,QAAQ;wBACtB,iBAAiB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC;wBAC1D,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;wBAClD,MAAM,EAAE,OAAO;wBACf,WAAW,EAAE,aAAa;wBAC1B,aAAa,EAAE,MAAM,CAAC,kBAAkB;4BACtC,CAAC,CAAC,kBAAkB;4BACpB,CAAC,CAAC,SAAS;qBACd,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;oBACrB,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;oBAC3C,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE;wBAC7B,MAAM,EAAE,OAAO;wBACf,YAAY,EAAE,kBAAkB;wBAChC,UAAU,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,QAAQ,EAAE;qBAC9C,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,SAAS,GAAG;wBAClB,MAAM,EAAE,OAAO;wBACf,YAAY,EAAE,kBAAkB;qBACjC,CAAC;gBACJ,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC;oBACT,EAAE,EAAE,OAAO,CAAC,MAAM;oBAClB,KAAK;oBACL,QAAQ;oBACR,MAAM;oBACN,YAAY;oBACZ,QAAQ,EAAE,WAAW;oBACrB,IAAI,EAAE,OAAO,CAAC,QAAQ;oBACtB,WAAW,EAAE,CAAC;oBACd,YAAY,EAAE,CAAC;oBACf,eAAe,EAAE,CAAC;oBAClB,gBAAgB,EAAE,CAAC;oBACnB,aAAa,EAAE,CAAC;oBAChB,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;oBACjD,MAAM,EAAE,OAAO;oBACf,YAAY,EAAE,kBAAkB;oBAChC,QAAQ,EAAE,IAAI;oBACd,SAAS,EAAE,MAAM;iBAClB,CAAC,CAAC;YACL,CAAC;YACD,YAAY,CAAC,KAAK,EAAE,CAAC;YACrB,kBAAkB,CAAC,KAAK,EAAE,CAAC;YAC3B,mBAAmB,CAAC,KAAK,EAAE,CAAC;QAC9B,CAAC;QAED,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC;YACH,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;YAC5D,IAAI,KAAK,EAAE,CAAC;gBACV,aAAa,GAAG,aAAa,CAC3B,KAAK,CAAC,WAAW,EACjB,KAAK,CAAC,YAAY,EAClB,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,eAAe,EACrB,KAAK,CAAC,gBAAgB,CACvB,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QAEV,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,IAAI,KAAK,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;YACnC,YAAY,GAAG,CAAC,CAAC;YACjB,MAAM,eAAe,GAAG,KAAK,IAAI;gBAC/B,WAAW,EAAE,CAAC;gBACd,YAAY,EAAE,CAAC;gBACf,eAAe,EAAE,CAAC;gBAClB,gBAAgB,EAAE,CAAC;gBACnB,KAAK,EAAE,QAAQ,CAAC,KAAK;aACtB,CAAC;YACF,qEAAqE;YACrE,iEAAiE;YACjE,wEAAwE;YACxE,sEAAsE;YACtE,0CAA0C;YAC1C,MAAM,aAAa,GAAG,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;YACpD,MAAM,YAAY,GAChB,KAAK,EAAE,oBAAoB,KAAK,SAAS;gBACvC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,oBAAoB,GAAG,QAAQ,CAAC;gBACpD,CAAC,CAAC,SAAS,CAAC;YAChB,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAc;gBACzB,EAAE,EAAE,SAAS;gBACb,KAAK;gBACL,QAAQ;gBACR,MAAM;gBACN,YAAY;gBACZ,QAAQ,EAAE,UAAU;gBACpB,IAAI,EAAE,eAAe,CAAC,KAAK;gBAC3B,WAAW,EAAE,eAAe,CAAC,WAAW;gBACxC,YAAY,EAAE,eAAe,CAAC,YAAY;gBAC1C,eAAe,EAAE,eAAe,CAAC,eAAe;gBAChD,gBAAgB,EAAE,eAAe,CAAC,gBAAgB;gBAClD,aAAa;gBACb,UAAU,EAAE,eAAe;gBAC3B,MAAM,EAAE,SAAS;gBACjB,YAAY;gBACZ,QAAQ,EAAE,IAAI;gBACd,SAAS,EAAE,QAAQ;aACpB,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACpB,8BAA8B,CAAC;gBAC7B,KAAK;gBACL,QAAQ;gBACR,MAAM;gBACN,YAAY;gBACZ,SAAS;gBACT,UAAU,EACR,OAAO,QAAQ,CAAC,MAAM,EAAE,IAAI,KAAK,QAAQ;oBACvC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI;oBACtB,CAAC,CAAC,SAAS;gBACf,KAAK,EAAE,eAAe,CAAC,KAAK;gBAC5B,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;gBACpE,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS;gBACtE,eAAe,EAAE,aAAa;oBAC5B,CAAC,CAAC,eAAe,CAAC,eAAe;oBACjC,CAAC,CAAC,SAAS;gBACb,gBAAgB,EAAE,aAAa;oBAC7B,CAAC,CAAC,eAAe,CAAC,gBAAgB;oBAClC,CAAC,CAAC,SAAS;gBACb,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;gBACxD,UAAU,EAAE,eAAe;gBAC3B,YAAY;gBACZ,MAAM,EAAE,SAAS;gBACjB,YAAY;gBACZ,SAAS,EAAE,aAAa;gBACxB,eAAe;gBACf,WAAW;gBACX,KAAK,EAAE,CAAC,GAAG,mBAAmB,CAAC,OAAO,EAAE,CAAC;qBACtC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;qBACzB,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC;gBAC9B,cAAc,EACZ,qBAAqB,GAAG,iCAAiC;gBAC3D,eAAe;gBACf,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,SAAS,EAAE,QAAQ;gBACnB,qBAAqB,EAAE,IAAI,CAAC,qBAAqB;gBACjD,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;aAChD,CAAC,CAAC;QACL,CAAC;QAED,MAAM,UAAU,GAAc;YAC5B,EAAE,EAAE,YAAY;YAChB,KAAK;YACL,QAAQ;YACR,MAAM;YACN,YAAY,EAAE,IAAI;YAClB,QAAQ,EAAE,WAAW;YACrB,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,KAAK,EAAE,WAAW,IAAI,CAAC;YACpC,YAAY,EAAE,KAAK,EAAE,YAAY,IAAI,CAAC;YACtC,eAAe,EAAE,KAAK,EAAE,eAAe,IAAI,CAAC;YAC5C,gBAAgB,EAAE,KAAK,EAAE,gBAAgB,IAAI,CAAC;YAC9C,aAAa;YACb,UAAU,EAAE,eAAe;YAC3B,MAAM,EAAE,SAAS;YACjB,YAAY;YACZ,QAAQ,EAAE,WAAW;YACrB,SAAS,EAAE,QAAQ;SACpB,CAAC;QACF,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAEvB,MAAM,OAAO,GAAiB;YAC5B,KAAK;YACL,QAAQ;YACR,MAAM;YACN,UAAU,EAAE,KAAK,CAAC,MAAM;YACxB,QAAQ,EAAE,YAAY;YACtB,SAAS,EAAE,aAAa;YACxB,eAAe;YACf,WAAW;YACX,eAAe;YACf,kBAAkB,EAAE,aAAa;YACjC,gBAAgB,EAAE,KAAK,EAAE,WAAW,IAAI,CAAC;YACzC,iBAAiB,EAAE,KAAK,EAAE,YAAY,IAAI,CAAC;YAC3C,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,QAAQ,CAAC,KAAK;YACrC,SAAS,EAAE,QAAQ;SACpB,CAAC;QAEF,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAE9D,uEAAuE;QACvE,uEAAuE;QACvE,6EAA6E;QAC7E,0EAA0E;QAC1E,IAAI,CAAC;YACH,IAAI,KAAK,EAAE,CAAC;gBACV,YAAY,CAAC,MAAM,cAAc,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE;oBACjD,MAAM,EAAE,SAAS;oBACjB,YAAY;oBACZ,UAAU,EAAE;wBACV,WAAW,EAAE,KAAK,CAAC,KAAK;wBACxB,kBAAkB,EAAE,KAAK,CAAC,WAAW;wBACrC,mBAAmB,EAAE,KAAK,CAAC,YAAY;wBACvC,uBAAuB,EAAE,KAAK,CAAC,eAAe;wBAC9C,wBAAwB,EAAE,KAAK,CAAC,gBAAgB;wBAChD,qBAAqB,EAAE,aAAa;qBACrC;iBACF,CAAC,CAAC;YACL,CAAC;YACD,KAAK,MAAM,QAAQ,IAAI,iBAAiB,EAAE,CAAC;gBACzC,YAAY,CAAC,QAAQ,EAAE;oBACrB,MAAM,EAAE,OAAO;oBACf,YAAY,EAAE,mCAAmC;iBAClD,CAAC,CAAC;YACL,CAAC;YACD,iBAAiB,CAAC,KAAK,EAAE,CAAC;YAC1B,YAAY,CAAC,MAAM,kBAAkB,EAAE;gBACrC,MAAM,EAAE,SAAS;gBACjB,YAAY;gBACZ,UAAU,EAAE;oBACV,kBAAkB,EAAE,aAAa;oBACjC,wBAAwB,EAAE,eAAe;oBACzC,oBAAoB,EAAE,WAAW;oBACjC,mBAAmB,EAAE,eAAe;oBACpC,oBAAoB,EAAE,KAAK,EAAE,WAAW,IAAI,CAAC;oBAC7C,qBAAqB,EAAE,KAAK,EAAE,YAAY,IAAI,CAAC;oBAC/C,uBAAuB,EAAE,aAAa;oBACtC,sBAAsB,EAAE,eAAe,EAAE,KAAK;oBAC9C,qBAAqB,EACnB,eAAe,EAAE,KAAK,KAAK,QAAQ;wBACnC,eAAe,EAAE,KAAK,KAAK,gBAAgB;wBACzC,CAAC,CAAC,eAAe,CAAC,IAAI;wBACtB,CAAC,CAAC,SAAS;iBAChB;aACF,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,wCAAwC;QAC1C,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,2EAA2E;IAC3E,8EAA8E;IAC9E,wEAAwE;IACxE,IAAI,KAAK,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,iBAAiB,GAAG,MAAM,wBAAwB,CAAC;YACzD,IAAI,iBAAiB,EAAE,CAAC;gBACtB,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;gBAClE,MAAM,sBAAsB,CAAC;oBAC3B,eAAe,EAAE,MAAM,CAAC,sBAAsB;oBAC9C,sBAAsB,EAAE,iBAAiB,CAAC,KAAK;oBAC/C,IAAI,EAAE,IAAI,CAAC,cAAc;oBACzB,cAAc,EAAE,iBAAiB,CAAC,KAAK;oBACvC,0BAA0B,EAAE,KAAK;oBACjC,QAAQ;oBACR,MAAM;oBACN,UAAU,EAAE,MAAM,CAAC,2BAA2B;iBAC/C,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kEAAkE;QACpE,CAAC;IACH,CAAC;IAED,OAAO,KAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,KAAkB,EAClB,OAAqB,EACrB,KAAa,EACb,MAA2B;IAE3B,MAAM,EAAE,eAAe,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;IAC3E,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAElD,qDAAqD;IACrD,IAAI,CAAC;QACH,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QACnD,MAAM,WAAW,CAAC,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC","sourcesContent":["import type {\n AgentLoopOutcome,\n AgentLoopUsage,\n} from \"../agent/production-agent.js\";\nimport type { AgentChatEvent, AgentToolInput } from \"../agent/types.js\";\nimport { type AgentSpan, endAgentSpan, startAgentSpan } from \"./tracing.js\";\nimport { trackingIdentityProperties } from \"./tracking-identity.js\";\nimport type { TraceSpan, TraceSummary, ObservabilityConfig } from \"./types.js\";\nimport { DEFAULT_OBSERVABILITY_CONFIG } from \"./types.js\";\n\nfunction spanId(): string {\n return `span-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\nfunction llmProviderFromEngine(\n engineName: string | undefined,\n model: string,\n): string {\n const engine = engineName?.trim();\n if (engine?.startsWith(\"ai-sdk:\")) return engine.slice(\"ai-sdk:\".length);\n if (engine) return engine;\n if (/claude|anthropic/i.test(model)) return \"anthropic\";\n if (/gpt|openai|codex/i.test(model)) return \"openai\";\n if (/gemini|google/i.test(model)) return \"google\";\n return \"unknown\";\n}\n\nfunction costUsdFromCenticents(value: number): number {\n return Math.round((value / 10_000) * 1_000_000) / 1_000_000;\n}\n\nconst MAX_TRACKED_GENERATION_TOOL_CALLS = 50;\nconst MAX_TOOL_ERROR_MESSAGE_LENGTH = 500;\nconst STANDALONE_API_KEY_PATTERN =\n /\\b(?:sk-(?:proj-|ant-)?[A-Za-z0-9_-]{8,}|(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{8,}|AIza[A-Za-z0-9_-]{16,}|gh[pousr]_[A-Za-z0-9]{16,})\\b/g;\n\ntype GenerationToolCall = {\n name: string;\n started_offset_ms: number;\n duration_ms: number;\n status: \"success\" | \"error\";\n error_class: \"tool_error\" | \"legacy_inferred_error\" | \"interrupted\" | null;\n error_message?: string;\n};\n\nfunction truncateToolErrorMessage(value: string): string {\n return value.length > MAX_TOOL_ERROR_MESSAGE_LENGTH\n ? `${value.slice(0, MAX_TOOL_ERROR_MESSAGE_LENGTH)}…`\n : value;\n}\n\nfunction redactToolErrorMessage(value: string): string {\n const credentialName =\n \"authorization|cookie|api[_ -]?key|password|secret|token|access[_ -]?token|refresh[_ -]?token\";\n const labeledCredential = `([\"']?\\\\b(?:${credentialName})\\\\b[\"']?\\\\s*[:=]\\\\s*[\"']?)`;\n return value\n .replace(\n new RegExp(\n `${labeledCredential}(?:Bearer|Basic)\\\\s+[^\"'\\\\s,;)}\\\\]]+`,\n \"gi\",\n ),\n \"$1[REDACTED]\",\n )\n .replace(\n new RegExp(`${labeledCredential}[^\"'\\\\s,;)}\\\\[\\\\]]+`, \"gi\"),\n \"$1[REDACTED]\",\n )\n .replace(/\\bBearer\\s+[A-Za-z0-9._~+/=-]+/gi, \"[REDACTED]\")\n .replace(STANDALONE_API_KEY_PATTERN, \"[REDACTED]\");\n}\n\nfunction emitLlmGenerationTrackingEvent(args: {\n runId: string;\n threadId: string | null;\n userId: string | null;\n parentSpanId: string;\n llmSpanId: string;\n engineName: string | undefined;\n model: string;\n /**\n * Undefined means the engine never reported a usage figure for this run\n * (e.g. killed for silence before any provider response arrived) — not\n * that the count was zero. Callers must omit these from the emitted event\n * rather than coerce to 0; a coerced 0 is indistinguishable from a real\n * empty-input run and defeats analysis of failing runs by input size.\n */\n inputTokens: number | undefined;\n outputTokens: number | undefined;\n cacheReadTokens: number | undefined;\n cacheWriteTokens: number | undefined;\n /** Same \"unknown vs zero\" rule as the token fields — cost is derived from\n * them and is equally unmeasurable when they were never reported. */\n costCentsX100: number | undefined;\n durationMs: number;\n /** Elapsed ms from run start to the first non-heartbeat engine event.\n * Undefined when no such event ever arrived (the run never produced a\n * token before being aborted) — never coerced to 0. */\n firstTokenMs: number | undefined;\n status: \"success\" | \"error\";\n errorMessage: string | null;\n toolCalls: number;\n successfulTools: number;\n failedTools: number;\n tools: GenerationToolCall[];\n toolsTruncated: boolean;\n terminalOutcome?: AgentLoopOutcome;\n delegation?: {\n protocol: \"a2a\" | \"mcp\";\n callerApp?: string;\n taskId?: string;\n parentRunId?: string;\n parentTurnId?: string;\n };\n createdAt: number;\n experimentAssignments?: Array<{\n experimentId: string;\n variantId: string;\n }>;\n modelSelectionSource?: string;\n}): void {\n const provider = llmProviderFromEngine(args.engineName, args.model);\n const costUsd =\n args.costCentsX100 !== undefined\n ? costUsdFromCenticents(args.costCentsX100)\n : undefined;\n const totalTokens =\n args.inputTokens !== undefined && args.outputTokens !== undefined\n ? args.inputTokens + args.outputTokens\n : undefined;\n const error = args.errorMessage ?? undefined;\n const properties: Record<string, unknown> = {\n ...trackingIdentityProperties(),\n source: \"agent_observability\",\n span_type: \"llm_call\",\n run_id: args.runId,\n thread_id: args.threadId,\n parent_span_id: args.parentSpanId,\n span_id: args.llmSpanId,\n model: args.model,\n provider,\n input_tokens: args.inputTokens,\n output_tokens: args.outputTokens,\n total_tokens: totalTokens,\n cache_read_tokens: args.cacheReadTokens,\n cache_write_tokens: args.cacheWriteTokens,\n cost_cents_x100: args.costCentsX100,\n cost_usd: costUsd,\n duration_ms: args.durationMs,\n time_to_first_token_ms: args.firstTokenMs,\n status: args.status,\n tool_calls: args.toolCalls,\n successful_tools: args.successfulTools,\n failed_tools: args.failedTools,\n tools: args.tools,\n tools_truncated: args.toolsTruncated,\n terminal_state: args.terminalOutcome?.state,\n terminal_code:\n args.terminalOutcome?.state === \"failed\" ||\n args.terminalOutcome?.state === \"input_required\"\n ? args.terminalOutcome.code\n : undefined,\n terminal_retryable:\n args.terminalOutcome?.state === \"failed\"\n ? args.terminalOutcome.retryable\n : undefined,\n delegated: args.delegation ? true : undefined,\n delegation_protocol: args.delegation?.protocol,\n caller_app: args.delegation?.callerApp,\n a2a_task_id: args.delegation?.taskId,\n parent_run_id: args.delegation?.parentRunId,\n parent_turn_id: args.delegation?.parentTurnId,\n model_selection_source: args.modelSelectionSource,\n created_at: new Date(args.createdAt).toISOString(),\n created_at_ms: args.createdAt,\n $ai_trace_id: args.runId,\n $ai_session_id: args.threadId ?? undefined,\n $ai_span_id: args.llmSpanId,\n $ai_span_name: \"agent_run\",\n $ai_parent_id: args.parentSpanId,\n $ai_model: args.model,\n $ai_provider: provider,\n $ai_input_tokens: args.inputTokens,\n $ai_output_tokens: args.outputTokens,\n $ai_latency: Math.round((args.durationMs / 1000) * 1000) / 1000,\n $ai_is_error: args.status === \"error\",\n $ai_error: error,\n $ai_cache_read_input_tokens: args.cacheReadTokens,\n $ai_cache_creation_input_tokens: args.cacheWriteTokens,\n $ai_request_count: 1,\n $ai_total_cost_usd: costUsd,\n };\n if (args.experimentAssignments?.length) {\n properties.experiment_ids = args.experimentAssignments\n .map((assignment) => assignment.experimentId)\n .join(\",\");\n properties.experiment_variants = args.experimentAssignments\n .map((assignment) => assignment.variantId)\n .join(\",\");\n if (args.experimentAssignments.length === 1) {\n properties.experiment_id = args.experimentAssignments[0].experimentId;\n properties.experiment_variant = args.experimentAssignments[0].variantId;\n }\n }\n if (error) properties.error_message = error;\n\n for (const key of Object.keys(properties)) {\n if (properties[key] === undefined) delete properties[key];\n }\n\n try {\n void import(\"../tracking/registry.js\")\n .then(({ track }) => {\n track(\"$ai_generation\", properties, {\n userId: args.userId ?? undefined,\n });\n })\n .catch(() => {});\n } catch {\n // Tracking must never affect the agent run or trace persistence.\n }\n}\n\n/** Keys whose values are stripped from persisted tool inputs when\n * `captureToolArgs` is enabled. Matched case-insensitively and tolerant\n * of `_` / `-` separators. M14 in the MCP/A2A audit: tool calls\n * routinely receive credentials verbatim (db-exec INSERTs, fetchTool\n * Authorization headers, ad-hoc bearer tokens) — keeping those values\n * out of agent_trace_spans.metadata avoids long-term storage of\n * short-lived secrets. */\nconst SENSITIVE_FIELD_PATTERN =\n /^(authorization|cookie|api[_-]?key|password|secret|token|access[_-]?token|refresh[_-]?token|bearer)$/i;\n\n/** Recursively walk a structured value and replace sensitive field\n * values with the literal string \"[REDACTED]\". Pure (returns a copy);\n * the original input is never mutated. Cycles are tolerated via a\n * small WeakSet seen-tracker that returns \"[Circular]\" for repeats. */\nexport function redactSensitiveFields(value: unknown): unknown {\n return redactWalk(value, new WeakSet<object>());\n}\n\nfunction redactWalk(value: unknown, seen: WeakSet<object>): unknown {\n if (value === null || typeof value !== \"object\") return value;\n if (seen.has(value as object)) return \"[Circular]\";\n seen.add(value as object);\n if (Array.isArray(value)) {\n return value.map((v) => redactWalk(v, seen));\n }\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (SENSITIVE_FIELD_PATTERN.test(k)) {\n out[k] = \"[REDACTED]\";\n } else {\n out[k] = redactWalk(v, seen);\n }\n }\n return out;\n}\n\nexport async function getObservabilityConfig(): Promise<ObservabilityConfig> {\n let stored: Partial<ObservabilityConfig> | null = null;\n try {\n const { getSetting } = await import(\"../settings/store.js\");\n stored = (await getSetting(\n \"observability-config\",\n )) as Partial<ObservabilityConfig> | null;\n } catch {}\n const { resolveInferredSentimentConfig } = await import(\"./sentiment.js\");\n return {\n ...DEFAULT_OBSERVABILITY_CONFIG,\n ...(stored ?? {}),\n ...resolveInferredSentimentConfig(stored),\n };\n}\n\nexport async function instrumentAgentLoop(opts: {\n runAgentLoop: (loopOpts: {\n engine: any;\n model: string;\n systemPrompt: string;\n tools: any[];\n messages: any[];\n actions: Record<string, any>;\n send: (event: AgentChatEvent) => void;\n signal: AbortSignal;\n onUsage?: (usage: AgentLoopUsage) => void;\n onOutcome?: (outcome: AgentLoopOutcome) => void;\n providerOptions?: any;\n runId?: string;\n }) => Promise<AgentLoopUsage>;\n loopOpts: {\n engine: any;\n model: string;\n systemPrompt: string;\n tools: any[];\n messages: any[];\n actions: Record<string, any>;\n send: (event: AgentChatEvent) => void;\n signal: AbortSignal;\n onUsage?: (usage: AgentLoopUsage) => void;\n onOutcome?: (outcome: AgentLoopOutcome) => void;\n providerOptions?: any;\n runId?: string;\n };\n runId: string;\n threadId: string | null;\n /** Owner of this run; persisted on every span + summary so dashboard\n * reads can filter to a single user. Null for unauthenticated callers\n * (background tasks, etc.) — those rows aren't returned by per-user\n * reads. */\n userId: string | null;\n config: ObservabilityConfig;\n metadata?: Record<string, unknown> | null;\n experimentAssignments?: Array<{\n experimentId: string;\n variantId: string;\n }>;\n modelSelectionSource?: string;\n delegation?: {\n protocol: \"a2a\" | \"mcp\";\n callerApp?: string;\n taskId?: string;\n parentRunId?: string;\n parentTurnId?: string;\n };\n /** Raw user-authored message before prompt/context enrichment. */\n sentimentInput?: string;\n classifyError?: (error: unknown) =>\n | {\n status?: \"success\" | \"error\";\n errorMessage?: string | null;\n metadata?: Record<string, unknown> | null;\n }\n | null\n | undefined;\n}): Promise<AgentLoopUsage> {\n const { runAgentLoop, loopOpts, runId, threadId, userId, config } = opts;\n const runStart = Date.now();\n const parentSpanId = spanId();\n const precedingResponsePromise =\n config.inferredSentimentEnabled && opts.sentimentInput && threadId && userId\n ? import(\"./store.js\")\n .then(({ getLatestTraceSummaryForThread }) =>\n getLatestTraceSummaryForThread(threadId, {\n userId,\n excludeRunId: runId,\n }),\n )\n .catch(() => null)\n : Promise.resolve(null);\n\n // Optional OpenTelemetry root span for this run. No-ops unless a host has\n // installed `@opentelemetry/api` and registered a provider. The promise is\n // resolved before the loop runs so child tool/model spans can parent under\n // it conceptually (we keep them flat in the same tracer, which is enough\n // for the dashboards an embedding app would build).\n const otelRunSpanPromise = startAgentSpan(\"agent.run\", {\n \"agent.run_id\": runId,\n \"agent.thread_id\": threadId ?? undefined,\n \"agent.user_id\": userId ?? undefined,\n \"agent.model\": loopOpts.model,\n \"agent.model_selection_source\": opts.modelSelectionSource,\n \"agent.experiment_id\":\n opts.experimentAssignments?.length === 1\n ? opts.experimentAssignments[0].experimentId\n : undefined,\n \"agent.experiment_variant\":\n opts.experimentAssignments?.length === 1\n ? opts.experimentAssignments[0].variantId\n : undefined,\n });\n\n const spans: TraceSpan[] = [];\n let toolInvocationCounter = 0;\n // Keyed by counter to handle concurrent calls to the same tool name\n const pendingTools = new Map<\n number,\n {\n spanId: string;\n callId?: string;\n startMs: number;\n toolName: string;\n input: AgentToolInput;\n otelSpan: AgentSpan | null;\n endResult?: { status: \"success\" | \"error\"; errorMessage: string | null };\n }\n >();\n // Secondary index for legacy emitters without call ids. Current tool events\n // are paired by id first; same-name FIFO remains as a compatibility fallback.\n const toolNameToCounters = new Map<string, number[]>();\n const toolCallIdToCounter = new Map<string, number>();\n const generationToolCalls = new Map<number, GenerationToolCall>();\n\n let toolCallCount = 0;\n let successfulTools = 0;\n let failedTools = 0;\n\n // Track in-flight OTel tool spans so they're all ended even if the loop\n // throws before a matching `tool_done` arrives.\n const openOtelToolSpans = new Set<AgentSpan>();\n let usage: AgentLoopUsage | undefined;\n let runStatus: \"success\" | \"error\" = \"success\";\n let errorMessage: string | null = null;\n let runMetadata: Record<string, unknown> | null = opts.metadata ?? null;\n let terminalOutcome: AgentLoopOutcome | undefined;\n\n const instrumentedOutcome = (outcome: AgentLoopOutcome): void => {\n terminalOutcome = outcome;\n if (outcome.state === \"completed\") {\n runStatus = \"success\";\n errorMessage = null;\n } else {\n runStatus = \"error\";\n errorMessage =\n outcome.state === \"canceled\"\n ? (outcome.message ?? \"Agent run was canceled.\")\n : outcome.message;\n }\n runMetadata = {\n ...(runMetadata ?? {}),\n terminal_state: outcome.state,\n ...(\"code\" in outcome ? { terminal_code: outcome.code } : {}),\n ...(outcome.state === \"failed\"\n ? { terminal_retryable: outcome.retryable }\n : {}),\n };\n try {\n loopOpts.onOutcome?.(outcome);\n } catch {\n // Observability adapters cannot alter the agent run.\n }\n };\n\n const instrumentedSend = (event: AgentChatEvent): void => {\n try {\n // Some guardrails intentionally stop the loop by emitting a terminal\n // event and returning usage instead of throwing. Preserve that terminal\n // state in telemetry so a tripwire/loop-limit/provider error cannot be\n // counted as a successful delegated generation. A later clear/done means\n // the wrapper recovered and finished cleanly, so reset in that case.\n if (event.type === \"clear\" || event.type === \"done\") {\n runStatus = \"success\";\n errorMessage = null;\n } else if (event.type === \"error\") {\n runStatus = \"error\";\n errorMessage = event.error;\n } else if (event.type === \"tripwire\") {\n runStatus = \"error\";\n errorMessage = event.reason;\n } else if (event.type === \"loop_limit\") {\n runStatus = \"error\";\n errorMessage = \"Agent stopped at the loop limit\";\n } else if (event.type === \"missing_api_key\") {\n runStatus = \"error\";\n errorMessage = \"Missing API key\";\n }\n if (event.type === \"tool_start\") {\n const counter = toolInvocationCounter++;\n const sid = spanId();\n // Start the OTel tool span synchronously-ish: kick off the async\n // resolution and stash the span once it lands. Tool spans are short\n // and the api tracer is synchronous in practice, but we tolerate the\n // microtask gap by recording the span on the pending entry when ready.\n const entry: {\n spanId: string;\n callId?: string;\n startMs: number;\n toolName: string;\n input: AgentToolInput;\n otelSpan: AgentSpan | null;\n // Set by the done handler if it fires before the span promise\n // resolves, so the resolved span is ended with the correct status.\n endResult?: {\n status: \"success\" | \"error\";\n errorMessage: string | null;\n };\n } = {\n spanId: sid,\n ...(event.id ? { callId: event.id } : {}),\n startMs: Date.now(),\n toolName: event.tool,\n input: event.input,\n otelSpan: null,\n };\n pendingTools.set(counter, entry);\n if (event.id) toolCallIdToCounter.set(event.id, counter);\n void startAgentSpan(\"tool.call\", {\n \"tool.name\": event.tool,\n }).then((span) => {\n if (!span) return;\n // If `tool_done` already ran for this call, end the span now with the\n // status it recorded; otherwise stash it for the done handler.\n if (entry.endResult) {\n endAgentSpan(span, {\n status: entry.endResult.status,\n errorMessage: entry.endResult.errorMessage,\n });\n } else {\n entry.otelSpan = span;\n openOtelToolSpans.add(span);\n }\n });\n const queue = toolNameToCounters.get(event.tool);\n if (queue) queue.push(counter);\n else toolNameToCounters.set(event.tool, [counter]);\n } else if (event.type === \"tool_done\") {\n const queue = toolNameToCounters.get(event.tool);\n const counterFromId = event.id\n ? toolCallIdToCounter.get(event.id)\n : undefined;\n const legacyQueueIndex =\n event.id && counterFromId === undefined && queue\n ? queue.findIndex(\n (candidate) => !pendingTools.get(candidate)?.callId,\n )\n : -1;\n const counter =\n counterFromId ??\n (event.id\n ? legacyQueueIndex >= 0\n ? queue?.[legacyQueueIndex]\n : undefined\n : queue?.shift());\n const pending =\n counter !== undefined ? pendingTools.get(counter) : undefined;\n if (counter !== undefined) {\n pendingTools.delete(counter);\n if (pending?.callId) toolCallIdToCounter.delete(pending.callId);\n if ((counterFromId !== undefined || legacyQueueIndex >= 0) && queue) {\n const queueIndex = queue.indexOf(counter);\n if (queueIndex >= 0) queue.splice(queueIndex, 1);\n }\n if (queue && queue.length === 0)\n toolNameToCounters.delete(event.tool);\n }\n toolCallCount++;\n\n const finishedAt = Date.now();\n\n const explicitError = event.isError === true;\n const isError =\n typeof event.isError === \"boolean\"\n ? event.isError\n : typeof event.result === \"string\" &&\n (event.result.startsWith(\"Error\") ||\n event.result.startsWith(\"Error running \"));\n if (isError) failedTools++;\n else successfulTools++;\n\n if (\n counter !== undefined &&\n counter < MAX_TRACKED_GENERATION_TOOL_CALLS &&\n pending\n ) {\n generationToolCalls.set(counter, {\n name: pending.toolName,\n started_offset_ms: Math.max(0, pending.startMs - runStart),\n duration_ms: Math.max(0, finishedAt - pending.startMs),\n status: isError ? \"error\" : \"success\",\n error_class: !isError\n ? null\n : explicitError\n ? \"tool_error\"\n : \"legacy_inferred_error\",\n error_message:\n isError && config.captureToolResults\n ? truncateToolErrorMessage(redactToolErrorMessage(event.result))\n : undefined,\n });\n }\n\n // Finalize the OTel tool span. If the span promise hasn't resolved yet\n // we record the result on the entry so its `.then` handler ends it.\n const otelEndResult = {\n status: (isError ? \"error\" : \"success\") as \"success\" | \"error\",\n errorMessage: isError ? (event.result as string) : null,\n };\n if (pending?.otelSpan) {\n openOtelToolSpans.delete(pending.otelSpan);\n endAgentSpan(pending.otelSpan, {\n status: otelEndResult.status,\n errorMessage: otelEndResult.errorMessage,\n attributes: { \"tool.name\": event.tool },\n });\n } else if (pending) {\n pending.endResult = otelEndResult;\n }\n\n const span: TraceSpan = {\n id: pending?.spanId ?? spanId(),\n runId,\n threadId,\n userId,\n parentSpanId,\n spanType: \"tool_call\",\n name: event.tool,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n costCentsX100: 0,\n durationMs: pending ? Math.max(0, finishedAt - pending.startMs) : 0,\n status: isError ? \"error\" : \"success\",\n errorMessage: isError ? event.result : null,\n metadata:\n config.captureToolArgs && pending\n ? // Strip Authorization/api-key/token-shaped values before\n // persisting (M14 in the MCP/A2A audit). Tool-runtime\n // execution still sees the unredacted input — only the\n // long-lived span row is sanitized.\n {\n input: redactSensitiveFields(pending.input) as Record<\n string,\n string\n >,\n }\n : null,\n createdAt: Date.now(),\n };\n spans.push(span);\n }\n } catch {}\n\n loopOpts.send(event);\n };\n\n try {\n usage = await runAgentLoop({\n ...loopOpts,\n runId,\n send: instrumentedSend,\n onOutcome: instrumentedOutcome,\n });\n } catch (err: any) {\n const classification = opts.classifyError?.(err) ?? null;\n runStatus = classification?.status ?? \"error\";\n errorMessage =\n classification?.errorMessage === undefined\n ? (err?.message ?? String(err))\n : classification.errorMessage;\n const errorMetadata = classification?.metadata ?? null;\n runMetadata =\n runMetadata || errorMetadata\n ? { ...(runMetadata ?? {}), ...(errorMetadata ?? {}) }\n : null;\n throw err;\n } finally {\n const runEnd = Date.now();\n const totalDurationMs = runEnd - runStart;\n\n if (pendingTools.size > 0) {\n if (runStatus === \"success\") {\n runStatus = \"error\";\n errorMessage ??= \"Agent run ended with interrupted tool calls\";\n }\n for (const [counter, pending] of pendingTools) {\n toolCallCount += 1;\n failedTools += 1;\n const interruptedMessage = \"Tool call interrupted before completion\";\n if (counter < MAX_TRACKED_GENERATION_TOOL_CALLS) {\n generationToolCalls.set(counter, {\n name: pending.toolName,\n started_offset_ms: Math.max(0, pending.startMs - runStart),\n duration_ms: Math.max(0, runEnd - pending.startMs),\n status: \"error\",\n error_class: \"interrupted\",\n error_message: config.captureToolResults\n ? interruptedMessage\n : undefined,\n });\n }\n if (pending.otelSpan) {\n openOtelToolSpans.delete(pending.otelSpan);\n endAgentSpan(pending.otelSpan, {\n status: \"error\",\n errorMessage: interruptedMessage,\n attributes: { \"tool.name\": pending.toolName },\n });\n } else {\n pending.endResult = {\n status: \"error\",\n errorMessage: interruptedMessage,\n };\n }\n spans.push({\n id: pending.spanId,\n runId,\n threadId,\n userId,\n parentSpanId,\n spanType: \"tool_call\",\n name: pending.toolName,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n costCentsX100: 0,\n durationMs: Math.max(0, runEnd - pending.startMs),\n status: \"error\",\n errorMessage: interruptedMessage,\n metadata: null,\n createdAt: runEnd,\n });\n }\n pendingTools.clear();\n toolNameToCounters.clear();\n toolCallIdToCounter.clear();\n }\n\n let costCentsX100 = 0;\n try {\n const { calculateCost } = await import(\"../usage/store.js\");\n if (usage) {\n costCentsX100 = calculateCost(\n usage.inputTokens,\n usage.outputTokens,\n usage.model,\n usage.cacheReadTokens,\n usage.cacheWriteTokens,\n );\n }\n } catch {}\n\n let llmCallCount = 0;\n if (usage || runStatus === \"error\") {\n llmCallCount = 1;\n const generationUsage = usage ?? {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n model: loopOpts.model,\n };\n // The engine never reported a `usage` event for this run (killed for\n // silence before any provider response, or the loop threw before\n // returning). `generationUsage`'s token fields are placeholder zeros in\n // that case, not measured values — the tracking event below must omit\n // them rather than report a fabricated 0.\n const usageReported = usage?.usageReported === true;\n const firstTokenMs =\n usage?.firstEngineEventAtMs !== undefined\n ? Math.max(0, usage.firstEngineEventAtMs - runStart)\n : undefined;\n const llmSpanId = spanId();\n const llmSpan: TraceSpan = {\n id: llmSpanId,\n runId,\n threadId,\n userId,\n parentSpanId,\n spanType: \"llm_call\",\n name: generationUsage.model,\n inputTokens: generationUsage.inputTokens,\n outputTokens: generationUsage.outputTokens,\n cacheReadTokens: generationUsage.cacheReadTokens,\n cacheWriteTokens: generationUsage.cacheWriteTokens,\n costCentsX100,\n durationMs: totalDurationMs,\n status: runStatus,\n errorMessage,\n metadata: null,\n createdAt: runStart,\n };\n spans.push(llmSpan);\n emitLlmGenerationTrackingEvent({\n runId,\n threadId,\n userId,\n parentSpanId,\n llmSpanId,\n engineName:\n typeof loopOpts.engine?.name === \"string\"\n ? loopOpts.engine.name\n : undefined,\n model: generationUsage.model,\n inputTokens: usageReported ? generationUsage.inputTokens : undefined,\n outputTokens: usageReported ? generationUsage.outputTokens : undefined,\n cacheReadTokens: usageReported\n ? generationUsage.cacheReadTokens\n : undefined,\n cacheWriteTokens: usageReported\n ? generationUsage.cacheWriteTokens\n : undefined,\n costCentsX100: usageReported ? costCentsX100 : undefined,\n durationMs: totalDurationMs,\n firstTokenMs,\n status: runStatus,\n errorMessage,\n toolCalls: toolCallCount,\n successfulTools,\n failedTools,\n tools: [...generationToolCalls.entries()]\n .sort(([a], [b]) => a - b)\n .map(([, detail]) => detail),\n toolsTruncated:\n toolInvocationCounter > MAX_TRACKED_GENERATION_TOOL_CALLS,\n terminalOutcome,\n delegation: opts.delegation,\n createdAt: runStart,\n experimentAssignments: opts.experimentAssignments,\n modelSelectionSource: opts.modelSelectionSource,\n });\n }\n\n const parentSpan: TraceSpan = {\n id: parentSpanId,\n runId,\n threadId,\n userId,\n parentSpanId: null,\n spanType: \"agent_run\",\n name: \"agent_run\",\n inputTokens: usage?.inputTokens ?? 0,\n outputTokens: usage?.outputTokens ?? 0,\n cacheReadTokens: usage?.cacheReadTokens ?? 0,\n cacheWriteTokens: usage?.cacheWriteTokens ?? 0,\n costCentsX100,\n durationMs: totalDurationMs,\n status: runStatus,\n errorMessage,\n metadata: runMetadata,\n createdAt: runStart,\n };\n spans.push(parentSpan);\n\n const summary: TraceSummary = {\n runId,\n threadId,\n userId,\n totalSpans: spans.length,\n llmCalls: llmCallCount,\n toolCalls: toolCallCount,\n successfulTools,\n failedTools,\n totalDurationMs,\n totalCostCentsX100: costCentsX100,\n totalInputTokens: usage?.inputTokens ?? 0,\n totalOutputTokens: usage?.outputTokens ?? 0,\n model: usage?.model ?? loopOpts.model,\n createdAt: runStart,\n };\n\n writeTraceData(spans, summary, runId, config).catch(() => {});\n\n // OpenTelemetry export (no-op unless a provider is registered). Emit a\n // self-contained `llm.call` span carrying model + token usage, end any\n // tool spans still open (loop threw mid-tool), and end the run span. Awaited\n // so the spans are emitted before the function returns; cheap when no-op.\n try {\n if (usage) {\n endAgentSpan(await startAgentSpan(\"llm.call\", {}), {\n status: runStatus,\n errorMessage,\n attributes: {\n \"llm.model\": usage.model,\n \"llm.input_tokens\": usage.inputTokens,\n \"llm.output_tokens\": usage.outputTokens,\n \"llm.cache_read_tokens\": usage.cacheReadTokens,\n \"llm.cache_write_tokens\": usage.cacheWriteTokens,\n \"llm.cost_cents_x100\": costCentsX100,\n },\n });\n }\n for (const toolSpan of openOtelToolSpans) {\n endAgentSpan(toolSpan, {\n status: \"error\",\n errorMessage: \"Agent run ended before tool_done.\",\n });\n }\n openOtelToolSpans.clear();\n endAgentSpan(await otelRunSpanPromise, {\n status: runStatus,\n errorMessage,\n attributes: {\n \"agent.tool_calls\": toolCallCount,\n \"agent.successful_tools\": successfulTools,\n \"agent.failed_tools\": failedTools,\n \"agent.duration_ms\": totalDurationMs,\n \"agent.input_tokens\": usage?.inputTokens ?? 0,\n \"agent.output_tokens\": usage?.outputTokens ?? 0,\n \"agent.cost_cents_x100\": costCentsX100,\n \"agent.terminal_state\": terminalOutcome?.state,\n \"agent.terminal_code\":\n terminalOutcome?.state === \"failed\" ||\n terminalOutcome?.state === \"input_required\"\n ? terminalOutcome.code\n : undefined,\n },\n });\n } catch {\n // OTel export must never break the run.\n }\n }\n\n // Classify only after the main loop has finished so the tiny managed Luna\n // request cannot contend with the user's response for a gateway slot. This\n // short, awaited tail keeps serverless runtimes alive long enough to emit the\n // event, while the response content has already streamed to the client.\n if (usage && opts.sentimentInput) {\n try {\n const precedingResponse = await precedingResponsePromise;\n if (precedingResponse) {\n const { inferAndTrackSentiment } = await import(\"./sentiment.js\");\n await inferAndTrackSentiment({\n classifierModel: config.inferredSentimentModel,\n precedingResponseModel: precedingResponse.model,\n text: opts.sentimentInput,\n precedingRunId: precedingResponse.runId,\n classificationTriggerRunId: runId,\n threadId,\n userId,\n sampleRate: config.inferredSentimentSampleRate,\n });\n }\n } catch {\n // Optional inference must never alter the result of the main run.\n }\n }\n\n return usage!;\n}\n\nasync function writeTraceData(\n spans: TraceSpan[],\n summary: TraceSummary,\n runId: string,\n config: ObservabilityConfig,\n): Promise<void> {\n const { insertTraceSpan, upsertTraceSummary } = await import(\"./store.js\");\n await Promise.all(spans.map((s) => insertTraceSpan(s).catch(() => {})));\n await upsertTraceSummary(summary).catch(() => {});\n\n // Fire automated evals after trace data is persisted\n try {\n const { evaluateRun } = await import(\"./evals.js\");\n await evaluateRun(runId, { sampleRate: config.evalSampleRate });\n } catch {}\n}\n"]}
1
+ {"version":3,"file":"traces.js","sourceRoot":"","sources":["../../src/observability/traces.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AgentLoopOutcome,\n AgentLoopUsage,\n} from \"../agent/production-agent.js\";\nimport type { AgentChatEvent, AgentToolInput } from \"../agent/types.js\";\nimport { getRequestContext } from \"../server/request-context.js\";\nimport {\n MAX_AI_CONTENT_BYTES,\n MAX_AI_SPANS_PER_RUN,\n boundAiContent,\n emitAiSpanEvent,\n emitAiTraceEvent,\n toAiErrorDetail,\n} from \"./posthog-ai.js\";\nimport { type AgentSpan, endAgentSpan, startAgentSpan } from \"./tracing.js\";\nimport { trackingIdentityProperties } from \"./tracking-identity.js\";\nimport type { TraceSpan, TraceSummary, ObservabilityConfig } from \"./types.js\";\nimport { DEFAULT_OBSERVABILITY_CONFIG } from \"./types.js\";\n\nfunction spanId(): string {\n return `span-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\nfunction llmProviderFromEngine(\n engineName: string | undefined,\n model: string,\n): string {\n const engine = engineName?.trim();\n if (engine?.startsWith(\"ai-sdk:\")) return engine.slice(\"ai-sdk:\".length);\n if (engine) return engine;\n if (/claude|anthropic/i.test(model)) return \"anthropic\";\n if (/gpt|openai|codex/i.test(model)) return \"openai\";\n if (/gemini|google/i.test(model)) return \"google\";\n return \"unknown\";\n}\n\nfunction costUsdFromCenticents(value: number): number {\n return Math.round((value / 10_000) * 1_000_000) / 1_000_000;\n}\n\nconst MAX_TRACKED_GENERATION_TOOL_CALLS = 50;\nconst MAX_TOOL_ERROR_MESSAGE_LENGTH = 500;\nconst STANDALONE_API_KEY_PATTERN =\n /\\b(?:sk-(?:proj-|ant-)?[A-Za-z0-9_-]{8,}|(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{8,}|AIza[A-Za-z0-9_-]{16,}|gh[pousr]_[A-Za-z0-9]{16,})\\b/g;\n\ntype GenerationToolCall = {\n name: string;\n started_offset_ms: number;\n duration_ms: number;\n status: \"success\" | \"error\";\n error_class: \"tool_error\" | \"legacy_inferred_error\" | \"interrupted\" | null;\n error_message?: string;\n};\n\nfunction truncateToolErrorMessage(value: string): string {\n return value.length > MAX_TOOL_ERROR_MESSAGE_LENGTH\n ? `${value.slice(0, MAX_TOOL_ERROR_MESSAGE_LENGTH)}…`\n : value;\n}\n\nfunction redactToolErrorMessage(value: string): string {\n const credentialName =\n \"authorization|cookie|api[_ -]?key|password|secret|token|access[_ -]?token|refresh[_ -]?token\";\n const labeledCredential = `([\"']?\\\\b(?:${credentialName})\\\\b[\"']?\\\\s*[:=]\\\\s*[\"']?)`;\n return value\n .replace(\n new RegExp(\n `${labeledCredential}(?:Bearer|Basic)\\\\s+[^\"'\\\\s,;)}\\\\]]+`,\n \"gi\",\n ),\n \"$1[REDACTED]\",\n )\n .replace(\n new RegExp(`${labeledCredential}[^\"'\\\\s,;)}\\\\[\\\\]]+`, \"gi\"),\n \"$1[REDACTED]\",\n )\n .replace(/\\bBearer\\s+[A-Za-z0-9._~+/=-]+/gi, \"[REDACTED]\")\n .replace(STANDALONE_API_KEY_PATTERN, \"[REDACTED]\");\n}\n\nfunction emitLlmGenerationTrackingEvent(args: {\n runId: string;\n threadId: string | null;\n userId: string | null;\n parentSpanId: string;\n llmSpanId: string;\n engineName: string | undefined;\n model: string;\n /**\n * Undefined means the engine never reported a usage figure for this run\n * (e.g. killed for silence before any provider response arrived) — not\n * that the count was zero. Callers must omit these from the emitted event\n * rather than coerce to 0; a coerced 0 is indistinguishable from a real\n * empty-input run and defeats analysis of failing runs by input size.\n */\n inputTokens: number | undefined;\n outputTokens: number | undefined;\n cacheReadTokens: number | undefined;\n cacheWriteTokens: number | undefined;\n /** Same \"unknown vs zero\" rule as the token fields — cost is derived from\n * them and is equally unmeasurable when they were never reported. */\n costCentsX100: number | undefined;\n durationMs: number;\n /** Elapsed ms from run start to the first non-heartbeat engine event.\n * Undefined when no such event ever arrived (the run never produced a\n * token before being aborted) — never coerced to 0. */\n firstTokenMs: number | undefined;\n status: \"success\" | \"error\";\n errorMessage: string | null;\n toolCalls: number;\n successfulTools: number;\n failedTools: number;\n tools: GenerationToolCall[];\n toolsTruncated: boolean;\n terminalOutcome?: AgentLoopOutcome;\n delegation?: {\n protocol: \"a2a\" | \"mcp\";\n callerApp?: string;\n taskId?: string;\n parentRunId?: string;\n parentTurnId?: string;\n };\n createdAt: number;\n experimentAssignments?: Array<{\n experimentId: string;\n variantId: string;\n }>;\n modelSelectionSource?: string;\n /**\n * PostHog content fields. Each is `undefined` unless the matching capture\n * flag is on, and is then OMITTED from the event — never sent as `[]`, which\n * PostHog would render as \"the model was called with no messages\".\n */\n aiInput?: unknown;\n aiOutputChoices?: unknown;\n aiTools?: unknown;\n aiInputTruncated?: boolean;\n aiOutputTruncated?: boolean;\n browserSessionId?: string;\n}): void {\n const provider = llmProviderFromEngine(args.engineName, args.model);\n const costUsd =\n args.costCentsX100 !== undefined\n ? costUsdFromCenticents(args.costCentsX100)\n : undefined;\n const totalTokens =\n args.inputTokens !== undefined && args.outputTokens !== undefined\n ? args.inputTokens + args.outputTokens\n : undefined;\n const error = args.errorMessage ?? undefined;\n const terminalCode =\n args.terminalOutcome?.state === \"failed\" ||\n args.terminalOutcome?.state === \"input_required\"\n ? args.terminalOutcome.code\n : undefined;\n const terminalRetryable =\n args.terminalOutcome?.state === \"failed\"\n ? args.terminalOutcome.retryable\n : undefined;\n const properties: Record<string, unknown> = {\n ...trackingIdentityProperties(),\n source: \"agent_observability\",\n span_type: \"llm_call\",\n run_id: args.runId,\n thread_id: args.threadId,\n parent_span_id: args.parentSpanId,\n span_id: args.llmSpanId,\n model: args.model,\n provider,\n input_tokens: args.inputTokens,\n output_tokens: args.outputTokens,\n total_tokens: totalTokens,\n cache_read_tokens: args.cacheReadTokens,\n cache_write_tokens: args.cacheWriteTokens,\n cost_cents_x100: args.costCentsX100,\n cost_usd: costUsd,\n duration_ms: args.durationMs,\n time_to_first_token_ms: args.firstTokenMs,\n status: args.status,\n tool_calls: args.toolCalls,\n successful_tools: args.successfulTools,\n failed_tools: args.failedTools,\n tools: args.tools,\n tools_truncated: args.toolsTruncated,\n terminal_state: args.terminalOutcome?.state,\n terminal_code: terminalCode,\n terminal_retryable: terminalRetryable,\n delegated: args.delegation ? true : undefined,\n delegation_protocol: args.delegation?.protocol,\n caller_app: args.delegation?.callerApp,\n a2a_task_id: args.delegation?.taskId,\n parent_run_id: args.delegation?.parentRunId,\n parent_turn_id: args.delegation?.parentTurnId,\n model_selection_source: args.modelSelectionSource,\n created_at: new Date(args.createdAt).toISOString(),\n created_at_ms: args.createdAt,\n $ai_trace_id: args.runId,\n $ai_session_id: args.threadId ?? undefined,\n $ai_span_id: args.llmSpanId,\n $ai_span_name: args.model,\n // Parent is the run's trace, not the internal `agent_run` span id — the\n // latter is never emitted to PostHog, so pointing at it orphaned the\n // generation and PostHog rendered a placeholder trace around it.\n $ai_parent_id: args.runId,\n $ai_model: args.model,\n $ai_provider: provider,\n $ai_input_tokens: args.inputTokens,\n $ai_output_tokens: args.outputTokens,\n $ai_latency: Math.round((args.durationMs / 1000) * 1000) / 1000,\n $ai_is_error: args.status === \"error\",\n $ai_error:\n args.status === \"error\"\n ? toAiErrorDetail(error, {\n state: args.terminalOutcome?.state,\n code: terminalCode,\n retryable: terminalRetryable,\n })\n : undefined,\n $ai_cache_read_input_tokens: args.cacheReadTokens,\n $ai_cache_creation_input_tokens: args.cacheWriteTokens,\n $ai_request_count: 1,\n $ai_total_cost_usd: costUsd,\n $ai_input: args.aiInput,\n $ai_output_choices: args.aiOutputChoices,\n $ai_tools: args.aiTools,\n $ai_input_truncated: args.aiInputTruncated || undefined,\n $ai_output_truncated: args.aiOutputTruncated || undefined,\n $ai_time_to_first_token: args.firstTokenMs,\n $session_id: args.browserSessionId,\n };\n if (args.experimentAssignments?.length) {\n properties.experiment_ids = args.experimentAssignments\n .map((assignment) => assignment.experimentId)\n .join(\",\");\n properties.experiment_variants = args.experimentAssignments\n .map((assignment) => assignment.variantId)\n .join(\",\");\n if (args.experimentAssignments.length === 1) {\n properties.experiment_id = args.experimentAssignments[0].experimentId;\n properties.experiment_variant = args.experimentAssignments[0].variantId;\n }\n }\n if (error) properties.error_message = error;\n\n for (const key of Object.keys(properties)) {\n if (properties[key] === undefined) delete properties[key];\n }\n\n try {\n void import(\"../tracking/registry.js\")\n .then(({ track }) => {\n track(\"$ai_generation\", properties, {\n userId: args.userId ?? undefined,\n });\n })\n .catch(() => {});\n } catch {\n // Tracking must never affect the agent run or trace persistence.\n }\n}\n\n/**\n * Build the PostHog content fields for a run's `$ai_generation`.\n *\n * This is one generation per run carrying the run's whole message list, not one\n * per model round-trip: the engine layer reports aggregate usage only\n * (`onUsage`) and exposes no per-step hook. Consequence to know when reading a\n * trace — per-round-trip latency and intermediate assistant turns are not\n * visible; a multi-step run collapses into a single generation node.\n *\n * `$ai_output_choices` is emitted whenever tool calls happened even with\n * `capturePrompts` off, because PostHog derives `$ai_tools_called` /\n * `$ai_tool_call_count` from tool-call blocks inside it and nothing else. The\n * assistant's text content stays gated; only the structural call list ships.\n */\nfunction buildGenerationContent(args: {\n config: ObservabilityConfig;\n messages: unknown;\n tools: unknown;\n assistantText: string;\n toolSpans: TraceSpan[];\n}): {\n aiInput?: unknown;\n aiOutputChoices?: unknown;\n aiTools?: unknown;\n aiInputTruncated?: boolean;\n aiOutputTruncated?: boolean;\n} {\n const { config } = args;\n\n const input = config.capturePrompts\n ? boundAiContent(redactSensitiveFields(args.messages))\n : undefined;\n\n const toolCalls = args.toolSpans\n .slice(0, MAX_TRACKED_GENERATION_TOOL_CALLS)\n .map((span) => ({\n type: \"function\" as const,\n id: span.id,\n function: {\n name: span.name,\n // Already redacted at span construction, and only present when\n // `captureToolArgs` is on.\n ...((span.metadata as { input?: unknown } | null)?.input !== undefined\n ? { arguments: (span.metadata as { input?: unknown }).input }\n : {}),\n },\n }));\n\n const hasChoice = config.capturePrompts || toolCalls.length > 0;\n const output = hasChoice\n ? boundAiContent([\n {\n role: \"assistant\",\n ...(config.capturePrompts\n ? { content: redactToolErrorMessage(args.assistantText) }\n : {}),\n ...(toolCalls.length ? { tool_calls: toolCalls } : {}),\n },\n ])\n : undefined;\n\n const toolList = Array.isArray(args.tools)\n ? args.tools\n .filter(\n (tool): tool is { name: string; description?: string } =>\n !!tool && typeof (tool as { name?: unknown }).name === \"string\",\n )\n .map((tool) => ({\n type: \"function\" as const,\n function: {\n name: tool.name,\n ...(typeof tool.description === \"string\"\n ? { description: tool.description }\n : {}),\n },\n }))\n : [];\n\n return {\n aiInput: input?.value,\n aiOutputChoices: output?.value,\n // Tool definitions are app configuration rather than user content, so they\n // are not gated — without them a trace shows calls to tools nobody can\n // identify. Schemas are excluded to keep the event small.\n aiTools: toolList.length ? toolList : undefined,\n aiInputTruncated: input?.truncated,\n aiOutputTruncated: output?.truncated,\n };\n}\n\n/** Keys whose values are stripped from persisted tool inputs when\n * `captureToolArgs` is enabled. Matched case-insensitively and tolerant\n * of `_` / `-` separators. M14 in the MCP/A2A audit: tool calls\n * routinely receive credentials verbatim (db-exec INSERTs, fetchTool\n * Authorization headers, ad-hoc bearer tokens) — keeping those values\n * out of agent_trace_spans.metadata avoids long-term storage of\n * short-lived secrets. */\nconst SENSITIVE_FIELD_PATTERN =\n /^(authorization|cookie|api[_-]?key|password|secret|token|access[_-]?token|refresh[_-]?token|bearer)$/i;\n\n/** Recursively walk a structured value and replace sensitive field\n * values with the literal string \"[REDACTED]\". Pure (returns a copy);\n * the original input is never mutated. Cycles are tolerated via a\n * small WeakSet seen-tracker that returns \"[Circular]\" for repeats. */\nexport function redactSensitiveFields(value: unknown): unknown {\n return redactWalk(value, new WeakSet<object>());\n}\n\nfunction redactWalk(value: unknown, seen: WeakSet<object>): unknown {\n if (value === null || typeof value !== \"object\") return value;\n if (seen.has(value as object)) return \"[Circular]\";\n seen.add(value as object);\n if (Array.isArray(value)) {\n return value.map((v) => redactWalk(v, seen));\n }\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (SENSITIVE_FIELD_PATTERN.test(k)) {\n out[k] = \"[REDACTED]\";\n } else {\n out[k] = redactWalk(v, seen);\n }\n }\n return out;\n}\n\nexport async function getObservabilityConfig(): Promise<ObservabilityConfig> {\n let stored: Partial<ObservabilityConfig> | null = null;\n try {\n const { getSetting } = await import(\"../settings/store.js\");\n stored = (await getSetting(\n \"observability-config\",\n )) as Partial<ObservabilityConfig> | null;\n } catch {}\n const { resolveInferredSentimentConfig } = await import(\"./sentiment.js\");\n return {\n ...DEFAULT_OBSERVABILITY_CONFIG,\n ...(stored ?? {}),\n ...resolveInferredSentimentConfig(stored),\n };\n}\n\nexport async function instrumentAgentLoop(opts: {\n runAgentLoop: (loopOpts: {\n engine: any;\n model: string;\n systemPrompt: string;\n tools: any[];\n messages: any[];\n actions: Record<string, any>;\n send: (event: AgentChatEvent) => void;\n signal: AbortSignal;\n onUsage?: (usage: AgentLoopUsage) => void;\n onOutcome?: (outcome: AgentLoopOutcome) => void;\n providerOptions?: any;\n runId?: string;\n }) => Promise<AgentLoopUsage>;\n loopOpts: {\n engine: any;\n model: string;\n systemPrompt: string;\n tools: any[];\n messages: any[];\n actions: Record<string, any>;\n send: (event: AgentChatEvent) => void;\n signal: AbortSignal;\n onUsage?: (usage: AgentLoopUsage) => void;\n onOutcome?: (outcome: AgentLoopOutcome) => void;\n providerOptions?: any;\n runId?: string;\n };\n runId: string;\n threadId: string | null;\n /** Owner of this run; persisted on every span + summary so dashboard\n * reads can filter to a single user. Null for unauthenticated callers\n * (background tasks, etc.) — those rows aren't returned by per-user\n * reads. */\n userId: string | null;\n config: ObservabilityConfig;\n metadata?: Record<string, unknown> | null;\n experimentAssignments?: Array<{\n experimentId: string;\n variantId: string;\n }>;\n modelSelectionSource?: string;\n delegation?: {\n protocol: \"a2a\" | \"mcp\";\n callerApp?: string;\n taskId?: string;\n parentRunId?: string;\n parentTurnId?: string;\n };\n /** Raw user-authored message before prompt/context enrichment. */\n sentimentInput?: string;\n /**\n * Browser session id of the request that started this run, when it came from\n * a page. Emitted as PostHog's `$session_id` so agent traces join to session\n * replay — distinct from `$ai_session_id`, which is the thread.\n *\n * Defaults to the in-flight request context, which the agent-chat route\n * populates from the `X-Agent-Native-Session-Id` header.\n */\n browserSessionId?: string;\n classifyError?: (error: unknown) =>\n | {\n status?: \"success\" | \"error\";\n errorMessage?: string | null;\n metadata?: Record<string, unknown> | null;\n }\n | null\n | undefined;\n}): Promise<AgentLoopUsage> {\n const { runAgentLoop, loopOpts, runId, threadId, userId, config } = opts;\n const runStart = Date.now();\n const parentSpanId = spanId();\n const precedingResponsePromise =\n config.inferredSentimentEnabled && opts.sentimentInput && threadId && userId\n ? import(\"./store.js\")\n .then(({ getLatestTraceSummaryForThread }) =>\n getLatestTraceSummaryForThread(threadId, {\n userId,\n excludeRunId: runId,\n }),\n )\n .catch(() => null)\n : Promise.resolve(null);\n\n // Falls back to the in-flight request so callers deep in the agent stack\n // don't have to thread it down by hand.\n const browserSessionId =\n opts.browserSessionId ?? getRequestContext()?.browserSessionId;\n\n // Optional OpenTelemetry root span for this run. No-ops unless a host has\n // installed `@opentelemetry/api` and registered a provider. The promise is\n // resolved before the loop runs so child tool/model spans can parent under\n // it conceptually (we keep them flat in the same tracer, which is enough\n // for the dashboards an embedding app would build).\n const otelRunSpanPromise = startAgentSpan(\"agent.run\", {\n \"agent.run_id\": runId,\n \"agent.thread_id\": threadId ?? undefined,\n \"agent.user_id\": userId ?? undefined,\n \"agent.model\": loopOpts.model,\n \"agent.model_selection_source\": opts.modelSelectionSource,\n \"agent.experiment_id\":\n opts.experimentAssignments?.length === 1\n ? opts.experimentAssignments[0].experimentId\n : undefined,\n \"agent.experiment_variant\":\n opts.experimentAssignments?.length === 1\n ? opts.experimentAssignments[0].variantId\n : undefined,\n });\n\n const spans: TraceSpan[] = [];\n let toolInvocationCounter = 0;\n // Keyed by counter to handle concurrent calls to the same tool name\n const pendingTools = new Map<\n number,\n {\n spanId: string;\n callId?: string;\n startMs: number;\n toolName: string;\n input: AgentToolInput;\n otelSpan: AgentSpan | null;\n endResult?: { status: \"success\" | \"error\"; errorMessage: string | null };\n }\n >();\n // Secondary index for legacy emitters without call ids. Current tool events\n // are paired by id first; same-name FIFO remains as a compatibility fallback.\n const toolNameToCounters = new Map<string, number[]>();\n const toolCallIdToCounter = new Map<string, number>();\n const generationToolCalls = new Map<number, GenerationToolCall>();\n // Assistant text, accumulated only when prompt capture is on so a disabled\n // config never holds message content in memory in the first place.\n const assistantTextParts: string[] = [];\n let assistantTextLength = 0;\n\n let toolCallCount = 0;\n let successfulTools = 0;\n let failedTools = 0;\n\n // Track in-flight OTel tool spans so they're all ended even if the loop\n // throws before a matching `tool_done` arrives.\n const openOtelToolSpans = new Set<AgentSpan>();\n let usage: AgentLoopUsage | undefined;\n let runStatus: \"success\" | \"error\" = \"success\";\n let errorMessage: string | null = null;\n let runMetadata: Record<string, unknown> | null = opts.metadata ?? null;\n let terminalOutcome: AgentLoopOutcome | undefined;\n\n const instrumentedOutcome = (outcome: AgentLoopOutcome): void => {\n terminalOutcome = outcome;\n if (outcome.state === \"completed\") {\n runStatus = \"success\";\n errorMessage = null;\n } else {\n runStatus = \"error\";\n errorMessage =\n outcome.state === \"canceled\"\n ? (outcome.message ?? \"Agent run was canceled.\")\n : outcome.message;\n }\n runMetadata = {\n ...(runMetadata ?? {}),\n terminal_state: outcome.state,\n ...(\"code\" in outcome ? { terminal_code: outcome.code } : {}),\n ...(outcome.state === \"failed\"\n ? { terminal_retryable: outcome.retryable }\n : {}),\n };\n try {\n loopOpts.onOutcome?.(outcome);\n } catch {\n // Observability adapters cannot alter the agent run.\n }\n };\n\n const instrumentedSend = (event: AgentChatEvent): void => {\n try {\n if (\n config.capturePrompts &&\n event.type === \"text\" &&\n assistantTextLength < MAX_AI_CONTENT_BYTES\n ) {\n assistantTextParts.push(event.text);\n assistantTextLength += event.text.length;\n }\n // Some guardrails intentionally stop the loop by emitting a terminal\n // event and returning usage instead of throwing. Preserve that terminal\n // state in telemetry so a tripwire/loop-limit/provider error cannot be\n // counted as a successful delegated generation. A later clear/done means\n // the wrapper recovered and finished cleanly, so reset in that case.\n if (event.type === \"clear\" || event.type === \"done\") {\n runStatus = \"success\";\n errorMessage = null;\n } else if (event.type === \"error\") {\n runStatus = \"error\";\n errorMessage = event.error;\n } else if (event.type === \"tripwire\") {\n runStatus = \"error\";\n errorMessage = event.reason;\n } else if (event.type === \"loop_limit\") {\n runStatus = \"error\";\n errorMessage = \"Agent stopped at the loop limit\";\n } else if (event.type === \"missing_api_key\") {\n runStatus = \"error\";\n errorMessage = \"Missing API key\";\n }\n if (event.type === \"tool_start\") {\n const counter = toolInvocationCounter++;\n const sid = spanId();\n // Start the OTel tool span synchronously-ish: kick off the async\n // resolution and stash the span once it lands. Tool spans are short\n // and the api tracer is synchronous in practice, but we tolerate the\n // microtask gap by recording the span on the pending entry when ready.\n const entry: {\n spanId: string;\n callId?: string;\n startMs: number;\n toolName: string;\n input: AgentToolInput;\n otelSpan: AgentSpan | null;\n // Set by the done handler if it fires before the span promise\n // resolves, so the resolved span is ended with the correct status.\n endResult?: {\n status: \"success\" | \"error\";\n errorMessage: string | null;\n };\n } = {\n spanId: sid,\n ...(event.id ? { callId: event.id } : {}),\n startMs: Date.now(),\n toolName: event.tool,\n input: event.input,\n otelSpan: null,\n };\n pendingTools.set(counter, entry);\n if (event.id) toolCallIdToCounter.set(event.id, counter);\n void startAgentSpan(\"tool.call\", {\n \"tool.name\": event.tool,\n }).then((span) => {\n if (!span) return;\n // If `tool_done` already ran for this call, end the span now with the\n // status it recorded; otherwise stash it for the done handler.\n if (entry.endResult) {\n endAgentSpan(span, {\n status: entry.endResult.status,\n errorMessage: entry.endResult.errorMessage,\n });\n } else {\n entry.otelSpan = span;\n openOtelToolSpans.add(span);\n }\n });\n const queue = toolNameToCounters.get(event.tool);\n if (queue) queue.push(counter);\n else toolNameToCounters.set(event.tool, [counter]);\n } else if (event.type === \"tool_done\") {\n const queue = toolNameToCounters.get(event.tool);\n const counterFromId = event.id\n ? toolCallIdToCounter.get(event.id)\n : undefined;\n const legacyQueueIndex =\n event.id && counterFromId === undefined && queue\n ? queue.findIndex(\n (candidate) => !pendingTools.get(candidate)?.callId,\n )\n : -1;\n const counter =\n counterFromId ??\n (event.id\n ? legacyQueueIndex >= 0\n ? queue?.[legacyQueueIndex]\n : undefined\n : queue?.shift());\n const pending =\n counter !== undefined ? pendingTools.get(counter) : undefined;\n if (counter !== undefined) {\n pendingTools.delete(counter);\n if (pending?.callId) toolCallIdToCounter.delete(pending.callId);\n if ((counterFromId !== undefined || legacyQueueIndex >= 0) && queue) {\n const queueIndex = queue.indexOf(counter);\n if (queueIndex >= 0) queue.splice(queueIndex, 1);\n }\n if (queue && queue.length === 0)\n toolNameToCounters.delete(event.tool);\n }\n toolCallCount++;\n\n const finishedAt = Date.now();\n\n const explicitError = event.isError === true;\n const isError =\n typeof event.isError === \"boolean\"\n ? event.isError\n : typeof event.result === \"string\" &&\n (event.result.startsWith(\"Error\") ||\n event.result.startsWith(\"Error running \"));\n if (isError) failedTools++;\n else successfulTools++;\n\n if (\n counter !== undefined &&\n counter < MAX_TRACKED_GENERATION_TOOL_CALLS &&\n pending\n ) {\n generationToolCalls.set(counter, {\n name: pending.toolName,\n started_offset_ms: Math.max(0, pending.startMs - runStart),\n duration_ms: Math.max(0, finishedAt - pending.startMs),\n status: isError ? \"error\" : \"success\",\n error_class: !isError\n ? null\n : explicitError\n ? \"tool_error\"\n : \"legacy_inferred_error\",\n error_message:\n isError && config.captureToolResults\n ? truncateToolErrorMessage(redactToolErrorMessage(event.result))\n : undefined,\n });\n }\n\n // Finalize the OTel tool span. If the span promise hasn't resolved yet\n // we record the result on the entry so its `.then` handler ends it.\n const otelEndResult = {\n status: (isError ? \"error\" : \"success\") as \"success\" | \"error\",\n errorMessage: isError ? (event.result as string) : null,\n };\n if (pending?.otelSpan) {\n openOtelToolSpans.delete(pending.otelSpan);\n endAgentSpan(pending.otelSpan, {\n status: otelEndResult.status,\n errorMessage: otelEndResult.errorMessage,\n attributes: { \"tool.name\": event.tool },\n });\n } else if (pending) {\n pending.endResult = otelEndResult;\n }\n\n const span: TraceSpan = {\n id: pending?.spanId ?? spanId(),\n runId,\n threadId,\n userId,\n parentSpanId,\n spanType: \"tool_call\",\n name: event.tool,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n costCentsX100: 0,\n durationMs: pending ? Math.max(0, finishedAt - pending.startMs) : 0,\n status: isError ? \"error\" : \"success\",\n errorMessage: isError ? event.result : null,\n metadata:\n config.captureToolArgs && pending\n ? // Strip Authorization/api-key/token-shaped values before\n // persisting (M14 in the MCP/A2A audit). Tool-runtime\n // execution still sees the unredacted input — only the\n // long-lived span row is sanitized.\n {\n input: redactSensitiveFields(pending.input) as Record<\n string,\n string\n >,\n }\n : null,\n createdAt: Date.now(),\n };\n spans.push(span);\n }\n } catch {}\n\n loopOpts.send(event);\n };\n\n try {\n usage = await runAgentLoop({\n ...loopOpts,\n runId,\n send: instrumentedSend,\n onOutcome: instrumentedOutcome,\n });\n } catch (err: any) {\n const classification = opts.classifyError?.(err) ?? null;\n runStatus = classification?.status ?? \"error\";\n errorMessage =\n classification?.errorMessage === undefined\n ? (err?.message ?? String(err))\n : classification.errorMessage;\n const errorMetadata = classification?.metadata ?? null;\n runMetadata =\n runMetadata || errorMetadata\n ? { ...(runMetadata ?? {}), ...(errorMetadata ?? {}) }\n : null;\n throw err;\n } finally {\n const runEnd = Date.now();\n const totalDurationMs = runEnd - runStart;\n\n if (pendingTools.size > 0) {\n if (runStatus === \"success\") {\n runStatus = \"error\";\n errorMessage ??= \"Agent run ended with interrupted tool calls\";\n }\n for (const [counter, pending] of pendingTools) {\n toolCallCount += 1;\n failedTools += 1;\n const interruptedMessage = \"Tool call interrupted before completion\";\n if (counter < MAX_TRACKED_GENERATION_TOOL_CALLS) {\n generationToolCalls.set(counter, {\n name: pending.toolName,\n started_offset_ms: Math.max(0, pending.startMs - runStart),\n duration_ms: Math.max(0, runEnd - pending.startMs),\n status: \"error\",\n error_class: \"interrupted\",\n error_message: config.captureToolResults\n ? interruptedMessage\n : undefined,\n });\n }\n if (pending.otelSpan) {\n openOtelToolSpans.delete(pending.otelSpan);\n endAgentSpan(pending.otelSpan, {\n status: \"error\",\n errorMessage: interruptedMessage,\n attributes: { \"tool.name\": pending.toolName },\n });\n } else {\n pending.endResult = {\n status: \"error\",\n errorMessage: interruptedMessage,\n };\n }\n spans.push({\n id: pending.spanId,\n runId,\n threadId,\n userId,\n parentSpanId,\n spanType: \"tool_call\",\n name: pending.toolName,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n costCentsX100: 0,\n durationMs: Math.max(0, runEnd - pending.startMs),\n status: \"error\",\n errorMessage: interruptedMessage,\n metadata: null,\n createdAt: runEnd,\n });\n }\n pendingTools.clear();\n toolNameToCounters.clear();\n toolCallIdToCounter.clear();\n }\n\n let costCentsX100 = 0;\n try {\n const { calculateCost } = await import(\"../usage/store.js\");\n if (usage) {\n costCentsX100 = calculateCost(\n usage.inputTokens,\n usage.outputTokens,\n usage.model,\n usage.cacheReadTokens,\n usage.cacheWriteTokens,\n );\n }\n } catch {}\n\n let llmCallCount = 0;\n if (usage || runStatus === \"error\") {\n llmCallCount = 1;\n const generationUsage = usage ?? {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n model: loopOpts.model,\n };\n // The engine never reported a `usage` event for this run (killed for\n // silence before any provider response, or the loop threw before\n // returning). `generationUsage`'s token fields are placeholder zeros in\n // that case, not measured values — the tracking event below must omit\n // them rather than report a fabricated 0.\n const usageReported = usage?.usageReported === true;\n const firstTokenMs =\n usage?.firstEngineEventAtMs !== undefined\n ? Math.max(0, usage.firstEngineEventAtMs - runStart)\n : undefined;\n const llmSpanId = spanId();\n const generationContent = buildGenerationContent({\n config,\n messages: loopOpts.messages,\n tools: loopOpts.tools,\n assistantText: assistantTextParts.join(\"\"),\n toolSpans: spans.filter((s) => s.spanType === \"tool_call\"),\n });\n const llmSpan: TraceSpan = {\n id: llmSpanId,\n runId,\n threadId,\n userId,\n parentSpanId,\n spanType: \"llm_call\",\n name: generationUsage.model,\n inputTokens: generationUsage.inputTokens,\n outputTokens: generationUsage.outputTokens,\n cacheReadTokens: generationUsage.cacheReadTokens,\n cacheWriteTokens: generationUsage.cacheWriteTokens,\n costCentsX100,\n durationMs: totalDurationMs,\n status: runStatus,\n errorMessage,\n metadata: null,\n createdAt: runStart,\n };\n spans.push(llmSpan);\n emitLlmGenerationTrackingEvent({\n runId,\n threadId,\n userId,\n parentSpanId,\n llmSpanId,\n engineName:\n typeof loopOpts.engine?.name === \"string\"\n ? loopOpts.engine.name\n : undefined,\n model: generationUsage.model,\n inputTokens: usageReported ? generationUsage.inputTokens : undefined,\n outputTokens: usageReported ? generationUsage.outputTokens : undefined,\n cacheReadTokens: usageReported\n ? generationUsage.cacheReadTokens\n : undefined,\n cacheWriteTokens: usageReported\n ? generationUsage.cacheWriteTokens\n : undefined,\n costCentsX100: usageReported ? costCentsX100 : undefined,\n durationMs: totalDurationMs,\n firstTokenMs,\n status: runStatus,\n errorMessage,\n toolCalls: toolCallCount,\n successfulTools,\n failedTools,\n tools: [...generationToolCalls.entries()]\n .sort(([a], [b]) => a - b)\n .map(([, detail]) => detail),\n toolsTruncated:\n toolInvocationCounter > MAX_TRACKED_GENERATION_TOOL_CALLS,\n terminalOutcome,\n delegation: opts.delegation,\n createdAt: runStart,\n experimentAssignments: opts.experimentAssignments,\n modelSelectionSource: opts.modelSelectionSource,\n browserSessionId,\n ...generationContent,\n });\n }\n\n const parentSpan: TraceSpan = {\n id: parentSpanId,\n runId,\n threadId,\n userId,\n parentSpanId: null,\n spanType: \"agent_run\",\n name: \"agent_run\",\n inputTokens: usage?.inputTokens ?? 0,\n outputTokens: usage?.outputTokens ?? 0,\n cacheReadTokens: usage?.cacheReadTokens ?? 0,\n cacheWriteTokens: usage?.cacheWriteTokens ?? 0,\n costCentsX100,\n durationMs: totalDurationMs,\n status: runStatus,\n errorMessage,\n metadata: runMetadata,\n createdAt: runStart,\n };\n spans.push(parentSpan);\n\n // PostHog LLM analytics: the run is a `$ai_trace`, each tool call an\n // `$ai_span` under it. Emitted from the collected spans rather than from a\n // second instrumentation pass, so the tree PostHog shows and the tree we\n // persist cannot drift apart.\n try {\n const aiError =\n runStatus === \"error\"\n ? toAiErrorDetail(errorMessage, {\n state: terminalOutcome?.state,\n code:\n terminalOutcome?.state === \"failed\" ||\n terminalOutcome?.state === \"input_required\"\n ? terminalOutcome.code\n : undefined,\n retryable:\n terminalOutcome?.state === \"failed\"\n ? terminalOutcome.retryable\n : undefined,\n })\n : undefined;\n const provider = llmProviderFromEngine(\n typeof loopOpts.engine?.name === \"string\"\n ? loopOpts.engine.name\n : undefined,\n usage?.model ?? loopOpts.model,\n );\n\n const toolSpans = config.captureLlmSpans\n ? spans.filter((s) => s.spanType === \"tool_call\")\n : [];\n const emittedToolSpans = toolSpans.slice(0, MAX_AI_SPANS_PER_RUN);\n const droppedToolSpans = toolSpans.length - emittedToolSpans.length;\n\n emitAiTraceEvent({\n runId,\n threadId,\n userId,\n spanName: \"agent_run\",\n model: usage?.model ?? loopOpts.model,\n provider,\n latencySeconds: Math.round(totalDurationMs) / 1000,\n isError: runStatus === \"error\",\n error: aiError,\n inputTokens: usage?.usageReported ? usage.inputTokens : undefined,\n outputTokens: usage?.usageReported ? usage.outputTokens : undefined,\n costUsd: usage?.usageReported\n ? costUsdFromCenticents(costCentsX100)\n : undefined,\n createdAt: runStart,\n browserSessionId,\n extraProperties: {\n ...trackingIdentityProperties(),\n source: \"agent_observability\",\n run_id: runId,\n thread_id: threadId,\n // A truncated run must not read as a complete one.\n ...(droppedToolSpans > 0\n ? {\n $ai_spans_dropped: droppedToolSpans,\n $ai_spans_emitted: emittedToolSpans.length,\n }\n : {}),\n },\n });\n\n for (const span of emittedToolSpans) {\n // `span.errorMessage` is the raw tool result. It routinely contains\n // upstream response bodies with Authorization headers and standalone\n // API keys, so it gets the same redaction + bounding the generation\n // event's `tools[].error_message` already applies, and the same\n // `captureToolResults` gate — exporting it here otherwise reintroduced\n // the leak that gate exists to prevent. `$ai_is_error` still marks the\n // failure when the content is withheld.\n const toolErrorMessage =\n span.status === \"error\" &&\n span.errorMessage &&\n config.captureToolResults\n ? truncateToolErrorMessage(\n redactToolErrorMessage(span.errorMessage),\n )\n : undefined;\n\n emitAiSpanEvent({\n runId,\n threadId,\n userId,\n spanId: span.id,\n spanName: span.name,\n latencySeconds: Math.round(span.durationMs) / 1000,\n isError: span.status === \"error\",\n error: toolErrorMessage\n ? toAiErrorDetail(toolErrorMessage)\n : undefined,\n createdAt: span.createdAt,\n browserSessionId,\n // `metadata.input` is already redacted and only present when\n // `captureToolArgs` is on; absent stays absent.\n inputState: (span.metadata as { input?: unknown } | null)?.input,\n outputState: toolErrorMessage,\n extraProperties: {\n ...trackingIdentityProperties(),\n source: \"agent_observability\",\n span_type: \"tool_call\",\n },\n });\n }\n // coercion-ok: a throw here would skip trace persistence below\n } catch {\n // LLM analytics must never affect the run or trace persistence.\n }\n\n const summary: TraceSummary = {\n runId,\n threadId,\n userId,\n totalSpans: spans.length,\n llmCalls: llmCallCount,\n toolCalls: toolCallCount,\n successfulTools,\n failedTools,\n totalDurationMs,\n totalCostCentsX100: costCentsX100,\n totalInputTokens: usage?.inputTokens ?? 0,\n totalOutputTokens: usage?.outputTokens ?? 0,\n model: usage?.model ?? loopOpts.model,\n createdAt: runStart,\n };\n\n writeTraceData(spans, summary, runId, config).catch(() => {});\n\n // OpenTelemetry export (no-op unless a provider is registered). Emit a\n // self-contained `llm.call` span carrying model + token usage, end any\n // tool spans still open (loop threw mid-tool), and end the run span. Awaited\n // so the spans are emitted before the function returns; cheap when no-op.\n try {\n if (usage) {\n endAgentSpan(await startAgentSpan(\"llm.call\", {}), {\n status: runStatus,\n errorMessage,\n attributes: {\n \"llm.model\": usage.model,\n \"llm.input_tokens\": usage.inputTokens,\n \"llm.output_tokens\": usage.outputTokens,\n \"llm.cache_read_tokens\": usage.cacheReadTokens,\n \"llm.cache_write_tokens\": usage.cacheWriteTokens,\n \"llm.cost_cents_x100\": costCentsX100,\n },\n });\n }\n for (const toolSpan of openOtelToolSpans) {\n endAgentSpan(toolSpan, {\n status: \"error\",\n errorMessage: \"Agent run ended before tool_done.\",\n });\n }\n openOtelToolSpans.clear();\n endAgentSpan(await otelRunSpanPromise, {\n status: runStatus,\n errorMessage,\n attributes: {\n \"agent.tool_calls\": toolCallCount,\n \"agent.successful_tools\": successfulTools,\n \"agent.failed_tools\": failedTools,\n \"agent.duration_ms\": totalDurationMs,\n \"agent.input_tokens\": usage?.inputTokens ?? 0,\n \"agent.output_tokens\": usage?.outputTokens ?? 0,\n \"agent.cost_cents_x100\": costCentsX100,\n \"agent.terminal_state\": terminalOutcome?.state,\n \"agent.terminal_code\":\n terminalOutcome?.state === \"failed\" ||\n terminalOutcome?.state === \"input_required\"\n ? terminalOutcome.code\n : undefined,\n },\n });\n } catch {\n // OTel export must never break the run.\n }\n }\n\n // Classify only after the main loop has finished so the tiny managed Luna\n // request cannot contend with the user's response for a gateway slot. This\n // short, awaited tail keeps serverless runtimes alive long enough to emit the\n // event, while the response content has already streamed to the client.\n if (usage && opts.sentimentInput) {\n try {\n const precedingResponse = await precedingResponsePromise;\n if (precedingResponse) {\n const { inferAndTrackSentiment } = await import(\"./sentiment.js\");\n await inferAndTrackSentiment({\n classifierModel: config.inferredSentimentModel,\n precedingResponseModel: precedingResponse.model,\n text: opts.sentimentInput,\n precedingRunId: precedingResponse.runId,\n classificationTriggerRunId: runId,\n threadId,\n userId,\n sampleRate: config.inferredSentimentSampleRate,\n });\n }\n } catch {\n // Optional inference must never alter the result of the main run.\n }\n }\n\n return usage!;\n}\n\nasync function writeTraceData(\n spans: TraceSpan[],\n summary: TraceSummary,\n runId: string,\n config: ObservabilityConfig,\n): Promise<void> {\n const { insertTraceSpan, upsertTraceSummary } = await import(\"./store.js\");\n await Promise.all(spans.map((s) => insertTraceSpan(s).catch(() => {})));\n await upsertTraceSummary(summary).catch(() => {});\n\n // Fire automated evals after trace data is persisted\n try {\n const { evaluateRun } = await import(\"./evals.js\");\n await evaluateRun(runId, { sampleRate: config.evalSampleRate });\n } catch {}\n}\n"]}
@@ -151,9 +151,19 @@ export interface ExperimentMetricResult {
151
151
  }
152
152
  export interface ObservabilityConfig {
153
153
  enabled: boolean;
154
+ /**
155
+ * Export prompt and completion content (`$ai_input`, `$ai_output_choices`)
156
+ * to configured LLM-analytics backends. Off by default: message bodies are
157
+ * user data, and a trace backend is not a place to put it without a decision.
158
+ *
159
+ * When off the fields are OMITTED, never sent empty — an empty array is
160
+ * indistinguishable from a genuinely empty prompt.
161
+ */
154
162
  capturePrompts: boolean;
155
163
  captureToolArgs: boolean;
156
164
  captureToolResults: boolean;
165
+ /** Emit one `$ai_span` per tool call alongside the run's `$ai_trace`. */
166
+ captureLlmSpans: boolean;
157
167
  evalSampleRate: number;
158
168
  /**
159
169
  * Classify the raw user message as positive, negative, or neutral. Off by
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/observability/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/observability/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,WAAW,CAAC;AAC9D,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC;AAE7C,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;0EAEsE;IACtE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,aAAa,GAAG,UAAU,GAAG,MAAM,CAAC;AAE7E,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,YAAY,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB;iCAC6B;IAC7B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,CAAC;AAE3D,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;8BAC0B;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAID,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE5E,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB;;;;;;;OAOG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,yEAAyE;IACzE,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,wBAAwB,EAAE,OAAO,CAAC;IAClC,0EAA0E;IAC1E,2BAA2B,EAAE,MAAM,CAAC;IACpC,oDAAoD;IACpD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,SAAS,EAAE,2BAA2B,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,eAAO,MAAM,4BAA4B,EAAE,mBAW1C,CAAC"}
@@ -10,6 +10,7 @@ export const DEFAULT_OBSERVABILITY_CONFIG = {
10
10
  capturePrompts: false,
11
11
  captureToolArgs: false,
12
12
  captureToolResults: false,
13
+ captureLlmSpans: true,
13
14
  evalSampleRate: 0,
14
15
  inferredSentimentEnabled: false,
15
16
  inferredSentimentSampleRate: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/observability/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkMH,MAAM,CAAC,MAAM,4BAA4B,GAAwB;IAC/D,OAAO,EAAE,IAAI;IACb,cAAc,EAAE,KAAK;IACrB,eAAe,EAAE,KAAK;IACtB,kBAAkB,EAAE,KAAK;IACzB,cAAc,EAAE,CAAC;IACjB,wBAAwB,EAAE,KAAK;IAC/B,2BAA2B,EAAE,CAAC;IAC9B,sBAAsB,EAAE,cAAc;IACtC,SAAS,EAAE,EAAE;CACd,CAAC","sourcesContent":["/**\n * Shared types for the agent observability system.\n *\n * Covers traces, feedback, evals, experiments, and satisfaction scoring.\n * Each domain module imports from here so the data model is consistent\n * across the entire observability stack.\n */\n\n// ─── Traces ───────────────────────────────────────────────────────────\n\nexport type SpanType = \"llm_call\" | \"tool_call\" | \"agent_run\";\nexport type SpanStatus = \"success\" | \"error\";\n\nexport interface TraceSpan {\n id: string;\n runId: string;\n threadId: string | null;\n /** Owner of the run that produced this span. Null for legacy rows\n * written before per-user isolation; null also means \"no auth context\"\n * (background tasks, etc.) and is filtered out of per-user reads. */\n userId: string | null;\n parentSpanId: string | null;\n spanType: SpanType;\n name: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n costCentsX100: number;\n durationMs: number;\n status: SpanStatus;\n errorMessage: string | null;\n metadata: Record<string, unknown> | null;\n createdAt: number;\n}\n\nexport interface TraceSummary {\n runId: string;\n threadId: string | null;\n /** See `TraceSpan.userId`. */\n userId: string | null;\n totalSpans: number;\n llmCalls: number;\n toolCalls: number;\n successfulTools: number;\n failedTools: number;\n totalDurationMs: number;\n totalCostCentsX100: number;\n totalInputTokens: number;\n totalOutputTokens: number;\n model: string;\n createdAt: number;\n}\n\n// ─── Feedback ────────────���────────────────────────────────────────────\n\nexport type FeedbackType = \"thumbs_up\" | \"thumbs_down\" | \"category\" | \"text\";\n\nexport interface FeedbackEntry {\n id: string;\n runId: string | null;\n threadId: string | null;\n messageSeq: number | null;\n feedbackType: FeedbackType;\n value: string;\n userId: string | null;\n createdAt: number;\n}\n\nexport interface SatisfactionScore {\n id: string;\n threadId: string;\n /** Owner of the thread the score was computed for. Same null semantics\n * as `TraceSpan.userId`. */\n userId: string | null;\n frustrationScore: number;\n rephrasingScore: number;\n abandonmentScore: number;\n sentimentScore: number;\n lengthTrendScore: number;\n computedAt: number;\n}\n\n// ─── Evals ─────────��──────────────────────────────────────────────────\n\nexport type EvalType = \"automated\" | \"llm_judge\" | \"human\";\n\nexport interface EvalResult {\n id: string;\n runId: string;\n threadId: string | null;\n /** Owner of the run being evaluated. Same null semantics as\n * `TraceSpan.userId`. */\n userId: string | null;\n evalType: EvalType;\n criteria: string;\n score: number;\n reasoning: string | null;\n metadata: Record<string, unknown> | null;\n createdAt: number;\n}\n\nexport interface EvalDataset {\n id: string;\n name: string;\n description: string;\n entries: EvalTestCase[];\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface EvalTestCase {\n input: string;\n expectedOutput?: string;\n context?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface EvalCriteria {\n name: string;\n description: string;\n rubric?: string;\n scoreRange?: { min: number; max: number };\n}\n\n// ─── Experiments ───────��──────────────────────────────────────────────\n\nexport type ExperimentStatus = \"draft\" | \"running\" | \"paused\" | \"completed\";\n\nexport interface ExperimentVariant {\n id: string;\n weight: number;\n config: Record<string, unknown>;\n}\n\nexport interface Experiment {\n id: string;\n name: string;\n status: ExperimentStatus;\n variants: ExperimentVariant[];\n metrics: string[];\n assignmentLevel: \"user\" | \"session\";\n startedAt: number | null;\n endedAt: number | null;\n createdAt: number;\n /**\n * Email of the user who created this experiment. Used to scope mutations\n * (PUT /experiments/:id, POST /experiments/:id/results) so one user can't\n * silently change another user's experiment in a multi-tenant deployment.\n * Null on legacy rows from before the owner_email migration shipped.\n */\n ownerEmail?: string | null;\n}\n\nexport interface ExperimentAssignment {\n experimentId: string;\n userId: string;\n variantId: string;\n assignedAt: number;\n}\n\nexport interface ExperimentMetricResult {\n id: string;\n experimentId: string;\n variantId: string;\n metric: string;\n value: number;\n sampleSize: number;\n confidenceLow: number;\n confidenceHigh: number;\n computedAt: number;\n}\n\n// ─── Observability config ─────────────────────────────────────────────\n\nexport interface ObservabilityConfig {\n enabled: boolean;\n capturePrompts: boolean;\n captureToolArgs: boolean;\n captureToolResults: boolean;\n evalSampleRate: number;\n /**\n * Classify the raw user message as positive, negative, or neutral. Off by\n * default for self-hosted apps; first-party agent-native.com deployments\n * enable it automatically unless explicitly disabled.\n */\n inferredSentimentEnabled: boolean;\n /** Deterministic fraction of eligible user messages to classify (0-1). */\n inferredSentimentSampleRate: number;\n /** Model used by the managed Builder classifier. */\n inferredSentimentModel: string;\n exporters: ObservabilityExporterConfig[];\n}\n\nexport interface ObservabilityExporterConfig {\n type: \"otlp\" | \"console\" | \"custom\";\n endpoint?: string;\n headers?: Record<string, string>;\n}\n\nexport const DEFAULT_OBSERVABILITY_CONFIG: ObservabilityConfig = {\n enabled: true,\n capturePrompts: false,\n captureToolArgs: false,\n captureToolResults: false,\n evalSampleRate: 0,\n inferredSentimentEnabled: false,\n inferredSentimentSampleRate: 0,\n inferredSentimentModel: \"gpt-5-6-luna\",\n exporters: [],\n};\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/observability/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA4MH,MAAM,CAAC,MAAM,4BAA4B,GAAwB;IAC/D,OAAO,EAAE,IAAI;IACb,cAAc,EAAE,KAAK;IACrB,eAAe,EAAE,KAAK;IACtB,kBAAkB,EAAE,KAAK;IACzB,eAAe,EAAE,IAAI;IACrB,cAAc,EAAE,CAAC;IACjB,wBAAwB,EAAE,KAAK;IAC/B,2BAA2B,EAAE,CAAC;IAC9B,sBAAsB,EAAE,cAAc;IACtC,SAAS,EAAE,EAAE;CACd,CAAC","sourcesContent":["/**\n * Shared types for the agent observability system.\n *\n * Covers traces, feedback, evals, experiments, and satisfaction scoring.\n * Each domain module imports from here so the data model is consistent\n * across the entire observability stack.\n */\n\n// ─── Traces ───────────────────────────────────────────────────────────\n\nexport type SpanType = \"llm_call\" | \"tool_call\" | \"agent_run\";\nexport type SpanStatus = \"success\" | \"error\";\n\nexport interface TraceSpan {\n id: string;\n runId: string;\n threadId: string | null;\n /** Owner of the run that produced this span. Null for legacy rows\n * written before per-user isolation; null also means \"no auth context\"\n * (background tasks, etc.) and is filtered out of per-user reads. */\n userId: string | null;\n parentSpanId: string | null;\n spanType: SpanType;\n name: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n costCentsX100: number;\n durationMs: number;\n status: SpanStatus;\n errorMessage: string | null;\n metadata: Record<string, unknown> | null;\n createdAt: number;\n}\n\nexport interface TraceSummary {\n runId: string;\n threadId: string | null;\n /** See `TraceSpan.userId`. */\n userId: string | null;\n totalSpans: number;\n llmCalls: number;\n toolCalls: number;\n successfulTools: number;\n failedTools: number;\n totalDurationMs: number;\n totalCostCentsX100: number;\n totalInputTokens: number;\n totalOutputTokens: number;\n model: string;\n createdAt: number;\n}\n\n// ─── Feedback ────────────���────────────────────────────────────────────\n\nexport type FeedbackType = \"thumbs_up\" | \"thumbs_down\" | \"category\" | \"text\";\n\nexport interface FeedbackEntry {\n id: string;\n runId: string | null;\n threadId: string | null;\n messageSeq: number | null;\n feedbackType: FeedbackType;\n value: string;\n userId: string | null;\n createdAt: number;\n}\n\nexport interface SatisfactionScore {\n id: string;\n threadId: string;\n /** Owner of the thread the score was computed for. Same null semantics\n * as `TraceSpan.userId`. */\n userId: string | null;\n frustrationScore: number;\n rephrasingScore: number;\n abandonmentScore: number;\n sentimentScore: number;\n lengthTrendScore: number;\n computedAt: number;\n}\n\n// ─── Evals ─────────��──────────────────────────────────────────────────\n\nexport type EvalType = \"automated\" | \"llm_judge\" | \"human\";\n\nexport interface EvalResult {\n id: string;\n runId: string;\n threadId: string | null;\n /** Owner of the run being evaluated. Same null semantics as\n * `TraceSpan.userId`. */\n userId: string | null;\n evalType: EvalType;\n criteria: string;\n score: number;\n reasoning: string | null;\n metadata: Record<string, unknown> | null;\n createdAt: number;\n}\n\nexport interface EvalDataset {\n id: string;\n name: string;\n description: string;\n entries: EvalTestCase[];\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface EvalTestCase {\n input: string;\n expectedOutput?: string;\n context?: Record<string, unknown>;\n tags?: string[];\n}\n\nexport interface EvalCriteria {\n name: string;\n description: string;\n rubric?: string;\n scoreRange?: { min: number; max: number };\n}\n\n// ─── Experiments ───────��──────────────────────────────────────────────\n\nexport type ExperimentStatus = \"draft\" | \"running\" | \"paused\" | \"completed\";\n\nexport interface ExperimentVariant {\n id: string;\n weight: number;\n config: Record<string, unknown>;\n}\n\nexport interface Experiment {\n id: string;\n name: string;\n status: ExperimentStatus;\n variants: ExperimentVariant[];\n metrics: string[];\n assignmentLevel: \"user\" | \"session\";\n startedAt: number | null;\n endedAt: number | null;\n createdAt: number;\n /**\n * Email of the user who created this experiment. Used to scope mutations\n * (PUT /experiments/:id, POST /experiments/:id/results) so one user can't\n * silently change another user's experiment in a multi-tenant deployment.\n * Null on legacy rows from before the owner_email migration shipped.\n */\n ownerEmail?: string | null;\n}\n\nexport interface ExperimentAssignment {\n experimentId: string;\n userId: string;\n variantId: string;\n assignedAt: number;\n}\n\nexport interface ExperimentMetricResult {\n id: string;\n experimentId: string;\n variantId: string;\n metric: string;\n value: number;\n sampleSize: number;\n confidenceLow: number;\n confidenceHigh: number;\n computedAt: number;\n}\n\n// ─── Observability config ─────────────────────────────────────────────\n\nexport interface ObservabilityConfig {\n enabled: boolean;\n /**\n * Export prompt and completion content (`$ai_input`, `$ai_output_choices`)\n * to configured LLM-analytics backends. Off by default: message bodies are\n * user data, and a trace backend is not a place to put it without a decision.\n *\n * When off the fields are OMITTED, never sent empty — an empty array is\n * indistinguishable from a genuinely empty prompt.\n */\n capturePrompts: boolean;\n captureToolArgs: boolean;\n captureToolResults: boolean;\n /** Emit one `$ai_span` per tool call alongside the run's `$ai_trace`. */\n captureLlmSpans: boolean;\n evalSampleRate: number;\n /**\n * Classify the raw user message as positive, negative, or neutral. Off by\n * default for self-hosted apps; first-party agent-native.com deployments\n * enable it automatically unless explicitly disabled.\n */\n inferredSentimentEnabled: boolean;\n /** Deterministic fraction of eligible user messages to classify (0-1). */\n inferredSentimentSampleRate: number;\n /** Model used by the managed Builder classifier. */\n inferredSentimentModel: string;\n exporters: ObservabilityExporterConfig[];\n}\n\nexport interface ObservabilityExporterConfig {\n type: \"otlp\" | \"console\" | \"custom\";\n endpoint?: string;\n headers?: Record<string, string>;\n}\n\nexport const DEFAULT_OBSERVABILITY_CONFIG: ObservabilityConfig = {\n enabled: true,\n capturePrompts: false,\n captureToolArgs: false,\n captureToolResults: false,\n captureLlmSpans: true,\n evalSampleRate: 0,\n inferredSentimentEnabled: false,\n inferredSentimentSampleRate: 0,\n inferredSentimentModel: \"gpt-5-6-luna\",\n exporters: [],\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"register-framework-secrets.d.ts","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,wBAAgB,wBAAwB,IAAI,IAAI,CAyN/C"}
1
+ {"version":3,"file":"register-framework-secrets.d.ts","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,wBAAgB,wBAAwB,IAAI,IAAI,CAyO/C"}
@@ -129,6 +129,20 @@ export function registerFrameworkSecrets() {
129
129
  },
130
130
  });
131
131
  }
132
+ // PostHog — product analytics, error tracking, and LLM analytics. One key
133
+ // arms all three; `POSTHOG_ERROR_TRACKING=false` opts out of exceptions
134
+ // while keeping analytics.
135
+ if (!getRequiredSecret("POSTHOG_API_KEY")) {
136
+ registerRequiredSecret({
137
+ key: "POSTHOG_API_KEY",
138
+ label: "PostHog project API key",
139
+ description: "Sends product analytics, server exceptions, and LLM traces to PostHog. Set POSTHOG_HOST for self-hosted or EU projects.",
140
+ docsUrl: "https://posthog.com/docs/getting-started/install",
141
+ scope: "workspace",
142
+ kind: "api-key",
143
+ required: false,
144
+ });
145
+ }
132
146
  // Web-search tool backends — optional; the tool selects the first
133
147
  // configured manual key at call time, then falls back to Builder Connect.
134
148
  const webSearchKeys = [
@@ -1 +1 @@
1
- {"version":3,"file":"register-framework-secrets.js","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Framework-level secret registrations.\n *\n * Side-effect module — imported by the core-routes plugin at boot so the\n * sidebar settings UI and the `/_agent-native/secrets` list route surface the\n * relevant keys in every template.\n *\n * Each call uses a `getRequiredSecret` guard so a template that has already\n * registered the same key (often with stricter settings like `required: true`)\n * wins — the framework registration is a fallback, not an override.\n *\n * OPENAI_API_KEY is optional framework-wide because it enables the shared\n * realtime speech-to-speech agent mode. Templates can pre-register the same\n * key with stricter requirements; the guard below preserves their definition.\n */\n\nimport { getRequiredSecret, registerRequiredSecret } from \"./register.js\";\n\nexport function registerFrameworkSecrets(): void {\n const workspaceOAuthProviders = [\n {\n id: \"figma\",\n credentialPrefix: \"FIGMA\",\n oauthProvider: \"figma\",\n label: \"Figma\",\n docsUrl: \"https://developers.figma.com/docs/rest-api/oauth-apps/\",\n },\n {\n id: \"google_drive\",\n credentialPrefix: \"GOOGLE\",\n oauthProvider: \"google\",\n label: \"Google Drive\",\n docsUrl:\n \"https://developers.google.com/identity/protocols/oauth2/web-server\",\n },\n {\n id: \"github\",\n credentialPrefix: \"GITHUB\",\n oauthProvider: \"github\",\n label: \"GitHub\",\n docsUrl: \"https://docs.github.com/apps/oauth-apps/building-oauth-apps\",\n },\n {\n id: \"hubspot\",\n credentialPrefix: \"HUBSPOT\",\n oauthProvider: \"hubspot\",\n label: \"HubSpot\",\n docsUrl:\n \"https://developers.hubspot.com/docs/apps/developer-platform/build-apps/authentication/oauth/oauth-quickstart-guide\",\n },\n {\n id: \"salesforce\",\n credentialPrefix: \"SALESFORCE\",\n oauthProvider: \"salesforce\",\n label: \"Salesforce\",\n docsUrl:\n \"https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_web_server_oauth_flow.htm\",\n },\n {\n id: \"jira\",\n credentialPrefix: \"JIRA\",\n oauthProvider: \"jira\",\n label: \"Jira Cloud\",\n docsUrl:\n \"https://developer.atlassian.com/cloud/jira/platform/oauth-2-3lo-apps/\",\n },\n {\n id: \"sentry\",\n credentialPrefix: \"SENTRY\",\n oauthProvider: \"sentry\",\n label: \"Sentry\",\n docsUrl: \"https://docs.sentry.io/api/auth/\",\n },\n {\n id: \"notion\",\n credentialPrefix: \"NOTION\",\n oauthProvider: \"notion\",\n label: \"Notion\",\n docsUrl: \"https://developers.notion.com/docs/authorization\",\n },\n ] as const;\n\n for (const provider of workspaceOAuthProviders) {\n const prefix = provider.credentialPrefix;\n for (const credential of [\n { suffix: \"CLIENT_ID\", label: \"OAuth client ID\" },\n { suffix: \"CLIENT_SECRET\", label: \"OAuth client secret\" },\n ] as const) {\n const key = `${prefix}_${credential.suffix}`;\n if (!getRequiredSecret(key)) {\n registerRequiredSecret({\n key,\n label: `${provider.label} ${credential.label}`,\n description: `Workspace-owned ${provider.label} OAuth application credential. Tokens granted by users are stored separately and encrypted.`,\n docsUrl: provider.docsUrl,\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n }\n\n const connectionKey = `${prefix}_CONNECTED`;\n if (!getRequiredSecret(connectionKey)) {\n registerRequiredSecret({\n key: connectionKey,\n label: `${provider.label} account`,\n description: `Connect a ${provider.label} account for scoped workspace imports.`,\n docsUrl: provider.docsUrl,\n scope: \"user\",\n kind: \"oauth\",\n required: false,\n oauthProvider: provider.oauthProvider,\n oauthConnectUrl: `/_agent-native/connections/oauth/${provider.id}/start`,\n });\n }\n }\n\n if (!getRequiredSecret(\"OPENAI_API_KEY\")) {\n registerRequiredSecret({\n key: \"OPENAI_API_KEY\",\n label: \"OpenAI API key\",\n description:\n \"Optional fallback for realtime voice when Builder is not connected, and for OpenAI transcription.\",\n docsUrl: \"https://platform.openai.com/api-keys\",\n scope: \"user\",\n kind: \"api-key\",\n required: false,\n validator: async (value) => {\n const response = await fetch(\"https://api.openai.com/v1/models\", {\n headers: { Authorization: `Bearer ${value}` },\n });\n return response.ok\n ? { ok: true }\n : {\n ok: false,\n error: `OpenAI rejected the key (HTTP ${response.status}).`,\n };\n },\n });\n }\n\n // Web-search tool backends — optional; the tool selects the first\n // configured manual key at call time, then falls back to Builder Connect.\n const webSearchKeys: Array<{\n key: string;\n label: string;\n description: string;\n docsUrl: string;\n }> = [\n {\n key: \"BRAVE_SEARCH_API_KEY\",\n label: \"Brave Search API Key\",\n description:\n \"Enables the web-search agent tool via Brave Search. Optional when Builder.io is connected for managed web search.\",\n docsUrl: \"https://brave.com/search/api/\",\n },\n {\n key: \"TAVILY_API_KEY\",\n label: \"Tavily API Key\",\n description:\n \"Enables the web-search agent tool via Tavily. Used as fallback when BRAVE_SEARCH_API_KEY is not set and before Builder-managed search.\",\n docsUrl: \"https://tavily.com/\",\n },\n {\n key: \"EXA_API_KEY\",\n label: \"Exa API Key\",\n description:\n \"Enables the web-search agent tool via Exa. Used as fallback when Brave and Tavily are not set and before Builder-managed search.\",\n docsUrl: \"https://exa.ai/\",\n },\n {\n key: \"FIRECRAWL_API_KEY\",\n label: \"Firecrawl API Key\",\n description:\n \"Enables the web-search agent tool via Firecrawl. Used as fallback when Brave, Tavily, and Exa are not set and before Builder-managed search.\",\n docsUrl: \"https://firecrawl.dev/\",\n },\n ];\n\n for (const entry of webSearchKeys) {\n if (!getRequiredSecret(entry.key)) {\n registerRequiredSecret({\n key: entry.key,\n label: entry.label,\n description: entry.description,\n docsUrl: entry.docsUrl,\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n }\n\n if (!getRequiredSecret(\"GITHUB_TOKEN\")) {\n registerRequiredSecret({\n key: \"GITHUB_TOKEN\",\n label: \"GitHub token\",\n description:\n \"Enables connector-scoped repository file reads and writes for headless/cloud agent runs.\",\n docsUrl:\n \"https://docs.github.com/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens\",\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n\n if (!getRequiredSecret(\"FIGMA_ACCESS_TOKEN\")) {\n registerRequiredSecret({\n key: \"FIGMA_ACCESS_TOKEN\",\n label: \"Figma access token\",\n description:\n \"Optional fallback for reading Figma file and node context when the hosted Figma MCP server is unavailable. Generate a personal access token with current_user:read and file_content:read.\",\n docsUrl:\n \"https://developers.figma.com/docs/rest-api/personal-access-tokens/\",\n scope: \"user\",\n kind: \"api-key\",\n required: false,\n validator: async (value) => {\n const response = await fetch(\"https://api.figma.com/v1/me\", {\n headers: {\n \"X-Figma-Token\": value,\n \"User-Agent\": \"AgentNative/1.0\",\n },\n });\n return response.ok\n ? { ok: true }\n : {\n ok: false,\n error: `Figma rejected the token (HTTP ${response.status}).`,\n };\n },\n });\n }\n}\n"]}
1
+ {"version":3,"file":"register-framework-secrets.js","sourceRoot":"","sources":["../../src/secrets/register-framework-secrets.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Framework-level secret registrations.\n *\n * Side-effect module — imported by the core-routes plugin at boot so the\n * sidebar settings UI and the `/_agent-native/secrets` list route surface the\n * relevant keys in every template.\n *\n * Each call uses a `getRequiredSecret` guard so a template that has already\n * registered the same key (often with stricter settings like `required: true`)\n * wins — the framework registration is a fallback, not an override.\n *\n * OPENAI_API_KEY is optional framework-wide because it enables the shared\n * realtime speech-to-speech agent mode. Templates can pre-register the same\n * key with stricter requirements; the guard below preserves their definition.\n */\n\nimport { getRequiredSecret, registerRequiredSecret } from \"./register.js\";\n\nexport function registerFrameworkSecrets(): void {\n const workspaceOAuthProviders = [\n {\n id: \"figma\",\n credentialPrefix: \"FIGMA\",\n oauthProvider: \"figma\",\n label: \"Figma\",\n docsUrl: \"https://developers.figma.com/docs/rest-api/oauth-apps/\",\n },\n {\n id: \"google_drive\",\n credentialPrefix: \"GOOGLE\",\n oauthProvider: \"google\",\n label: \"Google Drive\",\n docsUrl:\n \"https://developers.google.com/identity/protocols/oauth2/web-server\",\n },\n {\n id: \"github\",\n credentialPrefix: \"GITHUB\",\n oauthProvider: \"github\",\n label: \"GitHub\",\n docsUrl: \"https://docs.github.com/apps/oauth-apps/building-oauth-apps\",\n },\n {\n id: \"hubspot\",\n credentialPrefix: \"HUBSPOT\",\n oauthProvider: \"hubspot\",\n label: \"HubSpot\",\n docsUrl:\n \"https://developers.hubspot.com/docs/apps/developer-platform/build-apps/authentication/oauth/oauth-quickstart-guide\",\n },\n {\n id: \"salesforce\",\n credentialPrefix: \"SALESFORCE\",\n oauthProvider: \"salesforce\",\n label: \"Salesforce\",\n docsUrl:\n \"https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_web_server_oauth_flow.htm\",\n },\n {\n id: \"jira\",\n credentialPrefix: \"JIRA\",\n oauthProvider: \"jira\",\n label: \"Jira Cloud\",\n docsUrl:\n \"https://developer.atlassian.com/cloud/jira/platform/oauth-2-3lo-apps/\",\n },\n {\n id: \"sentry\",\n credentialPrefix: \"SENTRY\",\n oauthProvider: \"sentry\",\n label: \"Sentry\",\n docsUrl: \"https://docs.sentry.io/api/auth/\",\n },\n {\n id: \"notion\",\n credentialPrefix: \"NOTION\",\n oauthProvider: \"notion\",\n label: \"Notion\",\n docsUrl: \"https://developers.notion.com/docs/authorization\",\n },\n ] as const;\n\n for (const provider of workspaceOAuthProviders) {\n const prefix = provider.credentialPrefix;\n for (const credential of [\n { suffix: \"CLIENT_ID\", label: \"OAuth client ID\" },\n { suffix: \"CLIENT_SECRET\", label: \"OAuth client secret\" },\n ] as const) {\n const key = `${prefix}_${credential.suffix}`;\n if (!getRequiredSecret(key)) {\n registerRequiredSecret({\n key,\n label: `${provider.label} ${credential.label}`,\n description: `Workspace-owned ${provider.label} OAuth application credential. Tokens granted by users are stored separately and encrypted.`,\n docsUrl: provider.docsUrl,\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n }\n\n const connectionKey = `${prefix}_CONNECTED`;\n if (!getRequiredSecret(connectionKey)) {\n registerRequiredSecret({\n key: connectionKey,\n label: `${provider.label} account`,\n description: `Connect a ${provider.label} account for scoped workspace imports.`,\n docsUrl: provider.docsUrl,\n scope: \"user\",\n kind: \"oauth\",\n required: false,\n oauthProvider: provider.oauthProvider,\n oauthConnectUrl: `/_agent-native/connections/oauth/${provider.id}/start`,\n });\n }\n }\n\n if (!getRequiredSecret(\"OPENAI_API_KEY\")) {\n registerRequiredSecret({\n key: \"OPENAI_API_KEY\",\n label: \"OpenAI API key\",\n description:\n \"Optional fallback for realtime voice when Builder is not connected, and for OpenAI transcription.\",\n docsUrl: \"https://platform.openai.com/api-keys\",\n scope: \"user\",\n kind: \"api-key\",\n required: false,\n validator: async (value) => {\n const response = await fetch(\"https://api.openai.com/v1/models\", {\n headers: { Authorization: `Bearer ${value}` },\n });\n return response.ok\n ? { ok: true }\n : {\n ok: false,\n error: `OpenAI rejected the key (HTTP ${response.status}).`,\n };\n },\n });\n }\n\n // PostHog — product analytics, error tracking, and LLM analytics. One key\n // arms all three; `POSTHOG_ERROR_TRACKING=false` opts out of exceptions\n // while keeping analytics.\n if (!getRequiredSecret(\"POSTHOG_API_KEY\")) {\n registerRequiredSecret({\n key: \"POSTHOG_API_KEY\",\n label: \"PostHog project API key\",\n description:\n \"Sends product analytics, server exceptions, and LLM traces to PostHog. Set POSTHOG_HOST for self-hosted or EU projects.\",\n docsUrl: \"https://posthog.com/docs/getting-started/install\",\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n\n // Web-search tool backends — optional; the tool selects the first\n // configured manual key at call time, then falls back to Builder Connect.\n const webSearchKeys: Array<{\n key: string;\n label: string;\n description: string;\n docsUrl: string;\n }> = [\n {\n key: \"BRAVE_SEARCH_API_KEY\",\n label: \"Brave Search API Key\",\n description:\n \"Enables the web-search agent tool via Brave Search. Optional when Builder.io is connected for managed web search.\",\n docsUrl: \"https://brave.com/search/api/\",\n },\n {\n key: \"TAVILY_API_KEY\",\n label: \"Tavily API Key\",\n description:\n \"Enables the web-search agent tool via Tavily. Used as fallback when BRAVE_SEARCH_API_KEY is not set and before Builder-managed search.\",\n docsUrl: \"https://tavily.com/\",\n },\n {\n key: \"EXA_API_KEY\",\n label: \"Exa API Key\",\n description:\n \"Enables the web-search agent tool via Exa. Used as fallback when Brave and Tavily are not set and before Builder-managed search.\",\n docsUrl: \"https://exa.ai/\",\n },\n {\n key: \"FIRECRAWL_API_KEY\",\n label: \"Firecrawl API Key\",\n description:\n \"Enables the web-search agent tool via Firecrawl. Used as fallback when Brave, Tavily, and Exa are not set and before Builder-managed search.\",\n docsUrl: \"https://firecrawl.dev/\",\n },\n ];\n\n for (const entry of webSearchKeys) {\n if (!getRequiredSecret(entry.key)) {\n registerRequiredSecret({\n key: entry.key,\n label: entry.label,\n description: entry.description,\n docsUrl: entry.docsUrl,\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n }\n\n if (!getRequiredSecret(\"GITHUB_TOKEN\")) {\n registerRequiredSecret({\n key: \"GITHUB_TOKEN\",\n label: \"GitHub token\",\n description:\n \"Enables connector-scoped repository file reads and writes for headless/cloud agent runs.\",\n docsUrl:\n \"https://docs.github.com/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens\",\n scope: \"workspace\",\n kind: \"api-key\",\n required: false,\n });\n }\n\n if (!getRequiredSecret(\"FIGMA_ACCESS_TOKEN\")) {\n registerRequiredSecret({\n key: \"FIGMA_ACCESS_TOKEN\",\n label: \"Figma access token\",\n description:\n \"Optional fallback for reading Figma file and node context when the hosted Figma MCP server is unavailable. Generate a personal access token with current_user:read and file_content:read.\",\n docsUrl:\n \"https://developers.figma.com/docs/rest-api/personal-access-tokens/\",\n scope: \"user\",\n kind: \"api-key\",\n required: false,\n validator: async (value) => {\n const response = await fetch(\"https://api.figma.com/v1/me\", {\n headers: {\n \"X-Figma-Token\": value,\n \"User-Agent\": \"AgentNative/1.0\",\n },\n });\n return response.ok\n ? { ok: true }\n : {\n ok: false,\n error: `Figma rejected the token (HTTP ${response.status}).`,\n };\n },\n });\n }\n}\n"]}
@@ -9,6 +9,14 @@ export declare const AGENT_RUN_OWNER_CONTEXT_KEY = "__agentNativeOwnerContext";
9
9
  type AnonymousOwnerResolver = (event: H3Event) => string | null | Promise<string | null>;
10
10
  type OrgIdResolver = (event: H3Event) => string | null | undefined | Promise<string | null | undefined>;
11
11
  export declare function readAgentRunTimezone(event: H3Event): string | undefined;
12
+ /**
13
+ * The caller's browser analytics session id, when the page sent one.
14
+ *
15
+ * Emitted as PostHog's `$session_id` on the run's `$ai_*` events so an agent
16
+ * trace joins to the session replay it happened in. Distinct from
17
+ * `$ai_session_id`, which is the conversation thread.
18
+ */
19
+ export declare function readAgentRunBrowserSessionId(event: H3Event): string | undefined;
12
20
  export declare function seedAgentRunOwnerContext(event: H3Event, ownerContext: AgentRunOwnerContext): AgentRunOwnerContext;
13
21
  export declare function seedBackgroundAgentRunOwnerContext(event: H3Event, runId: string): Promise<AgentRunOwnerContext | null>;
14
22
  export declare function resolveAgentRunOwnerContext(event: H3Event, options?: {
@@ -1 +1 @@
1
- {"version":3,"file":"agent-run-context.d.ts","sourceRoot":"","sources":["../../src/server/agent-run-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,OAAO,EAAE,MAAM,IAAI,CAAC;AAI1D,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,2BAA2B,8BAA8B,CAAC;AAMvE,KAAK,sBAAsB,GAAG,CAC5B,KAAK,EAAE,OAAO,KACX,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAE5C,KAAK,aAAa,GAAG,CACnB,KAAK,EAAE,OAAO,KACX,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;AA2CpE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAQvE;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,YAAY,EAAE,oBAAoB,GACjC,oBAAoB,CAItB;AAED,wBAAsB,kCAAkC,CACtD,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAStC;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,OAAO,EACd,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,sBAAsB,CAAA;CAAO,GACxD,OAAO,CAAC,oBAAoB,CAAC,CA4B/B;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAClD,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,oBAAoB,CAAC;IACnC,YAAY,CAAC,EAAE,aAAa,CAAC;CAC9B,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAsC9B;AAED,wBAAsB,6BAA6B,CAAC,OAAO,EAAE;IAC3D,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,oBAAoB,CAAC;IACnC,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,GAAG,OAAO,CAAC,cAAc,CAAC,CAe1B;AAED,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,OAAO,EAAE;IACP,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,oBAAoB,CAAC;IACnC,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,EACD,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,CAAC,CAAC,CAGZ"}
1
+ {"version":3,"file":"agent-run-context.d.ts","sourceRoot":"","sources":["../../src/server/agent-run-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,OAAO,EAAE,MAAM,IAAI,CAAC;AAI1D,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,2BAA2B,8BAA8B,CAAC;AAMvE,KAAK,sBAAsB,GAAG,CAC5B,KAAK,EAAE,OAAO,KACX,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAE5C,KAAK,aAAa,GAAG,CACnB,KAAK,EAAE,OAAO,KACX,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;AA2CpE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAQvE;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,OAAO,GACb,MAAM,GAAG,SAAS,CAQpB;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,YAAY,EAAE,oBAAoB,GACjC,oBAAoB,CAItB;AAED,wBAAsB,kCAAkC,CACtD,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAStC;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,OAAO,EACd,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,sBAAsB,CAAA;CAAO,GACxD,OAAO,CAAC,oBAAoB,CAAC,CA4B/B;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAClD,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,oBAAoB,CAAC;IACnC,YAAY,CAAC,EAAE,aAAa,CAAC;CAC9B,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAsC9B;AAED,wBAAsB,6BAA6B,CAAC,OAAO,EAAE;IAC3D,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,oBAAoB,CAAC;IACnC,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,GAAG,OAAO,CAAC,cAAc,CAAC,CAiB1B;AAED,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,OAAO,EAAE;IACP,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,oBAAoB,CAAC;IACnC,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,EACD,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACvB,OAAO,CAAC,CAAC,CAAC,CAGZ"}
@@ -44,6 +44,22 @@ export function readAgentRunTimezone(event) {
44
44
  ? value.trim()
45
45
  : undefined;
46
46
  }
47
+ /**
48
+ * The caller's browser analytics session id, when the page sent one.
49
+ *
50
+ * Emitted as PostHog's `$session_id` on the run's `$ai_*` events so an agent
51
+ * trace joins to the session replay it happened in. Distinct from
52
+ * `$ai_session_id`, which is the conversation thread.
53
+ */
54
+ export function readAgentRunBrowserSessionId(event) {
55
+ const raw = readHeaderValue(event, "x-agent-native-session-id");
56
+ const value = Array.isArray(raw) ? raw[0] : raw;
57
+ return typeof value === "string" &&
58
+ value.trim().length > 0 &&
59
+ value.trim().length < 128
60
+ ? value.trim()
61
+ : undefined;
62
+ }
47
63
  export function seedAgentRunOwnerContext(event, ownerContext) {
48
64
  eventContext(event)[AGENT_RUN_OWNER_CONTEXT_KEY] =
49
65
  ownerContext;
@@ -124,6 +140,7 @@ export async function resolveAgentRunOrgId(options) {
124
140
  export async function resolveAgentRunRequestContext(options) {
125
141
  const orgId = await resolveAgentRunOrgId(options);
126
142
  const timezone = readAgentRunTimezone(options.event);
143
+ const browserSessionId = readAgentRunBrowserSessionId(options.event);
127
144
  const waitUntil = requestWaitUntil(options.event);
128
145
  const run = {
129
146
  ...(options.isBackgroundWorker ? { isBackgroundWorker: true } : {}),
@@ -134,6 +151,7 @@ export async function resolveAgentRunRequestContext(options) {
134
151
  userName: options.ownerContext.name,
135
152
  orgId,
136
153
  timezone,
154
+ ...(browserSessionId ? { browserSessionId } : {}),
137
155
  ...(Object.keys(run).length > 0 ? { run } : {}),
138
156
  };
139
157
  }