@darqlabs/curator-sdk 0.1.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/LICENSE +21 -0
- package/README.md +313 -0
- package/dist/cjs/client.d.ts +174 -0
- package/dist/cjs/client.d.ts.map +1 -0
- package/dist/cjs/client.js +417 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/errors.d.ts +91 -0
- package/dist/cjs/errors.d.ts.map +1 -0
- package/dist/cjs/errors.js +131 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/files.d.ts +66 -0
- package/dist/cjs/files.d.ts.map +1 -0
- package/dist/cjs/files.js +86 -0
- package/dist/cjs/files.js.map +1 -0
- package/dist/cjs/http.d.ts +92 -0
- package/dist/cjs/http.d.ts.map +1 -0
- package/dist/cjs/http.js +232 -0
- package/dist/cjs/http.js.map +1 -0
- package/dist/cjs/index.d.ts +10 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +22 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/sse.d.ts +20 -0
- package/dist/cjs/sse.d.ts.map +1 -0
- package/dist/cjs/sse.js +89 -0
- package/dist/cjs/sse.js.map +1 -0
- package/dist/cjs/streamEventParse.d.ts +13 -0
- package/dist/cjs/streamEventParse.d.ts.map +1 -0
- package/dist/cjs/streamEventParse.js +81 -0
- package/dist/cjs/streamEventParse.js.map +1 -0
- package/dist/cjs/streamEvents.d.ts +58 -0
- package/dist/cjs/streamEvents.d.ts.map +1 -0
- package/dist/cjs/streamEvents.js +22 -0
- package/dist/cjs/streamEvents.js.map +1 -0
- package/dist/cjs/types.d.ts +93 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +10 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/client.d.ts +174 -0
- package/dist/esm/client.d.ts.map +1 -0
- package/dist/esm/client.js +411 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/errors.d.ts +91 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js +119 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/files.d.ts +66 -0
- package/dist/esm/files.d.ts.map +1 -0
- package/dist/esm/files.js +82 -0
- package/dist/esm/files.js.map +1 -0
- package/dist/esm/http.d.ts +92 -0
- package/dist/esm/http.d.ts.map +1 -0
- package/dist/esm/http.js +228 -0
- package/dist/esm/http.js.map +1 -0
- package/dist/esm/index.d.ts +10 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/sse.d.ts +20 -0
- package/dist/esm/sse.d.ts.map +1 -0
- package/dist/esm/sse.js +86 -0
- package/dist/esm/sse.js.map +1 -0
- package/dist/esm/streamEventParse.d.ts +13 -0
- package/dist/esm/streamEventParse.d.ts.map +1 -0
- package/dist/esm/streamEventParse.js +78 -0
- package/dist/esm/streamEventParse.js.map +1 -0
- package/dist/esm/streamEvents.d.ts +58 -0
- package/dist/esm/streamEvents.d.ts.map +1 -0
- package/dist/esm/streamEvents.js +19 -0
- package/dist/esm/streamEvents.js.map +1 -0
- package/dist/esm/types.d.ts +93 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +9 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Darq Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# @darqlabs/curator-sdk
|
|
2
|
+
|
|
3
|
+
Official Curator SDK.
|
|
4
|
+
|
|
5
|
+
Integrate with your deployed agents. Works in Node, the browser, and modern edge runtimes (anywhere `fetch` exists).
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
const reply = await curator.agent("support-bot").run("How do I reset my password?")
|
|
9
|
+
//console.log(reply.content)
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Integration guide
|
|
15
|
+
|
|
16
|
+
### Before you start
|
|
17
|
+
|
|
18
|
+
You'll need three things from your Curator dashboard:
|
|
19
|
+
|
|
20
|
+
1. **An API key.** Generate one at **Settings → Developer**. Each key is scoped to a single environment (production, staging, or development) — pick the one you're integrating against.
|
|
21
|
+
2. **Your project slug.**
|
|
22
|
+
3. **A deployed agent's identifier slug.**
|
|
23
|
+
|
|
24
|
+
### 1. Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install @darqlabs/curator-sdk
|
|
28
|
+
# or
|
|
29
|
+
pnpm add @darqlabs/curator-sdk
|
|
30
|
+
# or
|
|
31
|
+
yarn add @darqlabs/curator-sdk
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Requires Node 18+ or any runtime with a global `fetch`. Ships ESM + CommonJS — modern bundlers tree-shake it automatically.
|
|
35
|
+
|
|
36
|
+
### 2. Initialize the client
|
|
37
|
+
|
|
38
|
+
Create one `Curator` instance and reuse it for the lifetime of your process.
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import { Curator } from "@darqlabs/curator-sdk"
|
|
42
|
+
|
|
43
|
+
export const curator = new Curator({
|
|
44
|
+
apiKey: "CURATOR_API_KEY",
|
|
45
|
+
project: "default", // your project slug
|
|
46
|
+
environment: "production", // 'production' | 'staging' | 'development'
|
|
47
|
+
})
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 3. Send your first message
|
|
51
|
+
|
|
52
|
+
For a single round-trip, use `agent.run()`:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
const reply = await curator
|
|
56
|
+
.agent("support-bot")
|
|
57
|
+
.run("Hi, I lost my receipt — can you resend it for order #4823?")
|
|
58
|
+
|
|
59
|
+
console.log(reply.content)
|
|
60
|
+
// reply.conversationId — store this if you want to follow up
|
|
61
|
+
// reply.runId — useful for log correlation
|
|
62
|
+
// reply.sequence — per-conversation message index
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 4. Multi-turn conversations
|
|
66
|
+
|
|
67
|
+
For ongoing chat, use `agent.chat()`:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
const chat = curator.agent("support-bot").chat()
|
|
71
|
+
|
|
72
|
+
await chat.send("I'd like to upgrade my plan.")
|
|
73
|
+
await chat.send("Actually, what's included in the Pro tier?")
|
|
74
|
+
|
|
75
|
+
console.log(chat.id) // "conv_8f2a1c4b9e0d"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 5. Resume a conversation later
|
|
79
|
+
|
|
80
|
+
Store `chat.id` somewhere durable, then reattach with `.conversation(id)`:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
const chat = curator.agent("support-bot").conversation(conversationId)
|
|
84
|
+
const reply = await chat.send("Following up on what we discussed yesterday…")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
You can also fetch the prior message history:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
const page = await chat.history({ limit: 50 })
|
|
91
|
+
for (const msg of page.messages) {
|
|
92
|
+
console.log(`[${msg.role}] ${msg.content}`)
|
|
93
|
+
}
|
|
94
|
+
if (page.hasMore) {
|
|
95
|
+
const next = await chat.history({ limit: 50, beforeSequence: page.oldestSequence! })
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 6. Handle errors
|
|
100
|
+
|
|
101
|
+
The SDK throws typed errors for non-success states. Catch the ones you care about:
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
import {
|
|
105
|
+
CuratorApprovalRequiredError,
|
|
106
|
+
CuratorAgentError,
|
|
107
|
+
CuratorTimeoutError,
|
|
108
|
+
CuratorAuthError,
|
|
109
|
+
CuratorNotFoundError,
|
|
110
|
+
} from "@darqlabs/curator-sdk"
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const reply = await chat.send("Refund my last order.")
|
|
114
|
+
// …use reply.content
|
|
115
|
+
} catch (err) {
|
|
116
|
+
if (err instanceof CuratorApprovalRequiredError) {
|
|
117
|
+
// The agent paused waiting for human approval. Resolution happens in
|
|
118
|
+
// the Curator dashboard — surface a friendly message to your user.
|
|
119
|
+
showToUser(
|
|
120
|
+
`That action needs administrator approval. Please contact your ` +
|
|
121
|
+
`administrator to review the request for "${err.approval.tool_name}".`,
|
|
122
|
+
)
|
|
123
|
+
} else if (err instanceof CuratorTimeoutError) {
|
|
124
|
+
// The wait expired but the agent is still working in the background.
|
|
125
|
+
// Either give the user a "still thinking…" message, or keep waiting:
|
|
126
|
+
const reply = await err.continueWaiting(180000)
|
|
127
|
+
} else if (err instanceof CuratorAgentError) {
|
|
128
|
+
// Terminal agent failure — LLM quota, provider auth, etc.
|
|
129
|
+
// err.failureClass is one of: provider_quota_exhausted | provider_auth |
|
|
130
|
+
// provider_bad_request | provider_rate_limited | provider_unavailable |
|
|
131
|
+
// internal | unknown. err.isPermanent tells you whether retrying helps.
|
|
132
|
+
log.error({ err }, "agent run failed")
|
|
133
|
+
} else if (err instanceof CuratorAuthError) {
|
|
134
|
+
// 401 — bad / revoked API key.
|
|
135
|
+
} else if (err instanceof CuratorNotFoundError) {
|
|
136
|
+
// 404 — wrong deployment slug, project, or conversation id.
|
|
137
|
+
} else {
|
|
138
|
+
throw err
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
All errors inherit from `CuratorError`, so a single `catch (err: CuratorError)` works as a backstop if you'd rather handle them generically.
|
|
144
|
+
|
|
145
|
+
### 7. Attach files
|
|
146
|
+
|
|
147
|
+
Give the SDK the bytes, get back a reference ready to attach:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
const fileRef = await curator.files.upload({
|
|
151
|
+
filename: "sales-2026-q2.csv",
|
|
152
|
+
mimeType: "text/csv",
|
|
153
|
+
data: csvBlob, // Blob, File, ArrayBuffer, Uint8Array, or Buffer
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
const reply = await chat.send("What does this CSV show?", {
|
|
157
|
+
files: [fileRef],
|
|
158
|
+
})
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Two-step** — useful when you want to drive the PUT yourself (progress UI, resumable uploads, custom transport):
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
const { uploadUrl, headers, fileReference } = await curator.files.createUpload({
|
|
165
|
+
filename: "sales-2026-q2.csv",
|
|
166
|
+
mimeType: "text/csv",
|
|
167
|
+
size: csvBlob.size,
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
await fetch(uploadUrl, { method: "PUT", headers, body: csvBlob })
|
|
171
|
+
|
|
172
|
+
const reply = await chat.send("What does this CSV show?", {
|
|
173
|
+
files: [fileReference],
|
|
174
|
+
})
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Common patterns
|
|
180
|
+
|
|
181
|
+
### Stateful chat in a web app
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
const chat = userSession.conversationId
|
|
185
|
+
? curator.agent("support-bot").conversation(userSession.conversationId)
|
|
186
|
+
: curator.agent("support-bot").chat()
|
|
187
|
+
|
|
188
|
+
const reply = await chat.send(userInput)
|
|
189
|
+
if (!userSession.conversationId) {
|
|
190
|
+
await persistConversationId(userSession.id, chat.id!)
|
|
191
|
+
}
|
|
192
|
+
return reply.content
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Long-running runs
|
|
196
|
+
|
|
197
|
+
Raise the timeout per-call (server cap 5 minutes):
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
const reply = await chat.send("Do a deep research pass on this brief.", {
|
|
201
|
+
timeoutMs: 300000,
|
|
202
|
+
})
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Using from a browser
|
|
208
|
+
|
|
209
|
+
**CORS:** browser requests hit the Curator API directly, so your origin must be on the allowlist. Add it in **Settings → Developer**.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Optional: verified end-user identity
|
|
214
|
+
|
|
215
|
+
**You don't need this to get started.** An API key + project is all it takes to talk to your agents — everything above works without any user-level identity.
|
|
216
|
+
|
|
217
|
+
Turn this on only when you want Curator to know *which* of your users is driving a conversation — for per-user policies, audit attribution, or tenant isolation. It's opt-in per org: until an operator enables it in **Settings → Developer → End-user auth**, the SDK ignores `endUserJwt` entirely and requests authenticate on the API key alone.
|
|
218
|
+
|
|
219
|
+
When enabled, your backend mints a short-lived JWT per user and hands it to the SDK. The server verifies it against your configured JWKS endpoint:
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
const curator = new Curator({
|
|
223
|
+
apiKey: process.env.CURATOR_API_KEY!,
|
|
224
|
+
project: "default",
|
|
225
|
+
// Static token, or a function the SDK calls per request to refresh it.
|
|
226
|
+
endUserJwt: () => mintEndUserJwtForCurrentUser(),
|
|
227
|
+
})
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Standing up a JWKS endpoint is **not required for MVP** — skip this section and revisit it when you need verified identity.
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## API reference
|
|
235
|
+
|
|
236
|
+
### `new Curator(options)`
|
|
237
|
+
|
|
238
|
+
| Option | Type | Default | Notes |
|
|
239
|
+
| --- | --- | --- | --- |
|
|
240
|
+
| `apiKey` | `string` | — | Required. `curator_live_*` (production) or `curator_test_*` (staging / development), from Settings → Developer. |
|
|
241
|
+
| `project` | `string` | — | Default project slug. Required unless every call passes `{ system: true }`. |
|
|
242
|
+
| `environment` | `'production' \| 'staging' \| 'development'` | `'production'` | Default environment. Must match the environment your `apiKey` was issued for. |
|
|
243
|
+
| `baseUrl` | `string` | managed host | Override for self-hosted. |
|
|
244
|
+
| `defaultTimeoutMs` | `number` | `120000` | Server-capped at `300000`. |
|
|
245
|
+
| `defaultHeaders` | `Record<string,string>` | `{}` | Sent on every request. |
|
|
246
|
+
| `fetch` | `typeof fetch` | global | Inject a custom fetch. |
|
|
247
|
+
| `endUserJwt` | `string \| () => string \| Promise<string>` | — | **Optional.** Only needed if your org has turned on verified end-user identity (see below). Leave it unset otherwise. |
|
|
248
|
+
|
|
249
|
+
### `curator.agent(slug, locator?)`
|
|
250
|
+
|
|
251
|
+
Returns an `Agent` bound to the given deployment. `locator` accepts `{ project?, environment?, system? }` to override the constructor defaults for this address.
|
|
252
|
+
|
|
253
|
+
### `agent.run(content, opts?) → Promise<AssistantMessage>`
|
|
254
|
+
|
|
255
|
+
Send a single message and return the reply. Equivalent to `agent.chat().send(content, opts)`.
|
|
256
|
+
|
|
257
|
+
### `agent.chat() → Chat`
|
|
258
|
+
|
|
259
|
+
Returns a new chat handle for multi-turn conversations.
|
|
260
|
+
|
|
261
|
+
### `agent.conversation(id) → Chat`
|
|
262
|
+
|
|
263
|
+
Reattach to an existing conversation by id.
|
|
264
|
+
|
|
265
|
+
### `chat.send(content, opts?) → Promise<AssistantMessage>`
|
|
266
|
+
|
|
267
|
+
`opts.files?: FileAttachment[]` — attachments.
|
|
268
|
+
`opts.timeoutMs?: number` — override the wait timeout for this call.
|
|
269
|
+
|
|
270
|
+
### `chat.history(opts?) → Promise<HistoryPage>`
|
|
271
|
+
|
|
272
|
+
`opts.limit?: number` — page size (server cap 500).
|
|
273
|
+
`opts.beforeSequence?: number` — cursor; pass `page.oldestSequence` from the previous page.
|
|
274
|
+
|
|
275
|
+
### `chat.id`
|
|
276
|
+
|
|
277
|
+
Conversation id, or `null` until the first send.
|
|
278
|
+
|
|
279
|
+
### `curator.files.upload(input) → Promise<FileAttachment>`
|
|
280
|
+
|
|
281
|
+
One-shot upload. `input` is `{ filename, mimeType, data, size? }` where `data` is a `Blob`, `File`, `ArrayBuffer`, `Uint8Array`, or `Buffer`. Returns the reference to pass into `chat.send(..., { files: [...] })`.
|
|
282
|
+
|
|
283
|
+
### `curator.files.createUpload(input) → Promise<PresignUploadResult>`
|
|
284
|
+
|
|
285
|
+
Two-step: returns `{ uploadUrl, method, headers, expiresAt, fileReference }`. PUT the bytes to `uploadUrl` with the returned `headers`, then attach `fileReference` to a send.
|
|
286
|
+
|
|
287
|
+
### Errors
|
|
288
|
+
|
|
289
|
+
| Class | Thrown when |
|
|
290
|
+
| --- | --- |
|
|
291
|
+
| `CuratorAuthError` | 401 — bad / revoked API key. |
|
|
292
|
+
| `CuratorForbiddenError` | 403 — permission denied. |
|
|
293
|
+
| `CuratorNotFoundError` | 404 — unknown deployment / conversation. |
|
|
294
|
+
| `CuratorDeploymentRetiredError` | 410 — deployment retired. |
|
|
295
|
+
| `CuratorRateLimitError` | 429 — back off. |
|
|
296
|
+
| `CuratorApprovalRequiredError` | Run paused for human approval. |
|
|
297
|
+
| `CuratorAgentError` | Terminal agent failure (LLM quota, etc.). `failureClass` + `isPermanent`. |
|
|
298
|
+
| `CuratorTimeoutError` | Wait expired. `continueWaiting()` resumes. |
|
|
299
|
+
| `CuratorError` | Base class — everything above extends this. |
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Troubleshooting
|
|
304
|
+
|
|
305
|
+
**`CuratorAuthError: Invalid or revoked API key`** — double-check the key in **Settings → Developer**. The SDK sends it as `Authorization: Bearer <key>`.
|
|
306
|
+
|
|
307
|
+
**`CuratorNotFoundError: Deployment not found`** — verify (project slug, environment, deployment slug) all match what the **Deployments** tab shows. Missing one of these is the #1 cause.
|
|
308
|
+
|
|
309
|
+
**`CuratorTimeoutError` on every call** — your agent is taking longer than `defaultTimeoutMs`. Raise the timeout (`new Curator({ defaultTimeoutMs: 300000 })`) or call `err.continueWaiting()` once.
|
|
310
|
+
|
|
311
|
+
**Browser requests fail with a CORS error** — add your origin to the allowlist in **Settings → Developer**. The SDK isn't doing anything unusual; the request gets blocked before it reaches Curator.
|
|
312
|
+
|
|
313
|
+
**Approval-required pauses on every send** — your agent has tools that require human approval. Resolve them once in the dashboard and adjust the deployment's policy if you don't want this gate in your environment.
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public surface of the Curator SDK.
|
|
3
|
+
*
|
|
4
|
+
* const curator = new Curator({ apiKey, project, environment })
|
|
5
|
+
* const reply = await curator.agent("support-bot").run("hello")
|
|
6
|
+
*
|
|
7
|
+
* const chat = curator.agent("support-bot").chat()
|
|
8
|
+
* const r1 = await chat.send("first")
|
|
9
|
+
* const r2 = await chat.send("follow up")
|
|
10
|
+
*
|
|
11
|
+
* const chat = curator.agent("support-bot").conversation("conv_xxx")
|
|
12
|
+
* const r = await chat.send("continuing later")
|
|
13
|
+
*
|
|
14
|
+
* Both helpers route through `?wait=true` under the hood — the caller
|
|
15
|
+
* never sees `run_id` or has to poll. Non-completion states (HITL
|
|
16
|
+
* pause, terminal agent error, timeout) surface as typed errors from
|
|
17
|
+
* `./errors`. HITL approvals are NOT resolved through the SDK — the
|
|
18
|
+
* pause is surfaced as an error so the calling app can tell its user
|
|
19
|
+
* to contact an administrator, who handles it in the dashboard.
|
|
20
|
+
*/
|
|
21
|
+
import { Files } from "./files.js";
|
|
22
|
+
import { HttpClient, type DeploymentRoute, type EndUserJwtProvider } from "./http.js";
|
|
23
|
+
import type { StreamEvent } from "./streamEvents.js";
|
|
24
|
+
import type { AssistantMessage, DeploymentConfig, Environment, HistoryOptions, HistoryPage, SendOptions } from "./types.js";
|
|
25
|
+
export interface CuratorOptions {
|
|
26
|
+
/** Org-scoped API key from Settings → Developer. `curator_live_*` for production, `curator_test_*` for staging / development. */
|
|
27
|
+
apiKey: string;
|
|
28
|
+
/**
|
|
29
|
+
* Base URL of the Curator deployment. Defaults to the public host.
|
|
30
|
+
* Override for self-hosted or staging environments.
|
|
31
|
+
*/
|
|
32
|
+
baseUrl?: string;
|
|
33
|
+
/** Default project slug. Can be overridden per-call via `agent(slug, { project })`. */
|
|
34
|
+
project?: string;
|
|
35
|
+
/** Default environment. Can be overridden per-call via `agent(slug, { environment })`. */
|
|
36
|
+
environment?: Environment;
|
|
37
|
+
/** Default sync-wait timeout, in ms. The server caps this at 300s. */
|
|
38
|
+
defaultTimeoutMs?: number;
|
|
39
|
+
/** Custom fetch implementation (test stubs, older Node, etc.). */
|
|
40
|
+
fetch?: typeof fetch;
|
|
41
|
+
/** Extra headers attached to every request. */
|
|
42
|
+
defaultHeaders?: Record<string, string>;
|
|
43
|
+
/**
|
|
44
|
+
* End-user JWT — proves which user on the customer's platform is driving
|
|
45
|
+
* the agent. Required when the org has opted into verified end-user
|
|
46
|
+
* identity. Accepts either a static string or a sync/async function the
|
|
47
|
+
* SDK calls per-request (typical for browsers refreshing short-lived
|
|
48
|
+
* tokens via their backend). See {@link EndUserJwtProvider}.
|
|
49
|
+
*/
|
|
50
|
+
endUserJwt?: EndUserJwtProvider;
|
|
51
|
+
}
|
|
52
|
+
export interface AgentLocator {
|
|
53
|
+
/** Project slug. Defaults to the value passed to `new Curator({ project })`. */
|
|
54
|
+
project?: string;
|
|
55
|
+
/** Environment. Defaults to the value passed to `new Curator({ environment })`. */
|
|
56
|
+
environment?: Environment;
|
|
57
|
+
/**
|
|
58
|
+
* Set to true to address a system-scoped deployment (no project /
|
|
59
|
+
* environment in the path). Mutually exclusive with `project`.
|
|
60
|
+
*/
|
|
61
|
+
system?: boolean;
|
|
62
|
+
}
|
|
63
|
+
export declare class Curator {
|
|
64
|
+
private readonly http;
|
|
65
|
+
private readonly defaultProject?;
|
|
66
|
+
private readonly defaultEnvironment;
|
|
67
|
+
private readonly defaultTimeoutMs;
|
|
68
|
+
/** File-upload surface — see {@link Files}. */
|
|
69
|
+
readonly files: Files;
|
|
70
|
+
constructor(opts: CuratorOptions);
|
|
71
|
+
/**
|
|
72
|
+
* Address an agent deployment by its slug. Project / environment fall
|
|
73
|
+
* back to the constructor defaults; pass overrides via the second arg.
|
|
74
|
+
*/
|
|
75
|
+
agent(slug: string, locator?: AgentLocator): Agent;
|
|
76
|
+
private resolveRoute;
|
|
77
|
+
}
|
|
78
|
+
export declare class Agent {
|
|
79
|
+
private readonly http;
|
|
80
|
+
private readonly defaultTimeoutMs;
|
|
81
|
+
private readonly route;
|
|
82
|
+
/** @internal */
|
|
83
|
+
constructor(http: HttpClient, defaultTimeoutMs: number, route: DeploymentRoute);
|
|
84
|
+
/**
|
|
85
|
+
* Open a fresh conversation, send `content`, await the reply, and
|
|
86
|
+
* return it. Equivalent to `agent.chat().send(content)` but one line.
|
|
87
|
+
*/
|
|
88
|
+
run(content: string, opts?: SendOptions): Promise<AssistantMessage>;
|
|
89
|
+
/**
|
|
90
|
+
* Open a fresh conversation and stream the reply as it's generated.
|
|
91
|
+
* Equivalent to `agent.chat().stream(content)`.
|
|
92
|
+
*/
|
|
93
|
+
stream(content: string, opts?: SendOptions): AsyncIterable<StreamEvent>;
|
|
94
|
+
/**
|
|
95
|
+
* Return a Chat handle whose conversation is created lazily on the
|
|
96
|
+
* first `send(...)`. Subsequent sends reuse the same conversation.
|
|
97
|
+
*/
|
|
98
|
+
chat(): Chat;
|
|
99
|
+
/**
|
|
100
|
+
* Reattach to an existing conversation by id (e.g. resuming a chat
|
|
101
|
+
* across processes or restoring from durable state).
|
|
102
|
+
*/
|
|
103
|
+
conversation(conversationId: string): Chat;
|
|
104
|
+
/**
|
|
105
|
+
* Fetch this deployment's read-only client config (branding entitlements,
|
|
106
|
+
* etc.). Resolved server-side from the org's subscription tier. No side
|
|
107
|
+
* effects — safe to call on widget mount. `<CuratorChat />` uses this to
|
|
108
|
+
* decide whether to render the "Powered by Curator" footer.
|
|
109
|
+
*/
|
|
110
|
+
config(): Promise<DeploymentConfig>;
|
|
111
|
+
}
|
|
112
|
+
export declare class Chat {
|
|
113
|
+
private readonly http;
|
|
114
|
+
private readonly defaultTimeoutMs;
|
|
115
|
+
private readonly route;
|
|
116
|
+
private conversationId;
|
|
117
|
+
/** Cached promise for an in-flight `POST /conversations`. */
|
|
118
|
+
private pendingCreate;
|
|
119
|
+
/** @internal */
|
|
120
|
+
constructor(http: HttpClient, defaultTimeoutMs: number, route: DeploymentRoute, initialConversationId: string | null);
|
|
121
|
+
/**
|
|
122
|
+
* Conversation id, or `null` until the first send creates one.
|
|
123
|
+
* Use `.ensureId()` if you need to materialize the conversation
|
|
124
|
+
* eagerly without sending a message.
|
|
125
|
+
*/
|
|
126
|
+
get id(): string | null;
|
|
127
|
+
/** Force conversation creation now and return its id. */
|
|
128
|
+
ensureId(): Promise<string>;
|
|
129
|
+
/**
|
|
130
|
+
* Send a user message and await the assistant's reply. Lazily creates
|
|
131
|
+
* the conversation if needed. Returns the final assistant message.
|
|
132
|
+
*
|
|
133
|
+
* Throws:
|
|
134
|
+
* - CuratorApprovalRequiredError if the run pauses for HITL (an
|
|
135
|
+
* administrator must resolve it in the dashboard)
|
|
136
|
+
* - CuratorAgentError on terminal agent failure
|
|
137
|
+
* - CuratorTimeoutError if the wait expires (the run keeps running)
|
|
138
|
+
*/
|
|
139
|
+
send(content: string, opts?: SendOptions): Promise<AssistantMessage>;
|
|
140
|
+
/**
|
|
141
|
+
* Send a user message and stream the agent's response back as it's
|
|
142
|
+
* generated. Each yielded event is one of `delta` / `tool_call.*` /
|
|
143
|
+
* `done` / `error` / `paused_for_approval`. The iterator ends on the
|
|
144
|
+
* first terminal event.
|
|
145
|
+
*
|
|
146
|
+
* for await (const e of chat.stream("hello")) {
|
|
147
|
+
* if (e.type === "delta") process.stdout.write(e.text)
|
|
148
|
+
* if (e.type === "done") console.log("\nfinal:", e.message?.content)
|
|
149
|
+
* }
|
|
150
|
+
*
|
|
151
|
+
* Aborting the iteration (breaking out of the loop, or calling
|
|
152
|
+
* `.return()`) closes the underlying HTTP connection — the server-
|
|
153
|
+
* side run keeps going independently. Use `chat.history()` later to
|
|
154
|
+
* fetch what landed.
|
|
155
|
+
*/
|
|
156
|
+
stream(content: string, opts?: SendOptions): AsyncGenerator<StreamEvent, void, void>;
|
|
157
|
+
/** Fetch (paginated) conversation history. */
|
|
158
|
+
history(opts?: HistoryOptions): Promise<HistoryPage>;
|
|
159
|
+
private createConversation;
|
|
160
|
+
/**
|
|
161
|
+
* Continue waiting for the next terminal state on an already-running
|
|
162
|
+
* conversation. Used to back `CuratorTimeoutError.continueWaiting()`.
|
|
163
|
+
*
|
|
164
|
+
* The server-side wait endpoint hangs off `POST /messages`, so to
|
|
165
|
+
* re-wait without sending a new user message we poll history for an
|
|
166
|
+
* assistant message whose `sequence` exceeds the baseline established
|
|
167
|
+
* before the wait began. For a still-in-flight run, the assistant
|
|
168
|
+
* reply typically lands within seconds.
|
|
169
|
+
*/
|
|
170
|
+
private waitForNextReply;
|
|
171
|
+
private latestSequence;
|
|
172
|
+
private unwrapWaitOutcome;
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
|