@arizeai/phoenix-client 6.8.1 → 6.9.1

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 (103) hide show
  1. package/README.md +78 -0
  2. package/dist/esm/__generated__/api/v1.d.ts +30 -15
  3. package/dist/esm/__generated__/api/v1.d.ts.map +1 -1
  4. package/dist/esm/constants/serverRequirements.d.ts +1 -0
  5. package/dist/esm/constants/serverRequirements.d.ts.map +1 -1
  6. package/dist/esm/constants/serverRequirements.js +7 -0
  7. package/dist/esm/constants/serverRequirements.js.map +1 -1
  8. package/dist/esm/sessions/addSessionNote.d.ts +45 -0
  9. package/dist/esm/sessions/addSessionNote.d.ts.map +1 -0
  10. package/dist/esm/sessions/addSessionNote.js +45 -0
  11. package/dist/esm/sessions/addSessionNote.js.map +1 -0
  12. package/dist/esm/sessions/index.d.ts +1 -0
  13. package/dist/esm/sessions/index.d.ts.map +1 -1
  14. package/dist/esm/sessions/index.js +1 -0
  15. package/dist/esm/sessions/index.js.map +1 -1
  16. package/dist/esm/spans/addSpanNote.d.ts +5 -3
  17. package/dist/esm/spans/addSpanNote.d.ts.map +1 -1
  18. package/dist/esm/spans/addSpanNote.js +7 -4
  19. package/dist/esm/spans/addSpanNote.js.map +1 -1
  20. package/dist/esm/traces/addTraceAnnotation.d.ts +43 -0
  21. package/dist/esm/traces/addTraceAnnotation.d.ts.map +1 -0
  22. package/dist/esm/traces/addTraceAnnotation.js +43 -0
  23. package/dist/esm/traces/addTraceAnnotation.js.map +1 -0
  24. package/dist/esm/traces/addTraceNote.d.ts +5 -2
  25. package/dist/esm/traces/addTraceNote.d.ts.map +1 -1
  26. package/dist/esm/traces/addTraceNote.js +7 -3
  27. package/dist/esm/traces/addTraceNote.js.map +1 -1
  28. package/dist/esm/traces/index.d.ts +3 -0
  29. package/dist/esm/traces/index.d.ts.map +1 -1
  30. package/dist/esm/traces/index.js +2 -0
  31. package/dist/esm/traces/index.js.map +1 -1
  32. package/dist/esm/traces/logTraceAnnotations.d.ts +53 -0
  33. package/dist/esm/traces/logTraceAnnotations.d.ts.map +1 -0
  34. package/dist/esm/traces/logTraceAnnotations.js +50 -0
  35. package/dist/esm/traces/logTraceAnnotations.js.map +1 -0
  36. package/dist/esm/traces/types.d.ts +24 -0
  37. package/dist/esm/traces/types.d.ts.map +1 -0
  38. package/dist/esm/traces/types.js +38 -0
  39. package/dist/esm/traces/types.js.map +1 -0
  40. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  41. package/dist/esm/utils/apiErrorUtils.d.ts +2 -0
  42. package/dist/esm/utils/apiErrorUtils.d.ts.map +1 -0
  43. package/dist/esm/utils/apiErrorUtils.js +19 -0
  44. package/dist/esm/utils/apiErrorUtils.js.map +1 -0
  45. package/dist/esm/utils/formatPromptMessages.d.ts.map +1 -1
  46. package/dist/esm/utils/getPromptBySelector.d.ts.map +1 -1
  47. package/dist/src/__generated__/api/v1.d.ts +30 -15
  48. package/dist/src/__generated__/api/v1.d.ts.map +1 -1
  49. package/dist/src/constants/serverRequirements.d.ts +1 -0
  50. package/dist/src/constants/serverRequirements.d.ts.map +1 -1
  51. package/dist/src/constants/serverRequirements.js +8 -1
  52. package/dist/src/constants/serverRequirements.js.map +1 -1
  53. package/dist/src/sessions/addSessionNote.d.ts +45 -0
  54. package/dist/src/sessions/addSessionNote.d.ts.map +1 -0
  55. package/dist/src/sessions/addSessionNote.js +48 -0
  56. package/dist/src/sessions/addSessionNote.js.map +1 -0
  57. package/dist/src/sessions/index.d.ts +1 -0
  58. package/dist/src/sessions/index.d.ts.map +1 -1
  59. package/dist/src/sessions/index.js +1 -0
  60. package/dist/src/sessions/index.js.map +1 -1
  61. package/dist/src/spans/addSpanNote.d.ts +5 -3
  62. package/dist/src/spans/addSpanNote.d.ts.map +1 -1
  63. package/dist/src/spans/addSpanNote.js +7 -4
  64. package/dist/src/spans/addSpanNote.js.map +1 -1
  65. package/dist/src/traces/addTraceAnnotation.d.ts +43 -0
  66. package/dist/src/traces/addTraceAnnotation.d.ts.map +1 -0
  67. package/dist/src/traces/addTraceAnnotation.js +47 -0
  68. package/dist/src/traces/addTraceAnnotation.js.map +1 -0
  69. package/dist/src/traces/addTraceNote.d.ts +5 -2
  70. package/dist/src/traces/addTraceNote.d.ts.map +1 -1
  71. package/dist/src/traces/addTraceNote.js +7 -3
  72. package/dist/src/traces/addTraceNote.js.map +1 -1
  73. package/dist/src/traces/index.d.ts +3 -0
  74. package/dist/src/traces/index.d.ts.map +1 -1
  75. package/dist/src/traces/index.js +2 -0
  76. package/dist/src/traces/index.js.map +1 -1
  77. package/dist/src/traces/logTraceAnnotations.d.ts +53 -0
  78. package/dist/src/traces/logTraceAnnotations.d.ts.map +1 -0
  79. package/dist/src/traces/logTraceAnnotations.js +53 -0
  80. package/dist/src/traces/logTraceAnnotations.js.map +1 -0
  81. package/dist/src/traces/types.d.ts +24 -0
  82. package/dist/src/traces/types.d.ts.map +1 -0
  83. package/dist/src/traces/types.js +42 -0
  84. package/dist/src/traces/types.js.map +1 -0
  85. package/dist/src/utils/apiErrorUtils.d.ts +2 -0
  86. package/dist/src/utils/apiErrorUtils.d.ts.map +1 -0
  87. package/dist/src/utils/apiErrorUtils.js +22 -0
  88. package/dist/src/utils/apiErrorUtils.js.map +1 -0
  89. package/dist/src/utils/formatPromptMessages.d.ts.map +1 -1
  90. package/dist/src/utils/getPromptBySelector.d.ts.map +1 -1
  91. package/dist/tsconfig.tsbuildinfo +1 -1
  92. package/package.json +4 -4
  93. package/src/__generated__/api/v1.ts +30 -15
  94. package/src/constants/serverRequirements.ts +8 -0
  95. package/src/sessions/addSessionNote.ts +74 -0
  96. package/src/sessions/index.ts +1 -0
  97. package/src/spans/addSpanNote.ts +7 -4
  98. package/src/traces/addTraceAnnotation.ts +65 -0
  99. package/src/traces/addTraceNote.ts +7 -3
  100. package/src/traces/index.ts +3 -0
  101. package/src/traces/logTraceAnnotations.ts +75 -0
  102. package/src/traces/types.ts +72 -0
  103. package/src/utils/apiErrorUtils.ts +17 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arizeai/phoenix-client",
