@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/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as ConfigStore, a as CliConfig, b as CliCredentials, c as ChatSession, A as AuthHeaders, U as UploadBatchResult, d as UploadOptions, e as UploadResult } from './browser-DFRwcoc1.cjs';
2
- export { f as AgentStepEvent, g as Arbi, h as ArbiApiError, i as ArbiError, j as ArbiOptions, k as ArtifactEvent, l as AuthContext, m as AuthenticatedClient, n as ConnectOptions, D as DocumentWaiter, o as DocumentWaiterOptions, F as FormattedWsMessage, L as LIFECYCLE_LABELS, M as MessageLevel, p as MessageMetadataPayload, q as MessageQueuedEvent, O as OutputTokensDetails, Q as QueryOptions, R as ReconnectOptions, r as ReconnectableWsConnection, s as ResponseCompletedEvent, t as ResponseContentPartAddedEvent, u as ResponseCreatedEvent, v as ResponseFailedEvent, w as ResponseOutputItemAddedEvent, x as ResponseOutputItemDoneEvent, y as ResponseOutputTextDeltaEvent, z as ResponseOutputTextDoneEvent, B as ResponseUsage, S as SSEEvent, E as SSEStreamCallbacks, G as SSEStreamResult, H as SSEStreamStartData, T as TOOL_LABELS, I as UserInfo, J as UserInputRequestEvent, K as UserMessageEvent, W as WorkspaceContext, N as WsConnection, P as agentconfig, V as assistant, X as authenticatedFetch, Y as buildRetrievalChunkTool, Z as buildRetrievalFullContextTool, _ as buildRetrievalTocTool, $ as connectWebSocket, a0 as connectWithReconnect, a1 as consumeSSEStream, a2 as contacts, a3 as conversations, a4 as createAuthenticatedClient, a5 as createDocumentWaiter, a6 as dm, a7 as doctags, a8 as documents, a9 as files, aa as formatAgentStepLabel, ab as formatFileSize, ac as formatUserName, ad as formatWorkspaceChoices, ae as formatWsMessage, af as generateEncryptedWorkspaceKey, ag as getErrorCode, ah as getErrorMessage, ai as health, aj as parseSSEEvents, ak as performPasswordLogin, al as requireData, am as requireOk, an as resolveAuth, ao as resolveWorkspace, ap as responses, aq as selectWorkspace, ar as selectWorkspaceById, as as settings, at as streamSSE, au as tags, av as workspaces } from './browser-DFRwcoc1.cjs';
1
+ import { C as ConfigStore, a as CliConfig, b as CliCredentials, c as ChatSession, A as AuthHeaders, U as UploadBatchResult, d as UploadOptions, e as UploadResult } from './browser-DUQ3Eyvd.cjs';
2
+ export { f as AgentStepEvent, g as Arbi, h as ArbiApiError, i as ArbiError, j as ArbiOptions, k as ArtifactEvent, l as AuthContext, m as AuthenticatedClient, n as CitationSummary, o as ConnectOptions, D as DocumentWaiter, p as DocumentWaiterOptions, F as FormattedWsMessage, L as LIFECYCLE_LABELS, M as MessageLevel, q as MessageMetadataPayload, r as MessageQueuedEvent, O as OutputTokensDetails, Q as QueryOptions, R as ReconnectOptions, s as ReconnectableWsConnection, t as ResolvedCitation, u as ResponseCompletedEvent, v as ResponseContentPartAddedEvent, w as ResponseCreatedEvent, x as ResponseFailedEvent, y as ResponseOutputItemAddedEvent, z as ResponseOutputItemDoneEvent, B as ResponseOutputTextDeltaEvent, E as ResponseOutputTextDoneEvent, G as ResponseUsage, S as SSEEvent, H as SSEStreamCallbacks, I as SSEStreamResult, J as SSEStreamStartData, T as TOOL_LABELS, K as UserInfo, N as UserInputRequestEvent, P as UserMessageEvent, W as WorkspaceContext, V as WsConnection, X as agentconfig, Y as assistant, Z as authenticatedFetch, _ as buildRetrievalChunkTool, $ as buildRetrievalFullContextTool, a0 as buildRetrievalTocTool, a1 as connectWebSocket, a2 as connectWithReconnect, a3 as consumeSSEStream, a4 as contacts, a5 as conversations, a6 as countCitations, a7 as createAuthenticatedClient, a8 as createDocumentWaiter, a9 as dm, aa as doctags, ab as documents, ac as files, ad as formatAgentStepLabel, ae as formatFileSize, af as formatStreamSummary, ag as formatUserName, ah as formatWorkspaceChoices, ai as formatWsMessage, aj as generateEncryptedWorkspaceKey, ak as getErrorCode, al as getErrorMessage, am as health, an as parseSSEEvents, ao as performPasswordLogin, ap as performSsoDeviceFlowLogin, aq as requireData, ar as requireOk, as as resolveAuth, at as resolveCitations, au as resolveWorkspace, av as responses, aw as selectWorkspace, ax as selectWorkspaceById, ay as settings, az as streamSSE, aA as stripCitationMarkdown, aB as summarizeCitations, aC as tags, aD as workspaces } from './browser-DUQ3Eyvd.cjs';
3
3
  import '@arbidocs/client';
