promptlayer 1.1.0 → 1.2.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 (64) hide show
  1. package/README.md +22 -0
  2. package/dist/claude-agents.d.mts +20 -0
  3. package/dist/claude-agents.d.ts +20 -0
  4. package/dist/claude-agents.js +2 -0
  5. package/dist/claude-agents.js.map +1 -0
  6. package/dist/esm/{chunk-SWBNW72U.js → chunk-DFBRFJOL.js} +2 -2
  7. package/dist/esm/{chunk-SWBNW72U.js.map → chunk-DFBRFJOL.js.map} +1 -1
  8. package/dist/esm/claude-agents.js +2 -0
  9. package/dist/esm/claude-agents.js.map +1 -0
  10. package/dist/esm/index.js +1 -1
  11. package/dist/esm/openai-agents.js +2 -2
  12. package/dist/esm/openai-agents.js.map +1 -1
  13. package/dist/index.js +2 -2
  14. package/dist/index.js.map +1 -1
  15. package/dist/openai-agents.js +2 -2
  16. package/dist/openai-agents.js.map +1 -1
  17. package/package.json +18 -1
  18. package/vendor/claude-agents/trace/.claude-plugin/plugin.json +8 -0
  19. package/vendor/claude-agents/trace/hooks/hook_utils.py +38 -0
  20. package/vendor/claude-agents/trace/hooks/hooks.json +60 -0
  21. package/vendor/claude-agents/trace/hooks/lib.sh +577 -0
  22. package/vendor/claude-agents/trace/hooks/parse_stop_transcript.py +375 -0
  23. package/vendor/claude-agents/trace/hooks/post_tool_use.sh +41 -0
  24. package/vendor/claude-agents/trace/hooks/session_end.sh +37 -0
  25. package/vendor/claude-agents/trace/hooks/session_start.sh +57 -0
  26. package/vendor/claude-agents/trace/hooks/stop_hook.sh +123 -0
  27. package/vendor/claude-agents/trace/hooks/user_prompt_submit.sh +25 -0
  28. package/vendor/claude-agents/vendor_metadata.json +5 -0
  29. package/.github/CODEOWNERS +0 -1
  30. package/.github/workflows/node.js.yml +0 -30
  31. package/.github/workflows/npm-publish.yml +0 -35
  32. package/src/groups.ts +0 -16
  33. package/src/index.ts +0 -383
  34. package/src/integrations/openai-agents/helpers.test.ts +0 -254
  35. package/src/integrations/openai-agents/ids.ts +0 -27
  36. package/src/integrations/openai-agents/index.ts +0 -8
  37. package/src/integrations/openai-agents/instrumentation.test.ts +0 -46
  38. package/src/integrations/openai-agents/instrumentation.ts +0 -47
  39. package/src/integrations/openai-agents/mapping.ts +0 -714
  40. package/src/integrations/openai-agents/otlp-json.ts +0 -120
  41. package/src/integrations/openai-agents/processor.test.ts +0 -509
  42. package/src/integrations/openai-agents/processor.ts +0 -388
  43. package/src/integrations/openai-agents/time.ts +0 -56
  44. package/src/integrations/openai-agents/types.ts +0 -49
  45. package/src/integrations/openai-agents/url.ts +0 -9
  46. package/src/openai-agents.ts +0 -1
  47. package/src/promptlayer.ts +0 -125
  48. package/src/run-error-tracking.test.ts +0 -146
  49. package/src/span-exporter.ts +0 -120
  50. package/src/span-wrapper.ts +0 -51
  51. package/src/templates.ts +0 -37
  52. package/src/tracing.ts +0 -20
  53. package/src/track.ts +0 -84
  54. package/src/types.ts +0 -689
  55. package/src/utils/blueprint-builder.test.ts +0 -727
  56. package/src/utils/blueprint-builder.ts +0 -1453
  57. package/src/utils/errors.test.ts +0 -68
  58. package/src/utils/errors.ts +0 -62
  59. package/src/utils/streaming.test.ts +0 -498
  60. package/src/utils/streaming.ts +0 -1402
  61. package/src/utils/utils.ts +0 -1228
  62. package/tsconfig.json +0 -115
  63. package/tsup.config.ts +0 -20
  64. package/vitest.config.ts +0 -9
