@arizeai/phoenix-client 6.10.0 → 6.11.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 (244) hide show
  1. package/README.md +62 -0
  2. package/dist/esm/__generated__/api/v1.d.ts +452 -28
  3. package/dist/esm/__generated__/api/v1.d.ts.map +1 -1
  4. package/dist/esm/experiments/helpers/getExampleGlobalId.d.ts +8 -0
  5. package/dist/esm/experiments/helpers/getExampleGlobalId.d.ts.map +1 -0
  6. package/dist/esm/experiments/helpers/getExampleGlobalId.js +9 -0
  7. package/dist/esm/experiments/helpers/getExampleGlobalId.js.map +1 -0
  8. package/dist/esm/experiments/resumeEvaluation.d.ts.map +1 -1
  9. package/dist/esm/experiments/resumeEvaluation.js +2 -1
  10. package/dist/esm/experiments/resumeEvaluation.js.map +1 -1
  11. package/dist/esm/experiments/resumeExperiment.d.ts.map +1 -1
  12. package/dist/esm/experiments/resumeExperiment.js +3 -2
  13. package/dist/esm/experiments/resumeExperiment.js.map +1 -1
  14. package/dist/esm/experiments/runExperiment.d.ts.map +1 -1
  15. package/dist/esm/experiments/runExperiment.js +6 -3
  16. package/dist/esm/experiments/runExperiment.js.map +1 -1
  17. package/dist/esm/jest/index.d.ts +5 -0
  18. package/dist/esm/jest/index.d.ts.map +1 -0
  19. package/dist/esm/jest/index.js +49 -0
  20. package/dist/esm/jest/index.js.map +1 -0
  21. package/dist/esm/jest/reporter.d.ts +13 -0
  22. package/dist/esm/jest/reporter.d.ts.map +1 -0
  23. package/dist/esm/jest/reporter.js +19 -0
  24. package/dist/esm/jest/reporter.js.map +1 -0
  25. package/dist/esm/prompts/sdks/toAI.d.ts +2 -2
  26. package/dist/esm/prompts/sdks/toAI.d.ts.map +1 -1
  27. package/dist/esm/prompts/sdks/toAI.js.map +1 -1
  28. package/dist/esm/prompts/sdks/toAnthropic.d.ts +2 -2
  29. package/dist/esm/prompts/sdks/toAnthropic.d.ts.map +1 -1
  30. package/dist/esm/prompts/sdks/toAnthropic.js.map +1 -1
  31. package/dist/esm/prompts/sdks/toOpenAI.d.ts +2 -2
  32. package/dist/esm/prompts/sdks/toOpenAI.d.ts.map +1 -1
  33. package/dist/esm/prompts/sdks/toOpenAI.js.map +1 -1
  34. package/dist/esm/prompts/sdks/toSDK.d.ts +8 -8
  35. package/dist/esm/prompts/sdks/toSDK.d.ts.map +1 -1
  36. package/dist/esm/prompts/sdks/toSDK.js.map +1 -1
  37. package/dist/esm/prompts/sdks/types.d.ts +2 -2
  38. package/dist/esm/prompts/sdks/types.d.ts.map +1 -1
  39. package/dist/esm/schemas/llm/anthropic/converters.d.ts +8 -8
  40. package/dist/esm/schemas/llm/anthropic/messagePartSchemas.d.ts +4 -4
  41. package/dist/esm/schemas/llm/anthropic/messageSchemas.d.ts +6 -6
  42. package/dist/esm/schemas/llm/constants.d.ts +3 -3
  43. package/dist/esm/schemas/llm/converters.d.ts +12 -12
  44. package/dist/esm/schemas/llm/openai/converters.d.ts +3 -3
  45. package/dist/esm/schemas/llm/schemas.d.ts +2 -2
  46. package/dist/esm/testing/acceptance.d.ts +20 -0
  47. package/dist/esm/testing/acceptance.d.ts.map +1 -0
  48. package/dist/esm/testing/acceptance.js +129 -0
  49. package/dist/esm/testing/acceptance.js.map +1 -0
  50. package/dist/esm/testing/define-api.d.ts +157 -0
  51. package/dist/esm/testing/define-api.d.ts.map +1 -0
  52. package/dist/esm/testing/define-api.js +78 -0
  53. package/dist/esm/testing/define-api.js.map +1 -0
  54. package/dist/esm/testing/helpers.d.ts +55 -0
  55. package/dist/esm/testing/helpers.d.ts.map +1 -0
  56. package/dist/esm/testing/helpers.js +179 -0
  57. package/dist/esm/testing/helpers.js.map +1 -0
  58. package/dist/esm/testing/phoenix-test-tracking.d.ts +68 -0
  59. package/dist/esm/testing/phoenix-test-tracking.d.ts.map +1 -0
  60. package/dist/esm/testing/phoenix-test-tracking.js +521 -0
  61. package/dist/esm/testing/phoenix-test-tracking.js.map +1 -0
  62. package/dist/esm/testing/report-artifacts.d.ts +45 -0
  63. package/dist/esm/testing/report-artifacts.d.ts.map +1 -0
  64. package/dist/esm/testing/report-artifacts.js +218 -0
  65. package/dist/esm/testing/report-artifacts.js.map +1 -0
  66. package/dist/esm/testing/report-run.d.ts +22 -0
  67. package/dist/esm/testing/report-run.d.ts.map +1 -0
  68. package/dist/esm/testing/report-run.js +41 -0
  69. package/dist/esm/testing/report-run.js.map +1 -0
  70. package/dist/esm/testing/reporter-format.d.ts +83 -0
  71. package/dist/esm/testing/reporter-format.d.ts.map +1 -0
  72. package/dist/esm/testing/reporter-format.js +852 -0
  73. package/dist/esm/testing/reporter-format.js.map +1 -0
  74. package/dist/esm/testing/runner.d.ts +31 -0
  75. package/dist/esm/testing/runner.d.ts.map +1 -0
  76. package/dist/esm/testing/runner.js +238 -0
  77. package/dist/esm/testing/runner.js.map +1 -0
  78. package/dist/esm/testing/state.d.ts +138 -0
  79. package/dist/esm/testing/state.d.ts.map +1 -0
  80. package/dist/esm/testing/state.js +31 -0
  81. package/dist/esm/testing/state.js.map +1 -0
  82. package/dist/esm/testing/types.d.ts +319 -0
  83. package/dist/esm/testing/types.d.ts.map +1 -0
  84. package/dist/esm/testing/types.js +9 -0
  85. package/dist/esm/testing/types.js.map +1 -0
  86. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  87. package/dist/esm/utils/channel.d.ts +7 -7
  88. package/dist/esm/utils/channel.d.ts.map +1 -1
  89. package/dist/esm/utils/channel.js +1 -1
  90. package/dist/esm/utils/channel.js.map +1 -1
  91. package/dist/esm/utils/formatPromptMessages.d.ts.map +1 -1
  92. package/dist/esm/utils/getPromptBySelector.d.ts.map +1 -1
  93. package/dist/esm/utils/promisifyResult.d.ts +1 -1
  94. package/dist/esm/utils/promisifyResult.d.ts.map +1 -1
  95. package/dist/esm/utils/promisifyResult.js.map +1 -1
  96. package/dist/esm/utils/schemaMatches.d.ts +5 -5
  97. package/dist/esm/utils/schemaMatches.d.ts.map +1 -1
  98. package/dist/esm/utils/schemaMatches.js.map +1 -1
  99. package/dist/esm/vitest/index.d.ts +5 -0
  100. package/dist/esm/vitest/index.d.ts.map +1 -0
  101. package/dist/esm/vitest/index.js +15 -0
  102. package/dist/esm/vitest/index.js.map +1 -0
  103. package/dist/esm/vitest/reporter.d.ts +19 -0
  104. package/dist/esm/vitest/reporter.d.ts.map +1 -0
  105. package/dist/esm/vitest/reporter.js +27 -0
  106. package/dist/esm/vitest/reporter.js.map +1 -0
  107. package/dist/src/__generated__/api/v1.d.ts +452 -28
  108. package/dist/src/__generated__/api/v1.d.ts.map +1 -1
  109. package/dist/src/experiments/helpers/getExampleGlobalId.d.ts +8 -0
  110. package/dist/src/experiments/helpers/getExampleGlobalId.d.ts.map +1 -0
  111. package/dist/src/experiments/helpers/getExampleGlobalId.js +13 -0
  112. package/dist/src/experiments/helpers/getExampleGlobalId.js.map +1 -0
  113. package/dist/src/experiments/resumeEvaluation.d.ts.map +1 -1
  114. package/dist/src/experiments/resumeEvaluation.js +2 -1
  115. package/dist/src/experiments/resumeEvaluation.js.map +1 -1
  116. package/dist/src/experiments/resumeExperiment.d.ts.map +1 -1
  117. package/dist/src/experiments/resumeExperiment.js +3 -2
  118. package/dist/src/experiments/resumeExperiment.js.map +1 -1
  119. package/dist/src/experiments/runExperiment.d.ts.map +1 -1
  120. package/dist/src/experiments/runExperiment.js +6 -3
  121. package/dist/src/experiments/runExperiment.js.map +1 -1
  122. package/dist/src/jest/index.d.ts +5 -0
  123. package/dist/src/jest/index.d.ts.map +1 -0
  124. package/dist/src/jest/index.js +58 -0
  125. package/dist/src/jest/index.js.map +1 -0
  126. package/dist/src/jest/reporter.d.ts +13 -0
  127. package/dist/src/jest/reporter.d.ts.map +1 -0
  128. package/dist/src/jest/reporter.js +23 -0
  129. package/dist/src/jest/reporter.js.map +1 -0
  130. package/dist/src/prompts/sdks/toAI.d.ts +2 -2
  131. package/dist/src/prompts/sdks/toAI.d.ts.map +1 -1
  132. package/dist/src/prompts/sdks/toAI.js.map +1 -1
  133. package/dist/src/prompts/sdks/toAnthropic.d.ts +2 -2
  134. package/dist/src/prompts/sdks/toAnthropic.d.ts.map +1 -1
  135. package/dist/src/prompts/sdks/toAnthropic.js.map +1 -1
  136. package/dist/src/prompts/sdks/toOpenAI.d.ts +2 -2
  137. package/dist/src/prompts/sdks/toOpenAI.d.ts.map +1 -1
  138. package/dist/src/prompts/sdks/toOpenAI.js.map +1 -1
  139. package/dist/src/prompts/sdks/toSDK.d.ts +8 -8
  140. package/dist/src/prompts/sdks/toSDK.d.ts.map +1 -1
  141. package/dist/src/prompts/sdks/toSDK.js.map +1 -1
  142. package/dist/src/prompts/sdks/types.d.ts +2 -2
  143. package/dist/src/prompts/sdks/types.d.ts.map +1 -1
  144. package/dist/src/schemas/llm/anthropic/converters.d.ts +8 -8
  145. package/dist/src/schemas/llm/anthropic/messagePartSchemas.d.ts +4 -4
  146. package/dist/src/schemas/llm/anthropic/messageSchemas.d.ts +6 -6
  147. package/dist/src/schemas/llm/constants.d.ts +3 -3
  148. package/dist/src/schemas/llm/converters.d.ts +12 -12
  149. package/dist/src/schemas/llm/openai/converters.d.ts +3 -3
  150. package/dist/src/schemas/llm/schemas.d.ts +2 -2
  151. package/dist/src/testing/acceptance.d.ts +20 -0
  152. package/dist/src/testing/acceptance.d.ts.map +1 -0
  153. package/dist/src/testing/acceptance.js +114 -0
  154. package/dist/src/testing/acceptance.js.map +1 -0
  155. package/dist/src/testing/define-api.d.ts +157 -0
  156. package/dist/src/testing/define-api.d.ts.map +1 -0
  157. package/dist/src/testing/define-api.js +81 -0
  158. package/dist/src/testing/define-api.js.map +1 -0
  159. package/dist/src/testing/helpers.d.ts +55 -0
  160. package/dist/src/testing/helpers.d.ts.map +1 -0
  161. package/dist/src/testing/helpers.js +182 -0
  162. package/dist/src/testing/helpers.js.map +1 -0
  163. package/dist/src/testing/phoenix-test-tracking.d.ts +68 -0
  164. package/dist/src/testing/phoenix-test-tracking.d.ts.map +1 -0
  165. package/dist/src/testing/phoenix-test-tracking.js +530 -0
  166. package/dist/src/testing/phoenix-test-tracking.js.map +1 -0
  167. package/dist/src/testing/report-artifacts.d.ts +45 -0
  168. package/dist/src/testing/report-artifacts.d.ts.map +1 -0
  169. package/dist/src/testing/report-artifacts.js +225 -0
  170. package/dist/src/testing/report-artifacts.js.map +1 -0
  171. package/dist/src/testing/report-run.d.ts +22 -0
  172. package/dist/src/testing/report-run.d.ts.map +1 -0
  173. package/dist/src/testing/report-run.js +47 -0
  174. package/dist/src/testing/report-run.js.map +1 -0
  175. package/dist/src/testing/reporter-format.d.ts +83 -0
  176. package/dist/src/testing/reporter-format.d.ts.map +1 -0
  177. package/dist/src/testing/reporter-format.js +870 -0
  178. package/dist/src/testing/reporter-format.js.map +1 -0
  179. package/dist/src/testing/runner.d.ts +31 -0
  180. package/dist/src/testing/runner.d.ts.map +1 -0
  181. package/dist/src/testing/runner.js +258 -0
  182. package/dist/src/testing/runner.js.map +1 -0
  183. package/dist/src/testing/state.d.ts +138 -0
  184. package/dist/src/testing/state.d.ts.map +1 -0
  185. package/dist/src/testing/state.js +38 -0
  186. package/dist/src/testing/state.js.map +1 -0
  187. package/dist/src/testing/types.d.ts +319 -0
  188. package/dist/src/testing/types.d.ts.map +1 -0
  189. package/dist/src/testing/types.js +13 -0
  190. package/dist/src/testing/types.js.map +1 -0
  191. package/dist/src/utils/channel.d.ts +7 -7
  192. package/dist/src/utils/channel.d.ts.map +1 -1
  193. package/dist/src/utils/channel.js +1 -1
  194. package/dist/src/utils/channel.js.map +1 -1
  195. package/dist/src/utils/formatPromptMessages.d.ts.map +1 -1
  196. package/dist/src/utils/getPromptBySelector.d.ts.map +1 -1
  197. package/dist/src/utils/promisifyResult.d.ts +1 -1
  198. package/dist/src/utils/promisifyResult.d.ts.map +1 -1
  199. package/dist/src/utils/promisifyResult.js.map +1 -1
  200. package/dist/src/utils/schemaMatches.d.ts +5 -5
  201. package/dist/src/utils/schemaMatches.d.ts.map +1 -1
  202. package/dist/src/utils/schemaMatches.js.map +1 -1
  203. package/dist/src/vitest/index.d.ts +5 -0
  204. package/dist/src/vitest/index.d.ts.map +1 -0
  205. package/dist/src/vitest/index.js +23 -0
  206. package/dist/src/vitest/index.js.map +1 -0
  207. package/dist/src/vitest/reporter.d.ts +19 -0
  208. package/dist/src/vitest/reporter.d.ts.map +1 -0
  209. package/dist/src/vitest/reporter.js +34 -0
  210. package/dist/src/vitest/reporter.js.map +1 -0
  211. package/dist/tsconfig.tsbuildinfo +1 -1
  212. package/docs/ci-evals-annotations.mdx +190 -0
  213. package/docs/ci-evals-jest.mdx +78 -0
  214. package/docs/ci-evals-vitest.mdx +240 -0
  215. package/docs/ci-evals.mdx +263 -0
  216. package/docs/overview.mdx +9 -1
  217. package/package.json +49 -17
  218. package/src/__generated__/api/v1.ts +452 -28
  219. package/src/experiments/helpers/getExampleGlobalId.ts +12 -0
  220. package/src/experiments/resumeEvaluation.ts +2 -1
  221. package/src/experiments/resumeExperiment.ts +3 -2
  222. package/src/experiments/runExperiment.ts +6 -3
  223. package/src/jest/index.ts +124 -0
  224. package/src/jest/reporter.ts +22 -0
  225. package/src/prompts/sdks/toAI.ts +4 -3
  226. package/src/prompts/sdks/toAnthropic.ts +4 -3
  227. package/src/prompts/sdks/toOpenAI.ts +4 -3
  228. package/src/prompts/sdks/toSDK.ts +16 -11
  229. package/src/prompts/sdks/types.ts +2 -2
  230. package/src/testing/acceptance.ts +190 -0
  231. package/src/testing/define-api.ts +279 -0
  232. package/src/testing/helpers.ts +251 -0
  233. package/src/testing/phoenix-test-tracking.ts +637 -0
  234. package/src/testing/report-artifacts.ts +272 -0
  235. package/src/testing/report-run.ts +44 -0
  236. package/src/testing/reporter-format.ts +1072 -0
  237. package/src/testing/runner.ts +350 -0
  238. package/src/testing/state.ts +165 -0
  239. package/src/testing/types.ts +366 -0
  240. package/src/utils/channel.ts +17 -15
  241. package/src/utils/promisifyResult.ts +6 -4
  242. package/src/utils/schemaMatches.ts +12 -10
  243. package/src/vitest/index.ts +57 -0
  244. package/src/vitest/reporter.ts +32 -0
