@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.
@@ -1,2 +1,2 @@
1
- export { A as AgentControlStateEvent, a as AgentStepDeltaEvent, b as AgentStepEvent, c as Arbi, d as ArbiApiError, e as ArbiError, f as ArbiErrorEvent, g as ArbiOptions, i as ArtifactEvent, j as AuthContext, k as AuthHeaders, l as AuthenticatedClient, C as ChatSession, m as CitationSummary, n as CliConfig, o as CliCredentials, p as CommandDescriptor, q as ConfigStore, r as ConnectOptions, s as CreateFactRequest, t as CreateFactsRequest, u as CreateTaskRequest, v as DeferredInterjectionEvent, F as FactResponse, G as FactSearchRequest, H as FactSearchResponse, J as ListFactsOptions, N as MessageMetadataPayload, O as MessageQueuedEvent, P as OutputTokensDetails, Q as ParsedSlashCommand, R as ProbeAnswerEvent, S as ProjectInvoicesResponse, T as ProjectUsageResponse, U as QueryOptions, V as ReconnectOptions, W as ReconnectableWsConnection, X as ResolvedCitation, Z as ResponseCompletedEvent, _ as ResponseContentPartAddedEvent, $ as ResponseCreatedEvent, a0 as ResponseFailedEvent, a1 as ResponseOutputItemAddedEvent, a2 as ResponseOutputItemDoneEvent, a3 as ResponseOutputTextDeltaEvent, a4 as ResponseOutputTextDoneEvent, a5 as ResponseUsage, a6 as SSEEvent, a7 as SSEStreamCallbacks, a8 as SSEStreamResult, a9 as SSEStreamStartData, ab as SkillSummary, ad as TaskResponse, ae as TokenBudgetContext, af as UpdateFactRequest, ag as UpdateTaskRequest, am as UserDailyUsageResponse, an as UserInfo, ao as UserInputRequestEvent, ap as UserMessageEvent, aq as WebSocketAuthError, ar as WorkspaceContext, as as WsConnection, at as agentconfig, au as assistant, av as authenticatedFetch, ax as buildRetrievalChunkTool, ay as buildRetrievalFullContextTool, az as buildRetrievalTocTool, aA as connectWebSocket, aB as connectWithReconnect, aC as consumeSSEStream, aD as contacts, aE as conversations, aF as countCitations, aG as createAuthenticatedClient, aI as dm, aJ as doctags, aK as documents, aL as facts, aM as files, aN as filterSkills, aO as formatAgentStepLabel, aP as formatFileSize, aQ as formatItemLabel, aS as formatUserName, aT as formatWorkspaceChoices, aY as getErrorMessage, aZ as getRawWorkspaceKey, a_ as health, a$ as parseSSEEvents, b0 as parseSlashCommand, b1 as parseSlashTokenInProgress, b2 as performPasswordLogin, b5 as projects, b6 as requireData, b7 as requireOk, b8 as resolveAuth, b9 as resolveCitations, ba as resolveWorkspace, bb as responses, bc as selectWorkspace, bd as selectWorkspaceById, be as settings, bf as streamSSE, bg as stripCitationMarkdown, bh as summarizeCitations, bi as tags, bj as tasks, bk as workspaces } from './browser-4VHbRx1J.cjs';
1
+ export { A as AgentControlStateEvent, a as AgentStepDeltaEvent, b as AgentStepEvent, c as Arbi, d as ArbiApiError, e as ArbiError, f as ArbiErrorEvent, g as ArbiOptions, i as ArtifactEvent, j as AuthContext, k as AuthHeaders, l as AuthenticatedClient, C as ChatSession, m as CitationSummary, n as CliConfig, o as CliCredentials, p as CommandDescriptor, q as ConfigStore, r as ConnectOptions, s as CreateFactRequest, t as CreateFactsRequest, u as CreateTaskRequest, v as DeferredInterjectionEvent, F as FactResponse, G as FactSearchRequest, H as FactSearchResponse, J as ListFactsOptions, N as MessageMetadataPayload, O as MessageQueuedEvent, P as OutputTokensDetails, Q as ParsedSlashCommand, R as ProbeAnswerEvent, S as ProjectInvoicesResponse, T as ProjectUsageResponse, U as QueryOptions, V as ReconnectOptions, W as ReconnectableWsConnection, X as ResolvedCitation, Z as ResponseCompletedEvent, _ as ResponseContentPartAddedEvent, $ as ResponseCreatedEvent, a0 as ResponseFailedEvent, a1 as ResponseOutputItemAddedEvent, a2 as ResponseOutputItemDoneEvent, a3 as ResponseOutputTextDeltaEvent, a4 as ResponseOutputTextDoneEvent, a5 as ResponseUsage, a6 as SSEEvent, a7 as SSEStreamCallbacks, a8 as SSEStreamResult, a9 as SSEStreamStartData, ab as SkillSummary, ad as TaskResponse, ae as TokenBudgetContext, af as UpdateFactRequest, ag as UpdateTaskRequest, am as UserDailyUsageResponse, an as UserInfo, ao as UserInputRequestEvent, ap as UserMessageEvent, aq as WebSocketAuthError, ar as WorkspaceContext, as as WsConnection, at as agentconfig, au as assistant, av as authenticatedFetch, ax as buildRetrievalChunkTool, ay as buildRetrievalFullContextTool, az as buildRetrievalTocTool, aA as connectWebSocket, aB as connectWithReconnect, aC as consumeSSEStream, aD as contacts, aE as conversations, aF as countCitations, aG as createAuthenticatedClient, aI as dm, aJ as doctags, aK as documents, aL as facts, aM as files, aN as filterSkills, aO as formatAgentStepLabel, aP as formatFileSize, aQ as formatItemLabel, aS as formatUserName, aT as formatWorkspaceChoices, aY as getErrorMessage, aZ as getRawWorkspaceKey, a_ as health, a$ as parseSSEEvents, b0 as parseSlashCommand, b1 as parseSlashTokenInProgress, b2 as performPasswordLogin, b5 as projects, b6 as requireData, b7 as requireOk, b8 as resolveAuth, b9 as resolveCitations, ba as resolveWorkspace, bb as responses, bc as selectWorkspace, bd as selectWorkspaceById, be as settings, bf as streamSSE, bg as stripCitationMarkdown, bh as summarizeCitations, bi as tags, bj as tasks, bk as workspaces } from './browser-Bdzn5DIN.cjs';
2
2
  import '@arbidocs/client';
