@askexenow/exe-os 0.9.67 → 0.9.68
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/cli.js +1175 -855
- 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 +626 -220
- package/package.json +1 -1
|
@@ -3202,10 +3202,10 @@ function evictLRU() {
|
|
|
3202
3202
|
}
|
|
3203
3203
|
}
|
|
3204
3204
|
function evictIdleShards() {
|
|
3205
|
-
const
|
|
3205
|
+
const now2 = Date.now();
|
|
3206
3206
|
const toEvict = [];
|
|
3207
3207
|
for (const [name, lastAccess] of _shardLastAccess) {
|
|
3208
|
-
if (
|
|
3208
|
+
if (now2 - lastAccess > SHARD_IDLE_MS) {
|
|
3209
3209
|
toEvict.push(name);
|
|
3210
3210
|
}
|
|
3211
3211
|
}
|
|
@@ -3485,22 +3485,22 @@ ${sections.join("\n\n")}
|
|
|
3485
3485
|
}
|
|
3486
3486
|
async function storeGlobalProcedure(input) {
|
|
3487
3487
|
const id = randomUUID2();
|
|
3488
|
-
const
|
|
3488
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
3489
3489
|
const client = getClient();
|
|
3490
3490
|
await client.execute({
|
|
3491
3491
|
sql: `INSERT INTO company_procedures (id, title, content, priority, domain, active, created_at, updated_at)
|
|
3492
3492
|
VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
|
|
3493
|
-
args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null,
|
|
3493
|
+
args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null, now2, now2]
|
|
3494
3494
|
});
|
|
3495
3495
|
await loadGlobalProcedures();
|
|
3496
3496
|
return id;
|
|
3497
3497
|
}
|
|
3498
3498
|
async function deactivateGlobalProcedure(id) {
|
|
3499
|
-
const
|
|
3499
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
3500
3500
|
const client = getClient();
|
|
3501
3501
|
const result = await client.execute({
|
|
3502
3502
|
sql: "UPDATE company_procedures SET active = 0, updated_at = ? WHERE id = ?",
|
|
3503
|
-
args: [
|
|
3503
|
+
args: [now2, id]
|
|
3504
3504
|
});
|
|
3505
3505
|
await loadGlobalProcedures();
|
|
3506
3506
|
return result.rowsAffected > 0;
|
|
@@ -3694,8 +3694,8 @@ function deriveMachineKey() {
|
|
|
3694
3694
|
}
|
|
3695
3695
|
function readMachineId() {
|
|
3696
3696
|
try {
|
|
3697
|
-
const { readFileSync:
|
|
3698
|
-
return
|
|
3697
|
+
const { readFileSync: readFileSync6 } = __require("fs");
|
|
3698
|
+
return readFileSync6("/etc/machine-id", "utf-8").trim();
|
|
3699
3699
|
} catch {
|
|
3700
3700
|
return "";
|
|
3701
3701
|
}
|
|
@@ -4062,7 +4062,7 @@ async function resolveClient(client) {
|
|
|
4062
4062
|
}
|
|
4063
4063
|
async function insertReflectionCheckpoint(checkpoint, client) {
|
|
4064
4064
|
const db = await resolveClient(client);
|
|
4065
|
-
const
|
|
4065
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
4066
4066
|
await db.execute({
|
|
4067
4067
|
sql: `INSERT INTO agent_reflection_checkpoints
|
|
4068
4068
|
(id, project_name, session_id, window_start_at, window_end_at, event_count, goal_count,
|
|
@@ -4087,7 +4087,7 @@ async function insertReflectionCheckpoint(checkpoint, client) {
|
|
|
4087
4087
|
JSON.stringify(checkpoint.nextActions),
|
|
4088
4088
|
JSON.stringify(checkpoint.evidenceEventIds),
|
|
4089
4089
|
checkpoint.confidence,
|
|
4090
|
-
|
|
4090
|
+
now2
|
|
4091
4091
|
]
|
|
4092
4092
|
});
|
|
4093
4093
|
}
|
|
@@ -4127,14 +4127,169 @@ async function generateReflectionCheckpoints(opts = {}) {
|
|
|
4127
4127
|
return inserted;
|
|
4128
4128
|
}
|
|
4129
4129
|
|
|
4130
|
+
// src/lib/background-jobs.ts
|
|
4131
|
+
init_config();
|
|
4132
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3, unlinkSync as unlinkSync3 } from "fs";
|
|
4133
|
+
import { execFileSync } from "child_process";
|
|
4134
|
+
import os6 from "os";
|
|
4135
|
+
import path8 from "path";
|
|
4136
|
+
var JOB_DIR = path8.join(EXE_AI_DIR, "jobs");
|
|
4137
|
+
var JOBS_FILE = path8.join(JOB_DIR, "jobs.json");
|
|
4138
|
+
var LOCK_DIR = path8.join(JOB_DIR, "locks");
|
|
4139
|
+
var DEFAULT_LOCK_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
4140
|
+
var MAX_HISTORY = 200;
|
|
4141
|
+
function ensureDirs() {
|
|
4142
|
+
mkdirSync3(LOCK_DIR, { recursive: true });
|
|
4143
|
+
}
|
|
4144
|
+
function now() {
|
|
4145
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
4146
|
+
}
|
|
4147
|
+
function isAlive(pid) {
|
|
4148
|
+
if (!pid || pid <= 0) return false;
|
|
4149
|
+
try {
|
|
4150
|
+
process.kill(pid, 0);
|
|
4151
|
+
return true;
|
|
4152
|
+
} catch {
|
|
4153
|
+
return false;
|
|
4154
|
+
}
|
|
4155
|
+
}
|
|
4156
|
+
function readJobsRaw() {
|
|
4157
|
+
ensureDirs();
|
|
4158
|
+
if (!existsSync8(JOBS_FILE)) return [];
|
|
4159
|
+
try {
|
|
4160
|
+
const parsed = JSON.parse(readFileSync5(JOBS_FILE, "utf8"));
|
|
4161
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
4162
|
+
} catch {
|
|
4163
|
+
return [];
|
|
4164
|
+
}
|
|
4165
|
+
}
|
|
4166
|
+
function writeJobsRaw(jobs) {
|
|
4167
|
+
ensureDirs();
|
|
4168
|
+
const running = jobs.filter((j) => j.status === "running");
|
|
4169
|
+
const rest = jobs.filter((j) => j.status !== "running").slice(-MAX_HISTORY);
|
|
4170
|
+
writeFileSync3(JOBS_FILE, JSON.stringify([...rest, ...running], null, 2) + "\n");
|
|
4171
|
+
}
|
|
4172
|
+
function lockPath(type) {
|
|
4173
|
+
return path8.join(LOCK_DIR, `${type.replace(/[^a-zA-Z0-9_.-]/g, "_")}.lock`);
|
|
4174
|
+
}
|
|
4175
|
+
function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
4176
|
+
ensureDirs();
|
|
4177
|
+
const file = lockPath(type);
|
|
4178
|
+
if (existsSync8(file)) {
|
|
4179
|
+
try {
|
|
4180
|
+
const lock = JSON.parse(readFileSync5(file, "utf8"));
|
|
4181
|
+
const age = Date.now() - Date.parse(lock.updatedAt ?? "");
|
|
4182
|
+
if (lock.pid && isAlive(lock.pid) && Number.isFinite(age) && age < ttlMs) return false;
|
|
4183
|
+
} catch {
|
|
4184
|
+
}
|
|
4185
|
+
try {
|
|
4186
|
+
unlinkSync3(file);
|
|
4187
|
+
} catch {
|
|
4188
|
+
}
|
|
4189
|
+
}
|
|
4190
|
+
try {
|
|
4191
|
+
writeFileSync3(file, JSON.stringify({ pid: process.pid, updatedAt: now() }, null, 2) + "\n", { flag: "wx" });
|
|
4192
|
+
return true;
|
|
4193
|
+
} catch {
|
|
4194
|
+
return false;
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
function releaseJobLock(type) {
|
|
4198
|
+
const file = lockPath(type);
|
|
4199
|
+
try {
|
|
4200
|
+
if (!existsSync8(file)) return;
|
|
4201
|
+
const lock = JSON.parse(readFileSync5(file, "utf8"));
|
|
4202
|
+
if (lock.pid === process.pid || !lock.pid || !isAlive(lock.pid)) unlinkSync3(file);
|
|
4203
|
+
} catch {
|
|
4204
|
+
try {
|
|
4205
|
+
unlinkSync3(file);
|
|
4206
|
+
} catch {
|
|
4207
|
+
}
|
|
4208
|
+
}
|
|
4209
|
+
}
|
|
4210
|
+
function startManagedJob(options) {
|
|
4211
|
+
const lowPriority = options.lowPriority ?? true;
|
|
4212
|
+
if (!acquireJobLock(options.type, options.lockTtlMs)) return null;
|
|
4213
|
+
if (lowPriority) {
|
|
4214
|
+
try {
|
|
4215
|
+
os6.setPriority(process.pid, 10);
|
|
4216
|
+
} catch {
|
|
4217
|
+
}
|
|
4218
|
+
}
|
|
4219
|
+
const id = `${options.type}-${Date.now()}-${process.pid}`.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
4220
|
+
const record = {
|
|
4221
|
+
id,
|
|
4222
|
+
type: options.type,
|
|
4223
|
+
name: options.name,
|
|
4224
|
+
pid: process.pid,
|
|
4225
|
+
command: options.command ?? process.argv.join(" "),
|
|
4226
|
+
cwd: process.cwd(),
|
|
4227
|
+
status: "running",
|
|
4228
|
+
startedAt: now(),
|
|
4229
|
+
updatedAt: now(),
|
|
4230
|
+
lastHeartbeatAt: now(),
|
|
4231
|
+
cancelCommand: `exe-os jobs cancel ${id}`,
|
|
4232
|
+
lowPriority
|
|
4233
|
+
};
|
|
4234
|
+
const upsert = (patch) => {
|
|
4235
|
+
const jobs = readJobsRaw().filter((j) => j.id !== id);
|
|
4236
|
+
Object.assign(record, patch, { updatedAt: now() });
|
|
4237
|
+
writeJobsRaw([...jobs, record]);
|
|
4238
|
+
const file = lockPath(options.type);
|
|
4239
|
+
try {
|
|
4240
|
+
writeFileSync3(file, JSON.stringify({ pid: process.pid, jobId: id, updatedAt: record.updatedAt }, null, 2) + "\n");
|
|
4241
|
+
} catch {
|
|
4242
|
+
}
|
|
4243
|
+
};
|
|
4244
|
+
upsert({});
|
|
4245
|
+
const timer = setInterval(() => upsert({ lastHeartbeatAt: now() }), 3e4);
|
|
4246
|
+
timer.unref?.();
|
|
4247
|
+
const cleanup = (status, error) => {
|
|
4248
|
+
clearInterval(timer);
|
|
4249
|
+
upsert({ status, error, lastHeartbeatAt: now() });
|
|
4250
|
+
releaseJobLock(options.type);
|
|
4251
|
+
};
|
|
4252
|
+
process.once("SIGTERM", () => {
|
|
4253
|
+
cleanup("cancelled");
|
|
4254
|
+
process.exit(0);
|
|
4255
|
+
});
|
|
4256
|
+
process.once("SIGINT", () => {
|
|
4257
|
+
cleanup("cancelled");
|
|
4258
|
+
process.exit(130);
|
|
4259
|
+
});
|
|
4260
|
+
process.once("exit", () => releaseJobLock(options.type));
|
|
4261
|
+
return {
|
|
4262
|
+
id,
|
|
4263
|
+
update(progress) {
|
|
4264
|
+
upsert({ progressCurrent: progress.current, progressTotal: progress.total, progressLabel: progress.label, lastHeartbeatAt: now() });
|
|
4265
|
+
},
|
|
4266
|
+
complete() {
|
|
4267
|
+
cleanup("completed");
|
|
4268
|
+
},
|
|
4269
|
+
fail(err) {
|
|
4270
|
+
cleanup("failed", err instanceof Error ? err.message : String(err));
|
|
4271
|
+
},
|
|
4272
|
+
cancel() {
|
|
4273
|
+
cleanup("cancelled");
|
|
4274
|
+
}
|
|
4275
|
+
};
|
|
4276
|
+
}
|
|
4277
|
+
|
|
4130
4278
|
// src/bin/agentic-reflection-backfill.ts
|
|
4131
4279
|
async function main() {
|
|
4280
|
+
const job = startManagedJob({ type: "agentic-reflection-backfill", name: "Agentic reflection checkpoint backfill", lowPriority: true });
|
|
4281
|
+
if (!job) {
|
|
4282
|
+
process.stderr.write("[agentic-reflection-backfill] Another reflection backfill is already running.\n");
|
|
4283
|
+
return;
|
|
4284
|
+
}
|
|
4132
4285
|
const projectName = process.argv.includes("--project") ? process.argv[process.argv.indexOf("--project") + 1] : void 0;
|
|
4133
4286
|
const limitArg = process.argv.includes("--limit") ? process.argv[process.argv.indexOf("--limit") + 1] : void 0;
|
|
4134
4287
|
await initStore();
|
|
4135
4288
|
const inserted = await generateReflectionCheckpoints({ projectName, limit: limitArg ? Number(limitArg) : void 0 });
|
|
4136
4289
|
process.stderr.write(`[agentic-reflection-backfill] Inserted/updated ${inserted} reflection checkpoints.
|
|
4137
4290
|
`);
|
|
4291
|
+
job.update({ current: inserted, label: `Inserted/updated ${inserted} reflection checkpoints` });
|
|
4292
|
+
job.complete();
|
|
4138
4293
|
process.exit(0);
|
|
4139
4294
|
}
|
|
4140
4295
|
main().catch((err) => {
|
|
@@ -3202,10 +3202,10 @@ function evictLRU() {
|
|
|
3202
3202
|
}
|
|
3203
3203
|
}
|
|
3204
3204
|
function evictIdleShards() {
|
|
3205
|
-
const
|
|
3205
|
+
const now2 = Date.now();
|
|
3206
3206
|
const toEvict = [];
|
|
3207
3207
|
for (const [name, lastAccess] of _shardLastAccess) {
|
|
3208
|
-
if (
|
|
3208
|
+
if (now2 - lastAccess > SHARD_IDLE_MS) {
|
|
3209
3209
|
toEvict.push(name);
|
|
3210
3210
|
}
|
|
3211
3211
|
}
|
|
@@ -3485,22 +3485,22 @@ ${sections.join("\n\n")}
|
|
|
3485
3485
|
}
|
|
3486
3486
|
async function storeGlobalProcedure(input) {
|
|
3487
3487
|
const id = randomUUID2();
|
|
3488
|
-
const
|
|
3488
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
3489
3489
|
const client = getClient();
|
|
3490
3490
|
await client.execute({
|
|
3491
3491
|
sql: `INSERT INTO company_procedures (id, title, content, priority, domain, active, created_at, updated_at)
|
|
3492
3492
|
VALUES (?, ?, ?, ?, ?, 1, ?, ?)`,
|
|
3493
|
-
args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null,
|
|
3493
|
+
args: [id, input.title, input.content, input.priority ?? "p0", input.domain ?? null, now2, now2]
|
|
3494
3494
|
});
|
|
3495
3495
|
await loadGlobalProcedures();
|
|
3496
3496
|
return id;
|
|
3497
3497
|
}
|
|
3498
3498
|
async function deactivateGlobalProcedure(id) {
|
|
3499
|
-
const
|
|
3499
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
3500
3500
|
const client = getClient();
|
|
3501
3501
|
const result = await client.execute({
|
|
3502
3502
|
sql: "UPDATE company_procedures SET active = 0, updated_at = ? WHERE id = ?",
|
|
3503
|
-
args: [
|
|
3503
|
+
args: [now2, id]
|
|
3504
3504
|
});
|
|
3505
3505
|
await loadGlobalProcedures();
|
|
3506
3506
|
return result.rowsAffected > 0;
|
|
@@ -3818,8 +3818,8 @@ function deriveMachineKey() {
|
|
|
3818
3818
|
}
|
|
3819
3819
|
function readMachineId() {
|
|
3820
3820
|
try {
|
|
3821
|
-
const { readFileSync:
|
|
3822
|
-
return
|
|
3821
|
+
const { readFileSync: readFileSync6 } = __require("fs");
|
|
3822
|
+
return readFileSync6("/etc/machine-id", "utf-8").trim();
|
|
3823
3823
|
} catch {
|
|
3824
3824
|
return "";
|
|
3825
3825
|
}
|
|
@@ -4197,7 +4197,7 @@ async function resolveClient(client) {
|
|
|
4197
4197
|
async function upsertSemanticLabel(row, label, client) {
|
|
4198
4198
|
const db = await resolveClient(client);
|
|
4199
4199
|
const eventId = stableId("event", row.id);
|
|
4200
|
-
const
|
|
4200
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
4201
4201
|
await db.execute({
|
|
4202
4202
|
sql: `INSERT INTO agent_semantic_labels
|
|
4203
4203
|
(id, source_memory_id, event_id, labeler, schema_version, confidence, labels, created_at, updated_at)
|
|
@@ -4212,8 +4212,8 @@ async function upsertSemanticLabel(row, label, client) {
|
|
|
4212
4212
|
label.schemaVersion,
|
|
4213
4213
|
label.confidence,
|
|
4214
4214
|
JSON.stringify(label),
|
|
4215
|
-
|
|
4216
|
-
|
|
4215
|
+
now2,
|
|
4216
|
+
now2
|
|
4217
4217
|
]
|
|
4218
4218
|
});
|
|
4219
4219
|
if (label.labeler === "llm") {
|
|
@@ -4226,6 +4226,157 @@ async function upsertSemanticLabel(row, label, client) {
|
|
|
4226
4226
|
}
|
|
4227
4227
|
}
|
|
4228
4228
|
|
|
4229
|
+
// src/lib/background-jobs.ts
|
|
4230
|
+
init_config();
|
|
4231
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3, unlinkSync as unlinkSync3 } from "fs";
|
|
4232
|
+
import { execFileSync } from "child_process";
|
|
4233
|
+
import os6 from "os";
|
|
4234
|
+
import path8 from "path";
|
|
4235
|
+
var JOB_DIR = path8.join(EXE_AI_DIR, "jobs");
|
|
4236
|
+
var JOBS_FILE = path8.join(JOB_DIR, "jobs.json");
|
|
4237
|
+
var LOCK_DIR = path8.join(JOB_DIR, "locks");
|
|
4238
|
+
var DEFAULT_LOCK_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
4239
|
+
var MAX_HISTORY = 200;
|
|
4240
|
+
function ensureDirs() {
|
|
4241
|
+
mkdirSync3(LOCK_DIR, { recursive: true });
|
|
4242
|
+
}
|
|
4243
|
+
function now() {
|
|
4244
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
4245
|
+
}
|
|
4246
|
+
function isAlive(pid) {
|
|
4247
|
+
if (!pid || pid <= 0) return false;
|
|
4248
|
+
try {
|
|
4249
|
+
process.kill(pid, 0);
|
|
4250
|
+
return true;
|
|
4251
|
+
} catch {
|
|
4252
|
+
return false;
|
|
4253
|
+
}
|
|
4254
|
+
}
|
|
4255
|
+
function readJobsRaw() {
|
|
4256
|
+
ensureDirs();
|
|
4257
|
+
if (!existsSync8(JOBS_FILE)) return [];
|
|
4258
|
+
try {
|
|
4259
|
+
const parsed = JSON.parse(readFileSync5(JOBS_FILE, "utf8"));
|
|
4260
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
4261
|
+
} catch {
|
|
4262
|
+
return [];
|
|
4263
|
+
}
|
|
4264
|
+
}
|
|
4265
|
+
function writeJobsRaw(jobs) {
|
|
4266
|
+
ensureDirs();
|
|
4267
|
+
const running = jobs.filter((j) => j.status === "running");
|
|
4268
|
+
const rest = jobs.filter((j) => j.status !== "running").slice(-MAX_HISTORY);
|
|
4269
|
+
writeFileSync3(JOBS_FILE, JSON.stringify([...rest, ...running], null, 2) + "\n");
|
|
4270
|
+
}
|
|
4271
|
+
function lockPath(type) {
|
|
4272
|
+
return path8.join(LOCK_DIR, `${type.replace(/[^a-zA-Z0-9_.-]/g, "_")}.lock`);
|
|
4273
|
+
}
|
|
4274
|
+
function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
4275
|
+
ensureDirs();
|
|
4276
|
+
const file = lockPath(type);
|
|
4277
|
+
if (existsSync8(file)) {
|
|
4278
|
+
try {
|
|
4279
|
+
const lock = JSON.parse(readFileSync5(file, "utf8"));
|
|
4280
|
+
const age = Date.now() - Date.parse(lock.updatedAt ?? "");
|
|
4281
|
+
if (lock.pid && isAlive(lock.pid) && Number.isFinite(age) && age < ttlMs) return false;
|
|
4282
|
+
} catch {
|
|
4283
|
+
}
|
|
4284
|
+
try {
|
|
4285
|
+
unlinkSync3(file);
|
|
4286
|
+
} catch {
|
|
4287
|
+
}
|
|
4288
|
+
}
|
|
4289
|
+
try {
|
|
4290
|
+
writeFileSync3(file, JSON.stringify({ pid: process.pid, updatedAt: now() }, null, 2) + "\n", { flag: "wx" });
|
|
4291
|
+
return true;
|
|
4292
|
+
} catch {
|
|
4293
|
+
return false;
|
|
4294
|
+
}
|
|
4295
|
+
}
|
|
4296
|
+
function releaseJobLock(type) {
|
|
4297
|
+
const file = lockPath(type);
|
|
4298
|
+
try {
|
|
4299
|
+
if (!existsSync8(file)) return;
|
|
4300
|
+
const lock = JSON.parse(readFileSync5(file, "utf8"));
|
|
4301
|
+
if (lock.pid === process.pid || !lock.pid || !isAlive(lock.pid)) unlinkSync3(file);
|
|
4302
|
+
} catch {
|
|
4303
|
+
try {
|
|
4304
|
+
unlinkSync3(file);
|
|
4305
|
+
} catch {
|
|
4306
|
+
}
|
|
4307
|
+
}
|
|
4308
|
+
}
|
|
4309
|
+
function startManagedJob(options) {
|
|
4310
|
+
const lowPriority = options.lowPriority ?? true;
|
|
4311
|
+
if (!acquireJobLock(options.type, options.lockTtlMs)) return null;
|
|
4312
|
+
if (lowPriority) {
|
|
4313
|
+
try {
|
|
4314
|
+
os6.setPriority(process.pid, 10);
|
|
4315
|
+
} catch {
|
|
4316
|
+
}
|
|
4317
|
+
}
|
|
4318
|
+
const id = `${options.type}-${Date.now()}-${process.pid}`.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
4319
|
+
const record = {
|
|
4320
|
+
id,
|
|
4321
|
+
type: options.type,
|
|
4322
|
+
name: options.name,
|
|
4323
|
+
pid: process.pid,
|
|
4324
|
+
command: options.command ?? process.argv.join(" "),
|
|
4325
|
+
cwd: process.cwd(),
|
|
4326
|
+
status: "running",
|
|
4327
|
+
startedAt: now(),
|
|
4328
|
+
updatedAt: now(),
|
|
4329
|
+
lastHeartbeatAt: now(),
|
|
4330
|
+
cancelCommand: `exe-os jobs cancel ${id}`,
|
|
4331
|
+
lowPriority
|
|
4332
|
+
};
|
|
4333
|
+
const upsert = (patch) => {
|
|
4334
|
+
const jobs = readJobsRaw().filter((j) => j.id !== id);
|
|
4335
|
+
Object.assign(record, patch, { updatedAt: now() });
|
|
4336
|
+
writeJobsRaw([...jobs, record]);
|
|
4337
|
+
const file = lockPath(options.type);
|
|
4338
|
+
try {
|
|
4339
|
+
writeFileSync3(file, JSON.stringify({ pid: process.pid, jobId: id, updatedAt: record.updatedAt }, null, 2) + "\n");
|
|
4340
|
+
} catch {
|
|
4341
|
+
}
|
|
4342
|
+
};
|
|
4343
|
+
upsert({});
|
|
4344
|
+
const timer = setInterval(() => upsert({ lastHeartbeatAt: now() }), 3e4);
|
|
4345
|
+
timer.unref?.();
|
|
4346
|
+
const cleanup = (status, error) => {
|
|
4347
|
+
clearInterval(timer);
|
|
4348
|
+
upsert({ status, error, lastHeartbeatAt: now() });
|
|
4349
|
+
releaseJobLock(options.type);
|
|
4350
|
+
};
|
|
4351
|
+
process.once("SIGTERM", () => {
|
|
4352
|
+
cleanup("cancelled");
|
|
4353
|
+
process.exit(0);
|
|
4354
|
+
});
|
|
4355
|
+
process.once("SIGINT", () => {
|
|
4356
|
+
cleanup("cancelled");
|
|
4357
|
+
process.exit(130);
|
|
4358
|
+
});
|
|
4359
|
+
process.once("exit", () => releaseJobLock(options.type));
|
|
4360
|
+
return {
|
|
4361
|
+
id,
|
|
4362
|
+
update(progress) {
|
|
4363
|
+
upsert({ progressCurrent: progress.current, progressTotal: progress.total, progressLabel: progress.label, lastHeartbeatAt: now() });
|
|
4364
|
+
},
|
|
4365
|
+
complete() {
|
|
4366
|
+
cleanup("completed");
|
|
4367
|
+
},
|
|
4368
|
+
fail(err) {
|
|
4369
|
+
cleanup("failed", err instanceof Error ? err.message : String(err));
|
|
4370
|
+
},
|
|
4371
|
+
cancel() {
|
|
4372
|
+
cleanup("cancelled");
|
|
4373
|
+
}
|
|
4374
|
+
};
|
|
4375
|
+
}
|
|
4376
|
+
async function politeBatchPause(ms = 250) {
|
|
4377
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
4378
|
+
}
|
|
4379
|
+
|
|
4229
4380
|
// src/bin/agentic-semantic-label.ts
|
|
4230
4381
|
function arg(name) {
|
|
4231
4382
|
const i = process.argv.indexOf(name);
|
|
@@ -4235,6 +4386,11 @@ async function main() {
|
|
|
4235
4386
|
const limit = Number(arg("--limit") ?? "100");
|
|
4236
4387
|
const project = arg("--project");
|
|
4237
4388
|
const llm = process.argv.includes("--llm");
|
|
4389
|
+
const job = startManagedJob({ type: "agentic-semantic-label", name: "Agentic semantic label pass", lowPriority: true });
|
|
4390
|
+
if (!job) {
|
|
4391
|
+
process.stderr.write("[agentic-semantic-label] Another semantic label job is already running.\n");
|
|
4392
|
+
return;
|
|
4393
|
+
}
|
|
4238
4394
|
await initStore();
|
|
4239
4395
|
const db = getClient();
|
|
4240
4396
|
const where = project ? "WHERE project_name = ?" : "";
|
|
@@ -4251,11 +4407,16 @@ async function main() {
|
|
|
4251
4407
|
const label = llm ? await labelMemoryWithLlm(row) : inferSemanticLabel(row);
|
|
4252
4408
|
await upsertSemanticLabel(row, label, db);
|
|
4253
4409
|
count++;
|
|
4254
|
-
if (count % 25 === 0)
|
|
4410
|
+
if (count % 25 === 0) {
|
|
4411
|
+
process.stderr.write(`[agentic-semantic-label] labeled ${count}
|
|
4255
4412
|
`);
|
|
4413
|
+
job.update({ current: count, total: limit, label: `Labeled ${count}/${limit}` });
|
|
4414
|
+
await politeBatchPause(250);
|
|
4415
|
+
}
|
|
4256
4416
|
}
|
|
4257
4417
|
process.stderr.write(`[agentic-semantic-label] Complete: ${count} memories labeled (${llm ? "llm-if-configured" : "deterministic"}).
|
|
4258
4418
|
`);
|
|
4419
|
+
job.complete();
|
|
4259
4420
|
process.exit(0);
|
|
4260
4421
|
}
|
|
4261
4422
|
main().catch((err) => {
|