@deeplake/hivemind 0.7.4 → 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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +97 -0
- package/bundle/cli.js +820 -20
- package/codex/bundle/capture.js +40 -10
- package/codex/bundle/commands/auth-login.js +84 -18
- package/codex/bundle/pre-tool-use.js +41 -11
- package/codex/bundle/session-start-setup.js +40 -10
- package/codex/bundle/session-start.js +27 -3
- package/codex/bundle/shell/deeplake-shell.js +41 -11
- package/codex/bundle/skilify-worker.js +907 -0
- package/codex/bundle/stop.js +373 -51
- package/cursor/bundle/capture.js +354 -13
- package/cursor/bundle/commands/auth-login.js +84 -18
- package/cursor/bundle/pre-tool-use.js +40 -10
- package/cursor/bundle/session-end.js +303 -6
- package/cursor/bundle/session-start.js +68 -14
- package/cursor/bundle/shell/deeplake-shell.js +41 -11
- package/cursor/bundle/skilify-worker.js +907 -0
- package/hermes/bundle/capture.js +354 -13
- package/hermes/bundle/commands/auth-login.js +84 -18
- package/hermes/bundle/pre-tool-use.js +40 -10
- package/hermes/bundle/session-end.js +305 -7
- package/hermes/bundle/session-start.js +68 -14
- package/hermes/bundle/shell/deeplake-shell.js +41 -11
- package/hermes/bundle/skilify-worker.js +907 -0
- package/mcp/bundle/server.js +41 -11
- package/openclaw/dist/chunks/{config-G23NI5TV.js → config-ZLH6JFJS.js} +1 -0
- package/openclaw/dist/index.js +185 -16
- package/openclaw/dist/skilify-worker.js +907 -0
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/openclaw/skills/SKILL.md +19 -0
- package/package.json +6 -1
- package/pi/extension-source/hivemind.ts +130 -1
package/codex/bundle/capture.js
CHANGED
|
@@ -97,6 +97,7 @@ function loadConfig() {
|
|
|
97
97
|
apiUrl: process.env.HIVEMIND_API_URL ?? creds?.apiUrl ?? "https://api.deeplake.ai",
|
|
98
98
|
tableName: process.env.HIVEMIND_TABLE ?? "memory",
|
|
99
99
|
sessionsTableName: process.env.HIVEMIND_SESSIONS_TABLE ?? "sessions",
|
|
100
|
+
skillsTableName: process.env.HIVEMIND_SKILLS_TABLE ?? "skills",
|
|
100
101
|
memoryPath: process.env.HIVEMIND_MEMORY_PATH ?? join(home, ".deeplake", "memory")
|
|
101
102
|
};
|
|
102
103
|
}
|
|
@@ -124,6 +125,12 @@ function log(tag, msg) {
|
|
|
124
125
|
function sqlStr(value) {
|
|
125
126
|
return value.replace(/\\/g, "\\\\").replace(/'/g, "''").replace(/\0/g, "").replace(/[\x01-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
|
|
126
127
|
}
|
|
128
|
+
function sqlIdent(name) {
|
|
129
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
|
|
130
|
+
throw new Error(`Invalid SQL identifier: ${JSON.stringify(name)}`);
|
|
131
|
+
}
|
|
132
|
+
return name;
|
|
133
|
+
}
|
|
127
134
|
|
|
128
135
|
// dist/src/embeddings/columns.js
|
|
129
136
|
var SUMMARY_EMBEDDING_COL = "summary_embedding";
|
|
@@ -496,7 +503,7 @@ var DeeplakeApi = class {
|
|
|
496
503
|
}
|
|
497
504
|
/** Create the memory table if it doesn't already exist. Migrate columns on existing tables. */
|
|
498
505
|
async ensureTable(name) {
|
|
499
|
-
const tbl = name ?? this.tableName;
|
|
506
|
+
const tbl = sqlIdent(name ?? this.tableName);
|
|
500
507
|
const tables = await this.listTables();
|
|
501
508
|
if (!tables.includes(tbl)) {
|
|
502
509
|
log2(`table "${tbl}" not found, creating`);
|
|
@@ -510,17 +517,40 @@ var DeeplakeApi = class {
|
|
|
510
517
|
}
|
|
511
518
|
/** Create the sessions table (uses JSONB for message since every row is a JSON event). */
|
|
512
519
|
async ensureSessionsTable(name) {
|
|
520
|
+
const safe = sqlIdent(name);
|
|
521
|
+
const tables = await this.listTables();
|
|
522
|
+
if (!tables.includes(safe)) {
|
|
523
|
+
log2(`table "${safe}" not found, creating`);
|
|
524
|
+
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);
|
|
525
|
+
log2(`table "${safe}" created`);
|
|
526
|
+
if (!tables.includes(safe))
|
|
527
|
+
this._tablesCache = [...tables, safe];
|
|
528
|
+
}
|
|
529
|
+
await this.ensureEmbeddingColumn(safe, MESSAGE_EMBEDDING_COL);
|
|
530
|
+
await this.ensureColumn(safe, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
531
|
+
await this.ensureLookupIndex(safe, "path_creation_date", `("path", "creation_date")`);
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Create the skills table.
|
|
535
|
+
*
|
|
536
|
+
* One row per skill version. Workers INSERT a fresh row on every KEEP /
|
|
537
|
+
* MERGE rather than UPDATE-ing in place, so the full version history is
|
|
538
|
+
* recoverable. Uniqueness in the *current* state is by (project_key, name)
|
|
539
|
+
* — newer rows shadow older ones at read time (ORDER BY version DESC).
|
|
540
|
+
* This sidesteps the Deeplake UPDATE-coalescing quirk that bit the wiki
|
|
541
|
+
* worker.
|
|
542
|
+
*/
|
|
543
|
+
async ensureSkillsTable(name) {
|
|
544
|
+
const safe = sqlIdent(name);
|
|
513
545
|
const tables = await this.listTables();
|
|
514
|
-
if (!tables.includes(
|
|
515
|
-
log2(`table "${
|
|
516
|
-
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${
|
|
517
|
-
log2(`table "${
|
|
518
|
-
if (!tables.includes(
|
|
519
|
-
this._tablesCache = [...tables,
|
|
546
|
+
if (!tables.includes(safe)) {
|
|
547
|
+
log2(`table "${safe}" not found, creating`);
|
|
548
|
+
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);
|
|
549
|
+
log2(`table "${safe}" created`);
|
|
550
|
+
if (!tables.includes(safe))
|
|
551
|
+
this._tablesCache = [...tables, safe];
|
|
520
552
|
}
|
|
521
|
-
await this.
|
|
522
|
-
await this.ensureColumn(name, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
523
|
-
await this.ensureLookupIndex(name, "path_creation_date", `("path", "creation_date")`);
|
|
553
|
+
await this.ensureLookupIndex(safe, "project_key_name", `("project_key", "name")`);
|
|
524
554
|
}
|
|
525
555
|
};
|
|
526
556
|
|
|
@@ -299,6 +299,7 @@ function loadConfig() {
|
|
|
299
299
|
apiUrl: process.env.HIVEMIND_API_URL ?? creds?.apiUrl ?? "https://api.deeplake.ai",
|
|
300
300
|
tableName: process.env.HIVEMIND_TABLE ?? "memory",
|
|
301
301
|
sessionsTableName: process.env.HIVEMIND_SESSIONS_TABLE ?? "sessions",
|
|
302
|
+
skillsTableName: process.env.HIVEMIND_SKILLS_TABLE ?? "skills",
|
|
302
303
|
memoryPath: process.env.HIVEMIND_MEMORY_PATH ?? join2(home, ".deeplake", "memory")
|
|
303
304
|
};
|
|
304
305
|
}
|
|
@@ -323,6 +324,12 @@ function log(tag, msg) {
|
|
|
323
324
|
function sqlStr(value) {
|
|
324
325
|
return value.replace(/\\/g, "\\\\").replace(/'/g, "''").replace(/\0/g, "").replace(/[\x01-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
|
|
325
326
|
}
|
|
327
|
+
function sqlIdent(name) {
|
|
328
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
|
|
329
|
+
throw new Error(`Invalid SQL identifier: ${JSON.stringify(name)}`);
|
|
330
|
+
}
|
|
331
|
+
return name;
|
|
332
|
+
}
|
|
326
333
|
|
|
327
334
|
// dist/src/embeddings/columns.js
|
|
328
335
|
var SUMMARY_EMBEDDING_COL = "summary_embedding";
|
|
@@ -686,7 +693,7 @@ var DeeplakeApi = class {
|
|
|
686
693
|
}
|
|
687
694
|
/** Create the memory table if it doesn't already exist. Migrate columns on existing tables. */
|
|
688
695
|
async ensureTable(name) {
|
|
689
|
-
const tbl = name ?? this.tableName;
|
|
696
|
+
const tbl = sqlIdent(name ?? this.tableName);
|
|
690
697
|
const tables = await this.listTables();
|
|
691
698
|
if (!tables.includes(tbl)) {
|
|
692
699
|
log2(`table "${tbl}" not found, creating`);
|
|
@@ -700,17 +707,40 @@ var DeeplakeApi = class {
|
|
|
700
707
|
}
|
|
701
708
|
/** Create the sessions table (uses JSONB for message since every row is a JSON event). */
|
|
702
709
|
async ensureSessionsTable(name) {
|
|
710
|
+
const safe = sqlIdent(name);
|
|
703
711
|
const tables = await this.listTables();
|
|
704
|
-
if (!tables.includes(
|
|
705
|
-
log2(`table "${
|
|
706
|
-
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${
|
|
707
|
-
log2(`table "${
|
|
708
|
-
if (!tables.includes(
|
|
709
|
-
this._tablesCache = [...tables,
|
|
712
|
+
if (!tables.includes(safe)) {
|
|
713
|
+
log2(`table "${safe}" not found, creating`);
|
|
714
|
+
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);
|
|
715
|
+
log2(`table "${safe}" created`);
|
|
716
|
+
if (!tables.includes(safe))
|
|
717
|
+
this._tablesCache = [...tables, safe];
|
|
710
718
|
}
|
|
711
|
-
await this.ensureEmbeddingColumn(
|
|
712
|
-
await this.ensureColumn(
|
|
713
|
-
await this.ensureLookupIndex(
|
|
719
|
+
await this.ensureEmbeddingColumn(safe, MESSAGE_EMBEDDING_COL);
|
|
720
|
+
await this.ensureColumn(safe, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
721
|
+
await this.ensureLookupIndex(safe, "path_creation_date", `("path", "creation_date")`);
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Create the skills table.
|
|
725
|
+
*
|
|
726
|
+
* One row per skill version. Workers INSERT a fresh row on every KEEP /
|
|
727
|
+
* MERGE rather than UPDATE-ing in place, so the full version history is
|
|
728
|
+
* recoverable. Uniqueness in the *current* state is by (project_key, name)
|
|
729
|
+
* — newer rows shadow older ones at read time (ORDER BY version DESC).
|
|
730
|
+
* This sidesteps the Deeplake UPDATE-coalescing quirk that bit the wiki
|
|
731
|
+
* worker.
|
|
732
|
+
*/
|
|
733
|
+
async ensureSkillsTable(name) {
|
|
734
|
+
const safe = sqlIdent(name);
|
|
735
|
+
const tables = await this.listTables();
|
|
736
|
+
if (!tables.includes(safe)) {
|
|
737
|
+
log2(`table "${safe}" not found, creating`);
|
|
738
|
+
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);
|
|
739
|
+
log2(`table "${safe}" created`);
|
|
740
|
+
if (!tables.includes(safe))
|
|
741
|
+
this._tablesCache = [...tables, safe];
|
|
742
|
+
}
|
|
743
|
+
await this.ensureLookupIndex(safe, "project_key_name", `("project_key", "name")`);
|
|
714
744
|
}
|
|
715
745
|
};
|
|
716
746
|
|
|
@@ -890,8 +920,24 @@ async function runAuthCommand(args) {
|
|
|
890
920
|
console.log(`Org not found: ${target}`);
|
|
891
921
|
process.exit(1);
|
|
892
922
|
}
|
|
923
|
+
const prevWs = creds.workspaceId ?? "default";
|
|
924
|
+
const lcPrev = prevWs.toLowerCase();
|
|
925
|
+
const wsList = await listWorkspaces(creds.token, apiUrl, match.id);
|
|
926
|
+
const matchedWs = wsList.find((w) => w.id === prevWs || w.name && w.name.toLowerCase() === lcPrev);
|
|
893
927
|
await switchOrg(match.id, match.name);
|
|
894
928
|
console.log(`Switched to org: ${match.name}`);
|
|
929
|
+
if (!matchedWs) {
|
|
930
|
+
if (prevWs !== "default") {
|
|
931
|
+
await switchWorkspace("default");
|
|
932
|
+
console.log(`Workspace '${prevWs}' is not in org '${match.name}'. Reset workspace to 'default'.`);
|
|
933
|
+
if (wsList.length > 0) {
|
|
934
|
+
console.log(`Available workspaces: ${wsList.map((w) => w.name || w.id).join(", ")}`);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
} else if (matchedWs.id !== prevWs) {
|
|
938
|
+
await switchWorkspace(matchedWs.id);
|
|
939
|
+
console.log(`Workspace name '${prevWs}' resolved to id '${matchedWs.id}' in org '${match.name}'.`);
|
|
940
|
+
}
|
|
895
941
|
} else {
|
|
896
942
|
console.log("Usage: org list | org switch <name-or-id>");
|
|
897
943
|
}
|
|
@@ -903,7 +949,7 @@ async function runAuthCommand(args) {
|
|
|
903
949
|
process.exit(1);
|
|
904
950
|
}
|
|
905
951
|
const ws = await listWorkspaces(creds.token, apiUrl, creds.orgId);
|
|
906
|
-
ws.forEach((w) => console.log(
|
|
952
|
+
ws.forEach((w) => console.log(w.name || w.id));
|
|
907
953
|
break;
|
|
908
954
|
}
|
|
909
955
|
case "workspace": {
|
|
@@ -911,14 +957,34 @@ async function runAuthCommand(args) {
|
|
|
911
957
|
console.log("Not logged in.");
|
|
912
958
|
process.exit(1);
|
|
913
959
|
}
|
|
914
|
-
const
|
|
915
|
-
if (
|
|
916
|
-
|
|
917
|
-
|
|
960
|
+
const sub = args[1];
|
|
961
|
+
if (sub === "list") {
|
|
962
|
+
const wsList = await listWorkspaces(creds.token, apiUrl, creds.orgId);
|
|
963
|
+
wsList.forEach((w) => console.log(w.name || w.id));
|
|
964
|
+
break;
|
|
918
965
|
}
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
966
|
+
if (sub === "switch") {
|
|
967
|
+
const target = args[2];
|
|
968
|
+
if (!target) {
|
|
969
|
+
console.log("Usage: workspace switch <name-or-id>");
|
|
970
|
+
process.exit(1);
|
|
971
|
+
}
|
|
972
|
+
const wsList = await listWorkspaces(creds.token, apiUrl, creds.orgId);
|
|
973
|
+
const lcTarget = target.toLowerCase();
|
|
974
|
+
const match = wsList.find((w) => w.id === target || w.name && w.name.toLowerCase() === lcTarget);
|
|
975
|
+
if (!match) {
|
|
976
|
+
console.log(`Workspace not found: ${target}`);
|
|
977
|
+
if (wsList.length > 0) {
|
|
978
|
+
console.log(`Available workspaces: ${wsList.map((w) => w.name || w.id).join(", ")}`);
|
|
979
|
+
}
|
|
980
|
+
process.exit(1);
|
|
981
|
+
}
|
|
982
|
+
await switchWorkspace(match.id);
|
|
983
|
+
console.log(`Switched to workspace: ${match.name || match.id}`);
|
|
984
|
+
break;
|
|
985
|
+
}
|
|
986
|
+
console.log("Usage: workspace list | workspace switch <name-or-id>");
|
|
987
|
+
process.exit(1);
|
|
922
988
|
}
|
|
923
989
|
case "invite": {
|
|
924
990
|
if (!creds) {
|
|
@@ -103,6 +103,7 @@ function loadConfig() {
|
|
|
103
103
|
apiUrl: process.env.HIVEMIND_API_URL ?? creds?.apiUrl ?? "https://api.deeplake.ai",
|
|
104
104
|
tableName: process.env.HIVEMIND_TABLE ?? "memory",
|
|
105
105
|
sessionsTableName: process.env.HIVEMIND_SESSIONS_TABLE ?? "sessions",
|
|
106
|
+
skillsTableName: process.env.HIVEMIND_SKILLS_TABLE ?? "skills",
|
|
106
107
|
memoryPath: process.env.HIVEMIND_MEMORY_PATH ?? join(home, ".deeplake", "memory")
|
|
107
108
|
};
|
|
108
109
|
}
|
|
@@ -130,6 +131,12 @@ function sqlStr(value) {
|
|
|
130
131
|
function sqlLike(value) {
|
|
131
132
|
return sqlStr(value).replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
132
133
|
}
|
|
134
|
+
function sqlIdent(name) {
|
|
135
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
|
|
136
|
+
throw new Error(`Invalid SQL identifier: ${JSON.stringify(name)}`);
|
|
137
|
+
}
|
|
138
|
+
return name;
|
|
139
|
+
}
|
|
133
140
|
|
|
134
141
|
// dist/src/embeddings/columns.js
|
|
135
142
|
var SUMMARY_EMBEDDING_COL = "summary_embedding";
|
|
@@ -502,7 +509,7 @@ var DeeplakeApi = class {
|
|
|
502
509
|
}
|
|
503
510
|
/** Create the memory table if it doesn't already exist. Migrate columns on existing tables. */
|
|
504
511
|
async ensureTable(name) {
|
|
505
|
-
const tbl = name ?? this.tableName;
|
|
512
|
+
const tbl = sqlIdent(name ?? this.tableName);
|
|
506
513
|
const tables = await this.listTables();
|
|
507
514
|
if (!tables.includes(tbl)) {
|
|
508
515
|
log2(`table "${tbl}" not found, creating`);
|
|
@@ -516,17 +523,40 @@ var DeeplakeApi = class {
|
|
|
516
523
|
}
|
|
517
524
|
/** Create the sessions table (uses JSONB for message since every row is a JSON event). */
|
|
518
525
|
async ensureSessionsTable(name) {
|
|
526
|
+
const safe = sqlIdent(name);
|
|
527
|
+
const tables = await this.listTables();
|
|
528
|
+
if (!tables.includes(safe)) {
|
|
529
|
+
log2(`table "${safe}" not found, creating`);
|
|
530
|
+
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);
|
|
531
|
+
log2(`table "${safe}" created`);
|
|
532
|
+
if (!tables.includes(safe))
|
|
533
|
+
this._tablesCache = [...tables, safe];
|
|
534
|
+
}
|
|
535
|
+
await this.ensureEmbeddingColumn(safe, MESSAGE_EMBEDDING_COL);
|
|
536
|
+
await this.ensureColumn(safe, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
537
|
+
await this.ensureLookupIndex(safe, "path_creation_date", `("path", "creation_date")`);
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Create the skills table.
|
|
541
|
+
*
|
|
542
|
+
* One row per skill version. Workers INSERT a fresh row on every KEEP /
|
|
543
|
+
* MERGE rather than UPDATE-ing in place, so the full version history is
|
|
544
|
+
* recoverable. Uniqueness in the *current* state is by (project_key, name)
|
|
545
|
+
* — newer rows shadow older ones at read time (ORDER BY version DESC).
|
|
546
|
+
* This sidesteps the Deeplake UPDATE-coalescing quirk that bit the wiki
|
|
547
|
+
* worker.
|
|
548
|
+
*/
|
|
549
|
+
async ensureSkillsTable(name) {
|
|
550
|
+
const safe = sqlIdent(name);
|
|
519
551
|
const tables = await this.listTables();
|
|
520
|
-
if (!tables.includes(
|
|
521
|
-
log2(`table "${
|
|
522
|
-
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${
|
|
523
|
-
log2(`table "${
|
|
524
|
-
if (!tables.includes(
|
|
525
|
-
this._tablesCache = [...tables,
|
|
526
|
-
}
|
|
527
|
-
await this.
|
|
528
|
-
await this.ensureColumn(name, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
529
|
-
await this.ensureLookupIndex(name, "path_creation_date", `("path", "creation_date")`);
|
|
552
|
+
if (!tables.includes(safe)) {
|
|
553
|
+
log2(`table "${safe}" not found, creating`);
|
|
554
|
+
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);
|
|
555
|
+
log2(`table "${safe}" created`);
|
|
556
|
+
if (!tables.includes(safe))
|
|
557
|
+
this._tablesCache = [...tables, safe];
|
|
558
|
+
}
|
|
559
|
+
await this.ensureLookupIndex(safe, "project_key_name", `("project_key", "name")`);
|
|
530
560
|
}
|
|
531
561
|
};
|
|
532
562
|
|
|
@@ -120,6 +120,7 @@ function loadConfig() {
|
|
|
120
120
|
apiUrl: process.env.HIVEMIND_API_URL ?? creds?.apiUrl ?? "https://api.deeplake.ai",
|
|
121
121
|
tableName: process.env.HIVEMIND_TABLE ?? "memory",
|
|
122
122
|
sessionsTableName: process.env.HIVEMIND_SESSIONS_TABLE ?? "sessions",
|
|
123
|
+
skillsTableName: process.env.HIVEMIND_SKILLS_TABLE ?? "skills",
|
|
123
124
|
memoryPath: process.env.HIVEMIND_MEMORY_PATH ?? join2(home, ".deeplake", "memory")
|
|
124
125
|
};
|
|
125
126
|
}
|
|
@@ -147,6 +148,12 @@ function log(tag, msg) {
|
|
|
147
148
|
function sqlStr(value) {
|
|
148
149
|
return value.replace(/\\/g, "\\\\").replace(/'/g, "''").replace(/\0/g, "").replace(/[\x01-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
|
|
149
150
|
}
|
|
151
|
+
function sqlIdent(name) {
|
|
152
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
|
|
153
|
+
throw new Error(`Invalid SQL identifier: ${JSON.stringify(name)}`);
|
|
154
|
+
}
|
|
155
|
+
return name;
|
|
156
|
+
}
|
|
150
157
|
|
|
151
158
|
// dist/src/embeddings/columns.js
|
|
152
159
|
var SUMMARY_EMBEDDING_COL = "summary_embedding";
|
|
@@ -510,7 +517,7 @@ var DeeplakeApi = class {
|
|
|
510
517
|
}
|
|
511
518
|
/** Create the memory table if it doesn't already exist. Migrate columns on existing tables. */
|
|
512
519
|
async ensureTable(name) {
|
|
513
|
-
const tbl = name ?? this.tableName;
|
|
520
|
+
const tbl = sqlIdent(name ?? this.tableName);
|
|
514
521
|
const tables = await this.listTables();
|
|
515
522
|
if (!tables.includes(tbl)) {
|
|
516
523
|
log2(`table "${tbl}" not found, creating`);
|
|
@@ -524,17 +531,40 @@ var DeeplakeApi = class {
|
|
|
524
531
|
}
|
|
525
532
|
/** Create the sessions table (uses JSONB for message since every row is a JSON event). */
|
|
526
533
|
async ensureSessionsTable(name) {
|
|
534
|
+
const safe = sqlIdent(name);
|
|
535
|
+
const tables = await this.listTables();
|
|
536
|
+
if (!tables.includes(safe)) {
|
|
537
|
+
log2(`table "${safe}" not found, creating`);
|
|
538
|
+
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);
|
|
539
|
+
log2(`table "${safe}" created`);
|
|
540
|
+
if (!tables.includes(safe))
|
|
541
|
+
this._tablesCache = [...tables, safe];
|
|
542
|
+
}
|
|
543
|
+
await this.ensureEmbeddingColumn(safe, MESSAGE_EMBEDDING_COL);
|
|
544
|
+
await this.ensureColumn(safe, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
545
|
+
await this.ensureLookupIndex(safe, "path_creation_date", `("path", "creation_date")`);
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Create the skills table.
|
|
549
|
+
*
|
|
550
|
+
* One row per skill version. Workers INSERT a fresh row on every KEEP /
|
|
551
|
+
* MERGE rather than UPDATE-ing in place, so the full version history is
|
|
552
|
+
* recoverable. Uniqueness in the *current* state is by (project_key, name)
|
|
553
|
+
* — newer rows shadow older ones at read time (ORDER BY version DESC).
|
|
554
|
+
* This sidesteps the Deeplake UPDATE-coalescing quirk that bit the wiki
|
|
555
|
+
* worker.
|
|
556
|
+
*/
|
|
557
|
+
async ensureSkillsTable(name) {
|
|
558
|
+
const safe = sqlIdent(name);
|
|
527
559
|
const tables = await this.listTables();
|
|
528
|
-
if (!tables.includes(
|
|
529
|
-
log2(`table "${
|
|
530
|
-
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${
|
|
531
|
-
log2(`table "${
|
|
532
|
-
if (!tables.includes(
|
|
533
|
-
this._tablesCache = [...tables,
|
|
560
|
+
if (!tables.includes(safe)) {
|
|
561
|
+
log2(`table "${safe}" not found, creating`);
|
|
562
|
+
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);
|
|
563
|
+
log2(`table "${safe}" created`);
|
|
564
|
+
if (!tables.includes(safe))
|
|
565
|
+
this._tablesCache = [...tables, safe];
|
|
534
566
|
}
|
|
535
|
-
await this.
|
|
536
|
-
await this.ensureColumn(name, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
537
|
-
await this.ensureLookupIndex(name, "path_creation_date", `("path", "creation_date")`);
|
|
567
|
+
await this.ensureLookupIndex(safe, "project_key_name", `("project_key", "name")`);
|
|
538
568
|
}
|
|
539
569
|
};
|
|
540
570
|
|
|
@@ -101,7 +101,6 @@ function getInstalledVersion(bundleDir, pluginManifestDir) {
|
|
|
101
101
|
// dist/src/hooks/codex/session-start.js
|
|
102
102
|
var log2 = (msg) => log("codex-session-start", msg);
|
|
103
103
|
var __bundleDir = dirname2(fileURLToPath(import.meta.url));
|
|
104
|
-
var AUTH_CMD = join4(__bundleDir, "commands", "auth-login.js");
|
|
105
104
|
var context = `DEEPLAKE MEMORY: Persistent memory at ~/.deeplake/memory/ shared across sessions, users, and agents.
|
|
106
105
|
|
|
107
106
|
Deeplake memory has THREE tiers \u2014 pick the right one for the question:
|
|
@@ -118,7 +117,32 @@ Search workflow:
|
|
|
118
117
|
\u274C grep without a summaries/ or sessions/ suffix \u2014 too noisy
|
|
119
118
|
|
|
120
119
|
IMPORTANT: Only use bash builtins (cat, ls, grep, echo, jq, head, tail, sed, awk, etc.) on ~/.deeplake/memory/. Do NOT use python, python3, node, curl, or other interpreters \u2014 they are not available in the memory filesystem.
|
|
121
|
-
Do NOT spawn subagents to read deeplake memory
|
|
120
|
+
Do NOT spawn subagents to read deeplake memory.
|
|
121
|
+
|
|
122
|
+
Organization management \u2014 each argument is SEPARATE (do NOT quote subcommands together):
|
|
123
|
+
- hivemind login \u2014 SSO login
|
|
124
|
+
- hivemind whoami \u2014 show current user/org
|
|
125
|
+
- hivemind org list \u2014 list organizations
|
|
126
|
+
- hivemind org switch <name-or-id> \u2014 switch organization
|
|
127
|
+
- hivemind workspaces \u2014 list workspaces
|
|
128
|
+
- hivemind workspace <id> \u2014 switch workspace
|
|
129
|
+
- hivemind invite <email> <ADMIN|WRITE|READ> \u2014 invite member (ALWAYS ask user which role before inviting)
|
|
130
|
+
- hivemind members \u2014 list members
|
|
131
|
+
- hivemind remove <user-id> \u2014 remove member
|
|
132
|
+
|
|
133
|
+
SKILLS (skilify) \u2014 mine + share reusable skills across the org:
|
|
134
|
+
- hivemind skilify \u2014 show scope/team/install + per-project state
|
|
135
|
+
- hivemind skilify pull \u2014 sync project skills from the org table
|
|
136
|
+
- hivemind skilify pull --user <email> \u2014 only that author's skills
|
|
137
|
+
- hivemind skilify pull --users a,b,c \u2014 multiple authors (CSV)
|
|
138
|
+
- hivemind skilify pull --all-users \u2014 explicit "no author filter"
|
|
139
|
+
- hivemind skilify pull --to project|global \u2014 install location
|
|
140
|
+
- hivemind skilify pull --dry-run \u2014 preview only
|
|
141
|
+
- hivemind skilify pull --force \u2014 overwrite local (creates .bak)
|
|
142
|
+
- hivemind skilify pull <skill-name> \u2014 pull only that skill (combines with --user)
|
|
143
|
+
- hivemind skilify scope <me|team|org> \u2014 sharing scope for new skills
|
|
144
|
+
- hivemind skilify install <project|global> \u2014 default install location
|
|
145
|
+
- hivemind skilify team add|remove|list <name> \u2014 manage team list`;
|
|
122
146
|
async function main() {
|
|
123
147
|
if (process.env.HIVEMIND_WIKI_WORKER === "1")
|
|
124
148
|
return;
|
|
@@ -149,7 +173,7 @@ Hivemind v${current}`;
|
|
|
149
173
|
}
|
|
150
174
|
const additionalContext = creds?.token ? `${context}
|
|
151
175
|
Logged in to Deeplake as org: ${creds.orgName ?? creds.orgId} (workspace: ${creds.workspaceId ?? "default"})${versionNotice}` : `${context}
|
|
152
|
-
Not logged in to Deeplake. Run:
|
|
176
|
+
Not logged in to Deeplake. Run: hivemind login${versionNotice}`;
|
|
153
177
|
console.log(additionalContext);
|
|
154
178
|
}
|
|
155
179
|
main().catch((e) => {
|
|
@@ -66791,6 +66791,7 @@ function loadConfig() {
|
|
|
66791
66791
|
apiUrl: process.env.HIVEMIND_API_URL ?? creds?.apiUrl ?? "https://api.deeplake.ai",
|
|
66792
66792
|
tableName: process.env.HIVEMIND_TABLE ?? "memory",
|
|
66793
66793
|
sessionsTableName: process.env.HIVEMIND_SESSIONS_TABLE ?? "sessions",
|
|
66794
|
+
skillsTableName: process.env.HIVEMIND_SKILLS_TABLE ?? "skills",
|
|
66794
66795
|
memoryPath: process.env.HIVEMIND_MEMORY_PATH ?? join4(home, ".deeplake", "memory")
|
|
66795
66796
|
};
|
|
66796
66797
|
}
|
|
@@ -66818,6 +66819,12 @@ function sqlStr(value) {
|
|
|
66818
66819
|
function sqlLike(value) {
|
|
66819
66820
|
return sqlStr(value).replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
66820
66821
|
}
|
|
66822
|
+
function sqlIdent(name) {
|
|
66823
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
|
|
66824
|
+
throw new Error(`Invalid SQL identifier: ${JSON.stringify(name)}`);
|
|
66825
|
+
}
|
|
66826
|
+
return name;
|
|
66827
|
+
}
|
|
66821
66828
|
|
|
66822
66829
|
// dist/src/embeddings/columns.js
|
|
66823
66830
|
var SUMMARY_EMBEDDING_COL = "summary_embedding";
|
|
@@ -67190,7 +67197,7 @@ var DeeplakeApi = class {
|
|
|
67190
67197
|
}
|
|
67191
67198
|
/** Create the memory table if it doesn't already exist. Migrate columns on existing tables. */
|
|
67192
67199
|
async ensureTable(name) {
|
|
67193
|
-
const tbl = name ?? this.tableName;
|
|
67200
|
+
const tbl = sqlIdent(name ?? this.tableName);
|
|
67194
67201
|
const tables = await this.listTables();
|
|
67195
67202
|
if (!tables.includes(tbl)) {
|
|
67196
67203
|
log2(`table "${tbl}" not found, creating`);
|
|
@@ -67204,17 +67211,40 @@ var DeeplakeApi = class {
|
|
|
67204
67211
|
}
|
|
67205
67212
|
/** Create the sessions table (uses JSONB for message since every row is a JSON event). */
|
|
67206
67213
|
async ensureSessionsTable(name) {
|
|
67214
|
+
const safe = sqlIdent(name);
|
|
67215
|
+
const tables = await this.listTables();
|
|
67216
|
+
if (!tables.includes(safe)) {
|
|
67217
|
+
log2(`table "${safe}" not found, creating`);
|
|
67218
|
+
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);
|
|
67219
|
+
log2(`table "${safe}" created`);
|
|
67220
|
+
if (!tables.includes(safe))
|
|
67221
|
+
this._tablesCache = [...tables, safe];
|
|
67222
|
+
}
|
|
67223
|
+
await this.ensureEmbeddingColumn(safe, MESSAGE_EMBEDDING_COL);
|
|
67224
|
+
await this.ensureColumn(safe, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
67225
|
+
await this.ensureLookupIndex(safe, "path_creation_date", `("path", "creation_date")`);
|
|
67226
|
+
}
|
|
67227
|
+
/**
|
|
67228
|
+
* Create the skills table.
|
|
67229
|
+
*
|
|
67230
|
+
* One row per skill version. Workers INSERT a fresh row on every KEEP /
|
|
67231
|
+
* MERGE rather than UPDATE-ing in place, so the full version history is
|
|
67232
|
+
* recoverable. Uniqueness in the *current* state is by (project_key, name)
|
|
67233
|
+
* — newer rows shadow older ones at read time (ORDER BY version DESC).
|
|
67234
|
+
* This sidesteps the Deeplake UPDATE-coalescing quirk that bit the wiki
|
|
67235
|
+
* worker.
|
|
67236
|
+
*/
|
|
67237
|
+
async ensureSkillsTable(name) {
|
|
67238
|
+
const safe = sqlIdent(name);
|
|
67207
67239
|
const tables = await this.listTables();
|
|
67208
|
-
if (!tables.includes(
|
|
67209
|
-
log2(`table "${
|
|
67210
|
-
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${
|
|
67211
|
-
log2(`table "${
|
|
67212
|
-
if (!tables.includes(
|
|
67213
|
-
this._tablesCache = [...tables,
|
|
67214
|
-
}
|
|
67215
|
-
await this.
|
|
67216
|
-
await this.ensureColumn(name, "agent", "TEXT NOT NULL DEFAULT ''");
|
|
67217
|
-
await this.ensureLookupIndex(name, "path_creation_date", `("path", "creation_date")`);
|
|
67240
|
+
if (!tables.includes(safe)) {
|
|
67241
|
+
log2(`table "${safe}" not found, creating`);
|
|
67242
|
+
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);
|
|
67243
|
+
log2(`table "${safe}" created`);
|
|
67244
|
+
if (!tables.includes(safe))
|
|
67245
|
+
this._tablesCache = [...tables, safe];
|
|
67246
|
+
}
|
|
67247
|
+
await this.ensureLookupIndex(safe, "project_key_name", `("project_key", "name")`);
|
|
67218
67248
|
}
|
|
67219
67249
|
};
|
|
67220
67250
|
|