@askexenow/exe-os 0.8.37 → 0.8.38

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 (66) hide show
  1. package/dist/bin/backfill-conversations.js +66 -60
  2. package/dist/bin/backfill-responses.js +7 -8
  3. package/dist/bin/backfill-vectors.js +1 -8
  4. package/dist/bin/cleanup-stale-review-tasks.js +1 -8
  5. package/dist/bin/cli.js +520 -325
  6. package/dist/bin/exe-assign.js +7 -8
  7. package/dist/bin/exe-boot.js +54 -21
  8. package/dist/bin/exe-call.js +9 -4
  9. package/dist/bin/exe-cloud.js +37 -3
  10. package/dist/bin/exe-doctor.js +1 -8
  11. package/dist/bin/exe-export-behaviors.js +4 -11
  12. package/dist/bin/exe-forget.js +1 -8
  13. package/dist/bin/exe-gateway.js +72 -30
  14. package/dist/bin/exe-heartbeat.js +4 -11
  15. package/dist/bin/exe-kill.js +1 -8
  16. package/dist/bin/exe-launch-agent.js +51 -14
  17. package/dist/bin/exe-link.js +13 -3
  18. package/dist/bin/exe-new-employee.js +35 -10
  19. package/dist/bin/exe-pending-messages.js +1 -8
  20. package/dist/bin/exe-pending-notifications.js +1 -8
  21. package/dist/bin/exe-pending-reviews.js +4 -11
  22. package/dist/bin/exe-review.js +7 -8
  23. package/dist/bin/exe-search.js +10 -11
  24. package/dist/bin/exe-session-cleanup.js +11 -12
  25. package/dist/bin/exe-status.js +1 -8
  26. package/dist/bin/exe-team.js +1 -8
  27. package/dist/bin/git-sweep.js +7 -8
  28. package/dist/bin/graph-backfill.js +1 -8
  29. package/dist/bin/graph-export.js +1 -8
  30. package/dist/bin/install.js +9 -0
  31. package/dist/bin/scan-tasks.js +7 -8
  32. package/dist/bin/setup.js +396 -245
  33. package/dist/bin/shard-migrate.js +1 -8
  34. package/dist/bin/wiki-sync.js +1 -8
  35. package/dist/gateway/index.js +30 -30
  36. package/dist/hooks/bug-report-worker.js +4 -11
  37. package/dist/hooks/commit-complete.js +7 -8
  38. package/dist/hooks/error-recall.js +11 -12
  39. package/dist/hooks/ingest-worker.js +24 -9
  40. package/dist/hooks/instructions-loaded.js +7 -8
  41. package/dist/hooks/notification.js +7 -8
  42. package/dist/hooks/post-compact.js +7 -8
  43. package/dist/hooks/pre-compact.js +7 -8
  44. package/dist/hooks/pre-tool-use.js +7 -8
  45. package/dist/hooks/prompt-ingest-worker.js +19 -4
  46. package/dist/hooks/prompt-submit.js +14 -9
  47. package/dist/hooks/response-ingest-worker.js +20 -5
  48. package/dist/hooks/session-end.js +11 -12
  49. package/dist/hooks/session-start.js +11 -12
  50. package/dist/hooks/stop.js +7 -8
  51. package/dist/hooks/subagent-stop.js +7 -8
  52. package/dist/hooks/summary-worker.js +24 -9
  53. package/dist/index.js +11 -5
  54. package/dist/lib/cloud-sync.js +19 -2
  55. package/dist/lib/employee-templates.js +5 -0
  56. package/dist/lib/exe-daemon.js +24 -8
  57. package/dist/lib/hybrid-search.js +10 -11
  58. package/dist/lib/identity-templates.js +16 -7
  59. package/dist/lib/license.js +43 -2
  60. package/dist/lib/schedules.js +1 -8
  61. package/dist/lib/store.js +7 -8
  62. package/dist/mcp/server.js +184 -113
  63. package/dist/mcp/tools/list-tasks.js +35 -27
  64. package/dist/runtime/index.js +7 -2
  65. package/dist/tui/App.js +44 -5
  66. package/package.json +4 -2
@@ -1895,7 +1895,7 @@ __export(shard_manager_exports, {
1895
1895
  shardExists: () => shardExists
1896
1896
  });
1897
1897
  import path4 from "path";
1898
- import { existsSync as existsSync4, mkdirSync } from "fs";
1898
+ import { existsSync as existsSync4, mkdirSync, readdirSync } from "fs";
1899
1899
  import { createClient as createClient2 } from "@libsql/client";