3
- "version": "6.8.1",
3
+ "version": "6.9.1",
4
4
  "description": "A client for the Phoenix API",
5
5
  "keywords": [
6
6
  "arize",
@@ -79,8 +79,8 @@
79
79
  "openapi-fetch": "^0.12.5",
80
80
  "tiny-invariant": "^1.3.3",
81
81
  "zod": "^4.0.14",
82
- "@arizeai/phoenix-config": "0.1.3",
83
- "@arizeai/phoenix-otel": "1.0.0"
82
+ "@arizeai/phoenix-config": "0.1.4",
83
+ "@arizeai/phoenix-otel": "1.0.1"
84
84
  },
85
85
  "devDependencies": {
86
86
  "@ai-sdk/openai": "^3.0.29",
@@ -94,7 +94,7 @@
94
94
  "openapi-typescript": "^7.6.1",
95
95
  "tsx": "^4.19.3",
96
96
  "vitest": "^4.1.0",
97
- "@arizeai/phoenix-evals": "1.0.2"
97
+ "@arizeai/phoenix-evals": "1.0.3"
98
98
  },
99
99
  "peerDependencies": {
100
100
  "@anthropic-ai/sdk": "^0.35.0",
@@ -67,7 +67,10 @@ export interface paths {
67
67
  path?: never;
68
68
  cookie?: never;
69
69
  };
70
- /** Get span annotations for a list of span_ids. */
70
+ /**
71
+ * Get span annotations filtered by span_ids and/or identifier.
72
+ * @description Return span annotations for a project, filtered by `span_ids`, `identifier`, or both. At least one of `span_ids` or `identifier` must be supplied. When both are supplied, results are the AND-intersection of the two filters.
73
+ */
71
74
  get: operations["listSpanAnnotationsBySpanIds"];
72
75
  put?: never;
73
76
  post?: never;
@@ -84,7 +87,10 @@ export interface paths {
84
87
  path?: never;
85
88
  cookie?: never;
86
89
  };
87
- /** Get trace annotations for a list of trace_ids. */
90
+ /**
91
+ * Get trace annotations filtered by trace_ids and/or identifier.
92
+ * @description Return trace annotations for a project, filtered by `trace_ids`, `identifier`, or both. At least one of `trace_ids` or `identifier` must be supplied. When both are supplied, results are the AND-intersection of the two filters.
93
+ */
88
94
  get: operations["listTraceAnnotationsByTraceIds"];
89
95
  put?: never;
90
96
  post?: never;
@@ -101,7 +107,10 @@ export interface paths {
101
107
  path?: never;
102
108
  cookie?: never;
103
109
  };
104
- /** Get session annotations for a list of session_ids. */
110
+ /**
111
+ * Get session annotations filtered by session_ids and/or identifier.
112
+ * @description Return session annotations for a project, filtered by `session_ids`, `identifier`, or both. At least one of `session_ids` or `identifier` must be supplied. When both are supplied, results are the AND-intersection of the two filters.
113
+ */
105
114
  get: operations["listSessionAnnotationsBySessionIds"];
106
115
  put?: never;
107
116
  post?: never;
@@ -486,7 +495,7 @@ export interface paths {
486
495
  put?: never;
487
496
  /**
488
497
  * Create a trace note
489
- * @description Add a note annotation to a trace. Notes are special annotations that allow multiple entries per trace (unlike regular annotations which are unique by name and identifier). Each note gets a unique UUIDv4 identifier.
498
+ * @description Add a note annotation to a trace. Each call appends a new note with an auto-generated UUIDv4 identifier, so multiple notes accumulate on the same trace. Structured annotations, by contrast, are keyed by (name, trace_id, identifier) — re-writing the same key overwrites the existing annotation, so to keep multiple structured annotations with the same name on a trace you must supply distinct identifiers.
490
499
  */
491
500
  post: operations["createTraceNote"];
492
501
  delete?: never;
@@ -591,7 +600,7 @@ export interface paths {
591
600
  put?: never;
592
601
  /**
593
602
  * Create a span note
594
- * @description Add a note annotation to a span. Notes are special annotations that allow multiple entries per span (unlike regular annotations which are unique by name and identifier). Each note gets a unique UUIDv4 identifier.
603
+ * @description Add a note annotation to a span. Each call appends a new note with an auto-generated UUIDv4 identifier, so multiple notes accumulate on the same span. Structured annotations, by contrast, are keyed by (name, span_id, identifier) — re-writing the same key overwrites the existing annotation, so to keep multiple structured annotations with the same name on a span you must supply distinct identifiers.
595
604
  */
596
605
  post: operations["createSpanNote"];
597
606
  delete?: never;
@@ -942,7 +951,7 @@ export interface paths {
942
951
  put?: never;
943
952
  /**
944
953
  * Create a session note
945
- * @description Add a note annotation to a session. Notes are special annotations that allow multiple entries per session (unlike regular annotations which are unique by name and identifier). Each note gets a unique UUIDv4 identifier.
954
+ * @description Add a note annotation to a session. Each call appends a new note with an auto-generated UUIDv4 identifier, so multiple notes accumulate on the same session. Structured annotations, by contrast, are keyed by (name, session_id, identifier) — re-writing the same key overwrites the existing annotation, so to keep multiple structured annotations with the same name on a session you must supply distinct identifiers.
946
955
  */
947
956
  post: operations["createSessionNote"];
948
957
  delete?: never;
@@ -3967,9 +3976,11 @@ export interface operations {
3967
3976
  };
3968
3977
  listSpanAnnotationsBySpanIds: {
3969
3978
  parameters: {
3970
- query: {
3971
- /** @description One or more span id to fetch annotations for */
3972
- span_ids: string[];
3979
+ query?: {
3980
+ /** @description Optional list of span ids to fetch annotations for. If omitted, `identifier` must be supplied. */
3981
+ span_ids?: string[] | null;
3982
+ /** @description Optional list of annotation identifiers to filter by. Each value must be non-empty. If omitted, `span_ids` must be supplied. When combined with `span_ids`, results are the AND-intersection of both filters. */
3983
+ identifier?: string[] | null;
3973
3984
  /** @description Optional list of annotation names to include. If provided, only annotations with these names will be returned. 'note' annotations are excluded by default unless explicitly included in this list. */
3974
3985
  include_annotation_names?: string[] | null;
3975
3986
  /** @description Optional list of annotation names to exclude from results. */
@@ -4028,9 +4039,11 @@ export interface operations {
4028
4039
  };
4029
4040
  listTraceAnnotationsByTraceIds: {
4030
4041
  parameters: {
4031
- query: {
4032
- /** @description One or more trace id to fetch annotations for */
4033
- trace_ids: string[];
4042
+ query?: {
4043
+ /** @description Optional list of trace ids to fetch annotations for. If omitted, `identifier` must be supplied. */
4044
+ trace_ids?: string[] | null;
4045
+ /** @description Optional list of annotation identifiers to filter by. Each value must be non-empty. If omitted, `trace_ids` must be supplied. When combined with `trace_ids`, results are the AND-intersection of both filters. */
4046
+ identifier?: string[] | null;
4034
4047
  /** @description Optional list of annotation names to include. If provided, only annotations with these names will be returned. 'note' annotations are excluded by default unless explicitly included in this list. */
4035
4048
  include_annotation_names?: string[] | null;
4036
4049
  /** @description Optional list of annotation names to exclude from results. */
@@ -4089,9 +4102,11 @@ export interface operations {
4089
4102
  };
4090
4103
  listSessionAnnotationsBySessionIds: {
4091
4104
  parameters: {
4092
- query: {
4093
- /** @description One or more session id to fetch annotations for */
4094
- session_ids: string[];
4105
+ query?: {
4106
+ /** @description Optional list of session ids to fetch annotations for. If omitted, `identifier` must be supplied. */
4107
+ session_ids?: string[] | null;
4108
+ /** @description Optional list of annotation identifiers to filter by. Each value must be non-empty. If omitted, `session_ids` must be supplied. When combined with `session_ids`, results are the AND-intersection of both filters. */
4109
+ identifier?: string[] | null;
4095
4110
  /** @description Optional list of annotation names to include. If provided, only annotations with these names will be returned. 'note' annotations are excluded by default unless explicitly included in this list. */
4096
4111
  include_annotation_names?: string[] | null;
4097
4112
  /** @description Optional list of annotation names to exclude from results. */
@@ -60,6 +60,13 @@ export const ADD_TRACE_NOTE: RouteRequirement = {
60
60
  minServerVersion: [14, 13, 0],
61
61
  };
62
62
 
63
+ export const ADD_SESSION_NOTE: RouteRequirement = {
64
+ kind: "route",
65
+ method: "POST",
66
+ path: "/v1/session_notes",
67
+ minServerVersion: [14, 17, 0],
68
+ };
69
+
63
70
  export const GET_SPANS_TRACE_IDS: ParameterRequirement = {
64
71
  kind: "parameter",
65
72
  parameterName: "trace_id",
@@ -112,6 +119,7 @@ export const ALL_REQUIREMENTS: readonly CapabilityRequirement[] = [
112
119
  LIST_PROJECT_SESSIONS,
113
120
  ANNOTATE_SESSIONS,
114
121
  ADD_TRACE_NOTE,
122
+ ADD_SESSION_NOTE,
115
123
  GET_SPANS_TRACE_IDS,
116
124
  GET_SPANS_FILTERS,
117
125
  GET_SPANS_BY_ATTRIBUTE,
@@ -0,0 +1,74 @@
1
+ import { createClient } from "../client";
2
+ import { ADD_SESSION_NOTE } from "../constants/serverRequirements";
3
+ import type { ClientFn } from "../types/core";
4
+ import { formatApiError } from "../utils/apiErrorUtils";
5
+ import { ensureServerCapability } from "../utils/serverVersionUtils";
6
+
7
+ /**
8
+ * Parameters for a single session note.
9
+ */
10
+ export interface SessionNote {
11
+ /**
12
+ * The session ID used to track a conversation, thread, or session.
13
+ */
14
+ sessionId: string;
15
+ /**
16
+ * The note text to add to the session.
17
+ */
18
+ note: string;
19
+ }
20
+
21
+ /**
22
+ * Parameters to add a session note.
23
+ */
24
+ export interface AddSessionNoteParams extends ClientFn {
25
+ sessionNote: SessionNote;
26
+ }
27
+
28
+ /**
29
+ * Add a note to a session.
30
+ *
31
+ * Notes are a special type of annotation that allow multiple entries per session.
32
+ * Each note gets a unique UUIDv4 identifier.
33
+ *
34
+ * @param params - The parameters to add a session note.
35
+ * @returns The ID of the created note annotation.
36
+ *
37
+ * @requires Phoenix server >= 14.17.0
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * const result = await addSessionNote({
42
+ * sessionNote: {
43
+ * sessionId: "my-session",
44
+ * note: "Needs review"
45
+ * }
46
+ * });
47
+ * ```
48
+ */
49
+ export async function addSessionNote({
50
+ client: _client,
51
+ sessionNote,
52
+ }: AddSessionNoteParams): Promise<{ id: string }> {
53
+ const client = _client ?? createClient();
54
+ await ensureServerCapability({ client, requirement: ADD_SESSION_NOTE });
55
+
56
+ const { data, error } = await client.POST("/v1/session_notes", {
57
+ body: {
58
+ data: {
59
+ session_id: sessionNote.sessionId.trim(),
60
+ note: sessionNote.note,
61
+ },
62
+ },
63
+ });
64
+
65
+ if (error) {
66
+ throw new Error(`Failed to add session note: ${formatApiError(error)}`);
67
+ }
68
+
69
+ if (!data?.data) {
70
+ throw new Error("Failed to add session note: no data returned");
71
+ }
72
+
73
+ return data.data;
74
+ }
@@ -1,4 +1,5 @@
1
1
  export * from "./addSessionAnnotation";
2
+ export * from "./addSessionNote";
2
3
  export * from "./deleteSession";
3
4
  export * from "./deleteSessions";
4
5
  export * from "./getSession";
@@ -1,5 +1,6 @@
1
1
  import { createClient } from "../client";
2
2
  import type { ClientFn } from "../types/core";
3
+ import { formatApiError } from "../utils/apiErrorUtils";
3
4
 
4
5
  /**
5
6
  * Parameters for a single span note
@@ -25,9 +26,11 @@ export interface AddSpanNoteParams extends ClientFn {
25
26
  /**
26
27
  * Add a note to a span.
27
28
  *
28
- * Notes are a special type of annotation that allow multiple entries per span
29
- * (unlike regular annotations which are unique by name and identifier).
30
- * Each note gets a unique UUIDv4 identifier.
29
+ * Notes are append-only: each call creates a new note with an auto-generated
30
+ * UUIDv4 identifier, so multiple notes accumulate on the same span. Structured
31
+ * annotations, by contrast, are keyed by `(name, spanId, identifier)` — to keep
32
+ * multiple structured annotations with the same name on a span, supply distinct
33
+ * identifiers; otherwise re-writing the same name overwrites the existing one.
31
34
  *
32
35
  * @param params - The parameters to add a span note
33
36
  * @returns The ID of the created note annotation
@@ -58,7 +61,7 @@ export async function addSpanNote({
58
61
  });
59
62
 
60
63
  if (error) {
61
- throw new Error(`Failed to add span note: ${error}`);
64
+ throw new Error(`Failed to add span note: ${formatApiError(error)}`);
62
65
  }
63
66
 
64
67
  if (!data?.data) {
@@ -0,0 +1,65 @@
1
+ import { createClient } from "../client";
2
+ import type { ClientFn } from "../types/core";
3
+ import type { TraceAnnotation } from "./types";
4
+ import { toTraceAnnotationData } from "./types";
5
+
6
+ /**
7
+ * Parameters to add a trace annotation
8
+ */
9
+ export interface AddTraceAnnotationParams extends ClientFn {
10
+ traceAnnotation: TraceAnnotation;
11
+ /**
12
+ * If true, the request will be fulfilled synchronously and return the annotation ID.
13
+ * If false, the request will be processed asynchronously and return null.
14
+ * @default false
15
+ */
16
+ sync?: boolean;
17
+ }
18
+
19
+ /**
20
+ * Add an annotation to a trace.
21
+ *
22
+ * The annotation can be of type "LLM", "CODE", or "HUMAN" and can include a label, score, and metadata.
23
+ * If an identifier is provided and an annotation with that identifier already exists, it will be updated.
24
+ *
25
+ * @param params - The parameters to add a trace annotation
26
+ * @returns The ID of the created or updated annotation
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * const result = await addTraceAnnotation({
31
+ * traceAnnotation: {
32
+ * traceId: "abc123",
33
+ * name: "correctness",
34
+ * label: "correct",
35
+ * score: 1.0,
36
+ * annotatorKind: "HUMAN",
37
+ * identifier: "custom_id_123",
38
+ * metadata: { reviewer: "alice" }
39
+ * },
40
+ * sync: true,
41
+ * });
42
+ * ```
43
+ */
44
+ export async function addTraceAnnotation({
45
+ client: _client,
46
+ traceAnnotation,
47
+ sync = false,
48
+ }: AddTraceAnnotationParams): Promise<{ id: string } | null> {
49
+ const client = _client ?? createClient();
50
+
51
+ const { data, error } = await client.POST("/v1/trace_annotations", {
52
+ params: {
53
+ query: { sync },
54
+ },
55
+ body: {
56
+ data: [toTraceAnnotationData(traceAnnotation)],
57
+ },
58
+ });
59
+
60
+ if (error) {
61
+ throw new Error(`Failed to add trace annotation: ${error}`);
62
+ }
63
+
64
+ return data?.data?.[0] || null;
65
+ }
@@ -1,6 +1,7 @@
1
1
  import { createClient } from "../client";
2
2
  import { ADD_TRACE_NOTE } from "../constants/serverRequirements";
3
3
  import type { ClientFn } from "../types/core";
4
+ import { formatApiError } from "../utils/apiErrorUtils";
4
5
  import { ensureServerCapability } from "../utils/serverVersionUtils";
5
6
 
6
7
  /**
@@ -27,8 +28,11 @@ export interface AddTraceNoteParams extends ClientFn {
27
28
  /**
28
29
  * Add a note to a trace.
29
30
  *
30
- * Notes are a special type of annotation that allow multiple entries per trace.
31
- * Each note gets a unique timestamp-based identifier.
31
+ * Notes are append-only: each call creates a new note with an auto-generated
32
+ * UUIDv4 identifier, so multiple notes accumulate on the same trace. Structured
33
+ * annotations, by contrast, are keyed by `(name, traceId, identifier)` — to keep
34
+ * multiple structured annotations with the same name on a trace, supply distinct
35
+ * identifiers; otherwise re-writing the same name overwrites the existing one.
32
36
  *
33
37
  * @param params - The parameters to add a trace note.
34
38
  * @returns The ID of the created note annotation.
@@ -60,7 +64,7 @@ export async function addTraceNote({
60
64
  });
61
65
 
62
66
  if (error) {
63
- throw new Error(`Failed to add trace note: ${error}`);
67
+ throw new Error(`Failed to add trace note: ${formatApiError(error)}`);
64
68
  }
65
69
 
66
70
  if (!data?.data) {
@@ -1,2 +1,5 @@
1
+ export * from "./addTraceAnnotation";
1
2
  export * from "./addTraceNote";
2
3
  export * from "./getTraces";
4
+ export * from "./logTraceAnnotations";
5
+ export type { TraceAnnotation } from "./types";
@@ -0,0 +1,75 @@
1
+ import { createClient } from "../client";
2
+ import type { ClientFn } from "../types/core";
3
+ import type { TraceAnnotation } from "./types";
4
+ import { toTraceAnnotationData } from "./types";
5
+
6
+ /**
7
+ * Parameters to log multiple trace annotations
8
+ */
9
+ export interface LogTraceAnnotationsParams extends ClientFn {
10
+ /**
11
+ * The trace annotations to log
12
+ */
13
+ traceAnnotations: TraceAnnotation[];
14
+ /**
15
+ * If true, the request will be fulfilled synchronously and return the annotation IDs.
16
+ * If false, the request will be processed asynchronously and return null.
17
+ * @default false
18
+ */
19
+ sync?: boolean;
20
+ }
21
+
22
+ /**
23
+ * Log multiple trace annotations in a single request.
24
+ *
25
+ * Each annotation can be of type "LLM", "CODE", or "HUMAN" and can include a label, score, and metadata.
26
+ * If an identifier is provided and an annotation with that identifier already exists, it will be updated.
27
+ *
28
+ * @param params - The parameters to log trace annotations
29
+ * @returns The IDs of the created or updated annotations
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * const results = await logTraceAnnotations({
34
+ * traceAnnotations: [
35
+ * {
36
+ * traceId: "abc123",
37
+ * name: "correctness",
38
+ * label: "correct",
39
+ * score: 1.0,
40
+ * annotatorKind: "HUMAN",
41
+ * },
42
+ * {
43
+ * traceId: "def456",
44
+ * name: "faithfulness",
45
+ * label: "faithful",
46
+ * score: 0.9,
47
+ * annotatorKind: "LLM",
48
+ * },
49
+ * ],
50
+ * sync: true,
51
+ * });
52
+ * ```
53
+ */
54
+ export async function logTraceAnnotations({
55
+ client: _client,
56
+ traceAnnotations,
57
+ sync = false,
58
+ }: LogTraceAnnotationsParams): Promise<{ id: string }[]> {
59
+ const client = _client ?? createClient();
60
+
61
+ const { data, error } = await client.POST("/v1/trace_annotations", {
62
+ params: {
63
+ query: { sync },
64
+ },
65
+ body: {
66
+ data: traceAnnotations.map(toTraceAnnotationData),
67
+ },
68
+ });
69
+
70
+ if (error) {
71
+ throw new Error(`Failed to log trace annotations: ${error}`);
72
+ }
73
+
74
+ return data?.data || [];
75
+ }
@@ -0,0 +1,72 @@
1
+ import type { paths } from "../__generated__/api/v1";
2
+ import type { Annotation, AnnotationResult } from "../types/annotations";
3
+
4
+ type TraceAnnotationData =
5
+ paths["/v1/trace_annotations"]["post"]["requestBody"]["content"]["application/json"]["data"][0];
6
+
7
+ /**
8
+ * Parameters for a single trace annotation
9
+ */
10
+ export interface TraceAnnotation extends Annotation {
11
+ /**
12
+ * The OpenTelemetry Trace ID (hex format without 0x prefix)
13
+ */
14
+ traceId: string;
15
+ /**
16
+ * The kind of annotator used for the annotation
17
+ * Can be "HUMAN", "LLM", or "CODE"
18
+ * @default "HUMAN"
19
+ */
20
+ annotatorKind?: TraceAnnotationData["annotator_kind"];
21
+ }
22
+
23
+ /**
24
+ * Build and validate annotation result fields
25
+ */
26
+ function buildTraceAnnotationResult(
27
+ annotation: Pick<TraceAnnotation, "label" | "score" | "explanation">
28
+ ): AnnotationResult {
29
+ const result: AnnotationResult = {};
30
+
31
+ if (annotation.label !== undefined) {
32
+ result.label = annotation.label.trim() || null;
33
+ }
34
+ if (annotation.score !== undefined) {
35
+ result.score = annotation.score;
36
+ }
37
+ if (annotation.explanation !== undefined) {
38
+ result.explanation = annotation.explanation.trim() || null;
39
+ }
40
+
41
+ const hasValidResult =
42
+ result.label || result.score !== undefined || result.explanation;
43
+ if (!hasValidResult) {
44
+ throw new Error(
45
+ "At least one of label, score, or explanation must be provided for trace annotation"
46
+ );
47
+ }
48
+ return result;
49
+ }
50
+
51
+ /**
52
+ * Convert a TraceAnnotation to the API format
53
+ */
54
+ export function toTraceAnnotationData(
55
+ annotation: TraceAnnotation
56
+ ): TraceAnnotationData {
57
+ if (annotation.name.trim() === "note") {
58
+ throw new Error(
59
+ 'The name "note" is reserved for trace and span notes. Use addTraceNote instead.'
60
+ );
61
+ }
62
+ const result = buildTraceAnnotationResult(annotation);
63
+
64
+ return {
65
+ trace_id: annotation.traceId.trim(),
66
+ name: annotation.name.trim(),
67
+ annotator_kind: annotation.annotatorKind ?? "HUMAN",
68
+ result,
69
+ metadata: annotation.metadata ?? null,
70
+ identifier: annotation.identifier?.trim() ?? "",
71
+ };
72
+ }
@@ -0,0 +1,17 @@
1
+ export function formatApiError(error: unknown): string {
2
+ if (typeof error === "string") {
3
+ return error;
4
+ }
5
+ if (error && typeof error === "object") {
6
+ const errorWithDetail = error as { detail?: unknown };
7
+ if (typeof errorWithDetail.detail === "string") {
8
+ return errorWithDetail.detail;
9
+ }
10
+ try {
11
+ return JSON.stringify(error);
12
+ } catch {
13
+ return String(error);
14
+ }
15
+ }
16
+ return String(error);
17
+ }