@askexenow/exe-os 0.9.12 → 0.9.14

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 (70) hide show
  1. package/dist/bin/backfill-conversations.js +53 -5
  2. package/dist/bin/backfill-responses.js +53 -5
  3. package/dist/bin/backfill-vectors.js +47 -5
  4. package/dist/bin/cleanup-stale-review-tasks.js +23 -2
  5. package/dist/bin/cli.js +77 -9
  6. package/dist/bin/exe-assign.js +53 -5
  7. package/dist/bin/exe-boot.js +47 -5
  8. package/dist/bin/exe-dispatch.js +23 -2
  9. package/dist/bin/exe-doctor.js +23 -2
  10. package/dist/bin/exe-export-behaviors.js +23 -2
  11. package/dist/bin/exe-forget.js +23 -2
  12. package/dist/bin/exe-gateway.js +469 -22
  13. package/dist/bin/exe-heartbeat.js +23 -2
  14. package/dist/bin/exe-kill.js +23 -2
  15. package/dist/bin/exe-launch-agent.js +23 -2
  16. package/dist/bin/exe-link.js +53 -5
  17. package/dist/bin/exe-pending-messages.js +23 -2
  18. package/dist/bin/exe-pending-notifications.js +23 -2
  19. package/dist/bin/exe-pending-reviews.js +23 -2
  20. package/dist/bin/exe-rename.js +53 -5
  21. package/dist/bin/exe-review.js +23 -2
  22. package/dist/bin/exe-search.js +53 -5
  23. package/dist/bin/exe-session-cleanup.js +47 -5
  24. package/dist/bin/exe-start-codex.js +23 -2
  25. package/dist/bin/exe-start-opencode.js +23 -2
  26. package/dist/bin/exe-status.js +23 -2
  27. package/dist/bin/exe-team.js +23 -2
  28. package/dist/bin/git-sweep.js +47 -5
  29. package/dist/bin/graph-backfill.js +23 -2
  30. package/dist/bin/graph-export.js +23 -2
  31. package/dist/bin/scan-tasks.js +47 -5
  32. package/dist/bin/setup.js +68 -9
  33. package/dist/bin/shard-migrate.js +23 -2
  34. package/dist/bin/wiki-sync.js +23 -2
  35. package/dist/gateway/index.js +150 -126
  36. package/dist/hooks/bug-report-worker.js +23 -2
  37. package/dist/hooks/codex-stop-task-finalizer.js +23 -2
  38. package/dist/hooks/commit-complete.js +47 -5
  39. package/dist/hooks/error-recall.js +53 -5
  40. package/dist/hooks/ingest-worker.js +47 -5
  41. package/dist/hooks/ingest.js +3345 -232
  42. package/dist/hooks/instructions-loaded.js +53 -5
  43. package/dist/hooks/notification.js +53 -5
  44. package/dist/hooks/post-compact.js +53 -5
  45. package/dist/hooks/pre-compact.js +47 -5
  46. package/dist/hooks/pre-tool-use.js +53 -5
  47. package/dist/hooks/prompt-ingest-worker.js +47 -5
  48. package/dist/hooks/prompt-submit.js +1726 -1401
  49. package/dist/hooks/response-ingest-worker.js +47 -5
  50. package/dist/hooks/session-end.js +369 -190
  51. package/dist/hooks/session-start.js +335 -19
  52. package/dist/hooks/stop.js +47 -5
  53. package/dist/hooks/subagent-stop.js +53 -5
  54. package/dist/hooks/summary-worker.js +47 -5
  55. package/dist/index.js +150 -126
  56. package/dist/lib/cloud-sync.js +53 -5
  57. package/dist/lib/database.js +53 -5
  58. package/dist/lib/db-daemon-client.js +31 -3
  59. package/dist/lib/db.js +53 -5
  60. package/dist/lib/device-registry.js +53 -5
  61. package/dist/lib/embedder.js +30 -3
  62. package/dist/lib/exe-daemon-client.js +31 -3
  63. package/dist/lib/exe-daemon.js +1973 -147
  64. package/dist/lib/hybrid-search.js +53 -5
  65. package/dist/lib/schedules.js +23 -2
  66. package/dist/lib/store.js +23 -2
  67. package/dist/mcp/server.js +151 -5
  68. package/dist/runtime/index.js +47 -5
  69. package/dist/tui/App.js +56 -5
  70. package/package.json +1 -1
