@askexenow/exe-os 0.9.67 → 0.9.69
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/age-ontology-load.js +263 -0
- package/dist/bin/agentic-ontology-backfill.js +178 -17
- package/dist/bin/agentic-reflection-backfill.js +165 -10
- package/dist/bin/agentic-semantic-label.js +173 -12
- package/dist/bin/backfill-vectors.js +176 -13
- package/dist/bin/cc-doctor.js +293 -30
- package/dist/bin/cli.js +1175 -855
- package/dist/bin/exe-healthcheck.js +293 -30
- package/dist/bin/graph-backfill.js +176 -17
- package/dist/bin/postgres-agentic-reflection-backfill.js +270 -0
- package/dist/bin/postgres-agentic-semantic-backfill.js +271 -1
- package/dist/lib/exe-daemon.js +1714 -985
- package/dist/mcp/server.js +728 -530
- package/package.json +1 -1
|
@@ -3338,10 +3338,10 @@ function evictLRU() {
|
|
|
3338
3338
|
}
|
|
3339
3339
|
}
|
|
3340
3340
|
function evictIdleShards() {
|
|
3341
|
-
const
|
|
3341
|
+
const now2 = Date.now();
|
|
3342
3342
|
const toEvict = [];
|
|
3343
3343
|
for (const [name, lastAccess] of _shardLastAccess) {
|
|
3344
|
-
if (
|
|
3344
|
+
if (now2 - lastAccess > SHARD_IDLE_MS) {
|
|
3345
3345
|
toEvict.push(name);
|
|
3346
3346
|
}
|
|
3347
3347
|
}
|
|
@@ -3621,22 +3621,22 @@ ${sections.join("\n\n")}
|
|
|
3621
3621
|
}
|
|
3622
3622
|
async function storeGlobalProcedure(input) {
|
|
3623
3623
|
const id = randomUUID2();
|
|
3624
|
-
const
|
|
3624
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
3625
3625
|
const client = getClient();
|
|
3626
3626
|
await client.execute({
|
|
3627
3627
|
sql: `INSERT INTO company_procedures (id, title, content, priority, domain, active, created_at, updated_at)
|
|
3628
3628
|
VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
|
|
3629
|
-
args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null,
|
|
3629
|
+
args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null, now2, now2]
|
|
3630
3630
|
});
|
|
3631
3631
|
await loadGlobalProcedures();
|
|
3632
3632
|
return id;
|
|
3633
3633
|
}
|
|
3634
3634
|
async function deactivateGlobalProcedure(id) {
|
|
3635
|
-
const
|
|
3635
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
3636
3636
|
const client = getClient();
|
|
3637
3637
|
const result = await client.execute({
|
|
3638
3638
|
sql: "UPDATE company_procedures SET active = 0, updated_at = ? WHERE id = ?",
|
|
3639
|
-
args: [
|
|
3639
|
+
args: [now2, id]
|
|
3640
3640
|
});
|
|
3641
3641
|
await loadGlobalProcedures();
|
|
3642
3642
|
return result.rowsAffected > 0;
|
|
@@ -3816,8 +3816,8 @@ function deriveMachineKey() {
|
|
|
3816
3816
|
}
|
|
3817
3817
|
function readMachineId() {
|
|
3818
3818
|
try {
|
|
3819
|
-
const { readFileSync:
|
|
3820
|
-
return
|
|
3819
|
+
const { readFileSync: readFileSync6 } = __require("fs");
|
|
3820
|
+
return readFileSync6("/etc/machine-id", "utf-8").trim();
|
|
3821
3821
|
} catch {
|
|
3822
3822
|
return "";
|
|
3823
3823
|
}
|
|
@@ -4125,8 +4125,8 @@ function isMainModule(importMetaUrl) {
|
|
|
4125
4125
|
}
|
|
4126
4126
|
|
|
4127
4127
|
// src/bin/backfill-vectors.ts
|
|
4128
|
-
import { existsSync as
|
|
4129
|
-
import
|
|
4128
|
+
import { existsSync as existsSync10, unlinkSync as unlinkSync5 } from "fs";
|
|
4129
|
+
import path10 from "path";
|
|
4130
4130
|
|
|
4131
4131
|
// src/lib/worker-gate.ts
|
|
4132
4132
|
init_config();
|
|
@@ -4179,12 +4179,169 @@ function releaseBackfillLock() {
|
|
|
4179
4179
|
}
|
|
4180
4180
|
}
|
|
4181
4181
|
|
|
4182
|
+
// src/lib/background-jobs.ts
|
|
4183
|
+
init_config();
|
|
4184
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4, unlinkSync as unlinkSync4 } from "fs";
|
|
4185
|
+
import { execFileSync } from "child_process";
|
|
4186
|
+
import os6 from "os";
|
|
4187
|
+
import path9 from "path";
|
|
4188
|
+
var JOB_DIR = path9.join(EXE_AI_DIR, "jobs");
|
|
4189
|
+
var JOBS_FILE = path9.join(JOB_DIR, "jobs.json");
|
|
4190
|
+
var LOCK_DIR = path9.join(JOB_DIR, "locks");
|
|
4191
|
+
var DEFAULT_LOCK_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
4192
|
+
var MAX_HISTORY = 200;
|
|
4193
|
+
function ensureDirs() {
|
|
4194
|
+
mkdirSync4(LOCK_DIR, { recursive: true });
|
|
4195
|
+
}
|
|
4196
|
+
function now() {
|
|
4197
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
4198
|
+
}
|
|
4199
|
+
function isAlive(pid) {
|
|
4200
|
+
if (!pid || pid <= 0) return false;
|
|
4201
|
+
try {
|
|
4202
|
+
process.kill(pid, 0);
|
|
4203
|
+
return true;
|
|
4204
|
+
} catch {
|
|
4205
|
+
return false;
|
|
4206
|
+
}
|
|
4207
|
+
}
|
|
4208
|
+
function readJobsRaw() {
|
|
4209
|
+
ensureDirs();
|
|
4210
|
+
if (!existsSync9(JOBS_FILE)) return [];
|
|
4211
|
+
try {
|
|
4212
|
+
const parsed = JSON.parse(readFileSync5(JOBS_FILE, "utf8"));
|
|
4213
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
4214
|
+
} catch {
|
|
4215
|
+
return [];
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
function writeJobsRaw(jobs) {
|
|
4219
|
+
ensureDirs();
|
|
4220
|
+
const running = jobs.filter((j) => j.status === "running");
|
|
4221
|
+
const rest = jobs.filter((j) => j.status !== "running").slice(-MAX_HISTORY);
|
|
4222
|
+
writeFileSync4(JOBS_FILE, JSON.stringify([...rest, ...running], null, 2) + "\n");
|
|
4223
|
+
}
|
|
4224
|
+
function lockPath(type) {
|
|
4225
|
+
return path9.join(LOCK_DIR, `${type.replace(/[^a-zA-Z0-9_.-]/g, "_")}.lock`);
|
|
4226
|
+
}
|
|
4227
|
+
function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
4228
|
+
ensureDirs();
|
|
4229
|
+
const file = lockPath(type);
|
|
4230
|
+
if (existsSync9(file)) {
|
|
4231
|
+
try {
|
|
4232
|
+
const lock = JSON.parse(readFileSync5(file, "utf8"));
|
|
4233
|
+
const age = Date.now() - Date.parse(lock.updatedAt ?? "");
|
|
4234
|
+
if (lock.pid && isAlive(lock.pid) && Number.isFinite(age) && age < ttlMs) return false;
|
|
4235
|
+
} catch {
|
|
4236
|
+
}
|
|
4237
|
+
try {
|
|
4238
|
+
unlinkSync4(file);
|
|
4239
|
+
} catch {
|
|
4240
|
+
}
|
|
4241
|
+
}
|
|
4242
|
+
try {
|
|
4243
|
+
writeFileSync4(file, JSON.stringify({ pid: process.pid, updatedAt: now() }, null, 2) + "\n", { flag: "wx" });
|
|
4244
|
+
return true;
|
|
4245
|
+
} catch {
|
|
4246
|
+
return false;
|
|
4247
|
+
}
|
|
4248
|
+
}
|
|
4249
|
+
function releaseJobLock(type) {
|
|
4250
|
+
const file = lockPath(type);
|
|
4251
|
+
try {
|
|
4252
|
+
if (!existsSync9(file)) return;
|
|
4253
|
+
const lock = JSON.parse(readFileSync5(file, "utf8"));
|
|
4254
|
+
if (lock.pid === process.pid || !lock.pid || !isAlive(lock.pid)) unlinkSync4(file);
|
|
4255
|
+
} catch {
|
|
4256
|
+
try {
|
|
4257
|
+
unlinkSync4(file);
|
|
4258
|
+
} catch {
|
|
4259
|
+
}
|
|
4260
|
+
}
|
|
4261
|
+
}
|
|
4262
|
+
function startManagedJob(options) {
|
|
4263
|
+
const lowPriority = options.lowPriority ?? true;
|
|
4264
|
+
if (!acquireJobLock(options.type, options.lockTtlMs)) return null;
|
|
4265
|
+
if (lowPriority) {
|
|
4266
|
+
try {
|
|
4267
|
+
os6.setPriority(process.pid, 10);
|
|
4268
|
+
} catch {
|
|
4269
|
+
}
|
|
4270
|
+
}
|
|
4271
|
+
const id = `${options.type}-${Date.now()}-${process.pid}`.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
4272
|
+
const record = {
|
|
4273
|
+
id,
|
|
4274
|
+
type: options.type,
|
|
4275
|
+
name: options.name,
|
|
4276
|
+
pid: process.pid,
|
|
4277
|
+
command: options.command ?? process.argv.join(" "),
|
|
4278
|
+
cwd: process.cwd(),
|
|
4279
|
+
status: "running",
|
|
4280
|
+
startedAt: now(),
|
|
4281
|
+
updatedAt: now(),
|
|
4282
|
+
lastHeartbeatAt: now(),
|
|
4283
|
+
cancelCommand: `exe-os jobs cancel ${id}`,
|
|
4284
|
+
lowPriority
|
|
4285
|
+
};
|
|
4286
|
+
const upsert = (patch) => {
|
|
4287
|
+
const jobs = readJobsRaw().filter((j) => j.id !== id);
|
|
4288
|
+
Object.assign(record, patch, { updatedAt: now() });
|
|
4289
|
+
writeJobsRaw([...jobs, record]);
|
|
4290
|
+
const file = lockPath(options.type);
|
|
4291
|
+
try {
|
|
4292
|
+
writeFileSync4(file, JSON.stringify({ pid: process.pid, jobId: id, updatedAt: record.updatedAt }, null, 2) + "\n");
|
|
4293
|
+
} catch {
|
|
4294
|
+
}
|
|
4295
|
+
};
|
|
4296
|
+
upsert({});
|
|
4297
|
+
const timer = setInterval(() => upsert({ lastHeartbeatAt: now() }), 3e4);
|
|
4298
|
+
timer.unref?.();
|
|
4299
|
+
const cleanup = (status, error) => {
|
|
4300
|
+
clearInterval(timer);
|
|
4301
|
+
upsert({ status, error, lastHeartbeatAt: now() });
|
|
4302
|
+
releaseJobLock(options.type);
|
|
4303
|
+
};
|
|
4304
|
+
process.once("SIGTERM", () => {
|
|
4305
|
+
cleanup("cancelled");
|
|
4306
|
+
process.exit(0);
|
|
4307
|
+
});
|
|
4308
|
+
process.once("SIGINT", () => {
|
|
4309
|
+
cleanup("cancelled");
|
|
4310
|
+
process.exit(130);
|
|
4311
|
+
});
|
|
4312
|
+
process.once("exit", () => releaseJobLock(options.type));
|
|
4313
|
+
return {
|
|
4314
|
+
id,
|
|
4315
|
+
update(progress) {
|
|
4316
|
+
upsert({ progressCurrent: progress.current, progressTotal: progress.total, progressLabel: progress.label, lastHeartbeatAt: now() });
|
|
4317
|
+
},
|
|
4318
|
+
complete() {
|
|
4319
|
+
cleanup("completed");
|
|
4320
|
+
},
|
|
4321
|
+
fail(err) {
|
|
4322
|
+
cleanup("failed", err instanceof Error ? err.message : String(err));
|
|
4323
|
+
},
|
|
4324
|
+
cancel() {
|
|
4325
|
+
cleanup("cancelled");
|
|
4326
|
+
}
|
|
4327
|
+
};
|
|
4328
|
+
}
|
|
4329
|
+
async function politeBatchPause(ms = 250) {
|
|
4330
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
4331
|
+
}
|
|
4332
|
+
|
|
4182
4333
|
// src/bin/backfill-vectors.ts
|
|
4183
4334
|
var BATCH_SIZE = 100;
|
|
4184
|
-
var BACKFILL_FLAG =
|
|
4335
|
+
var BACKFILL_FLAG = path10.join(EXE_AI_DIR, "session-cache", "needs-backfill");
|
|
4185
4336
|
async function backfillVectors() {
|
|
4337
|
+
const job = startManagedJob({ type: "vector-backfill", name: "Vector embedding backfill", lowPriority: true });
|
|
4338
|
+
if (!job) {
|
|
4339
|
+
process.stderr.write("[backfill] Vector backfill is already running \u2014 exiting\n");
|
|
4340
|
+
return { processed: 0, failed: 0, remaining: -1 };
|
|
4341
|
+
}
|
|
4186
4342
|
if (!tryAcquireBackfillLock()) {
|
|
4187
4343
|
process.stderr.write("[backfill] Another backfill is already running \u2014 exiting\n");
|
|
4344
|
+
job.cancel();
|
|
4188
4345
|
return { processed: 0, failed: 0, remaining: -1 };
|
|
4189
4346
|
}
|
|
4190
4347
|
registerWorkerPid(process.pid);
|
|
@@ -4205,6 +4362,7 @@ async function backfillVectors() {
|
|
|
4205
4362
|
const connected = await connectEmbedDaemon();
|
|
4206
4363
|
if (!connected) {
|
|
4207
4364
|
process.stderr.write("[backfill] Cannot connect to embedding daemon \u2014 aborting\n");
|
|
4365
|
+
job.fail(new Error("Cannot connect to embedding daemon"));
|
|
4208
4366
|
return { processed: 0, failed: 0, remaining: -1 };
|
|
4209
4367
|
}
|
|
4210
4368
|
const client = getClient();
|
|
@@ -4218,6 +4376,7 @@ async function backfillVectors() {
|
|
|
4218
4376
|
if (batch.rows.length === 0) break;
|
|
4219
4377
|
process.stderr.write(`[backfill] Processing batch of ${batch.rows.length} memories...
|
|
4220
4378
|
`);
|
|
4379
|
+
job.update({ current: totalProcessed, label: `Processing batch of ${batch.rows.length} memories` });
|
|
4221
4380
|
for (const row of batch.rows) {
|
|
4222
4381
|
const id = row.id;
|
|
4223
4382
|
const rawText = row.raw_text;
|
|
@@ -4242,6 +4401,8 @@ async function backfillVectors() {
|
|
|
4242
4401
|
}
|
|
4243
4402
|
process.stderr.write(`[backfill] Batch done. Processed: ${totalProcessed}, Failed: ${totalFailed}
|
|
4244
4403
|
`);
|
|
4404
|
+
job.update({ current: totalProcessed, label: `Processed ${totalProcessed}, failed ${totalFailed}` });
|
|
4405
|
+
await politeBatchPause(500);
|
|
4245
4406
|
}
|
|
4246
4407
|
const remaining = await client.execute({
|
|
4247
4408
|
sql: "SELECT COUNT(*) as cnt FROM memories WHERE vector IS NULL",
|
|
@@ -4250,16 +4411,18 @@ async function backfillVectors() {
|
|
|
4250
4411
|
const remainingCount = Number(remaining.rows[0]?.cnt) || 0;
|
|
4251
4412
|
if (remainingCount === 0) {
|
|
4252
4413
|
try {
|
|
4253
|
-
|
|
4414
|
+
unlinkSync5(BACKFILL_FLAG);
|
|
4254
4415
|
} catch {
|
|
4255
4416
|
}
|
|
4256
4417
|
}
|
|
4257
4418
|
process.stderr.write(`[backfill] Complete. Processed: ${totalProcessed}, Failed: ${totalFailed}, Remaining: ${remainingCount}
|
|
4258
4419
|
`);
|
|
4420
|
+
if (totalFailed > 0) job.fail(new Error(`${totalFailed} embeddings failed`));
|
|
4421
|
+
else job.complete();
|
|
4259
4422
|
return { processed: totalProcessed, failed: totalFailed, remaining: remainingCount };
|
|
4260
4423
|
}
|
|
4261
4424
|
function isBackfillNeeded() {
|
|
4262
|
-
return
|
|
4425
|
+
return existsSync10(BACKFILL_FLAG);
|
|
4263
4426
|
}
|
|
4264
4427
|
if (isMainModule(import.meta.url)) {
|
|
4265
4428
|
backfillVectors().then((result) => {
|