@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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +147 -20
- package/bundle/cli.js +552 -95
- package/codex/bundle/capture.js +509 -89
- package/codex/bundle/commands/auth-login.js +209 -66
- package/codex/bundle/embeddings/embed-daemon.js +243 -0
- package/codex/bundle/pre-tool-use.js +629 -104
- package/codex/bundle/session-start-setup.js +194 -57
- package/codex/bundle/session-start.js +25 -10
- package/codex/bundle/shell/deeplake-shell.js +679 -112
- package/codex/bundle/stop.js +476 -58
- package/codex/bundle/wiki-worker.js +312 -11
- package/cursor/bundle/capture.js +768 -57
- package/cursor/bundle/commands/auth-login.js +209 -66
- package/cursor/bundle/embeddings/embed-daemon.js +243 -0
- package/cursor/bundle/pre-tool-use.js +561 -70
- package/cursor/bundle/session-end.js +223 -2
- package/cursor/bundle/session-start.js +192 -54
- package/cursor/bundle/shell/deeplake-shell.js +679 -112
- package/cursor/bundle/wiki-worker.js +571 -0
- package/hermes/bundle/capture.js +771 -58
- package/hermes/bundle/commands/auth-login.js +209 -66
- package/hermes/bundle/embeddings/embed-daemon.js +243 -0
- package/hermes/bundle/pre-tool-use.js +560 -69
- package/hermes/bundle/session-end.js +224 -1
- package/hermes/bundle/session-start.js +195 -54
- package/hermes/bundle/shell/deeplake-shell.js +679 -112
- package/hermes/bundle/wiki-worker.js +572 -0
- package/mcp/bundle/server.js +253 -68
- package/openclaw/dist/chunks/auth-creds-AEKS6D3P.js +14 -0
- package/openclaw/dist/chunks/chunk-SRCBBT4H.js +37 -0
- package/openclaw/dist/chunks/config-G23NI5TV.js +33 -0
- package/openclaw/dist/chunks/index-marker-store-PGT5CW6T.js +33 -0
- package/openclaw/dist/chunks/setup-config-C35UK4LP.js +114 -0
- package/openclaw/dist/index.js +752 -702
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/package.json +2 -1
- package/pi/extension-source/hivemind.ts +473 -21
package/mcp/bundle/server.js
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
23227
|
-
|
|
23228
|
-
|
|
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(
|
|
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
|
|
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 (
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
23576
|
+
markers.writeIndexMarker(markerPath);
|
|
23538
23577
|
} catch (e) {
|
|
23539
23578
|
if (isDuplicateIndexError(e)) {
|
|
23540
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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 =
|
|
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:
|
|
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
|
|
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,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
|
+
};
|