@askexenow/exe-os 0.9.0 → 0.9.2

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.
package/dist/bin/cli.js CHANGED
@@ -749,6 +749,10 @@ async function cleanSettingsJsonMcp(settingsPath) {
749
749
  }
750
750
  async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
751
751
  const settingsPath = path5.join(homeDir, ".claude", "settings.json");
752
+ const logsDir = path5.join(homeDir, ".exe-os", "logs");
753
+ const hookLogPath = path5.join(logsDir, "hooks.log");
754
+ const logSuffix = ` 2>> "${hookLogPath}"`;
755
+ await mkdir3(logsDir, { recursive: true });
752
756
  let settings = {};
753
757
  if (existsSync5(settingsPath)) {
754
758
  try {
@@ -772,11 +776,11 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
772
776
  hooks: [
773
777
  {
774
778
  type: "command",
775
- command: `node "${path5.join(packageRoot, "dist", "hooks", "ingest.js")}"`
779
+ command: `node "${path5.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
776
780
  },
777
781
  {
778
782
  type: "command",
779
- command: `node "${path5.join(packageRoot, "dist", "hooks", "error-recall.js")}"`
783
+ command: `node "${path5.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
780
784
  }
781
785
  ]
782
786
  },
@@ -788,7 +792,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
788
792
  hooks: [
789
793
  {
790
794
  type: "command",
791
- command: `node "${path5.join(packageRoot, "dist", "hooks", "session-start.js")}"`,
795
+ command: `node "${path5.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
792
796
  timeout: 1e4
793
797
  }
794
798
  ]
@@ -801,7 +805,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
801
805
  hooks: [
802
806
  {
803
807
  type: "command",
804
- command: `node "${path5.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"`
808
+ command: `node "${path5.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
805
809
  }
806
810
  ]
807
811
  },
@@ -813,7 +817,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
813
817
  hooks: [
814
818
  {
815
819
  type: "command",
816
- command: `node "${path5.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"`,
820
+ command: `node "${path5.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
817
821
  timeout: 5e3
818
822
  }
819
823
  ]
@@ -826,7 +830,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
826
830
  hooks: [
827
831
  {
828
832
  type: "command",
829
- command: `node "${path5.join(packageRoot, "dist", "hooks", "stop.js")}"`
833
+ command: `node "${path5.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
830
834
  }
831
835
  ]
832
836
  },
