@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.
@@ -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
- projectKey: string;
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
- export interface AgentSession {
9
- sessionToken: string;
10
- agentId: string;
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
- memoryEnabled: boolean;
13
- messages: Record<string, any>[];
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
- export interface TriggerResult {
16
- response: string;
17
- sessionId: string;
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
- export interface AgentEvent {
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
- output: string;
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
- constructor(message: string, statusCode?: number, responseText?: string);
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
- constructor(message: string, statusCode?: number, responseText?: string);
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
- constructor(message: string, statusCode?: number, responseText?: string);
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
- constructor(message: string, statusCode?: number, responseText?: string);
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
- constructor(message: string, statusCode?: number, responseText?: string);
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
- constructor(message: string, statusCode?: number, responseText?: string);
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
- constructor(message: string, statusCode?: number, responseText?: string);
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 projectKey;
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
- * Trigger an agent in a single blocking call — the primary way to use the SDK.
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
- * 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.
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
- * @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.
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
- * const { response, sessionId } = await client.triggerAgent(
73
- * "your-agent-id",
74
- * "What is the refund policy?",
75
- * { variables: { company: "Acme Corp" } }
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
- * // Follow-up keeps memory:
78
- * await client.triggerAgent("your-agent-id", "And for digital goods?", { sessionId });
464
+ * for (const r of results) console.log(r.filename, r.status, r.error ?? "");
465
+ * ```
79
466
  */
80
- triggerAgent(agentId: string, message: string, opts?: {
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 new agent chat session (streaming flow).
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
- * @param agentId - Your agent's id (from the Deploy tab).
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
- startAgent(agentId: string, options?: {
91
- visitor?: string;
92
- platform?: string;
93
- }): Promise<AgentSession>;
494
+ runOrchestration(slug: string, inputs?: RunInputs, options?: RunOptions): Promise<StartedRun>;
94
495
  /**
95
- * Stream an agent response as SSE events.
496
+ * What became of a run — poll this after {@link runOrchestration}.
96
497
  *
97
- * @param agentId - Your agent's id (from the Deploy tab).
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
- streamAgent(agentId: string, options: {
100
- sessionToken: string;
101
- query: string;
102
- }): AsyncGenerator<AgentEvent>;
507
+ getRun(runId: string, options?: {
508
+ signal?: AbortSignal;
509
+ }): Promise<RunStatus>;
103
510
  }
104
511
  export default PromptevClient;