@askexenow/exe-os 0.9.11 → 0.9.13

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 (67) hide show
  1. package/dist/bin/backfill-conversations.js +22 -1
  2. package/dist/bin/backfill-responses.js +22 -1
  3. package/dist/bin/backfill-vectors.js +22 -1
  4. package/dist/bin/cleanup-stale-review-tasks.js +22 -1
  5. package/dist/bin/cli.js +22 -1
  6. package/dist/bin/exe-assign.js +22 -1
  7. package/dist/bin/exe-boot.js +22 -1
  8. package/dist/bin/exe-dispatch.js +22 -1
  9. package/dist/bin/exe-doctor.js +22 -1
  10. package/dist/bin/exe-export-behaviors.js +22 -1
  11. package/dist/bin/exe-forget.js +22 -1
  12. package/dist/bin/exe-gateway.js +22 -1
  13. package/dist/bin/exe-heartbeat.js +22 -1
  14. package/dist/bin/exe-kill.js +22 -1
  15. package/dist/bin/exe-launch-agent.js +22 -1
  16. package/dist/bin/exe-link.js +22 -1
  17. package/dist/bin/exe-pending-messages.js +22 -1
  18. package/dist/bin/exe-pending-notifications.js +22 -1
  19. package/dist/bin/exe-pending-reviews.js +22 -1
  20. package/dist/bin/exe-rename.js +22 -1
  21. package/dist/bin/exe-review.js +22 -1
  22. package/dist/bin/exe-search.js +22 -1
  23. package/dist/bin/exe-session-cleanup.js +22 -1
  24. package/dist/bin/exe-start-codex.js +22 -1
  25. package/dist/bin/exe-start-opencode.js +22 -1
  26. package/dist/bin/exe-status.js +22 -1
  27. package/dist/bin/exe-team.js +22 -1
  28. package/dist/bin/git-sweep.js +22 -1
  29. package/dist/bin/graph-backfill.js +22 -1
  30. package/dist/bin/graph-export.js +22 -1
  31. package/dist/bin/scan-tasks.js +22 -1
  32. package/dist/bin/setup.js +22 -1
  33. package/dist/bin/shard-migrate.js +22 -1
  34. package/dist/bin/wiki-sync.js +22 -1
  35. package/dist/gateway/index.js +22 -1
  36. package/dist/hooks/bug-report-worker.js +22 -1
  37. package/dist/hooks/codex-stop-task-finalizer.js +22 -1
  38. package/dist/hooks/commit-complete.js +22 -1
  39. package/dist/hooks/error-recall.js +22 -1
  40. package/dist/hooks/ingest-worker.js +22 -1
  41. package/dist/hooks/ingest.js +3345 -232
  42. package/dist/hooks/instructions-loaded.js +22 -1
  43. package/dist/hooks/notification.js +22 -1
  44. package/dist/hooks/post-compact.js +22 -1
  45. package/dist/hooks/pre-compact.js +22 -1
  46. package/dist/hooks/pre-tool-use.js +22 -1
  47. package/dist/hooks/prompt-ingest-worker.js +22 -1
  48. package/dist/hooks/prompt-submit.js +1700 -1396
  49. package/dist/hooks/response-ingest-worker.js +22 -1
  50. package/dist/hooks/session-end.js +345 -187
  51. package/dist/hooks/session-start.js +304 -15
  52. package/dist/hooks/stop.js +22 -1
  53. package/dist/hooks/subagent-stop.js +22 -1
  54. package/dist/hooks/summary-worker.js +22 -1
  55. package/dist/index.js +22 -1
  56. package/dist/lib/cloud-sync.js +22 -1
  57. package/dist/lib/database.js +22 -1
  58. package/dist/lib/db.js +22 -1
  59. package/dist/lib/device-registry.js +22 -1
  60. package/dist/lib/exe-daemon.js +39 -1
  61. package/dist/lib/hybrid-search.js +22 -1
  62. package/dist/lib/schedules.js +22 -1
  63. package/dist/lib/store.js +22 -1
  64. package/dist/mcp/server.js +126 -1
  65. package/dist/runtime/index.js +22 -1
  66. package/dist/tui/App.js +22 -1
  67. package/package.json +1 -1