@@ -839,7 +843,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
839
843
  hooks: [
840
844
  {
841
845
  type: "command",
842
- command: `node "${path5.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"`
846
+ command: `node "${path5.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
843
847
  }
844
848
  ]
845
849
  },
@@ -851,7 +855,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
851
855
  hooks: [
852
856
  {
853
857
  type: "command",
854
- command: `node "${path5.join(packageRoot, "dist", "hooks", "subagent-stop.js")}"`
858
+ command: `node "${path5.join(packageRoot, "dist", "hooks", "subagent-stop.js")}"${logSuffix}`
855
859
  }
856
860
  ]
857
861
  },
@@ -863,7 +867,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
863
867
  hooks: [
864
868
  {
865
869
  type: "command",
866
- command: `node "${path5.join(packageRoot, "dist", "hooks", "pre-compact.js")}"`,
870
+ command: `node "${path5.join(packageRoot, "dist", "hooks", "pre-compact.js")}"${logSuffix}`,
867
871
  timeout: 1e4
868
872
  }
869
873
  ]
@@ -876,7 +880,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
876
880
  hooks: [
877
881
  {
878
882
  type: "command",
879
- command: `node "${path5.join(packageRoot, "dist", "hooks", "session-end.js")}"`
883
+ command: `node "${path5.join(packageRoot, "dist", "hooks", "session-end.js")}"${logSuffix}`
880
884
  }
881
885
  ]
882
886
  },
@@ -888,7 +892,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
888
892
  hooks: [
889
893
  {
890
894
  type: "command",
891
- command: `node "${path5.join(packageRoot, "dist", "hooks", "notification.js")}"`
895
+ command: `node "${path5.join(packageRoot, "dist", "hooks", "notification.js")}"${logSuffix}`
892
896
  }
893
897
  ]
894
898
  },
@@ -900,7 +904,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
900
904
  hooks: [
901
905
  {
902
906
  type: "command",
903
- command: `node "${path5.join(packageRoot, "dist", "hooks", "post-compact.js")}"`,
907
+ command: `node "${path5.join(packageRoot, "dist", "hooks", "post-compact.js")}"${logSuffix}`,
904
908
  timeout: 1e4
905
909
  }
906
910
  ]
@@ -913,7 +917,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
913
917
  hooks: [
914
918
  {
915
919
  type: "command",
916
- command: `node "${path5.join(packageRoot, "dist", "hooks", "instructions-loaded.js")}"`
920
+ command: `node "${path5.join(packageRoot, "dist", "hooks", "instructions-loaded.js")}"${logSuffix}`
917
921
  }
918
922
  ]
919
923
  },
@@ -3940,21 +3944,21 @@ async function withRosterLock(fn) {
3940
3944
  }
3941
3945
  }
3942
3946
  async function fetchWithRetry(url, init) {
3943
- const MAX_RETRIES3 = 3;
3947
+ const MAX_RETRIES4 = 3;
3944
3948
  const BASE_DELAY_MS2 = 200;
3945
3949
  let lastError;
3946
- for (let attempt = 0; attempt <= MAX_RETRIES3; attempt++) {
3950
+ for (let attempt = 0; attempt <= MAX_RETRIES4; attempt++) {
3947
3951
  try {
3948
3952
  const signal = AbortSignal.timeout(FETCH_TIMEOUT_MS);
3949
3953
  const resp = await fetch(url, { ...init, signal });
3950
- if (resp && resp.status >= 500 && attempt < MAX_RETRIES3) {
3954
+ if (resp && resp.status >= 500 && attempt < MAX_RETRIES4) {
3951
3955
  await new Promise((r) => setTimeout(r, BASE_DELAY_MS2 * Math.pow(2, attempt)));
3952
3956
  continue;
3953
3957
  }
3954
3958
  return resp;
3955
3959
  } catch (err) {
3956
3960
  lastError = err;
3957
- if (attempt === MAX_RETRIES3) throw err;
3961
+ if (attempt === MAX_RETRIES4) throw err;
3958
3962
  await new Promise((r) => setTimeout(r, BASE_DELAY_MS2 * Math.pow(2, attempt)));
3959
3963
  }
3960
3964
  }
@@ -7583,6 +7587,14 @@ var init_agent_config = __esm({
7583
7587
  });
7584
7588
 
7585
7589
  // src/lib/intercom-queue.ts
7590
+ var intercom_queue_exports = {};
7591
+ __export(intercom_queue_exports, {
7592
+ clearQueueForAgent: () => clearQueueForAgent,
7593
+ drainForSession: () => drainForSession,
7594
+ drainQueue: () => drainQueue,
7595
+ queueIntercom: () => queueIntercom,
7596
+ readQueue: () => readQueue
7597
+ });
7586
7598
  import { readFileSync as readFileSync11, writeFileSync as writeFileSync9, renameSync as renameSync3, existsSync as existsSync14, mkdirSync as mkdirSync10 } from "fs";
7587
7599
  import path15 from "path";
7588
7600
  import os9 from "os";
@@ -7621,11 +7633,80 @@ function queueIntercom(targetSession, reason) {
7621
7633
  }
7622
7634
  writeQueue(queue);
7623
7635
  }
7624
- var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
7636
+ function drainQueue(isSessionBusy2, sendKeys) {
7637
+ const queue = readQueue();
7638
+ if (queue.length === 0) return { drained: 0, failed: 0 };
7639
+ const remaining = [];
7640
+ let drained = 0;
7641
+ let failed = 0;
7642
+ for (const item of queue) {
7643
+ const age = Date.now() - new Date(item.queuedAt).getTime();
7644
+ if (age > TTL_MS) {
7645
+ logQueue(`EXPIRED \u2192 ${item.targetSession} (${Math.round(age / 6e4)}min old, reason: ${item.reason})`);
7646
+ failed++;
7647
+ continue;
7648
+ }
7649
+ try {
7650
+ if (!isSessionBusy2(item.targetSession)) {
7651
+ const success = sendKeys(item.targetSession);
7652
+ if (success) {
7653
+ logQueue(`DRAINED \u2192 ${item.targetSession} (after ${item.attempts} retries)`);
7654
+ drained++;
7655
+ continue;
7656
+ }
7657
+ }
7658
+ } catch {
7659
+ }
7660
+ item.attempts++;
7661
+ if (item.attempts >= MAX_RETRIES2) {
7662
+ logQueue(`FAILED \u2192 ${item.targetSession} (${MAX_RETRIES2} retries exhausted, reason: ${item.reason})`);
7663
+ failed++;
7664
+ continue;
7665
+ }
7666
+ remaining.push(item);
7667
+ }
7668
+ writeQueue(remaining);
7669
+ return { drained, failed };
7670
+ }
7671
+ function drainForSession(targetSession, sendKeys) {
7672
+ const queue = readQueue();
7673
+ const match = queue.findIndex((q) => q.targetSession === targetSession);
7674
+ if (match < 0) return false;
7675
+ const success = sendKeys(targetSession);
7676
+ if (success) {
7677
+ queue.splice(match, 1);
7678
+ writeQueue(queue);
7679
+ logQueue(`DRAINED \u2192 ${targetSession} (prompt-submit trigger)`);
7680
+ return true;
7681
+ }
7682
+ return false;
7683
+ }
7684
+ function clearQueueForAgent(agentName) {
7685
+ const queue = readQueue();
7686
+ const before = queue.length;
7687
+ const filtered = queue.filter((q) => !q.targetSession.startsWith(`${agentName}-`));
7688
+ if (filtered.length < before) {
7689
+ writeQueue(filtered);
7690
+ logQueue(`CLEARED ${before - filtered.length} stale item(s) for ${agentName}`);
7691
+ }
7692
+ }
7693
+ function logQueue(msg) {
7694
+ const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [queue] ${msg}
7695
+ `;
7696
+ process.stderr.write(`[intercom-queue] ${msg}
7697
+ `);
7698
+ try {
7699
+ const { appendFileSync: appendFileSync3 } = __require("fs");
7700
+ appendFileSync3(INTERCOM_LOG, line);
7701
+ } catch {
7702
+ }
7703
+ }
7704
+ var QUEUE_PATH, MAX_RETRIES2, TTL_MS, INTERCOM_LOG;
7625
7705
  var init_intercom_queue = __esm({
7626
7706
  "src/lib/intercom-queue.ts"() {
7627
7707
  "use strict";
7628
7708
  QUEUE_PATH = path15.join(os9.homedir(), ".exe-os", "intercom-queue.json");
7709
+ MAX_RETRIES2 = 5;
7629
7710
  TTL_MS = 60 * 60 * 1e3;
7630
7711
  INTERCOM_LOG = path15.join(os9.homedir(), ".exe-os", "intercom.log");
7631
7712
  }
@@ -8332,6 +8413,13 @@ ${input.result}` : `\u26A0\uFE0F ${warning}`;
8332
8413
  await client.execute("PRAGMA wal_checkpoint(PASSIVE)");
8333
8414
  } catch {
8334
8415
  }
8416
+ if (input.status === "done" || input.status === "cancelled") {
8417
+ try {
8418
+ const { clearQueueForAgent: clearQueueForAgent2 } = await Promise.resolve().then(() => (init_intercom_queue(), intercom_queue_exports));
8419
+ clearQueueForAgent2(String(row.assigned_to));
8420
+ } catch {
8421
+ }
8422
+ }
8335
8423
  try {
8336
8424
  await writeCheckpoint({
8337
8425
  taskId,
@@ -10571,7 +10659,7 @@ async function deliverLocalMessage(messageId) {
10571
10659
  return true;
10572
10660
  } catch {
10573
10661
  const newRetryCount = msg.retryCount + 1;
10574
- if (newRetryCount >= MAX_RETRIES2) {
10662
+ if (newRetryCount >= MAX_RETRIES3) {
10575
10663
  await markFailed(messageId, "session unavailable after 10 retries");
10576
10664
  } else {
10577
10665
  await client.execute({
@@ -10660,7 +10748,7 @@ async function retryPendingMessages() {
10660
10748
  sql: `SELECT * FROM messages
10661
10749
  WHERE status = 'pending' AND retry_count < ?
10662
10750
  ORDER BY id`,
10663
- args: [MAX_RETRIES2]
10751
+ args: [MAX_RETRIES3]
10664
10752
  });
10665
10753
  let delivered = 0;
10666
10754
  for (const row of result.rows) {
@@ -10673,13 +10761,13 @@ async function retryPendingMessages() {
10673
10761
  }
10674
10762
  return delivered;
10675
10763
  }
10676
- var MAX_RETRIES2, _wsClientSend;
10764
+ var MAX_RETRIES3, _wsClientSend;
10677
10765
  var init_messaging = __esm({
10678
10766
  "src/lib/messaging.ts"() {
10679
10767
  "use strict";
10680
10768
  init_database();
10681
10769
  init_tmux_routing();
10682
- MAX_RETRIES2 = 10;
10770
+ MAX_RETRIES3 = 10;
10683
10771
  _wsClientSend = null;
10684
10772
  }
10685
10773
  });
@@ -11692,11 +11780,11 @@ async function downloadModel(opts) {
11692
11780
  return destPath;
11693
11781
  }
11694
11782
  }
11695
- const MAX_RETRIES3 = 3;
11783
+ const MAX_RETRIES4 = 3;
11696
11784
  const DOWNLOAD_TIMEOUT_MS = 3e5;
11697
11785
  let lastErr;
11698
11786
  let downloaded = 0;
11699
- for (let attempt = 1; attempt <= MAX_RETRIES3; attempt++) {
11787
+ for (let attempt = 1; attempt <= MAX_RETRIES4; attempt++) {
11700
11788
  try {
11701
11789
  if (existsSync21(tmpPath)) unlinkSync11(tmpPath);
11702
11790
  const response = await fetchFn(GGUF_URL, {
@@ -11739,7 +11827,7 @@ async function downloadModel(opts) {
11739
11827
  return destPath;
11740
11828
  } catch (err) {
11741
11829
  lastErr = err instanceof Error ? err : new Error(String(err));
11742
- if (attempt < MAX_RETRIES3) {
11830
+ if (attempt < MAX_RETRIES4) {
11743
11831
  process.stderr.write(`
11744
11832
  Download attempt ${attempt} failed, retrying...
11745
11833
  `);
@@ -13467,10 +13555,11 @@ async function runUpdate(cliArgs) {
13467
13555
  console.log(" Skipped (non-critical)");
13468
13556
  }
13469
13557
  console.log("\u{1F4E5} Installing @askexenow/exe-os@latest...");
13558
+ console.log(" This may take a minute...\n");
13470
13559
  try {
13471
13560
  execSync12("npm install -g @askexenow/exe-os@latest", {
13472
- stdio: ["pipe", "pipe", "pipe"],
13473
- timeout: 12e4
13561
+ stdio: ["pipe", "pipe", "inherit"],
13562
+ timeout: 3e5
13474
13563
  });
13475
13564
  } catch (err) {
13476
13565
  console.error("\n\u274C Update failed.");
@@ -27838,7 +27927,11 @@ import os16 from "os";
27838
27927
  async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
27839
27928
  const codexDir = path40.join(homeDir, ".codex");
27840
27929
  const hooksPath = path40.join(codexDir, "hooks.json");
27930
+ const logsDir = path40.join(homeDir, ".exe-os", "logs");
27931
+ const hookLogPath = path40.join(logsDir, "hooks.log");
27932
+ const logSuffix = ` 2>> "${hookLogPath}"`;
27841
27933
  await mkdir8(codexDir, { recursive: true });
27934
+ await mkdir8(logsDir, { recursive: true });
27842
27935
  let hooksJson = {};
27843
27936
  if (existsSync27(hooksPath)) {
27844
27937
  try {
@@ -27857,7 +27950,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
27857
27950
  hooks: [
27858
27951
  {
27859
27952
  type: "command",
27860
- command: `node "${path40.join(packageRoot, "dist", "hooks", "session-start.js")}"`,
27953
+ command: `node "${path40.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
27861
27954
  timeout: 30,
27862
27955
  statusMessage: "exe-os: loading memory brief"
27863
27956
  }
@@ -27872,11 +27965,11 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
27872
27965
  hooks: [
27873
27966
  {
27874
27967
  type: "command",
27875
- command: `node "${path40.join(packageRoot, "dist", "hooks", "ingest.js")}"`
27968
+ command: `node "${path40.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
27876
27969
  },
27877
27970
  {
27878
27971
  type: "command",
27879
- command: `node "${path40.join(packageRoot, "dist", "hooks", "error-recall.js")}"`
27972
+ command: `node "${path40.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
27880
27973
  }
27881
27974
  ]
27882
27975
  },
@@ -27888,11 +27981,11 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
27888
27981
  hooks: [
27889
27982
  {
27890
27983
  type: "command",
27891
- command: `node "${path40.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"`
27984
+ command: `node "${path40.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
27892
27985
  },
27893
27986
  {
27894
27987
  type: "command",
27895
- command: `node "${path40.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"`,
27988
+ command: `node "${path40.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
27896
27989
  timeout: 5
27897
27990
  }
27898
27991
  ]
@@ -27905,7 +27998,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
27905
27998
  hooks: [
27906
27999
  {
27907
28000
  type: "command",
27908
- command: `node "${path40.join(packageRoot, "dist", "hooks", "stop.js")}"`
28001
+ command: `node "${path40.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
27909
28002
  }
27910
28003
  ]
27911
28004
  },
@@ -27918,7 +28011,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
27918
28011
  hooks: [
27919
28012
  {
27920
28013
  type: "command",
27921
- command: `node "${path40.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"`
28014
+ command: `node "${path40.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
27922
28015
  }
27923
28016
  ]
27924
28017
  },
