@askexenow/exe-os 0.8.37 → 0.8.39
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/README.md +17 -8
- package/dist/bin/backfill-conversations.js +112 -70
- package/dist/bin/backfill-responses.js +53 -18
- package/dist/bin/backfill-vectors.js +43 -16
- package/dist/bin/cleanup-stale-review-tasks.js +38 -16
- package/dist/bin/cli.js +790 -468
- package/dist/bin/exe-agent.js +19 -4
- package/dist/bin/exe-assign.js +46 -13
- package/dist/bin/exe-boot.js +288 -129
- package/dist/bin/exe-call.js +20 -10
- package/dist/bin/exe-cloud.js +135 -30
- package/dist/bin/exe-dispatch.js +1 -1
- package/dist/bin/exe-doctor.js +38 -16
- package/dist/bin/exe-export-behaviors.js +43 -21
- package/dist/bin/exe-forget.js +39 -17
- package/dist/bin/exe-gateway.js +159 -50
- package/dist/bin/exe-heartbeat.js +53 -31
- package/dist/bin/exe-kill.js +40 -18
- package/dist/bin/exe-launch-agent.js +109 -36
- package/dist/bin/exe-link.js +196 -87
- package/dist/bin/exe-new-employee.js +56 -17
- package/dist/bin/exe-pending-messages.js +47 -25
- package/dist/bin/exe-pending-notifications.js +38 -16
- package/dist/bin/exe-pending-reviews.js +51 -29
- package/dist/bin/exe-rename.js +21 -7
- package/dist/bin/exe-review.js +41 -13
- package/dist/bin/exe-search.js +57 -21
- package/dist/bin/exe-session-cleanup.js +67 -31
- package/dist/bin/exe-settings.js +63 -2
- package/dist/bin/exe-status.js +35 -13
- package/dist/bin/exe-team.js +35 -13
- package/dist/bin/git-sweep.js +45 -17
- package/dist/bin/graph-backfill.js +38 -16
- package/dist/bin/graph-export.js +38 -16
- package/dist/bin/install.js +10 -1
- package/dist/bin/scan-tasks.js +47 -19
- package/dist/bin/setup.js +444 -259
- package/dist/bin/shard-migrate.js +38 -16
- package/dist/bin/wiki-sync.js +40 -17
- package/dist/gateway/index.js +113 -48
- package/dist/hooks/bug-report-worker.js +66 -39
- package/dist/hooks/commit-complete.js +45 -17
- package/dist/hooks/error-recall.js +60 -20
- package/dist/hooks/exe-heartbeat-hook.js +3 -2
- package/dist/hooks/ingest-worker.js +174 -45
- package/dist/hooks/ingest.js +74 -28
- package/dist/hooks/instructions-loaded.js +46 -17
- package/dist/hooks/notification.js +44 -15
- package/dist/hooks/post-compact.js +44 -15
- package/dist/hooks/pre-compact.js +42 -14
- package/dist/hooks/pre-tool-use.js +59 -22
- package/dist/hooks/prompt-ingest-worker.js +75 -14
- package/dist/hooks/prompt-submit.js +75 -32
- package/dist/hooks/response-ingest-worker.js +76 -15
- package/dist/hooks/session-end.js +54 -22
- package/dist/hooks/session-start.js +57 -20
- package/dist/hooks/stop.js +44 -15
- package/dist/hooks/subagent-stop.js +44 -15
- package/dist/hooks/summary-worker.js +339 -106
- package/dist/index.js +94 -23
- package/dist/lib/cloud-sync.js +191 -80
- package/dist/lib/config.js +4 -1
- package/dist/lib/consolidation.js +5 -4
- package/dist/lib/database.js +1 -0
- package/dist/lib/device-registry.js +2 -1
- package/dist/lib/embedder.js +9 -1
- package/dist/lib/employee-templates.js +5 -0
- package/dist/lib/employees.js +11 -6
- package/dist/lib/exe-daemon-client.js +6 -1
- package/dist/lib/exe-daemon.js +95 -36
- package/dist/lib/hybrid-search.js +57 -21
- package/dist/lib/identity-templates.js +16 -7
- package/dist/lib/identity.js +1 -1
- package/dist/lib/keychain.js +2 -1
- package/dist/lib/license.js +56 -6
- package/dist/lib/messaging.js +1 -1
- package/dist/lib/reminders.js +2 -2
- package/dist/lib/schedules.js +38 -16
- package/dist/lib/skill-learning.js +1 -1
- package/dist/lib/store.js +44 -16
- package/dist/lib/tasks.js +1 -1
- package/dist/lib/tmux-routing.js +1 -1
- package/dist/mcp/server.js +280 -155
- package/dist/mcp/tools/complete-reminder.js +1 -1
- package/dist/mcp/tools/create-task.js +14 -6
- package/dist/mcp/tools/deactivate-behavior.js +2 -2
- package/dist/mcp/tools/list-reminders.js +1 -1
- package/dist/mcp/tools/list-tasks.js +36 -28
- package/dist/mcp/tools/send-message.js +1 -1
- package/dist/mcp/tools/update-task.js +1 -1
- package/dist/runtime/index.js +42 -8
- package/dist/tui/App.js +220 -99
- package/package.json +5 -3
package/dist/tui/App.js
CHANGED
|
@@ -141,6 +141,7 @@ async function ensureSchema() {
|
|
|
141
141
|
const client = getRawClient();
|
|
142
142
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
143
143
|
await client.execute("PRAGMA busy_timeout = 30000");
|
|
144
|
+
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
144
145
|
try {
|
|
145
146
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
146
147
|
} catch {
|
|
@@ -964,7 +965,7 @@ __export(config_exports, {
|
|
|
964
965
|
migrateConfig: () => migrateConfig,
|
|
965
966
|
saveConfig: () => saveConfig
|
|
966
967
|
});
|
|
967
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
968
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
968
969
|
import { readFileSync as readFileSync2, existsSync as existsSync2, renameSync } from "fs";
|
|
969
970
|
import path from "path";
|
|
970
971
|
import os from "os";
|
|
@@ -1090,6 +1091,9 @@ async function saveConfig(config) {
|
|
|
1090
1091
|
await mkdir(dir, { recursive: true });
|
|
1091
1092
|
const configPath = path.join(dir, "config.json");
|
|
1092
1093
|
await writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
1094
|
+
if (config.cloud?.apiKey) {
|
|
1095
|
+
await chmod(configPath, 384);
|
|
1096
|
+
}
|
|
1093
1097
|
}
|
|
1094
1098
|
async function loadConfigFrom(configPath) {
|
|
1095
1099
|
const raw = await readFile(configPath, "utf-8");
|
|
@@ -1204,12 +1208,22 @@ __export(license_exports, {
|
|
|
1204
1208
|
loadLicense: () => loadLicense,
|
|
1205
1209
|
mirrorLicenseKey: () => mirrorLicenseKey,
|
|
1206
1210
|
saveLicense: () => saveLicense,
|
|
1211
|
+
startLicenseRevalidation: () => startLicenseRevalidation,
|
|
1212
|
+
stopLicenseRevalidation: () => stopLicenseRevalidation,
|
|
1207
1213
|
validateLicense: () => validateLicense
|
|
1208
1214
|
});
|
|
1209
1215
|
import { readFileSync as readFileSync3, writeFileSync, existsSync as existsSync3, mkdirSync } from "fs";
|
|
1210
1216
|
import { randomUUID } from "crypto";
|
|
1211
1217
|
import path2 from "path";
|
|
1212
1218
|
import { jwtVerify, importSPKI } from "jose";
|
|
1219
|
+
async function fetchRetry(url, init) {
|
|
1220
|
+
try {
|
|
1221
|
+
return await fetch(url, init);
|
|
1222
|
+
} catch {
|
|
1223
|
+
await new Promise((r) => setTimeout(r, RETRY_DELAY_MS));
|
|
1224
|
+
return fetch(url, { ...init, signal: AbortSignal.timeout(1e4) });
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1213
1227
|
function loadDeviceId() {
|
|
1214
1228
|
const deviceJsonPath = path2.join(EXE_AI_DIR, "device.json");
|
|
1215
1229
|
try {
|
|
@@ -1241,7 +1255,7 @@ function loadLicense() {
|
|
|
1241
1255
|
}
|
|
1242
1256
|
function saveLicense(apiKey) {
|
|
1243
1257
|
mkdirSync(EXE_AI_DIR, { recursive: true });
|
|
1244
|
-
writeFileSync(LICENSE_PATH, apiKey.trim(), "utf8");
|
|
1258
|
+
writeFileSync(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
|
|
1245
1259
|
}
|
|
1246
1260
|
async function verifyLicenseJwt(token) {
|
|
1247
1261
|
try {
|
|
@@ -1293,7 +1307,7 @@ function cacheResponse(token) {
|
|
|
1293
1307
|
async function validateLicense(apiKey, deviceId) {
|
|
1294
1308
|
const did = deviceId ?? loadDeviceId();
|
|
1295
1309
|
try {
|
|
1296
|
-
const res = await
|
|
1310
|
+
const res = await fetchRetry(`${API_BASE}/auth/activate`, {
|
|
1297
1311
|
method: "POST",
|
|
1298
1312
|
headers: { "Content-Type": "application/json" },
|
|
1299
1313
|
body: JSON.stringify({ apiKey, deviceId: did }),
|
|
@@ -1328,14 +1342,23 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
1328
1342
|
} catch {
|
|
1329
1343
|
const cached = await getCachedLicense();
|
|
1330
1344
|
if (cached) return cached;
|
|
1331
|
-
return FREE_LICENSE;
|
|
1345
|
+
return { ...FREE_LICENSE, valid: false, error: "offline" };
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
function getCacheAgeMs() {
|
|
1349
|
+
try {
|
|
1350
|
+
const { statSync } = __require("fs");
|
|
1351
|
+
const s = statSync(CACHE_PATH);
|
|
1352
|
+
return Date.now() - s.mtimeMs;
|
|
1353
|
+
} catch {
|
|
1354
|
+
return Infinity;
|
|
1332
1355
|
}
|
|
1333
1356
|
}
|
|
1334
1357
|
async function checkLicense() {
|
|
1335
1358
|
const key = loadLicense();
|
|
1336
1359
|
if (!key) return FREE_LICENSE;
|
|
1337
1360
|
const cached = await getCachedLicense();
|
|
1338
|
-
if (cached) return cached;
|
|
1361
|
+
if (cached && getCacheAgeMs() < CACHE_MAX_AGE_MS) return cached;
|
|
1339
1362
|
const deviceId = loadDeviceId();
|
|
1340
1363
|
return validateLicense(key, deviceId);
|
|
1341
1364
|
}
|
|
@@ -1375,7 +1398,7 @@ async function assertVpsLicense(opts) {
|
|
|
1375
1398
|
let explicitRejection = false;
|
|
1376
1399
|
let transientFailure = false;
|
|
1377
1400
|
try {
|
|
1378
|
-
const res = await
|
|
1401
|
+
const res = await fetchRetry(`${API_BASE}/auth/activate`, {
|
|
1379
1402
|
method: "POST",
|
|
1380
1403
|
headers: { "Content-Type": "application/json" },
|
|
1381
1404
|
body: JSON.stringify({ apiKey, deviceId }),
|
|
@@ -1456,7 +1479,28 @@ async function assertVpsLicense(opts) {
|
|
|
1456
1479
|
`License validation unreachable for more than ${graceDays} days. Restore network connectivity to https://askexe.com/cloud and retry. This VPS image refuses to boot after the offline grace window.`
|
|
1457
1480
|
);
|
|
1458
1481
|
}
|
|
1459
|
-
|
|
1482
|
+
function startLicenseRevalidation(intervalMs = 36e5) {
|
|
1483
|
+
if (_revalTimer) return;
|
|
1484
|
+
_revalTimer = setInterval(async () => {
|
|
1485
|
+
try {
|
|
1486
|
+
const license = await checkLicense();
|
|
1487
|
+
if (!license.valid) {
|
|
1488
|
+
process.stderr.write("[exe-os] License expired or invalid \u2014 features may be restricted\n");
|
|
1489
|
+
}
|
|
1490
|
+
} catch {
|
|
1491
|
+
}
|
|
1492
|
+
}, intervalMs);
|
|
1493
|
+
if (_revalTimer && typeof _revalTimer === "object" && "unref" in _revalTimer) {
|
|
1494
|
+
_revalTimer.unref();
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
function stopLicenseRevalidation() {
|
|
1498
|
+
if (_revalTimer) {
|
|
1499
|
+
clearInterval(_revalTimer);
|
|
1500
|
+
_revalTimer = null;
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE, RETRY_DELAY_MS, LICENSE_PUBLIC_KEY_PEM, LICENSE_JWT_ALG, PLAN_LIMITS, FREE_LICENSE, CACHE_MAX_AGE_MS, _revalTimer;
|
|
1460
1504
|
var init_license = __esm({
|
|
1461
1505
|
"src/lib/license.ts"() {
|
|
1462
1506
|
"use strict";
|
|
@@ -1465,6 +1509,7 @@ var init_license = __esm({
|
|
|
1465
1509
|
CACHE_PATH = path2.join(EXE_AI_DIR, "license-cache.json");
|
|
1466
1510
|
DEVICE_ID_PATH = path2.join(EXE_AI_DIR, "device-id");
|
|
1467
1511
|
API_BASE = "https://askexe.com/cloud";
|
|
1512
|
+
RETRY_DELAY_MS = 500;
|
|
1468
1513
|
LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
|
|
1469
1514
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|
|
1470
1515
|
4uj+UqeKCcvtgNHKmOK278HJaJcANe9xAeji8AFYu27q3WtzCi04pHudow==
|
|
@@ -1486,6 +1531,8 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|
|
|
1486
1531
|
employeeLimit: 1,
|
|
1487
1532
|
memoryLimit: 5e3
|
|
1488
1533
|
};
|
|
1534
|
+
CACHE_MAX_AGE_MS = 36e5;
|
|
1535
|
+
_revalTimer = null;
|
|
1489
1536
|
}
|
|
1490
1537
|
});
|
|
1491
1538
|
|
|
@@ -3335,8 +3382,13 @@ function runRipgrep(input, searchPath, context) {
|
|
|
3335
3382
|
timeout: 3e4,
|
|
3336
3383
|
stdio: ["ignore", "pipe", "pipe"]
|
|
3337
3384
|
});
|
|
3385
|
+
const MAX_OUTPUT = 1e7;
|
|
3338
3386
|
const chunks = [];
|
|
3339
|
-
|
|
3387
|
+
let totalSize = 0;
|
|
3388
|
+
child.stdout.on("data", (chunk) => {
|
|
3389
|
+
totalSize += chunk.length;
|
|
3390
|
+
if (totalSize <= MAX_OUTPUT) chunks.push(chunk);
|
|
3391
|
+
});
|
|
3340
3392
|
const onAbort = () => child.kill("SIGTERM");
|
|
3341
3393
|
context.abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
3342
3394
|
child.on("close", (code) => {
|
|
@@ -3720,10 +3772,19 @@ var init_bash = __esm({
|
|
|
3720
3772
|
stdio: ["ignore", "pipe", "pipe"],
|
|
3721
3773
|
env: { ...process.env }
|
|
3722
3774
|
});
|
|
3775
|
+
const MAX_OUTPUT_SIZE = 5242880;
|
|
3723
3776
|
const stdoutChunks = [];
|
|
3724
3777
|
const stderrChunks = [];
|
|
3725
|
-
|
|
3726
|
-
|
|
3778
|
+
let stdoutSize = 0;
|
|
3779
|
+
let stderrSize = 0;
|
|
3780
|
+
child.stdout.on("data", (chunk) => {
|
|
3781
|
+
if (stdoutSize < MAX_OUTPUT_SIZE) stdoutChunks.push(chunk);
|
|
3782
|
+
stdoutSize += chunk.length;
|
|
3783
|
+
});
|
|
3784
|
+
child.stderr.on("data", (chunk) => {
|
|
3785
|
+
if (stderrSize < MAX_OUTPUT_SIZE) stderrChunks.push(chunk);
|
|
3786
|
+
stderrSize += chunk.length;
|
|
3787
|
+
});
|
|
3727
3788
|
const onAbort = () => {
|
|
3728
3789
|
child.kill("SIGTERM");
|
|
3729
3790
|
setTimeout(() => {
|
|
@@ -3903,15 +3964,20 @@ function addEmployee(employees, employee) {
|
|
|
3903
3964
|
}
|
|
3904
3965
|
return [...employees, normalized];
|
|
3905
3966
|
}
|
|
3967
|
+
function findExeBin() {
|
|
3968
|
+
try {
|
|
3969
|
+
return execSync3(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
|
|
3970
|
+
} catch {
|
|
3971
|
+
return null;
|
|
3972
|
+
}
|
|
3973
|
+
}
|
|
3906
3974
|
function registerBinSymlinks(name) {
|
|
3907
3975
|
const created = [];
|
|
3908
3976
|
const skipped = [];
|
|
3909
3977
|
const errors = [];
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
} catch {
|
|
3914
|
-
errors.push("Could not find 'exe' in PATH");
|
|
3978
|
+
const exeBinPath = findExeBin();
|
|
3979
|
+
if (!exeBinPath) {
|
|
3980
|
+
errors.push("Could not find 'exe-os' in PATH");
|
|
3915
3981
|
return { created, skipped, errors };
|
|
3916
3982
|
}
|
|
3917
3983
|
const binDir = path10.dirname(exeBinPath);
|
|
@@ -4270,10 +4336,10 @@ var init_provider_table = __esm({
|
|
|
4270
4336
|
|
|
4271
4337
|
// src/lib/intercom-queue.ts
|
|
4272
4338
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync3, renameSync as renameSync2, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
|
|
4273
|
-
import
|
|
4339
|
+
import path12 from "path";
|
|
4274
4340
|
import os4 from "os";
|
|
4275
4341
|
function ensureDir() {
|
|
4276
|
-
const dir =
|
|
4342
|
+
const dir = path12.dirname(QUEUE_PATH);
|
|
4277
4343
|
if (!existsSync6(dir)) mkdirSync3(dir, { recursive: true });
|
|
4278
4344
|
}
|
|
4279
4345
|
function readQueue() {
|
|
@@ -4311,15 +4377,15 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
|
4311
4377
|
var init_intercom_queue = __esm({
|
|
4312
4378
|
"src/lib/intercom-queue.ts"() {
|
|
4313
4379
|
"use strict";
|
|
4314
|
-
QUEUE_PATH =
|
|
4380
|
+
QUEUE_PATH = path12.join(os4.homedir(), ".exe-os", "intercom-queue.json");
|
|
4315
4381
|
TTL_MS = 60 * 60 * 1e3;
|
|
4316
|
-
INTERCOM_LOG =
|
|
4382
|
+
INTERCOM_LOG = path12.join(os4.homedir(), ".exe-os", "intercom.log");
|
|
4317
4383
|
}
|
|
4318
4384
|
});
|
|
4319
4385
|
|
|
4320
4386
|
// src/lib/plan-limits.ts
|
|
4321
4387
|
import { readFileSync as readFileSync7, existsSync as existsSync7 } from "fs";
|
|
4322
|
-
import
|
|
4388
|
+
import path13 from "path";
|
|
4323
4389
|
function getLicenseSync() {
|
|
4324
4390
|
try {
|
|
4325
4391
|
if (!existsSync7(CACHE_PATH2)) return freeLicense();
|
|
@@ -4391,13 +4457,13 @@ var init_plan_limits = __esm({
|
|
|
4391
4457
|
this.name = "PlanLimitError";
|
|
4392
4458
|
}
|
|
4393
4459
|
};
|
|
4394
|
-
CACHE_PATH2 =
|
|
4460
|
+
CACHE_PATH2 = path13.join(EXE_AI_DIR, "license-cache.json");
|
|
4395
4461
|
}
|
|
4396
4462
|
});
|
|
4397
4463
|
|
|
4398
4464
|
// src/lib/notifications.ts
|
|
4399
4465
|
import crypto from "crypto";
|
|
4400
|
-
import
|
|
4466
|
+
import path14 from "path";
|
|
4401
4467
|
import os5 from "os";
|
|
4402
4468
|
import {
|
|
4403
4469
|
readFileSync as readFileSync8,
|
|
@@ -4483,7 +4549,7 @@ var init_session_kill_telemetry = __esm({
|
|
|
4483
4549
|
|
|
4484
4550
|
// src/lib/tasks-crud.ts
|
|
4485
4551
|
import crypto3 from "crypto";
|
|
4486
|
-
import
|
|
4552
|
+
import path15 from "path";
|
|
4487
4553
|
import { execSync as execSync6 } from "child_process";
|
|
4488
4554
|
import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
|
|
4489
4555
|
import { existsSync as existsSync9, readFileSync as readFileSync9 } from "fs";
|
|
@@ -4616,8 +4682,8 @@ async function createTaskCore(input) {
|
|
|
4616
4682
|
}
|
|
4617
4683
|
if (input.baseDir) {
|
|
4618
4684
|
try {
|
|
4619
|
-
await mkdir3(
|
|
4620
|
-
await mkdir3(
|
|
4685
|
+
await mkdir3(path15.join(input.baseDir, "exe", "output"), { recursive: true });
|
|
4686
|
+
await mkdir3(path15.join(input.baseDir, "exe", "research"), { recursive: true });
|
|
4621
4687
|
await ensureArchitectureDoc(input.baseDir, input.projectName);
|
|
4622
4688
|
await ensureGitignoreExe(input.baseDir);
|
|
4623
4689
|
} catch {
|
|
@@ -4825,7 +4891,7 @@ async function deleteTaskCore(taskId, _baseDir) {
|
|
|
4825
4891
|
return { taskFile, assignedTo, assignedBy, taskSlug };
|
|
4826
4892
|
}
|
|
4827
4893
|
async function ensureArchitectureDoc(baseDir, projectName) {
|
|
4828
|
-
const archPath =
|
|
4894
|
+
const archPath = path15.join(baseDir, "exe", "ARCHITECTURE.md");
|
|
4829
4895
|
try {
|
|
4830
4896
|
if (existsSync9(archPath)) return;
|
|
4831
4897
|
const template = [
|
|
@@ -4860,7 +4926,7 @@ async function ensureArchitectureDoc(baseDir, projectName) {
|
|
|
4860
4926
|
}
|
|
4861
4927
|
}
|
|
4862
4928
|
async function ensureGitignoreExe(baseDir) {
|
|
4863
|
-
const gitignorePath =
|
|
4929
|
+
const gitignorePath = path15.join(baseDir, ".gitignore");
|
|
4864
4930
|
try {
|
|
4865
4931
|
if (existsSync9(gitignorePath)) {
|
|
4866
4932
|
const content = readFileSync9(gitignorePath, "utf-8");
|
|
@@ -4883,7 +4949,7 @@ var init_tasks_crud = __esm({
|
|
|
4883
4949
|
});
|
|
4884
4950
|
|
|
4885
4951
|
// src/lib/tasks-review.ts
|
|
4886
|
-
import
|
|
4952
|
+
import path16 from "path";
|
|
4887
4953
|
import { existsSync as existsSync10, readdirSync as readdirSync2, unlinkSync as unlinkSync2 } from "fs";
|
|
4888
4954
|
async function countPendingReviews() {
|
|
4889
4955
|
const client = getClient();
|
|
@@ -5004,11 +5070,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
5004
5070
|
);
|
|
5005
5071
|
}
|
|
5006
5072
|
try {
|
|
5007
|
-
const cacheDir =
|
|
5073
|
+
const cacheDir = path16.join(EXE_AI_DIR, "session-cache");
|
|
5008
5074
|
if (existsSync10(cacheDir)) {
|
|
5009
5075
|
for (const f of readdirSync2(cacheDir)) {
|
|
5010
5076
|
if (f.startsWith("review-notified-")) {
|
|
5011
|
-
unlinkSync2(
|
|
5077
|
+
unlinkSync2(path16.join(cacheDir, f));
|
|
5012
5078
|
}
|
|
5013
5079
|
}
|
|
5014
5080
|
}
|
|
@@ -5029,7 +5095,7 @@ var init_tasks_review = __esm({
|
|
|
5029
5095
|
});
|
|
5030
5096
|
|
|
5031
5097
|
// src/lib/tasks-chain.ts
|
|
5032
|
-
import
|
|
5098
|
+
import path17 from "path";
|
|
5033
5099
|
import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
|
|
5034
5100
|
async function cascadeUnblock(taskId, baseDir, now) {
|
|
5035
5101
|
const client = getClient();
|
|
@@ -5045,7 +5111,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
|
|
|
5045
5111
|
});
|
|
5046
5112
|
for (const ur of unblockedRows.rows) {
|
|
5047
5113
|
try {
|
|
5048
|
-
const ubFile =
|
|
5114
|
+
const ubFile = path17.join(baseDir, String(ur.task_file));
|
|
5049
5115
|
let ubContent = await readFile3(ubFile, "utf-8");
|
|
5050
5116
|
ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
|
|
5051
5117
|
ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
|
|
@@ -5111,7 +5177,7 @@ var init_tasks_chain = __esm({
|
|
|
5111
5177
|
|
|
5112
5178
|
// src/lib/project-name.ts
|
|
5113
5179
|
import { execSync as execSync7 } from "child_process";
|
|
5114
|
-
import
|
|
5180
|
+
import path18 from "path";
|
|
5115
5181
|
function getProjectName(cwd2) {
|
|
5116
5182
|
const dir = cwd2 ?? process.cwd();
|
|
5117
5183
|
if (_cached2 && _cachedCwd === dir) return _cached2;
|
|
@@ -5124,7 +5190,7 @@ function getProjectName(cwd2) {
|
|
|
5124
5190
|
timeout: 2e3,
|
|
5125
5191
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5126
5192
|
}).trim();
|
|
5127
|
-
repoRoot =
|
|
5193
|
+
repoRoot = path18.dirname(gitCommonDir);
|
|
5128
5194
|
} catch {
|
|
5129
5195
|
repoRoot = execSync7("git rev-parse --show-toplevel", {
|
|
5130
5196
|
cwd: dir,
|
|
@@ -5133,11 +5199,11 @@ function getProjectName(cwd2) {
|
|
|
5133
5199
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5134
5200
|
}).trim();
|
|
5135
5201
|
}
|
|
5136
|
-
_cached2 =
|
|
5202
|
+
_cached2 = path18.basename(repoRoot);
|
|
5137
5203
|
_cachedCwd = dir;
|
|
5138
5204
|
return _cached2;
|
|
5139
5205
|
} catch {
|
|
5140
|
-
_cached2 =
|
|
5206
|
+
_cached2 = path18.basename(dir);
|
|
5141
5207
|
_cachedCwd = dir;
|
|
5142
5208
|
return _cached2;
|
|
5143
5209
|
}
|
|
@@ -5608,7 +5674,7 @@ __export(tasks_exports, {
|
|
|
5608
5674
|
updateTaskStatus: () => updateTaskStatus,
|
|
5609
5675
|
writeCheckpoint: () => writeCheckpoint
|
|
5610
5676
|
});
|
|
5611
|
-
import
|
|
5677
|
+
import path19 from "path";
|
|
5612
5678
|
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, unlinkSync as unlinkSync3 } from "fs";
|
|
5613
5679
|
async function createTask(input) {
|
|
5614
5680
|
const result = await createTaskCore(input);
|
|
@@ -5628,8 +5694,8 @@ async function updateTask(input) {
|
|
|
5628
5694
|
const { row, taskFile, now, taskId } = await updateTaskStatus(input);
|
|
5629
5695
|
try {
|
|
5630
5696
|
const agent = String(row.assigned_to);
|
|
5631
|
-
const cacheDir =
|
|
5632
|
-
const cachePath =
|
|
5697
|
+
const cacheDir = path19.join(EXE_AI_DIR, "session-cache");
|
|
5698
|
+
const cachePath = path19.join(cacheDir, `current-task-${agent}.json`);
|
|
5633
5699
|
if (input.status === "in_progress") {
|
|
5634
5700
|
mkdirSync4(cacheDir, { recursive: true });
|
|
5635
5701
|
writeFileSync4(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
|
|
@@ -6051,12 +6117,12 @@ __export(tmux_routing_exports, {
|
|
|
6051
6117
|
});
|
|
6052
6118
|
import { execFileSync as execFileSync3, execSync as execSync8 } from "child_process";
|
|
6053
6119
|
import { readFileSync as readFileSync10, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync11, appendFileSync } from "fs";
|
|
6054
|
-
import
|
|
6120
|
+
import path20 from "path";
|
|
6055
6121
|
import os6 from "os";
|
|
6056
6122
|
import { fileURLToPath } from "url";
|
|
6057
6123
|
import { unlinkSync as unlinkSync4 } from "fs";
|
|
6058
6124
|
function spawnLockPath(sessionName) {
|
|
6059
|
-
return
|
|
6125
|
+
return path20.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
6060
6126
|
}
|
|
6061
6127
|
function isProcessAlive(pid) {
|
|
6062
6128
|
try {
|
|
@@ -6093,8 +6159,8 @@ function releaseSpawnLock(sessionName) {
|
|
|
6093
6159
|
function resolveBehaviorsExporterScript() {
|
|
6094
6160
|
try {
|
|
6095
6161
|
const thisFile = fileURLToPath(import.meta.url);
|
|
6096
|
-
const scriptPath =
|
|
6097
|
-
|
|
6162
|
+
const scriptPath = path20.join(
|
|
6163
|
+
path20.dirname(thisFile),
|
|
6098
6164
|
"..",
|
|
6099
6165
|
"bin",
|
|
6100
6166
|
"exe-export-behaviors.js"
|
|
@@ -6144,7 +6210,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
|
6144
6210
|
mkdirSync5(SESSION_CACHE, { recursive: true });
|
|
6145
6211
|
}
|
|
6146
6212
|
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
6147
|
-
const filePath =
|
|
6213
|
+
const filePath = path20.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
6148
6214
|
writeFileSync5(filePath, JSON.stringify({
|
|
6149
6215
|
parentExe: rootExe,
|
|
6150
6216
|
dispatchedBy: dispatchedBy || rootExe,
|
|
@@ -6153,7 +6219,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
|
6153
6219
|
}
|
|
6154
6220
|
function getParentExe(sessionKey) {
|
|
6155
6221
|
try {
|
|
6156
|
-
const data = JSON.parse(readFileSync10(
|
|
6222
|
+
const data = JSON.parse(readFileSync10(path20.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
6157
6223
|
return data.parentExe || null;
|
|
6158
6224
|
} catch {
|
|
6159
6225
|
return null;
|
|
@@ -6162,7 +6228,7 @@ function getParentExe(sessionKey) {
|
|
|
6162
6228
|
function getDispatchedBy(sessionKey) {
|
|
6163
6229
|
try {
|
|
6164
6230
|
const data = JSON.parse(readFileSync10(
|
|
6165
|
-
|
|
6231
|
+
path20.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
|
|
6166
6232
|
"utf8"
|
|
6167
6233
|
));
|
|
6168
6234
|
return data.dispatchedBy ?? data.parentExe ?? null;
|
|
@@ -6405,8 +6471,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6405
6471
|
const transport = getTransport();
|
|
6406
6472
|
const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
|
|
6407
6473
|
const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
6408
|
-
const logDir =
|
|
6409
|
-
const logFile =
|
|
6474
|
+
const logDir = path20.join(os6.homedir(), ".exe-os", "session-logs");
|
|
6475
|
+
const logFile = path20.join(logDir, `${instanceLabel}-${Date.now()}.log`);
|
|
6410
6476
|
if (!existsSync11(logDir)) {
|
|
6411
6477
|
mkdirSync5(logDir, { recursive: true });
|
|
6412
6478
|
}
|
|
@@ -6414,14 +6480,14 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6414
6480
|
let cleanupSuffix = "";
|
|
6415
6481
|
try {
|
|
6416
6482
|
const thisFile = fileURLToPath(import.meta.url);
|
|
6417
|
-
const cleanupScript =
|
|
6483
|
+
const cleanupScript = path20.join(path20.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
|
|
6418
6484
|
if (existsSync11(cleanupScript)) {
|
|
6419
6485
|
cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
|
|
6420
6486
|
}
|
|
6421
6487
|
} catch {
|
|
6422
6488
|
}
|
|
6423
6489
|
try {
|
|
6424
|
-
const claudeJsonPath =
|
|
6490
|
+
const claudeJsonPath = path20.join(os6.homedir(), ".claude.json");
|
|
6425
6491
|
let claudeJson = {};
|
|
6426
6492
|
try {
|
|
6427
6493
|
claudeJson = JSON.parse(readFileSync10(claudeJsonPath, "utf8"));
|
|
@@ -6436,10 +6502,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6436
6502
|
} catch {
|
|
6437
6503
|
}
|
|
6438
6504
|
try {
|
|
6439
|
-
const settingsDir =
|
|
6505
|
+
const settingsDir = path20.join(os6.homedir(), ".claude", "projects");
|
|
6440
6506
|
const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
|
|
6441
|
-
const projSettingsDir =
|
|
6442
|
-
const settingsPath =
|
|
6507
|
+
const projSettingsDir = path20.join(settingsDir, normalizedKey);
|
|
6508
|
+
const settingsPath = path20.join(projSettingsDir, "settings.json");
|
|
6443
6509
|
let settings = {};
|
|
6444
6510
|
try {
|
|
6445
6511
|
settings = JSON.parse(readFileSync10(settingsPath, "utf8"));
|
|
@@ -6483,7 +6549,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6483
6549
|
let behaviorsFlag = "";
|
|
6484
6550
|
let legacyFallbackWarned = false;
|
|
6485
6551
|
if (!useExeAgent && !useBinSymlink) {
|
|
6486
|
-
const identityPath =
|
|
6552
|
+
const identityPath = path20.join(
|
|
6487
6553
|
os6.homedir(),
|
|
6488
6554
|
".exe-os",
|
|
6489
6555
|
"identity",
|
|
@@ -6499,7 +6565,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6499
6565
|
}
|
|
6500
6566
|
const behaviorsFile = exportBehaviorsSync(
|
|
6501
6567
|
employeeName,
|
|
6502
|
-
|
|
6568
|
+
path20.basename(spawnCwd),
|
|
6503
6569
|
sessionName
|
|
6504
6570
|
);
|
|
6505
6571
|
if (behaviorsFile) {
|
|
@@ -6514,9 +6580,9 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6514
6580
|
}
|
|
6515
6581
|
let sessionContextFlag = "";
|
|
6516
6582
|
try {
|
|
6517
|
-
const ctxDir =
|
|
6583
|
+
const ctxDir = path20.join(os6.homedir(), ".exe-os", "session-cache");
|
|
6518
6584
|
mkdirSync5(ctxDir, { recursive: true });
|
|
6519
|
-
const ctxFile =
|
|
6585
|
+
const ctxFile = path20.join(ctxDir, `session-context-${sessionName}.md`);
|
|
6520
6586
|
const ctxContent = [
|
|
6521
6587
|
`## Session Context`,
|
|
6522
6588
|
`You are running in tmux session: ${sessionName}.`,
|
|
@@ -6561,7 +6627,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6561
6627
|
transport.pipeLog(sessionName, logFile);
|
|
6562
6628
|
try {
|
|
6563
6629
|
const mySession = getMySession();
|
|
6564
|
-
const dispatchInfo =
|
|
6630
|
+
const dispatchInfo = path20.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
|
|
6565
6631
|
writeFileSync5(dispatchInfo, JSON.stringify({
|
|
6566
6632
|
dispatchedBy: mySession,
|
|
6567
6633
|
rootExe: exeSession,
|
|
@@ -6625,13 +6691,13 @@ var init_tmux_routing = __esm({
|
|
|
6625
6691
|
init_provider_table();
|
|
6626
6692
|
init_intercom_queue();
|
|
6627
6693
|
init_plan_limits();
|
|
6628
|
-
SPAWN_LOCK_DIR =
|
|
6629
|
-
SESSION_CACHE =
|
|
6694
|
+
SPAWN_LOCK_DIR = path20.join(os6.homedir(), ".exe-os", "spawn-locks");
|
|
6695
|
+
SESSION_CACHE = path20.join(os6.homedir(), ".exe-os", "session-cache");
|
|
6630
6696
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
6631
6697
|
VERIFY_PANE_LINES = 200;
|
|
6632
6698
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
6633
|
-
INTERCOM_LOG2 =
|
|
6634
|
-
DEBOUNCE_FILE =
|
|
6699
|
+
INTERCOM_LOG2 = path20.join(os6.homedir(), ".exe-os", "intercom.log");
|
|
6700
|
+
DEBOUNCE_FILE = path20.join(SESSION_CACHE, "intercom-debounce.json");
|
|
6635
6701
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
6636
6702
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
|
|
6637
6703
|
}
|
|
@@ -6938,15 +7004,16 @@ __export(keychain_exports, {
|
|
|
6938
7004
|
importMnemonic: () => importMnemonic,
|
|
6939
7005
|
setMasterKey: () => setMasterKey
|
|
6940
7006
|
});
|
|
6941
|
-
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod } from "fs/promises";
|
|
7007
|
+
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
6942
7008
|
import { existsSync as existsSync12 } from "fs";
|
|
6943
|
-
import
|
|
7009
|
+
import path22 from "path";
|
|
7010
|
+
import os7 from "os";
|
|
6944
7011
|
import crypto6 from "crypto";
|
|
6945
7012
|
function getKeyDir() {
|
|
6946
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ??
|
|
7013
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path22.join(os7.homedir(), ".exe-os");
|
|
6947
7014
|
}
|
|
6948
7015
|
function getKeyPath() {
|
|
6949
|
-
return
|
|
7016
|
+
return path22.join(getKeyDir(), "master.key");
|
|
6950
7017
|
}
|
|
6951
7018
|
async function tryKeytar() {
|
|
6952
7019
|
try {
|
|
@@ -6991,7 +7058,7 @@ async function setMasterKey(key) {
|
|
|
6991
7058
|
await mkdir4(dir, { recursive: true });
|
|
6992
7059
|
const keyPath = getKeyPath();
|
|
6993
7060
|
await writeFile5(keyPath, b64 + "\n", "utf-8");
|
|
6994
|
-
await
|
|
7061
|
+
await chmod2(keyPath, 384);
|
|
6995
7062
|
}
|
|
6996
7063
|
async function deleteMasterKey() {
|
|
6997
7064
|
const keytar = await tryKeytar();
|
|
@@ -7333,8 +7400,8 @@ __export(wiki_client_exports, {
|
|
|
7333
7400
|
listDocuments: () => listDocuments,
|
|
7334
7401
|
listWorkspaces: () => listWorkspaces
|
|
7335
7402
|
});
|
|
7336
|
-
async function wikiFetch(config,
|
|
7337
|
-
const url = `${config.baseUrl}/api/v1${
|
|
7403
|
+
async function wikiFetch(config, path24, method = "GET", body) {
|
|
7404
|
+
const url = `${config.baseUrl}/api/v1${path24}`;
|
|
7338
7405
|
const headers = {
|
|
7339
7406
|
Authorization: `Bearer ${config.apiKey}`,
|
|
7340
7407
|
"Content-Type": "application/json"
|
|
@@ -7342,14 +7409,32 @@ async function wikiFetch(config, path22, method = "GET", body) {
|
|
|
7342
7409
|
const controller = new AbortController();
|
|
7343
7410
|
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
7344
7411
|
try {
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7412
|
+
let response;
|
|
7413
|
+
try {
|
|
7414
|
+
response = await fetch(url, {
|
|
7415
|
+
method,
|
|
7416
|
+
headers,
|
|
7417
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
7418
|
+
signal: controller.signal
|
|
7419
|
+
});
|
|
7420
|
+
} catch {
|
|
7421
|
+
clearTimeout(timeout);
|
|
7422
|
+
const retryController = new AbortController();
|
|
7423
|
+
const retryTimeout = setTimeout(() => retryController.abort(), REQUEST_TIMEOUT_MS);
|
|
7424
|
+
try {
|
|
7425
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
7426
|
+
response = await fetch(url, {
|
|
7427
|
+
method,
|
|
7428
|
+
headers,
|
|
7429
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
7430
|
+
signal: retryController.signal
|
|
7431
|
+
});
|
|
7432
|
+
} finally {
|
|
7433
|
+
clearTimeout(retryTimeout);
|
|
7434
|
+
}
|
|
7435
|
+
}
|
|
7351
7436
|
if (!response.ok) {
|
|
7352
|
-
throw new Error(`Wiki API ${method} ${
|
|
7437
|
+
throw new Error(`Wiki API ${method} ${path24}: ${response.status} ${response.statusText}`);
|
|
7353
7438
|
}
|
|
7354
7439
|
return response.json();
|
|
7355
7440
|
} finally {
|
|
@@ -7470,8 +7555,8 @@ __export(shard_manager_exports, {
|
|
|
7470
7555
|
listShards: () => listShards,
|
|
7471
7556
|
shardExists: () => shardExists
|
|
7472
7557
|
});
|
|
7473
|
-
import
|
|
7474
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync6 } from "fs";
|
|
7558
|
+
import path23 from "path";
|
|
7559
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync6, readdirSync as readdirSync3 } from "fs";
|
|
7475
7560
|
import { createClient as createClient2 } from "@libsql/client";
|
|
7476
7561
|
function initShardManager(encryptionKey) {
|
|
7477
7562
|
_encryptionKey = encryptionKey;
|
|
@@ -7496,7 +7581,7 @@ function getShardClient(projectName) {
|
|
|
7496
7581
|
}
|
|
7497
7582
|
const cached = _shards.get(safeName);
|
|
7498
7583
|
if (cached) return cached;
|
|
7499
|
-
const dbPath =
|
|
7584
|
+
const dbPath = path23.join(SHARDS_DIR, `${safeName}.db`);
|
|
7500
7585
|
const client = createClient2({
|
|
7501
7586
|
url: `file:${dbPath}`,
|
|
7502
7587
|
encryptionKey: _encryptionKey
|
|
@@ -7506,11 +7591,10 @@ function getShardClient(projectName) {
|
|
|
7506
7591
|
}
|
|
7507
7592
|
function shardExists(projectName) {
|
|
7508
7593
|
const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7509
|
-
return existsSync13(
|
|
7594
|
+
return existsSync13(path23.join(SHARDS_DIR, `${safeName}.db`));
|
|
7510
7595
|
}
|
|
7511
7596
|
function listShards() {
|
|
7512
7597
|
if (!existsSync13(SHARDS_DIR)) return [];
|
|
7513
|
-
const { readdirSync: readdirSync3 } = __require("fs");
|
|
7514
7598
|
return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
7515
7599
|
}
|
|
7516
7600
|
async function ensureShardSchema(client) {
|
|
@@ -7692,7 +7776,7 @@ var init_shard_manager = __esm({
|
|
|
7692
7776
|
"src/lib/shard-manager.ts"() {
|
|
7693
7777
|
"use strict";
|
|
7694
7778
|
init_config();
|
|
7695
|
-
SHARDS_DIR =
|
|
7779
|
+
SHARDS_DIR = path23.join(EXE_AI_DIR, "shards");
|
|
7696
7780
|
_shards = /* @__PURE__ */ new Map();
|
|
7697
7781
|
_encryptionKey = null;
|
|
7698
7782
|
_shardingEnabled = false;
|
|
@@ -7716,6 +7800,28 @@ __export(store_exports, {
|
|
|
7716
7800
|
vectorToBlob: () => vectorToBlob,
|
|
7717
7801
|
writeMemory: () => writeMemory
|
|
7718
7802
|
});
|
|
7803
|
+
function isBusyError2(err) {
|
|
7804
|
+
if (err instanceof Error) {
|
|
7805
|
+
const msg = err.message.toLowerCase();
|
|
7806
|
+
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
7807
|
+
}
|
|
7808
|
+
return false;
|
|
7809
|
+
}
|
|
7810
|
+
async function retryOnBusy2(fn, label) {
|
|
7811
|
+
for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
|
|
7812
|
+
try {
|
|
7813
|
+
return await fn();
|
|
7814
|
+
} catch (err) {
|
|
7815
|
+
if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
|
|
7816
|
+
process.stderr.write(
|
|
7817
|
+
`[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
|
|
7818
|
+
`
|
|
7819
|
+
);
|
|
7820
|
+
await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
|
|
7821
|
+
}
|
|
7822
|
+
}
|
|
7823
|
+
throw new Error("unreachable");
|
|
7824
|
+
}
|
|
7719
7825
|
async function initStore(options) {
|
|
7720
7826
|
if (_flushTimer !== null) {
|
|
7721
7827
|
clearInterval(_flushTimer);
|
|
@@ -7744,14 +7850,17 @@ async function initStore(options) {
|
|
|
7744
7850
|
dbPath,
|
|
7745
7851
|
encryptionKey: hexKey
|
|
7746
7852
|
});
|
|
7747
|
-
await ensureSchema();
|
|
7853
|
+
await retryOnBusy2(() => ensureSchema(), "ensureSchema");
|
|
7748
7854
|
try {
|
|
7749
7855
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
7750
7856
|
initShardManager2(hexKey);
|
|
7751
7857
|
} catch {
|
|
7752
7858
|
}
|
|
7753
7859
|
const client = getClient();
|
|
7754
|
-
const vResult = await
|
|
7860
|
+
const vResult = await retryOnBusy2(
|
|
7861
|
+
() => client.execute("SELECT MAX(version) as max_v FROM memories"),
|
|
7862
|
+
"version-query"
|
|
7863
|
+
);
|
|
7755
7864
|
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
7756
7865
|
}
|
|
7757
7866
|
function classifyTier(record) {
|
|
@@ -7794,6 +7903,12 @@ async function writeMemory(record) {
|
|
|
7794
7903
|
supersedes_id: record.supersedes_id ?? null
|
|
7795
7904
|
};
|
|
7796
7905
|
_pendingRecords.push(dbRow);
|
|
7906
|
+
const MAX_PENDING = 1e3;
|
|
7907
|
+
if (_pendingRecords.length > MAX_PENDING) {
|
|
7908
|
+
const dropped = _pendingRecords.length - MAX_PENDING;
|
|
7909
|
+
_pendingRecords = _pendingRecords.slice(-MAX_PENDING);
|
|
7910
|
+
console.warn(`[store] Dropped ${dropped} oldest pending records (overflow)`);
|
|
7911
|
+
}
|
|
7797
7912
|
if (_flushTimer === null) {
|
|
7798
7913
|
_flushTimer = setInterval(() => {
|
|
7799
7914
|
void flushBatch();
|
|
@@ -8125,7 +8240,7 @@ async function getMemoryCardinality(agentId) {
|
|
|
8125
8240
|
return 0;
|
|
8126
8241
|
}
|
|
8127
8242
|
}
|
|
8128
|
-
var _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
8243
|
+
var INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
8129
8244
|
var init_store = __esm({
|
|
8130
8245
|
"src/lib/store.ts"() {
|
|
8131
8246
|
"use strict";
|
|
@@ -8133,6 +8248,8 @@ var init_store = __esm({
|
|
|
8133
8248
|
init_database();
|
|
8134
8249
|
init_keychain();
|
|
8135
8250
|
init_config();
|
|
8251
|
+
INIT_MAX_RETRIES = 3;
|
|
8252
|
+
INIT_RETRY_DELAY_MS = 1e3;
|
|
8136
8253
|
_pendingRecords = [];
|
|
8137
8254
|
_batchSize = 20;
|
|
8138
8255
|
_flushIntervalMs = 1e4;
|
|
@@ -12137,8 +12254,8 @@ function Text({ color, backgroundColor, dimColor = false, bold = false, italic =
|
|
|
12137
12254
|
}
|
|
12138
12255
|
|
|
12139
12256
|
// src/tui/ink/components/ErrorOverview.js
|
|
12140
|
-
var cleanupPath = (
|
|
12141
|
-
return
|
|
12257
|
+
var cleanupPath = (path24) => {
|
|
12258
|
+
return path24?.replace(`file://${cwd()}/`, "");
|
|
12142
12259
|
};
|
|
12143
12260
|
var stackUtils = new StackUtils({
|
|
12144
12261
|
cwd: cwd(),
|
|
@@ -14146,6 +14263,8 @@ function Footer() {
|
|
|
14146
14263
|
// src/tui/views/CommandCenter.tsx
|
|
14147
14264
|
import { useState as useState6, useEffect as useEffect8, useMemo as useMemo4, useCallback as useCallback4, useRef as useRef4 } from "react";
|
|
14148
14265
|
import TextInput from "ink-text-input";
|
|
14266
|
+
import path11 from "path";
|
|
14267
|
+
import { homedir } from "os";
|
|
14149
14268
|
|
|
14150
14269
|
// src/tui/components/StatusDot.tsx
|
|
14151
14270
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
@@ -14168,7 +14287,7 @@ function StatusDot({ status, showLabel = true }) {
|
|
|
14168
14287
|
|
|
14169
14288
|
// src/tui/demo-data.ts
|
|
14170
14289
|
var DEMO_EMPLOYEES = [
|
|
14171
|
-
{ name: "exe", role: "COO", status: "active", activity: "Reviewing yoshi's task-aware behavior injection PR", memoryCount:
|
|
14290
|
+
{ name: "exe", role: "COO", status: "active", activity: "Reviewing yoshi's task-aware behavior injection PR", memoryCount: 15e3, projects: [
|
|
14172
14291
|
{ name: "exe-os", status: "active" },
|
|
14173
14292
|
{ name: "exe-create", status: "has_tasks" },
|
|
14174
14293
|
{ name: "openclaw", status: "idle" }
|
|
@@ -14177,7 +14296,7 @@ var DEMO_EMPLOYEES = [
|
|
|
14177
14296
|
"Dispatched behavior injection task",
|
|
14178
14297
|
"Approved gateway Phase 4"
|
|
14179
14298
|
] },
|
|
14180
|
-
{ name: "yoshi", role: "CTO", status: "active", activity: "Implementing skill learning trajectory capture", memoryCount:
|
|
14299
|
+
{ name: "yoshi", role: "CTO", status: "active", activity: "Implementing skill learning trajectory capture", memoryCount: 8e3, projects: [
|
|
14181
14300
|
{ name: "exe-os", status: "active" },
|
|
14182
14301
|
{ name: "exe-create", status: "idle" }
|
|
14183
14302
|
], recentTasks: [
|
|
@@ -14185,7 +14304,7 @@ var DEMO_EMPLOYEES = [
|
|
|
14185
14304
|
"Fixed TUI mouse listener leak",
|
|
14186
14305
|
"Built task-aware behavior injection"
|
|
14187
14306
|
] },
|
|
14188
|
-
{ name: "mari", role: "CMO", status: "idle", activity: "", memoryCount:
|
|
14307
|
+
{ name: "mari", role: "CMO", status: "idle", activity: "", memoryCount: 2e3, projects: [
|
|
14189
14308
|
{ name: "exe-build-skills", status: "has_tasks" },
|
|
14190
14309
|
{ name: "exe-os", status: "idle" }
|
|
14191
14310
|
], recentTasks: [
|
|
@@ -14193,13 +14312,13 @@ var DEMO_EMPLOYEES = [
|
|
|
14193
14312
|
"Designed exe-os UI system",
|
|
14194
14313
|
"Fixed logo layouts"
|
|
14195
14314
|
] },
|
|
14196
|
-
{ name: "tom", role: "Principal Engineer", status: "idle", activity: "", memoryCount:
|
|
14315
|
+
{ name: "tom", role: "Principal Engineer", status: "idle", activity: "", memoryCount: 700, projects: [
|
|
14197
14316
|
{ name: "exe-os", status: "idle" }
|
|
14198
14317
|
], recentTasks: [
|
|
14199
14318
|
"Implemented BashTool sandboxed execution",
|
|
14200
14319
|
"Ported session scoping to exe-agent-memory"
|
|
14201
14320
|
] },
|
|
14202
|
-
{ name: "sasha", role: "Content Production", status: "offline", activity: "", memoryCount:
|
|
14321
|
+
{ name: "sasha", role: "Content Production", status: "offline", activity: "", memoryCount: 50, projects: [
|
|
14203
14322
|
{ name: "exe-build-skills", status: "idle" }
|
|
14204
14323
|
], recentTasks: [
|
|
14205
14324
|
"Rendered carousel export prototype"
|
|
@@ -14212,7 +14331,7 @@ var DEMO_ACTIVITY = [
|
|
|
14212
14331
|
{ time: "11:15", agent: "mari", action: "Completed exe-os UI design system" },
|
|
14213
14332
|
{ time: "10:50", agent: "exe", action: "Approved gateway Phase 4" }
|
|
14214
14333
|
];
|
|
14215
|
-
var DEMO_HEALTH = { memories:
|
|
14334
|
+
var DEMO_HEALTH = { memories: 25750, daemon: "running", cloud: "disabled" };
|
|
14216
14335
|
var DEMO_PROJECTS = [
|
|
14217
14336
|
{
|
|
14218
14337
|
projectName: "exe-os",
|
|
@@ -14790,8 +14909,8 @@ function CommandCenterView({
|
|
|
14790
14909
|
const { createDefaultHooks: createDefaultHooks2 } = await Promise.resolve().then(() => (init_hooks(), hooks_exports));
|
|
14791
14910
|
const { readFileSync: readFileSync11, existsSync: existsSync14 } = await import("fs");
|
|
14792
14911
|
const { join } = await import("path");
|
|
14793
|
-
const { homedir } = await import("os");
|
|
14794
|
-
const configPath = join(
|
|
14912
|
+
const { homedir: homedir3 } = await import("os");
|
|
14913
|
+
const configPath = join(homedir3(), ".exe-os", "config.json");
|
|
14795
14914
|
let failoverChain = ["anthropic", "opencode", "gemini", "openai"];
|
|
14796
14915
|
let providerConfigs = {};
|
|
14797
14916
|
if (existsSync14(configPath)) {
|
|
@@ -14854,7 +14973,7 @@ function CommandCenterView({
|
|
|
14854
14973
|
registry.register(BashTool2);
|
|
14855
14974
|
let agentRole = "CTO";
|
|
14856
14975
|
try {
|
|
14857
|
-
const markerDir = join(
|
|
14976
|
+
const markerDir = join(homedir3(), ".exe-os", "session-cache");
|
|
14858
14977
|
const agentFiles = (await import("fs")).readdirSync(markerDir).filter((f) => f.startsWith("active-agent-"));
|
|
14859
14978
|
for (const f of agentFiles) {
|
|
14860
14979
|
const data = JSON.parse(readFileSync11(join(markerDir, f), "utf8"));
|
|
@@ -14994,10 +15113,10 @@ function CommandCenterView({
|
|
|
14994
15113
|
const demoEntries = DEMO_PROJECTS.map((p) => ({
|
|
14995
15114
|
projectName: p.projectName,
|
|
14996
15115
|
exeSession: p.exeSession,
|
|
14997
|
-
projectDir:
|
|
15116
|
+
projectDir: path11.join(homedir(), p.projectName),
|
|
14998
15117
|
employeeCount: p.employees.length,
|
|
14999
15118
|
activeCount: p.employees.filter((e) => e.status === "active").length,
|
|
15000
|
-
memoryCount: p.
|
|
15119
|
+
memoryCount: p.employees.length * 4e3,
|
|
15001
15120
|
status: p.employees.some((e) => e.status === "active") ? "active" : "idle",
|
|
15002
15121
|
type: p.projectName.startsWith("exe-") ? "code" : "automation",
|
|
15003
15122
|
recentTasks: DEMO_RECENT_TASKS[p.projectName] ?? []
|
|
@@ -15395,6 +15514,8 @@ function ChatMessageRow({ msg }) {
|
|
|
15395
15514
|
|
|
15396
15515
|
// src/tui/views/Sessions.tsx
|
|
15397
15516
|
import { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
|
|
15517
|
+
import path21 from "path";
|
|
15518
|
+
import { homedir as homedir2 } from "os";
|
|
15398
15519
|
|
|
15399
15520
|
// src/tui/components/TmuxPane.tsx
|
|
15400
15521
|
import { useState as useState7, useEffect as useEffect9 } from "react";
|
|
@@ -15673,7 +15794,7 @@ function SessionsView({
|
|
|
15673
15794
|
if (demo) {
|
|
15674
15795
|
setProjects(DEMO_PROJECTS.map((p) => ({
|
|
15675
15796
|
...p,
|
|
15676
|
-
projectDir:
|
|
15797
|
+
projectDir: path21.join(homedir2(), p.projectName),
|
|
15677
15798
|
employees: p.employees.map((e) => ({ ...e, attached: e.status === "active" }))
|
|
15678
15799
|
})));
|
|
15679
15800
|
return;
|