package/dist/lib/db.js CHANGED
@@ -2143,12 +2143,26 @@ async function ensureSchema() {
2143
2143
  session_name TEXT,
2144
2144
  task_id TEXT,
2145
2145
  project_name TEXT,
2146
- started_at TEXT NOT NULL
2146
+ started_at TEXT NOT NULL,
2147
+ cache_cold_count INTEGER NOT NULL DEFAULT 0
2147
2148
  );
2148
2149
 
2149
2150
  CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
2150
2151
  ON session_agent_map(agent_id);
2151
2152
  `);
2153
+ await client.executeMultiple(`
2154
+ CREATE TABLE IF NOT EXISTS agent_file_reads (
2155
+ session_uuid TEXT NOT NULL,
2156
+ agent_id TEXT NOT NULL,
2157
+ file_path TEXT NOT NULL,
2158
+ read_at TEXT NOT NULL,
2159
+ commit_hash TEXT,
2160
+ PRIMARY KEY (session_uuid, file_path)
2161
+ );
2162
+
2163
+ CREATE INDEX IF NOT EXISTS idx_agent_file_reads_agent_read_at
2164
+ ON agent_file_reads(agent_id, read_at);
2165
+ `);
2152
2166
  try {
2153
2167
  const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
2154
2168
  if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
@@ -2163,6 +2177,13 @@ async function ensureSchema() {
2163
2177
  }
2164
2178
  } catch {
2165
2179
  }
2180
+ try {
2181
+ await client.execute({
2182
+ sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
2183
+ args: []
2184
+ });
2185
+ } catch {
2186
+ }
2166
2187
  try {
2167
2188
  await client.execute({
2168
2189
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
@@ -2165,12 +2165,26 @@ async function ensureSchema() {
2165
2165
  session_name TEXT,
2166
2166
  task_id TEXT,
2167
2167
  project_name TEXT,
2168
- started_at TEXT NOT NULL
2168
+ started_at TEXT NOT NULL,
2169
+ cache_cold_count INTEGER NOT NULL DEFAULT 0
2169
2170
  );
2170
2171
 
2171
2172
  CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
2172
2173
  ON session_agent_map(agent_id);
2173
2174
  `);
2175
+ await client.executeMultiple(`
2176
+ CREATE TABLE IF NOT EXISTS agent_file_reads (
2177
+ session_uuid TEXT NOT NULL,
2178
+ agent_id TEXT NOT NULL,
2179
+ file_path TEXT NOT NULL,
2180
+ read_at TEXT NOT NULL,
2181
+ commit_hash TEXT,
2182
+ PRIMARY KEY (session_uuid, file_path)
2183
+ );
2184
+
2185
+ CREATE INDEX IF NOT EXISTS idx_agent_file_reads_agent_read_at
2186
+ ON agent_file_reads(agent_id, read_at);
2187
+ `);
2174
2188
  try {
2175
2189
  const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
2176
2190
  if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
@@ -2185,6 +2199,13 @@ async function ensureSchema() {
2185
2199
  }
2186
2200
  } catch {
2187
2201
  }
