@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.
@@ -3202,10 +3202,10 @@ function evictLRU() {
3202
3202
  }
3203
3203
  }
3204
3204
  function evictIdleShards() {
3205
- const now = Date.now();
3205
+ const now2 = Date.now();
3206
3206
  const toEvict = [];
3207
3207
  for (const [name, lastAccess] of _shardLastAccess) {
3208
- if (now - lastAccess > SHARD_IDLE_MS) {
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 now = (/* @__PURE__ */ new Date()).toISOString();
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, now, now]
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 now = (/* @__PURE__ */ new Date()).toISOString();
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: [now, id]
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: readFileSync5 } = __require("fs");
3698
- return readFileSync5("/etc/machine-id", "utf-8").trim();
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 now = (/* @__PURE__ */ new Date()).toISOString();
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
- now
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 now = Date.now();
3205
+ const now2 = Date.now();
3206
3206
  const toEvict = [];
3207
3207
  for (const [name, lastAccess] of _shardLastAccess) {
3208
- if (now - lastAccess > SHARD_IDLE_MS) {
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 now = (/* @__PURE__ */ new Date()).toISOString();
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, now, now]
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 now = (/* @__PURE__ */ new Date()).toISOString();
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: [now, id]
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: readFileSync5 } = __require("fs");
3822
- return readFileSync5("/etc/machine-id", "utf-8").trim();
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 now = (/* @__PURE__ */ new Date()).toISOString();
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
- now,
4216
- now
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) process.stderr.write(`[agentic-semantic-label] labeled ${count}
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) => {