@deeplake/hivemind 0.7.78 → 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
|
@@ -366,38 +366,38 @@ function readQueue() {
|
|
|
366
366
|
return { queue: [] };
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
|
-
function _isQueuePathInsideHome(
|
|
370
|
-
const r = resolve(
|
|
369
|
+
function _isQueuePathInsideHome(path2, home) {
|
|
370
|
+
const r = resolve(path2);
|
|
371
371
|
const h = resolve(home);
|
|
372
372
|
return r.startsWith(h + "/") || r === h;
|
|
373
373
|
}
|
|
374
374
|
function writeQueue(q) {
|
|
375
|
-
const
|
|
375
|
+
const path2 = queuePath();
|
|
376
376
|
const home = resolve(homedir3());
|
|
377
|
-
if (!_isQueuePathInsideHome(
|
|
378
|
-
throw new Error(`notifications-queue write blocked: ${
|
|
377
|
+
if (!_isQueuePathInsideHome(path2, home)) {
|
|
378
|
+
throw new Error(`notifications-queue write blocked: ${path2} is outside ${home}`);
|
|
379
379
|
}
|
|
380
380
|
mkdirSync(join3(home, ".deeplake"), { recursive: true, mode: 448 });
|
|
381
|
-
const tmp = `${
|
|
381
|
+
const tmp = `${path2}.${process.pid}.tmp`;
|
|
382
382
|
writeFileSync(tmp, JSON.stringify(q, null, 2), { mode: 384 });
|
|
383
|
-
renameSync(tmp,
|
|
383
|
+
renameSync(tmp, path2);
|
|
384
384
|
}
|
|
385
385
|
async function withQueueLock(fn) {
|
|
386
|
-
const
|
|
386
|
+
const path2 = lockPath();
|
|
387
387
|
mkdirSync(join3(homedir3(), ".deeplake"), { recursive: true, mode: 448 });
|
|
388
388
|
let fd = null;
|
|
389
389
|
for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
|
|
390
390
|
try {
|
|
391
|
-
fd = openSync(
|
|
391
|
+
fd = openSync(path2, "wx", 384);
|
|
392
392
|
break;
|
|
393
393
|
} catch (e) {
|
|
394
394
|
const code = e.code;
|
|
395
395
|
if (code !== "EEXIST")
|
|
396
396
|
throw e;
|
|
397
397
|
try {
|
|
398
|
-
const age = Date.now() - statSync(
|
|
398
|
+
const age = Date.now() - statSync(path2).mtimeMs;
|
|
399
399
|
if (age > LOCK_STALE_MS) {
|
|
400
|
-
unlinkSync(
|
|
400
|
+
unlinkSync(path2);
|
|
401
401
|
continue;
|
|
402
402
|
}
|
|
403
403
|
} catch {
|
|
@@ -418,7 +418,7 @@ async function withQueueLock(fn) {
|
|
|
418
418
|
} catch {
|
|
419
419
|
}
|
|
420
420
|
try {
|
|
421
|
-
unlinkSync(
|
|
421
|
+
unlinkSync(path2);
|
|
422
422
|
} catch {
|
|
423
423
|
}
|
|
424
424
|
}
|
|
@@ -694,9 +694,9 @@ var DeeplakeApi = class {
|
|
|
694
694
|
}
|
|
695
695
|
}
|
|
696
696
|
/** Update specific columns on a row by path. */
|
|
697
|
-
async updateColumns(
|
|
697
|
+
async updateColumns(path2, columns) {
|
|
698
698
|
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(
|
|
699
|
+
await this.query(`UPDATE "${this.tableName}" SET ${setClauses} WHERE path = '${sqlStr(path2)}'`);
|
|
700
700
|
}
|
|
701
701
|
// ── Convenience ─────────────────────────────────────────────────────────────
|
|
702
702
|
/** Create a BM25 search index on a column. */
|
|
@@ -1128,8 +1128,8 @@ function formatToolCall(obj) {
|
|
|
1128
1128
|
input: ${formatToolInput(obj?.tool_input)}
|
|
1129
1129
|
response: ${formatToolResponse(obj?.tool_response, obj?.tool_input, obj?.tool_name)}`;
|
|
1130
1130
|
}
|
|
1131
|
-
function normalizeContent(
|
|
1132
|
-
if (!
|
|
1131
|
+
function normalizeContent(path2, raw) {
|
|
1132
|
+
if (!path2.includes("/sessions/"))
|
|
1133
1133
|
return raw;
|
|
1134
1134
|
if (!raw || raw[0] !== "{")
|
|
1135
1135
|
return raw;
|
|
@@ -1856,13 +1856,13 @@ var _migrated = false;
|
|
|
1856
1856
|
function readUserConfig() {
|
|
1857
1857
|
if (_cache !== null)
|
|
1858
1858
|
return _cache;
|
|
1859
|
-
const
|
|
1860
|
-
if (!existsSync4(
|
|
1859
|
+
const path2 = _configPath();
|
|
1860
|
+
if (!existsSync4(path2)) {
|
|
1861
1861
|
_cache = {};
|
|
1862
1862
|
return _cache;
|
|
1863
1863
|
}
|
|
1864
1864
|
try {
|
|
1865
|
-
const raw = readFileSync6(
|
|
1865
|
+
const raw = readFileSync6(path2, "utf-8");
|
|
1866
1866
|
const parsed = JSON.parse(raw);
|
|
1867
1867
|
_cache = isPlainObject(parsed) ? parsed : {};
|
|
1868
1868
|
} catch {
|
|
@@ -1873,13 +1873,13 @@ function readUserConfig() {
|
|
|
1873
1873
|
function writeUserConfig(patch) {
|
|
1874
1874
|
const current = readUserConfig();
|
|
1875
1875
|
const merged = deepMerge(current, patch);
|
|
1876
|
-
const
|
|
1877
|
-
const dir = dirname(
|
|
1876
|
+
const path2 = _configPath();
|
|
1877
|
+
const dir = dirname(path2);
|
|
1878
1878
|
if (!existsSync4(dir))
|
|
1879
1879
|
mkdirSync4(dir, { recursive: true });
|
|
1880
|
-
const tmp = `${
|
|
1880
|
+
const tmp = `${path2}.tmp.${process.pid}`;
|
|
1881
1881
|
writeFileSync4(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
1882
|
-
renameSync2(tmp,
|
|
1882
|
+
renameSync2(tmp, path2);
|
|
1883
1883
|
_cache = merged;
|
|
1884
1884
|
return merged;
|
|
1885
1885
|
}
|
|
@@ -2350,18 +2350,18 @@ function lastBuildPath(baseDir, worktreeId) {
|
|
|
2350
2350
|
return join11(baseDir, ".last-build.json");
|
|
2351
2351
|
}
|
|
2352
2352
|
function readLastBuild(baseDir, worktreeId) {
|
|
2353
|
-
let
|
|
2354
|
-
if (!existsSync5(
|
|
2353
|
+
let path2 = lastBuildPath(baseDir, worktreeId);
|
|
2354
|
+
if (!existsSync5(path2)) {
|
|
2355
2355
|
if (worktreeId === void 0)
|
|
2356
2356
|
return null;
|
|
2357
2357
|
const legacy = lastBuildPath(baseDir, void 0);
|
|
2358
2358
|
if (!existsSync5(legacy))
|
|
2359
2359
|
return null;
|
|
2360
|
-
|
|
2360
|
+
path2 = legacy;
|
|
2361
2361
|
}
|
|
2362
2362
|
let raw;
|
|
2363
2363
|
try {
|
|
2364
|
-
raw = readFileSync7(
|
|
2364
|
+
raw = readFileSync7(path2, "utf8");
|
|
2365
2365
|
} catch {
|
|
2366
2366
|
return null;
|
|
2367
2367
|
}
|
|
@@ -2970,18 +2970,18 @@ function workTreeIdFor(cwd) {
|
|
|
2970
2970
|
return createHash3("sha256").update(cwd).digest("hex").slice(0, 16);
|
|
2971
2971
|
}
|
|
2972
2972
|
function handleGraphVfs(subpath, cwd) {
|
|
2973
|
-
const
|
|
2974
|
-
if (
|
|
2973
|
+
const path2 = subpath.replace(/^\/+/, "");
|
|
2974
|
+
if (path2 === "" || path2 === "/") {
|
|
2975
2975
|
return { kind: "ok", body: dirListing() };
|
|
2976
2976
|
}
|
|
2977
|
-
if (
|
|
2977
|
+
if (path2 === "index.md" || path2 === "index") {
|
|
2978
2978
|
return loadSnapshotOrError(cwd, (snap, baseDir) => ({
|
|
2979
2979
|
kind: "ok",
|
|
2980
2980
|
body: renderIndex(snap, baseDir, cwd)
|
|
2981
2981
|
}));
|
|
2982
2982
|
}
|
|
2983
|
-
if (
|
|
2984
|
-
const pattern =
|
|
2983
|
+
if (path2.startsWith("find/")) {
|
|
2984
|
+
const pattern = path2.slice("find/".length);
|
|
2985
2985
|
if (pattern === "") {
|
|
2986
2986
|
return { kind: "not-found", message: "find/ requires a pattern: cat memory/graph/find/<keyword>" };
|
|
2987
2987
|
}
|
|
@@ -2990,8 +2990,8 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
2990
2990
|
body: renderFind(snap, pattern, baseDir, workTreeIdFor(cwd))
|
|
2991
2991
|
}));
|
|
2992
2992
|
}
|
|
2993
|
-
if (
|
|
2994
|
-
const key =
|
|
2993
|
+
if (path2.startsWith("show/")) {
|
|
2994
|
+
const key = path2.slice("show/".length);
|
|
2995
2995
|
if (key === "") {
|
|
2996
2996
|
return { kind: "not-found", message: "show/ requires a handle or pattern" };
|
|
2997
2997
|
}
|
|
@@ -3000,8 +3000,8 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
3000
3000
|
body: renderShow(snap, key, baseDir, workTreeIdFor(cwd))
|
|
3001
3001
|
}));
|
|
3002
3002
|
}
|
|
3003
|
-
if (
|
|
3004
|
-
const pattern =
|
|
3003
|
+
if (path2.startsWith("query/")) {
|
|
3004
|
+
const pattern = path2.slice("query/".length);
|
|
3005
3005
|
if (pattern === "") {
|
|
3006
3006
|
return { kind: "not-found", message: "query/ requires a pattern: cat memory/graph/query/<keyword>" };
|
|
3007
3007
|
}
|
|
@@ -3010,28 +3010,28 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
3010
3010
|
body: renderQuery(snap, pattern, baseDir, workTreeIdFor(cwd))
|
|
3011
3011
|
}));
|
|
3012
3012
|
}
|
|
3013
|
-
if (
|
|
3014
|
-
const pattern =
|
|
3013
|
+
if (path2.startsWith("impact/")) {
|
|
3014
|
+
const pattern = path2.slice("impact/".length);
|
|
3015
3015
|
if (pattern === "") {
|
|
3016
3016
|
return { kind: "not-found", message: "impact/ requires a pattern: cat memory/graph/impact/<symbol>" };
|
|
3017
3017
|
}
|
|
3018
3018
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderImpact(snap, pattern) }));
|
|
3019
3019
|
}
|
|
3020
|
-
if (
|
|
3021
|
-
const file =
|
|
3020
|
+
if (path2.startsWith("neighborhood/")) {
|
|
3021
|
+
const file = path2.slice("neighborhood/".length);
|
|
3022
3022
|
if (file === "") {
|
|
3023
3023
|
return { kind: "not-found", message: "neighborhood/ requires a file path: cat memory/graph/neighborhood/<file>" };
|
|
3024
3024
|
}
|
|
3025
3025
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderNeighborhood(snap, file) }));
|
|
3026
3026
|
}
|
|
3027
|
-
if (
|
|
3027
|
+
if (path2 === "layers" || path2 === "layers/" || path2 === "layers/index.md") {
|
|
3028
3028
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderLayers(snap) }));
|
|
3029
3029
|
}
|
|
3030
|
-
if (
|
|
3030
|
+
if (path2 === "tour" || path2 === "tour/" || path2 === "tour/index.md") {
|
|
3031
3031
|
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderTour(snap) }));
|
|
3032
3032
|
}
|
|
3033
|
-
if (
|
|
3034
|
-
const rest =
|
|
3033
|
+
if (path2.startsWith("path/")) {
|
|
3034
|
+
const rest = path2.slice("path/".length);
|
|
3035
3035
|
const slash = rest.indexOf("/");
|
|
3036
3036
|
if (slash <= 0 || slash === rest.length - 1) {
|
|
3037
3037
|
return { kind: "not-found", message: "path/ needs two patterns: cat memory/graph/path/<from>/<to> (each a symbol-name substring, no slash)" };
|
|
@@ -3042,7 +3042,7 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
3042
3042
|
}
|
|
3043
3043
|
return {
|
|
3044
3044
|
kind: "not-found",
|
|
3045
|
-
message: `Unknown endpoint: graph/${
|
|
3045
|
+
message: `Unknown endpoint: graph/${path2}
|
|
3046
3046
|
Available: index.md, find/<pattern>, query/<pattern>, show/<handle-or-pattern>, impact/<pattern>, neighborhood/<file>, layers, tour, path/<from>/<to>`
|
|
3047
3047
|
};
|
|
3048
3048
|
}
|
|
@@ -3441,22 +3441,22 @@ function handlesPath(baseDir, worktreeId) {
|
|
|
3441
3441
|
return join14(baseDir, "worktrees", worktreeId, ".find-handles.json");
|
|
3442
3442
|
}
|
|
3443
3443
|
function saveHandles(baseDir, worktreeId, ids, pattern) {
|
|
3444
|
-
const
|
|
3444
|
+
const path2 = handlesPath(baseDir, worktreeId);
|
|
3445
3445
|
const payload = { pattern, ts: Date.now(), ids };
|
|
3446
3446
|
try {
|
|
3447
|
-
mkdirSync8(dirname6(
|
|
3448
|
-
const tmp = `${
|
|
3447
|
+
mkdirSync8(dirname6(path2), { recursive: true });
|
|
3448
|
+
const tmp = `${path2}.tmp.${process.pid}.${Date.now()}`;
|
|
3449
3449
|
writeFileSync7(tmp, JSON.stringify(payload));
|
|
3450
|
-
renameSync5(tmp,
|
|
3450
|
+
renameSync5(tmp, path2);
|
|
3451
3451
|
} catch {
|
|
3452
3452
|
}
|
|
3453
3453
|
}
|
|
3454
3454
|
function loadHandles(baseDir, worktreeId) {
|
|
3455
|
-
const
|
|
3456
|
-
if (!existsSync7(
|
|
3455
|
+
const path2 = handlesPath(baseDir, worktreeId);
|
|
3456
|
+
if (!existsSync7(path2))
|
|
3457
3457
|
return null;
|
|
3458
3458
|
try {
|
|
3459
|
-
const parsed = JSON.parse(readFileSync9(
|
|
3459
|
+
const parsed = JSON.parse(readFileSync9(path2, "utf8"));
|
|
3460
3460
|
if (parsed === null || typeof parsed !== "object")
|
|
3461
3461
|
return null;
|
|
3462
3462
|
const o = parsed;
|
|
@@ -3546,10 +3546,230 @@ function tryGraphRead(rewrittenCommand, cwd) {
|
|
|
3546
3546
|
return result.kind === "ok" ? result.body : `(${result.kind}) ${result.message}`;
|
|
3547
3547
|
}
|
|
3548
3548
|
|
|
3549
|
+
// dist/src/skillify/skillopt-trigger.js
|
|
3550
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
3551
|
+
import fs from "node:fs";
|
|
3552
|
+
import path from "node:path";
|
|
3553
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
3554
|
+
|
|
3555
|
+
// dist/src/skillify/state-dir.js
|
|
3556
|
+
import { homedir as homedir10 } from "node:os";
|
|
3557
|
+
import { join as join15 } from "node:path";
|
|
3558
|
+
function getStateDir() {
|
|
3559
|
+
const override = process.env.HIVEMIND_STATE_DIR?.trim();
|
|
3560
|
+
return override && override.length > 0 ? override : join15(homedir10(), ".deeplake", "state", "skillify");
|
|
3561
|
+
}
|
|
3562
|
+
|
|
3563
|
+
// dist/src/skillify/skill-invocations.js
|
|
3564
|
+
function pathToSkillRef(s) {
|
|
3565
|
+
if (typeof s !== "string")
|
|
3566
|
+
return null;
|
|
3567
|
+
const m = s.match(/\/skills\/(?:[^/\s"'`]+\/)*([^/\s"'`]+)\/SKILL\.md/);
|
|
3568
|
+
return m ? m[1] : null;
|
|
3569
|
+
}
|
|
3570
|
+
function splitOrgSkill(skill) {
|
|
3571
|
+
if (skill.includes(":"))
|
|
3572
|
+
return null;
|
|
3573
|
+
if (skill.includes("/") || skill.includes("\\") || skill.includes(".."))
|
|
3574
|
+
return null;
|
|
3575
|
+
const i = skill.lastIndexOf("--");
|
|
3576
|
+
if (i <= 0 || i + 2 >= skill.length)
|
|
3577
|
+
return null;
|
|
3578
|
+
return { name: skill.slice(0, i), author: skill.slice(i + 2) };
|
|
3579
|
+
}
|
|
3580
|
+
|
|
3581
|
+
// dist/src/skillify/manifest.js
|
|
3582
|
+
import { existsSync as existsSync9, lstatSync, mkdirSync as mkdirSync9, readFileSync as readFileSync10, renameSync as renameSync7, unlinkSync as unlinkSync4, writeFileSync as writeFileSync8 } from "node:fs";
|
|
3583
|
+
import { dirname as dirname8, join as join17 } from "node:path";
|
|
3584
|
+
|
|
3585
|
+
// dist/src/skillify/legacy-migration.js
|
|
3586
|
+
import { existsSync as existsSync8, renameSync as renameSync6 } from "node:fs";
|
|
3587
|
+
import { dirname as dirname7, join as join16 } from "node:path";
|
|
3588
|
+
var dlog = (msg) => log("skillify-migrate", msg);
|
|
3589
|
+
var attempted = false;
|
|
3590
|
+
function migrateLegacyStateDir() {
|
|
3591
|
+
if (process.env.HIVEMIND_STATE_DIR?.trim())
|
|
3592
|
+
return;
|
|
3593
|
+
if (attempted)
|
|
3594
|
+
return;
|
|
3595
|
+
attempted = true;
|
|
3596
|
+
const current = getStateDir();
|
|
3597
|
+
const legacy = join16(dirname7(current), "skilify");
|
|
3598
|
+
if (!existsSync8(legacy))
|
|
3599
|
+
return;
|
|
3600
|
+
if (existsSync8(current))
|
|
3601
|
+
return;
|
|
3602
|
+
try {
|
|
3603
|
+
renameSync6(legacy, current);
|
|
3604
|
+
dlog(`migrated ${legacy} -> ${current}`);
|
|
3605
|
+
} catch (err) {
|
|
3606
|
+
const code = err.code;
|
|
3607
|
+
if (code === "EXDEV" || code === "EPERM" || code === "ENOENT" || code === "EEXIST" || code === "ENOTEMPTY") {
|
|
3608
|
+
dlog(`migration skipped (${code}); legacy dir left as-is or another process handled it`);
|
|
3609
|
+
return;
|
|
3610
|
+
}
|
|
3611
|
+
throw err;
|
|
3612
|
+
}
|
|
3613
|
+
}
|
|
3614
|
+
|
|
3615
|
+
// dist/src/skillify/manifest.js
|
|
3616
|
+
function emptyManifest() {
|
|
3617
|
+
return { version: 1, entries: [] };
|
|
3618
|
+
}
|
|
3619
|
+
function manifestPath() {
|
|
3620
|
+
return join17(getStateDir(), "pulled.json");
|
|
3621
|
+
}
|
|
3622
|
+
function loadManifest(path2 = manifestPath()) {
|
|
3623
|
+
migrateLegacyStateDir();
|
|
3624
|
+
if (!existsSync9(path2))
|
|
3625
|
+
return emptyManifest();
|
|
3626
|
+
let raw;
|
|
3627
|
+
try {
|
|
3628
|
+
raw = readFileSync10(path2, "utf-8");
|
|
3629
|
+
} catch {
|
|
3630
|
+
return emptyManifest();
|
|
3631
|
+
}
|
|
3632
|
+
try {
|
|
3633
|
+
const parsed = JSON.parse(raw);
|
|
3634
|
+
if (!parsed || typeof parsed !== "object")
|
|
3635
|
+
return emptyManifest();
|
|
3636
|
+
if (parsed.version !== 1 || !Array.isArray(parsed.entries))
|
|
3637
|
+
return emptyManifest();
|
|
3638
|
+
const entries = [];
|
|
3639
|
+
for (const e of parsed.entries) {
|
|
3640
|
+
if (!e || typeof e !== "object")
|
|
3641
|
+
continue;
|
|
3642
|
+
if (typeof e.dirName !== "string" || !e.dirName)
|
|
3643
|
+
continue;
|
|
3644
|
+
if (e.dirName.includes("/") || e.dirName.includes("\\") || e.dirName.includes(".."))
|
|
3645
|
+
continue;
|
|
3646
|
+
if (typeof e.name !== "string" || !e.name)
|
|
3647
|
+
continue;
|
|
3648
|
+
if (typeof e.author !== "string")
|
|
3649
|
+
continue;
|
|
3650
|
+
if (typeof e.installRoot !== "string" || !e.installRoot)
|
|
3651
|
+
continue;
|
|
3652
|
+
if (e.install !== "global" && e.install !== "project")
|
|
3653
|
+
continue;
|
|
3654
|
+
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)
|
|
3655
|
+
!p.includes("..")) : [];
|
|
3656
|
+
entries.push({
|
|
3657
|
+
dirName: e.dirName,
|
|
3658
|
+
name: e.name,
|
|
3659
|
+
author: e.author,
|
|
3660
|
+
projectKey: typeof e.projectKey === "string" ? e.projectKey : "",
|
|
3661
|
+
remoteVersion: typeof e.remoteVersion === "number" ? e.remoteVersion : 1,
|
|
3662
|
+
install: e.install,
|
|
3663
|
+
installRoot: e.installRoot,
|
|
3664
|
+
pulledAt: typeof e.pulledAt === "string" ? e.pulledAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
3665
|
+
symlinks
|
|
3666
|
+
});
|
|
3667
|
+
}
|
|
3668
|
+
return { version: 1, entries };
|
|
3669
|
+
} catch {
|
|
3670
|
+
return emptyManifest();
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3673
|
+
|
|
3674
|
+
// dist/src/skillify/skillopt-env.js
|
|
3675
|
+
var SKILLOPT_ENV = {
|
|
3676
|
+
/** User-set kill switch: "1" disables the whole trigger. */
|
|
3677
|
+
DISABLED: "HIVEMIND_SKILLOPT_DISABLED",
|
|
3678
|
+
/** Recursion guard the trigger sets on the spawned worker so the worker can't re-arm. */
|
|
3679
|
+
WORKER: "HIVEMIND_SKILLOPT_WORKER",
|
|
3680
|
+
/** Worker inputs, handed trigger → worker via the child env. */
|
|
3681
|
+
SESSION: "HIVEMIND_SKILLOPT_SESSION",
|
|
3682
|
+
SKILL: "HIVEMIND_SKILLOPT_SKILL",
|
|
3683
|
+
REACTION: "HIVEMIND_SKILLOPT_REACTION",
|
|
3684
|
+
TOOL_USE_ID: "HIVEMIND_SKILLOPT_TOOL_USE_ID",
|
|
3685
|
+
/** Which agent's CLI runs the judge/proposer (claude_code/codex/hermes/cursor/pi). */
|
|
3686
|
+
AGENT: "HIVEMIND_SKILLOPT_AGENT",
|
|
3687
|
+
/** K-message judgment-window size override. */
|
|
3688
|
+
JUDGE_WINDOW: "HIVEMIND_SKILLOPT_JUDGE_WINDOW"
|
|
3689
|
+
};
|
|
3690
|
+
|
|
3691
|
+
// dist/src/skillify/skillopt-trigger.js
|
|
3692
|
+
var DEFAULT_JUDGE_WINDOW = 3;
|
|
3693
|
+
function judgeWindow(env = process.env) {
|
|
3694
|
+
const n = Number(env[SKILLOPT_ENV.JUDGE_WINDOW]);
|
|
3695
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : DEFAULT_JUDGE_WINDOW;
|
|
3696
|
+
}
|
|
3697
|
+
function defaultIsOrgSkill(skillRef) {
|
|
3698
|
+
try {
|
|
3699
|
+
return loadManifest().entries.some((e) => e.dirName === skillRef);
|
|
3700
|
+
} catch {
|
|
3701
|
+
return false;
|
|
3702
|
+
}
|
|
3703
|
+
}
|
|
3704
|
+
function pendingFile(sessionId) {
|
|
3705
|
+
const safe = sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 200);
|
|
3706
|
+
return path.join(getStateDir(), "skillopt", "pending", `${safe}.json`);
|
|
3707
|
+
}
|
|
3708
|
+
var fileStore = {
|
|
3709
|
+
load(sessionId) {
|
|
3710
|
+
try {
|
|
3711
|
+
return JSON.parse(fs.readFileSync(pendingFile(sessionId), "utf8"));
|
|
3712
|
+
} catch {
|
|
3713
|
+
return null;
|
|
3714
|
+
}
|
|
3715
|
+
},
|
|
3716
|
+
save(sessionId, p) {
|
|
3717
|
+
try {
|
|
3718
|
+
const f = pendingFile(sessionId);
|
|
3719
|
+
if (p === null) {
|
|
3720
|
+
try {
|
|
3721
|
+
fs.unlinkSync(f);
|
|
3722
|
+
} catch {
|
|
3723
|
+
}
|
|
3724
|
+
return;
|
|
3725
|
+
}
|
|
3726
|
+
fs.mkdirSync(path.dirname(f), { recursive: true });
|
|
3727
|
+
const tmp = `${f}.${process.pid}.tmp`;
|
|
3728
|
+
fs.writeFileSync(tmp, JSON.stringify(p));
|
|
3729
|
+
fs.renameSync(tmp, f);
|
|
3730
|
+
} catch {
|
|
3731
|
+
}
|
|
3732
|
+
}
|
|
3733
|
+
};
|
|
3734
|
+
function markSkillPending(sessionId, skillRef, toolUseId, deps = {}) {
|
|
3735
|
+
if (!sessionId || !skillRef)
|
|
3736
|
+
return false;
|
|
3737
|
+
if (!splitOrgSkill(skillRef))
|
|
3738
|
+
return false;
|
|
3739
|
+
if (!(deps.isOrgSkill ?? defaultIsOrgSkill)(skillRef))
|
|
3740
|
+
return false;
|
|
3741
|
+
(deps.store ?? fileStore).save(sessionId, { skill: skillRef, budget: judgeWindow(deps.env ?? process.env), toolUseId });
|
|
3742
|
+
return true;
|
|
3743
|
+
}
|
|
3744
|
+
|
|
3745
|
+
// dist/src/hooks/shared/skillopt-hook.js
|
|
3746
|
+
function skillRefFromSkillFileRead(toolName, toolInput) {
|
|
3747
|
+
if (/^read$/i.test(toolName))
|
|
3748
|
+
return pathToSkillRef(toolInput?.path);
|
|
3749
|
+
return pathToSkillRef(toolInput?.command);
|
|
3750
|
+
}
|
|
3751
|
+
function armSkillOptOnSkillUse(sessionId, toolName, toolInput, toolUseId) {
|
|
3752
|
+
try {
|
|
3753
|
+
if (process.env[SKILLOPT_ENV.DISABLED] === "1")
|
|
3754
|
+
return;
|
|
3755
|
+
let ref = null;
|
|
3756
|
+
if (toolName === "Skill") {
|
|
3757
|
+
const s = toolInput?.skill;
|
|
3758
|
+
ref = typeof s === "string" ? s : null;
|
|
3759
|
+
} else {
|
|
3760
|
+
ref = skillRefFromSkillFileRead(toolName, toolInput);
|
|
3761
|
+
}
|
|
3762
|
+
if (ref)
|
|
3763
|
+
markSkillPending(sessionId, ref, toolUseId);
|
|
3764
|
+
} catch {
|
|
3765
|
+
}
|
|
3766
|
+
}
|
|
3767
|
+
|
|
3549
3768
|
// dist/src/hooks/hermes/pre-tool-use.js
|
|
3550
3769
|
var log5 = (msg) => log("hermes-pre-tool-use", msg);
|
|
3551
3770
|
async function main() {
|
|
3552
3771
|
const input = await readStdin();
|
|
3772
|
+
armSkillOptOnSkillUse(input.session_id ?? "", input.tool_name ?? "", input.tool_input);
|
|
3553
3773
|
if (input.tool_name !== "terminal")
|
|
3554
3774
|
return;
|
|
3555
3775
|
const ti = input.tool_input;
|