promptlayer 1.3.2 → 1.3.4

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.
package/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  # 🍰 PromptLayer
4
4
 
5
- **The first platform built for <span style="background-color: rgb(219, 234, 254);">prompt engineers</span>**
5
+ **Version, test, and monitor every prompt and agent with robust evals, tracing, and regression sets.**
6
6
 
7
- <a href="https://nodejs.org"><img alt="Node" src="https://img.shields.io/badge/Node.js-43853D?style=for-the-badge&logo=node.js&logoColor=white"></a>
7
+ <a href="https://nodejs.org/"><img alt="Node.js" src="https://img.shields.io/badge/-Node.js 18+-43853D?style=for-the-badge&logo=node.js&logoColor=white"></a>
8
8
  <a href="https://docs.promptlayer.com"><img alt="Docs" src="https://custom-icon-badges.herokuapp.com/badge/docs-PL-green.svg?logo=cake&style=for-the-badge"></a>
9
9
  <a href="https://www.loom.com/share/196c42e43acd4a369d75e9a7374a0850"><img alt="Demo with Loom" src="https://img.shields.io/badge/Demo-loom-552586.svg?logo=loom&style=for-the-badge&labelColor=gray"></a>
10
10
 
@@ -12,124 +12,150 @@
12
12
 
13
13
  <div align="left">
14
14
 
