@askexenow/exe-os 0.9.113 → 0.9.115

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 (86) hide show
  1. package/dist/bin/agentic-ontology-backfill.js +36 -12
  2. package/dist/bin/agentic-reflection-backfill.js +36 -12
  3. package/dist/bin/agentic-semantic-label.js +36 -12
  4. package/dist/bin/backfill-conversations.js +36 -12
  5. package/dist/bin/backfill-responses.js +36 -12
  6. package/dist/bin/backfill-vectors.js +36 -12
  7. package/dist/bin/bulk-sync-postgres.js +36 -12
  8. package/dist/bin/cleanup-stale-review-tasks.js +470 -113
  9. package/dist/bin/cli.js +413 -62
  10. package/dist/bin/exe-agent.js +27 -0
  11. package/dist/bin/exe-assign.js +36 -12
  12. package/dist/bin/exe-boot.js +246 -54
  13. package/dist/bin/exe-call.js +8 -0
  14. package/dist/bin/exe-cloud.js +47 -12
  15. package/dist/bin/exe-dispatch.js +348 -53
  16. package/dist/bin/exe-doctor.js +51 -13
  17. package/dist/bin/exe-export-behaviors.js +37 -12
  18. package/dist/bin/exe-forget.js +36 -12
  19. package/dist/bin/exe-gateway.js +348 -53
  20. package/dist/bin/exe-heartbeat.js +471 -113
  21. package/dist/bin/exe-kill.js +36 -12
  22. package/dist/bin/exe-launch-agent.js +117 -18
  23. package/dist/bin/exe-new-employee.js +9 -1
  24. package/dist/bin/exe-pending-messages.js +452 -95
  25. package/dist/bin/exe-pending-notifications.js +452 -95
  26. package/dist/bin/exe-pending-reviews.js +452 -95
  27. package/dist/bin/exe-rename.js +36 -12
  28. package/dist/bin/exe-review.js +36 -12
  29. package/dist/bin/exe-search.js +37 -12
  30. package/dist/bin/exe-session-cleanup.js +348 -53
  31. package/dist/bin/exe-settings.js +12 -0
  32. package/dist/bin/exe-start-codex.js +46 -13
  33. package/dist/bin/exe-start-opencode.js +46 -13
  34. package/dist/bin/exe-status.js +460 -114
  35. package/dist/bin/exe-support.js +12 -0
  36. package/dist/bin/exe-team.js +36 -12
  37. package/dist/bin/git-sweep.js +348 -53
  38. package/dist/bin/graph-backfill.js +36 -12
  39. package/dist/bin/graph-export.js +36 -12
  40. package/dist/bin/install.js +9 -1
  41. package/dist/bin/intercom-check.js +255 -53
  42. package/dist/bin/scan-tasks.js +348 -53
  43. package/dist/bin/setup.js +74 -12
  44. package/dist/bin/shard-migrate.js +36 -12
  45. package/dist/gateway/index.js +348 -53
  46. package/dist/hooks/bug-report-worker.js +348 -53
  47. package/dist/hooks/codex-stop-task-finalizer.js +308 -37
  48. package/dist/hooks/commit-complete.js +348 -53
  49. package/dist/hooks/error-recall.js +37 -12
  50. package/dist/hooks/ingest.js +363 -54
  51. package/dist/hooks/instructions-loaded.js +36 -12
  52. package/dist/hooks/notification.js +36 -12
  53. package/dist/hooks/post-compact.js +426 -72
  54. package/dist/hooks/post-tool-combined.js +501 -146
  55. package/dist/hooks/pre-compact.js +348 -53
  56. package/dist/hooks/pre-tool-use.js +92 -13
  57. package/dist/hooks/prompt-submit.js +348 -53
  58. package/dist/hooks/session-end.js +158 -53
  59. package/dist/hooks/session-start.js +66 -13
  60. package/dist/hooks/stop.js +420 -72
  61. package/dist/hooks/subagent-stop.js +419 -72
  62. package/dist/hooks/summary-worker.js +442 -121
  63. package/dist/index.js +375 -53
  64. package/dist/lib/agent-config.js +8 -0
  65. package/dist/lib/cloud-sync.js +35 -12
  66. package/dist/lib/config.js +13 -0
  67. package/dist/lib/consolidation.js +9 -1
  68. package/dist/lib/embedder.js +13 -0
  69. package/dist/lib/employees.js +8 -0
  70. package/dist/lib/exe-daemon.js +524 -60
  71. package/dist/lib/hybrid-search.js +37 -12
  72. package/dist/lib/keychain.js +25 -13
  73. package/dist/lib/messaging.js +395 -74
  74. package/dist/lib/schedules.js +36 -12
  75. package/dist/lib/skill-learning.js +21 -0
  76. package/dist/lib/store.js +36 -12
  77. package/dist/lib/tasks.js +324 -41
  78. package/dist/lib/tmux-routing.js +324 -41
  79. package/dist/mcp/server.js +374 -54
  80. package/dist/mcp/tools/create-task.js +324 -41
  81. package/dist/mcp/tools/list-tasks.js +406 -57
  82. package/dist/mcp/tools/send-message.js +395 -74
  83. package/dist/mcp/tools/update-task.js +324 -41
  84. package/dist/runtime/index.js +375 -53
  85. package/dist/tui/App.js +377 -55
  86. package/package.json +1 -1