@@ -1,146 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, type Mock } from "vitest";
2
-
3
- // Mock modules before importing the subject
4
- vi.mock("@/utils/utils", () => ({
5
- trackRequest: vi.fn().mockResolvedValue({ request_id: 1, prompt_blueprint: {} }),
6
- configureProviderSettings: vi.fn().mockReturnValue({
7
- provider_type: "openai",
8
- kwargs: { model: "gpt-4" },
9
- }),
10
- getProviderConfig: vi.fn().mockReturnValue({
11
- function_name: "openai.chat.completions.create",
12
- stream_function: null,
13
- }),
14
- openaiRequest: vi.fn().mockResolvedValue({ choices: [{ message: { content: "hi" } }] }),
15
- anthropicRequest: vi.fn(),
16
- azureOpenAIRequest: vi.fn(),
17
- googleRequest: vi.fn(),
18
- mistralRequest: vi.fn(),
19
- vertexaiRequest: vi.fn(),
20
- amazonBedrockRequest: vi.fn(),
21
- anthropicBedrockRequest: vi.fn(),
22
- readEnv: vi.fn().mockReturnValue("test-api-key"),
23
- runWorkflowRequest: vi.fn(),
24
- utilLogRequest: vi.fn(),
25
- }));
26
-
27
- vi.mock("@/templates", () => {
28
- return {
29
- TemplateManager: class {
30
- get = vi.fn().mockResolvedValue({
31
- id: 1,
32
- version: 1,
33
- prompt_template: { type: "chat", messages: [] },
34
- metadata: { model: { provider: "openai", name: "gpt-4", parameters: {} } },
35
- llm_kwargs: { model: "gpt-4" },
36
- custom_provider: null,
37
- });
38
- },
39
- };
40
- });
41
-
42
- vi.mock("@/tracing", () => {
43
- const fakeSpan = {
44
- setAttribute: vi.fn(),
45
- setStatus: vi.fn(),
46
- end: vi.fn(),
47
- spanContext: () => ({ spanId: "test-span-id" }),
48
- };
49
- return {
50
- getTracer: () => ({
51
- startActiveSpan: (_name: string, fn: (span: any) => any) => fn(fakeSpan),
52
- }),
53
- setupTracing: vi.fn(),
54
- };
55
- });
56
-
57
- vi.mock("@/groups", () => ({
58
- GroupManager: class {},
59
- }));
60
-
61
- vi.mock("@/track", () => ({
62
- TrackManager: class {},
63
- }));
64
-
65
- vi.mock("@/span-wrapper", () => ({
66
- wrapWithSpan: vi.fn(),
67
- }));
68
-
69
- vi.mock("@/utils/streaming", () => ({
70
- streamResponse: vi.fn().mockReturnValue({ async *[Symbol.asyncIterator]() {} }),
71
- }));
72
-
73
- import { PromptLayer } from "@/index";
74
- import { trackRequest, openaiRequest } from "@/utils/utils";
75
- import { RateLimitError } from "openai";
76
-
77
- describe("run() error tracking", () => {
78
- let client: PromptLayer;
79
-
80
- beforeEach(() => {
81
- vi.clearAllMocks();
82
- client = new PromptLayer({ apiKey: "test-api-key" });
83
- });
84
-
85
- it("tracks error with UNKNOWN_ERROR type and re-throws when LLM call fails", async () => {
86
- const llmError = new Error("model overloaded");
87
- (openaiRequest as Mock).mockRejectedValueOnce(llmError);
88
-
89
- await expect(
90
- client.run({ promptName: "test-prompt" })
91
- ).rejects.toThrow("model overloaded");
92
-
93
- expect(trackRequest).toHaveBeenCalledWith(
94
- expect.any(String),
95
- expect.objectContaining({
96
- request_response: {},
97
- status: "ERROR",
98
- error_type: "UNKNOWN_ERROR",
99
- error_message: "model overloaded",
100
- }),
101
- true
102
- );
103
- });
104
-
105
- it("tracks PROVIDER_RATE_LIMIT when LLM throws RateLimitError", async () => {
106
- const rateLimitError = new RateLimitError(
107
- 429, undefined, "Too Many Requests", undefined
108
- );
109
- (openaiRequest as Mock).mockRejectedValueOnce(rateLimitError);
110
-
111
- await expect(
112
- client.run({ promptName: "test-prompt" })
113
- ).rejects.toThrow("Too Many Requests");
114
-
115
- expect(trackRequest).toHaveBeenCalledWith(
116
- expect.any(String),
117
- expect.objectContaining({
118
- request_response: {},
119
- status: "ERROR",
120
- error_type: "PROVIDER_RATE_LIMIT",
121
- error_message: expect.stringContaining("Too Many Requests"),
122
- }),
123
- true
124
- );
125
- });
126
-
127
- it("calls trackRequest without error fields on success", async () => {
128
- const successResponse = { choices: [{ message: { content: "hello" } }] };
129
- (openaiRequest as Mock).mockResolvedValueOnce(successResponse);
130
-
131
- await client.run({ promptName: "test-prompt" });
132
-
133
- expect(trackRequest).toHaveBeenCalledWith(
134
- expect.any(String),
135
- expect.objectContaining({
136
- request_response: successResponse,
137
- }),
138
- true
139
- );
140
-
141
- const callArgs = (trackRequest as Mock).mock.calls[0][1];
142
- expect(callArgs).not.toHaveProperty("error_type");
143
- expect(callArgs).not.toHaveProperty("error_message");
144
- expect(callArgs).not.toHaveProperty("status");
145
- });
146
- });
@@ -1,120 +0,0 @@
1
- import { fetchWithRetry, getCommonHeaders } from "@/utils/utils";
2
- import { Attributes, SpanKind, SpanStatusCode } from "@opentelemetry/api";
3
- import { ExportResultCode } from "@opentelemetry/core";
4
- import { ReadableSpan, SpanExporter } from "@opentelemetry/sdk-trace-base";
5
-
6
- class PromptLayerSpanExporter implements SpanExporter {
7
- private apiKey: string;
8
- private baseURL: string;
9
- private enableTracing: boolean;
10
- private url: string;
11
-
12
- constructor(enableTracing: boolean, apiKey: string, baseURL: string) {
13
- this.apiKey = apiKey;
14
- this.baseURL = baseURL;
15
- this.enableTracing = enableTracing;
16
- this.url = `${this.baseURL}/spans-bulk`;
17
- }
18
-
19
- private attributesToObject(
20
- attributes: Attributes | undefined
21
- ): Record<string, any> {
22
- if (!attributes) return {};
23
- return Object.fromEntries(Object.entries(attributes));
24
- }
25
-
26
- private spanKindToString(kind: SpanKind): string {
27
- const kindMap: Record<SpanKind, string> = {
28
- [SpanKind.INTERNAL]: "SpanKind.INTERNAL",
29
- [SpanKind.SERVER]: "SpanKind.SERVER",
30
- [SpanKind.CLIENT]: "SpanKind.CLIENT",
31
- [SpanKind.PRODUCER]: "SpanKind.PRODUCER",
32
- [SpanKind.CONSUMER]: "SpanKind.CONSUMER",
33
- };
34
- return kindMap[kind] || "SpanKind.INTERNAL";
35
- }
36
-
37
- private statusCodeToString(code: SpanStatusCode): string {
38
- const statusMap: Record<SpanStatusCode, string> = {
39
- [SpanStatusCode.ERROR]: "StatusCode.ERROR",
40
- [SpanStatusCode.OK]: "StatusCode.OK",
41
- [SpanStatusCode.UNSET]: "StatusCode.UNSET",
42
- };
43
- return statusMap[code] || "StatusCode.UNSET";
44
- }
45
-
46
- private toNanoseconds(time: [number, number]): string {
47
- return (BigInt(time[0]) * BigInt(1e9) + BigInt(time[1])).toString();
48
- }
49
-
50
- export(spans: ReadableSpan[]): Promise<ExportResultCode> {
51
- if (!this.enableTracing) {
52
- return Promise.resolve(ExportResultCode.SUCCESS);
53
- }
54
-
55
- const requestData = spans.map((span) => ({
56
- name: span.name,
57
- context: {
58
- trace_id: span.spanContext().traceId,
59
- span_id: span.spanContext().spanId,
60
- trace_state: span.spanContext().traceState?.serialize() || "",
61
- },
62
- kind: this.spanKindToString(span.kind),
63
- parent_id: span.parentSpanId || null,
64
- start_time: this.toNanoseconds(span.startTime),
65
- end_time: this.toNanoseconds(span.endTime),
66
- status: {
67
- status_code: this.statusCodeToString(span.status.code),
68
- description: span.status.message,
69
- },
70
- attributes: this.attributesToObject(span.attributes),
71
- events: span.events.map((event) => ({
72
- name: event.name,
73
- timestamp: this.toNanoseconds(event.time),
74
- attributes: this.attributesToObject(event.attributes),
75
- })),
76
- links: span.links.map((link) => ({
77
- context: link.context,
78
- attributes: this.attributesToObject(link.attributes),
79
- })),
80
- resource: {
81
- attributes: {
82
- ...span.resource.attributes,
83
- "service.name": "prompt-layer-js",
84
- },
85
- schema_url: "",
86
- },
87
- }));
88
-
89
- return fetchWithRetry(this.url, {
90
- method: "POST",
91
- headers: {
92
- "Content-Type": "application/json",
93
- "X-API-KEY": this.apiKey || "",
94
- ...getCommonHeaders(),
95
- },
96
- body: JSON.stringify({
97
- spans: requestData,
98
- }),
99
- })
100
- .then((response) => {
101
- if (!response.ok) {
102
- console.error(
103
- `Error exporting spans\nHTTP error! status: ${response.status}`
104
- );
105
- return ExportResultCode.FAILED;
106
- }
107
- return ExportResultCode.SUCCESS;
108
- })
109
- .catch((error) => {
110
- console.error("Error exporting spans:", error);
111
- return ExportResultCode.FAILED;
112
- });
113
- }
114
-
115
- shutdown(): Promise<void> {
116
- return Promise.resolve();
117
- }
118
- }
119
-
120
- export default PromptLayerSpanExporter;
@@ -1,51 +0,0 @@
1
- import * as opentelemetry from '@opentelemetry/api';
2
- import { getTracer } from '@/tracing';
3
-
4
- export const wrapWithSpan = (functionName: string, func: Function, attributes?: Record<string, any>) => {
5
- return function (...args: any[]) {
6
- const tracer = getTracer();
7
-
8
- const wrapperFunction = (span: opentelemetry.Span) => {
9
- try {
10
- if (attributes) {
11
- Object.entries(attributes).forEach(([key, value]) => {
12
- span.setAttribute(key, value);
13
- });
14
- }
15
-
16
- span.setAttribute('function_input', JSON.stringify(args));
17
- const result = func(...args);
18
-
19
- if (result instanceof Promise) {
20
- return result.then((resolvedResult) => {
21
- span.setAttribute('function_output', JSON.stringify(resolvedResult));
22
- span.setStatus({ code: opentelemetry.SpanStatusCode.OK });
23
- return resolvedResult;
24
- }).catch((error) => {
25
- handleError(span, error, args);
26
- throw error;
27
- }).finally(() => span.end());
28
- } else {
29
- span.setAttribute('function_output', JSON.stringify(result));
30
- span.setStatus({ code: opentelemetry.SpanStatusCode.OK });
31
- span.end();
32
- return result;
33
- }
34
- } catch (error) {
35
- handleError(span, error, args);
36
- throw error;
37
- }
38
- };
39
-
40
- return tracer.startActiveSpan(functionName, wrapperFunction);
41
- };
42
- };
43
-
44
- const handleError = (span: opentelemetry.Span, error: any, args: any[]) => {
45
- span.setAttribute('function_input', JSON.stringify(args));
46
- span.setStatus({
47
- code: opentelemetry.SpanStatusCode.ERROR,
48
- message: error instanceof Error ? error.message : 'Unknown error',
49
- });
50
- span.end();
51
- }
package/src/templates.ts DELETED
@@ -1,37 +0,0 @@
1
- import {
2
- GetPromptTemplateParams,
3
- Pagination,
4
- PublishPromptTemplate,
5
- } from "@/types";
6
- import {
7
- getAllPromptTemplates,
8
- getPromptTemplate,
9
- publishPromptTemplate,
10
- } from "@/utils/utils";
11
-
12
- export class TemplateManager {
13
- apiKey: string;
14
- baseURL: string;
15
- throwOnError: boolean;
16
-
17
- constructor(apiKey: string, baseURL: string, throwOnError: boolean = true) {
18
- this.apiKey = apiKey;
19
- this.baseURL = baseURL;
20
- this.throwOnError = throwOnError;
21
- }
22
-
23
- get = (promptName: string, params?: Partial<GetPromptTemplateParams>) =>
24
- getPromptTemplate(
25
- this.apiKey,
26
- this.baseURL,
27
- promptName,
28
- params,
29
- this.throwOnError
30
- );
31
-
32
- publish = (body: PublishPromptTemplate) =>
33
- publishPromptTemplate(this.apiKey, this.baseURL, body, this.throwOnError);
34
-
35
- all = (params?: Pagination) =>
36
- getAllPromptTemplates(this.apiKey, this.baseURL, params, this.throwOnError);
37
- }
package/src/tracing.ts DELETED
@@ -1,20 +0,0 @@
1
- import PromptLayerSpanExporter from "@/span-exporter";
2
- import * as opentelemetry from "@opentelemetry/api";
3
- import { SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base";
4
- import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
5
-
6
- export const getTracer = (name: string = "promptlayer-tracer") => {
7
- return opentelemetry.trace.getTracer(name);
8
- };
9
-
10
- export const setupTracing = (
11
- enableTracing: boolean,
12
- apiKey: string,
13
- baseURL: string
14
- ) => {
15
- const provider = new NodeTracerProvider();
16
- const exporter = new PromptLayerSpanExporter(enableTracing, apiKey, baseURL);
17
- const processor = new SimpleSpanProcessor(exporter);
18
- provider.addSpanProcessor(processor);
19
- provider.register();
20
- };
package/src/track.ts DELETED
@@ -1,84 +0,0 @@
1
- import { TrackGroup, TrackMetadata, TrackPrompt, TrackScore } from "@/types";
2
- import {
3
- promptLayerTrackGroup,
4
- promptLayerTrackMetadata,
5
- promptLayerTrackPrompt,
6
- promptLayerTrackScore,
7
- } from "@/utils/utils";
8
-
9
- const metadata = (
10
- apiKey: string,
11
- baseURL: string,
12
- body: TrackMetadata,
13
- throwOnError: boolean = true
14
- ): Promise<boolean> => {
15
- if (!(body.metadata instanceof Object)) {
16
- throw new Error("Please provide a dictionary of metadata.");
17
- }
18
- for (const [key, value] of Object.entries(body.metadata)) {
19
- if (typeof key !== "string" || typeof value !== "string") {
20
- throw new Error(
21
- "Please provide a dictionary of metadata with key value pair of strings."
22
- );
23
- }
24
- }
25
- return promptLayerTrackMetadata(apiKey, baseURL, body, throwOnError);
26
- };
27
-
28
- const score = (
29
- apiKey: string,
30
- baseURL: string,
31
- body: TrackScore,
32
- throwOnError: boolean = true
33
- ): Promise<boolean> => {
34
- if (typeof body.score !== "number") {
35
- throw new Error("Score must be a number");
36
- }
37
- if (body.score < 0 || body.score > 100) {
38
- throw new Error("Score must be a number between 0 and 100.");
39
- }
40
- return promptLayerTrackScore(apiKey, baseURL, body, throwOnError);
41
- };
42
-
43
- const prompt = (
44
- apiKey: string,
45
- baseURL: string,
46
- body: TrackPrompt,
47
- throwOnError: boolean = true
48
- ): Promise<boolean> => {
49
- if (!(body.prompt_input_variables instanceof Object)) {
50
- throw new Error("Prompt template input variable dictionary not provided.");
51
- }
52
- return promptLayerTrackPrompt(apiKey, baseURL, body, throwOnError);
53
- };
54
-
55
- const group = (
56
- apiKey: string,
57
- baseURL: string,
58
- body: TrackGroup,
59
- throwOnError: boolean = true
60
- ) => promptLayerTrackGroup(apiKey, baseURL, body, throwOnError);
61
-
62
- export class TrackManager {
63
- apiKey: string;
64
- baseURL: string;
65
- throwOnError: boolean;
66
-
67
- constructor(apiKey: string, baseURL: string, throwOnError: boolean = true) {
68
- this.apiKey = apiKey;
69
- this.baseURL = baseURL;
70
- this.throwOnError = throwOnError;
71
- }
72
-
73
- group = (body: TrackGroup) =>
74
- group(this.apiKey, this.baseURL, body, this.throwOnError);
75
-
76
- metadata = (body: TrackMetadata) =>
77
- metadata(this.apiKey, this.baseURL, body, this.throwOnError);
78
-
79
- prompt = (body: TrackPrompt) =>
80
- prompt(this.apiKey, this.baseURL, body, this.throwOnError);
81
-
82
- score = (body: TrackScore) =>
83
- score(this.apiKey, this.baseURL, body, this.throwOnError);
84
- }