@arbidocs/sdk 0.4.3 → 0.4.4

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/browser.cjs CHANGED
@@ -3644,6 +3644,16 @@ async function selectWorkspace(arbi, workspaceId, wrappedKey, serverSessionKey,
3644
3644
  arbi.session.setSelectedWorkspace(workspaceId);
3645
3645
  return header;
3646
3646
  }
3647
+ async function generateEncryptedWorkspaceKey(arbi, wrappedKey, serverSessionKey, signingPrivateKeyBase64) {
3648
+ const signingPrivateKey = client.base64ToBytes(signingPrivateKeyBase64);
3649
+ const ed25519PublicKey = signingPrivateKey.slice(32, 64);
3650
+ const encryptionKeyPair = client.deriveEncryptionKeypairFromSigning({
3651
+ publicKey: ed25519PublicKey,
3652
+ secretKey: signingPrivateKey
3653
+ });
3654
+ const workspaceKey = client.sealedBoxDecrypt(wrappedKey, encryptionKeyPair.secretKey);
3655
+ return client.sealKeyForSession(workspaceKey, serverSessionKey);
3656
+ }
3647
3657
  async function getRawWorkspaceKey(arbi, workspaceId, signingPrivateKeyBase64) {
3648
3658
  const { data: workspaces, error } = await arbi.fetch.GET("/v1/user/workspaces");
3649
3659
  if (error || !workspaces) {
@@ -4666,6 +4676,7 @@ __export(workspaces_exports, {
4666
4676
  copyDocuments: () => copyDocuments,
4667
4677
  createWorkspace: () => createWorkspace,
4668
4678
  deleteWorkspaces: () => deleteWorkspaces,
4679
+ grantTemporaryWorkspaceAccess: () => grantTemporaryWorkspaceAccess,
4669
4680
  listWorkspaceUsers: () => listWorkspaceUsers,
4670
4681
  listWorkspaces: () => listWorkspaces,
4671
4682
  removeWorkspaceUsers: () => removeWorkspaceUsers,
@@ -4706,14 +4717,33 @@ async function updateWorkspace(arbi, body) {
4706
4717
  async function listWorkspaceUsers(arbi) {
4707
4718
  return requireData(await arbi.fetch.GET("/v1/workspace/users"), "Failed to fetch workspace users");
4708
4719
  }
4709
- async function addWorkspaceUsers(arbi, emails, role = "collaborator") {
4720
+ async function addWorkspaceUsers(arbi, emails, role = "collaborator", target) {
4710
4721
  return requireData(
4711
4722
  await arbi.fetch.POST("/v1/workspace/users", {
4712
- body: { emails, role }
4723
+ body: target ? {
4724
+ emails,
4725
+ role,
4726
+ workspace_ext_id: target.workspaceExtId,
4727
+ workspace_key: target.workspaceKey
4728
+ } : { emails, role }
4713
4729
  }),
4714
4730
  "Failed to add users"
4715
4731
  );
4716
4732
  }
4733
+ async function grantTemporaryWorkspaceAccess(arbi, params) {
4734
+ return requireData(
4735
+ await arbi.fetch.POST("/v1/workspace/users", {
4736
+ body: {
4737
+ emails: params.emails,
4738
+ role: params.role ?? "collaborator",
4739
+ workspace_ext_id: params.workspaceExtId,
4740
+ workspace_key: params.workspaceKey,
4741
+ session_pubkey_b64: params.sessionPubkeyB64
4742
+ }
4743
+ }),
4744
+ "Failed to grant temporary access"
4745
+ );
4746
+ }
4717
4747
  async function removeWorkspaceUsers(arbi, userIds) {
4718
4748
  requireOk(
4719
4749
  await arbi.fetch.DELETE("/v1/workspace/users", {
@@ -5138,6 +5168,21 @@ async function deleteAgents(arbi, agentExtIds) {
5138
5168
  "Failed to delete agents"
5139
5169
  );
5140
5170
  }
5171
+ async function authorizeAgent(arbi, agentExtId, workspaceExtId, ttlSeconds) {
5172
+ return requireData(
5173
+ await arbi.fetch.POST("/v1/agents/{agent_ext_id}/authorize", {
5174
+ params: { path: { agent_ext_id: agentExtId } },
5175
+ body: { workspace_ext_id: workspaceExtId, ttl_seconds: ttlSeconds ?? null }
5176
+ }),
5177
+ "Failed to authorize agent"
5178
+ );
5179
+ }
5180
+ async function getAuthorizeLimits(arbi) {
5181
+ return requireData(
5182
+ await arbi.fetch.GET("/v1/agents/authorize-limits"),
5183
+ "Failed to fetch authorize limits"
5184
+ );
5185
+ }
5141
5186
 
5142
5187
  // src/operations/dm.ts
5143
5188
  function createDmCryptoContext(arbi, signingPrivateKeyBytes, userExtId) {
@@ -5520,6 +5565,7 @@ __export(tasks_exports, {
5520
5565
  createTask: () => createTask,
5521
5566
  deleteTask: () => deleteTask,
5522
5567
  getTask: () => getTask,
5568
+ listTaskRuns: () => listTaskRuns,
5523
5569
  listTasks: () => listTasks,
5524
5570
  runTask: () => runTask,
5525
5571
  updateTask: () => updateTask
@@ -5557,6 +5603,12 @@ async function runTask(arbi, taskId) {
5557
5603
  "Failed to run task"
5558
5604
  );
5559
5605
  }
5606
+ async function listTaskRuns(arbi, taskId) {
5607
+ return requireData(
5608
+ await arbi.fetch.GET("/v1/tasks/{task_id}/runs", { params: { path: { task_id: taskId } } }),
5609
+ "Failed to list task runs"
5610
+ );
5611
+ }
5560
5612
 
5561
5613
  // src/operations/facts.ts
5562
5614
  var facts_exports = {};
@@ -5698,6 +5750,22 @@ var Arbi = class {
5698
5750
  const signingPrivateKey = client.crypto.base64ToBytes(signingPrivateKeyBase64);
5699
5751
  this.loginResult = await client.auth.loginWithKey({ email, signingPrivateKey });
5700
5752
  }
5753
+ /** A workspace's key, sealed to the caller's own session (what `/open` and `POST /workspace/users` take). */
5754
+ async sealWorkspaceKey(workspaceId) {
5755
+ const client = this.requireClient();
5756
+ const lr2 = this.requireLogin();
5757
+ const all = await listWorkspaces(client);
5758
+ const ws = all.find((w2) => w2.external_id === workspaceId);
5759
+ if (!ws || !ws.wrapped_key) {
5760
+ throw new ArbiError(`Workspace ${workspaceId} not found or has no encryption key`);
5761
+ }
5762
+ return generateEncryptedWorkspaceKey(
5763
+ client,
5764
+ ws.wrapped_key,
5765
+ lr2.serverSessionKey,
5766
+ client.crypto.bytesToBase64(lr2.signingPrivateKey)
5767
+ );
5768
+ }
5701
5769
  /**
5702
5770
  * Select a workspace by ID. Fetches the workspace list, finds the matching
5703
5771
  * workspace, decrypts the wrapped key, and sets up auth headers.
@@ -5880,6 +5948,30 @@ var Arbi = class {
5880
5948
  update: (body) => updateWorkspace(this.requireClient(), body),
5881
5949
  listUsers: () => listWorkspaceUsers(this.requireClient()),
5882
5950
  addUsers: (emails, role) => addWorkspaceUsers(this.requireClient(), emails, role),
5951
+ /**
5952
+ * Grant users a temporary key scoped to ONE session (identified by its public key), for
5953
+ * example an agent's run session minted by `agents.authorize()`. Nothing standing is created:
5954
+ * the grant expires with that session. Works for any workspace the caller holds a key for;
5955
+ * it does not need to be the open one.
5956
+ */
5957
+ grantTemporaryAccess: async (params) => {
5958
+ const client = this.requireClient();
5959
+ return grantTemporaryWorkspaceAccess(client, {
5960
+ emails: params.emails,
5961
+ workspaceExtId: params.workspaceId,
5962
+ workspaceKey: await this.sealWorkspaceKey(params.workspaceId),
5963
+ sessionPubkeyB64: params.sessionPubkeyB64,
5964
+ role: params.role
5965
+ });
5966
+ },
5967
+ /**
5968
+ * Add users (standing, permanent membership) to ANY workspace the caller holds a key for,
5969
+ * without opening it. `addUsers` does the same for the currently open workspace.
5970
+ */
5971
+ grantAccess: async (params) => addWorkspaceUsers(this.requireClient(), params.emails, params.role, {
5972
+ workspaceExtId: params.workspaceId,
5973
+ workspaceKey: await this.sealWorkspaceKey(params.workspaceId)
5974
+ }),
5883
5975
  removeUsers: (userIds) => removeWorkspaceUsers(this.requireClient(), userIds),
5884
5976
  setUserRole: (userIds, role) => setUserRole(this.requireClient(), userIds, role),
5885
5977
  /**
@@ -5995,6 +6087,8 @@ var Arbi = class {
5995
6087
  * Respond to an agent's question during a human-in-the-loop workflow.
5996
6088
  */
5997
6089
  respond: (assistantMessageExtId, answer) => respondToAgent(this.requireClient(), assistantMessageExtId, answer),
6090
+ /** The skills the caller can run (own + shared marketplace), metadata only. */
6091
+ listSkills: (options) => listSkills(this.requireClient(), options),
5998
6092
  /**
5999
6093
  * Search documents without LLM generation (retrieval only).
6000
6094
  */
@@ -6151,7 +6245,28 @@ var Arbi = class {
6151
6245
  create: (name) => createAgent(this.requireClient(), name),
6152
6246
  getConfig: (agentExtId) => getAgentConfig(this.requireClient(), agentExtId),
6153
6247
  listWorkspaces: (agentExtId) => listAgentWorkspaces(this.requireClient(), agentExtId),
6154
- delete: (agentExtIds) => deleteAgents(this.requireClient(), agentExtIds)
6248
+ delete: (agentExtIds) => deleteAgents(this.requireClient(), agentExtIds),
6249
+ /** Mint a TTL'd run session for an agent; see `grantTemporaryAccess` to also deposit a key. */
6250
+ authorize: (agentExtId, workspaceId, ttlSeconds) => authorizeAgent(this.requireClient(), agentExtId, workspaceId, ttlSeconds),
6251
+ authorizeLimits: () => getAuthorizeLimits(this.requireClient()),
6252
+ /**
6253
+ * Give an agent temporary, session-scoped access to a workspace: mint its run session, then
6254
+ * deposit the workspace key on it. Returns the session details (`ttl` in seconds).
6255
+ */
6256
+ grantTemporaryAccess: async (agentExtId, workspaceId, ttlSeconds) => {
6257
+ const session = await authorizeAgent(
6258
+ this.requireClient(),
6259
+ agentExtId,
6260
+ workspaceId,
6261
+ ttlSeconds
6262
+ );
6263
+ await this.workspaces.grantTemporaryAccess({
6264
+ workspaceId,
6265
+ emails: [session.agent_email],
6266
+ sessionPubkeyB64: session.session_pubkey_b64
6267
+ });
6268
+ return session;
6269
+ }
6155
6270
  };
6156
6271
  // ── Scheduled tasks ───────────────────────────────────────────────────
6157
6272
  tasks = {
@@ -6160,7 +6275,26 @@ var Arbi = class {
6160
6275
  get: (taskId) => getTask(this.requireClient(), taskId),
6161
6276
  update: (taskId, body) => updateTask(this.requireClient(), taskId, body),
6162
6277
  delete: (taskId) => deleteTask(this.requireClient(), taskId),
6163
- run: (taskId) => runTask(this.requireClient(), taskId)
6278
+ run: (taskId) => runTask(this.requireClient(), taskId),
6279
+ listRuns: (taskId) => listTaskRuns(this.requireClient(), taskId),
6280
+ /**
6281
+ * Run a task and, when the run is parked waiting for workspace access (a temporary
6282
+ * authorization tier), grant the agent's run session a temporary key and run it again.
6283
+ * A task that needs no approval returns from the first call already running.
6284
+ */
6285
+ runWithAuth: async (taskId) => {
6286
+ const client = this.requireClient();
6287
+ const first = await runTask(client, taskId);
6288
+ if (!first.pending_auth_request_id || !first.pending_auth_session_pubkey || !first.pending_auth_agent_email || !first.workspace_ext_id) {
6289
+ return first;
6290
+ }
6291
+ await this.workspaces.grantTemporaryAccess({
6292
+ workspaceId: first.workspace_ext_id,
6293
+ emails: [first.pending_auth_agent_email],
6294
+ sessionPubkeyB64: first.pending_auth_session_pubkey
6295
+ });
6296
+ return runTask(client, taskId);
6297
+ }
6164
6298
  };
6165
6299
  // ── Workspace facts ─────────────────────────────────────────────────
6166
6300
  facts = {