package/dist/browser.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { A as AgentControlStateEvent, a as AgentStepDeltaEvent, b as AgentStepEvent, c as Arbi, d as ArbiApiError, e as ArbiError, f as ArbiErrorEvent, g as ArbiOptions, i as ArtifactEvent, j as AuthContext, k as AuthHeaders, l as AuthenticatedClient, C as ChatSession, m as CitationSummary, n as CliConfig, o as CliCredentials, p as CommandDescriptor, q as ConfigStore, r as ConnectOptions, s as CreateFactRequest, t as CreateFactsRequest, u as CreateTaskRequest, v as DeferredInterjectionEvent, F as FactResponse, G as FactSearchRequest, H as FactSearchResponse, J as ListFactsOptions, N as MessageMetadataPayload, O as MessageQueuedEvent, P as OutputTokensDetails, Q as ParsedSlashCommand, R as ProbeAnswerEvent, S as ProjectInvoicesResponse, T as ProjectUsageResponse, U as QueryOptions, V as ReconnectOptions, W as ReconnectableWsConnection, X as ResolvedCitation, Z as ResponseCompletedEvent, _ as ResponseContentPartAddedEvent, $ as ResponseCreatedEvent, a0 as ResponseFailedEvent, a1 as ResponseOutputItemAddedEvent, a2 as ResponseOutputItemDoneEvent, a3 as ResponseOutputTextDeltaEvent, a4 as ResponseOutputTextDoneEvent, a5 as ResponseUsage, a6 as SSEEvent, a7 as SSEStreamCallbacks, a8 as SSEStreamResult, a9 as SSEStreamStartData, ab as SkillSummary, ad as TaskResponse, ae as TokenBudgetContext, af as UpdateFactRequest, ag as UpdateTaskRequest, am as UserDailyUsageResponse, an as UserInfo, ao as UserInputRequestEvent, ap as UserMessageEvent, aq as WebSocketAuthError, ar as WorkspaceContext, as as WsConnection, at as agentconfig, au as assistant, av as authenticatedFetch, ax as buildRetrievalChunkTool, ay as buildRetrievalFullContextTool, az as buildRetrievalTocTool, aA as connectWebSocket, aB as connectWithReconnect, aC as consumeSSEStream, aD as contacts, aE as conversations, aF as countCitations, aG as createAuthenticatedClient, aI as dm, aJ as doctags, aK as documents, aL as facts, aM as files, aN as filterSkills, aO as formatAgentStepLabel, aP as formatFileSize, aQ as formatItemLabel, aS as formatUserName, aT as formatWorkspaceChoices, aY as getErrorMessage, aZ as getRawWorkspaceKey, a_ as health, a$ as parseSSEEvents, b0 as parseSlashCommand, b1 as parseSlashTokenInProgress, b2 as performPasswordLogin, b5 as projects, b6 as requireData, b7 as requireOk, b8 as resolveAuth, b9 as resolveCitations, ba as resolveWorkspace, bb as responses, bc as selectWorkspace, bd as selectWorkspaceById, be as settings, bf as streamSSE, bg as stripCitationMarkdown, bh as summarizeCitations, bi as tags, bj as tasks, bk as workspaces } from './browser-4VHbRx1J.js';
1
+ export { A as AgentControlStateEvent, a as AgentStepDeltaEvent, b as AgentStepEvent, c as Arbi, d as ArbiApiError, e as ArbiError, f as ArbiErrorEvent, g as ArbiOptions, i as ArtifactEvent, j as AuthContext, k as AuthHeaders, l as AuthenticatedClient, C as ChatSession, m as CitationSummary, n as CliConfig, o as CliCredentials, p as CommandDescriptor, q as ConfigStore, r as ConnectOptions, s as CreateFactRequest, t as CreateFactsRequest, u as CreateTaskRequest, v as DeferredInterjectionEvent, F as FactResponse, G as FactSearchRequest, H as FactSearchResponse, J as ListFactsOptions, N as MessageMetadataPayload, O as MessageQueuedEvent, P as OutputTokensDetails, Q as ParsedSlashCommand, R as ProbeAnswerEvent, S as ProjectInvoicesResponse, T as ProjectUsageResponse, U as QueryOptions, V as ReconnectOptions, W as ReconnectableWsConnection, X as ResolvedCitation, Z as ResponseCompletedEvent, _ as ResponseContentPartAddedEvent, $ as ResponseCreatedEvent, a0 as ResponseFailedEvent, a1 as ResponseOutputItemAddedEvent, a2 as ResponseOutputItemDoneEvent, a3 as ResponseOutputTextDeltaEvent, a4 as ResponseOutputTextDoneEvent, a5 as ResponseUsage, a6 as SSEEvent, a7 as SSEStreamCallbacks, a8 as SSEStreamResult, a9 as SSEStreamStartData, ab as SkillSummary, ad as TaskResponse, ae as TokenBudgetContext, af as UpdateFactRequest, ag as UpdateTaskRequest, am as UserDailyUsageResponse, an as UserInfo, ao as UserInputRequestEvent, ap as UserMessageEvent, aq as WebSocketAuthError, ar as WorkspaceContext, as as WsConnection, at as agentconfig, au as assistant, av as authenticatedFetch, ax as buildRetrievalChunkTool, ay as buildRetrievalFullContextTool, az as buildRetrievalTocTool, aA as connectWebSocket, aB as connectWithReconnect, aC as consumeSSEStream, aD as contacts, aE as conversations, aF as countCitations, aG as createAuthenticatedClient, aI as dm, aJ as doctags, aK as documents, aL as facts, aM as files, aN as filterSkills, aO as formatAgentStepLabel, aP as formatFileSize, aQ as formatItemLabel, aS as formatUserName, aT as formatWorkspaceChoices, aY as getErrorMessage, aZ as getRawWorkspaceKey, a_ as health, a$ as parseSSEEvents, b0 as parseSlashCommand, b1 as parseSlashTokenInProgress, b2 as performPasswordLogin, b5 as projects, b6 as requireData, b7 as requireOk, b8 as resolveAuth, b9 as resolveCitations, ba as resolveWorkspace, bb as responses, bc as selectWorkspace, bd as selectWorkspaceById, be as settings, bf as streamSSE, bg as stripCitationMarkdown, bh as summarizeCitations, bi as tags, bj as tasks, bk as workspaces } from './browser-Bdzn5DIN.js';
2
2
  import '@arbidocs/client';
