@arbidocs/sdk 0.4.2 → 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-U90kdb7T.d.cts → browser-Bdzn5DIN.d.cts} +212 -4
- package/dist/{browser-U90kdb7T.d.ts → browser-Bdzn5DIN.d.ts} +212 -4
- package/dist/browser.cjs +233 -24
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +233 -24
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +226 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.js +226 -25
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/browser.cjs
CHANGED
|
@@ -3484,6 +3484,12 @@ var ArbiError = class extends Error {
|
|
|
3484
3484
|
this.name = "ArbiError";
|
|
3485
3485
|
}
|
|
3486
3486
|
};
|
|
3487
|
+
var ArbiSessionExpiredError = class extends ArbiError {
|
|
3488
|
+
constructor(message = "Your session expired. Sign in again.") {
|
|
3489
|
+
super(message);
|
|
3490
|
+
this.name = "ArbiSessionExpiredError";
|
|
3491
|
+
}
|
|
3492
|
+
};
|
|
3487
3493
|
var ArbiApiError = class extends ArbiError {
|
|
3488
3494
|
apiError;
|
|
3489
3495
|
constructor(message, apiError) {
|
|
@@ -3638,6 +3644,16 @@ async function selectWorkspace(arbi, workspaceId, wrappedKey, serverSessionKey,
|
|
|
3638
3644
|
arbi.session.setSelectedWorkspace(workspaceId);
|
|
3639
3645
|
return header;
|
|
3640
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
|
+
}
|
|
3641
3657
|
async function getRawWorkspaceKey(arbi, workspaceId, signingPrivateKeyBase64) {
|
|
3642
3658
|
const { data: workspaces, error } = await arbi.fetch.GET("/v1/user/workspaces");
|
|
3643
3659
|
if (error || !workspaces) {
|
|
@@ -4660,6 +4676,7 @@ __export(workspaces_exports, {
|
|
|
4660
4676
|
copyDocuments: () => copyDocuments,
|
|
4661
4677
|
createWorkspace: () => createWorkspace,
|
|
4662
4678
|
deleteWorkspaces: () => deleteWorkspaces,
|
|
4679
|
+
grantTemporaryWorkspaceAccess: () => grantTemporaryWorkspaceAccess,
|
|
4663
4680
|
listWorkspaceUsers: () => listWorkspaceUsers,
|
|
4664
4681
|
listWorkspaces: () => listWorkspaces,
|
|
4665
4682
|
removeWorkspaceUsers: () => removeWorkspaceUsers,
|
|
@@ -4700,14 +4717,33 @@ async function updateWorkspace(arbi, body) {
|
|
|
4700
4717
|
async function listWorkspaceUsers(arbi) {
|
|
4701
4718
|
return requireData(await arbi.fetch.GET("/v1/workspace/users"), "Failed to fetch workspace users");
|
|
4702
4719
|
}
|
|
4703
|
-
async function addWorkspaceUsers(arbi, emails, role = "collaborator") {
|
|
4720
|
+
async function addWorkspaceUsers(arbi, emails, role = "collaborator", target) {
|
|
4704
4721
|
return requireData(
|
|
4705
4722
|
await arbi.fetch.POST("/v1/workspace/users", {
|
|
4706
|
-
body:
|
|
4723
|
+
body: target ? {
|
|
4724
|
+
emails,
|
|
4725
|
+
role,
|
|
4726
|
+
workspace_ext_id: target.workspaceExtId,
|
|
4727
|
+
workspace_key: target.workspaceKey
|
|
4728
|
+
} : { emails, role }
|
|
4707
4729
|
}),
|
|
4708
4730
|
"Failed to add users"
|
|
4709
4731
|
);
|
|
4710
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
|
+
}
|
|
4711
4747
|
async function removeWorkspaceUsers(arbi, userIds) {
|
|
4712
4748
|
requireOk(
|
|
4713
4749
|
await arbi.fetch.DELETE("/v1/workspace/users", {
|
|
@@ -5132,6 +5168,21 @@ async function deleteAgents(arbi, agentExtIds) {
|
|
|
5132
5168
|
"Failed to delete agents"
|
|
5133
5169
|
);
|
|
5134
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
|
+
}
|
|
5135
5186
|
|
|
5136
5187
|
// src/operations/dm.ts
|
|
5137
5188
|
function createDmCryptoContext(arbi, signingPrivateKeyBytes, userExtId) {
|
|
@@ -5514,6 +5565,7 @@ __export(tasks_exports, {
|
|
|
5514
5565
|
createTask: () => createTask,
|
|
5515
5566
|
deleteTask: () => deleteTask,
|
|
5516
5567
|
getTask: () => getTask,
|
|
5568
|
+
listTaskRuns: () => listTaskRuns,
|
|
5517
5569
|
listTasks: () => listTasks,
|
|
5518
5570
|
runTask: () => runTask,
|
|
5519
5571
|
updateTask: () => updateTask
|
|
@@ -5551,6 +5603,12 @@ async function runTask(arbi, taskId) {
|
|
|
5551
5603
|
"Failed to run task"
|
|
5552
5604
|
);
|
|
5553
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
|
+
}
|
|
5554
5612
|
|
|
5555
5613
|
// src/operations/facts.ts
|
|
5556
5614
|
var facts_exports = {};
|
|
@@ -5620,11 +5678,23 @@ async function remindFact(arbi, factId, options = {}) {
|
|
|
5620
5678
|
}
|
|
5621
5679
|
|
|
5622
5680
|
// src/arbi.ts
|
|
5681
|
+
function tokenExpiresWithin(token, seconds) {
|
|
5682
|
+
const payload = token?.split(".")[1];
|
|
5683
|
+
if (!payload) return false;
|
|
5684
|
+
try {
|
|
5685
|
+
const json = atob(payload.replace(/-/g, "+").replace(/_/g, "/"));
|
|
5686
|
+
const { exp } = JSON.parse(json);
|
|
5687
|
+
return typeof exp === "number" && exp * 1e3 - Date.now() < seconds * 1e3;
|
|
5688
|
+
} catch {
|
|
5689
|
+
return false;
|
|
5690
|
+
}
|
|
5691
|
+
}
|
|
5623
5692
|
var Arbi = class {
|
|
5624
5693
|
client = null;
|
|
5625
5694
|
loginResult = null;
|
|
5626
5695
|
currentWorkspaceId = null;
|
|
5627
5696
|
dmCryptoContext = null;
|
|
5697
|
+
sessionExpiredListeners = /* @__PURE__ */ new Set();
|
|
5628
5698
|
options;
|
|
5629
5699
|
constructor(options) {
|
|
5630
5700
|
this.options = options;
|
|
@@ -5637,7 +5707,13 @@ var Arbi = class {
|
|
|
5637
5707
|
this.client = client.createArbiClient({
|
|
5638
5708
|
baseUrl: this.options.url,
|
|
5639
5709
|
deploymentDomain: domain,
|
|
5640
|
-
credentials: this.options.credentials ?? "omit"
|
|
5710
|
+
credentials: this.options.credentials ?? "omit",
|
|
5711
|
+
// A silent re-login rotates the server session key: keep ours in step, or the next
|
|
5712
|
+
// workspace open would seal the key for a session the server no longer has.
|
|
5713
|
+
onReloginSuccess: ({ serverSessionKey }) => {
|
|
5714
|
+
if (this.loginResult) this.loginResult = { ...this.loginResult, serverSessionKey };
|
|
5715
|
+
},
|
|
5716
|
+
onSessionExpired: () => this.expireSession()
|
|
5641
5717
|
});
|
|
5642
5718
|
await this.client.crypto.initSodium();
|
|
5643
5719
|
return this.client;
|
|
@@ -5674,6 +5750,22 @@ var Arbi = class {
|
|
|
5674
5750
|
const signingPrivateKey = client.crypto.base64ToBytes(signingPrivateKeyBase64);
|
|
5675
5751
|
this.loginResult = await client.auth.loginWithKey({ email, signingPrivateKey });
|
|
5676
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
|
+
}
|
|
5677
5769
|
/**
|
|
5678
5770
|
* Select a workspace by ID. Fetches the workspace list, finds the matching
|
|
5679
5771
|
* workspace, decrypts the wrapped key, and sets up auth headers.
|
|
@@ -5700,6 +5792,52 @@ var Arbi = class {
|
|
|
5700
5792
|
});
|
|
5701
5793
|
this.currentWorkspaceId = ws.external_id;
|
|
5702
5794
|
}
|
|
5795
|
+
/**
|
|
5796
|
+
* Subscribe to "the session cannot be recovered". Fires when a request failed with 401 or
|
|
5797
|
+
* "No active workspace" and neither a workspace re-open nor a silent re-login was possible
|
|
5798
|
+
* (the server refused; an unreachable server does not fire). The local session is already
|
|
5799
|
+
* cleared when it fires: show "Your session expired, sign in again". Returns an unsubscribe.
|
|
5800
|
+
*/
|
|
5801
|
+
onSessionExpired(listener) {
|
|
5802
|
+
this.sessionExpiredListeners.add(listener);
|
|
5803
|
+
return () => this.sessionExpiredListeners.delete(listener);
|
|
5804
|
+
}
|
|
5805
|
+
expireSession() {
|
|
5806
|
+
if (this.loginResult) {
|
|
5807
|
+
this.loginResult.signingPrivateKey.fill(0);
|
|
5808
|
+
this.loginResult.serverSessionKey.fill(0);
|
|
5809
|
+
}
|
|
5810
|
+
this.loginResult = null;
|
|
5811
|
+
this.currentWorkspaceId = null;
|
|
5812
|
+
this.dmCryptoContext = null;
|
|
5813
|
+
this.client?.session.clear();
|
|
5814
|
+
for (const listener of [...this.sessionExpiredListeners]) listener();
|
|
5815
|
+
}
|
|
5816
|
+
/**
|
|
5817
|
+
* Run a raw-fetch operation (streaming, multipart: no middleware) and, when it fails because
|
|
5818
|
+
* the token expired or the server lost the open workspace, recover once and run it again.
|
|
5819
|
+
* `run` must read the auth headers itself so the retry carries the fresh token.
|
|
5820
|
+
*/
|
|
5821
|
+
async recovering(run) {
|
|
5822
|
+
if (this.client && tokenExpiresWithin(this.client.session.getState().accessToken, 30)) {
|
|
5823
|
+
await this.client.auth.relogin();
|
|
5824
|
+
}
|
|
5825
|
+
try {
|
|
5826
|
+
return await run();
|
|
5827
|
+
} catch (error) {
|
|
5828
|
+
const message = error instanceof Error ? error.message : "";
|
|
5829
|
+
const noWorkspace = /no active workspace/i.test(message);
|
|
5830
|
+
const unauthorised = /\b401\b|token has expired/i.test(message);
|
|
5831
|
+
if (!(error instanceof ArbiApiError) || !(noWorkspace || unauthorised)) throw error;
|
|
5832
|
+
const client = this.requireClient();
|
|
5833
|
+
const recovered = noWorkspace && await client.auth.reopenWorkspace() || await client.auth.relogin() !== null;
|
|
5834
|
+
if (!recovered) {
|
|
5835
|
+
this.expireSession();
|
|
5836
|
+
throw new ArbiSessionExpiredError();
|
|
5837
|
+
}
|
|
5838
|
+
return run();
|
|
5839
|
+
}
|
|
5840
|
+
}
|
|
5703
5841
|
/** Log out and clear internal state. */
|
|
5704
5842
|
async logout() {
|
|
5705
5843
|
if (this.client) {
|
|
@@ -5810,6 +5948,30 @@ var Arbi = class {
|
|
|
5810
5948
|
update: (body) => updateWorkspace(this.requireClient(), body),
|
|
5811
5949
|
listUsers: () => listWorkspaceUsers(this.requireClient()),
|
|
5812
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
|
+
}),
|
|
5813
5975
|
removeUsers: (userIds) => removeWorkspaceUsers(this.requireClient(), userIds),
|
|
5814
5976
|
setUserRole: (userIds, role) => setUserRole(this.requireClient(), userIds, role),
|
|
5815
5977
|
/**
|
|
@@ -5866,16 +6028,18 @@ var Arbi = class {
|
|
|
5866
6028
|
},
|
|
5867
6029
|
uploadFile: (fileData, fileName, options) => {
|
|
5868
6030
|
this.requireWorkspace();
|
|
5869
|
-
return
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
6031
|
+
return this.recovering(
|
|
6032
|
+
() => uploadFile(
|
|
6033
|
+
this.getAuthHeaders(),
|
|
6034
|
+
fileData,
|
|
6035
|
+
fileName,
|
|
6036
|
+
options?.folder ? { folder: options.folder } : void 0
|
|
6037
|
+
)
|
|
5874
6038
|
);
|
|
5875
6039
|
},
|
|
5876
|
-
download: (docId) => downloadDocument(this.getAuthHeaders(), docId),
|
|
5877
|
-
getParsedContent: (docId, stage) => getParsedContent(this.getAuthHeaders(), docId, stage),
|
|
5878
|
-
getThumbnails: (docIds) => getThumbnails(this.getAuthHeaders(), docIds)
|
|
6040
|
+
download: (docId) => this.recovering(() => downloadDocument(this.getAuthHeaders(), docId)),
|
|
6041
|
+
getParsedContent: (docId, stage) => this.recovering(() => getParsedContent(this.getAuthHeaders(), docId, stage)),
|
|
6042
|
+
getThumbnails: (docIds) => this.recovering(() => getThumbnails(this.getAuthHeaders(), docIds))
|
|
5879
6043
|
};
|
|
5880
6044
|
// ── Conversations ─────────────────────────────────────────────────────
|
|
5881
6045
|
conversations = {
|
|
@@ -5894,16 +6058,17 @@ var Arbi = class {
|
|
|
5894
6058
|
* Returns the accumulated result after the stream completes.
|
|
5895
6059
|
*/
|
|
5896
6060
|
query: async (question, options) => {
|
|
5897
|
-
const auth = this.getAuthHeaders();
|
|
5898
6061
|
const workspaceId = this.requireWorkspace();
|
|
5899
|
-
const response = await
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
6062
|
+
const response = await this.recovering(
|
|
6063
|
+
() => queryAssistant({
|
|
6064
|
+
...this.getAuthHeaders(),
|
|
6065
|
+
workspaceId,
|
|
6066
|
+
question,
|
|
6067
|
+
docIds: options.docIds,
|
|
6068
|
+
previousResponseId: options.previousResponseId,
|
|
6069
|
+
model: options.model
|
|
6070
|
+
})
|
|
6071
|
+
);
|
|
5907
6072
|
const callbacks = {
|
|
5908
6073
|
onToken: options.onToken,
|
|
5909
6074
|
onStreamStart: options.onStreamStart,
|
|
@@ -5922,6 +6087,8 @@ var Arbi = class {
|
|
|
5922
6087
|
* Respond to an agent's question during a human-in-the-loop workflow.
|
|
5923
6088
|
*/
|
|
5924
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),
|
|
5925
6092
|
/**
|
|
5926
6093
|
* Search documents without LLM generation (retrieval only).
|
|
5927
6094
|
*/
|
|
@@ -6067,8 +6234,10 @@ var Arbi = class {
|
|
|
6067
6234
|
list: (options) => listFiles(this.requireClient(), options),
|
|
6068
6235
|
get: (fileId) => getFile(this.requireClient(), fileId),
|
|
6069
6236
|
delete: (fileId) => deleteFile(this.requireClient(), fileId),
|
|
6070
|
-
upload: (fileData, fileName, purpose) =>
|
|
6071
|
-
|
|
6237
|
+
upload: (fileData, fileName, purpose) => this.recovering(
|
|
6238
|
+
() => uploadFile2(this.getAuthHeaders(), fileData, fileName, purpose)
|
|
6239
|
+
),
|
|
6240
|
+
getContent: (fileId) => this.recovering(() => getFileContent(this.getAuthHeaders(), fileId))
|
|
6072
6241
|
};
|
|
6073
6242
|
// ── Agents ──────────────────────────────────────────────────────────
|
|
6074
6243
|
agents = {
|
|
@@ -6076,7 +6245,28 @@ var Arbi = class {
|
|
|
6076
6245
|
create: (name) => createAgent(this.requireClient(), name),
|
|
6077
6246
|
getConfig: (agentExtId) => getAgentConfig(this.requireClient(), agentExtId),
|
|
6078
6247
|
listWorkspaces: (agentExtId) => listAgentWorkspaces(this.requireClient(), agentExtId),
|
|
6079
|
-
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
|
+
}
|
|
6080
6270
|
};
|
|
6081
6271
|
// ── Scheduled tasks ───────────────────────────────────────────────────
|
|
6082
6272
|
tasks = {
|
|
@@ -6085,7 +6275,26 @@ var Arbi = class {
|
|
|
6085
6275
|
get: (taskId) => getTask(this.requireClient(), taskId),
|
|
6086
6276
|
update: (taskId, body) => updateTask(this.requireClient(), taskId, body),
|
|
6087
6277
|
delete: (taskId) => deleteTask(this.requireClient(), taskId),
|
|
6088
|
-
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
|
+
}
|
|
6089
6298
|
};
|
|
6090
6299
|
// ── Workspace facts ─────────────────────────────────────────────────
|
|
6091
6300
|
facts = {
|