2202
+ try {
2203
+ await client.execute({
2204
+ sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
2205
+ args: []
2206
+ });
2207
+ } catch {
2208
+ }
2188
2209
  try {
2189
2210
  await client.execute({
2190
2211
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
@@ -3298,12 +3298,26 @@ async function ensureSchema() {
3298
3298
  session_name TEXT,
3299
3299
  task_id TEXT,
3300
3300
  project_name TEXT,
3301
- started_at TEXT NOT NULL
3301
+ started_at TEXT NOT NULL,
3302
+ cache_cold_count INTEGER NOT NULL DEFAULT 0
3302
3303
  );
3303
3304
 
3304
3305
  CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
3305
3306
  ON session_agent_map(agent_id);
3306
3307
  `);
3308
+ await client.executeMultiple(`
3309
+ CREATE TABLE IF NOT EXISTS agent_file_reads (
3310
+ session_uuid TEXT NOT NULL,
3311
+ agent_id TEXT NOT NULL,
3312
+ file_path TEXT NOT NULL,
3313
+ read_at TEXT NOT NULL,
3314
+ commit_hash TEXT,
3315
+ PRIMARY KEY (session_uuid, file_path)
3316
+ );
3317
+
3318
+ CREATE INDEX IF NOT EXISTS idx_agent_file_reads_agent_read_at
3319
+ ON agent_file_reads(agent_id, read_at);
3320
+ `);
3307
3321
  try {
3308
3322
  const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
3309
3323
  if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
@@ -3318,6 +3332,13 @@ async function ensureSchema() {
3318
3332
  }
3319
3333
  } catch {
3320
3334
  }
3335
+ try {
3336
+ await client.execute({
3337
+ sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
3338
+ args: []
3339
+ });
3340
+ } catch {
3341
+ }
3321
3342
  try {
3322
3343
  await client.execute({
3323
3344
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
@@ -7167,6 +7188,23 @@ async function pollIdleKill(deps, idleTickCounts, opts) {
7167
7188
  continue;
7168
7189
  }
7169
7190
  const signals = await deps.collectSignals(entry.agentId, entry.windowName);
7191
+ if (signals.hasOpenTasks) {
7192
+ const instanceName = entry.windowName.split("-")[0] ?? entry.agentId;
7193
+ if (instanceName !== entry.agentId) {
7194
+ try {
7195
+ const markerPath = __require("path").join(
7196
+ __require("os").homedir(),
7197
+ ".exe-os",
7198
+ "session-cache",
7199
+ `current-task-${instanceName}.json`
7200
+ );
7201
+ if (!__require("fs").existsSync(markerPath)) {
7202
+ signals.hasOpenTasks = false;
7203
+ }
7204
+ } catch {
7205
+ }
7206
+ }
7207
+ }
7170
7208
  if (signals.hasOpenTasks || signals.hasNeedsReview || signals.hasUnreadInbox || signals.hadRecentIntercomAck) {
7171
7209
  idleTickCounts.delete(entry.windowName);
7172
7210
  continue;
@@ -1808,12 +1808,26 @@ async function ensureSchema() {
1808
1808
  session_name TEXT,
1809
1809
  task_id TEXT,
1810
1810
  project_name TEXT,
1811
- started_at TEXT NOT NULL
1811
+ started_at TEXT NOT NULL,
1812
+ cache_cold_count INTEGER NOT NULL DEFAULT 0
1812
1813
  );
1813
1814
 
1814
1815
  CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
1815
1816
  ON session_agent_map(agent_id);
1816
1817
  `);
1818
+ await client.executeMultiple(`
1819
+ CREATE TABLE IF NOT EXISTS agent_file_reads (
1820
+ session_uuid TEXT NOT NULL,
1821
+ agent_id TEXT NOT NULL,
1822
+ file_path TEXT NOT NULL,
1823
+ read_at TEXT NOT NULL,
1824
+ commit_hash TEXT,
1825
+ PRIMARY KEY (session_uuid, file_path)
1826
+ );
1827
+
1828
+ CREATE INDEX IF NOT EXISTS idx_agent_file_reads_agent_read_at
1829
+ ON agent_file_reads(agent_id, read_at);
1830
+ `);
1817
1831
  try {
1818
1832
  const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
1819
1833
  if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
@@ -1828,6 +1842,13 @@ async function ensureSchema() {
1828
1842
  }
1829
1843
  } catch {
1830
1844
  }
1845
+ try {
1846
+ await client.execute({
1847
+ sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
1848
+ args: []
1849
+ });
1850
+ } catch {
1851
+ }
1831
1852
  try {
1832
1853
  await client.execute({
1833
1854
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
@@ -1734,12 +1734,26 @@ async function ensureSchema() {
1734
1734
  session_name TEXT,
1735
1735
  task_id TEXT,
1736
1736
  project_name TEXT,
1737
- started_at TEXT NOT NULL
1737
+ started_at TEXT NOT NULL,
1738
+ cache_cold_count INTEGER NOT NULL DEFAULT 0
1738
1739
  );
1739
1740
 
1740
1741
  CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
1741
1742
  ON session_agent_map(agent_id);
1742
1743
  `);
1744
+ await client.executeMultiple(`
1745
+ CREATE TABLE IF NOT EXISTS agent_file_reads (
1746
+ session_uuid TEXT NOT NULL,
1747
+ agent_id TEXT NOT NULL,
1748
+ file_path TEXT NOT NULL,
1749
+ read_at TEXT NOT NULL,
1750
+ commit_hash TEXT,
1751
+ PRIMARY KEY (session_uuid, file_path)
1752
+ );
1753
+
1754
+ CREATE INDEX IF NOT EXISTS idx_agent_file_reads_agent_read_at
1755
+ ON agent_file_reads(agent_id, read_at);
1756
+ `);
1743
1757
  try {
1744
1758
  const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
1745
1759
  if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
@@ -1754,6 +1768,13 @@ async function ensureSchema() {
1754
1768
  }
1755
1769
  } catch {
1756
1770
  }
1771
+ try {
1772
+ await client.execute({
1773
+ sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
1774
+ args: []
1775
+ });
1776
+ } catch {
1777
+ }
1757
1778
  try {
1758
1779
  await client.execute({
1759
1780
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
package/dist/lib/store.js CHANGED
@@ -1731,12 +1731,26 @@ async function ensureSchema() {
1731
1731
  session_name TEXT,
1732
1732
  task_id TEXT,
1733
1733
  project_name TEXT,
1734
- started_at TEXT NOT NULL
1734
+ started_at TEXT NOT NULL,
1735
+ cache_cold_count INTEGER NOT NULL DEFAULT 0
1735
1736
  );
1736
1737
 
1737
1738
  CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
1738
1739
  ON session_agent_map(agent_id);
1739
1740
  `);
1741
+ await client.executeMultiple(`
1742
+ CREATE TABLE IF NOT EXISTS agent_file_reads (
1743
+ session_uuid TEXT NOT NULL,
1744
+ agent_id TEXT NOT NULL,
1745
+ file_path TEXT NOT NULL,
1746
+ read_at TEXT NOT NULL,
1747
+ commit_hash TEXT,
1748
+ PRIMARY KEY (session_uuid, file_path)
1749
+ );
1750
+
1751
+ CREATE INDEX IF NOT EXISTS idx_agent_file_reads_agent_read_at
1752
+ ON agent_file_reads(agent_id, read_at);
1753
+ `);
1740
1754
  try {
1741
1755
  const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
1742
1756
  if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
@@ -1751,6 +1765,13 @@ async function ensureSchema() {
1751
1765
  }
1752
1766
  } catch {
1753
1767
  }
1768
+ try {
1769
+ await client.execute({
1770
+ sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
1771
+ args: []
1772
+ });
1773
+ } catch {
1774
+ }
1754
1775
  try {
1755
1776
  await client.execute({
1756
1777
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
@@ -2932,12 +2932,26 @@ async function ensureSchema() {
2932
2932
  session_name TEXT,
2933
2933
  task_id TEXT,
2934
2934
  project_name TEXT,
2935
- started_at TEXT NOT NULL
2935
+ started_at TEXT NOT NULL,
2936
+ cache_cold_count INTEGER NOT NULL DEFAULT 0
2936
2937
  );
2937
2938
 
2938
2939
  CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
2939
2940
  ON session_agent_map(agent_id);
2940
2941
  `);
2942
+ await client.executeMultiple(`
2943
+ CREATE TABLE IF NOT EXISTS agent_file_reads (
2944
+ session_uuid TEXT NOT NULL,
2945
+ agent_id TEXT NOT NULL,
2946
+ file_path TEXT NOT NULL,
2947
+ read_at TEXT NOT NULL,
2948
+ commit_hash TEXT,
2949
+ PRIMARY KEY (session_uuid, file_path)
2950
+ );
2951
+
2952
+ CREATE INDEX IF NOT EXISTS idx_agent_file_reads_agent_read_at
2953
+ ON agent_file_reads(agent_id, read_at);
2954
+ `);
2941
2955
  try {
2942
2956
  const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
2943
2957
  if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
@@ -2952,6 +2966,13 @@ async function ensureSchema() {
2952
2966
  }
2953
2967
  } catch {
2954
2968
  }
2969
+ try {
2970
+ await client.execute({
2971
+ sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
2972
+ args: []
2973
+ });
2974
+ } catch {
2975
+ }
2955
2976
  try {
2956
2977
  await client.execute({
2957
2978
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
@@ -22180,6 +22201,109 @@ Key saved to ~/.exe-os/license.key. Device ID: ${deviceId}`);
22180
22201
  );
22181
22202
  }
22182
22203
 
22204
+ // src/mcp/tools/query-company-brain.ts
22205
+ init_config();
22206
+ import { z as z72 } from "zod";
22207
+ var FETCH_TIMEOUT_MS5 = 1e4;
22208
+ var QUERY_SCOPE = z72.enum(["raw", "wiki", "memory", "gateway", "all"]);
22209
+ function formatSuccess(query, scope, payload) {
22210
+ const pretty = typeof payload === "string" ? payload : JSON.stringify(payload, null, 2);
22211
+ return [
22212
+ `# Company Brain Query`,
22213
+ "",
22214
+ `query: ${query}`,
22215
+ `scope: ${scope}`,
22216
+ "",
22217
+ pretty
22218
+ ].join("\n");
22219
+ }
22220
+ function registerQueryCompanyBrain(server2) {
22221
+ server2.registerTool(
22222
+ "query_company_brain",
22223
+ {
22224
+ title: "Query Company Brain",
22225
+ description: "Search the Company Brain \u2014 queries across all data (raw events, wiki docs, agent memories, gateway messages).",
22226
+ inputSchema: {
22227
+ query: z72.string().min(1).describe("Search text"),
22228
+ scope: QUERY_SCOPE.default("all").describe("Which data scope to search"),
22229
+ source: z72.string().optional().describe("Filter raw events by source (shopify, asana, etc.)"),
22230
+ limit: z72.coerce.number().int().min(1).max(100).default(20).describe("Max results per scope")
22231
+ }
22232
+ },
22233
+ async ({ query, scope, source, limit }) => {
22234
+ const config2 = await loadConfig();
22235
+ const gatewayUrl = config2.gateway?.url || process.env.EXE_GATEWAY_URL;
22236
+ const authToken = config2.gateway?.authToken || process.env.EXE_GATEWAY_AUTH_TOKEN;
22237
+ if (!gatewayUrl) {
22238
+ return {
22239
+ content: [
22240
+ {
22241
+ type: "text",
22242
+ text: "Company Brain query not configured. Set gateway.url in ~/.exe-os/config.json"
22243
+ }
22244
+ ]
22245
+ };
22246
+ }
22247
+ let url;
22248
+ try {
22249
+ url = new URL("/query", gatewayUrl);
22250
+ } catch (err) {
22251
+ return {
22252
+ content: [
22253
+ {
22254
+ type: "text",
22255
+ text: `Company Brain query not configured. Invalid gateway.url: ${err instanceof Error ? err.message : String(err)}`
22256
+ }
22257
+ ],
22258
+ isError: true
22259
+ };
22260
+ }
22261
+ url.searchParams.set("q", query);
22262
+ url.searchParams.set("scope", scope);
22263
+ if (source) url.searchParams.set("source", source);
22264
+ url.searchParams.set("limit", String(limit));
22265
+ try {
22266
+ const response = await fetch(url.toString(), {
22267
+ headers: authToken ? { Authorization: `Bearer ${authToken}` } : {},
22268
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS5)
22269
+ });
22270
+ if (!response.ok) {
22271
+ const body = await response.text();
22272
+ return {
22273
+ content: [
22274
+ {
22275
+ type: "text",
22276
+ text: `Company Brain query failed (${response.status}): ${body || response.statusText}`
22277
+ }
22278
+ ],
22279
+ isError: true
22280
+ };
22281
+ }
22282
+ const contentType = response.headers.get("content-type") ?? "";
22283
+ const payload = contentType.includes("application/json") ? await response.json() : await response.text();
22284
+ return {
22285
+ content: [
22286
+ {
22287
+ type: "text",
22288
+ text: formatSuccess(query, scope, payload)
22289
+ }
22290
+ ]
22291
+ };
22292
+ } catch {
22293
+ return {
22294
+ content: [
22295
+ {
22296
+ type: "text",
22297
+ text: `Gateway unreachable at ${url.origin}`
22298
+ }
22299
+ ],
22300
+ isError: true
22301
+ };
22302
+ }
22303
+ }
22304
+ );
22305
+ }
22306
+
22183
22307
  // src/lib/telemetry.ts
22184
22308
  var ENABLED = process.env.EXE_TELEMETRY === "1";
22185
22309
  var initialized = false;
@@ -22320,6 +22444,7 @@ registerIngestRaw(server);
22320
22444
  registerCreateLicense(server);
22321
22445
  registerListLicenses(server);
22322
22446
  registerActivateLicense(server);
22447
+ registerQueryCompanyBrain(server);
22323
22448
  try {
22324
22449
  await initStore();
22325
22450
  process.stderr.write("[exe-os] MCP server starting...\n");
@@ -2827,12 +2827,26 @@ async function ensureSchema() {
2827
2827
  session_name TEXT,
2828
2828
  task_id TEXT,
2829
2829
  project_name TEXT,
2830
- started_at TEXT NOT NULL
2830
+ started_at TEXT NOT NULL,
2831
+ cache_cold_count INTEGER NOT NULL DEFAULT 0
2831
2832
  );
2832
2833
 
2833
2834
  CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
2834
2835
  ON session_agent_map(agent_id);
2835
2836
  `);
2837
+ await client.executeMultiple(`
2838
+ CREATE TABLE IF NOT EXISTS agent_file_reads (
2839
+ session_uuid TEXT NOT NULL,
2840
+ agent_id TEXT NOT NULL,
2841
+ file_path TEXT NOT NULL,
2842
+ read_at TEXT NOT NULL,
2843
+ commit_hash TEXT,
2844
+ PRIMARY KEY (session_uuid, file_path)
2845
+ );
2846
+
2847
+ CREATE INDEX IF NOT EXISTS idx_agent_file_reads_agent_read_at
2848
+ ON agent_file_reads(agent_id, read_at);
2849
+ `);
2836
2850
  try {
2837
2851
  const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
2838
2852
  if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
@@ -2847,6 +2861,13 @@ async function ensureSchema() {
2847
2861
  }
2848
2862
  } catch {
2849
2863
  }
2864
+ try {
2865
+ await client.execute({
2866
+ sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
2867
+ args: []
2868
+ });
2869
+ } catch {
2870
+ }
2850
2871
  try {
2851
2872
  await client.execute({
2852
2873
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
package/dist/tui/App.js CHANGED
@@ -3131,12 +3131,26 @@ async function ensureSchema() {
3131
3131
  session_name TEXT,
3132
3132
  task_id TEXT,
3133
3133
  project_name TEXT,
3134
- started_at TEXT NOT NULL
3134
+ started_at TEXT NOT NULL,
3135
+ cache_cold_count INTEGER NOT NULL DEFAULT 0
3135
3136
  );
3136
3137
 
3137
3138
  CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
3138
3139
  ON session_agent_map(agent_id);
3139
3140
  `);
3141
+ await client.executeMultiple(`
3142
+ CREATE TABLE IF NOT EXISTS agent_file_reads (
3143
+ session_uuid TEXT NOT NULL,
3144
+ agent_id TEXT NOT NULL,
3145
+ file_path TEXT NOT NULL,
3146
+ read_at TEXT NOT NULL,
3147
+ commit_hash TEXT,
3148
+ PRIMARY KEY (session_uuid, file_path)
3149
+ );
3150
+
3151
+ CREATE INDEX IF NOT EXISTS idx_agent_file_reads_agent_read_at
3152
+ ON agent_file_reads(agent_id, read_at);
3153
+ `);
3140
3154
  try {
3141
3155
  const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
3142
3156
  if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
@@ -3151,6 +3165,13 @@ async function ensureSchema() {
3151
3165
  }
3152
3166
  } catch {
3153
3167
  }
3168
+ try {
3169
+ await client.execute({
3170
+ sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
3171
+ args: []
3172
+ });
3173
+ } catch {
3174
+ }
3154
3175
  try {
3155
3176
  await client.execute({
3156
3177
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.9.11",
3
+ "version": "0.9.13",
4
4
  "description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
5
5
  "license": "CC-BY-NC-4.0",
6
6
  "type": "module",