15
- [PromptLayer](https://promptlayer.com/) is the first platform that allows you to track, manage, and share your GPT prompt engineering. PromptLayer acts a middleware between your code and OpenAI’s JavaScript library.
15
+ This library provides convenient access to the PromptLayer API from applications written in JavaScript.
16
16
 
17
- PromptLayer records all your OpenAI API requests, allowing you to search and explore request history in the PromptLayer dashboard.
17
+ ## Installation
18
18
 
19
- This repo contains the JavaScript wrapper library for PromptLayer.
20
-
21
- ## Quickstart ⚡
19
+ ```bash
20
+ npm install promptlayer
21
+ ```
22
22
 
23
- ### Install PromptLayer
23
+ Optional peer dependencies [(learn more)](#integration-modules):
24
24
 
25
25
  ```bash
26
- npm install promptlayer
26
+ npm install promptlayer @openai/agents
27
+ npm install promptlayer @anthropic-ai/claude-agent-sdk
27
28
  ```
28
29
 
29
- ### Installing PromptLayer Locally
30
+ ## Quick Start
31
+
32
+ To follow along, you need a [PromptLayer](https://www.promptlayer.com/) API key. Once logged in, go to Settings to generate a key.
30
33
 
31
- Use `npm install .` to install locally.
34
+ Create a client and fetch a prompt template from PromptLayer:
32
35
 
33
- ### Using PromptLayer
36
+ ```ts
37
+ import { PromptLayer } from "promptlayer";
34
38
 
35
- To get started, create an account by clicking “_Log in_” on [PromptLayer](https://promptlayer.com/). Once logged in, click the button to create an API key and save this in a secure location ([Guide to Using Env Vars](https://nodejs.dev/en/learn/how-to-read-environment-variables-from-nodejs/)).
39
+ async function main() {
40
+ const pl = new PromptLayer({
41
+ apiKey: process.env.PROMPTLAYER_API_KEY,
42
+ });
36
43
 
37
- ```bash
38
- export OPENAI_API_KEY=sk_xxxxxx
39
- export PROMPTLAYER_API_KEY=pl_xxxxxx
40
- ```
44
+ const prompt = await pl.templates.get("support-reply", {
45
+ input_variables: {
46
+ customer_name: "Ada",
47
+ question: "How do I reset my password?",
48
+ },
49
+ });
41
50
 
42
- Once you have that all set up, install PromptLayer using `npm`.
51
+ console.log(prompt?.prompt_template);
52
+ }
43
53
 
44
- In the JavaScript file where you use OpenAI APIs, add the following. This allows us to keep track of your requests without needing any other code changes.
54
+ main();
55
+ ```
45
56
 
46
- ```js
47
- import BaseOpenAI from "openai";
48
- import { PromptLayer } from "promptlayer";
57
+ SDK methods that make network requests return promises.
49
58
 
50
- const promptlayer = new PromptLayer({
51
- apiKey: process.env.PROMPTLAYER_API_KEY,
52
- });
53
- // Typescript
54
- const OpenAI: typeof BaseOpenAI = promptlayer.OpenAI;
55
- const openai = new OpenAI();
59
+ You can also use the client as a proxy around supported provider SDKs:
60
+
61
+ ```bash
62
+ npm install openai
56
63
  ```
57
64
 
58
- **You can then use `openai` as you would if you had imported it directly.**
65
+ ```ts
66
+ import OpenAI from "openai";
67
+ import { PromptLayer } from "promptlayer";
59
68
 
60
- <aside>
61
- 💡 Your OpenAI API Key is **never** sent to our servers. All OpenAI requests are made locally from your machine, PromptLayer just logs the request.
62
- </aside>
69
+ async function main() {
70
+ const pl = new PromptLayer({
71
+ apiKey: process.env.PROMPTLAYER_API_KEY,
72
+ });
63
73
 
64
- ### Adding PromptLayer tags: `pl_tags`
74
+ const PromptLayerOpenAI: typeof OpenAI = pl.OpenAI;
75
+ const openai = new PromptLayerOpenAI();
65
76
 
66
- PromptLayer allows you to add tags through the `pl_tags` argument. This allows you to track and group requests in the dashboard.
77
+ const response = await openai.chat.completions.create({
78
+ model: "gpt-4.1-mini",
79
+ messages: [{ role: "user", content: "Say hello in one short sentence." }],
80
+ // @ts-ignore PromptLayer proxy option
81
+ pl_tags: ["proxy-example"],
82
+ });
67
83
 
68
- _Tags are not required but we recommend them!_
84
+ console.log(response);
85
+ }
69
86
 
70
- ```js
71
- openai.chat.completions.create({
72
- messages: [{ role: "user", content: "Say this is a test" }],
73
- model: "gpt-3.5-turbo",
74
- // @ts-ignore
75
- pl_tags: ["test"],
76
- });
87
+ main();
77
88
  ```
78
89
 
79
- ### Returning request id: `return_pl_id`
90
+ ## Configuration
80
91
 
81
- PromptLayer allows you to return the request id through the `return_pl_id` argument. When you set this to `true`, a tuple is returned with the request id as the second element.
92
+ ### Client Options
82
93
 
83
- ```js
84
- openai.chat.completions.create({
85
- messages: [{ role: "user", content: "Say this is a test" }],
86
- model: "gpt-3.5-turbo",
87
- // @ts-ignore
88
- return_pl_id: true,
89
- });
90
- ```
94
+ `PromptLayer(...)` accepts these parameters:
91
95
 
92
- <aside>
93
- Notice the `ts-ignore` comment. This is because the `pl_tags` and `return_pl_id` arguments are not part of the OpenAI API. We are working on a way to make this more seamless.
94
- </aside>
96
+ - `apiKey: string | undefined`: Your PromptLayer API key. If omitted, the SDK looks for `PROMPTLAYER_API_KEY`.
97
+ - `enableTracing: boolean = false`: Enables OpenTelemetry tracing export to PromptLayer.
98
+ - `baseURL: string | undefined`: Overrides the PromptLayer API base URL. If omitted, the SDK uses `PROMPTLAYER_BASE_URL` or the default API URL.
99
+ - `throwOnError: boolean = true`: Controls whether SDK methods throw errors or return `null` or fallback values for many API errors.
100
+ - `cacheTtlSeconds: number = 0`: Enables in-memory prompt-template caching when greater than `0`.
95
101
 
96
- After making your first few requests, you should be able to see them in the PromptLayer dashboard!
102
+ ### Environment Variables
97
103
 
98
- ## Optional Extensions
104
+ The SDK relies on the following environment variables:
99
105
 
100
- OpenAI Agents telemetry support is available as an optional extension of the
101
- base library.
106
+ | Variable | Required | Description |
107
+ | --- | --- | --- |
108
+ | `PROMPTLAYER_API_KEY` | Yes, unless passed as `apiKey` | API key used to authenticate requests to PromptLayer. |
109
+ | `PROMPTLAYER_BASE_URL` | No | Overrides the PromptLayer API base URL. Defaults to `https://api.promptlayer.com`. |
110
+ | `PROMPTLAYER_TRACEPARENT` | No | Optional trace context passed through the Claude Agents integration. |
102
111
 
103
- ```bash
104
- npm install promptlayer @openai/agents
105
- ```
112
+ ## Client Resources
106
113
 
107
- Claude Agents plugin support is available as an optional extension of the base
108
- library on macOS and Linux.
114
+ The main resources surfaced by `PromptLayer` are:
109
115
 
110
- ```bash
111
- npm install promptlayer @anthropic-ai/claude-agent-sdk
112
- ```
116
+ | Resource | Description |
117
+ | --- | --- |
118
+ | `client.templates` | Prompt template retrieval, listing, publishing, and cache invalidation. |
119
+ | `client.run()` and `client.runWorkflow()` | Helpers for running prompts and workflows. |
120
+ | `client.logRequest()` | Manual request logging. |
121
+ | `client.track` | Request annotation utilities for metadata, prompt linkage, scores, and groups. |
122
+ | `client.group` | Group creation for organizing related requests. |
123
+ | `client.wrapWithSpan()` | Helper for tracing your own functions and sending those spans to PromptLayer when tracing is enabled. |
124
+ | `client.skills` | Skill collection pull, publish, and update operations. |
125
+ | `client.OpenAI` and `client.Anthropic` | Provider proxies that wrap those SDKs and log requests to PromptLayer. |
113
126
 
114
- ```ts
115
- import { ClaudeAgentOptions } from "@anthropic-ai/claude-agent-sdk";
116
- import { getClaudeConfig } from "promptlayer/claude-agents";
117
-
118
- const plClaudeConfig = getClaudeConfig();
119
-
120
- const options = new ClaudeAgentOptions({
121
- model: "claude-sonnet-4-5",
122
- plugins: [plClaudeConfig.plugin],
123
- env: {
124
- ...plClaudeConfig.env,
125
- },
126
- });
127
- ```
127
+ Note: When tracing is enabled, spans are exported to PromptLayer using OpenTelemetry.
128
+
129
+ ## Integration Modules
130
+
131
+ Optional modules that are imported directly rather than accessed through the client:
132
+
133
+ | Module | Description |
134
+ | --- | --- |
135
+ | `promptlayer/openai-agents` | Tracing utilities for the [OpenAI Agents SDK](https://www.npmjs.com/package/@openai/agents) that instrument agent runs and export their traces to PromptLayer. |
136
+ | `promptlayer/claude-agents` | Configuration utilities for the [Claude Agent SDK](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk) that load the PromptLayer plugin and required environment settings so Claude agent runs send traces to PromptLayer. |
137
+
138
+ ## Error Handling
139
+
140
+ The SDK throws JavaScript `Error` instances for validation failures, missing API keys, unsupported providers, and PromptLayer API errors.
128
141
 
129
- ## Contributing
142
+ | Error case | Description |
143
+ | --- | --- |
144
+ | Missing API key | `PromptLayer` throws if no API key is passed and `PROMPTLAYER_API_KEY` is not set. |
145
+ | Validation failure | Some resource methods validate inputs before making a request, such as score ranges and skill collection providers. |
146
+ | PromptLayer API error | Non-success PromptLayer responses throw with the API error message when `throwOnError` is enabled. |
147
+ | Provider SDK error | Provider SDK calls made through `client.run()` or a provider proxy surface the underlying provider error. |
148
+ | Workflow failure | `client.runWorkflow()` can return `{ success: false, message }` for some workflow-start failures, and throws for errors such as timeouts or no successful output node. |
130
149
 
131
- We welcome contributions to our open source project, including new features, infrastructure improvements, and better documentation. For more information or any questions, contact us at [hello@promptlayer.com](mailto:hello@promptlayer.com).
150
+ By default, the client throws these errors. If you initialize `PromptLayer` with `throwOnError: false`, many resource methods return `null`, `false`, an empty result, or the original provider response instead of throwing on PromptLayer API errors.
132
151
 
133
- ## Requirements
152
+ ## Caching
134
153
 
135
- - Node.js 18.x or higher
154
+ When enabled, the SDK caches fetched prompt templates in memory for faster repeat reads, locally re-renders them with new variables, and falls back to stale cache on temporary API failures.
155
+ - Caching is disabled by default and is enabled by setting `cacheTtlSeconds` when creating `PromptLayer`.
156
+ - The cache applies to prompt templates fetched through `client.templates.get(...)`.
157
+ - Cached entries are stored in memory and keyed by prompt name, version, label, provider, and model.
158
+ - Requests that include `metadata_filters` or `model_parameter_overrides` bypass the cache.
159
+ - Templates that require server-side rendering behavior, such as placeholder messages or tool-variable expansion, are not cached for local rendering.
160
+ - If a cached template is stale and PromptLayer returns a transient error, the SDK can serve the stale cached version as a fallback.
161
+ - You can clear cached entries with `client.invalidate(...)` or `client.templates.invalidate(...)`.
@@ -1,2 +1,2 @@
1
- "use strict";var h=Object.create;var r=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var R=Object.getPrototypeOf,A=Object.prototype.hasOwnProperty;var P=(t,e)=>{for(var n in e)r(t,n,{get:e[n],enumerable:!0})},d=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of b(e))!A.call(t,o)&&o!==n&&r(t,o,{get:()=>e[o],enumerable:!(s=x(e,o))||s.enumerable});return t};var l=(t,e,n)=>(n=t!=null?h(R(t)):{},d(e||!t||!t.__esModule?r(n,"default",{value:t,enumerable:!0}):n,t)),w=t=>d(r({},"__esModule",{value:!0}),t);var K={};P(K,{getClaudeConfig:()=>y});module.exports=w(K);var c=l(require("fs")),a=l(require("path")),g=require("url");var I=l(require("ably")),O=require("centrifuge"),S=l(require("p-retry"));var N="1.3.2",q=()=>{var t;if(typeof process!="undefined"&&((t=process.versions)!=null&&t.node)){let e=process.versions.node.split(".");return`${e[0]}.${e[1]}`}return"unknown"},L=q(),it=`promptlayer-js/${N} (node ${L})`;var M=t=>{var e,n,s,o,i,u;if(typeof globalThis.process!="undefined")return(s=(n=(e=globalThis.process.env)==null?void 0:e[t])==null?void 0:n.trim())!=null?s:void 0;if(typeof globalThis.Deno!="undefined")return(u=(i=(o=globalThis.Deno.env)==null?void 0:o.get)==null?void 0:i.call(o,t))==null?void 0:u.trim()},f=t=>{if(t!==void 0){let n=t.trim();if(!n)throw new Error("PromptLayer API key not provided. Please set PROMPTLAYER_API_KEY or pass apiKey.");return n}let e=M("PROMPTLAYER_API_KEY");if(!e)throw new Error("PromptLayer API key not provided. Please set PROMPTLAYER_API_KEY or pass apiKey.");return e};var W=[".claude-plugin/plugin.json","setup.sh","hooks/hooks.json","hooks/lib.sh","hooks/session_start.sh","hooks/user_prompt_submit.sh","hooks/post_tool_use.sh","hooks/stop_hook.sh","hooks/session_end.sh","hooks/py/__init__.py","hooks/py/cli.py","hooks/py/context.py","hooks/py/handlers.py","hooks/py/otlp.py","hooks/py/settings.py","hooks/py/state.py","hooks/py/stop_parser.py","hooks/py/traceparent.py"],p=a.default.join("vendor","claude-agents","trace");function j(){let t=Error.prepareStackTrace;try{Error.prepareStackTrace=(s,o)=>o;let e=new Error().stack,n=e==null?void 0:e.map(s=>s.getFileName()).find(s=>s&&!s.startsWith("node:"));if(!n)throw new Error("PromptLayer Claude Agents could not determine its current module path.");return a.default.dirname(n.startsWith("file://")?(0,g.fileURLToPath)(n):n)}finally{Error.prepareStackTrace=t}}function $(){if(process.platform==="win32")throw new Error("PromptLayer Claude Agents integration does not support Windows. Use Linux or macOS.")}function G(){let t=j();return[a.default.resolve(t,"..","..","..",p),a.default.resolve(t,"..",p),a.default.resolve(t,"..","..",p)]}function U(t){let e=W.filter(n=>!c.default.existsSync(a.default.join(t,n)));if(e.length>0)throw new Error(`PromptLayer Claude Agents vendored plugin is incomplete. Missing: ${e.join(", ")}`)}function F(){for(let t of G())if(!(!c.default.existsSync(t)||!c.default.statSync(t).isDirectory()))return U(t),t;throw new Error("PromptLayer Claude Agents vendored plugin was not found in the installed package.")}function y(t={}){var i;$();let e=F(),n=f(t.apiKey),s=(i=t.traceparent)==null?void 0:i.trim(),o={TRACE_TO_PROMPTLAYER:"true",PROMPTLAYER_API_KEY:n};return s&&(o.PROMPTLAYER_TRACEPARENT=s),{plugin:{type:"local",path:e},env:o}}0&&(module.exports={getClaudeConfig});
1
+ "use strict";var h=Object.create;var r=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var R=Object.getPrototypeOf,A=Object.prototype.hasOwnProperty;var P=(t,e)=>{for(var n in e)r(t,n,{get:e[n],enumerable:!0})},d=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of b(e))!A.call(t,o)&&o!==n&&r(t,o,{get:()=>e[o],enumerable:!(s=x(e,o))||s.enumerable});return t};var l=(t,e,n)=>(n=t!=null?h(R(t)):{},d(e||!t||!t.__esModule?r(n,"default",{value:t,enumerable:!0}):n,t)),w=t=>d(r({},"__esModule",{value:!0}),t);var K={};P(K,{getClaudeConfig:()=>y});module.exports=w(K);var c=l(require("fs")),a=l(require("path")),g=require("url");var I=l(require("ably")),O=require("centrifuge"),S=l(require("p-retry"));var N="1.3.4",q=()=>{var t;if(typeof process!="undefined"&&((t=process.versions)!=null&&t.node)){let e=process.versions.node.split(".");return`${e[0]}.${e[1]}`}return"unknown"},L=q(),it=`promptlayer-js/${N} (node ${L})`;var M=t=>{var e,n,s,o,i,u;if(typeof globalThis.process!="undefined")return(s=(n=(e=globalThis.process.env)==null?void 0:e[t])==null?void 0:n.trim())!=null?s:void 0;if(typeof globalThis.Deno!="undefined")return(u=(i=(o=globalThis.Deno.env)==null?void 0:o.get)==null?void 0:i.call(o,t))==null?void 0:u.trim()},f=t=>{if(t!==void 0){let n=t.trim();if(!n)throw new Error("PromptLayer API key not provided. Please set PROMPTLAYER_API_KEY or pass apiKey.");return n}let e=M("PROMPTLAYER_API_KEY");if(!e)throw new Error("PromptLayer API key not provided. Please set PROMPTLAYER_API_KEY or pass apiKey.");return e};var W=[".claude-plugin/plugin.json","setup.sh","hooks/hooks.json","hooks/lib.sh","hooks/session_start.sh","hooks/user_prompt_submit.sh","hooks/post_tool_use.sh","hooks/stop_hook.sh","hooks/session_end.sh","hooks/py/__init__.py","hooks/py/cli.py","hooks/py/context.py","hooks/py/handlers.py","hooks/py/otlp.py","hooks/py/settings.py","hooks/py/state.py","hooks/py/stop_parser.py","hooks/py/traceparent.py"],p=a.default.join("vendor","claude-agents","trace");function j(){let t=Error.prepareStackTrace;try{Error.prepareStackTrace=(s,o)=>o;let e=new Error().stack,n=e==null?void 0:e.map(s=>s.getFileName()).find(s=>s&&!s.startsWith("node:"));if(!n)throw new Error("PromptLayer Claude Agents could not determine its current module path.");return a.default.dirname(n.startsWith("file://")?(0,g.fileURLToPath)(n):n)}finally{Error.prepareStackTrace=t}}function $(){if(process.platform==="win32")throw new Error("PromptLayer Claude Agents integration does not support Windows. Use Linux or macOS.")}function G(){let t=j();return[a.default.resolve(t,"..","..","..",p),a.default.resolve(t,"..",p),a.default.resolve(t,"..","..",p)]}function U(t){let e=W.filter(n=>!c.default.existsSync(a.default.join(t,n)));if(e.length>0)throw new Error(`PromptLayer Claude Agents vendored plugin is incomplete. Missing: ${e.join(", ")}`)}function F(){for(let t of G())if(!(!c.default.existsSync(t)||!c.default.statSync(t).isDirectory()))return U(t),t;throw new Error("PromptLayer Claude Agents vendored plugin was not found in the installed package.")}function y(t={}){var i;$();let e=F(),n=f(t.apiKey),s=(i=t.traceparent)==null?void 0:i.trim(),o={TRACE_TO_PROMPTLAYER:"true",PROMPTLAYER_API_KEY:n};return s&&(o.PROMPTLAYER_TRACEPARENT=s),{plugin:{type:"local",path:e},env:o}}0&&(module.exports={getClaudeConfig});
2
2
  //# sourceMappingURL=claude-agents.js.map