@deeplake/hivemind 0.7.32 → 0.7.33
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 +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/bundle/cli.js +304 -171
- package/codex/bundle/capture.js +365 -332
- package/codex/bundle/commands/auth-login.js +163 -30
- package/codex/bundle/pre-tool-use.js +334 -301
- package/codex/bundle/session-start-setup.js +193 -60
- package/codex/bundle/session-start.js +221 -88
- package/codex/bundle/shell/deeplake-shell.js +328 -295
- package/codex/bundle/stop.js +424 -391
- package/codex/bundle/wiki-worker.js +174 -292
- package/cursor/bundle/capture.js +420 -387
- package/cursor/bundle/commands/auth-login.js +163 -30
- package/cursor/bundle/pre-tool-use.js +324 -291
- package/cursor/bundle/session-start.js +263 -130
- package/cursor/bundle/shell/deeplake-shell.js +328 -295
- package/cursor/bundle/wiki-worker.js +174 -292
- package/hermes/bundle/capture.js +420 -387
- package/hermes/bundle/commands/auth-login.js +163 -30
- package/hermes/bundle/pre-tool-use.js +324 -291
- package/hermes/bundle/session-start.js +260 -127
- package/hermes/bundle/shell/deeplake-shell.js +328 -295
- package/hermes/bundle/wiki-worker.js +174 -292
- package/mcp/bundle/server.js +190 -57
- package/openclaw/dist/index.js +160 -32
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/package.json +1 -1
package/bundle/cli.js
CHANGED
|
@@ -17,21 +17,21 @@ __export(index_marker_store_exports, {
|
|
|
17
17
|
hasFreshIndexMarker: () => hasFreshIndexMarker,
|
|
18
18
|
writeIndexMarker: () => writeIndexMarker
|
|
19
19
|
});
|
|
20
|
-
import { existsSync as existsSync14, mkdirSync as
|
|
21
|
-
import { join as
|
|
20
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "node:fs";
|
|
21
|
+
import { join as join18 } from "node:path";
|
|
22
22
|
import { tmpdir } from "node:os";
|
|
23
23
|
function getIndexMarkerDir() {
|
|
24
|
-
return process.env.HIVEMIND_INDEX_MARKER_DIR ??
|
|
24
|
+
return process.env.HIVEMIND_INDEX_MARKER_DIR ?? join18(tmpdir(), "hivemind-deeplake-indexes");
|
|
25
25
|
}
|
|
26
26
|
function buildIndexMarkerPath(workspaceId, orgId, table, suffix) {
|
|
27
27
|
const markerKey = [workspaceId, orgId, table, suffix].join("__").replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
28
|
-
return
|
|
28
|
+
return join18(getIndexMarkerDir(), `${markerKey}.json`);
|
|
29
29
|
}
|
|
30
30
|
function hasFreshIndexMarker(markerPath) {
|
|
31
31
|
if (!existsSync14(markerPath))
|
|
32
32
|
return false;
|
|
33
33
|
try {
|
|
34
|
-
const raw = JSON.parse(
|
|
34
|
+
const raw = JSON.parse(readFileSync13(markerPath, "utf-8"));
|
|
35
35
|
const updatedAt = raw.updatedAt ? new Date(raw.updatedAt).getTime() : NaN;
|
|
36
36
|
if (!Number.isFinite(updatedAt) || Date.now() - updatedAt > INDEX_MARKER_TTL_MS)
|
|
37
37
|
return false;
|
|
@@ -41,8 +41,8 @@ function hasFreshIndexMarker(markerPath) {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
function writeIndexMarker(markerPath) {
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
mkdirSync5(getIndexMarkerDir(), { recursive: true });
|
|
45
|
+
writeFileSync9(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
|
|
46
46
|
}
|
|
47
47
|
var INDEX_MARKER_TTL_MS;
|
|
48
48
|
var init_index_marker_store = __esm({
|
|
@@ -4343,6 +4343,107 @@ function sqlIdent(name) {
|
|
|
4343
4343
|
var SUMMARY_EMBEDDING_COL = "summary_embedding";
|
|
4344
4344
|
var MESSAGE_EMBEDDING_COL = "message_embedding";
|
|
4345
4345
|
|
|
4346
|
+
// dist/src/notifications/queue.js
|
|
4347
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, renameSync as renameSync3, mkdirSync as mkdirSync4, openSync, closeSync, unlinkSync as unlinkSync7, statSync as statSync2 } from "node:fs";
|
|
4348
|
+
import { join as join17, resolve } from "node:path";
|
|
4349
|
+
import { homedir as homedir8 } from "node:os";
|
|
4350
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
4351
|
+
var log3 = (msg) => log2("notifications-queue", msg);
|
|
4352
|
+
var LOCK_RETRY_MAX = 50;
|
|
4353
|
+
var LOCK_RETRY_BASE_MS = 5;
|
|
4354
|
+
var LOCK_STALE_MS = 5e3;
|
|
4355
|
+
function queuePath() {
|
|
4356
|
+
return join17(homedir8(), ".deeplake", "notifications-queue.json");
|
|
4357
|
+
}
|
|
4358
|
+
function lockPath() {
|
|
4359
|
+
return `${queuePath()}.lock`;
|
|
4360
|
+
}
|
|
4361
|
+
function readQueue() {
|
|
4362
|
+
try {
|
|
4363
|
+
const raw = readFileSync12(queuePath(), "utf-8");
|
|
4364
|
+
const parsed = JSON.parse(raw);
|
|
4365
|
+
if (!parsed || !Array.isArray(parsed.queue)) {
|
|
4366
|
+
log3(`queue malformed \u2192 treating as empty`);
|
|
4367
|
+
return { queue: [] };
|
|
4368
|
+
}
|
|
4369
|
+
return { queue: parsed.queue };
|
|
4370
|
+
} catch {
|
|
4371
|
+
return { queue: [] };
|
|
4372
|
+
}
|
|
4373
|
+
}
|
|
4374
|
+
function _isQueuePathInsideHome(path, home) {
|
|
4375
|
+
const r = resolve(path);
|
|
4376
|
+
const h = resolve(home);
|
|
4377
|
+
return r.startsWith(h + "/") || r === h;
|
|
4378
|
+
}
|
|
4379
|
+
function writeQueue(q) {
|
|
4380
|
+
const path = queuePath();
|
|
4381
|
+
const home = resolve(homedir8());
|
|
4382
|
+
if (!_isQueuePathInsideHome(path, home)) {
|
|
4383
|
+
throw new Error(`notifications-queue write blocked: ${path} is outside ${home}`);
|
|
4384
|
+
}
|
|
4385
|
+
mkdirSync4(join17(home, ".deeplake"), { recursive: true, mode: 448 });
|
|
4386
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
4387
|
+
writeFileSync8(tmp, JSON.stringify(q, null, 2), { mode: 384 });
|
|
4388
|
+
renameSync3(tmp, path);
|
|
4389
|
+
}
|
|
4390
|
+
async function withQueueLock(fn) {
|
|
4391
|
+
const path = lockPath();
|
|
4392
|
+
mkdirSync4(join17(homedir8(), ".deeplake"), { recursive: true, mode: 448 });
|
|
4393
|
+
let fd = null;
|
|
4394
|
+
for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
|
|
4395
|
+
try {
|
|
4396
|
+
fd = openSync(path, "wx", 384);
|
|
4397
|
+
break;
|
|
4398
|
+
} catch (e) {
|
|
4399
|
+
const code = e.code;
|
|
4400
|
+
if (code !== "EEXIST")
|
|
4401
|
+
throw e;
|
|
4402
|
+
try {
|
|
4403
|
+
const age = Date.now() - statSync2(path).mtimeMs;
|
|
4404
|
+
if (age > LOCK_STALE_MS) {
|
|
4405
|
+
unlinkSync7(path);
|
|
4406
|
+
continue;
|
|
4407
|
+
}
|
|
4408
|
+
} catch {
|
|
4409
|
+
}
|
|
4410
|
+
const delay = LOCK_RETRY_BASE_MS * (attempt + 1);
|
|
4411
|
+
await sleep(delay);
|
|
4412
|
+
}
|
|
4413
|
+
}
|
|
4414
|
+
if (fd === null) {
|
|
4415
|
+
log3(`lock acquisition gave up after ${LOCK_RETRY_MAX} attempts \u2014 proceeding unlocked (last-writer-wins)`);
|
|
4416
|
+
return fn();
|
|
4417
|
+
}
|
|
4418
|
+
try {
|
|
4419
|
+
return fn();
|
|
4420
|
+
} finally {
|
|
4421
|
+
try {
|
|
4422
|
+
closeSync(fd);
|
|
4423
|
+
} catch {
|
|
4424
|
+
}
|
|
4425
|
+
try {
|
|
4426
|
+
unlinkSync7(path);
|
|
4427
|
+
} catch {
|
|
4428
|
+
}
|
|
4429
|
+
}
|
|
4430
|
+
}
|
|
4431
|
+
function sameDedupKey(a, b) {
|
|
4432
|
+
if (a.id !== b.id)
|
|
4433
|
+
return false;
|
|
4434
|
+
return JSON.stringify(a.dedupKey) === JSON.stringify(b.dedupKey);
|
|
4435
|
+
}
|
|
4436
|
+
async function enqueueNotification(n) {
|
|
4437
|
+
await withQueueLock(() => {
|
|
4438
|
+
const q = readQueue();
|
|
4439
|
+
if (q.queue.some((existing) => sameDedupKey(existing, n))) {
|
|
4440
|
+
return;
|
|
4441
|
+
}
|
|
4442
|
+
q.queue.push(n);
|
|
4443
|
+
writeQueue(q);
|
|
4444
|
+
});
|
|
4445
|
+
}
|
|
4446
|
+
|
|
4346
4447
|
// dist/src/deeplake-api.js
|
|
4347
4448
|
var indexMarkerStorePromise = null;
|
|
4348
4449
|
function getIndexMarkerStore() {
|
|
@@ -4350,7 +4451,7 @@ function getIndexMarkerStore() {
|
|
|
4350
4451
|
indexMarkerStorePromise = Promise.resolve().then(() => (init_index_marker_store(), index_marker_store_exports));
|
|
4351
4452
|
return indexMarkerStorePromise;
|
|
4352
4453
|
}
|
|
4353
|
-
var
|
|
4454
|
+
var log4 = (msg) => log2("sdk", msg);
|
|
4354
4455
|
function summarizeSql(sql, maxLen = 220) {
|
|
4355
4456
|
const compact = sql.replace(/\s+/g, " ").trim();
|
|
4356
4457
|
return compact.length > maxLen ? `${compact.slice(0, maxLen)}...` : compact;
|
|
@@ -4362,7 +4463,38 @@ function traceSql(msg) {
|
|
|
4362
4463
|
process.stderr.write(`[deeplake-sql] ${msg}
|
|
4363
4464
|
`);
|
|
4364
4465
|
if (process.env.HIVEMIND_DEBUG === "1")
|
|
4365
|
-
|
|
4466
|
+
log4(msg);
|
|
4467
|
+
}
|
|
4468
|
+
var _signalledBalanceExhausted = false;
|
|
4469
|
+
function maybeSignalBalanceExhausted(status, bodyText) {
|
|
4470
|
+
if (status !== 402)
|
|
4471
|
+
return;
|
|
4472
|
+
if (!bodyText.includes("balance_cents"))
|
|
4473
|
+
return;
|
|
4474
|
+
if (_signalledBalanceExhausted)
|
|
4475
|
+
return;
|
|
4476
|
+
_signalledBalanceExhausted = true;
|
|
4477
|
+
log4(`balance exhausted \u2014 enqueuing session-start banner (body=${bodyText.slice(0, 120)})`);
|
|
4478
|
+
enqueueNotification({
|
|
4479
|
+
id: "balance-exhausted",
|
|
4480
|
+
severity: "warn",
|
|
4481
|
+
transient: true,
|
|
4482
|
+
title: "Hivemind credits exhausted \u2014 top up to keep capturing",
|
|
4483
|
+
body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
|
|
4484
|
+
dedupKey: { reason: "balance-zero" }
|
|
4485
|
+
}).catch((e) => {
|
|
4486
|
+
log4(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
4487
|
+
});
|
|
4488
|
+
}
|
|
4489
|
+
function billingUrl() {
|
|
4490
|
+
try {
|
|
4491
|
+
const c = loadCredentials();
|
|
4492
|
+
if (c?.orgName && c?.workspaceId) {
|
|
4493
|
+
return `https://deeplake.ai/${encodeURIComponent(c.orgName)}/workspace/${encodeURIComponent(c.workspaceId)}/billing`;
|
|
4494
|
+
}
|
|
4495
|
+
} catch {
|
|
4496
|
+
}
|
|
4497
|
+
return "https://deeplake.ai";
|
|
4366
4498
|
}
|
|
4367
4499
|
var RETRYABLE_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
4368
4500
|
var MAX_RETRIES = 3;
|
|
@@ -4371,8 +4503,8 @@ var MAX_CONCURRENCY = 5;
|
|
|
4371
4503
|
function getQueryTimeoutMs() {
|
|
4372
4504
|
return Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
|
|
4373
4505
|
}
|
|
4374
|
-
function
|
|
4375
|
-
return new Promise((
|
|
4506
|
+
function sleep2(ms) {
|
|
4507
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
4376
4508
|
}
|
|
4377
4509
|
function isTimeoutError(error) {
|
|
4378
4510
|
const name = error instanceof Error ? error.name.toLowerCase() : "";
|
|
@@ -4402,7 +4534,7 @@ var Semaphore = class {
|
|
|
4402
4534
|
this.active++;
|
|
4403
4535
|
return;
|
|
4404
4536
|
}
|
|
4405
|
-
await new Promise((
|
|
4537
|
+
await new Promise((resolve2) => this.waiting.push(resolve2));
|
|
4406
4538
|
}
|
|
4407
4539
|
release() {
|
|
4408
4540
|
this.active--;
|
|
@@ -4473,8 +4605,8 @@ var DeeplakeApi = class {
|
|
|
4473
4605
|
lastError = e instanceof Error ? e : new Error(String(e));
|
|
4474
4606
|
if (attempt < MAX_RETRIES) {
|
|
4475
4607
|
const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
|
|
4476
|
-
|
|
4477
|
-
await
|
|
4608
|
+
log4(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
|
|
4609
|
+
await sleep2(delay);
|
|
4478
4610
|
continue;
|
|
4479
4611
|
}
|
|
4480
4612
|
throw lastError;
|
|
@@ -4490,10 +4622,11 @@ var DeeplakeApi = class {
|
|
|
4490
4622
|
const alreadyExists = resp.status === 500 && isDuplicateIndexError(text);
|
|
4491
4623
|
if (!alreadyExists && attempt < MAX_RETRIES && (RETRYABLE_CODES.has(resp.status) || retryable403)) {
|
|
4492
4624
|
const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
|
|
4493
|
-
|
|
4494
|
-
await
|
|
4625
|
+
log4(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
|
|
4626
|
+
await sleep2(delay);
|
|
4495
4627
|
continue;
|
|
4496
4628
|
}
|
|
4629
|
+
maybeSignalBalanceExhausted(resp.status, text);
|
|
4497
4630
|
throw new Error(`Query failed: ${resp.status}: ${text.slice(0, 200)}`);
|
|
4498
4631
|
}
|
|
4499
4632
|
throw lastError ?? new Error("Query failed: max retries exceeded");
|
|
@@ -4514,7 +4647,7 @@ var DeeplakeApi = class {
|
|
|
4514
4647
|
const chunk = rows.slice(i, i + CONCURRENCY);
|
|
4515
4648
|
await Promise.allSettled(chunk.map((r) => this.upsertRowSql(r)));
|
|
4516
4649
|
}
|
|
4517
|
-
|
|
4650
|
+
log4(`commit: ${rows.length} rows`);
|
|
4518
4651
|
}
|
|
4519
4652
|
async upsertRowSql(row) {
|
|
4520
4653
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -4570,7 +4703,7 @@ var DeeplakeApi = class {
|
|
|
4570
4703
|
markers.writeIndexMarker(markerPath);
|
|
4571
4704
|
return;
|
|
4572
4705
|
}
|
|
4573
|
-
|
|
4706
|
+
log4(`index "${indexName}" skipped: ${e.message}`);
|
|
4574
4707
|
}
|
|
4575
4708
|
}
|
|
4576
4709
|
/**
|
|
@@ -4660,13 +4793,13 @@ var DeeplakeApi = class {
|
|
|
4660
4793
|
};
|
|
4661
4794
|
}
|
|
4662
4795
|
if (attempt < MAX_RETRIES && RETRYABLE_CODES.has(resp.status)) {
|
|
4663
|
-
await
|
|
4796
|
+
await sleep2(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
|
|
4664
4797
|
continue;
|
|
4665
4798
|
}
|
|
4666
4799
|
return { tables: [], cacheable: false };
|
|
4667
4800
|
} catch {
|
|
4668
4801
|
if (attempt < MAX_RETRIES) {
|
|
4669
|
-
await
|
|
4802
|
+
await sleep2(BASE_DELAY_MS * Math.pow(2, attempt));
|
|
4670
4803
|
continue;
|
|
4671
4804
|
}
|
|
4672
4805
|
return { tables: [], cacheable: false };
|
|
@@ -4694,9 +4827,9 @@ var DeeplakeApi = class {
|
|
|
4694
4827
|
} catch (err) {
|
|
4695
4828
|
lastErr = err;
|
|
4696
4829
|
const msg = err instanceof Error ? err.message : String(err);
|
|
4697
|
-
|
|
4830
|
+
log4(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
|
|
4698
4831
|
if (attempt < OUTER_BACKOFFS_MS.length) {
|
|
4699
|
-
await
|
|
4832
|
+
await sleep2(OUTER_BACKOFFS_MS[attempt]);
|
|
4700
4833
|
}
|
|
4701
4834
|
}
|
|
4702
4835
|
}
|
|
@@ -4707,9 +4840,9 @@ var DeeplakeApi = class {
|
|
|
4707
4840
|
const tbl = sqlIdent(name ?? this.tableName);
|
|
4708
4841
|
const tables = await this.listTables();
|
|
4709
4842
|
if (!tables.includes(tbl)) {
|
|
4710
|
-
|
|
4843
|
+
log4(`table "${tbl}" not found, creating`);
|
|
4711
4844
|
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', summary TEXT NOT NULL DEFAULT '', summary_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'text/plain', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', plugin_version TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, tbl);
|
|
4712
|
-
|
|
4845
|
+
log4(`table "${tbl}" created`);
|
|
4713
4846
|
if (!tables.includes(tbl))
|
|
4714
4847
|
this._tablesCache = [...tables, tbl];
|
|
4715
4848
|
}
|
|
@@ -4722,9 +4855,9 @@ var DeeplakeApi = class {
|
|
|
4722
4855
|
const safe = sqlIdent(name);
|
|
4723
4856
|
const tables = await this.listTables();
|
|
4724
4857
|
if (!tables.includes(safe)) {
|
|
4725
|
-
|
|
4858
|
+
log4(`table "${safe}" not found, creating`);
|
|
4726
4859
|
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', message JSONB, message_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/json', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', plugin_version TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, safe);
|
|
4727
|
-
|
|
4860
|
+
log4(`table "${safe}" created`);
|
|
4728
4861
|
if (!tables.includes(safe))
|
|
4729
4862
|
this._tablesCache = [...tables, safe];
|
|
4730
4863
|
}
|
|
@@ -4747,9 +4880,9 @@ var DeeplakeApi = class {
|
|
|
4747
4880
|
const safe = sqlIdent(name);
|
|
4748
4881
|
const tables = await this.listTables();
|
|
4749
4882
|
if (!tables.includes(safe)) {
|
|
4750
|
-
|
|
4883
|
+
log4(`table "${safe}" not found, creating`);
|
|
4751
4884
|
await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', name TEXT NOT NULL DEFAULT '', project TEXT NOT NULL DEFAULT '', project_key TEXT NOT NULL DEFAULT '', local_path TEXT NOT NULL DEFAULT '', install TEXT NOT NULL DEFAULT 'project', source_sessions TEXT NOT NULL DEFAULT '[]', source_agent TEXT NOT NULL DEFAULT '', scope TEXT NOT NULL DEFAULT 'me', author TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', trigger_text TEXT NOT NULL DEFAULT '', body TEXT NOT NULL DEFAULT '', version BIGINT NOT NULL DEFAULT 1, created_at TEXT NOT NULL DEFAULT '', updated_at TEXT NOT NULL DEFAULT '') USING deeplake`, safe);
|
|
4752
|
-
|
|
4885
|
+
log4(`table "${safe}" created`);
|
|
4753
4886
|
if (!tables.includes(safe))
|
|
4754
4887
|
this._tablesCache = [...tables, safe];
|
|
4755
4888
|
}
|
|
@@ -4780,10 +4913,10 @@ function parseArgs(argv) {
|
|
|
4780
4913
|
}
|
|
4781
4914
|
function confirm(message) {
|
|
4782
4915
|
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
4783
|
-
return new Promise((
|
|
4916
|
+
return new Promise((resolve2) => {
|
|
4784
4917
|
rl.question(`${message} [y/N] `, (answer) => {
|
|
4785
4918
|
rl.close();
|
|
4786
|
-
|
|
4919
|
+
resolve2(answer.trim().toLowerCase() === "y");
|
|
4787
4920
|
});
|
|
4788
4921
|
});
|
|
4789
4922
|
}
|
|
@@ -5085,34 +5218,34 @@ if (process.argv[1] && process.argv[1].endsWith("auth-login.js")) {
|
|
|
5085
5218
|
}
|
|
5086
5219
|
|
|
5087
5220
|
// dist/src/commands/skillify.js
|
|
5088
|
-
import { readdirSync as readdirSync5, existsSync as existsSync26, readFileSync as
|
|
5089
|
-
import { homedir as
|
|
5090
|
-
import { dirname as dirname7, join as
|
|
5221
|
+
import { readdirSync as readdirSync5, existsSync as existsSync26, readFileSync as readFileSync21, mkdirSync as mkdirSync12, renameSync as renameSync7 } from "node:fs";
|
|
5222
|
+
import { homedir as homedir20 } from "node:os";
|
|
5223
|
+
import { dirname as dirname7, join as join30 } from "node:path";
|
|
5091
5224
|
|
|
5092
5225
|
// dist/src/skillify/scope-config.js
|
|
5093
|
-
import { existsSync as existsSync16, mkdirSync as
|
|
5094
|
-
import { homedir as
|
|
5095
|
-
import { join as
|
|
5226
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync6, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "node:fs";
|
|
5227
|
+
import { homedir as homedir10 } from "node:os";
|
|
5228
|
+
import { join as join20 } from "node:path";
|
|
5096
5229
|
|
|
5097
5230
|
// dist/src/skillify/legacy-migration.js
|
|
5098
|
-
import { existsSync as existsSync15, renameSync as
|
|
5099
|
-
import { homedir as
|
|
5100
|
-
import { join as
|
|
5231
|
+
import { existsSync as existsSync15, renameSync as renameSync4 } from "node:fs";
|
|
5232
|
+
import { homedir as homedir9 } from "node:os";
|
|
5233
|
+
import { join as join19 } from "node:path";
|
|
5101
5234
|
var dlog = (msg) => log2("skillify-migrate", msg);
|
|
5102
5235
|
var attempted = false;
|
|
5103
5236
|
function migrateLegacyStateDir() {
|
|
5104
5237
|
if (attempted)
|
|
5105
5238
|
return;
|
|
5106
5239
|
attempted = true;
|
|
5107
|
-
const root =
|
|
5108
|
-
const legacy =
|
|
5109
|
-
const current =
|
|
5240
|
+
const root = join19(homedir9(), ".deeplake", "state");
|
|
5241
|
+
const legacy = join19(root, "skilify");
|
|
5242
|
+
const current = join19(root, "skillify");
|
|
5110
5243
|
if (!existsSync15(legacy))
|
|
5111
5244
|
return;
|
|
5112
5245
|
if (existsSync15(current))
|
|
5113
5246
|
return;
|
|
5114
5247
|
try {
|
|
5115
|
-
|
|
5248
|
+
renameSync4(legacy, current);
|
|
5116
5249
|
dlog(`migrated ${legacy} -> ${current}`);
|
|
5117
5250
|
} catch (err) {
|
|
5118
5251
|
const code = err.code;
|
|
@@ -5125,15 +5258,15 @@ function migrateLegacyStateDir() {
|
|
|
5125
5258
|
}
|
|
5126
5259
|
|
|
5127
5260
|
// dist/src/skillify/scope-config.js
|
|
5128
|
-
var STATE_DIR =
|
|
5129
|
-
var CONFIG_PATH2 =
|
|
5261
|
+
var STATE_DIR = join20(homedir10(), ".deeplake", "state", "skillify");
|
|
5262
|
+
var CONFIG_PATH2 = join20(STATE_DIR, "config.json");
|
|
5130
5263
|
var DEFAULT = { scope: "me", team: [], install: "project" };
|
|
5131
5264
|
function loadScopeConfig() {
|
|
5132
5265
|
migrateLegacyStateDir();
|
|
5133
5266
|
if (!existsSync16(CONFIG_PATH2))
|
|
5134
5267
|
return DEFAULT;
|
|
5135
5268
|
try {
|
|
5136
|
-
const raw = JSON.parse(
|
|
5269
|
+
const raw = JSON.parse(readFileSync14(CONFIG_PATH2, "utf-8"));
|
|
5137
5270
|
const scope = raw.scope === "team" ? "team" : raw.scope === "org" ? "team" : "me";
|
|
5138
5271
|
const team = Array.isArray(raw.team) ? raw.team.filter((s) => typeof s === "string") : [];
|
|
5139
5272
|
const install = raw.install === "global" ? "global" : "project";
|
|
@@ -5144,19 +5277,19 @@ function loadScopeConfig() {
|
|
|
5144
5277
|
}
|
|
5145
5278
|
function saveScopeConfig(cfg) {
|
|
5146
5279
|
migrateLegacyStateDir();
|
|
5147
|
-
|
|
5148
|
-
|
|
5280
|
+
mkdirSync6(STATE_DIR, { recursive: true });
|
|
5281
|
+
writeFileSync10(CONFIG_PATH2, JSON.stringify(cfg, null, 2));
|
|
5149
5282
|
}
|
|
5150
5283
|
|
|
5151
5284
|
// dist/src/skillify/pull.js
|
|
5152
|
-
import { existsSync as existsSync20, readFileSync as
|
|
5153
|
-
import { homedir as
|
|
5154
|
-
import { dirname as dirname4, join as
|
|
5285
|
+
import { existsSync as existsSync20, readFileSync as readFileSync17, writeFileSync as writeFileSync13, mkdirSync as mkdirSync9, renameSync as renameSync6, lstatSync as lstatSync4, readlinkSync as readlinkSync2, symlinkSync as symlinkSync2, unlinkSync as unlinkSync9 } from "node:fs";
|
|
5286
|
+
import { homedir as homedir14 } from "node:os";
|
|
5287
|
+
import { dirname as dirname4, join as join24 } from "node:path";
|
|
5155
5288
|
|
|
5156
5289
|
// dist/src/skillify/skill-writer.js
|
|
5157
|
-
import { existsSync as existsSync17, mkdirSync as
|
|
5158
|
-
import { homedir as
|
|
5159
|
-
import { join as
|
|
5290
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync7, readFileSync as readFileSync15, readdirSync as readdirSync2, statSync as statSync3, writeFileSync as writeFileSync11 } from "node:fs";
|
|
5291
|
+
import { homedir as homedir11 } from "node:os";
|
|
5292
|
+
import { join as join21 } from "node:path";
|
|
5160
5293
|
function assertValidSkillName(name) {
|
|
5161
5294
|
if (typeof name !== "string" || name.length === 0) {
|
|
5162
5295
|
throw new Error(`invalid skill name: empty or non-string`);
|
|
@@ -5172,10 +5305,10 @@ function assertValidSkillName(name) {
|
|
|
5172
5305
|
}
|
|
5173
5306
|
}
|
|
5174
5307
|
function skillDir(skillsRoot, name) {
|
|
5175
|
-
return
|
|
5308
|
+
return join21(skillsRoot, name);
|
|
5176
5309
|
}
|
|
5177
5310
|
function skillPath(skillsRoot, name) {
|
|
5178
|
-
return
|
|
5311
|
+
return join21(skillDir(skillsRoot, name), "SKILL.md");
|
|
5179
5312
|
}
|
|
5180
5313
|
function renderFrontmatter(fm) {
|
|
5181
5314
|
const lines = ["---"];
|
|
@@ -5256,7 +5389,7 @@ function writeNewSkill(args) {
|
|
|
5256
5389
|
if (existsSync17(path)) {
|
|
5257
5390
|
throw new Error(`skill already exists at ${path}; use mergeSkill`);
|
|
5258
5391
|
}
|
|
5259
|
-
|
|
5392
|
+
mkdirSync7(dir, { recursive: true });
|
|
5260
5393
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5261
5394
|
const author = args.author && args.author.length > 0 ? args.author : void 0;
|
|
5262
5395
|
const contributors = author ? [author] : [];
|
|
@@ -5276,7 +5409,7 @@ function writeNewSkill(args) {
|
|
|
5276
5409
|
|
|
5277
5410
|
${args.body.trim()}
|
|
5278
5411
|
`;
|
|
5279
|
-
|
|
5412
|
+
writeFileSync11(path, text);
|
|
5280
5413
|
return {
|
|
5281
5414
|
path,
|
|
5282
5415
|
action: "created",
|
|
@@ -5292,29 +5425,29 @@ function listSkills(skillsRoot) {
|
|
|
5292
5425
|
return [];
|
|
5293
5426
|
const out = [];
|
|
5294
5427
|
for (const name of readdirSync2(skillsRoot)) {
|
|
5295
|
-
const skillFile =
|
|
5296
|
-
if (existsSync17(skillFile) &&
|
|
5297
|
-
out.push({ name, body:
|
|
5428
|
+
const skillFile = join21(skillsRoot, name, "SKILL.md");
|
|
5429
|
+
if (existsSync17(skillFile) && statSync3(skillFile).isFile()) {
|
|
5430
|
+
out.push({ name, body: readFileSync15(skillFile, "utf-8") });
|
|
5298
5431
|
}
|
|
5299
5432
|
}
|
|
5300
5433
|
return out;
|
|
5301
5434
|
}
|
|
5302
5435
|
function resolveSkillsRoot(install, cwd) {
|
|
5303
5436
|
if (install === "global") {
|
|
5304
|
-
return
|
|
5437
|
+
return join21(homedir11(), ".claude", "skills");
|
|
5305
5438
|
}
|
|
5306
|
-
return
|
|
5439
|
+
return join21(cwd, ".claude", "skills");
|
|
5307
5440
|
}
|
|
5308
5441
|
|
|
5309
5442
|
// dist/src/skillify/manifest.js
|
|
5310
|
-
import { existsSync as existsSync18, lstatSync as lstatSync3, mkdirSync as
|
|
5311
|
-
import { homedir as
|
|
5312
|
-
import { dirname as dirname3, join as
|
|
5443
|
+
import { existsSync as existsSync18, lstatSync as lstatSync3, mkdirSync as mkdirSync8, readFileSync as readFileSync16, renameSync as renameSync5, unlinkSync as unlinkSync8, writeFileSync as writeFileSync12 } from "node:fs";
|
|
5444
|
+
import { homedir as homedir12 } from "node:os";
|
|
5445
|
+
import { dirname as dirname3, join as join22 } from "node:path";
|
|
5313
5446
|
function emptyManifest() {
|
|
5314
5447
|
return { version: 1, entries: [] };
|
|
5315
5448
|
}
|
|
5316
5449
|
function manifestPath() {
|
|
5317
|
-
return
|
|
5450
|
+
return join22(homedir12(), ".deeplake", "state", "skillify", "pulled.json");
|
|
5318
5451
|
}
|
|
5319
5452
|
function loadManifest(path = manifestPath()) {
|
|
5320
5453
|
migrateLegacyStateDir();
|
|
@@ -5322,7 +5455,7 @@ function loadManifest(path = manifestPath()) {
|
|
|
5322
5455
|
return emptyManifest();
|
|
5323
5456
|
let raw;
|
|
5324
5457
|
try {
|
|
5325
|
-
raw =
|
|
5458
|
+
raw = readFileSync16(path, "utf-8");
|
|
5326
5459
|
} catch {
|
|
5327
5460
|
return emptyManifest();
|
|
5328
5461
|
}
|
|
@@ -5369,10 +5502,10 @@ function loadManifest(path = manifestPath()) {
|
|
|
5369
5502
|
}
|
|
5370
5503
|
function saveManifest(m, path = manifestPath()) {
|
|
5371
5504
|
migrateLegacyStateDir();
|
|
5372
|
-
|
|
5505
|
+
mkdirSync8(dirname3(path), { recursive: true });
|
|
5373
5506
|
const tmp = `${path}.tmp`;
|
|
5374
|
-
|
|
5375
|
-
|
|
5507
|
+
writeFileSync12(tmp, JSON.stringify(m, null, 2) + "\n", { mode: 384 });
|
|
5508
|
+
renameSync5(tmp, path);
|
|
5376
5509
|
}
|
|
5377
5510
|
function recordPull(entry, path = manifestPath()) {
|
|
5378
5511
|
const m = loadManifest(path);
|
|
@@ -5404,7 +5537,7 @@ function unlinkSymlinks(paths) {
|
|
|
5404
5537
|
if (!st.isSymbolicLink())
|
|
5405
5538
|
continue;
|
|
5406
5539
|
try {
|
|
5407
|
-
|
|
5540
|
+
unlinkSync8(path);
|
|
5408
5541
|
} catch {
|
|
5409
5542
|
}
|
|
5410
5543
|
}
|
|
@@ -5414,7 +5547,7 @@ function pruneOrphanedEntries(path = manifestPath()) {
|
|
|
5414
5547
|
const live = [];
|
|
5415
5548
|
let pruned = 0;
|
|
5416
5549
|
for (const e of m.entries) {
|
|
5417
|
-
if (existsSync18(
|
|
5550
|
+
if (existsSync18(join22(e.installRoot, e.dirName))) {
|
|
5418
5551
|
live.push(e);
|
|
5419
5552
|
continue;
|
|
5420
5553
|
}
|
|
@@ -5428,25 +5561,25 @@ function pruneOrphanedEntries(path = manifestPath()) {
|
|
|
5428
5561
|
|
|
5429
5562
|
// dist/src/skillify/agent-roots.js
|
|
5430
5563
|
import { existsSync as existsSync19 } from "node:fs";
|
|
5431
|
-
import { homedir as
|
|
5432
|
-
import { join as
|
|
5564
|
+
import { homedir as homedir13 } from "node:os";
|
|
5565
|
+
import { join as join23 } from "node:path";
|
|
5433
5566
|
function resolveDetected(home) {
|
|
5434
5567
|
const out = [];
|
|
5435
|
-
const codexInstalled = existsSync19(
|
|
5436
|
-
const piInstalled = existsSync19(
|
|
5437
|
-
const hermesInstalled = existsSync19(
|
|
5568
|
+
const codexInstalled = existsSync19(join23(home, ".codex"));
|
|
5569
|
+
const piInstalled = existsSync19(join23(home, ".pi", "agent"));
|
|
5570
|
+
const hermesInstalled = existsSync19(join23(home, ".hermes"));
|
|
5438
5571
|
if (codexInstalled || piInstalled) {
|
|
5439
|
-
out.push(
|
|
5572
|
+
out.push(join23(home, ".agents", "skills"));
|
|
5440
5573
|
}
|
|
5441
5574
|
if (hermesInstalled) {
|
|
5442
|
-
out.push(
|
|
5575
|
+
out.push(join23(home, ".hermes", "skills"));
|
|
5443
5576
|
}
|
|
5444
5577
|
if (piInstalled) {
|
|
5445
|
-
out.push(
|
|
5578
|
+
out.push(join23(home, ".pi", "agent", "skills"));
|
|
5446
5579
|
}
|
|
5447
5580
|
return out;
|
|
5448
5581
|
}
|
|
5449
|
-
function detectAgentSkillsRoots(canonicalRoot, home =
|
|
5582
|
+
function detectAgentSkillsRoots(canonicalRoot, home = homedir13()) {
|
|
5450
5583
|
return resolveDetected(home).filter((p) => p !== canonicalRoot);
|
|
5451
5584
|
}
|
|
5452
5585
|
|
|
@@ -5490,15 +5623,15 @@ function isMissingTableError(message) {
|
|
|
5490
5623
|
}
|
|
5491
5624
|
function resolvePullDestination(install, cwd) {
|
|
5492
5625
|
if (install === "global")
|
|
5493
|
-
return
|
|
5626
|
+
return join24(homedir14(), ".claude", "skills");
|
|
5494
5627
|
if (!cwd)
|
|
5495
5628
|
throw new Error("install=project requires a cwd");
|
|
5496
|
-
return
|
|
5629
|
+
return join24(cwd, ".claude", "skills");
|
|
5497
5630
|
}
|
|
5498
5631
|
function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
|
|
5499
5632
|
const out = [];
|
|
5500
5633
|
for (const root of agentRoots) {
|
|
5501
|
-
const link =
|
|
5634
|
+
const link = join24(root, dirName);
|
|
5502
5635
|
let existing;
|
|
5503
5636
|
try {
|
|
5504
5637
|
existing = lstatSync4(link);
|
|
@@ -5520,13 +5653,13 @@ function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
|
|
|
5520
5653
|
continue;
|
|
5521
5654
|
}
|
|
5522
5655
|
try {
|
|
5523
|
-
|
|
5656
|
+
unlinkSync9(link);
|
|
5524
5657
|
} catch {
|
|
5525
5658
|
continue;
|
|
5526
5659
|
}
|
|
5527
5660
|
}
|
|
5528
5661
|
try {
|
|
5529
|
-
|
|
5662
|
+
mkdirSync9(dirname4(link), { recursive: true });
|
|
5530
5663
|
symlinkSync2(canonicalDir, link, "dir");
|
|
5531
5664
|
out.push(link);
|
|
5532
5665
|
} catch {
|
|
@@ -5541,7 +5674,7 @@ function backfillSymlinks(installRoot) {
|
|
|
5541
5674
|
return;
|
|
5542
5675
|
const detected = detectAgentSkillsRoots(installRoot);
|
|
5543
5676
|
for (const entry of entries) {
|
|
5544
|
-
const canonical =
|
|
5677
|
+
const canonical = join24(entry.installRoot, entry.dirName);
|
|
5545
5678
|
if (!existsSync20(canonical))
|
|
5546
5679
|
continue;
|
|
5547
5680
|
const fresh = fanOutSymlinks(canonical, entry.dirName, detected);
|
|
@@ -5655,7 +5788,7 @@ function readLocalVersion(path) {
|
|
|
5655
5788
|
if (!existsSync20(path))
|
|
5656
5789
|
return null;
|
|
5657
5790
|
try {
|
|
5658
|
-
const text =
|
|
5791
|
+
const text = readFileSync17(path, "utf-8");
|
|
5659
5792
|
const parsed = parseFrontmatter(text);
|
|
5660
5793
|
if (!parsed)
|
|
5661
5794
|
return null;
|
|
@@ -5750,8 +5883,8 @@ async function runPull(opts) {
|
|
|
5750
5883
|
summary.skipped++;
|
|
5751
5884
|
continue;
|
|
5752
5885
|
}
|
|
5753
|
-
const skillDir2 =
|
|
5754
|
-
const skillFile =
|
|
5886
|
+
const skillDir2 = join24(root, dirName);
|
|
5887
|
+
const skillFile = join24(skillDir2, "SKILL.md");
|
|
5755
5888
|
const remoteVersion = Number(row.version ?? 1);
|
|
5756
5889
|
const localVersion = readLocalVersion(skillFile);
|
|
5757
5890
|
const action = decideAction({
|
|
@@ -5762,14 +5895,14 @@ async function runPull(opts) {
|
|
|
5762
5895
|
});
|
|
5763
5896
|
let manifestError;
|
|
5764
5897
|
if (action === "wrote") {
|
|
5765
|
-
|
|
5898
|
+
mkdirSync9(skillDir2, { recursive: true });
|
|
5766
5899
|
if (existsSync20(skillFile)) {
|
|
5767
5900
|
try {
|
|
5768
|
-
|
|
5901
|
+
renameSync6(skillFile, `${skillFile}.bak`);
|
|
5769
5902
|
} catch {
|
|
5770
5903
|
}
|
|
5771
5904
|
}
|
|
5772
|
-
|
|
5905
|
+
writeFileSync13(skillFile, renderSkillFile(row));
|
|
5773
5906
|
const symlinks = opts.install === "global" ? fanOutSymlinks(skillDir2, dirName, detectAgentSkillsRoots(root)) : [];
|
|
5774
5907
|
try {
|
|
5775
5908
|
recordPull({
|
|
@@ -5811,15 +5944,15 @@ async function runPull(opts) {
|
|
|
5811
5944
|
}
|
|
5812
5945
|
|
|
5813
5946
|
// dist/src/skillify/unpull.js
|
|
5814
|
-
import { existsSync as existsSync21, readdirSync as readdirSync3, rmSync as rmSync5, statSync as
|
|
5815
|
-
import { homedir as
|
|
5816
|
-
import { join as
|
|
5947
|
+
import { existsSync as existsSync21, readdirSync as readdirSync3, rmSync as rmSync5, statSync as statSync4 } from "node:fs";
|
|
5948
|
+
import { homedir as homedir15 } from "node:os";
|
|
5949
|
+
import { join as join25 } from "node:path";
|
|
5817
5950
|
function resolveUnpullRoot(install, cwd) {
|
|
5818
5951
|
if (install === "global")
|
|
5819
|
-
return
|
|
5952
|
+
return join25(homedir15(), ".claude", "skills");
|
|
5820
5953
|
if (!cwd)
|
|
5821
5954
|
throw new Error("cwd required when install === 'project'");
|
|
5822
|
-
return
|
|
5955
|
+
return join25(cwd, ".claude", "skills");
|
|
5823
5956
|
}
|
|
5824
5957
|
function runUnpull(opts) {
|
|
5825
5958
|
const root = resolveUnpullRoot(opts.install, opts.cwd);
|
|
@@ -5842,7 +5975,7 @@ function runUnpull(opts) {
|
|
|
5842
5975
|
const entries = entriesForRoot(manifest, opts.install, root);
|
|
5843
5976
|
for (const entry of entries) {
|
|
5844
5977
|
summary.scanned++;
|
|
5845
|
-
const path =
|
|
5978
|
+
const path = join25(root, entry.dirName);
|
|
5846
5979
|
if (!existsSync21(path)) {
|
|
5847
5980
|
if (!opts.dryRun) {
|
|
5848
5981
|
unlinkSymlinks(entry.symlinks);
|
|
@@ -5901,10 +6034,10 @@ function runUnpull(opts) {
|
|
|
5901
6034
|
for (const dirName of readdirSync3(root)) {
|
|
5902
6035
|
if (manifestDirNames.has(dirName))
|
|
5903
6036
|
continue;
|
|
5904
|
-
const path =
|
|
6037
|
+
const path = join25(root, dirName);
|
|
5905
6038
|
let st;
|
|
5906
6039
|
try {
|
|
5907
|
-
st =
|
|
6040
|
+
st = statSync4(path);
|
|
5908
6041
|
} catch {
|
|
5909
6042
|
continue;
|
|
5910
6043
|
}
|
|
@@ -5980,21 +6113,21 @@ function decideTargetForManifestEntry(entry, opts, userFilter, haveUserFilter) {
|
|
|
5980
6113
|
|
|
5981
6114
|
// dist/src/commands/mine-local.js
|
|
5982
6115
|
import { spawn } from "node:child_process";
|
|
5983
|
-
import { existsSync as existsSync25, mkdirSync as
|
|
5984
|
-
import { homedir as
|
|
5985
|
-
import { basename, dirname as dirname6, join as
|
|
6116
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync11, readFileSync as readFileSync20, writeFileSync as writeFileSync15 } from "node:fs";
|
|
6117
|
+
import { homedir as homedir19 } from "node:os";
|
|
6118
|
+
import { basename, dirname as dirname6, join as join29 } from "node:path";
|
|
5986
6119
|
|
|
5987
6120
|
// dist/src/skillify/local-source.js
|
|
5988
|
-
import { readdirSync as readdirSync4, readFileSync as
|
|
5989
|
-
import { homedir as
|
|
5990
|
-
import { join as
|
|
5991
|
-
var HOME2 =
|
|
6121
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync18, existsSync as existsSync22, statSync as statSync5 } from "node:fs";
|
|
6122
|
+
import { homedir as homedir16 } from "node:os";
|
|
6123
|
+
import { join as join26 } from "node:path";
|
|
6124
|
+
var HOME2 = homedir16();
|
|
5992
6125
|
function encodeCwdClaudeCode(cwd) {
|
|
5993
6126
|
return cwd.replace(/[/_]/g, "-");
|
|
5994
6127
|
}
|
|
5995
6128
|
function detectInstalledAgents() {
|
|
5996
6129
|
const installs = [];
|
|
5997
|
-
const claudeRoot =
|
|
6130
|
+
const claudeRoot = join26(HOME2, ".claude", "projects");
|
|
5998
6131
|
if (existsSync22(claudeRoot)) {
|
|
5999
6132
|
installs.push({
|
|
6000
6133
|
agent: "claude_code",
|
|
@@ -6002,7 +6135,7 @@ function detectInstalledAgents() {
|
|
|
6002
6135
|
encodeCwd: encodeCwdClaudeCode
|
|
6003
6136
|
});
|
|
6004
6137
|
}
|
|
6005
|
-
const codexRoot =
|
|
6138
|
+
const codexRoot = join26(HOME2, ".codex", "sessions");
|
|
6006
6139
|
if (existsSync22(codexRoot)) {
|
|
6007
6140
|
installs.push({
|
|
6008
6141
|
agent: "codex",
|
|
@@ -6030,9 +6163,9 @@ function listLocalSessions(installs, cwd) {
|
|
|
6030
6163
|
continue;
|
|
6031
6164
|
}
|
|
6032
6165
|
for (const sub of subdirs) {
|
|
6033
|
-
const subdirPath =
|
|
6166
|
+
const subdirPath = join26(install.sessionRoot, sub);
|
|
6034
6167
|
try {
|
|
6035
|
-
if (!
|
|
6168
|
+
if (!statSync5(subdirPath).isDirectory())
|
|
6036
6169
|
continue;
|
|
6037
6170
|
} catch {
|
|
6038
6171
|
continue;
|
|
@@ -6047,10 +6180,10 @@ function listLocalSessions(installs, cwd) {
|
|
|
6047
6180
|
for (const f of files) {
|
|
6048
6181
|
if (!f.endsWith(".jsonl"))
|
|
6049
6182
|
continue;
|
|
6050
|
-
const fullPath =
|
|
6183
|
+
const fullPath = join26(subdirPath, f);
|
|
6051
6184
|
let stats;
|
|
6052
6185
|
try {
|
|
6053
|
-
stats =
|
|
6186
|
+
stats = statSync5(fullPath);
|
|
6054
6187
|
} catch {
|
|
6055
6188
|
continue;
|
|
6056
6189
|
}
|
|
@@ -6108,7 +6241,7 @@ function pickSessions(candidates, opts) {
|
|
|
6108
6241
|
function nativeJsonlToRows(filePath, sessionId, agent) {
|
|
6109
6242
|
let raw;
|
|
6110
6243
|
try {
|
|
6111
|
-
raw =
|
|
6244
|
+
raw = readFileSync18(filePath, "utf-8");
|
|
6112
6245
|
} catch {
|
|
6113
6246
|
return [];
|
|
6114
6247
|
}
|
|
@@ -6200,8 +6333,8 @@ function extractPairs(rows) {
|
|
|
6200
6333
|
// dist/src/skillify/gate-runner.js
|
|
6201
6334
|
import { existsSync as existsSync23 } from "node:fs";
|
|
6202
6335
|
import { createRequire } from "node:module";
|
|
6203
|
-
import { homedir as
|
|
6204
|
-
import { join as
|
|
6336
|
+
import { homedir as homedir17 } from "node:os";
|
|
6337
|
+
import { join as join27 } from "node:path";
|
|
6205
6338
|
var requireForCp = createRequire(import.meta.url);
|
|
6206
6339
|
var { execFileSync: runChildProcess } = requireForCp("node:child_process");
|
|
6207
6340
|
var inheritedEnv = process;
|
|
@@ -6213,7 +6346,7 @@ function firstExistingPath(candidates) {
|
|
|
6213
6346
|
return null;
|
|
6214
6347
|
}
|
|
6215
6348
|
function findAgentBin(agent) {
|
|
6216
|
-
const home =
|
|
6349
|
+
const home = homedir17();
|
|
6217
6350
|
switch (agent) {
|
|
6218
6351
|
// /usr/bin/<name> is included in every candidate list — that's the
|
|
6219
6352
|
// common Linux package-manager install path (apt, dnf, pacman). Old
|
|
@@ -6222,45 +6355,45 @@ function findAgentBin(agent) {
|
|
|
6222
6355
|
// #170 caught the gap.
|
|
6223
6356
|
case "claude_code":
|
|
6224
6357
|
return firstExistingPath([
|
|
6225
|
-
|
|
6358
|
+
join27(home, ".claude", "local", "claude"),
|
|
6226
6359
|
"/usr/local/bin/claude",
|
|
6227
6360
|
"/usr/bin/claude",
|
|
6228
|
-
|
|
6229
|
-
|
|
6361
|
+
join27(home, ".npm-global", "bin", "claude"),
|
|
6362
|
+
join27(home, ".local", "bin", "claude"),
|
|
6230
6363
|
"/opt/homebrew/bin/claude"
|
|
6231
|
-
]) ??
|
|
6364
|
+
]) ?? join27(home, ".claude", "local", "claude");
|
|
6232
6365
|
case "codex":
|
|
6233
6366
|
return firstExistingPath([
|
|
6234
6367
|
"/usr/local/bin/codex",
|
|
6235
6368
|
"/usr/bin/codex",
|
|
6236
|
-
|
|
6237
|
-
|
|
6369
|
+
join27(home, ".npm-global", "bin", "codex"),
|
|
6370
|
+
join27(home, ".local", "bin", "codex"),
|
|
6238
6371
|
"/opt/homebrew/bin/codex"
|
|
6239
6372
|
]) ?? "/usr/local/bin/codex";
|
|
6240
6373
|
case "cursor":
|
|
6241
6374
|
return firstExistingPath([
|
|
6242
6375
|
"/usr/local/bin/cursor-agent",
|
|
6243
6376
|
"/usr/bin/cursor-agent",
|
|
6244
|
-
|
|
6245
|
-
|
|
6377
|
+
join27(home, ".npm-global", "bin", "cursor-agent"),
|
|
6378
|
+
join27(home, ".local", "bin", "cursor-agent"),
|
|
6246
6379
|
"/opt/homebrew/bin/cursor-agent"
|
|
6247
6380
|
]) ?? "/usr/local/bin/cursor-agent";
|
|
6248
6381
|
case "hermes":
|
|
6249
6382
|
return firstExistingPath([
|
|
6250
|
-
|
|
6383
|
+
join27(home, ".local", "bin", "hermes"),
|
|
6251
6384
|
"/usr/local/bin/hermes",
|
|
6252
6385
|
"/usr/bin/hermes",
|
|
6253
|
-
|
|
6386
|
+
join27(home, ".npm-global", "bin", "hermes"),
|
|
6254
6387
|
"/opt/homebrew/bin/hermes"
|
|
6255
|
-
]) ??
|
|
6388
|
+
]) ?? join27(home, ".local", "bin", "hermes");
|
|
6256
6389
|
case "pi":
|
|
6257
6390
|
return firstExistingPath([
|
|
6258
|
-
|
|
6391
|
+
join27(home, ".local", "bin", "pi"),
|
|
6259
6392
|
"/usr/local/bin/pi",
|
|
6260
6393
|
"/usr/bin/pi",
|
|
6261
|
-
|
|
6394
|
+
join27(home, ".npm-global", "bin", "pi"),
|
|
6262
6395
|
"/opt/homebrew/bin/pi"
|
|
6263
|
-
]) ??
|
|
6396
|
+
]) ?? join27(home, ".local", "bin", "pi");
|
|
6264
6397
|
}
|
|
6265
6398
|
}
|
|
6266
6399
|
|
|
@@ -6290,27 +6423,27 @@ function extractJsonBlock(s) {
|
|
|
6290
6423
|
}
|
|
6291
6424
|
|
|
6292
6425
|
// dist/src/skillify/local-manifest.js
|
|
6293
|
-
import { existsSync as existsSync24, mkdirSync as
|
|
6294
|
-
import { homedir as
|
|
6295
|
-
import { dirname as dirname5, join as
|
|
6296
|
-
var LOCAL_MANIFEST_PATH =
|
|
6297
|
-
var LOCAL_MINE_LOCK_PATH =
|
|
6426
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync10, readFileSync as readFileSync19, writeFileSync as writeFileSync14 } from "node:fs";
|
|
6427
|
+
import { homedir as homedir18 } from "node:os";
|
|
6428
|
+
import { dirname as dirname5, join as join28 } from "node:path";
|
|
6429
|
+
var LOCAL_MANIFEST_PATH = join28(homedir18(), ".claude", "hivemind", "local-mined.json");
|
|
6430
|
+
var LOCAL_MINE_LOCK_PATH = join28(homedir18(), ".claude", "hivemind", "local-mined.lock");
|
|
6298
6431
|
function readLocalManifest(path = LOCAL_MANIFEST_PATH) {
|
|
6299
6432
|
if (!existsSync24(path))
|
|
6300
6433
|
return null;
|
|
6301
6434
|
try {
|
|
6302
|
-
return JSON.parse(
|
|
6435
|
+
return JSON.parse(readFileSync19(path, "utf-8"));
|
|
6303
6436
|
} catch {
|
|
6304
6437
|
return null;
|
|
6305
6438
|
}
|
|
6306
6439
|
}
|
|
6307
6440
|
function writeLocalManifest(m, path = LOCAL_MANIFEST_PATH) {
|
|
6308
|
-
|
|
6309
|
-
|
|
6441
|
+
mkdirSync10(dirname5(path), { recursive: true });
|
|
6442
|
+
writeFileSync14(path, JSON.stringify(m, null, 2));
|
|
6310
6443
|
}
|
|
6311
6444
|
|
|
6312
6445
|
// dist/src/commands/mine-local.js
|
|
6313
|
-
import { unlinkSync as
|
|
6446
|
+
import { unlinkSync as unlinkSync10 } from "node:fs";
|
|
6314
6447
|
var EPSILON = 0.3;
|
|
6315
6448
|
var DEFAULT_N = 8;
|
|
6316
6449
|
var PAIR_CHAR_CAP = 4e3;
|
|
@@ -6321,9 +6454,9 @@ var IN_FLIGHT_MAX_AGE_MS = 6e4;
|
|
|
6321
6454
|
var GATE_TIMEOUT_MS = 24e4;
|
|
6322
6455
|
var MANIFEST_PATH = LOCAL_MANIFEST_PATH;
|
|
6323
6456
|
function runGateViaStdin(opts) {
|
|
6324
|
-
return new Promise((
|
|
6457
|
+
return new Promise((resolve2) => {
|
|
6325
6458
|
if (opts.agent !== "claude_code") {
|
|
6326
|
-
|
|
6459
|
+
resolve2({
|
|
6327
6460
|
stdout: "",
|
|
6328
6461
|
stderr: "",
|
|
6329
6462
|
errored: true,
|
|
@@ -6332,7 +6465,7 @@ function runGateViaStdin(opts) {
|
|
|
6332
6465
|
return;
|
|
6333
6466
|
}
|
|
6334
6467
|
if (!existsSync25(opts.bin)) {
|
|
6335
|
-
|
|
6468
|
+
resolve2({
|
|
6336
6469
|
stdout: "",
|
|
6337
6470
|
stderr: "",
|
|
6338
6471
|
errored: true,
|
|
@@ -6359,7 +6492,7 @@ function runGateViaStdin(opts) {
|
|
|
6359
6492
|
if (settled)
|
|
6360
6493
|
return;
|
|
6361
6494
|
settled = true;
|
|
6362
|
-
|
|
6495
|
+
resolve2(r);
|
|
6363
6496
|
};
|
|
6364
6497
|
const timer = setTimeout(() => {
|
|
6365
6498
|
try {
|
|
@@ -6619,7 +6752,7 @@ async function runMineLocal(args) {
|
|
|
6619
6752
|
return;
|
|
6620
6753
|
lockReleased = true;
|
|
6621
6754
|
try {
|
|
6622
|
-
|
|
6755
|
+
unlinkSync10(LOCAL_MINE_LOCK_PATH);
|
|
6623
6756
|
} catch {
|
|
6624
6757
|
}
|
|
6625
6758
|
};
|
|
@@ -6676,8 +6809,8 @@ async function runMineLocalImpl(args) {
|
|
|
6676
6809
|
console.log(`Dry-run: would invoke ${gateAgent} gate on ${picked.length} session(s) in parallel (concurrency=${GATE_CONCURRENCY}).`);
|
|
6677
6810
|
return;
|
|
6678
6811
|
}
|
|
6679
|
-
const tmpDir =
|
|
6680
|
-
|
|
6812
|
+
const tmpDir = join29(homedir19(), ".claude", "hivemind", `mine-local-${Date.now()}`);
|
|
6813
|
+
mkdirSync11(tmpDir, { recursive: true });
|
|
6681
6814
|
console.log(`Running ${picked.length} gate call(s) in parallel (concurrency=${GATE_CONCURRENCY}, timeout=${GATE_TIMEOUT_MS / 1e3}s each)...`);
|
|
6682
6815
|
const results = await parallelMap(picked, GATE_CONCURRENCY, async (s) => {
|
|
6683
6816
|
const shortId = s.sessionId.slice(0, 8);
|
|
@@ -6688,23 +6821,23 @@ async function runMineLocalImpl(args) {
|
|
|
6688
6821
|
return { session: s, skills: [], reason: "no pairs", error: null };
|
|
6689
6822
|
}
|
|
6690
6823
|
const tail = pairs2.slice(-PER_SESSION_PAIR_CAP);
|
|
6691
|
-
const sessionTmp =
|
|
6692
|
-
|
|
6693
|
-
const verdictPath =
|
|
6824
|
+
const sessionTmp = join29(tmpDir, `s-${shortId}`);
|
|
6825
|
+
mkdirSync11(sessionTmp, { recursive: true });
|
|
6826
|
+
const verdictPath = join29(sessionTmp, "verdict.json");
|
|
6694
6827
|
const prompt = buildSessionPrompt(tail, s, verdictPath);
|
|
6695
|
-
|
|
6828
|
+
writeFileSync15(join29(sessionTmp, "prompt.txt"), prompt);
|
|
6696
6829
|
const gate = await runGateViaStdin({ agent: gateAgent, bin: gateBin, prompt, timeoutMs: GATE_TIMEOUT_MS });
|
|
6697
6830
|
try {
|
|
6698
|
-
|
|
6831
|
+
writeFileSync15(join29(sessionTmp, "gate-stdout.txt"), gate.stdout);
|
|
6699
6832
|
if (gate.stderr)
|
|
6700
|
-
|
|
6833
|
+
writeFileSync15(join29(sessionTmp, "gate-stderr.txt"), gate.stderr);
|
|
6701
6834
|
} catch {
|
|
6702
6835
|
}
|
|
6703
6836
|
if (gate.errored) {
|
|
6704
6837
|
console.log(` [${shortId}] gate failed: ${gate.errorMessage}`);
|
|
6705
6838
|
return { session: s, skills: [], reason: null, error: gate.errorMessage ?? "gate failed" };
|
|
6706
6839
|
}
|
|
6707
|
-
const verdictText = existsSync25(verdictPath) ?
|
|
6840
|
+
const verdictText = existsSync25(verdictPath) ? readFileSync20(verdictPath, "utf-8") : gate.stdout;
|
|
6708
6841
|
const mv = parseMultiVerdict(verdictText);
|
|
6709
6842
|
if (!mv) {
|
|
6710
6843
|
console.log(` [${shortId}] unparseable verdict (kept at ${sessionTmp})`);
|
|
@@ -6920,7 +7053,7 @@ function wrapAt(s, max) {
|
|
|
6920
7053
|
|
|
6921
7054
|
// dist/src/commands/skillify.js
|
|
6922
7055
|
function stateDir() {
|
|
6923
|
-
return
|
|
7056
|
+
return join30(homedir20(), ".deeplake", "state", "skillify");
|
|
6924
7057
|
}
|
|
6925
7058
|
function showStatus() {
|
|
6926
7059
|
const cfg = loadScopeConfig();
|
|
@@ -6940,7 +7073,7 @@ function showStatus() {
|
|
|
6940
7073
|
console.log(`state: ${files.length} project(s) tracked`);
|
|
6941
7074
|
for (const f of files) {
|
|
6942
7075
|
try {
|
|
6943
|
-
const s = JSON.parse(
|
|
7076
|
+
const s = JSON.parse(readFileSync21(join30(dir, f), "utf-8"));
|
|
6944
7077
|
const last = typeof s.updatedAt === "number" ? new Date(s.updatedAt).toISOString() : s.lastDate ?? "never";
|
|
6945
7078
|
const skills = Array.isArray(s.skillsGenerated) && s.skillsGenerated.length > 0 ? s.skillsGenerated.join(", ") : "none";
|
|
6946
7079
|
console.log(` - ${s.project} (counter=${s.counter}, last=${last}, skills=${skills})`);
|
|
@@ -6967,7 +7100,7 @@ function setInstall(loc) {
|
|
|
6967
7100
|
}
|
|
6968
7101
|
const cfg = loadScopeConfig();
|
|
6969
7102
|
saveScopeConfig({ ...cfg, install: loc });
|
|
6970
|
-
const path = loc === "global" ?
|
|
7103
|
+
const path = loc === "global" ? join30(homedir20(), ".claude", "skills") : "<cwd>/.claude/skills";
|
|
6971
7104
|
console.log(`Install location set to '${loc}'. New skills will be written to ${path}/<name>/SKILL.md.`);
|
|
6972
7105
|
}
|
|
6973
7106
|
function promoteSkill(name, cwd) {
|
|
@@ -6975,18 +7108,18 @@ function promoteSkill(name, cwd) {
|
|
|
6975
7108
|
console.error("Usage: hivemind skillify promote <skill-name>");
|
|
6976
7109
|
process.exit(1);
|
|
6977
7110
|
}
|
|
6978
|
-
const projectPath =
|
|
6979
|
-
const globalPath =
|
|
6980
|
-
if (!existsSync26(
|
|
7111
|
+
const projectPath = join30(cwd, ".claude", "skills", name);
|
|
7112
|
+
const globalPath = join30(homedir20(), ".claude", "skills", name);
|
|
7113
|
+
if (!existsSync26(join30(projectPath, "SKILL.md"))) {
|
|
6981
7114
|
console.error(`Skill '${name}' not found at ${projectPath}/SKILL.md`);
|
|
6982
7115
|
process.exit(1);
|
|
6983
7116
|
}
|
|
6984
|
-
if (existsSync26(
|
|
7117
|
+
if (existsSync26(join30(globalPath, "SKILL.md"))) {
|
|
6985
7118
|
console.error(`Skill '${name}' already exists at ${globalPath}/SKILL.md \u2014 refusing to overwrite. Remove it first or rename the project skill.`);
|
|
6986
7119
|
process.exit(1);
|
|
6987
7120
|
}
|
|
6988
|
-
|
|
6989
|
-
|
|
7121
|
+
mkdirSync12(dirname7(globalPath), { recursive: true });
|
|
7122
|
+
renameSync7(projectPath, globalPath);
|
|
6990
7123
|
console.log(`Promoted '${name}' from ${projectPath} \u2192 ${globalPath}.`);
|
|
6991
7124
|
}
|
|
6992
7125
|
function teamAdd(name) {
|
|
@@ -7092,7 +7225,7 @@ async function pullSkills(args) {
|
|
|
7092
7225
|
console.error(`pull failed: ${e?.message ?? e}`);
|
|
7093
7226
|
process.exit(1);
|
|
7094
7227
|
}
|
|
7095
|
-
const dest = toRaw === "global" ?
|
|
7228
|
+
const dest = toRaw === "global" ? join30(homedir20(), ".claude", "skills") : `${process.cwd()}/.claude/skills`;
|
|
7096
7229
|
const filterDesc = users.length === 0 ? "all users" : users.join(", ");
|
|
7097
7230
|
console.log(`Destination: ${dest}`);
|
|
7098
7231
|
console.log(`Filter: ${filterDesc}${skillName ? ` \xB7 skill='${skillName}'` : ""}${dryRun ? " \xB7 dry-run" : ""}${force ? " \xB7 force" : ""}`);
|
|
@@ -7142,7 +7275,7 @@ async function unpullSkills(args) {
|
|
|
7142
7275
|
all,
|
|
7143
7276
|
legacyCleanup
|
|
7144
7277
|
});
|
|
7145
|
-
const dest = toRaw === "global" ?
|
|
7278
|
+
const dest = toRaw === "global" ? join30(homedir20(), ".claude", "skills") : `${process.cwd()}/.claude/skills`;
|
|
7146
7279
|
const filterParts = [];
|
|
7147
7280
|
if (users.length > 0)
|
|
7148
7281
|
filterParts.push(`users=${users.join(",")}`);
|
|
@@ -7238,13 +7371,13 @@ if (process.argv[1] && process.argv[1].endsWith("skillify.js")) {
|
|
|
7238
7371
|
|
|
7239
7372
|
// dist/src/cli/update.js
|
|
7240
7373
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
7241
|
-
import { existsSync as existsSync27, readFileSync as
|
|
7374
|
+
import { existsSync as existsSync27, readFileSync as readFileSync23, realpathSync } from "node:fs";
|
|
7242
7375
|
import { dirname as dirname9, sep } from "node:path";
|
|
7243
7376
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
7244
7377
|
|
|
7245
7378
|
// dist/src/utils/version-check.js
|
|
7246
|
-
import { readFileSync as
|
|
7247
|
-
import { dirname as dirname8, join as
|
|
7379
|
+
import { readFileSync as readFileSync22 } from "node:fs";
|
|
7380
|
+
import { dirname as dirname8, join as join31 } from "node:path";
|
|
7248
7381
|
function isNewer(latest, current) {
|
|
7249
7382
|
const parse = (v) => v.split(".").map(Number);
|
|
7250
7383
|
const [la, lb, lc] = parse(latest);
|
|
@@ -7268,7 +7401,7 @@ function detectInstallKind(argv1) {
|
|
|
7268
7401
|
for (let i = 0; i < 10; i++) {
|
|
7269
7402
|
const pkgPath = `${dir}${sep}package.json`;
|
|
7270
7403
|
try {
|
|
7271
|
-
const pkg = JSON.parse(
|
|
7404
|
+
const pkg = JSON.parse(readFileSync23(pkgPath, "utf-8"));
|
|
7272
7405
|
if (pkg.name === PKG_NAME || pkg.name === "hivemind") {
|
|
7273
7406
|
installDir = dir;
|
|
7274
7407
|
break;
|