oh-my-opencode 3.17.12 → 3.17.14

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/index.js CHANGED
@@ -3003,6 +3003,7 @@ function truncateDescription(description, maxLength = 120) {
3003
3003
  var require_constants = __commonJS((exports, module) => {
3004
3004
  var WIN_SLASH = "\\\\/";
3005
3005
  var WIN_NO_SLASH = `[^${WIN_SLASH}]`;
3006
+ var DEFAULT_MAX_EXTGLOB_RECURSION = 0;
3006
3007
  var DOT_LITERAL = "\\.";
3007
3008
  var PLUS_LITERAL = "\\+";
3008
3009
  var QMARK_LITERAL = "\\?";
@@ -3053,6 +3054,7 @@ var require_constants = __commonJS((exports, module) => {
3053
3054
  SEP: "\\"
3054
3055
  };
3055
3056
  var POSIX_REGEX_SOURCE = {
3057
+ __proto__: null,
3056
3058
  alnum: "a-zA-Z0-9",
3057
3059
  alpha: "a-zA-Z",
3058
3060
  ascii: "\\x00-\\x7F",
@@ -3069,6 +3071,7 @@ var require_constants = __commonJS((exports, module) => {
3069
3071
  xdigit: "A-Fa-f0-9"
3070
3072
  };
3071
3073
  module.exports = {
3074
+ DEFAULT_MAX_EXTGLOB_RECURSION,
3072
3075
  MAX_LENGTH: 1024 * 64,
3073
3076
  POSIX_REGEX_SOURCE,
3074
3077
  REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g,
@@ -3546,6 +3549,213 @@ var require_parse = __commonJS((exports, module) => {
3546
3549
  var syntaxError = (type2, char) => {
3547
3550
  return `Missing ${type2}: "${char}" - use "\\\\${char}" to match literal characters`;
3548
3551
  };
3552
+ var splitTopLevel = (input) => {
3553
+ const parts = [];
3554
+ let bracket = 0;
3555
+ let paren = 0;
3556
+ let quote = 0;
3557
+ let value = "";
3558
+ let escaped = false;
3559
+ for (const ch of input) {
3560
+ if (escaped === true) {
3561
+ value += ch;
3562
+ escaped = false;
3563
+ continue;
3564
+ }
3565
+ if (ch === "\\") {
3566
+ value += ch;
3567
+ escaped = true;
3568
+ continue;
3569
+ }
3570
+ if (ch === '"') {
3571
+ quote = quote === 1 ? 0 : 1;
3572
+ value += ch;
3573
+ continue;
3574
+ }
3575
+ if (quote === 0) {
3576
+ if (ch === "[") {
3577
+ bracket++;
3578
+ } else if (ch === "]" && bracket > 0) {
3579
+ bracket--;
3580
+ } else if (bracket === 0) {
3581
+ if (ch === "(") {
3582
+ paren++;
3583
+ } else if (ch === ")" && paren > 0) {
3584
+ paren--;
3585
+ } else if (ch === "|" && paren === 0) {
3586
+ parts.push(value);
3587
+ value = "";
3588
+ continue;
3589
+ }
3590
+ }
3591
+ }
3592
+ value += ch;
3593
+ }
3594
+ parts.push(value);
3595
+ return parts;
3596
+ };
3597
+ var isPlainBranch = (branch) => {
3598
+ let escaped = false;
3599
+ for (const ch of branch) {
3600
+ if (escaped === true) {
3601
+ escaped = false;
3602
+ continue;
3603
+ }
3604
+ if (ch === "\\") {
3605
+ escaped = true;
3606
+ continue;
3607
+ }
3608
+ if (/[?*+@!()[\]{}]/.test(ch)) {
3609
+ return false;
3610
+ }
3611
+ }
3612
+ return true;
3613
+ };
3614
+ var normalizeSimpleBranch = (branch) => {
3615
+ let value = branch.trim();
3616
+ let changed = true;
3617
+ while (changed === true) {
3618
+ changed = false;
3619
+ if (/^@\([^\\()[\]{}|]+\)$/.test(value)) {
3620
+ value = value.slice(2, -1);
3621
+ changed = true;
3622
+ }
3623
+ }
3624
+ if (!isPlainBranch(value)) {
3625
+ return;
3626
+ }
3627
+ return value.replace(/\\(.)/g, "$1");
3628
+ };
3629
+ var hasRepeatedCharPrefixOverlap = (branches) => {
3630
+ const values = branches.map(normalizeSimpleBranch).filter(Boolean);
3631
+ for (let i2 = 0;i2 < values.length; i2++) {
3632
+ for (let j = i2 + 1;j < values.length; j++) {
3633
+ const a = values[i2];
3634
+ const b = values[j];
3635
+ const char = a[0];
3636
+ if (!char || a !== char.repeat(a.length) || b !== char.repeat(b.length)) {
3637
+ continue;
3638
+ }
3639
+ if (a === b || a.startsWith(b) || b.startsWith(a)) {
3640
+ return true;
3641
+ }
3642
+ }
3643
+ }
3644
+ return false;
3645
+ };
3646
+ var parseRepeatedExtglob = (pattern, requireEnd = true) => {
3647
+ if (pattern[0] !== "+" && pattern[0] !== "*" || pattern[1] !== "(") {
3648
+ return;
3649
+ }
3650
+ let bracket = 0;
3651
+ let paren = 0;
3652
+ let quote = 0;
3653
+ let escaped = false;
3654
+ for (let i2 = 1;i2 < pattern.length; i2++) {
3655
+ const ch = pattern[i2];
3656
+ if (escaped === true) {
3657
+ escaped = false;
3658
+ continue;
3659
+ }
3660
+ if (ch === "\\") {
3661
+ escaped = true;
3662
+ continue;
3663
+ }
3664
+ if (ch === '"') {
3665
+ quote = quote === 1 ? 0 : 1;
3666
+ continue;
3667
+ }
3668
+ if (quote === 1) {
3669
+ continue;
3670
+ }
3671
+ if (ch === "[") {
3672
+ bracket++;
3673
+ continue;
3674
+ }
3675
+ if (ch === "]" && bracket > 0) {
3676
+ bracket--;
3677
+ continue;
3678
+ }
3679
+ if (bracket > 0) {
3680
+ continue;
3681
+ }
3682
+ if (ch === "(") {
3683
+ paren++;
3684
+ continue;
3685
+ }
3686
+ if (ch === ")") {
3687
+ paren--;
3688
+ if (paren === 0) {
3689
+ if (requireEnd === true && i2 !== pattern.length - 1) {
3690
+ return;
3691
+ }
3692
+ return {
3693
+ type: pattern[0],
3694
+ body: pattern.slice(2, i2),
3695
+ end: i2
3696
+ };
3697
+ }
3698
+ }
3699
+ }
3700
+ };
3701
+ var getStarExtglobSequenceOutput = (pattern) => {
3702
+ let index = 0;
3703
+ const chars = [];
3704
+ while (index < pattern.length) {
3705
+ const match = parseRepeatedExtglob(pattern.slice(index), false);
3706
+ if (!match || match.type !== "*") {
3707
+ return;
3708
+ }
3709
+ const branches = splitTopLevel(match.body).map((branch2) => branch2.trim());
3710
+ if (branches.length !== 1) {
3711
+ return;
3712
+ }
3713
+ const branch = normalizeSimpleBranch(branches[0]);
3714
+ if (!branch || branch.length !== 1) {
3715
+ return;
3716
+ }
3717
+ chars.push(branch);
3718
+ index += match.end + 1;
3719
+ }
3720
+ if (chars.length < 1) {
3721
+ return;
3722
+ }
3723
+ const source = chars.length === 1 ? utils.escapeRegex(chars[0]) : `[${chars.map((ch) => utils.escapeRegex(ch)).join("")}]`;
3724
+ return `${source}*`;
3725
+ };
3726
+ var repeatedExtglobRecursion = (pattern) => {
3727
+ let depth = 0;
3728
+ let value = pattern.trim();
3729
+ let match = parseRepeatedExtglob(value);
3730
+ while (match) {
3731
+ depth++;
3732
+ value = match.body.trim();
3733
+ match = parseRepeatedExtglob(value);
3734
+ }
3735
+ return depth;
3736
+ };
3737
+ var analyzeRepeatedExtglob = (body, options) => {
3738
+ if (options.maxExtglobRecursion === false) {
3739
+ return { risky: false };
3740
+ }
3741
+ const max = typeof options.maxExtglobRecursion === "number" ? options.maxExtglobRecursion : constants5.DEFAULT_MAX_EXTGLOB_RECURSION;
3742
+ const branches = splitTopLevel(body).map((branch) => branch.trim());
3743
+ if (branches.length > 1) {
3744
+ if (branches.some((branch) => branch === "") || branches.some((branch) => /^[*?]+$/.test(branch)) || hasRepeatedCharPrefixOverlap(branches)) {
3745
+ return { risky: true };
3746
+ }
3747
+ }
3748
+ for (const branch of branches) {
3749
+ const safeOutput = getStarExtglobSequenceOutput(branch);
3750
+ if (safeOutput) {
3751
+ return { risky: true, safeOutput };
3752
+ }
3753
+ if (repeatedExtglobRecursion(branch) > max) {
3754
+ return { risky: true };
3755
+ }
3756
+ }
3757
+ return { risky: false };
3758
+ };
3549
3759
  var parse3 = (input, options) => {
3550
3760
  if (typeof input !== "string") {
3551
3761
  throw new TypeError("Expected a string");
@@ -3677,6 +3887,8 @@ var require_parse = __commonJS((exports, module) => {
3677
3887
  token.prev = prev;
3678
3888
  token.parens = state3.parens;
3679
3889
  token.output = state3.output;
3890
+ token.startIndex = state3.index;
3891
+ token.tokensIndex = tokens.length;
3680
3892
  const output = (opts.capture ? "(" : "") + token.open;
3681
3893
  increment("parens");
3682
3894
  push({ type: type2, value: value2, output: state3.output ? "" : ONE_CHAR });
@@ -3684,6 +3896,26 @@ var require_parse = __commonJS((exports, module) => {
3684
3896
  extglobs.push(token);
3685
3897
  };
3686
3898
  const extglobClose = (token) => {
3899
+ const literal = input.slice(token.startIndex, state3.index + 1);
3900
+ const body = input.slice(token.startIndex + 2, state3.index);
3901
+ const analysis = analyzeRepeatedExtglob(body, opts);
3902
+ if ((token.type === "plus" || token.type === "star") && analysis.risky) {
3903
+ const safeOutput = analysis.safeOutput ? (token.output ? "" : ONE_CHAR) + (opts.capture ? `(${analysis.safeOutput})` : analysis.safeOutput) : undefined;
3904
+ const open = tokens[token.tokensIndex];
3905
+ open.type = "text";
3906
+ open.value = literal;
3907
+ open.output = safeOutput || utils.escapeRegex(literal);
3908
+ for (let i2 = token.tokensIndex + 1;i2 < tokens.length; i2++) {
3909
+ tokens[i2].value = "";
3910
+ tokens[i2].output = "";
3911
+ delete tokens[i2].suffix;
3912
+ }
3913
+ state3.output = token.output + open.output;
3914
+ state3.backtrack = true;
3915
+ push({ type: "paren", extglob: true, value, output: "" });
3916
+ decrement("parens");
3917
+ return;
3918
+ }
3687
3919
  let output = token.close + (opts.capture ? ")" : "");
3688
3920
  let rest;
3689
3921
  if (token.type === "negate") {
@@ -19339,13 +19571,11 @@ var AGENT_RESTRICTIONS = {
19339
19571
  },
19340
19572
  metis: {
19341
19573
  write: false,
19342
- edit: false,
19343
- task: false
19574
+ edit: false
19344
19575
  },
19345
19576
  momus: {
19346
19577
  write: false,
19347
- edit: false,
19348
- task: false
19578
+ edit: false
19349
19579
  },
19350
19580
  "multimodal-looker": {
19351
19581
  read: true
@@ -19382,6 +19612,7 @@ function toLogLabel(cacheLabel) {
19382
19612
  }
19383
19613
  function createJsonFileCacheStore(options) {
19384
19614
  let memoryValue;
19615
+ let writtenInCurrentProcess = false;
19385
19616
  function getCacheFilePath() {
19386
19617
  return join10(options.getCacheDir(), options.filename);
19387
19618
  }
@@ -19416,6 +19647,12 @@ function createJsonFileCacheStore(options) {
19416
19647
  }
19417
19648
  }
19418
19649
  function has() {
19650
+ if (memoryValue !== undefined && memoryValue !== null) {
19651
+ return true;
19652
+ }
19653
+ if (writtenInCurrentProcess) {
19654
+ return true;
19655
+ }
19419
19656
  return existsSync10(getCacheFilePath());
19420
19657
  }
19421
19658
  function write(value) {
@@ -19424,6 +19661,7 @@ function createJsonFileCacheStore(options) {
19424
19661
  try {
19425
19662
  writeFileSync2(cacheFile, options.serialize?.(value) ?? JSON.stringify(value, null, 2));
19426
19663
  memoryValue = value;
19664
+ writtenInCurrentProcess = true;
19427
19665
  log(`[${options.logPrefix}] ${options.cacheLabel} written`, options.describe(value));
19428
19666
  } catch (error) {
19429
19667
  log(`[${options.logPrefix}] Error writing ${toLogLabel(options.cacheLabel)}`, {
@@ -19433,6 +19671,7 @@ function createJsonFileCacheStore(options) {
19433
19671
  }
19434
19672
  function resetMemory() {
19435
19673
  memoryValue = undefined;
19674
+ writtenInCurrentProcess = false;
19436
19675
  }
19437
19676
  return {
19438
19677
  read,
@@ -19443,6 +19682,7 @@ function createJsonFileCacheStore(options) {
19443
19682
  }
19444
19683
 
19445
19684
  // src/shared/connected-providers-cache.ts
19685
+ var providerModelsCacheWrittenInCurrentProcess = false;
19446
19686
  var CONNECTED_PROVIDERS_CACHE_FILE = "connected-providers.json";
19447
19687
  var PROVIDER_MODELS_CACHE_FILE = "provider-models.json";
19448
19688
  function isRecord(value) {
@@ -19482,6 +19722,9 @@ function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDi
19482
19722
  return providerModelsCacheStore.read();
19483
19723
  }
19484
19724
  function hasProviderModelsCache() {
19725
+ if (providerModelsCacheWrittenInCurrentProcess) {
19726
+ return true;
19727
+ }
19485
19728
  return providerModelsCacheStore.has();
19486
19729
  }
19487
19730
  function writeProviderModelsCache(data) {
@@ -19489,6 +19732,7 @@ function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDi
19489
19732
  ...data,
19490
19733
  updatedAt: new Date().toISOString()
19491
19734
  });
19735
+ providerModelsCacheWrittenInCurrentProcess = true;
19492
19736
  }
19493
19737
  async function updateConnectedProvidersCache(client) {
19494
19738
  if (!client?.provider?.list) {
@@ -19537,6 +19781,7 @@ function createConnectedProvidersCacheStore(getCacheDir2 = getOmoOpenCodeCacheDi
19537
19781
  function _resetMemCacheForTesting() {
19538
19782
  connectedProvidersCacheStore.resetMemory();
19539
19783
  providerModelsCacheStore.resetMemory();
19784
+ providerModelsCacheWrittenInCurrentProcess = false;
19540
19785
  }
19541
19786
  return {
19542
19787
  readConnectedProvidersCache,
@@ -66429,7 +66674,7 @@ async function injectContinuation(args) {
66429
66674
  log(`[${HOOK_NAME}] Skipped injection: continuation stopped for session`, { sessionID });
66430
66675
  return;
66431
66676
  }
66432
- const hasRunningBgTasks = backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((task) => task.status === "running") : false;
66677
+ const hasRunningBgTasks = backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((task) => task.status === "running" || task.status === "pending") : false;
66433
66678
  if (hasRunningBgTasks) {
66434
66679
  log(`[${HOOK_NAME}] Skipped injection: background tasks running`, { sessionID });
66435
66680
  return;
@@ -66635,7 +66880,7 @@ async function handleSessionIdle(args) {
66635
66880
  }
66636
66881
  state2.abortDetectedAt = undefined;
66637
66882
  }
66638
- const hasRunningBgTasks = backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((task) => task.status === "running") : false;
66883
+ const hasRunningBgTasks = backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((task) => task.status === "running" || task.status === "pending") : false;
66639
66884
  if (hasRunningBgTasks) {
66640
66885
  log(`[${HOOK_NAME}] Skipped: background tasks running`, { sessionID });
66641
66886
  return;
@@ -67193,8 +67438,9 @@ function createContextWindowMonitorHook(_ctx, modelCacheState) {
67193
67438
  if (actualUsagePercentage < CONTEXT_WARNING_THRESHOLD)
67194
67439
  return;
67195
67440
  remindedSessions.add(sessionID);
67196
- const usedPct = (actualUsagePercentage * 100).toFixed(1);
67197
- const remainingPct = ((1 - actualUsagePercentage) * 100).toFixed(1);
67441
+ const clampedPercentage = Math.min(Math.max(actualUsagePercentage, 0), 1);
67442
+ const usedPct = (clampedPercentage * 100).toFixed(1);
67443
+ const remainingPct = ((1 - clampedPercentage) * 100).toFixed(1);
67198
67444
  const usedTokens = totalInputTokens.toLocaleString();
67199
67445
  const limitTokens = actualLimit.toLocaleString();
67200
67446
  output.output += `
@@ -67349,8 +67595,12 @@ var getAfplayPath = createCommandFinder("afplay");
67349
67595
  var getPaplayPath = createCommandFinder("paplay");
67350
67596
  var getAplayPath = createCommandFinder("aplay");
67351
67597
  var getTerminalNotifierPath = createCommandFinder("terminal-notifier");
67598
+ var getCmuxPath = createCommandFinder("cmux");
67352
67599
  function startBackgroundCheck2(platform) {
67353
67600
  if (platform === "darwin") {
67601
+ getCmuxPath().catch((error) => {
67602
+ logBackgroundCheckError("cmux", error);
67603
+ });
67354
67604
  getOsascriptPath().catch((error) => {
67355
67605
  logBackgroundCheckError("osascript", error);
67356
67606
  });
@@ -67423,6 +67673,13 @@ function getDefaultSoundPath(platform2) {
67423
67673
  async function sendSessionNotification(ctx, platform2, title, message) {
67424
67674
  switch (platform2) {
67425
67675
  case "darwin": {
67676
+ const cmuxPath = await getCmuxPath();
67677
+ if (cmuxPath) {
67678
+ try {
67679
+ await ctx.$`${cmuxPath} notify --title ${title} --body ${message}`.quiet();
67680
+ break;
67681
+ } catch {}
67682
+ }
67426
67683
  const terminalNotifierPath = await getTerminalNotifierPath();
67427
67684
  if (terminalNotifierPath) {
67428
67685
  const bundleId = process.env.__CFBundleIdentifier;
@@ -67654,9 +67911,9 @@ function createIdleNotificationScheduler(options) {
67654
67911
  return;
67655
67912
  }
67656
67913
  notifiedSessions.add(sessionID);
67657
- await options.send(options.ctx, options.platform, sessionID);
67914
+ await options.send(options.ctx, sessionID);
67658
67915
  if (options.config.playSound && options.config.soundPath) {
67659
- await options.playSound(options.ctx, options.platform, options.config.soundPath);
67916
+ await options.playSound(options.ctx, options.config.soundPath);
67660
67917
  }
67661
67918
  } finally {
67662
67919
  executingNotifications.delete(sessionID);
@@ -67746,10 +68003,10 @@ function createSessionNotification(ctx, config = {}) {
67746
68003
  let defaultSoundPath = mergedConfig.soundPath;
67747
68004
  const scheduler = createIdleNotificationScheduler({
67748
68005
  ctx,
67749
- platform: "unsupported",
67750
68006
  config: mergedConfig,
67751
68007
  hasIncompleteTodos,
67752
- send: async (hookCtx, platform2, sessionID) => {
68008
+ send: async (hookCtx, sessionID) => {
68009
+ const platform2 = ensureNotificationPlatform();
67753
68010
  if (typeof hookCtx.client.session.get !== "function" && typeof hookCtx.client.session.messages !== "function") {
67754
68011
  await sendSessionNotification(hookCtx, platform2, mergedConfig.title, mergedConfig.message);
67755
68012
  return;
@@ -67761,7 +68018,10 @@ function createSessionNotification(ctx, config = {}) {
67761
68018
  });
67762
68019
  await sendSessionNotification(hookCtx, platform2, content.title, content.message);
67763
68020
  },
67764
- playSound: playSessionNotificationSound
68021
+ playSound: async (hookCtx, soundPath) => {
68022
+ const platform2 = ensureNotificationPlatform();
68023
+ await playSessionNotificationSound(hookCtx, platform2, soundPath);
68024
+ }
67765
68025
  });
67766
68026
  const QUESTION_TOOLS = new Set(["question", "ask_user_question", "askuserquestion"]);
67767
68027
  const PERMISSION_EVENTS = new Set(["permission.ask", "permission.asked", "permission.updated", "permission.requested"]);
@@ -74560,6 +74820,7 @@ async function runBunInstallWithDetails(options) {
74560
74820
  try {
74561
74821
  const proc = spawnWithWindowsHide(["bun", "install"], {
74562
74822
  cwd: cacheDir,
74823
+ env: process.env,
74563
74824
  stdout: outputMode,
74564
74825
  stderr: outputMode
74565
74826
  });
@@ -76173,7 +76434,7 @@ IF COMPLEX - DO NOT STRUGGLE ALONE. Consult specialists:
76173
76434
 
76174
76435
  SYNTHESIZE findings before proceeding.
76175
76436
  ---
76176
- MANDATORY delegate_task params: ALWAYS include load_skills=[] and run_in_background when calling delegate_task.
76437
+ MANDATORY delegate_task params: ALWAYS include load_skills and run_in_background when calling delegate_task. Evaluate available skills before dispatch - pass task-appropriate skills when relevant, pass [] ONLY when no skill matches the task domain.
76177
76438
  Example: delegate_task(subagent_type="explore", prompt="...", run_in_background=true, load_skills=[])`
76178
76439
  }
76179
76440
  ];
@@ -85832,6 +86093,7 @@ async function resolveRecentPromptContextForSession(ctx, sessionID) {
85832
86093
  }
85833
86094
 
85834
86095
  // src/hooks/atlas/boulder-continuation-injector.ts
86096
+ var ACTIVE_BACKGROUND_TASK_STATUSES = new Set(["pending", "running"]);
85835
86097
  async function injectBoulderContinuation(input) {
85836
86098
  const {
85837
86099
  ctx,
@@ -85846,7 +86108,7 @@ async function injectBoulderContinuation(input) {
85846
86108
  backgroundManager,
85847
86109
  sessionState
85848
86110
  } = input;
85849
- const hasRunningBgTasks = backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((t) => t.status === "running") : false;
86111
+ const hasRunningBgTasks = backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((t) => ACTIVE_BACKGROUND_TASK_STATUSES.has(t.status)) : false;
85850
86112
  if (hasRunningBgTasks) {
85851
86113
  log(`[${HOOK_NAME7}] Skipped injection: background tasks running`, { sessionID });
85852
86114
  return "skipped_background_tasks";
@@ -87795,7 +88057,7 @@ Task ID: ${task.id}
87795
88057
  Description: ${task.description}
87796
88058
  Agent: ${task.agent}
87797
88059
  Status: ${task.status}
87798
- Session ID: ${task.sessionID ?? "N/A"}
88060
+ Session ID: ${task.sessionId ?? "N/A"}
87799
88061
 
87800
88062
  Thinking summary (first ${THINKING_SUMMARY_MAX_CHARS} chars):
87801
88063
  ${summaryText}
@@ -87944,7 +88206,7 @@ function createUnstableAgentBabysitterHook(ctx, options) {
87944
88206
  const lastReminderAt = reminderCooldowns.get(task.id);
87945
88207
  if (lastReminderAt && now - lastReminderAt < COOLDOWN_MS)
87946
88208
  continue;
87947
- const summary = task.sessionID ? await getThinkingSummary(ctx, task.sessionID) : null;
88209
+ const summary = task.sessionId ? await getThinkingSummary(ctx, task.sessionId) : null;
87948
88210
  const reminder = buildReminder(task, summary, idleMs);
87949
88211
  const { agent, model, tools } = await resolveMainSessionTarget(ctx, mainSessionID);
87950
88212
  try {
@@ -96102,7 +96364,8 @@ function createSkillMcpTool(options) {
96102
96364
  serverName: args.mcp_name,
96103
96365
  skillName: found.skill.name,
96104
96366
  sessionID,
96105
- scope: found.skill.scope
96367
+ scope: found.skill.scope,
96368
+ directory: toolContext.directory
96106
96369
  };
96107
96370
  const context = {
96108
96371
  config: found.config,
@@ -96264,7 +96527,7 @@ ${truncated}
96264
96527
  | Agent | ${task.agent} |
96265
96528
  | Status | **${task.status}** |
96266
96529
  | ${durationLabel} | ${duration} |
96267
- | Session ID | \`${task.sessionID}\` |${progressSection}
96530
+ | Session ID | \`${task.sessionId}\` |${progressSection}
96268
96531
  ${statusNote}
96269
96532
  ## Original Prompt
96270
96533
 
@@ -96296,11 +96559,11 @@ function extractToolResultText(part) {
96296
96559
  return [];
96297
96560
  }
96298
96561
  async function formatFullSession(task, client2, options) {
96299
- if (!task.sessionID) {
96562
+ if (!task.sessionId) {
96300
96563
  return formatTaskStatus(task);
96301
96564
  }
96302
96565
  const messagesResult = await client2.session.messages({
96303
- path: { id: task.sessionID }
96566
+ path: { id: task.sessionId }
96304
96567
  });
96305
96568
  const errorMessage = getErrorMessage4(messagesResult);
96306
96569
  if (errorMessage) {
@@ -96351,7 +96614,7 @@ async function formatFullSession(task, client2, options) {
96351
96614
  lines.push(`Task ID: ${task.id}`);
96352
96615
  lines.push(`Description: ${task.description}`);
96353
96616
  lines.push(`Status: ${task.status}`);
96354
- lines.push(`Session ID: ${task.sessionID}`);
96617
+ lines.push(`Session ID: ${task.sessionId}`);
96355
96618
  lines.push(`Total messages: ${normalizedMessages.length}`);
96356
96619
  lines.push(`Returned: ${visibleMessages.length}`);
96357
96620
  lines.push(`Has more: ${hasMore ? "true" : "false"}`);
@@ -96471,11 +96734,11 @@ function getTimeString(value) {
96471
96734
  return typeof value === "string" ? value : "";
96472
96735
  }
96473
96736
  async function formatTaskResult(task, client2) {
96474
- if (!task.sessionID) {
96737
+ if (!task.sessionId) {
96475
96738
  return `Error: Task has no sessionID`;
96476
96739
  }
96477
96740
  const messagesResult = await client2.session.messages({
96478
- path: { id: task.sessionID }
96741
+ path: { id: task.sessionId }
96479
96742
  });
96480
96743
  const errorMessage = getErrorMessage4(messagesResult);
96481
96744
  if (errorMessage) {
@@ -96488,7 +96751,7 @@ async function formatTaskResult(task, client2) {
96488
96751
  Task ID: ${task.id}
96489
96752
  Description: ${task.description}
96490
96753
  Duration: ${formatDuration(task.startedAt ?? new Date, task.completedAt)}
96491
- Session ID: ${task.sessionID}
96754
+ Session ID: ${task.sessionId}
96492
96755
 
96493
96756
  ---
96494
96757
 
@@ -96501,7 +96764,7 @@ Session ID: ${task.sessionID}
96501
96764
  Task ID: ${task.id}
96502
96765
  Description: ${task.description}
96503
96766
  Duration: ${formatDuration(task.startedAt ?? new Date, task.completedAt)}
96504
- Session ID: ${task.sessionID}
96767
+ Session ID: ${task.sessionId}
96505
96768
 
96506
96769
  ---
96507
96770
 
@@ -96519,13 +96782,13 @@ Session ID: ${task.sessionID}
96519
96782
  Task ID: ${task.id}
96520
96783
  Description: ${task.description}
96521
96784
  Duration: ${formatDuration(task.startedAt ?? new Date, task.completedAt)}
96522
- Session ID: ${task.sessionID}
96785
+ Session ID: ${task.sessionId}
96523
96786
 
96524
96787
  ---
96525
96788
 
96526
96789
  Session error: ${sessionError}`;
96527
96790
  }
96528
- const newMessages = consumeNewMessages(task.sessionID, sortedMessages);
96791
+ const newMessages = consumeNewMessages(task.sessionId, sortedMessages);
96529
96792
  if (newMessages.length === 0) {
96530
96793
  const duration2 = formatDuration(task.startedAt ?? new Date, task.completedAt);
96531
96794
  return `Task Result
@@ -96533,7 +96796,7 @@ Session error: ${sessionError}`;
96533
96796
  Task ID: ${task.id}
96534
96797
  Description: ${task.description}
96535
96798
  Duration: ${duration2}
96536
- Session ID: ${task.sessionID}
96799
+ Session ID: ${task.sessionId}
96537
96800
 
96538
96801
  ---
96539
96802
 
@@ -96571,7 +96834,7 @@ Session ID: ${task.sessionID}
96571
96834
  Task ID: ${task.id}
96572
96835
  Description: ${task.description}
96573
96836
  Duration: ${duration}
96574
- Session ID: ${task.sessionID}
96837
+ Session ID: ${task.sessionId}
96575
96838
 
96576
96839
  ---
96577
96840
 
@@ -96673,7 +96936,7 @@ function createBackgroundOutput(manager, client2) {
96673
96936
  agent: task.agent,
96674
96937
  category: task.category,
96675
96938
  description: task.description,
96676
- ...task.sessionID ? { sessionId: task.sessionID, taskId: task.sessionID } : {}
96939
+ ...task.sessionId ? { sessionId: task.sessionId, taskId: task.sessionId } : {}
96677
96940
  }
96678
96941
  };
96679
96942
  await publishToolMetadata(ctx, meta);
@@ -96719,7 +96982,7 @@ function createBackgroundOutput(manager, client2) {
96719
96982
  return didTimeoutWhileActive ? appendTimeoutNote(output, timeoutMs) : output;
96720
96983
  }
96721
96984
  if (resolvedTask.status === "completed") {
96722
- recordBackgroundOutputConsumption(ctx.sessionID, ctx.messageID, resolvedTask.sessionID);
96985
+ recordBackgroundOutputConsumption(ctx.sessionID, ctx.messageID, resolvedTask.sessionId);
96723
96986
  return await formatTaskResult(resolvedTask, client2);
96724
96987
  }
96725
96988
  if (resolvedTask.status === "error" || resolvedTask.status === "cancelled" || resolvedTask.status === "interrupt") {
@@ -96767,7 +97030,7 @@ function createBackgroundCancel(manager, _client) {
96767
97030
  id: task2.id,
96768
97031
  description: task2.description,
96769
97032
  status: originalStatus === "pending" ? "pending" : "running",
96770
- sessionID: task2.sessionID
97033
+ sessionID: task2.sessionId
96771
97034
  });
96772
97035
  }
96773
97036
  const tableRows = cancelledInfo.map((t) => `| \`${t.id}\` | ${t.description} | ${t.status} | ${t.sessionID ? `\`${t.sessionID}\`` : "(not started)"} |`).join(`
@@ -96818,7 +97081,7 @@ Status: ${task.status}`;
96818
97081
 
96819
97082
  Task ID: ${task.id}
96820
97083
  Description: ${task.description}
96821
- Session ID: ${task.sessionID}
97084
+ Session ID: ${task.sessionId}
96822
97085
  Status: ${task.status}`;
96823
97086
  } catch (error) {
96824
97087
  return `[ERROR] Error cancelling task: ${error instanceof Error ? error.message : String(error)}`;
@@ -96955,8 +97218,8 @@ async function executeBackground(args, toolContext, manager, client2, fallbackCh
96955
97218
  description: args.description,
96956
97219
  prompt: args.prompt,
96957
97220
  agent: args.subagent_type,
96958
- parentSessionID: toolContext.sessionID,
96959
- parentMessageID: toolContext.messageID,
97221
+ parentSessionId: toolContext.sessionID,
97222
+ parentMessageId: toolContext.messageID,
96960
97223
  parentAgent,
96961
97224
  parentTools: getSessionTools(toolContext.sessionID),
96962
97225
  model,
@@ -96965,7 +97228,7 @@ async function executeBackground(args, toolContext, manager, client2, fallbackCh
96965
97228
  const WAIT_FOR_SESSION_INTERVAL_MS = 50;
96966
97229
  const WAIT_FOR_SESSION_TIMEOUT_MS = 30000;
96967
97230
  const waitStart = Date.now();
96968
- let sessionId = task.sessionID;
97231
+ let sessionId = task.sessionId;
96969
97232
  while (!sessionId && Date.now() - waitStart < WAIT_FOR_SESSION_TIMEOUT_MS) {
96970
97233
  const updated = manager.getTask(task.id);
96971
97234
  if (updated?.status === "error" || updated?.status === "cancelled" || updated?.status === "interrupt") {
@@ -96973,7 +97236,7 @@ async function executeBackground(args, toolContext, manager, client2, fallbackCh
96973
97236
 
96974
97237
  Task ID: ${task.id}`;
96975
97238
  }
96976
- sessionId = updated?.sessionID;
97239
+ sessionId = updated?.sessionId;
96977
97240
  if (sessionId) {
96978
97241
  break;
96979
97242
  }
@@ -98332,13 +98595,13 @@ ${args.prompt}` : args.prompt;
98332
98595
  const task = await manager.resume({
98333
98596
  sessionId: taskID,
98334
98597
  prompt: effectivePrompt,
98335
- parentSessionID: parentContext.sessionID,
98336
- parentMessageID: parentContext.messageID,
98598
+ parentSessionId: parentContext.sessionID,
98599
+ parentMessageId: parentContext.messageID,
98337
98600
  parentModel: parentContext.model,
98338
98601
  parentAgent: parentContext.agent,
98339
98602
  parentTools: getSessionTools(parentContext.sessionID)
98340
98603
  });
98341
- const sessionId = task.sessionID;
98604
+ const sessionId = task.sessionId;
98342
98605
  const backgroundTaskId = task.id;
98343
98606
  const resolvedModel = resolveMetadataModel(task.model, parentContext.model);
98344
98607
  const bgContMeta = {
@@ -98829,8 +99092,8 @@ async function executeUnstableAgentTask(args, ctx, executorCtx, parentContext, a
98829
99092
  description: args.description,
98830
99093
  prompt: effectivePrompt,
98831
99094
  agent: agentToUse,
98832
- parentSessionID: parentContext.sessionID,
98833
- parentMessageID: parentContext.messageID,
99095
+ parentSessionId: parentContext.sessionID,
99096
+ parentMessageId: parentContext.messageID,
98834
99097
  parentModel: parentContext.model,
98835
99098
  parentAgent: parentContext.agent,
98836
99099
  parentTools: getSessionTools(parentContext.sessionID),
@@ -98843,7 +99106,7 @@ async function executeUnstableAgentTask(args, ctx, executorCtx, parentContext, a
98843
99106
  launchedTaskID = task.id;
98844
99107
  const timing = getTimingConfig();
98845
99108
  const waitStart = Date.now();
98846
- let sessionID = task.sessionID;
99109
+ let sessionID = task.sessionId;
98847
99110
  while (!sessionID && Date.now() - waitStart < timing.WAIT_FOR_SESSION_TIMEOUT_MS) {
98848
99111
  if (ctx.abort?.aborted) {
98849
99112
  cleanupReason = "Parent aborted while waiting for unstable task session start";
@@ -98853,7 +99116,7 @@ Task ID: ${task.id}`;
98853
99116
  }
98854
99117
  await new Promise((resolve21) => setTimeout(resolve21, timing.WAIT_FOR_SESSION_INTERVAL_MS));
98855
99118
  const updated = manager.getTask(task.id);
98856
- sessionID = updated?.sessionID;
99119
+ sessionID = updated?.sessionId;
98857
99120
  }
98858
99121
  if (!sessionID) {
98859
99122
  cleanupReason = "Unstable task session start timed out before session became available";
@@ -99048,7 +99311,7 @@ function continueSessionSetup(args) {
99048
99311
  if (updated.status === "error" || updated.status === "cancelled" || updated.status === "interrupt") {
99049
99312
  return;
99050
99313
  }
99051
- const sessionId = updated.sessionID;
99314
+ const sessionId = updated.sessionId;
99052
99315
  if (!sessionId) {
99053
99316
  continue;
99054
99317
  }
@@ -99070,7 +99333,7 @@ async function waitForBackgroundSessionStart(args) {
99070
99333
  if (updated?.status === "error" || updated?.status === "cancelled" || updated?.status === "interrupt") {
99071
99334
  return;
99072
99335
  }
99073
- sessionId = updated?.sessionID;
99336
+ sessionId = updated?.sessionId;
99074
99337
  if (sessionId) {
99075
99338
  return sessionId;
99076
99339
  }
@@ -99092,8 +99355,8 @@ async function executeBackgroundTask(args, ctx, executorCtx, parentContext, agen
99092
99355
  description: args.description,
99093
99356
  prompt: effectivePrompt,
99094
99357
  agent: normalizedAgent,
99095
- parentSessionID: parentContext.sessionID,
99096
- parentMessageID: parentContext.messageID,
99358
+ parentSessionId: parentContext.sessionID,
99359
+ parentMessageId: parentContext.messageID,
99097
99360
  parentModel: parentContext.model,
99098
99361
  parentAgent: parentContext.agent,
99099
99362
  parentTools: getSessionTools(parentContext.sessionID),
@@ -99107,7 +99370,7 @@ async function executeBackgroundTask(args, ctx, executorCtx, parentContext, agen
99107
99370
  const timing = getTimingConfig();
99108
99371
  let sessionId = await waitForBackgroundSessionStart({
99109
99372
  taskId: task.id,
99110
- initialSessionId: task.sessionID,
99373
+ initialSessionId: task.sessionId,
99111
99374
  manager,
99112
99375
  timing,
99113
99376
  abortSignal: ctx.abort,
@@ -103742,14 +104005,14 @@ function formatDuration3(start, end) {
103742
104005
 
103743
104006
  // src/features/background-agent/background-task-notification-template.ts
103744
104007
  function formatAttemptModel(attempt) {
103745
- if (attempt.providerID && attempt.modelID) {
103746
- return `${attempt.providerID}/${attempt.modelID}`;
104008
+ if (attempt.providerId && attempt.modelId) {
104009
+ return `${attempt.providerId}/${attempt.modelId}`;
103747
104010
  }
103748
- if (attempt.modelID) {
103749
- return attempt.modelID;
104011
+ if (attempt.modelId) {
104012
+ return attempt.modelId;
103750
104013
  }
103751
- if (attempt.providerID) {
103752
- return attempt.providerID;
104014
+ if (attempt.providerId) {
104015
+ return attempt.providerId;
103753
104016
  }
103754
104017
  return "unknown-model";
103755
104018
  }
@@ -103759,7 +104022,7 @@ function formatAttemptTimeline(task) {
103759
104022
  }
103760
104023
  const lines = task.attempts.map((attempt) => {
103761
104024
  const attemptLines = [
103762
- ` - Attempt ${attempt.attemptNumber} \u2014 ${attempt.status.toUpperCase()} \u2014 ${formatAttemptModel(attempt)} \u2014 ${attempt.sessionID ?? "unknown"}`
104025
+ ` - Attempt ${attempt.attemptNumber} \u2014 ${attempt.status.toUpperCase()} \u2014 ${formatAttemptModel(attempt)} \u2014 ${attempt.sessionId ?? "unknown"}`
103763
104026
  ];
103764
104027
  if (attempt.status !== "completed" && attempt.error) {
103765
104028
  attemptLines.push(` Error: ${attempt.error}`);
@@ -103862,23 +104125,23 @@ async function abortWithTimeout(client2, sessionID, timeoutMs = 1e4) {
103862
104125
  // src/features/background-agent/attempt-lifecycle.ts
103863
104126
  function toAttemptModel(model) {
103864
104127
  return {
103865
- providerID: model?.providerID,
103866
- modelID: model?.modelID,
104128
+ providerId: model?.providerID,
104129
+ modelId: model?.modelID,
103867
104130
  variant: model?.variant
103868
104131
  };
103869
104132
  }
103870
104133
  function toTaskModel(attempt) {
103871
- if (!attempt.providerID || !attempt.modelID) {
104134
+ if (!attempt.providerId || !attempt.modelId) {
103872
104135
  return;
103873
104136
  }
103874
104137
  return {
103875
- providerID: attempt.providerID,
103876
- modelID: attempt.modelID,
104138
+ providerID: attempt.providerId,
104139
+ modelID: attempt.modelId,
103877
104140
  ...attempt.variant ? { variant: attempt.variant } : {}
103878
104141
  };
103879
104142
  }
103880
104143
  function getAttemptIndex(task, attemptID) {
103881
- return task.attempts?.findIndex((attempt) => attempt.attemptID === attemptID) ?? -1;
104144
+ return task.attempts?.findIndex((attempt) => attempt.attemptId === attemptID) ?? -1;
103882
104145
  }
103883
104146
  function getAttempt(task, attemptID) {
103884
104147
  const index = getAttemptIndex(task, attemptID);
@@ -103899,9 +104162,9 @@ function ensureCurrentAttempt(task, model = task.model) {
103899
104162
  return existingAttempt;
103900
104163
  }
103901
104164
  const attempt = {
103902
- attemptID: `att_${crypto.randomUUID().slice(0, 8)}`,
104165
+ attemptId: `att_${crypto.randomUUID().slice(0, 8)}`,
103903
104166
  attemptNumber: (task.attempts?.length ?? 0) + 1,
103904
- sessionID: task.sessionID,
104167
+ sessionId: task.sessionId,
103905
104168
  ...toAttemptModel(model),
103906
104169
  status: task.status,
103907
104170
  error: task.error,
@@ -103909,7 +104172,7 @@ function ensureCurrentAttempt(task, model = task.model) {
103909
104172
  completedAt: task.completedAt
103910
104173
  };
103911
104174
  task.attempts = [...task.attempts ?? [], attempt];
103912
- task.currentAttemptID = attempt.attemptID;
104175
+ task.currentAttemptID = attempt.attemptId;
103913
104176
  return attempt;
103914
104177
  }
103915
104178
  function projectTaskFromCurrentAttempt(task) {
@@ -103918,7 +104181,7 @@ function projectTaskFromCurrentAttempt(task) {
103918
104181
  return task;
103919
104182
  }
103920
104183
  task.status = currentAttempt.status;
103921
- task.sessionID = currentAttempt.sessionID;
104184
+ task.sessionId = currentAttempt.sessionId;
103922
104185
  task.startedAt = currentAttempt.startedAt;
103923
104186
  task.completedAt = currentAttempt.completedAt;
103924
104187
  task.error = currentAttempt.error;
@@ -103927,15 +104190,15 @@ function projectTaskFromCurrentAttempt(task) {
103927
104190
  }
103928
104191
  function startAttempt(task, model) {
103929
104192
  const attempt = {
103930
- attemptID: `att_${crypto.randomUUID().slice(0, 8)}`,
104193
+ attemptId: `att_${crypto.randomUUID().slice(0, 8)}`,
103931
104194
  attemptNumber: (task.attempts?.length ?? 0) + 1,
103932
104195
  ...toAttemptModel(model),
103933
104196
  status: "pending"
103934
104197
  };
103935
104198
  task.attempts = [...task.attempts ?? [], attempt];
103936
- task.currentAttemptID = attempt.attemptID;
104199
+ task.currentAttemptID = attempt.attemptId;
103937
104200
  task.status = "pending";
103938
- task.sessionID = undefined;
104201
+ task.sessionId = undefined;
103939
104202
  task.startedAt = undefined;
103940
104203
  task.completedAt = undefined;
103941
104204
  task.error = undefined;
@@ -103951,13 +104214,13 @@ function bindAttemptSession(task, attemptID, sessionID, model) {
103951
104214
  if (!attempt || isTerminalStatus(attempt.status)) {
103952
104215
  return;
103953
104216
  }
103954
- attempt.sessionID = sessionID;
104217
+ attempt.sessionId = sessionID;
103955
104218
  attempt.status = "running";
103956
104219
  attempt.startedAt = new Date;
103957
104220
  attempt.completedAt = undefined;
103958
104221
  attempt.error = undefined;
103959
- attempt.providerID = model?.providerID ?? attempt.providerID;
103960
- attempt.modelID = model?.modelID ?? attempt.modelID;
104222
+ attempt.providerId = model?.providerID ?? attempt.providerId;
104223
+ attempt.modelId = model?.modelID ?? attempt.modelId;
103961
104224
  attempt.variant = model?.variant ?? attempt.variant;
103962
104225
  return getCurrentAttempt(projectTaskFromCurrentAttempt(task));
103963
104226
  }
@@ -103982,7 +104245,7 @@ function scheduleRetryAttempt(task, failedAttemptID, nextModel, error) {
103982
104245
  return startAttempt(task, nextModel);
103983
104246
  }
103984
104247
  function findAttemptBySession(task, sessionID) {
103985
- return task.attempts?.find((attempt) => attempt.sessionID === sessionID);
104248
+ return task.attempts?.find((attempt) => attempt.sessionId === sessionID);
103986
104249
  }
103987
104250
 
103988
104251
  // src/features/background-agent/fallback-retry-handler.ts
@@ -104061,7 +104324,7 @@ async function tryFallbackRetry(args) {
104061
104324
  clearTimeout(idleTimer);
104062
104325
  idleDeferralTimers.delete(task.id);
104063
104326
  }
104064
- const previousSessionID = task.sessionID;
104327
+ const previousSessionID = task.sessionId;
104065
104328
  const previousModel = task.model;
104066
104329
  const transformedModelId = transformModelForProvider(providerID, nextFallback.model);
104067
104330
  const nextModel = {
@@ -104070,7 +104333,7 @@ async function tryFallbackRetry(args) {
104070
104333
  variant: nextFallback.variant
104071
104334
  };
104072
104335
  task.attemptCount = selectedAttemptCount;
104073
- const failedAttemptID = ensureCurrentAttempt(task, previousModel).attemptID;
104336
+ const failedAttemptID = ensureCurrentAttempt(task, previousModel).attemptId;
104074
104337
  const nextAttempt = failedAttemptID ? scheduleRetryAttempt(task, failedAttemptID, nextModel, errorInfo.message) : undefined;
104075
104338
  if (!nextAttempt) {
104076
104339
  return false;
@@ -104096,8 +104359,8 @@ async function tryFallbackRetry(args) {
104096
104359
  description: task.description,
104097
104360
  prompt: task.prompt,
104098
104361
  agent: task.agent,
104099
- parentSessionID: task.parentSessionID,
104100
- parentMessageID: task.parentMessageID,
104362
+ parentSessionId: task.parentSessionId,
104363
+ parentMessageId: task.parentMessageId,
104101
104364
  parentModel: task.parentModel,
104102
104365
  parentAgent: task.parentAgent,
104103
104366
  parentTools: task.parentTools,
@@ -104109,18 +104372,24 @@ async function tryFallbackRetry(args) {
104109
104372
  if (previousSessionID) {
104110
104373
  await abortWithTimeout(client2, previousSessionID).catch(() => {});
104111
104374
  }
104112
- queue.push({ task, input: retryInput, attemptID: nextAttempt.attemptID });
104375
+ queue.push({ task, input: retryInput, attemptID: nextAttempt.attemptId });
104113
104376
  queuesByKey.set(key, queue);
104114
104377
  processKey(key);
104115
104378
  return true;
104116
104379
  }
104117
104380
 
104118
104381
  // src/features/background-agent/process-cleanup.ts
104119
- function scheduleForcedExit(cleanupResult, exitCode) {
104382
+ var _scheduleForcedExitEnabled = true;
104383
+ function scheduleForcedExit(cleanupResult, exitCode, exitAfterCleanup = false) {
104384
+ if (!_scheduleForcedExitEnabled)
104385
+ return;
104120
104386
  process.exitCode = exitCode;
104121
104387
  const exitTimeout = setTimeout(() => process.exit(), 6000);
104122
104388
  Promise.resolve(cleanupResult).finally(() => {
104123
104389
  clearTimeout(exitTimeout);
104390
+ if (exitAfterCleanup) {
104391
+ process.exit(exitCode);
104392
+ }
104124
104393
  });
104125
104394
  }
104126
104395
  function registerProcessSignal(signal, handler, exitAfter) {
@@ -104135,8 +104404,9 @@ function registerProcessSignal(signal, handler, exitAfter) {
104135
104404
  }
104136
104405
  function registerErrorEvent(signal, handler) {
104137
104406
  const listener = (error) => {
104407
+ process.off(signal, listener);
104138
104408
  log(`[background-agent] ${signal} received during shutdown cleanup:`, error);
104139
- scheduleForcedExit(handler(error), 1);
104409
+ scheduleForcedExit(handler(error), 1, true);
104140
104410
  };
104141
104411
  process.on(signal, listener);
104142
104412
  return listener;
@@ -104521,7 +104791,7 @@ async function checkAndInterruptStaleTasks(args) {
104521
104791
  if (task.status !== "running")
104522
104792
  continue;
104523
104793
  const startedAt = task.startedAt;
104524
- const sessionID = task.sessionID;
104794
+ const sessionID = task.sessionId;
104525
104795
  if (!startedAt || !sessionID)
104526
104796
  continue;
104527
104797
  const sessionStatus = sessionStatuses?.[sessionID]?.type;
@@ -104728,16 +104998,16 @@ function resolveMessagePartInfo(properties) {
104728
104998
  return properties;
104729
104999
  }
104730
105000
  function formatAttemptModelSummary(attempt) {
104731
- if (!attempt?.providerID || !attempt.modelID) {
105001
+ if (!attempt?.providerId || !attempt.modelId) {
104732
105002
  return;
104733
105003
  }
104734
- return `${attempt.providerID}/${attempt.modelID}`;
105004
+ return `${attempt.providerId}/${attempt.modelId}`;
104735
105005
  }
104736
105006
  function getPreviousAttempt(task, attemptID) {
104737
105007
  if (!attemptID || !task.attempts || task.attempts.length === 0) {
104738
105008
  return;
104739
105009
  }
104740
- const attemptIndex = task.attempts.findIndex((attempt) => attempt.attemptID === attemptID);
105010
+ const attemptIndex = task.attempts.findIndex((attempt) => attempt.attemptId === attemptID);
104741
105011
  if (attemptIndex <= 0) {
104742
105012
  return;
104743
105013
  }
@@ -104783,18 +105053,20 @@ class BackgroundManager {
104783
105053
  preStartDescendantReservations;
104784
105054
  enableParentSessionNotifications;
104785
105055
  modelFallbackControllerAccessor;
105056
+ loggedSessionStatusUnavailable = false;
104786
105057
  taskHistory = new TaskHistory;
104787
105058
  cachedCircuitBreakerSettings;
104788
- constructor(ctx, config2, options) {
105059
+ constructor(config2) {
105060
+ const { pluginContext, ...options } = config2;
104789
105061
  this.tasks = new Map;
104790
105062
  this.tasksByParentSession = new Map;
104791
105063
  this.notifications = new Map;
104792
105064
  this.pendingNotifications = new Map;
104793
105065
  this.pendingByParent = new Map;
104794
- this.client = ctx.client;
104795
- this.directory = ctx.directory;
104796
- this.concurrencyManager = new ConcurrencyManager(config2);
104797
- this.config = config2;
105066
+ this.client = pluginContext.client;
105067
+ this.directory = pluginContext.directory;
105068
+ this.concurrencyManager = new ConcurrencyManager(options.config);
105069
+ this.config = options.config;
104798
105070
  this.tmuxEnabled = options?.tmuxConfig?.enabled ?? false;
104799
105071
  this.onSubagentSessionCreated = options?.onSubagentSessionCreated;
104800
105072
  this.onShutdown = options?.onShutdown;
@@ -104869,30 +105141,30 @@ class BackgroundManager {
104869
105141
  if (!this.preStartDescendantReservations.delete(task.id)) {
104870
105142
  return;
104871
105143
  }
104872
- if (!task.rootSessionID) {
105144
+ if (!task.rootSessionId) {
104873
105145
  return;
104874
105146
  }
104875
- this.unregisterRootDescendant(task.rootSessionID);
105147
+ this.unregisterRootDescendant(task.rootSessionId);
104876
105148
  }
104877
105149
  addTask(task) {
104878
105150
  this.tasks.set(task.id, task);
104879
- if (!task.parentSessionID) {
105151
+ if (!task.parentSessionId) {
104880
105152
  return;
104881
105153
  }
104882
- const taskIDs = this.tasksByParentSession.get(task.parentSessionID) ?? new Set;
105154
+ const taskIDs = this.tasksByParentSession.get(task.parentSessionId) ?? new Set;
104883
105155
  taskIDs.add(task.id);
104884
- this.tasksByParentSession.set(task.parentSessionID, taskIDs);
105156
+ this.tasksByParentSession.set(task.parentSessionId, taskIDs);
104885
105157
  }
104886
105158
  removeTask(task) {
104887
105159
  this.tasks.delete(task.id);
104888
- this.removeTaskFromParentIndex(task.id, task.parentSessionID);
105160
+ this.removeTaskFromParentIndex(task.id, task.parentSessionId);
104889
105161
  }
104890
105162
  updateTaskParent(task, parentSessionID) {
104891
- if (task.parentSessionID === parentSessionID) {
105163
+ if (task.parentSessionId === parentSessionID) {
104892
105164
  return;
104893
105165
  }
104894
- this.removeTaskFromParentIndex(task.id, task.parentSessionID);
104895
- task.parentSessionID = parentSessionID;
105166
+ this.removeTaskFromParentIndex(task.id, task.parentSessionId);
105167
+ task.parentSessionId = parentSessionID;
104896
105168
  const taskIDs = this.tasksByParentSession.get(parentSessionID) ?? new Set;
104897
105169
  taskIDs.add(task.id);
104898
105170
  this.tasksByParentSession.set(parentSessionID, taskIDs);
@@ -104915,15 +105187,15 @@ class BackgroundManager {
104915
105187
  agent: input.agent,
104916
105188
  model: input.model,
104917
105189
  description: input.description,
104918
- parentSessionID: input.parentSessionID
105190
+ parentSessionID: input.parentSessionId
104919
105191
  });
104920
105192
  if (!input.agent || input.agent.trim() === "") {
104921
105193
  throw new Error("Agent parameter is required");
104922
105194
  }
104923
- const spawnReservation = await this.reserveSubagentSpawn(input.parentSessionID);
105195
+ const spawnReservation = await this.reserveSubagentSpawn(input.parentSessionId);
104924
105196
  try {
104925
105197
  log("[background-agent] spawn guard passed", {
104926
- parentSessionID: input.parentSessionID,
105198
+ parentSessionID: input.parentSessionId,
104927
105199
  rootSessionID: spawnReservation.spawnContext.rootSessionID,
104928
105200
  childDepth: spawnReservation.spawnContext.childDepth,
104929
105201
  descendantCount: spawnReservation.descendantCount
@@ -104932,13 +105204,13 @@ class BackgroundManager {
104932
105204
  id: `bg_${crypto.randomUUID().slice(0, 8)}`,
104933
105205
  status: "pending",
104934
105206
  queuedAt: new Date,
104935
- rootSessionID: spawnReservation.spawnContext.rootSessionID,
105207
+ rootSessionId: spawnReservation.spawnContext.rootSessionID,
104936
105208
  description: input.description,
104937
105209
  prompt: input.prompt,
104938
105210
  agent: input.agent,
104939
105211
  spawnDepth: spawnReservation.spawnContext.childDepth,
104940
- parentSessionID: input.parentSessionID,
104941
- parentMessageID: input.parentMessageID,
105212
+ parentSessionId: input.parentSessionId,
105213
+ parentMessageId: input.parentMessageId,
104942
105214
  parentModel: input.parentModel,
104943
105215
  parentAgent: input.parentAgent,
104944
105216
  parentTools: input.parentTools,
@@ -104949,15 +105221,15 @@ class BackgroundManager {
104949
105221
  };
104950
105222
  const firstAttempt = startAttempt(task, input.model);
104951
105223
  this.addTask(task);
104952
- this.taskHistory.record(input.parentSessionID, { id: task.id, agent: input.agent, description: input.description, status: "pending", category: input.category });
104953
- if (input.parentSessionID) {
104954
- const pending = this.pendingByParent.get(input.parentSessionID) ?? new Set;
105224
+ this.taskHistory.record(input.parentSessionId, { id: task.id, agent: input.agent, description: input.description, status: "pending", category: input.category });
105225
+ if (input.parentSessionId) {
105226
+ const pending = this.pendingByParent.get(input.parentSessionId) ?? new Set;
104955
105227
  pending.add(task.id);
104956
- this.pendingByParent.set(input.parentSessionID, pending);
105228
+ this.pendingByParent.set(input.parentSessionId, pending);
104957
105229
  }
104958
105230
  const key = this.getConcurrencyKeyFromInput(input);
104959
105231
  const queue = this.queuesByKey.get(key) ?? [];
104960
- queue.push({ task, input, attemptID: firstAttempt.attemptID });
105232
+ queue.push({ task, input, attemptID: firstAttempt.attemptId });
104961
105233
  this.queuesByKey.set(key, queue);
104962
105234
  log("[background-agent] Task queued:", { taskId: task.id, key, queueLength: queue.length });
104963
105235
  const toastManager = getTaskToastManager();
@@ -104973,6 +105245,7 @@ class BackgroundManager {
104973
105245
  }
104974
105246
  spawnReservation.commit();
104975
105247
  this.markPreStartDescendantReservation(task);
105248
+ this.updateBackgroundTaskMarker(input.parentSessionId);
104976
105249
  this.processKey(key);
104977
105250
  return { ...task };
104978
105251
  } catch (error) {
@@ -105017,11 +105290,12 @@ class BackgroundManager {
105017
105290
  this.concurrencyManager.release(key);
105018
105291
  }
105019
105292
  removeTaskToastTracking(item.task.id);
105020
- if (item.task.sessionID) {
105021
- await this.abortSessionWithLogging(item.task.sessionID, "startTask error cleanup");
105293
+ if (item.task.sessionId) {
105294
+ await this.abortSessionWithLogging(item.task.sessionId, "startTask error cleanup");
105022
105295
  }
105296
+ this.updateBackgroundTaskMarker(item.task.parentSessionId);
105023
105297
  this.markForNotification(item.task);
105024
- this.enqueueNotificationForParent(item.task.parentSessionID, () => this.notifyParentSession(item.task)).catch((err) => {
105298
+ this.enqueueNotificationForParent(item.task.parentSessionId, () => this.notifyParentSession(item.task)).catch((err) => {
105025
105299
  log("[background-agent] Failed to notify on startTask error:", err);
105026
105300
  });
105027
105301
  }
@@ -105032,7 +105306,7 @@ class BackgroundManager {
105032
105306
  }
105033
105307
  async startTask(item) {
105034
105308
  const { task, input } = item;
105035
- const attemptID = item.attemptID ?? ensureCurrentAttempt(task, input.model).attemptID;
105309
+ const attemptID = item.attemptID ?? ensureCurrentAttempt(task, input.model).attemptId;
105036
105310
  log("[background-agent] Starting task:", {
105037
105311
  taskId: task.id,
105038
105312
  agent: input.agent,
@@ -105040,7 +105314,7 @@ class BackgroundManager {
105040
105314
  });
105041
105315
  const concurrencyKey = this.getConcurrencyKeyFromInput(input);
105042
105316
  const parentSession = await this.client.session.get({
105043
- path: { id: input.parentSessionID },
105317
+ path: { id: input.parentSessionId },
105044
105318
  query: { directory: this.directory }
105045
105319
  }).catch((err) => {
105046
105320
  log(`[background-agent] Failed to get parent session: ${err}`);
@@ -105050,7 +105324,7 @@ class BackgroundManager {
105050
105324
  log(`[background-agent] Parent dir: ${parentSession?.data?.directory}, using: ${parentDirectory}`);
105051
105325
  const createResult = await this.client.session.create({
105052
105326
  body: {
105053
- parentID: input.parentSessionID,
105327
+ parentID: input.parentSessionId,
105054
105328
  title: `${input.description} (@${input.agent} subagent)`,
105055
105329
  ...input.sessionPermission ? { permission: input.sessionPermission } : {}
105056
105330
  },
@@ -105077,13 +105351,13 @@ class BackgroundManager {
105077
105351
  tmuxEnabled: this.tmuxEnabled,
105078
105352
  isInsideTmux: isInsideTmux(),
105079
105353
  sessionID,
105080
- parentID: input.parentSessionID
105354
+ parentID: input.parentSessionId
105081
105355
  });
105082
105356
  if (this.onSubagentSessionCreated && this.tmuxEnabled && isInsideTmux()) {
105083
105357
  log("[background-agent] Invoking tmux callback NOW", { sessionID });
105084
105358
  await this.onSubagentSessionCreated({
105085
105359
  sessionID,
105086
- parentID: input.parentSessionID,
105360
+ parentID: input.parentSessionId,
105087
105361
  title: input.description
105088
105362
  }).catch((err) => {
105089
105363
  log("[background-agent] Failed to spawn tmux pane:", err);
@@ -105096,8 +105370,8 @@ class BackgroundManager {
105096
105370
  if (this.tasks.get(task.id)?.status === "cancelled") {
105097
105371
  await this.abortSessionWithLogging(sessionID, "cancelled during tmux setup");
105098
105372
  subagentSessions.delete(sessionID);
105099
- if (task.rootSessionID) {
105100
- this.unregisterRootDescendant(task.rootSessionID);
105373
+ if (task.rootSessionId) {
105374
+ this.unregisterRootDescendant(task.rootSessionId);
105101
105375
  }
105102
105376
  this.concurrencyManager.release(concurrencyKey);
105103
105377
  return;
@@ -105106,8 +105380,8 @@ class BackgroundManager {
105106
105380
  if (!boundAttempt) {
105107
105381
  await this.abortSessionWithLogging(sessionID, "stale attempt binding cleanup");
105108
105382
  subagentSessions.delete(sessionID);
105109
- if (task.rootSessionID) {
105110
- this.unregisterRootDescendant(task.rootSessionID);
105383
+ if (task.rootSessionId) {
105384
+ this.unregisterRootDescendant(task.rootSessionId);
105111
105385
  }
105112
105386
  this.concurrencyManager.release(concurrencyKey);
105113
105387
  return;
@@ -105121,8 +105395,8 @@ class BackgroundManager {
105121
105395
  if (task.retryNotification) {
105122
105396
  const attemptNumber = boundAttempt.attemptNumber;
105123
105397
  const retrySessionUrl = buildLocalSessionUrl(parentDirectory, sessionID);
105124
- const previousAttempt = getPreviousAttempt(task, boundAttempt.attemptID);
105125
- const failedSessionID = previousAttempt?.sessionID ?? task.retryNotification.previousSessionID;
105398
+ const previousAttempt = getPreviousAttempt(task, boundAttempt.attemptId);
105399
+ const failedSessionID = previousAttempt?.sessionId ?? task.retryNotification.previousSessionID;
105126
105400
  const failedSessionLine = failedSessionID ? `
105127
105401
  - Failed session: \`${failedSessionID}\`` : "";
105128
105402
  const failedModel = formatAttemptModelSummary(previousAttempt) ?? task.retryNotification.failedModel;
@@ -105132,7 +105406,7 @@ class BackgroundManager {
105132
105406
  const failedErrorLine = failedError ? `
105133
105407
  - Error: ${failedError}` : "";
105134
105408
  const retryModel = formatAttemptModelSummary(boundAttempt) ?? task.retryNotification.nextModel;
105135
- this.queuePendingNotification(task.parentSessionID, `<system-reminder>
105409
+ this.queuePendingNotification(task.parentSessionId, `<system-reminder>
105136
105410
  [BACKGROUND TASK RETRY SESSION READY]
105137
105411
  **ID:** \`${task.id}\`
105138
105412
  **Description:** ${task.description}
@@ -105145,7 +105419,7 @@ The fallback retry session is now created and can be inspected directly.
105145
105419
  </system-reminder>`);
105146
105420
  task.retryNotification = undefined;
105147
105421
  }
105148
- this.taskHistory.record(input.parentSessionID, { id: task.id, sessionID, agent: input.agent, description: input.description, status: "running", category: input.category, startedAt: task.startedAt });
105422
+ this.taskHistory.record(input.parentSessionId, { id: task.id, sessionID, agent: input.agent, description: input.description, status: "running", category: input.category, startedAt: task.startedAt });
105149
105423
  this.startPolling();
105150
105424
  log("[background-agent] Launching task:", { taskId: task.id, sessionID, agent: input.agent });
105151
105425
  const toastManager = getTaskToastManager();
@@ -105235,8 +105509,8 @@ The fallback retry session is now created and can be inspected directly.
105235
105509
  existingTask.error = terminalError;
105236
105510
  existingTask.completedAt = new Date;
105237
105511
  }
105238
- if (existingTask.rootSessionID) {
105239
- this.unregisterRootDescendant(existingTask.rootSessionID);
105512
+ if (existingTask.rootSessionId) {
105513
+ this.unregisterRootDescendant(existingTask.rootSessionId);
105240
105514
  }
105241
105515
  if (existingTask.concurrencyKey) {
105242
105516
  this.concurrencyManager.release(existingTask.concurrencyKey);
@@ -105245,7 +105519,7 @@ The fallback retry session is now created and can be inspected directly.
105245
105519
  removeTaskToastTracking(existingTask.id);
105246
105520
  await this.abortSessionWithLogging(sessionID, "launch error cleanup");
105247
105521
  this.markForNotification(existingTask);
105248
- this.enqueueNotificationForParent(existingTask.parentSessionID, () => this.notifyParentSession(existingTask)).catch((err) => {
105522
+ this.enqueueNotificationForParent(existingTask.parentSessionId, () => this.notifyParentSession(existingTask)).catch((err) => {
105249
105523
  log("[background-agent] Failed to notify on error:", err);
105250
105524
  });
105251
105525
  }
@@ -105259,7 +105533,7 @@ The fallback retry session is now created and can be inspected directly.
105259
105533
  if (!taskIDs) {
105260
105534
  const result = [];
105261
105535
  for (const task of this.tasks.values()) {
105262
- if (task.parentSessionID === sessionID) {
105536
+ if (task.parentSessionId === sessionID) {
105263
105537
  result.push(task);
105264
105538
  }
105265
105539
  }
@@ -105274,13 +105548,22 @@ The fallback retry session is now created and can be inspected directly.
105274
105548
  }
105275
105549
  return tasks;
105276
105550
  }
105551
+ updateBackgroundTaskMarker(parentSessionID) {
105552
+ const tasks = this.getTasksByParentSession(parentSessionID);
105553
+ const activeTasks = tasks.filter((t) => t.status === "running" || t.status === "pending");
105554
+ if (activeTasks.length > 0) {
105555
+ setContinuationMarkerSource(this.directory, parentSessionID, "background-task", "active", `${activeTasks.length} background task(s) active`);
105556
+ } else {
105557
+ setContinuationMarkerSource(this.directory, parentSessionID, "background-task", "idle");
105558
+ }
105559
+ }
105277
105560
  getAllDescendantTasks(sessionID) {
105278
105561
  const result = [];
105279
105562
  const directChildren = this.getTasksByParentSession(sessionID);
105280
105563
  for (const child of directChildren) {
105281
105564
  result.push(child);
105282
- if (child.sessionID) {
105283
- const descendants = this.getAllDescendantTasks(child.sessionID);
105565
+ if (child.sessionId) {
105566
+ const descendants = this.getAllDescendantTasks(child.sessionId);
105284
105567
  result.push(...descendants);
105285
105568
  }
105286
105569
  }
@@ -105288,7 +105571,7 @@ The fallback retry session is now created and can be inspected directly.
105288
105571
  }
105289
105572
  findBySession(sessionID) {
105290
105573
  for (const task of this.tasks.values()) {
105291
- if (task.sessionID === sessionID) {
105574
+ if (task.sessionId === sessionID) {
105292
105575
  return task;
105293
105576
  }
105294
105577
  if (findAttemptBySession(task, sessionID)) {
@@ -105307,13 +105590,13 @@ The fallback retry session is now created and can be inspected directly.
105307
105590
  return {
105308
105591
  task,
105309
105592
  attemptID: undefined,
105310
- isCurrent: task.sessionID === sessionID
105593
+ isCurrent: task.sessionId === sessionID
105311
105594
  };
105312
105595
  }
105313
105596
  return {
105314
105597
  task,
105315
- attemptID: attempt.attemptID,
105316
- isCurrent: task.currentAttemptID === attempt.attemptID
105598
+ attemptID: attempt.attemptId,
105599
+ isCurrent: task.currentAttemptID === attempt.attemptId
105317
105600
  };
105318
105601
  }
105319
105602
  getConcurrencyKeyFromInput(input) {
@@ -105325,10 +105608,10 @@ The fallback retry session is now created and can be inspected directly.
105325
105608
  async trackTask(input) {
105326
105609
  const existingTask = this.tasks.get(input.taskId);
105327
105610
  if (existingTask) {
105328
- const parentChanged = input.parentSessionID !== existingTask.parentSessionID;
105611
+ const parentChanged = input.parentSessionId !== existingTask.parentSessionId;
105329
105612
  if (parentChanged) {
105330
105613
  this.cleanupPendingByParent(existingTask);
105331
- this.updateTaskParent(existingTask, input.parentSessionID);
105614
+ this.updateTaskParent(existingTask, input.parentSessionId);
105332
105615
  }
105333
105616
  if (input.parentAgent !== undefined) {
105334
105617
  existingTask.parentAgent = input.parentAgent;
@@ -105336,18 +105619,18 @@ The fallback retry session is now created and can be inspected directly.
105336
105619
  if (!existingTask.concurrencyGroup) {
105337
105620
  existingTask.concurrencyGroup = input.concurrencyKey ?? existingTask.agent;
105338
105621
  }
105339
- if (existingTask.sessionID) {
105340
- subagentSessions.add(existingTask.sessionID);
105622
+ if (existingTask.sessionId) {
105623
+ subagentSessions.add(existingTask.sessionId);
105341
105624
  }
105342
105625
  this.startPolling();
105343
105626
  if (existingTask.status === "pending" || existingTask.status === "running") {
105344
- const pending = this.pendingByParent.get(input.parentSessionID) ?? new Set;
105627
+ const pending = this.pendingByParent.get(input.parentSessionId) ?? new Set;
105345
105628
  pending.add(existingTask.id);
105346
- this.pendingByParent.set(input.parentSessionID, pending);
105629
+ this.pendingByParent.set(input.parentSessionId, pending);
105347
105630
  } else if (!parentChanged) {
105348
105631
  this.cleanupPendingByParent(existingTask);
105349
105632
  }
105350
- log("[background-agent] External task already registered:", { taskId: existingTask.id, sessionID: existingTask.sessionID, status: existingTask.status });
105633
+ log("[background-agent] External task already registered:", { taskId: existingTask.id, sessionID: existingTask.sessionId, status: existingTask.status });
105351
105634
  return existingTask;
105352
105635
  }
105353
105636
  const concurrencyGroup = input.concurrencyKey ?? input.agent ?? "task";
@@ -105356,9 +105639,9 @@ The fallback retry session is now created and can be inspected directly.
105356
105639
  }
105357
105640
  const task = {
105358
105641
  id: input.taskId,
105359
- sessionID: input.sessionID,
105360
- parentSessionID: input.parentSessionID,
105361
- parentMessageID: "",
105642
+ sessionId: input.sessionId,
105643
+ parentSessionId: input.parentSessionId,
105644
+ parentMessageId: "",
105362
105645
  description: input.description,
105363
105646
  prompt: "",
105364
105647
  agent: input.agent || "task",
@@ -105373,15 +105656,15 @@ The fallback retry session is now created and can be inspected directly.
105373
105656
  concurrencyGroup
105374
105657
  };
105375
105658
  this.addTask(task);
105376
- subagentSessions.add(input.sessionID);
105659
+ subagentSessions.add(input.sessionId);
105377
105660
  this.startPolling();
105378
- this.taskHistory.record(input.parentSessionID, { id: task.id, sessionID: input.sessionID, agent: input.agent || "task", description: input.description, status: "running", startedAt: task.startedAt });
105379
- if (input.parentSessionID) {
105380
- const pending = this.pendingByParent.get(input.parentSessionID) ?? new Set;
105661
+ this.taskHistory.record(input.parentSessionId, { id: task.id, sessionID: input.sessionId, agent: input.agent || "task", description: input.description, status: "running", startedAt: task.startedAt });
105662
+ if (input.parentSessionId) {
105663
+ const pending = this.pendingByParent.get(input.parentSessionId) ?? new Set;
105381
105664
  pending.add(task.id);
105382
- this.pendingByParent.set(input.parentSessionID, pending);
105665
+ this.pendingByParent.set(input.parentSessionId, pending);
105383
105666
  }
105384
- log("[background-agent] Registered external task:", { taskId: task.id, sessionID: input.sessionID });
105667
+ log("[background-agent] Registered external task:", { taskId: task.id, sessionID: input.sessionId });
105385
105668
  return task;
105386
105669
  }
105387
105670
  async resume(input) {
@@ -105389,13 +105672,13 @@ The fallback retry session is now created and can be inspected directly.
105389
105672
  if (!existingTask) {
105390
105673
  throw new Error(`Task not found for session: ${input.sessionId}`);
105391
105674
  }
105392
- if (!existingTask.sessionID) {
105675
+ if (!existingTask.sessionId) {
105393
105676
  throw new Error(`Task has no sessionID: ${existingTask.id}`);
105394
105677
  }
105395
105678
  if (existingTask.status === "running") {
105396
105679
  log("[background-agent] Resume skipped - task already running:", {
105397
105680
  taskId: existingTask.id,
105398
- sessionID: existingTask.sessionID
105681
+ sessionID: existingTask.sessionId
105399
105682
  });
105400
105683
  return existingTask;
105401
105684
  }
@@ -105411,8 +105694,8 @@ The fallback retry session is now created and can be inspected directly.
105411
105694
  existingTask.status = "running";
105412
105695
  existingTask.completedAt = undefined;
105413
105696
  existingTask.error = undefined;
105414
- this.updateTaskParent(existingTask, input.parentSessionID);
105415
- existingTask.parentMessageID = input.parentMessageID;
105697
+ this.updateTaskParent(existingTask, input.parentSessionId);
105698
+ existingTask.parentMessageId = input.parentMessageId;
105416
105699
  existingTask.parentModel = input.parentModel;
105417
105700
  existingTask.parentAgent = input.parentAgent;
105418
105701
  if (input.parentTools) {
@@ -105426,13 +105709,13 @@ The fallback retry session is now created and can be inspected directly.
105426
105709
  lastUpdate: new Date
105427
105710
  };
105428
105711
  this.startPolling();
105429
- if (existingTask.sessionID) {
105430
- subagentSessions.add(existingTask.sessionID);
105712
+ if (existingTask.sessionId) {
105713
+ subagentSessions.add(existingTask.sessionId);
105431
105714
  }
105432
- if (input.parentSessionID) {
105433
- const pending = this.pendingByParent.get(input.parentSessionID) ?? new Set;
105715
+ if (input.parentSessionId) {
105716
+ const pending = this.pendingByParent.get(input.parentSessionId) ?? new Set;
105434
105717
  pending.add(existingTask.id);
105435
- this.pendingByParent.set(input.parentSessionID, pending);
105718
+ this.pendingByParent.set(input.parentSessionId, pending);
105436
105719
  }
105437
105720
  const toastManager = getTaskToastManager();
105438
105721
  if (toastManager) {
@@ -105443,9 +105726,9 @@ The fallback retry session is now created and can be inspected directly.
105443
105726
  isBackground: true
105444
105727
  });
105445
105728
  }
105446
- log("[background-agent] Resuming task:", { taskId: existingTask.id, sessionID: existingTask.sessionID });
105729
+ log("[background-agent] Resuming task:", { taskId: existingTask.id, sessionID: existingTask.sessionId });
105447
105730
  log("[background-agent] Resuming task - calling prompt (fire-and-forget) with:", {
105448
- sessionID: existingTask.sessionID,
105731
+ sessionID: existingTask.sessionId,
105449
105732
  agent: existingTask.agent,
105450
105733
  model: existingTask.model,
105451
105734
  promptLength: input.prompt.length
@@ -105456,10 +105739,10 @@ The fallback retry session is now created and can be inspected directly.
105456
105739
  } : undefined;
105457
105740
  const resumeVariant = existingTask.model?.variant;
105458
105741
  if (existingTask.model) {
105459
- applySessionPromptParams(existingTask.sessionID, existingTask.model);
105742
+ applySessionPromptParams(existingTask.sessionId, existingTask.model);
105460
105743
  }
105461
105744
  this.client.session.promptAsync({
105462
- path: { id: existingTask.sessionID },
105745
+ path: { id: existingTask.sessionId },
105463
105746
  body: {
105464
105747
  agent: existingTask.agent,
105465
105748
  ...resumeModel ? { model: resumeModel } : {},
@@ -105471,7 +105754,7 @@ The fallback retry session is now created and can be inspected directly.
105471
105754
  question: false,
105472
105755
  ...getAgentToolRestrictions(existingTask.agent)
105473
105756
  };
105474
- setSessionTools(existingTask.sessionID, tools);
105757
+ setSessionTools(existingTask.sessionId, tools);
105475
105758
  return tools;
105476
105759
  })(),
105477
105760
  parts: [createInternalAgentTextPart(input.prompt)]
@@ -105489,19 +105772,19 @@ The fallback retry session is now created and can be inspected directly.
105489
105772
  const errorMessage = errorInfo.message ?? (error instanceof Error ? error.message : String(error));
105490
105773
  existingTask.error = errorMessage;
105491
105774
  existingTask.completedAt = new Date;
105492
- if (existingTask.rootSessionID) {
105493
- this.unregisterRootDescendant(existingTask.rootSessionID);
105775
+ if (existingTask.rootSessionId) {
105776
+ this.unregisterRootDescendant(existingTask.rootSessionId);
105494
105777
  }
105495
105778
  if (existingTask.concurrencyKey) {
105496
105779
  this.concurrencyManager.release(existingTask.concurrencyKey);
105497
105780
  existingTask.concurrencyKey = undefined;
105498
105781
  }
105499
105782
  removeTaskToastTracking(existingTask.id);
105500
- if (existingTask.sessionID) {
105501
- await this.abortSessionWithLogging(existingTask.sessionID, "resume error cleanup");
105783
+ if (existingTask.sessionId) {
105784
+ await this.abortSessionWithLogging(existingTask.sessionId, "resume error cleanup");
105502
105785
  }
105503
105786
  this.markForNotification(existingTask);
105504
- this.enqueueNotificationForParent(existingTask.parentSessionID, () => this.notifyParentSession(existingTask)).catch((err) => {
105787
+ this.enqueueNotificationForParent(existingTask.parentSessionId, () => this.notifyParentSession(existingTask)).catch((err) => {
105505
105788
  log("[background-agent] Failed to notify on resume error:", err);
105506
105789
  });
105507
105790
  });
@@ -105743,23 +106026,23 @@ The fallback retry session is now created and can be inspected directly.
105743
106026
  const parentSessionsToClear = new Set;
105744
106027
  const deletedSessionIDs = new Set([sessionID]);
105745
106028
  for (const task of tasksToCancel.values()) {
105746
- if (task.sessionID) {
105747
- deletedSessionIDs.add(task.sessionID);
106029
+ if (task.sessionId) {
106030
+ deletedSessionIDs.add(task.sessionId);
105748
106031
  }
105749
106032
  }
105750
106033
  for (const task of tasksToCancel.values()) {
105751
- parentSessionsToClear.add(task.parentSessionID);
106034
+ parentSessionsToClear.add(task.parentSessionId);
105752
106035
  if (task.status === "running" || task.status === "pending") {
105753
106036
  this.cancelTask(task.id, {
105754
106037
  source: "session.deleted",
105755
106038
  reason: "Session deleted"
105756
106039
  }).then(() => {
105757
- if (deletedSessionIDs.has(task.parentSessionID)) {
105758
- this.pendingNotifications.delete(task.parentSessionID);
106040
+ if (deletedSessionIDs.has(task.parentSessionId)) {
106041
+ this.pendingNotifications.delete(task.parentSessionId);
105759
106042
  }
105760
106043
  }).catch((err) => {
105761
- if (deletedSessionIDs.has(task.parentSessionID)) {
105762
- this.pendingNotifications.delete(task.parentSessionID);
106044
+ if (deletedSessionIDs.has(task.parentSessionId)) {
106045
+ this.pendingNotifications.delete(task.parentSessionId);
105763
106046
  }
105764
106047
  log("[background-agent] Failed to cancel task on session.deleted:", { taskId: task.id, error: err });
105765
106048
  });
@@ -105794,8 +106077,8 @@ The fallback retry session is now created and can be inspected directly.
105794
106077
  }
105795
106078
  async handleSessionErrorEvent(args) {
105796
106079
  const { task, errorInfo, errorMessage, errorName } = args;
105797
- if (!task.fallbackChain && task.sessionID) {
105798
- const sessionFallbackChain = this.modelFallbackControllerAccessor?.getSessionFallbackChain(task.sessionID);
106080
+ if (!task.fallbackChain && task.sessionId) {
106081
+ const sessionFallbackChain = this.modelFallbackControllerAccessor?.getSessionFallbackChain(task.sessionId);
105799
106082
  if (sessionFallbackChain?.length) {
105800
106083
  task.fallbackChain = sessionFallbackChain;
105801
106084
  }
@@ -105826,10 +106109,10 @@ The fallback retry session is now created and can be inspected directly.
105826
106109
  task.error = errorMsg;
105827
106110
  task.completedAt = new Date;
105828
106111
  }
105829
- if (task.rootSessionID) {
105830
- this.unregisterRootDescendant(task.rootSessionID);
106112
+ if (task.rootSessionId) {
106113
+ this.unregisterRootDescendant(task.rootSessionId);
105831
106114
  }
105832
- this.taskHistory.record(task.parentSessionID, { id: task.id, sessionID: task.sessionID, agent: task.agent, description: task.description, status: "error", category: task.category, startedAt: task.startedAt, completedAt: task.completedAt });
106115
+ this.taskHistory.record(task.parentSessionId, { id: task.id, sessionID: task.sessionId, agent: task.agent, description: task.description, status: "error", category: task.category, startedAt: task.startedAt, completedAt: task.completedAt });
105833
106116
  if (task.concurrencyKey) {
105834
106117
  this.concurrencyManager.release(task.concurrencyKey);
105835
106118
  task.concurrencyKey = undefined;
@@ -105851,16 +106134,19 @@ The fallback retry session is now created and can be inspected directly.
105851
106134
  toastManager.removeTask(task.id);
105852
106135
  }
105853
106136
  this.scheduleTaskRemoval(task.id);
105854
- if (task.sessionID) {
105855
- SessionCategoryRegistry.remove(task.sessionID);
106137
+ if (task.sessionId) {
106138
+ SessionCategoryRegistry.remove(task.sessionId);
106139
+ }
106140
+ if (task.parentSessionId) {
106141
+ this.updateBackgroundTaskMarker(task.parentSessionId);
105856
106142
  }
105857
106143
  this.markForNotification(task);
105858
- this.enqueueNotificationForParent(task.parentSessionID, () => this.notifyParentSession(task)).catch((err) => {
106144
+ this.enqueueNotificationForParent(task.parentSessionId, () => this.notifyParentSession(task)).catch((err) => {
105859
106145
  log("[background-agent] Error in notifyParentSession for errored task:", { taskId: task.id, error: err });
105860
106146
  });
105861
106147
  }
105862
106148
  tryFallbackRetry(task, errorInfo, source) {
105863
- const previousSessionID = task.sessionID;
106149
+ const previousSessionID = task.sessionId;
105864
106150
  const result = tryFallbackRetry({
105865
106151
  task,
105866
106152
  errorInfo,
@@ -105872,17 +106158,17 @@ The fallback retry session is now created and can be inspected directly.
105872
106158
  processKey: (key) => this.processKey(key),
105873
106159
  onRetrying: ({ task: task2, source: source2 }) => {
105874
106160
  const currentAttempt = getCurrentAttempt(task2);
105875
- const previousAttempt = getPreviousAttempt(task2, currentAttempt?.attemptID);
106161
+ const previousAttempt = getPreviousAttempt(task2, currentAttempt?.attemptId);
105876
106162
  const sourceText = source2 ? ` via ${source2}` : "";
105877
- const failedSessionLine = previousAttempt?.sessionID ? `
105878
- - Failed session: \`${previousAttempt.sessionID}\`` : "";
106163
+ const failedSessionLine = previousAttempt?.sessionId ? `
106164
+ - Failed session: \`${previousAttempt.sessionId}\`` : "";
105879
106165
  const failedModel = formatAttemptModelSummary(previousAttempt);
105880
106166
  const failedModelLine = failedModel ? `
105881
106167
  - Failed model: \`${failedModel}\`` : "";
105882
106168
  const failedErrorLine = previousAttempt?.error ? `
105883
106169
  - Error: ${previousAttempt.error}` : "";
105884
106170
  const nextModel = formatAttemptModelSummary(currentAttempt);
105885
- this.queuePendingNotification(task2.parentSessionID, `<system-reminder>
106171
+ this.queuePendingNotification(task2.parentSessionId, `<system-reminder>
105886
106172
  [BACKGROUND TASK RETRYING]
105887
106173
  **ID:** \`${task2.id}\`
105888
106174
  **Description:** ${task2.description}${sourceText}${failedSessionLine}${failedModelLine}${failedErrorLine}${nextModel ? `
@@ -105902,9 +106188,9 @@ The task was re-queued on a fallback model after a retryable failure.
105902
106188
  });
105903
106189
  }
105904
106190
  markForNotification(task) {
105905
- const queue = this.notifications.get(task.parentSessionID) ?? [];
106191
+ const queue = this.notifications.get(task.parentSessionId) ?? [];
105906
106192
  queue.push(task);
105907
- this.notifications.set(task.parentSessionID, queue);
106193
+ this.notifications.set(task.parentSessionId, queue);
105908
106194
  }
105909
106195
  getPendingNotifications(sessionID) {
105910
106196
  return this.notifications.get(sessionID) ?? [];
@@ -105982,13 +106268,13 @@ ${originalText}`;
105982
106268
  }
105983
106269
  }
105984
106270
  cleanupPendingByParent(task) {
105985
- if (!task.parentSessionID)
106271
+ if (!task.parentSessionId)
105986
106272
  return;
105987
- const pending = this.pendingByParent.get(task.parentSessionID);
106273
+ const pending = this.pendingByParent.get(task.parentSessionId);
105988
106274
  if (pending) {
105989
106275
  pending.delete(task.id);
105990
106276
  if (pending.size === 0) {
105991
- this.pendingByParent.delete(task.parentSessionID);
106277
+ this.pendingByParent.delete(task.parentSessionId);
105992
106278
  }
105993
106279
  }
105994
106280
  }
@@ -106011,8 +106297,8 @@ ${originalText}`;
106011
106297
  const task = this.tasks.get(taskId);
106012
106298
  if (!task)
106013
106299
  return;
106014
- if (task.parentSessionID) {
106015
- const siblings = this.getTasksByParentSession(task.parentSessionID);
106300
+ if (task.parentSessionId) {
106301
+ const siblings = this.getTasksByParentSession(task.parentSessionId);
106016
106302
  const runningOrPendingSiblings = siblings.filter((sibling) => sibling.id !== taskId && (sibling.status === "running" || sibling.status === "pending"));
106017
106303
  const completedAtTimestamp = task.completedAt?.getTime();
106018
106304
  const reachedTaskTtl = completedAtTimestamp !== undefined && Date.now() - completedAtTimestamp >= TASK_TTL_MS;
@@ -106023,10 +106309,10 @@ ${originalText}`;
106023
106309
  }
106024
106310
  this.clearNotificationsForTask(taskId);
106025
106311
  this.removeTask(task);
106026
- this.clearTaskHistoryWhenParentTasksGone(task.parentSessionID);
106027
- if (task.sessionID) {
106028
- subagentSessions.delete(task.sessionID);
106029
- SessionCategoryRegistry.remove(task.sessionID);
106312
+ this.clearTaskHistoryWhenParentTasksGone(task.parentSessionId);
106313
+ if (task.sessionId) {
106314
+ subagentSessions.delete(task.sessionId);
106315
+ SessionCategoryRegistry.remove(task.sessionId);
106030
106316
  }
106031
106317
  log("[background-agent] Removed completed task from memory:", taskId);
106032
106318
  }, TASK_CLEANUP_DELAY_MS);
@@ -106065,10 +106351,10 @@ ${originalText}`;
106065
106351
  task.error = reason;
106066
106352
  }
106067
106353
  }
106068
- if (wasRunning && task.rootSessionID) {
106069
- this.unregisterRootDescendant(task.rootSessionID);
106354
+ if (wasRunning && task.rootSessionId) {
106355
+ this.unregisterRootDescendant(task.rootSessionId);
106070
106356
  }
106071
- this.taskHistory.record(task.parentSessionID, { id: task.id, sessionID: task.sessionID, agent: task.agent, description: task.description, status: "cancelled", category: task.category, startedAt: task.startedAt, completedAt: task.completedAt });
106357
+ this.taskHistory.record(task.parentSessionId, { id: task.id, sessionID: task.sessionId, agent: task.agent, description: task.description, status: "cancelled", category: task.category, startedAt: task.startedAt, completedAt: task.completedAt });
106072
106358
  if (task.concurrencyKey) {
106073
106359
  this.concurrencyManager.release(task.concurrencyKey);
106074
106360
  task.concurrencyKey = undefined;
@@ -106083,11 +106369,14 @@ ${originalText}`;
106083
106369
  clearTimeout(idleTimer);
106084
106370
  this.idleDeferralTimers.delete(task.id);
106085
106371
  }
106086
- if (abortSession && task.sessionID) {
106087
- await this.abortSessionWithLogging(task.sessionID, `task cancellation (${source})`);
106088
- SessionCategoryRegistry.remove(task.sessionID);
106372
+ if (abortSession && task.sessionId) {
106373
+ await this.abortSessionWithLogging(task.sessionId, `task cancellation (${source})`);
106374
+ SessionCategoryRegistry.remove(task.sessionId);
106089
106375
  }
106090
106376
  removeTaskToastTracking(task.id);
106377
+ if (task.parentSessionId) {
106378
+ this.updateBackgroundTaskMarker(task.parentSessionId);
106379
+ }
106091
106380
  if (options?.skipNotification) {
106092
106381
  this.cleanupPendingByParent(task);
106093
106382
  this.scheduleTaskRemoval(task.id);
@@ -106096,7 +106385,7 @@ ${originalText}`;
106096
106385
  }
106097
106386
  this.markForNotification(task);
106098
106387
  try {
106099
- await this.enqueueNotificationForParent(task.parentSessionID, () => this.notifyParentSession(task));
106388
+ await this.enqueueNotificationForParent(task.parentSessionId, () => this.notifyParentSession(task));
106100
106389
  log(`[background-agent] Task cancelled via ${source}:`, task.id);
106101
106390
  } catch (err) {
106102
106391
  log("[background-agent] Error in notifyParentSession for cancelled task:", { taskId: task.id, error: err });
@@ -106148,9 +106437,9 @@ ${originalText}`;
106148
106437
  task.status = "completed";
106149
106438
  task.completedAt = new Date;
106150
106439
  }
106151
- this.taskHistory.record(task.parentSessionID, { id: task.id, sessionID: task.sessionID, agent: task.agent, description: task.description, status: "completed", category: task.category, startedAt: task.startedAt, completedAt: task.completedAt });
106152
- if (task.rootSessionID) {
106153
- this.unregisterRootDescendant(task.rootSessionID);
106440
+ this.taskHistory.record(task.parentSessionId, { id: task.id, sessionID: task.sessionId, agent: task.agent, description: task.description, status: "completed", category: task.category, startedAt: task.startedAt, completedAt: task.completedAt });
106441
+ if (task.rootSessionId) {
106442
+ this.unregisterRootDescendant(task.rootSessionId);
106154
106443
  }
106155
106444
  removeTaskToastTracking(task.id);
106156
106445
  if (task.concurrencyKey) {
@@ -106163,12 +106452,15 @@ ${originalText}`;
106163
106452
  clearTimeout(idleTimer);
106164
106453
  this.idleDeferralTimers.delete(task.id);
106165
106454
  }
106166
- if (task.sessionID) {
106167
- await this.abortSessionWithLogging(task.sessionID, `task completion (${source})`);
106168
- SessionCategoryRegistry.remove(task.sessionID);
106455
+ if (task.sessionId) {
106456
+ await this.abortSessionWithLogging(task.sessionId, `task completion (${source})`);
106457
+ SessionCategoryRegistry.remove(task.sessionId);
106458
+ }
106459
+ if (task.parentSessionId) {
106460
+ this.updateBackgroundTaskMarker(task.parentSessionId);
106169
106461
  }
106170
106462
  try {
106171
- await this.enqueueNotificationForParent(task.parentSessionID, () => this.notifyParentSession(task));
106463
+ await this.enqueueNotificationForParent(task.parentSessionId, () => this.notifyParentSession(task));
106172
106464
  log(`[background-agent] Task completed via ${source}:`, task.id);
106173
106465
  } catch (err) {
106174
106466
  log("[background-agent] Error in notifyParentSession:", { taskId: task.id, error: err });
@@ -106186,17 +106478,17 @@ ${originalText}`;
106186
106478
  duration
106187
106479
  });
106188
106480
  }
106189
- if (!this.completedTaskSummaries.has(task.parentSessionID)) {
106190
- this.completedTaskSummaries.set(task.parentSessionID, []);
106481
+ if (!this.completedTaskSummaries.has(task.parentSessionId)) {
106482
+ this.completedTaskSummaries.set(task.parentSessionId, []);
106191
106483
  }
106192
- this.completedTaskSummaries.get(task.parentSessionID).push({
106484
+ this.completedTaskSummaries.get(task.parentSessionId).push({
106193
106485
  id: task.id,
106194
106486
  description: task.description,
106195
106487
  status: task.status,
106196
106488
  error: task.error,
106197
106489
  attempts: cloneAttempts(task)
106198
106490
  });
106199
- const pendingSet = this.pendingByParent.get(task.parentSessionID);
106491
+ const pendingSet = this.pendingByParent.get(task.parentSessionId);
106200
106492
  let allComplete = false;
106201
106493
  let remainingCount = 0;
106202
106494
  if (pendingSet) {
@@ -106204,15 +106496,15 @@ ${originalText}`;
106204
106496
  remainingCount = pendingSet.size;
106205
106497
  allComplete = remainingCount === 0;
106206
106498
  if (allComplete) {
106207
- this.pendingByParent.delete(task.parentSessionID);
106499
+ this.pendingByParent.delete(task.parentSessionId);
106208
106500
  }
106209
106501
  } else {
106210
- remainingCount = Array.from(this.tasks.values()).filter((t) => t.parentSessionID === task.parentSessionID && t.id !== task.id && (t.status === "running" || t.status === "pending")).length;
106502
+ remainingCount = Array.from(this.tasks.values()).filter((t) => t.parentSessionId === task.parentSessionId && t.id !== task.id && (t.status === "running" || t.status === "pending")).length;
106211
106503
  allComplete = remainingCount === 0;
106212
106504
  }
106213
- const completedTasks = allComplete ? this.completedTaskSummaries.get(task.parentSessionID) ?? [{ id: task.id, description: task.description, status: task.status, error: task.error, attempts: cloneAttempts(task) }] : [];
106505
+ const completedTasks = allComplete ? this.completedTaskSummaries.get(task.parentSessionId) ?? [{ id: task.id, description: task.description, status: task.status, error: task.error, attempts: cloneAttempts(task) }] : [];
106214
106506
  if (allComplete) {
106215
- this.completedTaskSummaries.delete(task.parentSessionID);
106507
+ this.completedTaskSummaries.delete(task.parentSessionId);
106216
106508
  }
106217
106509
  const statusText = task.status === "completed" ? "COMPLETED" : task.status === "interrupt" ? "INTERRUPTED" : task.status === "error" ? "ERROR" : "CANCELLED";
106218
106510
  const notification2 = buildBackgroundTaskNotificationText({
@@ -106229,9 +106521,9 @@ ${originalText}`;
106229
106521
  let promptContext = null;
106230
106522
  if (this.enableParentSessionNotifications) {
106231
106523
  try {
106232
- const messagesResp = await this.client.session.messages({ path: { id: task.parentSessionID } });
106524
+ const messagesResp = await this.client.session.messages({ path: { id: task.parentSessionId } });
106233
106525
  const messages = normalizeSDKResponse(messagesResp, []);
106234
- promptContext = resolvePromptContextFromSessionMessages(messages, task.parentSessionID);
106526
+ promptContext = resolvePromptContextFromSessionMessages(messages, task.parentSessionId);
106235
106527
  const normalizedTools = isRecord15(promptContext?.tools) ? normalizePromptTools(promptContext.tools) : undefined;
106236
106528
  if (promptContext?.agent || promptContext?.model || normalizedTools) {
106237
106529
  agent = promptContext?.agent ?? task.parentAgent;
@@ -106242,16 +106534,16 @@ ${originalText}`;
106242
106534
  if (isAbortedSessionError(error)) {
106243
106535
  log("[background-agent] Parent session aborted while loading messages; using messageDir fallback:", {
106244
106536
  taskId: task.id,
106245
- parentSessionID: task.parentSessionID
106537
+ parentSessionID: task.parentSessionId
106246
106538
  });
106247
106539
  }
106248
- const messageDir = join95(MESSAGE_STORAGE, task.parentSessionID);
106249
- const currentMessage = messageDir ? findNearestMessageExcludingCompaction(messageDir, task.parentSessionID) : null;
106540
+ const messageDir = join95(MESSAGE_STORAGE, task.parentSessionId);
106541
+ const currentMessage = messageDir ? findNearestMessageExcludingCompaction(messageDir, task.parentSessionId) : null;
106250
106542
  agent = currentMessage?.agent ?? task.parentAgent;
106251
106543
  model = currentMessage?.model?.providerID && currentMessage?.model?.modelID ? { providerID: currentMessage.model.providerID, modelID: currentMessage.model.modelID } : undefined;
106252
106544
  tools = normalizePromptTools(currentMessage?.tools) ?? tools;
106253
106545
  }
106254
- const resolvedTools = resolveInheritedPromptTools(task.parentSessionID, tools);
106546
+ const resolvedTools = resolveInheritedPromptTools(task.parentSessionId, tools);
106255
106547
  log("[background-agent] notifyParentSession context:", {
106256
106548
  taskId: task.id,
106257
106549
  resolvedAgent: agent,
@@ -106262,7 +106554,7 @@ ${originalText}`;
106262
106554
  const variant = promptContext?.model?.variant;
106263
106555
  try {
106264
106556
  await this.client.session.promptAsync({
106265
- path: { id: task.parentSessionID },
106557
+ path: { id: task.parentSessionId },
106266
106558
  body: {
106267
106559
  noReply: !shouldReply,
106268
106560
  ...agent !== undefined ? { agent } : {},
@@ -106282,9 +106574,9 @@ ${originalText}`;
106282
106574
  if (isAbortedSessionError(error)) {
106283
106575
  log("[background-agent] Parent session aborted while sending notification; continuing cleanup:", {
106284
106576
  taskId: task.id,
106285
- parentSessionID: task.parentSessionID
106577
+ parentSessionID: task.parentSessionId
106286
106578
  });
106287
- this.queuePendingNotification(task.parentSessionID, notification2);
106579
+ this.queuePendingNotification(task.parentSessionId, notification2);
106288
106580
  } else {
106289
106581
  log("[background-agent] Failed to send notification:", error);
106290
106582
  }
@@ -106292,7 +106584,7 @@ ${originalText}`;
106292
106584
  } else {
106293
106585
  log("[background-agent] Parent session notifications disabled, skipping prompt injection:", {
106294
106586
  taskId: task.id,
106295
- parentSessionID: task.parentSessionID
106587
+ parentSessionID: task.parentSessionId
106296
106588
  });
106297
106589
  }
106298
106590
  if (task.status !== "running" && task.status !== "pending") {
@@ -106317,10 +106609,10 @@ ${originalText}`;
106317
106609
  task.status = "error";
106318
106610
  task.error = errorMessage;
106319
106611
  task.completedAt = new Date;
106320
- if (!wasPending && task.rootSessionID) {
106321
- this.unregisterRootDescendant(task.rootSessionID);
106612
+ if (!wasPending && task.rootSessionId) {
106613
+ this.unregisterRootDescendant(task.rootSessionId);
106322
106614
  }
106323
- this.taskHistory.record(task.parentSessionID, { id: task.id, sessionID: task.sessionID, agent: task.agent, description: task.description, status: "error", category: task.category, startedAt: task.startedAt, completedAt: task.completedAt });
106615
+ this.taskHistory.record(task.parentSessionId, { id: task.id, sessionID: task.sessionId, agent: task.agent, description: task.description, status: "error", category: task.category, startedAt: task.startedAt, completedAt: task.completedAt });
106324
106616
  if (task.concurrencyKey) {
106325
106617
  this.concurrencyManager.release(task.concurrencyKey);
106326
106618
  task.concurrencyKey = undefined;
@@ -106350,21 +106642,24 @@ ${originalText}`;
106350
106642
  }
106351
106643
  }
106352
106644
  this.cleanupPendingByParent(task);
106645
+ if (task.parentSessionId) {
106646
+ this.updateBackgroundTaskMarker(task.parentSessionId);
106647
+ }
106353
106648
  this.markForNotification(task);
106354
- this.enqueueNotificationForParent(task.parentSessionID, () => this.notifyParentSession(task)).catch((err) => {
106649
+ this.enqueueNotificationForParent(task.parentSessionId, () => this.notifyParentSession(task)).catch((err) => {
106355
106650
  log("[background-agent] Error in notifyParentSession for stale-pruned task:", { taskId: task.id, error: err });
106356
106651
  });
106357
106652
  }
106358
106653
  });
106359
106654
  }
106360
- async checkAndInterruptStaleTasks(allStatuses = {}) {
106655
+ async checkAndInterruptStaleTasks(allStatuses) {
106361
106656
  await checkAndInterruptStaleTasks({
106362
106657
  tasks: this.tasks.values(),
106363
106658
  client: this.client,
106364
106659
  directory: this.directory,
106365
106660
  config: this.config,
106366
106661
  concurrencyManager: this.concurrencyManager,
106367
- notifyParentSession: (task) => this.enqueueNotificationForParent(task.parentSessionID, () => this.notifyParentSession(task)),
106662
+ notifyParentSession: (task) => this.enqueueNotificationForParent(task.parentSessionId, () => this.notifyParentSession(task)),
106368
106663
  sessionStatuses: allStatuses
106369
106664
  });
106370
106665
  }
@@ -106379,10 +106674,10 @@ ${originalText}`;
106379
106674
  task.error = errorMessage;
106380
106675
  task.completedAt = new Date;
106381
106676
  }
106382
- if (task.rootSessionID) {
106383
- this.unregisterRootDescendant(task.rootSessionID);
106677
+ if (task.rootSessionId) {
106678
+ this.unregisterRootDescendant(task.rootSessionId);
106384
106679
  }
106385
- this.taskHistory.record(task.parentSessionID, { id: task.id, sessionID: task.sessionID, agent: task.agent, description: task.description, status: "error", category: task.category, startedAt: task.startedAt, completedAt: task.completedAt });
106680
+ this.taskHistory.record(task.parentSessionId, { id: task.id, sessionID: task.sessionId, agent: task.agent, description: task.description, status: "error", category: task.category, startedAt: task.startedAt, completedAt: task.completedAt });
106386
106681
  if (task.concurrencyKey) {
106387
106682
  this.concurrencyManager.release(task.concurrencyKey);
106388
106683
  task.concurrencyKey = undefined;
@@ -106401,11 +106696,14 @@ ${originalText}`;
106401
106696
  this.clearNotificationsForTask(task.id);
106402
106697
  removeTaskToastTracking(task.id);
106403
106698
  this.scheduleTaskRemoval(task.id);
106404
- if (task.sessionID) {
106405
- SessionCategoryRegistry.remove(task.sessionID);
106699
+ if (task.sessionId) {
106700
+ SessionCategoryRegistry.remove(task.sessionId);
106701
+ }
106702
+ if (task.parentSessionId) {
106703
+ this.updateBackgroundTaskMarker(task.parentSessionId);
106406
106704
  }
106407
106705
  this.markForNotification(task);
106408
- this.enqueueNotificationForParent(task.parentSessionID, () => this.notifyParentSession(task)).catch((err) => {
106706
+ this.enqueueNotificationForParent(task.parentSessionId, () => this.notifyParentSession(task)).catch((err) => {
106409
106707
  log("[background-agent] Error in notifyParentSession for crashed task:", { taskId: task.id, error: err });
106410
106708
  });
106411
106709
  }
@@ -106415,17 +106713,35 @@ ${originalText}`;
106415
106713
  this.pollingInFlight = true;
106416
106714
  try {
106417
106715
  this.pruneStaleTasksAndNotifications();
106418
- const statusResult = await this.client.session.status();
106419
- const allStatuses = normalizeSDKResponse(statusResult, {});
106716
+ let allStatuses;
106717
+ const sessionStatusMethod = this.client?.session?.status;
106718
+ if (typeof sessionStatusMethod !== "function") {
106719
+ if (!this.loggedSessionStatusUnavailable) {
106720
+ log("[background-agent] Unable to poll session statuses:", {
106721
+ reason: "session.status unavailable"
106722
+ });
106723
+ this.loggedSessionStatusUnavailable = true;
106724
+ }
106725
+ } else {
106726
+ try {
106727
+ const statusResult = await this.client.session.status();
106728
+ allStatuses = normalizeSDKResponse(statusResult, {});
106729
+ } catch (error) {
106730
+ if (!this.loggedSessionStatusUnavailable) {
106731
+ log("[background-agent] Error polling session statuses:", { error });
106732
+ this.loggedSessionStatusUnavailable = true;
106733
+ }
106734
+ }
106735
+ }
106420
106736
  await this.checkAndInterruptStaleTasks(allStatuses);
106421
106737
  for (const task of this.tasks.values()) {
106422
106738
  if (task.status !== "running")
106423
106739
  continue;
106424
- const sessionID = task.sessionID;
106740
+ const sessionID = task.sessionId;
106425
106741
  if (!sessionID)
106426
106742
  continue;
106427
106743
  try {
106428
- const sessionStatus = allStatuses[sessionID];
106744
+ const sessionStatus = allStatuses?.[sessionID];
106429
106745
  if (sessionStatus?.type === "retry") {
106430
106746
  const retryMessage = typeof sessionStatus.message === "string" ? sessionStatus.message : undefined;
106431
106747
  const errorInfo = { name: "SessionRetry", message: retryMessage };
@@ -106453,7 +106769,10 @@ ${originalText}`;
106453
106769
  sessionStatus: sessionStatus.type
106454
106770
  });
106455
106771
  }
106456
- const sessionGoneFromStatus = !sessionStatus;
106772
+ if (allStatuses === undefined) {
106773
+ continue;
106774
+ }
106775
+ const sessionGoneFromStatus = allStatuses !== undefined && !sessionStatus;
106457
106776
  const sessionGoneThresholdReached = sessionGoneFromStatus && (task.consecutiveMissedPolls ?? 0) >= MIN_SESSION_GONE_POLLS;
106458
106777
  const completionSource = sessionStatus?.type === "idle" ? "polling (idle status)" : "polling (session gone from status)";
106459
106778
  const hasValidOutput = await this.validateSessionHasOutput(sessionID);
@@ -106498,13 +106817,13 @@ ${originalText}`;
106498
106817
  const trackedSessionIDs = new Set;
106499
106818
  const abortRequests = [];
106500
106819
  for (const task of this.tasks.values()) {
106501
- if (task.sessionID) {
106502
- trackedSessionIDs.add(task.sessionID);
106820
+ if (task.sessionId) {
106821
+ trackedSessionIDs.add(task.sessionId);
106503
106822
  }
106504
- if (task.status === "running" && task.sessionID) {
106823
+ if (task.status === "running" && task.sessionId) {
106505
106824
  abortRequests.push({
106506
- sessionID: task.sessionID,
106507
- promise: abortWithTimeout(this.client, task.sessionID)
106825
+ sessionID: task.sessionId,
106826
+ promise: abortWithTimeout(this.client, task.sessionId)
106508
106827
  });
106509
106828
  }
106510
106829
  }
@@ -111508,7 +111827,8 @@ async function createStdioClient(params) {
111508
111827
  command,
111509
111828
  args,
111510
111829
  env: mergedEnv,
111511
- stderr: "ignore"
111830
+ stderr: "ignore",
111831
+ ...info.directory ? { cwd: info.directory } : {}
111512
111832
  });
111513
111833
  const client2 = stdioClientDependencies.createClient({ name: `skill-mcp-${info.skillName}-${info.serverName}`, version: "1.0.0" }, { capabilities: {} });
111514
111834
  try {
@@ -118830,8 +119150,7 @@ call_omo_agent(subagent_type="librarian", prompt="I'm looking for proven impleme
118830
119150
  var metisRestrictions = createAgentToolRestrictions([
118831
119151
  "write",
118832
119152
  "edit",
118833
- "apply_patch",
118834
- "task"
119153
+ "apply_patch"
118835
119154
  ]);
118836
119155
  function createMetisAgent(model) {
118837
119156
  return {
@@ -120348,8 +120667,7 @@ function createMomusAgent(model) {
120348
120667
  const restrictions = createAgentToolRestrictions([
120349
120668
  "write",
120350
120669
  "edit",
120351
- "apply_patch",
120352
- "task"
120670
+ "apply_patch"
120353
120671
  ]);
120354
120672
  const base = {
120355
120673
  description: "Expert reviewer for evaluating work plans against rigorous clarity, verifiability, and completeness standards. (Momus - OhMyOpenCode)",
@@ -121840,7 +122158,7 @@ function resolvePromptAppend(promptAppend, configDir) {
121840
122158
  filePath,
121841
122159
  projectRoot
121842
122160
  });
121843
- return `[WARNING: Path rejected: ${promptAppend}]`;
122161
+ return `[WARNING: Path rejected: ${promptAppend} (resolved outside project root ${projectRoot}; file:// prompts must reside within the project boundary)]`;
121844
122162
  }
121845
122163
  if (!existsSync91(filePath)) {
121846
122164
  return `[WARNING: Could not resolve file URI: ${promptAppend}]`;
@@ -126715,7 +127033,9 @@ function createManagers(args) {
126715
127033
  });
126716
127034
  }
126717
127035
  });
126718
- const backgroundManager = new deps.BackgroundManagerClass(ctx, pluginConfig.background_task, {
127036
+ const backgroundManager = new deps.BackgroundManagerClass({
127037
+ pluginContext: ctx,
127038
+ config: pluginConfig.background_task,
126719
127039
  tmuxConfig,
126720
127040
  onSubagentSessionCreated: async (event) => {
126721
127041
  log("[create-managers] onSubagentSessionCreated callback received", {
@@ -127339,7 +127659,6 @@ init_agent_display_names();
127339
127659
  init_agent_display_names();
127340
127660
 
127341
127661
  // src/plugin/ultrawork-db-model-override.ts
127342
- import { Database } from "bun:sqlite";
127343
127662
  import { join as join102 } from "path";
127344
127663
  import { existsSync as existsSync92 } from "fs";
127345
127664
  function getDbPath() {
@@ -127418,7 +127737,13 @@ function retryViaMicrotask(db, messageId, targetModel, variant, attempt) {
127418
127737
  });
127419
127738
  }
127420
127739
  function scheduleDeferredModelOverride(messageId, targetModel, variant) {
127421
- queueMicrotask(() => {
127740
+ queueMicrotask(async () => {
127741
+ const sqliteModule = await import("bun:sqlite").catch(() => null);
127742
+ const Database = sqliteModule?.Database;
127743
+ if (typeof Database !== "function") {
127744
+ log("[ultrawork-db-override] bun:sqlite unavailable, skipping deferred override", { messageId });
127745
+ return;
127746
+ }
127422
127747
  const dbPath = getDbPath();
127423
127748
  if (!existsSync92(dbPath)) {
127424
127749
  log("[ultrawork-db-override] DB not found, skipping deferred override");
@@ -127829,11 +128154,24 @@ function createChatMessageHandler3(args) {
127829
128154
  }
127830
128155
 
127831
128156
  // src/plugin/messages-transform.ts
128157
+ init_logger();
128158
+ async function runMessagesTransformHookSafely(hookName, handler, input, output) {
128159
+ if (!handler)
128160
+ return;
128161
+ try {
128162
+ await Promise.resolve(handler(input, output));
128163
+ } catch (error) {
128164
+ log("[messages-transform] hook execution failed", {
128165
+ hook: hookName,
128166
+ error
128167
+ });
128168
+ }
128169
+ }
127832
128170
  function createMessagesTransformHandler(args) {
127833
128171
  return async (input, output) => {
127834
- await args.hooks.contextInjectorMessagesTransform?.["experimental.chat.messages.transform"]?.(input, output);
127835
- await args.hooks.thinkingBlockValidator?.["experimental.chat.messages.transform"]?.(input, output);
127836
- await args.hooks.toolPairValidator?.["experimental.chat.messages.transform"]?.(input, output);
128172
+ await runMessagesTransformHookSafely("contextInjectorMessagesTransform", args.hooks.contextInjectorMessagesTransform?.["experimental.chat.messages.transform"], input, output);
128173
+ await runMessagesTransformHookSafely("thinkingBlockValidator", args.hooks.thinkingBlockValidator?.["experimental.chat.messages.transform"], input, output);
128174
+ await runMessagesTransformHookSafely("toolPairValidator", args.hooks.toolPairValidator?.["experimental.chat.messages.transform"], input, output);
127837
128175
  };
127838
128176
  }
127839
128177
 
@@ -133505,7 +133843,7 @@ class PostHog extends PostHogBackendClient {
133505
133843
  // package.json
133506
133844
  var package_default = {
133507
133845
  name: "oh-my-opencode",
133508
- version: "3.17.12",
133846
+ version: "3.17.14",
133509
133847
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
133510
133848
  main: "./dist/index.js",
133511
133849
  types: "dist/index.d.ts",
@@ -133573,7 +133911,7 @@ var package_default = {
133573
133911
  "js-yaml": "^4.1.1",
133574
133912
  "jsonc-parser": "^3.3.1",
133575
133913
  picocolors: "^1.1.1",
133576
- picomatch: "^4.0.2",
133914
+ picomatch: "^4.0.4",
133577
133915
  "posthog-node": "^5.29.2",
133578
133916
  "vscode-jsonrpc": "^8.2.0"
133579
133917
  },
@@ -133585,17 +133923,17 @@ var package_default = {
133585
133923
  zod: "^4.3.0"
133586
133924
  },
133587
133925
  optionalDependencies: {
133588
- "oh-my-opencode-darwin-arm64": "3.17.12",
133589
- "oh-my-opencode-darwin-x64": "3.17.12",
133590
- "oh-my-opencode-darwin-x64-baseline": "3.17.12",
133591
- "oh-my-opencode-linux-arm64": "3.17.12",
133592
- "oh-my-opencode-linux-arm64-musl": "3.17.12",
133593
- "oh-my-opencode-linux-x64": "3.17.12",
133594
- "oh-my-opencode-linux-x64-baseline": "3.17.12",
133595
- "oh-my-opencode-linux-x64-musl": "3.17.12",
133596
- "oh-my-opencode-linux-x64-musl-baseline": "3.17.12",
133597
- "oh-my-opencode-windows-x64": "3.17.12",
133598
- "oh-my-opencode-windows-x64-baseline": "3.17.12"
133926
+ "oh-my-opencode-darwin-arm64": "3.17.14",
133927
+ "oh-my-opencode-darwin-x64": "3.17.14",
133928
+ "oh-my-opencode-darwin-x64-baseline": "3.17.14",
133929
+ "oh-my-opencode-linux-arm64": "3.17.14",
133930
+ "oh-my-opencode-linux-arm64-musl": "3.17.14",
133931
+ "oh-my-opencode-linux-x64": "3.17.14",
133932
+ "oh-my-opencode-linux-x64-baseline": "3.17.14",
133933
+ "oh-my-opencode-linux-x64-musl": "3.17.14",
133934
+ "oh-my-opencode-linux-x64-musl-baseline": "3.17.14",
133935
+ "oh-my-opencode-windows-x64": "3.17.14",
133936
+ "oh-my-opencode-windows-x64-baseline": "3.17.14"
133599
133937
  },
133600
133938
  overrides: {},
133601
133939
  trustedDependencies: [
@@ -133674,21 +134012,6 @@ function getPostHogActivityCaptureState(now = new Date) {
133674
134012
  captureDaily
133675
134013
  };
133676
134014
  }
133677
- function getPluginLoadedCaptureState(now = new Date) {
133678
- const state3 = readPostHogActivityState();
133679
- const dayUTC = getUtcDayString(now);
133680
- const capturePluginLoaded = state3.lastPluginLoadedDayUTC !== dayUTC;
133681
- if (capturePluginLoaded) {
133682
- writePostHogActivityState({
133683
- ...state3,
133684
- lastPluginLoadedDayUTC: dayUTC
133685
- });
133686
- }
133687
- return {
133688
- dayUTC,
133689
- capturePluginLoaded
133690
- };
133691
- }
133692
134015
 
133693
134016
  // src/shared/posthog.ts
133694
134017
  var activityStateProviderOverride = null;
@@ -133698,12 +134021,6 @@ function resolveActivityState() {
133698
134021
  var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com";
133699
134022
  var DEFAULT_POSTHOG_API_KEY = "phc_CFJhj5HyvA62QPhvyaUCtaq23aUfznnijg5VaaGkNk74";
133700
134023
  var NO_OP_POSTHOG = {
133701
- capture: () => {
133702
- return;
133703
- },
133704
- captureException: () => {
133705
- return;
133706
- },
133707
134024
  trackActive: () => {
133708
134025
  return;
133709
134026
  },
@@ -133777,21 +134094,6 @@ function createPostHogClient(source, options) {
133777
134094
  }
133778
134095
  const sharedProperties = getSharedProperties(source);
133779
134096
  return {
133780
- capture: (message) => {
133781
- configuredClient.capture({
133782
- ...message,
133783
- properties: {
133784
- ...sharedProperties,
133785
- ...message.properties
133786
- }
133787
- });
133788
- },
133789
- captureException: (error, distinctId, additionalProperties) => {
133790
- configuredClient.captureException(error, distinctId, {
133791
- ...sharedProperties,
133792
- ...additionalProperties
133793
- });
133794
- },
133795
134097
  trackActive: (distinctId, reason) => {
133796
134098
  const activityState = resolveActivityState();
133797
134099
  if (activityState.captureDaily) {
@@ -133800,6 +134102,7 @@ function createPostHogClient(source, options) {
133800
134102
  event: "omo_daily_active",
133801
134103
  properties: {
133802
134104
  ...sharedProperties,
134105
+ $process_person_profile: false,
133803
134106
  day_utc: activityState.dayUTC,
133804
134107
  reason
133805
134108
  }
@@ -133839,23 +134142,6 @@ var serverPlugin = async (input, _options) => {
133839
134142
  try {
133840
134143
  posthog.trackActive(distinctId, "plugin_loaded");
133841
134144
  } catch {}
133842
- let pluginLoadedCaptureState = null;
133843
- try {
133844
- pluginLoadedCaptureState = getPluginLoadedCaptureState();
133845
- } catch {}
133846
- if (pluginLoadedCaptureState?.capturePluginLoaded) {
133847
- try {
133848
- posthog.capture({
133849
- distinctId,
133850
- event: "plugin_loaded",
133851
- properties: {
133852
- entry_point: "plugin",
133853
- has_openclaw: !!pluginConfig.openclaw,
133854
- tmux_enabled: isTmuxIntegrationEnabled(pluginConfig)
133855
- }
133856
- });
133857
- } catch {}
133858
- }
133859
134145
  if (pluginConfig.openclaw) {
133860
134146
  await initializeOpenClaw(pluginConfig.openclaw);
133861
134147
  }