Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
},
"metadata": {
"description": "Cloud-backed persistent shared memory for AI agents powered by Deeplake",
"version": "0.6.6"
"version": "0.6.7"
},
"plugins": [
{
"name": "hivemind",
"description": "Persistent shared memory powered by Deeplake — captures all session activity and provides cross-session, cross-agent memory search",
"version": "0.6.6",
"version": "0.6.7",
"source": "./claude-code",
"homepage": "https://github.com/activeloopai/hivemind"
}
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "hivemind",
"description": "Cloud-backed persistent memory powered by Deeplake — read, write, and share memory across Claude Code sessions and agents",
"version": "0.6.6",
"version": "0.6.7",
"author": {
"name": "Activeloop",
"url": "https://deeplake.ai"
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ tmp/
.env.*
coverage/
bench/
.claude/
9 changes: 4 additions & 5 deletions claude-code/bundle/capture.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,22 +186,21 @@ var DeeplakeApi = class {
log2(`commit: ${rows.length} rows`);
}
async upsertRowSql(row) {
const hex = row.content.toString("hex");
const ts = (/* @__PURE__ */ new Date()).toISOString();
const cd = row.creationDate ?? ts;
const lud = row.lastUpdateDate ?? ts;
const exists = await this.query(`SELECT path FROM "${this.tableName}" WHERE path = '${sqlStr(row.path)}' LIMIT 1`);
if (exists.length > 0) {
let setClauses = `content = E'\\\\x${hex}', summary = E'${sqlStr(row.contentText)}', mime_type = '${sqlStr(row.mimeType)}', size_bytes = ${row.sizeBytes}, last_update_date = '${lud}'`;
let setClauses = `summary = E'${sqlStr(row.contentText)}', mime_type = '${sqlStr(row.mimeType)}', size_bytes = ${row.sizeBytes}, last_update_date = '${lud}'`;
if (row.project !== void 0)
setClauses += `, project = '${sqlStr(row.project)}'`;
if (row.description !== void 0)
setClauses += `, description = '${sqlStr(row.description)}'`;
await this.query(`UPDATE "${this.tableName}" SET ${setClauses} WHERE path = '${sqlStr(row.path)}'`);
} else {
const id = randomUUID();
let cols = "id, path, filename, content, summary, mime_type, size_bytes, creation_date, last_update_date";
let vals = `'${id}', '${sqlStr(row.path)}', '${sqlStr(row.filename)}', E'\\\\x${hex}', E'${sqlStr(row.contentText)}', '${sqlStr(row.mimeType)}', ${row.sizeBytes}, '${cd}', '${lud}'`;
let cols = "id, path, filename, summary, mime_type, size_bytes, creation_date, last_update_date";
let vals = `'${id}', '${sqlStr(row.path)}', '${sqlStr(row.filename)}', E'${sqlStr(row.contentText)}', '${sqlStr(row.mimeType)}', ${row.sizeBytes}, '${cd}', '${lud}'`;
if (row.project !== void 0) {
cols += ", project";
vals += `, '${sqlStr(row.project)}'`;
Expand Down Expand Up @@ -258,7 +257,7 @@ var DeeplakeApi = class {
const tables = await this.listTables();
if (!tables.includes(tbl)) {
log2(`table "${tbl}" not found, creating`);
await this.query(`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', content BYTEA NOT NULL DEFAULT ''::bytea, summary TEXT NOT NULL DEFAULT '', author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/octet-stream', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`);
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 '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`);
log2(`table "${tbl}" created`);
} else {
for (const col of ["project", "description", "creation_date", "last_update_date", "author"]) {
Expand Down
9 changes: 4 additions & 5 deletions claude-code/bundle/pre-tool-use.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,22 +194,21 @@ var DeeplakeApi = class {
log2(`commit: ${rows.length} rows`);
}
async upsertRowSql(row) {
const hex = row.content.toString("hex");
const ts = (/* @__PURE__ */ new Date()).toISOString();
const cd = row.creationDate ?? ts;
const lud = row.lastUpdateDate ?? ts;
const exists = await this.query(`SELECT path FROM "${this.tableName}" WHERE path = '${sqlStr(row.path)}' LIMIT 1`);
if (exists.length > 0) {
let setClauses = `content = E'\\\\x${hex}', summary = E'${sqlStr(row.contentText)}', mime_type = '${sqlStr(row.mimeType)}', size_bytes = ${row.sizeBytes}, last_update_date = '${lud}'`;
let setClauses = `summary = E'${sqlStr(row.contentText)}', mime_type = '${sqlStr(row.mimeType)}', size_bytes = ${row.sizeBytes}, last_update_date = '${lud}'`;
if (row.project !== void 0)
setClauses += `, project = '${sqlStr(row.project)}'`;
if (row.description !== void 0)
setClauses += `, description = '${sqlStr(row.description)}'`;
await this.query(`UPDATE "${this.tableName}" SET ${setClauses} WHERE path = '${sqlStr(row.path)}'`);
} else {
const id = randomUUID();
let cols = "id, path, filename, content, summary, mime_type, size_bytes, creation_date, last_update_date";
let vals = `'${id}', '${sqlStr(row.path)}', '${sqlStr(row.filename)}', E'\\\\x${hex}', E'${sqlStr(row.contentText)}', '${sqlStr(row.mimeType)}', ${row.sizeBytes}, '${cd}', '${lud}'`;
let cols = "id, path, filename, summary, mime_type, size_bytes, creation_date, last_update_date";
let vals = `'${id}', '${sqlStr(row.path)}', '${sqlStr(row.filename)}', E'${sqlStr(row.contentText)}', '${sqlStr(row.mimeType)}', ${row.sizeBytes}, '${cd}', '${lud}'`;
if (row.project !== void 0) {
cols += ", project";
vals += `, '${sqlStr(row.project)}'`;
Expand Down Expand Up @@ -266,7 +265,7 @@ var DeeplakeApi = class {
const tables = await this.listTables();
if (!tables.includes(tbl)) {
log2(`table "${tbl}" not found, creating`);
await this.query(`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', content BYTEA NOT NULL DEFAULT ''::bytea, summary TEXT NOT NULL DEFAULT '', author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/octet-stream', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`);
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 '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`);
log2(`table "${tbl}" created`);
} else {
for (const col of ["project", "description", "creation_date", "last_update_date", "author"]) {
Expand Down
12 changes: 5 additions & 7 deletions claude-code/bundle/session-start.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,22 +198,21 @@ var DeeplakeApi = class {
log2(`commit: ${rows.length} rows`);
}
async upsertRowSql(row) {
const hex = row.content.toString("hex");
const ts = (/* @__PURE__ */ new Date()).toISOString();
const cd = row.creationDate ?? ts;
const lud = row.lastUpdateDate ?? ts;
const exists = await this.query(`SELECT path FROM "${this.tableName}" WHERE path = '${sqlStr(row.path)}' LIMIT 1`);
if (exists.length > 0) {
let setClauses = `content = E'\\\\x${hex}', summary = E'${sqlStr(row.contentText)}', mime_type = '${sqlStr(row.mimeType)}', size_bytes = ${row.sizeBytes}, last_update_date = '${lud}'`;
let setClauses = `summary = E'${sqlStr(row.contentText)}', mime_type = '${sqlStr(row.mimeType)}', size_bytes = ${row.sizeBytes}, last_update_date = '${lud}'`;
if (row.project !== void 0)
setClauses += `, project = '${sqlStr(row.project)}'`;
if (row.description !== void 0)
setClauses += `, description = '${sqlStr(row.description)}'`;
await this.query(`UPDATE "${this.tableName}" SET ${setClauses} WHERE path = '${sqlStr(row.path)}'`);
} else {
const id = randomUUID();
let cols = "id, path, filename, content, summary, mime_type, size_bytes, creation_date, last_update_date";
let vals = `'${id}', '${sqlStr(row.path)}', '${sqlStr(row.filename)}', E'\\\\x${hex}', E'${sqlStr(row.contentText)}', '${sqlStr(row.mimeType)}', ${row.sizeBytes}, '${cd}', '${lud}'`;
let cols = "id, path, filename, summary, mime_type, size_bytes, creation_date, last_update_date";
let vals = `'${id}', '${sqlStr(row.path)}', '${sqlStr(row.filename)}', E'${sqlStr(row.contentText)}', '${sqlStr(row.mimeType)}', ${row.sizeBytes}, '${cd}', '${lud}'`;
if (row.project !== void 0) {
cols += ", project";
vals += `, '${sqlStr(row.project)}'`;
Expand Down Expand Up @@ -270,7 +269,7 @@ var DeeplakeApi = class {
const tables = await this.listTables();
if (!tables.includes(tbl)) {
log2(`table "${tbl}" not found, creating`);
await this.query(`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', content BYTEA NOT NULL DEFAULT ''::bytea, summary TEXT NOT NULL DEFAULT '', author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/octet-stream', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`);
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 '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`);
log2(`table "${tbl}" created`);
} else {
for (const col of ["project", "description", "creation_date", "last_update_date", "author"]) {
Expand Down Expand Up @@ -399,9 +398,8 @@ async function createPlaceholder(api, table, sessionId, cwd, userName, orgName,
`- **Status**: in-progress`,
""
].join("\n");
const hex = Buffer.from(content, "utf-8").toString("hex");
const filename = `${sessionId}.md`;
await api.query(`INSERT INTO "${table}" (id, path, filename, content, summary, author, mime_type, size_bytes, project, description, creation_date, last_update_date) VALUES ('${crypto.randomUUID()}', '${sqlStr(summaryPath)}', '${sqlStr(filename)}', E'\\\\x${hex}', E'${sqlStr(content)}', '${sqlStr(userName)}', 'text/markdown', ${Buffer.byteLength(content, "utf-8")}, '${sqlStr(projectName)}', 'in progress', '${now}', '${now}')`);
await api.query(`INSERT INTO "${table}" (id, path, filename, summary, author, mime_type, size_bytes, project, description, creation_date, last_update_date) VALUES ('${crypto.randomUUID()}', '${sqlStr(summaryPath)}', '${sqlStr(filename)}', E'${sqlStr(content)}', '${sqlStr(userName)}', 'text/markdown', ${Buffer.byteLength(content, "utf-8")}, '${sqlStr(projectName)}', 'in progress', '${now}', '${now}')`);
wikiLog(`SessionStart: created placeholder for ${sessionId} (${cwd})`);
}
async function main() {
Expand Down
Loading
Loading