4
4
 
5
5
  /**
@@ -13,6 +13,7 @@ declare class FileConfigStore implements ConfigStore {
13
13
  private readonly configFile;
14
14
  private readonly credentialsFile;
15
15
  private readonly sessionFile;
16
+ private readonly metadataFile;
16
17
  constructor(configDir?: string);
17
18
  private ensureConfigDir;
18
19
  private writeSecureFile;
@@ -29,6 +30,8 @@ declare class FileConfigStore implements ConfigStore {
29
30
  saveChatSession(session: ChatSession): void;
30
31
  updateChatSession(updates: Partial<ChatSession>): void;
31
32
  clearChatSession(): void;
33
+ saveLastMetadata(metadata: unknown): void;
34
+ loadLastMetadata(): unknown | null;
32
35
  /**
33
36
  * Try to resolve config from multiple sources, in priority order:
34
37
  *
@@ -55,6 +58,66 @@ declare class FileConfigStore implements ConfigStore {
55
58
  private readPublicConfigDomain;
56
59
  }
57
60
 
61
+ /**
62
+ * OAuth 2.0 Device Authorization Grant (RFC 8628) for Auth0.
63
+ *
64
+ * Enables headless CLI login: the user authorizes in a browser while the CLI polls for a token.
65
+ */
66
+ interface SsoConfig {
67
+ ssoEnabled: boolean;
68
+ domain: string;
69
+ clientId: string;
70
+ audience: string;
71
+ }
72
+ interface DeviceCodeResponse {
73
+ device_code: string;
74
+ user_code: string;
75
+ verification_uri: string;
76
+ verification_uri_complete: string;
77
+ expires_in: number;
78
+ interval: number;
79
+ }
80
+ declare class DeviceFlowError extends Error {
81
+ constructor(message: string);
82
+ }
83
+ declare class DeviceFlowExpired extends DeviceFlowError {
84
+ constructor();
85
+ }
86
+ declare class DeviceFlowAccessDenied extends DeviceFlowError {
87
+ constructor();
88
+ }
89
+ /**
90
+ * Fetch SSO configuration from the ARBI deployment.
91
+ */
92
+ declare function fetchSsoConfig(baseUrl: string): Promise<SsoConfig>;
93
+ /**
94
+ * Request a device code from Auth0.
95
+ *
96
+ * POST https://{domain}/oauth/device/code
97
+ */
98
+ declare function requestDeviceCode(domain: string, clientId: string, audience?: string, scope?: string): Promise<DeviceCodeResponse>;
99
+ /**
100
+ * Poll Auth0 token endpoint until the user authorizes (or the code expires).
101
+ *
102
+ * Returns the Auth0 access_token (JWT).
103
+ */
104
+ declare function pollForToken(domain: string, clientId: string, deviceCode: string, interval: number, expiresIn: number, onPoll?: (elapsedMs: number) => void): Promise<string>;
105
+
106
+ type deviceFlow_DeviceCodeResponse = DeviceCodeResponse;
107
+ type deviceFlow_DeviceFlowAccessDenied = DeviceFlowAccessDenied;
108
+ declare const deviceFlow_DeviceFlowAccessDenied: typeof DeviceFlowAccessDenied;
109
+ type deviceFlow_DeviceFlowError = DeviceFlowError;
110
+ declare const deviceFlow_DeviceFlowError: typeof DeviceFlowError;
111
+ type deviceFlow_DeviceFlowExpired = DeviceFlowExpired;
112
+ declare const deviceFlow_DeviceFlowExpired: typeof DeviceFlowExpired;
113
+ type deviceFlow_SsoConfig = SsoConfig;
114
+ declare const deviceFlow_fetchSsoConfig: typeof fetchSsoConfig;
115
+ declare const deviceFlow_pollForToken: typeof pollForToken;
116
+ declare const deviceFlow_requestDeviceCode: typeof requestDeviceCode;
117
+ declare namespace deviceFlow {
118
+ export { type deviceFlow_DeviceCodeResponse as DeviceCodeResponse, deviceFlow_DeviceFlowAccessDenied as DeviceFlowAccessDenied, deviceFlow_DeviceFlowError as DeviceFlowError, deviceFlow_DeviceFlowExpired as DeviceFlowExpired, type deviceFlow_SsoConfig as SsoConfig, deviceFlow_fetchSsoConfig as fetchSsoConfig, deviceFlow_pollForToken as pollForToken, deviceFlow_requestDeviceCode as requestDeviceCode };
119
+ }
120
+
58
121
  /**
59
122
  * Document operations — Node.js file system operations.
60
123
  *
@@ -87,4 +150,4 @@ declare namespace documentsNode {
87
150
  export { documentsNode_uploadDirectory as uploadDirectory, documentsNode_uploadLocalFile as uploadLocalFile, documentsNode_uploadZip as uploadZip };
88
151
  }
89
152
 
90
- export { AuthHeaders, ChatSession, CliConfig, CliCredentials, ConfigStore, FileConfigStore, documentsNode };
153
+ export { AuthHeaders, ChatSession, CliConfig, CliCredentials, ConfigStore, FileConfigStore, deviceFlow, documentsNode };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as ConfigStore, a as CliConfig, b as CliCredentials, c as ChatSession, A as AuthHeaders, U as UploadBatchResult, d as UploadOptions, e as UploadResult } from './browser-DFRwcoc1.js';
2
- export { f as AgentStepEvent, g as Arbi, h as ArbiApiError, i as ArbiError, j as ArbiOptions, k as ArtifactEvent, l as AuthContext, m as AuthenticatedClient, n as ConnectOptions, D as DocumentWaiter, o as DocumentWaiterOptions, F as FormattedWsMessage, L as LIFECYCLE_LABELS, M as MessageLevel, p as MessageMetadataPayload, q as MessageQueuedEvent, O as OutputTokensDetails, Q as QueryOptions, R as ReconnectOptions, r as ReconnectableWsConnection, s as ResponseCompletedEvent, t as ResponseContentPartAddedEvent, u as ResponseCreatedEvent, v as ResponseFailedEvent, w as ResponseOutputItemAddedEvent, x as ResponseOutputItemDoneEvent, y as ResponseOutputTextDeltaEvent, z as ResponseOutputTextDoneEvent, B as ResponseUsage, S as SSEEvent, E as SSEStreamCallbacks, G as SSEStreamResult, H as SSEStreamStartData, T as TOOL_LABELS, I as UserInfo, J as UserInputRequestEvent, K as UserMessageEvent, W as WorkspaceContext, N as WsConnection, P as agentconfig, V as assistant, X as authenticatedFetch, Y as buildRetrievalChunkTool, Z as buildRetrievalFullContextTool, _ as buildRetrievalTocTool, $ as connectWebSocket, a0 as connectWithReconnect, a1 as consumeSSEStream, a2 as contacts, a3 as conversations, a4 as createAuthenticatedClient, a5 as createDocumentWaiter, a6 as dm, a7 as doctags, a8 as documents, a9 as files, aa as formatAgentStepLabel, ab as formatFileSize, ac as formatUserName, ad as formatWorkspaceChoices, ae as formatWsMessage, af as generateEncryptedWorkspaceKey, ag as getErrorCode, ah as getErrorMessage, ai as health, aj as parseSSEEvents, ak as performPasswordLogin, al as requireData, am as requireOk, an as resolveAuth, ao as resolveWorkspace, ap as responses, aq as selectWorkspace, ar as selectWorkspaceById, as as settings, at as streamSSE, au as tags, av as workspaces } from './browser-DFRwcoc1.js';
1
+ import { C as ConfigStore, a as CliConfig, b as CliCredentials, c as ChatSession, A as AuthHeaders, U as UploadBatchResult, d as UploadOptions, e as UploadResult } from './browser-DUQ3Eyvd.js';
2
+ export { f as AgentStepEvent, g as Arbi, h as ArbiApiError, i as ArbiError, j as ArbiOptions, k as ArtifactEvent, l as AuthContext, m as AuthenticatedClient, n as CitationSummary, o as ConnectOptions, D as DocumentWaiter, p as DocumentWaiterOptions, F as FormattedWsMessage, L as LIFECYCLE_LABELS, M as MessageLevel, q as MessageMetadataPayload, r as MessageQueuedEvent, O as OutputTokensDetails, Q as QueryOptions, R as ReconnectOptions, s as ReconnectableWsConnection, t as ResolvedCitation, u as ResponseCompletedEvent, v as ResponseContentPartAddedEvent, w as ResponseCreatedEvent, x as ResponseFailedEvent, y as ResponseOutputItemAddedEvent, z as ResponseOutputItemDoneEvent, B as ResponseOutputTextDeltaEvent, E as ResponseOutputTextDoneEvent, G as ResponseUsage, S as SSEEvent, H as SSEStreamCallbacks, I as SSEStreamResult, J as SSEStreamStartData, T as TOOL_LABELS, K as UserInfo, N as UserInputRequestEvent, P as UserMessageEvent, W as WorkspaceContext, V as WsConnection, X as agentconfig, Y as assistant, Z as authenticatedFetch, _ as buildRetrievalChunkTool, $ as buildRetrievalFullContextTool, a0 as buildRetrievalTocTool, a1 as connectWebSocket, a2 as connectWithReconnect, a3 as consumeSSEStream, a4 as contacts, a5 as conversations, a6 as countCitations, a7 as createAuthenticatedClient, a8 as createDocumentWaiter, a9 as dm, aa as doctags, ab as documents, ac as files, ad as formatAgentStepLabel, ae as formatFileSize, af as formatStreamSummary, ag as formatUserName, ah as formatWorkspaceChoices, ai as formatWsMessage, aj as generateEncryptedWorkspaceKey, ak as getErrorCode, al as getErrorMessage, am as health, an as parseSSEEvents, ao as performPasswordLogin, ap as performSsoDeviceFlowLogin, aq as requireData, ar as requireOk, as as resolveAuth, at as resolveCitations, au as resolveWorkspace, av as responses, aw as selectWorkspace, ax as selectWorkspaceById, ay as settings, az as streamSSE, aA as stripCitationMarkdown, aB as summarizeCitations, aC as tags, aD as workspaces } from './browser-DUQ3Eyvd.js';
3
3
  import '@arbidocs/client';
4
4
 
5
5
  /**
@@ -13,6 +13,7 @@ declare class FileConfigStore implements ConfigStore {
13
13
  private readonly configFile;
14
14
  private readonly credentialsFile;
15
15
  private readonly sessionFile;
16
+ private readonly metadataFile;
16
17
  constructor(configDir?: string);
17
18
  private ensureConfigDir;
18
19
  private writeSecureFile;
@@ -29,6 +30,8 @@ declare class FileConfigStore implements ConfigStore {
29
30
  saveChatSession(session: ChatSession): void;
30
31
  updateChatSession(updates: Partial<ChatSession>): void;
31
32
  clearChatSession(): void;
33
+ saveLastMetadata(metadata: unknown): void;
34
+ loadLastMetadata(): unknown | null;
32
35
  /**
33
36
  * Try to resolve config from multiple sources, in priority order:
34
37
  *
@@ -55,6 +58,66 @@ declare class FileConfigStore implements ConfigStore {
55
58
  private readPublicConfigDomain;
56
59
  }
57
60
 
61
+ /**
62
+ * OAuth 2.0 Device Authorization Grant (RFC 8628) for Auth0.
63
+ *
64
+ * Enables headless CLI login: the user authorizes in a browser while the CLI polls for a token.
65
+ */
66
+ interface SsoConfig {
67
+ ssoEnabled: boolean;
68
+ domain: string;
69
+ clientId: string;
70
+ audience: string;
71
+ }
72
+ interface DeviceCodeResponse {
73
+ device_code: string;
74
+ user_code: string;
75
+ verification_uri: string;
76
+ verification_uri_complete: string;
77
+ expires_in: number;
78
+ interval: number;
79
+ }
80
+ declare class DeviceFlowError extends Error {
81
+ constructor(message: string);
82
+ }
83
+ declare class DeviceFlowExpired extends DeviceFlowError {
84
+ constructor();
85
+ }
86
+ declare class DeviceFlowAccessDenied extends DeviceFlowError {
87
+ constructor();
88
+ }
89
+ /**
90
+ * Fetch SSO configuration from the ARBI deployment.
91
+ */
92
+ declare function fetchSsoConfig(baseUrl: string): Promise<SsoConfig>;
93
+ /**
94
+ * Request a device code from Auth0.
95
+ *
96
+ * POST https://{domain}/oauth/device/code
97
+ */
98
+ declare function requestDeviceCode(domain: string, clientId: string, audience?: string, scope?: string): Promise<DeviceCodeResponse>;
99
+ /**
100
+ * Poll Auth0 token endpoint until the user authorizes (or the code expires).
101
+ *
102
+ * Returns the Auth0 access_token (JWT).
103
+ */
104
+ declare function pollForToken(domain: string, clientId: string, deviceCode: string, interval: number, expiresIn: number, onPoll?: (elapsedMs: number) => void): Promise<string>;
105
+
106
+ type deviceFlow_DeviceCodeResponse = DeviceCodeResponse;
107
+ type deviceFlow_DeviceFlowAccessDenied = DeviceFlowAccessDenied;
108
+ declare const deviceFlow_DeviceFlowAccessDenied: typeof DeviceFlowAccessDenied;
109
+ type deviceFlow_DeviceFlowError = DeviceFlowError;
110
+ declare const deviceFlow_DeviceFlowError: typeof DeviceFlowError;
111
+ type deviceFlow_DeviceFlowExpired = DeviceFlowExpired;
112
+ declare const deviceFlow_DeviceFlowExpired: typeof DeviceFlowExpired;
113
+ type deviceFlow_SsoConfig = SsoConfig;
114
+ declare const deviceFlow_fetchSsoConfig: typeof fetchSsoConfig;
115
+ declare const deviceFlow_pollForToken: typeof pollForToken;
116
+ declare const deviceFlow_requestDeviceCode: typeof requestDeviceCode;
117
+ declare namespace deviceFlow {
118
+ export { type deviceFlow_DeviceCodeResponse as DeviceCodeResponse, deviceFlow_DeviceFlowAccessDenied as DeviceFlowAccessDenied, deviceFlow_DeviceFlowError as DeviceFlowError, deviceFlow_DeviceFlowExpired as DeviceFlowExpired, type deviceFlow_SsoConfig as SsoConfig, deviceFlow_fetchSsoConfig as fetchSsoConfig, deviceFlow_pollForToken as pollForToken, deviceFlow_requestDeviceCode as requestDeviceCode };
119
+ }
120
+
58
121
  /**
59
122
  * Document operations — Node.js file system operations.
60
123
  *
@@ -87,4 +150,4 @@ declare namespace documentsNode {
87
150
  export { documentsNode_uploadDirectory as uploadDirectory, documentsNode_uploadLocalFile as uploadLocalFile, documentsNode_uploadZip as uploadZip };
88
151
  }
89
152
 
90
- export { AuthHeaders, ChatSession, CliConfig, CliCredentials, ConfigStore, FileConfigStore, documentsNode };
153
+ export { AuthHeaders, ChatSession, CliConfig, CliCredentials, ConfigStore, FileConfigStore, deviceFlow, documentsNode };
package/dist/index.js CHANGED
@@ -121,11 +121,13 @@ var FileConfigStore = class {
121
121
  configFile;
122
122
  credentialsFile;
123
123
  sessionFile;
124
+ metadataFile;
124
125
  constructor(configDir) {
125
126
  this.configDir = configDir ?? process.env.ARBI_CONFIG_DIR ?? path2.join(os.homedir(), ".arbi");
126
127
  this.configFile = path2.join(this.configDir, "config.json");
127
128
  this.credentialsFile = path2.join(this.configDir, "credentials.json");
128
129
  this.sessionFile = path2.join(this.configDir, "session.json");
130
+ this.metadataFile = path2.join(this.configDir, "last-metadata.json");
129
131
  }
130
132
  ensureConfigDir() {
131
133
  if (!fs.existsSync(this.configDir)) {
@@ -196,6 +198,13 @@ var FileConfigStore = class {
196
198
  clearChatSession() {
197
199
  this.saveChatSession({ ...DEFAULT_SESSION });
198
200
  }
201
+ // ── Last metadata (for citation browsing) ────────────────────────────────
202
+ saveLastMetadata(metadata) {
203
+ this.writeSecureFile(this.metadataFile, metadata);
204
+ }
205
+ loadLastMetadata() {
206
+ return this.readJsonFile(this.metadataFile);
207
+ }
199
208
  /**
200
209
  * Try to resolve config from multiple sources, in priority order:
201
210
  *
@@ -268,6 +277,107 @@ var FileConfigStore = class {
268
277
  return null;
269
278
  }
270
279
  };
280
+
281
+ // src/device-flow.ts
282
+ var device_flow_exports = {};
283
+ __export(device_flow_exports, {
284
+ DeviceFlowAccessDenied: () => DeviceFlowAccessDenied,
285
+ DeviceFlowError: () => DeviceFlowError,
286
+ DeviceFlowExpired: () => DeviceFlowExpired,
287
+ fetchSsoConfig: () => fetchSsoConfig,
288
+ pollForToken: () => pollForToken,
289
+ requestDeviceCode: () => requestDeviceCode
290
+ });
291
+ var DeviceFlowError = class extends Error {
292
+ constructor(message) {
293
+ super(message);
294
+ this.name = "DeviceFlowError";
295
+ }
296
+ };
297
+ var DeviceFlowExpired = class extends DeviceFlowError {
298
+ constructor() {
299
+ super("Device code expired \u2014 please try again");
300
+ this.name = "DeviceFlowExpired";
301
+ }
302
+ };
303
+ var DeviceFlowAccessDenied = class extends DeviceFlowError {
304
+ constructor() {
305
+ super("Authorization was denied by the user");
306
+ this.name = "DeviceFlowAccessDenied";
307
+ }
308
+ };
309
+ async function fetchSsoConfig(baseUrl) {
310
+ const arbi = createArbiClient({ baseUrl, deploymentDomain: "", credentials: "omit" });
311
+ const { data, error } = await arbi.fetch.GET("/v1/user/sso-config");
312
+ if (error || !data) {
313
+ throw new DeviceFlowError(`Failed to fetch SSO config`);
314
+ }
315
+ return {
316
+ ssoEnabled: data.sso_enabled,
317
+ domain: data.domain,
318
+ clientId: data.cli_client_id || data.client_id,
319
+ audience: data.audience
320
+ };
321
+ }
322
+ async function requestDeviceCode(domain, clientId, audience, scope = "openid email profile") {
323
+ const body = new URLSearchParams({
324
+ client_id: clientId,
325
+ scope,
326
+ ...audience ? { audience } : {}
327
+ });
328
+ const res = await fetch(`https://${domain}/oauth/device/code`, {
329
+ method: "POST",
330
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
331
+ body
332
+ });
333
+ if (!res.ok) {
334
+ const text = await res.text();
335
+ throw new DeviceFlowError(`Device code request failed: ${res.status} ${text}`);
336
+ }
337
+ return await res.json();
338
+ }
339
+ async function pollForToken(domain, clientId, deviceCode, interval, expiresIn, onPoll) {
340
+ const deadline = Date.now() + expiresIn * 1e3;
341
+ let pollInterval = interval * 1e3;
342
+ while (Date.now() < deadline) {
343
+ await sleep(pollInterval);
344
+ onPoll?.(Date.now());
345
+ const res = await fetch(`https://${domain}/oauth/token`, {
346
+ method: "POST",
347
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
348
+ body: new URLSearchParams({
349
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
350
+ client_id: clientId,
351
+ device_code: deviceCode
352
+ })
353
+ });
354
+ if (res.ok) {
355
+ const data = await res.json();
356
+ return data.access_token;
357
+ }
358
+ const errBody = await res.json().catch(() => ({ error: "unknown" }));
359
+ if (errBody.error === "authorization_pending") {
360
+ continue;
361
+ } else if (errBody.error === "slow_down") {
362
+ pollInterval += 5e3;
363
+ continue;
364
+ } else if (errBody.error === "expired_token") {
365
+ throw new DeviceFlowExpired();
366
+ } else if (errBody.error === "access_denied") {
367
+ throw new DeviceFlowAccessDenied();
368
+ } else {
369
+ throw new DeviceFlowError(
370
+ `Token polling error: ${errBody.error} \u2014 ${errBody.error_description ?? ""}`
371
+ );
372
+ }
373
+ }
374
+ throw new DeviceFlowExpired();
375
+ }
376
+ function sleep(ms) {
377
+ return new Promise((resolve) => setTimeout(resolve, ms));
378
+ }
379
+
380
+ // src/auth.ts
271
381
  function formatWorkspaceChoices(wsList) {
272
382
  return wsList.map((ws) => {
273
383
  const totalDocs = ws.shared_document_count + ws.private_document_count;
@@ -288,7 +398,8 @@ async function createAuthenticatedClient(config, creds, store) {
288
398
  const signingPrivateKey = base64ToBytes(creds.signingPrivateKeyBase64);
289
399
  const loginResult = await arbi.auth.loginWithKey({
290
400
  email: creds.email,
291
- signingPrivateKey
401
+ signingPrivateKey,
402
+ ssoToken: creds.ssoToken
292
403
  });
293
404
  store.saveCredentials({
294
405
  ...creds,
@@ -320,6 +431,40 @@ async function performPasswordLogin(config, email, password, store) {
320
431
  });
321
432
  return { arbi, loginResult, config };
322
433
  }
434
+ async function performSsoDeviceFlowLogin(config, email, password, store, callbacks) {
435
+ const ssoConfig = await fetchSsoConfig(config.baseUrl);
436
+ if (!ssoConfig.ssoEnabled) {
437
+ throw new ArbiError("SSO is not enabled on this deployment");
438
+ }
439
+ const dc = await requestDeviceCode(ssoConfig.domain, ssoConfig.clientId, ssoConfig.audience);
440
+ callbacks?.onUserCode?.(dc.user_code, dc.verification_uri_complete);
441
+ const ssoToken = await pollForToken(
442
+ ssoConfig.domain,
443
+ ssoConfig.clientId,
444
+ dc.device_code,
445
+ dc.interval,
446
+ dc.expires_in,
447
+ callbacks?.onPoll
448
+ );
449
+ const arbi = createArbiClient({
450
+ baseUrl: config.baseUrl,
451
+ deploymentDomain: config.deploymentDomain,
452
+ credentials: "omit"
453
+ });
454
+ await arbi.crypto.initSodium();
455
+ const loginResult = await arbi.auth.login({ email, password, ssoToken });
456
+ store.saveCredentials({
457
+ email,
458
+ signingPrivateKeyBase64: arbi.crypto.bytesToBase64(loginResult.signingPrivateKey),
459
+ serverSessionKeyBase64: arbi.crypto.bytesToBase64(loginResult.serverSessionKey),
460
+ ssoToken,
461
+ accessToken: void 0,
462
+ workspaceKeyHeader: void 0,
463
+ workspaceId: void 0,
464
+ tokenTimestamp: void 0
465
+ });
466
+ return { arbi, loginResult, config };
467
+ }
323
468
  async function selectWorkspace(arbi, workspaceId, wrappedKey, serverSessionKey, signingPrivateKeyBase64) {
324
469
  const signingPrivateKey = base64ToBytes(signingPrivateKeyBase64);
325
470
  const ed25519PublicKey = signingPrivateKey.slice(32, 64);
@@ -644,6 +789,27 @@ async function streamSSE(response, callbacks = {}) {
644
789
  context
645
790
  };
646
791
  }
792
+ function formatStreamSummary(result, elapsedTime) {
793
+ const parts = [];
794
+ if (result.agentSteps.length > 0) {
795
+ let stepLabel = `${result.agentSteps.length} step${result.agentSteps.length === 1 ? "" : "s"}`;
796
+ if (result.toolCallCount > 0) {
797
+ stepLabel += ` (${result.toolCallCount} tool call${result.toolCallCount === 1 ? "" : "s"})`;
798
+ }
799
+ parts.push(stepLabel);
800
+ }
801
+ if (result.usage) {
802
+ parts.push(`${result.usage.total_tokens.toLocaleString()} tokens`);
803
+ }
804
+ if (result.context && result.context.context_window > 0) {
805
+ const used = result.context.all_llm_calls?.last_input_tokens ?? result.context.total_input;
806
+ parts.push(`${used.toLocaleString()}/${result.context.context_window.toLocaleString()} context`);
807
+ }
808
+ if (elapsedTime != null) {
809
+ parts.push(`${elapsedTime.toFixed(1)}s`);
810
+ }
811
+ return parts.length > 0 ? parts.join(" \xB7 ") : "";
812
+ }
647
813
  var consumeSSEStream = streamSSE;
648
814
  var AUTH_TIMEOUT_MS = 1e4;
649
815
  var MAX_BACKOFF_MS = 3e4;
@@ -868,6 +1034,66 @@ function formatUserName(user) {
868
1034
  return [user.given_name, user.family_name].filter(Boolean).join(" ");
869
1035
  }
870
1036
 
1037
+ // src/citations.ts
1038
+ function resolveCitations(metadata) {
1039
+ if (!metadata?.tools) return [];
1040
+ const tools = metadata.tools;
1041
+ const modelCitations = tools.model_citations;
1042
+ const citationMap = modelCitations?.tool_responses;
1043
+ if (!citationMap || Object.keys(citationMap).length === 0) return [];
1044
+ const chunkLookup = buildChunkLookup(tools);
1045
+ const resolved = [];
1046
+ for (const [citationNum, citationData] of Object.entries(citationMap)) {
1047
+ const chunks = [];
1048
+ for (const chunkId of citationData.chunk_ids ?? []) {
1049
+ const chunk = chunkLookup.get(chunkId);
1050
+ if (chunk) chunks.push(chunk);
1051
+ }
1052
+ resolved.push({ citationNum, citationData, chunks });
1053
+ }
1054
+ resolved.sort((a, b) => Number(a.citationNum) - Number(b.citationNum));
1055
+ return resolved;
1056
+ }
1057
+ function summarizeCitations(resolved) {
1058
+ return resolved.map((r) => {
1059
+ const firstChunk = r.chunks[0];
1060
+ return {
1061
+ citationNum: r.citationNum,
1062
+ statement: r.citationData.statement ?? "",
1063
+ docTitle: firstChunk?.metadata?.doc_title ?? "Unknown document",
1064
+ pageNumber: firstChunk?.metadata?.page_number ?? null,
1065
+ chunkCount: r.chunks.length
1066
+ };
1067
+ });
1068
+ }
1069
+ function countCitations(metadata) {
1070
+ if (!metadata?.tools) return 0;
1071
+ const tools = metadata.tools;
1072
+ const modelCitations = tools.model_citations;
1073
+ const responses = modelCitations?.tool_responses;
1074
+ return responses ? Object.keys(responses).length : 0;
1075
+ }
1076
+ function stripCitationMarkdown(text) {
1077
+ return text.replace(/\[([^\]]+)\]\(#cite-(\d+)\)/g, "$1[$2]");
1078
+ }
1079
+ function buildChunkLookup(tools) {
1080
+ const lookup = /* @__PURE__ */ new Map();
1081
+ for (const toolName of ["retrieval_chunk", "retrieval_full_context"]) {
1082
+ const tool = tools[toolName];
1083
+ if (!tool?.tool_responses) continue;
1084
+ for (const chunks of Object.values(tool.tool_responses)) {
1085
+ if (!Array.isArray(chunks)) continue;
1086
+ for (const chunk of chunks) {
1087
+ const id = chunk.metadata?.chunk_ext_id;
1088
+ if (id && !lookup.has(id)) {
1089
+ lookup.set(id, chunk);
1090
+ }
1091
+ }
1092
+ }
1093
+ }
1094
+ return lookup;
1095
+ }
1096
+
871
1097
  // src/operations/documents.ts
