@promptev/client 0.2.0 → 1.0.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.
- package/dist/cjs/index.cjs +429 -145
- package/dist/esm/index.d.ts +460 -53
- package/dist/esm/index.js +427 -144
- package/package.json +4 -3
- package/readme.md +392 -288
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,104 +1,511 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @promptev/client — the official JavaScript/TypeScript client for Promptev.
|
|
3
|
+
*
|
|
4
|
+
* 1.0 talks to Promptev's `/api/v1` surface, authenticated with a workspace
|
|
5
|
+
* API key (`fk_…`) sent as a Bearer token. The key is bound to ONE project and
|
|
6
|
+
* carries its own retrieval identity, so what a caller may read is part of the
|
|
7
|
+
* credential rather than a parameter on the call.
|
|
8
|
+
*
|
|
9
|
+
* Two methods:
|
|
10
|
+
* - `chat()` — stream a turn from an agent (SSE).
|
|
11
|
+
* - `uploadDocument()` — put files into the key's project corpus.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* The default host. NOT `api.promptev.ai` — that host still serves the
|
|
15
|
+
* previous product and would answer 404 for every `/api/v1` path here.
|
|
16
|
+
* FLIP THIS the day `api.promptev.ai` is repointed at the console backend.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Where the client talks by default.
|
|
20
|
+
*
|
|
21
|
+
* `api.promptev.ai` is the API's permanent home. At the time 1.0 was written
|
|
22
|
+
* that host still served the PREVIOUS product, and it is being repointed at
|
|
23
|
+
* the new backend — so this default is correct for where things are going and
|
|
24
|
+
* must not ship to npm before the DNS moves. Point `baseUrl` at
|
|
25
|
+
* `https://console.promptev.ai` in the meantime, or at your own host if you
|
|
26
|
+
* run Promptev yourself.
|
|
27
|
+
*/
|
|
28
|
+
export declare const DEFAULT_BASE_URL = "https://api.promptev.ai";
|
|
29
|
+
/** The server's own ceiling on one message (`ApiChatBody.message`). */
|
|
30
|
+
export declare const MAX_MESSAGE_CHARS = 20000;
|
|
31
|
+
/** `uploads.MAX_FILES_PER_REQUEST` — files in ONE upload request. */
|
|
32
|
+
export declare const MAX_FILES_PER_REQUEST = 20;
|
|
33
|
+
/** `file_types.MAX_UPLOAD_BYTES` — 25 MB per file. */
|
|
34
|
+
export declare const MAX_UPLOAD_BYTES: number;
|
|
35
|
+
/** Files ONE orchestration run may carry — the same ceiling a chat turn has.
|
|
36
|
+
* Server-side: `run_inputs.MAX_FILE_PARTS`. */
|
|
37
|
+
export declare const MAX_FILES_PER_RUN = 5;
|
|
1
38
|
export interface PromptevClientConfig {
|
|
2
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Your Promptev API key — `fk_…`, minted in Settings → API keys of the
|
|
41
|
+
* project it may reach. It is sent as `Authorization: Bearer <key>`, never
|
|
42
|
+
* in a URL, and it carries the retrieval identity the agent answers under.
|
|
43
|
+
*/
|
|
44
|
+
apiKey: string;
|
|
45
|
+
/** Override for self-hosted / staging. Defaults to {@link DEFAULT_BASE_URL}. */
|
|
3
46
|
baseUrl?: string;
|
|
47
|
+
/** Extra HTTP headers on every request. */
|
|
4
48
|
headers?: Record<string, string>;
|
|
49
|
+
/**
|
|
50
|
+
* Milliseconds to wait for the response HEADERS. A `chat()` stream is not
|
|
51
|
+
* bounded by it — once the response arrives the timer is cleared, because a
|
|
52
|
+
* turn that runs tools (or waits for an approval) legitimately outlives any
|
|
53
|
+
* request timeout.
|
|
54
|
+
*/
|
|
5
55
|
timeout?: number;
|
|
56
|
+
/** Retries for transient server errors (502/503/504) on non-streaming calls. */
|
|
6
57
|
maxRetries?: number;
|
|
7
58
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Assert, on this one call, WHICH end user your backend is acting for.
|
|
61
|
+
*
|
|
62
|
+
* The key's grant is a ceiling and this only ever narrows within it: the
|
|
63
|
+
* groups you assert are intersected with the key's `grp:` grants, and the
|
|
64
|
+
* key's `user:` grants drop entirely the moment an assertion is present. A
|
|
65
|
+
* compromised caller therefore cannot read beyond what the key was granted.
|
|
66
|
+
* `subject` is recorded as the conversation's actor for the audit trail; it is
|
|
67
|
+
* not verified by the server, so it never widens anything.
|
|
68
|
+
*/
|
|
69
|
+
export interface OnBehalfOf {
|
|
70
|
+
/** Who you are acting for — an email or a stable user id (1–320 chars). */
|
|
71
|
+
subject: string;
|
|
72
|
+
/** The end user's groups, as your system knows them. Omit for the key's full grant. */
|
|
73
|
+
groups?: string[];
|
|
74
|
+
}
|
|
75
|
+
export interface ChatOptions {
|
|
76
|
+
/**
|
|
77
|
+
* Continue an existing thread. Read it off the first `conversation` event
|
|
78
|
+
* and pass it back on the next turn. Omit to start a new conversation.
|
|
79
|
+
*
|
|
80
|
+
* Worth passing: with a tool's "Ask once" approval mode the agent asks on
|
|
81
|
+
* the FIRST call in a conversation and not again for the rest of it, so a
|
|
82
|
+
* continued thread sees far fewer `approval_required` events.
|
|
83
|
+
*
|
|
84
|
+
* A thread belongs to the agent, to this API surface, AND to the
|
|
85
|
+
* `onBehalfOf.subject` it was opened under — so keep the subject the same
|
|
86
|
+
* across the turns of one conversation, and never pass an id from the app,
|
|
87
|
+
* the portal or an embed. Any mismatch answers 404, not a new thread.
|
|
88
|
+
*/
|
|
89
|
+
conversationId?: string;
|
|
90
|
+
/** Act for one of your end users — see {@link OnBehalfOf}. */
|
|
91
|
+
onBehalfOf?: OnBehalfOf;
|
|
92
|
+
/** Abort the turn from your own signal (in addition to the client timeout). */
|
|
93
|
+
signal?: AbortSignal;
|
|
94
|
+
}
|
|
95
|
+
export interface UploadOptions {
|
|
96
|
+
/**
|
|
97
|
+
* How the document is indexed. `"hybrid"` (the default) or `"graph"`.
|
|
98
|
+
* `"graph"` needs a graph database and an extraction model configured for
|
|
99
|
+
* the workspace, or the server answers 422.
|
|
100
|
+
*/
|
|
101
|
+
mode?: "hybrid" | "graph";
|
|
102
|
+
/** Abort the upload from your own signal. */
|
|
103
|
+
signal?: AbortSignal;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* A file to upload. Either a web `File`/`Blob`, or a plain object naming its
|
|
107
|
+
* bytes — which is what you want in Node, where `File` is awkward:
|
|
108
|
+
*
|
|
109
|
+
* ```ts
|
|
110
|
+
* await client.uploadDocument({ name: "handbook.pdf", content: await readFile(path) });
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export type UploadInput = Blob | {
|
|
114
|
+
/** The filename the corpus stores it under — the extension picks the parser. */
|
|
115
|
+
name: string;
|
|
116
|
+
content: Blob | ArrayBuffer | ArrayBufferView | string;
|
|
117
|
+
/** Optional MIME type; the server decides from the name either way. */
|
|
118
|
+
type?: string;
|
|
119
|
+
};
|
|
120
|
+
/** One file's outcome — a batch reports every file, failures included. */
|
|
121
|
+
export interface UploadResult {
|
|
122
|
+
filename: string;
|
|
123
|
+
/** What the engine made of it — `"indexed"`, `"failed"`, … */
|
|
124
|
+
status: string;
|
|
125
|
+
/** The corpus id, or `null` when the file did not land. */
|
|
126
|
+
document_id: string | null;
|
|
127
|
+
chunks: number;
|
|
128
|
+
units: number;
|
|
129
|
+
/** Why this file failed, or `null`. */
|
|
130
|
+
error: string | null;
|
|
131
|
+
}
|
|
132
|
+
export interface UploadResponse {
|
|
133
|
+
results: UploadResult[];
|
|
134
|
+
}
|
|
135
|
+
/** First frame of every stream: the id that continues this thread. */
|
|
136
|
+
export interface ConversationEvent {
|
|
137
|
+
type: "conversation";
|
|
138
|
+
/** Pass as `conversationId` on the next `chat()` call. */
|
|
139
|
+
id: string;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* One delta of the model's REASONING — not the answer. Never concatenate it
|
|
143
|
+
* into the reply; render it separately, or ignore it.
|
|
144
|
+
*
|
|
145
|
+
* Emitted only by models that actually stream thinking (Anthropic with a
|
|
146
|
+
* thinking budget, Gemini, the OpenAI Responses API) — many turns carry none.
|
|
147
|
+
*/
|
|
148
|
+
export interface ThinkingEvent {
|
|
149
|
+
type: "thinking";
|
|
150
|
+
content: string;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* ONE delta of the answer. Concatenating every `token.content` in order gives
|
|
154
|
+
* the agent's complete reply.
|
|
155
|
+
*/
|
|
156
|
+
export interface TokenEvent {
|
|
157
|
+
type: "token";
|
|
158
|
+
content: string;
|
|
159
|
+
}
|
|
160
|
+
/** A stage of the turn — reading attachments, retrieving, waiting on an emailed approval. */
|
|
161
|
+
export interface StepEvent {
|
|
162
|
+
type: "step";
|
|
11
163
|
name: string;
|
|
12
|
-
|
|
13
|
-
|
|
164
|
+
status: "started" | "completed" | "failed";
|
|
165
|
+
detail?: string;
|
|
166
|
+
/** Set on the "waiting for approval — <tool>" step an EMAIL approval opens. */
|
|
167
|
+
tool_name?: string;
|
|
168
|
+
channel?: string;
|
|
169
|
+
}
|
|
170
|
+
/** Where the answer is grounded — one entry per retrieved document. */
|
|
171
|
+
export interface SourcesEvent {
|
|
172
|
+
type: "sources";
|
|
173
|
+
items: {
|
|
174
|
+
name: string;
|
|
175
|
+
document_id: string;
|
|
176
|
+
}[];
|
|
177
|
+
}
|
|
178
|
+
/** The agent decided to run a tool. `id` correlates with its `tool_result`. */
|
|
179
|
+
export interface ToolCallEvent {
|
|
180
|
+
type: "tool_call";
|
|
181
|
+
id: string;
|
|
182
|
+
name: string;
|
|
183
|
+
args?: Record<string, unknown>;
|
|
184
|
+
}
|
|
185
|
+
/** That tool answered. `ok: false` is a failure the agent will go on to explain. */
|
|
186
|
+
export interface ToolResultEvent {
|
|
187
|
+
type: "tool_result";
|
|
188
|
+
id: string;
|
|
189
|
+
name: string;
|
|
190
|
+
ok: boolean;
|
|
191
|
+
/** A one-line summary of the result — never the full payload. */
|
|
192
|
+
summary?: string;
|
|
193
|
+
/** How an approval ended, when the tool was gated: rejected / timeout / expired. */
|
|
194
|
+
approval?: string;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* THE TURN IS PAUSED, WAITING FOR A HUMAN.
|
|
198
|
+
*
|
|
199
|
+
* A tool the agent wants to run is gated on approval. The stream stays OPEN: a
|
|
200
|
+
* person approves it in the Promptev app, by email, or in Slack, and the turn
|
|
201
|
+
* then continues on this same connection — you never re-send the message. If
|
|
202
|
+
* nobody decides in time the approval expires and the turn reports it as a
|
|
203
|
+
* failed `tool_result` (`approval: "expired"`).
|
|
204
|
+
*
|
|
205
|
+
* Handle this event. An integration that ignores it looks hung to its user for
|
|
206
|
+
* as long as the approval window lasts, which is the single most common
|
|
207
|
+
* support ticket this API generates. At minimum, tell your user what is being
|
|
208
|
+
* asked and who has to decide it.
|
|
209
|
+
*
|
|
210
|
+
* NOT every gated tool sends this event. `channel` is only ever `"inline"` or
|
|
211
|
+
* `"slack"` — somewhere a human is already looking. A tool whose approval is
|
|
212
|
+
* routed to an APPROVER BY EMAIL sends no card at all: it streams a
|
|
213
|
+
* {@link StepEvent} named `waiting for approval — <tool>` instead, which
|
|
214
|
+
* closes when the decision lands. Code that waits only for
|
|
215
|
+
* `approval_required` would wait forever on those.
|
|
216
|
+
*
|
|
217
|
+
* Passing `conversationId` on follow-up turns materially reduces how often you
|
|
218
|
+
* see it: a tool set to "Ask once" asks on the first call in a conversation and
|
|
219
|
+
* not again for the rest of it.
|
|
220
|
+
*/
|
|
221
|
+
export interface ApprovalRequiredEvent {
|
|
222
|
+
type: "approval_required";
|
|
223
|
+
/** The pending approval's id — the same one the approver decides in Promptev. */
|
|
224
|
+
approval_id: string;
|
|
225
|
+
/** The tool waiting to run. */
|
|
226
|
+
tool_name: string;
|
|
227
|
+
/** The arguments it would run with — show these to whoever has to decide. */
|
|
228
|
+
args?: Record<string, unknown>;
|
|
229
|
+
/** Why approval is being asked for, in the operator's own words. */
|
|
230
|
+
reason?: string;
|
|
231
|
+
/**
|
|
232
|
+
* Where a human can decide it — `"inline"` (in the Promptev app) or
|
|
233
|
+
* `"slack"`. Never `"email"`: see this event's note above.
|
|
234
|
+
*/
|
|
235
|
+
channel?: "inline" | "slack";
|
|
236
|
+
/** ISO-8601 deadline, after which the approval expires and the tool fails. */
|
|
237
|
+
expires_at?: string;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* A file the agent produced this turn (`generate_file`). This surface carries
|
|
241
|
+
* no download link — open the conversation in Promptev to fetch the file, or
|
|
242
|
+
* have the agent put what you need in its answer.
|
|
243
|
+
*/
|
|
244
|
+
export interface ArtifactEvent {
|
|
245
|
+
type: "artifact";
|
|
246
|
+
id: string;
|
|
247
|
+
kind: string;
|
|
248
|
+
name: string;
|
|
249
|
+
mime: string;
|
|
250
|
+
size: number;
|
|
251
|
+
exports?: unknown[];
|
|
252
|
+
/** Only on surfaces that mint signed links; absent on `/api/v1`. */
|
|
253
|
+
url?: string;
|
|
254
|
+
}
|
|
255
|
+
/** 2–3 follow-ups the same person would plausibly ask next. Only when the agent has suggestions on. */
|
|
256
|
+
export interface SuggestionsEvent {
|
|
257
|
+
type: "suggestions";
|
|
258
|
+
questions: string[];
|
|
14
259
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
260
|
+
/** What the turn cost, emitted just before `done`. */
|
|
261
|
+
export interface UsageEvent {
|
|
262
|
+
type: "usage";
|
|
263
|
+
/** Credit units: one for the turn plus one per executed tool call. */
|
|
264
|
+
units: number;
|
|
265
|
+
/** Provider token counts, when the provider reported them. */
|
|
266
|
+
tokens?: Record<string, unknown>;
|
|
267
|
+
tool_calls?: number;
|
|
18
268
|
}
|
|
19
|
-
|
|
269
|
+
/** The stream finished cleanly. Nothing follows it. */
|
|
270
|
+
export interface DoneEvent {
|
|
271
|
+
type: "done";
|
|
272
|
+
}
|
|
273
|
+
/** The turn failed mid-stream. Nothing follows it. */
|
|
274
|
+
export interface ErrorEvent {
|
|
275
|
+
type: "error";
|
|
276
|
+
message: string;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* A frame from a NEWER server than this client knows about.
|
|
280
|
+
*
|
|
281
|
+
* Unknown types are yielded, never thrown on: a server that adds an event must
|
|
282
|
+
* not break an integration that had nothing to do with the deploy. Such a
|
|
283
|
+
* frame arrives typed as {@link AgentEvent} — its `type` simply matches none of
|
|
284
|
+
* the cases you handle. Cast it if you want its fields:
|
|
285
|
+
*
|
|
286
|
+
* ```ts
|
|
287
|
+
* default: console.log("new event:", (ev as UnknownEvent).type);
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
290
|
+
export interface UnknownEvent {
|
|
20
291
|
type: string;
|
|
21
|
-
|
|
22
|
-
raw: Record<string, any>;
|
|
292
|
+
[key: string]: unknown;
|
|
23
293
|
}
|
|
294
|
+
/**
|
|
295
|
+
* Every frame `chat()` can yield. Narrow on `type`.
|
|
296
|
+
*
|
|
297
|
+
* The union names what today's server emits, so narrowing gives you real field
|
|
298
|
+
* types. A frame from a newer server still reaches you at runtime — see
|
|
299
|
+
* {@link UnknownEvent}.
|
|
300
|
+
*/
|
|
301
|
+
export type AgentEvent = ConversationEvent | ThinkingEvent | TokenEvent | StepEvent | SourcesEvent | ToolCallEvent | ToolResultEvent | ApprovalRequiredEvent | ArtifactEvent | SuggestionsEvent | UsageEvent | DoneEvent | ErrorEvent;
|
|
302
|
+
/** The named event types — the vocabulary, for switch tables and filters. */
|
|
303
|
+
export type AgentEventType = "conversation" | "thinking" | "token" | "step" | "sources" | "tool_call" | "tool_result" | "approval_required" | "artifact" | "suggestions" | "usage" | "done" | "error";
|
|
24
304
|
export declare class PromptevError extends Error {
|
|
25
305
|
statusCode?: number;
|
|
26
306
|
responseText?: string;
|
|
27
|
-
|
|
307
|
+
/** Which request field the server objected to, when it named one. */
|
|
308
|
+
field?: string;
|
|
309
|
+
constructor(message: string, statusCode?: number, responseText?: string, field?: string);
|
|
28
310
|
}
|
|
311
|
+
/** 400/422 — the request itself was wrong. `field` says which part. */
|
|
29
312
|
export declare class ValidationError extends PromptevError {
|
|
30
|
-
|
|
313
|
+
name: string;
|
|
31
314
|
}
|
|
315
|
+
/** 401/403 — the key is missing, malformed, revoked or expired. */
|
|
32
316
|
export declare class AuthenticationError extends PromptevError {
|
|
33
|
-
|
|
317
|
+
name: string;
|
|
34
318
|
}
|
|
319
|
+
/**
|
|
320
|
+
* 404 — no such agent, OR an agent your key cannot reach, OR one that has
|
|
321
|
+
* never been published. All three answer identically on purpose: a key holder
|
|
322
|
+
* learns nothing about projects it was not given.
|
|
323
|
+
*/
|
|
35
324
|
export declare class NotFoundError extends PromptevError {
|
|
36
|
-
|
|
325
|
+
name: string;
|
|
37
326
|
}
|
|
327
|
+
/** 429 — too many requests. `retryAfter` is the server's own answer, in seconds. */
|
|
38
328
|
export declare class RateLimitError extends PromptevError {
|
|
39
|
-
|
|
329
|
+
name: string;
|
|
330
|
+
/** Seconds to wait, from the `Retry-After` header, when the server sent one. */
|
|
331
|
+
retryAfter?: number;
|
|
332
|
+
constructor(message: string, statusCode?: number, responseText?: string, field?: string, retryAfter?: number);
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* 402 — the workspace is out of credits. Not a rate limit: waiting does not
|
|
336
|
+
* fix it, a top-up does.
|
|
337
|
+
*/
|
|
338
|
+
export declare class InsufficientCreditsError extends PromptevError {
|
|
339
|
+
name: string;
|
|
40
340
|
}
|
|
341
|
+
/** 5xx — the server failed, after the client's retries were exhausted. */
|
|
41
342
|
export declare class ServerError extends PromptevError {
|
|
42
|
-
|
|
343
|
+
name: string;
|
|
43
344
|
}
|
|
345
|
+
/** The request never got an answer: DNS, connection, abort, or the client timeout. */
|
|
44
346
|
export declare class NetworkError extends PromptevError {
|
|
45
|
-
|
|
347
|
+
name: string;
|
|
348
|
+
}
|
|
349
|
+
/** What an orchestration takes: its own declared input keys. Values are plain
|
|
350
|
+
* scalars or flat lists of them — the shape the server bounds (50 keys, 64-char
|
|
351
|
+
* names, lists of 100, 64 KB). Files do NOT go in here; they are their own
|
|
352
|
+
* parts, keyed by the input they fill. */
|
|
353
|
+
export type RunInputs = Record<string, unknown>;
|
|
354
|
+
export interface RunOptions {
|
|
355
|
+
/** Files for inputs declared `File(s)`, keyed by the input's key — the part
|
|
356
|
+
* is NAMED after the input it fills, which is what lets one call fill two
|
|
357
|
+
* different file inputs. */
|
|
358
|
+
files?: Record<string, UploadInput | UploadInput[]>;
|
|
359
|
+
/** Send one and a retry returns the run you already started instead of
|
|
360
|
+
* running the team twice. */
|
|
361
|
+
idempotencyKey?: string;
|
|
362
|
+
signal?: AbortSignal;
|
|
363
|
+
}
|
|
364
|
+
export interface StartedRun {
|
|
365
|
+
/** Pass this to {@link PromptevClient.getRun}. */
|
|
366
|
+
run_id: string;
|
|
367
|
+
status: "accepted";
|
|
368
|
+
}
|
|
369
|
+
export interface RunStatus {
|
|
370
|
+
run_id: string;
|
|
371
|
+
/** The orchestration's slug. */
|
|
372
|
+
orchestration: string;
|
|
373
|
+
/** `running` · `awaiting_review` · `revising` · `delivered` · `failed`. */
|
|
374
|
+
status: string;
|
|
375
|
+
created_at: string | null;
|
|
376
|
+
/** Present only once there IS one — a half-written answer read mid-run is
|
|
377
|
+
* worse than none, because a caller would act on a draft. */
|
|
378
|
+
output?: string;
|
|
379
|
+
error?: string;
|
|
46
380
|
}
|
|
47
381
|
export declare class PromptevClient {
|
|
48
|
-
private
|
|
382
|
+
private apiKey;
|
|
49
383
|
private baseUrl;
|
|
50
384
|
private headers;
|
|
51
385
|
private timeout;
|
|
52
386
|
private maxRetries;
|
|
53
387
|
constructor(config: PromptevClientConfig);
|
|
388
|
+
/**
|
|
389
|
+
* Every refusal on `/api/v1` is `{"error": {"message", "field"?}}`. The
|
|
390
|
+
* older `{"detail": …}` shape is still read as a fallback, so a proxy or an
|
|
391
|
+
* un-migrated route can never produce an empty message.
|
|
392
|
+
*/
|
|
54
393
|
private static raiseForStatus;
|
|
394
|
+
private authHeaders;
|
|
55
395
|
private fetchWithRetry;
|
|
396
|
+
/**
|
|
397
|
+
* One `fetch`, with the client timeout applied to the RESPONSE only.
|
|
398
|
+
*
|
|
399
|
+
* The timer is cleared the moment the response resolves, which is what lets
|
|
400
|
+
* a `chat()` stream run for minutes — a tool call, or a human deciding an
|
|
401
|
+
* approval, is not a stalled request.
|
|
402
|
+
*/
|
|
403
|
+
private fetchOnce;
|
|
56
404
|
private parseSSE;
|
|
57
405
|
/**
|
|
58
|
-
*
|
|
406
|
+
* Send a message to one of your project's agents and stream the answer.
|
|
407
|
+
*
|
|
408
|
+
* This is the whole conversational surface: it starts a thread or continues
|
|
409
|
+
* one, streams every event the turn produces, and ends with `done` (or
|
|
410
|
+
* `error`). There is no separate "start" call and no session token — the API
|
|
411
|
+
* key IS the credential, and `conversationId` is the thread.
|
|
412
|
+
*
|
|
413
|
+
* @param agentSlug The agent's slug, as shown on its page in Promptev. Only
|
|
414
|
+
* PUBLISHED agents in the key's own project can be reached; anything else
|
|
415
|
+
* answers 404 ({@link NotFoundError}).
|
|
416
|
+
* @param message What to say. Required, non-empty after trimming, at most
|
|
417
|
+
* {@link MAX_MESSAGE_CHARS} characters.
|
|
418
|
+
*
|
|
419
|
+
* @example Stream the answer
|
|
420
|
+
* ```ts
|
|
421
|
+
* let conversationId: string | undefined;
|
|
422
|
+
* for await (const ev of client.chat("support-agent", "What is the refund policy?")) {
|
|
423
|
+
* switch (ev.type) {
|
|
424
|
+
* case "conversation": conversationId = ev.id; break;
|
|
425
|
+
* case "token": process.stdout.write(ev.content); break;
|
|
426
|
+
* case "approval_required":
|
|
427
|
+
* console.log(`\n${ev.tool_name} needs approval — ${ev.reason ?? "policy"}`);
|
|
428
|
+
* break;
|
|
429
|
+
* case "error": throw new Error(ev.message);
|
|
430
|
+
* }
|
|
431
|
+
* }
|
|
432
|
+
* // Continue the thread — and see far fewer approval prompts:
|
|
433
|
+
* for await (const ev of client.chat("support-agent", "And for digital goods?", { conversationId })) {
|
|
434
|
+
* if (ev.type === "token") process.stdout.write(ev.content);
|
|
435
|
+
* }
|
|
436
|
+
* ```
|
|
437
|
+
*/
|
|
438
|
+
chat(agentSlug: string, message: string, options?: ChatOptions): AsyncGenerator<AgentEvent>;
|
|
439
|
+
/**
|
|
440
|
+
* Put one or more documents into the project's corpus — the same "Uploads"
|
|
441
|
+
* source the app writes to, so what you upload here is what the agents in
|
|
442
|
+
* that project retrieve.
|
|
443
|
+
*
|
|
444
|
+
* The key names the project, so nothing about the destination is in the
|
|
445
|
+
* request: a key cannot upload into a project it does not reach.
|
|
59
446
|
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
447
|
+
* Limits, checked here and again on the server: at most
|
|
448
|
+
* {@link MAX_FILES_PER_REQUEST} files per call, at most
|
|
449
|
+
* {@link MAX_UPLOAD_BYTES} (25 MB) per file — a larger set belongs in a
|
|
450
|
+
* connector source. Ingestion is content-addressed: re-uploading identical
|
|
451
|
+
* bytes updates the existing document instead of duplicating it.
|
|
62
452
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
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.
|
|
453
|
+
* Ingestion is slow, and the request does not return until every file is
|
|
454
|
+
* indexed — raise `timeout` well above its 30 s default for real documents.
|
|
70
455
|
*
|
|
71
456
|
* @example
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
457
|
+
* ```ts
|
|
458
|
+
* import { readFile } from "node:fs/promises";
|
|
459
|
+
*
|
|
460
|
+
* const { results } = await client.uploadDocument(
|
|
461
|
+
* { name: "handbook.pdf", content: await readFile("handbook.pdf") },
|
|
462
|
+
* { mode: "hybrid" }
|
|
76
463
|
* );
|
|
77
|
-
*
|
|
78
|
-
*
|
|
464
|
+
* for (const r of results) console.log(r.filename, r.status, r.error ?? "");
|
|
465
|
+
* ```
|
|
79
466
|
*/
|
|
80
|
-
|
|
81
|
-
sessionId?: string;
|
|
82
|
-
variables?: Record<string, any>;
|
|
83
|
-
visitor?: string;
|
|
84
|
-
}): Promise<TriggerResult>;
|
|
467
|
+
uploadDocument(files: UploadInput | UploadInput[], options?: UploadOptions): Promise<UploadResponse>;
|
|
85
468
|
/**
|
|
86
|
-
* Start a
|
|
469
|
+
* Start a run of a published orchestration. Answers as soon as the run is
|
|
470
|
+
* recorded — **not** when it finishes.
|
|
471
|
+
*
|
|
472
|
+
* An orchestration is a team of agents; it runs in a worker for as long as it
|
|
473
|
+
* takes, so this returns a `run_id` and {@link getRun} tells you what became
|
|
474
|
+
* of it. That is the difference from {@link chat}, which streams one agent's
|
|
475
|
+
* answer inline.
|
|
87
476
|
*
|
|
88
|
-
*
|
|
477
|
+
* ```ts
|
|
478
|
+
* const { run_id } = await client.runOrchestration("month-end-close", {
|
|
479
|
+
* period: "2026-03",
|
|
480
|
+
* entity: "Acme GmbH",
|
|
481
|
+
* });
|
|
482
|
+
* ```
|
|
483
|
+
*
|
|
484
|
+
* With files — the part is named after the input it fills:
|
|
485
|
+
*
|
|
486
|
+
* ```ts
|
|
487
|
+
* const { run_id } = await client.runOrchestration(
|
|
488
|
+
* "contract-review",
|
|
489
|
+
* { matter: "Acme renewal" },
|
|
490
|
+
* { files: { contract: { name: "lease.pdf", content: bytes } } },
|
|
491
|
+
* );
|
|
492
|
+
* ```
|
|
89
493
|
*/
|
|
90
|
-
|
|
91
|
-
visitor?: string;
|
|
92
|
-
platform?: string;
|
|
93
|
-
}): Promise<AgentSession>;
|
|
494
|
+
runOrchestration(slug: string, inputs?: RunInputs, options?: RunOptions): Promise<StartedRun>;
|
|
94
495
|
/**
|
|
95
|
-
*
|
|
496
|
+
* What became of a run — poll this after {@link runOrchestration}.
|
|
96
497
|
*
|
|
97
|
-
*
|
|
498
|
+
* ```ts
|
|
499
|
+
* let run = await client.getRun(run_id);
|
|
500
|
+
* while (run.status === "running" || run.status === "revising") {
|
|
501
|
+
* await new Promise((r) => setTimeout(r, 2000));
|
|
502
|
+
* run = await client.getRun(run_id);
|
|
503
|
+
* }
|
|
504
|
+
* console.log(run.output);
|
|
505
|
+
* ```
|
|
98
506
|
*/
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}): AsyncGenerator<AgentEvent>;
|
|
507
|
+
getRun(runId: string, options?: {
|
|
508
|
+
signal?: AbortSignal;
|
|
509
|
+
}): Promise<RunStatus>;
|
|
103
510
|
}
|
|
104
511
|
export default PromptevClient;
|