@askexenow/exe-os 0.9.87 → 0.9.88

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.
Files changed (101) hide show
  1. package/deploy/compose/docker-compose.yml +3 -3
  2. package/dist/bin/age-ontology-load.js +8 -2
  3. package/dist/bin/agentic-ontology-backfill.js +11 -0
  4. package/dist/bin/agentic-reflection-backfill.js +11 -0
  5. package/dist/bin/agentic-semantic-label.js +11 -0
  6. package/dist/bin/backfill-conversations.js +12 -0
  7. package/dist/bin/backfill-responses.js +12 -0
  8. package/dist/bin/backfill-vectors.js +12 -0
  9. package/dist/bin/bulk-sync-postgres.js +29 -1
  10. package/dist/bin/cc-doctor.js +3 -2
  11. package/dist/bin/cleanup-stale-review-tasks.js +12 -0
  12. package/dist/bin/cli.js +170 -15
  13. package/dist/bin/exe-agent.js +1 -0
  14. package/dist/bin/exe-assign.js +12 -0
  15. package/dist/bin/exe-boot.js +139 -4
  16. package/dist/bin/exe-call.js +2 -0
  17. package/dist/bin/exe-cloud.js +138 -3
  18. package/dist/bin/exe-dispatch.js +12 -1
  19. package/dist/bin/exe-doctor.js +12 -0
  20. package/dist/bin/exe-export-behaviors.js +11 -0
  21. package/dist/bin/exe-forget.js +12 -0
  22. package/dist/bin/exe-gateway.js +132 -35
  23. package/dist/bin/exe-healthcheck.js +2 -1
  24. package/dist/bin/exe-heartbeat.js +12 -0
  25. package/dist/bin/exe-kill.js +11 -0
  26. package/dist/bin/exe-launch-agent.js +11 -0
  27. package/dist/bin/exe-new-employee.js +4 -2
  28. package/dist/bin/exe-pending-messages.js +11 -0
  29. package/dist/bin/exe-pending-notifications.js +12 -0
  30. package/dist/bin/exe-pending-reviews.js +12 -0
  31. package/dist/bin/exe-rename.js +12 -0
  32. package/dist/bin/exe-review.js +12 -0
  33. package/dist/bin/exe-search.js +12 -0
  34. package/dist/bin/exe-session-cleanup.js +12 -1
  35. package/dist/bin/exe-settings.js +3 -0
  36. package/dist/bin/exe-start-codex.js +13 -2
  37. package/dist/bin/exe-start-opencode.js +13 -2
  38. package/dist/bin/exe-status.js +12 -0
  39. package/dist/bin/exe-team.js +12 -0
  40. package/dist/bin/git-sweep.js +12 -1
  41. package/dist/bin/graph-backfill.js +11 -0
  42. package/dist/bin/graph-export.js +11 -0
  43. package/dist/bin/graph-layer-benchmark.js +9 -1
  44. package/dist/bin/intercom-check.js +13 -1
  45. package/dist/bin/list-providers.js +1 -0
  46. package/dist/bin/postgres-agentic-reflection-backfill.js +7 -1
  47. package/dist/bin/postgres-agentic-semantic-backfill.js +7 -1
  48. package/dist/bin/registry-proxy.js +1 -0
  49. package/dist/bin/scan-tasks.js +13 -1
  50. package/dist/bin/setup.js +141 -7
  51. package/dist/bin/shard-migrate.js +11 -0
  52. package/dist/bin/stack-update.js +24 -7
  53. package/dist/bin/update.js +5 -0
  54. package/dist/gateway/index.js +12 -1
  55. package/dist/hooks/bug-report-worker.js +12 -1
  56. package/dist/hooks/codex-stop-task-finalizer.js +12 -1
  57. package/dist/hooks/commit-complete.js +12 -1
  58. package/dist/hooks/error-recall.js +11 -0
  59. package/dist/hooks/ingest.js +11 -0
  60. package/dist/hooks/instructions-loaded.js +11 -0
  61. package/dist/hooks/notification.js +11 -0
  62. package/dist/hooks/post-compact.js +11 -0
  63. package/dist/hooks/post-tool-combined.js +11 -0
  64. package/dist/hooks/pre-compact.js +12 -1
  65. package/dist/hooks/pre-tool-use.js +11 -0
  66. package/dist/hooks/prompt-submit.js +12 -1
  67. package/dist/hooks/session-end.js +12 -1
  68. package/dist/hooks/session-start.js +11 -0
  69. package/dist/hooks/stop.js +11 -0
  70. package/dist/hooks/subagent-stop.js +11 -0
  71. package/dist/hooks/summary-worker.js +137 -3
  72. package/dist/index.js +12 -1
  73. package/dist/lib/cloud-sync.js +136 -2
  74. package/dist/lib/consolidation.js +1 -0
  75. package/dist/lib/database.js +11 -0
  76. package/dist/lib/db.js +11 -0
  77. package/dist/lib/device-registry.js +11 -0
  78. package/dist/lib/employee-templates.js +1 -0
  79. package/dist/lib/exe-daemon.js +749 -45
  80. package/dist/lib/hybrid-search.js +11 -0
  81. package/dist/lib/identity.js +1 -0
  82. package/dist/lib/messaging.js +2 -1
  83. package/dist/lib/reminders.js +1 -0
  84. package/dist/lib/schedules.js +11 -0
  85. package/dist/lib/skill-learning.js +1 -0
  86. package/dist/lib/store.js +11 -0
  87. package/dist/lib/tasks.js +2 -1
  88. package/dist/lib/tmux-routing.js +2 -1
  89. package/dist/lib/token-spend.js +1 -0
  90. package/dist/mcp/server.js +613 -27
  91. package/dist/mcp/tools/complete-reminder.js +1 -0
  92. package/dist/mcp/tools/create-reminder.js +1 -0
  93. package/dist/mcp/tools/create-task.js +2 -1
  94. package/dist/mcp/tools/deactivate-behavior.js +1 -0
  95. package/dist/mcp/tools/list-reminders.js +1 -0
  96. package/dist/mcp/tools/list-tasks.js +1 -0
  97. package/dist/mcp/tools/send-message.js +2 -1
  98. package/dist/mcp/tools/update-task.js +2 -1
  99. package/dist/runtime/index.js +12 -1
  100. package/dist/tui/App.js +12 -1
  101. package/package.json +2 -2
