@smthrs/observability 0.35.0 → 1.0.0-rc.4

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 (363) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/LICENSE +1 -1
  3. package/README.md +84 -0
  4. package/dist/cjs/BrowserOtel.d.ts +37 -0
  5. package/dist/cjs/BrowserOtel.d.ts.map +1 -0
  6. package/dist/cjs/BrowserOtel.js +47 -0
  7. package/dist/cjs/BrowserOtel.js.map +7 -0
  8. package/dist/cjs/Endpoint.d.ts +70 -0
  9. package/dist/cjs/Endpoint.d.ts.map +1 -0
  10. package/dist/cjs/Endpoint.js +85 -0
  11. package/dist/cjs/Endpoint.js.map +7 -0
  12. package/dist/cjs/JournalLogger.d.ts +232 -0
  13. package/dist/cjs/JournalLogger.d.ts.map +1 -0
  14. package/dist/cjs/JournalLogger.js +388 -0
  15. package/dist/cjs/JournalLogger.js.map +7 -0
  16. package/dist/cjs/Logger.d.ts +55 -0
  17. package/dist/cjs/Logger.d.ts.map +1 -0
  18. package/dist/cjs/Logger.js +72 -0
  19. package/dist/cjs/Logger.js.map +7 -0
  20. package/dist/cjs/Metric.d.ts +67 -0
  21. package/dist/cjs/Metric.d.ts.map +1 -0
  22. package/dist/cjs/Metric.js +68 -0
  23. package/dist/cjs/Metric.js.map +7 -0
  24. package/dist/cjs/NodeOtel.d.ts +42 -0
  25. package/dist/cjs/NodeOtel.d.ts.map +1 -0
  26. package/dist/cjs/NodeOtel.js +78 -0
  27. package/dist/cjs/NodeOtel.js.map +7 -0
  28. package/dist/cjs/Otel.d.ts +62 -0
  29. package/dist/cjs/Otel.d.ts.map +1 -0
  30. package/dist/cjs/Otel.js +75 -0
  31. package/dist/cjs/Otel.js.map +7 -0
  32. package/dist/cjs/Otlp.d.ts +200 -0
  33. package/dist/cjs/Otlp.d.ts.map +1 -0
  34. package/dist/cjs/Otlp.js +235 -0
  35. package/dist/cjs/Otlp.js.map +7 -0
  36. package/dist/cjs/Resource.d.ts +162 -0
  37. package/dist/cjs/Resource.d.ts.map +1 -0
  38. package/dist/cjs/Resource.js +186 -0
  39. package/dist/cjs/Resource.js.map +7 -0
  40. package/dist/cjs/index.d.ts +61 -0
  41. package/dist/cjs/index.d.ts.map +1 -0
  42. package/dist/cjs/index.js +47 -0
  43. package/dist/cjs/index.js.map +7 -0
  44. package/dist/cjs/internal/schemaIssuePath.d.ts +31 -0
  45. package/dist/cjs/internal/schemaIssuePath.d.ts.map +1 -0
  46. package/dist/cjs/internal/schemaIssuePath.js +49 -0
  47. package/dist/cjs/internal/schemaIssuePath.js.map +7 -0
  48. package/dist/cjs/package.json +1 -0
  49. package/dist/esm/BrowserOtel.d.ts +37 -0
  50. package/dist/esm/BrowserOtel.d.ts.map +1 -0
  51. package/dist/esm/BrowserOtel.js +24 -0
  52. package/dist/esm/BrowserOtel.js.map +1 -0
  53. package/dist/esm/Endpoint.d.ts +70 -0
  54. package/dist/esm/Endpoint.d.ts.map +1 -0
  55. package/dist/esm/Endpoint.js +110 -0
  56. package/dist/esm/Endpoint.js.map +1 -0
  57. package/dist/esm/JournalLogger.d.ts +232 -0
  58. package/dist/esm/JournalLogger.d.ts.map +1 -0
  59. package/dist/esm/JournalLogger.js +482 -0
  60. package/dist/esm/JournalLogger.js.map +1 -0
  61. package/dist/esm/Logger.d.ts +55 -0
  62. package/dist/esm/Logger.d.ts.map +1 -0
  63. package/dist/esm/Logger.js +60 -0
  64. package/dist/esm/Logger.js.map +1 -0
  65. package/dist/esm/Metric.d.ts +67 -0
  66. package/dist/esm/Metric.d.ts.map +1 -0
  67. package/dist/esm/Metric.js +80 -0
  68. package/dist/esm/Metric.js.map +1 -0
  69. package/dist/esm/NodeOtel.d.ts +42 -0
  70. package/dist/esm/NodeOtel.d.ts.map +1 -0
  71. package/dist/esm/NodeOtel.js +56 -0
  72. package/dist/esm/NodeOtel.js.map +1 -0
  73. package/dist/esm/Otel.d.ts +62 -0
  74. package/dist/esm/Otel.d.ts.map +1 -0
  75. package/dist/esm/Otel.js +51 -0
  76. package/dist/esm/Otel.js.map +1 -0
  77. package/dist/esm/Otlp.d.ts +200 -0
  78. package/dist/esm/Otlp.d.ts.map +1 -0
  79. package/dist/esm/Otlp.js +350 -0
  80. package/dist/esm/Otlp.js.map +1 -0
  81. package/dist/esm/Resource.d.ts +162 -0
  82. package/dist/esm/Resource.d.ts.map +1 -0
  83. package/dist/esm/Resource.js +237 -0
  84. package/dist/esm/Resource.js.map +1 -0
  85. package/dist/esm/index.d.ts +61 -0
  86. package/dist/esm/index.d.ts.map +1 -0
  87. package/dist/esm/index.js +61 -0
  88. package/dist/esm/index.js.map +1 -0
  89. package/dist/esm/internal/schemaIssuePath.d.ts +31 -0
  90. package/dist/esm/internal/schemaIssuePath.d.ts.map +1 -0
  91. package/dist/esm/internal/schemaIssuePath.js +59 -0
  92. package/dist/esm/internal/schemaIssuePath.js.map +1 -0
  93. package/docs/README.md +162 -0
  94. package/docs/api.md +768 -0
  95. package/docs/concepts/instrumentation-and-export.md +68 -0
  96. package/docs/concepts/layer-map.md +72 -0
  97. package/docs/concepts/validated-acquisition.md +105 -0
  98. package/docs/guides/export-to-a-collector.md +167 -0
  99. package/docs/guides/forward-logs-to-the-journal.md +226 -0
  100. package/docs/guides/install-a-logger.md +111 -0
  101. package/docs/guides/read-runtime-metrics.md +83 -0
  102. package/docs/guides/testing.md +134 -0
  103. package/docs/guides/wire-an-opentelemetry-sdk.md +220 -0
  104. package/docs/installation.md +98 -0
  105. package/docs/quickstart.md +145 -0
  106. package/docs/troubleshooting.md +168 -0
  107. package/package.json +221 -32
  108. package/src/BrowserOtel.ts +51 -0
  109. package/src/Endpoint.ts +131 -0
  110. package/src/JournalLogger.ts +596 -0
  111. package/src/Logger.ts +106 -0
  112. package/src/Metric.ts +88 -0
  113. package/src/NodeOtel.ts +90 -0
  114. package/src/Otel.ts +117 -0
  115. package/src/Otlp.ts +477 -0
  116. package/src/Resource.ts +324 -0
  117. package/src/index.ts +67 -0
  118. package/src/internal/schemaIssuePath.ts +65 -0
  119. package/docker-compose.otel.yml +0 -104
  120. package/grafana/dashboards/smithers-dashboard.json +0 -453
  121. package/grafana/provisioning/dashboards/dashboards.yml +0 -12
  122. package/grafana/provisioning/datasources/datasources.yml +0 -49
  123. package/loki/loki-config.yaml +0 -35
  124. package/otel-collector-config.yml +0 -38
  125. package/prometheus/prometheus.yml +0 -8
  126. package/src/MetricName.ts +0 -1
  127. package/src/MetricsServiceLive.js +0 -9
  128. package/src/README.md +0 -28
  129. package/src/ResolvedSmithersObservabilityOptions.ts +0 -12
  130. package/src/SmithersEvent.ts +0 -843
  131. package/src/SmithersLogFormat.ts +0 -1
  132. package/src/SmithersMetricDefinition.ts +0 -15
  133. package/src/SmithersMetricType.ts +0 -1
  134. package/src/SmithersMetricUnit.ts +0 -1
  135. package/src/SmithersObservability.js +0 -15
  136. package/src/SmithersObservabilityOptions.ts +0 -12
  137. package/src/SmithersObservabilityService.ts +0 -13
  138. package/src/_coreCorrelation/CorrelationContext.ts +0 -10
  139. package/src/_coreCorrelation/CorrelationContextLive.js +0 -11
  140. package/src/_coreCorrelation/CorrelationContextService.js +0 -15
  141. package/src/_coreCorrelation/CorrelationContextServiceShape.ts +0 -12
  142. package/src/_coreCorrelation/CorrelationPatch.ts +0 -3
  143. package/src/_coreCorrelation/README.md +0 -20
  144. package/src/_coreCorrelation/_correlationStorage.js +0 -4
  145. package/src/_coreCorrelation/correlationContextFiberRef.js +0 -5
  146. package/src/_coreCorrelation/correlationContextToLogAnnotations.js +0 -18
  147. package/src/_coreCorrelation/getCurrentCorrelationContext.js +0 -9
  148. package/src/_coreCorrelation/getCurrentCorrelationContextEffect.js +0 -11
  149. package/src/_coreCorrelation/index.js +0 -14
  150. package/src/_coreCorrelation/mergeCorrelationContext.js +0 -51
  151. package/src/_coreCorrelation/runWithCorrelationContext.js +0 -14
  152. package/src/_coreCorrelation/updateCurrentCorrelationContext.js +0 -17
  153. package/src/_coreCorrelation/withCorrelationContext.js +0 -38
  154. package/src/_coreCorrelation/withCurrentCorrelationContext.js +0 -11
  155. package/src/_coreMetrics.js +0 -14
  156. package/src/_coreMetricsShape.ts +0 -44
  157. package/src/_corePrometheus.js +0 -91
  158. package/src/_corePrometheusShape.ts +0 -11
  159. package/src/_coreTracing.js +0 -132
  160. package/src/_coreTracingShape.ts +0 -17
  161. package/src/_otelLogBuilders.js +0 -102
  162. package/src/_sessionFileResolvers.js +0 -164
  163. package/src/_smithersSpanAttributeAliases.js +0 -19
  164. package/src/_smithersTraceSpanStorage.js +0 -3
  165. package/src/_traceEventNormalizers.js +0 -499
  166. package/src/_traceRedaction.js +0 -162
  167. package/src/agentSessionEventToOtelLogRecord.js +0 -55
  168. package/src/agentTrace.ts +0 -144
  169. package/src/agentTraceCapabilities.js +0 -151
  170. package/src/annotateSmithersTrace.js +0 -11
  171. package/src/canonicalTraceEventToOtelLogRecord.js +0 -55
  172. package/src/correlation.js +0 -56
  173. package/src/createSmithersObservabilityLayer.js +0 -59
  174. package/src/createSmithersOtelLayer.js +0 -23
  175. package/src/createSmithersRuntimeLayer.js +0 -2
  176. package/src/detectAgentFamily.js +0 -26
  177. package/src/detectCaptureMode.js +0 -29
  178. package/src/emitOtelLogRecord.js +0 -19
  179. package/src/getCurrentSmithersTraceAnnotations.js +0 -14
  180. package/src/getCurrentSmithersTraceSpan.js +0 -7
  181. package/src/index.d.ts +0 -1392
  182. package/src/index.js +0 -137
  183. package/src/kindPhase.js +0 -17
  184. package/src/logging.js +0 -264
  185. package/src/makeSmithersSpanAttributes.js +0 -20
  186. package/src/metrics/README.md +0 -22
  187. package/src/metrics/SmithersMetricDefinition.ts +0 -17
  188. package/src/metrics/SmithersMetricType.ts +0 -1
  189. package/src/metrics/SmithersMetricUnit.ts +0 -1
  190. package/src/metrics/_asyncExternalWaitCounts.js +0 -4
  191. package/src/metrics/_buckets.js +0 -37
  192. package/src/metrics/_incrementGauge.js +0 -11
  193. package/src/metrics/_processStartMs.js +0 -1
  194. package/src/metrics/activeNodes.js +0 -2
  195. package/src/metrics/activeRuns.js +0 -2
  196. package/src/metrics/agentActionsTotal.js +0 -2
  197. package/src/metrics/agentDurationMs.js +0 -3
  198. package/src/metrics/agentErrorsTotal.js +0 -2
  199. package/src/metrics/agentEventsTotal.js +0 -2
  200. package/src/metrics/agentInvocationsTotal.js +0 -2
  201. package/src/metrics/agentRetriesTotal.js +0 -2
  202. package/src/metrics/agentSessionsTotal.js +0 -2
  203. package/src/metrics/agentTokensTotal.js +0 -2
  204. package/src/metrics/alertDeliveriesAttempted.js +0 -2
  205. package/src/metrics/alertDeliveriesSuppressed.js +0 -2
  206. package/src/metrics/alertsAcknowledgedTotal.js +0 -2
  207. package/src/metrics/alertsActive.js +0 -2
  208. package/src/metrics/alertsEscalatedTotal.js +0 -2
  209. package/src/metrics/alertsFiredTotal.js +0 -2
  210. package/src/metrics/alertsReopenedTotal.js +0 -2
  211. package/src/metrics/alertsResolvedTotal.js +0 -2
  212. package/src/metrics/alertsSilencedTotal.js +0 -2
  213. package/src/metrics/approvalPending.js +0 -2
  214. package/src/metrics/approvalWaitDuration.js +0 -5
  215. package/src/metrics/approvalsDenied.js +0 -2
  216. package/src/metrics/approvalsGranted.js +0 -2
  217. package/src/metrics/approvalsRequested.js +0 -2
  218. package/src/metrics/attemptDuration.js +0 -3
  219. package/src/metrics/attentionBacklog.js +0 -2
  220. package/src/metrics/cacheHits.js +0 -2
  221. package/src/metrics/cacheMisses.js +0 -2
  222. package/src/metrics/dbQueryDuration.js +0 -3
  223. package/src/metrics/dbRetries.js +0 -2
  224. package/src/metrics/dbTransactionDuration.js +0 -3
  225. package/src/metrics/dbTransactionRetries.js +0 -2
  226. package/src/metrics/dbTransactionRollbacks.js +0 -2
  227. package/src/metrics/devtoolsActiveSubscribers.js +0 -2
  228. package/src/metrics/devtoolsBackpressureDisconnectTotal.js +0 -2
  229. package/src/metrics/devtoolsDeltaBuildMs.js +0 -3
  230. package/src/metrics/devtoolsEventBytes.js +0 -3
  231. package/src/metrics/devtoolsEventTotal.js +0 -2
  232. package/src/metrics/devtoolsSnapshotBuildMs.js +0 -5
  233. package/src/metrics/devtoolsSubscribeTotal.js +0 -2
  234. package/src/metrics/errorsTotal.js +0 -2
  235. package/src/metrics/eventsEmittedTotal.js +0 -2
  236. package/src/metrics/externalWaitAsyncPending.js +0 -2
  237. package/src/metrics/gatewayApprovalDecisionsTotal.js +0 -2
  238. package/src/metrics/gatewayAuthEventsTotal.js +0 -2
  239. package/src/metrics/gatewayConnectionsActive.js +0 -2
  240. package/src/metrics/gatewayConnectionsClosedTotal.js +0 -2
  241. package/src/metrics/gatewayConnectionsTotal.js +0 -2
  242. package/src/metrics/gatewayCronTriggersTotal.js +0 -2
  243. package/src/metrics/gatewayErrorsTotal.js +0 -2
  244. package/src/metrics/gatewayHeartbeatTicksTotal.js +0 -2
  245. package/src/metrics/gatewayMessagesReceivedTotal.js +0 -2
  246. package/src/metrics/gatewayMessagesSentTotal.js +0 -2
  247. package/src/metrics/gatewayRpcCallsTotal.js +0 -2
  248. package/src/metrics/gatewayRpcDuration.js +0 -3
  249. package/src/metrics/gatewayRunEventBackpressureDisconnectTotal.js +0 -4
  250. package/src/metrics/gatewayRunsCompletedTotal.js +0 -2
  251. package/src/metrics/gatewayRunsStartedTotal.js +0 -2
  252. package/src/metrics/gatewaySignalsTotal.js +0 -2
  253. package/src/metrics/gatewayWebhooksReceivedTotal.js +0 -2
  254. package/src/metrics/gatewayWebhooksRejectedTotal.js +0 -2
  255. package/src/metrics/gatewayWebhooksVerifiedTotal.js +0 -2
  256. package/src/metrics/heartbeatDataSizeBytes.js +0 -5
  257. package/src/metrics/heartbeatIntervalMs.js +0 -3
  258. package/src/metrics/hotReloadDuration.js +0 -3
  259. package/src/metrics/hotReloadFailures.js +0 -2
  260. package/src/metrics/hotReloads.js +0 -2
  261. package/src/metrics/httpRequestDuration.js +0 -3
  262. package/src/metrics/httpRequests.js +0 -2
  263. package/src/metrics/index.d.ts +0 -1222
  264. package/src/metrics/index.js +0 -168
  265. package/src/metrics/memoryFactReads.js +0 -3
  266. package/src/metrics/memoryFactWrites.js +0 -3
  267. package/src/metrics/memoryMessageSaves.js +0 -3
  268. package/src/metrics/memoryRecallDuration.js +0 -11
  269. package/src/metrics/memoryRecallQueries.js +0 -3
  270. package/src/metrics/metricsServiceAdapter.js +0 -181
  271. package/src/metrics/nodeDuration.js +0 -3
  272. package/src/metrics/nodeRetriesTotal.js +0 -2
  273. package/src/metrics/nodesFailed.js +0 -2
  274. package/src/metrics/nodesFinished.js +0 -2
  275. package/src/metrics/nodesStarted.js +0 -2
  276. package/src/metrics/openApiToolCallErrorsTotal.js +0 -3
  277. package/src/metrics/openApiToolCallsTotal.js +0 -3
  278. package/src/metrics/openApiToolDuration.js +0 -9
  279. package/src/metrics/processHeapUsedBytes.js +0 -2
  280. package/src/metrics/processMemoryRssBytes.js +0 -2
  281. package/src/metrics/processUptimeSeconds.js +0 -2
  282. package/src/metrics/promptSizeBytes.js +0 -3
  283. package/src/metrics/replaysStarted.js +0 -3
  284. package/src/metrics/responseSizeBytes.js +0 -3
  285. package/src/metrics/rewindDurationMs.js +0 -3
  286. package/src/metrics/rewindFramesDeleted.js +0 -3
  287. package/src/metrics/rewindRollbackTotal.js +0 -2
  288. package/src/metrics/rewindSandboxesReverted.js +0 -3
  289. package/src/metrics/rewindTotal.js +0 -2
  290. package/src/metrics/runDuration.js +0 -3
  291. package/src/metrics/runForksCreated.js +0 -3
  292. package/src/metrics/runsAncestryDepth.js +0 -3
  293. package/src/metrics/runsCancelledTotal.js +0 -2
  294. package/src/metrics/runsCarriedStateBytes.js +0 -5
  295. package/src/metrics/runsContinuedTotal.js +0 -2
  296. package/src/metrics/runsFailedTotal.js +0 -2
  297. package/src/metrics/runsFinishedTotal.js +0 -2
  298. package/src/metrics/runsResumedTotal.js +0 -2
  299. package/src/metrics/runsTotal.js +0 -2
  300. package/src/metrics/sandboxActive.js +0 -2
  301. package/src/metrics/sandboxBundleSizeBytes.js +0 -5
  302. package/src/metrics/sandboxCompletedTotal.js +0 -2
  303. package/src/metrics/sandboxCreatedTotal.js +0 -2
  304. package/src/metrics/sandboxDurationMs.js +0 -3
  305. package/src/metrics/sandboxPatchCount.js +0 -3
  306. package/src/metrics/sandboxTransportDurationMs.js +0 -5
  307. package/src/metrics/schedulerConcurrencyUtilization.js +0 -2
  308. package/src/metrics/schedulerQueueDepth.js +0 -2
  309. package/src/metrics/schedulerWaitDuration.js +0 -5
  310. package/src/metrics/scorerDuration.js +0 -9
  311. package/src/metrics/scorerEventsFailed.js +0 -2
  312. package/src/metrics/scorerEventsFinished.js +0 -2
  313. package/src/metrics/scorerEventsStarted.js +0 -2
  314. package/src/metrics/scorersFailed.js +0 -3
  315. package/src/metrics/scorersFinished.js +0 -3
  316. package/src/metrics/scorersStarted.js +0 -3
  317. package/src/metrics/smithersMetricCatalog.js +0 -893
  318. package/src/metrics/smithersMetricCatalogByKey.js +0 -2
  319. package/src/metrics/smithersMetricCatalogByName.js +0 -2
  320. package/src/metrics/smithersMetricCatalogByPrometheusName.js +0 -4
  321. package/src/metrics/snapshotDuration.js +0 -9
  322. package/src/metrics/snapshotsCaptured.js +0 -3
  323. package/src/metrics/supervisorPollDuration.js +0 -5
  324. package/src/metrics/supervisorPollsTotal.js +0 -2
  325. package/src/metrics/supervisorResumeLag.js +0 -5
  326. package/src/metrics/supervisorResumedTotal.js +0 -2
  327. package/src/metrics/supervisorSkippedTotal.js +0 -2
  328. package/src/metrics/supervisorStaleDetected.js +0 -2
  329. package/src/metrics/taskHeartbeatTimeoutTotal.js +0 -2
  330. package/src/metrics/taskHeartbeatsTotal.js +0 -2
  331. package/src/metrics/timerDelayDuration.js +0 -3
  332. package/src/metrics/timersCancelled.js +0 -2
  333. package/src/metrics/timersCreated.js +0 -2
  334. package/src/metrics/timersFired.js +0 -2
  335. package/src/metrics/timersPending.js +0 -2
  336. package/src/metrics/toPrometheusMetricName.js +0 -8
  337. package/src/metrics/tokensCacheReadTotal.js +0 -2
  338. package/src/metrics/tokensCacheWriteTotal.js +0 -2
  339. package/src/metrics/tokensContextWindowBucketTotal.js +0 -2
  340. package/src/metrics/tokensContextWindowPerCall.js +0 -5
  341. package/src/metrics/tokensInputPerCall.js +0 -3
  342. package/src/metrics/tokensInputTotal.js +0 -2
  343. package/src/metrics/tokensOutputPerCall.js +0 -3
  344. package/src/metrics/tokensOutputTotal.js +0 -2
  345. package/src/metrics/tokensReasoningTotal.js +0 -2
  346. package/src/metrics/toolCallErrorsTotal.js +0 -2
  347. package/src/metrics/toolCallsTotal.js +0 -2
  348. package/src/metrics/toolDuration.js +0 -3
  349. package/src/metrics/toolOutputTruncatedTotal.js +0 -2
  350. package/src/metrics/trackEvent.js +0 -608
  351. package/src/metrics/updateAsyncExternalWaitPending.js +0 -18
  352. package/src/metrics/updateProcessMetrics.js +0 -20
  353. package/src/metrics/vcsDuration.js +0 -3
  354. package/src/normalizeStructuredEvent.js +0 -15
  355. package/src/prometheusContentType.js +0 -1
  356. package/src/renderPrometheusMetrics.js +0 -212
  357. package/src/resolveAgentTraceCapabilities.js +0 -59
  358. package/src/resolveSmithersObservabilityOptions.js +0 -109
  359. package/src/smithersMetrics.js +0 -2
  360. package/src/smithersSpanNames.js +0 -6
  361. package/src/unsupportedKindsForCapabilities.js +0 -32
  362. package/src/withSmithersSpan.js +0 -17
  363. package/tempo/tempo.yml +0 -17
