@arbidocs/sdk 0.3.65 → 0.3.67
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-D2dkZnc9.d.cts → browser-B5xRfc7b.d.cts} +143 -17
- package/dist/{browser-D2dkZnc9.d.ts → browser-B5xRfc7b.d.ts} +143 -17
- package/dist/browser.cjs +136 -60
- 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 +136 -60
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +153 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +151 -63
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/browser.cjs
CHANGED
|
@@ -3568,6 +3568,7 @@ async function authenticatedFetch(options) {
|
|
|
3568
3568
|
}
|
|
3569
3569
|
|
|
3570
3570
|
// src/auth.ts
|
|
3571
|
+
var TOKEN_MAX_AGE_MS = 50 * 60 * 1e3;
|
|
3571
3572
|
function formatWorkspaceChoices(wsList) {
|
|
3572
3573
|
return wsList.map((ws) => {
|
|
3573
3574
|
const totalDocs = ws.shared_document_count + ws.private_document_count;
|
|
@@ -3598,11 +3599,11 @@ async function createAuthenticatedClient(config, creds, store) {
|
|
|
3598
3599
|
});
|
|
3599
3600
|
store.saveCredentials({
|
|
3600
3601
|
...creds,
|
|
3602
|
+
userExtId: loginResult.userExtId ?? creds.userExtId,
|
|
3601
3603
|
serverSessionKeyBase64: arbi.crypto.bytesToBase64(loginResult.serverSessionKey),
|
|
3602
3604
|
accessToken: void 0,
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
tokenTimestamp: void 0
|
|
3605
|
+
tokenTimestamp: void 0,
|
|
3606
|
+
openedWorkspaces: void 0
|
|
3606
3607
|
});
|
|
3607
3608
|
return { arbi, loginResult };
|
|
3608
3609
|
}
|
|
@@ -3612,13 +3613,18 @@ async function performPasswordLogin(config, email, password, store) {
|
|
|
3612
3613
|
const loginResult = await arbi.auth.login({ email, password });
|
|
3613
3614
|
store.saveCredentials({
|
|
3614
3615
|
email,
|
|
3616
|
+
userExtId: loginResult.userExtId,
|
|
3615
3617
|
signingPrivateKeyBase64: arbi.crypto.bytesToBase64(loginResult.signingPrivateKey),
|
|
3616
3618
|
serverSessionKeyBase64: arbi.crypto.bytesToBase64(loginResult.serverSessionKey),
|
|
3617
|
-
//
|
|
3619
|
+
// `parent_ext_id` is set for persistent agent accounts (the user is
|
|
3620
|
+
// an Assistant owned by another user). Persisting it makes the CLI's
|
|
3621
|
+
// `arbi listen` work — it requires this to confirm a real agent
|
|
3622
|
+
// identity. Regular users get `null`, which we store as `undefined`.
|
|
3623
|
+
parentExtId: loginResult.parentExtId ?? void 0,
|
|
3624
|
+
// New session = no workspaces deposited yet.
|
|
3618
3625
|
accessToken: void 0,
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
tokenTimestamp: void 0
|
|
3626
|
+
tokenTimestamp: void 0,
|
|
3627
|
+
openedWorkspaces: void 0
|
|
3622
3628
|
});
|
|
3623
3629
|
return { arbi, loginResult, config };
|
|
3624
3630
|
}
|
|
@@ -3634,16 +3640,6 @@ async function selectWorkspace(arbi, workspaceId, wrappedKey, serverSessionKey,
|
|
|
3634
3640
|
arbi.session.setSelectedWorkspace(workspaceId);
|
|
3635
3641
|
return header;
|
|
3636
3642
|
}
|
|
3637
|
-
async function generateEncryptedWorkspaceKey(arbi, wrappedKey, serverSessionKey, signingPrivateKeyBase64) {
|
|
3638
|
-
const signingPrivateKey = client.base64ToBytes(signingPrivateKeyBase64);
|
|
3639
|
-
const ed25519PublicKey = signingPrivateKey.slice(32, 64);
|
|
3640
|
-
const encryptionKeyPair = client.deriveEncryptionKeypairFromSigning({
|
|
3641
|
-
publicKey: ed25519PublicKey,
|
|
3642
|
-
secretKey: signingPrivateKey
|
|
3643
|
-
});
|
|
3644
|
-
const workspaceKey = client.sealedBoxDecrypt(wrappedKey, encryptionKeyPair.secretKey);
|
|
3645
|
-
return client.sealKeyForSession(workspaceKey, serverSessionKey);
|
|
3646
|
-
}
|
|
3647
3643
|
async function getRawWorkspaceKey(arbi, workspaceId, signingPrivateKeyBase64) {
|
|
3648
3644
|
const { data: workspaces, error } = await arbi.fetch.GET("/v1/user/workspaces");
|
|
3649
3645
|
if (error || !workspaces) {
|
|
@@ -3661,38 +3657,79 @@ async function getRawWorkspaceKey(arbi, workspaceId, signingPrivateKeyBase64) {
|
|
|
3661
3657
|
});
|
|
3662
3658
|
return client.sealedBoxDecrypt(ws.wrapped_key, encryptionKeyPair.secretKey);
|
|
3663
3659
|
}
|
|
3660
|
+
async function openWorkspaceEntry(arbi, ws, serverSessionKey, signingPrivateKeyBase64) {
|
|
3661
|
+
if (ws.wrapped_key) {
|
|
3662
|
+
const sealedKey = await selectWorkspace(
|
|
3663
|
+
arbi,
|
|
3664
|
+
ws.external_id,
|
|
3665
|
+
ws.wrapped_key,
|
|
3666
|
+
serverSessionKey,
|
|
3667
|
+
signingPrivateKeyBase64
|
|
3668
|
+
);
|
|
3669
|
+
const { error: error2 } = await arbi.fetch.POST("/v1/workspace/{workspace_ext_id}/open", {
|
|
3670
|
+
params: { path: { workspace_ext_id: ws.external_id } },
|
|
3671
|
+
body: { workspace_key: sealedKey }
|
|
3672
|
+
});
|
|
3673
|
+
if (error2) {
|
|
3674
|
+
throw new ArbiError(`Workspace open failed for ${ws.external_id}: ${JSON.stringify(error2)}`);
|
|
3675
|
+
}
|
|
3676
|
+
return sealedKey;
|
|
3677
|
+
}
|
|
3678
|
+
arbi.session.setSelectedWorkspace(ws.external_id);
|
|
3679
|
+
const { error } = await arbi.fetch.POST("/v1/workspace/{workspace_ext_id}/open", {
|
|
3680
|
+
params: { path: { workspace_ext_id: ws.external_id } },
|
|
3681
|
+
body: {}
|
|
3682
|
+
});
|
|
3683
|
+
if (error) {
|
|
3684
|
+
throw new ArbiError(`Workspace open failed for ${ws.external_id}: ${JSON.stringify(error)}`);
|
|
3685
|
+
}
|
|
3686
|
+
return null;
|
|
3687
|
+
}
|
|
3664
3688
|
async function selectWorkspaceById(arbi, workspaceId, serverSessionKey, signingPrivateKeyBase64) {
|
|
3665
3689
|
const { data: workspaces, error } = await arbi.fetch.GET("/v1/user/workspaces");
|
|
3666
3690
|
if (error || !workspaces) {
|
|
3667
3691
|
throw new ArbiError("Failed to fetch workspaces");
|
|
3668
3692
|
}
|
|
3669
3693
|
const ws = workspaces.find((w2) => w2.external_id === workspaceId);
|
|
3670
|
-
if (!ws
|
|
3671
|
-
throw new ArbiError(`Workspace ${workspaceId} not found
|
|
3694
|
+
if (!ws) {
|
|
3695
|
+
throw new ArbiError(`Workspace ${workspaceId} not found`);
|
|
3672
3696
|
}
|
|
3673
|
-
const sealedKey = await
|
|
3674
|
-
|
|
3675
|
-
ws.external_id,
|
|
3676
|
-
ws.
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3697
|
+
const sealedKey = await openWorkspaceEntry(arbi, ws, serverSessionKey, signingPrivateKeyBase64);
|
|
3698
|
+
return {
|
|
3699
|
+
external_id: ws.external_id,
|
|
3700
|
+
name: ws.name,
|
|
3701
|
+
wrapped_key: ws.wrapped_key ?? null,
|
|
3702
|
+
sealed_key: sealedKey
|
|
3703
|
+
};
|
|
3704
|
+
}
|
|
3705
|
+
function isSessionAlive(creds) {
|
|
3706
|
+
return !!(creds.accessToken && creds.tokenTimestamp && Date.now() - new Date(creds.tokenTimestamp).getTime() < TOKEN_MAX_AGE_MS);
|
|
3707
|
+
}
|
|
3708
|
+
async function buildAuthFromCache(config, creds, store) {
|
|
3709
|
+
const arbi = client.createArbiClient(buildClientOptions(config, store, creds.email));
|
|
3710
|
+
await arbi.crypto.initSodium();
|
|
3711
|
+
arbi.session.setUser(creds.email, creds.userExtId);
|
|
3712
|
+
arbi.session.setAccessToken(creds.accessToken);
|
|
3713
|
+
const signingPrivateKey = client.base64ToBytes(creds.signingPrivateKeyBase64);
|
|
3714
|
+
const serverSessionKey = client.base64ToBytes(creds.serverSessionKeyBase64);
|
|
3715
|
+
const loginResult = {
|
|
3716
|
+
accessToken: creds.accessToken,
|
|
3717
|
+
userExtId: creds.userExtId,
|
|
3718
|
+
signingPrivateKey,
|
|
3719
|
+
serverSessionKey
|
|
3720
|
+
};
|
|
3721
|
+
return { arbi, loginResult };
|
|
3685
3722
|
}
|
|
3686
3723
|
async function resolveAuth(store) {
|
|
3687
3724
|
const config = store.requireConfig();
|
|
3688
3725
|
const creds = store.requireCredentials();
|
|
3726
|
+
if (isSessionAlive(creds)) {
|
|
3727
|
+
const { arbi: arbi2, loginResult: loginResult2 } = await buildAuthFromCache(config, creds, store);
|
|
3728
|
+
return { arbi: arbi2, loginResult: loginResult2, config };
|
|
3729
|
+
}
|
|
3689
3730
|
const { arbi, loginResult } = await createAuthenticatedClient(config, creds, store);
|
|
3690
3731
|
return { arbi, loginResult, config };
|
|
3691
3732
|
}
|
|
3692
|
-
var TOKEN_MAX_AGE_MS = 50 * 60 * 1e3;
|
|
3693
|
-
function isCachedTokenValid(creds, workspaceId) {
|
|
3694
|
-
return !!(creds.accessToken && creds.sealedWorkspaceKey && creds.workspaceId === workspaceId && creds.tokenTimestamp && Date.now() - new Date(creds.tokenTimestamp).getTime() < TOKEN_MAX_AGE_MS);
|
|
3695
|
-
}
|
|
3696
3733
|
async function resolveWorkspace(store, workspaceOpt) {
|
|
3697
3734
|
const config = store.requireConfig();
|
|
3698
3735
|
const creds = store.requireCredentials();
|
|
@@ -3700,53 +3737,52 @@ async function resolveWorkspace(store, workspaceOpt) {
|
|
|
3700
3737
|
if (!workspaceId) {
|
|
3701
3738
|
throw new ArbiError("No workspace selected. Run: arbi workspace select <id>");
|
|
3702
3739
|
}
|
|
3703
|
-
if (
|
|
3704
|
-
const arbi2 =
|
|
3705
|
-
await arbi2.crypto.initSodium();
|
|
3706
|
-
arbi2.session.setUser(creds.email);
|
|
3740
|
+
if (isSessionAlive(creds)) {
|
|
3741
|
+
const { arbi: arbi2, loginResult: loginResult2 } = await buildAuthFromCache(config, creds, store);
|
|
3707
3742
|
arbi2.session.setSelectedWorkspace(workspaceId);
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3743
|
+
await selectWorkspaceById(
|
|
3744
|
+
arbi2,
|
|
3745
|
+
workspaceId,
|
|
3746
|
+
loginResult2.serverSessionKey,
|
|
3747
|
+
creds.signingPrivateKeyBase64
|
|
3748
|
+
);
|
|
3749
|
+
const nextOpened = Array.from(/* @__PURE__ */ new Set([...creds.openedWorkspaces ?? [], workspaceId]));
|
|
3750
|
+
store.saveCredentials({
|
|
3751
|
+
...store.requireCredentials(),
|
|
3752
|
+
openedWorkspaces: nextOpened
|
|
3753
|
+
});
|
|
3716
3754
|
return {
|
|
3717
3755
|
arbi: arbi2,
|
|
3718
3756
|
loginResult: loginResult2,
|
|
3719
3757
|
config,
|
|
3720
3758
|
workspaceId,
|
|
3721
|
-
accessToken: creds.accessToken
|
|
3722
|
-
sealedWorkspaceKey: creds.sealedWorkspaceKey
|
|
3759
|
+
accessToken: creds.accessToken
|
|
3723
3760
|
};
|
|
3724
3761
|
}
|
|
3725
3762
|
const { arbi, loginResult } = await createAuthenticatedClient(config, creds, store);
|
|
3726
|
-
|
|
3763
|
+
await selectWorkspaceById(
|
|
3727
3764
|
arbi,
|
|
3728
3765
|
workspaceId,
|
|
3729
3766
|
loginResult.serverSessionKey,
|
|
3730
3767
|
creds.signingPrivateKeyBase64
|
|
3731
3768
|
);
|
|
3732
3769
|
const accessToken = arbi.session.getState().accessToken;
|
|
3733
|
-
const sealedWorkspaceKey = await generateEncryptedWorkspaceKey(
|
|
3734
|
-
arbi,
|
|
3735
|
-
wsInfo.wrapped_key,
|
|
3736
|
-
loginResult.serverSessionKey,
|
|
3737
|
-
creds.signingPrivateKeyBase64
|
|
3738
|
-
);
|
|
3739
3770
|
if (!accessToken) {
|
|
3740
3771
|
throw new ArbiError("Authentication error \u2014 missing token");
|
|
3741
3772
|
}
|
|
3742
3773
|
store.saveCredentials({
|
|
3743
3774
|
...store.requireCredentials(),
|
|
3744
3775
|
accessToken,
|
|
3745
|
-
|
|
3746
|
-
workspaceId
|
|
3747
|
-
tokenTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3776
|
+
tokenTimestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3777
|
+
openedWorkspaces: [workspaceId]
|
|
3748
3778
|
});
|
|
3749
|
-
return {
|
|
3779
|
+
return {
|
|
3780
|
+
arbi,
|
|
3781
|
+
loginResult,
|
|
3782
|
+
config,
|
|
3783
|
+
workspaceId,
|
|
3784
|
+
accessToken
|
|
3785
|
+
};
|
|
3750
3786
|
}
|
|
3751
3787
|
|
|
3752
3788
|
// src/sse.ts
|
|
@@ -4310,6 +4346,7 @@ async function uploadFile(auth, fileData, fileName, options) {
|
|
|
4310
4346
|
const params = new URLSearchParams();
|
|
4311
4347
|
if (options?.folder) params.set("folder", sanitizeFolderPath(options.folder));
|
|
4312
4348
|
if (options?.configExtId) params.set("config_ext_id", options.configExtId);
|
|
4349
|
+
if (options?.wpType) params.set("wp_type", options.wpType);
|
|
4313
4350
|
const qs = params.toString();
|
|
4314
4351
|
const res = await authenticatedFetch({
|
|
4315
4352
|
...auth,
|
|
@@ -4325,6 +4362,7 @@ async function uploadFiles(auth, files, options) {
|
|
|
4325
4362
|
const params = new URLSearchParams();
|
|
4326
4363
|
if (options?.folder) params.set("folder", sanitizeFolderPath(options.folder));
|
|
4327
4364
|
if (options?.configExtId) params.set("config_ext_id", options.configExtId);
|
|
4365
|
+
if (options?.wpType) params.set("wp_type", options.wpType);
|
|
4328
4366
|
const qs = params.toString();
|
|
4329
4367
|
const res = await authenticatedFetch({
|
|
4330
4368
|
...auth,
|
|
@@ -4650,6 +4688,10 @@ __export(assistant_exports, {
|
|
|
4650
4688
|
buildRetrievalChunkTool: () => buildRetrievalChunkTool,
|
|
4651
4689
|
buildRetrievalFullContextTool: () => buildRetrievalFullContextTool,
|
|
4652
4690
|
buildRetrievalTocTool: () => buildRetrievalTocTool,
|
|
4691
|
+
filterSkills: () => filterSkills,
|
|
4692
|
+
listSkills: () => listSkills,
|
|
4693
|
+
parseSlashCommand: () => parseSlashCommand,
|
|
4694
|
+
parseSlashTokenInProgress: () => parseSlashTokenInProgress,
|
|
4653
4695
|
queryAssistant: () => queryAssistant,
|
|
4654
4696
|
respondToAgent: () => respondToAgent,
|
|
4655
4697
|
retrieve: () => retrieve
|
|
@@ -4745,6 +4787,40 @@ async function respondToAgent(arbi, assistantMessageExtId, answer) {
|
|
|
4745
4787
|
"Failed to respond to agent"
|
|
4746
4788
|
);
|
|
4747
4789
|
}
|
|
4790
|
+
async function listSkills(arbi, options) {
|
|
4791
|
+
const result = requireData(
|
|
4792
|
+
await arbi.fetch.GET("/v1/assistant/skills", {
|
|
4793
|
+
params: { query: { include_hidden: options?.includeHidden ?? false } }
|
|
4794
|
+
}),
|
|
4795
|
+
"Failed to list skills"
|
|
4796
|
+
);
|
|
4797
|
+
return result.skills;
|
|
4798
|
+
}
|
|
4799
|
+
function parseSlashCommand(input) {
|
|
4800
|
+
const m2 = /^\s*\/([a-zA-Z0-9_-]+)(?:\s+([\s\S]*))?$/.exec(input);
|
|
4801
|
+
if (!m2) return null;
|
|
4802
|
+
return { slug: m2[1].toLowerCase(), args: m2[2] ?? "" };
|
|
4803
|
+
}
|
|
4804
|
+
function parseSlashTokenInProgress(buffer) {
|
|
4805
|
+
const m2 = /^\s*\/([a-zA-Z0-9_-]*)$/.exec(buffer);
|
|
4806
|
+
return m2 ? m2[1].toLowerCase() : null;
|
|
4807
|
+
}
|
|
4808
|
+
function filterSkills(items, query, pinned = []) {
|
|
4809
|
+
const q2 = query.toLowerCase();
|
|
4810
|
+
const pinnedSet = new Set(pinned);
|
|
4811
|
+
const key = (s2) => (s2.slug ?? s2.name).toLowerCase();
|
|
4812
|
+
const matched = q2 ? items.filter((s2) => key(s2).includes(q2)) : items.slice();
|
|
4813
|
+
matched.sort((a2, b2) => {
|
|
4814
|
+
const aPinned = pinnedSet.has(key(a2)) ? 0 : 1;
|
|
4815
|
+
const bPinned = pinnedSet.has(key(b2)) ? 0 : 1;
|
|
4816
|
+
if (aPinned !== bPinned) return aPinned - bPinned;
|
|
4817
|
+
const aPrefix = key(a2).startsWith(q2) ? 0 : 1;
|
|
4818
|
+
const bPrefix = key(b2).startsWith(q2) ? 0 : 1;
|
|
4819
|
+
if (aPrefix !== bPrefix) return aPrefix - bPrefix;
|
|
4820
|
+
return key(a2).localeCompare(key(b2));
|
|
4821
|
+
});
|
|
4822
|
+
return matched;
|
|
4823
|
+
}
|
|
4748
4824
|
|
|
4749
4825
|
// src/operations/tags.ts
|
|
4750
4826
|
var tags_exports = {};
|