@askexenow/exe-os 0.9.113 → 0.9.114

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 (79) hide show
  1. package/dist/bin/agentic-ontology-backfill.js +24 -12
  2. package/dist/bin/agentic-reflection-backfill.js +24 -12
  3. package/dist/bin/agentic-semantic-label.js +24 -12
  4. package/dist/bin/backfill-conversations.js +24 -12
  5. package/dist/bin/backfill-responses.js +24 -12
  6. package/dist/bin/backfill-vectors.js +24 -12
  7. package/dist/bin/bulk-sync-postgres.js +24 -12
  8. package/dist/bin/cleanup-stale-review-tasks.js +24 -12
  9. package/dist/bin/cli.js +96 -22
  10. package/dist/bin/exe-agent.js +27 -0
  11. package/dist/bin/exe-assign.js +24 -12
  12. package/dist/bin/exe-boot.js +44 -15
  13. package/dist/bin/exe-call.js +8 -0
  14. package/dist/bin/exe-cloud.js +34 -11
  15. package/dist/bin/exe-dispatch.js +34 -16
  16. package/dist/bin/exe-doctor.js +24 -12
  17. package/dist/bin/exe-export-behaviors.js +24 -12
  18. package/dist/bin/exe-forget.js +24 -12
  19. package/dist/bin/exe-gateway.js +33 -15
  20. package/dist/bin/exe-heartbeat.js +24 -12
  21. package/dist/bin/exe-kill.js +24 -12
  22. package/dist/bin/exe-launch-agent.js +103 -17
  23. package/dist/bin/exe-new-employee.js +9 -1
  24. package/dist/bin/exe-pending-messages.js +24 -12
  25. package/dist/bin/exe-pending-notifications.js +24 -12
  26. package/dist/bin/exe-pending-reviews.js +24 -12
  27. package/dist/bin/exe-rename.js +24 -12
  28. package/dist/bin/exe-review.js +24 -12
  29. package/dist/bin/exe-search.js +24 -12
  30. package/dist/bin/exe-session-cleanup.js +33 -15
  31. package/dist/bin/exe-start-codex.js +33 -13
  32. package/dist/bin/exe-start-opencode.js +33 -13
  33. package/dist/bin/exe-status.js +24 -12
  34. package/dist/bin/exe-team.js +24 -12
  35. package/dist/bin/git-sweep.js +34 -16
  36. package/dist/bin/graph-backfill.js +24 -12
  37. package/dist/bin/graph-export.js +24 -12
  38. package/dist/bin/install.js +9 -1
  39. package/dist/bin/intercom-check.js +33 -15
  40. package/dist/bin/scan-tasks.js +34 -16
  41. package/dist/bin/setup.js +60 -11
  42. package/dist/bin/shard-migrate.js +24 -12
  43. package/dist/gateway/index.js +33 -15
  44. package/dist/hooks/bug-report-worker.js +33 -15
  45. package/dist/hooks/codex-stop-task-finalizer.js +32 -12
  46. package/dist/hooks/commit-complete.js +34 -16
  47. package/dist/hooks/error-recall.js +24 -12
  48. package/dist/hooks/ingest.js +33 -15
  49. package/dist/hooks/instructions-loaded.js +24 -12
  50. package/dist/hooks/notification.js +24 -12
  51. package/dist/hooks/post-compact.js +24 -12
  52. package/dist/hooks/post-tool-combined.js +24 -12
  53. package/dist/hooks/pre-compact.js +34 -16
  54. package/dist/hooks/pre-tool-use.js +58 -11
  55. package/dist/hooks/prompt-submit.js +33 -15
  56. package/dist/hooks/session-end.js +34 -16
  57. package/dist/hooks/session-start.js +32 -12
  58. package/dist/hooks/stop.js +24 -12
  59. package/dist/hooks/subagent-stop.js +24 -12
  60. package/dist/hooks/summary-worker.js +34 -11
  61. package/dist/index.js +60 -15
  62. package/dist/lib/agent-config.js +8 -0
  63. package/dist/lib/cloud-sync.js +34 -11
  64. package/dist/lib/consolidation.js +9 -1
  65. package/dist/lib/employees.js +8 -0
  66. package/dist/lib/exe-daemon.js +174 -17
  67. package/dist/lib/hybrid-search.js +24 -12
  68. package/dist/lib/keychain.js +24 -12
  69. package/dist/lib/schedules.js +24 -12
  70. package/dist/lib/skill-learning.js +8 -0
  71. package/dist/lib/store.js +24 -12
  72. package/dist/lib/tasks.js +10 -4
  73. package/dist/lib/tmux-routing.js +10 -4
  74. package/dist/mcp/server.js +44 -15
  75. package/dist/mcp/tools/create-task.js +10 -4
  76. package/dist/mcp/tools/update-task.js +10 -4
  77. package/dist/runtime/index.js +60 -15
  78. package/dist/tui/App.js +61 -16
  79. package/package.json +1 -1
