@cephalization/phoenix-insight 0.1.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 (54) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +620 -0
  3. package/dist/agent/index.js +230 -0
  4. package/dist/cli.js +640 -0
  5. package/dist/commands/index.js +2 -0
  6. package/dist/commands/px-fetch-more-spans.js +98 -0
  7. package/dist/commands/px-fetch-more-trace.js +110 -0
  8. package/dist/config/index.js +165 -0
  9. package/dist/config/loader.js +141 -0
  10. package/dist/config/schema.js +53 -0
  11. package/dist/index.js +1 -0
  12. package/dist/modes/index.js +17 -0
  13. package/dist/modes/local.js +134 -0
  14. package/dist/modes/sandbox.js +121 -0
  15. package/dist/modes/types.js +1 -0
  16. package/dist/observability/index.js +65 -0
  17. package/dist/progress.js +209 -0
  18. package/dist/prompts/index.js +1 -0
  19. package/dist/prompts/system.js +30 -0
  20. package/dist/snapshot/client.js +74 -0
  21. package/dist/snapshot/context.js +332 -0
  22. package/dist/snapshot/datasets.js +68 -0
  23. package/dist/snapshot/experiments.js +135 -0
  24. package/dist/snapshot/index.js +262 -0
  25. package/dist/snapshot/projects.js +44 -0
  26. package/dist/snapshot/prompts.js +199 -0
  27. package/dist/snapshot/spans.js +80 -0
  28. package/dist/tsconfig.esm.tsbuildinfo +1 -0
  29. package/package.json +75 -0
  30. package/src/agent/index.ts +323 -0
  31. package/src/cli.ts +782 -0
  32. package/src/commands/index.ts +8 -0
  33. package/src/commands/px-fetch-more-spans.ts +174 -0
  34. package/src/commands/px-fetch-more-trace.ts +183 -0
  35. package/src/config/index.ts +225 -0
  36. package/src/config/loader.ts +173 -0
  37. package/src/config/schema.ts +66 -0
  38. package/src/index.ts +1 -0
  39. package/src/modes/index.ts +21 -0
  40. package/src/modes/local.ts +163 -0
  41. package/src/modes/sandbox.ts +144 -0
  42. package/src/modes/types.ts +31 -0
  43. package/src/observability/index.ts +90 -0
  44. package/src/progress.ts +239 -0
  45. package/src/prompts/index.ts +1 -0
  46. package/src/prompts/system.ts +31 -0
  47. package/src/snapshot/client.ts +129 -0
  48. package/src/snapshot/context.ts +462 -0
  49. package/src/snapshot/datasets.ts +132 -0
  50. package/src/snapshot/experiments.ts +246 -0
  51. package/src/snapshot/index.ts +403 -0
  52. package/src/snapshot/projects.ts +58 -0
  53. package/src/snapshot/prompts.ts +267 -0
  54. package/src/snapshot/spans.ts +142 -0
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Phoenix Insight AI agent setup using Vercel AI SDK
3
+ */
4
+ import { generateText, streamText, tool, stepCountIs, } from "ai";
5
+ import { anthropic } from "@ai-sdk/anthropic";
6
+ import { z } from "zod";
7
+ import { INSIGHT_SYSTEM_PROMPT } from "../prompts/system.js";
8
+ import { fetchMoreSpans, fetchMoreTrace, } from "../commands/index.js";
9
+ import { PhoenixClientError } from "../snapshot/client.js";
10
+ /**
11
+ * Phoenix Insight Agent
12
+ */
13
+ export class PhoenixInsightAgent {
14
+ mode;
15
+ client;
16
+ maxSteps;
17
+ tools = null;
18
+ model = anthropic("claude-sonnet-4-5");
19
+ constructor(config) {
20
+ this.mode = config.mode;
21
+ this.client = config.client;
22
+ this.maxSteps = config.maxSteps || 25;
23
+ }
24
+ /**
25
+ * Initialize the agent tools
26
+ */
27
+ async initializeTools() {
28
+ if (this.tools)
29
+ return this.tools;
30
+ // Get the bash tool from the execution mode
31
+ const bashTool = await this.mode.getBashTool();
32
+ // Store references in closure for the custom tools
33
+ const client = this.client;
34
+ const mode = this.mode;
35
+ // Create custom px-fetch-more-spans tool using AI SDK's tool function
36
+ const pxFetchMoreSpans = tool({
37
+ description: "Fetch additional spans from Phoenix. Use when you need more span data than what's in the snapshot. You must provide both project name and optionally a limit.",
38
+ inputSchema: z.object({
39
+ project: z.string().describe("The project name"),
40
+ limit: z
41
+ .number()
42
+ .optional()
43
+ .describe("Number of spans to fetch (default: 500)"),
44
+ startTime: z
45
+ .string()
46
+ .optional()
47
+ .describe("Start time filter in ISO format"),
48
+ endTime: z
49
+ .string()
50
+ .optional()
51
+ .describe("End time filter in ISO format"),
52
+ }),
53
+ execute: async (params) => {
54
+ try {
55
+ const options = {
56
+ project: params.project,
57
+ limit: params.limit || 500,
58
+ startTime: params.startTime,
59
+ endTime: params.endTime,
60
+ };
61
+ await fetchMoreSpans(client, mode, options);
62
+ return {
63
+ success: true,
64
+ message: `Fetched additional spans for project ${params.project}. Data saved to /phoenix/projects/${params.project}/spans/`,
65
+ };
66
+ }
67
+ catch (error) {
68
+ return {
69
+ success: false,
70
+ error: error instanceof Error ? error.message : String(error),
71
+ };
72
+ }
73
+ },
74
+ });
75
+ // Create custom px-fetch-more-trace tool using AI SDK's tool function
76
+ const pxFetchMoreTrace = tool({
77
+ description: "Fetch a specific trace by ID from Phoenix. Use when you need to examine a particular trace in detail. You must provide both the trace ID and the project name.",
78
+ inputSchema: z.object({
79
+ traceId: z.string().describe("The trace ID to fetch"),
80
+ project: z.string().describe("The project name to search in"),
81
+ }),
82
+ execute: async (params) => {
83
+ try {
84
+ const options = {
85
+ traceId: params.traceId,
86
+ project: params.project,
87
+ };
88
+ await fetchMoreTrace(client, mode, options);
89
+ return {
90
+ success: true,
91
+ message: `Fetched trace ${params.traceId}. Data saved to /phoenix/traces/${params.traceId}/`,
92
+ };
93
+ }
94
+ catch (error) {
95
+ return {
96
+ success: false,
97
+ error: error instanceof Error ? error.message : String(error),
98
+ };
99
+ }
100
+ },
101
+ });
102
+ this.tools = {
103
+ bash: bashTool,
104
+ px_fetch_more_spans: pxFetchMoreSpans,
105
+ px_fetch_more_trace: pxFetchMoreTrace,
106
+ };
107
+ return this.tools;
108
+ }
109
+ /**
110
+ * Generate a response for a user query
111
+ */
112
+ async generate(userQuery, options) {
113
+ let tools;
114
+ try {
115
+ tools = await this.initializeTools();
116
+ }
117
+ catch (error) {
118
+ throw new Error(`Failed to initialize agent tools: ${error instanceof Error ? error.message : String(error)}`);
119
+ }
120
+ try {
121
+ const result = await generateText({
122
+ model: this.model,
123
+ system: INSIGHT_SYSTEM_PROMPT,
124
+ prompt: userQuery,
125
+ tools,
126
+ stopWhen: stepCountIs(this.maxSteps),
127
+ onStepFinish: options?.onStepFinish,
128
+ experimental_telemetry: {
129
+ isEnabled: true,
130
+ },
131
+ });
132
+ return result;
133
+ }
134
+ catch (error) {
135
+ // Check for specific AI SDK errors
136
+ if (error instanceof Error) {
137
+ if (error.message.includes("rate limit")) {
138
+ throw new Error("AI model rate limit exceeded. Please wait and try again.");
139
+ }
140
+ if (error.message.includes("timeout")) {
141
+ throw new Error("AI model request timed out. Please try again.");
142
+ }
143
+ if (error.message.includes("authentication") ||
144
+ error.message.includes("API key")) {
145
+ throw new Error("AI model authentication failed. Check your API key configuration.");
146
+ }
147
+ }
148
+ throw new Error(`AI generation failed: ${error instanceof Error ? error.message : String(error)}`);
149
+ }
150
+ }
151
+ /**
152
+ * Stream a response for a user query
153
+ */
154
+ async stream(userQuery, options) {
155
+ let tools;
156
+ try {
157
+ tools = await this.initializeTools();
158
+ }
159
+ catch (error) {
160
+ throw new Error(`Failed to initialize agent tools: ${error instanceof Error ? error.message : String(error)}`);
161
+ }
162
+ try {
163
+ const result = streamText({
164
+ model: this.model,
165
+ system: INSIGHT_SYSTEM_PROMPT,
166
+ prompt: userQuery,
167
+ tools,
168
+ stopWhen: stepCountIs(this.maxSteps),
169
+ onStepFinish: options?.onStepFinish,
170
+ experimental_telemetry: {
171
+ isEnabled: true,
172
+ },
173
+ });
174
+ return result;
175
+ }
176
+ catch (error) {
177
+ // Check for specific AI SDK errors
178
+ if (error instanceof Error) {
179
+ if (error.message.includes("rate limit")) {
180
+ throw new Error("AI model rate limit exceeded. Please wait and try again.");
181
+ }
182
+ if (error.message.includes("timeout")) {
183
+ throw new Error("AI model request timed out. Please try again.");
184
+ }
185
+ if (error.message.includes("authentication") ||
186
+ error.message.includes("API key")) {
187
+ throw new Error("AI model authentication failed. Check your API key configuration.");
188
+ }
189
+ }
190
+ throw new Error(`AI streaming failed: ${error instanceof Error ? error.message : String(error)}`);
191
+ }
192
+ }
193
+ /**
194
+ * Clean up resources
195
+ */
196
+ async cleanup() {
197
+ await this.mode.cleanup();
198
+ }
199
+ }
200
+ /**
201
+ * Creates a Phoenix Insight agent
202
+ */
203
+ export async function createInsightAgent(config) {
204
+ return new PhoenixInsightAgent(config);
205
+ }
206
+ /**
207
+ * Run a query with the Phoenix Insight agent
208
+ */
209
+ export async function runQuery(agent, userQuery, options) {
210
+ const { stream = false, ...callbacks } = options || {};
211
+ if (stream) {
212
+ return await agent.stream(userQuery, callbacks);
213
+ }
214
+ else {
215
+ return await agent.generate(userQuery, callbacks);
216
+ }
217
+ }
218
+ /**
219
+ * Create and run a one-shot query
220
+ */
221
+ export async function runOneShotQuery(config, userQuery, options) {
222
+ const agent = await createInsightAgent(config);
223
+ try {
224
+ const result = await runQuery(agent, userQuery, options);
225
+ return result;
226
+ }
227
+ finally {
228
+ await agent.cleanup();
229
+ }
230
+ }