@deeplake/hivemind 0.6.48 → 0.7.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.
Files changed (40) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +147 -20
  4. package/bundle/cli.js +552 -95
  5. package/codex/bundle/capture.js +509 -89
  6. package/codex/bundle/commands/auth-login.js +209 -66
  7. package/codex/bundle/embeddings/embed-daemon.js +243 -0
  8. package/codex/bundle/pre-tool-use.js +629 -104
  9. package/codex/bundle/session-start-setup.js +194 -57
  10. package/codex/bundle/session-start.js +25 -10
  11. package/codex/bundle/shell/deeplake-shell.js +679 -112
  12. package/codex/bundle/stop.js +476 -58
  13. package/codex/bundle/wiki-worker.js +312 -11
  14. package/cursor/bundle/capture.js +768 -57
  15. package/cursor/bundle/commands/auth-login.js +209 -66
  16. package/cursor/bundle/embeddings/embed-daemon.js +243 -0
  17. package/cursor/bundle/pre-tool-use.js +561 -70
  18. package/cursor/bundle/session-end.js +223 -2
  19. package/cursor/bundle/session-start.js +192 -54
  20. package/cursor/bundle/shell/deeplake-shell.js +679 -112
  21. package/cursor/bundle/wiki-worker.js +571 -0
  22. package/hermes/bundle/capture.js +771 -58
  23. package/hermes/bundle/commands/auth-login.js +209 -66
  24. package/hermes/bundle/embeddings/embed-daemon.js +243 -0
  25. package/hermes/bundle/pre-tool-use.js +560 -69
  26. package/hermes/bundle/session-end.js +224 -1
  27. package/hermes/bundle/session-start.js +195 -54
  28. package/hermes/bundle/shell/deeplake-shell.js +679 -112
  29. package/hermes/bundle/wiki-worker.js +572 -0
  30. package/mcp/bundle/server.js +253 -68
  31. package/openclaw/dist/chunks/auth-creds-AEKS6D3P.js +14 -0
  32. package/openclaw/dist/chunks/chunk-SRCBBT4H.js +37 -0
  33. package/openclaw/dist/chunks/config-G23NI5TV.js +33 -0
  34. package/openclaw/dist/chunks/index-marker-store-PGT5CW6T.js +33 -0
  35. package/openclaw/dist/chunks/setup-config-C35UK4LP.js +114 -0
  36. package/openclaw/dist/index.js +752 -702
  37. package/openclaw/openclaw.plugin.json +1 -1
  38. package/openclaw/package.json +1 -1
  39. package/package.json +2 -1
  40. package/pi/extension-source/hivemind.ts +473 -21
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __commonJS = (cb, mod) => function __require() {
9
12
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
13
  };
@@ -6798,6 +6801,49 @@ var require_dist = __commonJS({
6798
6801
  }
6799
6802
  });
6800
6803
 