@@ -806,7 +806,7 @@ async function ensureCompatibilityViews(prisma) {
806
806
  for (const mapping of VIEW_MAPPINGS) {
807
807
  const relation = mapping.source.replace(/"/g, "");
808
808
  const rows = await prisma.$queryRawUnsafe(
809
- "SELECT to_regclass($1) AS regclass",
809
+ "SELECT to_regclass($1)::text AS regclass",
810
810
  relation
811
811
  );
812
812
  if (!rows[0]?.regclass) {
@@ -1160,8 +1160,29 @@ function findPackageRoot() {
1160
1160
  }
1161
1161
  return null;
1162
1162
  }
1163
+ function getAvailableMemoryGB() {
1164
+ if (process.platform === "darwin") {
1165
+ try {
1166
+ const { execSync: execSync10 } = __require("child_process");
1167
+ const vmstat = execSync10("vm_stat", { encoding: "utf8" });
1168
+ const pageSize = 16384;
1169
+ const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
1170
+ const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
1171
+ const free = vmstat.match(/Pages free:\s+(\d+)/);
1172
+ const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
1173
+ const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
1174
+ const freePages = free ? parseInt(free[1], 10) : 0;
1175
+ const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
1176
+ const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
1177
+ return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
1178
+ } catch {
1179
+ return os4.freemem() / (1024 * 1024 * 1024);
1180
+ }
1181
+ }
1182
+ return os4.freemem() / (1024 * 1024 * 1024);
1183
+ }
1163
1184
  function spawnDaemon() {
1164
- const freeGB = os4.freemem() / (1024 * 1024 * 1024);
1185
+ const freeGB = getAvailableMemoryGB();
1165
1186
  const totalGB = os4.totalmem() / (1024 * 1024 * 1024);
1166
1187
  if (totalGB <= 8) {
1167
1188
  process.stderr.write(
@@ -1170,9 +1191,9 @@ function spawnDaemon() {
1170
1191
  );
1171
1192
  return;
1172
1193
  }
1173
- if (totalGB <= 16 && freeGB < 4) {
1194
+ if (totalGB <= 16 && freeGB < 2) {
1174
1195
  process.stderr.write(
1175
- `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB free / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
1196
+ `[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
1176
1197
  `
1177
1198
  );
1178
1199
  return;
@@ -2421,12 +2442,26 @@ async function ensureSchema() {
2421
2442
  session_name TEXT,
2422
2443
  task_id TEXT,
2423
2444
  project_name TEXT,
2424
- started_at TEXT NOT NULL
2445
+ started_at TEXT NOT NULL,
2446
+ cache_cold_count INTEGER NOT NULL DEFAULT 0
2425
2447
  );
2426
2448
 
2427
2449
  CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
2428
2450
  ON session_agent_map(agent_id);
2429
2451
  `);
2452
+ await client.executeMultiple(`
2453
+ CREATE TABLE IF NOT EXISTS agent_file_reads (
2454
+ session_uuid TEXT NOT NULL,
2455
+ agent_id TEXT NOT NULL,
2456
+ file_path TEXT NOT NULL,
2457
+ read_at TEXT NOT NULL,
2458
+ commit_hash TEXT,
2459
+ PRIMARY KEY (session_uuid, file_path)
2460
+ );
2461
+
2462
+ CREATE INDEX IF NOT EXISTS idx_agent_file_reads_agent_read_at
2463
+ ON agent_file_reads(agent_id, read_at);
2464
+ `);
2430
2465
  try {
2431
2466
  const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
2432
2467
  if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
@@ -2441,6 +2476,13 @@ async function ensureSchema() {
2441
2476
  }
2442
2477
  } catch {
2443
2478
  }
2479
+ try {
2480
+ await client.execute({
2481
+ sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
2482
+ args: []
2483
+ });
2484
+ } catch {
2485
+ }
2444
2486
  try {
2445
2487
  await client.execute({
2446
2488
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
@@ -1164,7 +1164,7 @@ async function ensureCompatibilityViews(prisma) {
1164
1164
  for (const mapping of VIEW_MAPPINGS) {
1165
1165
  const relation = mapping.source.replace(/"/g, "");
1166
1166
  const rows = await prisma.$queryRawUnsafe(
1167
- "SELECT to_regclass($1) AS regclass",
1167
+ "SELECT to_regclass($1)::text AS regclass",
1168
1168
  relation
1169
1169
  );
1170
1170
  if (!rows[0]?.regclass) {
@@ -2252,12 +2252,26 @@ async function ensureSchema() {
2252
2252
  session_name TEXT,
2253
2253
  task_id TEXT,
2254
2254
  project_name TEXT,
2255
- started_at TEXT NOT NULL
2255
+ started_at TEXT NOT NULL,
2256
+ cache_cold_count INTEGER NOT NULL DEFAULT 0
2256
2257
  );
2257
2258
 
2258
2259
  CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
2259
2260
  ON session_agent_map(agent_id);
2260
2261
  `);
2262
+ await client.executeMultiple(`
2263
+ CREATE TABLE IF NOT EXISTS agent_file_reads (
2264
+ session_uuid TEXT NOT NULL,
2265
+ agent_id TEXT NOT NULL,
2266
+ file_path TEXT NOT NULL,
2267
+ read_at TEXT NOT NULL,
2268
+ commit_hash TEXT,
2269
+ PRIMARY KEY (session_uuid, file_path)
2270
+ );
2271
+
2272
+ CREATE INDEX IF NOT EXISTS idx_agent_file_reads_agent_read_at
2273
+ ON agent_file_reads(agent_id, read_at);
2274
+ `);
2261
2275
  try {
2262
2276
  const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
2263
2277
  if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
@@ -2272,6 +2286,13 @@ async function ensureSchema() {
2272
2286
  }
2273
2287
  } catch {
2274
2288
  }
2289
+ try {
2290
+ await client.execute({
2291
+ sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
2292
+ args: []
2293
+ });
2294
+ } catch {
2295
+ }
2275
2296
  try {
2276
2297
  await client.execute({
2277
2298
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
@@ -650,7 +650,7 @@ async function ensureCompatibilityViews(prisma) {
650
650
  for (const mapping of VIEW_MAPPINGS) {
651
651
  const relation = mapping.source.replace(/"/g, "");
652
652
  const rows = await prisma.$queryRawUnsafe(
653
- "SELECT to_regclass($1) AS regclass",
653
+ "SELECT to_regclass($1)::text AS regclass",
654
654
  relation
655
655
  );
656
656
  if (!rows[0]?.regclass) {
@@ -1738,12 +1738,26 @@ async function ensureSchema() {
1738
1738
  session_name TEXT,
1739
1739
  task_id TEXT,
1740
1740
  project_name TEXT,
1741
- started_at TEXT NOT NULL
1741
+ started_at TEXT NOT NULL,
1742
+ cache_cold_count INTEGER NOT NULL DEFAULT 0
1742
1743
  );
1743
1744
 
1744
1745
  CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
1745
1746
  ON session_agent_map(agent_id);
1746
1747
  `);
1748
+ await client.executeMultiple(`
1749
+ CREATE TABLE IF NOT EXISTS agent_file_reads (
1750
+ session_uuid TEXT NOT NULL,
1751
+ agent_id TEXT NOT NULL,
1752
+ file_path TEXT NOT NULL,
1753
+ read_at TEXT NOT NULL,
1754
+ commit_hash TEXT,
1755
+ PRIMARY KEY (session_uuid, file_path)
1756
+ );
1757
+
1758
+ CREATE INDEX IF NOT EXISTS idx_agent_file_reads_agent_read_at
1759
+ ON agent_file_reads(agent_id, read_at);
1760
+ `);
1747
1761
  try {
1748
1762
  const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
1749
1763
  if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
@@ -1758,6 +1772,13 @@ async function ensureSchema() {
1758
1772
  }
1759
1773
  } catch {
1760
1774
  }
1775
+ try {
1776
+ await client.execute({
1777
+ sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
1778
+ args: []
1779
+ });
1780
+ } catch {
1781
+ }
1761
1782
  try {
1762
1783
  await client.execute({
1763
1784
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
@@ -644,7 +644,7 @@ async function ensureCompatibilityViews(prisma) {
644
644
  for (const mapping of VIEW_MAPPINGS) {
645
645
  const relation = mapping.source.replace(/"/g, "");
646
646
  const rows = await prisma.$queryRawUnsafe(
647
- "SELECT to_regclass($1) AS regclass",
647
+ "SELECT to_regclass($1)::text AS regclass",
648
648
  relation
649
649
  );
650
650
  if (!rows[0]?.regclass) {
@@ -1732,12 +1732,26 @@ async function ensureSchema() {
1732
1732
  session_name TEXT,
1733
1733
  task_id TEXT,
1734
1734
  project_name TEXT,
1735
- started_at TEXT NOT NULL
1735
+ started_at TEXT NOT NULL,
1736
+ cache_cold_count INTEGER NOT NULL DEFAULT 0
1736
1737
  );
1737
1738
 
1738
1739
  CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
1739
1740
  ON session_agent_map(agent_id);
1740
1741
  `);
1742
+ await client.executeMultiple(`
1743
+ CREATE TABLE IF NOT EXISTS agent_file_reads (
1744
+ session_uuid TEXT NOT NULL,
1745
+ agent_id TEXT NOT NULL,
1746
+ file_path TEXT NOT NULL,
1747
+ read_at TEXT NOT NULL,
1748
+ commit_hash TEXT,
1749
+ PRIMARY KEY (session_uuid, file_path)
1750
+ );
1751
+
1752
+ CREATE INDEX IF NOT EXISTS idx_agent_file_reads_agent_read_at
1753
+ ON agent_file_reads(agent_id, read_at);
1754
+ `);
1741
1755
  try {
1742
1756
  const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
1743
1757
  if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
@@ -1752,6 +1766,13 @@ async function ensureSchema() {
1752
1766
  }
1753
1767
  } catch {
1754
1768
  }
1769
+ try {
1770
+ await client.execute({
1771
+ sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
1772
+ args: []
1773
+ });
1774
+ } catch {
1775
+ }
1755
1776
  try {
1756
1777
  await client.execute({
1757
1778
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
@@ -651,7 +651,7 @@ async function ensureCompatibilityViews(prisma) {
651
651
  for (const mapping of VIEW_MAPPINGS) {
652
652
  const relation = mapping.source.replace(/"/g, "");
653
653
  const rows = await prisma.$queryRawUnsafe(
654
- "SELECT to_regclass($1) AS regclass",
654
+ "SELECT to_regclass($1)::text AS regclass",
655
655
  relation
656
656
  );
657
657
  if (!rows[0]?.regclass) {
@@ -1739,12 +1739,26 @@ async function ensureSchema() {
1739
1739
  session_name TEXT,
1740
1740
  task_id TEXT,
1741
1741
  project_name TEXT,
1742
- started_at TEXT NOT NULL
1742
+ started_at TEXT NOT NULL,
1743
+ cache_cold_count INTEGER NOT NULL DEFAULT 0
1743
1744
  );
1744
1745
 
1745
1746
  CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
1746
1747
  ON session_agent_map(agent_id);
1747
1748
  `);
1749
+ await client.executeMultiple(`
1750
+ CREATE TABLE IF NOT EXISTS agent_file_reads (
1751
+ session_uuid TEXT NOT NULL,
1752
+ agent_id TEXT NOT NULL,
1753
+ file_path TEXT NOT NULL,
1754
+ read_at TEXT NOT NULL,
1755
+ commit_hash TEXT,
1756
+ PRIMARY KEY (session_uuid, file_path)
1757
+ );
1758
+
1759
+ CREATE INDEX IF NOT EXISTS idx_agent_file_reads_agent_read_at
1760
+ ON agent_file_reads(agent_id, read_at);
1761
+ `);
1748
1762
  try {
1749
1763
  const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
1750
1764
  if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
@@ -1759,6 +1773,13 @@ async function ensureSchema() {
1759
1773
  }
1760
1774
  } catch {
1761
1775
  }
1776
+ try {
1777
+ await client.execute({
1778
+ sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
1779
+ args: []
1780
+ });
1781
+ } catch {
1782
+ }
1762
1783
  try {
1763
1784
  await client.execute({
1764
1785
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,