@askexenow/exe-os 0.8.36 → 0.8.37
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 +9 -1
- package/dist/bin/backfill-responses.js +9 -1
- package/dist/bin/cli.js +255 -31
- package/dist/bin/exe-assign.js +9 -1
- package/dist/bin/exe-boot.js +554 -23
- package/dist/bin/exe-dispatch.js +43 -3
- package/dist/bin/exe-export-behaviors.js +7 -0
- package/dist/bin/exe-gateway.js +57 -9
- package/dist/bin/exe-heartbeat.js +2 -1
- package/dist/bin/exe-kill.js +7 -0
- package/dist/bin/exe-launch-agent.js +8 -1
- package/dist/bin/exe-link.js +503 -12
- package/dist/bin/exe-pending-messages.js +2 -1
- package/dist/bin/exe-pending-reviews.js +2 -1
- package/dist/bin/exe-review.js +9 -1
- package/dist/bin/exe-search.js +9 -1
- package/dist/bin/exe-session-cleanup.js +11 -2
- package/dist/bin/git-sweep.js +9 -1
- package/dist/bin/graph-backfill.js +7 -0
- package/dist/bin/graph-export.js +7 -0
- package/dist/bin/install.js +35 -5
- package/dist/bin/scan-tasks.js +9 -1
- package/dist/bin/shard-migrate.js +7 -0
- package/dist/bin/wiki-sync.js +7 -0
- package/dist/gateway/index.js +57 -9
- package/dist/hooks/bug-report-worker.js +45 -5
- package/dist/hooks/commit-complete.js +9 -1
- package/dist/hooks/error-recall.js +10 -2
- package/dist/hooks/exe-heartbeat-hook.js +1 -1
- package/dist/hooks/ingest-worker.js +56 -8
- package/dist/hooks/ingest.js +1 -1
- package/dist/hooks/instructions-loaded.js +10 -2
- package/dist/hooks/notification.js +10 -2
- package/dist/hooks/post-compact.js +10 -2
- package/dist/hooks/pre-compact.js +10 -2
- package/dist/hooks/pre-tool-use.js +10 -2
- package/dist/hooks/prompt-ingest-worker.js +9 -1
- package/dist/hooks/prompt-submit.js +56 -8
- package/dist/hooks/response-ingest-worker.js +9 -1
- package/dist/hooks/session-end.js +10 -2
- package/dist/hooks/session-start.js +10 -2
- package/dist/hooks/stop.js +10 -2
- package/dist/hooks/subagent-stop.js +10 -2
- package/dist/hooks/summary-worker.js +512 -13
- package/dist/index.js +65 -15
- package/dist/lib/cloud-sync.js +502 -11
- package/dist/lib/exe-daemon.js +73 -23
- package/dist/lib/hybrid-search.js +9 -1
- package/dist/lib/messaging.js +43 -3
- package/dist/lib/store.js +9 -1
- package/dist/lib/tasks.js +47 -7
- package/dist/lib/tmux-routing.js +45 -3
- package/dist/mcp/server.js +73 -16
- package/dist/mcp/tools/create-task.js +48 -8
- package/dist/mcp/tools/deactivate-behavior.js +1 -1
- package/dist/mcp/tools/list-tasks.js +2 -1
- package/dist/mcp/tools/send-message.js +46 -6
- package/dist/mcp/tools/update-task.js +3 -2
- package/dist/runtime/index.js +54 -4
- package/dist/tui/App.js +54 -4
- package/package.json +2 -2
- package/src/commands/exe/afk.md +116 -0
package/dist/index.js
CHANGED
|
@@ -3339,6 +3339,7 @@ var init_capacity_monitor = __esm({
|
|
|
3339
3339
|
// src/lib/tmux-routing.ts
|
|
3340
3340
|
var tmux_routing_exports = {};
|
|
3341
3341
|
__export(tmux_routing_exports, {
|
|
3342
|
+
acquireSpawnLock: () => acquireSpawnLock,
|
|
3342
3343
|
employeeSessionName: () => employeeSessionName,
|
|
3343
3344
|
ensureEmployee: () => ensureEmployee,
|
|
3344
3345
|
extractRootExe: () => extractRootExe,
|
|
@@ -3353,6 +3354,7 @@ __export(tmux_routing_exports, {
|
|
|
3353
3354
|
notifyParentExe: () => notifyParentExe,
|
|
3354
3355
|
parseParentExe: () => parseParentExe,
|
|
3355
3356
|
registerParentExe: () => registerParentExe,
|
|
3357
|
+
releaseSpawnLock: () => releaseSpawnLock,
|
|
3356
3358
|
resolveExeSession: () => resolveExeSession,
|
|
3357
3359
|
sendIntercom: () => sendIntercom,
|
|
3358
3360
|
spawnEmployee: () => spawnEmployee,
|
|
@@ -3363,6 +3365,42 @@ import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, mkdirSy
|
|
|
3363
3365
|
import path14 from "path";
|
|
3364
3366
|
import os6 from "os";
|
|
3365
3367
|
import { fileURLToPath } from "url";
|
|
3368
|
+
import { unlinkSync as unlinkSync4 } from "fs";
|
|
3369
|
+
function spawnLockPath(sessionName) {
|
|
3370
|
+
return path14.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
3371
|
+
}
|
|
3372
|
+
function isProcessAlive(pid) {
|
|
3373
|
+
try {
|
|
3374
|
+
process.kill(pid, 0);
|
|
3375
|
+
return true;
|
|
3376
|
+
} catch {
|
|
3377
|
+
return false;
|
|
3378
|
+
}
|
|
3379
|
+
}
|
|
3380
|
+
function acquireSpawnLock(sessionName) {
|
|
3381
|
+
if (!existsSync10(SPAWN_LOCK_DIR)) {
|
|
3382
|
+
mkdirSync5(SPAWN_LOCK_DIR, { recursive: true });
|
|
3383
|
+
}
|
|
3384
|
+
const lockFile = spawnLockPath(sessionName);
|
|
3385
|
+
if (existsSync10(lockFile)) {
|
|
3386
|
+
try {
|
|
3387
|
+
const lock = JSON.parse(readFileSync9(lockFile, "utf8"));
|
|
3388
|
+
const age = Date.now() - lock.timestamp;
|
|
3389
|
+
if (isProcessAlive(lock.pid) && age < 6e4) {
|
|
3390
|
+
return false;
|
|
3391
|
+
}
|
|
3392
|
+
} catch {
|
|
3393
|
+
}
|
|
3394
|
+
}
|
|
3395
|
+
writeFileSync5(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
|
|
3396
|
+
return true;
|
|
3397
|
+
}
|
|
3398
|
+
function releaseSpawnLock(sessionName) {
|
|
3399
|
+
try {
|
|
3400
|
+
unlinkSync4(spawnLockPath(sessionName));
|
|
3401
|
+
} catch {
|
|
3402
|
+
}
|
|
3403
|
+
}
|
|
3366
3404
|
function resolveBehaviorsExporterScript() {
|
|
3367
3405
|
try {
|
|
3368
3406
|
const thisFile = fileURLToPath(import.meta.url);
|
|
@@ -3461,10 +3499,10 @@ function isEmployeeAlive(sessionName) {
|
|
|
3461
3499
|
}
|
|
3462
3500
|
function findFreeInstance(employeeName, exeSession, maxInstances = 10, isAlive = isEmployeeAlive) {
|
|
3463
3501
|
const base = employeeSessionName(employeeName, exeSession);
|
|
3464
|
-
if (!isAlive(base)) return 0;
|
|
3502
|
+
if (!isAlive(base) && acquireSpawnLock(base)) return 0;
|
|
3465
3503
|
for (let i = 2; i <= maxInstances; i++) {
|
|
3466
3504
|
const candidate = employeeSessionName(employeeName, exeSession, i);
|
|
3467
|
-
if (!isAlive(candidate)) return i;
|
|
3505
|
+
if (!isAlive(candidate) && acquireSpawnLock(candidate)) return i;
|
|
3468
3506
|
}
|
|
3469
3507
|
return null;
|
|
3470
3508
|
}
|
|
@@ -3828,6 +3866,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
3828
3866
|
command: spawnCommand
|
|
3829
3867
|
});
|
|
3830
3868
|
if (spawnResult.error) {
|
|
3869
|
+
releaseSpawnLock(sessionName);
|
|
3831
3870
|
return { sessionName, error: `tmux new-session failed: ${spawnResult.error}` };
|
|
3832
3871
|
}
|
|
3833
3872
|
transport.pipeLog(sessionName, logFile);
|
|
@@ -3865,6 +3904,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
3865
3904
|
}
|
|
3866
3905
|
}
|
|
3867
3906
|
if (!booted) {
|
|
3907
|
+
releaseSpawnLock(sessionName);
|
|
3868
3908
|
return { sessionName, error: `${useExeAgent ? "exe-agent" : "claude"} did not boot within 15s` };
|
|
3869
3909
|
}
|
|
3870
3910
|
if (!useExeAgent) {
|
|
@@ -3881,9 +3921,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
3881
3921
|
pid: 0,
|
|
3882
3922
|
registeredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3883
3923
|
});
|
|
3924
|
+
releaseSpawnLock(sessionName);
|
|
3884
3925
|
return { sessionName };
|
|
3885
3926
|
}
|
|
3886
|
-
var SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, VERIFY_PANE_LINES, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
|
|
3927
|
+
var SPAWN_LOCK_DIR, SESSION_CACHE, BEHAVIORS_EXPORT_TIMEOUT_MS, VERIFY_PANE_LINES, INTERCOM_DEBOUNCE_MS, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS, BUSY_PATTERN;
|
|
3887
3928
|
var init_tmux_routing = __esm({
|
|
3888
3929
|
"src/lib/tmux-routing.ts"() {
|
|
3889
3930
|
"use strict";
|
|
@@ -3895,6 +3936,7 @@ var init_tmux_routing = __esm({
|
|
|
3895
3936
|
init_provider_table();
|
|
3896
3937
|
init_intercom_queue();
|
|
3897
3938
|
init_plan_limits();
|
|
3939
|
+
SPAWN_LOCK_DIR = path14.join(os6.homedir(), ".exe-os", "spawn-locks");
|
|
3898
3940
|
SESSION_CACHE = path14.join(os6.homedir(), ".exe-os", "session-cache");
|
|
3899
3941
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
3900
3942
|
VERIFY_PANE_LINES = 200;
|
|
@@ -4283,7 +4325,8 @@ async function writeMemory(record) {
|
|
|
4283
4325
|
has_error: record.has_error ? 1 : 0,
|
|
4284
4326
|
raw_text: record.raw_text,
|
|
4285
4327
|
vector: record.vector,
|
|
4286
|
-
version:
|
|
4328
|
+
version: 0,
|
|
4329
|
+
// Placeholder — assigned atomically at flush time
|
|
4287
4330
|
task_id: record.task_id ?? null,
|
|
4288
4331
|
importance: record.importance ?? 5,
|
|
4289
4332
|
status: record.status ?? "active",
|
|
@@ -4317,6 +4360,13 @@ async function flushBatch() {
|
|
|
4317
4360
|
_flushing = true;
|
|
4318
4361
|
try {
|
|
4319
4362
|
const batch = _pendingRecords.slice(0);
|
|
4363
|
+
const client = getClient();
|
|
4364
|
+
const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
|
|
4365
|
+
let baseVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
4366
|
+
for (const row of batch) {
|
|
4367
|
+
row.version = baseVersion++;
|
|
4368
|
+
}
|
|
4369
|
+
_nextVersion = baseVersion;
|
|
4320
4370
|
const buildStmt = (row) => {
|
|
4321
4371
|
const hasVector = row.vector !== null;
|
|
4322
4372
|
const taskId = row.task_id ?? null;
|
|
@@ -5247,7 +5297,7 @@ var init_crm_bridge = __esm({
|
|
|
5247
5297
|
import net from "net";
|
|
5248
5298
|
import { spawn } from "child_process";
|
|
5249
5299
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
5250
|
-
import { existsSync as existsSync13, unlinkSync as
|
|
5300
|
+
import { existsSync as existsSync13, unlinkSync as unlinkSync5, readFileSync as readFileSync10, openSync, closeSync, statSync } from "fs";
|
|
5251
5301
|
import path17 from "path";
|
|
5252
5302
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5253
5303
|
function handleData(chunk) {
|
|
@@ -5283,11 +5333,11 @@ function cleanupStaleFiles() {
|
|
|
5283
5333
|
} catch {
|
|
5284
5334
|
}
|
|
5285
5335
|
try {
|
|
5286
|
-
|
|
5336
|
+
unlinkSync5(PID_PATH);
|
|
5287
5337
|
} catch {
|
|
5288
5338
|
}
|
|
5289
5339
|
try {
|
|
5290
|
-
|
|
5340
|
+
unlinkSync5(SOCKET_PATH);
|
|
5291
5341
|
} catch {
|
|
5292
5342
|
}
|
|
5293
5343
|
}
|
|
@@ -5339,7 +5389,7 @@ function spawnDaemon() {
|
|
|
5339
5389
|
}
|
|
5340
5390
|
}
|
|
5341
5391
|
}
|
|
5342
|
-
function
|
|
5392
|
+
function acquireSpawnLock2() {
|
|
5343
5393
|
try {
|
|
5344
5394
|
const fd = openSync(SPAWN_LOCK_PATH, "wx");
|
|
5345
5395
|
closeSync(fd);
|
|
@@ -5349,7 +5399,7 @@ function acquireSpawnLock() {
|
|
|
5349
5399
|
const stat = statSync(SPAWN_LOCK_PATH);
|
|
5350
5400
|
if (Date.now() - stat.mtimeMs > SPAWN_LOCK_STALE_MS) {
|
|
5351
5401
|
try {
|
|
5352
|
-
|
|
5402
|
+
unlinkSync5(SPAWN_LOCK_PATH);
|
|
5353
5403
|
} catch {
|
|
5354
5404
|
}
|
|
5355
5405
|
try {
|
|
@@ -5364,9 +5414,9 @@ function acquireSpawnLock() {
|
|
|
5364
5414
|
return false;
|
|
5365
5415
|
}
|
|
5366
5416
|
}
|
|
5367
|
-
function
|
|
5417
|
+
function releaseSpawnLock2() {
|
|
5368
5418
|
try {
|
|
5369
|
-
|
|
5419
|
+
unlinkSync5(SPAWN_LOCK_PATH);
|
|
5370
5420
|
} catch {
|
|
5371
5421
|
}
|
|
5372
5422
|
}
|
|
@@ -5411,12 +5461,12 @@ function connectToSocket() {
|
|
|
5411
5461
|
async function connectEmbedDaemon() {
|
|
5412
5462
|
if (_socket && _connected) return true;
|
|
5413
5463
|
if (await connectToSocket()) return true;
|
|
5414
|
-
if (
|
|
5464
|
+
if (acquireSpawnLock2()) {
|
|
5415
5465
|
try {
|
|
5416
5466
|
cleanupStaleFiles();
|
|
5417
5467
|
spawnDaemon();
|
|
5418
5468
|
} finally {
|
|
5419
|
-
|
|
5469
|
+
releaseSpawnLock2();
|
|
5420
5470
|
}
|
|
5421
5471
|
}
|
|
5422
5472
|
const start = Date.now();
|
|
@@ -5497,11 +5547,11 @@ function killAndRespawnDaemon() {
|
|
|
5497
5547
|
_connected = false;
|
|
5498
5548
|
_buffer = "";
|
|
5499
5549
|
try {
|
|
5500
|
-
|
|
5550
|
+
unlinkSync5(PID_PATH);
|
|
5501
5551
|
} catch {
|
|
5502
5552
|
}
|
|
5503
5553
|
try {
|
|
5504
|
-
|
|
5554
|
+
unlinkSync5(SOCKET_PATH);
|
|
5505
5555
|
} catch {
|
|
5506
5556
|
}
|
|
5507
5557
|
spawnDaemon();
|