@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
@@ -3414,7 +3414,7 @@ var init_database = __esm({
3414
3414
  });
3415
3415
 
3416
3416
  // src/lib/keychain.ts
3417
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3417
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3418
3418
  import { existsSync as existsSync7, statSync as statSync3 } from "fs";
3419
3419
  import { execSync as execSync3 } from "child_process";
3420
3420
  import path6 from "path";
@@ -3449,12 +3449,14 @@ function linuxSecretAvailable() {
3449
3449
  function isRootOnlyTrustedServerKeyFile(keyPath) {
3450
3450
  if (process.platform !== "linux") return false;
3451
3451
  try {
3452
- const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3453
3452
  const st = statSync3(keyPath);
3454
3453
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3454
+ const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3455
3455
  if (uid === 0) return true;
3456
3456
  const exeOsDir = process.env.EXE_OS_DIR;
3457
- return Boolean(exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep));
3457
+ if (exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep)) return true;
3458
+ if (!linuxSecretAvailable()) return true;
3459
+ return false;
3458
3460
  } catch {
3459
3461
  return false;
3460
3462
  }
@@ -3604,15 +3606,25 @@ async function writeMachineBoundFileFallback(b64) {
3604
3606
  await mkdir3(dir, { recursive: true });
3605
3607
  const keyPath = getKeyPath();
3606
3608
  const machineKey = deriveMachineKey();
3607
- if (machineKey) {
3608
- const encrypted = encryptWithMachineKey(b64, machineKey);
3609
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
3610
- await chmod2(keyPath, 384);
3611
- return "encrypted";
3609
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
3610
+ const result = machineKey ? "encrypted" : "plaintext";
3611
+ const tmpPath = keyPath + ".tmp";
3612
+ try {
3613
+ if (existsSync7(keyPath)) {
3614
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
3615
+ });
3616
+ }
3617
+ await writeFile3(tmpPath, content, "utf-8");
3618
+ await chmod2(tmpPath, 384);
3619
+ await rename(tmpPath, keyPath);
3620
+ } catch (err) {
3621
+ try {
3622
+ await unlink(tmpPath);
3623
+ } catch {
3624
+ }
3625
+ throw err;
3612
3626
  }
3613
- await writeFile3(keyPath, b64 + "\n", "utf-8");
3614
- await chmod2(keyPath, 384);
3615
- return "plaintext";
3627
+ return result;
3616
3628
  }
3617
3629
  async function getMasterKey() {
3618
3630
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -5941,6 +5953,20 @@ var init_runtime_table = __esm({
5941
5953
  });
5942
5954
 
5943
5955
  // src/lib/agent-config.ts
5956
+ var agent_config_exports = {};
5957
+ __export(agent_config_exports, {
5958
+ AGENT_CONFIG_PATH: () => AGENT_CONFIG_PATH,
5959
+ DEFAULT_MODELS: () => DEFAULT_MODELS,
5960
+ KNOWN_RUNTIMES: () => KNOWN_RUNTIMES,
5961
+ RUNTIME_LABELS: () => RUNTIME_LABELS,
5962
+ clearAgentRuntime: () => clearAgentRuntime,
5963
+ getAgentRuntime: () => getAgentRuntime,
5964
+ loadAgentConfig: () => loadAgentConfig,
5965
+ normalizeCcModelName: () => normalizeCcModelName,
5966
+ saveAgentConfig: () => saveAgentConfig,
5967
+ setAgentMcps: () => setAgentMcps,
5968
+ setAgentRuntime: () => setAgentRuntime
5969
+ });
5944
5970
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync10 } from "fs";
5945
5971
  import path9 from "path";
5946
5972
  function loadAgentConfig() {
@@ -5951,6 +5977,12 @@ function loadAgentConfig() {
5951
5977
  return {};
5952
5978
  }
5953
5979
  }