package/dist/browser.js CHANGED
@@ -3641,6 +3641,16 @@ async function selectWorkspace(arbi, workspaceId, wrappedKey, serverSessionKey,
3641
3641
  arbi.session.setSelectedWorkspace(workspaceId);
3642
3642
  return header;
3643
3643
  }
3644
+ async function generateEncryptedWorkspaceKey(arbi, wrappedKey, serverSessionKey, signingPrivateKeyBase64) {
3645
+ const signingPrivateKey = base64ToBytes(signingPrivateKeyBase64);
3646
+ const ed25519PublicKey = signingPrivateKey.slice(32, 64);
3647
+ const encryptionKeyPair = deriveEncryptionKeypairFromSigning({
3648
+ publicKey: ed25519PublicKey,
3649
+ secretKey: signingPrivateKey
3650
+ });
3651
+ const workspaceKey = sealedBoxDecrypt(wrappedKey, encryptionKeyPair.secretKey);
3652
+ return sealKeyForSession(workspaceKey, serverSessionKey);
3653
+ }
3644
3654
  async function getRawWorkspaceKey(arbi, workspaceId, signingPrivateKeyBase64) {
3645
3655
  const { data: workspaces, error } = await arbi.fetch.GET("/v1/user/workspaces");
3646
3656
  if (error || !workspaces) {
@@ -4663,6 +4673,7 @@ __export(workspaces_exports, {
4663
4673
  copyDocuments: () => copyDocuments,
4664
4674
  createWorkspace: () => createWorkspace,
4665
4675
  deleteWorkspaces: () => deleteWorkspaces,
4676
+ grantTemporaryWorkspaceAccess: () => grantTemporaryWorkspaceAccess,
4666
4677
  listWorkspaceUsers: () => listWorkspaceUsers,
4667
4678
  listWorkspaces: () => listWorkspaces,
4668
4679
  removeWorkspaceUsers: () => removeWorkspaceUsers,
@@ -4703,14 +4714,33 @@ async function updateWorkspace(arbi, body) {
4703
4714
  async function listWorkspaceUsers(arbi) {
4704
4715
  return requireData(await arbi.fetch.GET("/v1/workspace/users"), "Failed to fetch workspace users");
4705
4716
  }
4706
- async function addWorkspaceUsers(arbi, emails, role = "collaborator") {
4717
+ async function addWorkspaceUsers(arbi, emails, role = "collaborator", target) {
4707
4718
  return requireData(
4708
4719
  await arbi.fetch.POST("/v1/workspace/users", {
4709
- body: { emails, role }
4720
+ body: target ? {
4721
+ emails,
4722
+ role,
4723
+ workspace_ext_id: target.workspaceExtId,
4724
+ workspace_key: target.workspaceKey
4725
+ } : { emails, role }
4710
4726
  }),
4711
4727
  "Failed to add users"
4712
4728
  );
4713
4729
  }
4730
+ async function grantTemporaryWorkspaceAccess(arbi, params) {
4731
+ return requireData(
4732
+ await arbi.fetch.POST("/v1/workspace/users", {
4733
+ body: {
4734
+ emails: params.emails,
4735
+ role: params.role ?? "collaborator",
4736
+ workspace_ext_id: params.workspaceExtId,
4737
+ workspace_key: params.workspaceKey,
4738
+ session_pubkey_b64: params.sessionPubkeyB64
4739
+ }
4740
+ }),
4741
+ "Failed to grant temporary access"
4742
+ );
4743
+ }
4714
4744
  async function removeWorkspaceUsers(arbi, userIds) {
4715
4745
  requireOk(
4716
4746
  await arbi.fetch.DELETE("/v1/workspace/users", {
@@ -5135,6 +5165,21 @@ async function deleteAgents(arbi, agentExtIds) {
5135
5165
  "Failed to delete agents"
5136
5166
  );
5137
5167
  }
5168
+ async function authorizeAgent(arbi, agentExtId, workspaceExtId, ttlSeconds) {
5169
+ return requireData(
5170
+ await arbi.fetch.POST("/v1/agents/{agent_ext_id}/authorize", {
5171
+ params: { path: { agent_ext_id: agentExtId } },
5172
+ body: { workspace_ext_id: workspaceExtId, ttl_seconds: ttlSeconds ?? null }
5173
+ }),
5174
+ "Failed to authorize agent"
5175
+ );
5176
+ }
5177
+ async function getAuthorizeLimits(arbi) {
5178
+ return requireData(
5179
+ await arbi.fetch.GET("/v1/agents/authorize-limits"),
5180
+ "Failed to fetch authorize limits"
5181
+ );
5182
+ }
5138
5183
 
5139
5184
  // src/operations/dm.ts
5140
5185
  function createDmCryptoContext(arbi, signingPrivateKeyBytes, userExtId) {
@@ -5517,6 +5562,7 @@ __export(tasks_exports, {
5517
5562
  createTask: () => createTask,
5518
5563
  deleteTask: () => deleteTask,
5519
5564
  getTask: () => getTask,
5565
+ listTaskRuns: () => listTaskRuns,
5520
5566
  listTasks: () => listTasks,
5521
5567
  runTask: () => runTask,
5522
5568
  updateTask: () => updateTask
@@ -5554,6 +5600,12 @@ async function runTask(arbi, taskId) {
5554
5600
  "Failed to run task"
5555
5601
  );
5556
5602
  }
5603
+ async function listTaskRuns(arbi, taskId) {
5604
+ return requireData(
5605
+ await arbi.fetch.GET("/v1/tasks/{task_id}/runs", { params: { path: { task_id: taskId } } }),
5606
+ "Failed to list task runs"
5607
+ );
5608
+ }
5557
5609
 
5558
5610
  // src/operations/facts.ts
5559
5611
  var facts_exports = {};
@@ -5695,6 +5747,22 @@ var Arbi = class {
5695
5747
  const signingPrivateKey = client.crypto.base64ToBytes(signingPrivateKeyBase64);
5696
5748
  this.loginResult = await client.auth.loginWithKey({ email, signingPrivateKey });
5697
5749
  }
5750
+ /** A workspace's key, sealed to the caller's own session (what `/open` and `POST /workspace/users` take). */
5751
+ async sealWorkspaceKey(workspaceId) {
5752
+ const client = this.requireClient();
5753
+ const lr2 = this.requireLogin();
5754
+ const all = await listWorkspaces(client);
5755
+ const ws = all.find((w2) => w2.external_id === workspaceId);
5756
+ if (!ws || !ws.wrapped_key) {
5757
+ throw new ArbiError(`Workspace ${workspaceId} not found or has no encryption key`);
5758
+ }
5759
+ return generateEncryptedWorkspaceKey(
5760
+ client,
5761
+ ws.wrapped_key,
5762
+ lr2.serverSessionKey,
5763
+ client.crypto.bytesToBase64(lr2.signingPrivateKey)
5764
+ );
5765
+ }
5698
5766
  /**
5699
5767
  * Select a workspace by ID. Fetches the workspace list, finds the matching
5700
5768
  * workspace, decrypts the wrapped key, and sets up auth headers.
@@ -5877,6 +5945,30 @@ var Arbi = class {
5877
5945
  update: (body) => updateWorkspace(this.requireClient(), body),
5878
5946
  listUsers: () => listWorkspaceUsers(this.requireClient()),
5879
5947
  addUsers: (emails, role) => addWorkspaceUsers(this.requireClient(), emails, role),
5948
+ /**
5949
+ * Grant users a temporary key scoped to ONE session (identified by its public key), for
5950
+ * example an agent's run session minted by `agents.authorize()`. Nothing standing is created:
5951
+ * the grant expires with that session. Works for any workspace the caller holds a key for;
5952
+ * it does not need to be the open one.
5953
+ */
5954
+ grantTemporaryAccess: async (params) => {
5955
+ const client = this.requireClient();
5956
+ return grantTemporaryWorkspaceAccess(client, {
5957
+ emails: params.emails,
5958
+ workspaceExtId: params.workspaceId,
5959
+ workspaceKey: await this.sealWorkspaceKey(params.workspaceId),
5960
+ sessionPubkeyB64: params.sessionPubkeyB64,
5961
+ role: params.role
5962
+ });
5963
+ },
5964
+ /**
5965
+ * Add users (standing, permanent membership) to ANY workspace the caller holds a key for,
5966
+ * without opening it. `addUsers` does the same for the currently open workspace.
5967
+ */
5968
+ grantAccess: async (params) => addWorkspaceUsers(this.requireClient(), params.emails, params.role, {
5969
+ workspaceExtId: params.workspaceId,
5970
+ workspaceKey: await this.sealWorkspaceKey(params.workspaceId)
5971
+ }),
5880
5972
  removeUsers: (userIds) => removeWorkspaceUsers(this.requireClient(), userIds),
5881
5973
  setUserRole: (userIds, role) => setUserRole(this.requireClient(), userIds, role),
5882
5974
  /**
@@ -5992,6 +6084,8 @@ var Arbi = class {
5992
6084
  * Respond to an agent's question during a human-in-the-loop workflow.
5993
6085
  */
5994
6086
  respond: (assistantMessageExtId, answer) => respondToAgent(this.requireClient(), assistantMessageExtId, answer),
6087
+ /** The skills the caller can run (own + shared marketplace), metadata only. */
6088
+ listSkills: (options) => listSkills(this.requireClient(), options),
5995
6089
  /**
5996
6090
  * Search documents without LLM generation (retrieval only).
5997
6091
  */
@@ -6148,7 +6242,28 @@ var Arbi = class {
6148
6242
  create: (name) => createAgent(this.requireClient(), name),
6149
6243
  getConfig: (agentExtId) => getAgentConfig(this.requireClient(), agentExtId),
6150
6244
  listWorkspaces: (agentExtId) => listAgentWorkspaces(this.requireClient(), agentExtId),
6151
- delete: (agentExtIds) => deleteAgents(this.requireClient(), agentExtIds)
6245
+ delete: (agentExtIds) => deleteAgents(this.requireClient(), agentExtIds),
6246
+ /** Mint a TTL'd run session for an agent; see `grantTemporaryAccess` to also deposit a key. */
6247
+ authorize: (agentExtId, workspaceId, ttlSeconds) => authorizeAgent(this.requireClient(), agentExtId, workspaceId, ttlSeconds),
6248
+ authorizeLimits: () => getAuthorizeLimits(this.requireClient()),
6249
+ /**
6250
+ * Give an agent temporary, session-scoped access to a workspace: mint its run session, then
6251
+ * deposit the workspace key on it. Returns the session details (`ttl` in seconds).
6252
+ */
6253
+ grantTemporaryAccess: async (agentExtId, workspaceId, ttlSeconds) => {
6254
+ const session = await authorizeAgent(
6255
+ this.requireClient(),
6256
+ agentExtId,
6257
+ workspaceId,
6258
+ ttlSeconds
6259
+ );
6260
+ await this.workspaces.grantTemporaryAccess({
6261
+ workspaceId,
6262
+ emails: [session.agent_email],
6263
+ sessionPubkeyB64: session.session_pubkey_b64
6264
+ });
6265
+ return session;
6266
+ }
6152
6267
  };
6153
6268
  // ── Scheduled tasks ───────────────────────────────────────────────────
6154
6269
  tasks = {
@@ -6157,7 +6272,26 @@ var Arbi = class {
6157
6272
  get: (taskId) => getTask(this.requireClient(), taskId),
6158
6273
  update: (taskId, body) => updateTask(this.requireClient(), taskId, body),
6159
6274
  delete: (taskId) => deleteTask(this.requireClient(), taskId),
6160
- run: (taskId) => runTask(this.requireClient(), taskId)
6275
+ run: (taskId) => runTask(this.requireClient(), taskId),
6276
+ listRuns: (taskId) => listTaskRuns(this.requireClient(), taskId),
6277
+ /**
6278
+ * Run a task and, when the run is parked waiting for workspace access (a temporary
6279
+ * authorization tier), grant the agent's run session a temporary key and run it again.
6280
+ * A task that needs no approval returns from the first call already running.
6281
+ */
6282
+ runWithAuth: async (taskId) => {
6283
+ const client = this.requireClient();
6284
+ const first = await runTask(client, taskId);
6285
+ if (!first.pending_auth_request_id || !first.pending_auth_session_pubkey || !first.pending_auth_agent_email || !first.workspace_ext_id) {
6286
+ return first;
6287
+ }
6288
+ await this.workspaces.grantTemporaryAccess({
6289
+ workspaceId: first.workspace_ext_id,
6290
+ emails: [first.pending_auth_agent_email],
6291
+ sessionPubkeyB64: first.pending_auth_session_pubkey
6292
+ });
6293
+ return runTask(client, taskId);
6294
+ }
6161
6295
  };
6162
6296
  // ── Workspace facts ─────────────────────────────────────────────────
6163
6297
  facts = {