872
1098
  var documents_exports = {};
873
1099
  __export(documents_exports, {
@@ -1565,6 +1791,19 @@ var Arbi = class {
1565
1791
  lr.serverSessionKey,
1566
1792
  signingPrivateKeyBase64
1567
1793
  );
1794
+ const workspaceKeyHeader = client.session.getWorkspaceKeyHeader();
1795
+ if (workspaceKeyHeader) {
1796
+ const { data: openResult, error: openError } = await client.fetch.POST(
1797
+ "/v1/workspace/{workspace_ext_id}/open",
1798
+ {
1799
+ params: { path: { workspace_ext_id: ws.external_id } },
1800
+ body: { workspace_key: workspaceKeyHeader }
1801
+ }
1802
+ );
1803
+ if (!openError && openResult?.access_token) {
1804
+ client.session.setAccessToken(openResult.access_token);
1805
+ }
1806
+ }
1568
1807
  this.currentWorkspaceId = ws.external_id;
1569
1808
  }
1570
1809
  /** Log out and clear internal state. */
@@ -1966,6 +2205,6 @@ function extractResponseText(response) {
1966
2205
  return parts.join("");
1967
2206
  }
1968
2207
 
1969
- export { Arbi, ArbiApiError, ArbiError, FileConfigStore, LIFECYCLE_LABELS, TOOL_LABELS, agentconfig_exports as agentconfig, assistant_exports as assistant, authenticatedFetch, buildRetrievalChunkTool, buildRetrievalFullContextTool, buildRetrievalTocTool, connectWebSocket, connectWithReconnect, consumeSSEStream, contacts_exports as contacts, conversations_exports as conversations, createAuthenticatedClient, createDocumentWaiter, dm_exports as dm, doctags_exports as doctags, documents_exports as documents, documents_node_exports as documentsNode, files_exports as files, formatAgentStepLabel, formatFileSize, formatUserName, formatWorkspaceChoices, formatWsMessage, generateEncryptedWorkspaceKey, getErrorCode, getErrorMessage, health_exports as health, parseSSEEvents, performPasswordLogin, requireData, requireOk, resolveAuth, resolveWorkspace, responses_exports as responses, selectWorkspace, selectWorkspaceById, settings_exports as settings, streamSSE, tags_exports as tags, workspaces_exports as workspaces };
2208
+ export { Arbi, ArbiApiError, ArbiError, FileConfigStore, LIFECYCLE_LABELS, TOOL_LABELS, agentconfig_exports as agentconfig, assistant_exports as assistant, authenticatedFetch, buildRetrievalChunkTool, buildRetrievalFullContextTool, buildRetrievalTocTool, connectWebSocket, connectWithReconnect, consumeSSEStream, contacts_exports as contacts, conversations_exports as conversations, countCitations, createAuthenticatedClient, createDocumentWaiter, device_flow_exports as deviceFlow, dm_exports as dm, doctags_exports as doctags, documents_exports as documents, documents_node_exports as documentsNode, files_exports as files, formatAgentStepLabel, formatFileSize, formatStreamSummary, formatUserName, formatWorkspaceChoices, formatWsMessage, generateEncryptedWorkspaceKey, getErrorCode, getErrorMessage, health_exports as health, parseSSEEvents, performPasswordLogin, performSsoDeviceFlowLogin, requireData, requireOk, resolveAuth, resolveCitations, resolveWorkspace, responses_exports as responses, selectWorkspace, selectWorkspaceById, settings_exports as settings, streamSSE, stripCitationMarkdown, summarizeCitations, tags_exports as tags, workspaces_exports as workspaces };
1970
2209
  //# sourceMappingURL=index.js.map
1971
2210
  //# sourceMappingURL=index.js.map