@deeplake/hivemind 0.7.54 → 0.7.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +2 -0
  4. package/bundle/cli.js +63 -31
  5. package/codex/bundle/capture.js +17 -0
  6. package/codex/bundle/commands/auth-login.js +17 -0
  7. package/codex/bundle/graph-pull-worker.js +17 -0
  8. package/codex/bundle/pre-tool-use.js +17 -0
  9. package/codex/bundle/session-start-setup.js +17 -0
  10. package/codex/bundle/session-start.js +59 -24
  11. package/codex/bundle/shell/deeplake-shell.js +17 -0
  12. package/codex/bundle/stop.js +17 -0
  13. package/cursor/bundle/capture.js +17 -0
  14. package/cursor/bundle/commands/auth-login.js +17 -0
  15. package/cursor/bundle/graph-pull-worker.js +17 -0
  16. package/cursor/bundle/pre-tool-use.js +17 -0
  17. package/cursor/bundle/session-start.js +86 -40
  18. package/cursor/bundle/shell/deeplake-shell.js +17 -0
  19. package/hermes/bundle/capture.js +17 -0
  20. package/hermes/bundle/commands/auth-login.js +17 -0
  21. package/hermes/bundle/graph-pull-worker.js +17 -0
  22. package/hermes/bundle/pre-tool-use.js +17 -0
  23. package/hermes/bundle/session-start.js +86 -40
  24. package/hermes/bundle/shell/deeplake-shell.js +17 -0
  25. package/mcp/bundle/server.js +17 -0
  26. package/openclaw/dist/index.js +16 -1
  27. package/openclaw/openclaw.plugin.json +1 -1
  28. package/openclaw/package.json +1 -1
  29. package/package.json +8 -3
  30. package/scripts/audit-openclaw-bundle.mjs +187 -0
  31. package/scripts/ensure-tree-sitter.mjs +91 -0
  32. package/scripts/pack-check.mjs +29 -0
  33. package/scripts/sync-versions.d.mts +15 -0
  34. package/scripts/sync-versions.mjs +103 -0
  35. package/scripts/verify-install.sh +218 -0
@@ -811,6 +811,23 @@ var DeeplakeApi = class {
811
811
  this._tablesCache = [...tables];
812
812
  return tables;
813
813
  }
