@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
|
@@ -266,12 +266,68 @@ var init_memory = __esm({
|
|
|
266
266
|
}
|
|
267
267
|
});
|
|
268
268
|
|
|
269
|
+
// src/lib/db-retry.ts
|
|
270
|
+
function isBusyError(err) {
|
|
271
|
+
if (err instanceof Error) {
|
|
272
|
+
const msg = err.message.toLowerCase();
|
|
273
|
+
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
274
|
+
}
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
function delay(ms) {
|
|
278
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
279
|
+
}
|
|
280
|
+
async function retryOnBusy(fn, label) {
|
|
281
|
+
let lastError;
|
|
282
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
283
|
+
try {
|
|
284
|
+
return await fn();
|
|
285
|
+
} catch (err) {
|
|
286
|
+
lastError = err;
|
|
287
|
+
if (!isBusyError(err) || attempt === MAX_RETRIES) {
|
|
288
|
+
throw err;
|
|
289
|
+
}
|
|
290
|
+
const backoff = BASE_DELAY_MS * Math.pow(2, attempt);
|
|
291
|
+
const jitter = Math.floor(Math.random() * MAX_JITTER_MS);
|
|
292
|
+
process.stderr.write(
|
|
293
|
+
`[exe-os] SQLITE_BUSY ${label} retry ${attempt + 1}/${MAX_RETRIES} \u2014 waiting ${backoff + jitter}ms
|
|
294
|
+
`
|
|
295
|
+
);
|
|
296
|
+
await delay(backoff + jitter);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
throw lastError;
|
|
300
|
+
}
|
|
301
|
+
function wrapWithRetry(client) {
|
|
302
|
+
return new Proxy(client, {
|
|
303
|
+
get(target, prop, receiver) {
|
|
304
|
+
if (prop === "execute") {
|
|
305
|
+
return (sql) => retryOnBusy(() => target.execute(sql), "execute");
|
|
306
|
+
}
|
|
307
|
+
if (prop === "batch") {
|
|
308
|
+
return (stmts) => retryOnBusy(() => target.batch(stmts), "batch");
|
|
309
|
+
}
|
|
310
|
+
return Reflect.get(target, prop, receiver);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
var MAX_RETRIES, BASE_DELAY_MS, MAX_JITTER_MS;
|
|
315
|
+
var init_db_retry = __esm({
|
|
316
|
+
"src/lib/db-retry.ts"() {
|
|
317
|
+
"use strict";
|
|
318
|
+
MAX_RETRIES = 3;
|
|
319
|
+
BASE_DELAY_MS = 200;
|
|
320
|
+
MAX_JITTER_MS = 300;
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
|
|
269
324
|
// src/lib/database.ts
|
|
270
325
|
import { createClient } from "@libsql/client";
|
|
271
326
|
async function initDatabase(config) {
|
|
272
327
|
if (_client) {
|
|
273
328
|
_client.close();
|
|
274
329
|
_client = null;
|
|
330
|
+
_resilientClient = null;
|
|
275
331
|
}
|
|
276
332
|
const opts = {
|
|
277
333
|
url: `file:${config.dbPath}`
|
|
@@ -280,17 +336,24 @@ async function initDatabase(config) {
|
|
|
280
336
|
opts.encryptionKey = config.encryptionKey;
|
|
281
337
|
}
|
|
282
338
|
_client = createClient(opts);
|
|
339
|
+
_resilientClient = wrapWithRetry(_client);
|
|
283
340
|
}
|
|
284
341
|
function getClient() {
|
|
342
|
+
if (!_resilientClient) {
|
|
343
|
+
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
344
|
+
}
|
|
345
|
+
return _resilientClient;
|
|
346
|
+
}
|
|
347
|
+
function getRawClient() {
|
|
285
348
|
if (!_client) {
|
|
286
349
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
287
350
|
}
|
|
288
351
|
return _client;
|
|
289
352
|
}
|
|
290
353
|
async function ensureSchema() {
|
|
291
|
-
const client =
|
|
354
|
+
const client = getRawClient();
|
|
292
355
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
293
|
-
await client.execute("PRAGMA busy_timeout =
|
|
356
|
+
await client.execute("PRAGMA busy_timeout = 30000");
|
|
294
357
|
try {
|
|
295
358
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
296
359
|
} catch {
|
|
@@ -1083,13 +1146,16 @@ async function disposeDatabase() {
|
|
|
1083
1146
|
if (_client) {
|
|
1084
1147
|
_client.close();
|
|
1085
1148
|
_client = null;
|
|
1149
|
+
_resilientClient = null;
|
|
1086
1150
|
}
|
|
1087
1151
|
}
|
|
1088
|
-
var _client, initTurso, disposeTurso;
|
|
1152
|
+
var _client, _resilientClient, initTurso, disposeTurso;
|
|
1089
1153
|
var init_database = __esm({
|
|
1090
1154
|
"src/lib/database.ts"() {
|
|
1091
1155
|
"use strict";
|
|
1156
|
+
init_db_retry();
|
|
1092
1157
|
_client = null;
|
|
1158
|
+
_resilientClient = null;
|
|
1093
1159
|
initTurso = initDatabase;
|
|
1094
1160
|
disposeTurso = disposeDatabase;
|
|
1095
1161
|
}
|
|
@@ -1202,7 +1268,7 @@ function listShards() {
|
|
|
1202
1268
|
}
|
|
1203
1269
|
async function ensureShardSchema(client) {
|
|
1204
1270
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
1205
|
-
await client.execute("PRAGMA busy_timeout =
|
|
1271
|
+
await client.execute("PRAGMA busy_timeout = 30000");
|
|
1206
1272
|
try {
|
|
1207
1273
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
1208
1274
|
} catch {
|
|
@@ -2087,11 +2153,11 @@ async function connectEmbedDaemon() {
|
|
|
2087
2153
|
}
|
|
2088
2154
|
}
|
|
2089
2155
|
const start = Date.now();
|
|
2090
|
-
let
|
|
2156
|
+
let delay2 = 100;
|
|
2091
2157
|
while (Date.now() - start < CONNECT_TIMEOUT_MS) {
|
|
2092
|
-
await new Promise((r) => setTimeout(r,
|
|
2158
|
+
await new Promise((r) => setTimeout(r, delay2));
|
|
2093
2159
|
if (await connectToSocket()) return true;
|
|
2094
|
-
|
|
2160
|
+
delay2 = Math.min(delay2 * 2, 3e3);
|
|
2095
2161
|
}
|
|
2096
2162
|
return false;
|
|
2097
2163
|
}
|
|
@@ -2183,11 +2249,11 @@ async function embedViaClient(text, priority = "high") {
|
|
|
2183
2249
|
`);
|
|
2184
2250
|
killAndRespawnDaemon();
|
|
2185
2251
|
const start = Date.now();
|
|
2186
|
-
let
|
|
2252
|
+
let delay2 = 200;
|
|
2187
2253
|
while (Date.now() - start < CONNECT_TIMEOUT_MS) {
|
|
2188
|
-
await new Promise((r) => setTimeout(r,
|
|
2254
|
+
await new Promise((r) => setTimeout(r, delay2));
|
|
2189
2255
|
if (await connectToSocket()) break;
|
|
2190
|
-
|
|
2256
|
+
delay2 = Math.min(delay2 * 2, 3e3);
|
|
2191
2257
|
}
|
|
2192
2258
|
if (!_connected) return null;
|
|
2193
2259
|
}
|
|
@@ -2199,11 +2265,11 @@ async function embedViaClient(text, priority = "high") {
|
|
|
2199
2265
|
`);
|
|
2200
2266
|
killAndRespawnDaemon();
|
|
2201
2267
|
const start = Date.now();
|
|
2202
|
-
let
|
|
2268
|
+
let delay2 = 200;
|
|
2203
2269
|
while (Date.now() - start < CONNECT_TIMEOUT_MS) {
|
|
2204
|
-
await new Promise((r) => setTimeout(r,
|
|
2270
|
+
await new Promise((r) => setTimeout(r, delay2));
|
|
2205
2271
|
if (await connectToSocket()) break;
|
|
2206
|
-
|
|
2272
|
+
delay2 = Math.min(delay2 * 2, 3e3);
|
|
2207
2273
|
}
|
|
2208
2274
|
if (!_connected) return null;
|
|
2209
2275
|
const retry = await sendRequest([text], priority);
|
|
@@ -109,6 +109,61 @@ var init_memory = __esm({
|
|
|
109
109
|
}
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
+
// src/lib/db-retry.ts
|
|
113
|
+
function isBusyError(err) {
|
|
114
|
+
if (err instanceof Error) {
|
|
115
|
+
const msg = err.message.toLowerCase();
|
|
116
|
+
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
function delay(ms) {
|
|
121
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
122
|
+
}
|
|
123
|
+
async function retryOnBusy(fn, label) {
|
|
124
|
+
let lastError;
|
|
125
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
126
|
+
try {
|
|
127
|
+
return await fn();
|
|
128
|
+
} catch (err) {
|
|
129
|
+
lastError = err;
|
|
130
|
+
if (!isBusyError(err) || attempt === MAX_RETRIES) {
|
|
131
|
+
throw err;
|
|
132
|
+
}
|
|
133
|
+
const backoff = BASE_DELAY_MS * Math.pow(2, attempt);
|
|
134
|
+
const jitter = Math.floor(Math.random() * MAX_JITTER_MS);
|
|
135
|
+
process.stderr.write(
|
|
136
|
+
`[exe-os] SQLITE_BUSY ${label} retry ${attempt + 1}/${MAX_RETRIES} \u2014 waiting ${backoff + jitter}ms
|
|
137
|
+
`
|
|
138
|
+
);
|
|
139
|
+
await delay(backoff + jitter);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
throw lastError;
|
|
143
|
+
}
|
|
144
|
+
function wrapWithRetry(client) {
|
|
145
|
+
return new Proxy(client, {
|
|
146
|
+
get(target, prop, receiver) {
|
|
147
|
+
if (prop === "execute") {
|
|
148
|
+
return (sql) => retryOnBusy(() => target.execute(sql), "execute");
|
|
149
|
+
}
|
|
150
|
+
if (prop === "batch") {
|
|
151
|
+
return (stmts) => retryOnBusy(() => target.batch(stmts), "batch");
|
|
152
|
+
}
|
|
153
|
+
return Reflect.get(target, prop, receiver);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
var MAX_RETRIES, BASE_DELAY_MS, MAX_JITTER_MS;
|
|
158
|
+
var init_db_retry = __esm({
|
|
159
|
+
"src/lib/db-retry.ts"() {
|
|
160
|
+
"use strict";
|
|
161
|
+
MAX_RETRIES = 3;
|
|
162
|
+
BASE_DELAY_MS = 200;
|
|
163
|
+
MAX_JITTER_MS = 300;
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
112
167
|
// src/lib/database.ts
|
|
113
168
|
var database_exports = {};
|
|
114
169
|
__export(database_exports, {
|
|
@@ -116,6 +171,7 @@ __export(database_exports, {
|
|
|
116
171
|
disposeTurso: () => disposeTurso,
|
|
117
172
|
ensureSchema: () => ensureSchema,
|
|
118
173
|
getClient: () => getClient,
|
|
174
|
+
getRawClient: () => getRawClient,
|
|
119
175
|
initDatabase: () => initDatabase,
|
|
120
176
|
initTurso: () => initTurso,
|
|
121
177
|
isInitialized: () => isInitialized
|
|
@@ -125,6 +181,7 @@ async function initDatabase(config) {
|
|
|
125
181
|
if (_client) {
|
|
126
182
|
_client.close();
|
|
127
183
|
_client = null;
|
|
184
|
+
_resilientClient = null;
|
|
128
185
|
}
|
|
129
186
|
const opts = {
|
|
130
187
|
url: `file:${config.dbPath}`
|
|
@@ -133,20 +190,27 @@ async function initDatabase(config) {
|
|
|
133
190
|
opts.encryptionKey = config.encryptionKey;
|
|
134
191
|
}
|
|
135
192
|
_client = createClient(opts);
|
|
193
|
+
_resilientClient = wrapWithRetry(_client);
|
|
136
194
|
}
|
|
137
195
|
function isInitialized() {
|
|
138
196
|
return _client !== null;
|
|
139
197
|
}
|
|
140
198
|
function getClient() {
|
|
199
|
+
if (!_resilientClient) {
|
|
200
|
+
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
201
|
+
}
|
|
202
|
+
return _resilientClient;
|
|
203
|
+
}
|
|
204
|
+
function getRawClient() {
|
|
141
205
|
if (!_client) {
|
|
142
206
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
143
207
|
}
|
|
144
208
|
return _client;
|
|
145
209
|
}
|
|
146
210
|
async function ensureSchema() {
|
|
147
|
-
const client =
|
|
211
|
+
const client = getRawClient();
|
|
148
212
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
149
|
-
await client.execute("PRAGMA busy_timeout =
|
|
213
|
+
await client.execute("PRAGMA busy_timeout = 30000");
|
|
150
214
|
try {
|
|
151
215
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
152
216
|
} catch {
|
|
@@ -939,13 +1003,16 @@ async function disposeDatabase() {
|
|
|
939
1003
|
if (_client) {
|
|
940
1004
|
_client.close();
|
|
941
1005
|
_client = null;
|
|
1006
|
+
_resilientClient = null;
|
|
942
1007
|
}
|
|
943
1008
|
}
|
|
944
|
-
var _client, initTurso, disposeTurso;
|
|
1009
|
+
var _client, _resilientClient, initTurso, disposeTurso;
|
|
945
1010
|
var init_database = __esm({
|
|
946
1011
|
"src/lib/database.ts"() {
|
|
947
1012
|
"use strict";
|
|
1013
|
+
init_db_retry();
|
|
948
1014
|
_client = null;
|
|
1015
|
+
_resilientClient = null;
|
|
949
1016
|
initTurso = initDatabase;
|
|
950
1017
|
disposeTurso = disposeDatabase;
|
|
951
1018
|
}
|
|
@@ -1252,7 +1319,7 @@ function listShards() {
|
|
|
1252
1319
|
}
|
|
1253
1320
|
async function ensureShardSchema(client) {
|
|
1254
1321
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
1255
|
-
await client.execute("PRAGMA busy_timeout =
|
|
1322
|
+
await client.execute("PRAGMA busy_timeout = 30000");
|
|
1256
1323
|
try {
|
|
1257
1324
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
1258
1325
|
} catch {
|
|
@@ -1490,20 +1557,38 @@ var init_notifications = __esm({
|
|
|
1490
1557
|
|
|
1491
1558
|
// src/lib/employees.ts
|
|
1492
1559
|
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
1493
|
-
import { existsSync as existsSync6, symlinkSync, readlinkSync } from "fs";
|
|
1560
|
+
import { existsSync as existsSync6, symlinkSync, readlinkSync, readFileSync as readFileSync4 } from "fs";
|
|
1494
1561
|
import { execSync as execSync3 } from "child_process";
|
|
1495
1562
|
import path7 from "path";
|
|
1496
|
-
|
|
1563
|
+
function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
|
|
1564
|
+
if (!existsSync6(employeesPath)) return [];
|
|
1565
|
+
try {
|
|
1566
|
+
return JSON.parse(readFileSync4(employeesPath, "utf-8"));
|
|
1567
|
+
} catch {
|
|
1568
|
+
return [];
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
function getEmployee(employees, name) {
|
|
1572
|
+
return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
|
|
1573
|
+
}
|
|
1574
|
+
function isMultiInstance(agentName, employees) {
|
|
1575
|
+
const roster = employees ?? loadEmployeesSync();
|
|
1576
|
+
const emp = getEmployee(roster, agentName);
|
|
1577
|
+
if (!emp) return false;
|
|
1578
|
+
return MULTI_INSTANCE_ROLES.has(emp.role.toLowerCase());
|
|
1579
|
+
}
|
|
1580
|
+
var EMPLOYEES_PATH, MULTI_INSTANCE_ROLES;
|
|
1497
1581
|
var init_employees = __esm({
|
|
1498
1582
|
"src/lib/employees.ts"() {
|
|
1499
1583
|
"use strict";
|
|
1500
1584
|
init_config();
|
|
1501
1585
|
EMPLOYEES_PATH = path7.join(EXE_AI_DIR, "exe-employees.json");
|
|
1586
|
+
MULTI_INSTANCE_ROLES = /* @__PURE__ */ new Set(["principal engineer", "content production specialist", "staff code reviewer"]);
|
|
1502
1587
|
}
|
|
1503
1588
|
});
|
|
1504
1589
|
|
|
1505
1590
|
// src/lib/license.ts
|
|
1506
|
-
import { readFileSync as
|
|
1591
|
+
import { readFileSync as readFileSync5, writeFileSync, existsSync as existsSync7, mkdirSync as mkdirSync2 } from "fs";
|
|
1507
1592
|
import { randomUUID } from "crypto";
|
|
1508
1593
|
import path8 from "path";
|
|
1509
1594
|
import { jwtVerify, importSPKI } from "jose";
|
|
@@ -1511,14 +1596,14 @@ function loadDeviceId() {
|
|
|
1511
1596
|
const deviceJsonPath = path8.join(EXE_AI_DIR, "device.json");
|
|
1512
1597
|
try {
|
|
1513
1598
|
if (existsSync7(deviceJsonPath)) {
|
|
1514
|
-
const data = JSON.parse(
|
|
1599
|
+
const data = JSON.parse(readFileSync5(deviceJsonPath, "utf8"));
|
|
1515
1600
|
if (data.deviceId) return data.deviceId;
|
|
1516
1601
|
}
|
|
1517
1602
|
} catch {
|
|
1518
1603
|
}
|
|
1519
1604
|
try {
|
|
1520
1605
|
if (existsSync7(DEVICE_ID_PATH)) {
|
|
1521
|
-
const id2 =
|
|
1606
|
+
const id2 = readFileSync5(DEVICE_ID_PATH, "utf8").trim();
|
|
1522
1607
|
if (id2) return id2;
|
|
1523
1608
|
}
|
|
1524
1609
|
} catch {
|
|
@@ -1531,7 +1616,7 @@ function loadDeviceId() {
|
|
|
1531
1616
|
function loadLicense() {
|
|
1532
1617
|
try {
|
|
1533
1618
|
if (!existsSync7(LICENSE_PATH)) return null;
|
|
1534
|
-
return
|
|
1619
|
+
return readFileSync5(LICENSE_PATH, "utf8").trim();
|
|
1535
1620
|
} catch {
|
|
1536
1621
|
return null;
|
|
1537
1622
|
}
|
|
@@ -1561,7 +1646,7 @@ async function verifyLicenseJwt(token) {
|
|
|
1561
1646
|
async function getCachedLicense() {
|
|
1562
1647
|
try {
|
|
1563
1648
|
if (!existsSync7(CACHE_PATH)) return null;
|
|
1564
|
-
const raw = JSON.parse(
|
|
1649
|
+
const raw = JSON.parse(readFileSync5(CACHE_PATH, "utf8"));
|
|
1565
1650
|
if (!raw.token || typeof raw.token !== "string") return null;
|
|
1566
1651
|
return await verifyLicenseJwt(raw.token);
|
|
1567
1652
|
} catch {
|
|
@@ -1657,12 +1742,12 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|
|
|
1657
1742
|
});
|
|
1658
1743
|
|
|
1659
1744
|
// src/lib/plan-limits.ts
|
|
1660
|
-
import { readFileSync as
|
|
1745
|
+
import { readFileSync as readFileSync6, existsSync as existsSync8 } from "fs";
|
|
1661
1746
|
import path9 from "path";
|
|
1662
1747
|
function getLicenseSync() {
|
|
1663
1748
|
try {
|
|
1664
1749
|
if (!existsSync8(CACHE_PATH2)) return freeLicense();
|
|
1665
|
-
const raw = JSON.parse(
|
|
1750
|
+
const raw = JSON.parse(readFileSync6(CACHE_PATH2, "utf8"));
|
|
1666
1751
|
if (!raw.token || typeof raw.token !== "string") return freeLicense();
|
|
1667
1752
|
const parts = raw.token.split(".");
|
|
1668
1753
|
if (parts.length !== 3) return freeLicense();
|
|
@@ -1720,7 +1805,7 @@ function assertEmployeeLimitSync(rosterPath) {
|
|
|
1720
1805
|
let count = 0;
|
|
1721
1806
|
try {
|
|
1722
1807
|
if (existsSync8(filePath)) {
|
|
1723
|
-
const raw =
|
|
1808
|
+
const raw = readFileSync6(filePath, "utf8");
|
|
1724
1809
|
const employees = JSON.parse(raw);
|
|
1725
1810
|
count = Array.isArray(employees) ? employees.length : 0;
|
|
1726
1811
|
}
|
|
@@ -1757,7 +1842,7 @@ var init_plan_limits = __esm({
|
|
|
1757
1842
|
import net from "net";
|
|
1758
1843
|
import { spawn } from "child_process";
|
|
1759
1844
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
1760
|
-
import { existsSync as existsSync9, unlinkSync as unlinkSync2, readFileSync as
|
|
1845
|
+
import { existsSync as existsSync9, unlinkSync as unlinkSync2, readFileSync as readFileSync7, openSync, closeSync, statSync as statSync2 } from "fs";
|
|
1761
1846
|
import path10 from "path";
|
|
1762
1847
|
import { fileURLToPath } from "url";
|
|
1763
1848
|
function handleData(chunk) {
|
|
@@ -1782,7 +1867,7 @@ function handleData(chunk) {
|
|
|
1782
1867
|
function cleanupStaleFiles() {
|
|
1783
1868
|
if (existsSync9(PID_PATH)) {
|
|
1784
1869
|
try {
|
|
1785
|
-
const pid = parseInt(
|
|
1870
|
+
const pid = parseInt(readFileSync7(PID_PATH, "utf8").trim(), 10);
|
|
1786
1871
|
if (pid > 0) {
|
|
1787
1872
|
try {
|
|
1788
1873
|
process.kill(pid, 0);
|
|
@@ -1930,11 +2015,11 @@ async function connectEmbedDaemon() {
|
|
|
1930
2015
|
}
|
|
1931
2016
|
}
|
|
1932
2017
|
const start = Date.now();
|
|
1933
|
-
let
|
|
2018
|
+
let delay2 = 100;
|
|
1934
2019
|
while (Date.now() - start < CONNECT_TIMEOUT_MS) {
|
|
1935
|
-
await new Promise((r) => setTimeout(r,
|
|
2020
|
+
await new Promise((r) => setTimeout(r, delay2));
|
|
1936
2021
|
if (await connectToSocket()) return true;
|
|
1937
|
-
|
|
2022
|
+
delay2 = Math.min(delay2 * 2, 3e3);
|
|
1938
2023
|
}
|
|
1939
2024
|
return false;
|
|
1940
2025
|
}
|
|
@@ -1990,7 +2075,7 @@ function killAndRespawnDaemon() {
|
|
|
1990
2075
|
process.stderr.write("[exed-client] Killing daemon for restart...\n");
|
|
1991
2076
|
if (existsSync9(PID_PATH)) {
|
|
1992
2077
|
try {
|
|
1993
|
-
const pid = parseInt(
|
|
2078
|
+
const pid = parseInt(readFileSync7(PID_PATH, "utf8").trim(), 10);
|
|
1994
2079
|
if (pid > 0) {
|
|
1995
2080
|
try {
|
|
1996
2081
|
process.kill(pid, "SIGKILL");
|
|
@@ -2026,11 +2111,11 @@ async function embedViaClient(text, priority = "high") {
|
|
|
2026
2111
|
`);
|
|
2027
2112
|
killAndRespawnDaemon();
|
|
2028
2113
|
const start = Date.now();
|
|
2029
|
-
let
|
|
2114
|
+
let delay2 = 200;
|
|
2030
2115
|
while (Date.now() - start < CONNECT_TIMEOUT_MS) {
|
|
2031
|
-
await new Promise((r) => setTimeout(r,
|
|
2116
|
+
await new Promise((r) => setTimeout(r, delay2));
|
|
2032
2117
|
if (await connectToSocket()) break;
|
|
2033
|
-
|
|
2118
|
+
delay2 = Math.min(delay2 * 2, 3e3);
|
|
2034
2119
|
}
|
|
2035
2120
|
if (!_connected) return null;
|
|
2036
2121
|
}
|
|
@@ -2042,11 +2127,11 @@ async function embedViaClient(text, priority = "high") {
|
|
|
2042
2127
|
`);
|
|
2043
2128
|
killAndRespawnDaemon();
|
|
2044
2129
|
const start = Date.now();
|
|
2045
|
-
let
|
|
2130
|
+
let delay2 = 200;
|
|
2046
2131
|
while (Date.now() - start < CONNECT_TIMEOUT_MS) {
|
|
2047
|
-
await new Promise((r) => setTimeout(r,
|
|
2132
|
+
await new Promise((r) => setTimeout(r, delay2));
|
|
2048
2133
|
if (await connectToSocket()) break;
|
|
2049
|
-
|
|
2134
|
+
delay2 = Math.min(delay2 * 2, 3e3);
|
|
2050
2135
|
}
|
|
2051
2136
|
if (!_connected) return null;
|
|
2052
2137
|
const retry = await sendRequest([text], priority);
|
|
@@ -2162,7 +2247,7 @@ import crypto4 from "crypto";
|
|
|
2162
2247
|
import path11 from "path";
|
|
2163
2248
|
import { execSync as execSync4 } from "child_process";
|
|
2164
2249
|
import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
|
|
2165
|
-
import { existsSync as existsSync10, readFileSync as
|
|
2250
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
|
|
2166
2251
|
async function writeCheckpoint(input2) {
|
|
2167
2252
|
const client = getClient();
|
|
2168
2253
|
const row = await resolveTask(client, input2.taskId);
|
|
@@ -2539,7 +2624,7 @@ async function ensureGitignoreExe(baseDir) {
|
|
|
2539
2624
|
const gitignorePath = path11.join(baseDir, ".gitignore");
|
|
2540
2625
|
try {
|
|
2541
2626
|
if (existsSync10(gitignorePath)) {
|
|
2542
|
-
const content =
|
|
2627
|
+
const content = readFileSync8(gitignorePath, "utf-8");
|
|
2543
2628
|
if (/^\/?exe\/?$/m.test(content)) return;
|
|
2544
2629
|
await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
|
|
2545
2630
|
} else {
|
|
@@ -2559,7 +2644,7 @@ var init_tasks_crud = __esm({
|
|
|
2559
2644
|
});
|
|
2560
2645
|
|
|
2561
2646
|
// src/lib/session-registry.ts
|
|
2562
|
-
import { readFileSync as
|
|
2647
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, existsSync as existsSync11 } from "fs";
|
|
2563
2648
|
import path12 from "path";
|
|
2564
2649
|
import os3 from "os";
|
|
2565
2650
|
function registerSession(entry) {
|
|
@@ -2578,7 +2663,7 @@ function registerSession(entry) {
|
|
|
2578
2663
|
}
|
|
2579
2664
|
function listSessions() {
|
|
2580
2665
|
try {
|
|
2581
|
-
const raw =
|
|
2666
|
+
const raw = readFileSync9(REGISTRY_PATH, "utf8");
|
|
2582
2667
|
return JSON.parse(raw);
|
|
2583
2668
|
} catch {
|
|
2584
2669
|
return [];
|
|
@@ -2785,7 +2870,7 @@ var init_provider_table = __esm({
|
|
|
2785
2870
|
});
|
|
2786
2871
|
|
|
2787
2872
|
// src/lib/intercom-queue.ts
|
|
2788
|
-
import { readFileSync as
|
|
2873
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync3, renameSync as renameSync2, existsSync as existsSync12, mkdirSync as mkdirSync4 } from "fs";
|
|
2789
2874
|
import path13 from "path";
|
|
2790
2875
|
import os4 from "os";
|
|
2791
2876
|
function ensureDir() {
|
|
@@ -2795,7 +2880,7 @@ function ensureDir() {
|
|
|
2795
2880
|
function readQueue() {
|
|
2796
2881
|
try {
|
|
2797
2882
|
if (!existsSync12(QUEUE_PATH)) return [];
|
|
2798
|
-
return JSON.parse(
|
|
2883
|
+
return JSON.parse(readFileSync10(QUEUE_PATH, "utf8"));
|
|
2799
2884
|
} catch {
|
|
2800
2885
|
return [];
|
|
2801
2886
|
}
|
|
@@ -2835,7 +2920,7 @@ var init_intercom_queue = __esm({
|
|
|
2835
2920
|
|
|
2836
2921
|
// src/lib/tmux-routing.ts
|
|
2837
2922
|
import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
|
|
2838
|
-
import { readFileSync as
|
|
2923
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, existsSync as existsSync13, appendFileSync } from "fs";
|
|
2839
2924
|
import path14 from "path";
|
|
2840
2925
|
import os5 from "os";
|
|
2841
2926
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
@@ -2884,7 +2969,7 @@ function extractRootExe(name) {
|
|
|
2884
2969
|
}
|
|
2885
2970
|
function getParentExe(sessionKey) {
|
|
2886
2971
|
try {
|
|
2887
|
-
const data = JSON.parse(
|
|
2972
|
+
const data = JSON.parse(readFileSync11(path14.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
2888
2973
|
return data.parentExe || null;
|
|
2889
2974
|
} catch {
|
|
2890
2975
|
return null;
|
|
@@ -2892,7 +2977,7 @@ function getParentExe(sessionKey) {
|
|
|
2892
2977
|
}
|
|
2893
2978
|
function getDispatchedBy(sessionKey) {
|
|
2894
2979
|
try {
|
|
2895
|
-
const data = JSON.parse(
|
|
2980
|
+
const data = JSON.parse(readFileSync11(
|
|
2896
2981
|
path14.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
|
|
2897
2982
|
"utf8"
|
|
2898
2983
|
));
|
|
@@ -2929,7 +3014,7 @@ function findFreeInstance(employeeName, exeSession, maxInstances = 10, isAlive =
|
|
|
2929
3014
|
function readDebounceState() {
|
|
2930
3015
|
try {
|
|
2931
3016
|
if (!existsSync13(DEBOUNCE_FILE)) return {};
|
|
2932
|
-
return JSON.parse(
|
|
3017
|
+
return JSON.parse(readFileSync11(DEBOUNCE_FILE, "utf8"));
|
|
2933
3018
|
} catch {
|
|
2934
3019
|
return {};
|
|
2935
3020
|
}
|
|
@@ -3125,7 +3210,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
3125
3210
|
const claudeJsonPath = path14.join(os5.homedir(), ".claude.json");
|
|
3126
3211
|
let claudeJson = {};
|
|
3127
3212
|
try {
|
|
3128
|
-
claudeJson = JSON.parse(
|
|
3213
|
+
claudeJson = JSON.parse(readFileSync11(claudeJsonPath, "utf8"));
|
|
3129
3214
|
} catch {
|
|
3130
3215
|
}
|
|
3131
3216
|
if (!claudeJson.projects) claudeJson.projects = {};
|
|
@@ -3143,7 +3228,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
3143
3228
|
const settingsPath = path14.join(projSettingsDir, "settings.json");
|
|
3144
3229
|
let settings = {};
|
|
3145
3230
|
try {
|
|
3146
|
-
settings = JSON.parse(
|
|
3231
|
+
settings = JSON.parse(readFileSync11(settingsPath, "utf8"));
|
|
3147
3232
|
} catch {
|
|
3148
3233
|
}
|
|
3149
3234
|
const perms = settings.permissions ?? {};
|
|
@@ -3648,7 +3733,7 @@ async function dispatchTaskToEmployee(input2) {
|
|
|
3648
3733
|
} else {
|
|
3649
3734
|
const projectDir = input2.projectDir ?? process.cwd();
|
|
3650
3735
|
const result = ensureEmployee(input2.assignedTo, exeSession, projectDir, {
|
|
3651
|
-
autoInstance: input2.assignedTo
|
|
3736
|
+
autoInstance: isMultiInstance(input2.assignedTo)
|
|
3652
3737
|
});
|
|
3653
3738
|
if (result.status === "failed") {
|
|
3654
3739
|
process.stderr.write(
|
|
@@ -3683,6 +3768,7 @@ var init_tasks_notify = __esm({
|
|
|
3683
3768
|
init_session_key();
|
|
3684
3769
|
init_notifications();
|
|
3685
3770
|
init_transport();
|
|
3771
|
+
init_employees();
|
|
3686
3772
|
}
|
|
3687
3773
|
});
|
|
3688
3774
|
|
|
@@ -4571,8 +4657,8 @@ function findContainingChunk(filePath, snippet) {
|
|
|
4571
4657
|
try {
|
|
4572
4658
|
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
4573
4659
|
if (ext !== "ts" && ext !== "tsx" && ext !== "js" && ext !== "jsx") return "";
|
|
4574
|
-
const { readFileSync:
|
|
4575
|
-
const source =
|
|
4660
|
+
const { readFileSync: readFileSync12 } = __require("fs");
|
|
4661
|
+
const source = readFileSync12(filePath, "utf8");
|
|
4576
4662
|
const lines = source.split("\n");
|
|
4577
4663
|
const lowerSnippet = snippet.toLowerCase().slice(0, 80);
|
|
4578
4664
|
let matchLine = -1;
|
|
@@ -4853,8 +4939,8 @@ process.stdin.on("end", async () => {
|
|
|
4853
4939
|
fileContent = data.tool_input?.content ?? "";
|
|
4854
4940
|
} else {
|
|
4855
4941
|
try {
|
|
4856
|
-
const { readFileSync:
|
|
4857
|
-
fileContent =
|
|
4942
|
+
const { readFileSync: readFileSync12 } = await import("fs");
|
|
4943
|
+
fileContent = readFileSync12(filePath, "utf8");
|
|
4858
4944
|
} catch (err) {
|
|
4859
4945
|
process.stderr.write(`[ingest-worker] file read failed (${filePath}): ${err instanceof Error ? err.message : String(err)}
|
|
4860
4946
|
`);
|