@deeplake/hivemind 0.7.37 → 0.7.39
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/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +11 -1
- package/bundle/cli.js +263 -55
- package/codex/bundle/commands/auth-login.js +88 -24
- package/cursor/bundle/commands/auth-login.js +88 -24
- package/hermes/bundle/commands/auth-login.js +88 -24
- package/mcp/bundle/server.js +1 -0
- package/openclaw/dist/index.js +1 -1
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/package.json +1 -1
|
@@ -6,18 +6,18 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Cloud-backed persistent shared memory for AI agents powered by Deeplake",
|
|
9
|
-
"version": "0.7.
|
|
9
|
+
"version": "0.7.39"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
13
13
|
"name": "hivemind",
|
|
14
14
|
"description": "Persistent shared memory powered by Deeplake — captures all session activity and provides cross-session, cross-agent memory search",
|
|
15
|
-
"version": "0.7.
|
|
15
|
+
"version": "0.7.39",
|
|
16
16
|
"source": {
|
|
17
17
|
"source": "git-subdir",
|
|
18
18
|
"url": "https://github.com/activeloopai/hivemind.git",
|
|
19
19
|
"path": "claude-code",
|
|
20
|
-
"sha": "
|
|
20
|
+
"sha": "2fa2f3d4c0da98f6888a1f2870ffe68a871227f9"
|
|
21
21
|
},
|
|
22
22
|
"homepage": "https://github.com/activeloopai/hivemind"
|
|
23
23
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hivemind",
|
|
3
3
|
"description": "Cloud-backed persistent memory powered by Deeplake — read, write, and share memory across Claude Code sessions and agents",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.39",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Activeloop",
|
|
7
7
|
"url": "https://deeplake.ai"
|
package/README.md
CHANGED
|
@@ -43,7 +43,17 @@ One command, all your agents:
|
|
|
43
43
|
npm install -g @deeplake/hivemind && hivemind install
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
The installer detects every supported assistant on your machine (table below), wires up the hooks, and
|
|
46
|
+
The installer detects every supported assistant on your machine (table below), wires up the hooks, and shows a one-line consent prompt before opening a browser for sign-in. Restart your assistants after install.
|
|
47
|
+
|
|
48
|
+
**Headless / CI installs** — pass an API token instead of using the browser flow:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
HIVEMIND_TOKEN=<your-token> hivemind install
|
|
52
|
+
# or
|
|
53
|
+
hivemind install --token <your-token>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Get a token from your account settings on https://deeplake.ai. With no token in a non-interactive shell, the install completes with hooks but skips sign-in; run `hivemind login` later to enable shared memory.
|
|
47
57
|
|
|
48
58
|
**Install for a specific assistant only:**
|
|
49
59
|
|
package/bundle/cli.js
CHANGED
|
@@ -63,6 +63,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync, cpSync, symlinkSync
|
|
|
63
63
|
import { join, dirname } from "node:path";
|
|
64
64
|
import { homedir } from "node:os";
|
|
65
65
|
import { fileURLToPath } from "node:url";
|
|
66
|
+
import { createInterface } from "node:readline";
|
|
66
67
|
var HOME = homedir();
|
|
67
68
|
function pkgRoot() {
|
|
68
69
|
let dir = fileURLToPath(new URL(".", import.meta.url));
|
|
@@ -140,6 +141,29 @@ function log(msg) {
|
|
|
140
141
|
function warn(msg) {
|
|
141
142
|
process.stderr.write(msg + "\n");
|
|
142
143
|
}
|
|
144
|
+
function confirm(message, defaultYes = true) {
|
|
145
|
+
const hint = defaultYes ? "[Y/n]" : "[y/N]";
|
|
146
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
147
|
+
return new Promise((resolve2) => {
|
|
148
|
+
rl.question(`${message} ${hint} `, (answer) => {
|
|
149
|
+
rl.close();
|
|
150
|
+
const a = answer.trim().toLowerCase();
|
|
151
|
+
if (a === "")
|
|
152
|
+
resolve2(defaultYes);
|
|
153
|
+
else
|
|
154
|
+
resolve2(a === "y" || a === "yes");
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function promptLine(message) {
|
|
159
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
160
|
+
return new Promise((resolve2) => {
|
|
161
|
+
rl.question(message, (answer) => {
|
|
162
|
+
rl.close();
|
|
163
|
+
resolve2(answer.trim());
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
}
|
|
143
167
|
|
|
144
168
|
// dist/src/cli/install-claude.js
|
|
145
169
|
var MARKETPLACE_NAME = "hivemind";
|
|
@@ -4067,6 +4091,19 @@ function deleteCredentials() {
|
|
|
4067
4091
|
|
|
4068
4092
|
// dist/src/commands/auth.js
|
|
4069
4093
|
var DEFAULT_API_URL = "https://api.deeplake.ai";
|
|
4094
|
+
function decodeJwtPayload(token) {
|
|
4095
|
+
try {
|
|
4096
|
+
const parts = token.split(".");
|
|
4097
|
+
if (parts.length !== 3)
|
|
4098
|
+
return null;
|
|
4099
|
+
let payload = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
4100
|
+
while (payload.length % 4)
|
|
4101
|
+
payload += "=";
|
|
4102
|
+
return JSON.parse(Buffer.from(payload, "base64").toString("utf8"));
|
|
4103
|
+
} catch {
|
|
4104
|
+
return null;
|
|
4105
|
+
}
|
|
4106
|
+
}
|
|
4070
4107
|
async function apiGet(path, token, apiUrl, orgId) {
|
|
4071
4108
|
const headers = {
|
|
4072
4109
|
Authorization: `Bearer ${token}`,
|
|
@@ -4197,17 +4234,32 @@ async function listMembers(token, orgId, apiUrl = DEFAULT_API_URL) {
|
|
|
4197
4234
|
async function removeMember(userId, token, orgId, apiUrl = DEFAULT_API_URL) {
|
|
4198
4235
|
await apiDelete(`/organizations/${orgId}/members/${userId}`, token, apiUrl, orgId);
|
|
4199
4236
|
}
|
|
4200
|
-
async function
|
|
4201
|
-
const
|
|
4202
|
-
const user = await apiGet("/me", authToken, apiUrl);
|
|
4237
|
+
async function saveCredentialsFromToken(token, apiUrl, opts = {}) {
|
|
4238
|
+
const user = await apiGet("/me", token, apiUrl);
|
|
4203
4239
|
const userName = user.name || (user.email ? user.email.split("@")[0] : "unknown");
|
|
4204
4240
|
process.stderr.write(`
|
|
4205
4241
|
Logged in as: ${userName}
|
|
4206
4242
|
`);
|
|
4207
|
-
const orgs = await listOrgs(
|
|
4243
|
+
const orgs = await listOrgs(token, apiUrl);
|
|
4244
|
+
if (orgs.length === 0)
|
|
4245
|
+
throw new Error("No organizations found for this account.");
|
|
4246
|
+
const envOrgId = process.env.HIVEMIND_ORG_ID;
|
|
4247
|
+
let preferredOrgId = envOrgId;
|
|
4248
|
+
if (!preferredOrgId && opts.skipTokenMint) {
|
|
4249
|
+
const claims = decodeJwtPayload(token);
|
|
4250
|
+
const claimOrg = claims && typeof claims.org_id === "string" ? claims.org_id : void 0;
|
|
4251
|
+
if (claimOrg)
|
|
4252
|
+
preferredOrgId = claimOrg;
|
|
4253
|
+
}
|
|
4208
4254
|
let orgId;
|
|
4209
4255
|
let orgName;
|
|
4210
|
-
|
|
4256
|
+
const matched = preferredOrgId ? orgs.find((o) => o.id === preferredOrgId) : void 0;
|
|
4257
|
+
if (matched) {
|
|
4258
|
+
orgId = matched.id;
|
|
4259
|
+
orgName = matched.name;
|
|
4260
|
+
process.stderr.write(`Organization: ${orgName}
|
|
4261
|
+
`);
|
|
4262
|
+
} else if (orgs.length === 1) {
|
|
4211
4263
|
orgId = orgs[0].id;
|
|
4212
4264
|
orgName = orgs[0].name;
|
|
4213
4265
|
process.stderr.write(`Organization: ${orgName}
|
|
@@ -4218,17 +4270,26 @@ Logged in as: ${userName}
|
|
|
4218
4270
|
`));
|
|
4219
4271
|
orgId = orgs[0].id;
|
|
4220
4272
|
orgName = orgs[0].name;
|
|
4221
|
-
|
|
4273
|
+
if (opts.skipTokenMint) {
|
|
4274
|
+
process.stderr.write(`
|
|
4275
|
+
Using: ${orgName} (set HIVEMIND_ORG_ID to override)
|
|
4276
|
+
`);
|
|
4277
|
+
} else {
|
|
4278
|
+
process.stderr.write(`
|
|
4222
4279
|
Using: ${orgName}
|
|
4223
4280
|
`);
|
|
4281
|
+
}
|
|
4282
|
+
}
|
|
4283
|
+
let apiToken = token;
|
|
4284
|
+
if (!opts.skipTokenMint) {
|
|
4285
|
+
const tokenName = `deeplake-plugin-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
|
|
4286
|
+
const tokenData = await apiPost("/users/me/tokens", {
|
|
4287
|
+
name: tokenName,
|
|
4288
|
+
duration: 365 * 24 * 3600,
|
|
4289
|
+
organization_id: orgId
|
|
4290
|
+
}, token, apiUrl);
|
|
4291
|
+
apiToken = tokenData.token.token;
|
|
4224
4292
|
}
|
|
4225
|
-
const tokenName = `deeplake-plugin-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
|
|
4226
|
-
const tokenData = await apiPost("/users/me/tokens", {
|
|
4227
|
-
name: tokenName,
|
|
4228
|
-
duration: 365 * 24 * 3600,
|
|
4229
|
-
organization_id: orgId
|
|
4230
|
-
}, authToken, apiUrl);
|
|
4231
|
-
const apiToken = tokenData.token.token;
|
|
4232
4293
|
const creds = {
|
|
4233
4294
|
token: apiToken,
|
|
4234
4295
|
orgId,
|
|
@@ -4241,8 +4302,16 @@ Using: ${orgName}
|
|
|
4241
4302
|
saveCredentials(creds);
|
|
4242
4303
|
return creds;
|
|
4243
4304
|
}
|
|
4305
|
+
async function login(apiUrl = DEFAULT_API_URL) {
|
|
4306
|
+
const { token: authToken } = await deviceFlowLogin(apiUrl);
|
|
4307
|
+
return saveCredentialsFromToken(authToken, apiUrl, { skipTokenMint: false });
|
|
4308
|
+
}
|
|
4244
4309
|
|
|
4245
4310
|
// dist/src/cli/auth.js
|
|
4311
|
+
var DEFAULT_API_URL2 = "https://api.deeplake.ai";
|
|
4312
|
+
function resolveApiUrl() {
|
|
4313
|
+
return process.env.HIVEMIND_API_URL ?? DEFAULT_API_URL2;
|
|
4314
|
+
}
|
|
4246
4315
|
var CREDS_PATH = join14(HOME, ".deeplake", "credentials.json");
|
|
4247
4316
|
function isLoggedIn() {
|
|
4248
4317
|
return existsSync12(CREDS_PATH) && loadCredentials() !== null;
|
|
@@ -4253,14 +4322,27 @@ async function ensureLoggedIn() {
|
|
|
4253
4322
|
log("");
|
|
4254
4323
|
log("No Deeplake credentials found. Starting login...");
|
|
4255
4324
|
try {
|
|
4256
|
-
|
|
4257
|
-
await login(apiUrl);
|
|
4325
|
+
await login(resolveApiUrl());
|
|
4258
4326
|
} catch (err) {
|
|
4259
4327
|
warn(`Login failed: ${err.message}`);
|
|
4260
4328
|
return false;
|
|
4261
4329
|
}
|
|
4262
4330
|
return isLoggedIn();
|
|
4263
4331
|
}
|
|
4332
|
+
async function loginWithProvidedToken(flagToken) {
|
|
4333
|
+
const token = flagToken ?? process.env.HIVEMIND_TOKEN;
|
|
4334
|
+
if (!token)
|
|
4335
|
+
return false;
|
|
4336
|
+
try {
|
|
4337
|
+
await saveCredentialsFromToken(token, resolveApiUrl(), { skipTokenMint: true });
|
|
4338
|
+
const source = flagToken ? "--token flag" : "HIVEMIND_TOKEN";
|
|
4339
|
+
log(`Signed in via ${source}.`);
|
|
4340
|
+
return true;
|
|
4341
|
+
} catch (err) {
|
|
4342
|
+
warn(`Token authentication failed: ${err.message}`);
|
|
4343
|
+
return false;
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4264
4346
|
async function maybeShowOrgChoice() {
|
|
4265
4347
|
const creds = loadCredentials();
|
|
4266
4348
|
if (!creds)
|
|
@@ -4976,7 +5058,6 @@ var DeeplakeApi = class {
|
|
|
4976
5058
|
};
|
|
4977
5059
|
|
|
4978
5060
|
// dist/src/commands/session-prune.js
|
|
4979
|
-
import { createInterface } from "node:readline";
|
|
4980
5061
|
function parseArgs(argv) {
|
|
4981
5062
|
let before;
|
|
4982
5063
|
let sessionId;
|
|
@@ -4996,15 +5077,6 @@ function parseArgs(argv) {
|
|
|
4996
5077
|
}
|
|
4997
5078
|
return { before, sessionId, all, yes };
|
|
4998
5079
|
}
|
|
4999
|
-
function confirm(message) {
|
|
5000
|
-
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
5001
|
-
return new Promise((resolve2) => {
|
|
5002
|
-
rl.question(`${message} [y/N] `, (answer) => {
|
|
5003
|
-
rl.close();
|
|
5004
|
-
resolve2(answer.trim().toLowerCase() === "y");
|
|
5005
|
-
});
|
|
5006
|
-
});
|
|
5007
|
-
}
|
|
5008
5080
|
function extractSessionId(path) {
|
|
5009
5081
|
const m = path.match(/\/sessions\/[^/]+\/[^/]+_([^.]+)\.jsonl$/);
|
|
5010
5082
|
return m ? m[1] : path.split("/").pop()?.replace(/\.jsonl$/, "") ?? path;
|
|
@@ -5100,7 +5172,7 @@ To delete, use: --all, --before <date>, or --session-id <id>`);
|
|
|
5100
5172
|
}
|
|
5101
5173
|
console.log();
|
|
5102
5174
|
if (!yes) {
|
|
5103
|
-
const ok = await confirm("Proceed with deletion?");
|
|
5175
|
+
const ok = await confirm("Proceed with deletion?", false);
|
|
5104
5176
|
if (!ok) {
|
|
5105
5177
|
console.log("Aborted.");
|
|
5106
5178
|
return;
|
|
@@ -6842,7 +6914,7 @@ function takeBoolFlag(args, flag) {
|
|
|
6842
6914
|
}
|
|
6843
6915
|
async function runMineLocal(args) {
|
|
6844
6916
|
let lockReleased = false;
|
|
6845
|
-
const
|
|
6917
|
+
const releaseLock2 = () => {
|
|
6846
6918
|
if (lockReleased)
|
|
6847
6919
|
return;
|
|
6848
6920
|
lockReleased = true;
|
|
@@ -6851,11 +6923,11 @@ async function runMineLocal(args) {
|
|
|
6851
6923
|
} catch {
|
|
6852
6924
|
}
|
|
6853
6925
|
};
|
|
6854
|
-
process.on("exit",
|
|
6926
|
+
process.on("exit", releaseLock2);
|
|
6855
6927
|
try {
|
|
6856
6928
|
return await runMineLocalImpl(args);
|
|
6857
6929
|
} finally {
|
|
6858
|
-
|
|
6930
|
+
releaseLock2();
|
|
6859
6931
|
}
|
|
6860
6932
|
}
|
|
6861
6933
|
async function runMineLocalImpl(args) {
|
|
@@ -7466,8 +7538,9 @@ if (process.argv[1] && process.argv[1].endsWith("skillify.js")) {
|
|
|
7466
7538
|
|
|
7467
7539
|
// dist/src/cli/update.js
|
|
7468
7540
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
7469
|
-
import { existsSync as existsSync27, readFileSync as readFileSync23, realpathSync } from "node:fs";
|
|
7470
|
-
import {
|
|
7541
|
+
import { closeSync as closeSync2, existsSync as existsSync27, mkdirSync as mkdirSync13, openSync as openSync2, readFileSync as readFileSync23, realpathSync, unlinkSync as unlinkSync11, writeSync } from "node:fs";
|
|
7542
|
+
import { homedir as homedir19 } from "node:os";
|
|
7543
|
+
import { dirname as dirname10, join as join33, sep } from "node:path";
|
|
7471
7544
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
7472
7545
|
|
|
7473
7546
|
// dist/src/utils/version-check.js
|
|
@@ -7483,6 +7556,9 @@ function isNewer(latest, current) {
|
|
|
7483
7556
|
// dist/src/cli/update.js
|
|
7484
7557
|
var NPM_REGISTRY_URL = "https://registry.npmjs.org/@deeplake/hivemind/latest";
|
|
7485
7558
|
var PKG_NAME = "@deeplake/hivemind";
|
|
7559
|
+
function defaultLockPath() {
|
|
7560
|
+
return join33(homedir19(), ".deeplake", "hivemind-update.lock");
|
|
7561
|
+
}
|
|
7486
7562
|
function detectInstallKind(argv1) {
|
|
7487
7563
|
const realArgv1 = (() => {
|
|
7488
7564
|
try {
|
|
@@ -7541,6 +7617,58 @@ async function getLatestNpmVersion(timeoutMs = 5e3) {
|
|
|
7541
7617
|
var defaultSpawn = (cmd, args) => {
|
|
7542
7618
|
execFileSync4(cmd, args, { stdio: "inherit" });
|
|
7543
7619
|
};
|
|
7620
|
+
function tryAcquireLock(path) {
|
|
7621
|
+
mkdirSync13(dirname10(path), { recursive: true, mode: 448 });
|
|
7622
|
+
const claim = () => {
|
|
7623
|
+
const fd = openSync2(path, "wx", 384);
|
|
7624
|
+
writeSync(fd, String(process.pid));
|
|
7625
|
+
return fd;
|
|
7626
|
+
};
|
|
7627
|
+
try {
|
|
7628
|
+
return claim();
|
|
7629
|
+
} catch (e) {
|
|
7630
|
+
if (e.code !== "EEXIST")
|
|
7631
|
+
throw e;
|
|
7632
|
+
}
|
|
7633
|
+
let holderPid = 0;
|
|
7634
|
+
try {
|
|
7635
|
+
holderPid = Number(readFileSync23(path, "utf-8").trim()) || 0;
|
|
7636
|
+
} catch {
|
|
7637
|
+
try {
|
|
7638
|
+
return claim();
|
|
7639
|
+
} catch {
|
|
7640
|
+
return null;
|
|
7641
|
+
}
|
|
7642
|
+
}
|
|
7643
|
+
if (holderPid > 0) {
|
|
7644
|
+
try {
|
|
7645
|
+
process.kill(holderPid, 0);
|
|
7646
|
+
log(`another hivemind update is already running (pid=${holderPid}); skipping.`);
|
|
7647
|
+
return null;
|
|
7648
|
+
} catch {
|
|
7649
|
+
}
|
|
7650
|
+
}
|
|
7651
|
+
try {
|
|
7652
|
+
unlinkSync11(path);
|
|
7653
|
+
} catch {
|
|
7654
|
+
}
|
|
7655
|
+
try {
|
|
7656
|
+
return claim();
|
|
7657
|
+
} catch {
|
|
7658
|
+
log(`another hivemind update is already running; skipping.`);
|
|
7659
|
+
return null;
|
|
7660
|
+
}
|
|
7661
|
+
}
|
|
7662
|
+
function releaseLock(fd, path) {
|
|
7663
|
+
try {
|
|
7664
|
+
closeSync2(fd);
|
|
7665
|
+
} catch {
|
|
7666
|
+
}
|
|
7667
|
+
try {
|
|
7668
|
+
unlinkSync11(path);
|
|
7669
|
+
} catch {
|
|
7670
|
+
}
|
|
7671
|
+
}
|
|
7544
7672
|
async function runUpdate(opts = {}) {
|
|
7545
7673
|
const current = opts.currentVersionOverride ?? getVersion();
|
|
7546
7674
|
const latest = opts.latestVersionOverride !== void 0 ? opts.latestVersionOverride : await getLatestNpmVersion();
|
|
@@ -7563,26 +7691,34 @@ async function runUpdate(opts = {}) {
|
|
|
7563
7691
|
log(`(dry-run) Would re-run: hivemind install --skip-auth`);
|
|
7564
7692
|
return 0;
|
|
7565
7693
|
}
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
|
|
7570
|
-
warn(`npm install failed: ${e.message}`);
|
|
7571
|
-
warn(`Try running it manually: npm install -g ${PKG_NAME}@latest`);
|
|
7572
|
-
return 1;
|
|
7573
|
-
}
|
|
7574
|
-
log(``);
|
|
7575
|
-
log(`Refreshing agent bundles\u2026`);
|
|
7694
|
+
const lockPath2 = opts.lockPathOverride ?? defaultLockPath();
|
|
7695
|
+
const lockFd = tryAcquireLock(lockPath2);
|
|
7696
|
+
if (lockFd === null)
|
|
7697
|
+
return 0;
|
|
7576
7698
|
try {
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
|
|
7699
|
+
log(`Upgrading via npm\u2026`);
|
|
7700
|
+
try {
|
|
7701
|
+
spawn2("npm", ["install", "-g", `${PKG_NAME}@latest`]);
|
|
7702
|
+
} catch (e) {
|
|
7703
|
+
warn(`npm install failed: ${e.message}`);
|
|
7704
|
+
warn(`Try running it manually: npm install -g ${PKG_NAME}@latest`);
|
|
7705
|
+
return 1;
|
|
7706
|
+
}
|
|
7707
|
+
log(``);
|
|
7708
|
+
log(`Refreshing agent bundles\u2026`);
|
|
7709
|
+
try {
|
|
7710
|
+
spawn2("hivemind", ["install", "--skip-auth"]);
|
|
7711
|
+
} catch (e) {
|
|
7712
|
+
warn(`Agent refresh failed: ${e.message}`);
|
|
7713
|
+
warn(`Run manually: hivemind install`);
|
|
7714
|
+
return 1;
|
|
7715
|
+
}
|
|
7716
|
+
log(``);
|
|
7717
|
+
log(`Updated to ${latest}.`);
|
|
7718
|
+
return 0;
|
|
7719
|
+
} finally {
|
|
7720
|
+
releaseLock(lockFd, lockPath2);
|
|
7582
7721
|
}
|
|
7583
|
-
log(``);
|
|
7584
|
-
log(`Updated to ${latest}.`);
|
|
7585
|
-
return 0;
|
|
7586
7722
|
}
|
|
7587
7723
|
case "npx": {
|
|
7588
7724
|
if (opts.dryRun) {
|
|
@@ -7639,9 +7775,13 @@ var USAGE = `
|
|
|
7639
7775
|
hivemind \u2014 one brain for every agent on your team
|
|
7640
7776
|
|
|
7641
7777
|
Usage:
|
|
7642
|
-
hivemind install [--only <platforms>] [--skip-auth]
|
|
7778
|
+
hivemind install [--only <platforms>] [--skip-auth] [--token <value>]
|
|
7643
7779
|
Auto-detect assistants on this machine and install hivemind into each.
|
|
7644
7780
|
--only takes a comma-separated list: ${allPlatformIds().join(",")}
|
|
7781
|
+
--token, or env HIVEMIND_TOKEN, signs in non-interactively (useful
|
|
7782
|
+
for CI / scripted installs). Without it, a TTY install shows a
|
|
7783
|
+
consent prompt; a headless install skips auth and prints a hint
|
|
7784
|
+
for 'hivemind login'.
|
|
7645
7785
|
|
|
7646
7786
|
hivemind uninstall [--only <platforms>]
|
|
7647
7787
|
Auto-detect installed assistants and remove hivemind from each.
|
|
@@ -7730,6 +7870,78 @@ function parseOnly(args) {
|
|
|
7730
7870
|
function hasFlag(args, flag) {
|
|
7731
7871
|
return args.includes(flag);
|
|
7732
7872
|
}
|
|
7873
|
+
function parseToken(args) {
|
|
7874
|
+
const idx = args.findIndex((a) => a === "--token" || a.startsWith("--token="));
|
|
7875
|
+
if (idx === -1)
|
|
7876
|
+
return void 0;
|
|
7877
|
+
const raw = args[idx].includes("=") ? args[idx].split("=", 2)[1] : args[idx + 1];
|
|
7878
|
+
return raw && raw.length > 0 ? raw : void 0;
|
|
7879
|
+
}
|
|
7880
|
+
function hasEnvToken() {
|
|
7881
|
+
return Boolean(process.env.HIVEMIND_TOKEN);
|
|
7882
|
+
}
|
|
7883
|
+
async function runAuthGate(args) {
|
|
7884
|
+
const flagToken = parseToken(args);
|
|
7885
|
+
const isTTY = Boolean(process.stdin.isTTY);
|
|
7886
|
+
if (flagToken || hasEnvToken()) {
|
|
7887
|
+
const ok = await loginWithProvidedToken(flagToken);
|
|
7888
|
+
if (ok)
|
|
7889
|
+
return;
|
|
7890
|
+
}
|
|
7891
|
+
if (!isTTY) {
|
|
7892
|
+
log("");
|
|
7893
|
+
log("No TTY detected \u2014 continuing without sign-in.");
|
|
7894
|
+
log("To sign in:");
|
|
7895
|
+
log(" 1) Visit https://app.deeplake.ai/api-keys to create an API key");
|
|
7896
|
+
log(" 2) Rerun: HIVEMIND_TOKEN=<key> hivemind install");
|
|
7897
|
+
log("Or run `hivemind login` after install.");
|
|
7898
|
+
return;
|
|
7899
|
+
}
|
|
7900
|
+
log("");
|
|
7901
|
+
log("\u{1F41D} One more step to unlock Hivemind");
|
|
7902
|
+
log("");
|
|
7903
|
+
log("To enable shared memory and auto-learning across your agents,");
|
|
7904
|
+
log("we need to sign you in. Your traces will be securely stored in");
|
|
7905
|
+
log("your private Hivemind, so all your agents can recall them.");
|
|
7906
|
+
log("");
|
|
7907
|
+
log("You can later connect your own cloud storage like S3/GCS/Azure Blob.");
|
|
7908
|
+
log("");
|
|
7909
|
+
const yes = await confirm("Sign in now?", true);
|
|
7910
|
+
let signedIn = false;
|
|
7911
|
+
if (yes) {
|
|
7912
|
+
signedIn = await ensureLoggedIn();
|
|
7913
|
+
if (!signedIn) {
|
|
7914
|
+
warn("Login did not complete.");
|
|
7915
|
+
}
|
|
7916
|
+
}
|
|
7917
|
+
if (!signedIn) {
|
|
7918
|
+
log("");
|
|
7919
|
+
log("Alternatively, sign in at https://app.deeplake.ai/api-keys, create");
|
|
7920
|
+
log("an API key, and paste it here. Press Enter to skip and continue");
|
|
7921
|
+
log("installing without sign-in (you can run `hivemind login` later).");
|
|
7922
|
+
log("");
|
|
7923
|
+
const MAX_PASTE_ATTEMPTS = 3;
|
|
7924
|
+
for (let attempt = 1; attempt <= MAX_PASTE_ATTEMPTS; attempt++) {
|
|
7925
|
+
const pasted = await promptLine("API key: ");
|
|
7926
|
+
if (!pasted)
|
|
7927
|
+
break;
|
|
7928
|
+
signedIn = await loginWithProvidedToken(pasted);
|
|
7929
|
+
if (signedIn)
|
|
7930
|
+
break;
|
|
7931
|
+
const remaining = MAX_PASTE_ATTEMPTS - attempt;
|
|
7932
|
+
if (remaining > 0) {
|
|
7933
|
+
log("");
|
|
7934
|
+
log(`That key wasn't accepted (likely invalid or revoked). Try again (${remaining} attempt${remaining === 1 ? "" : "s"} left) or press Enter to skip.`);
|
|
7935
|
+
log("");
|
|
7936
|
+
}
|
|
7937
|
+
}
|
|
7938
|
+
if (!signedIn) {
|
|
7939
|
+
log("");
|
|
7940
|
+
log("Continuing install without sign-in. Run `hivemind login` later, or");
|
|
7941
|
+
log("rerun with `HIVEMIND_TOKEN=<key> hivemind install`.");
|
|
7942
|
+
}
|
|
7943
|
+
}
|
|
7944
|
+
}
|
|
7733
7945
|
async function runInstallAll(args) {
|
|
7734
7946
|
const only = parseOnly(args);
|
|
7735
7947
|
const skipAuth = hasFlag(args, "--skip-auth");
|
|
@@ -7744,11 +7956,7 @@ async function runInstallAll(args) {
|
|
|
7744
7956
|
log(`Installing hivemind ${getVersion()} for: ${targets.join(", ")}`);
|
|
7745
7957
|
log("");
|
|
7746
7958
|
if (!skipAuth && !isLoggedIn()) {
|
|
7747
|
-
|
|
7748
|
-
if (!ok) {
|
|
7749
|
-
warn("Skipping install because login did not complete.");
|
|
7750
|
-
process.exit(1);
|
|
7751
|
-
}
|
|
7959
|
+
await runAuthGate(args);
|
|
7752
7960
|
}
|
|
7753
7961
|
for (const id of targets)
|
|
7754
7962
|
runSingleInstall(id);
|
|
@@ -96,6 +96,19 @@ function deleteCredentials() {
|
|
|
96
96
|
|
|
97
97
|
// dist/src/commands/auth.js
|
|
98
98
|
var DEFAULT_API_URL = "https://api.deeplake.ai";
|
|
99
|
+
function decodeJwtPayload(token) {
|
|
100
|
+
try {
|
|
101
|
+
const parts = token.split(".");
|
|
102
|
+
if (parts.length !== 3)
|
|
103
|
+
return null;
|
|
104
|
+
let payload = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
105
|
+
while (payload.length % 4)
|
|
106
|
+
payload += "=";
|
|
107
|
+
return JSON.parse(Buffer.from(payload, "base64").toString("utf8"));
|
|
108
|
+
} catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
99
112
|
async function apiGet(path, token, apiUrl, orgId) {
|
|
100
113
|
const headers = {
|
|
101
114
|
Authorization: `Bearer ${token}`,
|
|
@@ -226,17 +239,32 @@ async function listMembers(token, orgId, apiUrl = DEFAULT_API_URL) {
|
|
|
226
239
|
async function removeMember(userId, token, orgId, apiUrl = DEFAULT_API_URL) {
|
|
227
240
|
await apiDelete(`/organizations/${orgId}/members/${userId}`, token, apiUrl, orgId);
|
|
228
241
|
}
|
|
229
|
-
async function
|
|
230
|
-
const
|
|
231
|
-
const user = await apiGet("/me", authToken, apiUrl);
|
|
242
|
+
async function saveCredentialsFromToken(token, apiUrl, opts = {}) {
|
|
243
|
+
const user = await apiGet("/me", token, apiUrl);
|
|
232
244
|
const userName = user.name || (user.email ? user.email.split("@")[0] : "unknown");
|
|
233
245
|
process.stderr.write(`
|
|
234
246
|
Logged in as: ${userName}
|
|
235
247
|
`);
|
|
236
|
-
const orgs = await listOrgs(
|
|
248
|
+
const orgs = await listOrgs(token, apiUrl);
|
|
249
|
+
if (orgs.length === 0)
|
|
250
|
+
throw new Error("No organizations found for this account.");
|
|
251
|
+
const envOrgId = process.env.HIVEMIND_ORG_ID;
|
|
252
|
+
let preferredOrgId = envOrgId;
|
|
253
|
+
if (!preferredOrgId && opts.skipTokenMint) {
|
|
254
|
+
const claims = decodeJwtPayload(token);
|
|
255
|
+
const claimOrg = claims && typeof claims.org_id === "string" ? claims.org_id : void 0;
|
|
256
|
+
if (claimOrg)
|
|
257
|
+
preferredOrgId = claimOrg;
|
|
258
|
+
}
|
|
237
259
|
let orgId;
|
|
238
260
|
let orgName;
|
|
239
|
-
|
|
261
|
+
const matched = preferredOrgId ? orgs.find((o) => o.id === preferredOrgId) : void 0;
|
|
262
|
+
if (matched) {
|
|
263
|
+
orgId = matched.id;
|
|
264
|
+
orgName = matched.name;
|
|
265
|
+
process.stderr.write(`Organization: ${orgName}
|
|
266
|
+
`);
|
|
267
|
+
} else if (orgs.length === 1) {
|
|
240
268
|
orgId = orgs[0].id;
|
|
241
269
|
orgName = orgs[0].name;
|
|
242
270
|
process.stderr.write(`Organization: ${orgName}
|
|
@@ -247,17 +275,26 @@ Logged in as: ${userName}
|
|
|
247
275
|
`));
|
|
248
276
|
orgId = orgs[0].id;
|
|
249
277
|
orgName = orgs[0].name;
|
|
250
|
-
|
|
278
|
+
if (opts.skipTokenMint) {
|
|
279
|
+
process.stderr.write(`
|
|
280
|
+
Using: ${orgName} (set HIVEMIND_ORG_ID to override)
|
|
281
|
+
`);
|
|
282
|
+
} else {
|
|
283
|
+
process.stderr.write(`
|
|
251
284
|
Using: ${orgName}
|
|
252
285
|
`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
let apiToken = token;
|
|
289
|
+
if (!opts.skipTokenMint) {
|
|
290
|
+
const tokenName = `deeplake-plugin-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
|
|
291
|
+
const tokenData = await apiPost("/users/me/tokens", {
|
|
292
|
+
name: tokenName,
|
|
293
|
+
duration: 365 * 24 * 3600,
|
|
294
|
+
organization_id: orgId
|
|
295
|
+
}, token, apiUrl);
|
|
296
|
+
apiToken = tokenData.token.token;
|
|
253
297
|
}
|
|
254
|
-
const tokenName = `deeplake-plugin-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
|
|
255
|
-
const tokenData = await apiPost("/users/me/tokens", {
|
|
256
|
-
name: tokenName,
|
|
257
|
-
duration: 365 * 24 * 3600,
|
|
258
|
-
organization_id: orgId
|
|
259
|
-
}, authToken, apiUrl);
|
|
260
|
-
const apiToken = tokenData.token.token;
|
|
261
298
|
const creds = {
|
|
262
299
|
token: apiToken,
|
|
263
300
|
orgId,
|
|
@@ -270,6 +307,10 @@ Using: ${orgName}
|
|
|
270
307
|
saveCredentials(creds);
|
|
271
308
|
return creds;
|
|
272
309
|
}
|
|
310
|
+
async function login(apiUrl = DEFAULT_API_URL) {
|
|
311
|
+
const { token: authToken } = await deviceFlowLogin(apiUrl);
|
|
312
|
+
return saveCredentialsFromToken(authToken, apiUrl, { skipTokenMint: false });
|
|
313
|
+
}
|
|
273
314
|
|
|
274
315
|
// dist/src/config.js
|
|
275
316
|
import { readFileSync as readFileSync2, existsSync } from "node:fs";
|
|
@@ -969,8 +1010,40 @@ var DeeplakeApi = class {
|
|
|
969
1010
|
}
|
|
970
1011
|
};
|
|
971
1012
|
|
|
972
|
-
// dist/src/
|
|
1013
|
+
// dist/src/cli/util.js
|
|
1014
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4, cpSync, symlinkSync, unlinkSync as unlinkSync3, lstatSync } from "node:fs";
|
|
1015
|
+
import { join as join6, dirname } from "node:path";
|
|
1016
|
+
import { homedir as homedir5 } from "node:os";
|
|
1017
|
+
import { fileURLToPath } from "node:url";
|
|
973
1018
|
import { createInterface } from "node:readline";
|
|
1019
|
+
var HOME = homedir5();
|
|
1020
|
+
var PLATFORM_MARKERS = [
|
|
1021
|
+
{ id: "claude", markerDir: join6(HOME, ".claude") },
|
|
1022
|
+
{ id: "codex", markerDir: join6(HOME, ".codex") },
|
|
1023
|
+
{ id: "claw", markerDir: join6(HOME, ".openclaw") },
|
|
1024
|
+
{ id: "cursor", markerDir: join6(HOME, ".cursor") },
|
|
1025
|
+
{ id: "hermes", markerDir: join6(HOME, ".hermes") },
|
|
1026
|
+
// pi (badlogic/pi-mono coding-agent) — config at ~/.pi/agent/. pi exposes
|
|
1027
|
+
// a rich extension event API (session_start / input / tool_call /
|
|
1028
|
+
// tool_result / message_end / session_shutdown / etc.) — Tier 1 capable.
|
|
1029
|
+
{ id: "pi", markerDir: join6(HOME, ".pi") }
|
|
1030
|
+
];
|
|
1031
|
+
function confirm(message, defaultYes = true) {
|
|
1032
|
+
const hint = defaultYes ? "[Y/n]" : "[y/N]";
|
|
1033
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
1034
|
+
return new Promise((resolve2) => {
|
|
1035
|
+
rl.question(`${message} ${hint} `, (answer) => {
|
|
1036
|
+
rl.close();
|
|
1037
|
+
const a = answer.trim().toLowerCase();
|
|
1038
|
+
if (a === "")
|
|
1039
|
+
resolve2(defaultYes);
|
|
1040
|
+
else
|
|
1041
|
+
resolve2(a === "y" || a === "yes");
|
|
1042
|
+
});
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
// dist/src/commands/session-prune.js
|
|
974
1047
|
function parseArgs(argv) {
|
|
975
1048
|
let before;
|
|
976
1049
|
let sessionId;
|
|
@@ -990,15 +1063,6 @@ function parseArgs(argv) {
|
|
|
990
1063
|
}
|
|
991
1064
|
return { before, sessionId, all, yes };
|
|
992
1065
|
}
|
|
993
|
-
function confirm(message) {
|
|
994
|
-
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
995
|
-
return new Promise((resolve2) => {
|
|
996
|
-
rl.question(`${message} [y/N] `, (answer) => {
|
|
997
|
-
rl.close();
|
|
998
|
-
resolve2(answer.trim().toLowerCase() === "y");
|
|
999
|
-
});
|
|
1000
|
-
});
|
|
1001
|
-
}
|
|
1002
1066
|
function extractSessionId(path) {
|
|
1003
1067
|
const m = path.match(/\/sessions\/[^/]+\/[^/]+_([^.]+)\.jsonl$/);
|
|
1004
1068
|
return m ? m[1] : path.split("/").pop()?.replace(/\.jsonl$/, "") ?? path;
|
|
@@ -1094,7 +1158,7 @@ To delete, use: --all, --before <date>, or --session-id <id>`);
|
|
|
1094
1158
|
}
|
|
1095
1159
|
console.log();
|
|
1096
1160
|
if (!yes) {
|
|
1097
|
-
const ok = await confirm("Proceed with deletion?");
|
|
1161
|
+
const ok = await confirm("Proceed with deletion?", false);
|
|
1098
1162
|
if (!ok) {
|
|
1099
1163
|
console.log("Aborted.");
|
|
1100
1164
|
return;
|
|
@@ -96,6 +96,19 @@ function deleteCredentials() {
|
|
|
96
96
|
|
|
97
97
|
// dist/src/commands/auth.js
|
|
98
98
|
var DEFAULT_API_URL = "https://api.deeplake.ai";
|
|
99
|
+
function decodeJwtPayload(token) {
|
|
100
|
+
try {
|
|
101
|
+
const parts = token.split(".");
|
|
102
|
+
if (parts.length !== 3)
|
|
103
|
+
return null;
|
|
104
|
+
let payload = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
105
|
+
while (payload.length % 4)
|
|
106
|
+
payload += "=";
|
|
107
|
+
return JSON.parse(Buffer.from(payload, "base64").toString("utf8"));
|
|
108
|
+
} catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
99
112
|
async function apiGet(path, token, apiUrl, orgId) {
|
|
100
113
|
const headers = {
|
|
101
114
|
Authorization: `Bearer ${token}`,
|
|
@@ -226,17 +239,32 @@ async function listMembers(token, orgId, apiUrl = DEFAULT_API_URL) {
|
|
|
226
239
|
async function removeMember(userId, token, orgId, apiUrl = DEFAULT_API_URL) {
|
|
227
240
|
await apiDelete(`/organizations/${orgId}/members/${userId}`, token, apiUrl, orgId);
|
|
228
241
|
}
|
|
229
|
-
async function
|
|
230
|
-
const
|
|
231
|
-
const user = await apiGet("/me", authToken, apiUrl);
|
|
242
|
+
async function saveCredentialsFromToken(token, apiUrl, opts = {}) {
|
|
243
|
+
const user = await apiGet("/me", token, apiUrl);
|
|
232
244
|
const userName = user.name || (user.email ? user.email.split("@")[0] : "unknown");
|
|
233
245
|
process.stderr.write(`
|
|
234
246
|
Logged in as: ${userName}
|
|
235
247
|
`);
|
|
236
|
-
const orgs = await listOrgs(
|
|
248
|
+
const orgs = await listOrgs(token, apiUrl);
|
|
249
|
+
if (orgs.length === 0)
|
|
250
|
+
throw new Error("No organizations found for this account.");
|
|
251
|
+
const envOrgId = process.env.HIVEMIND_ORG_ID;
|
|
252
|
+
let preferredOrgId = envOrgId;
|
|
253
|
+
if (!preferredOrgId && opts.skipTokenMint) {
|
|
254
|
+
const claims = decodeJwtPayload(token);
|
|
255
|
+
const claimOrg = claims && typeof claims.org_id === "string" ? claims.org_id : void 0;
|
|
256
|
+
if (claimOrg)
|
|
257
|
+
preferredOrgId = claimOrg;
|
|
258
|
+
}
|
|
237
259
|
let orgId;
|
|
238
260
|
let orgName;
|
|
239
|
-
|
|
261
|
+
const matched = preferredOrgId ? orgs.find((o) => o.id === preferredOrgId) : void 0;
|
|
262
|
+
if (matched) {
|
|
263
|
+
orgId = matched.id;
|
|
264
|
+
orgName = matched.name;
|
|
265
|
+
process.stderr.write(`Organization: ${orgName}
|
|
266
|
+
`);
|
|
267
|
+
} else if (orgs.length === 1) {
|
|
240
268
|
orgId = orgs[0].id;
|
|
241
269
|
orgName = orgs[0].name;
|
|
242
270
|
process.stderr.write(`Organization: ${orgName}
|
|
@@ -247,17 +275,26 @@ Logged in as: ${userName}
|
|
|
247
275
|
`));
|
|
248
276
|
orgId = orgs[0].id;
|
|
249
277
|
orgName = orgs[0].name;
|
|
250
|
-
|
|
278
|
+
if (opts.skipTokenMint) {
|
|
279
|
+
process.stderr.write(`
|
|
280
|
+
Using: ${orgName} (set HIVEMIND_ORG_ID to override)
|
|
281
|
+
`);
|
|
282
|
+
} else {
|
|
283
|
+
process.stderr.write(`
|
|
251
284
|
Using: ${orgName}
|
|
252
285
|
`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
let apiToken = token;
|
|
289
|
+
if (!opts.skipTokenMint) {
|
|
290
|
+
const tokenName = `deeplake-plugin-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
|
|
291
|
+
const tokenData = await apiPost("/users/me/tokens", {
|
|
292
|
+
name: tokenName,
|
|
293
|
+
duration: 365 * 24 * 3600,
|
|
294
|
+
organization_id: orgId
|
|
295
|
+
}, token, apiUrl);
|
|
296
|
+
apiToken = tokenData.token.token;
|
|
253
297
|
}
|
|
254
|
-
const tokenName = `deeplake-plugin-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
|
|
255
|
-
const tokenData = await apiPost("/users/me/tokens", {
|
|
256
|
-
name: tokenName,
|
|
257
|
-
duration: 365 * 24 * 3600,
|
|
258
|
-
organization_id: orgId
|
|
259
|
-
}, authToken, apiUrl);
|
|
260
|
-
const apiToken = tokenData.token.token;
|
|
261
298
|
const creds = {
|
|
262
299
|
token: apiToken,
|
|
263
300
|
orgId,
|
|
@@ -270,6 +307,10 @@ Using: ${orgName}
|
|
|
270
307
|
saveCredentials(creds);
|
|
271
308
|
return creds;
|
|
272
309
|
}
|
|
310
|
+
async function login(apiUrl = DEFAULT_API_URL) {
|
|
311
|
+
const { token: authToken } = await deviceFlowLogin(apiUrl);
|
|
312
|
+
return saveCredentialsFromToken(authToken, apiUrl, { skipTokenMint: false });
|
|
313
|
+
}
|
|
273
314
|
|
|
274
315
|
// dist/src/config.js
|
|
275
316
|
import { readFileSync as readFileSync2, existsSync } from "node:fs";
|
|
@@ -969,8 +1010,40 @@ var DeeplakeApi = class {
|
|
|
969
1010
|
}
|
|
970
1011
|
};
|
|
971
1012
|
|
|
972
|
-
// dist/src/
|
|
1013
|
+
// dist/src/cli/util.js
|
|
1014
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4, cpSync, symlinkSync, unlinkSync as unlinkSync3, lstatSync } from "node:fs";
|
|
1015
|
+
import { join as join6, dirname } from "node:path";
|
|
1016
|
+
import { homedir as homedir5 } from "node:os";
|
|
1017
|
+
import { fileURLToPath } from "node:url";
|
|
973
1018
|
import { createInterface } from "node:readline";
|
|
1019
|
+
var HOME = homedir5();
|
|
1020
|
+
var PLATFORM_MARKERS = [
|
|
1021
|
+
{ id: "claude", markerDir: join6(HOME, ".claude") },
|
|
1022
|
+
{ id: "codex", markerDir: join6(HOME, ".codex") },
|
|
1023
|
+
{ id: "claw", markerDir: join6(HOME, ".openclaw") },
|
|
1024
|
+
{ id: "cursor", markerDir: join6(HOME, ".cursor") },
|
|
1025
|
+
{ id: "hermes", markerDir: join6(HOME, ".hermes") },
|
|
1026
|
+
// pi (badlogic/pi-mono coding-agent) — config at ~/.pi/agent/. pi exposes
|
|
1027
|
+
// a rich extension event API (session_start / input / tool_call /
|
|
1028
|
+
// tool_result / message_end / session_shutdown / etc.) — Tier 1 capable.
|
|
1029
|
+
{ id: "pi", markerDir: join6(HOME, ".pi") }
|
|
1030
|
+
];
|
|
1031
|
+
function confirm(message, defaultYes = true) {
|
|
1032
|
+
const hint = defaultYes ? "[Y/n]" : "[y/N]";
|
|
1033
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
1034
|
+
return new Promise((resolve2) => {
|
|
1035
|
+
rl.question(`${message} ${hint} `, (answer) => {
|
|
1036
|
+
rl.close();
|
|
1037
|
+
const a = answer.trim().toLowerCase();
|
|
1038
|
+
if (a === "")
|
|
1039
|
+
resolve2(defaultYes);
|
|
1040
|
+
else
|
|
1041
|
+
resolve2(a === "y" || a === "yes");
|
|
1042
|
+
});
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
// dist/src/commands/session-prune.js
|
|
974
1047
|
function parseArgs(argv) {
|
|
975
1048
|
let before;
|
|
976
1049
|
let sessionId;
|
|
@@ -990,15 +1063,6 @@ function parseArgs(argv) {
|
|
|
990
1063
|
}
|
|
991
1064
|
return { before, sessionId, all, yes };
|
|
992
1065
|
}
|
|
993
|
-
function confirm(message) {
|
|
994
|
-
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
995
|
-
return new Promise((resolve2) => {
|
|
996
|
-
rl.question(`${message} [y/N] `, (answer) => {
|
|
997
|
-
rl.close();
|
|
998
|
-
resolve2(answer.trim().toLowerCase() === "y");
|
|
999
|
-
});
|
|
1000
|
-
});
|
|
1001
|
-
}
|
|
1002
1066
|
function extractSessionId(path) {
|
|
1003
1067
|
const m = path.match(/\/sessions\/[^/]+\/[^/]+_([^.]+)\.jsonl$/);
|
|
1004
1068
|
return m ? m[1] : path.split("/").pop()?.replace(/\.jsonl$/, "") ?? path;
|
|
@@ -1094,7 +1158,7 @@ To delete, use: --all, --before <date>, or --session-id <id>`);
|
|
|
1094
1158
|
}
|
|
1095
1159
|
console.log();
|
|
1096
1160
|
if (!yes) {
|
|
1097
|
-
const ok = await confirm("Proceed with deletion?");
|
|
1161
|
+
const ok = await confirm("Proceed with deletion?", false);
|
|
1098
1162
|
if (!ok) {
|
|
1099
1163
|
console.log("Aborted.");
|
|
1100
1164
|
return;
|
|
@@ -96,6 +96,19 @@ function deleteCredentials() {
|
|
|
96
96
|
|
|
97
97
|
// dist/src/commands/auth.js
|
|
98
98
|
var DEFAULT_API_URL = "https://api.deeplake.ai";
|
|
99
|
+
function decodeJwtPayload(token) {
|
|
100
|
+
try {
|
|
101
|
+
const parts = token.split(".");
|
|
102
|
+
if (parts.length !== 3)
|
|
103
|
+
return null;
|
|
104
|
+
let payload = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
105
|
+
while (payload.length % 4)
|
|
106
|
+
payload += "=";
|
|
107
|
+
return JSON.parse(Buffer.from(payload, "base64").toString("utf8"));
|
|
108
|
+
} catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
99
112
|
async function apiGet(path, token, apiUrl, orgId) {
|
|
100
113
|
const headers = {
|
|
101
114
|
Authorization: `Bearer ${token}`,
|
|
@@ -226,17 +239,32 @@ async function listMembers(token, orgId, apiUrl = DEFAULT_API_URL) {
|
|
|
226
239
|
async function removeMember(userId, token, orgId, apiUrl = DEFAULT_API_URL) {
|
|
227
240
|
await apiDelete(`/organizations/${orgId}/members/${userId}`, token, apiUrl, orgId);
|
|
228
241
|
}
|
|
229
|
-
async function
|
|
230
|
-
const
|
|
231
|
-
const user = await apiGet("/me", authToken, apiUrl);
|
|
242
|
+
async function saveCredentialsFromToken(token, apiUrl, opts = {}) {
|
|
243
|
+
const user = await apiGet("/me", token, apiUrl);
|
|
232
244
|
const userName = user.name || (user.email ? user.email.split("@")[0] : "unknown");
|
|
233
245
|
process.stderr.write(`
|
|
234
246
|
Logged in as: ${userName}
|
|
235
247
|
`);
|
|
236
|
-
const orgs = await listOrgs(
|
|
248
|
+
const orgs = await listOrgs(token, apiUrl);
|
|
249
|
+
if (orgs.length === 0)
|
|
250
|
+
throw new Error("No organizations found for this account.");
|
|
251
|
+
const envOrgId = process.env.HIVEMIND_ORG_ID;
|
|
252
|
+
let preferredOrgId = envOrgId;
|
|
253
|
+
if (!preferredOrgId && opts.skipTokenMint) {
|
|
254
|
+
const claims = decodeJwtPayload(token);
|
|
255
|
+
const claimOrg = claims && typeof claims.org_id === "string" ? claims.org_id : void 0;
|
|
256
|
+
if (claimOrg)
|
|
257
|
+
preferredOrgId = claimOrg;
|
|
258
|
+
}
|
|
237
259
|
let orgId;
|
|
238
260
|
let orgName;
|
|
239
|
-
|
|
261
|
+
const matched = preferredOrgId ? orgs.find((o) => o.id === preferredOrgId) : void 0;
|
|
262
|
+
if (matched) {
|
|
263
|
+
orgId = matched.id;
|
|
264
|
+
orgName = matched.name;
|
|
265
|
+
process.stderr.write(`Organization: ${orgName}
|
|
266
|
+
`);
|
|
267
|
+
} else if (orgs.length === 1) {
|
|
240
268
|
orgId = orgs[0].id;
|
|
241
269
|
orgName = orgs[0].name;
|
|
242
270
|
process.stderr.write(`Organization: ${orgName}
|
|
@@ -247,17 +275,26 @@ Logged in as: ${userName}
|
|
|
247
275
|
`));
|
|
248
276
|
orgId = orgs[0].id;
|
|
249
277
|
orgName = orgs[0].name;
|
|
250
|
-
|
|
278
|
+
if (opts.skipTokenMint) {
|
|
279
|
+
process.stderr.write(`
|
|
280
|
+
Using: ${orgName} (set HIVEMIND_ORG_ID to override)
|
|
281
|
+
`);
|
|
282
|
+
} else {
|
|
283
|
+
process.stderr.write(`
|
|
251
284
|
Using: ${orgName}
|
|
252
285
|
`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
let apiToken = token;
|
|
289
|
+
if (!opts.skipTokenMint) {
|
|
290
|
+
const tokenName = `deeplake-plugin-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
|
|
291
|
+
const tokenData = await apiPost("/users/me/tokens", {
|
|
292
|
+
name: tokenName,
|
|
293
|
+
duration: 365 * 24 * 3600,
|
|
294
|
+
organization_id: orgId
|
|
295
|
+
}, token, apiUrl);
|
|
296
|
+
apiToken = tokenData.token.token;
|
|
253
297
|
}
|
|
254
|
-
const tokenName = `deeplake-plugin-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
|
|
255
|
-
const tokenData = await apiPost("/users/me/tokens", {
|
|
256
|
-
name: tokenName,
|
|
257
|
-
duration: 365 * 24 * 3600,
|
|
258
|
-
organization_id: orgId
|
|
259
|
-
}, authToken, apiUrl);
|
|
260
|
-
const apiToken = tokenData.token.token;
|
|
261
298
|
const creds = {
|
|
262
299
|
token: apiToken,
|
|
263
300
|
orgId,
|
|
@@ -270,6 +307,10 @@ Using: ${orgName}
|
|
|
270
307
|
saveCredentials(creds);
|
|
271
308
|
return creds;
|
|
272
309
|
}
|
|
310
|
+
async function login(apiUrl = DEFAULT_API_URL) {
|
|
311
|
+
const { token: authToken } = await deviceFlowLogin(apiUrl);
|
|
312
|
+
return saveCredentialsFromToken(authToken, apiUrl, { skipTokenMint: false });
|
|
313
|
+
}
|
|
273
314
|
|
|
274
315
|
// dist/src/config.js
|
|
275
316
|
import { readFileSync as readFileSync2, existsSync } from "node:fs";
|
|
@@ -969,8 +1010,40 @@ var DeeplakeApi = class {
|
|
|
969
1010
|
}
|
|
970
1011
|
};
|
|
971
1012
|
|
|
972
|
-
// dist/src/
|
|
1013
|
+
// dist/src/cli/util.js
|
|
1014
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4, cpSync, symlinkSync, unlinkSync as unlinkSync3, lstatSync } from "node:fs";
|
|
1015
|
+
import { join as join6, dirname } from "node:path";
|
|
1016
|
+
import { homedir as homedir5 } from "node:os";
|
|
1017
|
+
import { fileURLToPath } from "node:url";
|
|
973
1018
|
import { createInterface } from "node:readline";
|
|
1019
|
+
var HOME = homedir5();
|
|
1020
|
+
var PLATFORM_MARKERS = [
|
|
1021
|
+
{ id: "claude", markerDir: join6(HOME, ".claude") },
|
|
1022
|
+
{ id: "codex", markerDir: join6(HOME, ".codex") },
|
|
1023
|
+
{ id: "claw", markerDir: join6(HOME, ".openclaw") },
|
|
1024
|
+
{ id: "cursor", markerDir: join6(HOME, ".cursor") },
|
|
1025
|
+
{ id: "hermes", markerDir: join6(HOME, ".hermes") },
|
|
1026
|
+
// pi (badlogic/pi-mono coding-agent) — config at ~/.pi/agent/. pi exposes
|
|
1027
|
+
// a rich extension event API (session_start / input / tool_call /
|
|
1028
|
+
// tool_result / message_end / session_shutdown / etc.) — Tier 1 capable.
|
|
1029
|
+
{ id: "pi", markerDir: join6(HOME, ".pi") }
|
|
1030
|
+
];
|
|
1031
|
+
function confirm(message, defaultYes = true) {
|
|
1032
|
+
const hint = defaultYes ? "[Y/n]" : "[y/N]";
|
|
1033
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
1034
|
+
return new Promise((resolve2) => {
|
|
1035
|
+
rl.question(`${message} ${hint} `, (answer) => {
|
|
1036
|
+
rl.close();
|
|
1037
|
+
const a = answer.trim().toLowerCase();
|
|
1038
|
+
if (a === "")
|
|
1039
|
+
resolve2(defaultYes);
|
|
1040
|
+
else
|
|
1041
|
+
resolve2(a === "y" || a === "yes");
|
|
1042
|
+
});
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
// dist/src/commands/session-prune.js
|
|
974
1047
|
function parseArgs(argv) {
|
|
975
1048
|
let before;
|
|
976
1049
|
let sessionId;
|
|
@@ -990,15 +1063,6 @@ function parseArgs(argv) {
|
|
|
990
1063
|
}
|
|
991
1064
|
return { before, sessionId, all, yes };
|
|
992
1065
|
}
|
|
993
|
-
function confirm(message) {
|
|
994
|
-
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
995
|
-
return new Promise((resolve2) => {
|
|
996
|
-
rl.question(`${message} [y/N] `, (answer) => {
|
|
997
|
-
rl.close();
|
|
998
|
-
resolve2(answer.trim().toLowerCase() === "y");
|
|
999
|
-
});
|
|
1000
|
-
});
|
|
1001
|
-
}
|
|
1002
1066
|
function extractSessionId(path) {
|
|
1003
1067
|
const m = path.match(/\/sessions\/[^/]+\/[^/]+_([^.]+)\.jsonl$/);
|
|
1004
1068
|
return m ? m[1] : path.split("/").pop()?.replace(/\.jsonl$/, "") ?? path;
|
|
@@ -1094,7 +1158,7 @@ To delete, use: --all, --before <date>, or --session-id <id>`);
|
|
|
1094
1158
|
}
|
|
1095
1159
|
console.log();
|
|
1096
1160
|
if (!yes) {
|
|
1097
|
-
const ok = await confirm("Proceed with deletion?");
|
|
1161
|
+
const ok = await confirm("Proceed with deletion?", false);
|
|
1098
1162
|
if (!ok) {
|
|
1099
1163
|
console.log("Aborted.");
|
|
1100
1164
|
return;
|
package/mcp/bundle/server.js
CHANGED
|
@@ -24379,6 +24379,7 @@ import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as rea
|
|
|
24379
24379
|
import { join as join6, dirname } from "node:path";
|
|
24380
24380
|
import { homedir as homedir5 } from "node:os";
|
|
24381
24381
|
import { fileURLToPath } from "node:url";
|
|
24382
|
+
import { createInterface } from "node:readline";
|
|
24382
24383
|
var HOME = homedir5();
|
|
24383
24384
|
function pkgRoot() {
|
|
24384
24385
|
let dir = fileURLToPath(new URL(".", import.meta.url));
|
package/openclaw/dist/index.js
CHANGED
|
@@ -1543,7 +1543,7 @@ function extractLatestVersion(body) {
|
|
|
1543
1543
|
return typeof v === "string" && v.length > 0 ? v : null;
|
|
1544
1544
|
}
|
|
1545
1545
|
function getInstalledVersion() {
|
|
1546
|
-
return "0.7.
|
|
1546
|
+
return "0.7.39".length > 0 ? "0.7.39" : null;
|
|
1547
1547
|
}
|
|
1548
1548
|
function isNewer(latest, current) {
|
|
1549
1549
|
const parse = (v) => v.replace(/-.*$/, "").split(".").map(Number);
|
package/openclaw/package.json
CHANGED