@@ -1,499 +0,0 @@
1
- /**
2
- * @typedef {import('./agentTrace.ts').AgentFamily} AgentFamily
3
- * @typedef {import('./agentTrace.ts').CanonicalAgentTraceEventKind} CanonicalAgentTraceEventKind
4
- *
5
- * @typedef {"message" | "tool" | "pi" | "none"} PayloadKind
6
- *
7
- * @typedef {{
8
- * kind: CanonicalAgentTraceEventKind;
9
- * payloadKind: PayloadKind;
10
- * expect?: CanonicalAgentTraceEventKind;
11
- * }} MappedStructuredEvent
12
- *
13
- * @typedef {{
14
- * kind: CanonicalAgentTraceEventKind;
15
- * payload: Record<string, unknown> | null;
16
- * raw: unknown;
17
- * rawType?: string;
18
- * observed?: boolean;
19
- * }} NormalizedTraceEvent
20
- *
21
- * @typedef {{
22
- * events: NormalizedTraceEvent[];
23
- * expectedKinds?: CanonicalAgentTraceEventKind[];
24
- * }} NormalizedTraceBatch
25
- */
26
-
27
- /**
28
- * @param {unknown} value
29
- * @returns {string | undefined}
30
- */
31
- function extractTextFromJsonValue(value) {
32
- if (typeof value === "string") return value;
33
- if (Array.isArray(value)) {
34
- const text = value.map((item) => extractTextFromJsonValue(item) ?? "").join("");
35
- return text || undefined;
36
- }
37
- if (!value || typeof value !== "object") return undefined;
38
- const record = /** @type {Record<string, unknown>} */ (value);
39
- if (typeof record.text === "string") return record.text;
40
- if (typeof record.content === "string") return record.content;
41
- if (typeof record.output_text === "string") return record.output_text;
42
- if (Array.isArray(record.content)) {
43
- const text = record.content.map((part) => extractTextFromJsonValue(part) ?? "").join("");
44
- if (text) return text;
45
- }
46
- if (record.type === "text" && record.part) return extractTextFromJsonValue(record.part);
47
- for (const field of ["response", "message", "result", "output", "data", "item"]) {
48
- const text = extractTextFromJsonValue(record[field]);
49
- if (text) return text;
50
- }
51
- return undefined;
52
- }
53
-
54
- /** @type {Record<string, ReadonlyArray<ReadonlyArray<string>>>} */
55
- const _usageFieldAliases = {
56
- inputTokens: [
57
- ["inputTokens"],
58
- ["promptTokens"],
59
- ["prompt_tokens"],
60
- ["input_tokens"],
61
- ["input"],
62
- ["models", "gemini", "tokens", "input"],
63
- ],
64
- outputTokens: [
65
- ["outputTokens"],
66
- ["completionTokens"],
67
- ["completion_tokens"],
68
- ["output_tokens"],
69
- ["output"],
70
- ["models", "gemini", "tokens", "output"],
71
- ],
72
- cacheReadTokens: [
73
- ["cacheReadTokens"],
74
- ["cache_read_input_tokens"],
75
- ["cached_input_tokens"],
76
- ["cache_read_tokens"],
77
- ["inputTokenDetails", "cacheReadTokens"],
78
- ],
79
- cacheWriteTokens: [
80
- ["cacheWriteTokens"],
81
- ["cache_write_input_tokens"],
82
- ["cache_creation_input_tokens"],
83
- ["cache_write_tokens"],
84
- ["inputTokenDetails", "cacheWriteTokens"],
85
- ],
86
- reasoningTokens: [["reasoningTokens"], ["reasoning_tokens"], ["outputTokenDetails", "reasoningTokens"]],
87
- totalTokens: [["totalTokens"], ["total_tokens"]],
88
- };
89
-
90
- /**
91
- * @param {unknown} value
92
- * @param {ReadonlyArray<string>} path
93
- * @returns {unknown}
94
- */
95
- function _readUsagePath(value, path) {
96
- let current = value;
97
- for (const segment of path) {
98
- if (!current || typeof current !== "object") return undefined;
99
- current = /** @type {Record<string, unknown>} */ (current)[segment];
100
- }
101
- return current;
102
- }
103
-
104
- /**
105
- * @param {unknown} usage
106
- * @returns {Record<string, number> | null}
107
- */
108
- function normalizeTokenUsage(usage) {
109
- if (!usage || typeof usage !== "object") return null;
110
- /** @type {Record<string, number>} */
111
- const normalized = {};
112
- for (const [field, aliases] of Object.entries(_usageFieldAliases)) {
113
- for (const path of aliases) {
114
- const value = _readUsagePath(usage, path);
115
- if (typeof value === "number") {
116
- normalized[field] = value;
117
- break;
118
- }
119
- }
120
- }
121
- return Object.values(normalized).some((v) => Number.isFinite(v) && v > 0) ? normalized : null;
122
- }
123
-
124
- /** @type {Record<string, MappedStructuredEvent>} */
125
- const piSimpleEventMap = {
126
- session: { kind: "session.start", payloadKind: "pi" },
127
- agent_start: { kind: "session.start", payloadKind: "pi" },
128
- agent_end: { kind: "session.end", payloadKind: "pi" },
129
- turn_start: { kind: "turn.start", payloadKind: "pi", expect: "turn.end" },
130
- message_start: { kind: "message.start", payloadKind: "pi" },
131
- tool_execution_start: { kind: "tool.execution.start", payloadKind: "tool", expect: "tool.execution.end" },
132
- tool_execution_update: { kind: "tool.execution.update", payloadKind: "tool", expect: "tool.execution.end" },
133
- tool_execution_end: { kind: "tool.execution.end", payloadKind: "tool" },
134
- auto_compaction_start: { kind: "compaction.start", payloadKind: "pi" },
135
- auto_compaction_end: { kind: "compaction.end", payloadKind: "pi" },
136
- auto_retry_start: { kind: "retry.start", payloadKind: "pi" },
137
- auto_retry_end: { kind: "retry.end", payloadKind: "pi" },
138
- };
139
-
140
- /** @type {Record<string, MappedStructuredEvent>} */
141
- const genericStructuredEventMap = {
142
- message_start: { kind: "message.start", payloadKind: "message" },
143
- assistant_message_start: { kind: "message.start", payloadKind: "message" },
144
- "response.started": { kind: "message.start", payloadKind: "message" },
145
- tool_call_start: { kind: "tool.execution.start", payloadKind: "tool", expect: "tool.execution.end" },
146
- tool_execution_start: { kind: "tool.execution.start", payloadKind: "tool", expect: "tool.execution.end" },
147
- "tool_call.started": { kind: "tool.execution.start", payloadKind: "tool", expect: "tool.execution.end" },
148
- tool_call_delta: { kind: "tool.execution.update", payloadKind: "tool", expect: "tool.execution.end" },
149
- tool_call_update: { kind: "tool.execution.update", payloadKind: "tool", expect: "tool.execution.end" },
150
- tool_execution_update: { kind: "tool.execution.update", payloadKind: "tool", expect: "tool.execution.end" },
151
- "tool_call.delta": { kind: "tool.execution.update", payloadKind: "tool", expect: "tool.execution.end" },
152
- tool_call_end: { kind: "tool.execution.end", payloadKind: "tool" },
153
- tool_execution_end: { kind: "tool.execution.end", payloadKind: "tool" },
154
- "tool_call.completed": { kind: "tool.execution.end", payloadKind: "tool" },
155
- tool_result: { kind: "tool.result", payloadKind: "tool" },
156
- "tool_result.completed": { kind: "tool.result", payloadKind: "tool" },
157
- };
158
-
159
- /**
160
- * @param {any} parsed
161
- * @returns {string | undefined}
162
- */
163
- function extractGenericDeltaText(parsed) {
164
- const candidates = [
165
- parsed?.delta?.text,
166
- parsed?.delta,
167
- parsed?.text,
168
- parsed?.content_block?.text,
169
- parsed?.contentBlock?.text,
170
- parsed?.message?.text,
171
- parsed?.message?.content,
172
- parsed?.output_text,
173
- ];
174
- for (const candidate of candidates) {
175
- if (typeof candidate === "string" && candidate) return candidate;
176
- }
177
- return undefined;
178
- }
179
-
180
- /**
181
- * @param {any} parsed
182
- * @returns {string | undefined}
183
- */
184
- function extractGenericMessageText(parsed) {
185
- return extractTextFromJsonValue(parsed?.message ?? parsed?.response ?? parsed?.item ?? parsed);
186
- }
187
-
188
- /**
189
- * @param {any} parsed
190
- * @returns {Record<string, unknown>}
191
- */
192
- function extractGenericMessagePayload(parsed) {
193
- /** @type {Record<string, unknown>} */
194
- const payload = {};
195
- const role = parsed?.message?.role ?? parsed?.role ?? parsed?.response?.role;
196
- if (typeof role === "string") payload.role = role;
197
- const text = extractGenericMessageText(parsed);
198
- if (text) payload.text = text;
199
- if (parsed?.id) payload.id = parsed.id;
200
- return payload;
201
- }
202
-
203
- /**
204
- * @param {any} parsed
205
- * @returns {Record<string, unknown>}
206
- */
207
- function extractGenericToolPayload(parsed) {
208
- const tool = parsed?.tool ?? parsed?.toolCall ?? parsed?.tool_call ?? parsed?.toolExecution ?? parsed;
209
- return {
210
- toolCallId: tool?.id ?? tool?.toolCallId ?? parsed?.id,
211
- toolName: tool?.name ?? tool?.toolName ?? parsed?.toolName,
212
- argsPreview: tool?.args ?? tool?.arguments ?? parsed?.args,
213
- resultPreview: tool?.result ?? parsed?.result,
214
- isError: Boolean(tool?.isError ?? parsed?.isError ?? parsed?.error),
215
- };
216
- }
217
-
218
- /**
219
- * @param {any} parsed
220
- * @returns {Record<string, unknown>}
221
- */
222
- function extractPiPayload(parsed) {
223
- /** @type {Record<string, unknown>} */
224
- const payload = {};
225
- if (parsed?.message?.role) payload.role = parsed.message.role;
226
- const text = extractGenericMessageText(parsed?.message);
227
- if (text) payload.text = text;
228
- if (parsed?.id) payload.id = parsed.id;
229
- return payload;
230
- }
231
-
232
- /**
233
- * @param {any} parsed
234
- * @param {PayloadKind} payloadKind
235
- * @returns {Record<string, unknown> | null}
236
- */
237
- function extractMappedPayload(parsed, payloadKind) {
238
- if (payloadKind === "message") return extractGenericMessagePayload(parsed);
239
- if (payloadKind === "tool") return extractGenericToolPayload(parsed);
240
- if (payloadKind === "pi") return extractPiPayload(parsed);
241
- return {};
242
- }
243
-
244
- /**
245
- * @param {CanonicalAgentTraceEventKind} kind
246
- * @param {Record<string, unknown> | null} payload
247
- * @param {unknown} raw
248
- * @param {string | undefined} rawType
249
- * @param {boolean} [observed]
250
- * @returns {NormalizedTraceEvent}
251
- */
252
- function buildNormalizedEvent(kind, payload, raw, rawType, observed = false) {
253
- return { kind, payload, raw, rawType, observed };
254
- }
255
-
256
- /**
257
- * @param {any} parsed
258
- * @param {string} rawType
259
- * @param {MappedStructuredEvent} mapped
260
- * @returns {NormalizedTraceBatch}
261
- */
262
- function normalizeMappedEvent(parsed, rawType, mapped) {
263
- return {
264
- events: [buildNormalizedEvent(mapped.kind, extractMappedPayload(parsed, mapped.payloadKind), parsed, rawType)],
265
- expectedKinds: mapped.expect ? [mapped.expect] : undefined,
266
- };
267
- }
268
-
269
- /**
270
- * @param {any} parsed
271
- * @param {string} rawType
272
- * @returns {NormalizedTraceBatch | null}
273
- */
274
- function normalizeClaudeStructuredEvent(parsed, rawType) {
275
- if (rawType === "assistant") {
276
- const text = extractGenericMessageText(parsed?.message ?? parsed);
277
- const events = text
278
- ? [
279
- buildNormalizedEvent(
280
- "message.update",
281
- extractGenericMessagePayload(parsed?.message ?? parsed),
282
- parsed,
283
- rawType,
284
- ),
285
- ]
286
- : [buildNormalizedEvent("stdout", { eventType: rawType }, parsed, rawType, true)];
287
- const usage = normalizeTokenUsage(parsed?.message?.usage);
288
- if (usage) events.push(buildNormalizedEvent("usage", usage, parsed, rawType));
289
- return { events };
290
- }
291
- if (rawType === "result") {
292
- /** @type {NormalizedTraceEvent[]} */
293
- const events = [];
294
- const usage = normalizeTokenUsage(parsed?.usage);
295
- if (usage) events.push(buildNormalizedEvent("usage", usage, parsed, rawType));
296
- const text = extractGenericMessageText(parsed);
297
- if (text) {
298
- events.push(buildNormalizedEvent("assistant.message.final", { text }, parsed, rawType));
299
- }
300
- return events.length > 0 ? { events } : null;
301
- }
302
- return null;
303
- }
304
-
305
- /**
306
- * @param {any} parsed
307
- * @param {string} rawType
308
- * @returns {NormalizedTraceBatch | null}
309
- */
310
- function normalizeGeminiStructuredEvent(parsed, rawType) {
311
- if (rawType === "message") {
312
- const text = extractGenericMessageText(parsed);
313
- if (parsed?.role === "assistant" && typeof text === "string" && text) {
314
- return {
315
- events: [
316
- buildNormalizedEvent(
317
- parsed?.delta ? "assistant.text.delta" : "assistant.message.final",
318
- { text },
319
- parsed,
320
- rawType,
321
- ),
322
- ],
323
- };
324
- }
325
- }
326
- if (rawType === "result" && parsed?.stats) {
327
- const usage = normalizeTokenUsage(parsed.stats);
328
- return usage ? { events: [buildNormalizedEvent("usage", usage, parsed, rawType)] } : null;
329
- }
330
- return null;
331
- }
332
-
333
- /**
334
- * @param {any} parsed
335
- * @param {string} rawType
336
- * @returns {NormalizedTraceBatch | null}
337
- */
338
- function normalizeCodexStructuredEvent(parsed, rawType) {
339
- if (rawType === "thread.started") {
340
- return { events: [buildNormalizedEvent("stdout", { eventType: rawType }, parsed, rawType, true)] };
341
- }
342
- if (rawType === "turn.started") {
343
- return { events: [buildNormalizedEvent("turn.start", {}, parsed, rawType)], expectedKinds: ["turn.end"] };
344
- }
345
- if (rawType === "item.completed" && parsed?.item?.type === "agent_message") {
346
- const text = extractGenericMessageText(parsed.item);
347
- if (typeof text === "string" && text) {
348
- return { events: [buildNormalizedEvent("assistant.message.final", { text }, parsed, rawType)] };
349
- }
350
- }
351
- if (rawType === "turn.completed") {
352
- /** @type {NormalizedTraceEvent[]} */
353
- const events = [];
354
- const usage = normalizeTokenUsage(parsed?.usage);
355
- if (usage) events.push(buildNormalizedEvent("usage", usage, parsed, rawType));
356
- events.push(buildNormalizedEvent("turn.end", {}, parsed, rawType));
357
- const text = extractGenericMessageText(parsed);
358
- if (text) {
359
- events.push(buildNormalizedEvent("assistant.message.final", { text }, parsed, rawType));
360
- }
361
- return { events };
362
- }
363
- return null;
364
- }
365
-
366
- /**
367
- * @param {any} parsed
368
- * @param {string} rawType
369
- * @returns {NormalizedTraceBatch | null}
370
- */
371
- function normalizePiStructuredEvent(parsed, rawType) {
372
- const simple = piSimpleEventMap[rawType];
373
- if (simple) return normalizeMappedEvent(parsed, rawType, simple);
374
- if (rawType === "turn_end") {
375
- /** @type {NormalizedTraceEvent[]} */
376
- const events = [buildNormalizedEvent("turn.end", extractPiPayload(parsed), parsed, rawType)];
377
- const text = extractGenericMessageText(parsed?.message);
378
- if (text) {
379
- events.push(buildNormalizedEvent("assistant.message.final", { text }, parsed?.message, rawType));
380
- }
381
- const usage = normalizeTokenUsage(parsed?.message?.usage);
382
- if (usage) events.push(buildNormalizedEvent("usage", usage, parsed.message.usage, "usage"));
383
- return { events };
384
- }
385
- if (rawType === "message_end") {
386
- /** @type {NormalizedTraceEvent[]} */
387
- const events = [buildNormalizedEvent("message.end", extractPiPayload(parsed), parsed, rawType)];
388
- const text = extractGenericMessageText(parsed?.message);
389
- if (parsed?.message?.role === "assistant" && text) {
390
- events.push(buildNormalizedEvent("assistant.message.final", { text }, parsed?.message, rawType));
391
- }
392
- return { events };
393
- }
394
- if (rawType === "message_update") {
395
- const evt = parsed?.assistantMessageEvent;
396
- if (evt?.type === "text_delta" && typeof evt.delta === "string") {
397
- return { events: [buildNormalizedEvent("assistant.text.delta", { text: evt.delta }, parsed, evt.type)] };
398
- }
399
- if ((evt?.type === "thinking_delta" || evt?.type === "reasoning_delta") && typeof evt.delta === "string") {
400
- return { events: [buildNormalizedEvent("assistant.thinking.delta", { text: evt.delta }, parsed, evt.type)] };
401
- }
402
- return { events: [buildNormalizedEvent("message.update", extractPiPayload(parsed), parsed, rawType)] };
403
- }
404
- return { events: [buildNormalizedEvent("stdout", { eventType: rawType }, parsed, rawType, true)] };
405
- }
406
-
407
- /**
408
- * @param {any} parsed
409
- * @param {string} rawType
410
- * @returns {NormalizedTraceBatch | null}
411
- */
412
- function normalizeSharedStructuredEvent(parsed, rawType) {
413
- const mapped = genericStructuredEventMap[rawType];
414
- if (mapped) return normalizeMappedEvent(parsed, rawType, mapped);
415
- if (
416
- [
417
- "message_delta",
418
- "assistant_message.delta",
419
- "assistant_message_delta",
420
- "response.output_text.delta",
421
- "content_block_delta",
422
- ].includes(rawType)
423
- ) {
424
- const text = extractGenericDeltaText(parsed);
425
- if (typeof text === "string" && text) {
426
- return { events: [buildNormalizedEvent("assistant.text.delta", { text }, parsed, rawType)] };
427
- }
428
- }
429
- if (["thinking_delta", "reasoning_delta", "response.reasoning.delta"].includes(rawType)) {
430
- const text = extractGenericDeltaText(parsed);
431
- if (typeof text === "string" && text) {
432
- return { events: [buildNormalizedEvent("assistant.thinking.delta", { text }, parsed, rawType)] };
433
- }
434
- }
435
- if (["message_end", "assistant_message_end", "response.completed", "message_stop"].includes(rawType)) {
436
- /** @type {NormalizedTraceEvent[]} */
437
- const events = [buildNormalizedEvent("message.end", extractGenericMessagePayload(parsed), parsed, rawType)];
438
- const text = extractGenericMessageText(parsed);
439
- if (text) {
440
- events.push(buildNormalizedEvent("assistant.message.final", { text }, parsed, rawType));
441
- }
442
- const usage = normalizeTokenUsage(parsed?.usage);
443
- if (usage) events.push(buildNormalizedEvent("usage", usage, parsed, rawType));
444
- return { events };
445
- }
446
- return null;
447
- }
448
-
449
- /**
450
- * @param {AgentFamily} agentFamily
451
- * @param {any} parsed
452
- * @param {string} rawType
453
- * @returns {NormalizedTraceBatch}
454
- */
455
- export function normalizeStructuredEventForFamily(agentFamily, parsed, rawType) {
456
- if (agentFamily === "pi") {
457
- return (
458
- normalizePiStructuredEvent(parsed, rawType) ?? {
459
- events: [buildNormalizedEvent("stdout", { eventType: rawType }, parsed, rawType, true)],
460
- }
461
- );
462
- }
463
- if (agentFamily === "claude-code") {
464
- const normalized = normalizeClaudeStructuredEvent(parsed, rawType);
465
- if (normalized) return normalized;
466
- }
467
- if (agentFamily === "gemini" || agentFamily === "antigravity") {
468
- const normalized = normalizeGeminiStructuredEvent(parsed, rawType);
469
- if (normalized) return normalized;
470
- }
471
- if (agentFamily === "codex") {
472
- const normalized = normalizeCodexStructuredEvent(parsed, rawType);
473
- if (normalized) return normalized;
474
- }
475
- const shared = normalizeSharedStructuredEvent(parsed, rawType);
476
- if (shared) return shared;
477
- return { events: [buildNormalizedEvent("stdout", { eventType: rawType }, parsed, rawType, true)] };
478
- }
479
-
480
- /**
481
- * @param {AgentFamily} agentFamily
482
- * @param {any} parsed
483
- * @returns {{ sessionId?: string; threadId?: string }}
484
- */
485
- export function extractProviderSessionCorrelation(agentFamily, parsed) {
486
- if (agentFamily === "codex") {
487
- const threadId = typeof parsed?.thread_id === "string" ? parsed.thread_id : undefined;
488
- return { threadId };
489
- }
490
- const sessionId =
491
- typeof parsed?.session_id === "string"
492
- ? parsed.session_id
493
- : typeof parsed?.sessionId === "string"
494
- ? parsed.sessionId
495
- : agentFamily === "pi" && typeof parsed?.id === "string"
496
- ? parsed.id
497
- : undefined;
498
- return { sessionId };
499
- }
@@ -1,162 +0,0 @@
1
- /**
2
- * @typedef {{ value: unknown; applied: boolean; ruleIds: string[] }} RedactionResult
3
- */
4
-
5
- /** @type {Array<{ id: string; pattern: RegExp; replace?: string }>} */
6
- const rules = [
7
- {
8
- id: "api-key",
9
- // Covers Stripe-style `sk_`/`pk_` AND the hyphenated provider keys
10
- // Smithers actually drives: OpenAI `sk-…`/`sk-proj-…` and Anthropic
11
- // `sk-ant-api03-…`. The separator after sk/pk may be `-` or `_`, and the
12
- // body may contain further `-`/`_` segments (namespaces like `proj-`,
13
- // `ant-`, `api03-`).
14
- pattern: /\b(?:sk|pk)[-_][A-Za-z0-9][A-Za-z0-9_-]{7,}\b/g,
15
- replace: "[REDACTED_API_KEY]",
16
- },
17
- {
18
- id: "bearer-token",
19
- pattern: /Bearer\s+[A-Za-z0-9._-]{8,}/gi,
20
- replace: "Bearer [REDACTED_TOKEN]",
21
- },
22
- {
23
- id: "auth-header",
24
- pattern: /"authorization"\s*:\s*"[^"]+"/gi,
25
- },
26
- {
27
- id: "cookie-header",
28
- pattern: /"cookie"\s*:\s*"[^"]+"/gi,
29
- },
30
- {
31
- id: "secret-ish",
32
- // Negative lookbehind (not `\b`) so an underscore-joined prefix like
33
- // `ANTHROPIC_API_KEY=` still matches: `_` is a word char, so `\bapi`
34
- // never fired after it, leaking env-style key dumps.
35
- pattern: /(?<![A-Za-z0-9])(?:api[_-]?key|token|secret|password)=([^\s"']+)/gi,
36
- // No `replace` field: redactValue special-cases this rule by id and
37
- // rewrites the captured value itself, so a top-level replace is never read.
38
- },
39
- ];
40
-
41
- const sensitiveKeySuffixes = ["authorization", "cookie", "apikey", "token", "password", "secret"];
42
-
43
- /**
44
- * @param {string} key
45
- * @returns {boolean}
46
- */
47
- function isSensitiveKey(key) {
48
- const canonicalKey = key.toLowerCase().replace(/[^a-z0-9]/g, "");
49
- return sensitiveKeySuffixes.some((suffix) => canonicalKey.endsWith(suffix));
50
- }
51
-
52
- /**
53
- * @param {unknown} value
54
- * @param {Set<string>} applied
55
- * @param {WeakSet<object>} ancestors
56
- * @param {string} key
57
- * @returns {unknown}
58
- */
59
- function redactStructuredFields(value, applied, ancestors = new WeakSet(), key = "") {
60
- if (value === null || typeof value !== "object") return value;
61
- if (ancestors.has(value)) return "[Circular]";
62
-
63
- ancestors.add(value);
64
- try {
65
- // JSON.stringify invokes toJSON before it visits object fields. Materialize
66
- // that result here so sensitive fields introduced by a custom serializer are
67
- // still seen by the structural redactor.
68
- let skipOwnToJSON = false;
69
- try {
70
- const toJSON = /** @type {{ toJSON?: unknown }} */ (value).toJSON;
71
- if (typeof toJSON === "function") {
72
- let jsonValue;
73
- try {
74
- jsonValue = toJSON.call(value, key);
75
- } catch {
76
- // Fall back to enumerable fields, but remove the throwing
77
- // serializer from the copied object so JSON.stringify cannot
78
- // invoke it again later.
79
- skipOwnToJSON = true;
80
- }
81
- if (!skipOwnToJSON) {
82
- return redactStructuredFields(jsonValue, applied, ancestors, key);
83
- }
84
- }
85
- } catch {
86
- // A throwing toJSON getter should be treated the same way as a
87
- // throwing serializer: preserve the remaining enumerable fields.
88
- skipOwnToJSON = true;
89
- }
90
-
91
- if (Array.isArray(value)) {
92
- let next = value;
93
- for (let index = 0; index < value.length; index++) {
94
- const redacted = redactStructuredFields(value[index], applied, ancestors, String(index));
95
- if (redacted === value[index]) continue;
96
- if (next === value) next = [...value];
97
- next[index] = redacted;
98
- }
99
- if (skipOwnToJSON && next === value) return [...value];
100
- return next;
101
- }
102
-
103
- const record = /** @type {Record<string, unknown>} */ (value);
104
- const entries = Object.keys(record)
105
- .filter((fieldKey) => !(skipOwnToJSON && fieldKey === "toJSON"))
106
- .map((fieldKey) => [fieldKey, record[fieldKey]]);
107
- let next = record;
108
- for (const [fieldKey, fieldValue] of entries) {
109
- let redacted = fieldValue;
110
- if (isSensitiveKey(fieldKey)) {
111
- redacted = "[REDACTED]";
112
- applied.add("sensitive-field");
113
- } else {
114
- redacted = redactStructuredFields(fieldValue, applied, ancestors, fieldKey);
115
- }
116
- if (redacted === fieldValue) continue;
117
- if (next === record) next = Object.fromEntries(entries);
118
- next[fieldKey] = redacted;
119
- }
120
- if (skipOwnToJSON && next === record) {
121
- next = Object.fromEntries(entries);
122
- }
123
- return next;
124
- } finally {
125
- ancestors.delete(value);
126
- }
127
- }
128
-
129
- /**
130
- * @param {unknown} value
131
- * @returns {RedactionResult}
132
- */
133
- export function redactValue(value) {
134
- /** @type {Set<string>} */
135
- const applied = new Set();
136
- const structured = redactStructuredFields(value, applied);
137
- const input = typeof structured === "string" ? structured : (JSON.stringify(structured ?? null) ?? "null");
138
- let next = input;
139
- for (const rule of rules) {
140
- next = next.replace(rule.pattern, (match) => {
141
- applied.add(rule.id);
142
- if (rule.id === "secret-ish") {
143
- const idx = match.indexOf("=");
144
- return `${match.slice(0, idx + 1)}[REDACTED_SECRET]`;
145
- }
146
- if (rule.id === "auth-header" || rule.id === "cookie-header") {
147
- const idx = match.indexOf(":");
148
- return `${match.slice(0, idx + 1)}"[REDACTED]"`;
149
- }
150
- return rule.replace ?? "[REDACTED]";
151
- });
152
- }
153
- if (applied.size === 0) return { value: structured, applied: false, ruleIds: [] };
154
- if (typeof structured === "string") {
155
- return { value: next, applied: true, ruleIds: [...applied] };
156
- }
157
- try {
158
- return { value: JSON.parse(next), applied: true, ruleIds: [...applied] };
159
- } catch {
160
- return { value: next, applied: true, ruleIds: [...applied] };
161
- }
162
- }