@arbidocs/sdk 0.4.5 → 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);
@@ -5476,7 +5477,7 @@ async function retrieve(options) {
5476
5477
  return data;
5477
5478
  }
5478
5479
  async function queryAssistant(options) {
5479
- const { workspaceId, question, docIds, previousResponseId, model, ...auth } = options;
5480
+ const { workspaceId, question, docIds, previousResponseId, model, signal, ...auth } = options;
5480
5481
  const body = {
5481
5482
  input: question,
5482
5483
  workspace_ext_id: workspaceId,
@@ -5495,7 +5496,8 @@ async function queryAssistant(options) {
5495
5496
  path: "/v1/assistant/query",
5496
5497
  method: "POST",
5497
5498
  body: JSON.stringify(body),
5498
- headers: { "Content-Type": "application/json" }
5499
+ headers: { "Content-Type": "application/json" },
5500
+ signal
5499
5501
  });
5500
5502
  }
5501
5503
  async function respondToAgent(arbi, assistantMessageExtId, answer) {
@@ -6043,11 +6045,76 @@ async function getFileContent(auth, fileId) {
6043
6045
  // src/operations/sessions.ts
6044
6046
  var sessions_exports = {};
6045
6047
  __export(sessions_exports, {
6046
- listSessions: () => listSessions
6048
+ currentSessionId: () => currentSessionId,
6049
+ listSessions: () => listSessions,
6050
+ logoutAllSessions: () => logoutAllSessions,
6051
+ terminateSession: () => terminateSession
6047
6052
  });
6048
6053
  async function listSessions(arbi) {
6049
6054
  return requireData(await arbi.fetch.GET("/v1/user/sessions"), "Failed to fetch sessions");
6050
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
+ }
6051
6118
 
6052
6119
  // src/operations/projects.ts
6053
6120
  var projects_exports = {};
@@ -6257,6 +6324,8 @@ function tokenExpiresWithin(token, seconds) {
6257
6324
  var Arbi = class {
6258
6325
  client = null;
6259
6326
  loginResult = null;
6327
+ userProfile = null;
6328
+ profileListeners = /* @__PURE__ */ new Set();
6260
6329
  currentWorkspaceId = null;
6261
6330
  dmCryptoContext = null;
6262
6331
  sessionExpiredListeners = /* @__PURE__ */ new Set();
@@ -6305,6 +6374,7 @@ var Arbi = class {
6305
6374
  async login(email, password) {
6306
6375
  const client = await this.init();
6307
6376
  this.loginResult = await client.auth.login({ email, password });
6377
+ this.userProfile = this.loginResult.profile ?? null;
6308
6378
  }
6309
6379
  /**
6310
6380
  * Recover a session using a stored signing private key (base64).
@@ -6314,6 +6384,7 @@ var Arbi = class {
6314
6384
  const client = await this.init();
6315
6385
  const signingPrivateKey = client.crypto.base64ToBytes(signingPrivateKeyBase64);
6316
6386
  this.loginResult = await client.auth.loginWithKey({ email, signingPrivateKey });
6387
+ this.userProfile = this.loginResult.profile ?? null;
6317
6388
  }
6318
6389
  /** A workspace's key, sealed to the caller's own session (what `/open` and `POST /workspace/users` take). */
6319
6390
  async sealWorkspaceKey(workspaceId) {
@@ -6373,6 +6444,7 @@ var Arbi = class {
6373
6444
  this.loginResult.serverSessionKey.fill(0);
6374
6445
  }
6375
6446
  this.loginResult = null;
6447
+ this.userProfile = null;
6376
6448
  this.currentWorkspaceId = null;
6377
6449
  this.dmCryptoContext = null;
6378
6450
  this.client?.session.clear();
@@ -6403,6 +6475,10 @@ var Arbi = class {
6403
6475
  return run();
6404
6476
  }
6405
6477
  }
6478
+ setUserProfile(profile) {
6479
+ this.userProfile = profile;
6480
+ for (const listener of [...this.profileListeners]) listener(profile);
6481
+ }
6406
6482
  /** Log out and clear internal state. */
6407
6483
  async logout() {
6408
6484
  if (this.client) {
@@ -6413,6 +6489,7 @@ var Arbi = class {
6413
6489
  this.loginResult.serverSessionKey.fill(0);
6414
6490
  }
6415
6491
  this.loginResult = null;
6492
+ this.userProfile = null;
6416
6493
  this.currentWorkspaceId = null;
6417
6494
  this.dmCryptoContext = null;
6418
6495
  }
@@ -6486,9 +6563,76 @@ var Arbi = class {
6486
6563
  const state = this.requireClient().session.getState();
6487
6564
  return state.userExtId ? { externalId: state.userExtId, email: state.userEmail ?? null } : null;
6488
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
+ },
6489
6578
  /** Today's deployment-wide credit spend for the current user. */
6490
6579
  usageToday: () => getUserUsageToday(this.requireClient())
6491
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
+ };
6492
6636
  // ── Workspaces ────────────────────────────────────────────────────────
6493
6637
  workspaces = {
6494
6638
  list: () => listWorkspaces(this.requireClient()),
@@ -6626,7 +6770,8 @@ var Arbi = class {
6626
6770
  question,
6627
6771
  docIds: options.docIds,
6628
6772
  previousResponseId: options.previousResponseId,
6629
- model: options.model
6773
+ model: options.model,
6774
+ signal: options.signal
6630
6775
  })
6631
6776
  );
6632
6777
  const callbacks = {
@@ -6874,7 +7019,16 @@ var Arbi = class {
6874
7019
  };
6875
7020
  // ── Sessions ────────────────────────────────────────────────────────
6876
7021
  sessions = {
6877
- 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
+ }
6878
7032
  };
6879
7033
  // ── Internal guards ───────────────────────────────────────────────────
6880
7034
  requireClient() {
@@ -7705,18 +7859,6 @@ function extractResponseText(response) {
7705
7859
  return parts.join("");
7706
7860
  }
7707
7861
 
7708
- // src/operations/profile.ts
7709
- var profile_exports = {};
7710
- __export(profile_exports, {
7711
- updateProfile: () => updateProfile
7712
- });
7713
- async function updateProfile(arbi, body) {
7714
- return requireData(
7715
- await arbi.fetch.PATCH("/v1/user/profile", { body }),
7716
- "Failed to update profile"
7717
- );
7718
- }
7719
-
7720
7862
  // src/listen/index.ts
7721
7863
  var listen_exports = {};
7722
7864
  __export(listen_exports, {
@@ -8028,6 +8170,7 @@ exports.DOC_TERMINAL_STATUSES = DOC_TERMINAL_STATUSES;
8028
8170
  exports.FileConfigStore = FileConfigStore;
8029
8171
  exports.OpenClawOrchestrator = OpenClawOrchestrator;
8030
8172
  exports.WebSocketAuthError = WebSocketAuthError;
8173
+ exports.account = account_exports;
8031
8174
  exports.agentconfig = agentconfig_exports;
8032
8175
  exports.agents = agents_exports;
8033
8176
  exports.assistant = assistant_exports;