@smthrs/observability 0.33.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 (247) hide show
  1. package/LICENSE +21 -0
  2. package/docker-compose.otel.yml +104 -0
  3. package/grafana/dashboards/smithers-dashboard.json +453 -0
  4. package/grafana/provisioning/dashboards/dashboards.yml +12 -0
  5. package/grafana/provisioning/datasources/datasources.yml +49 -0
  6. package/loki/loki-config.yaml +35 -0
  7. package/otel-collector-config.yml +38 -0
  8. package/package.json +47 -0
  9. package/prometheus/prometheus.yml +8 -0
  10. package/src/MetricName.ts +1 -0
  11. package/src/MetricsServiceLive.js +9 -0
  12. package/src/README.md +28 -0
  13. package/src/ResolvedSmithersObservabilityOptions.ts +12 -0
  14. package/src/SmithersEvent.ts +773 -0
  15. package/src/SmithersLogFormat.ts +1 -0
  16. package/src/SmithersMetricDefinition.ts +15 -0
  17. package/src/SmithersMetricType.ts +1 -0
  18. package/src/SmithersMetricUnit.ts +1 -0
  19. package/src/SmithersObservability.js +15 -0
  20. package/src/SmithersObservabilityOptions.ts +12 -0
  21. package/src/SmithersObservabilityService.ts +13 -0
  22. package/src/_coreCorrelation/CorrelationContext.ts +10 -0
  23. package/src/_coreCorrelation/CorrelationContextLive.js +11 -0
  24. package/src/_coreCorrelation/CorrelationContextService.js +15 -0
  25. package/src/_coreCorrelation/CorrelationContextServiceShape.ts +12 -0
  26. package/src/_coreCorrelation/CorrelationPatch.ts +3 -0
  27. package/src/_coreCorrelation/README.md +20 -0
  28. package/src/_coreCorrelation/_correlationStorage.js +4 -0
  29. package/src/_coreCorrelation/correlationContextFiberRef.js +5 -0
  30. package/src/_coreCorrelation/correlationContextToLogAnnotations.js +18 -0
  31. package/src/_coreCorrelation/getCurrentCorrelationContext.js +9 -0
  32. package/src/_coreCorrelation/getCurrentCorrelationContextEffect.js +11 -0
  33. package/src/_coreCorrelation/index.js +14 -0
  34. package/src/_coreCorrelation/mergeCorrelationContext.js +51 -0
  35. package/src/_coreCorrelation/runWithCorrelationContext.js +14 -0
  36. package/src/_coreCorrelation/updateCurrentCorrelationContext.js +17 -0
  37. package/src/_coreCorrelation/withCorrelationContext.js +38 -0
  38. package/src/_coreCorrelation/withCurrentCorrelationContext.js +11 -0
  39. package/src/_coreMetrics.js +14 -0
  40. package/src/_coreMetricsShape.ts +44 -0
  41. package/src/_corePrometheus.js +91 -0
  42. package/src/_corePrometheusShape.ts +11 -0
  43. package/src/_coreTracing.js +132 -0
  44. package/src/_coreTracingShape.ts +17 -0
  45. package/src/_otelLogBuilders.js +102 -0
  46. package/src/_sessionFileResolvers.js +164 -0
  47. package/src/_smithersSpanAttributeAliases.js +19 -0
  48. package/src/_smithersTraceSpanStorage.js +3 -0
  49. package/src/_traceEventNormalizers.js +499 -0
  50. package/src/_traceRedaction.js +162 -0
  51. package/src/agentSessionEventToOtelLogRecord.js +55 -0
  52. package/src/agentTrace.ts +144 -0
  53. package/src/agentTraceCapabilities.js +151 -0
  54. package/src/annotateSmithersTrace.js +11 -0
  55. package/src/canonicalTraceEventToOtelLogRecord.js +55 -0
  56. package/src/correlation.js +56 -0
  57. package/src/createSmithersObservabilityLayer.js +59 -0
  58. package/src/createSmithersOtelLayer.js +23 -0
  59. package/src/createSmithersRuntimeLayer.js +2 -0
  60. package/src/detectAgentFamily.js +26 -0
  61. package/src/detectCaptureMode.js +24 -0
  62. package/src/emitOtelLogRecord.js +19 -0
  63. package/src/getCurrentSmithersTraceAnnotations.js +14 -0
  64. package/src/getCurrentSmithersTraceSpan.js +7 -0
  65. package/src/index.d.ts +1321 -0
  66. package/src/index.js +136 -0
  67. package/src/kindPhase.js +17 -0
  68. package/src/logging.js +248 -0
  69. package/src/makeSmithersSpanAttributes.js +20 -0
  70. package/src/metrics/README.md +22 -0
  71. package/src/metrics/SmithersMetricDefinition.ts +17 -0
  72. package/src/metrics/SmithersMetricType.ts +1 -0
  73. package/src/metrics/SmithersMetricUnit.ts +1 -0
  74. package/src/metrics/_asyncExternalWaitCounts.js +4 -0
  75. package/src/metrics/_buckets.js +37 -0
  76. package/src/metrics/_incrementGauge.js +11 -0
  77. package/src/metrics/_processStartMs.js +1 -0
  78. package/src/metrics/activeNodes.js +2 -0
  79. package/src/metrics/activeRuns.js +2 -0
  80. package/src/metrics/agentActionsTotal.js +2 -0
  81. package/src/metrics/agentDurationMs.js +3 -0
  82. package/src/metrics/agentErrorsTotal.js +2 -0
  83. package/src/metrics/agentEventsTotal.js +2 -0
  84. package/src/metrics/agentInvocationsTotal.js +2 -0
  85. package/src/metrics/agentRetriesTotal.js +2 -0
  86. package/src/metrics/agentSessionsTotal.js +2 -0
  87. package/src/metrics/agentTokensTotal.js +2 -0
  88. package/src/metrics/alertDeliveriesAttempted.js +2 -0
  89. package/src/metrics/alertDeliveriesSuppressed.js +2 -0
  90. package/src/metrics/alertsAcknowledgedTotal.js +2 -0
  91. package/src/metrics/alertsActive.js +2 -0
  92. package/src/metrics/alertsEscalatedTotal.js +2 -0
  93. package/src/metrics/alertsFiredTotal.js +2 -0
  94. package/src/metrics/alertsReopenedTotal.js +2 -0
  95. package/src/metrics/alertsResolvedTotal.js +2 -0
  96. package/src/metrics/alertsSilencedTotal.js +2 -0
  97. package/src/metrics/approvalPending.js +2 -0
  98. package/src/metrics/approvalWaitDuration.js +5 -0
  99. package/src/metrics/approvalsDenied.js +2 -0
  100. package/src/metrics/approvalsGranted.js +2 -0
  101. package/src/metrics/approvalsRequested.js +2 -0
  102. package/src/metrics/attemptDuration.js +3 -0
  103. package/src/metrics/attentionBacklog.js +2 -0
  104. package/src/metrics/cacheHits.js +2 -0
  105. package/src/metrics/cacheMisses.js +2 -0
  106. package/src/metrics/dbQueryDuration.js +3 -0
  107. package/src/metrics/dbRetries.js +2 -0
  108. package/src/metrics/dbTransactionDuration.js +3 -0
  109. package/src/metrics/dbTransactionRetries.js +2 -0
  110. package/src/metrics/dbTransactionRollbacks.js +2 -0
  111. package/src/metrics/devtoolsActiveSubscribers.js +2 -0
  112. package/src/metrics/devtoolsBackpressureDisconnectTotal.js +2 -0
  113. package/src/metrics/devtoolsDeltaBuildMs.js +3 -0
  114. package/src/metrics/devtoolsEventBytes.js +3 -0
  115. package/src/metrics/devtoolsEventTotal.js +2 -0
  116. package/src/metrics/devtoolsSnapshotBuildMs.js +5 -0
  117. package/src/metrics/devtoolsSubscribeTotal.js +2 -0
  118. package/src/metrics/errorsTotal.js +2 -0
  119. package/src/metrics/eventsEmittedTotal.js +2 -0
  120. package/src/metrics/externalWaitAsyncPending.js +2 -0
  121. package/src/metrics/gatewayApprovalDecisionsTotal.js +2 -0
  122. package/src/metrics/gatewayAuthEventsTotal.js +2 -0
  123. package/src/metrics/gatewayConnectionsActive.js +2 -0
  124. package/src/metrics/gatewayConnectionsClosedTotal.js +2 -0
  125. package/src/metrics/gatewayConnectionsTotal.js +2 -0
  126. package/src/metrics/gatewayCronTriggersTotal.js +2 -0
  127. package/src/metrics/gatewayErrorsTotal.js +2 -0
  128. package/src/metrics/gatewayHeartbeatTicksTotal.js +2 -0
  129. package/src/metrics/gatewayMessagesReceivedTotal.js +2 -0
  130. package/src/metrics/gatewayMessagesSentTotal.js +2 -0
  131. package/src/metrics/gatewayRpcCallsTotal.js +2 -0
  132. package/src/metrics/gatewayRpcDuration.js +3 -0
  133. package/src/metrics/gatewayRunEventBackpressureDisconnectTotal.js +4 -0
  134. package/src/metrics/gatewayRunsCompletedTotal.js +2 -0
  135. package/src/metrics/gatewayRunsStartedTotal.js +2 -0
  136. package/src/metrics/gatewaySignalsTotal.js +2 -0
  137. package/src/metrics/gatewayWebhooksReceivedTotal.js +2 -0
  138. package/src/metrics/gatewayWebhooksRejectedTotal.js +2 -0
  139. package/src/metrics/gatewayWebhooksVerifiedTotal.js +2 -0
  140. package/src/metrics/heartbeatDataSizeBytes.js +5 -0
  141. package/src/metrics/heartbeatIntervalMs.js +3 -0
  142. package/src/metrics/hotReloadDuration.js +3 -0
  143. package/src/metrics/hotReloadFailures.js +2 -0
  144. package/src/metrics/hotReloads.js +2 -0
  145. package/src/metrics/httpRequestDuration.js +3 -0
  146. package/src/metrics/httpRequests.js +2 -0
  147. package/src/metrics/index.d.ts +1163 -0
  148. package/src/metrics/index.js +168 -0
  149. package/src/metrics/memoryFactReads.js +3 -0
  150. package/src/metrics/memoryFactWrites.js +3 -0
  151. package/src/metrics/memoryMessageSaves.js +3 -0
  152. package/src/metrics/memoryRecallDuration.js +11 -0
  153. package/src/metrics/memoryRecallQueries.js +3 -0
  154. package/src/metrics/metricsServiceAdapter.js +181 -0
  155. package/src/metrics/nodeDuration.js +3 -0
  156. package/src/metrics/nodeRetriesTotal.js +2 -0
  157. package/src/metrics/nodesFailed.js +2 -0
  158. package/src/metrics/nodesFinished.js +2 -0
  159. package/src/metrics/nodesStarted.js +2 -0
  160. package/src/metrics/openApiToolCallErrorsTotal.js +3 -0
  161. package/src/metrics/openApiToolCallsTotal.js +3 -0
  162. package/src/metrics/openApiToolDuration.js +9 -0
  163. package/src/metrics/processHeapUsedBytes.js +2 -0
  164. package/src/metrics/processMemoryRssBytes.js +2 -0
  165. package/src/metrics/processUptimeSeconds.js +2 -0
  166. package/src/metrics/promptSizeBytes.js +3 -0
  167. package/src/metrics/replaysStarted.js +3 -0
  168. package/src/metrics/responseSizeBytes.js +3 -0
  169. package/src/metrics/rewindDurationMs.js +3 -0
  170. package/src/metrics/rewindFramesDeleted.js +3 -0
  171. package/src/metrics/rewindRollbackTotal.js +2 -0
  172. package/src/metrics/rewindSandboxesReverted.js +3 -0
  173. package/src/metrics/rewindTotal.js +2 -0
  174. package/src/metrics/runDuration.js +3 -0
  175. package/src/metrics/runForksCreated.js +3 -0
  176. package/src/metrics/runsAncestryDepth.js +3 -0
  177. package/src/metrics/runsCancelledTotal.js +2 -0
  178. package/src/metrics/runsCarriedStateBytes.js +5 -0
  179. package/src/metrics/runsContinuedTotal.js +2 -0
  180. package/src/metrics/runsFailedTotal.js +2 -0
  181. package/src/metrics/runsFinishedTotal.js +2 -0
  182. package/src/metrics/runsResumedTotal.js +2 -0
  183. package/src/metrics/runsTotal.js +2 -0
  184. package/src/metrics/sandboxActive.js +2 -0
  185. package/src/metrics/sandboxBundleSizeBytes.js +5 -0
  186. package/src/metrics/sandboxCompletedTotal.js +2 -0
  187. package/src/metrics/sandboxCreatedTotal.js +2 -0
  188. package/src/metrics/sandboxDurationMs.js +3 -0
  189. package/src/metrics/sandboxPatchCount.js +3 -0
  190. package/src/metrics/sandboxTransportDurationMs.js +5 -0
  191. package/src/metrics/schedulerConcurrencyUtilization.js +2 -0
  192. package/src/metrics/schedulerQueueDepth.js +2 -0
  193. package/src/metrics/schedulerWaitDuration.js +5 -0
  194. package/src/metrics/scorerDuration.js +9 -0
  195. package/src/metrics/scorerEventsFailed.js +2 -0
  196. package/src/metrics/scorerEventsFinished.js +2 -0
  197. package/src/metrics/scorerEventsStarted.js +2 -0
  198. package/src/metrics/scorersFailed.js +3 -0
  199. package/src/metrics/scorersFinished.js +3 -0
  200. package/src/metrics/scorersStarted.js +3 -0
  201. package/src/metrics/smithersMetricCatalog.js +893 -0
  202. package/src/metrics/smithersMetricCatalogByKey.js +2 -0
  203. package/src/metrics/smithersMetricCatalogByName.js +2 -0
  204. package/src/metrics/smithersMetricCatalogByPrometheusName.js +4 -0
  205. package/src/metrics/snapshotDuration.js +9 -0
  206. package/src/metrics/snapshotsCaptured.js +3 -0
  207. package/src/metrics/supervisorPollDuration.js +5 -0
  208. package/src/metrics/supervisorPollsTotal.js +2 -0
  209. package/src/metrics/supervisorResumeLag.js +5 -0
  210. package/src/metrics/supervisorResumedTotal.js +2 -0
  211. package/src/metrics/supervisorSkippedTotal.js +2 -0
  212. package/src/metrics/supervisorStaleDetected.js +2 -0
  213. package/src/metrics/taskHeartbeatTimeoutTotal.js +2 -0
  214. package/src/metrics/taskHeartbeatsTotal.js +2 -0
  215. package/src/metrics/timerDelayDuration.js +3 -0
  216. package/src/metrics/timersCancelled.js +2 -0
  217. package/src/metrics/timersCreated.js +2 -0
  218. package/src/metrics/timersFired.js +2 -0
  219. package/src/metrics/timersPending.js +2 -0
  220. package/src/metrics/toPrometheusMetricName.js +8 -0
  221. package/src/metrics/tokensCacheReadTotal.js +2 -0
  222. package/src/metrics/tokensCacheWriteTotal.js +2 -0
  223. package/src/metrics/tokensContextWindowBucketTotal.js +2 -0
  224. package/src/metrics/tokensContextWindowPerCall.js +5 -0
  225. package/src/metrics/tokensInputPerCall.js +3 -0
  226. package/src/metrics/tokensInputTotal.js +2 -0
  227. package/src/metrics/tokensOutputPerCall.js +3 -0
  228. package/src/metrics/tokensOutputTotal.js +2 -0
  229. package/src/metrics/tokensReasoningTotal.js +2 -0
  230. package/src/metrics/toolCallErrorsTotal.js +2 -0
  231. package/src/metrics/toolCallsTotal.js +2 -0
  232. package/src/metrics/toolDuration.js +3 -0
  233. package/src/metrics/toolOutputTruncatedTotal.js +2 -0
  234. package/src/metrics/trackEvent.js +608 -0
  235. package/src/metrics/updateAsyncExternalWaitPending.js +18 -0
  236. package/src/metrics/updateProcessMetrics.js +20 -0
  237. package/src/metrics/vcsDuration.js +3 -0
  238. package/src/normalizeStructuredEvent.js +15 -0
  239. package/src/prometheusContentType.js +1 -0
  240. package/src/renderPrometheusMetrics.js +212 -0
  241. package/src/resolveAgentTraceCapabilities.js +59 -0
  242. package/src/resolveSmithersObservabilityOptions.js +109 -0
  243. package/src/smithersMetrics.js +2 -0
  244. package/src/smithersSpanNames.js +6 -0
  245. package/src/unsupportedKindsForCapabilities.js +32 -0
  246. package/src/withSmithersSpan.js +17 -0
  247. package/tempo/tempo.yml +17 -0
