@deeplake/hivemind 0.7.79 → 0.7.81
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 +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/bundle/cli.js +140 -94
- package/codex/bundle/capture.js +232 -72
- package/codex/bundle/commands/auth-login.js +14 -10
- package/codex/bundle/embeddings/embed-daemon.js +9 -5
- package/codex/bundle/graph-on-stop.js +32 -28
- package/codex/bundle/graph-pull-worker.js +27 -23
- package/codex/bundle/pre-tool-use.js +366 -123
- package/codex/bundle/session-start-setup.js +18 -14
- package/codex/bundle/session-start.js +26 -22
- package/codex/bundle/shell/deeplake-shell.js +30 -26
- package/codex/bundle/skillify-worker.js +14 -10
- package/codex/bundle/skillopt-worker.js +2061 -0
- package/codex/bundle/stop.js +50 -45
- package/codex/bundle/wiki-worker.js +18 -14
- package/cursor/bundle/capture.js +71 -44
- package/cursor/bundle/commands/auth-login.js +14 -10
- package/cursor/bundle/embeddings/embed-daemon.js +9 -5
- package/cursor/bundle/graph-on-stop.js +32 -28
- package/cursor/bundle/graph-pull-worker.js +27 -23
- package/cursor/bundle/pre-tool-use.js +28 -24
- package/cursor/bundle/session-end.js +40 -36
- package/cursor/bundle/session-start.js +39 -35
- package/cursor/bundle/shell/deeplake-shell.js +30 -26
- package/cursor/bundle/skillify-worker.js +14 -10
- package/cursor/bundle/wiki-worker.js +18 -14
- package/hermes/bundle/capture.js +235 -85
- package/hermes/bundle/commands/auth-login.js +14 -10
- package/hermes/bundle/embeddings/embed-daemon.js +9 -5
- package/hermes/bundle/graph-on-stop.js +32 -28
- package/hermes/bundle/graph-pull-worker.js +27 -23
- package/hermes/bundle/pre-tool-use.js +298 -74
- package/hermes/bundle/session-end.js +40 -36
- package/hermes/bundle/session-start.js +39 -35
- package/hermes/bundle/shell/deeplake-shell.js +30 -26
- package/hermes/bundle/skillify-worker.js +14 -10
- package/hermes/bundle/skillopt-worker.js +2061 -0
- package/hermes/bundle/wiki-worker.js +18 -14
- package/mcp/bundle/server.js +15 -11
- package/openclaw/dist/index.js +11 -7
- package/openclaw/dist/skillify-worker.js +14 -10
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/package.json +1 -1
- package/pi/extension-source/hivemind.ts +93 -0
|
@@ -17,7 +17,7 @@ __export(index_marker_store_exports, {
|
|
|
17
17
|
hasFreshIndexMarker: () => hasFreshIndexMarker,
|
|
18
18
|
writeIndexMarker: () => writeIndexMarker
|
|
19
19
|
});
|
|
20
|
-
import { existsSync as existsSync2, mkdirSync as
|
|
20
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
21
21
|
import { join as join5 } from "node:path";
|
|
22
22
|
import { tmpdir } from "node:os";
|
|
23
23
|
function getIndexMarkerDir() {
|
|
@@ -41,7 +41,7 @@ function hasFreshIndexMarker(markerPath) {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
function writeIndexMarker(markerPath) {
|
|
44
|
-
|
|
44
|
+
mkdirSync4(getIndexMarkerDir(), { recursive: true });
|
|
45
45
|
writeFileSync3(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
|
|
46
46
|
}
|
|
47
47
|
var INDEX_MARKER_TTL_MS;
|
|
@@ -52,6 +52,11 @@ var init_index_marker_store = __esm({
|
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
+
// dist/src/hooks/codex/pre-tool-use.js
|
|
56
|
+
import { join as join19, dirname as dirname10 } from "node:path";
|
|
57
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
58
|
+
import { spawnSync } from "node:child_process";
|
|
59
|
+
|
|
55
60
|
// dist/src/utils/stdin.js
|
|
56
61
|
function readStdin() {
|
|
57
62
|
return new Promise((resolve4, reject) => {
|
|
@@ -120,8 +125,8 @@ function loadConfig() {
|
|
|
120
125
|
import { randomUUID } from "node:crypto";
|
|
121
126
|
|
|
122
127
|
// dist/src/utils/debug.js
|
|
123
|
-
import { appendFileSync } from "node:fs";
|
|
124
|
-
import { join as join2 } from "node:path";
|
|
128
|
+
import { appendFileSync, mkdirSync } from "node:fs";
|
|
129
|
+
import { dirname, join as join2 } from "node:path";
|
|
125
130
|
import { homedir as homedir2 } from "node:os";
|
|
126
131
|
var LOG = join2(homedir2(), ".deeplake", "hook-debug.log");
|
|
127
132
|
function isDebug() {
|
|
@@ -130,8 +135,12 @@ function isDebug() {
|
|
|
130
135
|
function log(tag, msg) {
|
|
131
136
|
if (!isDebug())
|
|
132
137
|
return;
|
|
133
|
-
|
|
138
|
+
try {
|
|
139
|
+
mkdirSync(dirname(LOG), { recursive: true });
|
|
140
|
+
appendFileSync(LOG, `${(/* @__PURE__ */ new Date()).toISOString()} [${tag}] ${msg}
|
|
134
141
|
`);
|
|
142
|
+
} catch {
|
|
143
|
+
}
|
|
135
144
|
}
|
|
136
145
|
|
|
137
146
|
// dist/src/utils/sql.js
|
|
@@ -340,7 +349,7 @@ async function healMissingColumns(args) {
|
|
|
340
349
|
}
|
|
341
350
|
|
|
342
351
|
// dist/src/notifications/queue.js
|
|
343
|
-
import { readFileSync as readFileSync2, writeFileSync, renameSync, mkdirSync, openSync, closeSync, unlinkSync, statSync } from "node:fs";
|
|
352
|
+
import { readFileSync as readFileSync2, writeFileSync, renameSync, mkdirSync as mkdirSync2, openSync, closeSync, unlinkSync, statSync } from "node:fs";
|
|
344
353
|
import { join as join3, resolve } from "node:path";
|
|
345
354
|
import { homedir as homedir3 } from "node:os";
|
|
346
355
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
@@ -367,38 +376,38 @@ function readQueue() {
|
|
|
367
376
|
return { queue: [] };
|
|
368
377
|
}
|
|
369
378
|
}
|
|
370
|
-
function _isQueuePathInsideHome(
|
|
371
|
-
const r = resolve(
|
|
379
|
+
function _isQueuePathInsideHome(path2, home) {
|
|
380
|
+
const r = resolve(path2);
|
|
372
381
|
const h = resolve(home);
|
|
373
382
|
return r.startsWith(h + "/") || r === h;
|
|
374
383
|
}
|
|
375
384
|
function writeQueue(q) {
|
|
376
|
-
const
|
|
385
|
+
const path2 = queuePath();
|
|
377
386
|
const home = resolve(homedir3());
|
|
378
|
-
if (!_isQueuePathInsideHome(
|
|
379
|
-
throw new Error(`notifications-queue write blocked: ${
|
|
387
|
+
if (!_isQueuePathInsideHome(path2, home)) {
|
|
388
|
+
throw new Error(`notifications-queue write blocked: ${path2} is outside ${home}`);
|
|
380
389
|
}
|
|
381
|
-
|
|
382
|
-
const tmp = `${
|
|
390
|
+
mkdirSync2(join3(home, ".deeplake"), { recursive: true, mode: 448 });
|
|
391
|
+
const tmp = `${path2}.${process.pid}.tmp`;
|
|
383
392
|
writeFileSync(tmp, JSON.stringify(q, null, 2), { mode: 384 });
|
|
384
|
-
renameSync(tmp,
|
|
393
|
+
renameSync(tmp, path2);
|
|
385
394
|
}
|
|
386
395
|
async function withQueueLock(fn) {
|
|
387
|
-
const
|
|
388
|
-
|
|
396
|
+
const path2 = lockPath();
|
|
397
|
+
mkdirSync2(join3(homedir3(), ".deeplake"), { recursive: true, mode: 448 });
|
|
389
398
|
let fd = null;
|
|
390
399
|
for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
|
|
391
400
|
try {
|
|
392
|
-
fd = openSync(
|
|
401
|
+
fd = openSync(path2, "wx", 384);
|
|
393
402
|
break;
|
|
394
403
|
} catch (e) {
|
|
395
404
|
const code = e.code;
|
|
396
405
|
if (code !== "EEXIST")
|
|
397
406
|
throw e;
|
|
398
407
|
try {
|
|
399
|
-
const age = Date.now() - statSync(
|
|
408
|
+
const age = Date.now() - statSync(path2).mtimeMs;
|
|
400
409
|
if (age > LOCK_STALE_MS) {
|
|
401
|
-
unlinkSync(
|
|
410
|
+
unlinkSync(path2);
|
|
402
411
|
continue;
|
|
403
412
|
}
|
|
404
413
|
} catch {
|
|
@@ -419,7 +428,7 @@ async function withQueueLock(fn) {
|
|
|
419
428
|
} catch {
|
|
420
429
|
}
|
|
421
430
|
try {
|
|
422
|
-
unlinkSync(
|
|
431
|
+
unlinkSync(path2);
|
|
423
432
|
} catch {
|
|
424
433
|
}
|
|
425
434
|
}
|
|
@@ -441,7 +450,7 @@ async function enqueueNotification(n) {
|
|
|
441
450
|
}
|
|
442
451
|
|
|
443
452
|
// dist/src/commands/auth-creds.js
|
|
444
|
-
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as
|
|
453
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, unlinkSync as unlinkSync2 } from "node:fs";
|
|
445
454
|
import { join as join4 } from "node:path";
|
|
446
455
|
import { homedir as homedir4 } from "node:os";
|
|
447
456
|
function configDir() {
|
|
@@ -695,9 +704,9 @@ var DeeplakeApi = class {
|
|
|
695
704
|
}
|
|
696
705
|
}
|
|
697
706
|
/** Update specific columns on a row by path. */
|
|
698
|
-
async updateColumns(
|
|
707
|
+
async updateColumns(path2, columns) {
|
|
699
708
|
const setClauses = Object.entries(columns).map(([col, val]) => typeof val === "number" ? `${col} = ${val}` : `${col} = '${sqlStr(String(val))}'`).join(", ");
|
|
700
|
-
await this.query(`UPDATE "${this.tableName}" SET ${setClauses} WHERE path = '${sqlStr(
|
|
709
|
+
await this.query(`UPDATE "${this.tableName}" SET ${setClauses} WHERE path = '${sqlStr(path2)}'`);
|
|
701
710
|
}
|
|
702
711
|
// ── Convenience ─────────────────────────────────────────────────────────────
|
|
703
712
|
/** Create a BM25 search index on a column. */
|
|
@@ -1129,8 +1138,8 @@ function formatToolCall(obj) {
|
|
|
1129
1138
|
input: ${formatToolInput(obj?.tool_input)}
|
|
1130
1139
|
response: ${formatToolResponse(obj?.tool_response, obj?.tool_input, obj?.tool_name)}`;
|
|
1131
1140
|
}
|
|
1132
|
-
function normalizeContent(
|
|
1133
|
-
if (!
|
|
1141
|
+
function normalizeContent(path2, raw) {
|
|
1142
|
+
if (!path2.includes("/sessions/"))
|
|
1134
1143
|
return raw;
|
|
1135
1144
|
if (!raw || raw[0] !== "{")
|
|
1136
1145
|
return raw;
|
|
@@ -1848,22 +1857,22 @@ import { join as join8 } from "node:path";
|
|
|
1848
1857
|
import { pathToFileURL } from "node:url";
|
|
1849
1858
|
|
|
1850
1859
|
// dist/src/user-config.js
|
|
1851
|
-
import { existsSync as existsSync4, mkdirSync as
|
|
1860
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync6, renameSync as renameSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
1852
1861
|
import { homedir as homedir6 } from "node:os";
|
|
1853
|
-
import { dirname, join as join7 } from "node:path";
|
|
1862
|
+
import { dirname as dirname2, join as join7 } from "node:path";
|
|
1854
1863
|
var _configPath = () => process.env.HIVEMIND_CONFIG_PATH ?? join7(homedir6(), ".deeplake", "config.json");
|
|
1855
1864
|
var _cache = null;
|
|
1856
1865
|
var _migrated = false;
|
|
1857
1866
|
function readUserConfig() {
|
|
1858
1867
|
if (_cache !== null)
|
|
1859
1868
|
return _cache;
|
|
1860
|
-
const
|
|
1861
|
-
if (!existsSync4(
|
|
1869
|
+
const path2 = _configPath();
|
|
1870
|
+
if (!existsSync4(path2)) {
|
|
1862
1871
|
_cache = {};
|
|
1863
1872
|
return _cache;
|
|
1864
1873
|
}
|
|
1865
1874
|
try {
|
|
1866
|
-
const raw = readFileSync6(
|
|
1875
|
+
const raw = readFileSync6(path2, "utf-8");
|
|
1867
1876
|
const parsed = JSON.parse(raw);
|
|
1868
1877
|
_cache = isPlainObject(parsed) ? parsed : {};
|
|
1869
1878
|
} catch {
|
|
@@ -1874,13 +1883,13 @@ function readUserConfig() {
|
|
|
1874
1883
|
function writeUserConfig(patch) {
|
|
1875
1884
|
const current = readUserConfig();
|
|
1876
1885
|
const merged = deepMerge(current, patch);
|
|
1877
|
-
const
|
|
1878
|
-
const dir =
|
|
1886
|
+
const path2 = _configPath();
|
|
1887
|
+
const dir = dirname2(path2);
|
|
1879
1888
|
if (!existsSync4(dir))
|
|
1880
|
-
|
|
1881
|
-
const tmp = `${
|
|
1889
|
+
mkdirSync5(dir, { recursive: true });
|
|
1890
|
+
const tmp = `${path2}.tmp.${process.pid}`;
|
|
1882
1891
|
writeFileSync4(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
1883
|
-
renameSync2(tmp,
|
|
1892
|
+
renameSync2(tmp, path2);
|
|
1884
1893
|
_cache = merged;
|
|
1885
1894
|
return merged;
|
|
1886
1895
|
}
|
|
@@ -1961,11 +1970,11 @@ function embeddingsDisabled() {
|
|
|
1961
1970
|
|
|
1962
1971
|
// dist/src/hooks/grep-direct.js
|
|
1963
1972
|
import { fileURLToPath } from "node:url";
|
|
1964
|
-
import { dirname as
|
|
1973
|
+
import { dirname as dirname3, join as join9 } from "node:path";
|
|
1965
1974
|
var SEMANTIC_ENABLED = process.env.HIVEMIND_SEMANTIC_SEARCH !== "false" && !embeddingsDisabled();
|
|
1966
1975
|
var SEMANTIC_TIMEOUT_MS = Number(process.env.HIVEMIND_SEMANTIC_EMBED_TIMEOUT_MS ?? "500");
|
|
1967
1976
|
function resolveDaemonPath() {
|
|
1968
|
-
return join9(
|
|
1977
|
+
return join9(dirname3(fileURLToPath(import.meta.url)), "..", "embeddings", "embed-daemon.js");
|
|
1969
1978
|
}
|
|
1970
1979
|
var sharedEmbedClient = null;
|
|
1971
1980
|
function getEmbedClient() {
|
|
@@ -2318,13 +2327,13 @@ async function handleGrepDirect(api, table, sessionsTable, params) {
|
|
|
2318
2327
|
}
|
|
2319
2328
|
|
|
2320
2329
|
// dist/src/graph/vfs-handler.js
|
|
2321
|
-
import { existsSync as existsSync7, mkdirSync as
|
|
2330
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync9, readFileSync as readFileSync9, renameSync as renameSync5, writeFileSync as writeFileSync7 } from "node:fs";
|
|
2322
2331
|
import { createHash as createHash3 } from "node:crypto";
|
|
2323
|
-
import { join as join13, dirname as
|
|
2332
|
+
import { join as join13, dirname as dirname7 } from "node:path";
|
|
2324
2333
|
|
|
2325
2334
|
// dist/src/graph/last-build.js
|
|
2326
|
-
import { existsSync as existsSync5, mkdirSync as
|
|
2327
|
-
import { dirname as
|
|
2335
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync6, readFileSync as readFileSync7, renameSync as renameSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
2336
|
+
import { dirname as dirname4, join as join10 } from "node:path";
|
|
2328
2337
|
function lastBuildPath(baseDir, worktreeId) {
|
|
2329
2338
|
if (worktreeId !== void 0) {
|
|
2330
2339
|
return join10(baseDir, "worktrees", worktreeId, ".last-build.json");
|
|
@@ -2332,18 +2341,18 @@ function lastBuildPath(baseDir, worktreeId) {
|
|
|
2332
2341
|
return join10(baseDir, ".last-build.json");
|
|
2333
2342
|
}
|
|
2334
2343
|
function readLastBuild(baseDir, worktreeId) {
|
|
2335
|
-
let
|
|
2336
|
-
if (!existsSync5(
|
|
2344
|
+
let path2 = lastBuildPath(baseDir, worktreeId);
|
|
2345
|
+
if (!existsSync5(path2)) {
|
|
2337
2346
|
if (worktreeId === void 0)
|
|
2338
2347
|
return null;
|
|
2339
2348
|
const legacy = lastBuildPath(baseDir, void 0);
|
|
2340
2349
|
if (!existsSync5(legacy))
|
|
2341
2350
|
return null;
|
|
2342
|
-
|
|
2351
|
+
path2 = legacy;
|
|
2343
2352
|
}
|
|
2344
2353
|
let raw;
|
|
2345
2354
|
try {
|
|
2346
|
-
raw = readFileSync7(
|
|
2355
|
+
raw = readFileSync7(path2, "utf8");
|
|
2347
2356
|
} catch {
|
|
2348
2357
|
return null;
|
|
2349
2358
|
}
|
|
@@ -2374,13 +2383,13 @@ function readLastBuild(baseDir, worktreeId) {
|
|
|
2374
2383
|
|
|
2375
2384
|
// dist/src/graph/snapshot.js
|
|
2376
2385
|
import { createHash } from "node:crypto";
|
|
2377
|
-
import { mkdirSync as
|
|
2386
|
+
import { mkdirSync as mkdirSync8, renameSync as renameSync4, writeFileSync as writeFileSync6 } from "node:fs";
|
|
2378
2387
|
import { homedir as homedir8 } from "node:os";
|
|
2379
|
-
import { dirname as
|
|
2388
|
+
import { dirname as dirname6, join as join12 } from "node:path";
|
|
2380
2389
|
|
|
2381
2390
|
// dist/src/graph/history.js
|
|
2382
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync6, mkdirSync as
|
|
2383
|
-
import { dirname as
|
|
2391
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync7, readFileSync as readFileSync8 } from "node:fs";
|
|
2392
|
+
import { dirname as dirname5, join as join11 } from "node:path";
|
|
2384
2393
|
|
|
2385
2394
|
// dist/src/graph/resolve/cross-file.js
|
|
2386
2395
|
import { posix } from "node:path";
|
|
@@ -2952,18 +2961,18 @@ function workTreeIdFor(cwd) {
|
|
|
2952
2961
|
return createHash3("sha256").update(cwd).digest("hex").slice(0, 16);
|
|
2953
2962
|
}
|
|
2954
2963
|
function handleGraphVfs(subpath, cwd) {
|
|
2955
|
-
const
|
|
2956
|
-
if (
|
|
2964
|
+
const path2 = subpath.replace(/^\/+/, "");
|
|
2965
|
+
if (path2 === "" || path2 === "/") {
|
|
2957
2966
|
return { kind: "ok", body: dirListing() };
|
|
2958
2967
|
}
|
|
2959
|
-
if (
|
|
2968
|
+
if (path2 === "index.md" || path2 === "index") {
|
|
2960
2969
|
return loadSnapshotOrError(cwd, (snap, baseDir) => ({
|
|
2961
2970
|
kind: "ok",
|
|
2962
2971
|
body: renderIndex(snap, baseDir, cwd)
|
|
2963
2972
|
}));
|
|
2964
2973
|
}
|
|
2965
|
-
if (
|
|
2966
|
-
const pattern =
|
|
2974
|
+
if (path2.startsWith("find/")) {
|
|
2975
|
+
const pattern = path2.slice("find/".length);
|
|
2967
2976
|
if (pattern === "") {
|
|
2968
2977
|
return { kind: "not-found", message: "find/ requires a pattern: cat memory/graph/find/<keyword>" };
|
|
2969
2978
|
}
|
|
@@ -2972,8 +2981,8 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
2972
2981
|
body: renderFind(snap, pattern, baseDir, workTreeIdFor(cwd))
|
|
2973
2982
|
}));
|
|
2974
2983
|
}
|
|
2975
|
-
if (
|
|
2976
|
-
const key =
|
|
2984
|
+
if (path2.startsWith("show/")) {
|
|
2985
|
+
const key = path2.slice("show/".length);
|
|
2977
2986
|
if (key === "") {
|
|
2978
2987
|
return { kind: "not-found", message: "show/ requires a handle or pattern" };
|
|
2979
2988
|
}
|
|
@@ -2982,8 +2991,8 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
2982
2991
|
body: renderShow(snap, key, baseDir, workTreeIdFor(cwd))
|
|
2983
2992
|
}));
|
|
2984
2993
|
}
|
|
2985
|
-
if (
|
|
2986
|
-
const pattern =
|
|
2994
|
+
if (path2.startsWith("query/")) {
|
|
2995
|
+
const pattern = path2.slice("query/".length);
|
|
2987
2996
|
if (pattern === "") {
|
|
2988
2997
|
return { kind: "not-found", message: "query/ requires a pattern: cat memory/graph/query/<keyword>" };
|
|
2989
2998
|
}
|
|
@@ -2992,28 +3001,28 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
2992
3001
|
body: renderQuery(snap, pattern, baseDir, workTreeIdFor(cwd))
|
|
2993
3002
|
}));
|
|
2994
3003
|
}
|
|
2995
|
-
if (
|
|
2996
|
-
const pattern =
|
|
3004
|
+
if (path2.startsWith("impact/")) {
|
|
3005
|
+
const pattern = path2.slice("impact/".length);
|
|
2997
3006
|
if (pattern === "") {
|
|
2998
3007
|
return { kind: "not-found", message: "impact/ requires a pattern: cat memory/graph/impact/<symbol>" };
|
|
2999
3008
|
}
|
|
3000
3009
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderImpact(snap, pattern) }));
|
|
3001
3010
|
}
|
|
3002
|
-
if (
|
|
3003
|
-
const file =
|
|
3011
|
+
if (path2.startsWith("neighborhood/")) {
|
|
3012
|
+
const file = path2.slice("neighborhood/".length);
|
|
3004
3013
|
if (file === "") {
|
|
3005
3014
|
return { kind: "not-found", message: "neighborhood/ requires a file path: cat memory/graph/neighborhood/<file>" };
|
|
3006
3015
|
}
|
|
3007
3016
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderNeighborhood(snap, file) }));
|
|
3008
3017
|
}
|
|
3009
|
-
if (
|
|
3018
|
+
if (path2 === "layers" || path2 === "layers/" || path2 === "layers/index.md") {
|
|
3010
3019
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderLayers(snap) }));
|
|
3011
3020
|
}
|
|
3012
|
-
if (
|
|
3021
|
+
if (path2 === "tour" || path2 === "tour/" || path2 === "tour/index.md") {
|
|
3013
3022
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderTour(snap) }));
|
|
3014
3023
|
}
|
|
3015
|
-
if (
|
|
3016
|
-
const rest =
|
|
3024
|
+
if (path2.startsWith("path/")) {
|
|
3025
|
+
const rest = path2.slice("path/".length);
|
|
3017
3026
|
const slash = rest.indexOf("/");
|
|
3018
3027
|
if (slash <= 0 || slash === rest.length - 1) {
|
|
3019
3028
|
return { kind: "not-found", message: "path/ needs two patterns: cat memory/graph/path/<from>/<to> (each a symbol-name substring, no slash)" };
|
|
@@ -3024,7 +3033,7 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
3024
3033
|
}
|
|
3025
3034
|
return {
|
|
3026
3035
|
kind: "not-found",
|
|
3027
|
-
message: `Unknown endpoint: graph/${
|
|
3036
|
+
message: `Unknown endpoint: graph/${path2}
|
|
3028
3037
|
Available: index.md, find/<pattern>, query/<pattern>, show/<handle-or-pattern>, impact/<pattern>, neighborhood/<file>, layers, tour, path/<from>/<to>`
|
|
3029
3038
|
};
|
|
3030
3039
|
}
|
|
@@ -3423,22 +3432,22 @@ function handlesPath(baseDir, worktreeId) {
|
|
|
3423
3432
|
return join13(baseDir, "worktrees", worktreeId, ".find-handles.json");
|
|
3424
3433
|
}
|
|
3425
3434
|
function saveHandles(baseDir, worktreeId, ids, pattern) {
|
|
3426
|
-
const
|
|
3435
|
+
const path2 = handlesPath(baseDir, worktreeId);
|
|
3427
3436
|
const payload = { pattern, ts: Date.now(), ids };
|
|
3428
3437
|
try {
|
|
3429
|
-
|
|
3430
|
-
const tmp = `${
|
|
3438
|
+
mkdirSync9(dirname7(path2), { recursive: true });
|
|
3439
|
+
const tmp = `${path2}.tmp.${process.pid}.${Date.now()}`;
|
|
3431
3440
|
writeFileSync7(tmp, JSON.stringify(payload));
|
|
3432
|
-
renameSync5(tmp,
|
|
3441
|
+
renameSync5(tmp, path2);
|
|
3433
3442
|
} catch {
|
|
3434
3443
|
}
|
|
3435
3444
|
}
|
|
3436
3445
|
function loadHandles(baseDir, worktreeId) {
|
|
3437
|
-
const
|
|
3438
|
-
if (!existsSync7(
|
|
3446
|
+
const path2 = handlesPath(baseDir, worktreeId);
|
|
3447
|
+
if (!existsSync7(path2))
|
|
3439
3448
|
return null;
|
|
3440
3449
|
try {
|
|
3441
|
-
const parsed = JSON.parse(readFileSync9(
|
|
3450
|
+
const parsed = JSON.parse(readFileSync9(path2, "utf8"));
|
|
3442
3451
|
if (parsed === null || typeof parsed !== "object")
|
|
3443
3452
|
return null;
|
|
3444
3453
|
const o = parsed;
|
|
@@ -3529,8 +3538,8 @@ function tryGraphRead(rewrittenCommand, cwd) {
|
|
|
3529
3538
|
}
|
|
3530
3539
|
|
|
3531
3540
|
// dist/src/hooks/virtual-table-query.js
|
|
3532
|
-
function normalizeSessionPart(
|
|
3533
|
-
return normalizeContent(
|
|
3541
|
+
function normalizeSessionPart(path2, content) {
|
|
3542
|
+
return normalizeContent(path2, content);
|
|
3534
3543
|
}
|
|
3535
3544
|
var INDEX_LIMIT_PER_SECTION = 50;
|
|
3536
3545
|
function buildVirtualIndexContent(summaryRows, sessionRows = [], opts = {}) {
|
|
@@ -3597,7 +3606,7 @@ function buildUnionQuery(memoryQuery, sessionsQuery) {
|
|
|
3597
3606
|
return `SELECT path, content, size_bytes, creation_date, source_order FROM ((${memoryQuery}) UNION ALL (${sessionsQuery})) AS combined ORDER BY path, source_order, creation_date`;
|
|
3598
3607
|
}
|
|
3599
3608
|
function buildInList(paths) {
|
|
3600
|
-
return paths.map((
|
|
3609
|
+
return paths.map((path2) => `'${sqlStr(path2)}'`).join(", ");
|
|
3601
3610
|
}
|
|
3602
3611
|
function buildDirFilter(dirs) {
|
|
3603
3612
|
const cleaned = [...new Set(dirs.map((dir) => dir.replace(/\/+$/, "") || "/"))];
|
|
@@ -3620,7 +3629,7 @@ async function queryUnionRows(api, memoryQuery, sessionsQuery) {
|
|
|
3620
3629
|
}
|
|
3621
3630
|
async function readVirtualPathContents(api, memoryTable, sessionsTable, virtualPaths) {
|
|
3622
3631
|
const uniquePaths = [...new Set(virtualPaths)];
|
|
3623
|
-
const result = new Map(uniquePaths.map((
|
|
3632
|
+
const result = new Map(uniquePaths.map((path2) => [path2, null]));
|
|
3624
3633
|
if (uniquePaths.length === 0)
|
|
3625
3634
|
return result;
|
|
3626
3635
|
const inList = buildInList(uniquePaths);
|
|
@@ -3628,27 +3637,27 @@ async function readVirtualPathContents(api, memoryTable, sessionsTable, virtualP
|
|
|
3628
3637
|
const memoryHits = /* @__PURE__ */ new Map();
|
|
3629
3638
|
const sessionHits = /* @__PURE__ */ new Map();
|
|
3630
3639
|
for (const row of rows) {
|
|
3631
|
-
const
|
|
3640
|
+
const path2 = row["path"];
|
|
3632
3641
|
const content = row["content"];
|
|
3633
3642
|
const sourceOrder = Number(row["source_order"] ?? 0);
|
|
3634
|
-
if (typeof
|
|
3643
|
+
if (typeof path2 !== "string" || typeof content !== "string")
|
|
3635
3644
|
continue;
|
|
3636
3645
|
if (sourceOrder === 0) {
|
|
3637
|
-
memoryHits.set(
|
|
3646
|
+
memoryHits.set(path2, content);
|
|
3638
3647
|
} else {
|
|
3639
|
-
const current = sessionHits.get(
|
|
3640
|
-
current.push(normalizeSessionPart(
|
|
3641
|
-
sessionHits.set(
|
|
3648
|
+
const current = sessionHits.get(path2) ?? [];
|
|
3649
|
+
current.push(normalizeSessionPart(path2, content));
|
|
3650
|
+
sessionHits.set(path2, current);
|
|
3642
3651
|
}
|
|
3643
3652
|
}
|
|
3644
|
-
for (const
|
|
3645
|
-
if (memoryHits.has(
|
|
3646
|
-
result.set(
|
|
3653
|
+
for (const path2 of uniquePaths) {
|
|
3654
|
+
if (memoryHits.has(path2)) {
|
|
3655
|
+
result.set(path2, memoryHits.get(path2) ?? null);
|
|
3647
3656
|
continue;
|
|
3648
3657
|
}
|
|
3649
|
-
const sessionParts = sessionHits.get(
|
|
3658
|
+
const sessionParts = sessionHits.get(path2) ?? [];
|
|
3650
3659
|
if (sessionParts.length > 0) {
|
|
3651
|
-
result.set(
|
|
3660
|
+
result.set(path2, sessionParts.join("\n"));
|
|
3652
3661
|
}
|
|
3653
3662
|
}
|
|
3654
3663
|
if (result.get("/index.md") === null && uniquePaths.includes("/index.md")) {
|
|
@@ -3675,12 +3684,12 @@ async function listVirtualPathRowsForDirs(api, memoryTable, sessionsTable, dirs)
|
|
|
3675
3684
|
for (const dir of uniqueDirs)
|
|
3676
3685
|
byDir.set(dir, []);
|
|
3677
3686
|
for (const row of deduped) {
|
|
3678
|
-
const
|
|
3679
|
-
if (typeof
|
|
3687
|
+
const path2 = row["path"];
|
|
3688
|
+
if (typeof path2 !== "string")
|
|
3680
3689
|
continue;
|
|
3681
3690
|
for (const dir of uniqueDirs) {
|
|
3682
3691
|
const prefix = dir === "/" ? "/" : `${dir}/`;
|
|
3683
|
-
if (dir === "/" ||
|
|
3692
|
+
if (dir === "/" || path2.startsWith(prefix)) {
|
|
3684
3693
|
byDir.get(dir)?.push(row);
|
|
3685
3694
|
}
|
|
3686
3695
|
}
|
|
@@ -3703,10 +3712,10 @@ function dedupeRowsByPath(rows) {
|
|
|
3703
3712
|
const seen = /* @__PURE__ */ new Set();
|
|
3704
3713
|
const unique = [];
|
|
3705
3714
|
for (const row of rows) {
|
|
3706
|
-
const
|
|
3707
|
-
if (!
|
|
3715
|
+
const path2 = typeof row["path"] === "string" ? row["path"] : "";
|
|
3716
|
+
if (!path2 || seen.has(path2))
|
|
3708
3717
|
continue;
|
|
3709
|
-
seen.add(
|
|
3718
|
+
seen.add(path2);
|
|
3710
3719
|
unique.push(row);
|
|
3711
3720
|
}
|
|
3712
3721
|
return unique;
|
|
@@ -3952,12 +3961,12 @@ function parseCompiledSegment(segment) {
|
|
|
3952
3961
|
return null;
|
|
3953
3962
|
if (headTokens[1] === "-n" && headTokens.length < 4 || /^-\d+$/.test(headTokens[1] ?? "") && headTokens.length < 3 || headTokens.length === 2 && /^-?\d+$/.test(headTokens[1] ?? ""))
|
|
3954
3963
|
return null;
|
|
3955
|
-
const
|
|
3956
|
-
if (
|
|
3964
|
+
const path2 = headTokens[headTokens.length - 1];
|
|
3965
|
+
if (path2 === "head" || path2 === "tail" || path2 === "-n")
|
|
3957
3966
|
return null;
|
|
3958
3967
|
return {
|
|
3959
3968
|
kind: "cat",
|
|
3960
|
-
paths: expandBraceToken(
|
|
3969
|
+
paths: expandBraceToken(path2),
|
|
3961
3970
|
lineLimit: parsed.lineLimit,
|
|
3962
3971
|
fromEnd: parsed.fromEnd,
|
|
3963
3972
|
countLines: false,
|
|
@@ -4068,10 +4077,10 @@ function renderDirectoryListing(dir, rows, longFormat) {
|
|
|
4068
4077
|
const entries = /* @__PURE__ */ new Map();
|
|
4069
4078
|
const prefix = dir === "/" ? "/" : `${dir}/`;
|
|
4070
4079
|
for (const row of rows) {
|
|
4071
|
-
const
|
|
4072
|
-
if (!
|
|
4080
|
+
const path2 = row["path"];
|
|
4081
|
+
if (!path2.startsWith(prefix) && dir !== "/")
|
|
4073
4082
|
continue;
|
|
4074
|
-
const rest = dir === "/" ?
|
|
4083
|
+
const rest = dir === "/" ? path2.slice(1) : path2.slice(prefix.length);
|
|
4075
4084
|
const slash = rest.indexOf("/");
|
|
4076
4085
|
const name = slash === -1 ? rest : rest.slice(0, slash);
|
|
4077
4086
|
if (!name)
|
|
@@ -4115,8 +4124,8 @@ async function executeCompiledBashCommand(api, memoryTable, sessionsTable, cmd,
|
|
|
4115
4124
|
}
|
|
4116
4125
|
if (segment.kind === "cat") {
|
|
4117
4126
|
const contents = [];
|
|
4118
|
-
for (const
|
|
4119
|
-
const content = contentMap.get(
|
|
4127
|
+
for (const path2 of segment.paths) {
|
|
4128
|
+
const content = contentMap.get(path2) ?? null;
|
|
4120
4129
|
if (content === null) {
|
|
4121
4130
|
if (segment.ignoreMissing)
|
|
4122
4131
|
continue;
|
|
@@ -4153,11 +4162,11 @@ async function executeCompiledBashCommand(api, memoryTable, sessionsTable, cmd,
|
|
|
4153
4162
|
continue;
|
|
4154
4163
|
}
|
|
4155
4164
|
const candidateContents = await readVirtualPathContentsFn(api, memoryTable, sessionsTable, candidatePaths);
|
|
4156
|
-
const matched = refineGrepMatches(candidatePaths.flatMap((
|
|
4157
|
-
const content = candidateContents.get(
|
|
4165
|
+
const matched = refineGrepMatches(candidatePaths.flatMap((path2) => {
|
|
4166
|
+
const content = candidateContents.get(path2);
|
|
4158
4167
|
if (content === null || content === void 0)
|
|
4159
4168
|
return [];
|
|
4160
|
-
return [{ path, content: normalizeContent(
|
|
4169
|
+
return [{ path: path2, content: normalizeContent(path2, content) }];
|
|
4161
4170
|
}), segment.params);
|
|
4162
4171
|
const limited = segment.lineLimit > 0 ? matched.slice(0, segment.lineLimit) : matched;
|
|
4163
4172
|
outputs.push(limited.join("\n") || "(no matches)");
|
|
@@ -4179,7 +4188,7 @@ async function executeCompiledBashCommand(api, memoryTable, sessionsTable, cmd,
|
|
|
4179
4188
|
}
|
|
4180
4189
|
|
|
4181
4190
|
// dist/src/hooks/query-cache.js
|
|
4182
|
-
import { mkdirSync as
|
|
4191
|
+
import { mkdirSync as mkdirSync10, readFileSync as readFileSync10, rmSync, writeFileSync as writeFileSync8 } from "node:fs";
|
|
4183
4192
|
import { join as join14 } from "node:path";
|
|
4184
4193
|
import { homedir as homedir9 } from "node:os";
|
|
4185
4194
|
var log5 = (msg) => log("query-cache", msg);
|
|
@@ -4204,7 +4213,7 @@ function writeCachedIndexContent(sessionId, content, deps = {}) {
|
|
|
4204
4213
|
const { logFn = log5 } = deps;
|
|
4205
4214
|
try {
|
|
4206
4215
|
const dir = getSessionQueryCacheDir(sessionId, deps);
|
|
4207
|
-
|
|
4216
|
+
mkdirSync10(dir, { recursive: true });
|
|
4208
4217
|
writeFileSync8(join14(dir, INDEX_CACHE_FILE), content, "utf-8");
|
|
4209
4218
|
} catch (e) {
|
|
4210
4219
|
logFn(`write failed for session=${sessionId}: ${e.message}`);
|
|
@@ -4372,7 +4381,227 @@ function rewritePaths(cmd) {
|
|
|
4372
4381
|
return cmd.replace(new RegExp(escapeRe(MEMORY_PATH) + tail, "g"), "/").replace(new RegExp(escapeRe(TILDE_PATH) + tail, "g"), "/").replace(new RegExp('"' + escapeRe(HOME_VAR_PATH) + tail + '"', "g"), '"/"').replace(new RegExp(escapeRe(HOME_VAR_PATH) + tail, "g"), "/");
|
|
4373
4382
|
}
|
|
4374
4383
|
|
|
4384
|
+
// dist/src/skillify/skillopt-trigger.js
|
|
4385
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
4386
|
+
import fs from "node:fs";
|
|
4387
|
+
import path from "node:path";
|
|
4388
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
4389
|
+
|
|
4390
|
+
// dist/src/skillify/state-dir.js
|
|
4391
|
+
import { homedir as homedir11 } from "node:os";
|
|
4392
|
+
import { join as join16 } from "node:path";
|
|
4393
|
+
function getStateDir() {
|
|
4394
|
+
const override = process.env.HIVEMIND_STATE_DIR?.trim();
|
|
4395
|
+
return override && override.length > 0 ? override : join16(homedir11(), ".deeplake", "state", "skillify");
|
|
4396
|
+
}
|
|
4397
|
+
|
|
4398
|
+
// dist/src/skillify/skill-invocations.js
|
|
4399
|
+
function pathToSkillRef(s) {
|
|
4400
|
+
if (typeof s !== "string")
|
|
4401
|
+
return null;
|
|
4402
|
+
const m = s.match(/\/skills\/(?:[^/\s"'`]+\/)*([^/\s"'`]+)\/SKILL\.md/);
|
|
4403
|
+
return m ? m[1] : null;
|
|
4404
|
+
}
|
|
4405
|
+
function splitOrgSkill(skill) {
|
|
4406
|
+
if (skill.includes(":"))
|
|
4407
|
+
return null;
|
|
4408
|
+
if (skill.includes("/") || skill.includes("\\") || skill.includes(".."))
|
|
4409
|
+
return null;
|
|
4410
|
+
const i = skill.lastIndexOf("--");
|
|
4411
|
+
if (i <= 0 || i + 2 >= skill.length)
|
|
4412
|
+
return null;
|
|
4413
|
+
return { name: skill.slice(0, i), author: skill.slice(i + 2) };
|
|
4414
|
+
}
|
|
4415
|
+
|
|
4416
|
+
// dist/src/skillify/manifest.js
|
|
4417
|
+
import { existsSync as existsSync9, lstatSync, mkdirSync as mkdirSync11, readFileSync as readFileSync11, renameSync as renameSync7, unlinkSync as unlinkSync4, writeFileSync as writeFileSync9 } from "node:fs";
|
|
4418
|
+
import { dirname as dirname9, join as join18 } from "node:path";
|
|
4419
|
+
|
|
4420
|
+
// dist/src/skillify/legacy-migration.js
|
|
4421
|
+
import { existsSync as existsSync8, renameSync as renameSync6 } from "node:fs";
|
|
4422
|
+
import { dirname as dirname8, join as join17 } from "node:path";
|
|
4423
|
+
var dlog = (msg) => log("skillify-migrate", msg);
|
|
4424
|
+
var attempted = false;
|
|
4425
|
+
function migrateLegacyStateDir() {
|
|
4426
|
+
if (process.env.HIVEMIND_STATE_DIR?.trim())
|
|
4427
|
+
return;
|
|
4428
|
+
if (attempted)
|
|
4429
|
+
return;
|
|
4430
|
+
attempted = true;
|
|
4431
|
+
const current = getStateDir();
|
|
4432
|
+
const legacy = join17(dirname8(current), "skilify");
|
|
4433
|
+
if (!existsSync8(legacy))
|
|
4434
|
+
return;
|
|
4435
|
+
if (existsSync8(current))
|
|
4436
|
+
return;
|
|
4437
|
+
try {
|
|
4438
|
+
renameSync6(legacy, current);
|
|
4439
|
+
dlog(`migrated ${legacy} -> ${current}`);
|
|
4440
|
+
} catch (err) {
|
|
4441
|
+
const code = err.code;
|
|
4442
|
+
if (code === "EXDEV" || code === "EPERM" || code === "ENOENT" || code === "EEXIST" || code === "ENOTEMPTY") {
|
|
4443
|
+
dlog(`migration skipped (${code}); legacy dir left as-is or another process handled it`);
|
|
4444
|
+
return;
|
|
4445
|
+
}
|
|
4446
|
+
throw err;
|
|
4447
|
+
}
|
|
4448
|
+
}
|
|
4449
|
+
|
|
4450
|
+
// dist/src/skillify/manifest.js
|
|
4451
|
+
function emptyManifest() {
|
|
4452
|
+
return { version: 1, entries: [] };
|
|
4453
|
+
}
|
|
4454
|
+
function manifestPath() {
|
|
4455
|
+
return join18(getStateDir(), "pulled.json");
|
|
4456
|
+
}
|
|
4457
|
+
function loadManifest(path2 = manifestPath()) {
|
|
4458
|
+
migrateLegacyStateDir();
|
|
4459
|
+
if (!existsSync9(path2))
|
|
4460
|
+
return emptyManifest();
|
|
4461
|
+
let raw;
|
|
4462
|
+
try {
|
|
4463
|
+
raw = readFileSync11(path2, "utf-8");
|
|
4464
|
+
} catch {
|
|
4465
|
+
return emptyManifest();
|
|
4466
|
+
}
|
|
4467
|
+
try {
|
|
4468
|
+
const parsed = JSON.parse(raw);
|
|
4469
|
+
if (!parsed || typeof parsed !== "object")
|
|
4470
|
+
return emptyManifest();
|
|
4471
|
+
if (parsed.version !== 1 || !Array.isArray(parsed.entries))
|
|
4472
|
+
return emptyManifest();
|
|
4473
|
+
const entries = [];
|
|
4474
|
+
for (const e of parsed.entries) {
|
|
4475
|
+
if (!e || typeof e !== "object")
|
|
4476
|
+
continue;
|
|
4477
|
+
if (typeof e.dirName !== "string" || !e.dirName)
|
|
4478
|
+
continue;
|
|
4479
|
+
if (e.dirName.includes("/") || e.dirName.includes("\\") || e.dirName.includes(".."))
|
|
4480
|
+
continue;
|
|
4481
|
+
if (typeof e.name !== "string" || !e.name)
|
|
4482
|
+
continue;
|
|
4483
|
+
if (typeof e.author !== "string")
|
|
4484
|
+
continue;
|
|
4485
|
+
if (typeof e.installRoot !== "string" || !e.installRoot)
|
|
4486
|
+
continue;
|
|
4487
|
+
if (e.install !== "global" && e.install !== "project")
|
|
4488
|
+
continue;
|
|
4489
|
+
const symlinks = Array.isArray(e.symlinks) ? e.symlinks.filter((p) => typeof p === "string" && p.length > 0 && (p.startsWith("/") || /^[A-Za-z]:[\\/]/.test(p)) && // absolute (POSIX or Windows)
|
|
4490
|
+
!p.includes("..")) : [];
|
|
4491
|
+
entries.push({
|
|
4492
|
+
dirName: e.dirName,
|
|
4493
|
+
name: e.name,
|
|
4494
|
+
author: e.author,
|
|
4495
|
+
projectKey: typeof e.projectKey === "string" ? e.projectKey : "",
|
|
4496
|
+
remoteVersion: typeof e.remoteVersion === "number" ? e.remoteVersion : 1,
|
|
4497
|
+
install: e.install,
|
|
4498
|
+
installRoot: e.installRoot,
|
|
4499
|
+
pulledAt: typeof e.pulledAt === "string" ? e.pulledAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
4500
|
+
symlinks
|
|
4501
|
+
});
|
|
4502
|
+
}
|
|
4503
|
+
return { version: 1, entries };
|
|
4504
|
+
} catch {
|
|
4505
|
+
return emptyManifest();
|
|
4506
|
+
}
|
|
4507
|
+
}
|
|
4508
|
+
|
|
4509
|
+
// dist/src/skillify/skillopt-env.js
|
|
4510
|
+
var SKILLOPT_ENV = {
|
|
4511
|
+
/** User-set kill switch: "1" disables the whole trigger. */
|
|
4512
|
+
DISABLED: "HIVEMIND_SKILLOPT_DISABLED",
|
|
4513
|
+
/** Recursion guard the trigger sets on the spawned worker so the worker can't re-arm. */
|
|
4514
|
+
WORKER: "HIVEMIND_SKILLOPT_WORKER",
|
|
4515
|
+
/** Worker inputs, handed trigger → worker via the child env. */
|
|
4516
|
+
SESSION: "HIVEMIND_SKILLOPT_SESSION",
|
|
4517
|
+
SKILL: "HIVEMIND_SKILLOPT_SKILL",
|
|
4518
|
+
REACTION: "HIVEMIND_SKILLOPT_REACTION",
|
|
4519
|
+
TOOL_USE_ID: "HIVEMIND_SKILLOPT_TOOL_USE_ID",
|
|
4520
|
+
/** Which agent's CLI runs the judge/proposer (claude_code/codex/hermes/cursor/pi). */
|
|
4521
|
+
AGENT: "HIVEMIND_SKILLOPT_AGENT",
|
|
4522
|
+
/** K-message judgment-window size override. */
|
|
4523
|
+
JUDGE_WINDOW: "HIVEMIND_SKILLOPT_JUDGE_WINDOW"
|
|
4524
|
+
};
|
|
4525
|
+
|
|
4526
|
+
// dist/src/skillify/skillopt-trigger.js
|
|
4527
|
+
var DEFAULT_JUDGE_WINDOW = 3;
|
|
4528
|
+
function judgeWindow(env = process.env) {
|
|
4529
|
+
const n = Number(env[SKILLOPT_ENV.JUDGE_WINDOW]);
|
|
4530
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : DEFAULT_JUDGE_WINDOW;
|
|
4531
|
+
}
|
|
4532
|
+
function defaultIsOrgSkill(skillRef) {
|
|
4533
|
+
try {
|
|
4534
|
+
return loadManifest().entries.some((e) => e.dirName === skillRef);
|
|
4535
|
+
} catch {
|
|
4536
|
+
return false;
|
|
4537
|
+
}
|
|
4538
|
+
}
|
|
4539
|
+
function pendingFile(sessionId) {
|
|
4540
|
+
const safe = sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 200);
|
|
4541
|
+
return path.join(getStateDir(), "skillopt", "pending", `${safe}.json`);
|
|
4542
|
+
}
|
|
4543
|
+
var fileStore = {
|
|
4544
|
+
load(sessionId) {
|
|
4545
|
+
try {
|
|
4546
|
+
return JSON.parse(fs.readFileSync(pendingFile(sessionId), "utf8"));
|
|
4547
|
+
} catch {
|
|
4548
|
+
return null;
|
|
4549
|
+
}
|
|
4550
|
+
},
|
|
4551
|
+
save(sessionId, p) {
|
|
4552
|
+
try {
|
|
4553
|
+
const f = pendingFile(sessionId);
|
|
4554
|
+
if (p === null) {
|
|
4555
|
+
try {
|
|
4556
|
+
fs.unlinkSync(f);
|
|
4557
|
+
} catch {
|
|
4558
|
+
}
|
|
4559
|
+
return;
|
|
4560
|
+
}
|
|
4561
|
+
fs.mkdirSync(path.dirname(f), { recursive: true });
|
|
4562
|
+
const tmp = `${f}.${process.pid}.tmp`;
|
|
4563
|
+
fs.writeFileSync(tmp, JSON.stringify(p));
|
|
4564
|
+
fs.renameSync(tmp, f);
|
|
4565
|
+
} catch {
|
|
4566
|
+
}
|
|
4567
|
+
}
|
|
4568
|
+
};
|
|
4569
|
+
function markSkillPending(sessionId, skillRef, toolUseId, deps = {}) {
|
|
4570
|
+
if (!sessionId || !skillRef)
|
|
4571
|
+
return false;
|
|
4572
|
+
if (!splitOrgSkill(skillRef))
|
|
4573
|
+
return false;
|
|
4574
|
+
if (!(deps.isOrgSkill ?? defaultIsOrgSkill)(skillRef))
|
|
4575
|
+
return false;
|
|
4576
|
+
(deps.store ?? fileStore).save(sessionId, { skill: skillRef, budget: judgeWindow(deps.env ?? process.env), toolUseId });
|
|
4577
|
+
return true;
|
|
4578
|
+
}
|
|
4579
|
+
|
|
4580
|
+
// dist/src/hooks/shared/skillopt-hook.js
|
|
4581
|
+
function skillRefFromSkillFileRead(toolName, toolInput) {
|
|
4582
|
+
if (/^read$/i.test(toolName))
|
|
4583
|
+
return pathToSkillRef(toolInput?.path);
|
|
4584
|
+
return pathToSkillRef(toolInput?.command);
|
|
4585
|
+
}
|
|
4586
|
+
function armSkillOptOnSkillUse(sessionId, toolName, toolInput, toolUseId) {
|
|
4587
|
+
try {
|
|
4588
|
+
if (process.env[SKILLOPT_ENV.DISABLED] === "1")
|
|
4589
|
+
return;
|
|
4590
|
+
let ref = null;
|
|
4591
|
+
if (toolName === "Skill") {
|
|
4592
|
+
const s = toolInput?.skill;
|
|
4593
|
+
ref = typeof s === "string" ? s : null;
|
|
4594
|
+
} else {
|
|
4595
|
+
ref = skillRefFromSkillFileRead(toolName, toolInput);
|
|
4596
|
+
}
|
|
4597
|
+
if (ref)
|
|
4598
|
+
markSkillPending(sessionId, ref, toolUseId);
|
|
4599
|
+
} catch {
|
|
4600
|
+
}
|
|
4601
|
+
}
|
|
4602
|
+
|
|
4375
4603
|
// dist/src/hooks/codex/pre-tool-use.js
|
|
4604
|
+
var __bundleDir = dirname10(fileURLToPath4(import.meta.url));
|
|
4376
4605
|
var log6 = (msg) => log("codex-pre", msg);
|
|
4377
4606
|
function buildUnsupportedGuidance() {
|
|
4378
4607
|
return "This command is not supported for ~/.deeplake/memory/ operations. Only bash builtins are available: cat, ls, grep, echo, jq, head, tail, wc, sort, find, etc. Do NOT use python, python3, node, curl, or other interpreters. Rewrite your command using only bash tools and retry.";
|
|
@@ -4380,11 +4609,11 @@ function buildUnsupportedGuidance() {
|
|
|
4380
4609
|
function buildIndexContent(rows) {
|
|
4381
4610
|
const lines = ["# Memory Index", "", `${rows.length} sessions:`, ""];
|
|
4382
4611
|
for (const row of rows) {
|
|
4383
|
-
const
|
|
4612
|
+
const path2 = row["path"];
|
|
4384
4613
|
const project = row["project"] || "";
|
|
4385
4614
|
const description = (row["description"] || "").slice(0, 120);
|
|
4386
4615
|
const date = (row["creation_date"] || "").slice(0, 10);
|
|
4387
|
-
lines.push(`- [${
|
|
4616
|
+
lines.push(`- [${path2}](${path2}) ${date} ${project ? `[${project}]` : ""} ${description}`);
|
|
4388
4617
|
}
|
|
4389
4618
|
return lines.join("\n");
|
|
4390
4619
|
}
|
|
@@ -4414,16 +4643,16 @@ async function processCodexPreToolUse(input, deps = {}) {
|
|
|
4414
4643
|
const api = createApi(table, config);
|
|
4415
4644
|
const readVirtualPathContentsWithCache = async (cachePaths) => {
|
|
4416
4645
|
const uniquePaths = [...new Set(cachePaths)];
|
|
4417
|
-
const result = new Map(uniquePaths.map((
|
|
4646
|
+
const result = new Map(uniquePaths.map((path2) => [path2, null]));
|
|
4418
4647
|
const cachedIndex = uniquePaths.includes("/index.md") ? readCachedIndexContentFn(input.session_id) : null;
|
|
4419
|
-
const remainingPaths = cachedIndex === null ? uniquePaths : uniquePaths.filter((
|
|
4648
|
+
const remainingPaths = cachedIndex === null ? uniquePaths : uniquePaths.filter((path2) => path2 !== "/index.md");
|
|
4420
4649
|
if (cachedIndex !== null) {
|
|
4421
4650
|
result.set("/index.md", cachedIndex);
|
|
4422
4651
|
}
|
|
4423
4652
|
if (remainingPaths.length > 0) {
|
|
4424
4653
|
const fetched = await readVirtualPathContentsFn(api, table, sessionsTable, remainingPaths);
|
|
4425
|
-
for (const [
|
|
4426
|
-
result.set(
|
|
4654
|
+
for (const [path2, content] of fetched)
|
|
4655
|
+
result.set(path2, content);
|
|
4427
4656
|
}
|
|
4428
4657
|
const fetchedIndex = result.get("/index.md");
|
|
4429
4658
|
if (typeof fetchedIndex === "string") {
|
|
@@ -4519,10 +4748,10 @@ async function processCodexPreToolUse(input, deps = {}) {
|
|
|
4519
4748
|
const entries = /* @__PURE__ */ new Map();
|
|
4520
4749
|
const prefix = dir === "/" ? "/" : `${dir}/`;
|
|
4521
4750
|
for (const row of rows) {
|
|
4522
|
-
const
|
|
4523
|
-
if (!
|
|
4751
|
+
const path2 = row["path"];
|
|
4752
|
+
if (!path2.startsWith(prefix) && dir !== "/")
|
|
4524
4753
|
continue;
|
|
4525
|
-
const rest = dir === "/" ?
|
|
4754
|
+
const rest = dir === "/" ? path2.slice(1) : path2.slice(prefix.length);
|
|
4526
4755
|
const slash = rest.indexOf("/");
|
|
4527
4756
|
const name = slash === -1 ? rest : rest.slice(0, slash);
|
|
4528
4757
|
if (!name)
|
|
@@ -4582,15 +4811,29 @@ async function processCodexPreToolUse(input, deps = {}) {
|
|
|
4582
4811
|
logFn(`direct query failed: ${e.message}`);
|
|
4583
4812
|
}
|
|
4584
4813
|
}
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4814
|
+
const isWriteRedirect = /^\s*(echo|printf|tee)\b/.test(rewritten) && /\s>>?\s/.test(rewritten);
|
|
4815
|
+
const shellBundle = join19(__bundleDir, "shell", "deeplake-shell.js");
|
|
4816
|
+
logFn(`unroutable memory command, falling back to VFS shell: ${rewritten}`);
|
|
4817
|
+
try {
|
|
4818
|
+
const proc = spawnSync("node", [shellBundle, "-c", rewritten], {
|
|
4819
|
+
encoding: "utf-8",
|
|
4820
|
+
timeout: 1e4
|
|
4821
|
+
});
|
|
4822
|
+
if (proc.status === 0 || proc.stdout && proc.stdout.trim()) {
|
|
4823
|
+
const output = (proc.stdout?.trim() ?? "") || "(done)";
|
|
4824
|
+
return { action: isWriteRedirect ? "guide" : "block", output, rewrittenCommand: rewritten };
|
|
4825
|
+
}
|
|
4826
|
+
return { action: "block", output: buildUnsupportedGuidance(), rewrittenCommand: rewritten };
|
|
4827
|
+
} catch {
|
|
4828
|
+
return { action: "block", output: buildUnsupportedGuidance(), rewrittenCommand: rewritten };
|
|
4829
|
+
}
|
|
4591
4830
|
}
|
|
4592
4831
|
async function main() {
|
|
4593
4832
|
const input = await readStdin();
|
|
4833
|
+
try {
|
|
4834
|
+
armSkillOptOnSkillUse(input.session_id, input.tool_name, input.tool_input, input.tool_use_id);
|
|
4835
|
+
} catch {
|
|
4836
|
+
}
|
|
4594
4837
|
const decision = await processCodexPreToolUse(input);
|
|
4595
4838
|
if (decision.action === "pass")
|
|
4596
4839
|
return;
|