@deeplake/hivemind 0.6.48 → 0.7.9

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 (45) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +244 -20
  4. package/bundle/cli.js +1369 -112
  5. package/codex/bundle/capture.js +546 -96
  6. package/codex/bundle/commands/auth-login.js +290 -81
  7. package/codex/bundle/embeddings/embed-daemon.js +243 -0
  8. package/codex/bundle/pre-tool-use.js +666 -111
  9. package/codex/bundle/session-start-setup.js +231 -64
  10. package/codex/bundle/session-start.js +52 -13
  11. package/codex/bundle/shell/deeplake-shell.js +716 -119
  12. package/codex/bundle/skilify-worker.js +907 -0
  13. package/codex/bundle/stop.js +819 -79
  14. package/codex/bundle/wiki-worker.js +312 -11
  15. package/cursor/bundle/capture.js +1116 -64
  16. package/cursor/bundle/commands/auth-login.js +290 -81
  17. package/cursor/bundle/embeddings/embed-daemon.js +243 -0
  18. package/cursor/bundle/pre-tool-use.js +598 -77
  19. package/cursor/bundle/session-end.js +520 -2
  20. package/cursor/bundle/session-start.js +257 -65
  21. package/cursor/bundle/shell/deeplake-shell.js +716 -119
  22. package/cursor/bundle/skilify-worker.js +907 -0
  23. package/cursor/bundle/wiki-worker.js +571 -0
  24. package/hermes/bundle/capture.js +1119 -65
  25. package/hermes/bundle/commands/auth-login.js +290 -81
  26. package/hermes/bundle/embeddings/embed-daemon.js +243 -0
  27. package/hermes/bundle/pre-tool-use.js +597 -76
  28. package/hermes/bundle/session-end.js +522 -1
  29. package/hermes/bundle/session-start.js +260 -65
  30. package/hermes/bundle/shell/deeplake-shell.js +716 -119
  31. package/hermes/bundle/skilify-worker.js +907 -0
  32. package/hermes/bundle/wiki-worker.js +572 -0
  33. package/mcp/bundle/server.js +290 -75
  34. package/openclaw/dist/chunks/auth-creds-AEKS6D3P.js +14 -0
  35. package/openclaw/dist/chunks/chunk-SRCBBT4H.js +37 -0
  36. package/openclaw/dist/chunks/config-ZLH6JFJS.js +34 -0
  37. package/openclaw/dist/chunks/index-marker-store-PGT5CW6T.js +33 -0
  38. package/openclaw/dist/chunks/setup-config-C35UK4LP.js +114 -0
  39. package/openclaw/dist/index.js +929 -710
  40. package/openclaw/dist/skilify-worker.js +907 -0
  41. package/openclaw/openclaw.plugin.json +1 -1
  42. package/openclaw/package.json +1 -1
  43. package/openclaw/skills/SKILL.md +19 -0
  44. package/package.json +7 -1
  45. package/pi/extension-source/hivemind.ts +603 -22
@@ -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 {
@@ -23264,15 +23323,13 @@ function loadConfig() {
23264
23323
  apiUrl: process.env.HIVEMIND_API_URL ?? creds?.apiUrl ?? "https://api.deeplake.ai",
23265
23324
  tableName: process.env.HIVEMIND_TABLE ?? "memory",
23266
23325
  sessionsTableName: process.env.HIVEMIND_SESSIONS_TABLE ?? "sessions",
23326
+ skillsTableName: process.env.HIVEMIND_SKILLS_TABLE ?? "skills",
23267
23327
  memoryPath: process.env.HIVEMIND_MEMORY_PATH ?? join2(home, ".deeplake", "memory")
23268
23328
  };
23269
23329
  }
23270
23330
 
23271
23331
  // dist/src/deeplake-api.js
23272
23332
  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
23333
 
23277
23334
  // dist/src/utils/debug.js
23278
23335
  import { appendFileSync } from "node:fs";