@@ -0,0 +1,17 @@
1
+ import type { Effect } from "effect";
2
+ import type { CorrelationPatch } from "./_coreCorrelation/CorrelationPatch.ts";
3
+
4
+ export type SmithersSpanAttributesInput = Readonly<Record<string, unknown>>;
5
+
6
+ export type TracingServiceShape = {
7
+ readonly withSpan: <A, E, R>(
8
+ name: string,
9
+ effect: Effect.Effect<A, E, R>,
10
+ attributes?: Record<string, unknown>,
11
+ ) => Effect.Effect<A, E, R>;
12
+ readonly annotate: (attributes: Record<string, unknown>) => Effect.Effect<void>;
13
+ readonly withCorrelation: <A, E, R>(
14
+ context: CorrelationPatch,
15
+ effect: Effect.Effect<A, E, R>,
16
+ ) => Effect.Effect<A, E, R>;
17
+ };
@@ -0,0 +1,102 @@
1
+ /**
2
+ * @typedef {"INFO" | "WARN" | "ERROR"} OtelLogSeverity
3
+ *
4
+ * @typedef {{
5
+ * body: string;
6
+ * attributes: Record<string, unknown>;
7
+ * severity: OtelLogSeverity;
8
+ * }} OtelLogRecord
9
+ *
10
+ * @typedef {import('./agentTrace.ts').CanonicalAgentTraceEvent} CanonicalAgentTraceEvent
11
+ */
12
+
13
+ /**
14
+ * @param {Record<string, unknown>} base
15
+ * @param {Record<string, string | number | boolean>} annotations
16
+ * @returns {Record<string, unknown>}
17
+ */
18
+ export function buildOtelAttributes(base, annotations) {
19
+ /** @type {Record<string, unknown>} */
20
+ const attributes = {};
21
+ for (const [key, value] of Object.entries(base)) {
22
+ if (value !== undefined) attributes[key] = value;
23
+ }
24
+ for (const [key, value] of Object.entries(annotations)) {
25
+ attributes[key.startsWith("custom.") ? key : `custom.${key}`] = value;
26
+ }
27
+ return attributes;
28
+ }
29
+
30
+ /**
31
+ * @param {{
32
+ * category: "agent-trace" | "agent-session";
33
+ * payload: unknown;
34
+ * raw: unknown;
35
+ * redaction: { applied: boolean; ruleIds: string[] };
36
+ * annotations: Record<string, string | number | boolean>;
37
+ * }} body
38
+ * @param {Record<string, unknown>} attributes
39
+ * @param {OtelLogSeverity} severity
40
+ * @returns {OtelLogRecord}
41
+ */
42
+ export function buildOtelLogRecord(body, attributes, severity) {
43
+ return {
44
+ body: JSON.stringify({
45
+ category: body.category,
46
+ payload: body.payload,
47
+ raw: body.raw,
48
+ redaction: body.redaction,
49
+ annotations: body.annotations,
50
+ }),
51
+ attributes,
52
+ severity,
53
+ };
54
+ }
55
+
56
+ /**
57
+ * @param {CanonicalAgentTraceEvent} event
58
+ * @returns {OtelLogSeverity}
59
+ */
60
+ export function inferCanonicalSeverity(event) {
61
+ if (event.event.kind === "capture.error") {
62
+ // Truncated output is a non-fatal capture issue, not an error
63
+ if (event.payload?.reason === "truncated-json-stream") {
64
+ return "WARN";
65
+ }
66
+ return "ERROR";
67
+ }
68
+ if (event.event.kind === "capture.warning" || event.event.kind === "stderr") {
69
+ return "WARN";
70
+ }
71
+ return "INFO";
72
+ }
73
+
74
+ /**
75
+ * @param {unknown} raw
76
+ * @returns {OtelLogSeverity}
77
+ */
78
+ export function inferSessionSeverity(raw) {
79
+ const row = /** @type {any} */ (raw);
80
+ const rowType = String(row?.type ?? "").toLowerCase();
81
+ if (
82
+ row?.is_error === true ||
83
+ row?.isError === true ||
84
+ row?.error ||
85
+ row?.errorMessage ||
86
+ row?.message?.stopReason === "error" ||
87
+ row?.message?.errorMessage ||
88
+ rowType.includes("error")
89
+ ) {
90
+ return "ERROR";
91
+ }
92
+ if (rowType.includes("warning")) return "WARN";
93
+ return "INFO";
94
+ }
95
+
96
+ /**
97
+ * @param {CanonicalAgentTraceEvent} event
98
+ * @returns {boolean}
99
+ */
100
+ export function shouldExportTraceEventToOtel(event) {
101
+ return event.event.kind !== "artifact.created";
102
+ }
@@ -0,0 +1,164 @@
1
+ import { readFile, readdir, stat } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { basename, join } from "node:path";
4
+
5
+ /**
6
+ * @param {string} dir
7
+ * @returns {Promise<string[]>}
8
+ */
9
+ async function listJsonlFiles(dir) {
10
+ try {
11
+ const entries = await readdir(dir, { withFileTypes: true });
12
+ const nested = await Promise.all(
13
+ entries.map(async (entry) => {
14
+ const path = join(dir, entry.name);
15
+ if (entry.isDirectory()) return listJsonlFiles(path);
16
+ return entry.isFile() && path.endsWith(".jsonl") ? [path] : [];
17
+ }),
18
+ );
19
+ return nested.flat();
20
+ } catch {
21
+ return [];
22
+ }
23
+ }
24
+
25
+ /**
26
+ * @param {any} agent
27
+ * @returns {string[]}
28
+ */
29
+ function buildCodexSessionRoots(agent) {
30
+ const custom = agent?.opts?.sessionDir ?? agent?.opts?.codexSessionDir;
31
+ if (typeof custom === "string" && custom) return [custom];
32
+ if (String(agent?.constructor?.name ?? "") !== "CodexAgent") return [];
33
+ // The Codex CLI keeps all state (including sessions) under CODEX_HOME
34
+ // when set; ~/.codex is only its default.
35
+ const codexHome = process.env.CODEX_HOME?.trim();
36
+ return [codexHome ? join(codexHome, "sessions") : join(homedir(), ".codex", "sessions")];
37
+ }
38
+
39
+ /**
40
+ * @param {any} agent
41
+ * @returns {string[]}
42
+ */
43
+ function buildClaudeSessionRoots(agent) {
44
+ const custom = agent?.opts?.sessionDir ?? agent?.opts?.claudeProjectsDir ?? agent?.opts?.projectsDir;
45
+ if (typeof custom === "string" && custom) return [custom];
46
+ if (String(agent?.constructor?.name ?? "") !== "ClaudeCodeAgent") return [];
47
+ return [join(homedir(), ".claude", "projects")];
48
+ }
49
+
50
+ /**
51
+ * @param {any} agent
52
+ * @returns {string[]}
53
+ */
54
+ function buildPiSessionRoots(agent) {
55
+ if (typeof agent?.opts?.session === "string" && agent.opts.session) {
56
+ return [agent.opts.session];
57
+ }
58
+ const custom = agent?.opts?.sessionDir;
59
+ if (typeof custom === "string" && custom) return [custom];
60
+ if (String(agent?.constructor?.name ?? "") !== "PiAgent") return [];
61
+ return [join(homedir(), ".pi", "agent", "sessions")];
62
+ }
63
+
64
+ /**
65
+ * @param {string} cwd
66
+ * @returns {string}
67
+ */
68
+ function sanitizeClaudeProjectPath(cwd) {
69
+ return cwd.replace(/[\\/]/g, "-");
70
+ }
71
+
72
+ /**
73
+ * @param {unknown} sessionCwd
74
+ * @param {string} cwd
75
+ * @returns {boolean}
76
+ */
77
+ function isCorrelatedSessionCwd(sessionCwd, cwd) {
78
+ if (typeof sessionCwd !== "string" || !sessionCwd) return false;
79
+ return sessionCwd === cwd || sessionCwd.startsWith(`${cwd}/`) || cwd.startsWith(`${sessionCwd}/`);
80
+ }
81
+
82
+ /**
83
+ * @param {any} agent
84
+ * @param {string} [sessionId]
85
+ * @returns {Promise<string | null>}
86
+ */
87
+ export async function resolvePiSessionFile(agent, sessionId) {
88
+ if (typeof agent?.opts?.session === "string" && agent.opts.session) {
89
+ return agent.opts.session;
90
+ }
91
+ if (!sessionId) return null;
92
+ for (const root of buildPiSessionRoots(agent)) {
93
+ const files = await listJsonlFiles(root);
94
+ const match = files.find((file) => file.includes(sessionId));
95
+ if (match) return match;
96
+ }
97
+ return null;
98
+ }
99
+
100
+ /**
101
+ * @param {any} agent
102
+ * @param {string} cwd
103
+ * @param {string} [sessionId]
104
+ * @returns {Promise<string | null>}
105
+ */
106
+ export async function resolveClaudeSessionFile(agent, cwd, sessionId) {
107
+ if (!sessionId) return null;
108
+ for (const root of buildClaudeSessionRoots(agent)) {
109
+ const direct = join(root, sanitizeClaudeProjectPath(cwd), `${sessionId}.jsonl`);
110
+ try {
111
+ const info = await stat(direct);
112
+ if (info.isFile()) return direct;
113
+ } catch {}
114
+ const files = await listJsonlFiles(root);
115
+ const match = files.find((file) => basename(file) === `${sessionId}.jsonl`);
116
+ if (match) return match;
117
+ }
118
+ return null;
119
+ }
120
+
121
+ /**
122
+ * @param {any} agent
123
+ * @param {string} cwd
124
+ * @param {number} startedAtMs
125
+ * @returns {Promise<string | null>}
126
+ */
127
+ export async function resolveCodexSessionFile(agent, cwd, startedAtMs) {
128
+ const dayFolders = new Set();
129
+ for (const offset of [-1, 0, 1]) {
130
+ const day = new Date(startedAtMs + offset * 24 * 60 * 60 * 1000);
131
+ dayFolders.add(
132
+ join(
133
+ String(day.getUTCFullYear()),
134
+ String(day.getUTCMonth() + 1).padStart(2, "0"),
135
+ String(day.getUTCDate()).padStart(2, "0"),
136
+ ),
137
+ );
138
+ dayFolders.add(
139
+ join(
140
+ String(day.getFullYear()),
141
+ String(day.getMonth() + 1).padStart(2, "0"),
142
+ String(day.getDate()).padStart(2, "0"),
143
+ ),
144
+ );
145
+ }
146
+ const dayRoots = buildCodexSessionRoots(agent).flatMap((root) => [...dayFolders].map((folder) => join(root, folder)));
147
+ const candidates = (await Promise.all(dayRoots.map((root) => listJsonlFiles(root)))).flat();
148
+ /** @type {{ file: string; delta: number } | null} */
149
+ let best = null;
150
+ for (const file of candidates) {
151
+ try {
152
+ const firstLine = (await readFile(file, "utf8")).split(/\r?\n/, 1)[0];
153
+ if (!firstLine) continue;
154
+ const parsed = JSON.parse(firstLine);
155
+ if (parsed?.type !== "session_meta") continue;
156
+ const sessionCwd = parsed?.payload?.cwd;
157
+ const sessionTs = Date.parse(String(parsed?.payload?.timestamp ?? parsed?.timestamp ?? ""));
158
+ if (!isCorrelatedSessionCwd(sessionCwd, cwd) || !Number.isFinite(sessionTs)) continue;
159
+ const delta = Math.abs(sessionTs - startedAtMs);
160
+ if (!best || delta < best.delta) best = { file, delta };
161
+ } catch {}
162
+ }
163
+ return best?.file ?? null;
164
+ }
@@ -0,0 +1,19 @@
1
+ export const smithersSpanAttributeAliases = {
2
+ runId: "smithers.run_id",
3
+ run_id: "smithers.run_id",
4
+ workflowName: "smithers.workflow_name",
5
+ workflow_name: "smithers.workflow_name",
6
+ nodeId: "smithers.node_id",
7
+ node_id: "smithers.node_id",
8
+ iteration: "smithers.iteration",
9
+ attempt: "smithers.attempt",
10
+ nodeLabel: "smithers.node_label",
11
+ node_label: "smithers.node_label",
12
+ toolName: "smithers.tool_name",
13
+ tool_name: "smithers.tool_name",
14
+ agent: "smithers.agent",
15
+ model: "smithers.model",
16
+ status: "smithers.status",
17
+ waitReason: "smithers.wait_reason",
18
+ wait_reason: "smithers.wait_reason",
19
+ };
@@ -0,0 +1,3 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ /** @type {AsyncLocalStorage<import("effect/Tracer").AnySpan>} */
3
+ export const smithersTraceSpanStorage = new AsyncLocalStorage();