@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
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
-
}) : x)(function(x) {
|
|
6
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
-
});
|
|
9
3
|
var __esm = (fn, res) => function __init() {
|
|
10
4
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
5
|
};
|
|
@@ -15,7 +9,7 @@ var __export = (target, all) => {
|
|
|
15
9
|
};
|
|
16
10
|
|
|
17
11
|
// src/lib/config.ts
|
|
18
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
12
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
19
13
|
import { readFileSync, existsSync, renameSync } from "fs";
|
|
20
14
|
import path from "path";
|
|
21
15
|
import os from "os";
|
|
@@ -314,6 +308,7 @@ async function ensureSchema() {
|
|
|
314
308
|
const client = getRawClient();
|
|
315
309
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
316
310
|
await client.execute("PRAGMA busy_timeout = 30000");
|
|
311
|
+
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
317
312
|
try {
|
|
318
313
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
319
314
|
} catch {
|
|
@@ -1122,12 +1117,13 @@ var init_database = __esm({
|
|
|
1122
1117
|
});
|
|
1123
1118
|
|
|
1124
1119
|
// src/lib/keychain.ts
|
|
1125
|
-
import { readFile as readFile2, writeFile as writeFile2, unlink, mkdir as mkdir2, chmod } from "fs/promises";
|
|
1120
|
+
import { readFile as readFile2, writeFile as writeFile2, unlink, mkdir as mkdir2, chmod as chmod2 } from "fs/promises";
|
|
1126
1121
|
import { existsSync as existsSync2 } from "fs";
|
|
1127
1122
|
import path3 from "path";
|
|
1123
|
+
import os2 from "os";
|
|
1128
1124
|
import crypto from "crypto";
|
|
1129
1125
|
function getKeyDir() {
|
|
1130
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path3.join(
|
|
1126
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path3.join(os2.homedir(), ".exe-os");
|
|
1131
1127
|
}
|
|
1132
1128
|
function getKeyPath() {
|
|
1133
1129
|
return path3.join(getKeyDir(), "master.key");
|
|
@@ -1184,7 +1180,7 @@ __export(shard_manager_exports, {
|
|
|
1184
1180
|
shardExists: () => shardExists
|
|
1185
1181
|
});
|
|
1186
1182
|
import path4 from "path";
|
|
1187
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
1183
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync as readdirSync2 } from "fs";
|
|
1188
1184
|
import { createClient as createClient2 } from "@libsql/client";
|
|
1189
1185
|
function initShardManager(encryptionKey) {
|
|
1190
1186
|
_encryptionKey = encryptionKey;
|
|
@@ -1223,7 +1219,6 @@ function shardExists(projectName) {
|
|
|
1223
1219
|
}
|
|
1224
1220
|
function listShards() {
|
|
1225
1221
|
if (!existsSync3(SHARDS_DIR)) return [];
|
|
1226
|
-
const { readdirSync: readdirSync2 } = __require("fs");
|
|
1227
1222
|
return readdirSync2(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
1228
1223
|
}
|
|
1229
1224
|
async function ensureShardSchema(client) {
|
|
@@ -1429,6 +1424,28 @@ __export(store_exports, {
|
|
|
1429
1424
|
vectorToBlob: () => vectorToBlob,
|
|
1430
1425
|
writeMemory: () => writeMemory
|
|
1431
1426
|
});
|
|
1427
|
+
function isBusyError2(err) {
|
|
1428
|
+
if (err instanceof Error) {
|
|
1429
|
+
const msg = err.message.toLowerCase();
|
|
1430
|
+
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
1431
|
+
}
|
|
1432
|
+
return false;
|
|
1433
|
+
}
|
|
1434
|
+
async function retryOnBusy2(fn, label) {
|
|
1435
|
+
for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
|
|
1436
|
+
try {
|
|
1437
|
+
return await fn();
|
|
1438
|
+
} catch (err) {
|
|
1439
|
+
if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
|
|
1440
|
+
process.stderr.write(
|
|
1441
|
+
`[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
|
|
1442
|
+
`
|
|
1443
|
+
);
|
|
1444
|
+
await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
throw new Error("unreachable");
|
|
1448
|
+
}
|
|
1432
1449
|
async function initStore(options) {
|
|
1433
1450
|
if (_flushTimer !== null) {
|
|
1434
1451
|
clearInterval(_flushTimer);
|
|
@@ -1457,14 +1474,17 @@ async function initStore(options) {
|
|
|
1457
1474
|
dbPath,
|
|
1458
1475
|
encryptionKey: hexKey
|
|
1459
1476
|
});
|
|
1460
|
-
await ensureSchema();
|
|
1477
|
+
await retryOnBusy2(() => ensureSchema(), "ensureSchema");
|
|
1461
1478
|
try {
|
|
1462
1479
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
1463
1480
|
initShardManager2(hexKey);
|
|
1464
1481
|
} catch {
|
|
1465
1482
|
}
|
|
1466
1483
|
const client = getClient();
|
|
1467
|
-
const vResult = await
|
|
1484
|
+
const vResult = await retryOnBusy2(
|
|
1485
|
+
() => client.execute("SELECT MAX(version) as max_v FROM memories"),
|
|
1486
|
+
"version-query"
|
|
1487
|
+
);
|
|
1468
1488
|
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
1469
1489
|
}
|
|
1470
1490
|
function classifyTier(record) {
|
|
@@ -1507,6 +1527,12 @@ async function writeMemory(record) {
|
|
|
1507
1527
|
supersedes_id: record.supersedes_id ?? null
|
|
1508
1528
|
};
|
|
1509
1529
|
_pendingRecords.push(dbRow);
|
|
1530
|
+
const MAX_PENDING = 1e3;
|
|
1531
|
+
if (_pendingRecords.length > MAX_PENDING) {
|
|
1532
|
+
const dropped = _pendingRecords.length - MAX_PENDING;
|
|
1533
|
+
_pendingRecords = _pendingRecords.slice(-MAX_PENDING);
|
|
1534
|
+
console.warn(`[store] Dropped ${dropped} oldest pending records (overflow)`);
|
|
1535
|
+
}
|
|
1510
1536
|
if (_flushTimer === null) {
|
|
1511
1537
|
_flushTimer = setInterval(() => {
|
|
1512
1538
|
void flushBatch();
|
|
@@ -1838,7 +1864,7 @@ async function getMemoryCardinality(agentId) {
|
|
|
1838
1864
|
return 0;
|
|
1839
1865
|
}
|
|
1840
1866
|
}
|
|
1841
|
-
var _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
1867
|
+
var INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
1842
1868
|
var init_store = __esm({
|
|
1843
1869
|
"src/lib/store.ts"() {
|
|
1844
1870
|
"use strict";
|
|
@@ -1846,6 +1872,8 @@ var init_store = __esm({
|
|
|
1846
1872
|
init_database();
|
|
1847
1873
|
init_keychain();
|
|
1848
1874
|
init_config();
|
|
1875
|
+
INIT_MAX_RETRIES = 3;
|
|
1876
|
+
INIT_RETRY_DELAY_MS = 1e3;
|
|
1849
1877
|
_pendingRecords = [];
|
|
1850
1878
|
_batchSize = 20;
|
|
1851
1879
|
_flushIntervalMs = 1e4;
|
|
@@ -1953,10 +1981,11 @@ var timeout = setTimeout(() => {
|
|
|
1953
1981
|
process.exit(0);
|
|
1954
1982
|
}, 5e3);
|
|
1955
1983
|
timeout.unref();
|
|
1984
|
+
var MAX_INPUT_SIZE = 1e6;
|
|
1956
1985
|
var input = "";
|
|
1957
1986
|
process.stdin.setEncoding("utf8");
|
|
1958
1987
|
process.stdin.on("data", (chunk) => {
|
|
1959
|
-
input += chunk;
|
|
1988
|
+
if (input.length < MAX_INPUT_SIZE) input += chunk;
|
|
1960
1989
|
});
|
|
1961
1990
|
process.stdin.on("end", async () => {
|
|
1962
1991
|
try {
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
-
}) : x)(function(x) {
|
|
6
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
-
});
|
|
9
3
|
var __esm = (fn, res) => function __init() {
|
|
10
4
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
5
|
};
|
|
@@ -15,7 +9,7 @@ var __export = (target, all) => {
|
|
|
15
9
|
};
|
|
16
10
|
|
|
17
11
|
// src/lib/config.ts
|
|
18
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
12
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
19
13
|
import { readFileSync, existsSync, renameSync } from "fs";
|
|
20
14
|
import path from "path";
|
|
21
15
|
import os from "os";
|
|
@@ -314,6 +308,7 @@ async function ensureSchema() {
|
|
|
314
308
|
const client = getRawClient();
|
|
315
309
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
316
310
|
await client.execute("PRAGMA busy_timeout = 30000");
|
|
311
|
+
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
317
312
|
try {
|
|
318
313
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
319
314
|
} catch {
|
|
@@ -1122,12 +1117,13 @@ var init_database = __esm({
|
|
|
1122
1117
|
});
|
|
1123
1118
|
|
|
1124
1119
|
// src/lib/keychain.ts
|
|
1125
|
-
import { readFile as readFile2, writeFile as writeFile2, unlink, mkdir as mkdir2, chmod } from "fs/promises";
|
|
1120
|
+
import { readFile as readFile2, writeFile as writeFile2, unlink, mkdir as mkdir2, chmod as chmod2 } from "fs/promises";
|
|
1126
1121
|
import { existsSync as existsSync2 } from "fs";
|
|
1127
1122
|
import path3 from "path";
|
|
1123
|
+
import os2 from "os";
|
|
1128
1124
|
import crypto from "crypto";
|
|
1129
1125
|
function getKeyDir() {
|
|
1130
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path3.join(
|
|
1126
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path3.join(os2.homedir(), ".exe-os");
|
|
1131
1127
|
}
|
|
1132
1128
|
function getKeyPath() {
|
|
1133
1129
|
return path3.join(getKeyDir(), "master.key");
|
|
@@ -1184,7 +1180,7 @@ __export(shard_manager_exports, {
|
|
|
1184
1180
|
shardExists: () => shardExists
|
|
1185
1181
|
});
|
|
1186
1182
|
import path4 from "path";
|
|
1187
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
1183
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync as readdirSync2 } from "fs";
|
|
1188
1184
|
import { createClient as createClient2 } from "@libsql/client";
|
|
1189
1185
|
function initShardManager(encryptionKey) {
|
|
1190
1186
|
_encryptionKey = encryptionKey;
|
|
@@ -1223,7 +1219,6 @@ function shardExists(projectName) {
|
|
|
1223
1219
|
}
|
|
1224
1220
|
function listShards() {
|
|
1225
1221
|
if (!existsSync3(SHARDS_DIR)) return [];
|
|
1226
|
-
const { readdirSync: readdirSync2 } = __require("fs");
|
|
1227
1222
|
return readdirSync2(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
1228
1223
|
}
|
|
1229
1224
|
async function ensureShardSchema(client) {
|
|
@@ -1429,6 +1424,28 @@ __export(store_exports, {
|
|
|
1429
1424
|
vectorToBlob: () => vectorToBlob,
|
|
1430
1425
|
writeMemory: () => writeMemory
|
|
1431
1426
|
});
|
|
1427
|
+
function isBusyError2(err) {
|
|
1428
|
+
if (err instanceof Error) {
|
|
1429
|
+
const msg = err.message.toLowerCase();
|
|
1430
|
+
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
1431
|
+
}
|
|
1432
|
+
return false;
|
|
1433
|
+
}
|
|
1434
|
+
async function retryOnBusy2(fn, label) {
|
|
1435
|
+
for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
|
|
1436
|
+
try {
|
|
1437
|
+
return await fn();
|
|
1438
|
+
} catch (err) {
|
|
1439
|
+
if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
|
|
1440
|
+
process.stderr.write(
|
|
1441
|
+
`[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
|
|
1442
|
+
`
|
|
1443
|
+
);
|
|
1444
|
+
await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
throw new Error("unreachable");
|
|
1448
|
+
}
|
|
1432
1449
|
async function initStore(options) {
|
|
1433
1450
|
if (_flushTimer !== null) {
|
|
1434
1451
|
clearInterval(_flushTimer);
|
|
@@ -1457,14 +1474,17 @@ async function initStore(options) {
|
|
|
1457
1474
|
dbPath,
|
|
1458
1475
|
encryptionKey: hexKey
|
|
1459
1476
|
});
|
|
1460
|
-
await ensureSchema();
|
|
1477
|
+
await retryOnBusy2(() => ensureSchema(), "ensureSchema");
|
|
1461
1478
|
try {
|
|
1462
1479
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
1463
1480
|
initShardManager2(hexKey);
|
|
1464
1481
|
} catch {
|
|
1465
1482
|
}
|
|
1466
1483
|
const client = getClient();
|
|
1467
|
-
const vResult = await
|
|
1484
|
+
const vResult = await retryOnBusy2(
|
|
1485
|
+
() => client.execute("SELECT MAX(version) as max_v FROM memories"),
|
|
1486
|
+
"version-query"
|
|
1487
|
+
);
|
|
1468
1488
|
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
1469
1489
|
}
|
|
1470
1490
|
function classifyTier(record) {
|
|
@@ -1507,6 +1527,12 @@ async function writeMemory(record) {
|
|
|
1507
1527
|
supersedes_id: record.supersedes_id ?? null
|
|
1508
1528
|
};
|
|
1509
1529
|
_pendingRecords.push(dbRow);
|
|
1530
|
+
const MAX_PENDING = 1e3;
|
|
1531
|
+
if (_pendingRecords.length > MAX_PENDING) {
|
|
1532
|
+
const dropped = _pendingRecords.length - MAX_PENDING;
|
|
1533
|
+
_pendingRecords = _pendingRecords.slice(-MAX_PENDING);
|
|
1534
|
+
console.warn(`[store] Dropped ${dropped} oldest pending records (overflow)`);
|
|
1535
|
+
}
|
|
1510
1536
|
if (_flushTimer === null) {
|
|
1511
1537
|
_flushTimer = setInterval(() => {
|
|
1512
1538
|
void flushBatch();
|
|
@@ -1838,7 +1864,7 @@ async function getMemoryCardinality(agentId) {
|
|
|
1838
1864
|
return 0;
|
|
1839
1865
|
}
|
|
1840
1866
|
}
|
|
1841
|
-
var _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
1867
|
+
var INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
1842
1868
|
var init_store = __esm({
|
|
1843
1869
|
"src/lib/store.ts"() {
|
|
1844
1870
|
"use strict";
|
|
@@ -1846,6 +1872,8 @@ var init_store = __esm({
|
|
|
1846
1872
|
init_database();
|
|
1847
1873
|
init_keychain();
|
|
1848
1874
|
init_config();
|
|
1875
|
+
INIT_MAX_RETRIES = 3;
|
|
1876
|
+
INIT_RETRY_DELAY_MS = 1e3;
|
|
1849
1877
|
_pendingRecords = [];
|
|
1850
1878
|
_batchSize = 20;
|
|
1851
1879
|
_flushIntervalMs = 1e4;
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
-
}) : x)(function(x) {
|
|
6
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
-
});
|
|
9
3
|
var __esm = (fn, res) => function __init() {
|
|
10
4
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
5
|
};
|
|
@@ -15,7 +9,7 @@ var __export = (target, all) => {
|
|
|
15
9
|
};
|
|
16
10
|
|
|
17
11
|
// src/lib/config.ts
|
|
18
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
12
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
19
13
|
import { readFileSync, existsSync, renameSync } from "fs";
|
|
20
14
|
import path from "path";
|
|
21
15
|
import os from "os";
|
|
@@ -305,6 +299,7 @@ async function ensureSchema() {
|
|
|
305
299
|
const client = getRawClient();
|
|
306
300
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
307
301
|
await client.execute("PRAGMA busy_timeout = 30000");
|
|
302
|
+
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
308
303
|
try {
|
|
309
304
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
310
305
|
} catch {
|
|
@@ -1199,15 +1194,20 @@ function addEmployee(employees, employee) {
|
|
|
1199
1194
|
}
|
|
1200
1195
|
return [...employees, normalized];
|
|
1201
1196
|
}
|
|
1197
|
+
function findExeBin() {
|
|
1198
|
+
try {
|
|
1199
|
+
return execSync3(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
|
|
1200
|
+
} catch {
|
|
1201
|
+
return null;
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1202
1204
|
function registerBinSymlinks(name) {
|
|
1203
1205
|
const created = [];
|
|
1204
1206
|
const skipped = [];
|
|
1205
1207
|
const errors = [];
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
} catch {
|
|
1210
|
-
errors.push("Could not find 'exe' in PATH");
|
|
1208
|
+
const exeBinPath = findExeBin();
|
|
1209
|
+
if (!exeBinPath) {
|
|
1210
|
+
errors.push("Could not find 'exe-os' in PATH");
|
|
1211
1211
|
return { created, skipped, errors };
|
|
1212
1212
|
}
|
|
1213
1213
|
const binDir = path3.dirname(exeBinPath);
|
|
@@ -1426,12 +1426,13 @@ var init_memory = __esm({
|
|
|
1426
1426
|
});
|
|
1427
1427
|
|
|
1428
1428
|
// src/lib/keychain.ts
|
|
1429
|
-
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod } from "fs/promises";
|
|
1429
|
+
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
1430
1430
|
import { existsSync as existsSync4 } from "fs";
|
|
1431
1431
|
import path5 from "path";
|
|
1432
|
+
import os3 from "os";
|
|
1432
1433
|
import crypto from "crypto";
|
|
1433
1434
|
function getKeyDir() {
|
|
1434
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path5.join(
|
|
1435
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path5.join(os3.homedir(), ".exe-os");
|
|
1435
1436
|
}
|
|
1436
1437
|
function getKeyPath() {
|
|
1437
1438
|
return path5.join(getKeyDir(), "master.key");
|
|
@@ -1488,7 +1489,7 @@ __export(shard_manager_exports, {
|
|
|
1488
1489
|
shardExists: () => shardExists
|
|
1489
1490
|
});
|
|
1490
1491
|
import path6 from "path";
|
|
1491
|
-
import { existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
|
|
1492
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync2, readdirSync as readdirSync2 } from "fs";
|
|
1492
1493
|
import { createClient as createClient2 } from "@libsql/client";
|
|
1493
1494
|
function initShardManager(encryptionKey) {
|
|
1494
1495
|
_encryptionKey = encryptionKey;
|
|
@@ -1527,7 +1528,6 @@ function shardExists(projectName) {
|
|
|
1527
1528
|
}
|
|
1528
1529
|
function listShards() {
|
|
1529
1530
|
if (!existsSync5(SHARDS_DIR)) return [];
|
|
1530
|
-
const { readdirSync: readdirSync2 } = __require("fs");
|
|
1531
1531
|
return readdirSync2(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
1532
1532
|
}
|
|
1533
1533
|
async function ensureShardSchema(client) {
|
|
@@ -1733,6 +1733,28 @@ __export(store_exports, {
|
|
|
1733
1733
|
vectorToBlob: () => vectorToBlob,
|
|
1734
1734
|
writeMemory: () => writeMemory
|
|
1735
1735
|
});
|
|
1736
|
+
function isBusyError2(err) {
|
|
1737
|
+
if (err instanceof Error) {
|
|
1738
|
+
const msg = err.message.toLowerCase();
|
|
1739
|
+
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
1740
|
+
}
|
|
1741
|
+
return false;
|
|
1742
|
+
}
|
|
1743
|
+
async function retryOnBusy2(fn, label) {
|
|
1744
|
+
for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
|
|
1745
|
+
try {
|
|
1746
|
+
return await fn();
|
|
1747
|
+
} catch (err) {
|
|
1748
|
+
if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
|
|
1749
|
+
process.stderr.write(
|
|
1750
|
+
`[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
|
|
1751
|
+
`
|
|
1752
|
+
);
|
|
1753
|
+
await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
throw new Error("unreachable");
|
|
1757
|
+
}
|
|
1736
1758
|
async function initStore(options) {
|
|
1737
1759
|
if (_flushTimer !== null) {
|
|
1738
1760
|
clearInterval(_flushTimer);
|
|
@@ -1761,14 +1783,17 @@ async function initStore(options) {
|
|
|
1761
1783
|
dbPath,
|
|
1762
1784
|
encryptionKey: hexKey
|
|
1763
1785
|
});
|
|
1764
|
-
await ensureSchema();
|
|
1786
|
+
await retryOnBusy2(() => ensureSchema(), "ensureSchema");
|
|
1765
1787
|
try {
|
|
1766
1788
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
1767
1789
|
initShardManager2(hexKey);
|
|
1768
1790
|
} catch {
|
|
1769
1791
|
}
|
|
1770
1792
|
const client = getClient();
|
|
1771
|
-
const vResult = await
|
|
1793
|
+
const vResult = await retryOnBusy2(
|
|
1794
|
+
() => client.execute("SELECT MAX(version) as max_v FROM memories"),
|
|
1795
|
+
"version-query"
|
|
1796
|
+
);
|
|
1772
1797
|
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
1773
1798
|
}
|
|
1774
1799
|
function classifyTier(record) {
|
|
@@ -1811,6 +1836,12 @@ async function writeMemory(record) {
|
|
|
1811
1836
|
supersedes_id: record.supersedes_id ?? null
|
|
1812
1837
|
};
|
|
1813
1838
|
_pendingRecords.push(dbRow);
|
|
1839
|
+
const MAX_PENDING = 1e3;
|
|
1840
|
+
if (_pendingRecords.length > MAX_PENDING) {
|
|
1841
|
+
const dropped = _pendingRecords.length - MAX_PENDING;
|
|
1842
|
+
_pendingRecords = _pendingRecords.slice(-MAX_PENDING);
|
|
1843
|
+
console.warn(`[store] Dropped ${dropped} oldest pending records (overflow)`);
|
|
1844
|
+
}
|
|
1814
1845
|
if (_flushTimer === null) {
|
|
1815
1846
|
_flushTimer = setInterval(() => {
|
|
1816
1847
|
void flushBatch();
|
|
@@ -2142,7 +2173,7 @@ async function getMemoryCardinality(agentId) {
|
|
|
2142
2173
|
return 0;
|
|
2143
2174
|
}
|
|
2144
2175
|
}
|
|
2145
|
-
var _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
2176
|
+
var INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
2146
2177
|
var init_store = __esm({
|
|
2147
2178
|
"src/lib/store.ts"() {
|
|
2148
2179
|
"use strict";
|
|
@@ -2150,6 +2181,8 @@ var init_store = __esm({
|
|
|
2150
2181
|
init_database();
|
|
2151
2182
|
init_keychain();
|
|
2152
2183
|
init_config();
|
|
2184
|
+
INIT_MAX_RETRIES = 3;
|
|
2185
|
+
INIT_RETRY_DELAY_MS = 1e3;
|
|
2153
2186
|
_pendingRecords = [];
|
|
2154
2187
|
_batchSize = 20;
|
|
2155
2188
|
_flushIntervalMs = 1e4;
|
|
@@ -2421,16 +2454,20 @@ function countTomSessions() {
|
|
|
2421
2454
|
return 0;
|
|
2422
2455
|
}
|
|
2423
2456
|
}
|
|
2457
|
+
var MAX_INPUT_SIZE = 1e6;
|
|
2424
2458
|
var input = "";
|
|
2425
2459
|
process.stdin.setEncoding("utf8");
|
|
2426
2460
|
process.stdin.on("data", (chunk) => {
|
|
2427
|
-
input += chunk;
|
|
2461
|
+
if (input.length < MAX_INPUT_SIZE) input += chunk;
|
|
2428
2462
|
});
|
|
2429
2463
|
process.stdin.on("end", async () => {
|
|
2430
2464
|
try {
|
|
2465
|
+
if (input.length >= MAX_INPUT_SIZE) {
|
|
2466
|
+
process.exit(0);
|
|
2467
|
+
}
|
|
2431
2468
|
const data = JSON.parse(input);
|
|
2432
2469
|
const agent = getActiveAgent();
|
|
2433
|
-
if (/^(Write|Edit)$/.test(data.tool_name) && agent.
|
|
2470
|
+
if (/^(Write|Edit)$/.test(data.tool_name) && agent.agentRole !== "COO" && agent.agentId !== "default") {
|
|
2434
2471
|
const filePath = data.tool_input?.file_path ?? "";
|
|
2435
2472
|
const exeMatch = filePath.match(/exe\/([^/]+)\//);
|
|
2436
2473
|
if (exeMatch && exeMatch[1] !== agent.agentId && exeMatch[1] !== "output") {
|
|
@@ -2484,7 +2521,7 @@ This write was prevented. Do NOT retry.`
|
|
|
2484
2521
|
if (/^(Write|Edit|Read)$/.test(data.tool_name)) {
|
|
2485
2522
|
const filePath = data.tool_input?.file_path ?? "";
|
|
2486
2523
|
const sensitivePatterns = /\/(\.env\.local|\.env\.production|id_rsa|id_ed25519|credentials\.json|\.ssh\/config)$/;
|
|
2487
|
-
if (sensitivePatterns.test(filePath) && agent.
|
|
2524
|
+
if (sensitivePatterns.test(filePath) && agent.agentRole !== "COO") {
|
|
2488
2525
|
const output = JSON.stringify({
|
|
2489
2526
|
hookSpecificOutput: {
|
|
2490
2527
|
permissionDecision: "ask"
|