@@ -23294,8 +23351,24 @@ function sqlStr(value) {
23294
23351
  function sqlLike(value) {
23295
23352
  return sqlStr(value).replace(/%/g, "\\%").replace(/_/g, "\\_");
23296
23353
  }
23354
+ function sqlIdent(name) {
23355
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
23356
+ throw new Error(`Invalid SQL identifier: ${JSON.stringify(name)}`);
23357
+ }
23358
+ return name;
23359
+ }
23360
+
23361
+ // dist/src/embeddings/columns.js
23362
+ var SUMMARY_EMBEDDING_COL = "summary_embedding";
23363
+ var MESSAGE_EMBEDDING_COL = "message_embedding";
23297
23364
 
23298
23365
  // dist/src/deeplake-api.js
23366
+ var indexMarkerStorePromise = null;
23367
+ function getIndexMarkerStore() {
23368
+ if (!indexMarkerStorePromise)
23369
+ indexMarkerStorePromise = Promise.resolve().then(() => (init_index_marker_store(), index_marker_store_exports));
23370
+ return indexMarkerStorePromise;
23371
+ }
23299
23372
  var log2 = (msg) => log("sdk", msg);
23300
23373
  function summarizeSql(sql, maxLen = 220) {
23301
23374
  const compact = sql.replace(/\s+/g, " ").trim();
@@ -23315,7 +23388,6 @@ var MAX_RETRIES = 3;
23315
23388
  var BASE_DELAY_MS = 500;
23316
23389
  var MAX_CONCURRENCY = 5;
23317
23390
  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
23391
  function sleep(ms) {
23320
23392
  return new Promise((resolve) => setTimeout(resolve, ms));
23321
23393
  }
@@ -23335,9 +23407,6 @@ function isTransientHtml403(text) {
23335
23407
  const body = text.toLowerCase();
23336
23408
  return body.includes("<html") || body.includes("403 forbidden") || body.includes("cloudflare") || body.includes("nginx");
23337
23409
  }
23338
- function getIndexMarkerDir() {
23339
- return process.env.HIVEMIND_INDEX_MARKER_DIR ?? join4(tmpdir(), "hivemind-deeplake-indexes");
23340
- }
23341
23410
  var Semaphore = class {
23342
23411
  max;
23343
23412
  waiting = [];
@@ -23406,7 +23475,8 @@ var DeeplakeApi = class {
23406
23475
  headers: {
23407
23476
  Authorization: `Bearer ${this.token}`,
23408
23477
  "Content-Type": "application/json",
23409
- "X-Activeloop-Org-Id": this.orgId
23478
+ "X-Activeloop-Org-Id": this.orgId,
23479
+ ...deeplakeClientHeader()
23410
23480
  },
23411
23481
  signal,
23412
23482
  body: JSON.stringify({ query: sql })
@@ -23433,7 +23503,8 @@ var DeeplakeApi = class {
23433
23503
  }
23434
23504
  const text = await resp.text().catch(() => "");
23435
23505
  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)) {
23506
+ const alreadyExists = resp.status === 500 && isDuplicateIndexError(text);
23507
+ if (!alreadyExists && attempt < MAX_RETRIES && (RETRYABLE_CODES.has(resp.status) || retryable403)) {
23437
23508
  const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
23438
23509
  log2(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
23439
23510
  await sleep(delay);
@@ -23467,7 +23538,7 @@ var DeeplakeApi = class {
23467
23538
  const lud = row.lastUpdateDate ?? ts;
23468
23539
  const exists = await this.query(`SELECT path FROM "${this.tableName}" WHERE path = '${sqlStr(row.path)}' LIMIT 1`);
23469
23540
  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}'`;
23541
+ 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
23542
  if (row.project !== void 0)
23472
23543
  setClauses += `, project = '${sqlStr(row.project)}'`;
23473
23544
  if (row.description !== void 0)
@@ -23475,8 +23546,8 @@ var DeeplakeApi = class {
23475
23546
  await this.query(`UPDATE "${this.tableName}" SET ${setClauses} WHERE path = '${sqlStr(row.path)}'`);
23476
23547
  } else {
23477
23548
  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}'`;
23549
+ let cols = `id, path, filename, summary, ${SUMMARY_EMBEDDING_COL}, mime_type, size_bytes, creation_date, last_update_date`;
23550
+ let vals = `'${id}', '${sqlStr(row.path)}', '${sqlStr(row.filename)}', E'${sqlStr(row.contentText)}', NULL, '${sqlStr(row.mimeType)}', ${row.sizeBytes}, '${cd}', '${lud}'`;
23480
23551
  if (row.project !== void 0) {
23481
23552
  cols += ", project";
23482
23553
  vals += `, '${sqlStr(row.project)}'`;
@@ -23501,48 +23572,83 @@ var DeeplakeApi = class {
23501
23572
  buildLookupIndexName(table, suffix) {
23502
23573
  return `idx_${table}_${suffix}`.replace(/[^a-zA-Z0-9_]/g, "_");
23503
23574
  }
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
23575
  async ensureLookupIndex(table, suffix, columnsSql) {
23532
- if (this.hasFreshLookupIndexMarker(table, suffix))
23576
+ const markers = await getIndexMarkerStore();
23577
+ const markerPath = markers.buildIndexMarkerPath(this.workspaceId, this.orgId, table, suffix);
23578
+ if (markers.hasFreshIndexMarker(markerPath))
23533
23579
  return;
23534
23580
  const indexName = this.buildLookupIndexName(table, suffix);
23535
23581
  try {
23536
23582
  await this.query(`CREATE INDEX IF NOT EXISTS "${indexName}" ON "${table}" ${columnsSql}`);
23537
- this.markLookupIndexReady(table, suffix);
23583
+ markers.writeIndexMarker(markerPath);
23538
23584
  } catch (e) {
23539
23585
  if (isDuplicateIndexError(e)) {
23540
- this.markLookupIndexReady(table, suffix);
23586
+ markers.writeIndexMarker(markerPath);
23541
23587
  return;
23542
23588
  }
23543
23589
  log2(`index "${indexName}" skipped: ${e.message}`);
23544
23590
  }
23545
23591
  }
23592
+ /**
23593
+ * Ensure a vector column exists on the given table.
23594
+ *
23595
+ * The previous implementation always issued `ALTER TABLE ADD COLUMN IF NOT
23596
+ * EXISTS …` on every SessionStart. On a long-running workspace that's
23597
+ * already migrated, every call returns 500 "Column already exists" — noisy
23598
+ * in the log and a wasted round-trip. Worse, the very first call after the
23599
+ * column is genuinely added triggers Deeplake's post-ALTER `vector::at`
23600
+ * window (~30s) during which subsequent INSERTs fail; minimising the
23601
+ * number of ALTER calls minimises exposure to that window.
23602
+ *
23603
+ * New flow:
23604
+ * 1. Check the local marker file (mirrors ensureLookupIndex). If fresh,
23605
+ * return — zero network calls.
23606
+ * 2. SELECT 1 FROM information_schema.columns WHERE table_name = T AND
23607
+ * column_name = C. Read-only, idempotent, can't tickle the post-ALTER
23608
+ * bug. If the column is present → mark + return.
23609
+ * 3. Only if step 2 says the column is missing, fall back to ALTER ADD
23610
+ * COLUMN IF NOT EXISTS. Mark on success, also mark if Deeplake reports
23611
+ * "already exists" (race: another client added it between our SELECT
23612
+ * and ALTER).
23613
+ *
23614
+ * Marker uses the same dir / TTL as ensureLookupIndex so both schema
23615
+ * caches share an opt-out (HIVEMIND_INDEX_MARKER_DIR) and a TTL knob.
23616
+ */
23617
+ async ensureEmbeddingColumn(table, column) {
23618
+ await this.ensureColumn(table, column, "FLOAT4[]");
23619
+ }
23620
+ /**
23621
+ * Generic marker-gated column migration. Same SELECT-then-ALTER flow as
23622
+ * ensureEmbeddingColumn, parameterized by SQL type so it can patch up any
23623
+ * column that was added to the schema after the table was originally
23624
+ * created. Used today for `summary_embedding`, `message_embedding`, and
23625
+ * the `agent` column (added 2026-04-11) — the latter has no fallback if
23626
+ * a user upgraded over a pre-2026-04-11 table, so every INSERT fails
23627
+ * with `column "agent" does not exist`.
23628
+ */
23629
+ async ensureColumn(table, column, sqlType) {
23630
+ const markers = await getIndexMarkerStore();
23631
+ const markerPath = markers.buildIndexMarkerPath(this.workspaceId, this.orgId, table, `col_${column}`);
23632
+ if (markers.hasFreshIndexMarker(markerPath))
23633
+ return;
23634
+ 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`;
23635
+ const rows = await this.query(colCheck);
23636
+ if (rows.length > 0) {
23637
+ markers.writeIndexMarker(markerPath);
23638
+ return;
23639
+ }
23640
+ try {
23641
+ await this.query(`ALTER TABLE "${table}" ADD COLUMN ${column} ${sqlType}`);
23642
+ } catch (e) {
23643
+ const msg = e instanceof Error ? e.message : String(e);
23644
+ if (!/already exists/i.test(msg))
23645
+ throw e;
23646
+ const recheck = await this.query(colCheck);
23647
+ if (recheck.length === 0)
23648
+ throw e;
23649
+ }
23650
+ markers.writeIndexMarker(markerPath);
23651
+ }
23546
23652
  /** List all tables in the workspace (with retry). */
23547
23653
  async listTables(forceRefresh = false) {
23548
23654
  if (!forceRefresh && this._tablesCache)
@@ -23558,7 +23664,8 @@ var DeeplakeApi = class {
23558
23664
  const resp = await fetch(`${this.apiUrl}/workspaces/${this.workspaceId}/tables`, {
23559
23665
  headers: {
23560
23666
  Authorization: `Bearer ${this.token}`,
23561
- "X-Activeloop-Org-Id": this.orgId
23667
+ "X-Activeloop-Org-Id": this.orgId,
23668
+ ...deeplakeClientHeader()
23562
23669
  }
23563
23670
  });
23564
23671
  if (resp.ok) {
@@ -23583,29 +23690,84 @@ var DeeplakeApi = class {
23583
23690
  }
23584
23691
  return { tables: [], cacheable: false };
23585
23692
  }
23693
+ /**
23694
+ * Run a `CREATE TABLE` with an extra outer retry budget. The base
23695
+ * `query()` already retries 3 times on fetch errors (~3.5s total), but a
23696
+ * failed CREATE is permanent corruption — every subsequent SELECT against
23697
+ * the missing table fails. Wrapping in an outer loop with longer backoff
23698
+ * (2s, 5s, then 10s) gives us ~17s of reach across transient network
23699
+ * blips before giving up. Failures still propagate; getApi() resets its
23700
+ * cache on init failure (openclaw plugin) so the next call retries the
23701
+ * whole init flow.
23702
+ */
23703
+ async createTableWithRetry(sql, label) {
23704
+ const OUTER_BACKOFFS_MS = [2e3, 5e3, 1e4];
23705
+ let lastErr = null;
23706
+ for (let attempt = 0; attempt <= OUTER_BACKOFFS_MS.length; attempt++) {
23707
+ try {
23708
+ await this.query(sql);
23709
+ return;
23710
+ } catch (err) {
23711
+ lastErr = err;
23712
+ const msg = err instanceof Error ? err.message : String(err);
23713
+ log2(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
23714
+ if (attempt < OUTER_BACKOFFS_MS.length) {
23715
+ await sleep(OUTER_BACKOFFS_MS[attempt]);
23716
+ }
23717
+ }
23718
+ }
23719
+ throw lastErr;
23720
+ }
23586
23721
  /** Create the memory table if it doesn't already exist. Migrate columns on existing tables. */
23587
23722
  async ensureTable(name) {
23588
- const tbl = name ?? this.tableName;
23723
+ const tbl = sqlIdent(name ?? this.tableName);
23589
23724
  const tables = await this.listTables();
23590
23725
  if (!tables.includes(tbl)) {
23591
23726
  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`);
23727
+ 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
23728
  log2(`table "${tbl}" created`);
23594
23729
  if (!tables.includes(tbl))
23595
23730
  this._tablesCache = [...tables, tbl];
23596
23731
  }
23732
+ await this.ensureEmbeddingColumn(tbl, SUMMARY_EMBEDDING_COL);
23733
+ await this.ensureColumn(tbl, "agent", "TEXT NOT NULL DEFAULT ''");
23597
23734
  }
23598
23735
  /** Create the sessions table (uses JSONB for message since every row is a JSON event). */
23599
23736
  async ensureSessionsTable(name) {
23737
+ const safe = sqlIdent(name);
23738
+ const tables = await this.listTables();
23739
+ if (!tables.includes(safe)) {
23740
+ log2(`table "${safe}" not found, creating`);
23741
+ await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${safe}" (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`, safe);
23742
+ log2(`table "${safe}" created`);
23743
+ if (!tables.includes(safe))
23744
+ this._tablesCache = [...tables, safe];
23745
+ }
23746
+ await this.ensureEmbeddingColumn(safe, MESSAGE_EMBEDDING_COL);
23747
+ await this.ensureColumn(safe, "agent", "TEXT NOT NULL DEFAULT ''");
23748
+ await this.ensureLookupIndex(safe, "path_creation_date", `("path", "creation_date")`);
23749
+ }
23750
+ /**
23751
+ * Create the skills table.
23752
+ *
23753
+ * One row per skill version. Workers INSERT a fresh row on every KEEP /
23754
+ * MERGE rather than UPDATE-ing in place, so the full version history is
23755
+ * recoverable. Uniqueness in the *current* state is by (project_key, name)
23756
+ * — newer rows shadow older ones at read time (ORDER BY version DESC).
23757
+ * This sidesteps the Deeplake UPDATE-coalescing quirk that bit the wiki
23758
+ * worker.
23759
+ */
23760
+ async ensureSkillsTable(name) {
23761
+ const safe = sqlIdent(name);
23600
23762
  const tables = await this.listTables();
23601
- if (!tables.includes(name)) {
23602
- 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`);
23604
- log2(`table "${name}" created`);
23605
- if (!tables.includes(name))
23606
- this._tablesCache = [...tables, name];
23763
+ if (!tables.includes(safe)) {
23764
+ log2(`table "${safe}" not found, creating`);
23765
+ await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', name TEXT NOT NULL DEFAULT '', project TEXT NOT NULL DEFAULT '', project_key TEXT NOT NULL DEFAULT '', local_path TEXT NOT NULL DEFAULT '', install TEXT NOT NULL DEFAULT 'project', source_sessions TEXT NOT NULL DEFAULT '[]', source_agent TEXT NOT NULL DEFAULT '', scope TEXT NOT NULL DEFAULT 'me', author TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', trigger_text TEXT NOT NULL DEFAULT '', body TEXT NOT NULL DEFAULT '', version BIGINT NOT NULL DEFAULT 1, created_at TEXT NOT NULL DEFAULT '', updated_at TEXT NOT NULL DEFAULT '') USING deeplake`, safe);
23766
+ log2(`table "${safe}" created`);
23767
+ if (!tables.includes(safe))
23768
+ this._tablesCache = [...tables, safe];
23607
23769
  }
23608
- await this.ensureLookupIndex(name, "path_creation_date", `("path", "creation_date")`);
23770
+ await this.ensureLookupIndex(safe, "project_key_name", `("project_key", "name")`);
23609
23771
  }
23610
23772
  };
23611
23773
 
@@ -23773,24 +23935,25 @@ function normalizeContent(path, raw) {
23773
23935
  return raw;
23774
23936
  }
23775
23937
  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
- }
23938
+ const dateHeader = obj.date_time ? `(${String(obj.date_time)}) ` : "";
23785
23939
  const lines = obj.turns.map((t) => {
23786
23940
  const sp = String(t?.speaker ?? t?.name ?? "?").trim();
23787
23941
  const tx = String(t?.text ?? t?.content ?? "").replace(/\s+/g, " ").trim();
23788
23942
  const tag = t?.dia_id ? `[${t.dia_id}] ` : "";
23789
- return `${tag}${sp}: ${tx}`;
23943
+ return `${dateHeader}${tag}${sp}: ${tx}`;
23790
23944
  });
23791
- const out2 = [...header, ...lines].join("\n");
23945
+ const out2 = lines.join("\n");
23792
23946
  return out2.trim() ? out2 : raw;
23793
23947
  }