@@ -114,7 +114,7 @@ var DEFAULT_RUNTIME = "claude";
114
114
  var AGENT_CONFIG_PATH = path2.join(EXE_AI_DIR, "agent-config.json");
115
115
  var KNOWN_RUNTIMES = {
116
116
  claude: ["claude-opus-4", "claude-sonnet-4", "claude-haiku-4.5"],
117
- codex: ["gpt-5.4", "gpt-5.5", "o3", "o4-mini"],
117
+ codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
118
118
  opencode: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4", "google/gemini-2.5-pro", "deepseek/deepseek-r3", "minimax/minimax-m2.5"]
119
119
  };
120
120
  var DEFAULT_MODELS = {
@@ -2994,6 +2994,14 @@ var init_agent_config = __esm({
2994
2994
  });
2995
2995
 
2996
2996
  // src/lib/intercom-queue.ts
2997
+ var intercom_queue_exports = {};
2998
+ __export(intercom_queue_exports, {
2999
+ clearQueueForAgent: () => clearQueueForAgent,
3000
+ drainForSession: () => drainForSession,
3001
+ drainQueue: () => drainQueue,
3002
+ queueIntercom: () => queueIntercom,
3003
+ readQueue: () => readQueue
3004
+ });
2997
3005
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync8, mkdirSync as mkdirSync4 } from "fs";
2998
3006
  import path8 from "path";
