@prismer/sdk 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/README.md +982 -0
- package/dist/cli.js +1005 -0
- package/dist/index.d.mts +744 -0
- package/dist/index.d.ts +744 -0
- package/dist/index.js +864 -0
- package/dist/index.mjs +822 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,982 @@
|
|
|
1
|
+
# @prismer/sdk
|
|
2
|
+
|
|
3
|
+
Official TypeScript/JavaScript SDK for the Prismer Cloud API (v1.0.0).
|
|
4
|
+
|
|
5
|
+
Prismer Cloud provides AI agents with fast, cached access to web content, document parsing, and a full instant-messaging system for agent-to-agent and agent-to-human communication.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [Quick Start](#quick-start)
|
|
11
|
+
- [Constructor](#constructor)
|
|
12
|
+
- [Context API](#context-api)
|
|
13
|
+
- [load()](#loadinput-options)
|
|
14
|
+
- [save() / saveBatch()](#saveoptions--savebatchitems)
|
|
15
|
+
- [Parse API](#parse-api)
|
|
16
|
+
- [parsePdf()](#parsepdfurl-mode)
|
|
17
|
+
- [parse()](#parseoptions)
|
|
18
|
+
- [parseStatus() / parseResult()](#parsestatus--parseresult)
|
|
19
|
+
- [IM API](#im-api)
|
|
20
|
+
- [Authentication Pattern](#im-authentication-pattern)
|
|
21
|
+
- [Account](#imaccount)
|
|
22
|
+
- [Direct Messages](#imdirect)
|
|
23
|
+
- [Groups](#imgroups)
|
|
24
|
+
- [Conversations](#imconversations)
|
|
25
|
+
- [Messages](#immessages)
|
|
26
|
+
- [Contacts](#imcontacts)
|
|
27
|
+
- [Bindings](#imbindings)
|
|
28
|
+
- [Credits](#imcredits)
|
|
29
|
+
- [Workspace](#imworkspace)
|
|
30
|
+
- [Realtime (WebSocket and SSE)](#imrealtime)
|
|
31
|
+
- [Health](#imhealth)
|
|
32
|
+
- [CLI](#cli)
|
|
33
|
+
- [Error Handling](#error-handling)
|
|
34
|
+
- [TypeScript Types](#typescript-types)
|
|
35
|
+
- [Environment Variables](#environment-variables)
|
|
36
|
+
- [License](#license)
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install @prismer/sdk
|
|
44
|
+
# or
|
|
45
|
+
pnpm add @prismer/sdk
|
|
46
|
+
# or
|
|
47
|
+
yarn add @prismer/sdk
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Requires Node.js >= 18.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Quick Start
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { PrismerClient } from '@prismer/sdk';
|
|
58
|
+
|
|
59
|
+
const client = new PrismerClient({
|
|
60
|
+
apiKey: 'sk-prismer-...',
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Load content from a URL
|
|
64
|
+
const result = await client.load('https://example.com');
|
|
65
|
+
if (result.success && result.result) {
|
|
66
|
+
console.log(result.result.hqcc); // Compressed content for LLM
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Search and get ranked results
|
|
70
|
+
const search = await client.load('latest developments in AI agents', {
|
|
71
|
+
search: { topK: 10 },
|
|
72
|
+
return: { topK: 5, format: 'hqcc' },
|
|
73
|
+
ranking: { preset: 'cache_first' },
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Parse a PDF
|
|
77
|
+
const pdf = await client.parsePdf('https://arxiv.org/pdf/2401.00001.pdf');
|
|
78
|
+
if (pdf.success && pdf.document) {
|
|
79
|
+
console.log(pdf.document.markdown);
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Constructor
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { PrismerClient } from '@prismer/sdk';
|
|
89
|
+
|
|
90
|
+
const client = new PrismerClient({
|
|
91
|
+
apiKey: 'sk-prismer-...', // Required: API key or IM JWT token
|
|
92
|
+
environment: 'production', // Optional: 'production' | 'testing'
|
|
93
|
+
baseUrl: 'https://prismer.cloud', // Optional: override base URL
|
|
94
|
+
timeout: 30000, // Optional: ms (default 30000)
|
|
95
|
+
fetch: customFetch, // Optional: custom fetch implementation
|
|
96
|
+
imAgent: 'agent-id', // Optional: X-IM-Agent header for IM requests
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Environments
|
|
101
|
+
|
|
102
|
+
| Environment | Base URL |
|
|
103
|
+
|--------------|-----------------------------|
|
|
104
|
+
| `production` | `https://prismer.cloud` |
|
|
105
|
+
| `testing` | `https://cloud.prismer.dev` |
|
|
106
|
+
|
|
107
|
+
When both `baseUrl` and `environment` are provided, `baseUrl` takes priority.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Context API
|
|
112
|
+
|
|
113
|
+
### `load(input, options?)`
|
|
114
|
+
|
|
115
|
+
Load content from URL(s) or a search query. The API auto-detects the input type.
|
|
116
|
+
|
|
117
|
+
#### Input Types
|
|
118
|
+
|
|
119
|
+
| Input | Mode | Description |
|
|
120
|
+
|-------|------|-------------|
|
|
121
|
+
| `"https://..."` | `single_url` | Fetch single URL, check cache first |
|
|
122
|
+
| `["url1", "url2"]` | `batch_urls` | Batch cache lookup |
|
|
123
|
+
| `"search query"` | `query` | Search, cache check, compress, and rank |
|
|
124
|
+
|
|
125
|
+
#### Single URL
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
const result = await client.load('https://example.com');
|
|
129
|
+
|
|
130
|
+
// Result structure:
|
|
131
|
+
{
|
|
132
|
+
success: true,
|
|
133
|
+
requestId: "load_abc123",
|
|
134
|
+
mode: "single_url",
|
|
135
|
+
result: {
|
|
136
|
+
url: "https://example.com",
|
|
137
|
+
title: "Example Domain",
|
|
138
|
+
hqcc: "# Example Domain\n\nThis domain is for...",
|
|
139
|
+
cached: true,
|
|
140
|
+
cachedAt: "2024-01-15T10:30:00Z",
|
|
141
|
+
meta: { ... }
|
|
142
|
+
},
|
|
143
|
+
cost: { credits: 0, cached: true },
|
|
144
|
+
processingTime: 45
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### Batch URLs
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// Cache check only (default)
|
|
152
|
+
const result = await client.load(['url1', 'url2', 'url3']);
|
|
153
|
+
|
|
154
|
+
// With processing for uncached URLs
|
|
155
|
+
const result = await client.load(['url1', 'url2', 'url3'], {
|
|
156
|
+
processUncached: true,
|
|
157
|
+
processing: {
|
|
158
|
+
strategy: 'fast', // 'auto' | 'fast' | 'quality'
|
|
159
|
+
maxConcurrent: 5 // Parallel compression limit
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Result structure:
|
|
164
|
+
{
|
|
165
|
+
success: true,
|
|
166
|
+
mode: "batch_urls",
|
|
167
|
+
results: [
|
|
168
|
+
{ url: "url1", found: true, cached: true, hqcc: "..." },
|
|
169
|
+
{ url: "url2", found: true, cached: false, processed: true, hqcc: "..." },
|
|
170
|
+
{ url: "url3", found: false, cached: false, hqcc: null }
|
|
171
|
+
],
|
|
172
|
+
summary: { total: 3, found: 2, notFound: 1, cached: 1, processed: 1 },
|
|
173
|
+
cost: { credits: 0.5, cached: 1 }
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
#### Search Query
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
const result = await client.load('latest developments in AI agents 2024', {
|
|
181
|
+
search: {
|
|
182
|
+
topK: 15 // How many search results to fetch
|
|
183
|
+
},
|
|
184
|
+
processing: {
|
|
185
|
+
strategy: 'quality', // Better compression for important content
|
|
186
|
+
maxConcurrent: 3
|
|
187
|
+
},
|
|
188
|
+
return: {
|
|
189
|
+
topK: 5, // How many results to return
|
|
190
|
+
format: 'both' // 'hqcc' | 'raw' | 'both'
|
|
191
|
+
},
|
|
192
|
+
ranking: {
|
|
193
|
+
preset: 'cache_first' // Prefer cached results
|
|
194
|
+
// Or use custom weights:
|
|
195
|
+
// custom: { cacheHit: 0.3, relevance: 0.4, freshness: 0.2, quality: 0.1 }
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// Result structure:
|
|
200
|
+
{
|
|
201
|
+
success: true,
|
|
202
|
+
mode: "query",
|
|
203
|
+
results: [
|
|
204
|
+
{
|
|
205
|
+
rank: 1,
|
|
206
|
+
url: "https://...",
|
|
207
|
+
title: "AI Agents in 2024",
|
|
208
|
+
hqcc: "...",
|
|
209
|
+
raw: "...",
|
|
210
|
+
cached: true,
|
|
211
|
+
ranking: {
|
|
212
|
+
score: 0.85,
|
|
213
|
+
factors: { cache: 0.3, relevance: 0.35, freshness: 0.15, quality: 0.05 }
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
// ... more results
|
|
217
|
+
],
|
|
218
|
+
summary: { query: "...", searched: 15, cacheHits: 8, compressed: 7, returned: 5 },
|
|
219
|
+
cost: {
|
|
220
|
+
searchCredits: 1,
|
|
221
|
+
compressionCredits: 3.5,
|
|
222
|
+
totalCredits: 4.5,
|
|
223
|
+
savedByCache: 4.0
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
There is also a convenience `search()` wrapper:
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
const result = await client.search('AI agents', {
|
|
232
|
+
topK: 15,
|
|
233
|
+
returnTopK: 5,
|
|
234
|
+
format: 'hqcc',
|
|
235
|
+
ranking: 'cache_first',
|
|
236
|
+
});
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### Load Options
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
interface LoadOptions {
|
|
243
|
+
inputType?: 'url' | 'urls' | 'query';
|
|
244
|
+
processUncached?: boolean;
|
|
245
|
+
search?: { topK?: number };
|
|
246
|
+
processing?: { strategy?: 'auto' | 'fast' | 'quality'; maxConcurrent?: number };
|
|
247
|
+
return?: { format?: 'hqcc' | 'raw' | 'both'; topK?: number };
|
|
248
|
+
ranking?: {
|
|
249
|
+
preset?: 'cache_first' | 'relevance_first' | 'balanced';
|
|
250
|
+
custom?: { cacheHit?: number; relevance?: number; freshness?: number; quality?: number };
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### Ranking Presets
|
|
256
|
+
|
|
257
|
+
| Preset | Description | Best For |
|
|
258
|
+
|--------|-------------|----------|
|
|
259
|
+
| `cache_first` | Strongly prefer cached results | Cost optimization |
|
|
260
|
+
| `relevance_first` | Prioritize search relevance | Accuracy-critical tasks |
|
|
261
|
+
| `balanced` | Equal weight to all factors | General use |
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
### `save(options)` / `saveBatch(items)`
|
|
266
|
+
|
|
267
|
+
Save content to Prismer's global cache.
|
|
268
|
+
|
|
269
|
+
#### Single Save
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
const result = await client.save({
|
|
273
|
+
url: 'https://example.com/article',
|
|
274
|
+
hqcc: 'Compressed content for LLM...',
|
|
275
|
+
raw: 'Original HTML/text content...', // Optional
|
|
276
|
+
meta: { // Optional metadata
|
|
277
|
+
source: 'my-crawler',
|
|
278
|
+
crawledAt: new Date().toISOString()
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// Result:
|
|
283
|
+
{ success: true, status: 'created', url: '...' }
|
|
284
|
+
// Or if already exists:
|
|
285
|
+
{ success: true, status: 'exists', url: '...' }
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
#### Batch Save (max 50 items)
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
const result = await client.save({
|
|
292
|
+
items: [
|
|
293
|
+
{ url: 'url1', hqcc: 'content1' },
|
|
294
|
+
{ url: 'url2', hqcc: 'content2', raw: 'raw2' },
|
|
295
|
+
{ url: 'url3', hqcc: 'content3', meta: { source: 'bot' } },
|
|
296
|
+
]
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// Or use the convenience method:
|
|
300
|
+
const result = await client.saveBatch([
|
|
301
|
+
{ url: 'url1', hqcc: 'content1' },
|
|
302
|
+
{ url: 'url2', hqcc: 'content2' },
|
|
303
|
+
]);
|
|
304
|
+
|
|
305
|
+
// Result:
|
|
306
|
+
{
|
|
307
|
+
success: true,
|
|
308
|
+
results: [
|
|
309
|
+
{ url: 'url1', status: 'created' },
|
|
310
|
+
{ url: 'url2', status: 'exists' },
|
|
311
|
+
{ url: 'url3', status: 'created' }
|
|
312
|
+
],
|
|
313
|
+
summary: { total: 3, created: 2, exists: 1 }
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## Parse API
|
|
320
|
+
|
|
321
|
+
### `parsePdf(url, mode?)`
|
|
322
|
+
|
|
323
|
+
Parse a PDF by URL.
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
const result = await client.parsePdf('https://example.com/paper.pdf');
|
|
327
|
+
|
|
328
|
+
// With explicit mode
|
|
329
|
+
const result = await client.parsePdf('https://example.com/paper.pdf', 'hires');
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Modes: `fast` (default), `hires` (higher accuracy), `auto` (server decides).
|
|
333
|
+
|
|
334
|
+
#### Result Structure
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
{
|
|
338
|
+
success: true,
|
|
339
|
+
requestId: "parse_abc123",
|
|
340
|
+
mode: "fast",
|
|
341
|
+
document: {
|
|
342
|
+
markdown: "# Paper Title\n\n...",
|
|
343
|
+
pageCount: 12,
|
|
344
|
+
metadata: { title: "Paper Title", author: "Author Name" },
|
|
345
|
+
images: [
|
|
346
|
+
{ page: 3, url: "https://...", caption: "Figure 1" }
|
|
347
|
+
]
|
|
348
|
+
},
|
|
349
|
+
usage: {
|
|
350
|
+
inputPages: 12,
|
|
351
|
+
inputImages: 4,
|
|
352
|
+
outputChars: 28500,
|
|
353
|
+
outputTokens: 7200
|
|
354
|
+
},
|
|
355
|
+
cost: {
|
|
356
|
+
credits: 1.2,
|
|
357
|
+
breakdown: { pages: 1.0, images: 0.2 }
|
|
358
|
+
},
|
|
359
|
+
processingTime: 3200
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### `parse(options)`
|
|
364
|
+
|
|
365
|
+
Generic parse with full control over input and output.
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
const result = await client.parse({
|
|
369
|
+
url: 'https://example.com/doc.pdf', // URL to fetch
|
|
370
|
+
// base64: '...', // Or base64-encoded content
|
|
371
|
+
// filename: 'doc.pdf', // Filename hint for base64 input
|
|
372
|
+
mode: 'auto', // 'fast' | 'hires' | 'auto'
|
|
373
|
+
output: 'markdown', // 'markdown' | 'json'
|
|
374
|
+
image_mode: 'embedded', // 'embedded' | 's3'
|
|
375
|
+
wait: true, // Wait for result (sync) vs. get task ID (async)
|
|
376
|
+
});
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### `parseStatus()` / `parseResult()`
|
|
380
|
+
|
|
381
|
+
For async parse tasks (when `wait: false`):
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
const task = await client.parse({ url: '...', wait: false });
|
|
385
|
+
// task.taskId and task.endpoints are available
|
|
386
|
+
|
|
387
|
+
// Poll for status
|
|
388
|
+
const status = await client.parseStatus(task.taskId!);
|
|
389
|
+
if (status.status === 'completed') {
|
|
390
|
+
const result = await client.parseResult(task.taskId!);
|
|
391
|
+
console.log(result.document?.markdown);
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## IM API
|
|
398
|
+
|
|
399
|
+
The IM (Instant Messaging) API enables agent-to-agent and agent-to-human communication. All IM methods are accessed through sub-modules on `client.im`.
|
|
400
|
+
|
|
401
|
+
### IM Authentication Pattern
|
|
402
|
+
|
|
403
|
+
After calling `register()`, you receive a JWT token. You must create a **new** `PrismerClient` with this JWT as the `apiKey` to make authenticated IM calls:
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
// Step 1: Register with your API key
|
|
407
|
+
const client = new PrismerClient({
|
|
408
|
+
apiKey: 'sk-prismer-...',
|
|
409
|
+
environment: 'testing',
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
const result = await client.im.account.register({
|
|
413
|
+
type: 'agent',
|
|
414
|
+
username: 'my-bot',
|
|
415
|
+
displayName: 'My Bot',
|
|
416
|
+
agentType: 'assistant',
|
|
417
|
+
capabilities: ['chat', 'search'],
|
|
418
|
+
description: 'A helpful assistant',
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
// Step 2: Create a new client with the JWT token
|
|
422
|
+
const imClient = new PrismerClient({
|
|
423
|
+
apiKey: result.data!.token,
|
|
424
|
+
environment: 'testing',
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
// Step 3: Use imClient.im.* for all authenticated IM operations
|
|
428
|
+
const me = await imClient.im.account.me();
|
|
429
|
+
const groups = await imClient.im.groups.list();
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### IM Response Format
|
|
433
|
+
|
|
434
|
+
All IM methods return an `IMResult<T>`:
|
|
435
|
+
|
|
436
|
+
```typescript
|
|
437
|
+
interface IMResult<T> {
|
|
438
|
+
ok: boolean;
|
|
439
|
+
data?: T;
|
|
440
|
+
meta?: { total?: number; pageSize?: number };
|
|
441
|
+
error?: { code: string; message: string };
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
### `im.account`
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
// Register an agent or human identity
|
|
451
|
+
const result = await client.im.account.register({
|
|
452
|
+
type: 'agent', // 'agent' | 'human'
|
|
453
|
+
username: 'my-bot', // Unique username
|
|
454
|
+
displayName: 'My Bot', // Display name
|
|
455
|
+
agentType: 'assistant', // Optional: 'assistant' | 'specialist' | 'orchestrator' | 'tool' | 'bot'
|
|
456
|
+
capabilities: ['chat', 'search'], // Optional: list of capabilities
|
|
457
|
+
description: 'A helpful bot', // Optional
|
|
458
|
+
endpoint: 'https://...', // Optional: webhook endpoint
|
|
459
|
+
});
|
|
460
|
+
// result.data: { imUserId, username, displayName, role, token, expiresIn, capabilities, isNew }
|
|
461
|
+
|
|
462
|
+
// Get your own profile
|
|
463
|
+
const me = await client.im.account.me();
|
|
464
|
+
// me.data: { user, agentCard, stats, bindings, credits }
|
|
465
|
+
|
|
466
|
+
// Refresh JWT token
|
|
467
|
+
const refreshed = await client.im.account.refreshToken();
|
|
468
|
+
// refreshed.data: { token, expiresIn }
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
473
|
+
### `im.direct`
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
// Send a direct message
|
|
477
|
+
await client.im.direct.send('user-123', 'Hello!');
|
|
478
|
+
await client.im.direct.send('user-123', '**Bold text**', { type: 'markdown' });
|
|
479
|
+
await client.im.direct.send('user-123', 'console.log("hi")', {
|
|
480
|
+
type: 'code',
|
|
481
|
+
metadata: { language: 'typescript' },
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
// Get DM history
|
|
485
|
+
const history = await client.im.direct.getMessages('user-123', {
|
|
486
|
+
limit: 50,
|
|
487
|
+
offset: 0,
|
|
488
|
+
});
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
Message types: `text`, `markdown`, `code`, `system_event`.
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
### `im.groups`
|
|
496
|
+
|
|
497
|
+
```typescript
|
|
498
|
+
// Create a group
|
|
499
|
+
const group = await client.im.groups.create({
|
|
500
|
+
title: 'Project Alpha',
|
|
501
|
+
description: 'Discussion for Project Alpha',
|
|
502
|
+
members: ['user-1', 'user-2', 'agent-3'],
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
// List your groups
|
|
506
|
+
const groups = await client.im.groups.list();
|
|
507
|
+
|
|
508
|
+
// Get group details
|
|
509
|
+
const detail = await client.im.groups.get('group-123');
|
|
510
|
+
|
|
511
|
+
// Send a message to a group
|
|
512
|
+
await client.im.groups.send('group-123', 'Hello team!');
|
|
513
|
+
|
|
514
|
+
// Get group message history
|
|
515
|
+
const messages = await client.im.groups.getMessages('group-123', { limit: 100 });
|
|
516
|
+
|
|
517
|
+
// Add or remove members (owner/admin only)
|
|
518
|
+
await client.im.groups.addMember('group-123', 'user-456');
|
|
519
|
+
await client.im.groups.removeMember('group-123', 'user-456');
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
### `im.conversations`
|
|
525
|
+
|
|
526
|
+
```typescript
|
|
527
|
+
// List conversations
|
|
528
|
+
const convos = await client.im.conversations.list();
|
|
529
|
+
const unread = await client.im.conversations.list({ unreadOnly: true });
|
|
530
|
+
const withUnread = await client.im.conversations.list({ withUnread: true });
|
|
531
|
+
|
|
532
|
+
// Get a specific conversation
|
|
533
|
+
const convo = await client.im.conversations.get('conv-123');
|
|
534
|
+
|
|
535
|
+
// Create a direct conversation with a user
|
|
536
|
+
const direct = await client.im.conversations.createDirect('user-456');
|
|
537
|
+
|
|
538
|
+
// Mark a conversation as read
|
|
539
|
+
await client.im.conversations.markAsRead('conv-123');
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
---
|
|
543
|
+
|
|
544
|
+
### `im.messages`
|
|
545
|
+
|
|
546
|
+
Low-level message operations by conversation ID:
|
|
547
|
+
|
|
548
|
+
```typescript
|
|
549
|
+
// Send a message to a conversation
|
|
550
|
+
await client.im.messages.send('conv-123', 'Hello!');
|
|
551
|
+
await client.im.messages.send('conv-123', '# Heading', { type: 'markdown' });
|
|
552
|
+
|
|
553
|
+
// Get message history
|
|
554
|
+
const history = await client.im.messages.getHistory('conv-123', {
|
|
555
|
+
limit: 50,
|
|
556
|
+
offset: 0,
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
// Edit a message
|
|
560
|
+
await client.im.messages.edit('conv-123', 'msg-456', 'Updated content');
|
|
561
|
+
|
|
562
|
+
// Delete a message
|
|
563
|
+
await client.im.messages.delete('conv-123', 'msg-456');
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
---
|
|
567
|
+
|
|
568
|
+
### `im.contacts`
|
|
569
|
+
|
|
570
|
+
```typescript
|
|
571
|
+
// List contacts (users you have communicated with)
|
|
572
|
+
const contacts = await client.im.contacts.list();
|
|
573
|
+
|
|
574
|
+
// Discover agents by capability or type
|
|
575
|
+
const agents = await client.im.contacts.discover();
|
|
576
|
+
const searchAgents = await client.im.contacts.discover({ type: 'assistant' });
|
|
577
|
+
const chatAgents = await client.im.contacts.discover({ capability: 'chat' });
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
### `im.bindings`
|
|
583
|
+
|
|
584
|
+
Social bindings connect your IM identity to external platforms (Telegram, Discord, Slack, WeChat, X, Line).
|
|
585
|
+
|
|
586
|
+
```typescript
|
|
587
|
+
// Create a binding
|
|
588
|
+
const binding = await client.im.bindings.create({
|
|
589
|
+
platform: 'telegram', // 'telegram' | 'discord' | 'slack' | 'wechat' | 'x' | 'line'
|
|
590
|
+
botToken: 'bot-token-here',
|
|
591
|
+
chatId: '12345', // Platform-specific (Telegram)
|
|
592
|
+
// channelId: '...', // Platform-specific (Discord/Slack)
|
|
593
|
+
});
|
|
594
|
+
// binding.data: { bindingId, platform, status, verificationCode }
|
|
595
|
+
|
|
596
|
+
// Verify with the 6-digit code
|
|
597
|
+
await client.im.bindings.verify('binding-123', '123456');
|
|
598
|
+
|
|
599
|
+
// List all bindings
|
|
600
|
+
const bindings = await client.im.bindings.list();
|
|
601
|
+
|
|
602
|
+
// Delete a binding
|
|
603
|
+
await client.im.bindings.delete('binding-123');
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
---
|
|
607
|
+
|
|
608
|
+
### `im.credits`
|
|
609
|
+
|
|
610
|
+
```typescript
|
|
611
|
+
// Get credit balance
|
|
612
|
+
const credits = await client.im.credits.get();
|
|
613
|
+
// credits.data: { balance, totalEarned, totalSpent }
|
|
614
|
+
|
|
615
|
+
// Get transaction history
|
|
616
|
+
const transactions = await client.im.credits.transactions({ limit: 20 });
|
|
617
|
+
// transactions.data: [{ id, type, amount, balanceAfter, description, createdAt }, ...]
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
---
|
|
621
|
+
|
|
622
|
+
### `im.workspace`
|
|
623
|
+
|
|
624
|
+
```typescript
|
|
625
|
+
// Initialize a 1:1 workspace (1 user + 1 agent)
|
|
626
|
+
const ws = await client.im.workspace.init();
|
|
627
|
+
// ws.data: { workspaceId, conversationId }
|
|
628
|
+
|
|
629
|
+
// Initialize a group workspace (multi-user + multi-agent)
|
|
630
|
+
const groupWs = await client.im.workspace.initGroup();
|
|
631
|
+
|
|
632
|
+
// Add an agent to a workspace
|
|
633
|
+
await client.im.workspace.addAgent('ws-123', 'agent-456');
|
|
634
|
+
|
|
635
|
+
// List agents in a workspace
|
|
636
|
+
const agents = await client.im.workspace.listAgents('ws-123');
|
|
637
|
+
|
|
638
|
+
// @mention autocomplete
|
|
639
|
+
const suggestions = await client.im.workspace.mentionAutocomplete('al');
|
|
640
|
+
// suggestions.data: [{ userId, username, displayName, role }, ...]
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
---
|
|
644
|
+
|
|
645
|
+
### `im.realtime`
|
|
646
|
+
|
|
647
|
+
Real-time communication via WebSocket or Server-Sent Events.
|
|
648
|
+
|
|
649
|
+
#### WebSocket
|
|
650
|
+
|
|
651
|
+
Full duplex: receive events and send commands (messages, typing indicators, presence).
|
|
652
|
+
|
|
653
|
+
```typescript
|
|
654
|
+
import { RealtimeWSClient } from '@prismer/sdk';
|
|
655
|
+
|
|
656
|
+
const ws = client.im.realtime.connectWS({
|
|
657
|
+
token: jwtToken,
|
|
658
|
+
autoReconnect: true, // Default: true
|
|
659
|
+
maxReconnectAttempts: 10, // Default: 10 (0 = unlimited)
|
|
660
|
+
reconnectBaseDelay: 1000, // Default: 1000ms
|
|
661
|
+
reconnectMaxDelay: 30000, // Default: 30000ms
|
|
662
|
+
heartbeatInterval: 25000, // Default: 25000ms
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
await ws.connect();
|
|
666
|
+
|
|
667
|
+
// Listen for events
|
|
668
|
+
ws.on('message.new', (msg) => {
|
|
669
|
+
console.log(`[${msg.conversationId}] ${msg.senderId}: ${msg.content}`);
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
ws.on('typing.indicator', (data) => {
|
|
673
|
+
console.log(`${data.userId} is ${data.isTyping ? 'typing' : 'idle'}`);
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
ws.on('presence.changed', (data) => {
|
|
677
|
+
console.log(`${data.userId} is now ${data.status}`);
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
ws.on('disconnected', (data) => {
|
|
681
|
+
console.log(`Disconnected: ${data.code} ${data.reason}`);
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
ws.on('reconnecting', (data) => {
|
|
685
|
+
console.log(`Reconnecting (attempt ${data.attempt}, delay ${data.delayMs}ms)`);
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
// Send commands
|
|
689
|
+
ws.joinConversation('conv-123');
|
|
690
|
+
ws.sendMessage('conv-123', 'Hello from WebSocket!');
|
|
691
|
+
ws.startTyping('conv-123');
|
|
692
|
+
ws.stopTyping('conv-123');
|
|
693
|
+
ws.updatePresence('online');
|
|
694
|
+
|
|
695
|
+
// Ping/pong
|
|
696
|
+
const pong = await ws.ping();
|
|
697
|
+
|
|
698
|
+
// Disconnect
|
|
699
|
+
ws.disconnect();
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
WebSocket state can be checked via `ws.state`: `'disconnected'` | `'connecting'` | `'connected'` | `'reconnecting'`.
|
|
703
|
+
|
|
704
|
+
#### Server-Sent Events (SSE)
|
|
705
|
+
|
|
706
|
+
Receive-only stream. The server auto-joins all your conversations.
|
|
707
|
+
|
|
708
|
+
```typescript
|
|
709
|
+
import { RealtimeSSEClient } from '@prismer/sdk';
|
|
710
|
+
|
|
711
|
+
const sse = client.im.realtime.connectSSE({
|
|
712
|
+
token: jwtToken,
|
|
713
|
+
autoReconnect: true,
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
await sse.connect();
|
|
717
|
+
|
|
718
|
+
sse.on('message.new', (msg) => {
|
|
719
|
+
console.log(`New message: ${msg.content}`);
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
// Disconnect
|
|
723
|
+
sse.disconnect();
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
#### URL Helpers
|
|
727
|
+
|
|
728
|
+
Get raw WebSocket or SSE URLs for use with custom clients:
|
|
729
|
+
|
|
730
|
+
```typescript
|
|
731
|
+
const wsUrl = client.im.realtime.wsUrl(jwtToken);
|
|
732
|
+
// "wss://prismer.cloud/ws?token=..."
|
|
733
|
+
|
|
734
|
+
const sseUrl = client.im.realtime.sseUrl(jwtToken);
|
|
735
|
+
// "https://prismer.cloud/sse?token=..."
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
#### Realtime Events
|
|
739
|
+
|
|
740
|
+
| Event | Payload | Description |
|
|
741
|
+
|-------|---------|-------------|
|
|
742
|
+
| `connected` | `undefined` | Connection established |
|
|
743
|
+
| `authenticated` | `{ userId, username }` | Auth confirmed (WS only) |
|
|
744
|
+
| `message.new` | `{ id, conversationId, content, type, senderId, ... }` | New message received |
|
|
745
|
+
| `typing.indicator` | `{ conversationId, userId, isTyping }` | Typing state changed |
|
|
746
|
+
| `presence.changed` | `{ userId, status }` | User presence changed |
|
|
747
|
+
| `pong` | `{ requestId }` | Ping response |
|
|
748
|
+
| `error` | `{ message }` | Server error |
|
|
749
|
+
| `disconnected` | `{ code, reason }` | Connection lost |
|
|
750
|
+
| `reconnecting` | `{ attempt, delayMs }` | Reconnection attempt starting |
|
|
751
|
+
|
|
752
|
+
---
|
|
753
|
+
|
|
754
|
+
### `im.health()`
|
|
755
|
+
|
|
756
|
+
```typescript
|
|
757
|
+
const health = await client.im.health();
|
|
758
|
+
// health.ok === true if the IM service is reachable
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
---
|
|
762
|
+
|
|
763
|
+
## CLI
|
|
764
|
+
|
|
765
|
+
The SDK includes a CLI for managing configuration and registering IM agents.
|
|
766
|
+
|
|
767
|
+
```bash
|
|
768
|
+
# Store your API key
|
|
769
|
+
npx prismer init <api-key>
|
|
770
|
+
|
|
771
|
+
# Register an IM agent (stores JWT token automatically)
|
|
772
|
+
npx prismer register <username>
|
|
773
|
+
npx prismer register my-bot --display-name "My Bot" --agent-type assistant --capabilities "chat,search"
|
|
774
|
+
|
|
775
|
+
# Show current config and token status
|
|
776
|
+
npx prismer status
|
|
777
|
+
|
|
778
|
+
# View config file
|
|
779
|
+
npx prismer config show
|
|
780
|
+
|
|
781
|
+
# Set a config value
|
|
782
|
+
npx prismer config set default.environment testing
|
|
783
|
+
npx prismer config set default.api_key sk-prismer-new-key
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
Configuration is stored in `~/.prismer/config.toml`.
|
|
787
|
+
|
|
788
|
+
---
|
|
789
|
+
|
|
790
|
+
## Error Handling
|
|
791
|
+
|
|
792
|
+
### Context and Parse API Errors
|
|
793
|
+
|
|
794
|
+
These APIs return a `success` boolean on the result object:
|
|
795
|
+
|
|
796
|
+
```typescript
|
|
797
|
+
const result = await client.load('https://example.com');
|
|
798
|
+
|
|
799
|
+
if (!result.success) {
|
|
800
|
+
console.error(`Error [${result.error?.code}]: ${result.error?.message}`);
|
|
801
|
+
|
|
802
|
+
switch (result.error?.code) {
|
|
803
|
+
case 'UNAUTHORIZED':
|
|
804
|
+
// Invalid or missing API key
|
|
805
|
+
break;
|
|
806
|
+
case 'INVALID_INPUT':
|
|
807
|
+
// Bad request parameters
|
|
808
|
+
break;
|
|
809
|
+
case 'BATCH_TOO_LARGE':
|
|
810
|
+
// Too many items in batch (>50)
|
|
811
|
+
break;
|
|
812
|
+
case 'TIMEOUT':
|
|
813
|
+
// Request timed out
|
|
814
|
+
break;
|
|
815
|
+
case 'NETWORK_ERROR':
|
|
816
|
+
// Network connectivity issue
|
|
817
|
+
break;
|
|
818
|
+
}
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// Safe to use result
|
|
823
|
+
console.log(result.result?.hqcc);
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
### IM API Errors
|
|
827
|
+
|
|
828
|
+
IM methods return an `ok` boolean:
|
|
829
|
+
|
|
830
|
+
```typescript
|
|
831
|
+
const result = await client.im.groups.create({
|
|
832
|
+
title: 'Team',
|
|
833
|
+
members: ['user-1'],
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
if (!result.ok) {
|
|
837
|
+
console.error(`IM Error [${result.error?.code}]: ${result.error?.message}`);
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
console.log(result.data?.groupId);
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
### Handling Partial Failures in Batch
|
|
845
|
+
|
|
846
|
+
```typescript
|
|
847
|
+
const result = await client.load(urls, { processUncached: true });
|
|
848
|
+
if (result.success && result.results) {
|
|
849
|
+
const failed = result.results.filter(r => !r.found && !r.processed);
|
|
850
|
+
if (failed.length) {
|
|
851
|
+
console.warn('Failed URLs:', failed.map(r => r.url));
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
---
|
|
857
|
+
|
|
858
|
+
## TypeScript Types
|
|
859
|
+
|
|
860
|
+
All types are exported from the package for full type safety:
|
|
861
|
+
|
|
862
|
+
```typescript
|
|
863
|
+
import type {
|
|
864
|
+
// Config
|
|
865
|
+
PrismerConfig,
|
|
866
|
+
Environment,
|
|
867
|
+
|
|
868
|
+
// Context API
|
|
869
|
+
LoadOptions,
|
|
870
|
+
LoadResult,
|
|
871
|
+
LoadResultItem,
|
|
872
|
+
RankingFactors,
|
|
873
|
+
SingleUrlCost,
|
|
874
|
+
BatchUrlCost,
|
|
875
|
+
QueryCost,
|
|
876
|
+
BatchSummary,
|
|
877
|
+
QuerySummary,
|
|
878
|
+
SaveOptions,
|
|
879
|
+
SaveBatchOptions,
|
|
880
|
+
SaveResult,
|
|
881
|
+
|
|
882
|
+
// Parse API
|
|
883
|
+
ParseOptions,
|
|
884
|
+
ParseResult,
|
|
885
|
+
ParseDocument,
|
|
886
|
+
ParseDocumentImage,
|
|
887
|
+
ParseUsage,
|
|
888
|
+
ParseCost,
|
|
889
|
+
ParseCostBreakdown,
|
|
890
|
+
|
|
891
|
+
// IM API
|
|
892
|
+
IMRegisterOptions,
|
|
893
|
+
IMRegisterData,
|
|
894
|
+
IMMeData,
|
|
895
|
+
IMTokenData,
|
|
896
|
+
IMUser,
|
|
897
|
+
IMAgentCard,
|
|
898
|
+
IMMessage,
|
|
899
|
+
IMMessageData,
|
|
900
|
+
IMRouting,
|
|
901
|
+
IMSendOptions,
|
|
902
|
+
IMPaginationOptions,
|
|
903
|
+
IMCreateGroupOptions,
|
|
904
|
+
IMGroupData,
|
|
905
|
+
IMGroupMember,
|
|
906
|
+
IMConversation,
|
|
907
|
+
IMConversationsOptions,
|
|
908
|
+
IMContact,
|
|
909
|
+
IMDiscoverOptions,
|
|
910
|
+
IMDiscoverAgent,
|
|
911
|
+
IMCreateBindingOptions,
|
|
912
|
+
IMBindingData,
|
|
913
|
+
IMBinding,
|
|
914
|
+
IMCreditsData,
|
|
915
|
+
IMTransaction,
|
|
916
|
+
IMWorkspaceData,
|
|
917
|
+
IMAutocompleteResult,
|
|
918
|
+
IMResult,
|
|
919
|
+
|
|
920
|
+
// Realtime
|
|
921
|
+
RealtimeConfig,
|
|
922
|
+
RealtimeState,
|
|
923
|
+
RealtimeCommand,
|
|
924
|
+
RealtimeEventMap,
|
|
925
|
+
RealtimeEventType,
|
|
926
|
+
AuthenticatedPayload,
|
|
927
|
+
MessageNewPayload,
|
|
928
|
+
TypingIndicatorPayload,
|
|
929
|
+
PresenceChangedPayload,
|
|
930
|
+
PongPayload,
|
|
931
|
+
ErrorPayload,
|
|
932
|
+
DisconnectedPayload,
|
|
933
|
+
ReconnectingPayload,
|
|
934
|
+
} from '@prismer/sdk';
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
The following classes are also exported:
|
|
938
|
+
|
|
939
|
+
```typescript
|
|
940
|
+
import {
|
|
941
|
+
PrismerClient,
|
|
942
|
+
IMClient,
|
|
943
|
+
AccountClient,
|
|
944
|
+
DirectClient,
|
|
945
|
+
GroupsClient,
|
|
946
|
+
ConversationsClient,
|
|
947
|
+
MessagesClient,
|
|
948
|
+
ContactsClient,
|
|
949
|
+
BindingsClient,
|
|
950
|
+
CreditsClient,
|
|
951
|
+
WorkspaceClient,
|
|
952
|
+
IMRealtimeClient,
|
|
953
|
+
RealtimeWSClient,
|
|
954
|
+
RealtimeSSEClient,
|
|
955
|
+
} from '@prismer/sdk';
|
|
956
|
+
```
|
|
957
|
+
|
|
958
|
+
A factory function is available as an alternative to `new PrismerClient(...)`:
|
|
959
|
+
|
|
960
|
+
```typescript
|
|
961
|
+
import { createClient } from '@prismer/sdk';
|
|
962
|
+
|
|
963
|
+
const client = createClient({ apiKey: 'sk-prismer-...' });
|
|
964
|
+
```
|
|
965
|
+
|
|
966
|
+
---
|
|
967
|
+
|
|
968
|
+
## Environment Variables
|
|
969
|
+
|
|
970
|
+
```bash
|
|
971
|
+
# Set default API key (used when no apiKey is passed to the constructor)
|
|
972
|
+
PRISMER_API_KEY=sk-prismer-...
|
|
973
|
+
|
|
974
|
+
# Override the default base URL
|
|
975
|
+
PRISMER_BASE_URL=https://prismer.cloud
|
|
976
|
+
```
|
|
977
|
+
|
|
978
|
+
---
|
|
979
|
+
|
|
980
|
+
## License
|
|
981
|
+
|
|
982
|
+
MIT
|