@arizeai/phoenix-client 7.1.1 → 7.3.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 (132) hide show
  1. package/README.md +28 -2
  2. package/dist/esm/__generated__/api/v1.d.ts +315 -9
  3. package/dist/esm/__generated__/api/v1.d.ts.map +1 -1
  4. package/dist/esm/client.d.ts +10 -2
  5. package/dist/esm/client.d.ts.map +1 -1
  6. package/dist/esm/client.js +6 -0
  7. package/dist/esm/client.js.map +1 -1
  8. package/dist/esm/config.d.ts +10 -0
  9. package/dist/esm/config.d.ts.map +1 -1
  10. package/dist/esm/config.js +13 -9
  11. package/dist/esm/config.js.map +1 -1
  12. package/dist/esm/experiments/getExperiment.d.ts.map +1 -1
  13. package/dist/esm/experiments/getExperiment.js.map +1 -1
  14. package/dist/esm/experiments/resumeEvaluation.d.ts.map +1 -1
  15. package/dist/esm/experiments/resumeEvaluation.js +5 -5
  16. package/dist/esm/experiments/resumeEvaluation.js.map +1 -1
  17. package/dist/esm/experiments/resumeExperiment.d.ts.map +1 -1
  18. package/dist/esm/experiments/resumeExperiment.js +5 -5
  19. package/dist/esm/experiments/resumeExperiment.js.map +1 -1
  20. package/dist/esm/experiments/runExperiment.d.ts.map +1 -1
  21. package/dist/esm/experiments/runExperiment.js +5 -5
  22. package/dist/esm/experiments/runExperiment.js.map +1 -1
  23. package/dist/esm/experiments/tracing.d.ts +27 -0
  24. package/dist/esm/experiments/tracing.d.ts.map +1 -1
  25. package/dist/esm/experiments/tracing.js +27 -0
  26. package/dist/esm/experiments/tracing.js.map +1 -1
  27. package/dist/esm/projects/getProjects.d.ts +31 -0
  28. package/dist/esm/projects/getProjects.d.ts.map +1 -0
  29. package/dist/esm/projects/getProjects.js +45 -0
  30. package/dist/esm/projects/getProjects.js.map +1 -0
  31. package/dist/esm/projects/index.d.ts +2 -0
  32. package/dist/esm/projects/index.d.ts.map +1 -0
  33. package/dist/esm/projects/index.js +2 -0
  34. package/dist/esm/projects/index.js.map +1 -0
  35. package/dist/esm/prompts/createPrompt.js +1 -1
  36. package/dist/esm/prompts/createPrompt.js.map +1 -1
  37. package/dist/esm/prompts/sdks/toSDK.js +1 -1
  38. package/dist/esm/prompts/sdks/toSDK.js.map +1 -1
  39. package/dist/esm/schemas/llm/converters.js +5 -5
  40. package/dist/esm/schemas/llm/converters.js.map +1 -1
  41. package/dist/esm/schemas/llm/openai/converters.js +3 -3
  42. package/dist/esm/schemas/llm/openai/converters.js.map +1 -1
  43. package/dist/esm/schemas/llm/phoenixPrompt/converters.d.ts.map +1 -1
  44. package/dist/esm/schemas/llm/phoenixPrompt/converters.js +2 -0
  45. package/dist/esm/schemas/llm/phoenixPrompt/converters.js.map +1 -1
  46. package/dist/esm/testing/phoenix-test-tracking.d.ts.map +1 -1
  47. package/dist/esm/testing/phoenix-test-tracking.js +9 -9
  48. package/dist/esm/testing/phoenix-test-tracking.js.map +1 -1
  49. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  50. package/dist/esm/types/projects.d.ts +5 -0
  51. package/dist/esm/types/projects.d.ts.map +1 -1
  52. package/dist/esm/types/projects.js.map +1 -1
  53. package/dist/esm/utils/serverVersionUtils.d.ts.map +1 -1
  54. package/dist/esm/utils/serverVersionUtils.js +3 -0
  55. package/dist/esm/utils/serverVersionUtils.js.map +1 -1
  56. package/dist/src/__generated__/api/v1.d.ts +315 -9
  57. package/dist/src/__generated__/api/v1.d.ts.map +1 -1
  58. package/dist/src/client.d.ts +10 -2
  59. package/dist/src/client.d.ts.map +1 -1
  60. package/dist/src/client.js +6 -1
  61. package/dist/src/client.js.map +1 -1
  62. package/dist/src/config.d.ts +10 -0
  63. package/dist/src/config.d.ts.map +1 -1
  64. package/dist/src/config.js +11 -7
  65. package/dist/src/config.js.map +1 -1
  66. package/dist/src/experiments/getExperiment.d.ts.map +1 -1
  67. package/dist/src/experiments/getExperiment.js.map +1 -1
  68. package/dist/src/experiments/resumeEvaluation.d.ts.map +1 -1
  69. package/dist/src/experiments/resumeEvaluation.js +4 -4
  70. package/dist/src/experiments/resumeEvaluation.js.map +1 -1
  71. package/dist/src/experiments/resumeExperiment.d.ts.map +1 -1
  72. package/dist/src/experiments/resumeExperiment.js +4 -4
  73. package/dist/src/experiments/resumeExperiment.js.map +1 -1
  74. package/dist/src/experiments/runExperiment.d.ts.map +1 -1
  75. package/dist/src/experiments/runExperiment.js +4 -4
  76. package/dist/src/experiments/runExperiment.js.map +1 -1
  77. package/dist/src/experiments/tracing.d.ts +27 -0
  78. package/dist/src/experiments/tracing.d.ts.map +1 -1
  79. package/dist/src/experiments/tracing.js +30 -0
  80. package/dist/src/experiments/tracing.js.map +1 -1
  81. package/dist/src/projects/getProjects.d.ts +31 -0
  82. package/dist/src/projects/getProjects.d.ts.map +1 -0
  83. package/dist/src/projects/getProjects.js +53 -0
  84. package/dist/src/projects/getProjects.js.map +1 -0
  85. package/dist/src/projects/index.d.ts +2 -0
  86. package/dist/src/projects/index.d.ts.map +1 -0
  87. package/dist/src/projects/index.js +18 -0
  88. package/dist/src/projects/index.js.map +1 -0
  89. package/dist/src/prompts/createPrompt.js +1 -1
  90. package/dist/src/prompts/createPrompt.js.map +1 -1
  91. package/dist/src/prompts/sdks/toSDK.js +1 -1
  92. package/dist/src/prompts/sdks/toSDK.js.map +1 -1
  93. package/dist/src/schemas/llm/converters.js +5 -5
  94. package/dist/src/schemas/llm/converters.js.map +1 -1
  95. package/dist/src/schemas/llm/openai/converters.js +3 -3
  96. package/dist/src/schemas/llm/openai/converters.js.map +1 -1
  97. package/dist/src/schemas/llm/phoenixPrompt/converters.d.ts.map +1 -1
  98. package/dist/src/schemas/llm/phoenixPrompt/converters.js +2 -0
  99. package/dist/src/schemas/llm/phoenixPrompt/converters.js.map +1 -1
  100. package/dist/src/testing/phoenix-test-tracking.d.ts.map +1 -1
  101. package/dist/src/testing/phoenix-test-tracking.js +8 -8
  102. package/dist/src/testing/phoenix-test-tracking.js.map +1 -1
  103. package/dist/src/types/projects.d.ts +5 -0
  104. package/dist/src/types/projects.d.ts.map +1 -1
  105. package/dist/src/types/projects.js.map +1 -1
  106. package/dist/src/utils/serverVersionUtils.d.ts.map +1 -1
  107. package/dist/src/utils/serverVersionUtils.js +3 -0
  108. package/dist/src/utils/serverVersionUtils.js.map +1 -1
  109. package/dist/tsconfig.tsbuildinfo +1 -1
  110. package/docs/ci-evals-jest.mdx +1 -1
  111. package/docs/ci-evals-vitest.mdx +1 -1
  112. package/docs/ci-evals.mdx +1 -1
  113. package/docs/overview.mdx +5 -5
  114. package/package.json +15 -11
  115. package/src/__generated__/api/v1.ts +315 -9
  116. package/src/client.ts +17 -1
  117. package/src/config.ts +28 -11
  118. package/src/experiments/getExperiment.ts +4 -7
  119. package/src/experiments/resumeEvaluation.ts +11 -9
  120. package/src/experiments/resumeExperiment.ts +11 -9
  121. package/src/experiments/runExperiment.ts +9 -11
  122. package/src/experiments/tracing.ts +35 -0
  123. package/src/projects/getProjects.ts +69 -0
  124. package/src/projects/index.ts +1 -0
  125. package/src/prompts/createPrompt.ts +1 -1
  126. package/src/prompts/sdks/toSDK.ts +1 -1
  127. package/src/schemas/llm/converters.ts +5 -5
  128. package/src/schemas/llm/openai/converters.ts +3 -3
  129. package/src/schemas/llm/phoenixPrompt/converters.ts +2 -0
  130. package/src/testing/phoenix-test-tracking.ts +12 -9
  131. package/src/types/projects.ts +7 -0
  132. package/src/utils/serverVersionUtils.ts +3 -0
