@arbidocs/sdk 0.3.65 → 0.3.66
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-6H2O896Y.d.cts} +55 -15
- package/dist/{browser-D2dkZnc9.d.ts → browser-6H2O896Y.d.ts} +55 -15
- package/dist/browser.cjs +96 -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 +96 -60
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +110 -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 +110 -62
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -3602,7 +3602,7 @@ var FileConfigStore = class {
|
|
|
3602
3602
|
sessionFile;
|
|
3603
3603
|
metadataFile;
|
|
3604
3604
|
constructor(configDir) {
|
|
3605
|
-
const arbiBase = process.env.ARBI_CONFIG_DIR ?? path2__default.default.join(os2__default.default.homedir(), ".arbi");
|
|
3605
|
+
const arbiBase = process.env.ARBI_CONFIG_DIR ?? (fs2__default.default.existsSync(path2__default.default.join(process.cwd(), ".arbi", "credentials.json")) ? path2__default.default.join(process.cwd(), ".arbi") : path2__default.default.join(os2__default.default.homedir(), ".arbi"));
|
|
3606
3606
|
const arbiId = process.env.ARBI_ID;
|
|
3607
3607
|
this.configDir = configDir ?? (arbiId ? path2__default.default.join(arbiBase, arbiId) : arbiBase);
|
|
3608
3608
|
this.configFile = path2__default.default.join(this.configDir, "config.json");
|
|
@@ -3700,12 +3700,12 @@ var FileConfigStore = class {
|
|
|
3700
3700
|
...existing,
|
|
3701
3701
|
signingPrivateKeyBase64: b64encode(data.signingPrivateKey),
|
|
3702
3702
|
serverSessionKeyBase64: data.serverSessionKey ? b64encode(data.serverSessionKey) : existing.serverSessionKeyBase64,
|
|
3703
|
-
// A fresh server session
|
|
3704
|
-
//
|
|
3705
|
-
// re-
|
|
3703
|
+
// A fresh server session = a fresh ``session.workspaces``
|
|
3704
|
+
// dict. The previous session's deposits do not transfer, so
|
|
3705
|
+
// wipe the client mirror to force re-deposit on next touch.
|
|
3706
3706
|
accessToken: void 0,
|
|
3707
|
-
|
|
3708
|
-
|
|
3707
|
+
tokenTimestamp: void 0,
|
|
3708
|
+
openedWorkspaces: void 0
|
|
3709
3709
|
});
|
|
3710
3710
|
}
|
|
3711
3711
|
};
|
|
@@ -3904,6 +3904,7 @@ function sleep(ms) {
|
|
|
3904
3904
|
}
|
|
3905
3905
|
|
|
3906
3906
|
// src/auth.ts
|
|
3907
|
+
var TOKEN_MAX_AGE_MS = 50 * 60 * 1e3;
|
|
3907
3908
|
function formatWorkspaceChoices(wsList) {
|
|
3908
3909
|
return wsList.map((ws) => {
|
|
3909
3910
|
const totalDocs = ws.shared_document_count + ws.private_document_count;
|
|
@@ -3934,11 +3935,11 @@ async function createAuthenticatedClient(config, creds, store) {
|
|
|
3934
3935
|
});
|
|
3935
3936
|
store.saveCredentials({
|
|
3936
3937
|
...creds,
|
|
3938
|
+
userExtId: loginResult.userExtId ?? creds.userExtId,
|
|
3937
3939
|
serverSessionKeyBase64: arbi.crypto.bytesToBase64(loginResult.serverSessionKey),
|
|
3938
3940
|
accessToken: void 0,
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
tokenTimestamp: void 0
|
|
3941
|
+
tokenTimestamp: void 0,
|
|
3942
|
+
openedWorkspaces: void 0
|
|
3942
3943
|
});
|
|
3943
3944
|
return { arbi, loginResult };
|
|
3944
3945
|
}
|
|
@@ -3948,13 +3949,18 @@ async function performPasswordLogin(config, email, password, store) {
|
|
|
3948
3949
|
const loginResult = await arbi.auth.login({ email, password });
|
|
3949
3950
|
store.saveCredentials({
|
|
3950
3951
|
email,
|
|
3952
|
+
userExtId: loginResult.userExtId,
|
|
3951
3953
|
signingPrivateKeyBase64: arbi.crypto.bytesToBase64(loginResult.signingPrivateKey),
|
|
3952
3954
|
serverSessionKeyBase64: arbi.crypto.bytesToBase64(loginResult.serverSessionKey),
|
|
3953
|
-
//
|
|
3955
|
+
// `parent_ext_id` is set for persistent agent accounts (the user is
|
|
3956
|
+
// an Assistant owned by another user). Persisting it makes the CLI's
|
|
3957
|
+
// `arbi listen` work — it requires this to confirm a real agent
|
|
3958
|
+
// identity. Regular users get `null`, which we store as `undefined`.
|
|
3959
|
+
parentExtId: loginResult.parentExtId ?? void 0,
|
|
3960
|
+
// New session = no workspaces deposited yet.
|
|
3954
3961
|
accessToken: void 0,
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
tokenTimestamp: void 0
|
|
3962
|
+
tokenTimestamp: void 0,
|
|
3963
|
+
openedWorkspaces: void 0
|
|
3958
3964
|
});
|
|
3959
3965
|
return { arbi, loginResult, config };
|
|
3960
3966
|
}
|
|
@@ -3965,12 +3971,13 @@ async function performSigningKeyLogin(config, email, signingPrivateKeyBase64, st
|
|
|
3965
3971
|
const loginResult = await arbi.auth.loginWithKey({ email, signingPrivateKey });
|
|
3966
3972
|
store.saveCredentials({
|
|
3967
3973
|
email,
|
|
3974
|
+
userExtId: loginResult.userExtId,
|
|
3968
3975
|
signingPrivateKeyBase64,
|
|
3969
3976
|
serverSessionKeyBase64: arbi.crypto.bytesToBase64(loginResult.serverSessionKey),
|
|
3977
|
+
parentExtId: loginResult.parentExtId ?? void 0,
|
|
3970
3978
|
accessToken: void 0,
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
tokenTimestamp: void 0
|
|
3979
|
+
tokenTimestamp: void 0,
|
|
3980
|
+
openedWorkspaces: void 0
|
|
3974
3981
|
});
|
|
3975
3982
|
return { arbi, loginResult, config };
|
|
3976
3983
|
}
|
|
@@ -3994,13 +4001,14 @@ async function performSsoDeviceFlowLogin(config, email, password, store, callbac
|
|
|
3994
4001
|
const loginResult = await arbi.auth.login({ email, password, ssoToken });
|
|
3995
4002
|
store.saveCredentials({
|
|
3996
4003
|
email,
|
|
4004
|
+
userExtId: loginResult.userExtId,
|
|
3997
4005
|
signingPrivateKeyBase64: arbi.crypto.bytesToBase64(loginResult.signingPrivateKey),
|
|
3998
4006
|
serverSessionKeyBase64: arbi.crypto.bytesToBase64(loginResult.serverSessionKey),
|
|
4007
|
+
parentExtId: loginResult.parentExtId ?? void 0,
|
|
3999
4008
|
ssoToken,
|
|
4000
4009
|
accessToken: void 0,
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
tokenTimestamp: void 0
|
|
4010
|
+
tokenTimestamp: void 0,
|
|
4011
|
+
openedWorkspaces: void 0
|
|
4004
4012
|
});
|
|
4005
4013
|
return { arbi, loginResult, config };
|
|
4006
4014
|
}
|
|
@@ -4050,38 +4058,79 @@ async function getRawWorkspaceKey(arbi, workspaceId, signingPrivateKeyBase64) {
|
|
|
4050
4058
|
});
|
|
4051
4059
|
return client.sealedBoxDecrypt(ws.wrapped_key, encryptionKeyPair.secretKey);
|
|
4052
4060
|
}
|
|
4061
|
+
async function openWorkspaceEntry(arbi, ws, serverSessionKey, signingPrivateKeyBase64) {
|
|
4062
|
+
if (ws.wrapped_key) {
|
|
4063
|
+
const sealedKey = await selectWorkspace(
|
|
4064
|
+
arbi,
|
|
4065
|
+
ws.external_id,
|
|
4066
|
+
ws.wrapped_key,
|
|
4067
|
+
serverSessionKey,
|
|
4068
|
+
signingPrivateKeyBase64
|
|
4069
|
+
);
|
|
4070
|
+
const { error: error2 } = await arbi.fetch.POST("/v1/workspace/{workspace_ext_id}/open", {
|
|
4071
|
+
params: { path: { workspace_ext_id: ws.external_id } },
|
|
4072
|
+
body: { workspace_key: sealedKey }
|
|
4073
|
+
});
|
|
4074
|
+
if (error2) {
|
|
4075
|
+
throw new ArbiError(`Workspace open failed for ${ws.external_id}: ${JSON.stringify(error2)}`);
|
|
4076
|
+
}
|
|
4077
|
+
return sealedKey;
|
|
4078
|
+
}
|
|
4079
|
+
arbi.session.setSelectedWorkspace(ws.external_id);
|
|
4080
|
+
const { error } = await arbi.fetch.POST("/v1/workspace/{workspace_ext_id}/open", {
|
|
4081
|
+
params: { path: { workspace_ext_id: ws.external_id } },
|
|
4082
|
+
body: {}
|
|
4083
|
+
});
|
|
4084
|
+
if (error) {
|
|
4085
|
+
throw new ArbiError(`Workspace open failed for ${ws.external_id}: ${JSON.stringify(error)}`);
|
|
4086
|
+
}
|
|
4087
|
+
return null;
|
|
4088
|
+
}
|
|
4053
4089
|
async function selectWorkspaceById(arbi, workspaceId, serverSessionKey, signingPrivateKeyBase64) {
|
|
4054
4090
|
const { data: workspaces, error } = await arbi.fetch.GET("/v1/user/workspaces");
|
|
4055
4091
|
if (error || !workspaces) {
|
|
4056
4092
|
throw new ArbiError("Failed to fetch workspaces");
|
|
4057
4093
|
}
|
|
4058
4094
|
const ws = workspaces.find((w2) => w2.external_id === workspaceId);
|
|
4059
|
-
if (!ws
|
|
4060
|
-
throw new ArbiError(`Workspace ${workspaceId} not found
|
|
4095
|
+
if (!ws) {
|
|
4096
|
+
throw new ArbiError(`Workspace ${workspaceId} not found`);
|
|
4061
4097
|
}
|
|
4062
|
-
const sealedKey = await
|
|
4063
|
-
|
|
4064
|
-
ws.external_id,
|
|
4065
|
-
ws.
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4098
|
+
const sealedKey = await openWorkspaceEntry(arbi, ws, serverSessionKey, signingPrivateKeyBase64);
|
|
4099
|
+
return {
|
|
4100
|
+
external_id: ws.external_id,
|
|
4101
|
+
name: ws.name,
|
|
4102
|
+
wrapped_key: ws.wrapped_key ?? null,
|
|
4103
|
+
sealed_key: sealedKey
|
|
4104
|
+
};
|
|
4105
|
+
}
|
|
4106
|
+
function isSessionAlive(creds) {
|
|
4107
|
+
return !!(creds.accessToken && creds.tokenTimestamp && Date.now() - new Date(creds.tokenTimestamp).getTime() < TOKEN_MAX_AGE_MS);
|
|
4108
|
+
}
|
|
4109
|
+
async function buildAuthFromCache(config, creds, store) {
|
|
4110
|
+
const arbi = client.createArbiClient(buildClientOptions(config, store, creds.email));
|
|
4111
|
+
await arbi.crypto.initSodium();
|
|
4112
|
+
arbi.session.setUser(creds.email, creds.userExtId);
|
|
4113
|
+
arbi.session.setAccessToken(creds.accessToken);
|
|
4114
|
+
const signingPrivateKey = client.base64ToBytes(creds.signingPrivateKeyBase64);
|
|
4115
|
+
const serverSessionKey = client.base64ToBytes(creds.serverSessionKeyBase64);
|
|
4116
|
+
const loginResult = {
|
|
4117
|
+
accessToken: creds.accessToken,
|
|
4118
|
+
userExtId: creds.userExtId,
|
|
4119
|
+
signingPrivateKey,
|
|
4120
|
+
serverSessionKey
|
|
4121
|
+
};
|
|
4122
|
+
return { arbi, loginResult };
|
|
4074
4123
|
}
|
|
4075
4124
|
async function resolveAuth(store) {
|
|
4076
4125
|
const config = store.requireConfig();
|
|
4077
4126
|
const creds = store.requireCredentials();
|
|
4127
|
+
if (isSessionAlive(creds)) {
|
|
4128
|
+
const { arbi: arbi2, loginResult: loginResult2 } = await buildAuthFromCache(config, creds, store);
|
|
4129
|
+
return { arbi: arbi2, loginResult: loginResult2, config };
|
|
4130
|
+
}
|
|
4078
4131
|
const { arbi, loginResult } = await createAuthenticatedClient(config, creds, store);
|
|
4079
4132
|
return { arbi, loginResult, config };
|
|
4080
4133
|
}
|
|
4081
|
-
var TOKEN_MAX_AGE_MS = 50 * 60 * 1e3;
|
|
4082
|
-
function isCachedTokenValid(creds, workspaceId) {
|
|
4083
|
-
return !!(creds.accessToken && creds.sealedWorkspaceKey && creds.workspaceId === workspaceId && creds.tokenTimestamp && Date.now() - new Date(creds.tokenTimestamp).getTime() < TOKEN_MAX_AGE_MS);
|
|
4084
|
-
}
|
|
4085
4134
|
async function resolveWorkspace(store, workspaceOpt) {
|
|
4086
4135
|
const config = store.requireConfig();
|
|
4087
4136
|
const creds = store.requireCredentials();
|
|
@@ -4089,53 +4138,52 @@ async function resolveWorkspace(store, workspaceOpt) {
|
|
|
4089
4138
|
if (!workspaceId) {
|
|
4090
4139
|
throw new ArbiError("No workspace selected. Run: arbi workspace select <id>");
|
|
4091
4140
|
}
|
|
4092
|
-
if (
|
|
4093
|
-
const arbi2 =
|
|
4094
|
-
await arbi2.crypto.initSodium();
|
|
4095
|
-
arbi2.session.setUser(creds.email);
|
|
4141
|
+
if (isSessionAlive(creds)) {
|
|
4142
|
+
const { arbi: arbi2, loginResult: loginResult2 } = await buildAuthFromCache(config, creds, store);
|
|
4096
4143
|
arbi2.session.setSelectedWorkspace(workspaceId);
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4144
|
+
await selectWorkspaceById(
|
|
4145
|
+
arbi2,
|
|
4146
|
+
workspaceId,
|
|
4147
|
+
loginResult2.serverSessionKey,
|
|
4148
|
+
creds.signingPrivateKeyBase64
|
|
4149
|
+
);
|
|
4150
|
+
const nextOpened = Array.from(/* @__PURE__ */ new Set([...creds.openedWorkspaces ?? [], workspaceId]));
|
|
4151
|
+
store.saveCredentials({
|
|
4152
|
+
...store.requireCredentials(),
|
|
4153
|
+
openedWorkspaces: nextOpened
|
|
4154
|
+
});
|
|
4105
4155
|
return {
|
|
4106
4156
|
arbi: arbi2,
|
|
4107
4157
|
loginResult: loginResult2,
|
|
4108
4158
|
config,
|
|
4109
4159
|
workspaceId,
|
|
4110
|
-
accessToken: creds.accessToken
|
|
4111
|
-
sealedWorkspaceKey: creds.sealedWorkspaceKey
|
|
4160
|
+
accessToken: creds.accessToken
|
|
4112
4161
|
};
|
|
4113
4162
|
}
|
|
4114
4163
|
const { arbi, loginResult } = await createAuthenticatedClient(config, creds, store);
|
|
4115
|
-
|
|
4164
|
+
await selectWorkspaceById(
|
|
4116
4165
|
arbi,
|
|
4117
4166
|
workspaceId,
|
|
4118
4167
|
loginResult.serverSessionKey,
|
|
4119
4168
|
creds.signingPrivateKeyBase64
|
|
4120
4169
|
);
|
|
4121
4170
|
const accessToken = arbi.session.getState().accessToken;
|
|
4122
|
-
const sealedWorkspaceKey = await generateEncryptedWorkspaceKey(
|
|
4123
|
-
arbi,
|
|
4124
|
-
wsInfo.wrapped_key,
|
|
4125
|
-
loginResult.serverSessionKey,
|
|
4126
|
-
creds.signingPrivateKeyBase64
|
|
4127
|
-
);
|
|
4128
4171
|
if (!accessToken) {
|
|
4129
4172
|
throw new ArbiError("Authentication error \u2014 missing token");
|
|
4130
4173
|
}
|
|
4131
4174
|
store.saveCredentials({
|
|
4132
4175
|
...store.requireCredentials(),
|
|
4133
4176
|
accessToken,
|
|
4134
|
-
|
|
4135
|
-
workspaceId
|
|
4136
|
-
tokenTimestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4177
|
+
tokenTimestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4178
|
+
openedWorkspaces: [workspaceId]
|
|
4137
4179
|
});
|
|
4138
|
-
return {
|
|
4180
|
+
return {
|
|
4181
|
+
arbi,
|
|
4182
|
+
loginResult,
|
|
4183
|
+
config,
|
|
4184
|
+
workspaceId,
|
|
4185
|
+
accessToken
|
|
4186
|
+
};
|
|
4139
4187
|
}
|
|
4140
4188
|
|
|
4141
4189
|
// src/sse.ts
|