@arbidocs/sdk 0.3.16 → 0.3.18
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 +58 -81
- package/dist/{browser-DFRwcoc1.d.cts → browser-DUQ3Eyvd.d.cts} +91 -5
- package/dist/{browser-DFRwcoc1.d.ts → browser-DUQ3Eyvd.d.ts} +91 -5
- package/dist/browser.cjs +81 -1
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +78 -2
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +247 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -3
- package/dist/index.d.ts +66 -3
- package/dist/index.js +241 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,130 +1,107 @@
|
|
|
1
1
|
# @arbidocs/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript SDK for the ARBI platform. Handles authentication, workspace encryption, and streaming AI queries.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Quickstart
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install @arbidocs/sdk
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
For Node.js, also install the IndexedDB polyfill:
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
npm install fake-indexeddb
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Quick Start
|
|
18
|
-
|
|
19
11
|
```typescript
|
|
20
|
-
import '
|
|
21
|
-
import { Arbi } from '@arbidocs/sdk'
|
|
12
|
+
import { Arbi } from '@arbidocs/sdk/browser'
|
|
22
13
|
|
|
23
|
-
const arbi = new Arbi({ url: 'https://
|
|
14
|
+
const arbi = new Arbi({ url: 'https://www.arbidocs.com' })
|
|
24
15
|
|
|
25
|
-
// Login
|
|
16
|
+
// Login and select a workspace
|
|
26
17
|
await arbi.login('user@example.com', 'password')
|
|
27
|
-
|
|
28
|
-
// Pick a workspace
|
|
29
18
|
const workspaces = await arbi.workspaces.list()
|
|
30
19
|
await arbi.selectWorkspace(workspaces[0].external_id)
|
|
31
20
|
|
|
32
|
-
//
|
|
21
|
+
// Ask a streaming question about your documents
|
|
33
22
|
const docs = await arbi.documents.list()
|
|
34
|
-
|
|
35
|
-
const conversations = await arbi.conversations.list()
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Streaming AI Queries
|
|
39
|
-
|
|
40
|
-
```typescript
|
|
41
|
-
const result = await arbi.assistant.query('What does section 3 say?', {
|
|
23
|
+
await arbi.assistant.query('Summarize this document', {
|
|
42
24
|
docIds: [docs[0].external_id],
|
|
43
25
|
onToken: (token) => process.stdout.write(token),
|
|
44
|
-
onStreamStart: ({ assistant_message_ext_id }) => {
|
|
45
|
-
console.log('Stream started:', assistant_message_ext_id)
|
|
46
|
-
},
|
|
47
|
-
onComplete: () => console.log('\nDone'),
|
|
48
26
|
})
|
|
49
27
|
```
|
|
50
28
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
After login, the SDK automatically persists your signing key (encrypted) in IndexedDB. You can also recover a session using the raw private key:
|
|
29
|
+
For Node.js, install `fake-indexeddb` and import it first:
|
|
54
30
|
|
|
55
31
|
```typescript
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// Later, recover without password:
|
|
60
|
-
await arbi.loginWithKey('user@example.com', signingKeyBase64)
|
|
32
|
+
import 'fake-indexeddb/auto'
|
|
33
|
+
import { Arbi } from '@arbidocs/sdk'
|
|
61
34
|
```
|
|
62
35
|
|
|
63
|
-
##
|
|
64
|
-
|
|
65
|
-
### Constructor
|
|
36
|
+
## Lifecycle
|
|
66
37
|
|
|
67
38
|
```typescript
|
|
68
|
-
const arbi = new Arbi({
|
|
69
|
-
url: 'https://arbi.mycompany.com', // Required: backend URL
|
|
70
|
-
deploymentDomain: 'arbi.mycompany.com', // Optional: defaults to URL hostname
|
|
71
|
-
credentials: 'omit', // Optional: 'omit' | 'include' | 'same-origin'
|
|
72
|
-
})
|
|
73
|
-
```
|
|
39
|
+
const arbi = new Arbi({ url: 'https://www.arbidocs.com' })
|
|
74
40
|
|
|
75
|
-
|
|
41
|
+
await arbi.login(email, password) // or arbi.loginWithKey(email, keyBase64)
|
|
42
|
+
await arbi.selectWorkspace(workspaceId)
|
|
43
|
+
// ... use the SDK ...
|
|
44
|
+
await arbi.logout()
|
|
45
|
+
```
|
|
76
46
|
|
|
77
|
-
|
|
|
78
|
-
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `selectWorkspace(workspaceId)` | Select a workspace (decrypts workspace key) |
|
|
82
|
-
| `logout()` | Log out and securely clear key material |
|
|
47
|
+
| Property | Description |
|
|
48
|
+
|----------|-------------|
|
|
49
|
+
| `arbi.isLoggedIn` | Whether the user is authenticated |
|
|
50
|
+
| `arbi.hasWorkspace` | Whether a workspace is selected |
|
|
83
51
|
|
|
84
|
-
|
|
52
|
+
## Operations
|
|
85
53
|
|
|
86
|
-
|
|
|
87
|
-
|
|
88
|
-
| `
|
|
89
|
-
| `
|
|
54
|
+
| Namespace | Key methods |
|
|
55
|
+
|-----------|-------------|
|
|
56
|
+
| `arbi.workspaces` | `list()`, `create()`, `update()`, `delete()`, `listUsers()`, `addUsers()`, `removeUsers()` |
|
|
57
|
+
| `arbi.documents` | `list()`, `get()`, `uploadFile()`, `uploadUrl()`, `update()`, `delete()`, `download()` |
|
|
58
|
+
| `arbi.conversations` | `list()`, `getThreads()`, `updateTitle()`, `share()`, `delete()` |
|
|
59
|
+
| `arbi.assistant` | `query(question, options)`, `retrieve(query, docIds)`, `respond(messageId, answer)` |
|
|
60
|
+
| `arbi.tags` | `list()`, `create()`, `update()`, `delete()` |
|
|
61
|
+
| `arbi.doctags` | `assign()`, `remove()`, `generate()` |
|
|
62
|
+
| `arbi.contacts` | `list()`, `add()`, `remove()` |
|
|
63
|
+
| `arbi.health` | `check()`, `models()`, `mcpTools()` |
|
|
90
64
|
|
|
91
|
-
|
|
65
|
+
## Streaming AI queries
|
|
92
66
|
|
|
93
|
-
|
|
67
|
+
```typescript
|
|
68
|
+
const result = await arbi.assistant.query('What does section 3 say?', {
|
|
69
|
+
docIds: [docId],
|
|
70
|
+
previousResponseId: lastMessageId, // for multi-turn conversations
|
|
71
|
+
onToken: (token) => { /* append to UI */ },
|
|
72
|
+
onStreamStart: ({ assistant_message_ext_id }) => { /* save for follow-ups */ },
|
|
73
|
+
onAgentStep: (step) => { /* agent tool usage */ },
|
|
74
|
+
onError: (message) => { /* handle error */ },
|
|
75
|
+
onComplete: () => { /* done */ },
|
|
76
|
+
})
|
|
94
77
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
| `arbi.documents` | `list()`, `get()`, `upload()`, `update()`, `delete()` |
|
|
99
|
-
| `arbi.conversations` | `list()`, `getThreads()`, `updateTitle()`, `share()`, `delete()` |
|
|
100
|
-
| `arbi.assistant` | `query(question, options)`, `retrieve(messageExtId)` |
|
|
101
|
-
| `arbi.tags` | `list()`, `create()`, `update()`, `delete()` |
|
|
102
|
-
| `arbi.doctags` | `assign()`, `remove()` |
|
|
103
|
-
| `arbi.contacts` | `list()`, `search()` |
|
|
104
|
-
| `arbi.health` | `check()` |
|
|
78
|
+
// result.text — full accumulated response
|
|
79
|
+
// result.assistantMessageExtId — use as previousResponseId for follow-ups
|
|
80
|
+
```
|
|
105
81
|
|
|
106
|
-
|
|
82
|
+
## Session recovery
|
|
107
83
|
|
|
108
|
-
|
|
84
|
+
The SDK persists the signing key (encrypted) in IndexedDB. Recover a session without a password:
|
|
109
85
|
|
|
110
86
|
```typescript
|
|
111
|
-
|
|
87
|
+
await arbi.loginWithKey('user@example.com', signingKeyBase64)
|
|
112
88
|
```
|
|
113
89
|
|
|
90
|
+
The SDK also auto-recovers on 401 responses using the stored key.
|
|
91
|
+
|
|
114
92
|
## Security
|
|
115
93
|
|
|
116
|
-
- **Zero-knowledge auth
|
|
117
|
-
- **E2E workspace encryption
|
|
118
|
-
- **Encrypted key storage
|
|
119
|
-
- **Key zeroing on logout
|
|
94
|
+
- **Zero-knowledge auth** — passwords never leave the client
|
|
95
|
+
- **E2E workspace encryption** — symmetric keys wrapped with your public key
|
|
96
|
+
- **Encrypted key storage** — private keys in IndexedDB encrypted with non-extractable AES-GCM
|
|
97
|
+
- **Key zeroing on logout** — signing and session keys scrubbed from memory
|
|
120
98
|
|
|
121
|
-
##
|
|
99
|
+
## React
|
|
122
100
|
|
|
123
|
-
|
|
124
|
-
- **[React Chat App](../../examples/react-chat/)** — Login form, workspace selector, document picker, streaming chat
|
|
101
|
+
For React apps, use `@arbidocs/react` instead — it wraps this SDK with hooks and a context provider. See the [@arbidocs/react README](../arbi-react/README.md).
|
|
125
102
|
|
|
126
103
|
## Requirements
|
|
127
104
|
|
|
128
105
|
- **Browser**: Any modern browser with Web Crypto API
|
|
129
|
-
- **Node.js**: v18+ (
|
|
106
|
+
- **Node.js**: v18+ (install `fake-indexeddb`)
|
|
130
107
|
- **TypeScript**: 5.0+ (optional)
|
|
@@ -92,6 +92,8 @@ interface CliCredentials {
|
|
|
92
92
|
workspaceId?: string;
|
|
93
93
|
/** ISO timestamp when the token was cached */
|
|
94
94
|
tokenTimestamp?: string;
|
|
95
|
+
/** Auth0 SSO token — needed for session recovery of SSO users */
|
|
96
|
+
ssoToken?: string;
|
|
95
97
|
}
|
|
96
98
|
interface ChatSession {
|
|
97
99
|
/** Last assistant message ID — used as previous_response_id for follow-ups */
|
|
@@ -114,6 +116,10 @@ interface ConfigStore {
|
|
|
114
116
|
saveChatSession(session: ChatSession): void;
|
|
115
117
|
updateChatSession(updates: Partial<ChatSession>): void;
|
|
116
118
|
clearChatSession(): void;
|
|
119
|
+
/** Persist last response metadata for citation browsing (optional). */
|
|
120
|
+
saveLastMetadata?(metadata: unknown): void;
|
|
121
|
+
/** Load last response metadata for citation browsing (optional). */
|
|
122
|
+
loadLastMetadata?(): unknown | null;
|
|
117
123
|
}
|
|
118
124
|
|
|
119
125
|
/**
|
|
@@ -169,6 +175,17 @@ declare function createAuthenticatedClient(config: CliConfig, creds: CliCredenti
|
|
|
169
175
|
* use createAuthenticatedClient() instead.
|
|
170
176
|
*/
|
|
171
177
|
declare function performPasswordLogin(config: CliConfig, email: string, password: string, store: ConfigStore): Promise<AuthContext>;
|
|
178
|
+
/**
|
|
179
|
+
* SSO device-flow login (RFC 8628).
|
|
180
|
+
*
|
|
181
|
+
* Fetches SSO config from the deployment, initiates the device authorization
|
|
182
|
+
* flow with Auth0, waits for the user to authorize in a browser, then logs
|
|
183
|
+
* in to the ARBI deployment using the Auth0 JWT.
|
|
184
|
+
*/
|
|
185
|
+
declare function performSsoDeviceFlowLogin(config: CliConfig, email: string, password: string, store: ConfigStore, callbacks?: {
|
|
186
|
+
onUserCode?: (userCode: string, verificationUri: string) => void;
|
|
187
|
+
onPoll?: (elapsedMs: number) => void;
|
|
188
|
+
}): Promise<AuthContext>;
|
|
172
189
|
/**
|
|
173
190
|
* Decrypt wrapped workspace key and set it as the active workspace header.
|
|
174
191
|
*/
|
|
@@ -219,7 +236,7 @@ type UserInputRequestEvent = components['schemas']['UserInputRequestEvent'];
|
|
|
219
236
|
type ArtifactEvent = components['schemas']['ArtifactEvent'];
|
|
220
237
|
type UserMessageEvent = components['schemas']['UserMessageEvent'];
|
|
221
238
|
type MessageQueuedEvent = components['schemas']['MessageQueuedEvent'];
|
|
222
|
-
type MessageMetadataPayload = components['schemas']['MessageMetadataPayload'];
|
|
239
|
+
type MessageMetadataPayload$1 = components['schemas']['MessageMetadataPayload'];
|
|
223
240
|
type ResponseUsage = components['schemas']['ResponseUsage'];
|
|
224
241
|
type OutputTokensDetails = components['schemas']['OutputTokensDetails'];
|
|
225
242
|
type TokenBudgetContext = components['schemas']['TokenBudgetContext'];
|
|
@@ -276,7 +293,7 @@ interface SSEStreamCallbacks {
|
|
|
276
293
|
onError?: (message: string) => void;
|
|
277
294
|
onMessageQueued?: (data: MessageQueuedEvent) => void;
|
|
278
295
|
onUserMessage?: (data: UserMessageEvent) => void;
|
|
279
|
-
onMetadata?: (data: MessageMetadataPayload) => void;
|
|
296
|
+
onMetadata?: (data: MessageMetadataPayload$1) => void;
|
|
280
297
|
onUserInputRequest?: (data: UserInputRequestEvent) => void;
|
|
281
298
|
onArtifact?: (data: ArtifactEvent) => void;
|
|
282
299
|
onElapsedTime?: (t: number) => void;
|
|
@@ -294,7 +311,7 @@ interface SSEStreamResult {
|
|
|
294
311
|
toolCallCount: number;
|
|
295
312
|
errors: string[];
|
|
296
313
|
userMessage: UserMessageEvent | null;
|
|
297
|
-
metadata: MessageMetadataPayload | null;
|
|
314
|
+
metadata: MessageMetadataPayload$1 | null;
|
|
298
315
|
artifacts: ArtifactEvent[];
|
|
299
316
|
usage: ResponseUsage | null;
|
|
300
317
|
/** Token budget context snapshot from response.completed. */
|
|
@@ -310,6 +327,15 @@ interface SSEStreamResult {
|
|
|
310
327
|
* both the streaming callbacks and the final result.
|
|
311
328
|
*/
|
|
312
329
|
declare function streamSSE(response: Response, callbacks?: SSEStreamCallbacks): Promise<SSEStreamResult>;
|
|
330
|
+
/**
|
|
331
|
+
* Format a human-readable summary line from a completed SSE stream result.
|
|
332
|
+
*
|
|
333
|
+
* Returns a string like:
|
|
334
|
+
* "3 steps (2 tool calls) · 1,234 tokens · 500/8,000 context · 2.5s"
|
|
335
|
+
*
|
|
336
|
+
* Returns empty string if there's nothing to report.
|
|
337
|
+
*/
|
|
338
|
+
declare function formatStreamSummary(result: SSEStreamResult, elapsedTime?: number | null): string;
|
|
313
339
|
/**
|
|
314
340
|
* Consume an entire SSE stream without streaming callbacks.
|
|
315
341
|
* Convenience alias for `streamSSE(response)`.
|
|
@@ -426,6 +452,66 @@ type UserInfo = {
|
|
|
426
452
|
*/
|
|
427
453
|
declare function formatUserName(user: UserInfo | null | undefined): string;
|
|
428
454
|
|
|
455
|
+
/**
|
|
456
|
+
* Citation resolution utilities — shared by CLI and TUI.
|
|
457
|
+
*
|
|
458
|
+
* Parses citation data from SSE metadata (`MessageMetadataPayload`) and
|
|
459
|
+
* resolves chunk references into displayable citation summaries and passages.
|
|
460
|
+
*
|
|
461
|
+
* Citation data flow:
|
|
462
|
+
* 1. `tools.model_citations.tool_responses` maps citation number → CitationData
|
|
463
|
+
* (contains chunk_ids, statement, offsets)
|
|
464
|
+
* 2. `tools.retrieval_chunk.tool_responses` and `tools.retrieval_full_context.tool_responses`
|
|
465
|
+
* map document file name → Chunk[] (contains content and metadata)
|
|
466
|
+
* 3. This module joins those two data sets to produce resolved citations.
|
|
467
|
+
*/
|
|
468
|
+
|
|
469
|
+
type MessageMetadataPayload = components['schemas']['MessageMetadataPayload'];
|
|
470
|
+
type CitationData$2 = components['schemas']['CitationData'];
|
|
471
|
+
type Chunk$1 = components['schemas']['Chunk'];
|
|
472
|
+
/** A fully resolved citation with its source chunks. */
|
|
473
|
+
interface ResolvedCitation {
|
|
474
|
+
/** Citation number as a string (e.g. "1", "2") */
|
|
475
|
+
citationNum: string;
|
|
476
|
+
/** Raw citation data from model_citations */
|
|
477
|
+
citationData: CitationData$2;
|
|
478
|
+
/** Resolved chunks matching the citation's chunk_ids */
|
|
479
|
+
chunks: Chunk$1[];
|
|
480
|
+
}
|
|
481
|
+
/** A compact citation summary for display in lists. */
|
|
482
|
+
interface CitationSummary {
|
|
483
|
+
citationNum: string;
|
|
484
|
+
statement: string;
|
|
485
|
+
docTitle: string;
|
|
486
|
+
pageNumber: number | null;
|
|
487
|
+
chunkCount: number;
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Resolve all citations from SSE metadata into full citation objects.
|
|
491
|
+
*
|
|
492
|
+
* Reads `tools.model_citations.tool_responses` for citation→chunk_id mappings,
|
|
493
|
+
* then builds a chunk lookup from `retrieval_chunk` and `retrieval_full_context`
|
|
494
|
+
* tool responses to resolve each chunk_id to its full Chunk object.
|
|
495
|
+
*
|
|
496
|
+
* Returns citations sorted by citation number (ascending).
|
|
497
|
+
*/
|
|
498
|
+
declare function resolveCitations(metadata: MessageMetadataPayload | null): ResolvedCitation[];
|
|
499
|
+
/**
|
|
500
|
+
* Produce compact summaries for display in citation lists.
|
|
501
|
+
* Uses the first chunk of each citation for doc title and page number.
|
|
502
|
+
*/
|
|
503
|
+
declare function summarizeCitations(resolved: ResolvedCitation[]): CitationSummary[];
|
|
504
|
+
/**
|
|
505
|
+
* Count the number of citations in metadata.
|
|
506
|
+
* Returns 0 if metadata is null or has no citations.
|
|
507
|
+
*/
|
|
508
|
+
declare function countCitations(metadata: MessageMetadataPayload | null): number;
|
|
509
|
+
/**
|
|
510
|
+
* Convert citation markdown to plain text with superscript-style numbers.
|
|
511
|
+
* Replaces `[text](#cite-N)` with `text[N]`.
|
|
512
|
+
*/
|
|
513
|
+
declare function stripCitationMarkdown(text: string): string;
|
|
514
|
+
|
|
429
515
|
/**
|
|
430
516
|
* Document operations — browser-safe functions.
|
|
431
517
|
*
|
|
@@ -909,7 +995,7 @@ interface QueryOptions {
|
|
|
909
995
|
/** Called when a user message event is received */
|
|
910
996
|
onUserMessage?: (data: UserMessageEvent) => void;
|
|
911
997
|
/** Called when message metadata is received */
|
|
912
|
-
onMetadata?: (data: MessageMetadataPayload) => void;
|
|
998
|
+
onMetadata?: (data: MessageMetadataPayload$1) => void;
|
|
913
999
|
/** Called when the agent requests user input */
|
|
914
1000
|
onUserInputRequest?: (data: UserInputRequestEvent) => void;
|
|
915
1001
|
/** Called when an artifact event is received */
|
|
@@ -3233,4 +3319,4 @@ declare namespace responses {
|
|
|
3233
3319
|
export { type responses_SubmitBackgroundQueryOptions as SubmitBackgroundQueryOptions, responses_extractResponseText as extractResponseText, responses_getResponse as getResponse, responses_submitBackgroundQuery as submitBackgroundQuery };
|
|
3234
3320
|
}
|
|
3235
3321
|
|
|
3236
|
-
export {
|
|
3322
|
+
export { buildRetrievalFullContextTool as $, type AuthHeaders as A, type ResponseOutputTextDeltaEvent as B, type ConfigStore as C, type DocumentWaiter as D, type ResponseOutputTextDoneEvent as E, type FormattedWsMessage as F, type ResponseUsage as G, type SSEStreamCallbacks as H, type SSEStreamResult as I, type SSEStreamStartData as J, type UserInfo as K, LIFECYCLE_LABELS as L, type MessageLevel as M, type UserInputRequestEvent as N, type OutputTokensDetails as O, type UserMessageEvent as P, type QueryOptions as Q, type ReconnectOptions as R, type SSEEvent as S, TOOL_LABELS as T, type UploadBatchResult as U, type WsConnection as V, type WorkspaceContext as W, agentconfig as X, assistant as Y, authenticatedFetch as Z, buildRetrievalChunkTool as _, type CliConfig as a, buildRetrievalTocTool as a0, connectWebSocket as a1, connectWithReconnect as a2, consumeSSEStream as a3, contacts as a4, conversations as a5, countCitations as a6, createAuthenticatedClient as a7, createDocumentWaiter as a8, dm as a9, stripCitationMarkdown as aA, summarizeCitations as aB, tags as aC, workspaces as aD, doctags as aa, documents as ab, files as ac, formatAgentStepLabel as ad, formatFileSize as ae, formatStreamSummary as af, formatUserName as ag, formatWorkspaceChoices as ah, formatWsMessage as ai, generateEncryptedWorkspaceKey as aj, getErrorCode as ak, getErrorMessage as al, health as am, parseSSEEvents as an, performPasswordLogin as ao, performSsoDeviceFlowLogin as ap, requireData as aq, requireOk as ar, resolveAuth as as, resolveCitations as at, resolveWorkspace as au, responses as av, selectWorkspace as aw, selectWorkspaceById as ax, settings as ay, streamSSE as az, type CliCredentials as b, type ChatSession as c, type UploadOptions as d, type UploadResult as e, type AgentStepEvent as f, Arbi as g, ArbiApiError as h, ArbiError as i, type ArbiOptions as j, type ArtifactEvent as k, type AuthContext as l, type AuthenticatedClient as m, type CitationSummary as n, type ConnectOptions as o, type DocumentWaiterOptions as p, type MessageMetadataPayload$1 as q, type MessageQueuedEvent as r, type ReconnectableWsConnection as s, type ResolvedCitation as t, type ResponseCompletedEvent as u, type ResponseContentPartAddedEvent as v, type ResponseCreatedEvent as w, type ResponseFailedEvent as x, type ResponseOutputItemAddedEvent as y, type ResponseOutputItemDoneEvent as z };
|
|
@@ -92,6 +92,8 @@ interface CliCredentials {
|
|
|
92
92
|
workspaceId?: string;
|
|
93
93
|
/** ISO timestamp when the token was cached */
|
|
94
94
|
tokenTimestamp?: string;
|
|
95
|
+
/** Auth0 SSO token — needed for session recovery of SSO users */
|
|
96
|
+
ssoToken?: string;
|
|
95
97
|
}
|
|
96
98
|
interface ChatSession {
|
|
97
99
|
/** Last assistant message ID — used as previous_response_id for follow-ups */
|
|
@@ -114,6 +116,10 @@ interface ConfigStore {
|
|
|
114
116
|
saveChatSession(session: ChatSession): void;
|
|
115
117
|
updateChatSession(updates: Partial<ChatSession>): void;
|
|
116
118
|
clearChatSession(): void;
|
|
119
|
+
/** Persist last response metadata for citation browsing (optional). */
|
|
120
|
+
saveLastMetadata?(metadata: unknown): void;
|
|
121
|
+
/** Load last response metadata for citation browsing (optional). */
|
|
122
|
+
loadLastMetadata?(): unknown | null;
|
|
117
123
|
}
|
|
118
124
|
|
|
119
125
|
/**
|
|
@@ -169,6 +175,17 @@ declare function createAuthenticatedClient(config: CliConfig, creds: CliCredenti
|
|
|
169
175
|
* use createAuthenticatedClient() instead.
|
|
170
176
|
*/
|
|
171
177
|
declare function performPasswordLogin(config: CliConfig, email: string, password: string, store: ConfigStore): Promise<AuthContext>;
|
|
178
|
+
/**
|
|
179
|
+
* SSO device-flow login (RFC 8628).
|
|
180
|
+
*
|
|
181
|
+
* Fetches SSO config from the deployment, initiates the device authorization
|
|
182
|
+
* flow with Auth0, waits for the user to authorize in a browser, then logs
|
|
183
|
+
* in to the ARBI deployment using the Auth0 JWT.
|
|
184
|
+
*/
|
|
185
|
+
declare function performSsoDeviceFlowLogin(config: CliConfig, email: string, password: string, store: ConfigStore, callbacks?: {
|
|
186
|
+
onUserCode?: (userCode: string, verificationUri: string) => void;
|
|
187
|
+
onPoll?: (elapsedMs: number) => void;
|
|
188
|
+
}): Promise<AuthContext>;
|
|
172
189
|
/**
|
|
173
190
|
* Decrypt wrapped workspace key and set it as the active workspace header.
|
|
174
191
|
*/
|
|
@@ -219,7 +236,7 @@ type UserInputRequestEvent = components['schemas']['UserInputRequestEvent'];
|
|
|
219
236
|
type ArtifactEvent = components['schemas']['ArtifactEvent'];
|
|
220
237
|
type UserMessageEvent = components['schemas']['UserMessageEvent'];
|
|
221
238
|
type MessageQueuedEvent = components['schemas']['MessageQueuedEvent'];
|
|
222
|
-
type MessageMetadataPayload = components['schemas']['MessageMetadataPayload'];
|
|
239
|
+
type MessageMetadataPayload$1 = components['schemas']['MessageMetadataPayload'];
|
|
223
240
|
type ResponseUsage = components['schemas']['ResponseUsage'];
|
|
224
241
|
type OutputTokensDetails = components['schemas']['OutputTokensDetails'];
|
|
225
242
|
type TokenBudgetContext = components['schemas']['TokenBudgetContext'];
|
|
@@ -276,7 +293,7 @@ interface SSEStreamCallbacks {
|
|
|
276
293
|
onError?: (message: string) => void;
|
|
277
294
|
onMessageQueued?: (data: MessageQueuedEvent) => void;
|
|
278
295
|
onUserMessage?: (data: UserMessageEvent) => void;
|
|
279
|
-
onMetadata?: (data: MessageMetadataPayload) => void;
|
|
296
|
+
onMetadata?: (data: MessageMetadataPayload$1) => void;
|
|
280
297
|
onUserInputRequest?: (data: UserInputRequestEvent) => void;
|
|
281
298
|
onArtifact?: (data: ArtifactEvent) => void;
|
|
282
299
|
onElapsedTime?: (t: number) => void;
|
|
@@ -294,7 +311,7 @@ interface SSEStreamResult {
|
|
|
294
311
|
toolCallCount: number;
|
|
295
312
|
errors: string[];
|
|
296
313
|
userMessage: UserMessageEvent | null;
|
|
297
|
-
metadata: MessageMetadataPayload | null;
|
|
314
|
+
metadata: MessageMetadataPayload$1 | null;
|
|
298
315
|
artifacts: ArtifactEvent[];
|
|
299
316
|
usage: ResponseUsage | null;
|
|
300
317
|
/** Token budget context snapshot from response.completed. */
|
|
@@ -310,6 +327,15 @@ interface SSEStreamResult {
|
|
|
310
327
|
* both the streaming callbacks and the final result.
|
|
311
328
|
*/
|
|
312
329
|
declare function streamSSE(response: Response, callbacks?: SSEStreamCallbacks): Promise<SSEStreamResult>;
|
|
330
|
+
/**
|
|
331
|
+
* Format a human-readable summary line from a completed SSE stream result.
|
|
332
|
+
*
|
|
333
|
+
* Returns a string like:
|
|
334
|
+
* "3 steps (2 tool calls) · 1,234 tokens · 500/8,000 context · 2.5s"
|
|
335
|
+
*
|
|
336
|
+
* Returns empty string if there's nothing to report.
|
|
337
|
+
*/
|
|
338
|
+
declare function formatStreamSummary(result: SSEStreamResult, elapsedTime?: number | null): string;
|
|
313
339
|
/**
|
|
314
340
|
* Consume an entire SSE stream without streaming callbacks.
|
|
315
341
|
* Convenience alias for `streamSSE(response)`.
|
|
@@ -426,6 +452,66 @@ type UserInfo = {
|
|
|
426
452
|
*/
|
|
427
453
|
declare function formatUserName(user: UserInfo | null | undefined): string;
|
|
428
454
|
|
|
455
|
+
/**
|
|
456
|
+
* Citation resolution utilities — shared by CLI and TUI.
|
|
457
|
+
*
|
|
458
|
+
* Parses citation data from SSE metadata (`MessageMetadataPayload`) and
|
|
459
|
+
* resolves chunk references into displayable citation summaries and passages.
|
|
460
|
+
*
|
|
461
|
+
* Citation data flow:
|
|
462
|
+
* 1. `tools.model_citations.tool_responses` maps citation number → CitationData
|
|
463
|
+
* (contains chunk_ids, statement, offsets)
|
|
464
|
+
* 2. `tools.retrieval_chunk.tool_responses` and `tools.retrieval_full_context.tool_responses`
|
|
465
|
+
* map document file name → Chunk[] (contains content and metadata)
|
|
466
|
+
* 3. This module joins those two data sets to produce resolved citations.
|
|
467
|
+
*/
|
|
468
|
+
|
|
469
|
+
type MessageMetadataPayload = components['schemas']['MessageMetadataPayload'];
|
|
470
|
+
type CitationData$2 = components['schemas']['CitationData'];
|
|
471
|
+
type Chunk$1 = components['schemas']['Chunk'];
|
|
472
|
+
/** A fully resolved citation with its source chunks. */
|
|
473
|
+
interface ResolvedCitation {
|
|
474
|
+
/** Citation number as a string (e.g. "1", "2") */
|
|
475
|
+
citationNum: string;
|
|
476
|
+
/** Raw citation data from model_citations */
|
|
477
|
+
citationData: CitationData$2;
|
|
478
|
+
/** Resolved chunks matching the citation's chunk_ids */
|
|
479
|
+
chunks: Chunk$1[];
|
|
480
|
+
}
|
|
481
|
+
/** A compact citation summary for display in lists. */
|
|
482
|
+
interface CitationSummary {
|
|
483
|
+
citationNum: string;
|
|
484
|
+
statement: string;
|
|
485
|
+
docTitle: string;
|
|
486
|
+
pageNumber: number | null;
|
|
487
|
+
chunkCount: number;
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Resolve all citations from SSE metadata into full citation objects.
|
|
491
|
+
*
|
|
492
|
+
* Reads `tools.model_citations.tool_responses` for citation→chunk_id mappings,
|
|
493
|
+
* then builds a chunk lookup from `retrieval_chunk` and `retrieval_full_context`
|
|
494
|
+
* tool responses to resolve each chunk_id to its full Chunk object.
|
|
495
|
+
*
|
|
496
|
+
* Returns citations sorted by citation number (ascending).
|
|
497
|
+
*/
|
|
498
|
+
declare function resolveCitations(metadata: MessageMetadataPayload | null): ResolvedCitation[];
|
|
499
|
+
/**
|
|
500
|
+
* Produce compact summaries for display in citation lists.
|
|
501
|
+
* Uses the first chunk of each citation for doc title and page number.
|
|
502
|
+
*/
|
|
503
|
+
declare function summarizeCitations(resolved: ResolvedCitation[]): CitationSummary[];
|
|
504
|
+
/**
|
|
505
|
+
* Count the number of citations in metadata.
|
|
506
|
+
* Returns 0 if metadata is null or has no citations.
|
|
507
|
+
*/
|
|
508
|
+
declare function countCitations(metadata: MessageMetadataPayload | null): number;
|
|
509
|
+
/**
|
|
510
|
+
* Convert citation markdown to plain text with superscript-style numbers.
|
|
511
|
+
* Replaces `[text](#cite-N)` with `text[N]`.
|
|
512
|
+
*/
|
|
513
|
+
declare function stripCitationMarkdown(text: string): string;
|
|
514
|
+
|
|
429
515
|
/**
|
|
430
516
|
* Document operations — browser-safe functions.
|
|
431
517
|
*
|
|
@@ -909,7 +995,7 @@ interface QueryOptions {
|
|
|
909
995
|
/** Called when a user message event is received */
|
|
910
996
|
onUserMessage?: (data: UserMessageEvent) => void;
|
|
911
997
|
/** Called when message metadata is received */
|
|
912
|
-
onMetadata?: (data: MessageMetadataPayload) => void;
|
|
998
|
+
onMetadata?: (data: MessageMetadataPayload$1) => void;
|
|
913
999
|
/** Called when the agent requests user input */
|
|
914
1000
|
onUserInputRequest?: (data: UserInputRequestEvent) => void;
|
|
915
1001
|
/** Called when an artifact event is received */
|
|
@@ -3233,4 +3319,4 @@ declare namespace responses {
|
|
|
3233
3319
|
export { type responses_SubmitBackgroundQueryOptions as SubmitBackgroundQueryOptions, responses_extractResponseText as extractResponseText, responses_getResponse as getResponse, responses_submitBackgroundQuery as submitBackgroundQuery };
|
|
3234
3320
|
}
|
|
3235
3321
|
|
|
3236
|
-
export {
|
|
3322
|
+
export { buildRetrievalFullContextTool as $, type AuthHeaders as A, type ResponseOutputTextDeltaEvent as B, type ConfigStore as C, type DocumentWaiter as D, type ResponseOutputTextDoneEvent as E, type FormattedWsMessage as F, type ResponseUsage as G, type SSEStreamCallbacks as H, type SSEStreamResult as I, type SSEStreamStartData as J, type UserInfo as K, LIFECYCLE_LABELS as L, type MessageLevel as M, type UserInputRequestEvent as N, type OutputTokensDetails as O, type UserMessageEvent as P, type QueryOptions as Q, type ReconnectOptions as R, type SSEEvent as S, TOOL_LABELS as T, type UploadBatchResult as U, type WsConnection as V, type WorkspaceContext as W, agentconfig as X, assistant as Y, authenticatedFetch as Z, buildRetrievalChunkTool as _, type CliConfig as a, buildRetrievalTocTool as a0, connectWebSocket as a1, connectWithReconnect as a2, consumeSSEStream as a3, contacts as a4, conversations as a5, countCitations as a6, createAuthenticatedClient as a7, createDocumentWaiter as a8, dm as a9, stripCitationMarkdown as aA, summarizeCitations as aB, tags as aC, workspaces as aD, doctags as aa, documents as ab, files as ac, formatAgentStepLabel as ad, formatFileSize as ae, formatStreamSummary as af, formatUserName as ag, formatWorkspaceChoices as ah, formatWsMessage as ai, generateEncryptedWorkspaceKey as aj, getErrorCode as ak, getErrorMessage as al, health as am, parseSSEEvents as an, performPasswordLogin as ao, performSsoDeviceFlowLogin as ap, requireData as aq, requireOk as ar, resolveAuth as as, resolveCitations as at, resolveWorkspace as au, responses as av, selectWorkspace as aw, selectWorkspaceById as ax, settings as ay, streamSSE as az, type CliCredentials as b, type ChatSession as c, type UploadOptions as d, type UploadResult as e, type AgentStepEvent as f, Arbi as g, ArbiApiError as h, ArbiError as i, type ArbiOptions as j, type ArtifactEvent as k, type AuthContext as l, type AuthenticatedClient as m, type CitationSummary as n, type ConnectOptions as o, type DocumentWaiterOptions as p, type MessageMetadataPayload$1 as q, type MessageQueuedEvent as r, type ReconnectableWsConnection as s, type ResolvedCitation as t, type ResponseCompletedEvent as u, type ResponseContentPartAddedEvent as v, type ResponseCreatedEvent as w, type ResponseFailedEvent as x, type ResponseOutputItemAddedEvent as y, type ResponseOutputItemDoneEvent as z };
|
package/dist/browser.cjs
CHANGED
|
@@ -98,6 +98,8 @@ async function authenticatedFetch(options) {
|
|
|
98
98
|
}
|
|
99
99
|
return res;
|
|
100
100
|
}
|
|
101
|
+
|
|
102
|
+
// src/auth.ts
|
|
101
103
|
function formatWorkspaceChoices(wsList) {
|
|
102
104
|
return wsList.map((ws) => {
|
|
103
105
|
const totalDocs = ws.shared_document_count + ws.private_document_count;
|
|
@@ -118,7 +120,8 @@ async function createAuthenticatedClient(config, creds, store) {
|
|
|
118
120
|
const signingPrivateKey = client.base64ToBytes(creds.signingPrivateKeyBase64);
|
|
119
121
|
const loginResult = await arbi.auth.loginWithKey({
|
|
120
122
|
email: creds.email,
|
|
121
|
-
signingPrivateKey
|
|
123
|
+
signingPrivateKey,
|
|
124
|
+
ssoToken: creds.ssoToken
|
|
122
125
|
});
|
|
123
126
|
store.saveCredentials({
|
|
124
127
|
...creds,
|
|
@@ -582,6 +585,66 @@ function formatUserName(user) {
|
|
|
582
585
|
return [user.given_name, user.family_name].filter(Boolean).join(" ");
|
|
583
586
|
}
|
|
584
587
|
|
|
588
|
+
// src/citations.ts
|
|
589
|
+
function resolveCitations(metadata) {
|
|
590
|
+
if (!metadata?.tools) return [];
|
|
591
|
+
const tools = metadata.tools;
|
|
592
|
+
const modelCitations = tools.model_citations;
|
|
593
|
+
const citationMap = modelCitations?.tool_responses;
|
|
594
|
+
if (!citationMap || Object.keys(citationMap).length === 0) return [];
|
|
595
|
+
const chunkLookup = buildChunkLookup(tools);
|
|
596
|
+
const resolved = [];
|
|
597
|
+
for (const [citationNum, citationData] of Object.entries(citationMap)) {
|
|
598
|
+
const chunks = [];
|
|
599
|
+
for (const chunkId of citationData.chunk_ids ?? []) {
|
|
600
|
+
const chunk = chunkLookup.get(chunkId);
|
|
601
|
+
if (chunk) chunks.push(chunk);
|
|
602
|
+
}
|
|
603
|
+
resolved.push({ citationNum, citationData, chunks });
|
|
604
|
+
}
|
|
605
|
+
resolved.sort((a, b) => Number(a.citationNum) - Number(b.citationNum));
|
|
606
|
+
return resolved;
|
|
607
|
+
}
|
|
608
|
+
function summarizeCitations(resolved) {
|
|
609
|
+
return resolved.map((r) => {
|
|
610
|
+
const firstChunk = r.chunks[0];
|
|
611
|
+
return {
|
|
612
|
+
citationNum: r.citationNum,
|
|
613
|
+
statement: r.citationData.statement ?? "",
|
|
614
|
+
docTitle: firstChunk?.metadata?.doc_title ?? "Unknown document",
|
|
615
|
+
pageNumber: firstChunk?.metadata?.page_number ?? null,
|
|
616
|
+
chunkCount: r.chunks.length
|
|
617
|
+
};
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
function countCitations(metadata) {
|
|
621
|
+
if (!metadata?.tools) return 0;
|
|
622
|
+
const tools = metadata.tools;
|
|
623
|
+
const modelCitations = tools.model_citations;
|
|
624
|
+
const responses = modelCitations?.tool_responses;
|
|
625
|
+
return responses ? Object.keys(responses).length : 0;
|
|
626
|
+
}
|
|
627
|
+
function stripCitationMarkdown(text) {
|
|
628
|
+
return text.replace(/\[([^\]]+)\]\(#cite-(\d+)\)/g, "$1[$2]");
|
|
629
|
+
}
|
|
630
|
+
function buildChunkLookup(tools) {
|
|
631
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
632
|
+
for (const toolName of ["retrieval_chunk", "retrieval_full_context"]) {
|
|
633
|
+
const tool = tools[toolName];
|
|
634
|
+
if (!tool?.tool_responses) continue;
|
|
635
|
+
for (const chunks of Object.values(tool.tool_responses)) {
|
|
636
|
+
if (!Array.isArray(chunks)) continue;
|
|
637
|
+
for (const chunk of chunks) {
|
|
638
|
+
const id = chunk.metadata?.chunk_ext_id;
|
|
639
|
+
if (id && !lookup.has(id)) {
|
|
640
|
+
lookup.set(id, chunk);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
return lookup;
|
|
646
|
+
}
|
|
647
|
+
|
|
585
648
|
// src/operations/documents.ts
|
|
586
649
|
var documents_exports = {};
|
|
587
650
|
__export(documents_exports, {
|
|
@@ -1279,6 +1342,19 @@ var Arbi = class {
|
|
|
1279
1342
|
lr.serverSessionKey,
|
|
1280
1343
|
signingPrivateKeyBase64
|
|
1281
1344
|
);
|
|
1345
|
+
const workspaceKeyHeader = client.session.getWorkspaceKeyHeader();
|
|
1346
|
+
if (workspaceKeyHeader) {
|
|
1347
|
+
const { data: openResult, error: openError } = await client.fetch.POST(
|
|
1348
|
+
"/v1/workspace/{workspace_ext_id}/open",
|
|
1349
|
+
{
|
|
1350
|
+
params: { path: { workspace_ext_id: ws.external_id } },
|
|
1351
|
+
body: { workspace_key: workspaceKeyHeader }
|
|
1352
|
+
}
|
|
1353
|
+
);
|
|
1354
|
+
if (!openError && openResult?.access_token) {
|
|
1355
|
+
client.session.setAccessToken(openResult.access_token);
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1282
1358
|
this.currentWorkspaceId = ws.external_id;
|
|
1283
1359
|
}
|
|
1284
1360
|
/** Log out and clear internal state. */
|
|
@@ -1579,6 +1655,7 @@ exports.connectWithReconnect = connectWithReconnect;
|
|
|
1579
1655
|
exports.consumeSSEStream = consumeSSEStream;
|
|
1580
1656
|
exports.contacts = contacts_exports;
|
|
1581
1657
|
exports.conversations = conversations_exports;
|
|
1658
|
+
exports.countCitations = countCitations;
|
|
1582
1659
|
exports.createAuthenticatedClient = createAuthenticatedClient;
|
|
1583
1660
|
exports.dm = dm_exports;
|
|
1584
1661
|
exports.doctags = doctags_exports;
|
|
@@ -1595,12 +1672,15 @@ exports.performPasswordLogin = performPasswordLogin;
|
|
|
1595
1672
|
exports.requireData = requireData;
|
|
1596
1673
|
exports.requireOk = requireOk;
|
|
1597
1674
|
exports.resolveAuth = resolveAuth;
|
|
1675
|
+
exports.resolveCitations = resolveCitations;
|
|
1598
1676
|
exports.resolveWorkspace = resolveWorkspace;
|
|
1599
1677
|
exports.responses = responses_exports;
|
|
1600
1678
|
exports.selectWorkspace = selectWorkspace;
|
|
1601
1679
|
exports.selectWorkspaceById = selectWorkspaceById;
|
|
1602
1680
|
exports.settings = settings_exports;
|
|
1603
1681
|
exports.streamSSE = streamSSE;
|
|
1682
|
+
exports.stripCitationMarkdown = stripCitationMarkdown;
|
|
1683
|
+
exports.summarizeCitations = summarizeCitations;
|
|
1604
1684
|
exports.tags = tags_exports;
|
|
1605
1685
|
exports.workspaces = workspaces_exports;
|
|
1606
1686
|
//# sourceMappingURL=browser.cjs.map
|