@@ -26,6 +26,21 @@ var __copyProps = (to, from, except, desc) => {
26
26
  };
27
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
28
 
29
+ // src/lib/pg-ssl.ts
30
+ var pg_ssl_exports = {};
31
+ __export(pg_ssl_exports, {
32
+ pgSslConfig: () => pgSslConfig
33
+ });
34
+ function pgSslConfig() {
35
+ if (process.env.EXE_DB_SSL_DISABLED === "true") return {};
36
+ return { ssl: { rejectUnauthorized: process.env.EXE_DB_SSL_ALLOW_SELFSIGNED !== "true" } };
37
+ }
38
+ var init_pg_ssl = __esm({
39
+ "src/lib/pg-ssl.ts"() {
40
+ "use strict";
41
+ }
42
+ });
43
+
29
44
  // src/lib/state-bus.ts
30
45
  var StateBus, orgBus;
31
46
  var init_state_bus = __esm({
@@ -1664,7 +1679,7 @@ var init_memory = __esm({
1664
1679
  });
1665
1680
 
1666
1681
  // src/lib/daemon-auth.ts
1667
- import crypto from "crypto";
1682
+ import crypto2 from "crypto";
1668
1683
  import path6 from "path";
1669
1684
  import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
1670
1685
  function normalizeToken(token) {
@@ -1683,7 +1698,7 @@ function readDaemonToken() {
1683
1698
  function ensureDaemonToken(seed) {
1684
1699
  const existing = readDaemonToken();
1685
1700
  if (existing) return existing;
1686
- const token = normalizeToken(seed) ?? crypto.randomBytes(32).toString("hex");
1701
+ const token = normalizeToken(seed) ?? crypto2.randomBytes(32).toString("hex");
1687
1702
  ensurePrivateDirSync(EXE_AI_DIR);
1688
1703
  writeFileSync3(DAEMON_TOKEN_PATH, `${token}
1689
1704
  `, "utf8");
@@ -2358,6 +2373,7 @@ __export(database_exports, {
2358
2373
  isInitialized: () => isInitialized,
2359
2374
  setExternalClient: () => setExternalClient
2360
2375
  });
2376
+ import { chmodSync as chmodSync2 } from "fs";
2361
2377
  import { createClient } from "@libsql/client";
2362
2378
  async function initDatabase(config2) {
2363
2379
  if (_walCheckpointTimer) {
@@ -2399,6 +2415,16 @@ async function initDatabase(config2) {
2399
2415
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") {
2400
2416
  _adapterClient = await createPrismaDbAdapter(_resilientClient);
2401
2417
  }
2418
+ try {
2419
+ chmodSync2(config2.dbPath, 384);
2420
+ for (const suffix of ["-wal", "-shm"]) {
2421
+ try {
2422
+ chmodSync2(config2.dbPath + suffix, 384);
2423
+ } catch {
2424
+ }
2425
+ }
2426
+ } catch {
2427
+ }
2402
2428
  }
2403
2429
  function isInitialized() {
2404
2430
  return _adapterClient !== null || _client !== null;
@@ -3960,7 +3986,7 @@ async function tryKeytar() {
3960
3986
  }
3961
3987
  function deriveMachineKey() {
3962
3988
  try {
3963
- const crypto10 = __require("crypto");
3989
+ const crypto11 = __require("crypto");
3964
3990
  const material = [
3965
3991
  os6.hostname(),
3966
3992
  os6.userInfo().username,
@@ -3969,7 +3995,7 @@ function deriveMachineKey() {
3969
3995
  // Machine ID on Linux (stable across reboots)
3970
3996
  process.platform === "linux" ? readMachineId() : ""
3971
3997
  ].join("|");
3972
- return crypto10.createHash("sha256").update(material).digest();
3998
+ return crypto11.createHash("sha256").update(material).digest();
3973
3999
  } catch {
3974
4000
  return null;
3975
4001
  }
@@ -3983,9 +4009,9 @@ function readMachineId() {
3983
4009
  }
3984
4010
  }
3985
4011
  function encryptWithMachineKey(plaintext, machineKey) {
3986
- const crypto10 = __require("crypto");
3987
- const iv = crypto10.randomBytes(12);
3988
- const cipher = crypto10.createCipheriv("aes-256-gcm", machineKey, iv);
4012
+ const crypto11 = __require("crypto");
4013
+ const iv = crypto11.randomBytes(12);
4014
+ const cipher = crypto11.createCipheriv("aes-256-gcm", machineKey, iv);
3989
4015
  let encrypted = cipher.update(plaintext, "utf-8", "base64");
3990
4016
  encrypted += cipher.final("base64");
3991
4017
  const authTag = cipher.getAuthTag().toString("base64");
@@ -3994,13 +4020,13 @@ function encryptWithMachineKey(plaintext, machineKey) {
3994
4020
  function decryptWithMachineKey(encrypted, machineKey) {
3995
4021
  if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
3996
4022
  try {
3997
- const crypto10 = __require("crypto");
4023
+ const crypto11 = __require("crypto");
3998
4024
  const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
3999
4025
  if (parts.length !== 3) return null;
4000
4026
  const [ivB64, tagB64, cipherB64] = parts;
4001
4027
  const iv = Buffer.from(ivB64, "base64");
4002
4028
  const authTag = Buffer.from(tagB64, "base64");
4003
- const decipher = crypto10.createDecipheriv("aes-256-gcm", machineKey, iv);
4029
+ const decipher = crypto11.createDecipheriv("aes-256-gcm", machineKey, iv);
4004
4030
  decipher.setAuthTag(authTag);
4005
4031
  let decrypted = decipher.update(cipherB64, "base64", "utf-8");
4006
4032
  decrypted += decipher.final("utf-8");
@@ -6452,13 +6478,13 @@ __export(graph_rag_exports, {
6452
6478
  resolveAlias: () => resolveAlias,
6453
6479
  storeExtraction: () => storeExtraction
6454
6480
  });
6455
- import crypto2 from "crypto";
6481
+ import crypto3 from "crypto";
6456
6482
  function normalizeEntityName(name) {
6457
6483
  return name.replace(/\s*\([^)]*\)\s*/g, "").trim().toLowerCase();
6458
6484
  }
6459
6485
  function entityId(name, type) {
6460
6486
  const normalized = normalizeEntityName(name);
6461
- return crypto2.createHash("sha256").update(`${normalized}::${type.toLowerCase()}`).digest("hex").slice(0, 16);
6487
+ return crypto3.createHash("sha256").update(`${normalized}::${type.toLowerCase()}`).digest("hex").slice(0, 16);
6462
6488
  }
6463
6489
  async function resolveAlias(client, name) {
6464
6490
  const normalized = normalizeEntityName(name);
@@ -6759,7 +6785,7 @@ async function storeExtraction(client, extraction, memoryId, timestamp) {
6759
6785
  const targetAlias = await resolveAlias(client, r.target);
6760
6786
  const sourceId = sourceAlias ?? entityId(r.source, r.sourceType);
6761
6787
  const targetId = targetAlias ?? entityId(r.target, r.targetType);
6762
- const relId = crypto2.randomUUID().slice(0, 16);
6788
+ const relId = crypto3.randomUUID().slice(0, 16);
6763
6789
  try {
6764
6790
  await client.execute({
6765
6791
  sql: `INSERT OR IGNORE INTO entities (id, name, type, first_seen, last_seen)
@@ -6822,7 +6848,7 @@ async function storeExtraction(client, extraction, memoryId, timestamp) {
6822
6848
  }
6823
6849
  }
6824
6850
  for (const h of extraction.hyperedges) {
6825
- const hId = crypto2.randomUUID().slice(0, 16);
6851
+ const hId = crypto3.randomUUID().slice(0, 16);
6826
6852
  try {
6827
6853
  await client.execute({
6828
6854
  sql: `INSERT OR IGNORE INTO hyperedges (id, label, relation, confidence, timestamp)
@@ -6886,7 +6912,7 @@ async function extractBatch(client, batchSize = 50, model = "claude-haiku-4-5-20
6886
6912
  totalEntities += stored.entitiesStored;
6887
6913
  totalRelationships += stored.relationshipsStored;
6888
6914
  }
6889
- const contentHash = crypto2.createHash("sha256").update(rawContent).digest("hex").slice(0, 32);
6915
+ const contentHash = crypto3.createHash("sha256").update(rawContent).digest("hex").slice(0, 32);
6890
6916
  await client.execute({
6891
6917
  sql: "UPDATE memories SET graph_extracted = 1, content_hash = ?, graph_extracted_hash = ? WHERE id = ?",
6892
6918
  args: [contentHash, contentHash, memoryId]
@@ -9726,7 +9752,7 @@ function readQueue() {
9726
9752
  function writeQueue(queue) {
9727
9753
  ensureDir();
9728
9754
  const tmp = `${QUEUE_PATH}.tmp`;
9729
- writeFileSync6(tmp, JSON.stringify(queue, null, 2));
9755
+ writeFileSync6(tmp, JSON.stringify(queue, null, 2), { mode: 384 });
9730
9756
  renameSync4(tmp, QUEUE_PATH);
9731
9757
  }
9732
9758
  function queueIntercom(targetSession, reason) {
@@ -10001,7 +10027,7 @@ var init_task_scope = __esm({
10001
10027
  });
10002
10028
 
10003
10029
  // src/lib/notifications.ts
10004
- import crypto4 from "crypto";
10030
+ import crypto5 from "crypto";
10005
10031
  import path16 from "path";
10006
10032
  import os12 from "os";
10007
10033
  import {
@@ -10014,7 +10040,7 @@ import {
10014
10040
  async function writeNotification(notification) {
10015
10041
  try {
10016
10042
  const client = getClient();
10017
- const id = crypto4.randomUUID();
10043
+ const id = crypto5.randomUUID();
10018
10044
  const now = (/* @__PURE__ */ new Date()).toISOString();
10019
10045
  const sessionScope = notification.sessionScope === void 0 ? getCurrentSessionScope() : notification.sessionScope;
10020
10046
  await client.execute({
@@ -10058,7 +10084,7 @@ var init_notifications = __esm({
10058
10084
  });
10059
10085
 
10060
10086
  // src/lib/session-kill-telemetry.ts
10061
- import crypto5 from "crypto";
10087
+ import crypto6 from "crypto";
10062
10088
  async function recordSessionKill(input) {
10063
10089
  try {
10064
10090
  const client = getClient();
@@ -10068,7 +10094,7 @@ async function recordSessionKill(input) {
10068
10094
  ticks_idle, estimated_tokens_saved)
10069
10095
  VALUES (?, ?, ?, ?, ?, ?, ?)`,
10070
10096
  args: [
10071
- crypto5.randomUUID(),
10097
+ crypto6.randomUUID(),
10072
10098
  input.sessionName,
10073
10099
  input.agentId,
10074
10100
  (/* @__PURE__ */ new Date()).toISOString(),
@@ -10196,7 +10222,7 @@ var init_session_scope = __esm({
10196
10222
  });
10197
10223
 
10198
10224
  // src/lib/tasks-crud.ts
10199
- import crypto6 from "crypto";
10225
+ import crypto7 from "crypto";
10200
10226
  import path18 from "path";
10201
10227
  import os13 from "os";
10202
10228
  import { execSync as execSync7 } from "child_process";
@@ -10317,7 +10343,7 @@ async function resolveTask(client, identifier, scopeSession) {
10317
10343
  }
10318
10344
  async function createTaskCore(input) {
10319
10345
  const client = getClient();
10320
- const id = crypto6.randomUUID();
10346
+ const id = crypto7.randomUUID();
10321
10347
  const now = (/* @__PURE__ */ new Date()).toISOString();
10322
10348
  const slug = slugify(input.title);
10323
10349
  let earlySessionScope = null;
@@ -11282,10 +11308,10 @@ var init_tasks_notify = __esm({
11282
11308
  });
11283
11309
 
11284
11310
  // src/lib/behaviors.ts
11285
- import crypto7 from "crypto";
11311
+ import crypto8 from "crypto";
11286
11312
  async function storeBehavior(opts) {
11287
11313
  const client = getClient();
11288
- const id = crypto7.randomUUID();
11314
+ const id = crypto8.randomUUID();
11289
11315
  const now = (/* @__PURE__ */ new Date()).toISOString();
11290
11316
  let vector = null;
11291
11317
  try {
@@ -11321,7 +11347,7 @@ __export(skill_learning_exports, {
11321
11347
  storeTrajectory: () => storeTrajectory,
11322
11348
  sweepTrajectories: () => sweepTrajectories
11323
11349
  });
11324
- import crypto8 from "crypto";
11350
+ import crypto9 from "crypto";
11325
11351
  async function extractTrajectory(taskId, agentId) {
11326
11352
  const client = getClient();
11327
11353
  const result = await client.execute({
@@ -11350,11 +11376,11 @@ async function extractTrajectory(taskId, agentId) {
11350
11376
  return signature;
11351
11377
  }
11352
11378
  function hashSignature(signature) {
11353
- return crypto8.createHash("sha256").update(signature.join("|")).digest("hex").slice(0, 16);
11379
+ return crypto9.createHash("sha256").update(signature.join("|")).digest("hex").slice(0, 16);
11354
11380
  }
11355
11381
  async function storeTrajectory(opts) {
11356
11382
  const client = getClient();
11357
- const id = crypto8.randomUUID();
11383
+ const id = crypto9.randomUUID();
11358
11384
  const now = (/* @__PURE__ */ new Date()).toISOString();
11359
11385
  const signatureHash = hashSignature(opts.signature);
11360
11386
  await client.execute({
@@ -12925,10 +12951,10 @@ __export(messaging_exports, {
12925
12951
  sendMessage: () => sendMessage,
12926
12952
  setWsClientSend: () => setWsClientSend
12927
12953
  });
12928
- import crypto9 from "crypto";
12954
+ import crypto10 from "crypto";
12929
12955
  function generateUlid() {
12930
12956
  const timestamp = Date.now().toString(36).padStart(10, "0");
12931
- const random = crypto9.randomBytes(10).toString("hex").slice(0, 16);
12957
+ const random = crypto10.randomBytes(10).toString("hex").slice(0, 16);
12932
12958
  return (timestamp + random).toUpperCase();
12933
12959
  }
12934
12960
  function rowToMessage(row) {
@@ -13549,6 +13575,7 @@ import os16 from "os";
13549
13575
  import { fileURLToPath as fileURLToPath3 } from "url";
13550
13576
 
13551
13577
  // src/gateway/webhook-server.ts
13578
+ import crypto from "crypto";
13552
13579
  import {
13553
13580
  createServer
13554
13581
  } from "http";
@@ -13896,7 +13923,7 @@ var ReadOnlySqlRunner = class {
13896
13923
  this.config = config2;
13897
13924
  }
13898
13925
  async run(sql, maxRows) {
13899
- const databaseUrl = this.config.databaseUrl ?? process.env.EXE_GATEWAY_SQL_DATABASE_URL ?? process.env.EXE_COMPANY_BRAIN_SQL_DATABASE_URL ?? process.env.DATABASE_URL;
13926
+ const databaseUrl = this.config.databaseUrl ?? process.env.EXE_GATEWAY_SQL_DATABASE_URL ?? process.env.MCP_READONLY_DATABASE_URL ?? process.env.EXE_COMPANY_BRAIN_SQL_DATABASE_URL ?? process.env.DATABASE_URL;
13900
13927
  if (!databaseUrl) {
13901
13928
  throw new Error("Read-only SQL is not configured. Set EXE_GATEWAY_SQL_DATABASE_URL or DATABASE_URL.");
13902
13929
  }
@@ -13904,7 +13931,8 @@ var ReadOnlySqlRunner = class {
13904
13931
  const limit = clampRows(maxRows ?? this.config.maxRows ?? DEFAULT_MAX_ROWS);
13905
13932
  const timeoutMs = this.config.statementTimeoutMs ?? DEFAULT_TIMEOUT_MS;
13906
13933
  const wrappedSql = `SELECT * FROM (${cleaned}) AS exe_readonly_sql LIMIT ${limit + 1}`;
13907
- const client = new Client({ connectionString: databaseUrl });
13934
+ const { pgSslConfig: pgSslConfig2 } = await Promise.resolve().then(() => (init_pg_ssl(), pg_ssl_exports));
13935
+ const client = new Client({ connectionString: databaseUrl, ...pgSslConfig2() });
13908
13936
  const start = Date.now();
13909
13937
  try {
13910
13938
  await client.connect();
@@ -13967,6 +13995,61 @@ function clampRows(value) {
13967
13995
  // src/gateway/webhook-server.ts
13968
13996
  var DEFAULT_HOST = process.env.EXE_WEBHOOK_HOST || "127.0.0.1";
13969
13997
  var BODY_SIZE_LIMIT = 1048576;
13998
+ function verifyWebhookSignature(rawBody, signature, secret, toleranceSec = 300) {
13999
+ if (!signature) return false;
14000
+ const dotIdx = signature.indexOf(".");
14001
+ if (dotIdx < 0) return false;
14002
+ const timestampStr = signature.slice(0, dotIdx);
14003
+ const hash = signature.slice(dotIdx + 1);
14004
+ const timestamp = parseInt(timestampStr, 10);
14005
+ if (isNaN(timestamp)) return false;
14006
+ if (Math.abs(Date.now() / 1e3 - timestamp) > toleranceSec) return false;
14007
+ const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
14008
+ if (hash.length !== expected.length) return false;
14009
+ return crypto.timingSafeEqual(
14010
+ Buffer.from(hash, "hex"),
14011
+ Buffer.from(expected, "hex")
14012
+ );
14013
+ }
14014
+ function readRawBody(req) {
14015
+ return new Promise((resolve, reject) => {
14016
+ const chunks = [];
14017
+ let size = 0;
14018
+ let done = false;
14019
+ req.on("data", (chunk) => {
14020
+ size += chunk.length;
14021
+ if (size > BODY_SIZE_LIMIT) {
14022
+ if (!done) {
14023
+ done = true;
14024
+ req.resume();
14025
+ reject(new Error("Body too large"));
14026
+ }
14027
+ return;
14028
+ }
14029
+ chunks.push(chunk);
14030
+ });
14031
+ req.on("end", () => {
14032
+ if (done) return;
14033
+ done = true;
14034
+ const raw = Buffer.concat(chunks).toString("utf-8");
14035
+ if (!raw) {
14036
+ resolve({ raw: "", parsed: {} });
14037
+ return;
14038
+ }
14039
+ try {
14040
+ resolve({ raw, parsed: JSON.parse(raw) });
14041
+ } catch {
14042
+ reject(new Error("Invalid JSON"));
14043
+ }
14044
+ });
14045
+ req.on("error", (err) => {
14046
+ if (!done) {
14047
+ done = true;
14048
+ reject(err);
14049
+ }
14050
+ });
14051
+ });
14052
+ }
13970
14053
  var WebhookServer = class {
13971
14054
  constructor(config2, queryHandler = new QueryHandler()) {
13972
14055
  this.config = config2;
@@ -14110,13 +14193,26 @@ var WebhookServer = class {
14110
14193
  }
14111
14194
  async handleWebhookPost(req, res, url) {
14112
14195
  let body;
14196
+ let rawBody = "";
14113
14197
  let parseError = null;
14114
14198
  try {
14115
- body = await readBody(req);
14199
+ const result = await readRawBody(req);
14200
+ rawBody = result.raw;
14201
+ body = result.parsed;
14116
14202
  } catch (err) {
14117
14203
  parseError = err instanceof Error ? err : new Error(String(err));
14118
14204
  }
14119
- if (this.config.authToken && !this.verifyAuth(req)) {
14205
+ if (this.config.webhookSigningSecret) {
14206
+ const sig = req.headers["x-webhook-signature"];
14207
+ if (!verifyWebhookSignature(
14208
+ rawBody,
14209
+ sig,
14210
+ this.config.webhookSigningSecret
14211
+ )) {
14212
+ sendJson(res, 401, { error: "Invalid webhook signature" });
14213
+ return;
14214
+ }
14215
+ } else if (this.config.authToken && !this.verifyAuth(req)) {
14120
14216
  sendJson(res, 401, { error: "Unauthorized" });
14121
14217
  return;
14122
14218
  }
@@ -14160,6 +14256,7 @@ var WebhookServer = class {
14160
14256
  if (!expectedToken) return false;
14161
14257
  const authHeader = req.headers.authorization ?? "";
14162
14258
  if (authHeader === `Bearer ${expectedToken}`) return true;
14259
+ if (process.env.NODE_ENV === "production") return false;
14163
14260
  const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
14164
14261
  return url.searchParams.get("token") === expectedToken;
14165
14262
  }
@@ -14283,11 +14380,11 @@ init_crm_bridge();
14283
14380
 
14284
14381
  // src/lib/pipeline-router.ts
14285
14382
  init_database();
14286
- import crypto3 from "crypto";
14383
+ import crypto4 from "crypto";
14287
14384
  async function sinkConversationStore(msg, agentResponse, agentName) {
14288
14385
  try {
14289
14386
  const client = getClient();
14290
- const id = crypto3.randomUUID();
14387
+ const id = crypto4.randomUUID();
14291
14388
  const mediaJson = msg.media ? JSON.stringify(msg.media) : null;
14292
14389
  await client.execute({
14293
14390
  sql: `INSERT INTO conversations
@@ -14337,7 +14434,7 @@ async function sinkMemory(msg, agentResponse, agentName) {
14337
14434
  ].filter(Boolean).join("\n");
14338
14435
  const vector = await embed2(rawText);
14339
14436
  await writeMemory2({
14340
- id: crypto3.randomUUID(),
14437
+ id: crypto4.randomUUID(),
14341
14438
  agent_id: agentName ?? "gateway",
14342
14439
  agent_role: "gateway",
14343
14440
  session_id: `gateway-${msg.platform}`,
@@ -12,6 +12,7 @@ import { fileURLToPath } from "url";
12
12
  function isMainModule(importMetaUrl) {
13
13
  if (process.argv[1] == null) return false;
14
14
  if (process.argv[1].includes("mcp/server")) return false;
15
+ if (process.argv[1].includes("exe-daemon")) return false;
15
16
  try {
16
17
  const scriptPath = realpathSync(process.argv[1]);
17
18
  const modulePath = realpathSync(fileURLToPath(importMetaUrl));
@@ -587,7 +588,7 @@ function runHealthCheck() {
587
588
  const failed = results.filter((r) => !r.pass).length;
588
589
  return { results, passed, failed };
589
590
  }
590
- if (isMainModule(import.meta.url)) {
591
+ if (isMainModule(import.meta.url) && (process.argv[1] ?? "").includes("exe-healthcheck")) {
591
592
  const { results, passed, failed } = runHealthCheck();
592
593
  console.log("\n exe-os Health Check\n");
593
594
  for (const r of results) {
@@ -1741,6 +1741,7 @@ __export(database_exports, {
1741
1741
  isInitialized: () => isInitialized,
1742
1742
  setExternalClient: () => setExternalClient
1743
1743
  });
1744
+ import { chmodSync as chmodSync2 } from "fs";
1744
1745
  import { createClient } from "@libsql/client";
1745
1746
  async function initDatabase(config) {
1746
1747
  if (_walCheckpointTimer) {
@@ -1782,6 +1783,16 @@ async function initDatabase(config) {
1782
1783
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") {
1783
1784
  _adapterClient = await createPrismaDbAdapter(_resilientClient);
1784
1785
  }
1786
+ try {
1787
+ chmodSync2(config.dbPath, 384);
1788
+ for (const suffix of ["-wal", "-shm"]) {
1789
+ try {
1790
+ chmodSync2(config.dbPath + suffix, 384);
1791
+ } catch {
1792
+ }
1793
+ }
1794
+ } catch {
1795
+ }
1785
1796
  }
1786
1797
  function isInitialized() {
1787
1798
  return _adapterClient !== null || _client !== null;
@@ -6007,6 +6018,7 @@ import { fileURLToPath as fileURLToPath2 } from "url";
6007
6018
  function isMainModule(importMetaUrl) {
6008
6019
  if (process.argv[1] == null) return false;
6009
6020
  if (process.argv[1].includes("mcp/server")) return false;
6021
+ if (process.argv[1].includes("exe-daemon")) return false;
6010
6022
  try {
6011
6023
  const scriptPath = realpathSync(process.argv[1]);
6012
6024
  const modulePath = realpathSync(fileURLToPath2(importMetaUrl));
@@ -1702,6 +1702,7 @@ __export(database_exports, {
1702
1702
  isInitialized: () => isInitialized,
1703
1703
  setExternalClient: () => setExternalClient
1704
1704
  });
1705
+ import { chmodSync as chmodSync2 } from "fs";
1705
1706
  import { createClient } from "@libsql/client";
1706
1707
  async function initDatabase(config) {
1707
1708
  if (_walCheckpointTimer) {
@@ -1743,6 +1744,16 @@ async function initDatabase(config) {
1743
1744
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") {
1744
1745
  _adapterClient = await createPrismaDbAdapter(_resilientClient);
1745
1746
  }
1747
+ try {
1748
+ chmodSync2(config.dbPath, 384);
1749
+ for (const suffix of ["-wal", "-shm"]) {
1750
+ try {
1751
+ chmodSync2(config.dbPath + suffix, 384);
1752
+ } catch {
1753
+ }
1754
+ }
1755
+ } catch {
1756
+ }
1746
1757
  }
1747
1758
  function isInitialized() {
1748
1759
  return _adapterClient !== null || _client !== null;
@@ -1800,6 +1800,7 @@ __export(database_exports, {
1800
1800
  isInitialized: () => isInitialized,
1801
1801
  setExternalClient: () => setExternalClient
1802
1802
  });
1803
+ import { chmodSync as chmodSync2 } from "fs";
1803
1804
  import { createClient } from "@libsql/client";
1804
1805
  async function initDatabase(config) {
1805
1806
  if (_walCheckpointTimer) {
@@ -1841,6 +1842,16 @@ async function initDatabase(config) {
1841
1842
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") {
1842
1843
  _adapterClient = await createPrismaDbAdapter(_resilientClient);
1843
1844
  }
1845
+ try {
1846
+ chmodSync2(config.dbPath, 384);
1847
+ for (const suffix of ["-wal", "-shm"]) {
1848
+ try {
1849
+ chmodSync2(config.dbPath + suffix, 384);
1850
+ } catch {
1851
+ }
1852
+ }
1853
+ } catch {
1854
+ }
1844
1855
  }
1845
1856
  function isInitialized() {
1846
1857
  return _adapterClient !== null || _client !== null;
@@ -450,6 +450,7 @@ var init_memory = __esm({
450
450
  });
451
451
 
452
452
  // src/lib/database.ts
453
+ import { chmodSync as chmodSync3 } from "fs";
453
454
  import { createClient } from "@libsql/client";
454
455
  function getClient() {
455
456
  if (!_adapterClient) {
@@ -1272,7 +1273,7 @@ var init_preferences = __esm({
1272
1273
  });
1273
1274
 
1274
1275
  // src/adapters/mcp-http-config.ts
1275
- import { chmodSync as chmodSync3, existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
1276
+ import { chmodSync as chmodSync4, existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
1276
1277
  import { randomBytes } from "crypto";
1277
1278
  import path11 from "path";
1278
1279
  import os7 from "os";
@@ -1297,7 +1298,7 @@ function readOrCreateDaemonToken(homeDir = os7.homedir()) {
1297
1298
  writeFileSync7(tokenPath, `${token}
1298
1299
  `, "utf-8");
1299
1300
  try {
1300
- chmodSync3(tokenPath, 384);
1301
+ chmodSync4(tokenPath, 384);
1301
1302
  } catch {
1302
1303
  }
1303
1304
  return token;
@@ -3186,6 +3187,7 @@ import { fileURLToPath } from "url";
3186
3187
  function isMainModule(importMetaUrl) {
3187
3188
  if (process.argv[1] == null) return false;
3188
3189
  if (process.argv[1].includes("mcp/server")) return false;
3190
+ if (process.argv[1].includes("exe-daemon")) return false;
3189
3191
  try {
3190
3192
  const scriptPath = realpathSync(process.argv[1]);
3191
3193
  const modulePath = realpathSync(fileURLToPath(importMetaUrl));
@@ -1712,6 +1712,7 @@ __export(database_exports, {
1712
1712
  isInitialized: () => isInitialized,
1713
1713
  setExternalClient: () => setExternalClient
1714
1714
  });
1715
+ import { chmodSync as chmodSync2 } from "fs";
1715
1716
  import { createClient } from "@libsql/client";
1716
1717
  async function initDatabase(config) {
1717
1718
  if (_walCheckpointTimer) {
@@ -1753,6 +1754,16 @@ async function initDatabase(config) {
1753
1754
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") {
1754
1755
  _adapterClient = await createPrismaDbAdapter(_resilientClient);
1755
1756
  }
1757
+ try {
1758
+ chmodSync2(config.dbPath, 384);
1759
+ for (const suffix of ["-wal", "-shm"]) {
1760
+ try {
1761
+ chmodSync2(config.dbPath + suffix, 384);
1762
+ } catch {
1763
+ }
1764
+ }
1765
+ } catch {
1766
+ }
1756
1767
  }
1757
1768
  function isInitialized() {
1758
1769
  return _adapterClient !== null || _client !== null;
@@ -1713,6 +1713,7 @@ __export(database_exports, {
1713
1713
  isInitialized: () => isInitialized,
1714
1714
  setExternalClient: () => setExternalClient
1715
1715
  });
1716
+ import { chmodSync as chmodSync2 } from "fs";
1716
1717
  import { createClient } from "@libsql/client";
1717
1718
  async function initDatabase(config) {
1718
1719
  if (_walCheckpointTimer) {
@@ -1754,6 +1755,16 @@ async function initDatabase(config) {
1754
1755
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") {
1755
1756
  _adapterClient = await createPrismaDbAdapter(_resilientClient);
1756
1757
  }
1758
+ try {
1759
+ chmodSync2(config.dbPath, 384);
1760
+ for (const suffix of ["-wal", "-shm"]) {
1761
+ try {
1762
+ chmodSync2(config.dbPath + suffix, 384);
1763
+ } catch {
1764
+ }
1765
+ }
1766
+ } catch {
1767
+ }
1757
1768
  }
1758
1769
  function isInitialized() {
1759
1770
  return _adapterClient !== null || _client !== null;
@@ -5923,6 +5934,7 @@ import { fileURLToPath as fileURLToPath3 } from "url";
5923
5934
  function isMainModule(importMetaUrl) {
5924
5935
  if (process.argv[1] == null) return false;
5925
5936
  if (process.argv[1].includes("mcp/server")) return false;
5937
+ if (process.argv[1].includes("exe-daemon")) return false;
5926
5938
  try {
5927
5939
  const scriptPath = realpathSync(process.argv[1]);
5928
5940
  const modulePath = realpathSync(fileURLToPath3(importMetaUrl));
@@ -1713,6 +1713,7 @@ __export(database_exports, {
1713
1713
  isInitialized: () => isInitialized,
1714
1714
  setExternalClient: () => setExternalClient
1715
1715
  });
1716
+ import { chmodSync as chmodSync2 } from "fs";
1716
1717
  import { createClient } from "@libsql/client";
1717
1718
  async function initDatabase(config) {
1718
1719
  if (_walCheckpointTimer) {
@@ -1754,6 +1755,16 @@ async function initDatabase(config) {
1754
1755
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") {
1755
1756
  _adapterClient = await createPrismaDbAdapter(_resilientClient);
1756
1757
  }
1758
+ try {
1759
+ chmodSync2(config.dbPath, 384);
1760
+ for (const suffix of ["-wal", "-shm"]) {
1761
+ try {
1762
+ chmodSync2(config.dbPath + suffix, 384);
1763
+ } catch {
1764
+ }
1765
+ }
1766
+ } catch {
1767
+ }
1757
1768
  }
1758
1769
  function isInitialized() {
1759
1770
  return _adapterClient !== null || _client !== null;
@@ -5959,6 +5970,7 @@ import { fileURLToPath } from "url";
5959
5970
  function isMainModule(importMetaUrl) {
5960
5971
  if (process.argv[1] == null) return false;
5961
5972
  if (process.argv[1].includes("mcp/server")) return false;
5973
+ if (process.argv[1].includes("exe-daemon")) return false;
5962
5974
  try {
5963
5975
  const scriptPath = realpathSync(process.argv[1]);
5964
5976
  const modulePath = realpathSync(fileURLToPath(importMetaUrl));
@@ -1557,6 +1557,7 @@ __export(database_exports, {
1557
1557
  isInitialized: () => isInitialized,
1558
1558
  setExternalClient: () => setExternalClient
1559
1559
  });
1560
+ import { chmodSync as chmodSync2 } from "fs";
1560
1561
  import { createClient } from "@libsql/client";
1561
1562
  async function initDatabase(config) {
1562
1563
  if (_walCheckpointTimer) {
@@ -1598,6 +1599,16 @@ async function initDatabase(config) {
1598
1599
  if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") {
1599
1600
  _adapterClient = await createPrismaDbAdapter(_resilientClient);
1600
1601
  }
1602
+ try {
1603
+ chmodSync2(config.dbPath, 384);
1604
+ for (const suffix of ["-wal", "-shm"]) {
1605
+ try {
1606
+ chmodSync2(config.dbPath + suffix, 384);
1607
+ } catch {
1608
+ }
1609
+ }
1610
+ } catch {
1611
+ }
1601
1612
  }
1602
1613
  function isInitialized() {
1603
1614
  return _adapterClient !== null || _client !== null;
@@ -5287,6 +5298,7 @@ import { fileURLToPath as fileURLToPath2 } from "url";
5287
5298
  function isMainModule(importMetaUrl) {
5288
5299
  if (process.argv[1] == null) return false;
5289
5300
  if (process.argv[1].includes("mcp/server")) return false;
5301
+ if (process.argv[1].includes("exe-daemon")) return false;
5290
5302
  try {
5291
5303
  const scriptPath = realpathSync(process.argv[1]);
5292
5304
  const modulePath = realpathSync(fileURLToPath2(importMetaUrl));