@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
|
@@ -16,7 +16,7 @@ __export(index_marker_store_exports, {
|
|
|
16
16
|
hasFreshIndexMarker: () => hasFreshIndexMarker,
|
|
17
17
|
writeIndexMarker: () => writeIndexMarker
|
|
18
18
|
});
|
|
19
|
-
import { existsSync as existsSync2, mkdirSync as
|
|
19
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
20
20
|
import { join as join5 } from "node:path";
|
|
21
21
|
import { tmpdir } from "node:os";
|
|
22
22
|
function getIndexMarkerDir() {
|
|
@@ -40,7 +40,7 @@ function hasFreshIndexMarker(markerPath) {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
function writeIndexMarker(markerPath) {
|
|
43
|
-
|
|
43
|
+
mkdirSync4(getIndexMarkerDir(), { recursive: true });
|
|
44
44
|
writeFileSync3(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
|
|
45
45
|
}
|
|
46
46
|
var INDEX_MARKER_TTL_MS;
|
|
@@ -119,8 +119,8 @@ function loadConfig() {
|
|
|
119
119
|
import { randomUUID } from "node:crypto";
|
|
120
120
|
|
|
121
121
|
// dist/src/utils/debug.js
|
|
122
|
-
import { appendFileSync } from "node:fs";
|
|
123
|
-
import { join as join2 } from "node:path";
|
|
122
|
+
import { appendFileSync, mkdirSync } from "node:fs";
|
|
123
|
+
import { dirname, join as join2 } from "node:path";
|
|
124
124
|
import { homedir as homedir2 } from "node:os";
|
|
125
125
|
var LOG = join2(homedir2(), ".deeplake", "hook-debug.log");
|
|
126
126
|
function isDebug() {
|
|
@@ -129,8 +129,12 @@ function isDebug() {
|
|
|
129
129
|
function log(tag, msg) {
|
|
130
130
|
if (!isDebug())
|
|
131
131
|
return;
|
|
132
|
-
|
|
132
|
+
try {
|
|
133
|
+
mkdirSync(dirname(LOG), { recursive: true });
|
|
134
|
+
appendFileSync(LOG, `${(/* @__PURE__ */ new Date()).toISOString()} [${tag}] ${msg}
|
|
133
135
|
`);
|
|
136
|
+
} catch {
|
|
137
|
+
}
|
|
134
138
|
}
|
|
135
139
|
|
|
136
140
|
// dist/src/utils/sql.js
|
|
@@ -339,7 +343,7 @@ async function healMissingColumns(args) {
|
|
|
339
343
|
}
|
|
340
344
|
|
|
341
345
|
// dist/src/notifications/queue.js
|
|
342
|
-
import { readFileSync as readFileSync2, writeFileSync, renameSync, mkdirSync, openSync, closeSync, unlinkSync, statSync } from "node:fs";
|
|
346
|
+
import { readFileSync as readFileSync2, writeFileSync, renameSync, mkdirSync as mkdirSync2, openSync, closeSync, unlinkSync, statSync } from "node:fs";
|
|
343
347
|
import { join as join3, resolve } from "node:path";
|
|
344
348
|
import { homedir as homedir3 } from "node:os";
|
|
345
349
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
@@ -366,38 +370,38 @@ function readQueue() {
|
|
|
366
370
|
return { queue: [] };
|
|
367
371
|
}
|
|
368
372
|
}
|
|
369
|
-
function _isQueuePathInsideHome(
|
|
370
|
-
const r = resolve(
|
|
373
|
+
function _isQueuePathInsideHome(path2, home) {
|
|
374
|
+
const r = resolve(path2);
|
|
371
375
|
const h = resolve(home);
|
|
372
376
|
return r.startsWith(h + "/") || r === h;
|
|
373
377
|
}
|
|
374
378
|
function writeQueue(q) {
|
|
375
|
-
const
|
|
379
|
+
const path2 = queuePath();
|
|
376
380
|
const home = resolve(homedir3());
|
|
377
|
-
if (!_isQueuePathInsideHome(
|
|
378
|
-
throw new Error(`notifications-queue write blocked: ${
|
|
381
|
+
if (!_isQueuePathInsideHome(path2, home)) {
|
|
382
|
+
throw new Error(`notifications-queue write blocked: ${path2} is outside ${home}`);
|
|
379
383
|
}
|
|
380
|
-
|
|
381
|
-
const tmp = `${
|
|
384
|
+
mkdirSync2(join3(home, ".deeplake"), { recursive: true, mode: 448 });
|
|
385
|
+
const tmp = `${path2}.${process.pid}.tmp`;
|
|
382
386
|
writeFileSync(tmp, JSON.stringify(q, null, 2), { mode: 384 });
|
|
383
|
-
renameSync(tmp,
|
|
387
|
+
renameSync(tmp, path2);
|
|
384
388
|
}
|
|
385
389
|
async function withQueueLock(fn) {
|
|
386
|
-
const
|
|
387
|
-
|
|
390
|
+
const path2 = lockPath();
|
|
391
|
+
mkdirSync2(join3(homedir3(), ".deeplake"), { recursive: true, mode: 448 });
|
|
388
392
|
let fd = null;
|
|
389
393
|
for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
|
|
390
394
|
try {
|
|
391
|
-
fd = openSync(
|
|
395
|
+
fd = openSync(path2, "wx", 384);
|
|
392
396
|
break;
|
|
393
397
|
} catch (e) {
|
|
394
398
|
const code = e.code;
|
|
395
399
|
if (code !== "EEXIST")
|
|
396
400
|
throw e;
|
|
397
401
|
try {
|
|
398
|
-
const age = Date.now() - statSync(
|
|
402
|
+
const age = Date.now() - statSync(path2).mtimeMs;
|
|
399
403
|
if (age > LOCK_STALE_MS) {
|
|
400
|
-
unlinkSync(
|
|
404
|
+
unlinkSync(path2);
|
|
401
405
|
continue;
|
|
402
406
|
}
|
|
403
407
|
} catch {
|
|
@@ -418,7 +422,7 @@ async function withQueueLock(fn) {
|
|
|
418
422
|
} catch {
|
|
419
423
|
}
|
|
420
424
|
try {
|
|
421
|
-
unlinkSync(
|
|
425
|
+
unlinkSync(path2);
|
|
422
426
|
} catch {
|
|
423
427
|
}
|
|
424
428
|
}
|
|
@@ -440,7 +444,7 @@ async function enqueueNotification(n) {
|
|
|
440
444
|
}
|
|
441
445
|
|
|
442
446
|
// dist/src/commands/auth-creds.js
|
|
443
|
-
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as
|
|
447
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, unlinkSync as unlinkSync2 } from "node:fs";
|
|
444
448
|
import { join as join4 } from "node:path";
|
|
445
449
|
import { homedir as homedir4 } from "node:os";
|
|
446
450
|
function configDir() {
|
|
@@ -694,9 +698,9 @@ var DeeplakeApi = class {
|
|
|
694
698
|
}
|
|
695
699
|
}
|
|
696
700
|
/** Update specific columns on a row by path. */
|
|
697
|
-
async updateColumns(
|
|
701
|
+
async updateColumns(path2, columns) {
|
|
698
702
|
const setClauses = Object.entries(columns).map(([col, val]) => typeof val === "number" ? `${col} = ${val}` : `${col} = '${sqlStr(String(val))}'`).join(", ");
|
|
699
|
-
await this.query(`UPDATE "${this.tableName}" SET ${setClauses} WHERE path = '${sqlStr(
|
|
703
|
+
await this.query(`UPDATE "${this.tableName}" SET ${setClauses} WHERE path = '${sqlStr(path2)}'`);
|
|
700
704
|
}
|
|
701
705
|
// ── Convenience ─────────────────────────────────────────────────────────────
|
|
702
706
|
/** Create a BM25 search index on a column. */
|
|
@@ -1128,8 +1132,8 @@ function formatToolCall(obj) {
|
|
|
1128
1132
|
input: ${formatToolInput(obj?.tool_input)}
|
|
1129
1133
|
response: ${formatToolResponse(obj?.tool_response, obj?.tool_input, obj?.tool_name)}`;
|
|
1130
1134
|
}
|
|
1131
|
-
function normalizeContent(
|
|
1132
|
-
if (!
|
|
1135
|
+
function normalizeContent(path2, raw) {
|
|
1136
|
+
if (!path2.includes("/sessions/"))
|
|
1133
1137
|
return raw;
|
|
1134
1138
|
if (!raw || raw[0] !== "{")
|
|
1135
1139
|
return raw;
|
|
@@ -1847,22 +1851,22 @@ import { join as join8 } from "node:path";
|
|
|
1847
1851
|
import { pathToFileURL } from "node:url";
|
|
1848
1852
|
|
|
1849
1853
|
// dist/src/user-config.js
|
|
1850
|
-
import { existsSync as existsSync4, mkdirSync as
|
|
1854
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync6, renameSync as renameSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
1851
1855
|
import { homedir as homedir6 } from "node:os";
|
|
1852
|
-
import { dirname, join as join7 } from "node:path";
|
|
1856
|
+
import { dirname as dirname2, join as join7 } from "node:path";
|
|
1853
1857
|
var _configPath = () => process.env.HIVEMIND_CONFIG_PATH ?? join7(homedir6(), ".deeplake", "config.json");
|
|
1854
1858
|
var _cache = null;
|
|
1855
1859
|
var _migrated = false;
|
|
1856
1860
|
function readUserConfig() {
|
|
1857
1861
|
if (_cache !== null)
|
|
1858
1862
|
return _cache;
|
|
1859
|
-
const
|
|
1860
|
-
if (!existsSync4(
|
|
1863
|
+
const path2 = _configPath();
|
|
1864
|
+
if (!existsSync4(path2)) {
|
|
1861
1865
|
_cache = {};
|
|
1862
1866
|
return _cache;
|
|
1863
1867
|
}
|
|
1864
1868
|
try {
|
|
1865
|
-
const raw = readFileSync6(
|
|
1869
|
+
const raw = readFileSync6(path2, "utf-8");
|
|
1866
1870
|
const parsed = JSON.parse(raw);
|
|
1867
1871
|
_cache = isPlainObject(parsed) ? parsed : {};
|
|
1868
1872
|
} catch {
|
|
@@ -1873,13 +1877,13 @@ function readUserConfig() {
|
|
|
1873
1877
|
function writeUserConfig(patch) {
|
|
1874
1878
|
const current = readUserConfig();
|
|
1875
1879
|
const merged = deepMerge(current, patch);
|
|
1876
|
-
const
|
|
1877
|
-
const dir =
|
|
1880
|
+
const path2 = _configPath();
|
|
1881
|
+
const dir = dirname2(path2);
|
|
1878
1882
|
if (!existsSync4(dir))
|
|
1879
|
-
|
|
1880
|
-
const tmp = `${
|
|
1883
|
+
mkdirSync5(dir, { recursive: true });
|
|
1884
|
+
const tmp = `${path2}.tmp.${process.pid}`;
|
|
1881
1885
|
writeFileSync4(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
1882
|
-
renameSync2(tmp,
|
|
1886
|
+
renameSync2(tmp, path2);
|
|
1883
1887
|
_cache = merged;
|
|
1884
1888
|
return merged;
|
|
1885
1889
|
}
|
|
@@ -1960,11 +1964,11 @@ function embeddingsDisabled() {
|
|
|
1960
1964
|
|
|
1961
1965
|
// dist/src/hooks/grep-direct.js
|
|
1962
1966
|
import { fileURLToPath } from "node:url";
|
|
1963
|
-
import { dirname as
|
|
1967
|
+
import { dirname as dirname3, join as join9 } from "node:path";
|
|
1964
1968
|
var SEMANTIC_ENABLED = process.env.HIVEMIND_SEMANTIC_SEARCH !== "false" && !embeddingsDisabled();
|
|
1965
1969
|
var SEMANTIC_TIMEOUT_MS = Number(process.env.HIVEMIND_SEMANTIC_EMBED_TIMEOUT_MS ?? "500");
|
|
1966
1970
|
function resolveDaemonPath() {
|
|
1967
|
-
return join9(
|
|
1971
|
+
return join9(dirname3(fileURLToPath(import.meta.url)), "..", "embeddings", "embed-daemon.js");
|
|
1968
1972
|
}
|
|
1969
1973
|
var sharedEmbedClient = null;
|
|
1970
1974
|
function getEmbedClient() {
|
|
@@ -2336,13 +2340,13 @@ function rewritePaths(cmd) {
|
|
|
2336
2340
|
}
|
|
2337
2341
|
|
|
2338
2342
|
// dist/src/graph/vfs-handler.js
|
|
2339
|
-
import { existsSync as existsSync7, mkdirSync as
|
|
2343
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync9, readFileSync as readFileSync9, renameSync as renameSync5, writeFileSync as writeFileSync7 } from "node:fs";
|
|
2340
2344
|
import { createHash as createHash3 } from "node:crypto";
|
|
2341
|
-
import { join as join14, dirname as
|
|
2345
|
+
import { join as join14, dirname as dirname7 } from "node:path";
|
|
2342
2346
|
|
|
2343
2347
|
// dist/src/graph/last-build.js
|
|
2344
|
-
import { existsSync as existsSync5, mkdirSync as
|
|
2345
|
-
import { dirname as
|
|
2348
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync6, readFileSync as readFileSync7, renameSync as renameSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
2349
|
+
import { dirname as dirname4, join as join11 } from "node:path";
|
|
2346
2350
|
function lastBuildPath(baseDir, worktreeId) {
|
|
2347
2351
|
if (worktreeId !== void 0) {
|
|
2348
2352
|
return join11(baseDir, "worktrees", worktreeId, ".last-build.json");
|
|
@@ -2350,18 +2354,18 @@ function lastBuildPath(baseDir, worktreeId) {
|
|
|
2350
2354
|
return join11(baseDir, ".last-build.json");
|
|
2351
2355
|
}
|
|
2352
2356
|
function readLastBuild(baseDir, worktreeId) {
|
|
2353
|
-
let
|
|
2354
|
-
if (!existsSync5(
|
|
2357
|
+
let path2 = lastBuildPath(baseDir, worktreeId);
|
|
2358
|
+
if (!existsSync5(path2)) {
|
|
2355
2359
|
if (worktreeId === void 0)
|
|
2356
2360
|
return null;
|
|
2357
2361
|
const legacy = lastBuildPath(baseDir, void 0);
|
|
2358
2362
|
if (!existsSync5(legacy))
|
|
2359
2363
|
return null;
|
|
2360
|
-
|
|
2364
|
+
path2 = legacy;
|
|
2361
2365
|
}
|
|
2362
2366
|
let raw;
|
|
2363
2367
|
try {
|
|
2364
|
-
raw = readFileSync7(
|
|
2368
|
+
raw = readFileSync7(path2, "utf8");
|
|
2365
2369
|
} catch {
|
|
2366
2370
|
return null;
|
|
2367
2371
|
}
|
|
@@ -2392,13 +2396,13 @@ function readLastBuild(baseDir, worktreeId) {
|
|
|
2392
2396
|
|
|
2393
2397
|
// dist/src/graph/snapshot.js
|
|
2394
2398
|
import { createHash } from "node:crypto";
|
|
2395
|
-
import { mkdirSync as
|
|
2399
|
+
import { mkdirSync as mkdirSync8, renameSync as renameSync4, writeFileSync as writeFileSync6 } from "node:fs";
|
|
2396
2400
|
import { homedir as homedir9 } from "node:os";
|
|
2397
|
-
import { dirname as
|
|
2401
|
+
import { dirname as dirname6, join as join13 } from "node:path";
|
|
2398
2402
|
|
|
2399
2403
|
// dist/src/graph/history.js
|
|
2400
|
-
import { appendFileSync as appendFileSync2, existsSync as existsSync6, mkdirSync as
|
|
2401
|
-
import { dirname as
|
|
2404
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync7, readFileSync as readFileSync8 } from "node:fs";
|
|
2405
|
+
import { dirname as dirname5, join as join12 } from "node:path";
|
|
2402
2406
|
|
|
2403
2407
|
// dist/src/graph/resolve/cross-file.js
|
|
2404
2408
|
import { posix } from "node:path";
|
|
@@ -2970,18 +2974,18 @@ function workTreeIdFor(cwd) {
|
|
|
2970
2974
|
return createHash3("sha256").update(cwd).digest("hex").slice(0, 16);
|
|
2971
2975
|
}
|
|
2972
2976
|
function handleGraphVfs(subpath, cwd) {
|
|
2973
|
-
const
|
|
2974
|
-
if (
|
|
2977
|
+
const path2 = subpath.replace(/^\/+/, "");
|
|
2978
|
+
if (path2 === "" || path2 === "/") {
|
|
2975
2979
|
return { kind: "ok", body: dirListing() };
|
|
2976
2980
|
}
|
|
2977
|
-
if (
|
|
2981
|
+
if (path2 === "index.md" || path2 === "index") {
|
|
2978
2982
|
return loadSnapshotOrError(cwd, (snap, baseDir) => ({
|
|
2979
2983
|
kind: "ok",
|
|
2980
2984
|
body: renderIndex(snap, baseDir, cwd)
|
|
2981
2985
|
}));
|
|
2982
2986
|
}
|
|
2983
|
-
if (
|
|
2984
|
-
const pattern =
|
|
2987
|
+
if (path2.startsWith("find/")) {
|
|
2988
|
+
const pattern = path2.slice("find/".length);
|
|
2985
2989
|
if (pattern === "") {
|
|
2986
2990
|
return { kind: "not-found", message: "find/ requires a pattern: cat memory/graph/find/<keyword>" };
|
|
2987
2991
|
}
|
|
@@ -2990,8 +2994,8 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
2990
2994
|
body: renderFind(snap, pattern, baseDir, workTreeIdFor(cwd))
|
|
2991
2995
|
}));
|
|
2992
2996
|
}
|
|
2993
|
-
if (
|
|
2994
|
-
const key =
|
|
2997
|
+
if (path2.startsWith("show/")) {
|
|
2998
|
+
const key = path2.slice("show/".length);
|
|
2995
2999
|
if (key === "") {
|
|
2996
3000
|
return { kind: "not-found", message: "show/ requires a handle or pattern" };
|
|
2997
3001
|
}
|
|
@@ -3000,8 +3004,8 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
3000
3004
|
body: renderShow(snap, key, baseDir, workTreeIdFor(cwd))
|
|
3001
3005
|
}));
|
|
3002
3006
|
}
|
|
3003
|
-
if (
|
|
3004
|
-
const pattern =
|
|
3007
|
+
if (path2.startsWith("query/")) {
|
|
3008
|
+
const pattern = path2.slice("query/".length);
|
|
3005
3009
|
if (pattern === "") {
|
|
3006
3010
|
return { kind: "not-found", message: "query/ requires a pattern: cat memory/graph/query/<keyword>" };
|
|
3007
3011
|
}
|
|
@@ -3010,28 +3014,28 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
3010
3014
|
body: renderQuery(snap, pattern, baseDir, workTreeIdFor(cwd))
|
|
3011
3015
|
}));
|
|
3012
3016
|
}
|
|
3013
|
-
if (
|
|
3014
|
-
const pattern =
|
|
3017
|
+
if (path2.startsWith("impact/")) {
|
|
3018
|
+
const pattern = path2.slice("impact/".length);
|
|
3015
3019
|
if (pattern === "") {
|
|
3016
3020
|
return { kind: "not-found", message: "impact/ requires a pattern: cat memory/graph/impact/<symbol>" };
|
|
3017
3021
|
}
|
|
3018
3022
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderImpact(snap, pattern) }));
|
|
3019
3023
|
}
|
|
3020
|
-
if (
|
|
3021
|
-
const file =
|
|
3024
|
+
if (path2.startsWith("neighborhood/")) {
|
|
3025
|
+
const file = path2.slice("neighborhood/".length);
|
|
3022
3026
|
if (file === "") {
|
|
3023
3027
|
return { kind: "not-found", message: "neighborhood/ requires a file path: cat memory/graph/neighborhood/<file>" };
|
|
3024
3028
|
}
|
|
3025
3029
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderNeighborhood(snap, file) }));
|
|
3026
3030
|
}
|
|
3027
|
-
if (
|
|
3031
|
+
if (path2 === "layers" || path2 === "layers/" || path2 === "layers/index.md") {
|
|
3028
3032
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderLayers(snap) }));
|
|
3029
3033
|
}
|
|
3030
|
-
if (
|
|
3034
|
+
if (path2 === "tour" || path2 === "tour/" || path2 === "tour/index.md") {
|
|
3031
3035
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderTour(snap) }));
|
|
3032
3036
|
}
|
|
3033
|
-
if (
|
|
3034
|
-
const rest =
|
|
3037
|
+
if (path2.startsWith("path/")) {
|
|
3038
|
+
const rest = path2.slice("path/".length);
|
|
3035
3039
|
const slash = rest.indexOf("/");
|
|
3036
3040
|
if (slash <= 0 || slash === rest.length - 1) {
|
|
3037
3041
|
return { kind: "not-found", message: "path/ needs two patterns: cat memory/graph/path/<from>/<to> (each a symbol-name substring, no slash)" };
|
|
@@ -3042,7 +3046,7 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
3042
3046
|
}
|
|
3043
3047
|
return {
|
|
3044
3048
|
kind: "not-found",
|
|
3045
|
-
message: `Unknown endpoint: graph/${
|
|
3049
|
+
message: `Unknown endpoint: graph/${path2}
|
|
3046
3050
|
Available: index.md, find/<pattern>, query/<pattern>, show/<handle-or-pattern>, impact/<pattern>, neighborhood/<file>, layers, tour, path/<from>/<to>`
|
|
3047
3051
|
};
|
|
3048
3052
|
}
|
|
@@ -3441,22 +3445,22 @@ function handlesPath(baseDir, worktreeId) {
|
|
|
3441
3445
|
return join14(baseDir, "worktrees", worktreeId, ".find-handles.json");
|
|
3442
3446
|
}
|
|
3443
3447
|
function saveHandles(baseDir, worktreeId, ids, pattern) {
|
|
3444
|
-
const
|
|
3448
|
+
const path2 = handlesPath(baseDir, worktreeId);
|
|
3445
3449
|
const payload = { pattern, ts: Date.now(), ids };
|
|
3446
3450
|
try {
|
|
3447
|
-
|
|
3448
|
-
const tmp = `${
|
|
3451
|
+
mkdirSync9(dirname7(path2), { recursive: true });
|
|
3452
|
+
const tmp = `${path2}.tmp.${process.pid}.${Date.now()}`;
|
|
3449
3453
|
writeFileSync7(tmp, JSON.stringify(payload));
|
|
3450
|
-
renameSync5(tmp,
|
|
3454
|
+
renameSync5(tmp, path2);
|
|
3451
3455
|
} catch {
|
|
3452
3456
|
}
|
|
3453
3457
|
}
|
|
3454
3458
|
function loadHandles(baseDir, worktreeId) {
|
|
3455
|
-
const
|
|
3456
|
-
if (!existsSync7(
|
|
3459
|
+
const path2 = handlesPath(baseDir, worktreeId);
|
|
3460
|
+
if (!existsSync7(path2))
|
|
3457
3461
|
return null;
|
|
3458
3462
|
try {
|
|
3459
|
-
const parsed = JSON.parse(readFileSync9(
|
|
3463
|
+
const parsed = JSON.parse(readFileSync9(path2, "utf8"));
|
|
3460
3464
|
if (parsed === null || typeof parsed !== "object")
|
|
3461
3465
|
return null;
|
|
3462
3466
|
const o = parsed;
|
|
@@ -3546,10 +3550,230 @@ function tryGraphRead(rewrittenCommand, cwd) {
|
|
|
3546
3550
|
return result.kind === "ok" ? result.body : `(${result.kind}) ${result.message}`;
|
|
3547
3551
|
}
|
|
3548
3552
|
|
|
3553
|
+
// dist/src/skillify/skillopt-trigger.js
|
|
3554
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
3555
|
+
import fs from "node:fs";
|
|
3556
|
+
import path from "node:path";
|
|
3557
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
3558
|
+
|
|
3559
|
+
// dist/src/skillify/state-dir.js
|
|
3560
|
+
import { homedir as homedir10 } from "node:os";
|
|
3561
|
+
import { join as join15 } from "node:path";
|
|
3562
|
+
function getStateDir() {
|
|
3563
|
+
const override = process.env.HIVEMIND_STATE_DIR?.trim();
|
|
3564
|
+
return override && override.length > 0 ? override : join15(homedir10(), ".deeplake", "state", "skillify");
|
|
3565
|
+
}
|
|
3566
|
+
|
|
3567
|
+
// dist/src/skillify/skill-invocations.js
|
|
3568
|
+
function pathToSkillRef(s) {
|
|
3569
|
+
if (typeof s !== "string")
|
|
3570
|
+
return null;
|
|
3571
|
+
const m = s.match(/\/skills\/(?:[^/\s"'`]+\/)*([^/\s"'`]+)\/SKILL\.md/);
|
|
3572
|
+
return m ? m[1] : null;
|
|
3573
|
+
}
|
|
3574
|
+
function splitOrgSkill(skill) {
|
|
3575
|
+
if (skill.includes(":"))
|
|
3576
|
+
return null;
|
|
3577
|
+
if (skill.includes("/") || skill.includes("\\") || skill.includes(".."))
|
|
3578
|
+
return null;
|
|
3579
|
+
const i = skill.lastIndexOf("--");
|
|
3580
|
+
if (i <= 0 || i + 2 >= skill.length)
|
|
3581
|
+
return null;
|
|
3582
|
+
return { name: skill.slice(0, i), author: skill.slice(i + 2) };
|
|
3583
|
+
}
|
|
3584
|
+
|
|
3585
|
+
// dist/src/skillify/manifest.js
|
|
3586
|
+
import { existsSync as existsSync9, lstatSync, mkdirSync as mkdirSync10, readFileSync as readFileSync10, renameSync as renameSync7, unlinkSync as unlinkSync4, writeFileSync as writeFileSync8 } from "node:fs";
|
|
3587
|
+
import { dirname as dirname9, join as join17 } from "node:path";
|
|
3588
|
+
|
|
3589
|
+
// dist/src/skillify/legacy-migration.js
|
|
3590
|
+
import { existsSync as existsSync8, renameSync as renameSync6 } from "node:fs";
|
|
3591
|
+
import { dirname as dirname8, join as join16 } from "node:path";
|
|
3592
|
+
var dlog = (msg) => log("skillify-migrate", msg);
|
|
3593
|
+
var attempted = false;
|
|
3594
|
+
function migrateLegacyStateDir() {
|
|
3595
|
+
if (process.env.HIVEMIND_STATE_DIR?.trim())
|
|
3596
|
+
return;
|
|
3597
|
+
if (attempted)
|
|
3598
|
+
return;
|
|
3599
|
+
attempted = true;
|
|
3600
|
+
const current = getStateDir();
|
|
3601
|
+
const legacy = join16(dirname8(current), "skilify");
|
|
3602
|
+
if (!existsSync8(legacy))
|
|
3603
|
+
return;
|
|
3604
|
+
if (existsSync8(current))
|
|
3605
|
+
return;
|
|
3606
|
+
try {
|
|
3607
|
+
renameSync6(legacy, current);
|
|
3608
|
+
dlog(`migrated ${legacy} -> ${current}`);
|
|
3609
|
+
} catch (err) {
|
|
3610
|
+
const code = err.code;
|
|
3611
|
+
if (code === "EXDEV" || code === "EPERM" || code === "ENOENT" || code === "EEXIST" || code === "ENOTEMPTY") {
|
|
3612
|
+
dlog(`migration skipped (${code}); legacy dir left as-is or another process handled it`);
|
|
3613
|
+
return;
|
|
3614
|
+
}
|
|
3615
|
+
throw err;
|
|
3616
|
+
}
|
|
3617
|
+
}
|
|
3618
|
+
|
|
3619
|
+
// dist/src/skillify/manifest.js
|
|
3620
|
+
function emptyManifest() {
|
|
3621
|
+
return { version: 1, entries: [] };
|
|
3622
|
+
}
|
|
3623
|
+
function manifestPath() {
|
|
3624
|
+
return join17(getStateDir(), "pulled.json");
|
|
3625
|
+
}
|
|
3626
|
+
function loadManifest(path2 = manifestPath()) {
|
|
3627
|
+
migrateLegacyStateDir();
|
|
3628
|
+
if (!existsSync9(path2))
|
|
3629
|
+
return emptyManifest();
|
|
3630
|
+
let raw;
|
|
3631
|
+
try {
|
|
3632
|
+
raw = readFileSync10(path2, "utf-8");
|
|
3633
|
+
} catch {
|
|
3634
|
+
return emptyManifest();
|
|
3635
|
+
}
|
|
3636
|
+
try {
|
|
3637
|
+
const parsed = JSON.parse(raw);
|
|
3638
|
+
if (!parsed || typeof parsed !== "object")
|
|
3639
|
+
return emptyManifest();
|
|
3640
|
+
if (parsed.version !== 1 || !Array.isArray(parsed.entries))
|
|
3641
|
+
return emptyManifest();
|
|
3642
|
+
const entries = [];
|
|
3643
|
+
for (const e of parsed.entries) {
|
|
3644
|
+
if (!e || typeof e !== "object")
|
|
3645
|
+
continue;
|
|
3646
|
+
if (typeof e.dirName !== "string" || !e.dirName)
|
|
3647
|
+
continue;
|
|
3648
|
+
if (e.dirName.includes("/") || e.dirName.includes("\\") || e.dirName.includes(".."))
|
|
3649
|
+
continue;
|
|
3650
|
+
if (typeof e.name !== "string" || !e.name)
|
|
3651
|
+
continue;
|
|
3652
|
+
if (typeof e.author !== "string")
|
|
3653
|
+
continue;
|
|
3654
|
+
if (typeof e.installRoot !== "string" || !e.installRoot)
|
|
3655
|
+
continue;
|
|
3656
|
+
if (e.install !== "global" && e.install !== "project")
|
|
3657
|
+
continue;
|
|
3658
|
+
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)
|
|
3659
|
+
!p.includes("..")) : [];
|
|
3660
|
+
entries.push({
|
|
3661
|
+
dirName: e.dirName,
|
|
3662
|
+
name: e.name,
|
|
3663
|
+
author: e.author,
|
|
3664
|
+
projectKey: typeof e.projectKey === "string" ? e.projectKey : "",
|
|
3665
|
+
remoteVersion: typeof e.remoteVersion === "number" ? e.remoteVersion : 1,
|
|
3666
|
+
install: e.install,
|
|
3667
|
+
installRoot: e.installRoot,
|
|
3668
|
+
pulledAt: typeof e.pulledAt === "string" ? e.pulledAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
3669
|
+
symlinks
|
|
3670
|
+
});
|
|
3671
|
+
}
|
|
3672
|
+
return { version: 1, entries };
|
|
3673
|
+
} catch {
|
|
3674
|
+
return emptyManifest();
|
|
3675
|
+
}
|
|
3676
|
+
}
|
|
3677
|
+
|
|
3678
|
+
// dist/src/skillify/skillopt-env.js
|
|
3679
|
+
var SKILLOPT_ENV = {
|
|
3680
|
+
/** User-set kill switch: "1" disables the whole trigger. */
|
|
3681
|
+
DISABLED: "HIVEMIND_SKILLOPT_DISABLED",
|
|
3682
|
+
/** Recursion guard the trigger sets on the spawned worker so the worker can't re-arm. */
|
|
3683
|
+
WORKER: "HIVEMIND_SKILLOPT_WORKER",
|
|
3684
|
+
/** Worker inputs, handed trigger → worker via the child env. */
|
|
3685
|
+
SESSION: "HIVEMIND_SKILLOPT_SESSION",
|
|
3686
|
+
SKILL: "HIVEMIND_SKILLOPT_SKILL",
|
|
3687
|
+
REACTION: "HIVEMIND_SKILLOPT_REACTION",
|
|
3688
|
+
TOOL_USE_ID: "HIVEMIND_SKILLOPT_TOOL_USE_ID",
|
|
3689
|
+
/** Which agent's CLI runs the judge/proposer (claude_code/codex/hermes/cursor/pi). */
|
|
3690
|
+
AGENT: "HIVEMIND_SKILLOPT_AGENT",
|
|
3691
|
+
/** K-message judgment-window size override. */
|
|
3692
|
+
JUDGE_WINDOW: "HIVEMIND_SKILLOPT_JUDGE_WINDOW"
|
|
3693
|
+
};
|
|
3694
|
+
|
|
3695
|
+
// dist/src/skillify/skillopt-trigger.js
|
|
3696
|
+
var DEFAULT_JUDGE_WINDOW = 3;
|
|
3697
|
+
function judgeWindow(env = process.env) {
|
|
3698
|
+
const n = Number(env[SKILLOPT_ENV.JUDGE_WINDOW]);
|
|
3699
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : DEFAULT_JUDGE_WINDOW;
|
|
3700
|
+
}
|
|
3701
|
+
function defaultIsOrgSkill(skillRef) {
|
|
3702
|
+
try {
|
|
3703
|
+
return loadManifest().entries.some((e) => e.dirName === skillRef);
|
|
3704
|
+
} catch {
|
|
3705
|
+
return false;
|
|
3706
|
+
}
|
|
3707
|
+
}
|
|
3708
|
+
function pendingFile(sessionId) {
|
|
3709
|
+
const safe = sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 200);
|
|
3710
|
+
return path.join(getStateDir(), "skillopt", "pending", `${safe}.json`);
|
|
3711
|
+
}
|
|
3712
|
+
var fileStore = {
|
|
3713
|
+
load(sessionId) {
|
|
3714
|
+
try {
|
|
3715
|
+
return JSON.parse(fs.readFileSync(pendingFile(sessionId), "utf8"));
|
|
3716
|
+
} catch {
|
|
3717
|
+
return null;
|
|
3718
|
+
}
|
|
3719
|
+
},
|
|
3720
|
+
save(sessionId, p) {
|
|
3721
|
+
try {
|
|
3722
|
+
const f = pendingFile(sessionId);
|
|
3723
|
+
if (p === null) {
|
|
3724
|
+
try {
|
|
3725
|
+
fs.unlinkSync(f);
|
|
3726
|
+
} catch {
|
|
3727
|
+
}
|
|
3728
|
+
return;
|
|
3729
|
+
}
|
|
3730
|
+
fs.mkdirSync(path.dirname(f), { recursive: true });
|
|
3731
|
+
const tmp = `${f}.${process.pid}.tmp`;
|
|
3732
|
+
fs.writeFileSync(tmp, JSON.stringify(p));
|
|
3733
|
+
fs.renameSync(tmp, f);
|
|
3734
|
+
} catch {
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3737
|
+
};
|
|
3738
|
+
function markSkillPending(sessionId, skillRef, toolUseId, deps = {}) {
|
|
3739
|
+
if (!sessionId || !skillRef)
|
|
3740
|
+
return false;
|
|
3741
|
+
if (!splitOrgSkill(skillRef))
|
|
3742
|
+
return false;
|
|
3743
|
+
if (!(deps.isOrgSkill ?? defaultIsOrgSkill)(skillRef))
|
|
3744
|
+
return false;
|
|
3745
|
+
(deps.store ?? fileStore).save(sessionId, { skill: skillRef, budget: judgeWindow(deps.env ?? process.env), toolUseId });
|
|
3746
|
+
return true;
|
|
3747
|
+
}
|
|
3748
|
+
|
|
3749
|
+
// dist/src/hooks/shared/skillopt-hook.js
|
|
3750
|
+
function skillRefFromSkillFileRead(toolName, toolInput) {
|
|
3751
|
+
if (/^read$/i.test(toolName))
|
|
3752
|
+
return pathToSkillRef(toolInput?.path);
|
|
3753
|
+
return pathToSkillRef(toolInput?.command);
|
|
3754
|
+
}
|
|
3755
|
+
function armSkillOptOnSkillUse(sessionId, toolName, toolInput, toolUseId) {
|
|
3756
|
+
try {
|
|
3757
|
+
if (process.env[SKILLOPT_ENV.DISABLED] === "1")
|
|
3758
|
+
return;
|
|
3759
|
+
let ref = null;
|
|
3760
|
+
if (toolName === "Skill") {
|
|
3761
|
+
const s = toolInput?.skill;
|
|
3762
|
+
ref = typeof s === "string" ? s : null;
|
|
3763
|
+
} else {
|
|
3764
|
+
ref = skillRefFromSkillFileRead(toolName, toolInput);
|
|
3765
|
+
}
|
|
3766
|
+
if (ref)
|
|
3767
|
+
markSkillPending(sessionId, ref, toolUseId);
|
|
3768
|
+
} catch {
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
|
|
3549
3772
|
// dist/src/hooks/hermes/pre-tool-use.js
|
|
3550
3773
|
var log5 = (msg) => log("hermes-pre-tool-use", msg);
|
|
3551
3774
|
async function main() {
|
|
3552
3775
|
const input = await readStdin();
|
|
3776
|
+
armSkillOptOnSkillUse(input.session_id ?? "", input.tool_name ?? "", input.tool_input);
|
|
3553
3777
|
if (input.tool_name !== "terminal")
|
|
3554
3778
|
return;
|
|
3555
3779
|
const ti = input.tool_input;
|