@promptev/client 0.0.3 → 0.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.
@@ -1,58 +1,276 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
2
+ // ── Types ───────────────────────────────────────────────
5
3
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.PromptevClient = void 0;
7
- const axios_1 = __importDefault(require("axios"));
4
+ exports.PromptevClient = exports.NetworkError = exports.ServerError = exports.RateLimitError = exports.NotFoundError = exports.AuthenticationError = exports.ValidationError = exports.PromptevError = void 0;
5
+ // ── Errors ──────────────────────────────────────────────
6
+ class PromptevError extends Error {
7
+ constructor(message, statusCode, responseText) {
8
+ super(message);
9
+ this.name = "PromptevError";
10
+ this.statusCode = statusCode;
11
+ this.responseText = responseText;
12
+ }
13
+ }
14
+ exports.PromptevError = PromptevError;
15
+ class ValidationError extends PromptevError {
16
+ constructor(message, statusCode, responseText) {
17
+ super(message, statusCode, responseText);
18
+ this.name = "ValidationError";
19
+ }
20
+ }
21
+ exports.ValidationError = ValidationError;
22
+ class AuthenticationError extends PromptevError {
23
+ constructor(message, statusCode, responseText) {
24
+ super(message, statusCode, responseText);
25
+ this.name = "AuthenticationError";
26
+ }
27
+ }
28
+ exports.AuthenticationError = AuthenticationError;
29
+ class NotFoundError extends PromptevError {
30
+ constructor(message, statusCode, responseText) {
31
+ super(message, statusCode, responseText);
32
+ this.name = "NotFoundError";
33
+ }
34
+ }
35
+ exports.NotFoundError = NotFoundError;
36
+ class RateLimitError extends PromptevError {
37
+ constructor(message, statusCode, responseText) {
38
+ super(message, statusCode, responseText);
39
+ this.name = "RateLimitError";
40
+ }
41
+ }
42
+ exports.RateLimitError = RateLimitError;
43
+ class ServerError extends PromptevError {
44
+ constructor(message, statusCode, responseText) {
45
+ super(message, statusCode, responseText);
46
+ this.name = "ServerError";
47
+ }
48
+ }
49
+ exports.ServerError = ServerError;
50
+ class NetworkError extends PromptevError {
51
+ constructor(message, statusCode, responseText) {
52
+ super(message, statusCode, responseText);
53
+ this.name = "NetworkError";
54
+ }
55
+ }
56
+ exports.NetworkError = NetworkError;
57
+ // ── Client ──────────────────────────────────────────────
58
+ const RETRYABLE_STATUS = new Set([502, 503, 504]);
59
+ const DEFAULT_MAX_RETRIES = 2;
60
+ const DEFAULT_BACKOFF = 500; // ms
8
61
  class PromptevClient {
9
62
  constructor(config) {
10
- this.baseUrl = config.baseUrl ?? "https://api.promptev.ai";
11
63
  this.projectKey = config.projectKey;
12
- this.client = axios_1.default.create({
13
- baseURL: this.baseUrl,
14
- headers: {
15
- "Content-Type": "application/json",
16
- ...(config.headers ?? {}),
17
- },
64
+ this.baseUrl = (config.baseUrl ?? "https://api.promptev.ai").replace(/\/+$/, "");
65
+ this.headers = {
66
+ "Content-Type": "application/json",
67
+ ...(config.headers ?? {}),
68
+ };
69
+ this.timeout = config.timeout ?? 30000;
70
+ this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
71
+ }
72
+ // ── Error handling ──────────────────────────────────
73
+ static raiseForStatus(status, text) {
74
+ if (status < 400)
75
+ return;
76
+ let detail;
77
+ try {
78
+ const body = JSON.parse(text);
79
+ detail =
80
+ typeof body.detail === "string" ? body.detail : text || "Unknown error";
81
+ }
82
+ catch {
83
+ detail = text || "Unknown error";
84
+ }
85
+ if (status === 400)
86
+ throw new ValidationError(detail, status, text);
87
+ if (status === 401)
88
+ throw new AuthenticationError(detail, status, text);
89
+ if (status === 403)
90
+ throw new AuthenticationError(detail, status, text);
91
+ if (status === 404)
92
+ throw new NotFoundError(detail, status, text);
93
+ if (status === 429)
94
+ throw new RateLimitError(detail, status, text);
95
+ if (status >= 500)
96
+ throw new ServerError(detail, status, text);
97
+ throw new PromptevError(detail, status, text);
98
+ }
99
+ // ── Retry helper ────────────────────────────────────
100
+ async fetchWithRetry(url, init) {
101
+ let lastError = null;
102
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
103
+ try {
104
+ const controller = new AbortController();
105
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
106
+ const resp = await fetch(url, {
107
+ ...init,
108
+ signal: controller.signal,
109
+ });
110
+ clearTimeout(timeoutId);
111
+ if (!RETRYABLE_STATUS.has(resp.status) || attempt === this.maxRetries) {
112
+ return resp;
113
+ }
114
+ lastError = new ServerError(`Server error (${resp.status})`, resp.status);
115
+ }
116
+ catch (err) {
117
+ if (err.name === "AbortError") {
118
+ lastError = new NetworkError("Request timed out");
119
+ }
120
+ else {
121
+ lastError = new NetworkError(`Network error: ${err.message}`);
122
+ }
123
+ if (attempt === this.maxRetries)
124
+ throw lastError;
125
+ }
126
+ const delay = DEFAULT_BACKOFF * Math.pow(2, attempt);
127
+ await new Promise((resolve) => setTimeout(resolve, delay));
128
+ }
129
+ throw lastError;
130
+ }
131
+ // ── SSE parser ──────────────────────────────────────
132
+ async *parseSSE(response) {
133
+ const reader = response.body.getReader();
134
+ const decoder = new TextDecoder();
135
+ let buffer = "";
136
+ try {
137
+ while (true) {
138
+ const { done, value } = await reader.read();
139
+ if (done)
140
+ break;
141
+ buffer += decoder.decode(value, { stream: true });
142
+ const lines = buffer.split("\n");
143
+ buffer = lines.pop() || "";
144
+ for (const line of lines) {
145
+ if (!line.startsWith("data: "))
146
+ continue;
147
+ try {
148
+ const data = JSON.parse(line.slice(6));
149
+ const event = {
150
+ type: data.type || "unknown",
151
+ output: data.output || "",
152
+ raw: data,
153
+ };
154
+ yield event;
155
+ if (event.type === "done" || event.type === "error")
156
+ return;
157
+ }
158
+ catch {
159
+ continue;
160
+ }
161
+ }
162
+ }
163
+ }
164
+ finally {
165
+ reader.releaseLock();
166
+ }
167
+ }
168
+ // ── Agent API ───────────────────────────────────────
169
+ /**
170
+ * Trigger an agent in a single blocking call — the primary way to use the SDK.
171
+ *
172
+ * Creates (or resumes) a session AND runs the agent, returning the final
173
+ * response as JSON. Any tools the agent has attached run server-side.
174
+ *
175
+ * @param agentId - Your agent's id (from the Deploy tab).
176
+ * @param message - The user message to send to the agent.
177
+ * @param opts.sessionId - Pass the `sessionId` from a previous call to keep
178
+ * conversation memory. Omit it for a fresh, stateless run.
179
+ * @param opts.variables - Object filling the agent's `{{...}}` prompt variables.
180
+ * @returns `{ response, sessionId }` — pass `sessionId` back on the next call
181
+ * to continue the same conversation.
182
+ *
183
+ * @example
184
+ * const { response, sessionId } = await client.triggerAgent(
185
+ * "your-agent-id",
186
+ * "What is the refund policy?",
187
+ * { variables: { company: "Acme Corp" } }
188
+ * );
189
+ * // Follow-up keeps memory:
190
+ * await client.triggerAgent("your-agent-id", "And for digital goods?", { sessionId });
191
+ */
192
+ async triggerAgent(agentId, message, opts) {
193
+ const url = `${this.baseUrl}/api/sdk/v1/agent/${this.projectKey}/${agentId}/trigger`;
194
+ const payload = { message };
195
+ if (opts?.sessionId != null)
196
+ payload.session_id = opts.sessionId;
197
+ if (opts?.variables != null)
198
+ payload.variables = opts.variables;
199
+ // Optional caller/end-user id stored on the chat session; defaults server-side
200
+ // to a generated webhook_<id> when omitted.
201
+ if (opts?.visitor != null)
202
+ payload.visitor = opts.visitor;
203
+ const resp = await this.fetchWithRetry(url, {
204
+ method: "POST",
205
+ headers: this.headers,
206
+ body: JSON.stringify(payload),
18
207
  });
208
+ const text = await resp.text();
209
+ PromptevClient.raiseForStatus(resp.status, text);
210
+ const data = JSON.parse(text);
211
+ return {
212
+ response: typeof data.response === "string" ? data.response : "",
213
+ sessionId: data.session_id,
214
+ };
19
215
  }
20
216
  /**
21
- * Compile a prompt by POSTing variables.
22
- * Body shape (exact):
23
- * {
24
- * "variables": {
25
- * "additionalProp1": "string",
26
- * "additionalProp2": "string",
27
- * "additionalProp3": "string"
28
- * }
29
- * }
217
+ * Start a new agent chat session (streaming flow).
218
+ *
219
+ * @param agentId - Your agent's id (from the Deploy tab).
30
220
  */
31
- async getPrompt(promptKey, variables = {}, opts) {
32
- const url = `/api/sdk/v1/prompt/client/${this.projectKey}/${promptKey}`;
221
+ async startAgent(agentId, options) {
222
+ const url = `${this.baseUrl}/api/sdk/v1/agent/${this.projectKey}/${agentId}/start`;
223
+ const payload = {};
224
+ if (options?.visitor != null)
225
+ payload.visitor = options.visitor;
226
+ if (options?.platform && options.platform !== "sdk")
227
+ payload.platform = options.platform;
228
+ const resp = await this.fetchWithRetry(url, {
229
+ method: "POST",
230
+ headers: this.headers,
231
+ body: JSON.stringify(payload),
232
+ });
233
+ const text = await resp.text();
234
+ PromptevClient.raiseForStatus(resp.status, text);
235
+ const data = JSON.parse(text);
236
+ return {
237
+ sessionToken: data.session_token,
238
+ agentId: data.chatbot_id,
239
+ name: data.name,
240
+ memoryEnabled: data.memory_enabled ?? false,
241
+ messages: data.messages ?? [],
242
+ };
243
+ }
244
+ /**
245
+ * Stream an agent response as SSE events.
246
+ *
247
+ * @param agentId - Your agent's id (from the Deploy tab).
248
+ */
249
+ async *streamAgent(agentId, options) {
250
+ const url = `${this.baseUrl}/api/sdk/v1/agent/${this.projectKey}/${agentId}/stream?session_token=${encodeURIComponent(options.sessionToken)}`;
251
+ const controller = new AbortController();
252
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
253
+ let resp;
33
254
  try {
34
- const resp = await this.client.post(url, { variables }, // <-- exact body
35
- { signal: opts?.signal });
36
- // Success shape: { prompt: string }
37
- const compiled = resp.data?.prompt;
38
- if (typeof compiled !== "string") {
39
- throw new Error("Unexpected response: missing 'prompt' field");
40
- }
41
- return compiled;
255
+ resp = await fetch(url, {
256
+ method: "POST",
257
+ headers: this.headers,
258
+ body: JSON.stringify({ query: options.query }),
259
+ signal: controller.signal,
260
+ });
42
261
  }
43
262
  catch (err) {
44
- const ax = err;
45
- const status = ax.response?.status;
46
- const body = ax.response?.data;
47
- const detail = body?.detail ?? body;
48
- // Your API returns detail as a plain string on 400
49
- if (typeof detail === "string") {
50
- throw new Error(detail);
51
- }
52
- // Fallback error
53
- const msg = `Request failed${status ? ` (${status})` : ""}`;
54
- throw new Error(msg);
263
+ clearTimeout(timeoutId);
264
+ if (err.name === "AbortError")
265
+ throw new NetworkError("Request timed out");
266
+ throw new NetworkError(`Network error: ${err.message}`);
267
+ }
268
+ clearTimeout(timeoutId);
269
+ if (resp.status >= 400) {
270
+ const text = await resp.text();
271
+ PromptevClient.raiseForStatus(resp.status, text);
55
272
  }
273
+ yield* this.parseSSE(resp);
56
274
  }
57
275
  }
58
276
  exports.PromptevClient = PromptevClient;
@@ -1,26 +1,104 @@
1
1
  export interface PromptevClientConfig {
2
- baseUrl?: string;
3
2
  projectKey: string;
3
+ baseUrl?: string;
4
4
  headers?: Record<string, string>;
5
+ timeout?: number;
6
+ maxRetries?: number;
7
+ }
8
+ export interface AgentSession {
9
+ sessionToken: string;
10
+ agentId: string;
11
+ name: string;
12
+ memoryEnabled: boolean;
13
+ messages: Record<string, any>[];
14
+ }
15
+ export interface TriggerResult {
16
+ response: string;
17
+ sessionId: string;
18
+ }
19
+ export interface AgentEvent {
20
+ type: string;
21
+ output: string;
22
+ raw: Record<string, any>;
23
+ }
24
+ export declare class PromptevError extends Error {
25
+ statusCode?: number;
26
+ responseText?: string;
27
+ constructor(message: string, statusCode?: number, responseText?: string);
28
+ }
29
+ export declare class ValidationError extends PromptevError {
30
+ constructor(message: string, statusCode?: number, responseText?: string);
31
+ }
32
+ export declare class AuthenticationError extends PromptevError {
33
+ constructor(message: string, statusCode?: number, responseText?: string);
34
+ }
35
+ export declare class NotFoundError extends PromptevError {
36
+ constructor(message: string, statusCode?: number, responseText?: string);
37
+ }
38
+ export declare class RateLimitError extends PromptevError {
39
+ constructor(message: string, statusCode?: number, responseText?: string);
40
+ }
41
+ export declare class ServerError extends PromptevError {
42
+ constructor(message: string, statusCode?: number, responseText?: string);
43
+ }
44
+ export declare class NetworkError extends PromptevError {
45
+ constructor(message: string, statusCode?: number, responseText?: string);
5
46
  }
6
47
  export declare class PromptevClient {
7
- private client;
8
- private baseUrl;
9
48
  private projectKey;
49
+ private baseUrl;
50
+ private headers;
51
+ private timeout;
52
+ private maxRetries;
10
53
  constructor(config: PromptevClientConfig);
54
+ private static raiseForStatus;
55
+ private fetchWithRetry;
56
+ private parseSSE;
57
+ /**
58
+ * Trigger an agent in a single blocking call — the primary way to use the SDK.
59
+ *
60
+ * Creates (or resumes) a session AND runs the agent, returning the final
61
+ * response as JSON. Any tools the agent has attached run server-side.
62
+ *
63
+ * @param agentId - Your agent's id (from the Deploy tab).
64
+ * @param message - The user message to send to the agent.
65
+ * @param opts.sessionId - Pass the `sessionId` from a previous call to keep
66
+ * conversation memory. Omit it for a fresh, stateless run.
67
+ * @param opts.variables - Object filling the agent's `{{...}}` prompt variables.
68
+ * @returns `{ response, sessionId }` — pass `sessionId` back on the next call
69
+ * to continue the same conversation.
70
+ *
71
+ * @example
72
+ * const { response, sessionId } = await client.triggerAgent(
73
+ * "your-agent-id",
74
+ * "What is the refund policy?",
75
+ * { variables: { company: "Acme Corp" } }
76
+ * );
77
+ * // Follow-up keeps memory:
78
+ * await client.triggerAgent("your-agent-id", "And for digital goods?", { sessionId });
79
+ */
80
+ triggerAgent(agentId: string, message: string, opts?: {
81
+ sessionId?: string;
82
+ variables?: Record<string, any>;
83
+ visitor?: string;
84
+ }): Promise<TriggerResult>;
85
+ /**
86
+ * Start a new agent chat session (streaming flow).
87
+ *
88
+ * @param agentId - Your agent's id (from the Deploy tab).
89
+ */
90
+ startAgent(agentId: string, options?: {
91
+ visitor?: string;
92
+ platform?: string;
93
+ }): Promise<AgentSession>;
11
94
  /**
12
- * Compile a prompt by POSTing variables.
13
- * Body shape (exact):
14
- * {
15
- * "variables": {
16
- * "additionalProp1": "string",
17
- * "additionalProp2": "string",
18
- * "additionalProp3": "string"
19
- * }
20
- * }
95
+ * Stream an agent response as SSE events.
96
+ *
97
+ * @param agentId - Your agent's id (from the Deploy tab).
21
98
  */
22
- getPrompt(promptKey: string, variables?: Record<string, string>, opts?: {
23
- signal?: AbortSignal;
24
- }): Promise<string>;
99
+ streamAgent(agentId: string, options: {
100
+ sessionToken: string;
101
+ query: string;
102
+ }): AsyncGenerator<AgentEvent>;
25
103
  }
26
104
  export default PromptevClient;
package/dist/esm/index.js CHANGED
@@ -1,52 +1,266 @@
1
- import axios from "axios";
1
+ // ── Types ───────────────────────────────────────────────
2
+ // ── Errors ──────────────────────────────────────────────
3
+ export class PromptevError extends Error {
4
+ constructor(message, statusCode, responseText) {
5
+ super(message);
6
+ this.name = "PromptevError";
7
+ this.statusCode = statusCode;
8
+ this.responseText = responseText;
9
+ }
10
+ }
11
+ export class ValidationError extends PromptevError {
12
+ constructor(message, statusCode, responseText) {
13
+ super(message, statusCode, responseText);
14
+ this.name = "ValidationError";
15
+ }
16
+ }
17
+ export class AuthenticationError extends PromptevError {
18
+ constructor(message, statusCode, responseText) {
19
+ super(message, statusCode, responseText);
20
+ this.name = "AuthenticationError";
21
+ }
22
+ }
23
+ export class NotFoundError extends PromptevError {
24
+ constructor(message, statusCode, responseText) {
25
+ super(message, statusCode, responseText);
26
+ this.name = "NotFoundError";
27
+ }
28
+ }
29
+ export class RateLimitError extends PromptevError {
30
+ constructor(message, statusCode, responseText) {
31
+ super(message, statusCode, responseText);
32
+ this.name = "RateLimitError";
33
+ }
34
+ }
35
+ export class ServerError extends PromptevError {
36
+ constructor(message, statusCode, responseText) {
37
+ super(message, statusCode, responseText);
38
+ this.name = "ServerError";
39
+ }
40
+ }
41
+ export class NetworkError extends PromptevError {
42
+ constructor(message, statusCode, responseText) {
43
+ super(message, statusCode, responseText);
44
+ this.name = "NetworkError";
45
+ }
46
+ }
47
+ // ── Client ──────────────────────────────────────────────
48
+ const RETRYABLE_STATUS = new Set([502, 503, 504]);
49
+ const DEFAULT_MAX_RETRIES = 2;
50
+ const DEFAULT_BACKOFF = 500; // ms
2
51
  export class PromptevClient {
3
52
  constructor(config) {
4
- this.baseUrl = config.baseUrl ?? "https://api.promptev.ai";
5
53
  this.projectKey = config.projectKey;
6
- this.client = axios.create({
7
- baseURL: this.baseUrl,
8
- headers: {
9
- "Content-Type": "application/json",
10
- ...(config.headers ?? {}),
11
- },
54
+ this.baseUrl = (config.baseUrl ?? "https://api.promptev.ai").replace(/\/+$/, "");
55
+ this.headers = {
56
+ "Content-Type": "application/json",
57
+ ...(config.headers ?? {}),
58
+ };
59
+ this.timeout = config.timeout ?? 30000;
60
+ this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
61
+ }
62
+ // ── Error handling ──────────────────────────────────
63
+ static raiseForStatus(status, text) {
64
+ if (status < 400)
65
+ return;
66
+ let detail;
67
+ try {
68
+ const body = JSON.parse(text);
69
+ detail =
70
+ typeof body.detail === "string" ? body.detail : text || "Unknown error";
71
+ }
72
+ catch {
73
+ detail = text || "Unknown error";
74
+ }
75
+ if (status === 400)
76
+ throw new ValidationError(detail, status, text);
77
+ if (status === 401)
78
+ throw new AuthenticationError(detail, status, text);
79
+ if (status === 403)
80
+ throw new AuthenticationError(detail, status, text);
81
+ if (status === 404)
82
+ throw new NotFoundError(detail, status, text);
83
+ if (status === 429)
84
+ throw new RateLimitError(detail, status, text);
85
+ if (status >= 500)
86
+ throw new ServerError(detail, status, text);
87
+ throw new PromptevError(detail, status, text);
88
+ }
89
+ // ── Retry helper ────────────────────────────────────
90
+ async fetchWithRetry(url, init) {
91
+ let lastError = null;
92
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
93
+ try {
94
+ const controller = new AbortController();
95
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
96
+ const resp = await fetch(url, {
97
+ ...init,
98
+ signal: controller.signal,
99
+ });
100
+ clearTimeout(timeoutId);
101
+ if (!RETRYABLE_STATUS.has(resp.status) || attempt === this.maxRetries) {
102
+ return resp;
103
+ }
104
+ lastError = new ServerError(`Server error (${resp.status})`, resp.status);
105
+ }
106
+ catch (err) {
107
+ if (err.name === "AbortError") {
108
+ lastError = new NetworkError("Request timed out");
109
+ }
110
+ else {
111
+ lastError = new NetworkError(`Network error: ${err.message}`);
112
+ }
113
+ if (attempt === this.maxRetries)
114
+ throw lastError;
115
+ }
116
+ const delay = DEFAULT_BACKOFF * Math.pow(2, attempt);
117
+ await new Promise((resolve) => setTimeout(resolve, delay));
118
+ }
119
+ throw lastError;
120
+ }
121
+ // ── SSE parser ──────────────────────────────────────
122
+ async *parseSSE(response) {
123
+ const reader = response.body.getReader();
124
+ const decoder = new TextDecoder();
125
+ let buffer = "";
126
+ try {
127
+ while (true) {
128
+ const { done, value } = await reader.read();
129
+ if (done)
130
+ break;
131
+ buffer += decoder.decode(value, { stream: true });
132
+ const lines = buffer.split("\n");
133
+ buffer = lines.pop() || "";
134
+ for (const line of lines) {
135
+ if (!line.startsWith("data: "))
136
+ continue;
137
+ try {
138
+ const data = JSON.parse(line.slice(6));
139
+ const event = {
140
+ type: data.type || "unknown",
141
+ output: data.output || "",
142
+ raw: data,
143
+ };
144
+ yield event;
145
+ if (event.type === "done" || event.type === "error")
146
+ return;
147
+ }
148
+ catch {
149
+ continue;
150
+ }
151
+ }
152
+ }
153
+ }
154
+ finally {
155
+ reader.releaseLock();
156
+ }
157
+ }
158
+ // ── Agent API ───────────────────────────────────────
159
+ /**
160
+ * Trigger an agent in a single blocking call — the primary way to use the SDK.
161
+ *
162
+ * Creates (or resumes) a session AND runs the agent, returning the final
163
+ * response as JSON. Any tools the agent has attached run server-side.
164
+ *
165
+ * @param agentId - Your agent's id (from the Deploy tab).
166
+ * @param message - The user message to send to the agent.
167
+ * @param opts.sessionId - Pass the `sessionId` from a previous call to keep
168
+ * conversation memory. Omit it for a fresh, stateless run.
169
+ * @param opts.variables - Object filling the agent's `{{...}}` prompt variables.
170
+ * @returns `{ response, sessionId }` — pass `sessionId` back on the next call
171
+ * to continue the same conversation.
172
+ *
173
+ * @example
174
+ * const { response, sessionId } = await client.triggerAgent(
175
+ * "your-agent-id",
176
+ * "What is the refund policy?",
177
+ * { variables: { company: "Acme Corp" } }
178
+ * );
179
+ * // Follow-up keeps memory:
180
+ * await client.triggerAgent("your-agent-id", "And for digital goods?", { sessionId });
181
+ */
182
+ async triggerAgent(agentId, message, opts) {
183
+ const url = `${this.baseUrl}/api/sdk/v1/agent/${this.projectKey}/${agentId}/trigger`;
184
+ const payload = { message };
185
+ if (opts?.sessionId != null)
186
+ payload.session_id = opts.sessionId;
187
+ if (opts?.variables != null)
188
+ payload.variables = opts.variables;
189
+ // Optional caller/end-user id stored on the chat session; defaults server-side
190
+ // to a generated webhook_<id> when omitted.
191
+ if (opts?.visitor != null)
192
+ payload.visitor = opts.visitor;
193
+ const resp = await this.fetchWithRetry(url, {
194
+ method: "POST",
195
+ headers: this.headers,
196
+ body: JSON.stringify(payload),
12
197
  });
198
+ const text = await resp.text();
199
+ PromptevClient.raiseForStatus(resp.status, text);
200
+ const data = JSON.parse(text);
201
+ return {
202
+ response: typeof data.response === "string" ? data.response : "",
203
+ sessionId: data.session_id,
204
+ };
13
205
  }
14
206
  /**
15
- * Compile a prompt by POSTing variables.
16
- * Body shape (exact):
17
- * {
18
- * "variables": {
19
- * "additionalProp1": "string",
20
- * "additionalProp2": "string",
21
- * "additionalProp3": "string"
22
- * }
23
- * }
207
+ * Start a new agent chat session (streaming flow).
208
+ *
209
+ * @param agentId - Your agent's id (from the Deploy tab).
24
210
  */
25
- async getPrompt(promptKey, variables = {}, opts) {
26
- const url = `/api/sdk/v1/prompt/client/${this.projectKey}/${promptKey}`;
211
+ async startAgent(agentId, options) {
212
+ const url = `${this.baseUrl}/api/sdk/v1/agent/${this.projectKey}/${agentId}/start`;
213
+ const payload = {};
214
+ if (options?.visitor != null)
215
+ payload.visitor = options.visitor;
216
+ if (options?.platform && options.platform !== "sdk")
217
+ payload.platform = options.platform;
218
+ const resp = await this.fetchWithRetry(url, {
219
+ method: "POST",
220
+ headers: this.headers,
221
+ body: JSON.stringify(payload),
222
+ });
223
+ const text = await resp.text();
224
+ PromptevClient.raiseForStatus(resp.status, text);
225
+ const data = JSON.parse(text);
226
+ return {
227
+ sessionToken: data.session_token,
228
+ agentId: data.chatbot_id,
229
+ name: data.name,
230
+ memoryEnabled: data.memory_enabled ?? false,
231
+ messages: data.messages ?? [],
232
+ };
233
+ }
234
+ /**
235
+ * Stream an agent response as SSE events.
236
+ *
237
+ * @param agentId - Your agent's id (from the Deploy tab).
238
+ */
239
+ async *streamAgent(agentId, options) {
240
+ const url = `${this.baseUrl}/api/sdk/v1/agent/${this.projectKey}/${agentId}/stream?session_token=${encodeURIComponent(options.sessionToken)}`;
241
+ const controller = new AbortController();
242
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
243
+ let resp;
27
244
  try {
28
- const resp = await this.client.post(url, { variables }, // <-- exact body
29
- { signal: opts?.signal });
30
- // Success shape: { prompt: string }
31
- const compiled = resp.data?.prompt;
32
- if (typeof compiled !== "string") {
33
- throw new Error("Unexpected response: missing 'prompt' field");
34
- }
35
- return compiled;
245
+ resp = await fetch(url, {
246
+ method: "POST",
247
+ headers: this.headers,
248
+ body: JSON.stringify({ query: options.query }),
249
+ signal: controller.signal,
250
+ });
36
251
  }
37
252
  catch (err) {
38
- const ax = err;
39
- const status = ax.response?.status;
40
- const body = ax.response?.data;
41
- const detail = body?.detail ?? body;
42
- // Your API returns detail as a plain string on 400
43
- if (typeof detail === "string") {
44
- throw new Error(detail);
45
- }
46
- // Fallback error
47
- const msg = `Request failed${status ? ` (${status})` : ""}`;
48
- throw new Error(msg);
253
+ clearTimeout(timeoutId);
254
+ if (err.name === "AbortError")
255
+ throw new NetworkError("Request timed out");
256
+ throw new NetworkError(`Network error: ${err.message}`);
257
+ }
258
+ clearTimeout(timeoutId);
259
+ if (resp.status >= 400) {
260
+ const text = await resp.text();
261
+ PromptevClient.raiseForStatus(resp.status, text);
49
262
  }
263
+ yield* this.parseSSE(resp);
50
264
  }
51
265
  }
52
266
  export default PromptevClient;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@promptev/client",
3
- "version": "0.0.3",
4
- "description": "Client library for accessing Promptev API",
3
+ "version": "0.2.0",
4
+ "description": "JavaScript/TypeScript SDK for Promptev — trigger and stream your AI agents programmatically",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.cjs",
7
7
  "module": "./dist/esm/index.js",
@@ -13,7 +13,7 @@
13
13
  "types": "./dist/esm/index.d.ts"
14
14
  }
15
15
  },
16
- "license": "MIT",
16
+ "license": "SEE LICENSE IN LICENSE.txt",
17
17
  "author": "Promptev Inc. <support@promptev.ai>",
18
18
  "private": false,
19
19
  "publishConfig": {
@@ -27,14 +27,13 @@
27
27
  ],
28
28
  "keywords": [
29
29
  "promptev",
30
- "prompts",
30
+ "agents",
31
+ "agent-sdk",
32
+ "ai",
31
33
  "api",
32
34
  "client",
33
35
  "sdk",
34
- "ai",
35
- "promptDev",
36
- "promptdev",
37
- "promptops",
36
+ "context-engineering",
38
37
  "typescript",
39
38
  "javascript"
40
39
  ],
@@ -44,10 +43,7 @@
44
43
  "build:cjs": "tsc -p tsconfig.cjs.json && node scripts/rename-cjs.cjs",
45
44
  "build": "npm run build:esm && npm run build:cjs"
46
45
  },
47
- "dependencies": {
48
- "axios": "^1.10.0",
49
- "node-cache": "^5.1.2"
50
- },
46
+ "dependencies": {},
51
47
  "devDependencies": {
52
48
  "@types/node": "^20.10.0",
53
49
  "ts-node": "^10.9.2",
package/readme.md CHANGED
@@ -1,116 +1,463 @@
1
- # promptev-client (JavaScript / TypeScript)
1
+ # Promptev JavaScript SDK
2
2
 
3
- A lightweight JS SDK to fetch compiled prompts from [Promptev.ai](https://promptev.ai).
3
+ The official JavaScript/TypeScript SDK for [Promptev.ai](https://promptev.ai) — trigger and stream your AI **agents** programmatically using your project API key.
4
4
 
5
- ---
5
+ > In Promptev, an **agent** is your deployed AI assistant: instructions + model + tools (Jira, Slack, GitHub, …) + context packs, all configured in the dashboard. This SDK runs those agents. Tools execute server-side, memory is built in.
6
6
 
7
7
  ## Installation
8
8
 
9
9
  ```bash
10
10
  npm install @promptev/client
11
11
  # or
12
- yarn install @promptev/client
13
- #or
12
+ yarn add @promptev/client
13
+ # or
14
14
  pnpm add @promptev/client
15
15
  ```
16
16
 
17
- ---
17
+ Requires Node.js 18+ or any modern browser. Zero dependencies.
18
+
19
+ ## Platform Support
20
+
21
+ Works everywhere — backend, frontend, and edge runtimes. Built entirely on [Web Platform APIs](https://wintercg.org/) (`fetch`, `ReadableStream`, `AbortController`, `TextDecoder`) with no Node.js-specific modules.
18
22
 
19
- ## What is Promptev?
23
+ | Environment | Supported | Notes |
24
+ |---|---|---|
25
+ | **Node.js 18+** | ✅ | ESM and CommonJS |
26
+ | **Bun** | ✅ | Native Web API support |
27
+ | **Deno** | ✅ | Native Web API support |
28
+ | **React / Next.js** | ✅ | Works with any bundler |
29
+ | **Angular** | ✅ | Full TypeScript types included |
30
+ | **Vue / Nuxt** | ✅ | Standard ESM import |
31
+ | **Svelte / SvelteKit** | ✅ | Standard ESM import |
32
+ | **Vanilla JS** | ✅ | No framework required |
33
+ | **Cloudflare Workers** | ✅ | Edge runtime compatible |
34
+ | **Vercel Edge Functions** | ✅ | Edge runtime compatible |
20
35
 
21
- [Promptev](https://promptev.ai) helps teams manage, version, and collaborate on AI prompts at scale — with variables, live context packs, histories, cost estimation, and SDK access.
22
- ---
36
+ ```js
37
+ // ESM (Node 18+, React, Next.js, Vue, Angular, Svelte, etc.)
38
+ import { PromptevClient } from "@promptev/client";
39
+
40
+ // CommonJS (legacy Node.js projects)
41
+ const { PromptevClient } = require("@promptev/client");
42
+ ```
23
43
 
24
- ## Usage
44
+ ## Quick Start
25
45
 
26
- ### 1. Initialize the client
46
+ The fastest way to use an agent is `triggerAgent` — one blocking call that runs the agent and returns its final answer. Pass your agent's id (from the **Deploy** tab) and a message:
27
47
 
28
48
  ```ts
29
49
  import { PromptevClient } from "@promptev/client";
30
50
 
31
- const client = new PromptevClient({
32
- projectKey: "pv_sk_abc123yourkey"
33
- });
51
+ const client = new PromptevClient({ projectKey: "pv_sk_your_key_here" });
52
+
53
+ const { response, sessionId } = await client.triggerAgent(
54
+ "your-agent-id",
55
+ "What is the refund policy?",
56
+ { variables: { company: "Acme Corp" } }
57
+ );
58
+ console.log(response);
59
+
60
+ // Keep conversation memory by passing the same sessionId back:
61
+ const followUp = await client.triggerAgent(
62
+ "your-agent-id",
63
+ "And for digital goods?",
64
+ { sessionId }
65
+ );
66
+ console.log(followUp.response);
34
67
  ```
35
68
 
36
- ---
69
+ That's it. The agent's tools, context packs, and model all run server-side — you just get the answer.
70
+
71
+ ## `triggerAgent` — run an agent in one call
37
72
 
38
- ### 2. Fetch a prompt with variables
73
+ `triggerAgent(agentId, message, opts?)` creates **or** resumes a session **and** runs the agent, returning the final response as JSON.
39
74
 
40
75
  ```ts
41
- const prompt = await client.getPrompt("onboarding-email", {
42
- name: "Ava",
43
- product: "Promptev"
44
- });
76
+ const result = await client.triggerAgent("your-agent-id", "Summarize our Q4 sales report");
77
+ console.log(result.response); // the agent's answer
78
+ console.log(result.sessionId); // pass this back to continue the conversation
79
+ ```
45
80
 
46
- console.log(prompt);
47
- // "Subject: Welcome, Ava! Hey Ava, Thanks for joining Promptev..."
81
+ | Parameter | Type | Description |
82
+ |---|---|---|
83
+ | `agentId` | `string` | Your agent's id (from the Deploy tab) |
84
+ | `message` | `string` | The user message to send to the agent |
85
+ | `opts.sessionId` | `string?` | Pass the `sessionId` from a previous call to keep memory. Omit for a fresh, stateless run. |
86
+ | `opts.variables` | `object?` | Fills the agent's `{{...}}` prompt variables |
87
+ | `opts.visitor` | `string?` | Attribute the run to an end-user id (stored on the chat session for analytics/audit). Defaults to a generated `webhook_<id>`. Set it on the first call of a conversation; a resumed session keeps its original visitor. |
88
+
89
+ Returns `{ response: string; sessionId: string }`.
90
+
91
+ ```ts
92
+ // Attribute the run to a specific end-user:
93
+ const { response } = await client.triggerAgent(
94
+ "your-agent-id",
95
+ "How do I reset my password?",
96
+ { visitor: "user_12345" }
97
+ );
48
98
  ```
49
99
 
50
- ---
100
+ ### Stateful (with memory)
51
101
 
52
- ### 3. Fetch a prompt without variables
102
+ Pass the returned `sessionId` back on each follow-up to keep context:
53
103
 
54
104
  ```ts
55
- const staticPrompt = await client.getPrompt("system-intro");
56
- console.log(staticPrompt);
57
- // "You are a helpful AI assistant..."
105
+ let { response, sessionId } = await client.triggerAgent("your-agent-id", "Summarize Q4 sales");
106
+ console.log(response);
107
+
108
+ ({ response } = await client.triggerAgent("your-agent-id", "Compare that with Q3", { sessionId }));
109
+ console.log(response);
58
110
  ```
59
111
 
60
- > ⚠️ No variables? You can omit the second argument.
112
+ ### Stateless (no memory)
113
+
114
+ Omit `sessionId` for an independent, one-shot run each time:
61
115
 
62
- ---
116
+ ```ts
117
+ const { response } = await client.triggerAgent(
118
+ "your-agent-id",
119
+ "What is the refund policy?",
120
+ { variables: { company: "Acme Corp" } }
121
+ );
122
+ ```
123
+
124
+ ### With prompt variables
63
125
 
64
- ### 4. Use with LLM APIs (OpenAI, Claude, Gemini, etc.)
126
+ If your agent's instructions contain `{{...}}` placeholders, fill them via `variables`:
65
127
 
66
128
  ```ts
67
- import OpenAI from "openai";
129
+ const { response } = await client.triggerAgent(
130
+ "your-agent-id",
131
+ "How do I reset my password?",
132
+ { variables: { company: "Acme Corp", tone: "professional" } }
133
+ );
134
+ ```
68
135
 
69
- const openai = new OpenAI({ apiKey: "sk-..." });
136
+ ## Streaming an agent
70
137
 
71
- const promptText = await client.getPrompt("clarify-topic", {
72
- topic: "prompt engineering"
73
- });
138
+ When you want real-time output — agent reasoning, tool-execution status, and the final answer as they happen — use the streaming flow: `startAgent` to open a session, then `streamAgent` to receive [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events).
74
139
 
75
- const response = await openai.chat.completions.create({
76
- model: "gpt-4",
77
- messages: [{ role: "user", content: promptText }]
78
- });
140
+ ### Start a session
141
+
142
+ ```ts
143
+ const session = await client.startAgent("your-agent-id", { visitor: "John" });
144
+
145
+ console.log(session.sessionToken); // use this for all subsequent stream calls
146
+ console.log(session.agentId); // the agent id, echoed back
147
+ console.log(session.name); // agent display name
148
+ console.log(session.memoryEnabled); // whether the agent retains conversation context
149
+ ```
150
+
151
+ ### Stream a response
152
+
153
+ Each event has a `type` and `output`:
154
+
155
+ | Event Type | Description |
156
+ |---|---|
157
+ | `thoughts` | Agent's internal reasoning |
158
+ | `processing` | Tool execution status (e.g., "Searching Jira...") |
159
+ | `approval_required` | Agent needs permission to run a tool |
160
+ | `done` | Final response text |
161
+ | `error` | Something went wrong |
162
+
163
+ ```ts
164
+ for await (const event of client.streamAgent(session.agentId, {
165
+ sessionToken: session.sessionToken,
166
+ query: "What are the open P1 bugs in our backlog?",
167
+ })) {
168
+ if (event.type === "thoughts") console.log(`Thinking: ${event.output}`);
169
+ else if (event.type === "processing") console.log(`Running: ${event.output}`);
170
+ else if (event.type === "done") console.log(`\n${event.output}`);
171
+ else if (event.type === "error") console.log(`Error: ${event.output}`);
172
+ }
173
+ ```
174
+
175
+ ### Multi-turn conversation
176
+
177
+ The session token maintains conversation context across messages:
79
178
 
80
- console.log(response.choices[0].message.content);
179
+ ```ts
180
+ const session = await client.startAgent("your-agent-id", { visitor: "Sarah" });
181
+
182
+ // First message
183
+ for await (const event of client.streamAgent(session.agentId, {
184
+ sessionToken: session.sessionToken,
185
+ query: "Summarize our Q4 sales report",
186
+ })) {
187
+ if (event.type === "done") console.log(event.output);
188
+ }
189
+
190
+ // Follow-up — agent remembers the previous context
191
+ for await (const event of client.streamAgent(session.agentId, {
192
+ sessionToken: session.sessionToken,
193
+ query: "Compare that with Q3",
194
+ })) {
195
+ if (event.type === "done") console.log(event.output);
196
+ }
81
197
  ```
82
198
 
83
- ---
199
+ ### Collect the final response only
84
200
 
85
- ## Features
201
+ ```ts
202
+ async function askAgent(client, session, query) {
203
+ for await (const event of client.streamAgent(session.agentId, {
204
+ sessionToken: session.sessionToken,
205
+ query,
206
+ })) {
207
+ if (event.type === "done") return event.output;
208
+ if (event.type === "error") throw new Error(event.output);
209
+ }
210
+ }
211
+
212
+ const answer = await askAgent(client, session, "What's our monthly churn rate?");
213
+ ```
86
214
 
87
- - ✅ Works with or without prompt variables
88
- - 🔐 Safe for frontend & server use
89
- - 🔌 Works with any LLM provider
215
+ > **When to use which:**
216
+ > - `triggerAgent()` — the default. One call, blocking, returns the final answer. Best for APIs, jobs, and server-to-server use.
217
+ > - `startAgent()` + `streamAgent()` — when you want to render reasoning and tool progress live (e.g., a chat UI).
90
218
 
91
- ---
219
+ ## Error Handling
92
220
 
93
- ## Options
221
+ The SDK raises typed errors for each failure scenario:
94
222
 
95
223
  ```ts
96
- new PromptevClient({
97
- projectKey: "pv_sk_abc...",
98
- baseUrl: "https://api.promptev.ai", // optional
99
- headers: { "X-PTV-API-Key": "..." } // optional: extra headers
224
+ import {
225
+ PromptevClient,
226
+ ValidationError,
227
+ AuthenticationError,
228
+ NotFoundError,
229
+ RateLimitError,
230
+ ServerError,
231
+ NetworkError,
232
+ } from "@promptev/client";
233
+
234
+ const client = new PromptevClient({ projectKey: "pv_sk_..." });
235
+
236
+ try {
237
+ const { response } = await client.triggerAgent("your-agent-id", "Hello");
238
+ console.log(response);
239
+ } catch (err) {
240
+ if (err instanceof ValidationError) {
241
+ // 400 — missing variables, bad input
242
+ console.log(`Invalid request: ${err.message}`);
243
+ } else if (err instanceof NotFoundError) {
244
+ // 404 — agent or project not found
245
+ console.log(`Not found: ${err.message}`);
246
+ } else if (err instanceof AuthenticationError) {
247
+ // 401/403 — invalid API key or agent not active
248
+ console.log(`Auth error: ${err.message}`);
249
+ } else if (err instanceof RateLimitError) {
250
+ // 429 — API usage quota exceeded
251
+ console.log(`Rate limited: ${err.message}`);
252
+ } else if (err instanceof ServerError) {
253
+ // 5xx — server error (after retries exhausted)
254
+ console.log(`Server error: ${err.message}`);
255
+ } else if (err instanceof NetworkError) {
256
+ // Connection failed, timeout, DNS error
257
+ console.log(`Network error: ${err.message}`);
258
+ }
259
+ }
260
+ ```
261
+
262
+ All errors extend `PromptevError` and include:
263
+ - `err.statusCode` — HTTP status code (if applicable)
264
+ - `err.responseText` — Raw response body (for debugging)
265
+
266
+ | Error | HTTP Status | When |
267
+ |---|---|---|
268
+ | `ValidationError` | 400 | Missing required variables, bad input |
269
+ | `AuthenticationError` | 401, 403 | Invalid API key, agent not active |
270
+ | `NotFoundError` | 404 | Project or agent not found |
271
+ | `RateLimitError` | 429 | API usage quota exceeded |
272
+ | `ServerError` | 5xx | Server error (after retries exhausted) |
273
+ | `NetworkError` | — | Connection failed, timeout, DNS error |
274
+ | `PromptevError` | any | Base class for all above errors |
275
+
276
+ ## Configuration
277
+
278
+ ```ts
279
+ const client = new PromptevClient({
280
+ projectKey: "pv_sk_...", // Required — your project API key
281
+ baseUrl: "https://api.promptev.ai", // Default — override for self-hosted
282
+ timeout: 30000, // Default — request timeout in ms
283
+ maxRetries: 2, // Default — retries for 502/503/504
284
+ headers: { "X-Custom": "value" }, // Optional — extra HTTP headers
285
+ });
286
+ ```
287
+
288
+ | Parameter | Default | Description |
289
+ |---|---|---|
290
+ | `projectKey` | *required* | Your Promptev project API key (`pv_sk_...`) |
291
+ | `baseUrl` | `https://api.promptev.ai` | API base URL |
292
+ | `timeout` | `30000` | Request timeout in milliseconds |
293
+ | `maxRetries` | `2` | Automatic retries for transient server errors (502, 503, 504) |
294
+ | `headers` | `{}` | Additional HTTP headers |
295
+
296
+ ## API Reference
297
+
298
+ ### `PromptevClient`
299
+
300
+ | Method | Description | Returns |
301
+ |---|---|---|
302
+ | `triggerAgent(agentId, message, opts?)` | Run an agent in one blocking call | `Promise<TriggerResult>` |
303
+ | `startAgent(agentId, options?)` | Start a streaming agent session | `Promise<AgentSession>` |
304
+ | `streamAgent(agentId, options)` | Stream an agent response (SSE) | `AsyncGenerator<AgentEvent>` |
305
+
306
+ ### `TriggerResult`
307
+
308
+ | Field | Type | Description |
309
+ |---|---|---|
310
+ | `response` | `string` | The agent's final answer |
311
+ | `sessionId` | `string` | Pass back as `opts.sessionId` to continue the conversation |
312
+
313
+ ### `AgentSession`
314
+
315
+ | Field | Type | Description |
316
+ |---|---|---|
317
+ | `sessionToken` | `string` | Token for subsequent stream calls |
318
+ | `agentId` | `string` | Agent identifier |
319
+ | `name` | `string` | Agent display name |
320
+ | `memoryEnabled` | `boolean` | Whether the agent retains conversation context |
321
+ | `messages` | `array` | Previous messages (populated when resuming a session) |
322
+
323
+ ### `AgentEvent`
324
+
325
+ | Field | Type | Description |
326
+ |---|---|---|
327
+ | `type` | `string` | Event type: `thoughts`, `processing`, `done`, `error`, `approval_required` |
328
+ | `output` | `string` | Event content text |
329
+ | `raw` | `object` | Full parsed SSE event data |
330
+
331
+ ## Framework Examples
332
+
333
+ ### React
334
+
335
+ ```tsx
336
+ import { useState } from "react";
337
+ import { PromptevClient } from "@promptev/client";
338
+
339
+ const client = new PromptevClient({ projectKey: "pv_sk_..." });
340
+
341
+ export function AskAgent() {
342
+ const [answer, setAnswer] = useState("");
343
+ const [loading, setLoading] = useState(false);
344
+
345
+ async function handleAsk() {
346
+ setLoading(true);
347
+ try {
348
+ const { response } = await client.triggerAgent("your-agent-id", "What is your refund policy?");
349
+ setAnswer(response);
350
+ } finally {
351
+ setLoading(false);
352
+ }
353
+ }
354
+
355
+ return (
356
+ <div>
357
+ <button onClick={handleAsk} disabled={loading}>Ask Agent</button>
358
+ {answer && <p>{answer}</p>}
359
+ </div>
360
+ );
361
+ }
362
+ ```
363
+
364
+ ### React — Streaming Agent Chat
365
+
366
+ ```tsx
367
+ import { useState, useRef } from "react";
368
+ import { PromptevClient } from "@promptev/client";
369
+
370
+ const client = new PromptevClient({ projectKey: "pv_sk_..." });
371
+
372
+ export function AgentChat() {
373
+ const [messages, setMessages] = useState<string[]>([]);
374
+ const [input, setInput] = useState("");
375
+ const sessionRef = useRef(null);
376
+
377
+ async function startChat() {
378
+ sessionRef.current = await client.startAgent("your-agent-id", { visitor: "user" });
379
+ }
380
+
381
+ async function sendMessage() {
382
+ if (!sessionRef.current) await startChat();
383
+
384
+ setMessages((prev) => [...prev, `You: ${input}`]);
385
+ const query = input;
386
+ setInput("");
387
+
388
+ for await (const event of client.streamAgent(sessionRef.current.agentId, {
389
+ sessionToken: sessionRef.current.sessionToken,
390
+ query,
391
+ })) {
392
+ if (event.type === "done") {
393
+ setMessages((prev) => [...prev, `Agent: ${event.output}`]);
394
+ }
395
+ }
396
+ }
397
+
398
+ return (
399
+ <div>
400
+ {messages.map((msg, i) => <p key={i}>{msg}</p>)}
401
+ <input value={input} onChange={(e) => setInput(e.target.value)} />
402
+ <button onClick={sendMessage}>Send</button>
403
+ </div>
404
+ );
405
+ }
406
+ ```
407
+
408
+ ### Node.js / Express API
409
+
410
+ ```js
411
+ import express from "express";
412
+ import { PromptevClient } from "@promptev/client";
413
+
414
+ const app = express();
415
+ const client = new PromptevClient({ projectKey: "pv_sk_..." });
416
+
417
+ app.post("/api/ask", express.json(), async (req, res) => {
418
+ const { response, sessionId } = await client.triggerAgent(
419
+ "your-agent-id",
420
+ req.body.question,
421
+ { sessionId: req.body.sessionId } // pass back to keep memory across turns
422
+ );
423
+ res.json({ answer: response, sessionId });
100
424
  });
425
+
426
+ app.listen(3000);
427
+ ```
428
+
429
+ ### Vanilla HTML
430
+
431
+ ```html
432
+ <script type="module">
433
+ import { PromptevClient } from "https://cdn.jsdelivr.net/npm/@promptev/client/dist/esm/index.js";
434
+
435
+ const client = new PromptevClient({ projectKey: "pv_sk_..." });
436
+
437
+ document.getElementById("ask-btn").addEventListener("click", async () => {
438
+ const { response } = await client.triggerAgent("your-agent-id", "What is the refund policy?");
439
+ document.getElementById("output").textContent = response;
440
+ });
441
+ </script>
101
442
  ```
102
443
 
103
- ---
444
+ ## Building from source
445
+
446
+ ```bash
447
+ npm install
448
+ npm run build # builds both ESM (dist/esm) and CommonJS (dist/cjs)
449
+ ```
104
450
 
105
451
  ## License
106
452
 
107
- This SDK is **commercial software** by Promptev Inc.
453
+ This SDK is commercial software by [Promptev Inc](https://promptev.ai).
108
454
 
109
- By using this package, you agree to the terms in [`LICENSE.txt`](./LICENSE.txt).
455
+ - Free tier use allowed
456
+ - Production use requires an active subscription
110
457
 
111
- ---
458
+ See [LICENSE](./LICENSE.txt) for full terms.
112
459
 
113
- ## Contact
460
+ ## Support
114
461
 
115
- - 🌐 https://promptev.ai
116
- - 📧 support@promptev.ai
462
+ - Website: [promptev.ai](https://promptev.ai)
463
+ - Email: support@promptev.ai
@@ -1,30 +0,0 @@
1
- export interface PromptliyClientConfig {
2
- baseUrl?: string;
3
- projectKey: string;
4
- }
5
- export interface Prompt {
6
- prompt: string;
7
- variables: string[] | string | null;
8
- format(values?: Record<string, string>): string;
9
- }
10
- export declare class PromptliyClient {
11
- private client;
12
- private baseUrl;
13
- private projectKey;
14
- private promptCache;
15
- private refreshInterval;
16
- private cacheRefreshIntervalMs;
17
- private isReady;
18
- constructor(config: PromptliyClientConfig);
19
- private ensureReady;
20
- private startCacheRefresh;
21
- private refreshCachedPrompt;
22
- private createPromptObject;
23
- getPrompt(promptKey: string): Promise<Prompt> & {
24
- format: (values: Record<string, string>) => Promise<string>;
25
- };
26
- private fetchPrompt;
27
- private fetchPromptFromServer;
28
- dispose(): Promise<void>;
29
- }
30
- export default PromptliyClient;