@@ -370,6 +370,7 @@ __export(agent_config_exports, {
370
370
  clearAgentRuntime: () => clearAgentRuntime,
371
371
  getAgentRuntime: () => getAgentRuntime,
372
372
  loadAgentConfig: () => loadAgentConfig,
373
+ normalizeCcModelName: () => normalizeCcModelName,
373
374
  saveAgentConfig: () => saveAgentConfig,
374
375
  setAgentMcps: () => setAgentMcps,
375
376
  setAgentRuntime: () => setAgentRuntime
@@ -398,6 +399,13 @@ function getAgentRuntime(agentId) {
398
399
  if (orgDefault) return orgDefault;
399
400
  return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
400
401
  }
402
+ function normalizeCcModelName(model) {
403
+ let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
404
+ if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
405
+ ccModel += "[1m]";
406
+ }
407
+ return ccModel;
408
+ }
401
409
  function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
402
410
  const knownModels = KNOWN_RUNTIMES[runtime];
403
411
  if (!knownModels) {
@@ -4303,7 +4311,7 @@ var init_cto_delegation_gate = __esm({
4303
4311
  });
4304
4312
 
4305
4313
  // src/lib/keychain.ts
4306
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
4314
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
4307
4315
  import { existsSync as existsSync14, statSync as statSync4 } from "fs";
4308
4316
  import { execSync as execSync6 } from "child_process";
4309
4317
  import path15 from "path";
@@ -4338,12 +4346,14 @@ function linuxSecretAvailable() {
4338
4346
  function isRootOnlyTrustedServerKeyFile(keyPath) {
4339
4347
  if (process.platform !== "linux") return false;
4340
4348
  try {
4341
- const uid = typeof os11.userInfo().uid === "number" ? os11.userInfo().uid : -1;
4342
4349
  const st = statSync4(keyPath);
4343
4350
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
4351
+ const uid = typeof os11.userInfo().uid === "number" ? os11.userInfo().uid : -1;
4344
4352
  if (uid === 0) return true;
4345
4353
  const exeOsDir = process.env.EXE_OS_DIR;
4346
- return Boolean(exeOsDir && path15.resolve(keyPath).startsWith(path15.resolve(exeOsDir) + path15.sep));
4354
+ if (exeOsDir && path15.resolve(keyPath).startsWith(path15.resolve(exeOsDir) + path15.sep)) return true;
4355
+ if (!linuxSecretAvailable()) return true;
4356
+ return false;
4347
4357
  } catch {
4348
4358
  return false;
4349
4359
  }
@@ -4493,15 +4503,25 @@ async function writeMachineBoundFileFallback(b64) {
4493
4503
  await mkdir3(dir, { recursive: true });
4494
4504
  const keyPath = getKeyPath();
4495
4505
  const machineKey = deriveMachineKey();
4496
- if (machineKey) {
4497
- const encrypted = encryptWithMachineKey(b64, machineKey);
4498
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
4499
- await chmod2(keyPath, 384);
4500
- return "encrypted";
4506
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
4507
+ const result = machineKey ? "encrypted" : "plaintext";
4508
+ const tmpPath = keyPath + ".tmp";
4509
+ try {
4510
+ if (existsSync14(keyPath)) {
4511
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
4512
+ });
4513
+ }
4514
+ await writeFile3(tmpPath, content, "utf-8");
4515
+ await chmod2(tmpPath, 384);
4516
+ await rename(tmpPath, keyPath);
4517
+ } catch (err) {
4518
+ try {
4519
+ await unlink(tmpPath);
4520
+ } catch {
4521
+ }
4522
+ throw err;
4501
4523
  }
4502
- await writeFile3(keyPath, b64 + "\n", "utf-8");
4503
- await chmod2(keyPath, 384);
4504
- return "plaintext";
4524
+ return result;
4505
4525
  }
4506
4526
  async function getMasterKey() {
4507
4527
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -7352,6 +7372,33 @@ Do NOT report this as successful. No file was changed. If you are a sub-agent, r
7352
7372
  } catch {
7353
7373
  }
7354
7374
  }
7375
+ if (data.tool_name === "Bash") {
7376
+ const command = String(data.tool_input?.command ?? "");
7377
+ if (command) {
7378
+ const mcpBypassPatterns = [
7379
+ { regex: /\bsqlite3\b.*\b(memories\.db|\.exe-os)\b/, reason: "Direct SQLite access to exe-os database" },
7380
+ { regex: /\bnode\s+-e\b.*\b(better-sqlite3|libsql|sqlite3)\b/, reason: "Inline Node.js script accessing SQLite" },
7381
+ { regex: /\brequire\s*\(\s*['"].*memories\.db['"]\s*\)/, reason: "Direct require of memories database" }
7382
+ ];
7383
+ for (const { regex, reason } of mcpBypassPatterns) {
7384
+ if (regex.test(command)) {
7385
+ process.stderr.write(
7386
+ `[pre-tool-use] MCP bypass BLOCKED: ${reason}
7387
+ `
7388
+ );
7389
+ const output = JSON.stringify({
7390
+ hookSpecificOutput: { permissionDecision: "deny" },
7391
+ systemMessage: `BLOCKED: ${reason}.
7392
+ The exe-os database is encrypted and must ONLY be accessed through MCP tools.
7393
+ If MCP is disconnected, tell the user: "MCP server is disconnected. Please run /mcp to reconnect."
7394
+ Do NOT attempt workarounds \u2014 direct DB access bypasses encryption, breaks data integrity, and violates the contract boundary.`
7395
+ });
7396
+ process.stdout.write(output);
7397
+ process.exit(0);
7398
+ }
7399
+ }
7400
+ }
7401
+ }
7355
7402
  } catch {
7356
7403
  }
7357
7404
  clearTimeout(timeout);
@@ -431,6 +431,7 @@ __export(agent_config_exports, {
431
431
  clearAgentRuntime: () => clearAgentRuntime,
432
432
  getAgentRuntime: () => getAgentRuntime,
433
433
  loadAgentConfig: () => loadAgentConfig,
434
+ normalizeCcModelName: () => normalizeCcModelName,
434
435
  saveAgentConfig: () => saveAgentConfig,
435
436
  setAgentMcps: () => setAgentMcps,
436
437
  setAgentRuntime: () => setAgentRuntime
@@ -459,6 +460,13 @@ function getAgentRuntime(agentId) {
459
460
  if (orgDefault) return orgDefault;
460
461
  return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
461
462
  }
463
+ function normalizeCcModelName(model) {
464
+ let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
465
+ if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
466
+ ccModel += "[1m]";
467
+ }
468
+ return ccModel;
469
+ }
462
470
  function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
463
471
  const knownModels = KNOWN_RUNTIMES[runtime];
464
472
  if (!knownModels) {
@@ -3741,7 +3749,7 @@ var init_database = __esm({
3741
3749
  });
3742
3750
 
3743
3751
  // src/lib/keychain.ts
3744
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3752
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3745
3753
  import { existsSync as existsSync8, statSync as statSync3 } from "fs";
3746
3754
  import { execSync as execSync3 } from "child_process";
3747
3755
  import path7 from "path";
@@ -3776,12 +3784,14 @@ function linuxSecretAvailable() {
3776
3784
  function isRootOnlyTrustedServerKeyFile(keyPath) {
3777
3785
  if (process.platform !== "linux") return false;
3778
3786
  try {
3779
- const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3780
3787
  const st = statSync3(keyPath);
3781
3788
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3789
+ const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3782
3790
  if (uid === 0) return true;
3783
3791
  const exeOsDir = process.env.EXE_OS_DIR;
3784
- return Boolean(exeOsDir && path7.resolve(keyPath).startsWith(path7.resolve(exeOsDir) + path7.sep));
3792
+ if (exeOsDir && path7.resolve(keyPath).startsWith(path7.resolve(exeOsDir) + path7.sep)) return true;
3793
+ if (!linuxSecretAvailable()) return true;
3794
+ return false;
3785
3795
  } catch {
3786
3796
  return false;
3787
3797
  }
@@ -3931,15 +3941,25 @@ async function writeMachineBoundFileFallback(b64) {
3931
3941
  await mkdir3(dir, { recursive: true });
3932
3942
  const keyPath = getKeyPath();
3933
3943
  const machineKey = deriveMachineKey();
3934
- if (machineKey) {
3935
- const encrypted = encryptWithMachineKey(b64, machineKey);
3936
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
3937
- await chmod2(keyPath, 384);
3938
- return "encrypted";
3944
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
3945
+ const result = machineKey ? "encrypted" : "plaintext";
3946
+ const tmpPath = keyPath + ".tmp";
3947
+ try {
3948
+ if (existsSync8(keyPath)) {
3949
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
3950
+ });
3951
+ }
3952
+ await writeFile3(tmpPath, content, "utf-8");
3953
+ await chmod2(tmpPath, 384);
3954
+ await rename(tmpPath, keyPath);
3955
+ } catch (err) {
3956
+ try {
3957
+ await unlink(tmpPath);
3958
+ } catch {
3959
+ }
3960
+ throw err;
3939
3961
  }
3940
- await writeFile3(keyPath, b64 + "\n", "utf-8");
3941
- await chmod2(keyPath, 384);
3942
- return "plaintext";
3962
+ return result;
3943
3963
  }
3944
3964
  async function getMasterKey() {
3945
3965
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -11400,10 +11420,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
11400
11420
  }
11401
11421
  if (!useExeAgent && !useCodex && !useOpencode && !useBinSymlink) {
11402
11422
  if (agentRtConfig.runtime === "claude" && agentRtConfig.model) {
11403
- let ccModel = agentRtConfig.model.replace(/(\d+)\.(\d+)/g, "$1-$2");
11404
- if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
11405
- ccModel += "[1m]";
11406
- }
11423
+ const { normalizeCcModelName: normalizeCcModelName2 } = (init_agent_config(), __toCommonJS(agent_config_exports));
11424
+ const ccModel = normalizeCcModelName2(agentRtConfig.model);
11407
11425
  envPrefix = `${envPrefix} ANTHROPIC_MODEL=${ccModel}`;
11408
11426
  }
11409
11427
  }
@@ -435,6 +435,7 @@ __export(agent_config_exports, {
435
435
  clearAgentRuntime: () => clearAgentRuntime,
436
436
  getAgentRuntime: () => getAgentRuntime,
437
437
  loadAgentConfig: () => loadAgentConfig,
438
+ normalizeCcModelName: () => normalizeCcModelName,
438
439
  saveAgentConfig: () => saveAgentConfig,
439
440
  setAgentMcps: () => setAgentMcps,
440
441
  setAgentRuntime: () => setAgentRuntime
@@ -463,6 +464,13 @@ function getAgentRuntime(agentId) {
463
464
  if (orgDefault) return orgDefault;
464
465
  return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
465
466
  }
467
+ function normalizeCcModelName(model) {
468
+ let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
469
+ if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
470
+ ccModel += "[1m]";
471
+ }
472
+ return ccModel;
473
+ }
466
474
  function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
467
475
  const knownModels = KNOWN_RUNTIMES[runtime];
468
476
  if (!knownModels) {
@@ -7978,10 +7986,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
7978
7986
  }
7979
7987
  if (!useExeAgent && !useCodex && !useOpencode && !useBinSymlink) {
7980
7988
  if (agentRtConfig.runtime === "claude" && agentRtConfig.model) {
7981
- let ccModel = agentRtConfig.model.replace(/(\d+)\.(\d+)/g, "$1-$2");
7982
- if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
7983
- ccModel += "[1m]";
7984
- }
7989
+ const { normalizeCcModelName: normalizeCcModelName2 } = (init_agent_config(), __toCommonJS(agent_config_exports));
7990
+ const ccModel = normalizeCcModelName2(agentRtConfig.model);
7985
7991
  envPrefix = `${envPrefix} ANTHROPIC_MODEL=${ccModel}`;
7986
7992
  }
7987
7993
  }
@@ -8146,7 +8152,7 @@ var init_task_scope = __esm({
8146
8152
  });
8147
8153
 
8148
8154
  // src/lib/keychain.ts
8149
- import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
8155
+ import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2, rename, copyFile } from "fs/promises";
8150
8156
  import { existsSync as existsSync19, statSync as statSync4 } from "fs";
8151
8157
  import { execSync as execSync9 } from "child_process";
8152
8158
  import path22 from "path";
@@ -8181,12 +8187,14 @@ function linuxSecretAvailable() {
8181
8187
  function isRootOnlyTrustedServerKeyFile(keyPath) {
8182
8188
  if (process.platform !== "linux") return false;
8183
8189
  try {
8184
- const uid = typeof os13.userInfo().uid === "number" ? os13.userInfo().uid : -1;
8185
8190
  const st = statSync4(keyPath);
8186
8191
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
8192
+ const uid = typeof os13.userInfo().uid === "number" ? os13.userInfo().uid : -1;
8187
8193
  if (uid === 0) return true;
8188
8194
  const exeOsDir = process.env.EXE_OS_DIR;
8189
- return Boolean(exeOsDir && path22.resolve(keyPath).startsWith(path22.resolve(exeOsDir) + path22.sep));
8195
+ if (exeOsDir && path22.resolve(keyPath).startsWith(path22.resolve(exeOsDir) + path22.sep)) return true;
8196
+ if (!linuxSecretAvailable()) return true;
8197
+ return false;
8190
8198
  } catch {
8191
8199
  return false;
8192
8200
  }
@@ -8336,15 +8344,25 @@ async function writeMachineBoundFileFallback(b64) {
8336
8344
  await mkdir4(dir, { recursive: true });
8337
8345
  const keyPath = getKeyPath();
8338
8346
  const machineKey = deriveMachineKey();
8339
- if (machineKey) {
8340
- const encrypted = encryptWithMachineKey(b64, machineKey);
8341
- await writeFile5(keyPath, encrypted + "\n", "utf-8");
8342
- await chmod2(keyPath, 384);
8343
- return "encrypted";
8344
- }
8345
- await writeFile5(keyPath, b64 + "\n", "utf-8");
8346
- await chmod2(keyPath, 384);
8347
- return "plaintext";
8347
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
8348
+ const result = machineKey ? "encrypted" : "plaintext";
8349
+ const tmpPath = keyPath + ".tmp";
8350
+ try {
8351
+ if (existsSync19(keyPath)) {
8352
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
8353
+ });
8354
+ }
8355
+ await writeFile5(tmpPath, content, "utf-8");
8356
+ await chmod2(tmpPath, 384);
8357
+ await rename(tmpPath, keyPath);
8358
+ } catch (err) {
8359
+ try {
8360
+ await unlink(tmpPath);
8361
+ } catch {
8362
+ }
8363
+ throw err;
8364
+ }
8365
+ return result;
8348
8366
  }
8349
8367
  async function getMasterKey() {
8350
8368
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -422,6 +422,7 @@ __export(agent_config_exports, {
422
422
  clearAgentRuntime: () => clearAgentRuntime,
423
423
  getAgentRuntime: () => getAgentRuntime,
424
424
  loadAgentConfig: () => loadAgentConfig,
425
+ normalizeCcModelName: () => normalizeCcModelName,
425
426
  saveAgentConfig: () => saveAgentConfig,
426
427
  setAgentMcps: () => setAgentMcps,
427
428
  setAgentRuntime: () => setAgentRuntime
@@ -450,6 +451,13 @@ function getAgentRuntime(agentId) {
450
451
  if (orgDefault) return orgDefault;
451
452
  return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
452
453
  }
454
+ function normalizeCcModelName(model) {
455
+ let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
456
+ if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
457
+ ccModel += "[1m]";
458
+ }
459
+ return ccModel;
460
+ }
453
461
  function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
454
462
  const knownModels = KNOWN_RUNTIMES[runtime];
455
463
  if (!knownModels) {
@@ -3741,7 +3749,7 @@ var init_database = __esm({
3741
3749
  });
3742
3750
 
3743
3751
  // src/lib/keychain.ts
3744
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3752
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3745
3753
  import { existsSync as existsSync8, statSync as statSync3 } from "fs";
3746
3754
  import { execSync as execSync3 } from "child_process";
3747
3755
  import path7 from "path";
@@ -3776,12 +3784,14 @@ function linuxSecretAvailable() {
3776
3784
  function isRootOnlyTrustedServerKeyFile(keyPath) {
3777
3785
  if (process.platform !== "linux") return false;
3778
3786
  try {
3779
- const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3780
3787
  const st = statSync3(keyPath);
3781
3788
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3789
+ const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3782
3790
  if (uid === 0) return true;
3783
3791
  const exeOsDir = process.env.EXE_OS_DIR;
3784
- return Boolean(exeOsDir && path7.resolve(keyPath).startsWith(path7.resolve(exeOsDir) + path7.sep));
3792
+ if (exeOsDir && path7.resolve(keyPath).startsWith(path7.resolve(exeOsDir) + path7.sep)) return true;
3793
+ if (!linuxSecretAvailable()) return true;
3794
+ return false;
3785
3795
  } catch {
3786
3796
  return false;
3787
3797
  }
@@ -3931,15 +3941,25 @@ async function writeMachineBoundFileFallback(b64) {
3931
3941
  await mkdir3(dir, { recursive: true });
3932
3942
  const keyPath = getKeyPath();
3933
3943
  const machineKey = deriveMachineKey();
3934
- if (machineKey) {
3935
- const encrypted = encryptWithMachineKey(b64, machineKey);
3936
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
3937
- await chmod2(keyPath, 384);
3938
- return "encrypted";
3939
- }
3940
- await writeFile3(keyPath, b64 + "\n", "utf-8");
3941
- await chmod2(keyPath, 384);
3942
- return "plaintext";
3944
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
3945
+ const result = machineKey ? "encrypted" : "plaintext";
3946
+ const tmpPath = keyPath + ".tmp";
3947
+ try {
3948
+ if (existsSync8(keyPath)) {
3949
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
3950
+ });
3951
+ }
3952
+ await writeFile3(tmpPath, content, "utf-8");
3953
+ await chmod2(tmpPath, 384);
3954
+ await rename(tmpPath, keyPath);
3955
+ } catch (err) {
3956
+ try {
3957
+ await unlink(tmpPath);
3958
+ } catch {
3959
+ }
3960
+ throw err;
3961
+ }
3962
+ return result;
3943
3963
  }
3944
3964
  async function getMasterKey() {
3945
3965
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -3861,7 +3861,7 @@ var init_task_scope = __esm({
3861
3861
  });
3862
3862
 
3863
3863
  // src/lib/keychain.ts
3864
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3864
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3865
3865
  import { existsSync as existsSync13, statSync as statSync3 } from "fs";
3866
3866
  import { execSync as execSync6 } from "child_process";
3867
3867
  import path14 from "path";
@@ -3896,12 +3896,14 @@ function linuxSecretAvailable() {
3896
3896
  function isRootOnlyTrustedServerKeyFile(keyPath) {
3897
3897
  if (process.platform !== "linux") return false;
3898
3898
  try {
3899
- const uid = typeof os10.userInfo().uid === "number" ? os10.userInfo().uid : -1;
3900
3899
  const st = statSync3(keyPath);
3901
3900
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3901
+ const uid = typeof os10.userInfo().uid === "number" ? os10.userInfo().uid : -1;
3902
3902
  if (uid === 0) return true;
3903
3903
  const exeOsDir = process.env.EXE_OS_DIR;
3904
- return Boolean(exeOsDir && path14.resolve(keyPath).startsWith(path14.resolve(exeOsDir) + path14.sep));
3904
+ if (exeOsDir && path14.resolve(keyPath).startsWith(path14.resolve(exeOsDir) + path14.sep)) return true;
3905
+ if (!linuxSecretAvailable()) return true;
3906
+ return false;
3905
3907
  } catch {
3906
3908
  return false;
3907
3909
  }
@@ -4051,15 +4053,25 @@ async function writeMachineBoundFileFallback(b64) {
4051
4053
  await mkdir3(dir, { recursive: true });
4052
4054
  const keyPath = getKeyPath();
4053
4055
  const machineKey = deriveMachineKey();
4054
- if (machineKey) {
4055
- const encrypted = encryptWithMachineKey(b64, machineKey);
4056
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
4057
- await chmod2(keyPath, 384);
4058
- return "encrypted";
4059
- }
4060
- await writeFile3(keyPath, b64 + "\n", "utf-8");
4061
- await chmod2(keyPath, 384);
4062
- return "plaintext";
4056
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
4057
+ const result = machineKey ? "encrypted" : "plaintext";
4058
+ const tmpPath = keyPath + ".tmp";
4059
+ try {
4060
+ if (existsSync13(keyPath)) {
4061
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
4062
+ });
4063
+ }
4064
+ await writeFile3(tmpPath, content, "utf-8");
4065
+ await chmod2(tmpPath, 384);
4066
+ await rename(tmpPath, keyPath);
4067
+ } catch (err) {
4068
+ try {
4069
+ await unlink(tmpPath);
4070
+ } catch {
4071
+ }
4072
+ throw err;
4073
+ }
4074
+ return result;
4063
4075
  }
4064
4076
  async function getMasterKey() {
4065
4077
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -3824,7 +3824,7 @@ var init_task_scope = __esm({
3824
3824
  });
3825
3825
 
3826
3826
  // src/lib/keychain.ts
3827
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3827
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3828
3828
  import { existsSync as existsSync13, statSync as statSync3 } from "fs";
3829
3829
  import { execSync as execSync6 } from "child_process";
3830
3830
  import path14 from "path";
@@ -3859,12 +3859,14 @@ function linuxSecretAvailable() {
3859
3859
  function isRootOnlyTrustedServerKeyFile(keyPath) {
3860
3860
  if (process.platform !== "linux") return false;
3861
3861
  try {
3862
- const uid = typeof os10.userInfo().uid === "number" ? os10.userInfo().uid : -1;
3863
3862
  const st = statSync3(keyPath);
3864
3863
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3864
+ const uid = typeof os10.userInfo().uid === "number" ? os10.userInfo().uid : -1;
3865
3865
  if (uid === 0) return true;
3866
3866
  const exeOsDir = process.env.EXE_OS_DIR;
3867
- return Boolean(exeOsDir && path14.resolve(keyPath).startsWith(path14.resolve(exeOsDir) + path14.sep));
3867
+ if (exeOsDir && path14.resolve(keyPath).startsWith(path14.resolve(exeOsDir) + path14.sep)) return true;
3868
+ if (!linuxSecretAvailable()) return true;
3869
+ return false;
3868
3870
  } catch {
3869
3871
  return false;
3870
3872
  }
@@ -4014,15 +4016,25 @@ async function writeMachineBoundFileFallback(b64) {
4014
4016
  await mkdir3(dir, { recursive: true });
4015
4017
  const keyPath = getKeyPath();
4016
4018
  const machineKey = deriveMachineKey();
4017
- if (machineKey) {
4018
- const encrypted = encryptWithMachineKey(b64, machineKey);
4019
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
4020
- await chmod2(keyPath, 384);
4021
- return "encrypted";
4022
- }
4023
- await writeFile3(keyPath, b64 + "\n", "utf-8");
4024
- await chmod2(keyPath, 384);
4025
- return "plaintext";
4019
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
4020
+ const result = machineKey ? "encrypted" : "plaintext";
4021
+ const tmpPath = keyPath + ".tmp";
4022
+ try {
4023
+ if (existsSync13(keyPath)) {
4024
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
4025
+ });
4026
+ }
4027
+ await writeFile3(tmpPath, content, "utf-8");
4028
+ await chmod2(tmpPath, 384);
4029
+ await rename(tmpPath, keyPath);
4030
+ } catch (err) {
4031
+ try {
4032
+ await unlink(tmpPath);
4033
+ } catch {
4034
+ }
4035
+ throw err;
4036
+ }
4037
+ return result;
4026
4038
  }
4027
4039
  async function getMasterKey() {
4028
4040
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -3396,7 +3396,7 @@ __export(keychain_exports, {
3396
3396
  importMnemonic: () => importMnemonic,
3397
3397
  setMasterKey: () => setMasterKey
3398
3398
  });
3399
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3399
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3400
3400
  import { existsSync as existsSync7, statSync as statSync3 } from "fs";
3401
3401
  import { execSync as execSync3 } from "child_process";
3402
3402
  import path6 from "path";
@@ -3431,12 +3431,14 @@ function linuxSecretAvailable() {
3431
3431
  function isRootOnlyTrustedServerKeyFile(keyPath) {
3432
3432
  if (process.platform !== "linux") return false;
3433
3433
  try {
3434
- const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3435
3434
  const st = statSync3(keyPath);
3436
3435
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3436
+ const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3437
3437
  if (uid === 0) return true;
3438
3438
  const exeOsDir = process.env.EXE_OS_DIR;
3439
- return Boolean(exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep));
3439
+ if (exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep)) return true;
3440
+ if (!linuxSecretAvailable()) return true;
3441
+ return false;
3440
3442
  } catch {
3441
3443
  return false;
3442
3444
  }
@@ -3586,15 +3588,25 @@ async function writeMachineBoundFileFallback(b64) {
3586
3588
  await mkdir3(dir, { recursive: true });
3587
3589
  const keyPath = getKeyPath();
3588
3590
  const machineKey = deriveMachineKey();
3589
- if (machineKey) {
3590
- const encrypted = encryptWithMachineKey(b64, machineKey);
3591
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
3592
- await chmod2(keyPath, 384);
3593
- return "encrypted";
3591
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
3592
+ const result = machineKey ? "encrypted" : "plaintext";
3593
+ const tmpPath = keyPath + ".tmp";
3594
+ try {
3595
+ if (existsSync7(keyPath)) {
3596
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
3597
+ });
3598
+ }
3599
+ await writeFile3(tmpPath, content, "utf-8");
3600
+ await chmod2(tmpPath, 384);
3601
+ await rename(tmpPath, keyPath);
3602
+ } catch (err) {
3603
+ try {
3604
+ await unlink(tmpPath);
3605
+ } catch {
3606
+ }
3607
+ throw err;
3594
3608
  }
3595
- await writeFile3(keyPath, b64 + "\n", "utf-8");
3596
- await chmod2(keyPath, 384);
3597
- return "plaintext";
3609
+ return result;
3598
3610
  }
3599
3611
  async function getMasterKey() {
3600
3612
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -6500,6 +6512,7 @@ __export(cloud_sync_exports, {
6500
6512
  markCloudReuploadRequired: () => markCloudReuploadRequired,
6501
6513
  mergeConfig: () => mergeConfig,
6502
6514
  mergeRosterFromRemote: () => mergeRosterFromRemote,
6515
+ migrateEndpoint: () => migrateEndpoint,
6503
6516
  pushToPostgres: () => pushToPostgres,
6504
6517
  recordRosterDeletion: () => recordRosterDeletion
6505
6518
  });
@@ -6670,6 +6683,15 @@ async function fetchWithRetry(url, init) {
6670
6683
  }
6671
6684
  throw lastError;
6672
6685
  }
6686
+ function migrateEndpoint(endpoint) {
6687
+ if (endpoint === "https://askexe.com/cloud" || endpoint === "https://askexe.com/cloud/") {
6688
+ process.stderr.write(
6689
+ "[cloud-sync] Auto-migrating endpoint from askexe.com/cloud to cloud.askexe.com (bypasses Cloudflare WAF for datacenter IPs)\n"
6690
+ );
6691
+ return "https://cloud.askexe.com";
6692
+ }
6693
+ return endpoint;
6694
+ }
6673
6695
  function assertSecureEndpoint(endpoint) {
6674
6696
  if (endpoint.startsWith("https://")) return;
6675
6697
  if (endpoint.startsWith("http://")) {
@@ -6807,6 +6829,7 @@ async function markCloudReuploadRequired(client = getClient()) {
6807
6829
  await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_reupload_required', '1')");
6808
6830
  }
6809
6831
  async function cloudSync(config) {
6832
+ config = { ...config, endpoint: migrateEndpoint(config.endpoint) };
6810
6833
  if (!isSyncCryptoInitialized()) {
6811
6834
  try {
6812
6835
  const { getMasterKey: getMasterKey2 } = await Promise.resolve().then(() => (init_keychain(), keychain_exports));