@deeplake/hivemind 0.7.75 → 0.7.77

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.
@@ -54,7 +54,7 @@ var init_index_marker_store = __esm({
54
54
 
55
55
  // dist/src/hooks/cursor/session-start.js
56
56
  import { fileURLToPath as fileURLToPath2 } from "node:url";
57
- import { dirname as dirname7 } from "node:path";
57
+ import { dirname as dirname10 } from "node:path";
58
58
 
59
59
  // dist/src/commands/auth.js
60
60
  import { execSync } from "node:child_process";
@@ -111,6 +111,19 @@ function decodeJwtPayload(token) {
111
111
  return null;
112
112
  }
113
113
  }
114
+ async function apiGet(path, token, apiUrl, orgId) {
115
+ const headers = {
116
+ Authorization: `Bearer ${token}`,
117
+ "Content-Type": "application/json",
118
+ ...deeplakeClientHeader()
119
+ };
120
+ if (orgId)
121
+ headers["X-Activeloop-Org-Id"] = orgId;
122
+ const resp = await fetch(`${apiUrl}${path}`, { headers });
123
+ if (!resp.ok)
124
+ throw new Error(`API ${resp.status}: ${await resp.text().catch(() => "")}`);
125
+ return resp.json();
126
+ }
114
127
  async function apiPost(path, body, token, apiUrl, orgId) {
115
128
  const headers = {
116
129
  Authorization: `Bearer ${token}`,
@@ -124,6 +137,10 @@ async function apiPost(path, body, token, apiUrl, orgId) {
124
137
  throw new Error(`API ${resp.status}: ${await resp.text().catch(() => "")}`);
125
138
  return resp.json();
126
139
  }
140
+ async function listOrgs(token, apiUrl = DEFAULT_API_URL) {
141
+ const data = await apiGet("/organizations", token, apiUrl);
142
+ return Array.isArray(data) ? data : [];
143
+ }
127
144
  async function healDriftedOrgToken(creds, log7 = () => {
128
145
  }) {
129
146
  if (!creds.token || !creds.orgId)
@@ -142,6 +159,33 @@ async function healDriftedOrgToken(creds, log7 = () => {
142
159
  organization_id: creds.orgId
143
160
  }, creds.token, apiUrl);
144
161
  const healed = { ...creds, token: tokenData.token.token };
162
+ try {
163
+ const orgs = await listOrgs(healed.token, apiUrl);
164
+ const matchedOrg = orgs.find((o) => o.id === creds.orgId);
165
+ if (matchedOrg && matchedOrg.name !== creds.orgName) {
166
+ log7(`orgName realigned: ${creds.orgName ?? "(unset)"} -> ${matchedOrg.name}`);
167
+ healed.orgName = matchedOrg.name;
168
+ }
169
+ } catch (e) {
170
+ log7(`orgName realign skipped: ${e.message}`);
171
+ }
172
+ const currentWs = creds.workspaceId ?? "default";
173
+ if (currentWs !== "default") {
174
+ try {
175
+ const wsList = await listWorkspaces(healed.token, apiUrl, creds.orgId);
176
+ const lcWs = currentWs.toLowerCase();
177
+ const wsMatch = wsList.find((w) => w.id === currentWs || w.name && w.name.toLowerCase() === lcWs);
178
+ if (!wsMatch) {
179
+ log7(`workspace '${currentWs}' not in org ${creds.orgId} \u2014 reset to default`);
180
+ healed.workspaceId = "default";
181
+ } else if (wsMatch.id !== currentWs) {
182
+ log7(`workspace '${currentWs}' resolved to id '${wsMatch.id}'`);
183
+ healed.workspaceId = wsMatch.id;
184
+ }
185
+ } catch (e) {
186
+ log7(`workspace realign skipped: ${e.message}`);
187
+ }
188
+ }
145
189
  saveCredentials(healed);
146
190
  log7(`token re-minted for org=${creds.orgId}`);
147
191
  return healed;
@@ -150,6 +194,11 @@ async function healDriftedOrgToken(creds, log7 = () => {
150
194
  return creds;
151
195
  }
152
196
  }
197
+ async function listWorkspaces(token, apiUrl = DEFAULT_API_URL, orgId) {
198
+ const raw = await apiGet("/workspaces", token, apiUrl, orgId);
199
+ const data = raw.data ?? raw;
200
+ return Array.isArray(data) ? data : [];
201
+ }
153
202
 
154
203
  // dist/src/config.js
155
204
  import { readFileSync as readFileSync3, existsSync } from "node:fs";
@@ -577,7 +626,7 @@ function getQueryTimeoutMs() {
577
626
  return Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
578
627
  }
579
628
  function sleep2(ms) {
580
- return new Promise((resolve2) => setTimeout(resolve2, ms));
629
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
581
630
  }
582
631
  function isTimeoutError(error) {
583
632
  const name = error instanceof Error ? error.name.toLowerCase() : "";
@@ -607,7 +656,7 @@ var Semaphore = class {
607
656
  this.active++;
608
657
  return;
609
658
  }
610
- await new Promise((resolve2) => this.waiting.push(resolve2));
659
+ await new Promise((resolve3) => this.waiting.push(resolve3));
611
660
  }
612
661
  release() {
613
662
  this.active--;
@@ -1359,13 +1408,13 @@ function maybeAutoMineLocal() {
1359
1408
 
1360
1409
  // dist/src/utils/stdin.js
1361
1410
  function readStdin() {
1362
- return new Promise((resolve2, reject) => {
1411
+ return new Promise((resolve3, reject) => {
1363
1412
  let data = "";
1364
1413
  process.stdin.setEncoding("utf-8");
1365
1414
  process.stdin.on("data", (chunk) => data += chunk);
1366
1415
  process.stdin.on("end", () => {
1367
1416
  try {
1368
- resolve2(JSON.parse(data));
1417
+ resolve3(JSON.parse(data));
1369
1418
  } catch (err) {
1370
1419
  reject(new Error(`Failed to parse hook input: ${err}`));
1371
1420
  }
@@ -2206,9 +2255,213 @@ function spawnGraphPullWorker(cwd, bundleDir, deps = {}) {
2206
2255
  }
2207
2256
  }
2208
2257
 
2258
+ // dist/src/graph/session-context.js
2259
+ import { createHash as createHash3 } from "node:crypto";
2260
+ import { existsSync as existsSync13 } from "node:fs";
2261
+ import { join as join21 } from "node:path";
2262
+
2263
+ // dist/src/graph/last-build.js
2264
+ import { existsSync as existsSync11, mkdirSync as mkdirSync10, readFileSync as readFileSync11, renameSync as renameSync5, writeFileSync as writeFileSync9 } from "node:fs";
2265
+ import { dirname as dirname7, join as join18 } from "node:path";
2266
+ function lastBuildPath(baseDir, worktreeId) {
2267
+ if (worktreeId !== void 0) {
2268
+ return join18(baseDir, "worktrees", worktreeId, ".last-build.json");
2269
+ }
2270
+ return join18(baseDir, ".last-build.json");
2271
+ }
2272
+ function readLastBuild(baseDir, worktreeId) {
2273
+ let path = lastBuildPath(baseDir, worktreeId);
2274
+ if (!existsSync11(path)) {
2275
+ if (worktreeId === void 0)
2276
+ return null;
2277
+ const legacy = lastBuildPath(baseDir, void 0);
2278
+ if (!existsSync11(legacy))
2279
+ return null;
2280
+ path = legacy;
2281
+ }
2282
+ let raw;
2283
+ try {
2284
+ raw = readFileSync11(path, "utf8");
2285
+ } catch {
2286
+ return null;
2287
+ }
2288
+ let parsed;
2289
+ try {
2290
+ parsed = JSON.parse(raw);
2291
+ } catch {
2292
+ return null;
2293
+ }
2294
+ if (parsed === null || typeof parsed !== "object")
2295
+ return null;
2296
+ const o = parsed;
2297
+ if (typeof o.ts !== "number" || !Number.isFinite(o.ts))
2298
+ return null;
2299
+ if (o.commit_sha !== null && typeof o.commit_sha !== "string")
2300
+ return null;
2301
+ if (typeof o.snapshot_sha256 !== "string")
2302
+ return null;
2303
+ const out = { ts: o.ts, commit_sha: o.commit_sha, snapshot_sha256: o.snapshot_sha256 };
2304
+ if (typeof o.node_count === "number" && Number.isFinite(o.node_count) && o.node_count >= 0) {
2305
+ out.node_count = o.node_count;
2306
+ }
2307
+ if (typeof o.edge_count === "number" && Number.isFinite(o.edge_count) && o.edge_count >= 0) {
2308
+ out.edge_count = o.edge_count;
2309
+ }
2310
+ return out;
2311
+ }
2312
+
2313
+ // dist/src/graph/snapshot.js
2314
+ import { createHash } from "node:crypto";
2315
+ import { mkdirSync as mkdirSync12, renameSync as renameSync6, writeFileSync as writeFileSync10 } from "node:fs";
2316
+ import { homedir as homedir12 } from "node:os";
2317
+ import { dirname as dirname9, join as join20 } from "node:path";
2318
+
2319
+ // dist/src/graph/history.js
2320
+ import { appendFileSync as appendFileSync2, existsSync as existsSync12, mkdirSync as mkdirSync11, readFileSync as readFileSync12 } from "node:fs";
2321
+ import { dirname as dirname8, join as join19 } from "node:path";
2322
+
2323
+ // dist/src/graph/resolve/cross-file.js
2324
+ import { posix } from "node:path";
2325
+
2326
+ // dist/src/graph/snapshot.js
2327
+ function graphsRoot() {
2328
+ return process.env.HIVEMIND_GRAPHS_HOME ?? join20(homedir12(), ".hivemind", "graphs");
2329
+ }
2330
+ function repoDir(repoKey) {
2331
+ return join20(graphsRoot(), repoKey);
2332
+ }
2333
+
2334
+ // dist/src/utils/repo-identity.js
2335
+ import { execSync as execSync2 } from "node:child_process";
2336
+ import { createHash as createHash2 } from "node:crypto";
2337
+ import { basename as basename2, resolve as resolve2 } from "node:path";
2338
+ var DEFAULT_PORTS = {
2339
+ http: "80",
2340
+ https: "443",
2341
+ ssh: "22",
2342
+ git: "9418"
2343
+ };
2344
+ function normalizeGitRemoteUrl(url) {
2345
+ let s = url.trim();
2346
+ const schemeMatch = s.match(/^([a-z][a-z0-9+.-]*):\/\//i);
2347
+ const scheme = schemeMatch ? schemeMatch[1].toLowerCase() : null;
2348
+ if (schemeMatch)
2349
+ s = s.slice(schemeMatch[0].length);
2350
+ if (!scheme) {
2351
+ const scp = s.match(/^(?:[^@/\s]+@)?([^:/\s]+):(.+)$/);
2352
+ if (scp)
2353
+ s = `${scp[1]}/${scp[2]}`;
2354
+ }
2355
+ s = s.replace(/^[^@/]+@/, "");
2356
+ if (scheme && DEFAULT_PORTS[scheme]) {
2357
+ s = s.replace(new RegExp(`^([^/]+):${DEFAULT_PORTS[scheme]}(/|$)`), "$1$2");
2358
+ }
2359
+ s = s.replace(/\.git\/?$/i, "");
2360
+ s = s.replace(/\/+$/, "");
2361
+ return s.toLowerCase();
2362
+ }
2363
+ function deriveProjectKey(cwd) {
2364
+ const absCwd = resolve2(cwd);
2365
+ const project = basename2(absCwd) || "unknown";
2366
+ let signature = null;
2367
+ try {
2368
+ const raw = execSync2("git config --get remote.origin.url", {
2369
+ cwd: absCwd,
2370
+ encoding: "utf-8",
2371
+ stdio: ["ignore", "pipe", "ignore"]
2372
+ }).trim();
2373
+ signature = raw ? normalizeGitRemoteUrl(raw) : null;
2374
+ } catch {
2375
+ }
2376
+ const input = signature ?? absCwd;
2377
+ const key = createHash2("sha1").update(input).digest("hex").slice(0, 16);
2378
+ return { key, project };
2379
+ }
2380
+
2381
+ // dist/src/graph/session-context.js
2382
+ function workTreeIdFor(cwd) {
2383
+ return createHash3("sha256").update(cwd).digest("hex").slice(0, 16);
2384
+ }
2385
+ function graphContextLine(cwd, deps = {}) {
2386
+ let key;
2387
+ let snapshotsDir;
2388
+ let baseDir;
2389
+ try {
2390
+ key = deriveProjectKey(cwd).key;
2391
+ baseDir = repoDir(key);
2392
+ snapshotsDir = join21(baseDir, "snapshots");
2393
+ } catch {
2394
+ return null;
2395
+ }
2396
+ if (!existsSync13(snapshotsDir))
2397
+ return null;
2398
+ const last = readLastBuild(baseDir, workTreeIdFor(cwd));
2399
+ if (last === null)
2400
+ return null;
2401
+ if (last.commit_sha !== null && !/^[0-9a-f]{4,64}$/.test(last.commit_sha))
2402
+ return null;
2403
+ if (!/^[0-9a-f]{64}$/.test(last.snapshot_sha256))
2404
+ return null;
2405
+ const now = (deps.now ?? Date.now)();
2406
+ const ageMs = Math.max(0, now - last.ts);
2407
+ const nodesStr = last.node_count !== void 0 ? String(last.node_count) : "?";
2408
+ const edgesStr = last.edge_count !== void 0 ? String(last.edge_count) : "?";
2409
+ const commitStr = last.commit_sha !== null ? last.commit_sha.slice(0, 7) : "no-commit";
2410
+ const ageStr = formatAge(ageMs);
2411
+ const snapshotFile = last.commit_sha ?? last.snapshot_sha256;
2412
+ const snapshotPath = join21(snapshotsDir, `${snapshotFile}.json`);
2413
+ const STALE_WARN_MS = 60 * 60 * 1e3;
2414
+ const STALE_HARD_MS = 24 * 60 * 60 * 1e3;
2415
+ let staleness;
2416
+ if (ageMs >= STALE_HARD_MS) {
2417
+ staleness = " \u26A0\uFE0F STALE: this snapshot is over a day old; the auto-rebuild may have stopped.\n Prefer reading current source for any file you suspect has changed.";
2418
+ } else if (ageMs >= STALE_WARN_MS) {
2419
+ staleness = " \u26A0\uFE0F Possibly out of date (> 1h since last build). For any file you've edited\n in this session, fall back to reading the live source instead of the graph.";
2420
+ } else {
2421
+ staleness = " Freshness: auto-rebuilds run on Stop/SessionEnd; if a file's mtime is newer\n than the build timestamp above, prefer reading the live source for that file.";
2422
+ }
2423
+ return [
2424
+ "",
2425
+ "LOCAL CODE GRAPH (TypeScript / JavaScript / Python, AST-based):",
2426
+ ` ${nodesStr} nodes, ${edgesStr} edges (commit ${commitStr}, built ${ageStr} ago)`,
2427
+ "",
2428
+ " Use it as a fast INDEX to locate the few files/symbols that matter, then",
2429
+ " open them with Read to answer. It is NOT a substitute for the source: it",
2430
+ " omits instance-method calls (obj.method()), nested/inner functions, and",
2431
+ " dynamic dispatch \u2014 so confirm every claim against the file before stating it.",
2432
+ "",
2433
+ " Query via the Deeplake mount (intercepted \u2014 use `cat`, not `ls`):",
2434
+ " cat ~/.deeplake/memory/graph/query/<pattern> \u2190 start here",
2435
+ " search + 1-hop expand (callers, callees, imports). AND: query/<a>+<b>.",
2436
+ " cat ~/.deeplake/memory/graph/find/<pattern> substring search \u2192 handles",
2437
+ " cat ~/.deeplake/memory/graph/show/<handle-or-pattern> node + 1-hop neighbors",
2438
+ " cat ~/.deeplake/memory/graph/neighborhood/<file> symbols + cross-file links",
2439
+ " Also: index.md \xB7 layers \xB7 tour \xB7 path/<from>/<to>",
2440
+ "",
2441
+ " Then READ the files the graph points you to \u2014 don't answer from the graph",
2442
+ " alone. Cross-file calls/imports resolved for named imports across TS/JS/Python;",
2443
+ " bare (npm)/aliased/barrel/dynamic + instance-method dispatch stay unresolved.",
2444
+ ` Raw snapshot (fallback): ${snapshotPath}`,
2445
+ staleness
2446
+ ].join("\n");
2447
+ }
2448
+ function formatAge(ms) {
2449
+ const s = Math.floor(ms / 1e3);
2450
+ if (s < 60)
2451
+ return `${s}s`;
2452
+ const m = Math.floor(s / 60);
2453
+ if (m < 60)
2454
+ return `${m}m`;
2455
+ const h = Math.floor(m / 60);
2456
+ if (h < 24)
2457
+ return `${h}h`;
2458
+ const d = Math.floor(h / 24);
2459
+ return `${d}d`;
2460
+ }
2461
+
2209
2462
  // dist/src/hooks/cursor/session-start.js
2210
2463
  var log6 = (msg) => log("cursor-session-start", msg);
2211
- var __bundleDir = dirname7(fileURLToPath2(import.meta.url));
2464
+ var __bundleDir = dirname10(fileURLToPath2(import.meta.url));
2212
2465
  var context = `DEEPLAKE MEMORY: Persistent memory at ~/.deeplake/memory/ shared across sessions, users, and agents.
2213
2466
 
2214
2467
  Structure: index.md (start here) \u2192 summaries/*.md \u2192 sessions/*.jsonl (last resort). Do NOT jump straight to JSONL.
@@ -2329,9 +2582,12 @@ Not logged in to Deeplake. Run: hivemind login${localMinedNote}${versionNotice}`
2329
2582
  const baseWithGoals = creds?.token ? `${baseContext}
2330
2583
 
2331
2584
  ${GOALS_INSTRUCTIONS_CLI}` : baseContext;
2332
- const additionalContext = rulesBlock ? `${baseWithGoals}
2585
+ const withRules = rulesBlock ? `${baseWithGoals}
2333
2586
 
2334
2587
  ${rulesBlock}` : baseWithGoals;
2588
+ const graphLine = graphContextLine(resolveCwd(input));
2589
+ const additionalContext = graphLine ? `${withRules}
2590
+ ${graphLine}` : withRules;
2335
2591
  console.log(JSON.stringify({ additional_context: additionalContext }));
2336
2592
  }
2337
2593
  main().catch((e) => {