6804
+ // dist/src/index-marker-store.js
6805
+ var index_marker_store_exports = {};
6806
+ __export(index_marker_store_exports, {
6807
+ buildIndexMarkerPath: () => buildIndexMarkerPath,
6808
+ getIndexMarkerDir: () => getIndexMarkerDir,
6809
+ hasFreshIndexMarker: () => hasFreshIndexMarker,
6810
+ writeIndexMarker: () => writeIndexMarker
6811
+ });
6812
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
6813
+ import { join as join4 } from "node:path";
6814
+ import { tmpdir } from "node:os";
6815
+ function getIndexMarkerDir() {
6816
+ return process.env.HIVEMIND_INDEX_MARKER_DIR ?? join4(tmpdir(), "hivemind-deeplake-indexes");
6817
+ }
6818
+ function buildIndexMarkerPath(workspaceId, orgId, table, suffix) {
6819
+ const markerKey = [workspaceId, orgId, table, suffix].join("__").replace(/[^a-zA-Z0-9_.-]/g, "_");
6820
+ return join4(getIndexMarkerDir(), `${markerKey}.json`);
6821
+ }
6822
+ function hasFreshIndexMarker(markerPath) {
6823
+ if (!existsSync2(markerPath))
6824
+ return false;
6825
+ try {
6826
+ const raw = JSON.parse(readFileSync3(markerPath, "utf-8"));
6827
+ const updatedAt = raw.updatedAt ? new Date(raw.updatedAt).getTime() : NaN;
6828
+ if (!Number.isFinite(updatedAt) || Date.now() - updatedAt > INDEX_MARKER_TTL_MS)
6829
+ return false;
6830
+ return true;
6831
+ } catch {
6832
+ return false;
6833
+ }
6834
+ }
6835
+ function writeIndexMarker(markerPath) {
6836
+ mkdirSync2(getIndexMarkerDir(), { recursive: true });
6837
+ writeFileSync2(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
6838
+ }
6839
+ var INDEX_MARKER_TTL_MS;
6840
+ var init_index_marker_store = __esm({
6841
+ "dist/src/index-marker-store.js"() {
6842
+ "use strict";
6843
+ INDEX_MARKER_TTL_MS = Number(process.env.HIVEMIND_INDEX_MARKER_TTL_MS ?? 6 * 60 * 6e4);
6844
+ }
6845
+ });
6846
+
6801
6847
  // node_modules/zod/v3/helpers/util.js
6802
6848
  var util;
6803
6849
  (function(util2) {
@@ -23220,31 +23266,44 @@ var StdioServerTransport = class {
23220
23266
  };
23221
23267
 
23222
23268
  // dist/src/commands/auth.js
23223
- import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync } from "node:fs";
23269
+ import { execSync } from "node:child_process";
23270
+
23271
+ // dist/src/utils/client-header.js
23272
+ var DEEPLAKE_CLIENT_HEADER = "X-Deeplake-Client";
23273
+ function deeplakeClientValue() {
23274
+ return "hivemind";
23275
+ }
23276
+ function deeplakeClientHeader() {
23277
+ return { [DEEPLAKE_CLIENT_HEADER]: deeplakeClientValue() };
23278
+ }
23279
+
23280
+ // dist/src/commands/auth-creds.js
23281
+ import { readFileSync, writeFileSync, mkdirSync, unlinkSync } from "node:fs";
23224
23282
  import { join } from "node:path";
23225
23283
  import { homedir } from "node:os";
23226
- import { execSync } from "node:child_process";
23227
- var CONFIG_DIR = join(homedir(), ".deeplake");
23228
- var CREDS_PATH = join(CONFIG_DIR, "credentials.json");
23284
+ function configDir() {
23285
+ return join(homedir(), ".deeplake");
23286
+ }
23287
+ function credsPath() {
23288
+ return join(configDir(), "credentials.json");
23289
+ }
23229
23290
  function loadCredentials() {
23230
- if (!existsSync(CREDS_PATH))
23231
- return null;
23232
23291
  try {
23233
- return JSON.parse(readFileSync(CREDS_PATH, "utf-8"));
23292
+ return JSON.parse(readFileSync(credsPath(), "utf-8"));
23234
23293
  } catch {
23235
23294
  return null;
23236
23295
  }
23237
23296
  }
23238
23297
 
23239
23298
  // dist/src/config.js
23240
- import { readFileSync as readFileSync2, existsSync as existsSync2 } from "node:fs";
23299
+ import { readFileSync as readFileSync2, existsSync } from "node:fs";
23241
23300
  import { join as join2 } from "node:path";
23242
23301
  import { homedir as homedir2, userInfo } from "node:os";
23243
23302
  function loadConfig() {
23244
23303
  const home = homedir2();
23245
23304
  const credPath = join2(home, ".deeplake", "credentials.json");
23246
23305
  let creds = null;
23247
- if (existsSync2(credPath)) {
23306
+ if (existsSync(credPath)) {
23248
23307
  try {
23249
23308
  creds = JSON.parse(readFileSync2(credPath, "utf-8"));
23250
23309
  } catch {
@@ -23270,9 +23329,6 @@ function loadConfig() {
23270
23329
 
23271
23330
  // dist/src/deeplake-api.js
23272
23331
  import { randomUUID } from "node:crypto";
23273
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
23274
- import { join as join4 } from "node:path";
23275
- import { tmpdir } from "node:os";
23276
23332
 
23277
23333
  // dist/src/utils/debug.js
23278
23334
  import { appendFileSync } from "node:fs";
@@ -23295,7 +23351,17 @@ function sqlLike(value) {
23295
23351
  return sqlStr(value).replace(/%/g, "\\%").replace(/_/g, "\\_");
23296
23352
  }
23297
23353
 
23354
+ // dist/src/embeddings/columns.js
23355
+ var SUMMARY_EMBEDDING_COL = "summary_embedding";
23356
+ var MESSAGE_EMBEDDING_COL = "message_embedding";
23357
+
23298
23358
  // dist/src/deeplake-api.js
23359
+ var indexMarkerStorePromise = null;
23360
+ function getIndexMarkerStore() {
23361
+ if (!indexMarkerStorePromise)
23362
+ indexMarkerStorePromise = Promise.resolve().then(() => (init_index_marker_store(), index_marker_store_exports));
23363
+ return indexMarkerStorePromise;
23364
+ }
23299
23365
  var log2 = (msg) => log("sdk", msg);
23300
23366
  function summarizeSql(sql, maxLen = 220) {
23301
23367
  const compact = sql.replace(/\s+/g, " ").trim();
@@ -23315,7 +23381,6 @@ var MAX_RETRIES = 3;
23315
23381
  var BASE_DELAY_MS = 500;
23316
23382
  var MAX_CONCURRENCY = 5;
23317
23383
  var QUERY_TIMEOUT_MS = Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
23318
- var INDEX_MARKER_TTL_MS = Number(process.env.HIVEMIND_INDEX_MARKER_TTL_MS ?? 6 * 60 * 6e4);
23319
23384
  function sleep(ms) {
23320
23385
  return new Promise((resolve) => setTimeout(resolve, ms));
23321
23386
  }
@@ -23335,9 +23400,6 @@ function isTransientHtml403(text) {
23335
23400
  const body = text.toLowerCase();
23336
23401
  return body.includes("<html") || body.includes("403 forbidden") || body.includes("cloudflare") || body.includes("nginx");
23337
23402
  }
23338
- function getIndexMarkerDir() {
23339
- return process.env.HIVEMIND_INDEX_MARKER_DIR ?? join4(tmpdir(), "hivemind-deeplake-indexes");
23340
- }
23341
23403
  var Semaphore = class {
23342
23404
  max;
23343
23405
  waiting = [];
@@ -23406,7 +23468,8 @@ var DeeplakeApi = class {
23406
23468
  headers: {
23407
23469
  Authorization: `Bearer ${this.token}`,
23408
23470
  "Content-Type": "application/json",
23409
- "X-Activeloop-Org-Id": this.orgId
23471
+ "X-Activeloop-Org-Id": this.orgId,
23472
+ ...deeplakeClientHeader()
23410
23473
  },
23411
23474
  signal,
23412
23475
  body: JSON.stringify({ query: sql })
@@ -23433,7 +23496,8 @@ var DeeplakeApi = class {
23433
23496
  }
23434
23497
  const text = await resp.text().catch(() => "");
23435
23498
  const retryable403 = isSessionInsertQuery(sql) && (resp.status === 401 || resp.status === 403 && (text.length === 0 || isTransientHtml403(text)));
23436
- if (attempt < MAX_RETRIES && (RETRYABLE_CODES.has(resp.status) || retryable403)) {
23499
+ const alreadyExists = resp.status === 500 && isDuplicateIndexError(text);
23500
+ if (!alreadyExists && attempt < MAX_RETRIES && (RETRYABLE_CODES.has(resp.status) || retryable403)) {
23437
23501
  const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
23438
23502
  log2(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
23439
23503
  await sleep(delay);
@@ -23467,7 +23531,7 @@ var DeeplakeApi = class {
23467
23531
  const lud = row.lastUpdateDate ?? ts;
23468
23532
  const exists = await this.query(`SELECT path FROM "${this.tableName}" WHERE path = '${sqlStr(row.path)}' LIMIT 1`);
23469
23533
  if (exists.length > 0) {
23470
- let setClauses = `summary = E'${sqlStr(row.contentText)}', mime_type = '${sqlStr(row.mimeType)}', size_bytes = ${row.sizeBytes}, last_update_date = '${lud}'`;
23534
+ let setClauses = `summary = E'${sqlStr(row.contentText)}', ${SUMMARY_EMBEDDING_COL} = NULL, mime_type = '${sqlStr(row.mimeType)}', size_bytes = ${row.sizeBytes}, last_update_date = '${lud}'`;
23471
23535
  if (row.project !== void 0)
23472
23536
  setClauses += `, project = '${sqlStr(row.project)}'`;
23473
23537
  if (row.description !== void 0)
@@ -23475,8 +23539,8 @@ var DeeplakeApi = class {
23475
23539
  await this.query(`UPDATE "${this.tableName}" SET ${setClauses} WHERE path = '${sqlStr(row.path)}'`);
23476
23540
  } else {
23477
23541
  const id = randomUUID();
23478
- let cols = "id, path, filename, summary, mime_type, size_bytes, creation_date, last_update_date";
23479
- let vals = `'${id}', '${sqlStr(row.path)}', '${sqlStr(row.filename)}', E'${sqlStr(row.contentText)}', '${sqlStr(row.mimeType)}', ${row.sizeBytes}, '${cd}', '${lud}'`;
23542
+ let cols = `id, path, filename, summary, ${SUMMARY_EMBEDDING_COL}, mime_type, size_bytes, creation_date, last_update_date`;
23543
+ let vals = `'${id}', '${sqlStr(row.path)}', '${sqlStr(row.filename)}', E'${sqlStr(row.contentText)}', NULL, '${sqlStr(row.mimeType)}', ${row.sizeBytes}, '${cd}', '${lud}'`;
23480
23544
  if (row.project !== void 0) {
23481
23545
  cols += ", project";
23482
23546
  vals += `, '${sqlStr(row.project)}'`;
@@ -23501,48 +23565,83 @@ var DeeplakeApi = class {
23501
23565
  buildLookupIndexName(table, suffix) {
23502
23566
  return `idx_${table}_${suffix}`.replace(/[^a-zA-Z0-9_]/g, "_");
23503
23567
  }
23504
- getLookupIndexMarkerPath(table, suffix) {
23505
- const markerKey = [
23506
- this.workspaceId,
23507
- this.orgId,
23508
- table,
23509
- suffix
23510
- ].join("__").replace(/[^a-zA-Z0-9_.-]/g, "_");
23511
- return join4(getIndexMarkerDir(), `${markerKey}.json`);
23512
- }
23513
- hasFreshLookupIndexMarker(table, suffix) {
23514
- const markerPath = this.getLookupIndexMarkerPath(table, suffix);
23515
- if (!existsSync3(markerPath))
23516
- return false;
23517
- try {
23518
- const raw = JSON.parse(readFileSync3(markerPath, "utf-8"));
23519
- const updatedAt = raw.updatedAt ? new Date(raw.updatedAt).getTime() : NaN;
23520
- if (!Number.isFinite(updatedAt) || Date.now() - updatedAt > INDEX_MARKER_TTL_MS)
23521
- return false;
23522
- return true;
23523
- } catch {
23524
- return false;
23525
- }
23526
- }
23527
- markLookupIndexReady(table, suffix) {
23528
- mkdirSync2(getIndexMarkerDir(), { recursive: true });
23529
- writeFileSync2(this.getLookupIndexMarkerPath(table, suffix), JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
23530
- }
23531
23568
  async ensureLookupIndex(table, suffix, columnsSql) {
23532
- if (this.hasFreshLookupIndexMarker(table, suffix))
23569
+ const markers = await getIndexMarkerStore();
23570
+ const markerPath = markers.buildIndexMarkerPath(this.workspaceId, this.orgId, table, suffix);
23571
+ if (markers.hasFreshIndexMarker(markerPath))
23533
23572
  return;
23534
23573
  const indexName = this.buildLookupIndexName(table, suffix);
23535
23574
  try {
23536
23575
  await this.query(`CREATE INDEX IF NOT EXISTS "${indexName}" ON "${table}" ${columnsSql}`);
23537
- this.markLookupIndexReady(table, suffix);
23576
+ markers.writeIndexMarker(markerPath);
23538
23577
  } catch (e) {
23539
23578
  if (isDuplicateIndexError(e)) {
23540
- this.markLookupIndexReady(table, suffix);
23579
+ markers.writeIndexMarker(markerPath);
23541
23580
  return;
23542
23581
  }
23543
23582
  log2(`index "${indexName}" skipped: ${e.message}`);
23544
23583
  }
23545
23584
  }
23585
+ /**
23586
+ * Ensure a vector column exists on the given table.
23587
+ *
23588
+ * The previous implementation always issued `ALTER TABLE ADD COLUMN IF NOT
23589
+ * EXISTS …` on every SessionStart. On a long-running workspace that's
23590
+ * already migrated, every call returns 500 "Column already exists" — noisy
23591
+ * in the log and a wasted round-trip. Worse, the very first call after the
23592
+ * column is genuinely added triggers Deeplake's post-ALTER `vector::at`
23593
+ * window (~30s) during which subsequent INSERTs fail; minimising the
23594
+ * number of ALTER calls minimises exposure to that window.
23595
+ *
23596
+ * New flow:
23597
+ * 1. Check the local marker file (mirrors ensureLookupIndex). If fresh,
23598
+ * return — zero network calls.
23599
+ * 2. SELECT 1 FROM information_schema.columns WHERE table_name = T AND
23600
+ * column_name = C. Read-only, idempotent, can't tickle the post-ALTER
23601
+ * bug. If the column is present → mark + return.
23602
+ * 3. Only if step 2 says the column is missing, fall back to ALTER ADD
23603
+ * COLUMN IF NOT EXISTS. Mark on success, also mark if Deeplake reports
23604
+ * "already exists" (race: another client added it between our SELECT
23605
+ * and ALTER).
23606
+ *
23607
+ * Marker uses the same dir / TTL as ensureLookupIndex so both schema
23608
+ * caches share an opt-out (HIVEMIND_INDEX_MARKER_DIR) and a TTL knob.
23609
+ */
23610
+ async ensureEmbeddingColumn(table, column) {
23611
+ await this.ensureColumn(table, column, "FLOAT4[]");
23612
+ }
23613
+ /**
23614
+ * Generic marker-gated column migration. Same SELECT-then-ALTER flow as
23615
+ * ensureEmbeddingColumn, parameterized by SQL type so it can patch up any
23616
+ * column that was added to the schema after the table was originally
23617
+ * created. Used today for `summary_embedding`, `message_embedding`, and
23618
+ * the `agent` column (added 2026-04-11) — the latter has no fallback if
23619
+ * a user upgraded over a pre-2026-04-11 table, so every INSERT fails
23620
+ * with `column "agent" does not exist`.
23621
+ */
23622
+ async ensureColumn(table, column, sqlType) {
23623
+ const markers = await getIndexMarkerStore();
23624
+ const markerPath = markers.buildIndexMarkerPath(this.workspaceId, this.orgId, table, `col_${column}`);
23625
+ if (markers.hasFreshIndexMarker(markerPath))
23626
+ return;
23627
+ const colCheck = `SELECT 1 FROM information_schema.columns WHERE table_name = '${sqlStr(table)}' AND column_name = '${sqlStr(column)}' AND table_schema = '${sqlStr(this.workspaceId)}' LIMIT 1`;
23628
+ const rows = await this.query(colCheck);
23629
+ if (rows.length > 0) {
23630
+ markers.writeIndexMarker(markerPath);
23631
+ return;
23632
+ }
23633
+ try {
23634
+ await this.query(`ALTER TABLE "${table}" ADD COLUMN ${column} ${sqlType}`);
23635
+ } catch (e) {
23636
+ const msg = e instanceof Error ? e.message : String(e);
23637
+ if (!/already exists/i.test(msg))
23638
+ throw e;
23639
+ const recheck = await this.query(colCheck);
23640
+ if (recheck.length === 0)
23641
+ throw e;
23642
+ }
23643
+ markers.writeIndexMarker(markerPath);
23644
+ }
23546
23645
  /** List all tables in the workspace (with retry). */
23547
23646
  async listTables(forceRefresh = false) {
23548
23647
  if (!forceRefresh && this._tablesCache)
@@ -23558,7 +23657,8 @@ var DeeplakeApi = class {
23558
23657
  const resp = await fetch(`${this.apiUrl}/workspaces/${this.workspaceId}/tables`, {
23559
23658
  headers: {
23560
23659
  Authorization: `Bearer ${this.token}`,
23561
- "X-Activeloop-Org-Id": this.orgId
23660
+ "X-Activeloop-Org-Id": this.orgId,
23661
+ ...deeplakeClientHeader()
23562
23662
  }
23563
23663
  });
23564
23664
  if (resp.ok) {
@@ -23583,28 +23683,60 @@ var DeeplakeApi = class {
23583
23683
  }
23584
23684
  return { tables: [], cacheable: false };
23585
23685
  }
23686
+ /**
23687
+ * Run a `CREATE TABLE` with an extra outer retry budget. The base
23688
+ * `query()` already retries 3 times on fetch errors (~3.5s total), but a
23689
+ * failed CREATE is permanent corruption — every subsequent SELECT against
23690
+ * the missing table fails. Wrapping in an outer loop with longer backoff
23691
+ * (2s, 5s, then 10s) gives us ~17s of reach across transient network
23692
+ * blips before giving up. Failures still propagate; getApi() resets its
23693
+ * cache on init failure (openclaw plugin) so the next call retries the
23694
+ * whole init flow.
23695
+ */
23696
+ async createTableWithRetry(sql, label) {
23697
+ const OUTER_BACKOFFS_MS = [2e3, 5e3, 1e4];
23698
+ let lastErr = null;
23699
+ for (let attempt = 0; attempt <= OUTER_BACKOFFS_MS.length; attempt++) {
23700
+ try {
23701
+ await this.query(sql);
23702
+ return;
23703
+ } catch (err) {
23704
+ lastErr = err;
23705
+ const msg = err instanceof Error ? err.message : String(err);
23706
+ log2(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
23707
+ if (attempt < OUTER_BACKOFFS_MS.length) {
23708
+ await sleep(OUTER_BACKOFFS_MS[attempt]);
23709
+ }
23710
+ }
23711
+ }
23712
+ throw lastErr;
23713
+ }
23586
23714
  /** Create the memory table if it doesn't already exist. Migrate columns on existing tables. */
23587
23715
  async ensureTable(name) {
23588
23716
  const tbl = name ?? this.tableName;
23589
23717
  const tables = await this.listTables();
23590
23718
  if (!tables.includes(tbl)) {
23591
23719
  log2(`table "${tbl}" not found, creating`);
23592
- await this.query(`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', summary TEXT NOT NULL DEFAULT '', author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'text/plain', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`);
23720
+ await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', summary TEXT NOT NULL DEFAULT '', summary_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'text/plain', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, tbl);
23593
23721
  log2(`table "${tbl}" created`);
23594
23722
  if (!tables.includes(tbl))
23595
23723
  this._tablesCache = [...tables, tbl];
23596
23724
  }
23725
+ await this.ensureEmbeddingColumn(tbl, SUMMARY_EMBEDDING_COL);
23726
+ await this.ensureColumn(tbl, "agent", "TEXT NOT NULL DEFAULT ''");
23597
23727
  }
23598
23728
  /** Create the sessions table (uses JSONB for message since every row is a JSON event). */
23599
23729
  async ensureSessionsTable(name) {
23600
23730
  const tables = await this.listTables();
23601
23731
  if (!tables.includes(name)) {
23602
23732
  log2(`table "${name}" not found, creating`);
23603
- await this.query(`CREATE TABLE IF NOT EXISTS "${name}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', message JSONB, author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/json', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`);
23733
+ await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${name}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', message JSONB, message_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/json', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, name);
23604
23734
  log2(`table "${name}" created`);
23605
23735
  if (!tables.includes(name))
23606
23736
  this._tablesCache = [...tables, name];
23607
23737
  }
23738
+ await this.ensureEmbeddingColumn(name, MESSAGE_EMBEDDING_COL);
23739
+ await this.ensureColumn(name, "agent", "TEXT NOT NULL DEFAULT ''");
23608
23740
  await this.ensureLookupIndex(name, "path_creation_date", `("path", "creation_date")`);
23609
23741
  }
23610
23742
  };
@@ -23773,24 +23905,25 @@ function normalizeContent(path, raw) {
23773
23905
  return raw;
23774
23906
  }
23775
23907
  if (Array.isArray(obj.turns)) {
23776
- const header = [];
23777
- if (obj.date_time)
23778
- header.push(`date: ${obj.date_time}`);
23779
- if (obj.speakers) {
23780
- const s = obj.speakers;
23781
- const names = [s.speaker_a, s.speaker_b].filter(Boolean).join(", ");
23782
- if (names)
23783
- header.push(`speakers: ${names}`);
23784
- }
23908
+ const dateHeader = obj.date_time ? `(${String(obj.date_time)}) ` : "";
23785
23909
  const lines = obj.turns.map((t) => {
23786
23910
  const sp = String(t?.speaker ?? t?.name ?? "?").trim();
23787
23911
  const tx = String(t?.text ?? t?.content ?? "").replace(/\s+/g, " ").trim();
23788
23912
  const tag = t?.dia_id ? `[${t.dia_id}] ` : "";
23789
- return `${tag}${sp}: ${tx}`;
23913
+ return `${dateHeader}${tag}${sp}: ${tx}`;
23790
23914
  });
23791
- const out2 = [...header, ...lines].join("\n");
23915
+ const out2 = lines.join("\n");
23792
23916
  return out2.trim() ? out2 : raw;
23793
23917
  }
23918
+ if (obj.turn && typeof obj.turn === "object" && !Array.isArray(obj.turn)) {
23919
+ const t = obj.turn;
23920
+ const sp = String(t.speaker ?? t.name ?? "?").trim();
23921
+ const tx = String(t.text ?? t.content ?? "").replace(/\s+/g, " ").trim();
23922
+ const tag = t.dia_id ? `[${String(t.dia_id)}] ` : "";
23923
+ const dateHeader = obj.date_time ? `(${String(obj.date_time)}) ` : "";
23924
+ const line = `${dateHeader}${tag}${sp}: ${tx}`;
23925
+ return line.trim() ? line : raw;
23926
+ }
23794
23927
  const stripRecalled = (t) => {
23795
23928
  const i = t.indexOf("<recalled-memories>");
23796
23929
  if (i === -1)
@@ -23833,8 +23966,38 @@ function buildPathCondition(targetPath) {
23833
23966
  return `(path = '${sqlStr(clean)}' OR path LIKE '${sqlLike(clean)}/%' ESCAPE '\\')`;
23834
23967
  }
23835
23968
  async function searchDeeplakeTables(api, memoryTable, sessionsTable, opts) {
23836
- const { pathFilter, contentScanOnly, likeOp, escapedPattern, prefilterPattern, prefilterPatterns, multiWordPatterns } = opts;
23969
+ const { pathFilter, contentScanOnly, likeOp, escapedPattern, prefilterPattern, prefilterPatterns, queryEmbedding, multiWordPatterns } = opts;
23837
23970
  const limit = opts.limit ?? 100;
23971
+ if (queryEmbedding && queryEmbedding.length > 0) {
23972
+ const vecLit = serializeFloat4Array(queryEmbedding);
23973
+ const semanticLimit = Math.min(limit, Number(process.env.HIVEMIND_SEMANTIC_LIMIT ?? "20"));
23974
+ const lexicalLimit = Math.min(limit, Number(process.env.HIVEMIND_HYBRID_LEXICAL_LIMIT ?? "20"));
23975
+ const filterPatternsForLex = contentScanOnly ? prefilterPatterns && prefilterPatterns.length > 0 ? prefilterPatterns : prefilterPattern ? [prefilterPattern] : [] : [escapedPattern];
23976
+ const memLexFilter = buildContentFilter("summary::text", likeOp, filterPatternsForLex);
23977
+ const sessLexFilter = buildContentFilter("message::text", likeOp, filterPatternsForLex);
23978
+ const memLexQuery = memLexFilter ? `SELECT path, summary::text AS content, 0 AS source_order, '' AS creation_date, 1.0 AS score FROM "${memoryTable}" WHERE 1=1${pathFilter}${memLexFilter} LIMIT ${lexicalLimit}` : null;
23979
+ const sessLexQuery = sessLexFilter ? `SELECT path, message::text AS content, 1 AS source_order, COALESCE(creation_date::text, '') AS creation_date, 1.0 AS score FROM "${sessionsTable}" WHERE 1=1${pathFilter}${sessLexFilter} LIMIT ${lexicalLimit}` : null;
23980
+ const memSemQuery = `SELECT path, summary::text AS content, 0 AS source_order, '' AS creation_date, (summary_embedding <#> ${vecLit}) AS score FROM "${memoryTable}" WHERE ARRAY_LENGTH(summary_embedding, 1) > 0${pathFilter} ORDER BY score DESC LIMIT ${semanticLimit}`;
23981
+ const sessSemQuery = `SELECT path, message::text AS content, 1 AS source_order, COALESCE(creation_date::text, '') AS creation_date, (message_embedding <#> ${vecLit}) AS score FROM "${sessionsTable}" WHERE ARRAY_LENGTH(message_embedding, 1) > 0${pathFilter} ORDER BY score DESC LIMIT ${semanticLimit}`;
23982
+ const parts = [memSemQuery, sessSemQuery];
23983
+ if (memLexQuery)
23984
+ parts.push(memLexQuery);
23985
+ if (sessLexQuery)
23986
+ parts.push(sessLexQuery);
23987
+ const unionSql = parts.map((q) => `(${q})`).join(" UNION ALL ");
23988
+ const outerLimit = semanticLimit + lexicalLimit;
23989
+ const rows2 = await api.query(`SELECT path, content, source_order, creation_date, score FROM (` + unionSql + `) AS combined ORDER BY score DESC LIMIT ${outerLimit}`);
23990
+ const seen = /* @__PURE__ */ new Set();
23991
+ const unique = [];
23992
+ for (const row of rows2) {
23993
+ const p = String(row["path"]);
23994
+ if (seen.has(p))
23995
+ continue;
23996
+ seen.add(p);
23997
+ unique.push({ path: p, content: String(row["content"] ?? "") });
23998
+ }
23999
+ return unique;
24000
+ }
23838
24001
  const filterPatterns = contentScanOnly ? prefilterPatterns && prefilterPatterns.length > 0 ? prefilterPatterns : prefilterPattern ? [prefilterPattern] : [] : multiWordPatterns && multiWordPatterns.length > 1 ? multiWordPatterns : [escapedPattern];
23839
24002
  const memFilter = buildContentFilter("summary::text", likeOp, filterPatterns);
23840
24003
  const sessFilter = buildContentFilter("message::text", likeOp, filterPatterns);
@@ -23846,6 +24009,15 @@ async function searchDeeplakeTables(api, memoryTable, sessionsTable, opts) {
23846
24009
  content: String(row["content"] ?? "")
23847
24010
  }));
23848
24011
  }
24012
+ function serializeFloat4Array(vec) {
24013
+ const parts = [];
24014
+ for (const v of vec) {
24015
+ if (!Number.isFinite(v))
24016
+ return "NULL";
24017
+ parts.push(String(v));
24018
+ }
24019
+ return `ARRAY[${parts.join(",")}]::float4[]`;
24020
+ }
23849
24021
  function buildPathFilter(targetPath) {
23850
24022
  const condition = buildPathCondition(targetPath);
23851
24023
  return condition ? ` AND ${condition}` : "";
@@ -23928,7 +24100,7 @@ function buildGrepSearchOptions(params, targetPath) {
23928
24100
  return {
23929
24101
  pathFilter: buildPathFilter(targetPath),
23930
24102
  contentScanOnly: hasRegexMeta,
23931
- likeOp: params.ignoreCase ? "ILIKE" : "LIKE",
24103
+ likeOp: process.env.HIVEMIND_GREP_LIKE === "case-sensitive" ? "LIKE" : "ILIKE",
23932
24104
  escapedPattern: sqlLike(params.pattern),
23933
24105
  prefilterPattern: literalPrefilter ? sqlLike(literalPrefilter) : void 0,
23934
24106
  prefilterPatterns: alternationPrefilters?.map((literal2) => sqlLike(literal2)),
@@ -23948,12 +24120,25 @@ import { readFileSync as readFileSync5 } from "node:fs";
23948
24120
  import { join as join6 } from "node:path";
23949
24121
 
23950
24122
  // dist/src/cli/util.js
23951
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3, cpSync, symlinkSync, unlinkSync as unlinkSync2, lstatSync } from "node:fs";
24123
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3, cpSync, symlinkSync, unlinkSync as unlinkSync2, lstatSync } from "node:fs";
23952
24124
  import { join as join5, dirname } from "node:path";
23953
24125
  import { homedir as homedir4 } from "node:os";
23954
24126
  import { fileURLToPath } from "node:url";
23955
24127
  var HOME = homedir4();
23956
24128
  function pkgRoot() {
24129
+ let dir = fileURLToPath(new URL(".", import.meta.url));
24130
+ for (let i = 0; i < 8; i++) {
24131
+ try {
24132
+ const pkg = JSON.parse(readFileSync4(join5(dir, "package.json"), "utf-8"));
24133
+ if (pkg.name === "@deeplake/hivemind" || pkg.name === "hivemind")
24134
+ return dir;
24135
+ } catch {
24136
+ }
24137
+ const parent = dirname(dir);
24138
+ if (parent === dir)
24139
+ break;
24140
+ dir = parent;
24141
+ }
23957
24142
  return fileURLToPath(new URL("..", import.meta.url));
23958
24143
  }
23959
24144
  var PLATFORM_MARKERS = [
@@ -0,0 +1,14 @@
1
+ import {
2
+ configDir,
3
+ credsPath,
4
+ deleteCredentials,
5
+ loadCredentials,
6
+ saveCredentials
7
+ } from "./chunk-SRCBBT4H.js";
8
+ export {
9
+ configDir,
10
+ credsPath,
11
+ deleteCredentials,
12
+ loadCredentials,
13
+ saveCredentials
14
+ };
@@ -0,0 +1,37 @@
1
+ // src/commands/auth-creds.ts
2
+ import { readFileSync, writeFileSync, mkdirSync, unlinkSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { homedir } from "node:os";
5
+ function configDir() {
6
+ return join(homedir(), ".deeplake");
7
+ }
8
+ function credsPath() {
9
+ return join(configDir(), "credentials.json");
10
+ }
11
+ function loadCredentials() {
12
+ try {
13
+ return JSON.parse(readFileSync(credsPath(), "utf-8"));
14
+ } catch {
15
+ return null;
16
+ }
17
+ }
18
+ function saveCredentials(creds) {
19
+ mkdirSync(configDir(), { recursive: true, mode: 448 });
20
+ writeFileSync(credsPath(), JSON.stringify({ ...creds, savedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), { mode: 384 });
21
+ }
22
+ function deleteCredentials() {
23
+ try {
24
+ unlinkSync(credsPath());
25
+ return true;
26
+ } catch {
27
+ return false;
28
+ }
29
+ }
30
+
31
+ export {
32
+ configDir,
33
+ credsPath,
34
+ loadCredentials,
35
+ saveCredentials,
36
+ deleteCredentials
37
+ };
@@ -0,0 +1,33 @@
1
+ // src/config.ts
2
+ import { readFileSync, existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { homedir, userInfo } from "node:os";
5
+ function loadConfig() {
6
+ const home = homedir();
7
+ const credPath = join(home, ".deeplake", "credentials.json");
8
+ let creds = null;
9
+ if (existsSync(credPath)) {
10
+ try {
11
+ creds = JSON.parse(readFileSync(credPath, "utf-8"));
12
+ } catch {
13
+ return null;
14
+ }
15
+ }
16
+ const token = creds?.token;
17
+ const orgId = creds?.orgId;
18
+ if (!token || !orgId) return null;
19
+ return {
20
+ token,
21
+ orgId,
22
+ orgName: creds?.orgName ?? orgId,
23
+ userName: creds?.userName || userInfo().username || "unknown",
24
+ workspaceId: creds?.workspaceId ?? "default",
25
+ apiUrl: creds?.apiUrl ?? "https://api.deeplake.ai",
26
+ tableName: "memory",
27
+ sessionsTableName: "sessions",
28
+ memoryPath: join(home, ".deeplake", "memory")
29
+ };
30
+ }
31
+ export {
32
+ loadConfig
33
+ };
@@ -0,0 +1,33 @@
1
+ // src/index-marker-store.ts
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ var INDEX_MARKER_TTL_MS = Number(6 * 60 * 6e4);
6
+ function getIndexMarkerDir() {
7
+ return join(tmpdir(), "hivemind-deeplake-indexes");
8
+ }
9
+ function buildIndexMarkerPath(workspaceId, orgId, table, suffix) {
10
+ const markerKey = [workspaceId, orgId, table, suffix].join("__").replace(/[^a-zA-Z0-9_.-]/g, "_");
11
+ return join(getIndexMarkerDir(), `${markerKey}.json`);
12
+ }
13
+ function hasFreshIndexMarker(markerPath) {
14
+ if (!existsSync(markerPath)) return false;
15
+ try {
16
+ const raw = JSON.parse(readFileSync(markerPath, "utf-8"));
17
+ const updatedAt = raw.updatedAt ? new Date(raw.updatedAt).getTime() : NaN;
18
+ if (!Number.isFinite(updatedAt) || Date.now() - updatedAt > INDEX_MARKER_TTL_MS) return false;
19
+ return true;
20
+ } catch {
21
+ return false;
22
+ }
23
+ }
24
+ function writeIndexMarker(markerPath) {
25
+ mkdirSync(getIndexMarkerDir(), { recursive: true });
26
+ writeFileSync(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
27
+ }
28
+ export {
29
+ buildIndexMarkerPath,
30
+ getIndexMarkerDir,
31
+ hasFreshIndexMarker,
32
+ writeIndexMarker
33
+ };