814
+ /**
815
+ * Like listTables() but returns null when the list could NOT be trusted
816
+ * (the fetch failed / was non-cacheable). Callers gating a read on table
817
+ * existence use this to tell a genuinely-empty workspace ([]) apart from a
818
+ * failed lookup (null): on [] they can safely skip the read (no table → no
819
+ * 42P01), on null they must fall back to SELECT-then-catch so a transient
820
+ * lookup blip doesn't drop a read of a table that really exists.
821
+ */
822
+ async knownTablesOrNull() {
823
+ if (this._tablesCache)
824
+ return [...this._tablesCache];
825
+ const { tables, cacheable } = await this._fetchTables();
826
+ if (!cacheable)
827
+ return null;
828
+ this._tablesCache = [...tables];
829
+ return [...tables];
830
+ }
814
831
  async _fetchTables() {
815
832
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
816
833
  try {
@@ -1056,24 +1073,33 @@ async function renderContextBlock(query, input, opts = {}) {
1056
1073
  const log7 = opts.log ?? (() => {
1057
1074
  });
1058
1075
  try {
1076
+ const tableExists = opts.tableExists;
1059
1077
  let rules = [];
1060
- try {
1061
- rules = await listRules(query, input.rulesTable, {
1062
- status: "active",
1063
- limit: Math.max(maxRules * 4, maxRules + 1)
1064
- });
1065
- } catch (rulesErr) {
1066
- const rmsg = rulesErr instanceof Error ? rulesErr.message : String(rulesErr);
1067
- log7(`render-context-block: rules unavailable (continuing): ${rmsg}`);
1078
+ if (tableExists && !tableExists(input.rulesTable)) {
1079
+ log7(`render-context-block: rules table "${input.rulesTable}" not present \u2014 skipping read`);
1080
+ } else {
1081
+ try {
1082
+ rules = await listRules(query, input.rulesTable, {
1083
+ status: "active",
1084
+ limit: Math.max(maxRules * 4, maxRules + 1)
1085
+ });
1086
+ } catch (rulesErr) {
1087
+ const rmsg = rulesErr instanceof Error ? rulesErr.message : String(rulesErr);
1088
+ log7(`render-context-block: rules unavailable (continuing): ${rmsg}`);
1089
+ }
1068
1090
  }
1069
1091
  let goals = [];
1070
- try {
1071
- goals = await listOpenGoals(query, input.goalsTable, input.currentUser, {
1072
- limit: Math.max(maxGoals * 4, maxGoals + 1)
1073
- });
1074
- } catch (goalsErr) {
1075
- const gmsg = goalsErr instanceof Error ? goalsErr.message : String(goalsErr);
1076
- log7(`render-context-block: goals unavailable (continuing): ${gmsg}`);
1092
+ if (tableExists && !tableExists(input.goalsTable)) {
1093
+ log7(`render-context-block: goals table "${input.goalsTable}" not present \u2014 skipping read`);
1094
+ } else {
1095
+ try {
1096
+ goals = await listOpenGoals(query, input.goalsTable, input.currentUser, {
1097
+ limit: Math.max(maxGoals * 4, maxGoals + 1)
1098
+ });
1099
+ } catch (goalsErr) {
1100
+ const gmsg = goalsErr instanceof Error ? goalsErr.message : String(goalsErr);
1101
+ log7(`render-context-block: goals unavailable (continuing): ${gmsg}`);
1102
+ }
1077
1103
  }
1078
1104
  const rulesShown = rules.slice(0, maxRules);
1079
1105
  const rulesHidden = Math.max(0, rules.length - maxRules);
@@ -1912,21 +1938,25 @@ async function runPull(opts) {
1912
1938
  skillName: opts.skillName
1913
1939
  });
1914
1940
  let rows = [];
1915
- try {
1916
- rows = await opts.query(sql);
1917
- } catch (e) {
1918
- if (isMissingTableError(e?.message)) {
1919
- rows = [];
1920
- } else if (isMissingContributorsColumnError(e?.message)) {
1921
- const legacySql = buildPullSql({
1922
- tableName: opts.tableName,
1923
- users: opts.users,
1924
- skillName: opts.skillName,
1925
- includeContributors: false
1926
- });
1927
- rows = await opts.query(legacySql);
1928
- } else {
1929
- throw e;
1941
+ if (opts.tableExists && !opts.tableExists(opts.tableName)) {
1942
+ rows = [];
1943
+ } else {
1944
+ try {
1945
+ rows = await opts.query(sql);
1946
+ } catch (e) {
1947
+ if (isMissingTableError(e?.message)) {
1948
+ rows = [];
1949
+ } else if (isMissingContributorsColumnError(e?.message)) {
1950
+ const legacySql = buildPullSql({
1951
+ tableName: opts.tableName,
1952
+ users: opts.users,
1953
+ skillName: opts.skillName,
1954
+ includeContributors: false
1955
+ });
1956
+ rows = await opts.query(legacySql);
1957
+ } else {
1958
+ throw e;
1959
+ }
1930
1960
  }
1931
1961
  }
1932
1962
  const latest = selectLatestPerName(rows);
@@ -2069,24 +2099,38 @@ async function autoPullSkills(deps = {}) {
2069
2099
  return { pulled: 0, skipped: true, reason: "not-logged-in" };
2070
2100
  }
2071
2101
  let query;
2102
+ let discoverTableExists = async () => void 0;
2072
2103
  if (deps.queryFn) {
2073
2104
  query = deps.queryFn;
2074
2105
  } else {
2075
2106
  const api = new DeeplakeApi(config.token, config.apiUrl, config.orgId, config.workspaceId, config.skillsTableName);
2076
2107
  query = (sql) => api.query(sql);
2108
+ discoverTableExists = async () => {
2109
+ const known = await api.knownTablesOrNull();
2110
+ return known ? (name) => known.includes(name) : void 0;
2111
+ };
2077
2112
  }
2078
2113
  const install = deps.install ?? "global";
2079
2114
  const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS;
2080
2115
  try {
2081
- const summary = await withTimeout(runPull({
2082
- query,
2083
- tableName: config.skillsTableName,
2084
- install,
2085
- cwd: install === "project" ? deps.cwd ?? process.cwd() : void 0,
2086
- users: [],
2087
- dryRun: false,
2088
- force: false
2089
- }), timeoutMs);
2116
+ const summary = await withTimeout(
2117
+ // Table discovery + pull share one budget: if `GET /tables` hangs the
2118
+ // whole thing times out and we degrade, instead of blocking startup.
2119
+ (async () => {
2120
+ const tableExists = await discoverTableExists();
2121
+ return runPull({
2122
+ query,
2123
+ tableName: config.skillsTableName,
2124
+ install,
2125
+ cwd: install === "project" ? deps.cwd ?? process.cwd() : void 0,
2126
+ users: [],
2127
+ dryRun: false,
2128
+ force: false,
2129
+ tableExists
2130
+ });
2131
+ })(),
2132
+ timeoutMs
2133
+ );
2090
2134
  log5(`pulled scanned=${summary.scanned} wrote=${summary.wrote} skipped=${summary.skipped}`);
2091
2135
  return { pulled: summary.wrote, skipped: false };
2092
2136
  } catch (e) {
@@ -2244,11 +2288,13 @@ async function main() {
2244
2288
  } else {
2245
2289
  log6("placeholder + schema ensure skipped (HIVEMIND_CAPTURE=false)");
2246
2290
  }
2291
+ const known = await api.knownTablesOrNull();
2292
+ const tableExists = known ? (name) => known.includes(name) : void 0;
2247
2293
  rulesBlock = await renderContextBlock((sql) => api.query(sql), {
2248
2294
  rulesTable: config.rulesTableName,
2249
2295
  goalsTable: config.goalsTableName,
2250
2296
  currentUser: config.userName
2251
- }, { log: log6 });
2297
+ }, { log: log6, tableExists });
2252
2298
  }
2253
2299
  } catch (e) {
2254
2300
  log6(`placeholder failed: ${e.message}`);
@@ -67450,6 +67450,23 @@ var DeeplakeApi = class {
67450
67450
  this._tablesCache = [...tables];
67451
67451
  return tables;
67452
67452
  }
67453
+ /**
67454
+ * Like listTables() but returns null when the list could NOT be trusted
67455
+ * (the fetch failed / was non-cacheable). Callers gating a read on table
67456
+ * existence use this to tell a genuinely-empty workspace ([]) apart from a
67457
+ * failed lookup (null): on [] they can safely skip the read (no table → no
67458
+ * 42P01), on null they must fall back to SELECT-then-catch so a transient
67459
+ * lookup blip doesn't drop a read of a table that really exists.
67460
+ */
67461
+ async knownTablesOrNull() {
67462
+ if (this._tablesCache)
67463
+ return [...this._tablesCache];
67464
+ const { tables, cacheable } = await this._fetchTables();
67465
+ if (!cacheable)
67466
+ return null;
67467
+ this._tablesCache = [...tables];
67468
+ return [...tables];
67469
+ }
67453
67470
  async _fetchTables() {
67454
67471
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
67455
67472
  try {
@@ -755,6 +755,23 @@ var DeeplakeApi = class {
755
755
  this._tablesCache = [...tables];
756
756
  return tables;
757
757
  }
758
+ /**
759
+ * Like listTables() but returns null when the list could NOT be trusted
760
+ * (the fetch failed / was non-cacheable). Callers gating a read on table
761
+ * existence use this to tell a genuinely-empty workspace ([]) apart from a
762
+ * failed lookup (null): on [] they can safely skip the read (no table → no
763
+ * 42P01), on null they must fall back to SELECT-then-catch so a transient
764
+ * lookup blip doesn't drop a read of a table that really exists.
765
+ */
766
+ async knownTablesOrNull() {
767
+ if (this._tablesCache)
768
+ return [...this._tablesCache];
769
+ const { tables, cacheable } = await this._fetchTables();
770
+ if (!cacheable)
771
+ return null;
772
+ this._tablesCache = [...tables];
773
+ return [...tables];
774
+ }
758
775
  async _fetchTables() {
759
776
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
760
777
  try {
@@ -1019,6 +1019,23 @@ var DeeplakeApi = class {
1019
1019
  this._tablesCache = [...tables];
1020
1020
  return tables;
1021
1021
  }
1022
+ /**
1023
+ * Like listTables() but returns null when the list could NOT be trusted
1024
+ * (the fetch failed / was non-cacheable). Callers gating a read on table
1025
+ * existence use this to tell a genuinely-empty workspace ([]) apart from a
1026
+ * failed lookup (null): on [] they can safely skip the read (no table → no
1027
+ * 42P01), on null they must fall back to SELECT-then-catch so a transient
1028
+ * lookup blip doesn't drop a read of a table that really exists.
1029
+ */
1030
+ async knownTablesOrNull() {
1031
+ if (this._tablesCache)
1032
+ return [...this._tablesCache];
1033
+ const { tables, cacheable } = await this._fetchTables();
1034
+ if (!cacheable)
1035
+ return null;
1036
+ this._tablesCache = [...tables];
1037
+ return [...tables];
1038
+ }
1022
1039
  async _fetchTables() {
1023
1040
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
1024
1041
  try {
@@ -746,6 +746,23 @@ var DeeplakeApi = class {
746
746
  this._tablesCache = [...tables];
747
747
  return tables;
748
748
  }
749
+ /**
750
+ * Like listTables() but returns null when the list could NOT be trusted
751
+ * (the fetch failed / was non-cacheable). Callers gating a read on table
752
+ * existence use this to tell a genuinely-empty workspace ([]) apart from a
753
+ * failed lookup (null): on [] they can safely skip the read (no table → no
754
+ * 42P01), on null they must fall back to SELECT-then-catch so a transient
755
+ * lookup blip doesn't drop a read of a table that really exists.
756
+ */
757
+ async knownTablesOrNull() {
758
+ if (this._tablesCache)
759
+ return [...this._tablesCache];
760
+ const { tables, cacheable } = await this._fetchTables();
761
+ if (!cacheable)
762
+ return null;
763
+ this._tablesCache = [...tables];
764
+ return [...tables];
765
+ }
749
766
  async _fetchTables() {
750
767
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
751
768
  try {
@@ -755,6 +755,23 @@ var DeeplakeApi = class {
755
755
  this._tablesCache = [...tables];
756
756
  return tables;
757
757
  }
758
+ /**
759
+ * Like listTables() but returns null when the list could NOT be trusted
760
+ * (the fetch failed / was non-cacheable). Callers gating a read on table
761
+ * existence use this to tell a genuinely-empty workspace ([]) apart from a
762
+ * failed lookup (null): on [] they can safely skip the read (no table → no
763
+ * 42P01), on null they must fall back to SELECT-then-catch so a transient
764
+ * lookup blip doesn't drop a read of a table that really exists.
765
+ */
766
+ async knownTablesOrNull() {
767
+ if (this._tablesCache)
768
+ return [...this._tablesCache];
769
+ const { tables, cacheable } = await this._fetchTables();
770
+ if (!cacheable)
771
+ return null;
772
+ this._tablesCache = [...tables];
773
+ return [...tables];
774
+ }
758
775
  async _fetchTables() {
759
776
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
760
777
  try {
@@ -810,6 +810,23 @@ var DeeplakeApi = class {
810
810
  this._tablesCache = [...tables];
811
811
  return tables;
812
812
  }
813
+ /**
814
+ * Like listTables() but returns null when the list could NOT be trusted
815
+ * (the fetch failed / was non-cacheable). Callers gating a read on table
816
+ * existence use this to tell a genuinely-empty workspace ([]) apart from a
817
+ * failed lookup (null): on [] they can safely skip the read (no table → no
818
+ * 42P01), on null they must fall back to SELECT-then-catch so a transient
819
+ * lookup blip doesn't drop a read of a table that really exists.
820
+ */
821
+ async knownTablesOrNull() {
822
+ if (this._tablesCache)
823
+ return [...this._tablesCache];
824
+ const { tables, cacheable } = await this._fetchTables();
825
+ if (!cacheable)
826
+ return null;
827
+ this._tablesCache = [...tables];
828
+ return [...tables];
829
+ }
813
830
  async _fetchTables() {
814
831
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
815
832
  try {
@@ -1055,24 +1072,33 @@ async function renderContextBlock(query, input, opts = {}) {
1055
1072
  const log7 = opts.log ?? (() => {
1056
1073
  });
1057
1074
  try {
1075
+ const tableExists = opts.tableExists;
1058
1076
  let rules = [];
1059
- try {
1060
- rules = await listRules(query, input.rulesTable, {
1061
- status: "active",
1062
- limit: Math.max(maxRules * 4, maxRules + 1)
1063
- });
1064
- } catch (rulesErr) {
1065
- const rmsg = rulesErr instanceof Error ? rulesErr.message : String(rulesErr);
1066
- log7(`render-context-block: rules unavailable (continuing): ${rmsg}`);
1077
+ if (tableExists && !tableExists(input.rulesTable)) {
1078
+ log7(`render-context-block: rules table "${input.rulesTable}" not present \u2014 skipping read`);
1079
+ } else {
1080
+ try {
1081
+ rules = await listRules(query, input.rulesTable, {
1082
+ status: "active",
1083
+ limit: Math.max(maxRules * 4, maxRules + 1)
1084
+ });
1085
+ } catch (rulesErr) {
1086
+ const rmsg = rulesErr instanceof Error ? rulesErr.message : String(rulesErr);
1087
+ log7(`render-context-block: rules unavailable (continuing): ${rmsg}`);
1088
+ }
1067
1089
  }
1068
1090
  let goals = [];
1069
- try {
1070
- goals = await listOpenGoals(query, input.goalsTable, input.currentUser, {
1071
- limit: Math.max(maxGoals * 4, maxGoals + 1)
1072
- });
1073
- } catch (goalsErr) {
1074
- const gmsg = goalsErr instanceof Error ? goalsErr.message : String(goalsErr);
1075
- log7(`render-context-block: goals unavailable (continuing): ${gmsg}`);
1091
+ if (tableExists && !tableExists(input.goalsTable)) {
1092
+ log7(`render-context-block: goals table "${input.goalsTable}" not present \u2014 skipping read`);
1093
+ } else {
1094
+ try {
1095
+ goals = await listOpenGoals(query, input.goalsTable, input.currentUser, {
1096
+ limit: Math.max(maxGoals * 4, maxGoals + 1)
1097
+ });
1098
+ } catch (goalsErr) {
1099
+ const gmsg = goalsErr instanceof Error ? goalsErr.message : String(goalsErr);
1100
+ log7(`render-context-block: goals unavailable (continuing): ${gmsg}`);
1101
+ }
1076
1102
  }
1077
1103
  const rulesShown = rules.slice(0, maxRules);
1078
1104
  const rulesHidden = Math.max(0, rules.length - maxRules);
@@ -1911,21 +1937,25 @@ async function runPull(opts) {
1911
1937
  skillName: opts.skillName
1912
1938
  });
1913
1939
  let rows = [];
1914
- try {
1915
- rows = await opts.query(sql);
1916
- } catch (e) {
1917
- if (isMissingTableError(e?.message)) {
1918
- rows = [];
1919
- } else if (isMissingContributorsColumnError(e?.message)) {
1920
- const legacySql = buildPullSql({
1921
- tableName: opts.tableName,
1922
- users: opts.users,
1923
- skillName: opts.skillName,
1924
- includeContributors: false
1925
- });
1926
- rows = await opts.query(legacySql);
1927
- } else {
1928
- throw e;
1940
+ if (opts.tableExists && !opts.tableExists(opts.tableName)) {
1941
+ rows = [];
1942
+ } else {
1943
+ try {
1944
+ rows = await opts.query(sql);
1945
+ } catch (e) {
1946
+ if (isMissingTableError(e?.message)) {
1947
+ rows = [];
1948
+ } else if (isMissingContributorsColumnError(e?.message)) {
1949
+ const legacySql = buildPullSql({
1950
+ tableName: opts.tableName,
1951
+ users: opts.users,
1952
+ skillName: opts.skillName,
1953
+ includeContributors: false
1954
+ });
1955
+ rows = await opts.query(legacySql);
1956
+ } else {
1957
+ throw e;
1958
+ }
1929
1959
  }
1930
1960
  }
1931
1961
  const latest = selectLatestPerName(rows);
@@ -2068,24 +2098,38 @@ async function autoPullSkills(deps = {}) {
2068
2098
  return { pulled: 0, skipped: true, reason: "not-logged-in" };
2069
2099
  }
2070
2100
  let query;
2101
+ let discoverTableExists = async () => void 0;
2071
2102
  if (deps.queryFn) {
2072
2103
  query = deps.queryFn;
2073
2104
  } else {
2074
2105
  const api = new DeeplakeApi(config.token, config.apiUrl, config.orgId, config.workspaceId, config.skillsTableName);
2075
2106
  query = (sql) => api.query(sql);
2107
+ discoverTableExists = async () => {
2108
+ const known = await api.knownTablesOrNull();
2109
+ return known ? (name) => known.includes(name) : void 0;
2110
+ };
2076
2111
  }
2077
2112
  const install = deps.install ?? "global";
2078
2113
  const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS;
2079
2114
  try {
2080
- const summary = await withTimeout(runPull({
2081
- query,
2082
- tableName: config.skillsTableName,
2083
- install,
2084
- cwd: install === "project" ? deps.cwd ?? process.cwd() : void 0,
2085
- users: [],
2086
- dryRun: false,
2087
- force: false
2088
- }), timeoutMs);
2115
+ const summary = await withTimeout(
2116
+ // Table discovery + pull share one budget: if `GET /tables` hangs the
2117
+ // whole thing times out and we degrade, instead of blocking startup.
2118
+ (async () => {
2119
+ const tableExists = await discoverTableExists();
2120
+ return runPull({
2121
+ query,
2122
+ tableName: config.skillsTableName,
2123
+ install,
2124
+ cwd: install === "project" ? deps.cwd ?? process.cwd() : void 0,
2125
+ users: [],
2126
+ dryRun: false,
2127
+ force: false,
2128
+ tableExists
2129
+ });
2130
+ })(),
2131
+ timeoutMs
2132
+ );
2089
2133
  log5(`pulled scanned=${summary.scanned} wrote=${summary.wrote} skipped=${summary.skipped}`);
2090
2134
  return { pulled: summary.wrote, skipped: false };
2091
2135
  } catch (e) {
@@ -2229,11 +2273,13 @@ async function main() {
2229
2273
  } else {
2230
2274
  log6("placeholder + schema ensure skipped (HIVEMIND_CAPTURE=false)");
2231
2275
  }
2276
+ const known = await api.knownTablesOrNull();
2277
+ const tableExists = known ? (name) => known.includes(name) : void 0;
2232
2278
  rulesBlock = await renderContextBlock((sql) => api.query(sql), {
2233
2279
  rulesTable: config.rulesTableName,
2234
2280
  goalsTable: config.goalsTableName,
2235
2281
  currentUser: config.userName
2236
- }, { log: log6 });
2282
+ }, { log: log6, tableExists });
2237
2283
  }
2238
2284
  } catch (e) {
2239
2285
  log6(`placeholder failed: ${e.message}`);
@@ -67450,6 +67450,23 @@ var DeeplakeApi = class {
67450
67450
  this._tablesCache = [...tables];
67451
67451
  return tables;
67452
67452
  }
67453
+ /**
67454
+ * Like listTables() but returns null when the list could NOT be trusted
67455
+ * (the fetch failed / was non-cacheable). Callers gating a read on table
67456
+ * existence use this to tell a genuinely-empty workspace ([]) apart from a
67457
+ * failed lookup (null): on [] they can safely skip the read (no table → no
67458
+ * 42P01), on null they must fall back to SELECT-then-catch so a transient
67459
+ * lookup blip doesn't drop a read of a table that really exists.
67460
+ */
67461
+ async knownTablesOrNull() {
67462
+ if (this._tablesCache)
67463
+ return [...this._tablesCache];
67464
+ const { tables, cacheable } = await this._fetchTables();
67465
+ if (!cacheable)
67466
+ return null;
67467
+ this._tablesCache = [...tables];
67468
+ return [...tables];
67469
+ }
67453
67470
  async _fetchTables() {
67454
67471
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
67455
67472
  try {
@@ -23961,6 +23961,23 @@ var DeeplakeApi = class {
23961
23961
  this._tablesCache = [...tables];
23962
23962
  return tables;
23963
23963
  }
23964
+ /**
23965
+ * Like listTables() but returns null when the list could NOT be trusted
23966
+ * (the fetch failed / was non-cacheable). Callers gating a read on table
23967
+ * existence use this to tell a genuinely-empty workspace ([]) apart from a
23968
+ * failed lookup (null): on [] they can safely skip the read (no table → no
23969
+ * 42P01), on null they must fall back to SELECT-then-catch so a transient
23970
+ * lookup blip doesn't drop a read of a table that really exists.
23971
+ */
23972
+ async knownTablesOrNull() {
23973
+ if (this._tablesCache)
23974
+ return [...this._tablesCache];
23975
+ const { tables, cacheable } = await this._fetchTables();
23976
+ if (!cacheable)
23977
+ return null;
23978
+ this._tablesCache = [...tables];
23979
+ return [...tables];
23980
+ }
23964
23981
  async _fetchTables() {
23965
23982
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
23966
23983
  try {
@@ -772,6 +772,21 @@ var DeeplakeApi = class {
772
772
  if (cacheable) this._tablesCache = [...tables];
773
773
  return tables;
774
774
  }
775
+ /**
776
+ * Like listTables() but returns null when the list could NOT be trusted
777
+ * (the fetch failed / was non-cacheable). Callers gating a read on table
778
+ * existence use this to tell a genuinely-empty workspace ([]) apart from a
779
+ * failed lookup (null): on [] they can safely skip the read (no table → no
780
+ * 42P01), on null they must fall back to SELECT-then-catch so a transient
781
+ * lookup blip doesn't drop a read of a table that really exists.
782
+ */
783
+ async knownTablesOrNull() {
784
+ if (this._tablesCache) return [...this._tablesCache];
785
+ const { tables, cacheable } = await this._fetchTables();
786
+ if (!cacheable) return null;
787
+ this._tablesCache = [...tables];
788
+ return [...tables];
789
+ }
775
790
  async _fetchTables() {
776
791
  for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
777
792
  try {
@@ -1780,7 +1795,7 @@ function extractLatestVersion(body) {
1780
1795
  return typeof v === "string" && v.length > 0 ? v : null;
1781
1796
  }
1782
1797
  function getInstalledVersion() {
1783
- return "0.7.54".length > 0 ? "0.7.54" : null;
1798
+ return "0.7.61".length > 0 ? "0.7.61" : null;
1784
1799
  }
1785
1800
  function isNewer(latest, current) {
1786
1801
  const parse = (v) => v.replace(/-.*$/, "").split(".").map(Number);
@@ -54,5 +54,5 @@
54
54
  }
55
55
  }
56
56
  },
57
- "version": "0.7.54"
57
+ "version": "0.7.61"
58
58
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hivemind",
3
- "version": "0.7.54",
3
+ "version": "0.7.61",
4
4
  "type": "module",
5
5
  "description": "Hivemind — cloud-backed persistent shared memory for AI agents, powered by DeepLake",
6
6
  "license": "Apache-2.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deeplake/hivemind",
3
- "version": "0.7.54",
3
+ "version": "0.7.61",
4
4
  "description": "Cloud-backed persistent shared memory for AI agents powered by Deeplake",
5
5
  "type": "module",
6
6
  "repository": {
@@ -26,6 +26,7 @@
26
26
  "openclaw/openclaw.plugin.json",
27
27
  "openclaw/package.json",
28
28
  ".claude-plugin",
29
+ "scripts",
29
30
  "README.md",
30
31
  "LICENSE"
31
32
  ],
@@ -41,7 +42,9 @@
41
42
  "dup": "jscpd src",
42
43
  "audit:openclaw": "node scripts/audit-openclaw-bundle.mjs",
43
44
  "pack:check": "node scripts/pack-check.mjs",
45
+ "rebuild:native": "node scripts/ensure-tree-sitter.mjs",
44
46
  "ci": "npm run typecheck && npm run dup && npm test",
47
+ "postinstall": "node scripts/ensure-tree-sitter.mjs",
45
48
  "prepare": "husky && npm run build",
46
49
  "prepack": "npm run build"
47
50
  },
@@ -58,11 +61,13 @@
58
61
  "deeplake": "^0.3.30",
59
62
  "js-yaml": "^4.1.1",
60
63
  "just-bash": "^2.14.0",
61
- "tree-sitter": "^0.21.1",
62
- "tree-sitter-typescript": "^0.23.2",
63
64
  "yargs-parser": "^22.0.0",
64
65
  "zod": "^4.3.6"
65
66
  },
67
+ "optionalDependencies": {
68
+ "tree-sitter": "^0.21.1",
69
+ "tree-sitter-typescript": "^0.23.2"
70
+ },
66
71
  "devDependencies": {
67
72
  "@types/js-yaml": "^4.0.9",
68
73
  "@types/node": "^25.0.0",