1900
1900
  function initShardManager(encryptionKey) {
1901
1901
  _encryptionKey = encryptionKey;
@@ -1934,8 +1934,7 @@ function shardExists(projectName) {
1934
1934
  }
1935
1935
  function listShards() {
1936
1936
  if (!existsSync4(SHARDS_DIR)) return [];
1937
- const { readdirSync: readdirSync3 } = __require("fs");
1938
- return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
1937
+ return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
1939
1938
  }
1940
1939
  async function ensureShardSchema(client) {
1941
1940
  await client.execute("PRAGMA journal_mode = WAL");
@@ -2218,6 +2217,12 @@ async function writeMemory(record) {
2218
2217
  supersedes_id: record.supersedes_id ?? null
2219
2218
  };
2220
2219
  _pendingRecords.push(dbRow);
2220
+ const MAX_PENDING = 1e3;
2221
+ if (_pendingRecords.length > MAX_PENDING) {
2222
+ const dropped = _pendingRecords.length - MAX_PENDING;
2223
+ _pendingRecords = _pendingRecords.slice(-MAX_PENDING);
2224
+ console.warn(`[store] Dropped ${dropped} oldest pending records (overflow)`);
2225
+ }
2221
2226
  if (_flushTimer === null) {
2222
2227
  _flushTimer = setInterval(() => {
2223
2228
  void flushBatch();
@@ -2703,6 +2708,8 @@ __export(license_exports, {
2703
2708
  loadLicense: () => loadLicense,
2704
2709
  mirrorLicenseKey: () => mirrorLicenseKey,
2705
2710
  saveLicense: () => saveLicense,
2711
+ startLicenseRevalidation: () => startLicenseRevalidation,
2712
+ stopLicenseRevalidation: () => stopLicenseRevalidation,
2706
2713
  validateLicense: () => validateLicense
2707
2714
  });
2708
2715
  import { readFileSync as readFileSync3, writeFileSync, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
@@ -2827,14 +2834,23 @@ async function validateLicense(apiKey, deviceId) {
2827
2834
  } catch {
2828
2835
  const cached = await getCachedLicense();
2829
2836
  if (cached) return cached;
2830
- return FREE_LICENSE;
2837
+ return { ...FREE_LICENSE, valid: false, error: "offline" };
2838
+ }
2839
+ }
2840
+ function getCacheAgeMs() {
2841
+ try {
2842
+ const { statSync: statSync2 } = __require("fs");
2843
+ const s = statSync2(CACHE_PATH);
2844
+ return Date.now() - s.mtimeMs;
2845
+ } catch {
2846
+ return Infinity;
2831
2847
  }
2832
2848
  }
2833
2849
  async function checkLicense() {
2834
2850
  const key = loadLicense();
2835
2851
  if (!key) return FREE_LICENSE;
2836
2852
  const cached = await getCachedLicense();
2837
- if (cached) return cached;
2853
+ if (cached && getCacheAgeMs() < CACHE_MAX_AGE_MS) return cached;
2838
2854
  const deviceId = loadDeviceId();
2839
2855
  return validateLicense(key, deviceId);
2840
2856
  }
@@ -2955,7 +2971,28 @@ async function assertVpsLicense(opts) {
2955
2971
  `License validation unreachable for more than ${graceDays} days. Restore network connectivity to https://askexe.com/cloud and retry. This VPS image refuses to boot after the offline grace window.`
2956
2972
  );
2957
2973
  }
2958
- var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE, LICENSE_PUBLIC_KEY_PEM, LICENSE_JWT_ALG, PLAN_LIMITS, FREE_LICENSE;
2974
+ function startLicenseRevalidation(intervalMs = 36e5) {
2975
+ if (_revalTimer) return;
2976
+ _revalTimer = setInterval(async () => {
2977
+ try {
2978
+ const license = await checkLicense();
2979
+ if (!license.valid) {
2980
+ process.stderr.write("[exe-os] License expired or invalid \u2014 features may be restricted\n");
2981
+ }
2982
+ } catch {
2983
+ }
2984
+ }, intervalMs);
2985
+ if (_revalTimer && typeof _revalTimer === "object" && "unref" in _revalTimer) {
2986
+ _revalTimer.unref();
2987
+ }
2988
+ }
2989
+ function stopLicenseRevalidation() {
2990
+ if (_revalTimer) {
2991
+ clearInterval(_revalTimer);
2992
+ _revalTimer = null;
2993
+ }
2994
+ }
2995
+ var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE, LICENSE_PUBLIC_KEY_PEM, LICENSE_JWT_ALG, PLAN_LIMITS, FREE_LICENSE, CACHE_MAX_AGE_MS, _revalTimer;
2959
2996
  var init_license = __esm({
2960
2997
  "src/lib/license.ts"() {
2961
2998
  "use strict";
@@ -2985,6 +3022,8 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
2985
3022
  employeeLimit: 1,
2986
3023
  memoryLimit: 5e3
2987
3024
  };
3025
+ CACHE_MAX_AGE_MS = 36e5;
3026
+ _revalTimer = null;
2988
3027
  }
2989
3028
  });
2990
3029
 
@@ -3813,6 +3852,7 @@ __export(imessage_exports, {
3813
3852
  });
3814
3853
  import { execFile } from "child_process";
3815
3854
  import { promisify } from "util";
3855
+ import os2 from "os";
3816
3856
  import path6 from "path";
3817
3857
  var execFileAsync, POLL_INTERVAL_MS, MESSAGES_DB_PATH, IMessageAdapter;
3818
3858
  var init_imessage = __esm({
@@ -3821,7 +3861,7 @@ var init_imessage = __esm({
3821
3861
  execFileAsync = promisify(execFile);
3822
3862
  POLL_INTERVAL_MS = 5e3;
3823
3863
  MESSAGES_DB_PATH = path6.join(
3824
- process.env.HOME ?? "/Users",
3864
+ process.env.HOME ?? os2.homedir(),
3825
3865
  "Library/Messages/chat.db"
3826
3866
  );
3827
3867
  IMessageAdapter = class {
@@ -4287,7 +4327,7 @@ var init_whatsapp_accounts = __esm({
4287
4327
  // src/lib/session-registry.ts
4288
4328
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync2, mkdirSync as mkdirSync4, existsSync as existsSync6 } from "fs";
4289
4329
  import path7 from "path";
4290
- import os2 from "os";
4330
+ import os3 from "os";
4291
4331
  function registerSession(entry) {
4292
4332
  const dir = path7.dirname(REGISTRY_PATH);
4293
4333
  if (!existsSync6(dir)) {
@@ -4314,7 +4354,7 @@ var REGISTRY_PATH;
4314
4354
  var init_session_registry = __esm({
4315
4355
  "src/lib/session-registry.ts"() {
4316
4356
  "use strict";
4317
- REGISTRY_PATH = path7.join(os2.homedir(), ".exe-os", "session-registry.json");
4357
+ REGISTRY_PATH = path7.join(os3.homedir(), ".exe-os", "session-registry.json");
4318
4358
  }
4319
4359
  });
4320
4360
 
@@ -4536,7 +4576,7 @@ var init_provider_table = __esm({
4536
4576
  // src/lib/intercom-queue.ts
4537
4577
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync3, renameSync as renameSync2, existsSync as existsSync7, mkdirSync as mkdirSync5 } from "fs";
4538
4578
  import path8 from "path";
4539
- import os3 from "os";
4579
+ import os4 from "os";
4540
4580
  function ensureDir() {
4541
4581
  const dir = path8.dirname(QUEUE_PATH);
4542
4582
  if (!existsSync7(dir)) mkdirSync5(dir, { recursive: true });
@@ -4576,9 +4616,9 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
4576
4616
  var init_intercom_queue = __esm({
4577
4617
  "src/lib/intercom-queue.ts"() {
4578
4618
  "use strict";
4579
- QUEUE_PATH = path8.join(os3.homedir(), ".exe-os", "intercom-queue.json");
4619
+ QUEUE_PATH = path8.join(os4.homedir(), ".exe-os", "intercom-queue.json");
4580
4620
  TTL_MS = 60 * 60 * 1e3;
4581
- INTERCOM_LOG = path8.join(os3.homedir(), ".exe-os", "intercom.log");
4621
+ INTERCOM_LOG = path8.join(os4.homedir(), ".exe-os", "intercom.log");
4582
4622
  }
4583
4623
  });
4584
4624
 
@@ -4696,7 +4736,7 @@ var init_plan_limits = __esm({
4696
4736
  import { execFileSync as execFileSync2, execSync as execSync4 } from "child_process";
4697
4737
  import { readFileSync as readFileSync9, writeFileSync as writeFileSync4, mkdirSync as mkdirSync6, existsSync as existsSync10, appendFileSync } from "fs";
4698
4738
  import path11 from "path";
4699
- import os4 from "os";
4739
+ import os5 from "os";
4700
4740
  import { fileURLToPath as fileURLToPath2 } from "url";
4701
4741
  import { unlinkSync as unlinkSync2 } from "fs";
4702
4742
  function spawnLockPath(sessionName) {
@@ -5001,7 +5041,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5001
5041
  const transport = getTransport();
5002
5042
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
5003
5043
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
5004
- const logDir = path11.join(os4.homedir(), ".exe-os", "session-logs");
5044
+ const logDir = path11.join(os5.homedir(), ".exe-os", "session-logs");
5005
5045
  const logFile = path11.join(logDir, `${instanceLabel}-${Date.now()}.log`);
5006
5046
  if (!existsSync10(logDir)) {
5007
5047
  mkdirSync6(logDir, { recursive: true });
@@ -5017,7 +5057,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5017
5057
  } catch {
5018
5058
  }
5019
5059
  try {
5020
- const claudeJsonPath = path11.join(os4.homedir(), ".claude.json");
5060
+ const claudeJsonPath = path11.join(os5.homedir(), ".claude.json");
5021
5061
  let claudeJson = {};
5022
5062
  try {
5023
5063
  claudeJson = JSON.parse(readFileSync9(claudeJsonPath, "utf8"));
@@ -5032,7 +5072,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5032
5072
  } catch {
5033
5073
  }
5034
5074
  try {
5035
- const settingsDir = path11.join(os4.homedir(), ".claude", "projects");
5075
+ const settingsDir = path11.join(os5.homedir(), ".claude", "projects");
5036
5076
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
5037
5077
  const projSettingsDir = path11.join(settingsDir, normalizedKey);
5038
5078
  const settingsPath = path11.join(projSettingsDir, "settings.json");
@@ -5080,7 +5120,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5080
5120
  let legacyFallbackWarned = false;
5081
5121
  if (!useExeAgent && !useBinSymlink) {
5082
5122
  const identityPath = path11.join(
5083
- os4.homedir(),
5123
+ os5.homedir(),
5084
5124
  ".exe-os",
5085
5125
  "identity",
5086
5126
  `${employeeName}.md`
@@ -5110,7 +5150,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
5110
5150
  }
5111
5151
  let sessionContextFlag = "";
5112
5152
  try {
5113
- const ctxDir = path11.join(os4.homedir(), ".exe-os", "session-cache");
5153
+ const ctxDir = path11.join(os5.homedir(), ".exe-os", "session-cache");
5114
5154
  mkdirSync6(ctxDir, { recursive: true });
5115
5155
  const ctxFile = path11.join(ctxDir, `session-context-${sessionName}.md`);
5116
5156
  const ctxContent = [
@@ -5221,11 +5261,11 @@ var init_tmux_routing = __esm({
5221
5261
  init_provider_table();
5222
5262
  init_intercom_queue();
5223
5263
  init_plan_limits();
5224
- SPAWN_LOCK_DIR = path11.join(os4.homedir(), ".exe-os", "spawn-locks");
5225
- SESSION_CACHE = path11.join(os4.homedir(), ".exe-os", "session-cache");
5264
+ SPAWN_LOCK_DIR = path11.join(os5.homedir(), ".exe-os", "spawn-locks");
5265
+ SESSION_CACHE = path11.join(os5.homedir(), ".exe-os", "session-cache");
5226
5266
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
5227
5267
  INTERCOM_DEBOUNCE_MS = 3e4;
5228
- INTERCOM_LOG2 = path11.join(os4.homedir(), ".exe-os", "intercom.log");
5268
+ INTERCOM_LOG2 = path11.join(os5.homedir(), ".exe-os", "intercom.log");
5229
5269
  DEBOUNCE_FILE = path11.join(SESSION_CACHE, "intercom-debounce.json");
5230
5270
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
5231
5271
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
@@ -5485,10 +5525,10 @@ var init_messaging = __esm({
5485
5525
  // src/lib/notifications.ts
5486
5526
  import crypto4 from "crypto";
5487
5527
  import path12 from "path";
5488
- import os5 from "os";
5528
+ import os6 from "os";
5489
5529
  import {
5490
5530
  readFileSync as readFileSync10,
5491
- readdirSync,
5531
+ readdirSync as readdirSync2,
5492
5532
  unlinkSync as unlinkSync3,
5493
5533
  existsSync as existsSync11,
5494
5534
  rmdirSync
@@ -5937,7 +5977,7 @@ var init_tasks_crud = __esm({
5937
5977
 
5938
5978
  // src/lib/tasks-review.ts
5939
5979
  import path14 from "path";
5940
- import { existsSync as existsSync13, readdirSync as readdirSync2, unlinkSync as unlinkSync4 } from "fs";
5980
+ import { existsSync as existsSync13, readdirSync as readdirSync3, unlinkSync as unlinkSync4 } from "fs";
5941
5981
  async function countPendingReviews() {
5942
5982
  const client = getClient();
5943
5983
  const result = await client.execute({
@@ -6059,7 +6099,7 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
6059
6099
  try {
6060
6100
  const cacheDir = path14.join(EXE_AI_DIR, "session-cache");
6061
6101
  if (existsSync13(cacheDir)) {
6062
- for (const f of readdirSync2(cacheDir)) {
6102
+ for (const f of readdirSync3(cacheDir)) {
6063
6103
  if (f.startsWith("review-notified-")) {
6064
6104
  unlinkSync4(path14.join(cacheDir, f));
6065
6105
  }
@@ -6802,7 +6842,7 @@ var init_tasks = __esm({
6802
6842
  import { readFileSync as readFileSync12, writeFileSync as writeFileSync6, existsSync as existsSync14, mkdirSync as mkdirSync8 } from "fs";
6803
6843
  import { randomUUID as randomUUID7 } from "crypto";
6804
6844
  import path18 from "path";
6805
- import os6 from "os";
6845
+ import os7 from "os";
6806
6846
  function substituteTemplate(template, record) {
6807
6847
  return template.replace(
6808
6848
  /\{\{(\w+(?:\.\w+)*)\}\}/g,
@@ -7091,7 +7131,7 @@ var TRIGGERS_PATH;
7091
7131
  var init_trigger_engine = __esm({
7092
7132
  "src/automation/trigger-engine.ts"() {
7093
7133
  "use strict";
7094
- TRIGGERS_PATH = path18.join(os6.homedir(), ".exe-os", "triggers.json");
7134
+ TRIGGERS_PATH = path18.join(os7.homedir(), ".exe-os", "triggers.json");
7095
7135
  }
7096
7136
  });
7097
7137
 
@@ -7155,7 +7195,7 @@ var init_crm_webhook = __esm({
7155
7195
  // src/bin/exe-gateway.ts
7156
7196
  import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
7157
7197
  import path19 from "path";
7158
- import os7 from "os";
7198
+ import os8 from "os";
7159
7199
 
7160
7200
  // src/gateway/webhook-server.ts
7161
7201
  import {
@@ -7979,7 +8019,7 @@ var BotRegistry = class {
7979
8019
  };
7980
8020
 
7981
8021
  // src/bin/exe-gateway.ts
7982
- var CONFIG_DIR = path19.join(os7.homedir(), ".exe-os");
8022
+ var CONFIG_DIR = path19.join(os8.homedir(), ".exe-os");
7983
8023
  var CONFIG_PATH3 = path19.join(CONFIG_DIR, "gateway.json");
7984
8024
  var DEFAULT_PORT = 3100;
7985
8025
  function loadConfig2() {
@@ -8135,6 +8175,8 @@ async function main() {
8135
8175
  console.log(`[exe-gateway] Ready on port ${port}`);
8136
8176
  }
8137
8177
  main().catch((err) => {
8138
- console.error("[exe-gateway] Fatal:", err);
8178
+ const msg = err instanceof Error ? err.message : String(err);
8179
+ console.error(`[exe-gateway] Fatal: ${msg}`);
8180
+ if (process.env.DEBUG) console.error(err);
8139
8181
  process.exit(1);
8140
8182
  });
@@ -1,12 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
5
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
6
- }) : x)(function(x) {
7
- if (typeof require !== "undefined") return require.apply(this, arguments);
8
- throw Error('Dynamic require of "' + x + '" is not supported');
9
- });
10
4
  var __esm = (fn, res) => function __init() {
11
5
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
6
  };
@@ -1124,7 +1118,7 @@ __export(shard_manager_exports, {
1124
1118
  shardExists: () => shardExists
1125
1119
  });
1126
1120
  import path3 from "path";
1127
- import { existsSync as existsSync3, mkdirSync } from "fs";
1121
+ import { existsSync as existsSync3, mkdirSync, readdirSync } from "fs";
1128
1122
  import { createClient as createClient2 } from "@libsql/client";
1129
1123
  function initShardManager(encryptionKey) {
1130
1124
  _encryptionKey = encryptionKey;
@@ -1163,8 +1157,7 @@ function shardExists(projectName) {
1163
1157
  }
1164
1158
  function listShards() {
1165
1159
  if (!existsSync3(SHARDS_DIR)) return [];
1166
- const { readdirSync: readdirSync3 } = __require("fs");
1167
- return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
1160
+ return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
1168
1161
  }
1169
1162
  async function ensureShardSchema(client) {
1170
1163
  await client.execute("PRAGMA journal_mode = WAL");
@@ -1372,7 +1365,7 @@ import path5 from "path";
1372
1365
  import os2 from "os";
1373
1366
  import {
1374
1367
  readFileSync as readFileSync3,
1375
- readdirSync,
1368
+ readdirSync as readdirSync2,
1376
1369
  unlinkSync,
1377
1370
  existsSync as existsSync5,
1378
1371
  rmdirSync
@@ -1523,7 +1516,7 @@ var init_tmux_routing = __esm({
1523
1516
 
1524
1517
  // src/lib/tasks-review.ts
1525
1518
  import path12 from "path";
1526
- import { existsSync as existsSync10, readdirSync as readdirSync2, unlinkSync as unlinkSync2 } from "fs";
1519
+ import { existsSync as existsSync10, readdirSync as readdirSync3, unlinkSync as unlinkSync2 } from "fs";
1527
1520
  async function listPendingReviews(limit) {
1528
1521
  const client = getClient();
1529
1522
  const result = await client.execute({
@@ -1,12 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
5
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
6
- }) : x)(function(x) {
7
- if (typeof require !== "undefined") return require.apply(this, arguments);
8
- throw Error('Dynamic require of "' + x + '" is not supported');
9
- });
10
4
  var __esm = (fn, res) => function __init() {
11
5
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
6
  };
@@ -218,7 +212,7 @@ __export(shard_manager_exports, {
218
212
  shardExists: () => shardExists
219
213
  });
220
214
  import path3 from "path";
221
- import { existsSync as existsSync3, mkdirSync } from "fs";
215
+ import { existsSync as existsSync3, mkdirSync, readdirSync } from "fs";
222
216
  import { createClient as createClient2 } from "@libsql/client";
223
217
  function initShardManager(encryptionKey) {
224
218
  _encryptionKey = encryptionKey;
@@ -257,7 +251,6 @@ function shardExists(projectName) {
257
251
  }
258
252
  function listShards() {
259
253
  if (!existsSync3(SHARDS_DIR)) return [];
260
- const { readdirSync } = __require("fs");
261
254
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
262
255
  }
263
256
  async function ensureShardSchema(client) {
@@ -218,7 +218,7 @@ __export(shard_manager_exports, {
218
218
  shardExists: () => shardExists
219
219
  });
220
220
  import path3 from "path";
221
- import { existsSync as existsSync3, mkdirSync } from "fs";
221
+ import { existsSync as existsSync3, mkdirSync, readdirSync } from "fs";
222
222
  import { createClient as createClient2 } from "@libsql/client";
223
223
  function initShardManager(encryptionKey) {
224
224
  _encryptionKey = encryptionKey;
@@ -257,8 +257,7 @@ function shardExists(projectName) {
257
257
  }
258
258
  function listShards() {
259
259
  if (!existsSync3(SHARDS_DIR)) return [];
260
- const { readdirSync: readdirSync4 } = __require("fs");
261
- return readdirSync4(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
260
+ return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
262
261
  }
263
262
  async function ensureShardSchema(client) {
264
263
  await client.execute("PRAGMA journal_mode = WAL");
@@ -589,6 +588,7 @@ __export(employee_templates_exports, {
589
588
  buildCustomEmployeePrompt: () => buildCustomEmployeePrompt,
590
589
  getSessionPrompt: () => getSessionPrompt,
591
590
  getTemplate: () => getTemplate,
591
+ getTemplateByRole: () => getTemplateByRole,
592
592
  personalizePrompt: () => personalizePrompt,
593
593
  renderClientCOOTemplate: () => renderClientCOOTemplate
594
594
  });
@@ -604,6 +604,10 @@ function buildCustomEmployeePrompt(name, role) {
604
604
  function getTemplate(name) {
605
605
  return TEMPLATES[name];
606
606
  }
607
+ function getTemplateByRole(role) {
608
+ const lower = role.toLowerCase();
609
+ return Object.values(TEMPLATES).find((t) => t.role.toLowerCase() === lower);
610
+ }
607
611
  function personalizePrompt(prompt, templateName, actualName) {
608
612
  if (templateName === actualName) return prompt;
609
613
  const escaped = templateName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -1240,7 +1244,7 @@ __export(active_agent_exports, {
1240
1244
  getAllActiveAgents: () => getAllActiveAgents,
1241
1245
  writeActiveAgent: () => writeActiveAgent
1242
1246
  });
1243
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, unlinkSync as unlinkSync2, readdirSync as readdirSync2 } from "fs";
1247
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, unlinkSync as unlinkSync2, readdirSync as readdirSync3 } from "fs";
1244
1248
  import { execSync as execSync4 } from "child_process";
1245
1249
  import path6 from "path";
1246
1250
  function getMarkerPath() {
@@ -1311,7 +1315,7 @@ function getActiveAgent() {
1311
1315
  }
1312
1316
  function getAllActiveAgents() {
1313
1317
  try {
1314
- const files = readdirSync2(CACHE_DIR);
1318
+ const files = readdirSync3(CACHE_DIR);
1315
1319
  const sessions = [];
1316
1320
  for (const file of files) {
1317
1321
  if (!file.startsWith("active-agent-") || !file.endsWith(".json")) continue;
@@ -1370,7 +1374,7 @@ var init_active_agent = __esm({
1370
1374
  // src/bin/exe-launch-agent.ts
1371
1375
  import os3 from "os";
1372
1376
  import path7 from "path";
1373
- import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, readdirSync as readdirSync3 } from "fs";
1377
+ import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, readdirSync as readdirSync4 } from "fs";
1374
1378
  import { spawnSync } from "child_process";
1375
1379
 
1376
1380
  // src/lib/database.ts
@@ -2500,7 +2504,7 @@ import path4 from "path";
2500
2504
  import {
2501
2505
  existsSync as existsSync4,
2502
2506
  mkdirSync as mkdirSync2,
2503
- readdirSync,
2507
+ readdirSync as readdirSync2,
2504
2508
  statSync,
2505
2509
  unlinkSync,
2506
2510
  writeFileSync
@@ -2548,7 +2552,7 @@ function sweepStaleBehaviorExports(now = Date.now()) {
2548
2552
  if (!existsSync4(BEHAVIORS_EXPORT_DIR)) return;
2549
2553
  let entries;
2550
2554
  try {
2551
- entries = readdirSync(BEHAVIORS_EXPORT_DIR);
2555
+ entries = readdirSync2(BEHAVIORS_EXPORT_DIR);
2552
2556
  } catch {
2553
2557
  return;
2554
2558
  }
@@ -2627,6 +2631,7 @@ function claudeSupportsAgentFlag() {
2627
2631
 
2628
2632
  // src/bin/exe-launch-agent.ts
2629
2633
  init_employees();
2634
+ import { execSync as execSync5 } from "child_process";
2630
2635
 
2631
2636
  // src/lib/provider-table.ts
2632
2637
  var PROVIDER_TABLE = {
@@ -2687,16 +2692,38 @@ function leanMcpConfigFor(agent) {
2687
2692
  const p = path7.join(os3.homedir(), ".exe-os", "mcp-configs", `${agent}-lean.json`);
2688
2693
  return existsSync6(p) ? p : null;
2689
2694
  }
2695
+ var _ccHelpOutput = null;
2696
+ function getCcHelpOutput() {
2697
+ if (_ccHelpOutput === null) {
2698
+ try {
2699
+ const result = execSync5("claude --help 2>&1", { encoding: "utf8", timeout: 5e3 });
2700
+ _ccHelpOutput = typeof result === "string" ? result : "";
2701
+ } catch {
2702
+ _ccHelpOutput = "";
2703
+ }
2704
+ }
2705
+ return _ccHelpOutput;
2706
+ }
2707
+ function ccSupportsFlag(flag) {
2708
+ return getCcHelpOutput().includes(flag);
2709
+ }
2710
+ function _resetCcHelpCache() {
2711
+ _ccHelpOutput = null;
2712
+ }
2690
2713
  function buildLaunchPlan(agent, behaviorsPath, passthrough, _hasAgentFlag, _provider) {
2691
2714
  const args = ["--dangerously-skip-permissions"];
2692
2715
  const idPath = identityPathFor(agent);
2693
2716
  const ccAgentPath = path7.join(os3.homedir(), ".claude", "agents", `${agent}.md`);
2694
2717
  const effectiveIdPath = existsSync6(idPath) ? idPath : existsSync6(ccAgentPath) ? ccAgentPath : null;
2695
2718
  if (effectiveIdPath) {
2696
- try {
2697
- const identity = readFileSync4(effectiveIdPath, "utf-8");
2698
- args.push("--system-prompt", identity);
2699
- } catch {
2719
+ if (ccSupportsFlag("--system-prompt")) {
2720
+ try {
2721
+ const identity = readFileSync4(effectiveIdPath, "utf-8");
2722
+ args.push("--system-prompt", identity);
2723
+ } catch {
2724
+ args.push("--append-system-prompt-file", effectiveIdPath);
2725
+ }
2726
+ } else {
2700
2727
  args.push("--append-system-prompt-file", effectiveIdPath);
2701
2728
  }
2702
2729
  }
@@ -2705,7 +2732,15 @@ function buildLaunchPlan(agent, behaviorsPath, passthrough, _hasAgentFlag, _prov
2705
2732
  }
2706
2733
  const leanMcp = leanMcpConfigFor(agent);
2707
2734
  if (leanMcp) {
2708
- args.push("--mcp-config", leanMcp, "--strict-mcp-config");
2735
+ if (ccSupportsFlag("--mcp-config")) {
2736
+ args.push("--mcp-config", leanMcp);
2737
+ if (ccSupportsFlag("--strict-mcp-config")) {
2738
+ args.push("--strict-mcp-config");
2739
+ }
2740
+ } else {
2741
+ process.stderr.write(`[exe-launch-agent] CC lacks --mcp-config \u2014 skipping lean MCP for ${agent}
2742
+ `);
2743
+ }
2709
2744
  }
2710
2745
  for (const arg of passthrough) args.push(arg);
2711
2746
  return { command: "claude", args };
@@ -2820,7 +2855,7 @@ async function main() {
2820
2855
  } else {
2821
2856
  try {
2822
2857
  const identityDir = path7.dirname(exeIdentity);
2823
- const files = readdirSync3(identityDir);
2858
+ const files = readdirSync4(identityDir);
2824
2859
  const match = files.find((f) => f.toLowerCase() === `${agent.toLowerCase()}.md`);
2825
2860
  if (match) sourceFile = path7.join(identityDir, match);
2826
2861
  } catch {
@@ -2890,8 +2925,10 @@ if (!process.env.VITEST) {
2890
2925
  export {
2891
2926
  DEFAULT_PROVIDER,
2892
2927
  PROVIDER_TABLE,
2928
+ _resetCcHelpCache,
2893
2929
  applyProviderEnv,
2894
2930
  buildLaunchPlan,
2931
+ ccSupportsFlag,
2895
2932
  parseBasename,
2896
2933
  resolveAgent
2897
2934
  };
@@ -535,14 +535,23 @@ async function validateLicense(apiKey, deviceId) {
535
535
  } catch {
536
536
  const cached = await getCachedLicense();
537
537
  if (cached) return cached;
538
- return FREE_LICENSE;
538
+ return { ...FREE_LICENSE, valid: false, error: "offline" };
539
+ }
540
+ }
541
+ function getCacheAgeMs() {
542
+ try {
543
+ const { statSync } = __require("fs");
544
+ const s = statSync(CACHE_PATH);
545
+ return Date.now() - s.mtimeMs;
546
+ } catch {
547
+ return Infinity;
539
548
  }
540
549
  }
541
550
  async function checkLicense() {
542
551
  const key = loadLicense();
543
552
  if (!key) return FREE_LICENSE;
544
553
  const cached = await getCachedLicense();
545
- if (cached) return cached;
554
+ if (cached && getCacheAgeMs() < CACHE_MAX_AGE_MS) return cached;
546
555
  const deviceId = loadDeviceId();
547
556
  return validateLicense(key, deviceId);
548
557
  }
@@ -556,7 +565,7 @@ function isFeatureAllowed(license, feature) {
556
565
  return license.plan === "team" || license.plan === "agency" || license.plan === "enterprise";
557
566
  }
558
567
  }
559
- var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE, LICENSE_PUBLIC_KEY_PEM, LICENSE_JWT_ALG, PLAN_LIMITS, FREE_LICENSE;
568
+ var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE, LICENSE_PUBLIC_KEY_PEM, LICENSE_JWT_ALG, PLAN_LIMITS, FREE_LICENSE, CACHE_MAX_AGE_MS;
560
569
  var init_license = __esm({
561
570
  "src/lib/license.ts"() {
562
571
  "use strict";
@@ -586,6 +595,7 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
586
595
  employeeLimit: 1,
587
596
  memoryLimit: 5e3
588
597
  };
598
+ CACHE_MAX_AGE_MS = 36e5;
589
599
  }
590
600
  });
591
601