@deeplake/hivemind 0.7.40 → 0.7.44
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 +233 -165
- package/codex/bundle/commands/auth-login.js +89 -46
- package/codex/bundle/session-start-setup.js +57 -51
- package/codex/bundle/session-start.js +103 -96
- package/cursor/bundle/commands/auth-login.js +89 -46
- package/cursor/bundle/session-start.js +103 -96
- package/hermes/bundle/commands/auth-login.js +89 -46
- package/hermes/bundle/session-start.js +103 -96
- package/mcp/bundle/server.js +53 -47
- package/openclaw/dist/index.js +68 -27
- 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 mkdirSync6, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "node:fs";
|
|
21
|
+
import { join as join19 } 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 ?? join19(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 join19(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(readFileSync14(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
|
+
mkdirSync6(getIndexMarkerDir(), { recursive: true });
|
|
45
|
+
writeFileSync10(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({
|
|
@@ -4045,7 +4045,7 @@ function statusEmbeddings() {
|
|
|
4045
4045
|
|
|
4046
4046
|
// dist/src/cli/auth.js
|
|
4047
4047
|
import { existsSync as existsSync12 } from "node:fs";
|
|
4048
|
-
import { join as
|
|
4048
|
+
import { join as join15 } from "node:path";
|
|
4049
4049
|
|
|
4050
4050
|
// dist/src/commands/auth.js
|
|
4051
4051
|
import { execSync } from "node:child_process";
|
|
@@ -4059,26 +4059,61 @@ function deeplakeClientHeader() {
|
|
|
4059
4059
|
return { [DEEPLAKE_CLIENT_HEADER]: deeplakeClientValue() };
|
|
4060
4060
|
}
|
|
4061
4061
|
|
|
4062
|
-
// dist/src/commands/
|
|
4063
|
-
import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, mkdirSync as mkdirSync3
|
|
4062
|
+
// dist/src/commands/install-id.js
|
|
4063
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, mkdirSync as mkdirSync3 } from "node:fs";
|
|
4064
4064
|
import { join as join13 } from "node:path";
|
|
4065
4065
|
import { homedir as homedir5 } from "node:os";
|
|
4066
|
+
import { randomUUID } from "node:crypto";
|
|
4066
4067
|
function configDir() {
|
|
4067
4068
|
return join13(homedir5(), ".deeplake");
|
|
4068
4069
|
}
|
|
4070
|
+
function installIDPath() {
|
|
4071
|
+
return join13(configDir(), "install-id");
|
|
4072
|
+
}
|
|
4073
|
+
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
4074
|
+
function getOrCreateInstallID() {
|
|
4075
|
+
try {
|
|
4076
|
+
const value = readFileSync10(installIDPath(), "utf-8").trim();
|
|
4077
|
+
if (UUID_RE.test(value))
|
|
4078
|
+
return value;
|
|
4079
|
+
} catch {
|
|
4080
|
+
}
|
|
4081
|
+
const id = randomUUID();
|
|
4082
|
+
try {
|
|
4083
|
+
mkdirSync3(configDir(), { recursive: true, mode: 448 });
|
|
4084
|
+
writeFileSync7(installIDPath(), id, { mode: 384 });
|
|
4085
|
+
return id;
|
|
4086
|
+
} catch {
|
|
4087
|
+
return "";
|
|
4088
|
+
}
|
|
4089
|
+
}
|
|
4090
|
+
function hivemindInstallIDHeader() {
|
|
4091
|
+
const id = getOrCreateInstallID();
|
|
4092
|
+
if (!id)
|
|
4093
|
+
return {};
|
|
4094
|
+
return { "X-Hivemind-Install-Id": id };
|
|
4095
|
+
}
|
|
4096
|
+
|
|
4097
|
+
// dist/src/commands/auth-creds.js
|
|
4098
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, mkdirSync as mkdirSync4, unlinkSync as unlinkSync6 } from "node:fs";
|
|
4099
|
+
import { join as join14 } from "node:path";
|
|
4100
|
+
import { homedir as homedir6 } from "node:os";
|
|
4101
|
+
function configDir2() {
|
|
4102
|
+
return join14(homedir6(), ".deeplake");
|
|
4103
|
+
}
|
|
4069
4104
|
function credsPath() {
|
|
4070
|
-
return
|
|
4105
|
+
return join14(configDir2(), "credentials.json");
|
|
4071
4106
|
}
|
|
4072
4107
|
function loadCredentials() {
|
|
4073
4108
|
try {
|
|
4074
|
-
return JSON.parse(
|
|
4109
|
+
return JSON.parse(readFileSync11(credsPath(), "utf-8"));
|
|
4075
4110
|
} catch {
|
|
4076
4111
|
return null;
|
|
4077
4112
|
}
|
|
4078
4113
|
}
|
|
4079
4114
|
function saveCredentials(creds) {
|
|
4080
|
-
|
|
4081
|
-
|
|
4115
|
+
mkdirSync4(configDir2(), { recursive: true, mode: 448 });
|
|
4116
|
+
writeFileSync8(credsPath(), JSON.stringify({ ...creds, savedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2), { mode: 384 });
|
|
4082
4117
|
}
|
|
4083
4118
|
function deleteCredentials() {
|
|
4084
4119
|
try {
|
|
@@ -4145,7 +4180,11 @@ async function apiDelete(path, token, apiUrl, orgId) {
|
|
|
4145
4180
|
async function requestDeviceCode(apiUrl = DEFAULT_API_URL) {
|
|
4146
4181
|
const resp = await fetch(`${apiUrl}/auth/device/code`, {
|
|
4147
4182
|
method: "POST",
|
|
4148
|
-
headers: {
|
|
4183
|
+
headers: {
|
|
4184
|
+
"Content-Type": "application/json",
|
|
4185
|
+
...deeplakeClientHeader(),
|
|
4186
|
+
...hivemindInstallIDHeader()
|
|
4187
|
+
}
|
|
4149
4188
|
});
|
|
4150
4189
|
if (!resp.ok)
|
|
4151
4190
|
throw new Error(`Device flow unavailable: HTTP ${resp.status}`);
|
|
@@ -4154,7 +4193,11 @@ async function requestDeviceCode(apiUrl = DEFAULT_API_URL) {
|
|
|
4154
4193
|
async function pollForToken(deviceCode, apiUrl = DEFAULT_API_URL) {
|
|
4155
4194
|
const resp = await fetch(`${apiUrl}/auth/device/token`, {
|
|
4156
4195
|
method: "POST",
|
|
4157
|
-
headers: {
|
|
4196
|
+
headers: {
|
|
4197
|
+
"Content-Type": "application/json",
|
|
4198
|
+
...deeplakeClientHeader(),
|
|
4199
|
+
...hivemindInstallIDHeader()
|
|
4200
|
+
},
|
|
4158
4201
|
body: JSON.stringify({ device_code: deviceCode })
|
|
4159
4202
|
});
|
|
4160
4203
|
if (resp.ok)
|
|
@@ -4312,7 +4355,7 @@ var DEFAULT_API_URL2 = "https://api.deeplake.ai";
|
|
|
4312
4355
|
function resolveApiUrl() {
|
|
4313
4356
|
return process.env.HIVEMIND_API_URL ?? DEFAULT_API_URL2;
|
|
4314
4357
|
}
|
|
4315
|
-
var CREDS_PATH =
|
|
4358
|
+
var CREDS_PATH = join15(HOME, ".deeplake", "credentials.json");
|
|
4316
4359
|
function isLoggedIn() {
|
|
4317
4360
|
return existsSync12(CREDS_PATH) && loadCredentials() !== null;
|
|
4318
4361
|
}
|
|
@@ -4360,16 +4403,16 @@ async function maybeShowOrgChoice() {
|
|
|
4360
4403
|
}
|
|
4361
4404
|
|
|
4362
4405
|
// dist/src/config.js
|
|
4363
|
-
import { readFileSync as
|
|
4364
|
-
import { join as
|
|
4365
|
-
import { homedir as
|
|
4406
|
+
import { readFileSync as readFileSync12, existsSync as existsSync13 } from "node:fs";
|
|
4407
|
+
import { join as join16 } from "node:path";
|
|
4408
|
+
import { homedir as homedir7, userInfo as userInfo2 } from "node:os";
|
|
4366
4409
|
function loadConfig() {
|
|
4367
|
-
const home =
|
|
4368
|
-
const credPath =
|
|
4410
|
+
const home = homedir7();
|
|
4411
|
+
const credPath = join16(home, ".deeplake", "credentials.json");
|
|
4369
4412
|
let creds = null;
|
|
4370
4413
|
if (existsSync13(credPath)) {
|
|
4371
4414
|
try {
|
|
4372
|
-
creds = JSON.parse(
|
|
4415
|
+
creds = JSON.parse(readFileSync12(credPath, "utf-8"));
|
|
4373
4416
|
} catch {
|
|
4374
4417
|
return null;
|
|
4375
4418
|
}
|
|
@@ -4388,18 +4431,18 @@ function loadConfig() {
|
|
|
4388
4431
|
tableName: process.env.HIVEMIND_TABLE ?? "memory",
|
|
4389
4432
|
sessionsTableName: process.env.HIVEMIND_SESSIONS_TABLE ?? "sessions",
|
|
4390
4433
|
skillsTableName: process.env.HIVEMIND_SKILLS_TABLE ?? "skills",
|
|
4391
|
-
memoryPath: process.env.HIVEMIND_MEMORY_PATH ??
|
|
4434
|
+
memoryPath: process.env.HIVEMIND_MEMORY_PATH ?? join16(home, ".deeplake", "memory")
|
|
4392
4435
|
};
|
|
4393
4436
|
}
|
|
4394
4437
|
|
|
4395
4438
|
// dist/src/deeplake-api.js
|
|
4396
|
-
import { randomUUID } from "node:crypto";
|
|
4439
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
4397
4440
|
|
|
4398
4441
|
// dist/src/utils/debug.js
|
|
4399
4442
|
import { appendFileSync } from "node:fs";
|
|
4400
|
-
import { join as
|
|
4401
|
-
import { homedir as
|
|
4402
|
-
var LOG =
|
|
4443
|
+
import { join as join17 } from "node:path";
|
|
4444
|
+
import { homedir as homedir8 } from "node:os";
|
|
4445
|
+
var LOG = join17(homedir8(), ".deeplake", "hook-debug.log");
|
|
4403
4446
|
function isDebug() {
|
|
4404
4447
|
return process.env.HIVEMIND_DEBUG === "1";
|
|
4405
4448
|
}
|
|
@@ -4542,23 +4585,23 @@ async function healMissingColumns(args) {
|
|
|
4542
4585
|
}
|
|
4543
4586
|
|
|
4544
4587
|
// dist/src/notifications/queue.js
|
|
4545
|
-
import { readFileSync as
|
|
4546
|
-
import { join as
|
|
4547
|
-
import { homedir as
|
|
4588
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, renameSync as renameSync3, mkdirSync as mkdirSync5, openSync, closeSync, unlinkSync as unlinkSync7, statSync as statSync2 } from "node:fs";
|
|
4589
|
+
import { join as join18, resolve } from "node:path";
|
|
4590
|
+
import { homedir as homedir9 } from "node:os";
|
|
4548
4591
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
4549
4592
|
var log3 = (msg) => log2("notifications-queue", msg);
|
|
4550
4593
|
var LOCK_RETRY_MAX = 50;
|
|
4551
4594
|
var LOCK_RETRY_BASE_MS = 5;
|
|
4552
4595
|
var LOCK_STALE_MS = 5e3;
|
|
4553
4596
|
function queuePath() {
|
|
4554
|
-
return
|
|
4597
|
+
return join18(homedir9(), ".deeplake", "notifications-queue.json");
|
|
4555
4598
|
}
|
|
4556
4599
|
function lockPath() {
|
|
4557
4600
|
return `${queuePath()}.lock`;
|
|
4558
4601
|
}
|
|
4559
4602
|
function readQueue() {
|
|
4560
4603
|
try {
|
|
4561
|
-
const raw =
|
|
4604
|
+
const raw = readFileSync13(queuePath(), "utf-8");
|
|
4562
4605
|
const parsed = JSON.parse(raw);
|
|
4563
4606
|
if (!parsed || !Array.isArray(parsed.queue)) {
|
|
4564
4607
|
log3(`queue malformed \u2192 treating as empty`);
|
|
@@ -4576,18 +4619,18 @@ function _isQueuePathInsideHome(path, home) {
|
|
|
4576
4619
|
}
|
|
4577
4620
|
function writeQueue(q) {
|
|
4578
4621
|
const path = queuePath();
|
|
4579
|
-
const home = resolve(
|
|
4622
|
+
const home = resolve(homedir9());
|
|
4580
4623
|
if (!_isQueuePathInsideHome(path, home)) {
|
|
4581
4624
|
throw new Error(`notifications-queue write blocked: ${path} is outside ${home}`);
|
|
4582
4625
|
}
|
|
4583
|
-
|
|
4626
|
+
mkdirSync5(join18(home, ".deeplake"), { recursive: true, mode: 448 });
|
|
4584
4627
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
4585
|
-
|
|
4628
|
+
writeFileSync9(tmp, JSON.stringify(q, null, 2), { mode: 384 });
|
|
4586
4629
|
renameSync3(tmp, path);
|
|
4587
4630
|
}
|
|
4588
4631
|
async function withQueueLock(fn) {
|
|
4589
4632
|
const path = lockPath();
|
|
4590
|
-
|
|
4633
|
+
mkdirSync5(join18(homedir9(), ".deeplake"), { recursive: true, mode: 448 });
|
|
4591
4634
|
let fd = null;
|
|
4592
4635
|
for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
|
|
4593
4636
|
try {
|
|
@@ -4860,7 +4903,7 @@ var DeeplakeApi = class {
|
|
|
4860
4903
|
setClauses += `, description = '${sqlStr(row.description)}'`;
|
|
4861
4904
|
await this.query(`UPDATE "${this.tableName}" SET ${setClauses} WHERE path = '${sqlStr(row.path)}'`);
|
|
4862
4905
|
} else {
|
|
4863
|
-
const id =
|
|
4906
|
+
const id = randomUUID2();
|
|
4864
4907
|
let cols = `id, path, filename, summary, ${SUMMARY_EMBEDDING_COL}, mime_type, size_bytes, creation_date, last_update_date`;
|
|
4865
4908
|
let vals = `'${id}', '${sqlStr(row.path)}', '${sqlStr(row.filename)}', E'${sqlStr(row.contentText)}', NULL, '${sqlStr(row.mimeType)}', ${row.sizeBytes}, '${cd}', '${lud}'`;
|
|
4866
4909
|
if (row.project !== void 0) {
|
|
@@ -5375,24 +5418,24 @@ if (process.argv[1] && process.argv[1].endsWith("auth-login.js")) {
|
|
|
5375
5418
|
}
|
|
5376
5419
|
|
|
5377
5420
|
// dist/src/commands/skillify.js
|
|
5378
|
-
import { readdirSync as readdirSync5, existsSync as existsSync26, readFileSync as
|
|
5379
|
-
import { homedir as
|
|
5380
|
-
import { dirname as dirname8, join as
|
|
5421
|
+
import { readdirSync as readdirSync5, existsSync as existsSync26, readFileSync as readFileSync22, mkdirSync as mkdirSync13, renameSync as renameSync7 } from "node:fs";
|
|
5422
|
+
import { homedir as homedir19 } from "node:os";
|
|
5423
|
+
import { dirname as dirname8, join as join32 } from "node:path";
|
|
5381
5424
|
|
|
5382
5425
|
// dist/src/skillify/scope-config.js
|
|
5383
|
-
import { existsSync as existsSync16, mkdirSync as
|
|
5384
|
-
import { join as
|
|
5426
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync7, readFileSync as readFileSync15, writeFileSync as writeFileSync11 } from "node:fs";
|
|
5427
|
+
import { join as join22 } from "node:path";
|
|
5385
5428
|
|
|
5386
5429
|
// dist/src/skillify/legacy-migration.js
|
|
5387
5430
|
import { existsSync as existsSync15, renameSync as renameSync4 } from "node:fs";
|
|
5388
|
-
import { dirname as dirname3, join as
|
|
5431
|
+
import { dirname as dirname3, join as join21 } from "node:path";
|
|
5389
5432
|
|
|
5390
5433
|
// dist/src/skillify/state-dir.js
|
|
5391
|
-
import { homedir as
|
|
5392
|
-
import { join as
|
|
5434
|
+
import { homedir as homedir10 } from "node:os";
|
|
5435
|
+
import { join as join20 } from "node:path";
|
|
5393
5436
|
function getStateDir() {
|
|
5394
5437
|
const override = process.env.HIVEMIND_STATE_DIR?.trim();
|
|
5395
|
-
return override && override.length > 0 ? override :
|
|
5438
|
+
return override && override.length > 0 ? override : join20(homedir10(), ".deeplake", "state", "skillify");
|
|
5396
5439
|
}
|
|
5397
5440
|
|
|
5398
5441
|
// dist/src/skillify/legacy-migration.js
|
|
@@ -5405,7 +5448,7 @@ function migrateLegacyStateDir() {
|
|
|
5405
5448
|
return;
|
|
5406
5449
|
attempted = true;
|
|
5407
5450
|
const current = getStateDir();
|
|
5408
|
-
const legacy =
|
|
5451
|
+
const legacy = join21(dirname3(current), "skilify");
|
|
5409
5452
|
if (!existsSync15(legacy))
|
|
5410
5453
|
return;
|
|
5411
5454
|
if (existsSync15(current))
|
|
@@ -5425,7 +5468,7 @@ function migrateLegacyStateDir() {
|
|
|
5425
5468
|
|
|
5426
5469
|
// dist/src/skillify/scope-config.js
|
|
5427
5470
|
function configPath() {
|
|
5428
|
-
return
|
|
5471
|
+
return join22(getStateDir(), "config.json");
|
|
5429
5472
|
}
|
|
5430
5473
|
var DEFAULT = { scope: "me", team: [], install: "project" };
|
|
5431
5474
|
function loadScopeConfig() {
|
|
@@ -5434,7 +5477,7 @@ function loadScopeConfig() {
|
|
|
5434
5477
|
if (!existsSync16(CONFIG_PATH2))
|
|
5435
5478
|
return DEFAULT;
|
|
5436
5479
|
try {
|
|
5437
|
-
const raw = JSON.parse(
|
|
5480
|
+
const raw = JSON.parse(readFileSync15(CONFIG_PATH2, "utf-8"));
|
|
5438
5481
|
const scope = raw.scope === "team" ? "team" : raw.scope === "org" ? "team" : "me";
|
|
5439
5482
|
const team = Array.isArray(raw.team) ? raw.team.filter((s) => typeof s === "string") : [];
|
|
5440
5483
|
const install = raw.install === "global" ? "global" : "project";
|
|
@@ -5445,19 +5488,19 @@ function loadScopeConfig() {
|
|
|
5445
5488
|
}
|
|
5446
5489
|
function saveScopeConfig(cfg) {
|
|
5447
5490
|
migrateLegacyStateDir();
|
|
5448
|
-
|
|
5449
|
-
|
|
5491
|
+
mkdirSync7(getStateDir(), { recursive: true });
|
|
5492
|
+
writeFileSync11(configPath(), JSON.stringify(cfg, null, 2));
|
|
5450
5493
|
}
|
|
5451
5494
|
|
|
5452
5495
|
// dist/src/skillify/pull.js
|
|
5453
|
-
import { existsSync as existsSync20, readFileSync as
|
|
5454
|
-
import { homedir as
|
|
5455
|
-
import { dirname as dirname5, join as
|
|
5496
|
+
import { existsSync as existsSync20, readFileSync as readFileSync18, writeFileSync as writeFileSync14, mkdirSync as mkdirSync10, renameSync as renameSync6, lstatSync as lstatSync4, readlinkSync as readlinkSync2, symlinkSync as symlinkSync2, unlinkSync as unlinkSync9 } from "node:fs";
|
|
5497
|
+
import { homedir as homedir13 } from "node:os";
|
|
5498
|
+
import { dirname as dirname5, join as join26 } from "node:path";
|
|
5456
5499
|
|
|
5457
5500
|
// dist/src/skillify/skill-writer.js
|
|
5458
|
-
import { existsSync as existsSync17, mkdirSync as
|
|
5459
|
-
import { homedir as
|
|
5460
|
-
import { join as
|
|
5501
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync8, readFileSync as readFileSync16, readdirSync as readdirSync2, statSync as statSync3, writeFileSync as writeFileSync12 } from "node:fs";
|
|
5502
|
+
import { homedir as homedir11 } from "node:os";
|
|
5503
|
+
import { join as join23 } from "node:path";
|
|
5461
5504
|
function assertValidSkillName(name) {
|
|
5462
5505
|
if (typeof name !== "string" || name.length === 0) {
|
|
5463
5506
|
throw new Error(`invalid skill name: empty or non-string`);
|
|
@@ -5473,10 +5516,10 @@ function assertValidSkillName(name) {
|
|
|
5473
5516
|
}
|
|
5474
5517
|
}
|
|
5475
5518
|
function skillDir(skillsRoot, name) {
|
|
5476
|
-
return
|
|
5519
|
+
return join23(skillsRoot, name);
|
|
5477
5520
|
}
|
|
5478
5521
|
function skillPath(skillsRoot, name) {
|
|
5479
|
-
return
|
|
5522
|
+
return join23(skillDir(skillsRoot, name), "SKILL.md");
|
|
5480
5523
|
}
|
|
5481
5524
|
function renderFrontmatter(fm) {
|
|
5482
5525
|
const lines = ["---"];
|
|
@@ -5557,7 +5600,7 @@ function writeNewSkill(args) {
|
|
|
5557
5600
|
if (existsSync17(path)) {
|
|
5558
5601
|
throw new Error(`skill already exists at ${path}; use mergeSkill`);
|
|
5559
5602
|
}
|
|
5560
|
-
|
|
5603
|
+
mkdirSync8(dir, { recursive: true });
|
|
5561
5604
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5562
5605
|
const author = args.author && args.author.length > 0 ? args.author : void 0;
|
|
5563
5606
|
const contributors = author ? [author] : [];
|
|
@@ -5577,7 +5620,7 @@ function writeNewSkill(args) {
|
|
|
5577
5620
|
|
|
5578
5621
|
${args.body.trim()}
|
|
5579
5622
|
`;
|
|
5580
|
-
|
|
5623
|
+
writeFileSync12(path, text);
|
|
5581
5624
|
return {
|
|
5582
5625
|
path,
|
|
5583
5626
|
action: "created",
|
|
@@ -5593,28 +5636,28 @@ function listSkills(skillsRoot) {
|
|
|
5593
5636
|
return [];
|
|
5594
5637
|
const out = [];
|
|
5595
5638
|
for (const name of readdirSync2(skillsRoot)) {
|
|
5596
|
-
const skillFile =
|
|
5639
|
+
const skillFile = join23(skillsRoot, name, "SKILL.md");
|
|
5597
5640
|
if (existsSync17(skillFile) && statSync3(skillFile).isFile()) {
|
|
5598
|
-
out.push({ name, body:
|
|
5641
|
+
out.push({ name, body: readFileSync16(skillFile, "utf-8") });
|
|
5599
5642
|
}
|
|
5600
5643
|
}
|
|
5601
5644
|
return out;
|
|
5602
5645
|
}
|
|
5603
5646
|
function resolveSkillsRoot(install, cwd) {
|
|
5604
5647
|
if (install === "global") {
|
|
5605
|
-
return
|
|
5648
|
+
return join23(homedir11(), ".claude", "skills");
|
|
5606
5649
|
}
|
|
5607
|
-
return
|
|
5650
|
+
return join23(cwd, ".claude", "skills");
|
|
5608
5651
|
}
|
|
5609
5652
|
|
|
5610
5653
|
// dist/src/skillify/manifest.js
|
|
5611
|
-
import { existsSync as existsSync18, lstatSync as lstatSync3, mkdirSync as
|
|
5612
|
-
import { dirname as dirname4, join as
|
|
5654
|
+
import { existsSync as existsSync18, lstatSync as lstatSync3, mkdirSync as mkdirSync9, readFileSync as readFileSync17, renameSync as renameSync5, unlinkSync as unlinkSync8, writeFileSync as writeFileSync13 } from "node:fs";
|
|
5655
|
+
import { dirname as dirname4, join as join24 } from "node:path";
|
|
5613
5656
|
function emptyManifest() {
|
|
5614
5657
|
return { version: 1, entries: [] };
|
|
5615
5658
|
}
|
|
5616
5659
|
function manifestPath() {
|
|
5617
|
-
return
|
|
5660
|
+
return join24(getStateDir(), "pulled.json");
|
|
5618
5661
|
}
|
|
5619
5662
|
function loadManifest(path = manifestPath()) {
|
|
5620
5663
|
migrateLegacyStateDir();
|
|
@@ -5622,7 +5665,7 @@ function loadManifest(path = manifestPath()) {
|
|
|
5622
5665
|
return emptyManifest();
|
|
5623
5666
|
let raw;
|
|
5624
5667
|
try {
|
|
5625
|
-
raw =
|
|
5668
|
+
raw = readFileSync17(path, "utf-8");
|
|
5626
5669
|
} catch {
|
|
5627
5670
|
return emptyManifest();
|
|
5628
5671
|
}
|
|
@@ -5669,9 +5712,9 @@ function loadManifest(path = manifestPath()) {
|
|
|
5669
5712
|
}
|
|
5670
5713
|
function saveManifest(m, path = manifestPath()) {
|
|
5671
5714
|
migrateLegacyStateDir();
|
|
5672
|
-
|
|
5715
|
+
mkdirSync9(dirname4(path), { recursive: true });
|
|
5673
5716
|
const tmp = `${path}.tmp`;
|
|
5674
|
-
|
|
5717
|
+
writeFileSync13(tmp, JSON.stringify(m, null, 2) + "\n", { mode: 384 });
|
|
5675
5718
|
renameSync5(tmp, path);
|
|
5676
5719
|
}
|
|
5677
5720
|
function recordPull(entry, path = manifestPath()) {
|
|
@@ -5714,7 +5757,7 @@ function pruneOrphanedEntries(path = manifestPath()) {
|
|
|
5714
5757
|
const live = [];
|
|
5715
5758
|
let pruned = 0;
|
|
5716
5759
|
for (const e of m.entries) {
|
|
5717
|
-
if (existsSync18(
|
|
5760
|
+
if (existsSync18(join24(e.installRoot, e.dirName))) {
|
|
5718
5761
|
live.push(e);
|
|
5719
5762
|
continue;
|
|
5720
5763
|
}
|
|
@@ -5728,25 +5771,25 @@ function pruneOrphanedEntries(path = manifestPath()) {
|
|
|
5728
5771
|
|
|
5729
5772
|
// dist/src/skillify/agent-roots.js
|
|
5730
5773
|
import { existsSync as existsSync19 } from "node:fs";
|
|
5731
|
-
import { homedir as
|
|
5732
|
-
import { join as
|
|
5774
|
+
import { homedir as homedir12 } from "node:os";
|
|
5775
|
+
import { join as join25 } from "node:path";
|
|
5733
5776
|
function resolveDetected(home) {
|
|
5734
5777
|
const out = [];
|
|
5735
|
-
const codexInstalled = existsSync19(
|
|
5736
|
-
const piInstalled = existsSync19(
|
|
5737
|
-
const hermesInstalled = existsSync19(
|
|
5778
|
+
const codexInstalled = existsSync19(join25(home, ".codex"));
|
|
5779
|
+
const piInstalled = existsSync19(join25(home, ".pi", "agent"));
|
|
5780
|
+
const hermesInstalled = existsSync19(join25(home, ".hermes"));
|
|
5738
5781
|
if (codexInstalled || piInstalled) {
|
|
5739
|
-
out.push(
|
|
5782
|
+
out.push(join25(home, ".agents", "skills"));
|
|
5740
5783
|
}
|
|
5741
5784
|
if (hermesInstalled) {
|
|
5742
|
-
out.push(
|
|
5785
|
+
out.push(join25(home, ".hermes", "skills"));
|
|
5743
5786
|
}
|
|
5744
5787
|
if (piInstalled) {
|
|
5745
|
-
out.push(
|
|
5788
|
+
out.push(join25(home, ".pi", "agent", "skills"));
|
|
5746
5789
|
}
|
|
5747
5790
|
return out;
|
|
5748
5791
|
}
|
|
5749
|
-
function detectAgentSkillsRoots(canonicalRoot, home =
|
|
5792
|
+
function detectAgentSkillsRoots(canonicalRoot, home = homedir12()) {
|
|
5750
5793
|
return resolveDetected(home).filter((p) => p !== canonicalRoot);
|
|
5751
5794
|
}
|
|
5752
5795
|
|
|
@@ -5790,15 +5833,15 @@ function isMissingTableError(message) {
|
|
|
5790
5833
|
}
|
|
5791
5834
|
function resolvePullDestination(install, cwd) {
|
|
5792
5835
|
if (install === "global")
|
|
5793
|
-
return
|
|
5836
|
+
return join26(homedir13(), ".claude", "skills");
|
|
5794
5837
|
if (!cwd)
|
|
5795
5838
|
throw new Error("install=project requires a cwd");
|
|
5796
|
-
return
|
|
5839
|
+
return join26(cwd, ".claude", "skills");
|
|
5797
5840
|
}
|
|
5798
5841
|
function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
|
|
5799
5842
|
const out = [];
|
|
5800
5843
|
for (const root of agentRoots) {
|
|
5801
|
-
const link =
|
|
5844
|
+
const link = join26(root, dirName);
|
|
5802
5845
|
let existing;
|
|
5803
5846
|
try {
|
|
5804
5847
|
existing = lstatSync4(link);
|
|
@@ -5826,7 +5869,7 @@ function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
|
|
|
5826
5869
|
}
|
|
5827
5870
|
}
|
|
5828
5871
|
try {
|
|
5829
|
-
|
|
5872
|
+
mkdirSync10(dirname5(link), { recursive: true });
|
|
5830
5873
|
symlinkSync2(canonicalDir, link, "dir");
|
|
5831
5874
|
out.push(link);
|
|
5832
5875
|
} catch {
|
|
@@ -5841,7 +5884,7 @@ function backfillSymlinks(installRoot) {
|
|
|
5841
5884
|
return;
|
|
5842
5885
|
const detected = detectAgentSkillsRoots(installRoot);
|
|
5843
5886
|
for (const entry of entries) {
|
|
5844
|
-
const canonical =
|
|
5887
|
+
const canonical = join26(entry.installRoot, entry.dirName);
|
|
5845
5888
|
if (!existsSync20(canonical))
|
|
5846
5889
|
continue;
|
|
5847
5890
|
const fresh = fanOutSymlinks(canonical, entry.dirName, detected);
|
|
@@ -5955,7 +5998,7 @@ function readLocalVersion(path) {
|
|
|
5955
5998
|
if (!existsSync20(path))
|
|
5956
5999
|
return null;
|
|
5957
6000
|
try {
|
|
5958
|
-
const text =
|
|
6001
|
+
const text = readFileSync18(path, "utf-8");
|
|
5959
6002
|
const parsed = parseFrontmatter(text);
|
|
5960
6003
|
if (!parsed)
|
|
5961
6004
|
return null;
|
|
@@ -6050,8 +6093,8 @@ async function runPull(opts) {
|
|
|
6050
6093
|
summary.skipped++;
|
|
6051
6094
|
continue;
|
|
6052
6095
|
}
|
|
6053
|
-
const skillDir2 =
|
|
6054
|
-
const skillFile =
|
|
6096
|
+
const skillDir2 = join26(root, dirName);
|
|
6097
|
+
const skillFile = join26(skillDir2, "SKILL.md");
|
|
6055
6098
|
const remoteVersion = Number(row.version ?? 1);
|
|
6056
6099
|
const localVersion = readLocalVersion(skillFile);
|
|
6057
6100
|
const action = decideAction({
|
|
@@ -6062,14 +6105,14 @@ async function runPull(opts) {
|
|
|
6062
6105
|
});
|
|
6063
6106
|
let manifestError;
|
|
6064
6107
|
if (action === "wrote") {
|
|
6065
|
-
|
|
6108
|
+
mkdirSync10(skillDir2, { recursive: true });
|
|
6066
6109
|
if (existsSync20(skillFile)) {
|
|
6067
6110
|
try {
|
|
6068
6111
|
renameSync6(skillFile, `${skillFile}.bak`);
|
|
6069
6112
|
} catch {
|
|
6070
6113
|
}
|
|
6071
6114
|
}
|
|
6072
|
-
|
|
6115
|
+
writeFileSync14(skillFile, renderSkillFile(row));
|
|
6073
6116
|
const symlinks = opts.install === "global" ? fanOutSymlinks(skillDir2, dirName, detectAgentSkillsRoots(root)) : [];
|
|
6074
6117
|
try {
|
|
6075
6118
|
recordPull({
|
|
@@ -6112,14 +6155,14 @@ async function runPull(opts) {
|
|
|
6112
6155
|
|
|
6113
6156
|
// dist/src/skillify/unpull.js
|
|
6114
6157
|
import { existsSync as existsSync21, readdirSync as readdirSync3, rmSync as rmSync5, statSync as statSync4 } from "node:fs";
|
|
6115
|
-
import { homedir as
|
|
6116
|
-
import { join as
|
|
6158
|
+
import { homedir as homedir14 } from "node:os";
|
|
6159
|
+
import { join as join27 } from "node:path";
|
|
6117
6160
|
function resolveUnpullRoot(install, cwd) {
|
|
6118
6161
|
if (install === "global")
|
|
6119
|
-
return
|
|
6162
|
+
return join27(homedir14(), ".claude", "skills");
|
|
6120
6163
|
if (!cwd)
|
|
6121
6164
|
throw new Error("cwd required when install === 'project'");
|
|
6122
|
-
return
|
|
6165
|
+
return join27(cwd, ".claude", "skills");
|
|
6123
6166
|
}
|
|
6124
6167
|
function runUnpull(opts) {
|
|
6125
6168
|
const root = resolveUnpullRoot(opts.install, opts.cwd);
|
|
@@ -6142,7 +6185,7 @@ function runUnpull(opts) {
|
|
|
6142
6185
|
const entries = entriesForRoot(manifest, opts.install, root);
|
|
6143
6186
|
for (const entry of entries) {
|
|
6144
6187
|
summary.scanned++;
|
|
6145
|
-
const path =
|
|
6188
|
+
const path = join27(root, entry.dirName);
|
|
6146
6189
|
if (!existsSync21(path)) {
|
|
6147
6190
|
if (!opts.dryRun) {
|
|
6148
6191
|
unlinkSymlinks(entry.symlinks);
|
|
@@ -6201,7 +6244,7 @@ function runUnpull(opts) {
|
|
|
6201
6244
|
for (const dirName of readdirSync3(root)) {
|
|
6202
6245
|
if (manifestDirNames.has(dirName))
|
|
6203
6246
|
continue;
|
|
6204
|
-
const path =
|
|
6247
|
+
const path = join27(root, dirName);
|
|
6205
6248
|
let st;
|
|
6206
6249
|
try {
|
|
6207
6250
|
st = statSync4(path);
|
|
@@ -6280,21 +6323,21 @@ function decideTargetForManifestEntry(entry, opts, userFilter, haveUserFilter) {
|
|
|
6280
6323
|
|
|
6281
6324
|
// dist/src/commands/mine-local.js
|
|
6282
6325
|
import { spawn } from "node:child_process";
|
|
6283
|
-
import { existsSync as existsSync25, mkdirSync as
|
|
6284
|
-
import { homedir as
|
|
6285
|
-
import { basename, dirname as dirname7, join as
|
|
6326
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync12, readFileSync as readFileSync21, writeFileSync as writeFileSync16 } from "node:fs";
|
|
6327
|
+
import { homedir as homedir18 } from "node:os";
|
|
6328
|
+
import { basename, dirname as dirname7, join as join31 } from "node:path";
|
|
6286
6329
|
|
|
6287
6330
|
// dist/src/skillify/local-source.js
|
|
6288
|
-
import { readdirSync as readdirSync4, readFileSync as
|
|
6289
|
-
import { homedir as
|
|
6290
|
-
import { join as
|
|
6291
|
-
var HOME2 =
|
|
6331
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync19, existsSync as existsSync22, statSync as statSync5 } from "node:fs";
|
|
6332
|
+
import { homedir as homedir15 } from "node:os";
|
|
6333
|
+
import { join as join28 } from "node:path";
|
|
6334
|
+
var HOME2 = homedir15();
|
|
6292
6335
|
function encodeCwdClaudeCode(cwd) {
|
|
6293
6336
|
return cwd.replace(/[/_]/g, "-");
|
|
6294
6337
|
}
|
|
6295
6338
|
function detectInstalledAgents() {
|
|
6296
6339
|
const installs = [];
|
|
6297
|
-
const claudeRoot =
|
|
6340
|
+
const claudeRoot = join28(HOME2, ".claude", "projects");
|
|
6298
6341
|
if (existsSync22(claudeRoot)) {
|
|
6299
6342
|
installs.push({
|
|
6300
6343
|
agent: "claude_code",
|
|
@@ -6302,7 +6345,7 @@ function detectInstalledAgents() {
|
|
|
6302
6345
|
encodeCwd: encodeCwdClaudeCode
|
|
6303
6346
|
});
|
|
6304
6347
|
}
|
|
6305
|
-
const codexRoot =
|
|
6348
|
+
const codexRoot = join28(HOME2, ".codex", "sessions");
|
|
6306
6349
|
if (existsSync22(codexRoot)) {
|
|
6307
6350
|
installs.push({
|
|
6308
6351
|
agent: "codex",
|
|
@@ -6330,7 +6373,7 @@ function listLocalSessions(installs, cwd) {
|
|
|
6330
6373
|
continue;
|
|
6331
6374
|
}
|
|
6332
6375
|
for (const sub of subdirs) {
|
|
6333
|
-
const subdirPath =
|
|
6376
|
+
const subdirPath = join28(install.sessionRoot, sub);
|
|
6334
6377
|
try {
|
|
6335
6378
|
if (!statSync5(subdirPath).isDirectory())
|
|
6336
6379
|
continue;
|
|
@@ -6347,7 +6390,7 @@ function listLocalSessions(installs, cwd) {
|
|
|
6347
6390
|
for (const f of files) {
|
|
6348
6391
|
if (!f.endsWith(".jsonl"))
|
|
6349
6392
|
continue;
|
|
6350
|
-
const fullPath =
|
|
6393
|
+
const fullPath = join28(subdirPath, f);
|
|
6351
6394
|
let stats;
|
|
6352
6395
|
try {
|
|
6353
6396
|
stats = statSync5(fullPath);
|
|
@@ -6408,7 +6451,7 @@ function pickSessions(candidates, opts) {
|
|
|
6408
6451
|
function nativeJsonlToRows(filePath, sessionId, agent) {
|
|
6409
6452
|
let raw;
|
|
6410
6453
|
try {
|
|
6411
|
-
raw =
|
|
6454
|
+
raw = readFileSync19(filePath, "utf-8");
|
|
6412
6455
|
} catch {
|
|
6413
6456
|
return [];
|
|
6414
6457
|
}
|
|
@@ -6500,8 +6543,8 @@ function extractPairs(rows) {
|
|
|
6500
6543
|
// dist/src/skillify/gate-runner.js
|
|
6501
6544
|
import { existsSync as existsSync23 } from "node:fs";
|
|
6502
6545
|
import { createRequire } from "node:module";
|
|
6503
|
-
import { homedir as
|
|
6504
|
-
import { join as
|
|
6546
|
+
import { homedir as homedir16 } from "node:os";
|
|
6547
|
+
import { join as join29 } from "node:path";
|
|
6505
6548
|
var requireForCp = createRequire(import.meta.url);
|
|
6506
6549
|
var { execFileSync: runChildProcess } = requireForCp("node:child_process");
|
|
6507
6550
|
var inheritedEnv = process;
|
|
@@ -6513,7 +6556,7 @@ function firstExistingPath(candidates) {
|
|
|
6513
6556
|
return null;
|
|
6514
6557
|
}
|
|
6515
6558
|
function findAgentBin(agent) {
|
|
6516
|
-
const home =
|
|
6559
|
+
const home = homedir16();
|
|
6517
6560
|
switch (agent) {
|
|
6518
6561
|
// /usr/bin/<name> is included in every candidate list — that's the
|
|
6519
6562
|
// common Linux package-manager install path (apt, dnf, pacman). Old
|
|
@@ -6522,45 +6565,45 @@ function findAgentBin(agent) {
|
|
|
6522
6565
|
// #170 caught the gap.
|
|
6523
6566
|
case "claude_code":
|
|
6524
6567
|
return firstExistingPath([
|
|
6525
|
-
|
|
6568
|
+
join29(home, ".claude", "local", "claude"),
|
|
6526
6569
|
"/usr/local/bin/claude",
|
|
6527
6570
|
"/usr/bin/claude",
|
|
6528
|
-
|
|
6529
|
-
|
|
6571
|
+
join29(home, ".npm-global", "bin", "claude"),
|
|
6572
|
+
join29(home, ".local", "bin", "claude"),
|
|
6530
6573
|
"/opt/homebrew/bin/claude"
|
|
6531
|
-
]) ??
|
|
6574
|
+
]) ?? join29(home, ".claude", "local", "claude");
|
|
6532
6575
|
case "codex":
|
|
6533
6576
|
return firstExistingPath([
|
|
6534
6577
|
"/usr/local/bin/codex",
|
|
6535
6578
|
"/usr/bin/codex",
|
|
6536
|
-
|
|
6537
|
-
|
|
6579
|
+
join29(home, ".npm-global", "bin", "codex"),
|
|
6580
|
+
join29(home, ".local", "bin", "codex"),
|
|
6538
6581
|
"/opt/homebrew/bin/codex"
|
|
6539
6582
|
]) ?? "/usr/local/bin/codex";
|
|
6540
6583
|
case "cursor":
|
|
6541
6584
|
return firstExistingPath([
|
|
6542
6585
|
"/usr/local/bin/cursor-agent",
|
|
6543
6586
|
"/usr/bin/cursor-agent",
|
|
6544
|
-
|
|
6545
|
-
|
|
6587
|
+
join29(home, ".npm-global", "bin", "cursor-agent"),
|
|
6588
|
+
join29(home, ".local", "bin", "cursor-agent"),
|
|
6546
6589
|
"/opt/homebrew/bin/cursor-agent"
|
|
6547
6590
|
]) ?? "/usr/local/bin/cursor-agent";
|
|
6548
6591
|
case "hermes":
|
|
6549
6592
|
return firstExistingPath([
|
|
6550
|
-
|
|
6593
|
+
join29(home, ".local", "bin", "hermes"),
|
|
6551
6594
|
"/usr/local/bin/hermes",
|
|
6552
6595
|
"/usr/bin/hermes",
|
|
6553
|
-
|
|
6596
|
+
join29(home, ".npm-global", "bin", "hermes"),
|
|
6554
6597
|
"/opt/homebrew/bin/hermes"
|
|
6555
|
-
]) ??
|
|
6598
|
+
]) ?? join29(home, ".local", "bin", "hermes");
|
|
6556
6599
|
case "pi":
|
|
6557
6600
|
return firstExistingPath([
|
|
6558
|
-
|
|
6601
|
+
join29(home, ".local", "bin", "pi"),
|
|
6559
6602
|
"/usr/local/bin/pi",
|
|
6560
6603
|
"/usr/bin/pi",
|
|
6561
|
-
|
|
6604
|
+
join29(home, ".npm-global", "bin", "pi"),
|
|
6562
6605
|
"/opt/homebrew/bin/pi"
|
|
6563
|
-
]) ??
|
|
6606
|
+
]) ?? join29(home, ".local", "bin", "pi");
|
|
6564
6607
|
}
|
|
6565
6608
|
}
|
|
6566
6609
|
|
|
@@ -6590,24 +6633,25 @@ function extractJsonBlock(s) {
|
|
|
6590
6633
|
}
|
|
6591
6634
|
|
|
6592
6635
|
// dist/src/skillify/local-manifest.js
|
|
6593
|
-
import { existsSync as existsSync24, mkdirSync as
|
|
6594
|
-
import { homedir as
|
|
6595
|
-
import { dirname as dirname6, join as
|
|
6596
|
-
var LOCAL_MANIFEST_PATH =
|
|
6597
|
-
var LOCAL_MINE_LOCK_PATH =
|
|
6636
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync11, readFileSync as readFileSync20, writeFileSync as writeFileSync15 } from "node:fs";
|
|
6637
|
+
import { homedir as homedir17 } from "node:os";
|
|
6638
|
+
import { dirname as dirname6, join as join30 } from "node:path";
|
|
6639
|
+
var LOCAL_MANIFEST_PATH = join30(homedir17(), ".claude", "hivemind", "local-mined.json");
|
|
6640
|
+
var LOCAL_MINE_LOCK_PATH = join30(homedir17(), ".claude", "hivemind", "local-mined.lock");
|
|
6598
6641
|
function readLocalManifest(path = LOCAL_MANIFEST_PATH) {
|
|
6599
6642
|
if (!existsSync24(path))
|
|
6600
6643
|
return null;
|
|
6601
6644
|
try {
|
|
6602
|
-
return JSON.parse(
|
|
6645
|
+
return JSON.parse(readFileSync20(path, "utf-8"));
|
|
6603
6646
|
} catch {
|
|
6604
6647
|
return null;
|
|
6605
6648
|
}
|
|
6606
6649
|
}
|
|
6607
6650
|
function writeLocalManifest(m, path = LOCAL_MANIFEST_PATH) {
|
|
6608
|
-
|
|
6609
|
-
|
|
6651
|
+
mkdirSync11(dirname6(path), { recursive: true });
|
|
6652
|
+
writeFileSync15(path, JSON.stringify(m, null, 2));
|
|
6610
6653
|
}
|
|
6654
|
+
var LATEST_RUN_WINDOW_MS = 5 * 60 * 1e3;
|
|
6611
6655
|
|
|
6612
6656
|
// dist/src/commands/mine-local.js
|
|
6613
6657
|
import { unlinkSync as unlinkSync10 } from "node:fs";
|
|
@@ -6739,11 +6783,26 @@ function buildSessionPrompt(pairs2, session, verdictPath) {
|
|
|
6739
6783
|
`- A skill qualifies if it captures a concrete, repeatable workflow OR a non-obvious`,
|
|
6740
6784
|
` constraint/gotcha a future engineer would benefit from knowing. Intra-session is fine \u2014`,
|
|
6741
6785
|
` one deep dive yielding a generalizable takeaway counts.`,
|
|
6786
|
+
`- Especially valuable: REPEATABLE-MISTAKE patterns. Cases where the assistant declared`,
|
|
6787
|
+
` work "done"/"fixed"/"verified" and the user came back to the same problem later; where`,
|
|
6788
|
+
` the same class of mistake recurs (forgot to run tests, mishandled async state,`,
|
|
6789
|
+
` hallucinated function/file existence, re-asked for confirmation on already-authorized`,
|
|
6790
|
+
` work, jumped to plans without checking with the user, etc.); where the user manually`,
|
|
6791
|
+
` corrected the same kind of error >1 time. These are the highest-value catches.`,
|
|
6742
6792
|
`- Skip patterns that are obvious from reading the codebase or already in CLAUDE.md.`,
|
|
6743
6793
|
`- Each body uses short sections (When to use, Workflow, Anti-patterns), concrete commands`,
|
|
6744
6794
|
` / paths / snippets drawn from the exchanges below, no marketing, no emojis.`,
|
|
6745
6795
|
`- Each body under ~3000 characters.`,
|
|
6746
6796
|
`- Skill names are kebab-case slugs (lowercase letters/digits/hyphens only).`,
|
|
6797
|
+
`- For each skill, also emit a one-line "insight": a concrete, quantified, second-person`,
|
|
6798
|
+
` sentence describing what hivemind found that prompted the skill. Examples:`,
|
|
6799
|
+
` "You revisited 4 merged PRs in the last month because the assistant declared 'done'`,
|
|
6800
|
+
` before checking test output."`,
|
|
6801
|
+
` "You corrected the same env-mismatch (beta vs prod) twice in the same week before`,
|
|
6802
|
+
` deciding to switch deployment targets."`,
|
|
6803
|
+
` The insight is what users will see at next SessionStart, so it must be honest \u2014 only`,
|
|
6804
|
+
` assert counts and patterns you can ground in THIS session's exchanges. Omit the field`,
|
|
6805
|
+
` if you cannot write a concrete, quantified line.`,
|
|
6747
6806
|
``,
|
|
6748
6807
|
`=== EXCHANGES (user prompts + assistant final answers, tool calls stripped) ===`,
|
|
6749
6808
|
renderPairsBlock(pairs2),
|
|
@@ -6762,7 +6821,8 @@ function buildSessionPrompt(pairs2, session, verdictPath) {
|
|
|
6762
6821
|
` "name": "<kebab-case>",`,
|
|
6763
6822
|
` "description": "<one-line>",`,
|
|
6764
6823
|
` "trigger": "<short trigger>",`,
|
|
6765
|
-
` "body": "<full SKILL.md body without frontmatter>"
|
|
6824
|
+
` "body": "<full SKILL.md body without frontmatter>",`,
|
|
6825
|
+
` "insight": "<one-line, concrete + quantified + second person; OPTIONAL>"`,
|
|
6766
6826
|
` },`,
|
|
6767
6827
|
` ... up to 3 entries, or [] if nothing qualifies`,
|
|
6768
6828
|
` ]`,
|
|
@@ -6794,9 +6854,12 @@ function parseMultiVerdict(raw) {
|
|
|
6794
6854
|
const description = typeof s.description === "string" ? s.description.trim() : "";
|
|
6795
6855
|
const body = typeof s.body === "string" ? s.body.trim() : "";
|
|
6796
6856
|
const trigger = typeof s.trigger === "string" ? s.trigger.trim() : void 0;
|
|
6857
|
+
const rawInsight = typeof s.insight === "string" ? s.insight : "";
|
|
6858
|
+
const normalizedInsight = rawInsight.replace(/\s+/g, " ").trim();
|
|
6859
|
+
const insight = normalizedInsight.length > 0 ? normalizedInsight.slice(0, 280) : void 0;
|
|
6797
6860
|
if (!name || !body)
|
|
6798
6861
|
continue;
|
|
6799
|
-
out.push({ name, description, body, trigger });
|
|
6862
|
+
out.push({ name, description, body, trigger, insight });
|
|
6800
6863
|
}
|
|
6801
6864
|
return { reason: typeof parsed.reason === "string" ? parsed.reason : void 0, skills: out };
|
|
6802
6865
|
}
|
|
@@ -6976,8 +7039,8 @@ async function runMineLocalImpl(args) {
|
|
|
6976
7039
|
console.log(`Dry-run: would invoke ${gateAgent} gate on ${picked.length} session(s) in parallel (concurrency=${GATE_CONCURRENCY}).`);
|
|
6977
7040
|
return;
|
|
6978
7041
|
}
|
|
6979
|
-
const tmpDir =
|
|
6980
|
-
|
|
7042
|
+
const tmpDir = join31(homedir18(), ".claude", "hivemind", `mine-local-${Date.now()}`);
|
|
7043
|
+
mkdirSync12(tmpDir, { recursive: true });
|
|
6981
7044
|
console.log(`Running ${picked.length} gate call(s) in parallel (concurrency=${GATE_CONCURRENCY}, timeout=${GATE_TIMEOUT_MS / 1e3}s each)...`);
|
|
6982
7045
|
const results = await parallelMap(picked, GATE_CONCURRENCY, async (s) => {
|
|
6983
7046
|
const shortId = s.sessionId.slice(0, 8);
|
|
@@ -6988,23 +7051,23 @@ async function runMineLocalImpl(args) {
|
|
|
6988
7051
|
return { session: s, skills: [], reason: "no pairs", error: null };
|
|
6989
7052
|
}
|
|
6990
7053
|
const tail = pairs2.slice(-PER_SESSION_PAIR_CAP);
|
|
6991
|
-
const sessionTmp =
|
|
6992
|
-
|
|
6993
|
-
const verdictPath =
|
|
7054
|
+
const sessionTmp = join31(tmpDir, `s-${shortId}`);
|
|
7055
|
+
mkdirSync12(sessionTmp, { recursive: true });
|
|
7056
|
+
const verdictPath = join31(sessionTmp, "verdict.json");
|
|
6994
7057
|
const prompt = buildSessionPrompt(tail, s, verdictPath);
|
|
6995
|
-
|
|
7058
|
+
writeFileSync16(join31(sessionTmp, "prompt.txt"), prompt);
|
|
6996
7059
|
const gate = await runGateViaStdin({ agent: gateAgent, bin: gateBin, prompt, timeoutMs: GATE_TIMEOUT_MS });
|
|
6997
7060
|
try {
|
|
6998
|
-
|
|
7061
|
+
writeFileSync16(join31(sessionTmp, "gate-stdout.txt"), gate.stdout);
|
|
6999
7062
|
if (gate.stderr)
|
|
7000
|
-
|
|
7063
|
+
writeFileSync16(join31(sessionTmp, "gate-stderr.txt"), gate.stderr);
|
|
7001
7064
|
} catch {
|
|
7002
7065
|
}
|
|
7003
7066
|
if (gate.errored) {
|
|
7004
7067
|
console.log(` [${shortId}] gate failed: ${gate.errorMessage}`);
|
|
7005
7068
|
return { session: s, skills: [], reason: null, error: gate.errorMessage ?? "gate failed" };
|
|
7006
7069
|
}
|
|
7007
|
-
const verdictText = existsSync25(verdictPath) ?
|
|
7070
|
+
const verdictText = existsSync25(verdictPath) ? readFileSync21(verdictPath, "utf-8") : gate.stdout;
|
|
7008
7071
|
const mv = parseMultiVerdict(verdictText);
|
|
7009
7072
|
if (!mv) {
|
|
7010
7073
|
console.log(` [${shortId}] unparseable verdict (kept at ${sessionTmp})`);
|
|
@@ -7081,7 +7144,12 @@ async function runMineLocalImpl(args) {
|
|
|
7081
7144
|
source_agent: session.agent,
|
|
7082
7145
|
gate_agent: gateAgent,
|
|
7083
7146
|
created_at: result.createdAt,
|
|
7084
|
-
uploaded: false
|
|
7147
|
+
uploaded: false,
|
|
7148
|
+
// Persist the one-line insight when the gate produced one. Omitted
|
|
7149
|
+
// (undefined → absent in JSON) when the gate couldn't ground a
|
|
7150
|
+
// concrete line, so the SessionStart banner falls back to the
|
|
7151
|
+
// count-only surface for entries written before this field landed.
|
|
7152
|
+
...skill.insight ? { insight: skill.insight } : {}
|
|
7085
7153
|
}));
|
|
7086
7154
|
saveManifest2({
|
|
7087
7155
|
created_at: existing?.created_at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -7240,7 +7308,7 @@ function showStatus() {
|
|
|
7240
7308
|
console.log(`state: ${files.length} project(s) tracked`);
|
|
7241
7309
|
for (const f of files) {
|
|
7242
7310
|
try {
|
|
7243
|
-
const s = JSON.parse(
|
|
7311
|
+
const s = JSON.parse(readFileSync22(join32(dir, f), "utf-8"));
|
|
7244
7312
|
const last = typeof s.updatedAt === "number" ? new Date(s.updatedAt).toISOString() : s.lastDate ?? "never";
|
|
7245
7313
|
const skills = Array.isArray(s.skillsGenerated) && s.skillsGenerated.length > 0 ? s.skillsGenerated.join(", ") : "none";
|
|
7246
7314
|
console.log(` - ${s.project} (counter=${s.counter}, last=${last}, skills=${skills})`);
|
|
@@ -7267,7 +7335,7 @@ function setInstall(loc) {
|
|
|
7267
7335
|
}
|
|
7268
7336
|
const cfg = loadScopeConfig();
|
|
7269
7337
|
saveScopeConfig({ ...cfg, install: loc });
|
|
7270
|
-
const path = loc === "global" ?
|
|
7338
|
+
const path = loc === "global" ? join32(homedir19(), ".claude", "skills") : "<cwd>/.claude/skills";
|
|
7271
7339
|
console.log(`Install location set to '${loc}'. New skills will be written to ${path}/<name>/SKILL.md.`);
|
|
7272
7340
|
}
|
|
7273
7341
|
function promoteSkill(name, cwd) {
|
|
@@ -7275,17 +7343,17 @@ function promoteSkill(name, cwd) {
|
|
|
7275
7343
|
console.error("Usage: hivemind skillify promote <skill-name>");
|
|
7276
7344
|
process.exit(1);
|
|
7277
7345
|
}
|
|
7278
|
-
const projectPath =
|
|
7279
|
-
const globalPath =
|
|
7280
|
-
if (!existsSync26(
|
|
7346
|
+
const projectPath = join32(cwd, ".claude", "skills", name);
|
|
7347
|
+
const globalPath = join32(homedir19(), ".claude", "skills", name);
|
|
7348
|
+
if (!existsSync26(join32(projectPath, "SKILL.md"))) {
|
|
7281
7349
|
console.error(`Skill '${name}' not found at ${projectPath}/SKILL.md`);
|
|
7282
7350
|
process.exit(1);
|
|
7283
7351
|
}
|
|
7284
|
-
if (existsSync26(
|
|
7352
|
+
if (existsSync26(join32(globalPath, "SKILL.md"))) {
|
|
7285
7353
|
console.error(`Skill '${name}' already exists at ${globalPath}/SKILL.md \u2014 refusing to overwrite. Remove it first or rename the project skill.`);
|
|
7286
7354
|
process.exit(1);
|
|
7287
7355
|
}
|
|
7288
|
-
|
|
7356
|
+
mkdirSync13(dirname8(globalPath), { recursive: true });
|
|
7289
7357
|
renameSync7(projectPath, globalPath);
|
|
7290
7358
|
console.log(`Promoted '${name}' from ${projectPath} \u2192 ${globalPath}.`);
|
|
7291
7359
|
}
|
|
@@ -7392,7 +7460,7 @@ async function pullSkills(args) {
|
|
|
7392
7460
|
console.error(`pull failed: ${e?.message ?? e}`);
|
|
7393
7461
|
process.exit(1);
|
|
7394
7462
|
}
|
|
7395
|
-
const dest = toRaw === "global" ?
|
|
7463
|
+
const dest = toRaw === "global" ? join32(homedir19(), ".claude", "skills") : `${process.cwd()}/.claude/skills`;
|
|
7396
7464
|
const filterDesc = users.length === 0 ? "all users" : users.join(", ");
|
|
7397
7465
|
console.log(`Destination: ${dest}`);
|
|
7398
7466
|
console.log(`Filter: ${filterDesc}${skillName ? ` \xB7 skill='${skillName}'` : ""}${dryRun ? " \xB7 dry-run" : ""}${force ? " \xB7 force" : ""}`);
|
|
@@ -7442,7 +7510,7 @@ async function unpullSkills(args) {
|
|
|
7442
7510
|
all,
|
|
7443
7511
|
legacyCleanup
|
|
7444
7512
|
});
|
|
7445
|
-
const dest = toRaw === "global" ?
|
|
7513
|
+
const dest = toRaw === "global" ? join32(homedir19(), ".claude", "skills") : `${process.cwd()}/.claude/skills`;
|
|
7446
7514
|
const filterParts = [];
|
|
7447
7515
|
if (users.length > 0)
|
|
7448
7516
|
filterParts.push(`users=${users.join(",")}`);
|
|
@@ -7538,14 +7606,14 @@ if (process.argv[1] && process.argv[1].endsWith("skillify.js")) {
|
|
|
7538
7606
|
|
|
7539
7607
|
// dist/src/cli/update.js
|
|
7540
7608
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
7541
|
-
import { closeSync as closeSync2, existsSync as existsSync27, mkdirSync as
|
|
7542
|
-
import { homedir as
|
|
7543
|
-
import { dirname as dirname10, join as
|
|
7609
|
+
import { closeSync as closeSync2, existsSync as existsSync27, mkdirSync as mkdirSync14, openSync as openSync2, readFileSync as readFileSync24, realpathSync, unlinkSync as unlinkSync11, writeSync } from "node:fs";
|
|
7610
|
+
import { homedir as homedir20 } from "node:os";
|
|
7611
|
+
import { dirname as dirname10, join as join34, sep } from "node:path";
|
|
7544
7612
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
7545
7613
|
|
|
7546
7614
|
// dist/src/utils/version-check.js
|
|
7547
|
-
import { readFileSync as
|
|
7548
|
-
import { dirname as dirname9, join as
|
|
7615
|
+
import { readFileSync as readFileSync23 } from "node:fs";
|
|
7616
|
+
import { dirname as dirname9, join as join33 } from "node:path";
|
|
7549
7617
|
function isNewer(latest, current) {
|
|
7550
7618
|
const parse = (v) => v.split(".").map(Number);
|
|
7551
7619
|
const [la, lb, lc] = parse(latest);
|
|
@@ -7557,7 +7625,7 @@ function isNewer(latest, current) {
|
|
|
7557
7625
|
var NPM_REGISTRY_URL = "https://registry.npmjs.org/@deeplake/hivemind/latest";
|
|
7558
7626
|
var PKG_NAME = "@deeplake/hivemind";
|
|
7559
7627
|
function defaultLockPath() {
|
|
7560
|
-
return
|
|
7628
|
+
return join34(homedir20(), ".deeplake", "hivemind-update.lock");
|
|
7561
7629
|
}
|
|
7562
7630
|
function detectInstallKind(argv1) {
|
|
7563
7631
|
const realArgv1 = (() => {
|
|
@@ -7572,7 +7640,7 @@ function detectInstallKind(argv1) {
|
|
|
7572
7640
|
for (let i = 0; i < 10; i++) {
|
|
7573
7641
|
const pkgPath = `${dir}${sep}package.json`;
|
|
7574
7642
|
try {
|
|
7575
|
-
const pkg = JSON.parse(
|
|
7643
|
+
const pkg = JSON.parse(readFileSync24(pkgPath, "utf-8"));
|
|
7576
7644
|
if (pkg.name === PKG_NAME || pkg.name === "hivemind") {
|
|
7577
7645
|
installDir = dir;
|
|
7578
7646
|
break;
|
|
@@ -7618,7 +7686,7 @@ var defaultSpawn = (cmd, args) => {
|
|
|
7618
7686
|
execFileSync4(cmd, args, { stdio: "inherit" });
|
|
7619
7687
|
};
|
|
7620
7688
|
function tryAcquireLock(path) {
|
|
7621
|
-
|
|
7689
|
+
mkdirSync14(dirname10(path), { recursive: true, mode: 448 });
|
|
7622
7690
|
const claim = () => {
|
|
7623
7691
|
const fd = openSync2(path, "wx", 384);
|
|
7624
7692
|
writeSync(fd, String(process.pid));
|
|
@@ -7632,7 +7700,7 @@ function tryAcquireLock(path) {
|
|
|
7632
7700
|
}
|
|
7633
7701
|
let holderPid = 0;
|
|
7634
7702
|
try {
|
|
7635
|
-
holderPid = Number(
|
|
7703
|
+
holderPid = Number(readFileSync24(path, "utf-8").trim()) || 0;
|
|
7636
7704
|
} catch {
|
|
7637
7705
|
try {
|
|
7638
7706
|
return claim();
|