2999
3007
  import os6 from "os";
@@ -3032,11 +3040,80 @@ function queueIntercom(targetSession, reason) {
3032
3040
  }
3033
3041
  writeQueue(queue);
3034
3042
  }
3035
- var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
3043
+ function drainQueue(isSessionBusy2, sendKeys) {
3044
+ const queue = readQueue();
3045
+ if (queue.length === 0) return { drained: 0, failed: 0 };
3046
+ const remaining = [];
3047
+ let drained = 0;
3048
+ let failed = 0;
3049
+ for (const item of queue) {
3050
+ const age = Date.now() - new Date(item.queuedAt).getTime();
3051
+ if (age > TTL_MS) {
3052
+ logQueue(`EXPIRED \u2192 ${item.targetSession} (${Math.round(age / 6e4)}min old, reason: ${item.reason})`);
3053
+ failed++;
3054
+ continue;
3055
+ }
3056
+ try {
3057
+ if (!isSessionBusy2(item.targetSession)) {
3058
+ const success = sendKeys(item.targetSession);
3059
+ if (success) {
3060
+ logQueue(`DRAINED \u2192 ${item.targetSession} (after ${item.attempts} retries)`);
3061
+ drained++;
3062
+ continue;
3063
+ }
3064
+ }
3065
+ } catch {
3066
+ }
3067
+ item.attempts++;
3068
+ if (item.attempts >= MAX_RETRIES2) {
3069
+ logQueue(`FAILED \u2192 ${item.targetSession} (${MAX_RETRIES2} retries exhausted, reason: ${item.reason})`);
3070
+ failed++;
3071
+ continue;
3072
+ }
3073
+ remaining.push(item);
3074
+ }
3075
+ writeQueue(remaining);
3076
+ return { drained, failed };
3077
+ }
3078
+ function drainForSession(targetSession, sendKeys) {
3079
+ const queue = readQueue();
3080
+ const match = queue.findIndex((q) => q.targetSession === targetSession);
3081
+ if (match < 0) return false;
3082
+ const success = sendKeys(targetSession);
3083
+ if (success) {
3084
+ queue.splice(match, 1);
3085
+ writeQueue(queue);
3086
+ logQueue(`DRAINED \u2192 ${targetSession} (prompt-submit trigger)`);
3087
+ return true;
3088
+ }
3089
+ return false;
3090
+ }
3091
+ function clearQueueForAgent(agentName) {
3092
+ const queue = readQueue();
3093
+ const before = queue.length;
3094
+ const filtered = queue.filter((q) => !q.targetSession.startsWith(`${agentName}-`));
3095
+ if (filtered.length < before) {
3096
+ writeQueue(filtered);
3097
+ logQueue(`CLEARED ${before - filtered.length} stale item(s) for ${agentName}`);
3098
+ }
3099
+ }
3100
+ function logQueue(msg) {
3101
+ const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [queue] ${msg}
3102
+ `;
3103
+ process.stderr.write(`[intercom-queue] ${msg}
3104
+ `);
3105
+ try {
3106
+ const { appendFileSync: appendFileSync3 } = __require("fs");
3107
+ appendFileSync3(INTERCOM_LOG, line);
3108
+ } catch {
3109
+ }
3110
+ }
3111
+ var QUEUE_PATH, MAX_RETRIES2, TTL_MS, INTERCOM_LOG;
3036
3112
  var init_intercom_queue = __esm({
3037
3113
  "src/lib/intercom-queue.ts"() {
3038
3114
  "use strict";
3039
3115
  QUEUE_PATH = path8.join(os6.homedir(), ".exe-os", "intercom-queue.json");
3116
+ MAX_RETRIES2 = 5;
3040
3117
  TTL_MS = 60 * 60 * 1e3;
3041
3118
  INTERCOM_LOG = path8.join(os6.homedir(), ".exe-os", "intercom.log");
3042
3119
  }
@@ -4276,6 +4353,13 @@ ${input.result}` : `\u26A0\uFE0F ${warning}`;
4276
4353
  await client.execute("PRAGMA wal_checkpoint(PASSIVE)");
4277
4354
  } catch {
4278
4355
  }
