@askexenow/exe-os 0.8.32 → 0.8.36
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/dist/bin/backfill-conversations.js +332 -348
- package/dist/bin/backfill-responses.js +72 -12
- package/dist/bin/backfill-vectors.js +72 -12
- package/dist/bin/cleanup-stale-review-tasks.js +63 -3
- package/dist/bin/cli.js +1518 -1122
- package/dist/bin/exe-agent.js +4 -4
- package/dist/bin/exe-assign.js +80 -18
- package/dist/bin/exe-boot.js +408 -89
- package/dist/bin/exe-call.js +83 -24
- package/dist/bin/exe-dispatch.js +18 -10
- package/dist/bin/exe-doctor.js +63 -3
- package/dist/bin/exe-export-behaviors.js +64 -3
- package/dist/bin/exe-forget.js +69 -4
- package/dist/bin/exe-gateway.js +121 -36
- package/dist/bin/exe-heartbeat.js +77 -13
- package/dist/bin/exe-kill.js +64 -3
- package/dist/bin/exe-launch-agent.js +162 -35
- package/dist/bin/exe-link.js +946 -0
- package/dist/bin/exe-new-employee.js +121 -36
- package/dist/bin/exe-pending-messages.js +72 -7
- package/dist/bin/exe-pending-notifications.js +63 -3
- package/dist/bin/exe-pending-reviews.js +75 -10
- package/dist/bin/exe-rename.js +1287 -0
- package/dist/bin/exe-review.js +64 -4
- package/dist/bin/exe-search.js +79 -13
- package/dist/bin/exe-session-cleanup.js +91 -26
- package/dist/bin/exe-status.js +64 -4
- package/dist/bin/exe-team.js +64 -4
- package/dist/bin/git-sweep.js +71 -4
- package/dist/bin/graph-backfill.js +64 -3
- package/dist/bin/graph-export.js +64 -3
- package/dist/bin/install.js +3 -3
- package/dist/bin/scan-tasks.js +71 -4
- package/dist/bin/setup.js +156 -38
- package/dist/bin/shard-migrate.js +64 -3
- package/dist/bin/wiki-sync.js +64 -3
- package/dist/gateway/index.js +122 -37
- package/dist/hooks/bug-report-worker.js +209 -23
- package/dist/hooks/commit-complete.js +71 -4
- package/dist/hooks/error-recall.js +79 -13
- package/dist/hooks/ingest-worker.js +129 -43
- package/dist/hooks/instructions-loaded.js +71 -4
- package/dist/hooks/notification.js +71 -4
- package/dist/hooks/post-compact.js +71 -4
- package/dist/hooks/pre-compact.js +71 -4
- package/dist/hooks/pre-tool-use.js +413 -194
- package/dist/hooks/prompt-ingest-worker.js +82 -22
- package/dist/hooks/prompt-submit.js +103 -37
- package/dist/hooks/response-ingest-worker.js +87 -22
- package/dist/hooks/session-end.js +71 -4
- package/dist/hooks/session-start.js +79 -13
- package/dist/hooks/stop.js +71 -4
- package/dist/hooks/subagent-stop.js +71 -4
- package/dist/hooks/summary-worker.js +303 -50
- package/dist/index.js +134 -46
- package/dist/lib/cloud-sync.js +209 -15
- package/dist/lib/consolidation.js +4 -4
- package/dist/lib/database.js +64 -2
- package/dist/lib/device-registry.js +70 -3
- package/dist/lib/employee-templates.js +48 -22
- package/dist/lib/employees.js +34 -1
- package/dist/lib/exe-daemon.js +136 -53
- package/dist/lib/hybrid-search.js +79 -13
- package/dist/lib/identity-templates.js +57 -6
- package/dist/lib/identity.js +3 -3
- package/dist/lib/messaging.js +22 -14
- package/dist/lib/reminders.js +3 -3
- package/dist/lib/schedules.js +63 -3
- package/dist/lib/skill-learning.js +3 -3
- package/dist/lib/status-brief.js +63 -5
- package/dist/lib/store.js +64 -3
- package/dist/lib/task-router.js +4 -2
- package/dist/lib/tasks.js +48 -21
- package/dist/lib/tmux-routing.js +47 -20
- package/dist/mcp/server.js +727 -58
- package/dist/mcp/tools/complete-reminder.js +3 -3
- package/dist/mcp/tools/create-reminder.js +3 -3
- package/dist/mcp/tools/create-task.js +151 -24
- package/dist/mcp/tools/deactivate-behavior.js +3 -3
- package/dist/mcp/tools/list-reminders.js +3 -3
- package/dist/mcp/tools/list-tasks.js +17 -8
- package/dist/mcp/tools/send-message.js +24 -16
- package/dist/mcp/tools/update-task.js +25 -16
- package/dist/runtime/index.js +112 -24
- package/dist/tui/App.js +139 -36
- package/package.json +6 -2
- package/src/commands/exe/rename.md +12 -0
package/dist/index.js
CHANGED
|
@@ -359,6 +359,61 @@ var init_intercom_queue = __esm({
|
|
|
359
359
|
}
|
|
360
360
|
});
|
|
361
361
|
|
|
362
|
+
// src/lib/db-retry.ts
|
|
363
|
+
function isBusyError(err) {
|
|
364
|
+
if (err instanceof Error) {
|
|
365
|
+
const msg = err.message.toLowerCase();
|
|
366
|
+
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
367
|
+
}
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
function delay(ms) {
|
|
371
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
372
|
+
}
|
|
373
|
+
async function retryOnBusy(fn, label) {
|
|
374
|
+
let lastError;
|
|
375
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
376
|
+
try {
|
|
377
|
+
return await fn();
|
|
378
|
+
} catch (err) {
|
|
379
|
+
lastError = err;
|
|
380
|
+
if (!isBusyError(err) || attempt === MAX_RETRIES) {
|
|
381
|
+
throw err;
|
|
382
|
+
}
|
|
383
|
+
const backoff = BASE_DELAY_MS * Math.pow(2, attempt);
|
|
384
|
+
const jitter = Math.floor(Math.random() * MAX_JITTER_MS);
|
|
385
|
+
process.stderr.write(
|
|
386
|
+
`[exe-os] SQLITE_BUSY ${label} retry ${attempt + 1}/${MAX_RETRIES} \u2014 waiting ${backoff + jitter}ms
|
|
387
|
+
`
|
|
388
|
+
);
|
|
389
|
+
await delay(backoff + jitter);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
throw lastError;
|
|
393
|
+
}
|
|
394
|
+
function wrapWithRetry(client) {
|
|
395
|
+
return new Proxy(client, {
|
|
396
|
+
get(target, prop, receiver) {
|
|
397
|
+
if (prop === "execute") {
|
|
398
|
+
return (sql) => retryOnBusy(() => target.execute(sql), "execute");
|
|
399
|
+
}
|
|
400
|
+
if (prop === "batch") {
|
|
401
|
+
return (stmts) => retryOnBusy(() => target.batch(stmts), "batch");
|
|
402
|
+
}
|
|
403
|
+
return Reflect.get(target, prop, receiver);
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
var MAX_RETRIES, BASE_DELAY_MS, MAX_JITTER_MS;
|
|
408
|
+
var init_db_retry = __esm({
|
|
409
|
+
"src/lib/db-retry.ts"() {
|
|
410
|
+
"use strict";
|
|
411
|
+
MAX_RETRIES = 3;
|
|
412
|
+
BASE_DELAY_MS = 200;
|
|
413
|
+
MAX_JITTER_MS = 300;
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
|
|
362
417
|
// src/lib/database.ts
|
|
363
418
|
var database_exports = {};
|
|
364
419
|
__export(database_exports, {
|
|
@@ -366,6 +421,7 @@ __export(database_exports, {
|
|
|
366
421
|
disposeTurso: () => disposeTurso,
|
|
367
422
|
ensureSchema: () => ensureSchema,
|
|
368
423
|
getClient: () => getClient,
|
|
424
|
+
getRawClient: () => getRawClient,
|
|
369
425
|
initDatabase: () => initDatabase,
|
|
370
426
|
initTurso: () => initTurso,
|
|
371
427
|
isInitialized: () => isInitialized
|
|
@@ -375,6 +431,7 @@ async function initDatabase(config2) {
|
|
|
375
431
|
if (_client) {
|
|
376
432
|
_client.close();
|
|
377
433
|
_client = null;
|
|
434
|
+
_resilientClient = null;
|
|
378
435
|
}
|
|
379
436
|
const opts = {
|
|
380
437
|
url: `file:${config2.dbPath}`
|
|
@@ -383,20 +440,27 @@ async function initDatabase(config2) {
|
|
|
383
440
|
opts.encryptionKey = config2.encryptionKey;
|
|
384
441
|
}
|
|
385
442
|
_client = createClient(opts);
|
|
443
|
+
_resilientClient = wrapWithRetry(_client);
|
|
386
444
|
}
|
|
387
445
|
function isInitialized() {
|
|
388
446
|
return _client !== null;
|
|
389
447
|
}
|
|
390
448
|
function getClient() {
|
|
449
|
+
if (!_resilientClient) {
|
|
450
|
+
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
451
|
+
}
|
|
452
|
+
return _resilientClient;
|
|
453
|
+
}
|
|
454
|
+
function getRawClient() {
|
|
391
455
|
if (!_client) {
|
|
392
456
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
393
457
|
}
|
|
394
458
|
return _client;
|
|
395
459
|
}
|
|
396
460
|
async function ensureSchema() {
|
|
397
|
-
const client =
|
|
461
|
+
const client = getRawClient();
|
|
398
462
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
399
|
-
await client.execute("PRAGMA busy_timeout =
|
|
463
|
+
await client.execute("PRAGMA busy_timeout = 30000");
|
|
400
464
|
try {
|
|
401
465
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
402
466
|
} catch {
|
|
@@ -1189,13 +1253,16 @@ async function disposeDatabase() {
|
|
|
1189
1253
|
if (_client) {
|
|
1190
1254
|
_client.close();
|
|
1191
1255
|
_client = null;
|
|
1256
|
+
_resilientClient = null;
|
|
1192
1257
|
}
|
|
1193
1258
|
}
|
|
1194
|
-
var _client, initTurso, disposeTurso;
|
|
1259
|
+
var _client, _resilientClient, initTurso, disposeTurso;
|
|
1195
1260
|
var init_database = __esm({
|
|
1196
1261
|
"src/lib/database.ts"() {
|
|
1197
1262
|
"use strict";
|
|
1263
|
+
init_db_retry();
|
|
1198
1264
|
_client = null;
|
|
1265
|
+
_resilientClient = null;
|
|
1199
1266
|
initTurso = initDatabase;
|
|
1200
1267
|
disposeTurso = disposeDatabase;
|
|
1201
1268
|
}
|
|
@@ -1446,20 +1513,38 @@ var init_config = __esm({
|
|
|
1446
1513
|
|
|
1447
1514
|
// src/lib/employees.ts
|
|
1448
1515
|
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
1449
|
-
import { existsSync as existsSync4, symlinkSync, readlinkSync } from "fs";
|
|
1516
|
+
import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync4 } from "fs";
|
|
1450
1517
|
import { execSync as execSync4 } from "child_process";
|
|
1451
1518
|
import path5 from "path";
|
|
1452
|
-
|
|
1519
|
+
function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
|
|
1520
|
+
if (!existsSync4(employeesPath)) return [];
|
|
1521
|
+
try {
|
|
1522
|
+
return JSON.parse(readFileSync4(employeesPath, "utf-8"));
|
|
1523
|
+
} catch {
|
|
1524
|
+
return [];
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
function getEmployee(employees, name) {
|
|
1528
|
+
return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
|
|
1529
|
+
}
|
|
1530
|
+
function isMultiInstance(agentName, employees) {
|
|
1531
|
+
const roster = employees ?? loadEmployeesSync();
|
|
1532
|
+
const emp = getEmployee(roster, agentName);
|
|
1533
|
+
if (!emp) return false;
|
|
1534
|
+
return MULTI_INSTANCE_ROLES.has(emp.role.toLowerCase());
|
|
1535
|
+
}
|
|
1536
|
+
var EMPLOYEES_PATH, MULTI_INSTANCE_ROLES;
|
|
1453
1537
|
var init_employees = __esm({
|
|
1454
1538
|
"src/lib/employees.ts"() {
|
|
1455
1539
|
"use strict";
|
|
1456
1540
|
init_config();
|
|
1457
1541
|
EMPLOYEES_PATH = path5.join(EXE_AI_DIR, "exe-employees.json");
|
|
1542
|
+
MULTI_INSTANCE_ROLES = /* @__PURE__ */ new Set(["principal engineer", "content production specialist", "staff code reviewer"]);
|
|
1458
1543
|
}
|
|
1459
1544
|
});
|
|
1460
1545
|
|
|
1461
1546
|
// src/lib/license.ts
|
|
1462
|
-
import { readFileSync as
|
|
1547
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
|
|
1463
1548
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
1464
1549
|
import path6 from "path";
|
|
1465
1550
|
import { jwtVerify, importSPKI } from "jose";
|
|
@@ -1482,12 +1567,12 @@ var init_license = __esm({
|
|
|
1482
1567
|
});
|
|
1483
1568
|
|
|
1484
1569
|
// src/lib/plan-limits.ts
|
|
1485
|
-
import { readFileSync as
|
|
1570
|
+
import { readFileSync as readFileSync6, existsSync as existsSync6 } from "fs";
|
|
1486
1571
|
import path7 from "path";
|
|
1487
1572
|
function getLicenseSync() {
|
|
1488
1573
|
try {
|
|
1489
1574
|
if (!existsSync6(CACHE_PATH2)) return freeLicense();
|
|
1490
|
-
const raw = JSON.parse(
|
|
1575
|
+
const raw = JSON.parse(readFileSync6(CACHE_PATH2, "utf8"));
|
|
1491
1576
|
if (!raw.token || typeof raw.token !== "string") return freeLicense();
|
|
1492
1577
|
const parts = raw.token.split(".");
|
|
1493
1578
|
if (parts.length !== 3) return freeLicense();
|
|
@@ -1526,7 +1611,7 @@ function assertEmployeeLimitSync(rosterPath) {
|
|
|
1526
1611
|
let count = 0;
|
|
1527
1612
|
try {
|
|
1528
1613
|
if (existsSync6(filePath)) {
|
|
1529
|
-
const raw =
|
|
1614
|
+
const raw = readFileSync6(filePath, "utf8");
|
|
1530
1615
|
const employees = JSON.parse(raw);
|
|
1531
1616
|
count = Array.isArray(employees) ? employees.length : 0;
|
|
1532
1617
|
}
|
|
@@ -1564,7 +1649,7 @@ import crypto from "crypto";
|
|
|
1564
1649
|
import path8 from "path";
|
|
1565
1650
|
import os5 from "os";
|
|
1566
1651
|
import {
|
|
1567
|
-
readFileSync as
|
|
1652
|
+
readFileSync as readFileSync7,
|
|
1568
1653
|
readdirSync,
|
|
1569
1654
|
unlinkSync,
|
|
1570
1655
|
existsSync as existsSync7,
|
|
@@ -1650,7 +1735,7 @@ import crypto3 from "crypto";
|
|
|
1650
1735
|
import path9 from "path";
|
|
1651
1736
|
import { execSync as execSync5 } from "child_process";
|
|
1652
1737
|
import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
|
|
1653
|
-
import { existsSync as existsSync8, readFileSync as
|
|
1738
|
+
import { existsSync as existsSync8, readFileSync as readFileSync8 } from "fs";
|
|
1654
1739
|
async function writeCheckpoint(input) {
|
|
1655
1740
|
const client = getClient();
|
|
1656
1741
|
const row = await resolveTask(client, input.taskId);
|
|
@@ -2027,7 +2112,7 @@ async function ensureGitignoreExe(baseDir) {
|
|
|
2027
2112
|
const gitignorePath = path9.join(baseDir, ".gitignore");
|
|
2028
2113
|
try {
|
|
2029
2114
|
if (existsSync8(gitignorePath)) {
|
|
2030
|
-
const content =
|
|
2115
|
+
const content = readFileSync8(gitignorePath, "utf-8");
|
|
2031
2116
|
if (/^\/?exe\/?$/m.test(content)) return;
|
|
2032
2117
|
await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
|
|
2033
2118
|
} else {
|
|
@@ -2403,7 +2488,7 @@ async function dispatchTaskToEmployee(input) {
|
|
|
2403
2488
|
} else {
|
|
2404
2489
|
const projectDir = input.projectDir ?? process.cwd();
|
|
2405
2490
|
const result = ensureEmployee(input.assignedTo, exeSession, projectDir, {
|
|
2406
|
-
autoInstance: input.assignedTo
|
|
2491
|
+
autoInstance: isMultiInstance(input.assignedTo)
|
|
2407
2492
|
});
|
|
2408
2493
|
if (result.status === "failed") {
|
|
2409
2494
|
process.stderr.write(
|
|
@@ -2438,6 +2523,7 @@ var init_tasks_notify = __esm({
|
|
|
2438
2523
|
init_session_key();
|
|
2439
2524
|
init_notifications();
|
|
2440
2525
|
init_transport();
|
|
2526
|
+
init_employees();
|
|
2441
2527
|
}
|
|
2442
2528
|
});
|
|
2443
2529
|
|
|
@@ -3273,7 +3359,7 @@ __export(tmux_routing_exports, {
|
|
|
3273
3359
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
3274
3360
|
});
|
|
3275
3361
|
import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
|
|
3276
|
-
import { readFileSync as
|
|
3362
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync10, appendFileSync } from "fs";
|
|
3277
3363
|
import path14 from "path";
|
|
3278
3364
|
import os6 from "os";
|
|
3279
3365
|
import { fileURLToPath } from "url";
|
|
@@ -3340,7 +3426,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
|
3340
3426
|
}
|
|
3341
3427
|
function getParentExe(sessionKey) {
|
|
3342
3428
|
try {
|
|
3343
|
-
const data = JSON.parse(
|
|
3429
|
+
const data = JSON.parse(readFileSync9(path14.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
3344
3430
|
return data.parentExe || null;
|
|
3345
3431
|
} catch {
|
|
3346
3432
|
return null;
|
|
@@ -3348,7 +3434,7 @@ function getParentExe(sessionKey) {
|
|
|
3348
3434
|
}
|
|
3349
3435
|
function getDispatchedBy(sessionKey) {
|
|
3350
3436
|
try {
|
|
3351
|
-
const data = JSON.parse(
|
|
3437
|
+
const data = JSON.parse(readFileSync9(
|
|
3352
3438
|
path14.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
|
|
3353
3439
|
"utf8"
|
|
3354
3440
|
));
|
|
@@ -3411,7 +3497,7 @@ async function verifyPaneAtCapacity(sessionName) {
|
|
|
3411
3497
|
function readDebounceState() {
|
|
3412
3498
|
try {
|
|
3413
3499
|
if (!existsSync10(DEBOUNCE_FILE)) return {};
|
|
3414
|
-
return JSON.parse(
|
|
3500
|
+
return JSON.parse(readFileSync9(DEBOUNCE_FILE, "utf8"));
|
|
3415
3501
|
} catch {
|
|
3416
3502
|
return {};
|
|
3417
3503
|
}
|
|
@@ -3611,7 +3697,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
3611
3697
|
const claudeJsonPath = path14.join(os6.homedir(), ".claude.json");
|
|
3612
3698
|
let claudeJson = {};
|
|
3613
3699
|
try {
|
|
3614
|
-
claudeJson = JSON.parse(
|
|
3700
|
+
claudeJson = JSON.parse(readFileSync9(claudeJsonPath, "utf8"));
|
|
3615
3701
|
} catch {
|
|
3616
3702
|
}
|
|
3617
3703
|
if (!claudeJson.projects) claudeJson.projects = {};
|
|
@@ -3629,7 +3715,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
3629
3715
|
const settingsPath = path14.join(projSettingsDir, "settings.json");
|
|
3630
3716
|
let settings = {};
|
|
3631
3717
|
try {
|
|
3632
|
-
settings = JSON.parse(
|
|
3718
|
+
settings = JSON.parse(readFileSync9(settingsPath, "utf8"));
|
|
3633
3719
|
} catch {
|
|
3634
3720
|
}
|
|
3635
3721
|
const perms = settings.permissions ?? {};
|
|
@@ -3936,7 +4022,7 @@ function listShards() {
|
|
|
3936
4022
|
}
|
|
3937
4023
|
async function ensureShardSchema(client) {
|
|
3938
4024
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
3939
|
-
await client.execute("PRAGMA busy_timeout =
|
|
4025
|
+
await client.execute("PRAGMA busy_timeout = 30000");
|
|
3940
4026
|
try {
|
|
3941
4027
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
3942
4028
|
} catch {
|
|
@@ -4588,8 +4674,8 @@ function findContainingChunk(filePath, snippet) {
|
|
|
4588
4674
|
try {
|
|
4589
4675
|
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
4590
4676
|
if (ext !== "ts" && ext !== "tsx" && ext !== "js" && ext !== "jsx") return "";
|
|
4591
|
-
const { readFileSync:
|
|
4592
|
-
const source =
|
|
4677
|
+
const { readFileSync: readFileSync13 } = __require("fs");
|
|
4678
|
+
const source = readFileSync13(filePath, "utf8");
|
|
4593
4679
|
const lines = source.split("\n");
|
|
4594
4680
|
const lowerSnippet = snippet.toLowerCase().slice(0, 80);
|
|
4595
4681
|
let matchLine = -1;
|
|
@@ -5161,7 +5247,7 @@ var init_crm_bridge = __esm({
|
|
|
5161
5247
|
import net from "net";
|
|
5162
5248
|
import { spawn } from "child_process";
|
|
5163
5249
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
5164
|
-
import { existsSync as existsSync13, unlinkSync as unlinkSync4, readFileSync as
|
|
5250
|
+
import { existsSync as existsSync13, unlinkSync as unlinkSync4, readFileSync as readFileSync10, openSync, closeSync, statSync } from "fs";
|
|
5165
5251
|
import path17 from "path";
|
|
5166
5252
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5167
5253
|
function handleData(chunk) {
|
|
@@ -5186,7 +5272,7 @@ function handleData(chunk) {
|
|
|
5186
5272
|
function cleanupStaleFiles() {
|
|
5187
5273
|
if (existsSync13(PID_PATH)) {
|
|
5188
5274
|
try {
|
|
5189
|
-
const pid = parseInt(
|
|
5275
|
+
const pid = parseInt(readFileSync10(PID_PATH, "utf8").trim(), 10);
|
|
5190
5276
|
if (pid > 0) {
|
|
5191
5277
|
try {
|
|
5192
5278
|
process.kill(pid, 0);
|
|
@@ -5334,11 +5420,11 @@ async function connectEmbedDaemon() {
|
|
|
5334
5420
|
}
|
|
5335
5421
|
}
|
|
5336
5422
|
const start = Date.now();
|
|
5337
|
-
let
|
|
5423
|
+
let delay2 = 100;
|
|
5338
5424
|
while (Date.now() - start < CONNECT_TIMEOUT_MS) {
|
|
5339
|
-
await new Promise((r) => setTimeout(r,
|
|
5425
|
+
await new Promise((r) => setTimeout(r, delay2));
|
|
5340
5426
|
if (await connectToSocket()) return true;
|
|
5341
|
-
|
|
5427
|
+
delay2 = Math.min(delay2 * 2, 3e3);
|
|
5342
5428
|
}
|
|
5343
5429
|
return false;
|
|
5344
5430
|
}
|
|
@@ -5394,7 +5480,7 @@ function killAndRespawnDaemon() {
|
|
|
5394
5480
|
process.stderr.write("[exed-client] Killing daemon for restart...\n");
|
|
5395
5481
|
if (existsSync13(PID_PATH)) {
|
|
5396
5482
|
try {
|
|
5397
|
-
const pid = parseInt(
|
|
5483
|
+
const pid = parseInt(readFileSync10(PID_PATH, "utf8").trim(), 10);
|
|
5398
5484
|
if (pid > 0) {
|
|
5399
5485
|
try {
|
|
5400
5486
|
process.kill(pid, "SIGKILL");
|
|
@@ -5430,11 +5516,11 @@ async function embedViaClient(text, priority = "high") {
|
|
|
5430
5516
|
`);
|
|
5431
5517
|
killAndRespawnDaemon();
|
|
5432
5518
|
const start = Date.now();
|
|
5433
|
-
let
|
|
5519
|
+
let delay2 = 200;
|
|
5434
5520
|
while (Date.now() - start < CONNECT_TIMEOUT_MS) {
|
|
5435
|
-
await new Promise((r) => setTimeout(r,
|
|
5521
|
+
await new Promise((r) => setTimeout(r, delay2));
|
|
5436
5522
|
if (await connectToSocket()) break;
|
|
5437
|
-
|
|
5523
|
+
delay2 = Math.min(delay2 * 2, 3e3);
|
|
5438
5524
|
}
|
|
5439
5525
|
if (!_connected) return null;
|
|
5440
5526
|
}
|
|
@@ -5446,11 +5532,11 @@ async function embedViaClient(text, priority = "high") {
|
|
|
5446
5532
|
`);
|
|
5447
5533
|
killAndRespawnDaemon();
|
|
5448
5534
|
const start = Date.now();
|
|
5449
|
-
let
|
|
5535
|
+
let delay2 = 200;
|
|
5450
5536
|
while (Date.now() - start < CONNECT_TIMEOUT_MS) {
|
|
5451
|
-
await new Promise((r) => setTimeout(r,
|
|
5537
|
+
await new Promise((r) => setTimeout(r, delay2));
|
|
5452
5538
|
if (await connectToSocket()) break;
|
|
5453
|
-
|
|
5539
|
+
delay2 = Math.min(delay2 * 2, 3e3);
|
|
5454
5540
|
}
|
|
5455
5541
|
if (!_connected) return null;
|
|
5456
5542
|
const retry = await sendRequest([text], priority);
|
|
@@ -5694,13 +5780,13 @@ __export(whatsapp_accounts_exports, {
|
|
|
5694
5780
|
getDefaultAccount: () => getDefaultAccount,
|
|
5695
5781
|
loadAccounts: () => loadAccounts
|
|
5696
5782
|
});
|
|
5697
|
-
import { readFileSync as
|
|
5783
|
+
import { readFileSync as readFileSync11 } from "fs";
|
|
5698
5784
|
import { join as join2 } from "path";
|
|
5699
5785
|
import { homedir as homedir2 } from "os";
|
|
5700
5786
|
function loadAccounts() {
|
|
5701
5787
|
if (cachedAccounts !== null) return cachedAccounts;
|
|
5702
5788
|
try {
|
|
5703
|
-
const raw =
|
|
5789
|
+
const raw = readFileSync11(CONFIG_PATH2, "utf8");
|
|
5704
5790
|
const parsed = JSON.parse(raw);
|
|
5705
5791
|
if (!Array.isArray(parsed)) {
|
|
5706
5792
|
console.warn("[whatsapp] Config is not an array, ignoring");
|
|
@@ -5876,7 +5962,7 @@ async function deliverLocalMessage(messageId) {
|
|
|
5876
5962
|
return true;
|
|
5877
5963
|
} catch {
|
|
5878
5964
|
const newRetryCount = msg.retryCount + 1;
|
|
5879
|
-
if (newRetryCount >=
|
|
5965
|
+
if (newRetryCount >= MAX_RETRIES2) {
|
|
5880
5966
|
await markFailed(messageId, "session unavailable after 10 retries");
|
|
5881
5967
|
} else {
|
|
5882
5968
|
await client.execute({
|
|
@@ -5965,7 +6051,7 @@ async function retryPendingMessages() {
|
|
|
5965
6051
|
sql: `SELECT * FROM messages
|
|
5966
6052
|
WHERE status = 'pending' AND retry_count < ?
|
|
5967
6053
|
ORDER BY id`,
|
|
5968
|
-
args: [
|
|
6054
|
+
args: [MAX_RETRIES2]
|
|
5969
6055
|
});
|
|
5970
6056
|
let delivered = 0;
|
|
5971
6057
|
for (const row of result.rows) {
|
|
@@ -5978,13 +6064,13 @@ async function retryPendingMessages() {
|
|
|
5978
6064
|
}
|
|
5979
6065
|
return delivered;
|
|
5980
6066
|
}
|
|
5981
|
-
var
|
|
6067
|
+
var MAX_RETRIES2, _wsClientSend;
|
|
5982
6068
|
var init_messaging = __esm({
|
|
5983
6069
|
"src/lib/messaging.ts"() {
|
|
5984
6070
|
"use strict";
|
|
5985
6071
|
init_database();
|
|
5986
6072
|
init_tmux_routing();
|
|
5987
|
-
|
|
6073
|
+
MAX_RETRIES2 = 10;
|
|
5988
6074
|
_wsClientSend = null;
|
|
5989
6075
|
}
|
|
5990
6076
|
});
|
|
@@ -7226,12 +7312,14 @@ var DEFAULT_BLOOM_CONFIG = {
|
|
|
7226
7312
|
},
|
|
7227
7313
|
tierRules: {
|
|
7228
7314
|
junior: {
|
|
7229
|
-
eligible: [
|
|
7315
|
+
eligible: [],
|
|
7316
|
+
// resolved dynamically from roster (Principal Engineer role)
|
|
7230
7317
|
reviewRequired: false,
|
|
7231
7318
|
manualOnly: false
|
|
7232
7319
|
},
|
|
7233
7320
|
standard: {
|
|
7234
|
-
eligible: [
|
|
7321
|
+
eligible: [],
|
|
7322
|
+
// resolved dynamically from roster (Principal Engineer role)
|
|
7235
7323
|
reviewRequired: false,
|
|
7236
7324
|
manualOnly: false
|
|
7237
7325
|
},
|
|
@@ -8352,8 +8440,8 @@ async function retryWithBackoff(fn, config2 = {}) {
|
|
|
8352
8440
|
} catch (err) {
|
|
8353
8441
|
lastError = err instanceof Error ? err : new Error(String(err));
|
|
8354
8442
|
if (attempt < maxRetries) {
|
|
8355
|
-
const
|
|
8356
|
-
await new Promise((r) => setTimeout(r,
|
|
8443
|
+
const delay2 = Math.min(baseDelayMs * 2 ** attempt, maxDelayMs);
|
|
8444
|
+
await new Promise((r) => setTimeout(r, delay2));
|
|
8357
8445
|
}
|
|
8358
8446
|
}
|
|
8359
8447
|
}
|
|
@@ -11850,7 +11938,7 @@ async function ensureCRMContact(info) {
|
|
|
11850
11938
|
}
|
|
11851
11939
|
|
|
11852
11940
|
// src/automation/trigger-engine.ts
|
|
11853
|
-
import { readFileSync as
|
|
11941
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync6, existsSync as existsSync14, mkdirSync as mkdirSync8 } from "fs";
|
|
11854
11942
|
import { randomUUID as randomUUID14 } from "crypto";
|
|
11855
11943
|
import path19 from "path";
|
|
11856
11944
|
import os7 from "os";
|
|
@@ -11909,7 +11997,7 @@ function evaluateConditions(conditions, record) {
|
|
|
11909
11997
|
function loadTriggers(project) {
|
|
11910
11998
|
if (!existsSync14(TRIGGERS_PATH)) return [];
|
|
11911
11999
|
try {
|
|
11912
|
-
const raw =
|
|
12000
|
+
const raw = readFileSync12(TRIGGERS_PATH, "utf-8");
|
|
11913
12001
|
const all = JSON.parse(raw);
|
|
11914
12002
|
if (!Array.isArray(all)) return [];
|
|
11915
12003
|
if (project) {
|