@@ -0,0 +1,521 @@
1
+ import { attachGlobalTracerProvider, context, createNoOpProvider, MimeType, OpenInferenceSpanKind, register, SemanticConventions, SpanStatusCode, suppressTracing, trace, } from "@arizeai/phoenix-otel";
2
+ import { createDataset } from "../datasets/index.js";
3
+ import { cleanupOwnedTracerProvider } from "../experiments/tracing.js";
4
+ import { createClient } from "../index.js";
5
+ import { ensureString } from "../utils/ensureString.js";
6
+ import { toObjectHeaders } from "../utils/toObjectHeaders.js";
7
+ import { getDatasetExperimentsUrl, getDatasetUrl, getExperimentUrl, } from "../utils/urlUtils.js";
8
+ import { currentRun } from "./state.js";
9
+ function isFalsyFlag(value) {
10
+ const v = (value ?? "").toLowerCase();
11
+ return v === "false" || v === "0" || v === "off" || v === "no";
12
+ }
13
+ /**
14
+ * Decide whether tests should sync to Phoenix.
15
+ *
16
+ * Tracing is enabled by default. It can be disabled globally by setting
17
+ * `PHOENIX_TEST_TRACING=false`, or per suite via `SuiteConfig.dryRun`.
18
+ */
19
+ export function isTrackingEnabled(suite) {
20
+ if (isFalsyFlag(process.env.PHOENIX_TEST_TRACING)) {
21
+ return { enabled: false, reason: "PHOENIX_TEST_TRACING is disabled" };
22
+ }
23
+ if (suite?.config.dryRun) {
24
+ return { enabled: false, reason: "suite configured dryRun" };
25
+ }
26
+ return { enabled: true };
27
+ }
28
+ /**
29
+ * Resolve the repetition count for a test: per-test value, else suite-level,
30
+ * else the `PHOENIX_TEST_REPETITIONS` env var, else `1`. Non-positive or
31
+ * non-finite values fall back to `1`.
32
+ */
33
+ export function resolveRepetitions(perTest, suite) {
34
+ const envValue = Number(process.env.PHOENIX_TEST_REPETITIONS);
35
+ const candidates = [
36
+ perTest,
37
+ suite.config.repetitions,
38
+ Number.isFinite(envValue) ? envValue : undefined,
39
+ ];
40
+ for (const c of candidates) {
41
+ if (typeof c === "number" && Number.isFinite(c) && c >= 1) {
42
+ return Math.floor(c);
43
+ }
44
+ }
45
+ return 1;
46
+ }
47
+ /**
48
+ * Deterministic key for matching dataset examples by content. Uses sorted
49
+ * keys so two inputs that differ only in property order hash the same.
50
+ */
51
+ function stableKey(value) {
52
+ return stableStringify(value);
53
+ }
54
+ function stableStringify(value) {
55
+ if (value === null || typeof value !== "object") {
56
+ return JSON.stringify(value);
57
+ }
58
+ if (Array.isArray(value)) {
59
+ return "[" + value.map(stableStringify).join(",") + "]";
60
+ }
61
+ const keys = Object.keys(value).sort();
62
+ return ("{" +
63
+ keys
64
+ .map((k) => JSON.stringify(k) +
65
+ ":" +
66
+ stableStringify(value[k]))
67
+ .join(",") +
68
+ "}");
69
+ }
70
+ /** TEXT for raw strings, JSON for everything else. */
71
+ function mimeTypeFor(value) {
72
+ return typeof value === "string" ? MimeType.TEXT : MimeType.JSON;
73
+ }
74
+ const taskSpansByRun = new WeakMap();
75
+ /**
76
+ * Warn once when `PHOENIX_HOST` is plain `http:` while an `Authorization`
77
+ * header is being forwarded to the OTLP exporter — that combination
78
+ * exfiltrates the bearer token in cleartext.
79
+ */
80
+ let warnedAboutHttpScheme = false;
81
+ function maybeWarnHttpScheme(baseUrl, headers) {
82
+ if (warnedAboutHttpScheme || !baseUrl)
83
+ return;
84
+ let parsed;
85
+ try {
86
+ parsed = new URL(baseUrl);
87
+ }
88
+ catch {
89
+ return;
90
+ }
91
+ if (parsed.protocol !== "http:")
92
+ return;
93
+ if (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1")
94
+ return;
95
+ if (!headers)
96
+ return;
97
+ const picked = toObjectHeaders(headers);
98
+ const hasAuth = Object.keys(picked).some((h) => h.toLowerCase() === "authorization");
99
+ if (!hasAuth)
100
+ return;
101
+ warnedAboutHttpScheme = true;
102
+ // eslint-disable-next-line no-console
103
+ console.warn(`[@arizeai/phoenix-client] PHOENIX_HOST="${baseUrl}" uses http:// with ` +
104
+ `an Authorization header set; the bearer token will travel in cleartext. ` +
105
+ `Use https:// for non-localhost Phoenix endpoints.`);
106
+ }
107
+ function buildLinks(client, datasetId, experimentId) {
108
+ const baseUrl = client.config.baseUrl;
109
+ if (!baseUrl)
110
+ return [];
111
+ return [
112
+ { label: "Dataset", url: getDatasetUrl({ baseUrl, datasetId }) },
113
+ {
114
+ label: "Experiments",
115
+ url: getDatasetExperimentsUrl({ baseUrl, datasetId }),
116
+ },
117
+ {
118
+ label: "Experiment",
119
+ url: getExperimentUrl({ baseUrl, datasetId, experimentId }),
120
+ },
121
+ ];
122
+ }
123
+ /**
124
+ * Initialize the suite: upload the dataset, create the experiment, and
125
+ * register the OpenInference tracer.
126
+ *
127
+ * If tracing is disabled (no Phoenix env vars, or PHOENIX_TEST_TRACING=false),
128
+ * this populates a no-op tracer and exits without making any network calls.
129
+ */
130
+ export async function initializeSuite(suite) {
131
+ const tracking = isTrackingEnabled(suite);
132
+ if (!tracking.enabled) {
133
+ suite.trackingDisabled = true;
134
+ suite.trackingDisabledReason = tracking.reason;
135
+ suite.tracer = createNoOpProvider().getTracer("no-op");
136
+ suite.evaluatorTracer = suite.tracer;
137
+ return;
138
+ }
139
+ const client = suite.config.client ?? createClient();
140
+ suite.client = client;
141
+ const datasetName = suite.config.datasetName ?? suite.name;
142
+ const description = suite.config.description ??
143
+ `Phoenix test dataset auto-generated from ${suite.name}`;
144
+ const examples = Array.from(suite.registeredExamples.values()).map((registered) => ({
145
+ id: registered.params.id ?? null,
146
+ input: registered.params.input,
147
+ output: registered.params.expected ?? {},
148
+ metadata: registered.params.metadata ?? {},
149
+ splits: registered.params.splits,
150
+ }));
151
+ let datasetId;
152
+ try {
153
+ const created = await createDataset({
154
+ client,
155
+ name: datasetName,
156
+ description,
157
+ examples,
158
+ });
159
+ datasetId = created.datasetId;
160
+ }
161
+ catch (err) {
162
+ suite.trackingDisabled = true;
163
+ suite.setupError = err instanceof Error ? err : new Error(String(err));
164
+ suite.tracer = createNoOpProvider().getTracer("no-op");
165
+ suite.evaluatorTracer = suite.tracer;
166
+ return;
167
+ }
168
+ suite.datasetId = datasetId;
169
+ // Map test names to server-side example ids by re-fetching the dataset.
170
+ // The server doesn't promise that the GET response order matches the
171
+ // upload order, so we match by user-supplied `id` first, then by
172
+ // `JSON.stringify(input)` deep-equality with FIFO-on-collision.
173
+ try {
174
+ const { data: response } = await client.GET("/v1/datasets/{id}/examples", {
175
+ params: { path: { id: datasetId } },
176
+ });
177
+ const fetched = response?.data?.examples ?? [];
178
+ const idToTestName = new Map();
179
+ const inputKeyToTestNames = new Map();
180
+ for (const [testName, registered] of suite.registeredExamples.entries()) {
181
+ if (registered.params.id) {
182
+ idToTestName.set(registered.params.id, testName);
183
+ continue;
184
+ }
185
+ const key = stableKey(registered.params.input);
186
+ const arr = inputKeyToTestNames.get(key) ?? [];
187
+ arr.push(testName);
188
+ inputKeyToTestNames.set(key, arr);
189
+ }
190
+ for (const ex of fetched) {
191
+ const byId = idToTestName.get(ex.id);
192
+ if (byId) {
193
+ suite.exampleIdsByTest.set(byId, {
194
+ exampleId: ex.id,
195
+ nodeId: ex.node_id,
196
+ });
197
+ idToTestName.delete(ex.id);
198
+ continue;
199
+ }
200
+ const queue = inputKeyToTestNames.get(stableKey(ex.input));
201
+ if (queue && queue.length) {
202
+ const testName = queue.shift();
203
+ suite.exampleIdsByTest.set(testName, {
204
+ exampleId: ex.id,
205
+ nodeId: ex.node_id,
206
+ });
207
+ }
208
+ }
209
+ }
210
+ catch {
211
+ // If we cannot resolve example ids, runs will be logged without one.
212
+ }
213
+ const projectName = `${datasetName}-${new Date().toISOString()}`;
214
+ suite.projectName = projectName;
215
+ try {
216
+ const experimentResponse = await client
217
+ .POST("/v1/datasets/{dataset_id}/experiments", {
218
+ params: { path: { dataset_id: datasetId } },
219
+ body: {
220
+ name: suite.config.datasetName ?? suite.name,
221
+ description,
222
+ metadata: { ...(suite.config.metadata ?? {}), ...envMetadata() },
223
+ project_name: projectName,
224
+ repetitions: Math.max(1, suite.maxRepetitions ?? 1),
225
+ },
226
+ })
227
+ .then((res) => res.data?.data);
228
+ if (!experimentResponse) {
229
+ throw new Error("Failed to create experiment");
230
+ }
231
+ suite.experimentId = experimentResponse.id;
232
+ suite.projectName = experimentResponse.project_name ?? projectName;
233
+ }
234
+ catch (err) {
235
+ suite.trackingDisabled = true;
236
+ suite.setupError = err instanceof Error ? err : new Error(String(err));
237
+ suite.tracer = createNoOpProvider().getTracer("no-op");
238
+ suite.evaluatorTracer = suite.tracer;
239
+ return;
240
+ }
241
+ const baseUrl = client.config.baseUrl;
242
+ if (!baseUrl) {
243
+ suite.trackingDisabled = true;
244
+ suite.setupError = new Error("Phoenix base URL not found. Set PHOENIX_HOST or pass baseUrl on the client.");
245
+ suite.tracer = createNoOpProvider().getTracer("no-op");
246
+ suite.evaluatorTracer = suite.tracer;
247
+ return;
248
+ }
249
+ maybeWarnHttpScheme(baseUrl, client.config.headers);
250
+ let provider;
251
+ try {
252
+ provider = register({
253
+ projectName: suite.projectName,
254
+ url: baseUrl,
255
+ headers: client.config.headers
256
+ ? toObjectHeaders(client.config.headers)
257
+ : undefined,
258
+ batch: false,
259
+ global: false,
260
+ });
261
+ suite.tracerProvider = provider;
262
+ suite.globalRegistration = attachGlobalTracerProvider(provider);
263
+ }
264
+ catch (err) {
265
+ suite.trackingDisabled = true;
266
+ suite.setupError = err instanceof Error ? err : new Error(String(err));
267
+ suite.tracer = createNoOpProvider().getTracer("no-op");
268
+ suite.evaluatorTracer = suite.tracer;
269
+ return;
270
+ }
271
+ suite.tracer = provider.getTracer(suite.projectName);
272
+ suite.evaluatorTracer = provider.getTracer(`${suite.projectName}-evaluators`);
273
+ if (suite.datasetId && suite.experimentId) {
274
+ suite.links = buildLinks(client, suite.datasetId, suite.experimentId);
275
+ }
276
+ }
277
+ /** Lazily-created no-op tracer reused for dry runs / fallbacks. */
278
+ let noOpTracer;
279
+ function getNoOpTracer() {
280
+ if (!noOpTracer)
281
+ noOpTracer = createNoOpProvider().getTracer("no-op");
282
+ return noOpTracer;
283
+ }
284
+ /** The tracer to use for the currently-running test — no-op when dry. */
285
+ function taskTracer(suite) {
286
+ if (currentRun()?.dryRun)
287
+ return getNoOpTracer();
288
+ return suite.tracer ?? getNoOpTracer();
289
+ }
290
+ /**
291
+ * Wrap the user's test body in an OpenInference task span and return the
292
+ * trace id so we can submit it with the experiment run.
293
+ */
294
+ export async function runTaskWithTracing(suite, testName, fn) {
295
+ const tracer = taskTracer(suite);
296
+ return tracer.startActiveSpan(`Test: ${testName}`, async (span) => {
297
+ const traceId = span.spanContext().traceId;
298
+ const run = currentRun();
299
+ if (run) {
300
+ run.traceId = traceId;
301
+ taskSpansByRun.set(run, { span, traceId, ended: false });
302
+ }
303
+ try {
304
+ const result = await fn();
305
+ if (run) {
306
+ endTaskSpan({ run, fallbackOutput: result });
307
+ }
308
+ else {
309
+ endSpanAsTask({ span, input: undefined, output: result });
310
+ }
311
+ return { traceId, result };
312
+ }
313
+ catch (err) {
314
+ const error = err instanceof Error ? err : new Error(String(err));
315
+ const isTaskError = run ? !hasTaskSpanEnded(run) : true;
316
+ if (run && isTaskError) {
317
+ endTaskSpan({ run, error });
318
+ }
319
+ else if (!run) {
320
+ span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
321
+ span.end();
322
+ }
323
+ return { traceId, error, isTaskError };
324
+ }
325
+ finally {
326
+ if (run) {
327
+ taskSpansByRun.delete(run);
328
+ }
329
+ }
330
+ });
331
+ }
332
+ function hasTaskSpanEnded(run) {
333
+ return taskSpansByRun.get(run)?.ended ?? false;
334
+ }
335
+ /**
336
+ * End the current run's task span. `logOutput()` calls this immediately so
337
+ * evaluator work that follows is not included in the task span duration.
338
+ */
339
+ export function endTaskSpanForRun(run) {
340
+ endTaskSpan({ run });
341
+ }
342
+ function endTaskSpan({ run, fallbackOutput, error, }) {
343
+ const lifecycle = taskSpansByRun.get(run);
344
+ if (!lifecycle || lifecycle.ended)
345
+ return;
346
+ const output = run.outputSet ? run.output : fallbackOutput;
347
+ if (error) {
348
+ lifecycle.span.setStatus({
349
+ code: SpanStatusCode.ERROR,
350
+ message: error.message,
351
+ });
352
+ lifecycle.span.setAttributes({
353
+ [SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.CHAIN,
354
+ [SemanticConventions.INPUT_MIME_TYPE]: mimeTypeFor(run.params.input),
355
+ [SemanticConventions.INPUT_VALUE]: ensureString(run.params.input),
356
+ });
357
+ lifecycle.span.end();
358
+ }
359
+ else {
360
+ endSpanAsTask({ span: lifecycle.span, input: run.params.input, output });
361
+ }
362
+ run.traceId = lifecycle.traceId;
363
+ run.taskEndTime = new Date();
364
+ lifecycle.ended = true;
365
+ }
366
+ function endSpanAsTask({ span, input, output, }) {
367
+ span.setAttributes({
368
+ [SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.CHAIN,
369
+ [SemanticConventions.INPUT_MIME_TYPE]: mimeTypeFor(input),
370
+ [SemanticConventions.INPUT_VALUE]: ensureString(input),
371
+ [SemanticConventions.OUTPUT_MIME_TYPE]: mimeTypeFor(output),
372
+ [SemanticConventions.OUTPUT_VALUE]: ensureString(output),
373
+ });
374
+ span.setStatus({ code: SpanStatusCode.OK });
375
+ span.end();
376
+ }
377
+ /**
378
+ * POST a single experiment run for one test case to Phoenix.
379
+ *
380
+ * Best-effort: failures are captured and surfaced via the test reporter but
381
+ * do not fail the test itself.
382
+ */
383
+ export async function postExperimentRun(suite, run) {
384
+ if (run.dryRun ||
385
+ suite.trackingDisabled ||
386
+ !suite.client ||
387
+ !suite.experimentId) {
388
+ return undefined;
389
+ }
390
+ const example = suite.exampleIdsByTest.get(run.logicalName);
391
+ if (!example) {
392
+ return undefined;
393
+ }
394
+ try {
395
+ const res = await suite.client.POST("/v1/experiments/{experiment_id}/runs", {
396
+ params: { path: { experiment_id: suite.experimentId } },
397
+ body: {
398
+ dataset_example_id: example.nodeId,
399
+ output: run.outputSet
400
+ ? run.output
401
+ : null,
402
+ repetition_number: run.repetitionNumber,
403
+ start_time: run.startTime.toISOString(),
404
+ end_time: (run.taskEndTime ??
405
+ run.endTime ??
406
+ new Date()).toISOString(),
407
+ error: run.error ?? null,
408
+ trace_id: run.traceId ?? null,
409
+ },
410
+ });
411
+ return res.data?.data.id;
412
+ }
413
+ catch {
414
+ suite.uploadFailureCount = (suite.uploadFailureCount ?? 0) + 1;
415
+ return undefined;
416
+ }
417
+ }
418
+ /**
419
+ * POST one annotation (an "experiment_evaluation") for a run.
420
+ */
421
+ export async function postAnnotation(suite, runId, annotation) {
422
+ if (suite.trackingDisabled || !suite.client || !runId)
423
+ return;
424
+ const start = new Date();
425
+ const end = new Date();
426
+ try {
427
+ await suite.client.POST("/v1/experiment_evaluations", {
428
+ body: {
429
+ experiment_run_id: runId,
430
+ name: annotation.name,
431
+ annotator_kind: annotation.annotatorKind ?? "CODE",
432
+ start_time: start.toISOString(),
433
+ end_time: end.toISOString(),
434
+ result: {
435
+ score: typeof annotation.score === "boolean"
436
+ ? annotation.score
437
+ ? 1
438
+ : 0
439
+ : (annotation.score ?? null),
440
+ label: annotation.label ?? null,
441
+ explanation: annotation.explanation ?? null,
442
+ // Forward annotation metadata, matching the experiment evaluator
443
+ // upload path in `runExperiment`. Spread so it's omitted when unset.
444
+ ...(annotation.metadata ? { metadata: annotation.metadata } : {}),
445
+ },
446
+ error: null,
447
+ trace_id: annotation.traceId ?? null,
448
+ },
449
+ });
450
+ }
451
+ catch {
452
+ suite.uploadFailureCount = (suite.uploadFailureCount ?? 0) + 1;
453
+ }
454
+ }
455
+ /** Run an evaluator in an OpenInference evaluator span. */
456
+ export async function runEvaluatorWithTracing(suite, name, params, fn) {
457
+ const isDryRun = currentRun()?.dryRun ?? false;
458
+ const tracer = isDryRun
459
+ ? getNoOpTracer()
460
+ : (suite.evaluatorTracer ?? suite.tracer ?? getNoOpTracer());
461
+ const parentlessContext = trace.deleteSpan(context.active());
462
+ const evaluatorContext = isDryRun
463
+ ? suppressTracing(parentlessContext)
464
+ : parentlessContext;
465
+ return context.with(evaluatorContext, () => tracer.startActiveSpan(`Evaluation: ${name}`, async (span) => {
466
+ const traceId = isDryRun ? null : span.spanContext().traceId;
467
+ try {
468
+ const result = await fn(params);
469
+ span.setAttributes({
470
+ [SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.EVALUATOR,
471
+ [SemanticConventions.INPUT_MIME_TYPE]: MimeType.JSON,
472
+ [SemanticConventions.INPUT_VALUE]: ensureString(params),
473
+ [SemanticConventions.OUTPUT_MIME_TYPE]: MimeType.JSON,
474
+ [SemanticConventions.OUTPUT_VALUE]: ensureString(result),
475
+ });
476
+ span.setStatus({ code: SpanStatusCode.OK });
477
+ return { result, traceId };
478
+ }
479
+ catch (err) {
480
+ const error = err instanceof Error ? err : new Error(String(err));
481
+ span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
482
+ throw error;
483
+ }
484
+ finally {
485
+ span.end();
486
+ }
487
+ }));
488
+ }
489
+ /**
490
+ * Tear down the tracer provider created for the suite, flushing any pending
491
+ * spans before the process exits.
492
+ */
493
+ export async function teardownSuite(suite) {
494
+ const provider = suite.tracerProvider;
495
+ if (!provider)
496
+ return;
497
+ try {
498
+ await cleanupOwnedTracerProvider({
499
+ provider,
500
+ globalRegistration: suite.globalRegistration,
501
+ });
502
+ }
503
+ finally {
504
+ suite.tracerProvider = undefined;
505
+ suite.globalRegistration = null;
506
+ }
507
+ }
508
+ /**
509
+ * Snapshot environment-derived metadata recorded on the experiment so users
510
+ * can filter experiments by env in the Phoenix UI.
511
+ */
512
+ function envMetadata() {
513
+ const out = {};
514
+ const env = process.env.PHOENIX_ENVIRONMENT ??
515
+ process.env.ENVIRONMENT ??
516
+ process.env.NODE_ENV;
517
+ if (env)
518
+ out.environment = env;
519
+ return out;
520
+ }
521
+ //# sourceMappingURL=phoenix-test-tracking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phoenix-test-tracking.js","sourceRoot":"","sources":["../../../src/testing/phoenix-test-tracking.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { SuiteSummary } from "./reporter-format.js";
2
+ import type { SuiteState } from "./state.js";
3
+ /**
4
+ * Env var that overrides where suite summary artifacts are written. When unset,
5
+ * a stable per-project subdirectory of the OS temp dir is used (see
6
+ * {@link getSuiteSummaryReportDir}).
7
+ */
8
+ export declare const PHOENIX_TEST_REPORT_DIR_ENV_VAR = "PHOENIX_TEST_REPORT_DIR";
9
+ /**
10
+ * Resolve the directory where suite summary artifacts are written and read.
11
+ *
12
+ * Honors {@link PHOENIX_TEST_REPORT_DIR_ENV_VAR} when set. Otherwise it derives
13
+ * a directory under the OS temp dir, namespaced by a hash of the current
14
+ * working directory so that concurrent test runs in different projects don't
15
+ * read each other's artifacts.
16
+ */
17
+ export declare function getSuiteSummaryReportDir(): string;
18
+ /**
19
+ * Delete any artifacts left over from a previous run. The reporter calls this
20
+ * at the start of every run so summaries from an earlier watch-mode invocation
21
+ * don't bleed into the next one.
22
+ */
23
+ export declare function clearSuiteSummaryArtifacts(): void;
24
+ /**
25
+ * Write one suite's summary to the report directory. Called from each worker
26
+ * when a suite finishes.
27
+ *
28
+ * The file is written to a `.tmp` path first and then atomically renamed into
29
+ * place, so the reader never observes a half-written artifact. Failures are
30
+ * intentionally swallowed — reporting must not break the user's tests.
31
+ */
32
+ export declare function writeSuiteSummaryArtifact(suite: SuiteState): void;
33
+ /**
34
+ * Read back all suite summaries the workers wrote during this run, sorted by
35
+ * suite name for stable output.
36
+ *
37
+ * @param sinceMs - When provided, only artifacts created at or after this
38
+ * timestamp are returned, so summaries from a previous run that share the
39
+ * report directory are ignored. A one-second slack is allowed to absorb
40
+ * small clock differences between worker processes.
41
+ */
42
+ export declare function readSuiteSummaryArtifacts({ sinceMs, }?: {
43
+ sinceMs?: number;
44
+ }): SuiteSummary[];
45
+ //# sourceMappingURL=report-artifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-artifacts.d.ts","sourceRoot":"","sources":["../../../src/testing/report-artifacts.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,SAAS,CAAC;AAEtD;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,4BAA4B,CAAC;AAazE;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAUjD;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAajD;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAiBjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,OAAO,GACR,GAAE;IACD,OAAO,CAAC,EAAE,MAAM,CAAC;CACb,GAAG,YAAY,EAAE,CAoCtB"}