Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
475 changes: 304 additions & 171 deletions bundle/cli.js

Large diffs are not rendered by default.

873 changes: 466 additions & 407 deletions claude-code/bundle/capture.js

Large diffs are not rendered by default.

193 changes: 163 additions & 30 deletions claude-code/bundle/commands/auth-login.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ __export(index_marker_store_exports, {
hasFreshIndexMarker: () => hasFreshIndexMarker,
writeIndexMarker: () => writeIndexMarker
});
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
import { join as join4 } from "node:path";
import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
import { join as join5 } from "node:path";
import { tmpdir } from "node:os";
function getIndexMarkerDir() {
return process.env.HIVEMIND_INDEX_MARKER_DIR ?? join4(tmpdir(), "hivemind-deeplake-indexes");
return process.env.HIVEMIND_INDEX_MARKER_DIR ?? join5(tmpdir(), "hivemind-deeplake-indexes");
}
function buildIndexMarkerPath(workspaceId, orgId, table, suffix) {
const markerKey = [workspaceId, orgId, table, suffix].join("__").replace(/[^a-zA-Z0-9_.-]/g, "_");
return join4(getIndexMarkerDir(), `${markerKey}.json`);
return join5(getIndexMarkerDir(), `${markerKey}.json`);
}
function hasFreshIndexMarker(markerPath) {
if (!existsSync2(markerPath))
return false;
try {
const raw = JSON.parse(readFileSync3(markerPath, "utf-8"));
const raw = JSON.parse(readFileSync4(markerPath, "utf-8"));
const updatedAt = raw.updatedAt ? new Date(raw.updatedAt).getTime() : NaN;
if (!Number.isFinite(updatedAt) || Date.now() - updatedAt > INDEX_MARKER_TTL_MS)
return false;
Expand All @@ -41,8 +41,8 @@ function hasFreshIndexMarker(markerPath) {
}
}
function writeIndexMarker(markerPath) {
mkdirSync2(getIndexMarkerDir(), { recursive: true });
writeFileSync2(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
mkdirSync3(getIndexMarkerDir(), { recursive: true });
writeFileSync3(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
}
var INDEX_MARKER_TTL_MS;
var init_index_marker_store = __esm({
Expand Down Expand Up @@ -337,14 +337,115 @@ function sqlIdent(name) {
var SUMMARY_EMBEDDING_COL = "summary_embedding";
var MESSAGE_EMBEDDING_COL = "message_embedding";

// dist/src/notifications/queue.js
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync, mkdirSync as mkdirSync2, openSync, closeSync, unlinkSync as unlinkSync2, statSync } from "node:fs";
import { join as join4, resolve } from "node:path";
import { homedir as homedir4 } from "node:os";
import { setTimeout as sleep } from "node:timers/promises";
var log2 = (msg) => log("notifications-queue", msg);
var LOCK_RETRY_MAX = 50;
var LOCK_RETRY_BASE_MS = 5;
var LOCK_STALE_MS = 5e3;
function queuePath() {
return join4(homedir4(), ".deeplake", "notifications-queue.json");
}
function lockPath() {
return `${queuePath()}.lock`;
}
function readQueue() {
try {
const raw = readFileSync3(queuePath(), "utf-8");
const parsed = JSON.parse(raw);
if (!parsed || !Array.isArray(parsed.queue)) {
log2(`queue malformed \u2192 treating as empty`);
return { queue: [] };
}
return { queue: parsed.queue };
} catch {
return { queue: [] };
}
}
function _isQueuePathInsideHome(path, home) {
const r = resolve(path);
const h = resolve(home);
return r.startsWith(h + "/") || r === h;
}
function writeQueue(q) {
const path = queuePath();
const home = resolve(homedir4());
if (!_isQueuePathInsideHome(path, home)) {
throw new Error(`notifications-queue write blocked: ${path} is outside ${home}`);
}
mkdirSync2(join4(home, ".deeplake"), { recursive: true, mode: 448 });
const tmp = `${path}.${process.pid}.tmp`;
writeFileSync2(tmp, JSON.stringify(q, null, 2), { mode: 384 });
renameSync(tmp, path);
}
async function withQueueLock(fn) {
const path = lockPath();
mkdirSync2(join4(homedir4(), ".deeplake"), { recursive: true, mode: 448 });
let fd = null;
for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
try {
fd = openSync(path, "wx", 384);
break;
} catch (e) {
const code = e.code;
if (code !== "EEXIST")
throw e;
try {
const age = Date.now() - statSync(path).mtimeMs;
if (age > LOCK_STALE_MS) {
unlinkSync2(path);
continue;
}
} catch {
}
const delay = LOCK_RETRY_BASE_MS * (attempt + 1);
await sleep(delay);
}
}
if (fd === null) {
log2(`lock acquisition gave up after ${LOCK_RETRY_MAX} attempts \u2014 proceeding unlocked (last-writer-wins)`);
return fn();
}
try {
return fn();
} finally {
try {
closeSync(fd);
} catch {
}
try {
unlinkSync2(path);
} catch {
}
}
}
function sameDedupKey(a, b) {
if (a.id !== b.id)
return false;
return JSON.stringify(a.dedupKey) === JSON.stringify(b.dedupKey);
}
async function enqueueNotification(n) {
await withQueueLock(() => {
const q = readQueue();
if (q.queue.some((existing) => sameDedupKey(existing, n))) {
return;
}
q.queue.push(n);
writeQueue(q);
});
}

// dist/src/deeplake-api.js
var indexMarkerStorePromise = null;
function getIndexMarkerStore() {
if (!indexMarkerStorePromise)
indexMarkerStorePromise = Promise.resolve().then(() => (init_index_marker_store(), index_marker_store_exports));
return indexMarkerStorePromise;
}
var log2 = (msg) => log("sdk", msg);
var log3 = (msg) => log("sdk", msg);
function summarizeSql(sql, maxLen = 220) {
const compact = sql.replace(/\s+/g, " ").trim();
return compact.length > maxLen ? `${compact.slice(0, maxLen)}...` : compact;
Expand All @@ -356,7 +457,38 @@ function traceSql(msg) {
process.stderr.write(`[deeplake-sql] ${msg}
`);
if (process.env.HIVEMIND_DEBUG === "1")
log2(msg);
log3(msg);
}
var _signalledBalanceExhausted = false;
function maybeSignalBalanceExhausted(status, bodyText) {
if (status !== 402)
return;
if (!bodyText.includes("balance_cents"))
return;
if (_signalledBalanceExhausted)
return;
_signalledBalanceExhausted = true;
log3(`balance exhausted \u2014 enqueuing session-start banner (body=${bodyText.slice(0, 120)})`);
enqueueNotification({
id: "balance-exhausted",
severity: "warn",
transient: true,
title: "Hivemind credits exhausted \u2014 top up to keep capturing",
body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
dedupKey: { reason: "balance-zero" }
}).catch((e) => {
log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
});
}
function billingUrl() {
try {
const c = loadCredentials();
if (c?.orgName && c?.workspaceId) {
return `https://deeplake.ai/${encodeURIComponent(c.orgName)}/workspace/${encodeURIComponent(c.workspaceId)}/billing`;
}
} catch {
}
return "https://deeplake.ai";
}
var RETRYABLE_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
var MAX_RETRIES = 3;
Expand All @@ -365,8 +497,8 @@ var MAX_CONCURRENCY = 5;
function getQueryTimeoutMs() {
return Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
function sleep2(ms) {
return new Promise((resolve2) => setTimeout(resolve2, ms));
}
function isTimeoutError(error) {
const name = error instanceof Error ? error.name.toLowerCase() : "";
Expand Down Expand Up @@ -396,7 +528,7 @@ var Semaphore = class {
this.active++;
return;
}
await new Promise((resolve) => this.waiting.push(resolve));
await new Promise((resolve2) => this.waiting.push(resolve2));
}
release() {
this.active--;
Expand Down Expand Up @@ -467,8 +599,8 @@ var DeeplakeApi = class {
lastError = e instanceof Error ? e : new Error(String(e));
if (attempt < MAX_RETRIES) {
const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
log2(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
await sleep(delay);
log3(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
await sleep2(delay);
continue;
}
throw lastError;
Expand All @@ -484,10 +616,11 @@ var DeeplakeApi = class {
const alreadyExists = resp.status === 500 && isDuplicateIndexError(text);
if (!alreadyExists && attempt < MAX_RETRIES && (RETRYABLE_CODES.has(resp.status) || retryable403)) {
const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
log2(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
await sleep(delay);
log3(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
await sleep2(delay);
continue;
}
maybeSignalBalanceExhausted(resp.status, text);
throw new Error(`Query failed: ${resp.status}: ${text.slice(0, 200)}`);
}
throw lastError ?? new Error("Query failed: max retries exceeded");
Expand All @@ -508,7 +641,7 @@ var DeeplakeApi = class {
const chunk = rows.slice(i, i + CONCURRENCY);
await Promise.allSettled(chunk.map((r) => this.upsertRowSql(r)));
}
log2(`commit: ${rows.length} rows`);
log3(`commit: ${rows.length} rows`);
}
async upsertRowSql(row) {
const ts = (/* @__PURE__ */ new Date()).toISOString();
Expand Down Expand Up @@ -564,7 +697,7 @@ var DeeplakeApi = class {
markers.writeIndexMarker(markerPath);
return;
}
log2(`index "${indexName}" skipped: ${e.message}`);
log3(`index "${indexName}" skipped: ${e.message}`);
}
}
/**
Expand Down Expand Up @@ -654,13 +787,13 @@ var DeeplakeApi = class {
};
}
if (attempt < MAX_RETRIES && RETRYABLE_CODES.has(resp.status)) {
await sleep(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
await sleep2(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
continue;
}
return { tables: [], cacheable: false };
} catch {
if (attempt < MAX_RETRIES) {
await sleep(BASE_DELAY_MS * Math.pow(2, attempt));
await sleep2(BASE_DELAY_MS * Math.pow(2, attempt));
continue;
}
return { tables: [], cacheable: false };
Expand Down Expand Up @@ -688,9 +821,9 @@ var DeeplakeApi = class {
} catch (err) {
lastErr = err;
const msg = err instanceof Error ? err.message : String(err);
log2(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
log3(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
if (attempt < OUTER_BACKOFFS_MS.length) {
await sleep(OUTER_BACKOFFS_MS[attempt]);
await sleep2(OUTER_BACKOFFS_MS[attempt]);
}
}
}
Expand All @@ -701,9 +834,9 @@ var DeeplakeApi = class {
const tbl = sqlIdent(name ?? this.tableName);
const tables = await this.listTables();
if (!tables.includes(tbl)) {
log2(`table "${tbl}" not found, creating`);
log3(`table "${tbl}" not found, creating`);
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 '', plugin_version TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, tbl);
log2(`table "${tbl}" created`);
log3(`table "${tbl}" created`);
if (!tables.includes(tbl))
this._tablesCache = [...tables, tbl];
}
Expand All @@ -716,9 +849,9 @@ var DeeplakeApi = class {
const safe = sqlIdent(name);
const tables = await this.listTables();
if (!tables.includes(safe)) {
log2(`table "${safe}" not found, creating`);
log3(`table "${safe}" not found, creating`);
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 '', plugin_version TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, safe);
log2(`table "${safe}" created`);
log3(`table "${safe}" created`);
if (!tables.includes(safe))
this._tablesCache = [...tables, safe];
}
Expand All @@ -741,9 +874,9 @@ var DeeplakeApi = class {
const safe = sqlIdent(name);
const tables = await this.listTables();
if (!tables.includes(safe)) {
log2(`table "${safe}" not found, creating`);
log3(`table "${safe}" not found, creating`);
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);
log2(`table "${safe}" created`);
log3(`table "${safe}" created`);
if (!tables.includes(safe))
this._tablesCache = [...tables, safe];
}
Expand Down Expand Up @@ -774,10 +907,10 @@ function parseArgs(argv) {
}
function confirm(message) {
const rl = createInterface({ input: process.stdin, output: process.stderr });
return new Promise((resolve) => {
return new Promise((resolve2) => {
rl.question(`${message} [y/N] `, (answer) => {
rl.close();
resolve(answer.trim().toLowerCase() === "y");
resolve2(answer.trim().toLowerCase() === "y");
});
});
}
Expand Down
Loading
Loading