23948
+ if (obj.turn && typeof obj.turn === "object" && !Array.isArray(obj.turn)) {
23949
+ const t = obj.turn;
23950
+ const sp = String(t.speaker ?? t.name ?? "?").trim();
23951
+ const tx = String(t.text ?? t.content ?? "").replace(/\s+/g, " ").trim();
23952
+ const tag = t.dia_id ? `[${String(t.dia_id)}] ` : "";
23953
+ const dateHeader = obj.date_time ? `(${String(obj.date_time)}) ` : "";
23954
+ const line = `${dateHeader}${tag}${sp}: ${tx}`;
23955
+ return line.trim() ? line : raw;
23956
+ }
23794
23957
  const stripRecalled = (t) => {
23795
23958
  const i = t.indexOf("<recalled-memories>");
23796
23959
  if (i === -1)
@@ -23833,8 +23996,38 @@ function buildPathCondition(targetPath) {
23833
23996
  return `(path = '${sqlStr(clean)}' OR path LIKE '${sqlLike(clean)}/%' ESCAPE '\\')`;
23834
23997
  }
23835
23998
  async function searchDeeplakeTables(api, memoryTable, sessionsTable, opts) {
23836
- const { pathFilter, contentScanOnly, likeOp, escapedPattern, prefilterPattern, prefilterPatterns, multiWordPatterns } = opts;
23999
+ const { pathFilter, contentScanOnly, likeOp, escapedPattern, prefilterPattern, prefilterPatterns, queryEmbedding, multiWordPatterns } = opts;
23837
24000
  const limit = opts.limit ?? 100;
24001
+ if (queryEmbedding && queryEmbedding.length > 0) {
24002
+ const vecLit = serializeFloat4Array(queryEmbedding);
24003
+ const semanticLimit = Math.min(limit, Number(process.env.HIVEMIND_SEMANTIC_LIMIT ?? "20"));
24004
+ const lexicalLimit = Math.min(limit, Number(process.env.HIVEMIND_HYBRID_LEXICAL_LIMIT ?? "20"));
24005
+ const filterPatternsForLex = contentScanOnly ? prefilterPatterns && prefilterPatterns.length > 0 ? prefilterPatterns : prefilterPattern ? [prefilterPattern] : [] : [escapedPattern];
24006
+ const memLexFilter = buildContentFilter("summary::text", likeOp, filterPatternsForLex);
24007
+ const sessLexFilter = buildContentFilter("message::text", likeOp, filterPatternsForLex);
24008
+ 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;
24009
+ 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;
24010
+ 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}`;
24011
+ 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}`;
24012
+ const parts = [memSemQuery, sessSemQuery];
24013
+ if (memLexQuery)
24014
+ parts.push(memLexQuery);
24015
+ if (sessLexQuery)
24016
+ parts.push(sessLexQuery);
24017
+ const unionSql = parts.map((q) => `(${q})`).join(" UNION ALL ");
24018
+ const outerLimit = semanticLimit + lexicalLimit;
24019
+ const rows2 = await api.query(`SELECT path, content, source_order, creation_date, score FROM (` + unionSql + `) AS combined ORDER BY score DESC LIMIT ${outerLimit}`);
24020
+ const seen = /* @__PURE__ */ new Set();
24021
+ const unique = [];
24022
+ for (const row of rows2) {
24023
+ const p = String(row["path"]);
24024
+ if (seen.has(p))
24025
+ continue;
24026
+ seen.add(p);
24027
+ unique.push({ path: p, content: String(row["content"] ?? "") });
24028
+ }
24029
+ return unique;
24030
+ }
23838
24031
  const filterPatterns = contentScanOnly ? prefilterPatterns && prefilterPatterns.length > 0 ? prefilterPatterns : prefilterPattern ? [prefilterPattern] : [] : multiWordPatterns && multiWordPatterns.length > 1 ? multiWordPatterns : [escapedPattern];
23839
24032
  const memFilter = buildContentFilter("summary::text", likeOp, filterPatterns);
23840
24033
  const sessFilter = buildContentFilter("message::text", likeOp, filterPatterns);
@@ -23846,6 +24039,15 @@ async function searchDeeplakeTables(api, memoryTable, sessionsTable, opts) {
23846
24039
  content: String(row["content"] ?? "")
23847
24040
  }));