5980
+ function saveAgentConfig(config) {
5981
+ const dir = path9.dirname(AGENT_CONFIG_PATH);
5982
+ ensurePrivateDirSync(dir);
5983
+ writeFileSync4(AGENT_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
5984
+ enforcePrivateFileSync(AGENT_CONFIG_PATH);
5985
+ }
5954
5986
  function getAgentRuntime(agentId) {
5955
5987
  const config = loadAgentConfig();
5956
5988
  const entry = config[agentId];
@@ -5959,7 +5991,54 @@ function getAgentRuntime(agentId) {
5959
5991
  if (orgDefault) return orgDefault;
5960
5992
  return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
5961
5993
  }
5962
- var AGENT_CONFIG_PATH, DEFAULT_MODELS;
5994
+ function normalizeCcModelName(model) {
5995
+ let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
5996
+ if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
5997
+ ccModel += "[1m]";
5998
+ }
5999
+ return ccModel;
6000
+ }
6001
+ function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
6002
+ const knownModels = KNOWN_RUNTIMES[runtime];
6003
+ if (!knownModels) {
6004
+ return {
6005
+ ok: false,
6006
+ error: `Unknown runtime "${runtime}". Valid: ${Object.keys(KNOWN_RUNTIMES).join(", ")}`
6007
+ };
6008
+ }
6009
+ if (!knownModels.includes(model)) {
6010
+ return {
6011
+ ok: false,
6012
+ error: `Unknown model "${model}" for runtime "${runtime}". Valid: ${knownModels.join(", ")}`
6013
+ };
6014
+ }
6015
+ const config = loadAgentConfig();
6016
+ const existing = config[agentId];
6017
+ const entry = { runtime, model };
6018
+ if (reasoning_effort) entry.reasoning_effort = reasoning_effort;
6019
+ if (mcps !== void 0) {
6020
+ entry.mcps = mcps.includes("exe-os") ? mcps : ["exe-os", ...mcps];
6021
+ } else if (existing?.mcps) {
6022
+ entry.mcps = existing.mcps;
6023
+ }
6024
+ config[agentId] = entry;
6025
+ saveAgentConfig(config);
6026
+ return { ok: true };
6027
+ }
6028
+ function setAgentMcps(agentId, mcps) {
6029
+ const config = loadAgentConfig();
6030
+ const existing = config[agentId] ?? getAgentRuntime(agentId);
6031
+ existing.mcps = mcps.includes("exe-os") ? mcps : ["exe-os", ...mcps];
6032
+ config[agentId] = existing;
6033
+ saveAgentConfig(config);
6034
+ return { ok: true };
6035
+ }
6036
+ function clearAgentRuntime(agentId) {
6037
+ const config = loadAgentConfig();
6038
+ delete config[agentId];
6039
+ saveAgentConfig(config);
6040
+ }
6041
+ var AGENT_CONFIG_PATH, KNOWN_RUNTIMES, RUNTIME_LABELS, DEFAULT_MODELS;
5963
6042
  var init_agent_config = __esm({
5964
6043
  "src/lib/agent-config.ts"() {
5965
6044
  "use strict";
@@ -5967,6 +6046,16 @@ var init_agent_config = __esm({
5967
6046
  init_runtime_table();
5968
6047
  init_secure_files();
5969
6048
  AGENT_CONFIG_PATH = path9.join(EXE_AI_DIR, "agent-config.json");
6049
+ KNOWN_RUNTIMES = {
6050
+ claude: ["claude-opus-4.6", "claude-opus-4", "claude-sonnet-4.6", "claude-sonnet-4", "claude-haiku-4.5"],
6051
+ codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
6052
+ opencode: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4", "google/gemini-2.5-pro", "deepseek/deepseek-r3", "minimax/minimax-m2.5"]
6053
+ };
6054
+ RUNTIME_LABELS = {
6055
+ claude: "Claude Code (Anthropic)",
6056
+ codex: "Codex (OpenAI)",
6057
+ opencode: "OpenCode (open source)"
6058
+ };
5970
6059
  DEFAULT_MODELS = {
5971
6060
  claude: "claude-opus-4.6",
5972
6061
  codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
@@ -7028,11 +7117,8 @@ async function main() {
7028
7117
  if (provider === DEFAULT_PROVIDER) {
7029
7118
  const rtConfig = getAgentRuntime(memoryAgent);
7030
7119
  if (rtConfig.runtime === "claude" && rtConfig.model) {
7031
- let ccModel = rtConfig.model.replace(/(\d+)\.(\d+)/g, "$1-$2");
7032
- if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
7033
- ccModel += "[1m]";
7034
- }
7035
- process.env.ANTHROPIC_MODEL = ccModel;
7120
+ const { normalizeCcModelName: normalizeCcModelName2 } = await Promise.resolve().then(() => (init_agent_config(), agent_config_exports));
7121
+ process.env.ANTHROPIC_MODEL = normalizeCcModelName2(rtConfig.model);
7036
7122
  }
7037
7123
  }
7038
7124
  const child = spawnSync(plan.command, plan.args, { stdio: "inherit" });
@@ -187,6 +187,7 @@ __export(agent_config_exports, {
187
187
  clearAgentRuntime: () => clearAgentRuntime,
188
188
  getAgentRuntime: () => getAgentRuntime,
189
189
  loadAgentConfig: () => loadAgentConfig,
190
+ normalizeCcModelName: () => normalizeCcModelName,
190
191
  saveAgentConfig: () => saveAgentConfig,
191
192
  setAgentMcps: () => setAgentMcps,
192
193
  setAgentRuntime: () => setAgentRuntime
@@ -215,6 +216,13 @@ function getAgentRuntime(agentId) {
215
216
  if (orgDefault) return orgDefault;
216
217
  return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
217
218
  }
219
+ function normalizeCcModelName(model) {
220
+ let ccModel = model.replace(/(\d+)\.(\d+)/g, "$1-$2");
221
+ if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
222
+ ccModel += "[1m]";
223
+ }
224
+ return ccModel;
225
+ }
218
226
  function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
219
227
  const knownModels = KNOWN_RUNTIMES[runtime];
220
228
  if (!knownModels) {
@@ -1458,7 +1466,7 @@ function readOrCreateDaemonToken(homeDir = os7.homedir()) {
1458
1466
  function buildMcpHttpHeaders(homeDir = os7.homedir(), opts = {}) {
1459
1467
  const agentId = opts.useShellPlaceholders ? "${AGENT_ID:-exe}" : opts.agentId ?? DEFAULT_MCP_HTTP_AGENT_ID;
1460
1468
  const agentRole = opts.useShellPlaceholders ? "${AGENT_ROLE:-COO}" : opts.agentRole ?? DEFAULT_MCP_HTTP_AGENT_ROLE;
1461
- const sessionName = opts.useShellPlaceholders ? "$(tmux display-message -p '#{session_name}' 2>/dev/null || echo '')" : process.env.EXE_SESSION_NAME ?? "";
1469
+ const sessionName = opts.useShellPlaceholders ? "" : process.env.EXE_SESSION_NAME ?? "";
1462
1470
  const headers = {
1463
1471
  Authorization: `Bearer ${readOrCreateDaemonToken(homeDir)}`,
1464
1472
  "X-Agent-Id": agentId,
@@ -3814,7 +3814,7 @@ var init_task_scope = __esm({
3814
3814
  });
3815
3815
 
3816
3816
  // src/lib/keychain.ts
3817
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3817
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3818
3818
  import { existsSync as existsSync13, statSync as statSync3 } from "fs";
3819
3819
  import { execSync as execSync5 } from "child_process";
3820
3820
  import path13 from "path";
@@ -3849,12 +3849,14 @@ function linuxSecretAvailable() {
3849
3849
  function isRootOnlyTrustedServerKeyFile(keyPath) {
3850
3850
  if (process.platform !== "linux") return false;
3851
3851
  try {
3852
- const uid = typeof os10.userInfo().uid === "number" ? os10.userInfo().uid : -1;
3853
3852
  const st = statSync3(keyPath);
3854
3853
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3854
+ const uid = typeof os10.userInfo().uid === "number" ? os10.userInfo().uid : -1;
3855
3855
  if (uid === 0) return true;
3856
3856
  const exeOsDir = process.env.EXE_OS_DIR;
3857
- return Boolean(exeOsDir && path13.resolve(keyPath).startsWith(path13.resolve(exeOsDir) + path13.sep));
3857
+ if (exeOsDir && path13.resolve(keyPath).startsWith(path13.resolve(exeOsDir) + path13.sep)) return true;
3858
+ if (!linuxSecretAvailable()) return true;
3859
+ return false;
3858
3860
  } catch {
3859
3861
  return false;
3860
3862
  }
@@ -4004,15 +4006,25 @@ async function writeMachineBoundFileFallback(b64) {
4004
4006
  await mkdir3(dir, { recursive: true });
4005
4007
  const keyPath = getKeyPath();
4006
4008
  const machineKey = deriveMachineKey();
4007
- if (machineKey) {
4008
- const encrypted = encryptWithMachineKey(b64, machineKey);
4009
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
4010
- await chmod2(keyPath, 384);
4011
- return "encrypted";
4012
- }
4013
- await writeFile3(keyPath, b64 + "\n", "utf-8");
4014
- await chmod2(keyPath, 384);
4015
- return "plaintext";
4009
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
4010
+ const result = machineKey ? "encrypted" : "plaintext";
4011
+ const tmpPath = keyPath + ".tmp";
4012
+ try {
4013
+ if (existsSync13(keyPath)) {
4014
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
4015
+ });
4016
+ }
4017
+ await writeFile3(tmpPath, content, "utf-8");
4018
+ await chmod2(tmpPath, 384);
4019
+ await rename(tmpPath, keyPath);
4020
+ } catch (err) {
4021
+ try {
4022
+ await unlink(tmpPath);
4023
+ } catch {
4024
+ }
4025
+ throw err;
4026
+ }
4027
+ return result;
4016
4028
  }
4017
4029
  async function getMasterKey() {
4018
4030
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -3880,7 +3880,7 @@ var init_notifications = __esm({
3880
3880
  });
3881
3881
 
3882
3882
  // src/lib/keychain.ts
3883
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3883
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3884
3884
  import { existsSync as existsSync14, statSync as statSync3 } from "fs";
3885
3885
  import { execSync as execSync5 } from "child_process";
3886
3886
  import path14 from "path";
@@ -3915,12 +3915,14 @@ function linuxSecretAvailable() {
3915
3915
  function isRootOnlyTrustedServerKeyFile(keyPath) {
3916
3916
  if (process.platform !== "linux") return false;
3917
3917
  try {
3918
- const uid = typeof os11.userInfo().uid === "number" ? os11.userInfo().uid : -1;
3919
3918
  const st = statSync3(keyPath);
3920
3919
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3920
+ const uid = typeof os11.userInfo().uid === "number" ? os11.userInfo().uid : -1;
3921
3921
  if (uid === 0) return true;
3922
3922
  const exeOsDir = process.env.EXE_OS_DIR;
3923
- return Boolean(exeOsDir && path14.resolve(keyPath).startsWith(path14.resolve(exeOsDir) + path14.sep));
3923
+ if (exeOsDir && path14.resolve(keyPath).startsWith(path14.resolve(exeOsDir) + path14.sep)) return true;
3924
+ if (!linuxSecretAvailable()) return true;
3925
+ return false;
3924
3926
  } catch {
3925
3927
  return false;
3926
3928
  }
@@ -4070,15 +4072,25 @@ async function writeMachineBoundFileFallback(b64) {
4070
4072
  await mkdir3(dir, { recursive: true });
4071
4073
  const keyPath = getKeyPath();
4072
4074
  const machineKey = deriveMachineKey();
4073
- if (machineKey) {
4074
- const encrypted = encryptWithMachineKey(b64, machineKey);
4075
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
4076
- await chmod2(keyPath, 384);
4077
- return "encrypted";
4078
- }
4079
- await writeFile3(keyPath, b64 + "\n", "utf-8");
4080
- await chmod2(keyPath, 384);
4081
- return "plaintext";
4075
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
4076
+ const result = machineKey ? "encrypted" : "plaintext";
4077
+ const tmpPath = keyPath + ".tmp";
4078
+ try {
4079
+ if (existsSync14(keyPath)) {
4080
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
4081
+ });
4082
+ }
4083
+ await writeFile3(tmpPath, content, "utf-8");
4084
+ await chmod2(tmpPath, 384);
4085
+ await rename(tmpPath, keyPath);
4086
+ } catch (err) {
4087
+ try {
4088
+ await unlink(tmpPath);
4089
+ } catch {
4090
+ }
4091
+ throw err;
4092
+ }
4093
+ return result;
4082
4094
  }
4083
4095
  async function getMasterKey() {
4084
4096
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -3974,7 +3974,7 @@ var init_tasks_review = __esm({
3974
3974
  });
3975
3975
 
3976
3976
  // src/lib/keychain.ts
3977
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3977
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3978
3978
  import { existsSync as existsSync15, statSync as statSync3 } from "fs";
3979
3979
  import { execSync as execSync5 } from "child_process";
3980
3980
  import path15 from "path";
@@ -4009,12 +4009,14 @@ function linuxSecretAvailable() {
4009
4009
  function isRootOnlyTrustedServerKeyFile(keyPath) {
4010
4010
  if (process.platform !== "linux") return false;
4011
4011
  try {
4012
- const uid = typeof os11.userInfo().uid === "number" ? os11.userInfo().uid : -1;
4013
4012
  const st = statSync3(keyPath);
4014
4013
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
4014
+ const uid = typeof os11.userInfo().uid === "number" ? os11.userInfo().uid : -1;
4015
4015
  if (uid === 0) return true;
4016
4016
  const exeOsDir = process.env.EXE_OS_DIR;
4017
- return Boolean(exeOsDir && path15.resolve(keyPath).startsWith(path15.resolve(exeOsDir) + path15.sep));
4017
+ if (exeOsDir && path15.resolve(keyPath).startsWith(path15.resolve(exeOsDir) + path15.sep)) return true;
4018
+ if (!linuxSecretAvailable()) return true;
4019
+ return false;
4018
4020
  } catch {
4019
4021
  return false;
4020
4022
  }
@@ -4164,15 +4166,25 @@ async function writeMachineBoundFileFallback(b64) {
4164
4166
  await mkdir3(dir, { recursive: true });
4165
4167
  const keyPath = getKeyPath();
4166
4168
  const machineKey = deriveMachineKey();
4167
- if (machineKey) {
4168
- const encrypted = encryptWithMachineKey(b64, machineKey);
4169
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
4170
- await chmod2(keyPath, 384);
4171
- return "encrypted";
4172
- }
4173
- await writeFile3(keyPath, b64 + "\n", "utf-8");
4174
- await chmod2(keyPath, 384);
4175
- return "plaintext";
4169
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
4170
+ const result = machineKey ? "encrypted" : "plaintext";
4171
+ const tmpPath = keyPath + ".tmp";
4172
+ try {
4173
+ if (existsSync15(keyPath)) {
4174
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
4175
+ });
4176
+ }
4177
+ await writeFile3(tmpPath, content, "utf-8");
4178
+ await chmod2(tmpPath, 384);
4179
+ await rename(tmpPath, keyPath);
4180
+ } catch (err) {
4181
+ try {
4182
+ await unlink(tmpPath);
4183
+ } catch {
4184
+ }
4185
+ throw err;
4186
+ }
4187
+ return result;
4176
4188
  }
4177
4189
  async function getMasterKey() {
4178
4190
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -3546,7 +3546,7 @@ ${p.content}`).join("\n\n");
3546
3546
  });
3547
3547
 
3548
3548
  // src/lib/keychain.ts
3549
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3549
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3550
3550
  import { existsSync as existsSync7, statSync as statSync3 } from "fs";
3551
3551
  import { execSync as execSync3 } from "child_process";
3552
3552
  import path6 from "path";
@@ -3581,12 +3581,14 @@ function linuxSecretAvailable() {
3581
3581
  function isRootOnlyTrustedServerKeyFile(keyPath) {
3582
3582
  if (process.platform !== "linux") return false;
3583
3583
  try {
3584
- const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3585
3584
  const st = statSync3(keyPath);
3586
3585
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3586
+ const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3587
3587
  if (uid === 0) return true;
3588
3588
  const exeOsDir = process.env.EXE_OS_DIR;
3589
- return Boolean(exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep));
3589
+ if (exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep)) return true;
3590
+ if (!linuxSecretAvailable()) return true;
3591
+ return false;
3590
3592
  } catch {
3591
3593
  return false;
3592
3594
  }
@@ -3736,15 +3738,25 @@ async function writeMachineBoundFileFallback(b64) {
3736
3738
  await mkdir3(dir, { recursive: true });
3737
3739
  const keyPath = getKeyPath();
3738
3740
  const machineKey = deriveMachineKey();
3739
- if (machineKey) {
3740
- const encrypted = encryptWithMachineKey(b64, machineKey);
3741
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
3742
- await chmod2(keyPath, 384);
3743
- return "encrypted";
3744
- }
3745
- await writeFile3(keyPath, b64 + "\n", "utf-8");
3746
- await chmod2(keyPath, 384);
3747
- return "plaintext";
3741
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
3742
+ const result = machineKey ? "encrypted" : "plaintext";
3743
+ const tmpPath = keyPath + ".tmp";
3744
+ try {
3745
+ if (existsSync7(keyPath)) {
3746
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
3747
+ });
3748
+ }
3749
+ await writeFile3(tmpPath, content, "utf-8");
3750
+ await chmod2(tmpPath, 384);
3751
+ await rename(tmpPath, keyPath);
3752
+ } catch (err) {
3753
+ try {
3754
+ await unlink(tmpPath);
3755
+ } catch {
3756
+ }
3757
+ throw err;
3758
+ }
3759
+ return result;
3748
3760
  }
3749
3761
  async function getMasterKey() {
3750
3762
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -3330,7 +3330,7 @@ var init_database = __esm({
3330
3330
  });
3331
3331
 
3332
3332
  // src/lib/keychain.ts
3333
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3333
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3334
3334
  import { existsSync as existsSync7, statSync as statSync3 } from "fs";
3335
3335
  import { execSync as execSync3 } from "child_process";
3336
3336
  import path6 from "path";
@@ -3365,12 +3365,14 @@ function linuxSecretAvailable() {
3365
3365
  function isRootOnlyTrustedServerKeyFile(keyPath) {
3366
3366
  if (process.platform !== "linux") return false;
3367
3367
  try {
3368
- const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3369
3368
  const st = statSync3(keyPath);
3370
3369
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3370
+ const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3371
3371
  if (uid === 0) return true;
3372
3372
  const exeOsDir = process.env.EXE_OS_DIR;
3373
- return Boolean(exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep));
3373
+ if (exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep)) return true;
3374
+ if (!linuxSecretAvailable()) return true;
3375
+ return false;
3374
3376
  } catch {
3375
3377
  return false;
3376
3378
  }
@@ -3520,15 +3522,25 @@ async function writeMachineBoundFileFallback(b64) {
3520
3522
  await mkdir3(dir, { recursive: true });
3521
3523
  const keyPath = getKeyPath();
3522
3524
  const machineKey = deriveMachineKey();
3523
- if (machineKey) {
3524
- const encrypted = encryptWithMachineKey(b64, machineKey);
3525
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
3526
- await chmod2(keyPath, 384);
3527
- return "encrypted";
3528
- }
3529
- await writeFile3(keyPath, b64 + "\n", "utf-8");
3530
- await chmod2(keyPath, 384);
3531
- return "plaintext";
3525
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
3526
+ const result = machineKey ? "encrypted" : "plaintext";
3527
+ const tmpPath = keyPath + ".tmp";
3528
+ try {
3529
+ if (existsSync7(keyPath)) {
3530
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
3531
+ });
3532
+ }
3533
+ await writeFile3(tmpPath, content, "utf-8");
3534
+ await chmod2(tmpPath, 384);
3535
+ await rename(tmpPath, keyPath);
3536
+ } catch (err) {
3537
+ try {
3538
+ await unlink(tmpPath);
3539
+ } catch {
3540
+ }
3541
+ throw err;
3542
+ }
3543
+ return result;
3532
3544
  }
3533
3545
  async function getMasterKey() {
3534
3546
  let nativeValue = macKeychainGet() ?? linuxSecretGet();
@@ -3315,7 +3315,7 @@ var init_database = __esm({
3315
3315
  });
3316
3316
 
3317
3317
  // src/lib/keychain.ts
3318
- import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3318
+ import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2, rename, copyFile } from "fs/promises";
3319
3319
  import { existsSync as existsSync7, statSync as statSync3 } from "fs";
3320
3320
  import { execSync as execSync3 } from "child_process";
3321
3321
  import path6 from "path";
@@ -3350,12 +3350,14 @@ function linuxSecretAvailable() {
3350
3350
  function isRootOnlyTrustedServerKeyFile(keyPath) {
3351
3351
  if (process.platform !== "linux") return false;
3352
3352
  try {
3353
- const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3354
3353
  const st = statSync3(keyPath);
3355
3354
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3355
+ const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3356
3356
  if (uid === 0) return true;
3357
3357
  const exeOsDir = process.env.EXE_OS_DIR;
3358
- return Boolean(exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep));
3358
+ if (exeOsDir && path6.resolve(keyPath).startsWith(path6.resolve(exeOsDir) + path6.sep)) return true;
3359
+ if (!linuxSecretAvailable()) return true;
3360
+ return false;
3359
3361
  } catch {
3360
3362
  return false;
3361
3363
  }
@@ -3505,15 +3507,25 @@ async function writeMachineBoundFileFallback(b64) {
3505
3507
  await mkdir3(dir, { recursive: true });
3506
3508
  const keyPath = getKeyPath();
3507
3509
  const machineKey = deriveMachineKey();
3508
- if (machineKey) {
3509
- const encrypted = encryptWithMachineKey(b64, machineKey);
3510
- await writeFile3(keyPath, encrypted + "\n", "utf-8");
3511
- await chmod2(keyPath, 384);
3512
- return "encrypted";
3513
- }
3514
- await writeFile3(keyPath, b64 + "\n", "utf-8");
3515
- await chmod2(keyPath, 384);
3516
- return "plaintext";
3510
+ const content = machineKey ? encryptWithMachineKey(b64, machineKey) + "\n" : b64 + "\n";
3511
+ const result = machineKey ? "encrypted" : "plaintext";
3512
+ const tmpPath = keyPath + ".tmp";
3513
+ try {
3514
+ if (existsSync7(keyPath)) {
3515
+ await copyFile(keyPath, keyPath + ".bak").catch(() => {
3516
+ });
3517
+ }
3518
+ await writeFile3(tmpPath, content, "utf-8");
3519
+ await chmod2(tmpPath, 384);
3520
+ await rename(tmpPath, keyPath);
3521
+ } catch (err) {
3522
+ try {
3523
+ await unlink(tmpPath);
3524
+ } catch {
3525
+ }
3526
+ throw err;
3527
+ }
3528
+ return result;
3517
3529
  }
3518
3530
  async function getMasterKey() {
3519
3531
  let nativeValue = macKeychainGet() ?? linuxSecretGet();