@arbidocs/sdk 0.4.4 → 0.4.6

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.cjs CHANGED
@@ -3581,14 +3581,15 @@ async function extractErrorMessage(res) {
3581
3581
  return `Request failed: ${res.status} ${res.statusText}`;
3582
3582
  }
3583
3583
  async function authenticatedFetch(options) {
3584
- const { baseUrl, accessToken, path: path3, method, body, headers } = options;
3584
+ const { baseUrl, accessToken, path: path3, method, body, headers, signal } = options;
3585
3585
  const res = await fetch(`${baseUrl}${path3}`, {
3586
3586
  method: method ?? (body ? "POST" : "GET"),
3587
3587
  headers: {
3588
3588
  Authorization: `Bearer ${accessToken}`,
3589
3589
  ...headers
3590
3590
  },
3591
- body
3591
+ body,
3592
+ signal
3592
3593
  });
3593
3594
  if (!res.ok) {
3594
3595
  const message = await extractErrorMessage(res);
@@ -5028,6 +5029,7 @@ async function uploadFile(auth, fileData, fileName, options) {
5028
5029
  if (options?.folder) params.set("folder", sanitizeFolderPath(options.folder));
5029
5030
  if (options?.configExtId) params.set("config_ext_id", options.configExtId);
5030
5031
  if (options?.wpType) params.set("wp_type", options.wpType);
5032
+ if (options?.parentExtId) params.set("parent_ext_id", options.parentExtId);
5031
5033
  const qs = params.toString();
5032
5034
  const res = await authenticatedFetch({
5033
5035
  ...auth,
@@ -5044,6 +5046,7 @@ async function uploadFiles(auth, files, options) {
5044
5046
  if (options?.folder) params.set("folder", sanitizeFolderPath(options.folder));
5045
5047
  if (options?.configExtId) params.set("config_ext_id", options.configExtId);
5046
5048
  if (options?.wpType) params.set("wp_type", options.wpType);
5049
+ if (options?.parentExtId) params.set("parent_ext_id", options.parentExtId);
5047
5050
  const qs = params.toString();
5048
5051
  const res = await authenticatedFetch({
5049
5052
  ...auth,
@@ -5474,7 +5477,7 @@ async function retrieve(options) {
5474
5477
  return data;
5475
5478
  }
5476
5479
  async function queryAssistant(options) {
5477
- const { workspaceId, question, docIds, previousResponseId, model, ...auth } = options;
5480
+ const { workspaceId, question, docIds, previousResponseId, model, signal, ...auth } = options;
5478
5481
  const body = {
5479
5482
  input: question,
5480
5483
  workspace_ext_id: workspaceId,
@@ -5493,7 +5496,8 @@ async function queryAssistant(options) {
5493
5496
  path: "/v1/assistant/query",
5494
5497
  method: "POST",
5495
5498
  body: JSON.stringify(body),
5496
- headers: { "Content-Type": "application/json" }
5499
+ headers: { "Content-Type": "application/json" },
5500
+ signal
5497
5501
  });
5498
5502
  }
5499
5503
  async function respondToAgent(arbi, assistantMessageExtId, answer) {
@@ -6041,11 +6045,76 @@ async function getFileContent(auth, fileId) {
6041
6045
  // src/operations/sessions.ts
6042
6046
  var sessions_exports = {};
6043
6047
  __export(sessions_exports, {
6044
- listSessions: () => listSessions
6048
+ currentSessionId: () => currentSessionId,
6049
+ listSessions: () => listSessions,
6050
+ logoutAllSessions: () => logoutAllSessions,
6051
+ terminateSession: () => terminateSession
6045
6052
  });
6046
6053
  async function listSessions(arbi) {
6047
6054
  return requireData(await arbi.fetch.GET("/v1/user/sessions"), "Failed to fetch sessions");
6048
6055
  }
6056
+ async function terminateSession(arbi, sessionId) {
6057
+ requireOk(
6058
+ await arbi.fetch.PATCH("/v1/user/sessions/{session_id}", {
6059
+ params: { path: { session_id: sessionId } },
6060
+ body: { ttl: 0 }
6061
+ }),
6062
+ "Failed to end session"
6063
+ );
6064
+ }
6065
+ async function logoutAllSessions(arbi) {
6066
+ requireOk(
6067
+ await arbi.fetch.POST("/v1/user/logout", { params: { query: { all_sessions: true } } }),
6068
+ "Failed to sign out of all sessions"
6069
+ );
6070
+ }
6071
+ function currentSessionId(accessToken) {
6072
+ const payload = accessToken?.split(".")[1];
6073
+ if (!payload) return null;
6074
+ try {
6075
+ const claims = JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
6076
+ return typeof claims.sk === "string" ? claims.sk.slice(0, 12) : null;
6077
+ } catch {
6078
+ return null;
6079
+ }
6080
+ }
6081
+
6082
+ // src/operations/profile.ts
6083
+ var profile_exports = {};
6084
+ __export(profile_exports, {
6085
+ updateProfile: () => updateProfile
6086
+ });
6087
+ async function updateProfile(arbi, body) {
6088
+ return requireData(
6089
+ await arbi.fetch.PATCH("/v1/user/profile", { body }),
6090
+ "Failed to update profile"
6091
+ );
6092
+ }
6093
+
6094
+ // src/operations/account.ts
6095
+ var account_exports = {};
6096
+ __export(account_exports, {
6097
+ confirmEmailChange: () => confirmEmailChange,
6098
+ requestDeletion: () => requestDeletion,
6099
+ requestEmailChange: () => requestEmailChange
6100
+ });
6101
+ async function requestEmailChange(arbi, newEmail) {
6102
+ requireOk(
6103
+ await arbi.fetch.POST("/v1/user/request-email-change", { body: { new_email: newEmail } }),
6104
+ "Failed to send the verification code"
6105
+ );
6106
+ }
6107
+ async function confirmEmailChange(arbi, newEmail, verificationCode) {
6108
+ return requireData(
6109
+ await arbi.fetch.POST("/v1/user/confirm-email-change", {
6110
+ body: { new_email: newEmail, verification_code: verificationCode }
6111
+ }),
6112
+ "Invalid or expired verification code"
6113
+ );
6114
+ }
6115
+ async function requestDeletion(arbi) {
6116
+ return requireData(await arbi.fetch.POST("/v1/user/request-deletion"), "Failed to delete account");
6117
+ }
6049
6118
 
6050
6119
  // src/operations/projects.ts
6051
6120
  var projects_exports = {};
@@ -6255,6 +6324,8 @@ function tokenExpiresWithin(token, seconds) {
6255
6324
  var Arbi = class {
6256
6325
  client = null;
6257
6326
  loginResult = null;
6327
+ userProfile = null;
6328
+ profileListeners = /* @__PURE__ */ new Set();
6258
6329
  currentWorkspaceId = null;
6259
6330
  dmCryptoContext = null;
6260
6331
  sessionExpiredListeners = /* @__PURE__ */ new Set();
@@ -6303,6 +6374,7 @@ var Arbi = class {
6303
6374
  async login(email, password) {
6304
6375
  const client = await this.init();
6305
6376
  this.loginResult = await client.auth.login({ email, password });
6377
+ this.userProfile = this.loginResult.profile ?? null;
6306
6378
  }
6307
6379
  /**
6308
6380
  * Recover a session using a stored signing private key (base64).
@@ -6312,6 +6384,7 @@ var Arbi = class {
6312
6384
  const client = await this.init();
6313
6385
  const signingPrivateKey = client.crypto.base64ToBytes(signingPrivateKeyBase64);
6314
6386
  this.loginResult = await client.auth.loginWithKey({ email, signingPrivateKey });
6387
+ this.userProfile = this.loginResult.profile ?? null;
6315
6388
  }
6316
6389
  /** A workspace's key, sealed to the caller's own session (what `/open` and `POST /workspace/users` take). */
6317
6390
  async sealWorkspaceKey(workspaceId) {
@@ -6371,6 +6444,7 @@ var Arbi = class {
6371
6444
  this.loginResult.serverSessionKey.fill(0);
6372
6445
  }
6373
6446
  this.loginResult = null;
6447
+ this.userProfile = null;
6374
6448
  this.currentWorkspaceId = null;
6375
6449
  this.dmCryptoContext = null;
6376
6450
  this.client?.session.clear();
@@ -6401,6 +6475,10 @@ var Arbi = class {
6401
6475
  return run();
6402
6476
  }
6403
6477
  }
6478
+ setUserProfile(profile) {
6479
+ this.userProfile = profile;
6480
+ for (const listener of [...this.profileListeners]) listener(profile);
6481
+ }
6404
6482
  /** Log out and clear internal state. */
6405
6483
  async logout() {
6406
6484
  if (this.client) {
@@ -6411,6 +6489,7 @@ var Arbi = class {
6411
6489
  this.loginResult.serverSessionKey.fill(0);
6412
6490
  }
6413
6491
  this.loginResult = null;
6492
+ this.userProfile = null;
6414
6493
  this.currentWorkspaceId = null;
6415
6494
  this.dmCryptoContext = null;
6416
6495
  }
@@ -6484,9 +6563,76 @@ var Arbi = class {
6484
6563
  const state = this.requireClient().session.getState();
6485
6564
  return state.userExtId ? { externalId: state.userExtId, email: state.userEmail ?? null } : null;
6486
6565
  },
6566
+ /**
6567
+ * The signed-in user's profile (name, picture, email, SSO flag) as the login response
6568
+ * carried it, kept current by `profile.update` and `account.confirmEmailChange`. `null` when
6569
+ * not logged in or when the session was restored without a login (then read the workspace
6570
+ * roster instead).
6571
+ */
6572
+ profile: () => this.userProfile,
6573
+ /** Be told when the profile changes (name, picture or email saved). Returns the unsubscribe. */
6574
+ onProfileChange: (listener) => {
6575
+ this.profileListeners.add(listener);
6576
+ return () => this.profileListeners.delete(listener);
6577
+ },
6487
6578
  /** Today's deployment-wide credit spend for the current user. */
6488
6579
  usageToday: () => getUserUsageToday(this.requireClient())
6489
6580
  };
6581
+ // ── Profile ───────────────────────────────────────────────────────────
6582
+ profile = {
6583
+ /** Update the display profile; pass only what changes (`''` clears family name or picture). */
6584
+ update: async (body) => {
6585
+ const updated = await updateProfile(this.requireClient(), body);
6586
+ if (this.userProfile) {
6587
+ this.setUserProfile({
6588
+ ...this.userProfile,
6589
+ givenName: updated.given_name ?? this.userProfile.givenName,
6590
+ familyName: updated.family_name ?? null,
6591
+ picture: updated.picture ?? null
6592
+ });
6593
+ }
6594
+ return updated;
6595
+ }
6596
+ };
6597
+ // ── Account ───────────────────────────────────────────────────────────
6598
+ account = {
6599
+ /** Send a verification code to the new address (not for SSO accounts). */
6600
+ requestEmailChange: (newEmail) => requestEmailChange(this.requireClient(), newEmail),
6601
+ /** Confirm the email change with the emailed code; the session and profile follow. */
6602
+ confirmEmailChange: async (newEmail, verificationCode) => {
6603
+ const client = this.requireClient();
6604
+ const result = await confirmEmailChange(client, newEmail, verificationCode);
6605
+ client.session.setUser(result.email, client.session.getState().userExtId ?? void 0);
6606
+ if (this.userProfile) this.setUserProfile({ ...this.userProfile, email: result.email });
6607
+ return result;
6608
+ },
6609
+ /**
6610
+ * Change (or, after recovery, set) the master password: re-keys the workspaces and direct
6611
+ * messages. Omit `currentPassword` in recovery mode. Resolves with the new signing key, whose
6612
+ * recovery file the user should save.
6613
+ */
6614
+ changePassword: async (params) => {
6615
+ const client$1 = this.requireClient();
6616
+ const lr2 = this.requireLogin();
6617
+ const email = client$1.session.getState().userEmail ?? this.userProfile?.email;
6618
+ if (!email) throw new ArbiError("The account email is unknown; sign in again.");
6619
+ const result = await client.changePasswordWithRekey(
6620
+ { ...params, email, userExtId: lr2.userExtId },
6621
+ {
6622
+ fetchClient: client$1.fetch,
6623
+ deploymentDomain: this.options.deploymentDomain ?? new URL(this.options.url).hostname
6624
+ }
6625
+ );
6626
+ this.loginResult = { ...lr2, signingPrivateKey: result.newSigningPrivateKey };
6627
+ return result;
6628
+ },
6629
+ /** Close the account (soft delete) and sign out. Refused while a subscription is active. */
6630
+ requestDeletion: async () => {
6631
+ const result = await requestDeletion(this.requireClient());
6632
+ await this.logout();
6633
+ return result;
6634
+ }
6635
+ };
6490
6636
  // ── Workspaces ────────────────────────────────────────────────────────
6491
6637
  workspaces = {
6492
6638
  list: () => listWorkspaces(this.requireClient()),
@@ -6592,12 +6738,7 @@ var Arbi = class {
6592
6738
  uploadFile: (fileData, fileName, options) => {
6593
6739
  this.requireWorkspace();
6594
6740
  return this.recovering(
6595
- () => uploadFile(
6596
- this.getAuthHeaders(),
6597
- fileData,
6598
- fileName,
6599
- options?.folder ? { folder: options.folder } : void 0
6600
- )
6741
+ () => uploadFile(this.getAuthHeaders(), fileData, fileName, options)
6601
6742
  );
6602
6743
  },
6603
6744
  download: (docId) => this.recovering(() => downloadDocument(this.getAuthHeaders(), docId)),
@@ -6629,7 +6770,8 @@ var Arbi = class {
6629
6770
  question,
6630
6771
  docIds: options.docIds,
6631
6772
  previousResponseId: options.previousResponseId,
6632
- model: options.model
6773
+ model: options.model,
6774
+ signal: options.signal
6633
6775
  })
6634
6776
  );
6635
6777
  const callbacks = {
@@ -6877,7 +7019,16 @@ var Arbi = class {
6877
7019
  };
6878
7020
  // ── Sessions ────────────────────────────────────────────────────────
6879
7021
  sessions = {
6880
- list: () => listSessions(this.requireClient())
7022
+ list: () => listSessions(this.requireClient()),
7023
+ /** The id this device's session is listed under in `list()`; `null` when unknown. */
7024
+ currentId: () => currentSessionId(this.client?.session.getState().accessToken),
7025
+ /** End one of your own sessions now (not the one this device is on: that is `logout`). */
7026
+ terminate: (sessionId) => terminateSession(this.requireClient(), sessionId),
7027
+ /** Sign out of every device on the server, then clear this instance. */
7028
+ logoutAll: async () => {
7029
+ await logoutAllSessions(this.requireClient());
7030
+ await this.logout();
7031
+ }
6881
7032
  };
6882
7033
  // ── Internal guards ───────────────────────────────────────────────────
6883
7034
  requireClient() {
@@ -7708,18 +7859,6 @@ function extractResponseText(response) {
7708
7859
  return parts.join("");
7709
7860
  }
7710
7861
 
7711
- // src/operations/profile.ts
7712
- var profile_exports = {};
7713
- __export(profile_exports, {
7714
- updateProfile: () => updateProfile
7715
- });
7716
- async function updateProfile(arbi, body) {
7717
- return requireData(
7718
- await arbi.fetch.PATCH("/v1/user/profile", { body }),
7719
- "Failed to update profile"
7720
- );
7721
- }
7722
-
7723
7862
  // src/listen/index.ts
7724
7863
  var listen_exports = {};
7725
7864
  __export(listen_exports, {
@@ -8031,6 +8170,7 @@ exports.DOC_TERMINAL_STATUSES = DOC_TERMINAL_STATUSES;
8031
8170
  exports.FileConfigStore = FileConfigStore;
8032
8171
  exports.OpenClawOrchestrator = OpenClawOrchestrator;
8033
8172
  exports.WebSocketAuthError = WebSocketAuthError;
8173
+ exports.account = account_exports;
8034
8174
  exports.agentconfig = agentconfig_exports;
8035
8175
  exports.agents = agents_exports;
8036
8176
  exports.assistant = assistant_exports;