@@ -31,7 +31,11 @@ import { getExperimentInfo } from "./getExperimentInfo.js";
31
31
  import { getExperimentEvaluators } from "./helpers";
32
32
  import { getExampleGlobalId } from "./helpers/getExampleGlobalId";
33
33
  import { logEvalResumeSummary, PROGRESS_PREFIX } from "./logging";
34
- import { cleanupOwnedTracerProvider } from "./tracing";
34
+ import {
35
+ cleanupOwnedTracerProvider,
36
+ getTraceExportUrl,
37
+ MISSING_BASE_URL_MESSAGE,
38
+ } from "./tracing";
35
39
 
36
40
  /**
37
41
  * Error thrown when evaluation is aborted due to a failure in stopOnFirstError mode.
@@ -199,14 +203,15 @@ async function handleEvaluationFetchError(
199
203
  */
200
204
  function setupEvaluationTracer({
201
205
  projectName,
202
- baseUrl,
206
+ traceExportUrl,
203
207
  headers,
204
208
  useBatchSpanProcessor,
205
209
  diagLogLevel,
206
210
  setGlobalTracerProvider,
207
211
  }: {
208
212
  projectName: string | null;
209
- baseUrl: string;
213
+ /** Where spans are exported; omit to let `register()` read the environment. */
214
+ traceExportUrl?: string;
210
215
  headers?: Record<string, string>;
211
216
  useBatchSpanProcessor: boolean;
212
217
  diagLogLevel?: DiagLogLevel;
@@ -222,7 +227,7 @@ function setupEvaluationTracer({
222
227
 
223
228
  const provider = register({
224
229
  projectName,
225
- url: baseUrl,
230
+ url: traceExportUrl,
226
231
  headers,
227
232
  batch: useBatchSpanProcessor,
228
233
  diagLogLevel,
@@ -323,14 +328,11 @@ export async function resumeEvaluation({
323
328
 
324
329
  // Initialize tracer (only if experiment has a project_name)
325
330
  const baseUrl = client.config.baseUrl;
326
- invariant(
327
- baseUrl,
328
- "Phoenix base URL not found. Please set PHOENIX_HOST or set baseUrl on the client."
329
- );
331
+ invariant(baseUrl, MISSING_BASE_URL_MESSAGE);
330
332
 
331
333
  const tracerSetup = setupEvaluationTracer({
332
334
  projectName: experiment.projectName,
333
- baseUrl,
335
+ traceExportUrl: getTraceExportUrl(client.config),
334
336
  headers: client.config.headers
335
337
  ? toObjectHeaders(client.config.headers)
336
338
  : undefined,
@@ -35,7 +35,11 @@ import {
35
35
  PROGRESS_PREFIX,
36
36
  } from "./logging";
37
37
  import { resumeEvaluation } from "./resumeEvaluation";
38
- import { cleanupOwnedTracerProvider } from "./tracing";
38
+ import {
39
+ cleanupOwnedTracerProvider,
40
+ getTraceExportUrl,
41
+ MISSING_BASE_URL_MESSAGE,
42
+ } from "./tracing";
39
43
 
40
44
  /**
41
45
  * Error thrown when task is aborted due to a failure in stopOnFirstError mode.
@@ -182,14 +186,15 @@ async function handleFetchError(
182
186
  */
183
187
  function setupTracer({
184
188
  projectName,
185
- baseUrl,
189
+ traceExportUrl,
186
190
  headers,
187
191
  useBatchSpanProcessor,
188
192
  diagLogLevel,
189
193
  setGlobalTracerProvider,
190
194
  }: {
191
195
  projectName: string | null;
192
- baseUrl: string;
196
+ /** Where spans are exported; omit to let `register()` read the environment. */
197
+ traceExportUrl?: string;
193
198
  headers?: Record<string, string>;
194
199
  useBatchSpanProcessor: boolean;
195
200
  diagLogLevel?: DiagLogLevel;
@@ -205,7 +210,7 @@ function setupTracer({
205
210
 
206
211
  const provider = register({
207
212
  projectName,
208
- url: baseUrl,
213
+ url: traceExportUrl,
209
214
  headers,
210
215
  batch: useBatchSpanProcessor,
211
216
  diagLogLevel,
@@ -307,15 +312,12 @@ export async function resumeExperiment({
307
312
 
308
313
  // Get base URL for tracing and URL generation
309
314
  const baseUrl = client.config.baseUrl;
310
- invariant(
311
- baseUrl,
312
- "Phoenix base URL not found. Please set PHOENIX_HOST or set baseUrl on the client."
313
- );
315
+ invariant(baseUrl, MISSING_BASE_URL_MESSAGE);
314
316
 
315
317
  // Initialize tracer (only if experiment has a project_name)
316
318
  const tracerSetup = setupTracer({
317
319
  projectName: experiment.projectName,
318
- baseUrl,
320
+ traceExportUrl: getTraceExportUrl(client.config),
319
321
  headers: client.config.headers
320
322
  ? toObjectHeaders(client.config.headers)
321
323
  : undefined,
@@ -54,7 +54,11 @@ import {
54
54
  logTaskSummary,
55
55
  PROGRESS_PREFIX,
56
56
  } from "./logging";
57
- import { cleanupOwnedTracerProvider } from "./tracing";
57
+ import {
58
+ cleanupOwnedTracerProvider,
59
+ getTraceExportUrl,
60
+ MISSING_BASE_URL_MESSAGE,
61
+ } from "./tracing";
58
62
 
59
63
  /**
60
64
  * Validate that a repetition is valid
@@ -270,14 +274,11 @@ export async function runExperiment({
270
274
  };
271
275
  // Initialize the tracer, now that we have a project name
272
276
  const baseUrl = client.config.baseUrl;
273
- invariant(
274
- baseUrl,
275
- "Phoenix base URL not found. Please set PHOENIX_HOST or set baseUrl on the client."
276
- );
277
+ invariant(baseUrl, MISSING_BASE_URL_MESSAGE);
277
278
 
278
279
  taskProvider = register({
279
280
  projectName,
280
- url: baseUrl,
281
+ url: getTraceExportUrl(client.config),
281
282
  headers: client.config.headers
282
283
  ? toObjectHeaders(client.config.headers)
283
284
  : undefined,
@@ -621,10 +622,7 @@ export async function evaluateExperiment({
621
622
  const isDryRun = typeof dryRun === "number" || dryRun === true;
622
623
  const client = _client ?? createClient();
623
624
  const baseUrl = client.config.baseUrl;
624
- invariant(
625
- baseUrl,
626
- "Phoenix base URL not found. Please set PHOENIX_HOST or set baseUrl on the client."
627
- );
625
+ invariant(baseUrl, MISSING_BASE_URL_MESSAGE);
628
626
  let provider: NodeTracerProvider;
629
627
  let globalRegistration: GlobalTracerProviderRegistration | null = null;
630
628
  const ownsProvider = !paramsTracerProvider;
@@ -635,7 +633,7 @@ export async function evaluateExperiment({
635
633
  } else if (!isDryRun) {
636
634
  provider = register({
637
635
  projectName: "evaluators",
638
- url: baseUrl,
636
+ url: getTraceExportUrl(client.config),
639
637
  headers: client.config.headers
640
638
  ? toObjectHeaders(client.config.headers)
641
639
  : undefined,
@@ -3,6 +3,41 @@ import type {
3
3
  NodeTracerProvider,
4
4
  } from "@arizeai/phoenix-otel";
5
5
 
6
+ import type { BaseUrlSource } from "../config";
7
+
8
+ /**
9
+ * Message for the invariant shared by every experiment entry point: a base URL
10
+ * must be resolvable before a tracer can be registered.
11
+ */
12
+ export const MISSING_BASE_URL_MESSAGE =
13
+ "Phoenix base URL not found. Please set PHOENIX_ENDPOINT (or PHOENIX_COLLECTOR_ENDPOINT) or set baseUrl on the client.";
14
+
15
+ /**
16
+ * Resolves the URL experiment spans are exported to, as the `url` argument to
17
+ * `register()`.
18
+ *
19
+ * Explicit code-level configuration outranks the ambient environment: a client
20
+ * created with an explicit `baseUrl` exports its spans to that server, so a
21
+ * `PHOENIX_COLLECTOR_ENDPOINT` left in the shell cannot silently retarget it.
22
+ * When the base URL itself came from the environment, so does trace export:
23
+ * returning `undefined` hands resolution to `register()`, which reads the
24
+ * trace-export chain (`PHOENIX_COLLECTOR_ENDPOINT`, the OTel-standard
25
+ * variables, then `PHOENIX_ENDPOINT`) exactly as a standalone `register()`
26
+ * call would.
27
+ *
28
+ * A base URL of unknown provenance — a hand-built client rather than one from
29
+ * `createClient()` — counts as explicit, since only deliberate configuration
30
+ * puts a URL there.
31
+ */
32
+ export function getTraceExportUrl(config: {
33
+ baseUrl?: string;
34
+ baseUrlSource?: BaseUrlSource;
35
+ }): string | undefined {
36
+ return (config.baseUrlSource ?? "explicit") === "explicit"
37
+ ? config.baseUrl
38
+ : undefined;
39
+ }
40
+
6
41
  /**
7
42
  * Flushes and shuts down a tracer provider that this package created, then
8
43
  * detaches any global OTEL registration it owns so another provider can be mounted.
@@ -0,0 +1,69 @@
1
+ import invariant from "tiny-invariant";
2
+
3
+ import type { components } from "../__generated__/api/v1";
4
+ import { createClient } from "../client";
5
+ import type { ClientFn } from "../types/core";
6
+ import type { Project } from "../types/projects";
7
+
8
+ export interface GetProjectsParams extends ClientFn {
9
+ /**
10
+ * Return only projects whose name contains this substring
11
+ * (case-insensitive). The match is performed server-side.
12
+ *
13
+ * @requires Phoenix server >= 17.16.0
14
+ */
15
+ nameContains?: string;
16
+ }
17
+
18
+ type ProjectsResponse = components["schemas"]["GetProjectsResponseBody"];
19
+
20
+ const DEFAULT_PAGE_SIZE = 100;
21
+
22
+ /**
23
+ * List projects with automatic pagination handling.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * import { getProjects } from "@arizeai/phoenix-client/projects";
28
+ *
29
+ * // Every project
30
+ * const projects = await getProjects();
31
+ *
32
+ * // Only projects whose name contains "agent" (requires Phoenix server >= 17.16.0)
33
+ * const agentProjects = await getProjects({ nameContains: "agent" });
34
+ *
35
+ * for (const project of agentProjects) {
36
+ * console.log(`Project: ${project.name} (${project.id})`);
37
+ * }
38
+ * ```
39
+ */
40
+ export async function getProjects(
41
+ params: GetProjectsParams = {}
42
+ ): Promise<Project[]> {
43
+ const client = params.client || createClient();
44
+ const { nameContains } = params;
45
+
46
+ const projects: Project[] = [];
47
+ let cursor: string | null | undefined = null;
48
+
49
+ do {
50
+ const response: { data?: ProjectsResponse; error?: unknown } =
51
+ await client.GET("/v1/projects", {
52
+ params: {
53
+ query: {
54
+ cursor,
55
+ limit: DEFAULT_PAGE_SIZE,
56
+ name_contains: nameContains,
57
+ },
58
+ },
59
+ });
60
+
61
+ if (response.error) throw response.error;
62
+ invariant(response.data?.data, "Failed to list projects");
63
+
64
+ cursor = response.data.next_cursor ?? null;
65
+ projects.push(...response.data.data);
66
+ } while (cursor != null);
67
+
68
+ return projects;
69
+ }
@@ -0,0 +1 @@
1
+ export * from "./getProjects";
@@ -301,6 +301,6 @@ export function promptVersion(params: PromptVersionInput): PromptVersionData {
301
301
  },
302
302
  };
303
303
  default:
304
- assertUnreachable(model_provider);
304
+ return assertUnreachable(model_provider);
305
305
  }
306
306
  }
@@ -42,7 +42,7 @@ const getTargetSDK = <SDK extends SupportedSDK>(sdk: SDK) => {
42
42
  case "ai":
43
43
  return PROVIDER_TO_SDK.ai;
44
44
  default:
45
- assertUnreachable(sdk);
45
+ return assertUnreachable(sdk);
46
46
  }
47
47
  };
48
48
 
@@ -294,7 +294,7 @@ export const fromOpenAIToolCall = <
294
294
  toolCall
295
295
  ) as ReturnType;
296
296
  default:
297
- assertUnreachable(targetProvider);
297
+ return assertUnreachable(targetProvider);
298
298
  }
299
299
  };
300
300
 
@@ -328,7 +328,7 @@ export const toOpenAIToolChoice = (
328
328
  validatedToolChoice
329
329
  );
330
330
  default:
331
- assertUnreachable(provider);
331
+ return assertUnreachable(provider);
332
332
  }
333
333
  };
334
334
 
@@ -373,7 +373,7 @@ export const fromOpenAIToolChoice = <
373
373
  toolChoice
374
374
  ) as ReturnType;
375
375
  default:
376
- assertUnreachable(targetProvider);
376
+ return assertUnreachable(targetProvider);
377
377
  }
378
378
  };
379
379
 
@@ -406,7 +406,7 @@ export const toOpenAIToolDefinition = (
406
406
  case null:
407
407
  return null;
408
408
  default:
409
- assertUnreachable(provider);
409
+ return assertUnreachable(provider);
410
410
  }
411
411
  };
412
412
 
@@ -447,7 +447,7 @@ export const fromOpenAIToolDefinition = <
447
447
  toolDefinition
448
448
  ) as ReturnType;
449
449
  default:
450
- assertUnreachable(targetProvider);
450
+ return assertUnreachable(targetProvider);
451
451
  }
452
452
  };
453
453
 
@@ -324,7 +324,7 @@ export const openAIMessageToVercelAI = openAIMessageSchema.transform(
324
324
  content: [],
325
325
  };
326
326
  default:
327
- assertUnreachable(role);
327
+ return assertUnreachable(role);
328
328
  }
329
329
  }
330
330
  );
