@deeplake/hivemind 0.7.78 → 0.7.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/bundle/cli.js +9 -0
- package/codex/bundle/capture.js +176 -43
- package/codex/bundle/pre-tool-use.js +316 -93
- package/codex/bundle/skillopt-worker.js +2057 -0
- package/hermes/bundle/capture.js +168 -45
- package/hermes/bundle/pre-tool-use.js +272 -52
- package/hermes/bundle/skillopt-worker.js +2057 -0
- package/openclaw/dist/index.js +1 -1
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/package.json +1 -1
- package/pi/extension-source/hivemind.ts +93 -0
package/hermes/bundle/capture.js
CHANGED
|
@@ -366,38 +366,38 @@ function readQueue() {
|
|
|
366
366
|
return { queue: [] };
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
|
-
function _isQueuePathInsideHome(
|
|
370
|
-
const r = resolve(
|
|
369
|
+
function _isQueuePathInsideHome(path2, home) {
|
|
370
|
+
const r = resolve(path2);
|
|
371
371
|
const h = resolve(home);
|
|
372
372
|
return r.startsWith(h + "/") || r === h;
|
|
373
373
|
}
|
|
374
374
|
function writeQueue(q) {
|
|
375
|
-
const
|
|
375
|
+
const path2 = queuePath();
|
|
376
376
|
const home = resolve(homedir3());
|
|
377
|
-
if (!_isQueuePathInsideHome(
|
|
378
|
-
throw new Error(`notifications-queue write blocked: ${
|
|
377
|
+
if (!_isQueuePathInsideHome(path2, home)) {
|
|
378
|
+
throw new Error(`notifications-queue write blocked: ${path2} is outside ${home}`);
|
|
379
379
|
}
|
|
380
380
|
mkdirSync(join3(home, ".deeplake"), { recursive: true, mode: 448 });
|
|
381
|
-
const tmp = `${
|
|
381
|
+
const tmp = `${path2}.${process.pid}.tmp`;
|
|
382
382
|
writeFileSync(tmp, JSON.stringify(q, null, 2), { mode: 384 });
|
|
383
|
-
renameSync(tmp,
|
|
383
|
+
renameSync(tmp, path2);
|
|
384
384
|
}
|
|
385
385
|
async function withQueueLock(fn) {
|
|
386
|
-
const
|
|
386
|
+
const path2 = lockPath();
|
|
387
387
|
mkdirSync(join3(homedir3(), ".deeplake"), { recursive: true, mode: 448 });
|
|
388
388
|
let fd = null;
|
|
389
389
|
for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
|
|
390
390
|
try {
|
|
391
|
-
fd = openSync(
|
|
391
|
+
fd = openSync(path2, "wx", 384);
|
|
392
392
|
break;
|
|
393
393
|
} catch (e) {
|
|
394
394
|
const code = e.code;
|
|
395
395
|
if (code !== "EEXIST")
|
|
396
396
|
throw e;
|
|
397
397
|
try {
|
|
398
|
-
const age = Date.now() - statSync(
|
|
398
|
+
const age = Date.now() - statSync(path2).mtimeMs;
|
|
399
399
|
if (age > LOCK_STALE_MS) {
|
|
400
|
-
unlinkSync(
|
|
400
|
+
unlinkSync(path2);
|
|
401
401
|
continue;
|
|
402
402
|
}
|
|
403
403
|
} catch {
|
|
@@ -418,7 +418,7 @@ async function withQueueLock(fn) {
|
|
|
418
418
|
} catch {
|
|
419
419
|
}
|
|
420
420
|
try {
|
|
421
|
-
unlinkSync(
|
|
421
|
+
unlinkSync(path2);
|
|
422
422
|
} catch {
|
|
423
423
|
}
|
|
424
424
|
}
|
|
@@ -694,9 +694,9 @@ var DeeplakeApi = class {
|
|
|
694
694
|
}
|
|
695
695
|
}
|
|
696
696
|
/** Update specific columns on a row by path. */
|
|
697
|
-
async updateColumns(
|
|
697
|
+
async updateColumns(path2, columns) {
|
|
698
698
|
const setClauses = Object.entries(columns).map(([col, val]) => typeof val === "number" ? `${col} = ${val}` : `${col} = '${sqlStr(String(val))}'`).join(", ");
|
|
699
|
-
await this.query(`UPDATE "${this.tableName}" SET ${setClauses} WHERE path = '${sqlStr(
|
|
699
|
+
await this.query(`UPDATE "${this.tableName}" SET ${setClauses} WHERE path = '${sqlStr(path2)}'`);
|
|
700
700
|
}
|
|
701
701
|
// ── Convenience ─────────────────────────────────────────────────────────────
|
|
702
702
|
/** Create a BM25 search index on a column. */
|
|
@@ -1402,13 +1402,13 @@ var _migrated = false;
|
|
|
1402
1402
|
function readUserConfig() {
|
|
1403
1403
|
if (_cache !== null)
|
|
1404
1404
|
return _cache;
|
|
1405
|
-
const
|
|
1406
|
-
if (!existsSync4(
|
|
1405
|
+
const path2 = _configPath();
|
|
1406
|
+
if (!existsSync4(path2)) {
|
|
1407
1407
|
_cache = {};
|
|
1408
1408
|
return _cache;
|
|
1409
1409
|
}
|
|
1410
1410
|
try {
|
|
1411
|
-
const raw = readFileSync6(
|
|
1411
|
+
const raw = readFileSync6(path2, "utf-8");
|
|
1412
1412
|
const parsed = JSON.parse(raw);
|
|
1413
1413
|
_cache = isPlainObject(parsed) ? parsed : {};
|
|
1414
1414
|
} catch {
|
|
@@ -1419,13 +1419,13 @@ function readUserConfig() {
|
|
|
1419
1419
|
function writeUserConfig(patch) {
|
|
1420
1420
|
const current = readUserConfig();
|
|
1421
1421
|
const merged = deepMerge(current, patch);
|
|
1422
|
-
const
|
|
1423
|
-
const dir = dirname(
|
|
1422
|
+
const path2 = _configPath();
|
|
1423
|
+
const dir = dirname(path2);
|
|
1424
1424
|
if (!existsSync4(dir))
|
|
1425
1425
|
mkdirSync4(dir, { recursive: true });
|
|
1426
|
-
const tmp = `${
|
|
1426
|
+
const tmp = `${path2}.tmp.${process.pid}`;
|
|
1427
1427
|
writeFileSync4(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
1428
|
-
renameSync2(tmp,
|
|
1428
|
+
renameSync2(tmp, path2);
|
|
1429
1429
|
_cache = merged;
|
|
1430
1430
|
return merged;
|
|
1431
1431
|
}
|
|
@@ -1570,8 +1570,8 @@ function createSymlinkAtomic(target, link) {
|
|
|
1570
1570
|
}
|
|
1571
1571
|
|
|
1572
1572
|
// dist/src/hooks/hermes/capture.js
|
|
1573
|
-
import { fileURLToPath as
|
|
1574
|
-
import { dirname as
|
|
1573
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
1574
|
+
import { dirname as dirname8, join as join21 } from "node:path";
|
|
1575
1575
|
|
|
1576
1576
|
// dist/src/hooks/summary-state.js
|
|
1577
1577
|
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, writeSync as writeSync2, mkdirSync as mkdirSync6, renameSync as renameSync4, existsSync as existsSync6, unlinkSync as unlinkSync4, openSync as openSync3, closeSync as closeSync3, statSync as statSync3 } from "node:fs";
|
|
@@ -1718,13 +1718,13 @@ import { homedir as homedir10, tmpdir as tmpdir2 } from "node:os";
|
|
|
1718
1718
|
import { mkdirSync as mkdirSync7, appendFileSync as appendFileSync2 } from "node:fs";
|
|
1719
1719
|
import { join as join11 } from "node:path";
|
|
1720
1720
|
function makeWikiLogger(hooksDir, filename = "deeplake-wiki.log") {
|
|
1721
|
-
const
|
|
1721
|
+
const path2 = join11(hooksDir, filename);
|
|
1722
1722
|
return {
|
|
1723
|
-
path,
|
|
1723
|
+
path: path2,
|
|
1724
1724
|
log(msg) {
|
|
1725
1725
|
try {
|
|
1726
1726
|
mkdirSync7(hooksDir, { recursive: true });
|
|
1727
|
-
appendFileSync2(
|
|
1727
|
+
appendFileSync2(path2, `[${utcTimestamp()}] ${msg}
|
|
1728
1728
|
`);
|
|
1729
1729
|
} catch {
|
|
1730
1730
|
}
|
|
@@ -1777,10 +1777,10 @@ function getInstalledVersion(bundleDir, pluginManifestDir) {
|
|
|
1777
1777
|
// dist/src/utils/spawn-detached.js
|
|
1778
1778
|
import { spawn as nodeSpawn } from "node:child_process";
|
|
1779
1779
|
function spawnDetachedNodeWorker(workerPath, args = [], deps = {}) {
|
|
1780
|
-
const
|
|
1780
|
+
const spawn3 = deps.spawn ?? nodeSpawn;
|
|
1781
1781
|
const execPath = deps.execPath ?? process.execPath;
|
|
1782
1782
|
try {
|
|
1783
|
-
const child =
|
|
1783
|
+
const child = spawn3(execPath, [workerPath, ...args], {
|
|
1784
1784
|
detached: true,
|
|
1785
1785
|
stdio: ["ignore", "ignore", "ignore"],
|
|
1786
1786
|
// Suppress the transient console window Windows would otherwise pop for
|
|
@@ -2317,12 +2317,132 @@ function tryStopCounterTrigger(opts) {
|
|
|
2317
2317
|
}
|
|
2318
2318
|
}
|
|
2319
2319
|
|
|
2320
|
+
// dist/src/skillify/skillopt-trigger.js
|
|
2321
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
2322
|
+
import fs from "node:fs";
|
|
2323
|
+
import path from "node:path";
|
|
2324
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
2325
|
+
|
|
2326
|
+
// dist/src/skillify/manifest.js
|
|
2327
|
+
import { existsSync as existsSync11, lstatSync as lstatSync3, mkdirSync as mkdirSync12, readFileSync as readFileSync11, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync10 } from "node:fs";
|
|
2328
|
+
import { dirname as dirname7, join as join20 } from "node:path";
|
|
2329
|
+
|
|
2330
|
+
// dist/src/skillify/skillopt-env.js
|
|
2331
|
+
var SKILLOPT_ENV = {
|
|
2332
|
+
/** User-set kill switch: "1" disables the whole trigger. */
|
|
2333
|
+
DISABLED: "HIVEMIND_SKILLOPT_DISABLED",
|
|
2334
|
+
/** Recursion guard the trigger sets on the spawned worker so the worker can't re-arm. */
|
|
2335
|
+
WORKER: "HIVEMIND_SKILLOPT_WORKER",
|
|
2336
|
+
/** Worker inputs, handed trigger → worker via the child env. */
|
|
2337
|
+
SESSION: "HIVEMIND_SKILLOPT_SESSION",
|
|
2338
|
+
SKILL: "HIVEMIND_SKILLOPT_SKILL",
|
|
2339
|
+
REACTION: "HIVEMIND_SKILLOPT_REACTION",
|
|
2340
|
+
TOOL_USE_ID: "HIVEMIND_SKILLOPT_TOOL_USE_ID",
|
|
2341
|
+
/** Which agent's CLI runs the judge/proposer (claude_code/codex/hermes/cursor/pi). */
|
|
2342
|
+
AGENT: "HIVEMIND_SKILLOPT_AGENT",
|
|
2343
|
+
/** K-message judgment-window size override. */
|
|
2344
|
+
JUDGE_WINDOW: "HIVEMIND_SKILLOPT_JUDGE_WINDOW"
|
|
2345
|
+
};
|
|
2346
|
+
|
|
2347
|
+
// dist/src/skillify/skillopt-trigger.js
|
|
2348
|
+
var log5 = (m) => log("skillopt-trigger", m);
|
|
2349
|
+
function defaultHasCreds() {
|
|
2350
|
+
try {
|
|
2351
|
+
return Boolean(loadConfig()?.token);
|
|
2352
|
+
} catch {
|
|
2353
|
+
return false;
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
var MAX_REACTION = 8e3;
|
|
2357
|
+
function pendingFile(sessionId) {
|
|
2358
|
+
const safe = sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 200);
|
|
2359
|
+
return path.join(getStateDir(), "skillopt", "pending", `${safe}.json`);
|
|
2360
|
+
}
|
|
2361
|
+
var fileStore = {
|
|
2362
|
+
load(sessionId) {
|
|
2363
|
+
try {
|
|
2364
|
+
return JSON.parse(fs.readFileSync(pendingFile(sessionId), "utf8"));
|
|
2365
|
+
} catch {
|
|
2366
|
+
return null;
|
|
2367
|
+
}
|
|
2368
|
+
},
|
|
2369
|
+
save(sessionId, p) {
|
|
2370
|
+
try {
|
|
2371
|
+
const f = pendingFile(sessionId);
|
|
2372
|
+
if (p === null) {
|
|
2373
|
+
try {
|
|
2374
|
+
fs.unlinkSync(f);
|
|
2375
|
+
} catch {
|
|
2376
|
+
}
|
|
2377
|
+
return;
|
|
2378
|
+
}
|
|
2379
|
+
fs.mkdirSync(path.dirname(f), { recursive: true });
|
|
2380
|
+
const tmp = `${f}.${process.pid}.tmp`;
|
|
2381
|
+
fs.writeFileSync(tmp, JSON.stringify(p));
|
|
2382
|
+
fs.renameSync(tmp, f);
|
|
2383
|
+
} catch {
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
};
|
|
2387
|
+
function runEventTrigger(sessionId, reaction, opts = {}) {
|
|
2388
|
+
const deps = opts.deps ?? {};
|
|
2389
|
+
const env = deps.env ?? process.env;
|
|
2390
|
+
if (env[SKILLOPT_ENV.DISABLED] === "1")
|
|
2391
|
+
return { fired: false, reason: "disabled" };
|
|
2392
|
+
if (env[SKILLOPT_ENV.WORKER] === "1")
|
|
2393
|
+
return { fired: false, reason: "in-worker" };
|
|
2394
|
+
if (!sessionId)
|
|
2395
|
+
return { fired: false, reason: "no-skill" };
|
|
2396
|
+
const store = deps.store ?? fileStore;
|
|
2397
|
+
const p = store.load(sessionId);
|
|
2398
|
+
if (!p)
|
|
2399
|
+
return { fired: false, reason: "no-skill" };
|
|
2400
|
+
if (!(deps.canFire ?? defaultHasCreds)())
|
|
2401
|
+
return { fired: false, reason: "no-creds" };
|
|
2402
|
+
store.save(sessionId, p.budget - 1 <= 0 ? null : { ...p, budget: p.budget - 1 });
|
|
2403
|
+
(deps.spawnWorker ?? spawnWorker)(sessionId, p.skill, reaction ?? "", p.toolUseId, opts.agent);
|
|
2404
|
+
return { fired: true, reason: "spawned" };
|
|
2405
|
+
}
|
|
2406
|
+
function spawnWorker(sessionId, skill, reaction, toolUseId, agent) {
|
|
2407
|
+
try {
|
|
2408
|
+
const here = path.dirname(fileURLToPath3(import.meta.url));
|
|
2409
|
+
const entry = path.join(here, "skillopt-worker.js");
|
|
2410
|
+
const child = spawn2(process.execPath, [entry], {
|
|
2411
|
+
detached: true,
|
|
2412
|
+
stdio: "ignore",
|
|
2413
|
+
env: {
|
|
2414
|
+
...process.env,
|
|
2415
|
+
[SKILLOPT_ENV.WORKER]: "1",
|
|
2416
|
+
[SKILLOPT_ENV.SESSION]: sessionId,
|
|
2417
|
+
[SKILLOPT_ENV.SKILL]: skill,
|
|
2418
|
+
[SKILLOPT_ENV.REACTION]: (reaction ?? "").slice(0, MAX_REACTION),
|
|
2419
|
+
...toolUseId ? { [SKILLOPT_ENV.TOOL_USE_ID]: toolUseId } : {},
|
|
2420
|
+
...agent ? { [SKILLOPT_ENV.AGENT]: agent } : {}
|
|
2421
|
+
}
|
|
2422
|
+
});
|
|
2423
|
+
child.unref();
|
|
2424
|
+
log5(`spawned skillopt worker for ${skill} in ${sessionId}${agent ? ` (agent=${agent})` : ""}`);
|
|
2425
|
+
} catch (e) {
|
|
2426
|
+
log5(`spawn failed (swallowed): ${e?.message ?? e}`);
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
|
|
2430
|
+
// dist/src/hooks/shared/skillopt-hook.js
|
|
2431
|
+
function reactSkillOpt(sessionId, prompt, agent) {
|
|
2432
|
+
try {
|
|
2433
|
+
if (prompt === void 0 || prompt.trim() === "" || process.env.HIVEMIND_WIKI_WORKER === "1")
|
|
2434
|
+
return;
|
|
2435
|
+
runEventTrigger(sessionId, prompt, { agent });
|
|
2436
|
+
} catch {
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
|
|
2320
2440
|
// dist/src/hooks/hermes/capture.js
|
|
2321
|
-
var
|
|
2441
|
+
var log6 = (msg) => log("hermes-capture", msg);
|
|
2322
2442
|
function resolveEmbedDaemonPath() {
|
|
2323
|
-
return
|
|
2443
|
+
return join21(dirname8(fileURLToPath4(import.meta.url)), "embeddings", "embed-daemon.js");
|
|
2324
2444
|
}
|
|
2325
|
-
var __bundleDir =
|
|
2445
|
+
var __bundleDir = dirname8(fileURLToPath4(import.meta.url));
|
|
2326
2446
|
var PLUGIN_VERSION = getInstalledVersion(__bundleDir, ".claude-plugin") ?? "";
|
|
2327
2447
|
if (!embeddingsDisabled()) {
|
|
2328
2448
|
try {
|
|
@@ -2344,7 +2464,7 @@ async function main() {
|
|
|
2344
2464
|
const input = await readStdin();
|
|
2345
2465
|
const config = loadConfig();
|
|
2346
2466
|
if (!config) {
|
|
2347
|
-
|
|
2467
|
+
log6("no config");
|
|
2348
2468
|
return;
|
|
2349
2469
|
}
|
|
2350
2470
|
const sessionId = input.session_id ?? `hermes-${Date.now()}`;
|
|
@@ -2361,17 +2481,19 @@ async function main() {
|
|
|
2361
2481
|
timestamp: ts
|
|
2362
2482
|
};
|
|
2363
2483
|
let entry = null;
|
|
2484
|
+
let reactPrompt;
|
|
2364
2485
|
if (event === "pre_llm_call") {
|
|
2365
2486
|
const prompt = pickString(extra.prompt, extra.user_message, extra.message?.content);
|
|
2366
2487
|
if (!prompt) {
|
|
2367
|
-
|
|
2488
|
+
log6(`pre_llm_call: no prompt found in extra`);
|
|
2368
2489
|
return;
|
|
2369
2490
|
}
|
|
2370
|
-
|
|
2491
|
+
log6(`user session=${sessionId}`);
|
|
2371
2492
|
entry = { id: crypto.randomUUID(), ...meta, type: "user_message", content: prompt };
|
|
2493
|
+
reactPrompt = prompt;
|
|
2372
2494
|
} else if (event === "post_tool_call" && typeof input.tool_name === "string") {
|
|
2373
2495
|
const toolResponse = extra.tool_result ?? extra.tool_output ?? extra.result ?? extra.output;
|
|
2374
|
-
|
|
2496
|
+
log6(`tool=${input.tool_name} session=${sessionId}`);
|
|
2375
2497
|
entry = {
|
|
2376
2498
|
id: crypto.randomUUID(),
|
|
2377
2499
|
...meta,
|
|
@@ -2383,18 +2505,18 @@ async function main() {
|
|
|
2383
2505
|
} else if (event === "post_llm_call") {
|
|
2384
2506
|
const text = pickString(extra.response, extra.assistant_message, extra.message?.content);
|
|
2385
2507
|
if (!text) {
|
|
2386
|
-
|
|
2508
|
+
log6(`post_llm_call: no response found in extra`);
|
|
2387
2509
|
return;
|
|
2388
2510
|
}
|
|
2389
|
-
|
|
2511
|
+
log6(`assistant session=${sessionId}`);
|
|
2390
2512
|
entry = { id: crypto.randomUUID(), ...meta, type: "assistant_message", content: text };
|
|
2391
2513
|
} else {
|
|
2392
|
-
|
|
2514
|
+
log6(`unknown/unhandled event: ${event}, skipping`);
|
|
2393
2515
|
return;
|
|
2394
2516
|
}
|
|
2395
2517
|
const sessionPath = buildSessionPath(config, sessionId);
|
|
2396
2518
|
const line = JSON.stringify(entry);
|
|
2397
|
-
|
|
2519
|
+
log6(`writing to ${sessionPath}`);
|
|
2398
2520
|
const projectName = projectNameFromCwd(cwd);
|
|
2399
2521
|
const filename = sessionPath.split("/").pop() ?? "";
|
|
2400
2522
|
const jsonForSql = line.replace(/'/g, "''");
|
|
@@ -2405,14 +2527,15 @@ async function main() {
|
|
|
2405
2527
|
await api.query(insertSql);
|
|
2406
2528
|
} catch (e) {
|
|
2407
2529
|
if (e.message?.includes("permission denied") || e.message?.includes("does not exist")) {
|
|
2408
|
-
|
|
2530
|
+
log6("table missing, creating and retrying");
|
|
2409
2531
|
await api.ensureSessionsTable(sessionsTable);
|
|
2410
2532
|
await api.query(insertSql);
|
|
2411
2533
|
} else {
|
|
2412
2534
|
throw e;
|
|
2413
2535
|
}
|
|
2414
2536
|
}
|
|
2415
|
-
|
|
2537
|
+
log6("capture ok \u2192 cloud");
|
|
2538
|
+
reactSkillOpt(sessionId, reactPrompt, "hermes");
|
|
2416
2539
|
maybeTriggerPeriodicSummary(sessionId, cwd, config);
|
|
2417
2540
|
if (event === "post_llm_call" && process.env.HIVEMIND_WIKI_WORKER !== "1" && process.env.HIVEMIND_SKILLIFY_WORKER !== "1") {
|
|
2418
2541
|
tryStopCounterTrigger({
|
|
@@ -2433,7 +2556,7 @@ function maybeTriggerPeriodicSummary(sessionId, cwd, config) {
|
|
|
2433
2556
|
if (!shouldTrigger(state, cfg))
|
|
2434
2557
|
return;
|
|
2435
2558
|
if (!tryAcquireLock(sessionId)) {
|
|
2436
|
-
|
|
2559
|
+
log6(`periodic trigger suppressed (lock held) session=${sessionId}`);
|
|
2437
2560
|
return;
|
|
2438
2561
|
}
|
|
2439
2562
|
wikiLog(`Periodic: threshold hit (total=${state.totalCount}, since=${state.totalCount - state.lastSummaryCount}, N=${cfg.everyNMessages}, hours=${cfg.everyHours})`);
|
|
@@ -2446,17 +2569,17 @@ function maybeTriggerPeriodicSummary(sessionId, cwd, config) {
|
|
|
2446
2569
|
reason: "Periodic"
|
|
2447
2570
|
});
|
|
2448
2571
|
} catch (e) {
|
|
2449
|
-
|
|
2572
|
+
log6(`periodic spawn failed: ${e.message}`);
|
|
2450
2573
|
try {
|
|
2451
2574
|
releaseLock(sessionId);
|
|
2452
2575
|
} catch {
|
|
2453
2576
|
}
|
|
2454
2577
|
}
|
|
2455
2578
|
} catch (e) {
|
|
2456
|
-
|
|
2579
|
+
log6(`periodic trigger error: ${e.message}`);
|
|
2457
2580
|
}
|
|
2458
2581
|
}
|
|
2459
2582
|
main().catch((e) => {
|
|
2460
|
-
|
|
2583
|
+
log6(`fatal: ${e.message}`);
|
|
2461
2584
|
process.exit(0);
|
|
2462
2585
|
});
|