23848
24041
  }
24042
+ function serializeFloat4Array(vec) {
24043
+ const parts = [];
24044
+ for (const v of vec) {
24045
+ if (!Number.isFinite(v))
24046
+ return "NULL";
24047
+ parts.push(String(v));
24048
+ }
24049
+ return `ARRAY[${parts.join(",")}]::float4[]`;
24050
+ }
23849
24051
  function buildPathFilter(targetPath) {
23850
24052
  const condition = buildPathCondition(targetPath);
23851
24053
  return condition ? ` AND ${condition}` : "";
@@ -23928,7 +24130,7 @@ function buildGrepSearchOptions(params, targetPath) {
23928
24130
  return {
23929
24131
  pathFilter: buildPathFilter(targetPath),
23930
24132
  contentScanOnly: hasRegexMeta,
23931
- likeOp: params.ignoreCase ? "ILIKE" : "LIKE",
24133
+ likeOp: process.env.HIVEMIND_GREP_LIKE === "case-sensitive" ? "LIKE" : "ILIKE",
23932
24134
  escapedPattern: sqlLike(params.pattern),
23933
24135
  prefilterPattern: literalPrefilter ? sqlLike(literalPrefilter) : void 0,
23934
24136
  prefilterPatterns: alternationPrefilters?.map((literal2) => sqlLike(literal2)),
@@ -23948,12 +24150,25 @@ import { readFileSync as readFileSync5 } from "node:fs";
23948
24150
  import { join as join6 } from "node:path";
23949
24151
 
23950
24152
  // 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";
24153
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3, cpSync, symlinkSync, unlinkSync as unlinkSync2, lstatSync } from "node:fs";
23952
24154
  import { join as join5, dirname } from "node:path";
23953
24155
  import { homedir as homedir4 } from "node:os";
23954
24156
  import { fileURLToPath } from "node:url";
23955
24157
  var HOME = homedir4();
23956
24158
  function pkgRoot() {
24159
+ let dir = fileURLToPath(new URL(".", import.meta.url));
24160
+ for (let i = 0; i < 8; i++) {
24161
+ try {
24162
+ const pkg = JSON.parse(readFileSync4(join5(dir, "package.json"), "utf-8"));
24163
+ if (pkg.name === "@deeplake/hivemind" || pkg.name === "hivemind")
24164
+ return dir;
24165
+ } catch {
24166
+ }
24167
+ const parent = dirname(dir);
24168
+ if (parent === dir)
24169
+ break;
24170
+ dir = parent;
24171
+ }
23957
24172
  return fileURLToPath(new URL("..", import.meta.url));
23958
24173
  }
23959
24174
  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,34 @@
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
+ skillsTableName: process.env.HIVEMIND_SKILLS_TABLE ?? "skills",
29
+ memoryPath: join(home, ".deeplake", "memory")
30
+ };
31
+ }
32
+ export {
33
+ loadConfig
34
+ };