@@ -219,6 +219,17 @@ function normalizeOrchestration(raw) {
219
219
  const userOrg = raw.orchestration ?? {};
220
220
  raw.orchestration = { ...defaultOrg, ...userOrg };
221
221
  }
222
+ function normalizeCloudEndpoint(raw) {
223
+ const cloud = raw.cloud;
224
+ if (!cloud?.endpoint) return;
225
+ const ep = String(cloud.endpoint);
226
+ if (ep === "https://askexe.com/cloud" || ep === "https://askexe.com/cloud/") {
227
+ cloud.endpoint = "https://cloud.askexe.com";
228
+ process.stderr.write(
229
+ "[config] Auto-migrated cloud endpoint: askexe.com/cloud \u2192 cloud.askexe.com\n"
230
+ );
231
+ }
232
+ }
222
233
  async function loadConfig() {
223
234
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
224
235
  await ensurePrivateDir(dir);
@@ -244,6 +255,7 @@ async function loadConfig() {
244
255
  normalizeSessionLifecycle(migratedCfg);
245
256
  normalizeAutoUpdate(migratedCfg);
246
257
  normalizeOrchestration(migratedCfg);
258
+ normalizeCloudEndpoint(migratedCfg);
247
259
  const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
248
260
  if (config.dbPath.startsWith("~")) {
249
261
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -272,6 +284,7 @@ function loadConfigSync() {
272
284
  normalizeSessionLifecycle(migratedCfg);
273
285
  normalizeAutoUpdate(migratedCfg);
274
286
  normalizeOrchestration(migratedCfg);
287
+ normalizeCloudEndpoint(migratedCfg);
275
288
  const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
276
289
  if (config.dbPath.startsWith("~")) {
277
290
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -432,6 +445,7 @@ __export(agent_config_exports, {
432
445
  clearAgentRuntime: () => clearAgentRuntime,
433
446
  getAgentRuntime: () => getAgentRuntime,
434
447
  loadAgentConfig: () => loadAgentConfig,
448
+ normalizeCcModelName: () => normalizeCcModelName,
435
449
  saveAgentConfig: () => saveAgentConfig,
436
450
  setAgentMcps: () => setAgentMcps,
437
451
  setAgentRuntime: () => setAgentRuntime
@@ -460,6 +474,13 @@ function getAgentRuntime(agentId) {
460
474
  if (orgDefault) return orgDefault;
461
475
  return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
462
476
  }
477
+ function normalizeCcModelName(model) {
478
+ let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
479
+ if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
480
+ ccModel += "[1m]";
481
+ }
482
+ return ccModel;
483
+ }
463
484
  function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
464
485
  const knownModels = KNOWN_RUNTIMES[runtime];
465
486
  if (!knownModels) {
@@ -5161,7 +5182,7 @@ function readOrCreateDaemonToken(homeDir = os9.homedir()) {
5161
5182
  function buildMcpHttpHeaders(homeDir = os9.homedir(), opts = {}) {
5162
5183
  const agentId = opts.useShellPlaceholders ? "${AGENT_ID:-exe}" : opts.agentId ?? DEFAULT_MCP_HTTP_AGENT_ID;
5163
5184
  const agentRole = opts.useShellPlaceholders ? "${AGENT_ROLE:-COO}" : opts.agentRole ?? DEFAULT_MCP_HTTP_AGENT_ROLE;
5164
- const sessionName = opts.useShellPlaceholders ? "$(tmux display-message -p '#{session_name}' 2>/dev/null || echo '')" : process.env.EXE_SESSION_NAME ?? "";
5185
+ const sessionName = opts.useShellPlaceholders ? "" : process.env.EXE_SESSION_NAME ?? "";
5165
5186
  const headers = {
5166
5187
  Authorization: `Bearer ${readOrCreateDaemonToken(homeDir)}`,
5167
5188
  "X-Agent-Id": agentId,
@@ -5714,7 +5735,7 @@ init_memory();
5714
5735
  init_database();
5715
5736
 
5716
5737
  // src/lib/keychain.ts
5717
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
5738
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
5718
5739
  import { existsSync as existsSync8, statSync as statSync3 } from "fs";
5719
5740
  import { execSync as execSync3 } from "child_process";
5720
5741
  import path7 from "path";
@@ -5753,12 +5774,14 @@ function linuxSecretAvailable() {
5753
5774
  function isRootOnlyTrustedServerKeyFile(keyPath) {
5754
5775
  if (process.platform !== "linux") return false;
5755
5776
  try {
5756
- const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
5757
5777
  const st = statSync3(keyPath);
5758
5778
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
5779
+ const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
5759
5780
  if (uid === 0) return true;
5760
5781
  const exeOsDir = process.env.EXE_OS_DIR;
5761
- return Boolean(exeOsDir && path7.resolve(keyPath).startsWith(path7.resolve(exeOsDir) + path7.sep));
5782
+ if (exeOsDir && path7.resolve(keyPath).startsWith(path7.resolve(exeOsDir) + path7.sep)) return true;
5783
+ if (!linuxSecretAvailable()) return true;
5784
+ return false;
5762
5785
  } catch {
5763
5786
  return false;
5764
5787
  }
@@ -5909,15 +5932,25 @@ async function writeMachineBoundFileFallback(b64) {
5909
5932
  await mkdir3(dir, { recursive: true });
5910
5933
  const keyPath = getKeyPath();
5911
5934
  const machineKey = deriveMachineKey();
5912
- if (machineKey) {
5913
- const encrypted = encryptWithMachineKey(b64, machineKey);
5914
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
5915
- await chmod2(keyPath, 384);
5916
- return "encrypted";
5935
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
5936
+ const result = machineKey ? "encrypted" : "plaintext";
5937
+ const tmpPath = keyPath + ".tmp";
5938
+ try {
5939
+ if (existsSync8(keyPath)) {
5940
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
5941
+ });
5942
+ }
5943
+ await writeFile3(tmpPath, content, "utf-8");
5944
+ await chmod2(tmpPath, 384);
5945
+ await rename(tmpPath, keyPath);
5946
+ } catch (err) {
5947
+ try {
5948
+ await unlink(tmpPath);
5949
+ } catch {
5950
+ }
5951
+ throw err;
5917
5952
  }
5918
- await writeFile3(keyPath, b64 + "\n", "utf-8");
5919
- await chmod2(keyPath, 384);
5920
- return "plaintext";
5953
+ return result;
5921
5954
  }
5922
5955
  async function getMasterKey() {
5923
5956
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -5984,7 +6017,7 @@ async function getMasterKey() {
5984
6017
  b64Value = content;
5985
6018
  }
5986
6019
  const key = Buffer.from(b64Value, "base64");
5987
- if (!content.startsWith(ENCRYPTED_PREFIX) && isRootOnlyTrustedServerKeyFile(keyPath)) {
6020
+ if (isRootOnlyTrustedServerKeyFile(keyPath)) {
5988
6021
  return key;
5989
6022
  }
5990
6023
  const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
@@ -219,6 +219,17 @@ function normalizeOrchestration(raw) {
219
219
  const userOrg = raw.orchestration ?? {};
220
220
  raw.orchestration = { ...defaultOrg, ...userOrg };
221
221
  }
222
+ function normalizeCloudEndpoint(raw) {
223
+ const cloud = raw.cloud;
224
+ if (!cloud?.endpoint) return;
225
+ const ep = String(cloud.endpoint);
226
+ if (ep === "https://askexe.com/cloud" || ep === "https://askexe.com/cloud/") {
227
+ cloud.endpoint = "https://cloud.askexe.com";
228
+ process.stderr.write(
229
+ "[config] Auto-migrated cloud endpoint: askexe.com/cloud \u2192 cloud.askexe.com\n"
230
+ );
231
+ }
232
+ }
222
233
  async function loadConfig() {
223
234
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
224
235
  await ensurePrivateDir(dir);
@@ -244,6 +255,7 @@ async function loadConfig() {
244
255
  normalizeSessionLifecycle(migratedCfg);
245
256
  normalizeAutoUpdate(migratedCfg);
246
257
  normalizeOrchestration(migratedCfg);
258
+ normalizeCloudEndpoint(migratedCfg);
247
259
  const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
248
260
  if (config.dbPath.startsWith("~")) {
249
261
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -272,6 +284,7 @@ function loadConfigSync() {
272
284
  normalizeSessionLifecycle(migratedCfg);
273
285
  normalizeAutoUpdate(migratedCfg);
274
286
  normalizeOrchestration(migratedCfg);
287
+ normalizeCloudEndpoint(migratedCfg);
275
288
  const config = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
276
289
  if (config.dbPath.startsWith("~")) {
277
290
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -432,6 +445,7 @@ __export(agent_config_exports, {
432
445
  clearAgentRuntime: () => clearAgentRuntime,
433
446
  getAgentRuntime: () => getAgentRuntime,
434
447
  loadAgentConfig: () => loadAgentConfig,
448
+ normalizeCcModelName: () => normalizeCcModelName,
435
449
  saveAgentConfig: () => saveAgentConfig,
436
450
  setAgentMcps: () => setAgentMcps,
437
451
  setAgentRuntime: () => setAgentRuntime
@@ -460,6 +474,13 @@ function getAgentRuntime(agentId) {
460
474
  if (orgDefault) return orgDefault;
461
475
  return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
462
476
  }
477
+ function normalizeCcModelName(model) {
478
+ let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
479
+ if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
480
+ ccModel += "[1m]";
481
+ }
482
+ return ccModel;
483
+ }
463
484
  function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
464
485
  const knownModels = KNOWN_RUNTIMES[runtime];
465
486
  if (!knownModels) {
@@ -5151,7 +5172,7 @@ function readOrCreateDaemonToken(homeDir = os9.homedir()) {
5151
5172
  function buildMcpHttpHeaders(homeDir = os9.homedir(), opts = {}) {
5152
5173
  const agentId = opts.useShellPlaceholders ? "${AGENT_ID:-exe}" : opts.agentId ?? DEFAULT_MCP_HTTP_AGENT_ID;
5153
5174
  const agentRole = opts.useShellPlaceholders ? "${AGENT_ROLE:-COO}" : opts.agentRole ?? DEFAULT_MCP_HTTP_AGENT_ROLE;
5154
- const sessionName = opts.useShellPlaceholders ? "$(tmux display-message -p '#{session_name}' 2>/dev/null || echo '')" : process.env.EXE_SESSION_NAME ?? "";
5175
+ const sessionName = opts.useShellPlaceholders ? "" : process.env.EXE_SESSION_NAME ?? "";
5155
5176
  const headers = {
5156
5177
  Authorization: `Bearer ${readOrCreateDaemonToken(homeDir)}`,
5157
5178
  "X-Agent-Id": agentId,
@@ -5667,7 +5688,7 @@ init_memory();
5667
5688
  init_database();
5668
5689
 
5669
5690
  // src/lib/keychain.ts
5670
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
5691
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
5671
5692
  import { existsSync as existsSync8, statSync as statSync3 } from "fs";
5672
5693
  import { execSync as execSync3 } from "child_process";
5673
5694
  import path7 from "path";
@@ -5706,12 +5727,14 @@ function linuxSecretAvailable() {
5706
5727
  function isRootOnlyTrustedServerKeyFile(keyPath) {
5707
5728
  if (process.platform !== "linux") return false;
5708
5729
  try {
5709
- const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
5710
5730
  const st = statSync3(keyPath);
5711
5731
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
5732
+ const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
5712
5733
  if (uid === 0) return true;
5713
5734
  const exeOsDir = process.env.EXE_OS_DIR;
5714
- return Boolean(exeOsDir && path7.resolve(keyPath).startsWith(path7.resolve(exeOsDir) + path7.sep));
5735
+ if (exeOsDir && path7.resolve(keyPath).startsWith(path7.resolve(exeOsDir) + path7.sep)) return true;
5736
+ if (!linuxSecretAvailable()) return true;
5737
+ return false;
5715
5738
  } catch {
5716
5739
  return false;
5717
5740
  }
@@ -5862,15 +5885,25 @@ async function writeMachineBoundFileFallback(b64) {
5862
5885
  await mkdir3(dir, { recursive: true });
5863
5886
  const keyPath = getKeyPath();
5864
5887
  const machineKey = deriveMachineKey();
5865
- if (machineKey) {
5866
- const encrypted = encryptWithMachineKey(b64, machineKey);
5867
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
5868
- await chmod2(keyPath, 384);
5869
- return "encrypted";
5888
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
5889
+ const result = machineKey ? "encrypted" : "plaintext";
5890
+ const tmpPath = keyPath + ".tmp";
5891
+ try {
5892
+ if (existsSync8(keyPath)) {
5893
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
5894
+ });
5895
+ }
5896
+ await writeFile3(tmpPath, content, "utf-8");
5897
+ await chmod2(tmpPath, 384);
5898
+ await rename(tmpPath, keyPath);
5899
+ } catch (err) {
5900
+ try {
5901
+ await unlink(tmpPath);
5902
+ } catch {
5903
+ }
5904
+ throw err;
5870
5905
  }
5871
- await writeFile3(keyPath, b64 + "\n", "utf-8");
5872
- await chmod2(keyPath, 384);
5873
- return "plaintext";
5906
+ return result;
5874
5907
  }
5875
5908
  async function getMasterKey() {
5876
5909
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -5937,7 +5970,7 @@ async function getMasterKey() {
5937
5970
  b64Value = content;
5938
5971
  }
5939
5972
  const key = Buffer.from(b64Value, "base64");
5940
- if (!content.startsWith(ENCRYPTED_PREFIX) && isRootOnlyTrustedServerKeyFile(keyPath)) {
5973
+ if (isRootOnlyTrustedServerKeyFile(keyPath)) {
5941
5974
  return key;
5942
5975
  }
5943
5976
  const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);