@deeplake/hivemind 0.7.79 → 0.7.80
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 +9 -0
- package/codex/bundle/capture.js +176 -43
- package/codex/bundle/pre-tool-use.js +316 -93
- package/codex/bundle/skillopt-worker.js +2057 -0
- package/hermes/bundle/capture.js +168 -45
- package/hermes/bundle/pre-tool-use.js +272 -52
- package/hermes/bundle/skillopt-worker.js +2057 -0
- package/openclaw/dist/index.js +1 -1
- 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
|
@@ -367,38 +367,38 @@ function readQueue() {
|
|
|
367
367
|
return { queue: [] };
|
|
368
368
|
}
|
|
369
369
|
}
|
|
370
|
-
function _isQueuePathInsideHome(
|
|
371
|
-
const r = resolve(
|
|
370
|
+
function _isQueuePathInsideHome(path2, home) {
|
|
371
|
+
const r = resolve(path2);
|
|
372
372
|
const h = resolve(home);
|
|
373
373
|
return r.startsWith(h + "/") || r === h;
|
|
374
374
|
}
|
|
375
375
|
function writeQueue(q) {
|
|
376
|
-
const
|
|
376
|
+
const path2 = queuePath();
|
|
377
377
|
const home = resolve(homedir3());
|
|
378
|
-
if (!_isQueuePathInsideHome(
|
|
379
|
-
throw new Error(`notifications-queue write blocked: ${
|
|
378
|
+
if (!_isQueuePathInsideHome(path2, home)) {
|
|
379
|
+
throw new Error(`notifications-queue write blocked: ${path2} is outside ${home}`);
|
|
380
380
|
}
|
|
381
381
|
mkdirSync(join3(home, ".deeplake"), { recursive: true, mode: 448 });
|
|
382
|
-
const tmp = `${
|
|
382
|
+
const tmp = `${path2}.${process.pid}.tmp`;
|
|
383
383
|
writeFileSync(tmp, JSON.stringify(q, null, 2), { mode: 384 });
|
|
384
|
-
renameSync(tmp,
|
|
384
|
+
renameSync(tmp, path2);
|
|
385
385
|
}
|
|
386
386
|
async function withQueueLock(fn) {
|
|
387
|
-
const
|
|
387
|
+
const path2 = lockPath();
|
|
388
388
|
mkdirSync(join3(homedir3(), ".deeplake"), { recursive: true, mode: 448 });
|
|
389
389
|
let fd = null;
|
|
390
390
|
for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
|
|
391
391
|
try {
|
|
392
|
-
fd = openSync(
|
|
392
|
+
fd = openSync(path2, "wx", 384);
|
|
393
393
|
break;
|
|
394
394
|
} catch (e) {
|
|
395
395
|
const code = e.code;
|
|
396
396
|
if (code !== "EEXIST")
|
|
397
397
|
throw e;
|
|
398
398
|
try {
|
|
399
|
-
const age = Date.now() - statSync(
|
|
399
|
+
const age = Date.now() - statSync(path2).mtimeMs;
|
|
400
400
|
if (age > LOCK_STALE_MS) {
|
|
401
|
-
unlinkSync(
|
|
401
|
+
unlinkSync(path2);
|
|
402
402
|
continue;
|
|
403
403
|
}
|
|
404
404
|
} catch {
|
|
@@ -419,7 +419,7 @@ async function withQueueLock(fn) {
|
|
|
419
419
|
} catch {
|
|
420
420
|
}
|
|
421
421
|
try {
|
|
422
|
-
unlinkSync(
|
|
422
|
+
unlinkSync(path2);
|
|
423
423
|
} catch {
|
|
424
424
|
}
|
|
425
425
|
}
|
|
@@ -695,9 +695,9 @@ var DeeplakeApi = class {
|
|
|
695
695
|
}
|
|
696
696
|
}
|
|
697
697
|
/** Update specific columns on a row by path. */
|
|
698
|
-
async updateColumns(
|
|
698
|
+
async updateColumns(path2, columns) {
|
|
699
699
|
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(
|
|
700
|
+
await this.query(`UPDATE "${this.tableName}" SET ${setClauses} WHERE path = '${sqlStr(path2)}'`);
|
|
701
701
|
}
|
|
702
702
|
// ── Convenience ─────────────────────────────────────────────────────────────
|
|
703
703
|
/** Create a BM25 search index on a column. */
|
|
@@ -1129,8 +1129,8 @@ function formatToolCall(obj) {
|
|
|
1129
1129
|
input: ${formatToolInput(obj?.tool_input)}
|
|
1130
1130
|
response: ${formatToolResponse(obj?.tool_response, obj?.tool_input, obj?.tool_name)}`;
|
|
1131
1131
|
}
|
|
1132
|
-
function normalizeContent(
|
|
1133
|
-
if (!
|
|
1132
|
+
function normalizeContent(path2, raw) {
|
|
1133
|
+
if (!path2.includes("/sessions/"))
|
|
1134
1134
|
return raw;
|
|
1135
1135
|
if (!raw || raw[0] !== "{")
|
|
1136
1136
|
return raw;
|
|
@@ -1857,13 +1857,13 @@ var _migrated = false;
|
|
|
1857
1857
|
function readUserConfig() {
|
|
1858
1858
|
if (_cache !== null)
|
|
1859
1859
|
return _cache;
|
|
1860
|
-
const
|
|
1861
|
-
if (!existsSync4(
|
|
1860
|
+
const path2 = _configPath();
|
|
1861
|
+
if (!existsSync4(path2)) {
|
|
1862
1862
|
_cache = {};
|
|
1863
1863
|
return _cache;
|
|
1864
1864
|
}
|
|
1865
1865
|
try {
|
|
1866
|
-
const raw = readFileSync6(
|
|
1866
|
+
const raw = readFileSync6(path2, "utf-8");
|
|
1867
1867
|
const parsed = JSON.parse(raw);
|
|
1868
1868
|
_cache = isPlainObject(parsed) ? parsed : {};
|
|
1869
1869
|
} catch {
|
|
@@ -1874,13 +1874,13 @@ function readUserConfig() {
|
|
|
1874
1874
|
function writeUserConfig(patch) {
|
|
1875
1875
|
const current = readUserConfig();
|
|
1876
1876
|
const merged = deepMerge(current, patch);
|
|
1877
|
-
const
|
|
1878
|
-
const dir = dirname(
|
|
1877
|
+
const path2 = _configPath();
|
|
1878
|
+
const dir = dirname(path2);
|
|
1879
1879
|
if (!existsSync4(dir))
|
|
1880
1880
|
mkdirSync4(dir, { recursive: true });
|
|
1881
|
-
const tmp = `${
|
|
1881
|
+
const tmp = `${path2}.tmp.${process.pid}`;
|
|
1882
1882
|
writeFileSync4(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
1883
|
-
renameSync2(tmp,
|
|
1883
|
+
renameSync2(tmp, path2);
|
|
1884
1884
|
_cache = merged;
|
|
1885
1885
|
return merged;
|
|
1886
1886
|
}
|
|
@@ -2332,18 +2332,18 @@ function lastBuildPath(baseDir, worktreeId) {
|
|
|
2332
2332
|
return join10(baseDir, ".last-build.json");
|
|
2333
2333
|
}
|
|
2334
2334
|
function readLastBuild(baseDir, worktreeId) {
|
|
2335
|
-
let
|
|
2336
|
-
if (!existsSync5(
|
|
2335
|
+
let path2 = lastBuildPath(baseDir, worktreeId);
|
|
2336
|
+
if (!existsSync5(path2)) {
|
|
2337
2337
|
if (worktreeId === void 0)
|
|
2338
2338
|
return null;
|
|
2339
2339
|
const legacy = lastBuildPath(baseDir, void 0);
|
|
2340
2340
|
if (!existsSync5(legacy))
|
|
2341
2341
|
return null;
|
|
2342
|
-
|
|
2342
|
+
path2 = legacy;
|
|
2343
2343
|
}
|
|
2344
2344
|
let raw;
|
|
2345
2345
|
try {
|
|
2346
|
-
raw = readFileSync7(
|
|
2346
|
+
raw = readFileSync7(path2, "utf8");
|
|
2347
2347
|
} catch {
|
|
2348
2348
|
return null;
|
|
2349
2349
|
}
|
|
@@ -2952,18 +2952,18 @@ function workTreeIdFor(cwd) {
|
|
|
2952
2952
|
return createHash3("sha256").update(cwd).digest("hex").slice(0, 16);
|
|
2953
2953
|
}
|
|
2954
2954
|
function handleGraphVfs(subpath, cwd) {
|
|
2955
|
-
const
|
|
2956
|
-
if (
|
|
2955
|
+
const path2 = subpath.replace(/^\/+/, "");
|
|
2956
|
+
if (path2 === "" || path2 === "/") {
|
|
2957
2957
|
return { kind: "ok", body: dirListing() };
|
|
2958
2958
|
}
|
|
2959
|
-
if (
|
|
2959
|
+
if (path2 === "index.md" || path2 === "index") {
|
|
2960
2960
|
return loadSnapshotOrError(cwd, (snap, baseDir) => ({
|
|
2961
2961
|
kind: "ok",
|
|
2962
2962
|
body: renderIndex(snap, baseDir, cwd)
|
|
2963
2963
|
}));
|
|
2964
2964
|
}
|
|
2965
|
-
if (
|
|
2966
|
-
const pattern =
|
|
2965
|
+
if (path2.startsWith("find/")) {
|
|
2966
|
+
const pattern = path2.slice("find/".length);
|
|
2967
2967
|
if (pattern === "") {
|
|
2968
2968
|
return { kind: "not-found", message: "find/ requires a pattern: cat memory/graph/find/<keyword>" };
|
|
2969
2969
|
}
|
|
@@ -2972,8 +2972,8 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
2972
2972
|
body: renderFind(snap, pattern, baseDir, workTreeIdFor(cwd))
|
|
2973
2973
|
}));
|
|
2974
2974
|
}
|
|
2975
|
-
if (
|
|
2976
|
-
const key =
|
|
2975
|
+
if (path2.startsWith("show/")) {
|
|
2976
|
+
const key = path2.slice("show/".length);
|
|
2977
2977
|
if (key === "") {
|
|
2978
2978
|
return { kind: "not-found", message: "show/ requires a handle or pattern" };
|
|
2979
2979
|
}
|
|
@@ -2982,8 +2982,8 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
2982
2982
|
body: renderShow(snap, key, baseDir, workTreeIdFor(cwd))
|
|
2983
2983
|
}));
|
|
2984
2984
|
}
|
|
2985
|
-
if (
|
|
2986
|
-
const pattern =
|
|
2985
|
+
if (path2.startsWith("query/")) {
|
|
2986
|
+
const pattern = path2.slice("query/".length);
|
|
2987
2987
|
if (pattern === "") {
|
|
2988
2988
|
return { kind: "not-found", message: "query/ requires a pattern: cat memory/graph/query/<keyword>" };
|
|
2989
2989
|
}
|
|
@@ -2992,28 +2992,28 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
2992
2992
|
body: renderQuery(snap, pattern, baseDir, workTreeIdFor(cwd))
|
|
2993
2993
|
}));
|
|
2994
2994
|
}
|
|
2995
|
-
if (
|
|
2996
|
-
const pattern =
|
|
2995
|
+
if (path2.startsWith("impact/")) {
|
|
2996
|
+
const pattern = path2.slice("impact/".length);
|
|
2997
2997
|
if (pattern === "") {
|
|
2998
2998
|
return { kind: "not-found", message: "impact/ requires a pattern: cat memory/graph/impact/<symbol>" };
|
|
2999
2999
|
}
|
|
3000
3000
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderImpact(snap, pattern) }));
|
|
3001
3001
|
}
|
|
3002
|
-
if (
|
|
3003
|
-
const file =
|
|
3002
|
+
if (path2.startsWith("neighborhood/")) {
|
|
3003
|
+
const file = path2.slice("neighborhood/".length);
|
|
3004
3004
|
if (file === "") {
|
|
3005
3005
|
return { kind: "not-found", message: "neighborhood/ requires a file path: cat memory/graph/neighborhood/<file>" };
|
|
3006
3006
|
}
|
|
3007
3007
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderNeighborhood(snap, file) }));
|
|
3008
3008
|
}
|
|
3009
|
-
if (
|
|
3009
|
+
if (path2 === "layers" || path2 === "layers/" || path2 === "layers/index.md") {
|
|
3010
3010
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderLayers(snap) }));
|
|
3011
3011
|
}
|
|
3012
|
-
if (
|
|
3012
|
+
if (path2 === "tour" || path2 === "tour/" || path2 === "tour/index.md") {
|
|
3013
3013
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderTour(snap) }));
|
|
3014
3014
|
}
|
|
3015
|
-
if (
|
|
3016
|
-
const rest =
|
|
3015
|
+
if (path2.startsWith("path/")) {
|
|
3016
|
+
const rest = path2.slice("path/".length);
|
|
3017
3017
|
const slash = rest.indexOf("/");
|
|
3018
3018
|
if (slash <= 0 || slash === rest.length - 1) {
|
|
3019
3019
|
return { kind: "not-found", message: "path/ needs two patterns: cat memory/graph/path/<from>/<to> (each a symbol-name substring, no slash)" };
|
|
@@ -3024,7 +3024,7 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
3024
3024
|
}
|
|
3025
3025
|
return {
|
|
3026
3026
|
kind: "not-found",
|
|
3027
|
-
message: `Unknown endpoint: graph/${
|
|
3027
|
+
message: `Unknown endpoint: graph/${path2}
|
|
3028
3028
|
Available: index.md, find/<pattern>, query/<pattern>, show/<handle-or-pattern>, impact/<pattern>, neighborhood/<file>, layers, tour, path/<from>/<to>`
|
|
3029
3029
|
};
|
|
3030
3030
|
}
|
|
@@ -3423,22 +3423,22 @@ function handlesPath(baseDir, worktreeId) {
|
|
|
3423
3423
|
return join13(baseDir, "worktrees", worktreeId, ".find-handles.json");
|
|
3424
3424
|
}
|
|
3425
3425
|
function saveHandles(baseDir, worktreeId, ids, pattern) {
|
|
3426
|
-
const
|
|
3426
|
+
const path2 = handlesPath(baseDir, worktreeId);
|
|
3427
3427
|
const payload = { pattern, ts: Date.now(), ids };
|
|
3428
3428
|
try {
|
|
3429
|
-
mkdirSync8(dirname6(
|
|
3430
|
-
const tmp = `${
|
|
3429
|
+
mkdirSync8(dirname6(path2), { recursive: true });
|
|
3430
|
+
const tmp = `${path2}.tmp.${process.pid}.${Date.now()}`;
|
|
3431
3431
|
writeFileSync7(tmp, JSON.stringify(payload));
|
|
3432
|
-
renameSync5(tmp,
|
|
3432
|
+
renameSync5(tmp, path2);
|
|
3433
3433
|
} catch {
|
|
3434
3434
|
}
|
|
3435
3435
|
}
|
|
3436
3436
|
function loadHandles(baseDir, worktreeId) {
|
|
3437
|
-
const
|
|
3438
|
-
if (!existsSync7(
|
|
3437
|
+
const path2 = handlesPath(baseDir, worktreeId);
|
|
3438
|
+
if (!existsSync7(path2))
|
|
3439
3439
|
return null;
|
|
3440
3440
|
try {
|
|
3441
|
-
const parsed = JSON.parse(readFileSync9(
|
|
3441
|
+
const parsed = JSON.parse(readFileSync9(path2, "utf8"));
|
|
3442
3442
|
if (parsed === null || typeof parsed !== "object")
|
|
3443
3443
|
return null;
|
|
3444
3444
|
const o = parsed;
|
|
@@ -3529,8 +3529,8 @@ function tryGraphRead(rewrittenCommand, cwd) {
|
|
|
3529
3529
|
}
|
|
3530
3530
|
|
|
3531
3531
|
// dist/src/hooks/virtual-table-query.js
|
|
3532
|
-
function normalizeSessionPart(
|
|
3533
|
-
return normalizeContent(
|
|
3532
|
+
function normalizeSessionPart(path2, content) {
|
|
3533
|
+
return normalizeContent(path2, content);
|
|
3534
3534
|
}
|
|
3535
3535
|
var INDEX_LIMIT_PER_SECTION = 50;
|
|
3536
3536
|
function buildVirtualIndexContent(summaryRows, sessionRows = [], opts = {}) {
|
|
@@ -3597,7 +3597,7 @@ function buildUnionQuery(memoryQuery, sessionsQuery) {
|
|
|
3597
3597
|
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
3598
|
}
|
|
3599
3599
|
function buildInList(paths) {
|
|
3600
|
-
return paths.map((
|
|
3600
|
+
return paths.map((path2) => `'${sqlStr(path2)}'`).join(", ");
|
|
3601
3601
|
}
|
|
3602
3602
|
function buildDirFilter(dirs) {
|
|
3603
3603
|
const cleaned = [...new Set(dirs.map((dir) => dir.replace(/\/+$/, "") || "/"))];
|
|
@@ -3620,7 +3620,7 @@ async function queryUnionRows(api, memoryQuery, sessionsQuery) {
|
|
|
3620
3620
|
}
|
|
3621
3621
|
async function readVirtualPathContents(api, memoryTable, sessionsTable, virtualPaths) {
|
|
3622
3622
|
const uniquePaths = [...new Set(virtualPaths)];
|
|
3623
|
-
const result = new Map(uniquePaths.map((
|
|
3623
|
+
const result = new Map(uniquePaths.map((path2) => [path2, null]));
|
|
3624
3624
|
if (uniquePaths.length === 0)
|
|
3625
3625
|
return result;
|
|
3626
3626
|
const inList = buildInList(uniquePaths);
|
|
@@ -3628,27 +3628,27 @@ async function readVirtualPathContents(api, memoryTable, sessionsTable, virtualP
|
|
|
3628
3628
|
const memoryHits = /* @__PURE__ */ new Map();
|
|
3629
3629
|
const sessionHits = /* @__PURE__ */ new Map();
|
|
3630
3630
|
for (const row of rows) {
|
|
3631
|
-
const
|
|
3631
|
+
const path2 = row["path"];
|
|
3632
3632
|
const content = row["content"];
|
|
3633
3633
|
const sourceOrder = Number(row["source_order"] ?? 0);
|
|
3634
|
-
if (typeof
|
|
3634
|
+
if (typeof path2 !== "string" || typeof content !== "string")
|
|
3635
3635
|
continue;
|
|
3636
3636
|
if (sourceOrder === 0) {
|
|
3637
|
-
memoryHits.set(
|
|
3637
|
+
memoryHits.set(path2, content);
|
|
3638
3638
|
} else {
|
|
3639
|
-
const current = sessionHits.get(
|
|
3640
|
-
current.push(normalizeSessionPart(
|
|
3641
|
-
sessionHits.set(
|
|
3639
|
+
const current = sessionHits.get(path2) ?? [];
|
|
3640
|
+
current.push(normalizeSessionPart(path2, content));
|
|
3641
|
+
sessionHits.set(path2, current);
|
|
3642
3642
|
}
|
|
3643
3643
|
}
|
|
3644
|
-
for (const
|
|
3645
|
-
if (memoryHits.has(
|
|
3646
|
-
result.set(
|
|
3644
|
+
for (const path2 of uniquePaths) {
|
|
3645
|
+
if (memoryHits.has(path2)) {
|
|
3646
|
+
result.set(path2, memoryHits.get(path2) ?? null);
|
|
3647
3647
|
continue;
|
|
3648
3648
|
}
|
|
3649
|
-
const sessionParts = sessionHits.get(
|
|
3649
|
+
const sessionParts = sessionHits.get(path2) ?? [];
|
|
3650
3650
|
if (sessionParts.length > 0) {
|
|
3651
|
-
result.set(
|
|
3651
|
+
result.set(path2, sessionParts.join("\n"));
|
|
3652
3652
|
}
|
|
3653
3653
|
}
|
|
3654
3654
|
if (result.get("/index.md") === null && uniquePaths.includes("/index.md")) {
|
|
@@ -3675,12 +3675,12 @@ async function listVirtualPathRowsForDirs(api, memoryTable, sessionsTable, dirs)
|
|
|
3675
3675
|
for (const dir of uniqueDirs)
|
|
3676
3676
|
byDir.set(dir, []);
|
|
3677
3677
|
for (const row of deduped) {
|
|
3678
|
-
const
|
|
3679
|
-
if (typeof
|
|
3678
|
+
const path2 = row["path"];
|
|
3679
|
+
if (typeof path2 !== "string")
|
|
3680
3680
|
continue;
|
|
3681
3681
|
for (const dir of uniqueDirs) {
|
|
3682
3682
|
const prefix = dir === "/" ? "/" : `${dir}/`;
|
|
3683
|
-
if (dir === "/" ||
|
|
3683
|
+
if (dir === "/" || path2.startsWith(prefix)) {
|
|
3684
3684
|
byDir.get(dir)?.push(row);
|
|
3685
3685
|
}
|
|
3686
3686
|
}
|
|
@@ -3703,10 +3703,10 @@ function dedupeRowsByPath(rows) {
|
|
|
3703
3703
|
const seen = /* @__PURE__ */ new Set();
|
|
3704
3704
|
const unique = [];
|
|
3705
3705
|
for (const row of rows) {
|
|
3706
|
-
const
|
|
3707
|
-
if (!
|
|
3706
|
+
const path2 = typeof row["path"] === "string" ? row["path"] : "";
|
|
3707
|
+
if (!path2 || seen.has(path2))
|
|
3708
3708
|
continue;
|
|
3709
|
-
seen.add(
|
|
3709
|
+
seen.add(path2);
|
|
3710
3710
|
unique.push(row);
|
|
3711
3711
|
}
|
|
3712
3712
|
return unique;
|
|
@@ -3952,12 +3952,12 @@ function parseCompiledSegment(segment) {
|
|
|
3952
3952
|
return null;
|
|
3953
3953
|
if (headTokens[1] === "-n" && headTokens.length < 4 || /^-\d+$/.test(headTokens[1] ?? "") && headTokens.length < 3 || headTokens.length === 2 && /^-?\d+$/.test(headTokens[1] ?? ""))
|
|
3954
3954
|
return null;
|
|
3955
|
-
const
|
|
3956
|
-
if (
|
|
3955
|
+
const path2 = headTokens[headTokens.length - 1];
|
|
3956
|
+
if (path2 === "head" || path2 === "tail" || path2 === "-n")
|
|
3957
3957
|
return null;
|
|
3958
3958
|
return {
|
|
3959
3959
|
kind: "cat",
|
|
3960
|
-
paths: expandBraceToken(
|
|
3960
|
+
paths: expandBraceToken(path2),
|
|
3961
3961
|
lineLimit: parsed.lineLimit,
|
|
3962
3962
|
fromEnd: parsed.fromEnd,
|
|
3963
3963
|
countLines: false,
|
|
@@ -4068,10 +4068,10 @@ function renderDirectoryListing(dir, rows, longFormat) {
|
|
|
4068
4068
|
const entries = /* @__PURE__ */ new Map();
|
|
4069
4069
|
const prefix = dir === "/" ? "/" : `${dir}/`;
|
|
4070
4070
|
for (const row of rows) {
|
|
4071
|
-
const
|
|
4072
|
-
if (!
|
|
4071
|
+
const path2 = row["path"];
|
|
4072
|
+
if (!path2.startsWith(prefix) && dir !== "/")
|
|
4073
4073
|
continue;
|
|
4074
|
-
const rest = dir === "/" ?
|
|
4074
|
+
const rest = dir === "/" ? path2.slice(1) : path2.slice(prefix.length);
|
|
4075
4075
|
const slash = rest.indexOf("/");
|
|
4076
4076
|
const name = slash === -1 ? rest : rest.slice(0, slash);
|
|
4077
4077
|
if (!name)
|
|
@@ -4115,8 +4115,8 @@ async function executeCompiledBashCommand(api, memoryTable, sessionsTable, cmd,
|
|
|
4115
4115
|
}
|
|
4116
4116
|
if (segment.kind === "cat") {
|
|
4117
4117
|
const contents = [];
|
|
4118
|
-
for (const
|
|
4119
|
-
const content = contentMap.get(
|
|
4118
|
+
for (const path2 of segment.paths) {
|
|
4119
|
+
const content = contentMap.get(path2) ?? null;
|
|
4120
4120
|
if (content === null) {
|
|
4121
4121
|
if (segment.ignoreMissing)
|
|
4122
4122
|
continue;
|
|
@@ -4153,11 +4153,11 @@ async function executeCompiledBashCommand(api, memoryTable, sessionsTable, cmd,
|
|
|
4153
4153
|
continue;
|
|
4154
4154
|
}
|
|
4155
4155
|
const candidateContents = await readVirtualPathContentsFn(api, memoryTable, sessionsTable, candidatePaths);
|
|
4156
|
-
const matched = refineGrepMatches(candidatePaths.flatMap((
|
|
4157
|
-
const content = candidateContents.get(
|
|
4156
|
+
const matched = refineGrepMatches(candidatePaths.flatMap((path2) => {
|
|
4157
|
+
const content = candidateContents.get(path2);
|
|
4158
4158
|
if (content === null || content === void 0)
|
|
4159
4159
|
return [];
|
|
4160
|
-
return [{ path, content: normalizeContent(
|
|
4160
|
+
return [{ path: path2, content: normalizeContent(path2, content) }];
|
|
4161
4161
|
}), segment.params);
|
|
4162
4162
|
const limited = segment.lineLimit > 0 ? matched.slice(0, segment.lineLimit) : matched;
|
|
4163
4163
|
outputs.push(limited.join("\n") || "(no matches)");
|
|
@@ -4372,6 +4372,225 @@ function rewritePaths(cmd) {
|
|
|
4372
4372
|
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
4373
|
}
|
|
4374
4374
|
|
|
4375
|
+
// dist/src/skillify/skillopt-trigger.js
|
|
4376
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
4377
|
+
import fs from "node:fs";
|
|
4378
|
+
import path from "node:path";
|
|
4379
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
4380
|
+
|
|
4381
|
+
// dist/src/skillify/state-dir.js
|
|
4382
|
+
import { homedir as homedir11 } from "node:os";
|
|
4383
|
+
import { join as join16 } from "node:path";
|
|
4384
|
+
function getStateDir() {
|
|
4385
|
+
const override = process.env.HIVEMIND_STATE_DIR?.trim();
|
|
4386
|
+
return override && override.length > 0 ? override : join16(homedir11(), ".deeplake", "state", "skillify");
|
|
4387
|
+
}
|
|
4388
|
+
|
|
4389
|
+
// dist/src/skillify/skill-invocations.js
|
|
4390
|
+
function pathToSkillRef(s) {
|
|
4391
|
+
if (typeof s !== "string")
|
|
4392
|
+
return null;
|
|
4393
|
+
const m = s.match(/\/skills\/(?:[^/\s"'`]+\/)*([^/\s"'`]+)\/SKILL\.md/);
|
|
4394
|
+
return m ? m[1] : null;
|
|
4395
|
+
}
|
|
4396
|
+
function splitOrgSkill(skill) {
|
|
4397
|
+
if (skill.includes(":"))
|
|
4398
|
+
return null;
|
|
4399
|
+
if (skill.includes("/") || skill.includes("\\") || skill.includes(".."))
|
|
4400
|
+
return null;
|
|
4401
|
+
const i = skill.lastIndexOf("--");
|
|
4402
|
+
if (i <= 0 || i + 2 >= skill.length)
|
|
4403
|
+
return null;
|
|
4404
|
+
return { name: skill.slice(0, i), author: skill.slice(i + 2) };
|
|
4405
|
+
}
|
|
4406
|
+
|
|
4407
|
+
// dist/src/skillify/manifest.js
|
|
4408
|
+
import { existsSync as existsSync9, lstatSync, mkdirSync as mkdirSync10, readFileSync as readFileSync11, renameSync as renameSync7, unlinkSync as unlinkSync4, writeFileSync as writeFileSync9 } from "node:fs";
|
|
4409
|
+
import { dirname as dirname8, join as join18 } from "node:path";
|
|
4410
|
+
|
|
4411
|
+
// dist/src/skillify/legacy-migration.js
|
|
4412
|
+
import { existsSync as existsSync8, renameSync as renameSync6 } from "node:fs";
|
|
4413
|
+
import { dirname as dirname7, join as join17 } from "node:path";
|
|
4414
|
+
var dlog = (msg) => log("skillify-migrate", msg);
|
|
4415
|
+
var attempted = false;
|
|
4416
|
+
function migrateLegacyStateDir() {
|
|
4417
|
+
if (process.env.HIVEMIND_STATE_DIR?.trim())
|
|
4418
|
+
return;
|
|
4419
|
+
if (attempted)
|
|
4420
|
+
return;
|
|
4421
|
+
attempted = true;
|
|
4422
|
+
const current = getStateDir();
|
|
4423
|
+
const legacy = join17(dirname7(current), "skilify");
|
|
4424
|
+
if (!existsSync8(legacy))
|
|
4425
|
+
return;
|
|
4426
|
+
if (existsSync8(current))
|
|
4427
|
+
return;
|
|
4428
|
+
try {
|
|
4429
|
+
renameSync6(legacy, current);
|
|
4430
|
+
dlog(`migrated ${legacy} -> ${current}`);
|
|
4431
|
+
} catch (err) {
|
|
4432
|
+
const code = err.code;
|
|
4433
|
+
if (code === "EXDEV" || code === "EPERM" || code === "ENOENT" || code === "EEXIST" || code === "ENOTEMPTY") {
|
|
4434
|
+
dlog(`migration skipped (${code}); legacy dir left as-is or another process handled it`);
|
|
4435
|
+
return;
|
|
4436
|
+
}
|
|
4437
|
+
throw err;
|
|
4438
|
+
}
|
|
4439
|
+
}
|
|
4440
|
+
|
|
4441
|
+
// dist/src/skillify/manifest.js
|
|
4442
|
+
function emptyManifest() {
|
|
4443
|
+
return { version: 1, entries: [] };
|
|
4444
|
+
}
|
|
4445
|
+
function manifestPath() {
|
|
4446
|
+
return join18(getStateDir(), "pulled.json");
|
|
4447
|
+
}
|
|
4448
|
+
function loadManifest(path2 = manifestPath()) {
|
|
4449
|
+
migrateLegacyStateDir();
|
|
4450
|
+
if (!existsSync9(path2))
|
|
4451
|
+
return emptyManifest();
|
|
4452
|
+
let raw;
|
|
4453
|
+
try {
|
|
4454
|
+
raw = readFileSync11(path2, "utf-8");
|
|
4455
|
+
} catch {
|
|
4456
|
+
return emptyManifest();
|
|
4457
|
+
}
|
|
4458
|
+
try {
|
|
4459
|
+
const parsed = JSON.parse(raw);
|
|
4460
|
+
if (!parsed || typeof parsed !== "object")
|
|
4461
|
+
return emptyManifest();
|
|
4462
|
+
if (parsed.version !== 1 || !Array.isArray(parsed.entries))
|
|
4463
|
+
return emptyManifest();
|
|
4464
|
+
const entries = [];
|
|
4465
|
+
for (const e of parsed.entries) {
|
|
4466
|
+
if (!e || typeof e !== "object")
|
|
4467
|
+
continue;
|
|
4468
|
+
if (typeof e.dirName !== "string" || !e.dirName)
|
|
4469
|
+
continue;
|
|
4470
|
+
if (e.dirName.includes("/") || e.dirName.includes("\\") || e.dirName.includes(".."))
|
|
4471
|
+
continue;
|
|
4472
|
+
if (typeof e.name !== "string" || !e.name)
|
|
4473
|
+
continue;
|
|
4474
|
+
if (typeof e.author !== "string")
|
|
4475
|
+
continue;
|
|
4476
|
+
if (typeof e.installRoot !== "string" || !e.installRoot)
|
|
4477
|
+
continue;
|
|
4478
|
+
if (e.install !== "global" && e.install !== "project")
|
|
4479
|
+
continue;
|
|
4480
|
+
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)
|
|
4481
|
+
!p.includes("..")) : [];
|
|
4482
|
+
entries.push({
|
|
4483
|
+
dirName: e.dirName,
|
|
4484
|
+
name: e.name,
|
|
4485
|
+
author: e.author,
|
|
4486
|
+
projectKey: typeof e.projectKey === "string" ? e.projectKey : "",
|
|
4487
|
+
remoteVersion: typeof e.remoteVersion === "number" ? e.remoteVersion : 1,
|
|
4488
|
+
install: e.install,
|
|
4489
|
+
installRoot: e.installRoot,
|
|
4490
|
+
pulledAt: typeof e.pulledAt === "string" ? e.pulledAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
4491
|
+
symlinks
|
|
4492
|
+
});
|
|
4493
|
+
}
|
|
4494
|
+
return { version: 1, entries };
|
|
4495
|
+
} catch {
|
|
4496
|
+
return emptyManifest();
|
|
4497
|
+
}
|
|
4498
|
+
}
|
|
4499
|
+
|
|
4500
|
+
// dist/src/skillify/skillopt-env.js
|
|
4501
|
+
var SKILLOPT_ENV = {
|
|
4502
|
+
/** User-set kill switch: "1" disables the whole trigger. */
|
|
4503
|
+
DISABLED: "HIVEMIND_SKILLOPT_DISABLED",
|
|
4504
|
+
/** Recursion guard the trigger sets on the spawned worker so the worker can't re-arm. */
|
|
4505
|
+
WORKER: "HIVEMIND_SKILLOPT_WORKER",
|
|
4506
|
+
/** Worker inputs, handed trigger → worker via the child env. */
|
|
4507
|
+
SESSION: "HIVEMIND_SKILLOPT_SESSION",
|
|
4508
|
+
SKILL: "HIVEMIND_SKILLOPT_SKILL",
|
|
4509
|
+
REACTION: "HIVEMIND_SKILLOPT_REACTION",
|
|
4510
|
+
TOOL_USE_ID: "HIVEMIND_SKILLOPT_TOOL_USE_ID",
|
|
4511
|
+
/** Which agent's CLI runs the judge/proposer (claude_code/codex/hermes/cursor/pi). */
|
|
4512
|
+
AGENT: "HIVEMIND_SKILLOPT_AGENT",
|
|
4513
|
+
/** K-message judgment-window size override. */
|
|
4514
|
+
JUDGE_WINDOW: "HIVEMIND_SKILLOPT_JUDGE_WINDOW"
|
|
4515
|
+
};
|
|
4516
|
+
|
|
4517
|
+
// dist/src/skillify/skillopt-trigger.js
|
|
4518
|
+
var DEFAULT_JUDGE_WINDOW = 3;
|
|
4519
|
+
function judgeWindow(env = process.env) {
|
|
4520
|
+
const n = Number(env[SKILLOPT_ENV.JUDGE_WINDOW]);
|
|
4521
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : DEFAULT_JUDGE_WINDOW;
|
|
4522
|
+
}
|
|
4523
|
+
function defaultIsOrgSkill(skillRef) {
|
|
4524
|
+
try {
|
|
4525
|
+
return loadManifest().entries.some((e) => e.dirName === skillRef);
|
|
4526
|
+
} catch {
|
|
4527
|
+
return false;
|
|
4528
|
+
}
|
|
4529
|
+
}
|
|
4530
|
+
function pendingFile(sessionId) {
|
|
4531
|
+
const safe = sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 200);
|
|
4532
|
+
return path.join(getStateDir(), "skillopt", "pending", `${safe}.json`);
|
|
4533
|
+
}
|
|
4534
|
+
var fileStore = {
|
|
4535
|
+
load(sessionId) {
|
|
4536
|
+
try {
|
|
4537
|
+
return JSON.parse(fs.readFileSync(pendingFile(sessionId), "utf8"));
|
|
4538
|
+
} catch {
|
|
4539
|
+
return null;
|
|
4540
|
+
}
|
|
4541
|
+
},
|
|
4542
|
+
save(sessionId, p) {
|
|
4543
|
+
try {
|
|
4544
|
+
const f = pendingFile(sessionId);
|
|
4545
|
+
if (p === null) {
|
|
4546
|
+
try {
|
|
4547
|
+
fs.unlinkSync(f);
|
|
4548
|
+
} catch {
|
|
4549
|
+
}
|
|
4550
|
+
return;
|
|
4551
|
+
}
|
|
4552
|
+
fs.mkdirSync(path.dirname(f), { recursive: true });
|
|
4553
|
+
const tmp = `${f}.${process.pid}.tmp`;
|
|
4554
|
+
fs.writeFileSync(tmp, JSON.stringify(p));
|
|
4555
|
+
fs.renameSync(tmp, f);
|
|
4556
|
+
} catch {
|
|
4557
|
+
}
|
|
4558
|
+
}
|
|
4559
|
+
};
|
|
4560
|
+
function markSkillPending(sessionId, skillRef, toolUseId, deps = {}) {
|
|
4561
|
+
if (!sessionId || !skillRef)
|
|
4562
|
+
return false;
|
|
4563
|
+
if (!splitOrgSkill(skillRef))
|
|
4564
|
+
return false;
|
|
4565
|
+
if (!(deps.isOrgSkill ?? defaultIsOrgSkill)(skillRef))
|
|
4566
|
+
return false;
|
|
4567
|
+
(deps.store ?? fileStore).save(sessionId, { skill: skillRef, budget: judgeWindow(deps.env ?? process.env), toolUseId });
|
|
4568
|
+
return true;
|
|
4569
|
+
}
|
|
4570
|
+
|
|
4571
|
+
// dist/src/hooks/shared/skillopt-hook.js
|
|
4572
|
+
function skillRefFromSkillFileRead(toolName, toolInput) {
|
|
4573
|
+
if (/^read$/i.test(toolName))
|
|
4574
|
+
return pathToSkillRef(toolInput?.path);
|
|
4575
|
+
return pathToSkillRef(toolInput?.command);
|
|
4576
|
+
}
|
|
4577
|
+
function armSkillOptOnSkillUse(sessionId, toolName, toolInput, toolUseId) {
|
|
4578
|
+
try {
|
|
4579
|
+
if (process.env[SKILLOPT_ENV.DISABLED] === "1")
|
|
4580
|
+
return;
|
|
4581
|
+
let ref = null;
|
|
4582
|
+
if (toolName === "Skill") {
|
|
4583
|
+
const s = toolInput?.skill;
|
|
4584
|
+
ref = typeof s === "string" ? s : null;
|
|
4585
|
+
} else {
|
|
4586
|
+
ref = skillRefFromSkillFileRead(toolName, toolInput);
|
|
4587
|
+
}
|
|
4588
|
+
if (ref)
|
|
4589
|
+
markSkillPending(sessionId, ref, toolUseId);
|
|
4590
|
+
} catch {
|
|
4591
|
+
}
|
|
4592
|
+
}
|
|
4593
|
+
|
|
4375
4594
|
// dist/src/hooks/codex/pre-tool-use.js
|
|
4376
4595
|
var log6 = (msg) => log("codex-pre", msg);
|
|
4377
4596
|
function buildUnsupportedGuidance() {
|
|
@@ -4380,11 +4599,11 @@ function buildUnsupportedGuidance() {
|
|
|
4380
4599
|
function buildIndexContent(rows) {
|
|
4381
4600
|
const lines = ["# Memory Index", "", `${rows.length} sessions:`, ""];
|
|
4382
4601
|
for (const row of rows) {
|
|
4383
|
-
const
|
|
4602
|
+
const path2 = row["path"];
|
|
4384
4603
|
const project = row["project"] || "";
|
|
4385
4604
|
const description = (row["description"] || "").slice(0, 120);
|
|
4386
4605
|
const date = (row["creation_date"] || "").slice(0, 10);
|
|
4387
|
-
lines.push(`- [${
|
|
4606
|
+
lines.push(`- [${path2}](${path2}) ${date} ${project ? `[${project}]` : ""} ${description}`);
|
|
4388
4607
|
}
|
|
4389
4608
|
return lines.join("\n");
|
|
4390
4609
|
}
|
|
@@ -4414,16 +4633,16 @@ async function processCodexPreToolUse(input, deps = {}) {
|
|
|
4414
4633
|
const api = createApi(table, config);
|
|
4415
4634
|
const readVirtualPathContentsWithCache = async (cachePaths) => {
|
|
4416
4635
|
const uniquePaths = [...new Set(cachePaths)];
|
|
4417
|
-
const result = new Map(uniquePaths.map((
|
|
4636
|
+
const result = new Map(uniquePaths.map((path2) => [path2, null]));
|
|
4418
4637
|
const cachedIndex = uniquePaths.includes("/index.md") ? readCachedIndexContentFn(input.session_id) : null;
|
|
4419
|
-
const remainingPaths = cachedIndex === null ? uniquePaths : uniquePaths.filter((
|
|
4638
|
+
const remainingPaths = cachedIndex === null ? uniquePaths : uniquePaths.filter((path2) => path2 !== "/index.md");
|
|
4420
4639
|
if (cachedIndex !== null) {
|
|
4421
4640
|
result.set("/index.md", cachedIndex);
|
|
4422
4641
|
}
|
|
4423
4642
|
if (remainingPaths.length > 0) {
|
|
4424
4643
|
const fetched = await readVirtualPathContentsFn(api, table, sessionsTable, remainingPaths);
|
|
4425
|
-
for (const [
|
|
4426
|
-
result.set(
|
|
4644
|
+
for (const [path2, content] of fetched)
|
|
4645
|
+
result.set(path2, content);
|
|
4427
4646
|
}
|
|
4428
4647
|
const fetchedIndex = result.get("/index.md");
|
|
4429
4648
|
if (typeof fetchedIndex === "string") {
|
|
@@ -4519,10 +4738,10 @@ async function processCodexPreToolUse(input, deps = {}) {
|
|
|
4519
4738
|
const entries = /* @__PURE__ */ new Map();
|
|
4520
4739
|
const prefix = dir === "/" ? "/" : `${dir}/`;
|
|
4521
4740
|
for (const row of rows) {
|
|
4522
|
-
const
|
|
4523
|
-
if (!
|
|
4741
|
+
const path2 = row["path"];
|
|
4742
|
+
if (!path2.startsWith(prefix) && dir !== "/")
|
|
4524
4743
|
continue;
|
|
4525
|
-
const rest = dir === "/" ?
|
|
4744
|
+
const rest = dir === "/" ? path2.slice(1) : path2.slice(prefix.length);
|
|
4526
4745
|
const slash = rest.indexOf("/");
|
|
4527
4746
|
const name = slash === -1 ? rest : rest.slice(0, slash);
|
|
4528
4747
|
if (!name)
|
|
@@ -4591,6 +4810,10 @@ async function processCodexPreToolUse(input, deps = {}) {
|
|
|
4591
4810
|
}
|
|
4592
4811
|
async function main() {
|
|
4593
4812
|
const input = await readStdin();
|
|
4813
|
+
try {
|
|
4814
|
+
armSkillOptOnSkillUse(input.session_id, input.tool_name, input.tool_input, input.tool_use_id);
|
|
4815
|
+
} catch {
|
|
4816
|
+
}
|
|
4594
4817
|
const decision = await processCodexPreToolUse(input);
|
|
4595
4818
|
if (decision.action === "pass")
|
|
4596
4819
|
return;
|