@deeplake/hivemind 0.7.32 → 0.7.34
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 +332 -189
- 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 +229 -87
- package/codex/bundle/shell/deeplake-shell.js +328 -295
- package/codex/bundle/skillify-worker.js +26 -18
- package/codex/bundle/stop.js +450 -394
- package/codex/bundle/wiki-worker.js +174 -292
- package/cursor/bundle/capture.js +448 -392
- package/cursor/bundle/commands/auth-login.js +163 -30
- package/cursor/bundle/pre-tool-use.js +324 -291
- package/cursor/bundle/session-end.js +43 -20
- package/cursor/bundle/session-start.js +272 -130
- package/cursor/bundle/shell/deeplake-shell.js +328 -295
- package/cursor/bundle/skillify-worker.js +26 -18
- package/cursor/bundle/wiki-worker.js +174 -292
- package/hermes/bundle/capture.js +448 -392
- package/hermes/bundle/commands/auth-login.js +163 -30
- package/hermes/bundle/pre-tool-use.js +324 -291
- package/hermes/bundle/session-end.js +43 -20
- package/hermes/bundle/session-start.js +269 -127
- package/hermes/bundle/shell/deeplake-shell.js +328 -295
- package/hermes/bundle/skillify-worker.js +26 -18
- package/hermes/bundle/wiki-worker.js +174 -292
- package/mcp/bundle/server.js +190 -57
- package/openclaw/dist/index.js +160 -32
- package/openclaw/dist/skillify-worker.js +26 -18
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/package.json +1 -1
package/openclaw/dist/index.js
CHANGED
|
@@ -104,13 +104,112 @@ function sqlIdent(name) {
|
|
|
104
104
|
var SUMMARY_EMBEDDING_COL = "summary_embedding";
|
|
105
105
|
var MESSAGE_EMBEDDING_COL = "message_embedding";
|
|
106
106
|
|
|
107
|
+
// src/notifications/queue.ts
|
|
108
|
+
import { readFileSync, writeFileSync, renameSync, mkdirSync, openSync, closeSync, unlinkSync, statSync } from "node:fs";
|
|
109
|
+
import { join as join2, resolve } from "node:path";
|
|
110
|
+
import { homedir as homedir2 } from "node:os";
|
|
111
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
112
|
+
var log2 = (msg) => log("notifications-queue", msg);
|
|
113
|
+
var LOCK_RETRY_MAX = 50;
|
|
114
|
+
var LOCK_RETRY_BASE_MS = 5;
|
|
115
|
+
var LOCK_STALE_MS = 5e3;
|
|
116
|
+
function queuePath() {
|
|
117
|
+
return join2(homedir2(), ".deeplake", "notifications-queue.json");
|
|
118
|
+
}
|
|
119
|
+
function lockPath() {
|
|
120
|
+
return `${queuePath()}.lock`;
|
|
121
|
+
}
|
|
122
|
+
function readQueue() {
|
|
123
|
+
try {
|
|
124
|
+
const raw = readFileSync(queuePath(), "utf-8");
|
|
125
|
+
const parsed = JSON.parse(raw);
|
|
126
|
+
if (!parsed || !Array.isArray(parsed.queue)) {
|
|
127
|
+
log2(`queue malformed \u2192 treating as empty`);
|
|
128
|
+
return { queue: [] };
|
|
129
|
+
}
|
|
130
|
+
return { queue: parsed.queue };
|
|
131
|
+
} catch {
|
|
132
|
+
return { queue: [] };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function _isQueuePathInsideHome(path, home) {
|
|
136
|
+
const r = resolve(path);
|
|
137
|
+
const h = resolve(home);
|
|
138
|
+
return r.startsWith(h + "/") || r === h;
|
|
139
|
+
}
|
|
140
|
+
function writeQueue(q) {
|
|
141
|
+
const path = queuePath();
|
|
142
|
+
const home = resolve(homedir2());
|
|
143
|
+
if (!_isQueuePathInsideHome(path, home)) {
|
|
144
|
+
throw new Error(`notifications-queue write blocked: ${path} is outside ${home}`);
|
|
145
|
+
}
|
|
146
|
+
mkdirSync(join2(home, ".deeplake"), { recursive: true, mode: 448 });
|
|
147
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
148
|
+
writeFileSync(tmp, JSON.stringify(q, null, 2), { mode: 384 });
|
|
149
|
+
renameSync(tmp, path);
|
|
150
|
+
}
|
|
151
|
+
async function withQueueLock(fn) {
|
|
152
|
+
const path = lockPath();
|
|
153
|
+
mkdirSync(join2(homedir2(), ".deeplake"), { recursive: true, mode: 448 });
|
|
154
|
+
let fd = null;
|
|
155
|
+
for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
|
|
156
|
+
try {
|
|
157
|
+
fd = openSync(path, "wx", 384);
|
|
158
|
+
break;
|
|
159
|
+
} catch (e) {
|
|
160
|
+
const code = e.code;
|
|
161
|
+
if (code !== "EEXIST") throw e;
|
|
162
|
+
try {
|
|
163
|
+
const age = Date.now() - statSync(path).mtimeMs;
|
|
164
|
+
if (age > LOCK_STALE_MS) {
|
|
165
|
+
unlinkSync(path);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
} catch {
|
|
169
|
+
}
|
|
170
|
+
const delay = LOCK_RETRY_BASE_MS * (attempt + 1);
|
|
171
|
+
await sleep(delay);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (fd === null) {
|
|
175
|
+
log2(`lock acquisition gave up after ${LOCK_RETRY_MAX} attempts \u2014 proceeding unlocked (last-writer-wins)`);
|
|
176
|
+
return fn();
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
return fn();
|
|
180
|
+
} finally {
|
|
181
|
+
try {
|
|
182
|
+
closeSync(fd);
|
|
183
|
+
} catch {
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
unlinkSync(path);
|
|
187
|
+
} catch {
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function sameDedupKey(a, b) {
|
|
192
|
+
if (a.id !== b.id) return false;
|
|
193
|
+
return JSON.stringify(a.dedupKey) === JSON.stringify(b.dedupKey);
|
|
194
|
+
}
|
|
195
|
+
async function enqueueNotification(n) {
|
|
196
|
+
await withQueueLock(() => {
|
|
197
|
+
const q = readQueue();
|
|
198
|
+
if (q.queue.some((existing) => sameDedupKey(existing, n))) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
q.queue.push(n);
|
|
202
|
+
writeQueue(q);
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
107
206
|
// src/deeplake-api.ts
|
|
108
207
|
var indexMarkerStorePromise = null;
|
|
109
208
|
function getIndexMarkerStore() {
|
|
110
209
|
if (!indexMarkerStorePromise) indexMarkerStorePromise = import("./chunks/index-marker-store-CPGF2BI7.js");
|
|
111
210
|
return indexMarkerStorePromise;
|
|
112
211
|
}
|
|
113
|
-
var
|
|
212
|
+
var log3 = (msg) => log("sdk", msg);
|
|
114
213
|
function summarizeSql(sql, maxLen = 220) {
|
|
115
214
|
const compact = sql.replace(/\s+/g, " ").trim();
|
|
116
215
|
return compact.length > maxLen ? `${compact.slice(0, maxLen)}...` : compact;
|
|
@@ -120,7 +219,35 @@ function traceSql(msg) {
|
|
|
120
219
|
if (!traceEnabled) return;
|
|
121
220
|
process.stderr.write(`[deeplake-sql] ${msg}
|
|
122
221
|
`);
|
|
123
|
-
if (globalThis.__hivemind_tuning__.HIVEMIND_DEBUG === "1")
|
|
222
|
+
if (globalThis.__hivemind_tuning__.HIVEMIND_DEBUG === "1") log3(msg);
|
|
223
|
+
}
|
|
224
|
+
var _signalledBalanceExhausted = false;
|
|
225
|
+
function maybeSignalBalanceExhausted(status, bodyText) {
|
|
226
|
+
if (status !== 402) return;
|
|
227
|
+
if (!bodyText.includes("balance_cents")) return;
|
|
228
|
+
if (_signalledBalanceExhausted) return;
|
|
229
|
+
_signalledBalanceExhausted = true;
|
|
230
|
+
log3(`balance exhausted \u2014 enqueuing session-start banner (body=${bodyText.slice(0, 120)})`);
|
|
231
|
+
enqueueNotification({
|
|
232
|
+
id: "balance-exhausted",
|
|
233
|
+
severity: "warn",
|
|
234
|
+
transient: true,
|
|
235
|
+
title: "Hivemind credits exhausted \u2014 top up to keep capturing",
|
|
236
|
+
body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
|
|
237
|
+
dedupKey: { reason: "balance-zero" }
|
|
238
|
+
}).catch((e) => {
|
|
239
|
+
log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
function billingUrl() {
|
|
243
|
+
try {
|
|
244
|
+
const c = loadCredentials();
|
|
245
|
+
if (c?.orgName && c?.workspaceId) {
|
|
246
|
+
return `https://deeplake.ai/${encodeURIComponent(c.orgName)}/workspace/${encodeURIComponent(c.workspaceId)}/billing`;
|
|
247
|
+
}
|
|
248
|
+
} catch {
|
|
249
|
+
}
|
|
250
|
+
return "https://deeplake.ai";
|
|
124
251
|
}
|
|
125
252
|
var RETRYABLE_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
126
253
|
var MAX_RETRIES = 3;
|
|
@@ -129,8 +256,8 @@ var MAX_CONCURRENCY = 5;
|
|
|
129
256
|
function getQueryTimeoutMs() {
|
|
130
257
|
return Number(globalThis.__hivemind_tuning__.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
|
|
131
258
|
}
|
|
132
|
-
function
|
|
133
|
-
return new Promise((
|
|
259
|
+
function sleep2(ms) {
|
|
260
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
134
261
|
}
|
|
135
262
|
function isTimeoutError(error) {
|
|
136
263
|
const name = error instanceof Error ? error.name.toLowerCase() : "";
|
|
@@ -160,7 +287,7 @@ var Semaphore = class {
|
|
|
160
287
|
this.active++;
|
|
161
288
|
return;
|
|
162
289
|
}
|
|
163
|
-
await new Promise((
|
|
290
|
+
await new Promise((resolve2) => this.waiting.push(resolve2));
|
|
164
291
|
}
|
|
165
292
|
release() {
|
|
166
293
|
this.active--;
|
|
@@ -231,8 +358,8 @@ var DeeplakeApi = class {
|
|
|
231
358
|
lastError = e instanceof Error ? e : new Error(String(e));
|
|
232
359
|
if (attempt < MAX_RETRIES) {
|
|
233
360
|
const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
|
|
234
|
-
|
|
235
|
-
await
|
|
361
|
+
log3(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
|
|
362
|
+
await sleep2(delay);
|
|
236
363
|
continue;
|
|
237
364
|
}
|
|
238
365
|
throw lastError;
|
|
@@ -249,10 +376,11 @@ var DeeplakeApi = class {
|
|
|
249
376
|
const alreadyExists = resp.status === 500 && isDuplicateIndexError(text);
|
|
250
377
|
if (!alreadyExists && attempt < MAX_RETRIES && (RETRYABLE_CODES.has(resp.status) || retryable403)) {
|
|
251
378
|
const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
|
|
252
|
-
|
|
253
|
-
await
|
|
379
|
+
log3(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
|
|
380
|
+
await sleep2(delay);
|
|
254
381
|
continue;
|
|
255
382
|
}
|
|
383
|
+
maybeSignalBalanceExhausted(resp.status, text);
|
|
256
384
|
throw new Error(`Query failed: ${resp.status}: ${text.slice(0, 200)}`);
|
|
257
385
|
}
|
|
258
386
|
throw lastError ?? new Error("Query failed: max retries exceeded");
|
|
@@ -272,7 +400,7 @@ var DeeplakeApi = class {
|
|
|
272
400
|
const chunk = rows.slice(i, i + CONCURRENCY);
|
|
273
401
|
await Promise.allSettled(chunk.map((r) => this.upsertRowSql(r)));
|
|
274
402
|
}
|
|
275
|
-
|
|
403
|
+
log3(`commit: ${rows.length} rows`);
|
|
276
404
|
}
|
|
277
405
|
async upsertRowSql(row) {
|
|
278
406
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -333,7 +461,7 @@ var DeeplakeApi = class {
|
|
|
333
461
|
markers.writeIndexMarker(markerPath);
|
|
334
462
|
return;
|
|
335
463
|
}
|
|
336
|
-
|
|
464
|
+
log3(`index "${indexName}" skipped: ${e.message}`);
|
|
337
465
|
}
|
|
338
466
|
}
|
|
339
467
|
/**
|
|
@@ -418,13 +546,13 @@ var DeeplakeApi = class {
|
|
|
418
546
|
};
|
|
419
547
|
}
|
|
420
548
|
if (attempt < MAX_RETRIES && RETRYABLE_CODES.has(resp.status)) {
|
|
421
|
-
await
|
|
549
|
+
await sleep2(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
|
|
422
550
|
continue;
|
|
423
551
|
}
|
|
424
552
|
return { tables: [], cacheable: false };
|
|
425
553
|
} catch {
|
|
426
554
|
if (attempt < MAX_RETRIES) {
|
|
427
|
-
await
|
|
555
|
+
await sleep2(BASE_DELAY_MS * Math.pow(2, attempt));
|
|
428
556
|
continue;
|
|
429
557
|
}
|
|
430
558
|
return { tables: [], cacheable: false };
|
|
@@ -452,9 +580,9 @@ var DeeplakeApi = class {
|
|
|
452
580
|
} catch (err) {
|
|
453
581
|
lastErr = err;
|
|
454
582
|
const msg = err instanceof Error ? err.message : String(err);
|
|
455
|
-
|
|
583
|
+
log3(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
|
|
456
584
|
if (attempt < OUTER_BACKOFFS_MS.length) {
|
|
457
|
-
await
|
|
585
|
+
await sleep2(OUTER_BACKOFFS_MS[attempt]);
|
|
458
586
|
}
|
|
459
587
|
}
|
|
460
588
|
}
|
|
@@ -465,12 +593,12 @@ var DeeplakeApi = class {
|
|
|
465
593
|
const tbl = sqlIdent(name ?? this.tableName);
|
|
466
594
|
const tables = await this.listTables();
|
|
467
595
|
if (!tables.includes(tbl)) {
|
|
468
|
-
|
|
596
|
+
log3(`table "${tbl}" not found, creating`);
|
|
469
597
|
await this.createTableWithRetry(
|
|
470
598
|
`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`,
|
|
471
599
|
tbl
|
|
472
600
|
);
|
|
473
|
-
|
|
601
|
+
log3(`table "${tbl}" created`);
|
|
474
602
|
if (!tables.includes(tbl)) this._tablesCache = [...tables, tbl];
|
|
475
603
|
}
|
|
476
604
|
await this.ensureEmbeddingColumn(tbl, SUMMARY_EMBEDDING_COL);
|
|
@@ -482,12 +610,12 @@ var DeeplakeApi = class {
|
|
|
482
610
|
const safe = sqlIdent(name);
|
|
483
611
|
const tables = await this.listTables();
|
|
484
612
|
if (!tables.includes(safe)) {
|
|
485
|
-
|
|
613
|
+
log3(`table "${safe}" not found, creating`);
|
|
486
614
|
await this.createTableWithRetry(
|
|
487
615
|
`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`,
|
|
488
616
|
safe
|
|
489
617
|
);
|
|
490
|
-
|
|
618
|
+
log3(`table "${safe}" created`);
|
|
491
619
|
if (!tables.includes(safe)) this._tablesCache = [...tables, safe];
|
|
492
620
|
}
|
|
493
621
|
await this.ensureEmbeddingColumn(safe, MESSAGE_EMBEDDING_COL);
|
|
@@ -509,12 +637,12 @@ var DeeplakeApi = class {
|
|
|
509
637
|
const safe = sqlIdent(name);
|
|
510
638
|
const tables = await this.listTables();
|
|
511
639
|
if (!tables.includes(safe)) {
|
|
512
|
-
|
|
640
|
+
log3(`table "${safe}" not found, creating`);
|
|
513
641
|
await this.createTableWithRetry(
|
|
514
642
|
`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`,
|
|
515
643
|
safe
|
|
516
644
|
);
|
|
517
|
-
|
|
645
|
+
log3(`table "${safe}" created`);
|
|
518
646
|
if (!tables.includes(safe)) this._tablesCache = [...tables, safe];
|
|
519
647
|
}
|
|
520
648
|
await this.ensureLookupIndex(safe, "project_key_name", `("project_key", "name")`);
|
|
@@ -1028,7 +1156,7 @@ async function readVirtualPathContent(api2, memoryTable2, sessionsTable2, virtua
|
|
|
1028
1156
|
// openclaw/src/index.ts
|
|
1029
1157
|
import { fileURLToPath } from "node:url";
|
|
1030
1158
|
import { join as joinPath, dirname as dirnamePath } from "node:path";
|
|
1031
|
-
import { homedir as
|
|
1159
|
+
import { homedir as homedir3, tmpdir } from "node:os";
|
|
1032
1160
|
import {
|
|
1033
1161
|
existsSync as fsExists,
|
|
1034
1162
|
mkdirSync as fsMkdir,
|
|
@@ -1111,7 +1239,7 @@ function extractLatestVersion(body) {
|
|
|
1111
1239
|
return typeof v === "string" && v.length > 0 ? v : null;
|
|
1112
1240
|
}
|
|
1113
1241
|
function getInstalledVersion() {
|
|
1114
|
-
return "0.7.
|
|
1242
|
+
return "0.7.34".length > 0 ? "0.7.34" : null;
|
|
1115
1243
|
}
|
|
1116
1244
|
function isNewer(latest, current) {
|
|
1117
1245
|
const parse = (v) => v.replace(/-.*$/, "").split(".").map(Number);
|
|
@@ -1218,8 +1346,8 @@ var skillifySpawnedFor = /* @__PURE__ */ new Set();
|
|
|
1218
1346
|
var __openclaw_filename = fileURLToPath(import.meta.url);
|
|
1219
1347
|
var __openclaw_dirname = dirnamePath(__openclaw_filename);
|
|
1220
1348
|
var OPENCLAW_SKILLIFY_WORKER_PATH = joinPath(__openclaw_dirname, "skillify-worker.js");
|
|
1221
|
-
var OPENCLAW_SKILLIFY_STATE_DIR = joinPath(
|
|
1222
|
-
var OPENCLAW_SKILLIFY_LEGACY_STATE_DIR = joinPath(
|
|
1349
|
+
var OPENCLAW_SKILLIFY_STATE_DIR = joinPath(homedir3(), ".deeplake", "state", "skillify");
|
|
1350
|
+
var OPENCLAW_SKILLIFY_LEGACY_STATE_DIR = joinPath(homedir3(), ".deeplake", "state", "skilify");
|
|
1223
1351
|
var openclawSkillifyMigrationAttempted = false;
|
|
1224
1352
|
function migrateOpenclawSkillifyLegacyStateDir() {
|
|
1225
1353
|
if (openclawSkillifyMigrationAttempted) return;
|
|
@@ -1244,9 +1372,9 @@ function tryAcquireOpenclawSkillifyLock(projectKey) {
|
|
|
1244
1372
|
try {
|
|
1245
1373
|
migrateOpenclawSkillifyLegacyStateDir();
|
|
1246
1374
|
fsMkdir(OPENCLAW_SKILLIFY_STATE_DIR, { recursive: true });
|
|
1247
|
-
const
|
|
1375
|
+
const lockPath2 = joinPath(OPENCLAW_SKILLIFY_STATE_DIR, `${projectKey}.worker.lock`);
|
|
1248
1376
|
const acquire = () => {
|
|
1249
|
-
const fd = fsOpen(
|
|
1377
|
+
const fd = fsOpen(lockPath2, fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_WRONLY);
|
|
1250
1378
|
try {
|
|
1251
1379
|
fsWriteFile(fd, String(Date.now()));
|
|
1252
1380
|
} finally {
|
|
@@ -1258,19 +1386,19 @@ function tryAcquireOpenclawSkillifyLock(projectKey) {
|
|
|
1258
1386
|
return acquire();
|
|
1259
1387
|
} catch {
|
|
1260
1388
|
try {
|
|
1261
|
-
const body = fsReadFile(
|
|
1389
|
+
const body = fsReadFile(lockPath2, "utf-8");
|
|
1262
1390
|
const ts = Number.parseInt(body.trim(), 10);
|
|
1263
1391
|
const ageByBody = Number.isFinite(ts) ? Date.now() - ts : Number.POSITIVE_INFINITY;
|
|
1264
1392
|
let ageByMtime = 0;
|
|
1265
1393
|
try {
|
|
1266
|
-
ageByMtime = Date.now() - fsStat(
|
|
1394
|
+
ageByMtime = Date.now() - fsStat(lockPath2).mtimeMs;
|
|
1267
1395
|
} catch {
|
|
1268
1396
|
ageByMtime = 0;
|
|
1269
1397
|
}
|
|
1270
1398
|
const effectiveAge = Number.isFinite(ts) ? ageByBody : ageByMtime;
|
|
1271
1399
|
if (effectiveAge > LOCK_MAX_AGE_MS) {
|
|
1272
1400
|
try {
|
|
1273
|
-
fsUnlink(
|
|
1401
|
+
fsUnlink(lockPath2);
|
|
1274
1402
|
} catch {
|
|
1275
1403
|
}
|
|
1276
1404
|
try {
|
|
@@ -1335,7 +1463,7 @@ function spawnOpenclawSkillifyWorker(a) {
|
|
|
1335
1463
|
sessionsTable,
|
|
1336
1464
|
skillsTable,
|
|
1337
1465
|
userName: a.userName,
|
|
1338
|
-
cwd:
|
|
1466
|
+
cwd: homedir3(),
|
|
1339
1467
|
// sentinel — only used by worker if install=project
|
|
1340
1468
|
projectKey,
|
|
1341
1469
|
project,
|
|
@@ -1351,7 +1479,7 @@ function spawnOpenclawSkillifyWorker(a) {
|
|
|
1351
1479
|
cursorModel: void 0,
|
|
1352
1480
|
hermesProvider: void 0,
|
|
1353
1481
|
hermesModel: void 0,
|
|
1354
|
-
skillifyLog: joinPath(
|
|
1482
|
+
skillifyLog: joinPath(homedir3(), ".deeplake", "hivemind-openclaw-skillify.log"),
|
|
1355
1483
|
currentSessionId: a.sessionId,
|
|
1356
1484
|
// Pass the tuning dispatch through so the worker can repopulate its
|
|
1357
1485
|
// own globalThis (each process has its own globalThis). The worker
|
|
@@ -3,7 +3,7 @@ globalThis.__hivemind_tuning__ ??= {};
|
|
|
3
3
|
|
|
4
4
|
// dist/src/skillify/skillify-worker.js
|
|
5
5
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsSync as existsSync5, appendFileSync as appendFileSync2, rmSync } from "node:fs";
|
|
6
|
-
import { join as
|
|
6
|
+
import { join as join7 } from "node:path";
|
|
7
7
|
|
|
8
8
|
// dist/src/utils/debug.js
|
|
9
9
|
import { appendFileSync } from "node:fs";
|
|
@@ -562,25 +562,34 @@ function resolveRecordScope(args) {
|
|
|
562
562
|
}
|
|
563
563
|
|
|
564
564
|
// dist/src/skillify/state.js
|
|
565
|
-
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, writeSync, mkdirSync as mkdirSync2, renameSync as renameSync2, existsSync as existsSync4, unlinkSync, openSync, closeSync } from "node:fs";
|
|
565
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, writeSync, mkdirSync as mkdirSync2, renameSync as renameSync2, rmdirSync, existsSync as existsSync4, lstatSync, unlinkSync, openSync, closeSync } from "node:fs";
|
|
566
566
|
import { execSync } from "node:child_process";
|
|
567
|
-
import { homedir as homedir5 } from "node:os";
|
|
568
567
|
import { createHash } from "node:crypto";
|
|
569
|
-
import { join as
|
|
568
|
+
import { join as join6, basename } from "node:path";
|
|
570
569
|
|
|
571
570
|
// dist/src/skillify/legacy-migration.js
|
|
572
571
|
import { existsSync as existsSync3, renameSync } from "node:fs";
|
|
572
|
+
import { dirname, join as join5 } from "node:path";
|
|
573
|
+
|
|
574
|
+
// dist/src/skillify/state-dir.js
|
|
573
575
|
import { homedir as homedir4 } from "node:os";
|
|
574
576
|
import { join as join4 } from "node:path";
|
|
577
|
+
function getStateDir() {
|
|
578
|
+
const override = globalThis.__hivemind_tuning__.HIVEMIND_STATE_DIR?.trim();
|
|
579
|
+
return override && override.length > 0 ? override : join4(homedir4(), ".deeplake", "state", "skillify");
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// dist/src/skillify/legacy-migration.js
|
|
575
583
|
var dlog = (msg) => log("skillify-migrate", msg);
|
|
576
584
|
var attempted = false;
|
|
577
585
|
function migrateLegacyStateDir() {
|
|
586
|
+
if (globalThis.__hivemind_tuning__.HIVEMIND_STATE_DIR?.trim())
|
|
587
|
+
return;
|
|
578
588
|
if (attempted)
|
|
579
589
|
return;
|
|
580
590
|
attempted = true;
|
|
581
|
-
const
|
|
582
|
-
const legacy =
|
|
583
|
-
const current = join4(root, "skillify");
|
|
591
|
+
const current = getStateDir();
|
|
592
|
+
const legacy = join5(dirname(current), "skilify");
|
|
584
593
|
if (!existsSync3(legacy))
|
|
585
594
|
return;
|
|
586
595
|
if (existsSync3(current))
|
|
@@ -590,8 +599,8 @@ function migrateLegacyStateDir() {
|
|
|
590
599
|
dlog(`migrated ${legacy} -> ${current}`);
|
|
591
600
|
} catch (err) {
|
|
592
601
|
const code = err.code;
|
|
593
|
-
if (code === "EXDEV" || code === "EPERM") {
|
|
594
|
-
dlog(`migration
|
|
602
|
+
if (code === "EXDEV" || code === "EPERM" || code === "ENOENT" || code === "EEXIST" || code === "ENOTEMPTY") {
|
|
603
|
+
dlog(`migration skipped (${code}); legacy dir left as-is or another process handled it`);
|
|
595
604
|
return;
|
|
596
605
|
}
|
|
597
606
|
throw err;
|
|
@@ -600,17 +609,16 @@ function migrateLegacyStateDir() {
|
|
|
600
609
|
|
|
601
610
|
// dist/src/skillify/state.js
|
|
602
611
|
var dlog2 = (msg) => log("skillify-state", msg);
|
|
603
|
-
var STATE_DIR = join5(homedir5(), ".deeplake", "state", "skillify");
|
|
604
612
|
var YIELD_BUF = new Int32Array(new SharedArrayBuffer(4));
|
|
605
613
|
var TRIGGER_THRESHOLD = (() => {
|
|
606
614
|
const n = Number(globalThis.__hivemind_tuning__.HIVEMIND_SKILLIFY_EVERY_N_TURNS ?? "");
|
|
607
615
|
return Number.isInteger(n) && n > 0 ? n : 20;
|
|
608
616
|
})();
|
|
609
617
|
function statePath(projectKey) {
|
|
610
|
-
return
|
|
618
|
+
return join6(getStateDir(), `${projectKey}.json`);
|
|
611
619
|
}
|
|
612
620
|
function lockPath(projectKey) {
|
|
613
|
-
return
|
|
621
|
+
return join6(getStateDir(), `${projectKey}.lock`);
|
|
614
622
|
}
|
|
615
623
|
function readState(projectKey) {
|
|
616
624
|
migrateLegacyStateDir();
|
|
@@ -625,7 +633,7 @@ function readState(projectKey) {
|
|
|
625
633
|
}
|
|
626
634
|
function writeState(projectKey, state) {
|
|
627
635
|
migrateLegacyStateDir();
|
|
628
|
-
mkdirSync2(
|
|
636
|
+
mkdirSync2(getStateDir(), { recursive: true });
|
|
629
637
|
const p = statePath(projectKey);
|
|
630
638
|
const tmp = `${p}.${process.pid}.${Date.now()}.tmp`;
|
|
631
639
|
writeFileSync2(tmp, JSON.stringify(state, null, 2));
|
|
@@ -633,7 +641,7 @@ function writeState(projectKey, state) {
|
|
|
633
641
|
}
|
|
634
642
|
function withRmwLock(projectKey, fn) {
|
|
635
643
|
migrateLegacyStateDir();
|
|
636
|
-
mkdirSync2(
|
|
644
|
+
mkdirSync2(getStateDir(), { recursive: true });
|
|
637
645
|
const rmw = lockPath(projectKey) + ".rmw";
|
|
638
646
|
const deadline = Date.now() + 2e3;
|
|
639
647
|
let fd = null;
|
|
@@ -706,8 +714,8 @@ function releaseWorkerLock(projectKey) {
|
|
|
706
714
|
var cfg = JSON.parse(readFileSync3(process.argv[2], "utf-8"));
|
|
707
715
|
globalThis.__hivemind_tuning__ = cfg.tuning ?? {};
|
|
708
716
|
var tmpDir = cfg.tmpDir;
|
|
709
|
-
var verdictPath =
|
|
710
|
-
var promptPath =
|
|
717
|
+
var verdictPath = join7(tmpDir, "verdict.json");
|
|
718
|
+
var promptPath = join7(tmpDir, "prompt.txt");
|
|
711
719
|
var SESSIONS_TO_MINE = 10;
|
|
712
720
|
var PAIR_CHAR_CAP = 2e3;
|
|
713
721
|
var TOTAL_PAIRS_CHAR_CAP = 4e4;
|
|
@@ -954,9 +962,9 @@ async function main() {
|
|
|
954
962
|
timeoutMs: 12e4
|
|
955
963
|
});
|
|
956
964
|
try {
|
|
957
|
-
writeFileSync3(
|
|
965
|
+
writeFileSync3(join7(tmpDir, "gate-stdout.txt"), gate.stdout);
|
|
958
966
|
if (gate.stderr)
|
|
959
|
-
writeFileSync3(
|
|
967
|
+
writeFileSync3(join7(tmpDir, "gate-stderr.txt"), gate.stderr);
|
|
960
968
|
} catch {
|
|
961
969
|
}
|
|
962
970
|
if (gate.errored) {
|
package/openclaw/package.json
CHANGED