4356
+ if (input.status === "done" || input.status === "cancelled") {
4357
+ try {
4358
+ const { clearQueueForAgent: clearQueueForAgent2 } = await Promise.resolve().then(() => (init_intercom_queue(), intercom_queue_exports));
4359
+ clearQueueForAgent2(String(row.assigned_to));
4360
+ } catch {
4361
+ }
4362
+ }
4279
4363
  try {
4280
4364
  await writeCheckpoint({
4281
4365
  taskId,
@@ -6919,21 +7003,21 @@ async function withRosterLock(fn) {
6919
7003
  }
6920
7004
  }
6921
7005
  async function fetchWithRetry(url, init) {
6922
- const MAX_RETRIES2 = 3;
7006
+ const MAX_RETRIES3 = 3;
6923
7007
  const BASE_DELAY_MS2 = 200;
6924
7008
  let lastError;
6925
- for (let attempt = 0; attempt <= MAX_RETRIES2; attempt++) {
7009
+ for (let attempt = 0; attempt <= MAX_RETRIES3; attempt++) {
6926
7010
  try {
6927
7011
  const signal = AbortSignal.timeout(FETCH_TIMEOUT_MS);
6928
7012
  const resp = await fetch(url, { ...init, signal });
6929
- if (resp && resp.status >= 500 && attempt < MAX_RETRIES2) {
7013
+ if (resp && resp.status >= 500 && attempt < MAX_RETRIES3) {
6930
7014
  await new Promise((r) => setTimeout(r, BASE_DELAY_MS2 * Math.pow(2, attempt)));
6931
7015
  continue;
6932
7016
  }
6933
7017
  return resp;
6934
7018
  } catch (err) {
6935
7019
  lastError = err;
6936
- if (attempt === MAX_RETRIES2) throw err;
7020
+ if (attempt === MAX_RETRIES3) throw err;
6937
7021
  await new Promise((r) => setTimeout(r, BASE_DELAY_MS2 * Math.pow(2, attempt)));
6938
7022
  }
6939
7023
  }
@@ -1178,7 +1178,7 @@ var init_agent_config = __esm({
1178
1178
  AGENT_CONFIG_PATH = path3.join(EXE_AI_DIR, "agent-config.json");
1179
1179
  KNOWN_RUNTIMES = {
1180
1180
  claude: ["claude-opus-4", "claude-sonnet-4", "claude-haiku-4.5"],
1181
- codex: ["gpt-5.4", "gpt-5.5", "o3", "o4-mini"],
1181
+ codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
1182
1182
  opencode: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4", "google/gemini-2.5-pro", "deepseek/deepseek-r3", "minimax/minimax-m2.5"]
1183
1183
  };
1184
1184
  RUNTIME_LABELS = {