@@ -354,7 +354,7 @@ export const openAIToolChoiceToAnthropic = openAIToolChoiceSchema.transform(
354
354
  case "required":
355
355
  return { type: "any" };
356
356
  default:
357
- assertUnreachable(openAI);
357
+ return assertUnreachable(openAI);
358
358
  }
359
359
  }
360
360
  );
@@ -372,7 +372,7 @@ export const openAIToolChoiceToVercelAI = openAIToolChoiceSchema.transform(
372
372
  case "required":
373
373
  return "required";
374
374
  default:
375
- assertUnreachable(openAI);
375
+ return assertUnreachable(openAI);
376
376
  }
377
377
  }
378
378
  );
@@ -172,6 +172,8 @@ export const phoenixToolChoiceToOpenAI = phoenixToolChoiceSchema.transform(
172
172
  return "required";
173
173
  case "specific_function":
174
174
  return { type: "function", function: { name: phoenix.function_name } };
175
+ default:
176
+ return assertUnreachable(phoenix);
175
177
  }
176
178
  }
177
179
  );
@@ -16,7 +16,10 @@ import {
16
16
  import type { Span } from "@opentelemetry/api";
17
17
 
18
18
  import { createDataset } from "../datasets";
19
- import { cleanupOwnedTracerProvider } from "../experiments/tracing";
19
+ import {
20
+ cleanupOwnedTracerProvider,
21
+ getTraceExportUrl,
22
+ } from "../experiments/tracing";
20
23
  import { createClient, type PhoenixClient } from "../index";
21
24
  import { ensureString } from "../utils/ensureString";
22
25
  import { toObjectHeaders } from "../utils/toObjectHeaders";
@@ -163,9 +166,9 @@ interface TaskSpanLifecycle {
163
166
  const taskSpansByRun = new WeakMap<RunState, TaskSpanLifecycle>();
164
167
 
165
168
  /**
166
- * Warn once when `PHOENIX_HOST` is plain `http:` while an `Authorization`
167
- * header is being forwarded to the OTLP exporter — that combination
168
- * exfiltrates the bearer token in cleartext.
169
+ * Warn once when the resolved base URL is plain `http:` while an
170
+ * `Authorization` header is being forwarded to the OTLP exporter — that
171
+ * combination exfiltrates the bearer token in cleartext.
169
172
  */
170
173
  let warnedAboutHttpScheme = false;
171
174
  function maybeWarnHttpScheme(
@@ -191,9 +194,9 @@ function maybeWarnHttpScheme(
191
194
  warnedAboutHttpScheme = true;
192
195
  // eslint-disable-next-line no-console
193
196
  console.warn(
194
- `[@arizeai/phoenix-client] PHOENIX_HOST="${baseUrl}" uses http:// with ` +
195
- `an Authorization header set; the bearer token will travel in cleartext. ` +
196
- `Use https:// for non-localhost Phoenix endpoints.`
197
+ `[@arizeai/phoenix-client] The Phoenix base URL "${baseUrl}" uses http:// ` +
198
+ `with an Authorization header set; the bearer token will travel in ` +
199
+ `cleartext. Use https:// for non-localhost Phoenix endpoints.`
197
200
  );
198
201
  }
199
202
 
@@ -349,7 +352,7 @@ export async function initializeSuite(suite: SuiteState): Promise<void> {
349
352
  if (!baseUrl) {
350
353
  suite.trackingDisabled = true;
351
354
  suite.setupError = new Error(
352
- "Phoenix base URL not found. Set PHOENIX_HOST or pass baseUrl on the client."
355
+ "Phoenix base URL not found. Set PHOENIX_ENDPOINT (or PHOENIX_COLLECTOR_ENDPOINT) or pass baseUrl on the client."
353
356
  );
354
357
  suite.tracer = createNoOpProvider().getTracer("no-op");
355
358
  suite.evaluatorTracer = suite.tracer;
@@ -362,7 +365,7 @@ export async function initializeSuite(suite: SuiteState): Promise<void> {
362
365
  try {
363
366
  provider = register({
364
367
  projectName: suite.projectName,
365
- url: baseUrl,
368
+ url: getTraceExportUrl(client.config),
366
369
  headers: client.config.headers
367
370
  ? toObjectHeaders(client.config.headers)
368
371
  : undefined,
@@ -1,3 +1,10 @@
1
+ import type { components } from "../__generated__/api/v1";
2
+
3
+ /**
4
+ * A project as returned by the Phoenix REST API.
5
+ */
6
+ export type Project = components["schemas"]["Project"];
7
+
1
8
  /**
2
9
  * Identifies a project. Accepts any of:
3
10
  * - `project` — a project ID or name (the server accepts either)
@@ -20,6 +20,7 @@
20
20
 
21
21
  import type { PhoenixClient } from "../client";
22
22
  import type { CapabilityRequirement } from "../types/serverRequirements";
23
+ import { assertUnreachable } from "./assertUnreachable";
23
24
  import { formatVersion, satisfiesMinVersion } from "./semverUtils";
24
25
 
25
26
  // ---------------------------------------------------------------------------
@@ -37,6 +38,8 @@ export function capabilityLabel(req: CapabilityRequirement): string {
37
38
  return `The ${req.method} ${req.path} route`;
38
39
  case "parameter":
39
40
  return `The '${req.parameterName}' ${req.parameterLocation} parameter on ${req.route}`;
41
+ default:
42
+ return assertUnreachable(req);
40
43
  }
41
44
  }
42
45