opencode-orchestrator 0.9.68 → 0.9.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +148 -150
  2. package/package.json +1 -7
package/dist/index.js CHANGED
@@ -15429,6 +15429,26 @@ function getBinaryPath() {
15429
15429
  return binaryPath;
15430
15430
  }
15431
15431
 
15432
+ // src/core/agents/logger.ts
15433
+ import * as fs from "fs";
15434
+ import * as os from "os";
15435
+ import * as path from "path";
15436
+ var DEBUG = process.env.DEBUG_PARALLEL_AGENT === "true";
15437
+ var LOG_FILE = path.join(os.tmpdir(), "opencode-orchestrator.log");
15438
+ function log(...args) {
15439
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
15440
+ const message = `[${timestamp}] [parallel-agent] ${args.map(
15441
+ (a) => typeof a === "object" ? JSON.stringify(a) : String(a)
15442
+ ).join(" ")}`;
15443
+ try {
15444
+ fs.appendFileSync(LOG_FILE, message + "\n");
15445
+ } catch {
15446
+ }
15447
+ }
15448
+ function getLogPath() {
15449
+ return LOG_FILE;
15450
+ }
15451
+
15432
15452
  // src/tools/rust.ts
15433
15453
  async function callRustTool(name, args) {
15434
15454
  const binary = getBinaryPath();
@@ -15443,7 +15463,7 @@ async function callRustTool(name, args) {
15443
15463
  });
15444
15464
  proc.stderr.on("data", (data) => {
15445
15465
  const msg = data.toString().trim();
15446
- if (msg) console.error(`[rust-stderr] ${msg}`);
15466
+ if (msg) log(`[rust-stderr] ${msg}`);
15447
15467
  });
15448
15468
  const request = JSON.stringify({
15449
15469
  jsonrpc: "2.0",
@@ -15460,7 +15480,7 @@ async function callRustTool(name, args) {
15460
15480
  proc.on("close", (code) => {
15461
15481
  clearTimeout(timeout);
15462
15482
  if (code !== 0 && code !== null) {
15463
- console.error(`Rust process exited with code ${code}`);
15483
+ log(`Rust process exited with code ${code}`);
15464
15484
  }
15465
15485
  try {
15466
15486
  const lines = stdout.trim().split("\n");
@@ -15661,7 +15681,7 @@ var BackgroundTaskManager = class _BackgroundTaskManager {
15661
15681
  debug(taskId, message) {
15662
15682
  if (this.debugMode) {
15663
15683
  const ts = (/* @__PURE__ */ new Date()).toISOString().substring(11, 23);
15664
- console.log(`[BG ${ts}] ${taskId}: ${message}`);
15684
+ log(`[BG ${ts}] ${taskId}: ${message}`);
15665
15685
  }
15666
15686
  }
15667
15687
  run(options) {
@@ -15920,9 +15940,9 @@ Duration: ${backgroundTaskManager.formatDuration(task)}`;
15920
15940
  });
15921
15941
 
15922
15942
  // src/core/agents/concurrency.ts
15923
- var DEBUG = process.env.DEBUG_PARALLEL_AGENT === "true";
15924
- var log = (...args) => {
15925
- if (DEBUG) console.log("[concurrency]", ...args);
15943
+ var DEBUG2 = process.env.DEBUG_PARALLEL_AGENT === "true";
15944
+ var log2 = (...args) => {
15945
+ if (DEBUG2) log("[concurrency]", ...args);
15926
15946
  };
15927
15947
  var ConcurrencyController = class {
15928
15948
  counts = /* @__PURE__ */ new Map();
@@ -15969,10 +15989,10 @@ var ConcurrencyController = class {
15969
15989
  const current = this.counts.get(key) ?? 0;
15970
15990
  if (current < limit) {
15971
15991
  this.counts.set(key, current + 1);
15972
- log(`Acquired ${key}: ${current + 1}/${limit}`);
15992
+ log2(`Acquired ${key}: ${current + 1}/${limit}`);
15973
15993
  return;
15974
15994
  }
15975
- log(`Queueing ${key}: ${current}/${limit}`);
15995
+ log2(`Queueing ${key}: ${current}/${limit}`);
15976
15996
  return new Promise((resolve) => {
15977
15997
  const queue = this.queues.get(key) ?? [];
15978
15998
  queue.push(resolve);
@@ -15985,13 +16005,13 @@ var ConcurrencyController = class {
15985
16005
  const queue = this.queues.get(key);
15986
16006
  if (queue && queue.length > 0) {
15987
16007
  const next = queue.shift();
15988
- log(`Released ${key}: next in queue`);
16008
+ log2(`Released ${key}: next in queue`);
15989
16009
  next();
15990
16010
  } else {
15991
16011
  const current = this.counts.get(key) ?? 0;
15992
16012
  if (current > 0) {
15993
16013
  this.counts.set(key, current - 1);
15994
- log(`Released ${key}: ${current - 1}/${limit}`);
16014
+ log2(`Released ${key}: ${current - 1}/${limit}`);
15995
16015
  }
15996
16016
  }
15997
16017
  }
@@ -16013,8 +16033,8 @@ var ConcurrencyController = class {
16013
16033
  };
16014
16034
 
16015
16035
  // src/core/agents/task-store.ts
16016
- import * as fs from "node:fs/promises";
16017
- import * as path from "node:path";
16036
+ import * as fs2 from "node:fs/promises";
16037
+ import * as path2 from "node:path";
16018
16038
  var TaskStore = class {
16019
16039
  tasks = /* @__PURE__ */ new Map();
16020
16040
  pendingByParent = /* @__PURE__ */ new Map();
@@ -16146,10 +16166,10 @@ var TaskStore = class {
16146
16166
  */
16147
16167
  async archiveTasks(tasks) {
16148
16168
  try {
16149
- await fs.mkdir(PATHS.TASK_ARCHIVE, { recursive: true });
16169
+ await fs2.mkdir(PATHS.TASK_ARCHIVE, { recursive: true });
16150
16170
  const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
16151
16171
  const filename = `tasks_${date5}.jsonl`;
16152
- const filepath = path.join(PATHS.TASK_ARCHIVE, filename);
16172
+ const filepath = path2.join(PATHS.TASK_ARCHIVE, filename);
16153
16173
  const lines = tasks.map((task) => JSON.stringify({
16154
16174
  id: task.id,
16155
16175
  agent: task.agent,
@@ -16160,10 +16180,9 @@ var TaskStore = class {
16160
16180
  completedAt: task.completedAt,
16161
16181
  parentSessionID: task.parentSessionID
16162
16182
  }));
16163
- await fs.appendFile(filepath, lines.join("\n") + "\n");
16183
+ await fs2.appendFile(filepath, lines.join("\n") + "\n");
16164
16184
  this.archivedCount += tasks.length;
16165
16185
  } catch (error45) {
16166
- console.error("[TaskStore] Archive failed:", error45);
16167
16186
  }
16168
16187
  }
16169
16188
  /**
@@ -16183,27 +16202,6 @@ var TaskStore = class {
16183
16202
  }
16184
16203
  };
16185
16204
 
16186
- // src/core/agents/logger.ts
16187
- import * as fs2 from "fs";
16188
- import * as os from "os";
16189
- import * as path2 from "path";
16190
- var DEBUG2 = process.env.DEBUG_PARALLEL_AGENT === "true";
16191
- var LOG_FILE = path2.join(os.tmpdir(), "opencode-orchestrator.log");
16192
- function log2(...args) {
16193
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
16194
- const message = `[${timestamp}] [parallel-agent] ${args.map(
16195
- (a) => typeof a === "object" ? JSON.stringify(a) : String(a)
16196
- ).join(" ")}`;
16197
- try {
16198
- fs2.appendFileSync(LOG_FILE, message + "\n");
16199
- } catch {
16200
- }
16201
- if (DEBUG2) console.log("[parallel-agent]", ...args);
16202
- }
16203
- function getLogPath() {
16204
- return LOG_FILE;
16205
- }
16206
-
16207
16205
  // src/core/agents/format.ts
16208
16206
  function formatDuration(start, end) {
16209
16207
  const duration3 = (end ?? /* @__PURE__ */ new Date()).getTime() - start.getTime();
@@ -16682,10 +16680,10 @@ var TaskLauncher = class {
16682
16680
  this.startPolling = startPolling;
16683
16681
  }
16684
16682
  async launch(input) {
16685
- log2("[task-launcher.ts] launch() called", { agent: input.agent, description: input.description, parent: input.parentSessionID });
16683
+ log("[task-launcher.ts] launch() called", { agent: input.agent, description: input.description, parent: input.parentSessionID });
16686
16684
  const concurrencyKey = input.agent;
16687
16685
  await this.concurrency.acquire(concurrencyKey);
16688
- log2("[task-launcher.ts] concurrency acquired for", concurrencyKey);
16686
+ log("[task-launcher.ts] concurrency acquired for", concurrencyKey);
16689
16687
  try {
16690
16688
  const createResult = await this.client.session.create({
16691
16689
  body: { parentID: input.parentSessionID, title: `${PARALLEL_TASK.SESSION_TITLE_PREFIX}: ${input.description}` },
@@ -16698,7 +16696,7 @@ var TaskLauncher = class {
16698
16696
  const sessionID = createResult.data.id;
16699
16697
  const taskId = `${ID_PREFIX.TASK}${crypto.randomUUID().slice(0, 8)}`;
16700
16698
  const depth = (input.depth ?? 0) + 1;
16701
- log2("[task-launcher.ts] Creating task with depth", depth);
16699
+ log("[task-launcher.ts] Creating task with depth", depth);
16702
16700
  const task = {
16703
16701
  id: taskId,
16704
16702
  sessionID,
@@ -16728,7 +16726,7 @@ var TaskLauncher = class {
16728
16726
  parts: [{ type: PART_TYPES.TEXT, text: input.prompt }]
16729
16727
  }
16730
16728
  }).catch((error45) => {
16731
- log2(`Prompt error for ${taskId}:`, error45);
16729
+ log(`Prompt error for ${taskId}:`, error45);
16732
16730
  this.onTaskError(taskId, error45);
16733
16731
  });
16734
16732
  const toastManager = getTaskToastManager();
@@ -16743,7 +16741,7 @@ var TaskLauncher = class {
16743
16741
  });
16744
16742
  }
16745
16743
  presets.sessionCreated(sessionID, input.agent);
16746
- log2(`Launched ${taskId} in session ${sessionID}`);
16744
+ log(`Launched ${taskId} in session ${sessionID}`);
16747
16745
  return task;
16748
16746
  } catch (error45) {
16749
16747
  this.concurrency.release(concurrencyKey);
@@ -16775,7 +16773,7 @@ var TaskResumer = class {
16775
16773
  existingTask.stablePolls = 0;
16776
16774
  this.store.trackPending(input.parentSessionID, existingTask.id);
16777
16775
  this.startPolling();
16778
- log2(`Resuming task ${existingTask.id} in session ${existingTask.sessionID}`);
16776
+ log(`Resuming task ${existingTask.id} in session ${existingTask.sessionID}`);
16779
16777
  this.client.session.prompt({
16780
16778
  path: { id: existingTask.sessionID },
16781
16779
  body: {
@@ -16783,7 +16781,7 @@ var TaskResumer = class {
16783
16781
  parts: [{ type: PART_TYPES.TEXT, text: input.prompt }]
16784
16782
  }
16785
16783
  }).catch((error45) => {
16786
- log2(`Resume prompt error for ${existingTask.id}:`, error45);
16784
+ log(`Resume prompt error for ${existingTask.id}:`, error45);
16787
16785
  existingTask.status = TASK_STATUS.ERROR;
16788
16786
  existingTask.error = error45 instanceof Error ? error45.message : String(error45);
16789
16787
  existingTask.completedAt = /* @__PURE__ */ new Date();
@@ -16817,7 +16815,7 @@ var TaskPoller = class {
16817
16815
  pollingInterval;
16818
16816
  start() {
16819
16817
  if (this.pollingInterval) return;
16820
- log2("[task-poller.ts] start() - polling started");
16818
+ log("[task-poller.ts] start() - polling started");
16821
16819
  this.pollingInterval = setInterval(() => this.poll(), CONFIG.POLL_INTERVAL_MS);
16822
16820
  this.pollingInterval.unref();
16823
16821
  }
@@ -16837,7 +16835,7 @@ var TaskPoller = class {
16837
16835
  this.stop();
16838
16836
  return;
16839
16837
  }
16840
- log2("[task-poller.ts] poll() checking", running.length, "running tasks");
16838
+ log("[task-poller.ts] poll() checking", running.length, "running tasks");
16841
16839
  try {
16842
16840
  const statusResult = await this.client.session.status();
16843
16841
  const allStatuses = statusResult.data ?? {};
@@ -16855,16 +16853,16 @@ var TaskPoller = class {
16855
16853
  const elapsed = Date.now() - task.startedAt.getTime();
16856
16854
  if (elapsed >= CONFIG.MIN_STABILITY_MS && task.stablePolls && task.stablePolls >= 3) {
16857
16855
  if (await this.validateSessionHasOutput(task.sessionID)) {
16858
- log2(`Task ${task.id} stable for 3 polls, completing...`);
16856
+ log(`Task ${task.id} stable for 3 polls, completing...`);
16859
16857
  await this.completeTask(task);
16860
16858
  }
16861
16859
  }
16862
16860
  } catch (error45) {
16863
- log2(`Poll error for task ${task.id}:`, error45);
16861
+ log(`Poll error for task ${task.id}:`, error45);
16864
16862
  }
16865
16863
  }
16866
16864
  } catch (error45) {
16867
- log2("Polling error:", error45);
16865
+ log("Polling error:", error45);
16868
16866
  }
16869
16867
  }
16870
16868
  async validateSessionHasOutput(sessionID) {
@@ -16877,7 +16875,7 @@ var TaskPoller = class {
16877
16875
  }
16878
16876
  }
16879
16877
  async completeTask(task) {
16880
- log2("[task-poller.ts] completeTask() called for", task.id, task.agent);
16878
+ log("[task-poller.ts] completeTask() called for", task.id, task.agent);
16881
16879
  task.status = TASK_STATUS.COMPLETED;
16882
16880
  task.completedAt = /* @__PURE__ */ new Date();
16883
16881
  if (task.concurrencyKey) {
@@ -16890,7 +16888,7 @@ var TaskPoller = class {
16890
16888
  this.scheduleCleanup(task.id);
16891
16889
  const duration3 = formatDuration(task.startedAt, task.completedAt);
16892
16890
  presets.sessionCompleted(task.sessionID, duration3);
16893
- log2(`Completed ${task.id} (${duration3})`);
16891
+ log(`Completed ${task.id} (${duration3})`);
16894
16892
  }
16895
16893
  async updateTaskProgress(task) {
16896
16894
  try {
@@ -16942,7 +16940,7 @@ var TaskCleaner = class {
16942
16940
  for (const [taskId, task] of this.store.getAll().map((t) => [t.id, t])) {
16943
16941
  const age = now - task.startedAt.getTime();
16944
16942
  if (age <= CONFIG.TASK_TTL_MS) continue;
16945
- log2(`Timeout: ${taskId}`);
16943
+ log(`Timeout: ${taskId}`);
16946
16944
  if (task.status === TASK_STATUS.RUNNING) {
16947
16945
  task.status = TASK_STATUS.TIMEOUT;
16948
16946
  task.error = "Task exceeded 30 minute time limit";
@@ -16977,7 +16975,7 @@ var TaskCleaner = class {
16977
16975
  }
16978
16976
  }
16979
16977
  this.store.delete(taskId);
16980
- log2(`Cleaned up ${taskId}`);
16978
+ log(`Cleaned up ${taskId}`);
16981
16979
  }, CONFIG.CLEANUP_DELAY_MS);
16982
16980
  }
16983
16981
  /**
@@ -17027,9 +17025,9 @@ You will be notified when ALL tasks complete. Continue productive work.`;
17027
17025
  parts: [{ type: PART_TYPES.TEXT, text: message }]
17028
17026
  }
17029
17027
  });
17030
- log2(`Notified parent ${parentSessionID} (allComplete=${allComplete}, noReply=${!allComplete})`);
17028
+ log(`Notified parent ${parentSessionID} (allComplete=${allComplete}, noReply=${!allComplete})`);
17031
17029
  } catch (error45) {
17032
- log2("Notification error:", error45);
17030
+ log("Notification error:", error45);
17033
17031
  }
17034
17032
  this.store.clearNotifications(parentSessionID);
17035
17033
  }
@@ -17058,7 +17056,7 @@ var EventHandler = class {
17058
17056
  const task = this.findBySession(sessionID);
17059
17057
  if (!task || task.status !== TASK_STATUS.RUNNING) return;
17060
17058
  this.handleSessionIdle(task).catch((err) => {
17061
- log2("Error handling session.idle:", err);
17059
+ log("Error handling session.idle:", err);
17062
17060
  });
17063
17061
  }
17064
17062
  if (event.type === SESSION_EVENTS.DELETED) {
@@ -17072,12 +17070,12 @@ var EventHandler = class {
17072
17070
  async handleSessionIdle(task) {
17073
17071
  const elapsed = Date.now() - task.startedAt.getTime();
17074
17072
  if (elapsed < CONFIG.MIN_STABILITY_MS) {
17075
- log2(`Session idle but too early for ${task.id}, waiting...`);
17073
+ log(`Session idle but too early for ${task.id}, waiting...`);
17076
17074
  return;
17077
17075
  }
17078
17076
  const hasOutput = await this.validateSessionHasOutput(task.sessionID);
17079
17077
  if (!hasOutput) {
17080
- log2(`Session idle but no output for ${task.id}, waiting...`);
17078
+ log(`Session idle but no output for ${task.id}, waiting...`);
17081
17079
  return;
17082
17080
  }
17083
17081
  task.status = TASK_STATUS.COMPLETED;
@@ -17090,10 +17088,10 @@ var EventHandler = class {
17090
17088
  this.store.queueNotification(task);
17091
17089
  await this.notifyParentIfAllComplete(task.parentSessionID);
17092
17090
  this.scheduleCleanup(task.id);
17093
- log2(`Task ${task.id} completed via session.idle event (${formatDuration(task.startedAt, task.completedAt)})`);
17091
+ log(`Task ${task.id} completed via session.idle event (${formatDuration(task.startedAt, task.completedAt)})`);
17094
17092
  }
17095
17093
  handleSessionDeleted(task) {
17096
- log2(`Session deleted event for task ${task.id}`);
17094
+ log(`Session deleted event for task ${task.id}`);
17097
17095
  if (task.status === TASK_STATUS.RUNNING) {
17098
17096
  task.status = TASK_STATUS.ERROR;
17099
17097
  task.error = "Session deleted";
@@ -17106,7 +17104,7 @@ var EventHandler = class {
17106
17104
  this.store.untrackPending(task.parentSessionID, task.id);
17107
17105
  this.store.clearNotificationsForTask(task.id);
17108
17106
  this.store.delete(task.id);
17109
- log2(`Cleaned up deleted session task: ${task.id}`);
17107
+ log(`Cleaned up deleted session task: ${task.id}`);
17110
17108
  }
17111
17109
  };
17112
17110
 
@@ -17201,12 +17199,12 @@ var ParallelAgentManager = class _ParallelAgentManager {
17201
17199
  this.store.untrackPending(task.parentSessionID, taskId);
17202
17200
  try {
17203
17201
  await this.client.session.delete({ path: { id: task.sessionID } });
17204
- log2(`Session ${task.sessionID.slice(0, 8)}... deleted`);
17202
+ log(`Session ${task.sessionID.slice(0, 8)}... deleted`);
17205
17203
  } catch {
17206
- log2(`Session ${task.sessionID.slice(0, 8)}... already gone`);
17204
+ log(`Session ${task.sessionID.slice(0, 8)}... already gone`);
17207
17205
  }
17208
17206
  this.cleaner.scheduleCleanup(taskId);
17209
- log2(`Cancelled ${taskId}`);
17207
+ log(`Cancelled ${taskId}`);
17210
17208
  return true;
17211
17209
  }
17212
17210
  async getResult(taskId) {
@@ -17301,7 +17299,7 @@ async function validateSessionHasOutput(session, sessionID) {
17301
17299
  });
17302
17300
  return hasContent;
17303
17301
  } catch (error45) {
17304
- log2(`${PARALLEL_LOG.DELEGATE_TASK} Error validating session output:`, error45);
17302
+ log(`${PARALLEL_LOG.DELEGATE_TASK} Error validating session output:`, error45);
17305
17303
  return true;
17306
17304
  }
17307
17305
  }
@@ -17315,11 +17313,11 @@ async function pollWithSafetyLimits(session, sessionID, startTime) {
17315
17313
  pollCount++;
17316
17314
  const elapsed = Date.now() - startTime;
17317
17315
  if (elapsed >= SYNC_TIMEOUT_MS) {
17318
- log2(`${PARALLEL_LOG.DELEGATE_TASK} Hard timeout reached`, { pollCount, elapsed });
17316
+ log(`${PARALLEL_LOG.DELEGATE_TASK} Hard timeout reached`, { pollCount, elapsed });
17319
17317
  return { success: false, timedOut: true, pollCount, elapsedMs: elapsed };
17320
17318
  }
17321
17319
  if (Date.now() - lastLogTime > 1e4) {
17322
- log2(`${PARALLEL_LOG.DELEGATE_TASK} Polling...`, {
17320
+ log(`${PARALLEL_LOG.DELEGATE_TASK} Polling...`, {
17323
17321
  pollCount,
17324
17322
  elapsed: Math.floor(elapsed / 1e3) + "s",
17325
17323
  stablePolls,
@@ -17347,14 +17345,14 @@ async function pollWithSafetyLimits(session, sessionID, startTime) {
17347
17345
  if (!hasValidOutput) {
17348
17346
  continue;
17349
17347
  }
17350
- log2(`${PARALLEL_LOG.DELEGATE_TASK} Valid output detected`, { pollCount, elapsed });
17348
+ log(`${PARALLEL_LOG.DELEGATE_TASK} Valid output detected`, { pollCount, elapsed });
17351
17349
  }
17352
17350
  const msgs = await session.messages({ path: { id: sessionID } });
17353
17351
  const count = (msgs.data ?? []).length;
17354
17352
  if (count === lastMsgCount) {
17355
17353
  stablePolls++;
17356
17354
  if (stablePolls >= STABLE_POLLS_REQUIRED) {
17357
- log2(`${PARALLEL_LOG.DELEGATE_TASK} Stable completion`, { pollCount, stablePolls, elapsed });
17355
+ log(`${PARALLEL_LOG.DELEGATE_TASK} Stable completion`, { pollCount, stablePolls, elapsed });
17358
17356
  return { success: true, timedOut: false, pollCount, elapsedMs: elapsed };
17359
17357
  }
17360
17358
  } else {
@@ -17362,10 +17360,10 @@ async function pollWithSafetyLimits(session, sessionID, startTime) {
17362
17360
  lastMsgCount = count;
17363
17361
  }
17364
17362
  } catch (error45) {
17365
- log2(`${PARALLEL_LOG.DELEGATE_TASK} Poll error (continuing):`, error45);
17363
+ log(`${PARALLEL_LOG.DELEGATE_TASK} Poll error (continuing):`, error45);
17366
17364
  }
17367
17365
  }
17368
- log2(`${PARALLEL_LOG.DELEGATE_TASK} Max poll count reached`, { pollCount, elapsed: Date.now() - startTime });
17366
+ log(`${PARALLEL_LOG.DELEGATE_TASK} Max poll count reached`, { pollCount, elapsed: Date.now() - startTime });
17369
17367
  return {
17370
17368
  success: false,
17371
17369
  timedOut: true,
@@ -17382,7 +17380,7 @@ async function extractSessionResult(session, sessionID) {
17382
17380
  const text = lastMsg?.parts?.filter((p) => p.type === PART_TYPES.TEXT || p.type === PART_TYPES.REASONING).map((p) => p.text ?? "").join("\n") || "";
17383
17381
  return text;
17384
17382
  } catch (error45) {
17385
- log2(`${PARALLEL_LOG.DELEGATE_TASK} Error extracting result:`, error45);
17383
+ log(`${PARALLEL_LOG.DELEGATE_TASK} Error extracting result:`, error45);
17386
17384
  return "(Error extracting result)";
17387
17385
  }
17388
17386
  }
@@ -17415,7 +17413,7 @@ var createDelegateTaskTool = (manager, client) => tool({
17415
17413
  async execute(args, context) {
17416
17414
  const { agent, description, prompt, background, resume } = args;
17417
17415
  const ctx = context;
17418
- log2(`${PARALLEL_LOG.DELEGATE_TASK} execute() called`, { agent, description, background, resume, parentSession: ctx.sessionID });
17416
+ log(`${PARALLEL_LOG.DELEGATE_TASK} execute() called`, { agent, description, background, resume, parentSession: ctx.sessionID });
17419
17417
  const sessionClient = client;
17420
17418
  if (background === void 0) {
17421
17419
  return `${OUTPUT_LABEL.ERROR} 'background' parameter is REQUIRED.`;
@@ -17434,7 +17432,7 @@ Previous context preserved. Use \`get_task_result({ taskId: "${task.id}" })\` wh
17434
17432
  }
17435
17433
  const startTime = Date.now();
17436
17434
  const session = sessionClient.session;
17437
- log2(`${PARALLEL_LOG.DELEGATE_TASK} Resume: starting sync wait`, { taskId: task.id, sessionID: task.sessionID });
17435
+ log(`${PARALLEL_LOG.DELEGATE_TASK} Resume: starting sync wait`, { taskId: task.id, sessionID: task.sessionID });
17438
17436
  const pollResult = await pollWithSafetyLimits(session, task.sessionID, startTime);
17439
17437
  if (pollResult.timedOut) {
17440
17438
  return `${OUTPUT_LABEL.TIMEOUT} after ${Math.floor(pollResult.elapsedMs / 1e3)}s (${pollResult.pollCount} polls)
@@ -17474,7 +17472,7 @@ Session: \`${task.sessionID}\` (save for resume)`;
17474
17472
  }
17475
17473
  const sessionID = createResult.data.id;
17476
17474
  const startTime = Date.now();
17477
- log2(`${PARALLEL_LOG.DELEGATE_TASK} Sync: starting`, { agent, sessionID });
17475
+ log(`${PARALLEL_LOG.DELEGATE_TASK} Sync: starting`, { agent, sessionID });
17478
17476
  await session.prompt({
17479
17477
  path: { id: sessionID },
17480
17478
  body: {
@@ -17490,18 +17488,18 @@ Session: \`${task.sessionID}\` (save for resume)`;
17490
17488
  });
17491
17489
  const pollResult = await pollWithSafetyLimits(session, sessionID, startTime);
17492
17490
  if (pollResult.timedOut) {
17493
- log2(`${PARALLEL_LOG.DELEGATE_TASK} Sync: timed out`, pollResult);
17491
+ log(`${PARALLEL_LOG.DELEGATE_TASK} Sync: timed out`, pollResult);
17494
17492
  return `${OUTPUT_LABEL.TIMEOUT} after ${Math.floor(pollResult.elapsedMs / 1e3)}s (${pollResult.pollCount} polls)
17495
17493
  Session: \`${sessionID}\` - Use get_task_result or resume later.`;
17496
17494
  }
17497
17495
  const text = await extractSessionResult(session, sessionID);
17498
- log2(`${PARALLEL_LOG.DELEGATE_TASK} Sync: completed`, { sessionID, elapsedMs: pollResult.elapsedMs });
17496
+ log(`${PARALLEL_LOG.DELEGATE_TASK} Sync: completed`, { sessionID, elapsedMs: pollResult.elapsedMs });
17499
17497
  return `${OUTPUT_LABEL.DONE} (${Math.floor(pollResult.elapsedMs / 1e3)}s)
17500
17498
  Session: \`${sessionID}\` (save for resume)
17501
17499
 
17502
17500
  ${text || "(No output)"}`;
17503
17501
  } catch (error45) {
17504
- log2(`${PARALLEL_LOG.DELEGATE_TASK} Sync: error`, error45);
17502
+ log(`${PARALLEL_LOG.DELEGATE_TASK} Sync: error`, error45);
17505
17503
  return `${OUTPUT_LABEL.ERROR} Failed: ${error45 instanceof Error ? error45.message : String(error45)}`;
17506
17504
  }
17507
17505
  }
@@ -17990,7 +17988,7 @@ async function searchBrave(query) {
17990
17988
  }
17991
17989
  return results;
17992
17990
  } catch (error45) {
17993
- console.error("Brave search error:", error45);
17991
+ log("Brave search error:", error45);
17994
17992
  return [];
17995
17993
  }
17996
17994
  }
@@ -18039,7 +18037,7 @@ async function searchDuckDuckGo(query) {
18039
18037
  }
18040
18038
  return results;
18041
18039
  } catch (error45) {
18042
- console.error("DuckDuckGo search error:", error45);
18040
+ log("DuckDuckGo search error:", error45);
18043
18041
  return [];
18044
18042
  }
18045
18043
  }
@@ -18070,7 +18068,7 @@ async function searchDuckDuckGoHtml(query) {
18070
18068
  }
18071
18069
  return results;
18072
18070
  } catch (error45) {
18073
- console.error("DuckDuckGo HTML search error:", error45);
18071
+ log("DuckDuckGo HTML search error:", error45);
18074
18072
  return [];
18075
18073
  }
18076
18074
  }
@@ -18298,7 +18296,7 @@ async function searchGrepApp(query, options) {
18298
18296
  }
18299
18297
  return results;
18300
18298
  } catch (error45) {
18301
- console.error("grep.app search error:", error45);
18299
+ log("grep.app search error:", error45);
18302
18300
  return [];
18303
18301
  }
18304
18302
  }
@@ -18339,7 +18337,7 @@ async function searchGitHub(query, options) {
18339
18337
  }
18340
18338
  return results;
18341
18339
  } catch (error45) {
18342
- console.error("GitHub search error:", error45);
18340
+ log("GitHub search error:", error45);
18343
18341
  return [];
18344
18342
  }
18345
18343
  }
@@ -18660,24 +18658,24 @@ There was a temporary processing issue. Please continue from where you left off.
18660
18658
  async function handleSessionError(client, sessionID, error45, properties) {
18661
18659
  const state2 = getState(sessionID);
18662
18660
  if (state2.isRecovering) {
18663
- log2("[session-recovery] Already recovering, skipping", { sessionID });
18661
+ log("[session-recovery] Already recovering, skipping", { sessionID });
18664
18662
  return false;
18665
18663
  }
18666
18664
  const now = Date.now();
18667
18665
  if (now - state2.lastErrorTime < BACKGROUND_TASK.RETRY_COOLDOWN_MS) {
18668
- log2("[session-recovery] Too soon since last error, skipping", { sessionID });
18666
+ log("[session-recovery] Too soon since last error, skipping", { sessionID });
18669
18667
  return false;
18670
18668
  }
18671
18669
  state2.lastErrorTime = now;
18672
18670
  state2.errorCount++;
18673
18671
  const errorType = detectErrorType(error45);
18674
18672
  if (!errorType) {
18675
- log2("[session-recovery] Unknown error type, using default handler", { sessionID, error: error45 });
18673
+ log("[session-recovery] Unknown error type, using default handler", { sessionID, error: error45 });
18676
18674
  return false;
18677
18675
  }
18678
- log2("[session-recovery] Detected error type", { sessionID, errorType, errorCount: state2.errorCount });
18676
+ log("[session-recovery] Detected error type", { sessionID, errorType, errorCount: state2.errorCount });
18679
18677
  if (state2.errorCount > RECOVERY.MAX_ATTEMPTS) {
18680
- log2("[session-recovery] Max recovery attempts exceeded", { sessionID });
18678
+ log("[session-recovery] Max recovery attempts exceeded", { sessionID });
18681
18679
  presets.warningMaxRetries();
18682
18680
  return false;
18683
18681
  }
@@ -18704,7 +18702,7 @@ async function handleSessionError(client, sessionID, error45, properties) {
18704
18702
  };
18705
18703
  const action = handleError(ctx);
18706
18704
  if (action.type === "retry" && action.delay) {
18707
- log2("[session-recovery] Rate limit, waiting", { delay: action.delay });
18705
+ log("[session-recovery] Rate limit, waiting", { delay: action.delay });
18708
18706
  await new Promise((r) => setTimeout(r, action.delay));
18709
18707
  }
18710
18708
  state2.isRecovering = false;
@@ -18714,7 +18712,7 @@ async function handleSessionError(client, sessionID, error45, properties) {
18714
18712
  state2.isRecovering = false;
18715
18713
  return false;
18716
18714
  case ERROR_TYPE.MESSAGE_ABORTED:
18717
- log2("[session-recovery] Message aborted by user, not recovering", { sessionID });
18715
+ log("[session-recovery] Message aborted by user, not recovering", { sessionID });
18718
18716
  state2.isRecovering = false;
18719
18717
  return false;
18720
18718
  default:
@@ -18729,14 +18727,14 @@ async function handleSessionError(client, sessionID, error45, properties) {
18729
18727
  parts: [{ type: PART_TYPES.TEXT, text: recoveryPrompt }]
18730
18728
  }
18731
18729
  });
18732
- log2("[session-recovery] Recovery prompt injected", { sessionID, errorType });
18730
+ log("[session-recovery] Recovery prompt injected", { sessionID, errorType });
18733
18731
  state2.isRecovering = false;
18734
18732
  return true;
18735
18733
  }
18736
18734
  state2.isRecovering = false;
18737
18735
  return false;
18738
18736
  } catch (injectionError) {
18739
- log2("[session-recovery] Failed to inject recovery prompt", { sessionID, error: injectionError });
18737
+ log("[session-recovery] Failed to inject recovery prompt", { sessionID, error: injectionError });
18740
18738
  state2.isRecovering = false;
18741
18739
  return false;
18742
18740
  }
@@ -18918,20 +18916,20 @@ async function showCountdownToast(client, secondsRemaining, incompleteCount) {
18918
18916
  async function injectContinuation(client, sessionID, todos) {
18919
18917
  const state2 = getState2(sessionID);
18920
18918
  if (state2.isAborting) {
18921
- log2("[todo-continuation] Skipped: user is aborting", { sessionID });
18919
+ log("[todo-continuation] Skipped: user is aborting", { sessionID });
18922
18920
  return;
18923
18921
  }
18924
18922
  if (hasRunningBackgroundTasks(sessionID)) {
18925
- log2("[todo-continuation] Skipped: background tasks running", { sessionID });
18923
+ log("[todo-continuation] Skipped: background tasks running", { sessionID });
18926
18924
  return;
18927
18925
  }
18928
18926
  if (isSessionRecovering(sessionID)) {
18929
- log2("[todo-continuation] Skipped: session is recovering from error", { sessionID });
18927
+ log("[todo-continuation] Skipped: session is recovering from error", { sessionID });
18930
18928
  return;
18931
18929
  }
18932
18930
  const prompt = generateContinuationPrompt(todos);
18933
18931
  if (!prompt) {
18934
- log2("[todo-continuation] Skipped: no continuation prompt needed", { sessionID });
18932
+ log("[todo-continuation] Skipped: no continuation prompt needed", { sessionID });
18935
18933
  return;
18936
18934
  }
18937
18935
  try {
@@ -18941,43 +18939,43 @@ async function injectContinuation(client, sessionID, todos) {
18941
18939
  parts: [{ type: PART_TYPES.TEXT, text: prompt }]
18942
18940
  }
18943
18941
  });
18944
- log2("[todo-continuation] Injected continuation prompt", {
18942
+ log("[todo-continuation] Injected continuation prompt", {
18945
18943
  sessionID,
18946
18944
  incompleteCount: getIncompleteCount(todos),
18947
18945
  progress: formatProgress(todos)
18948
18946
  });
18949
18947
  } catch (error45) {
18950
- log2("[todo-continuation] Failed to inject continuation", { sessionID, error: error45 });
18948
+ log("[todo-continuation] Failed to inject continuation", { sessionID, error: error45 });
18951
18949
  }
18952
18950
  }
18953
18951
  async function handleSessionIdle(client, sessionID, mainSessionID) {
18954
18952
  const state2 = getState2(sessionID);
18955
18953
  const now = Date.now();
18956
18954
  if (state2.lastIdleTime && now - state2.lastIdleTime < MIN_TIME_BETWEEN_CONTINUATIONS_MS) {
18957
- log2("[todo-continuation] Skipped: too soon since last check", { sessionID });
18955
+ log("[todo-continuation] Skipped: too soon since last check", { sessionID });
18958
18956
  return;
18959
18957
  }
18960
18958
  state2.lastIdleTime = now;
18961
18959
  cancelCountdown(sessionID);
18962
18960
  if (mainSessionID && sessionID !== mainSessionID) {
18963
- log2("[todo-continuation] Skipped: not main session", { sessionID, mainSessionID });
18961
+ log("[todo-continuation] Skipped: not main session", { sessionID, mainSessionID });
18964
18962
  return;
18965
18963
  }
18966
18964
  if (isSessionRecovering(sessionID)) {
18967
- log2("[todo-continuation] Skipped: in recovery mode", { sessionID });
18965
+ log("[todo-continuation] Skipped: in recovery mode", { sessionID });
18968
18966
  return;
18969
18967
  }
18970
18968
  if (state2.abortDetectedAt) {
18971
18969
  const timeSinceAbort = Date.now() - state2.abortDetectedAt;
18972
18970
  if (timeSinceAbort < ABORT_WINDOW_MS) {
18973
- log2("[todo-continuation] Skipped: abort detected recently", { sessionID, timeSinceAbort });
18971
+ log("[todo-continuation] Skipped: abort detected recently", { sessionID, timeSinceAbort });
18974
18972
  state2.abortDetectedAt = void 0;
18975
18973
  return;
18976
18974
  }
18977
18975
  state2.abortDetectedAt = void 0;
18978
18976
  }
18979
18977
  if (hasRunningBackgroundTasks(sessionID)) {
18980
- log2("[todo-continuation] Skipped: background tasks running", { sessionID });
18978
+ log("[todo-continuation] Skipped: background tasks running", { sessionID });
18981
18979
  return;
18982
18980
  }
18983
18981
  let todos = [];
@@ -18985,16 +18983,16 @@ async function handleSessionIdle(client, sessionID, mainSessionID) {
18985
18983
  const response = await client.session.todo({ path: { id: sessionID } });
18986
18984
  todos = parseTodos(response.data ?? response);
18987
18985
  } catch (error45) {
18988
- log2("[todo-continuation] Failed to fetch todos", { sessionID, error: error45 });
18986
+ log("[todo-continuation] Failed to fetch todos", { sessionID, error: error45 });
18989
18987
  return;
18990
18988
  }
18991
18989
  if (!hasRemainingWork(todos)) {
18992
- log2("[todo-continuation] All todos complete", { sessionID });
18990
+ log("[todo-continuation] All todos complete", { sessionID });
18993
18991
  return;
18994
18992
  }
18995
18993
  const incompleteCount = getIncompleteCount(todos);
18996
18994
  const nextPending = getNextPending(todos);
18997
- log2("[todo-continuation] Starting countdown", {
18995
+ log("[todo-continuation] Starting countdown", {
18998
18996
  sessionID,
18999
18997
  incompleteCount,
19000
18998
  nextPending: nextPending?.id
@@ -19009,10 +19007,10 @@ async function handleSessionIdle(client, sessionID, mainSessionID) {
19009
19007
  if (hasRemainingWork(freshTodos)) {
19010
19008
  await injectContinuation(client, sessionID, freshTodos);
19011
19009
  } else {
19012
- log2("[todo-continuation] Todos completed during countdown", { sessionID });
19010
+ log("[todo-continuation] Todos completed during countdown", { sessionID });
19013
19011
  }
19014
19012
  } catch {
19015
- log2("[todo-continuation] Failed to re-fetch todos for continuation", { sessionID });
19013
+ log("[todo-continuation] Failed to re-fetch todos for continuation", { sessionID });
19016
19014
  }
19017
19015
  }, COUNTDOWN_SECONDS * TIME.SECOND);
19018
19016
  }
@@ -19021,12 +19019,12 @@ function handleUserMessage(sessionID) {
19021
19019
  if (state2.countdownStartedAt) {
19022
19020
  const elapsed = Date.now() - state2.countdownStartedAt;
19023
19021
  if (elapsed < COUNTDOWN_GRACE_PERIOD_MS) {
19024
- log2("[todo-continuation] Ignoring message in grace period", { sessionID, elapsed });
19022
+ log("[todo-continuation] Ignoring message in grace period", { sessionID, elapsed });
19025
19023
  return;
19026
19024
  }
19027
19025
  }
19028
19026
  if (state2.countdownTimer) {
19029
- log2("[todo-continuation] Cancelled: user interaction", { sessionID });
19027
+ log("[todo-continuation] Cancelled: user interaction", { sessionID });
19030
19028
  cancelCountdown(sessionID);
19031
19029
  }
19032
19030
  state2.isAborting = false;
@@ -19037,7 +19035,7 @@ function handleSessionError2(sessionID, error45) {
19037
19035
  const errorObj = error45;
19038
19036
  if (errorObj?.name === "MessageAbortedError" || errorObj?.name === "AbortError") {
19039
19037
  state2.abortDetectedAt = Date.now();
19040
- log2("[todo-continuation] Abort detected", { sessionID, errorName: errorObj.name });
19038
+ log("[todo-continuation] Abort detected", { sessionID, errorName: errorObj.name });
19041
19039
  }
19042
19040
  cancelCountdown(sessionID);
19043
19041
  }
@@ -19071,7 +19069,7 @@ function readLoopState(directory) {
19071
19069
  const content = readFileSync(filePath, "utf-8");
19072
19070
  return JSON.parse(content);
19073
19071
  } catch (error45) {
19074
- log2(`[mission-seal] Failed to read state: ${error45}`);
19072
+ log(`[mission-seal] Failed to read state: ${error45}`);
19075
19073
  return null;
19076
19074
  }
19077
19075
  }
@@ -19085,7 +19083,7 @@ function writeLoopState(directory, state2) {
19085
19083
  writeFileSync(filePath, JSON.stringify(state2, null, 2), "utf-8");
19086
19084
  return true;
19087
19085
  } catch (error45) {
19088
- log2(`[mission-seal] Failed to write state: ${error45}`);
19086
+ log(`[mission-seal] Failed to write state: ${error45}`);
19089
19087
  return false;
19090
19088
  }
19091
19089
  }
@@ -19098,7 +19096,7 @@ function clearLoopState(directory) {
19098
19096
  unlinkSync(filePath);
19099
19097
  return true;
19100
19098
  } catch (error45) {
19101
- log2(`[mission-seal] Failed to clear state: ${error45}`);
19099
+ log(`[mission-seal] Failed to clear state: ${error45}`);
19102
19100
  return false;
19103
19101
  }
19104
19102
  }
@@ -19134,7 +19132,7 @@ async function detectSealInSession(client, sessionID) {
19134
19132
  }
19135
19133
  return false;
19136
19134
  } catch (error45) {
19137
- log2(`[mission-seal] Failed to check session messages: ${error45}`);
19135
+ log(`[mission-seal] Failed to check session messages: ${error45}`);
19138
19136
  return false;
19139
19137
  }
19140
19138
  }
@@ -19149,7 +19147,7 @@ function startMissionLoop(directory, sessionID, prompt, options = {}) {
19149
19147
  };
19150
19148
  const success2 = writeLoopState(directory, state2);
19151
19149
  if (success2) {
19152
- log2(`[mission-seal] Loop started`, {
19150
+ log(`[mission-seal] Loop started`, {
19153
19151
  sessionID,
19154
19152
  maxIterations: state2.maxIterations
19155
19153
  });
@@ -19276,20 +19274,20 @@ async function showMaxIterationsToast(client, state2) {
19276
19274
  async function injectContinuation2(client, directory, sessionID, loopState) {
19277
19275
  const handlerState = getState3(sessionID);
19278
19276
  if (handlerState.isAborting) {
19279
- log2("[mission-seal-handler] Skipped: user is aborting");
19277
+ log("[mission-seal-handler] Skipped: user is aborting");
19280
19278
  return;
19281
19279
  }
19282
19280
  if (hasRunningBackgroundTasks2(sessionID)) {
19283
- log2("[mission-seal-handler] Skipped: background tasks running");
19281
+ log("[mission-seal-handler] Skipped: background tasks running");
19284
19282
  return;
19285
19283
  }
19286
19284
  if (isSessionRecovering(sessionID)) {
19287
- log2("[mission-seal-handler] Skipped: session recovering");
19285
+ log("[mission-seal-handler] Skipped: session recovering");
19288
19286
  return;
19289
19287
  }
19290
19288
  const sealDetected = await detectSealInSession(client, sessionID);
19291
19289
  if (sealDetected) {
19292
- log2("[mission-seal-handler] Seal detected before injection, completing");
19290
+ log("[mission-seal-handler] Seal detected before injection, completing");
19293
19291
  await handleSealDetected(client, directory, loopState);
19294
19292
  return;
19295
19293
  }
@@ -19301,18 +19299,18 @@ async function injectContinuation2(client, directory, sessionID, loopState) {
19301
19299
  parts: [{ type: PART_TYPES.TEXT, text: prompt }]
19302
19300
  }
19303
19301
  });
19304
- log2("[mission-seal-handler] Continuation injected", {
19302
+ log("[mission-seal-handler] Continuation injected", {
19305
19303
  sessionID,
19306
19304
  iteration: loopState.iteration
19307
19305
  });
19308
19306
  } catch (error45) {
19309
- log2(`[mission-seal-handler] Failed to inject: ${error45}`);
19307
+ log(`[mission-seal-handler] Failed to inject: ${error45}`);
19310
19308
  }
19311
19309
  }
19312
19310
  async function handleSealDetected(client, directory, loopState) {
19313
19311
  clearLoopState(directory);
19314
19312
  await showSealedToast(client, loopState);
19315
- log2("[mission-seal-handler] Mission sealed!", {
19313
+ log("[mission-seal-handler] Mission sealed!", {
19316
19314
  sessionID: loopState.sessionID,
19317
19315
  iterations: loopState.iteration
19318
19316
  });
@@ -19320,7 +19318,7 @@ async function handleSealDetected(client, directory, loopState) {
19320
19318
  async function handleMaxIterations(client, directory, loopState) {
19321
19319
  clearLoopState(directory);
19322
19320
  await showMaxIterationsToast(client, loopState);
19323
- log2("[mission-seal-handler] Max iterations reached", {
19321
+ log("[mission-seal-handler] Max iterations reached", {
19324
19322
  sessionID: loopState.sessionID,
19325
19323
  iterations: loopState.iteration,
19326
19324
  max: loopState.maxIterations
@@ -19338,11 +19336,11 @@ async function handleMissionSealIdle(client, directory, sessionID, mainSessionID
19338
19336
  return;
19339
19337
  }
19340
19338
  if (isSessionRecovering(sessionID)) {
19341
- log2("[mission-seal-handler] Skipped: recovering");
19339
+ log("[mission-seal-handler] Skipped: recovering");
19342
19340
  return;
19343
19341
  }
19344
19342
  if (hasRunningBackgroundTasks2(sessionID)) {
19345
- log2("[mission-seal-handler] Skipped: background tasks");
19343
+ log("[mission-seal-handler] Skipped: background tasks");
19346
19344
  return;
19347
19345
  }
19348
19346
  const loopState = readLoopState(directory);
@@ -19352,7 +19350,7 @@ async function handleMissionSealIdle(client, directory, sessionID, mainSessionID
19352
19350
  if (loopState.sessionID !== sessionID) {
19353
19351
  return;
19354
19352
  }
19355
- log2("[mission-seal-handler] Checking for seal", {
19353
+ log("[mission-seal-handler] Checking for seal", {
19356
19354
  sessionID,
19357
19355
  iteration: loopState.iteration
19358
19356
  });
@@ -19367,7 +19365,7 @@ async function handleMissionSealIdle(client, directory, sessionID, mainSessionID
19367
19365
  }
19368
19366
  const newState = incrementIteration(directory);
19369
19367
  if (!newState) {
19370
- log2("[mission-seal-handler] Failed to increment iteration");
19368
+ log("[mission-seal-handler] Failed to increment iteration");
19371
19369
  return;
19372
19370
  }
19373
19371
  await showCountdownToast2(client, COUNTDOWN_SECONDS2, newState.iteration, newState.maxIterations);
@@ -19375,7 +19373,7 @@ async function handleMissionSealIdle(client, directory, sessionID, mainSessionID
19375
19373
  cancelCountdown2(sessionID);
19376
19374
  await injectContinuation2(client, directory, sessionID, newState);
19377
19375
  }, COUNTDOWN_SECONDS2 * 1e3);
19378
- log2("[mission-seal-handler] Countdown started", {
19376
+ log("[mission-seal-handler] Countdown started", {
19379
19377
  sessionID,
19380
19378
  iteration: newState.iteration,
19381
19379
  seconds: COUNTDOWN_SECONDS2
@@ -19384,7 +19382,7 @@ async function handleMissionSealIdle(client, directory, sessionID, mainSessionID
19384
19382
  function handleUserMessage2(sessionID) {
19385
19383
  const state2 = getState3(sessionID);
19386
19384
  if (state2.countdownTimer) {
19387
- log2("[mission-seal-handler] Cancelled by user interaction");
19385
+ log("[mission-seal-handler] Cancelled by user interaction");
19388
19386
  cancelCountdown2(sessionID);
19389
19387
  }
19390
19388
  state2.isAborting = false;
@@ -19393,7 +19391,7 @@ function handleAbort(sessionID) {
19393
19391
  const state2 = getState3(sessionID);
19394
19392
  state2.isAborting = true;
19395
19393
  cancelCountdown2(sessionID);
19396
- log2("[mission-seal-handler] Marked as aborting");
19394
+ log("[mission-seal-handler] Marked as aborting");
19397
19395
  }
19398
19396
  function cleanupSession2(sessionID) {
19399
19397
  cancelCountdown2(sessionID);
@@ -19408,7 +19406,7 @@ function cleanupSession3(sessionID) {
19408
19406
  clearInterval(state2.intervalId);
19409
19407
  }
19410
19408
  sessionStates3.delete(sessionID);
19411
- log2("[context-window-monitor] Session cleaned up", { sessionID });
19409
+ log("[context-window-monitor] Session cleaned up", { sessionID });
19412
19410
  }
19413
19411
 
19414
19412
  // src/plugin-handlers/event-handler.ts
@@ -19423,7 +19421,7 @@ function createEventHandler(ctx) {
19423
19421
  }
19424
19422
  if (event.type === SESSION_EVENTS.CREATED) {
19425
19423
  const sessionID = event.properties?.id || "";
19426
- log2("[event-handler] session.created", { sessionID });
19424
+ log("[event-handler] session.created", { sessionID });
19427
19425
  presets.missionStarted(`Session ${sessionID.slice(0, 12)}...`);
19428
19426
  }
19429
19427
  if (event.type === SESSION_EVENTS.DELETED) {
@@ -19432,7 +19430,7 @@ function createEventHandler(ctx) {
19432
19430
  if (session) {
19433
19431
  const totalTime = Date.now() - session.startTime;
19434
19432
  const duration3 = totalTime < 6e4 ? `${Math.round(totalTime / 1e3)}s` : `${Math.round(totalTime / 6e4)}m`;
19435
- log2("[event-handler] session.deleted", { sessionID, steps: session.step, duration: duration3 });
19433
+ log("[event-handler] session.deleted", { sessionID, steps: session.step, duration: duration3 });
19436
19434
  sessions.delete(sessionID);
19437
19435
  state2.sessions.delete(sessionID);
19438
19436
  clearSession(sessionID);
@@ -19446,7 +19444,7 @@ function createEventHandler(ctx) {
19446
19444
  if (event.type === SESSION_EVENTS.ERROR) {
19447
19445
  const sessionID = event.properties?.sessionId || event.properties?.sessionID || "";
19448
19446
  const error45 = event.properties?.error;
19449
- log2("[event-handler] session.error", { sessionID, error: error45 });
19447
+ log("[event-handler] session.error", { sessionID, error: error45 });
19450
19448
  if (sessionID) {
19451
19449
  handleSessionError2(sessionID, error45);
19452
19450
  handleAbort(sessionID);
@@ -19459,7 +19457,7 @@ function createEventHandler(ctx) {
19459
19457
  event.properties
19460
19458
  );
19461
19459
  if (recovered) {
19462
- log2("[event-handler] auto-recovery initiated", { sessionID });
19460
+ log("[event-handler] auto-recovery initiated", { sessionID });
19463
19461
  return;
19464
19462
  }
19465
19463
  }
@@ -19491,13 +19489,13 @@ function createEventHandler(ctx) {
19491
19489
  directory,
19492
19490
  sessionID,
19493
19491
  sessionID
19494
- ).catch((err) => log2("[event-handler] mission-seal-handler error", err));
19492
+ ).catch((err) => log("[event-handler] mission-seal-handler error", err));
19495
19493
  } else {
19496
19494
  await handleSessionIdle(
19497
19495
  client,
19498
19496
  sessionID,
19499
19497
  sessionID
19500
- ).catch((err) => log2("[event-handler] todo-continuation error", err));
19498
+ ).catch((err) => log("[event-handler] todo-continuation error", err));
19501
19499
  }
19502
19500
  }
19503
19501
  }, 500);
@@ -19615,7 +19613,7 @@ function createChatMessageHandler(ctx) {
19615
19613
  const parsed = detectSlashCommand(originalText);
19616
19614
  const sessionID = msgInput.sessionID;
19617
19615
  const agentName = (msgInput.agent || "").toLowerCase();
19618
- log2("[chat-message-handler] hook triggered", { sessionID, agent: agentName, textLength: originalText.length });
19616
+ log("[chat-message-handler] hook triggered", { sessionID, agent: agentName, textLength: originalText.length });
19619
19617
  if (sessionID) {
19620
19618
  handleUserMessage(sessionID);
19621
19619
  }
@@ -19648,7 +19646,7 @@ function createChatMessageHandler(ctx) {
19648
19646
  userMessage || PROMPTS.CONTINUE
19649
19647
  );
19650
19648
  startMissionLoop(directory, sessionID, userMessage || originalText);
19651
- log2("[chat-message-handler] Auto-applied mission mode + started loop", { originalLength: originalText.length });
19649
+ log("[chat-message-handler] Auto-applied mission mode + started loop", { originalLength: originalText.length });
19652
19650
  }
19653
19651
  }
19654
19652
  if (parsed) {
@@ -19678,14 +19676,14 @@ function createChatMessageHandler(ctx) {
19678
19676
  anomalyCount: 0
19679
19677
  });
19680
19678
  startSession(sessionID);
19681
- log2("[chat-message-handler] Session registered for /task command", { sessionID, agent: agentName });
19679
+ log("[chat-message-handler] Session registered for /task command", { sessionID, agent: agentName });
19682
19680
  }
19683
19681
  parts[textPartIndex].text = command.template.replace(
19684
19682
  /\$ARGUMENTS/g,
19685
19683
  parsed.args || PROMPTS.CONTINUE
19686
19684
  );
19687
19685
  startMissionLoop(directory, sessionID, parsed.args || "continue from where we left off");
19688
- log2("[chat-message-handler] /task command: started mission loop", { sessionID, args: parsed.args?.slice(0, 50) });
19686
+ log("[chat-message-handler] /task command: started mission loop", { sessionID, args: parsed.args?.slice(0, 50) });
19689
19687
  }
19690
19688
  }
19691
19689
  };
@@ -19958,7 +19956,7 @@ function createAssistantDoneHandler(ctx) {
19958
19956
  state.missionActive = false;
19959
19957
  clearLoopState(directory);
19960
19958
  presets.missionComplete("Mission Sealed - Explicit completion confirmed");
19961
- log2("[assistant-done-handler] Mission sealed detected", { sessionID });
19959
+ log("[assistant-done-handler] Mission sealed detected", { sessionID });
19962
19960
  clearSession(sessionID);
19963
19961
  sessions.delete(sessionID);
19964
19962
  state.sessions.delete(sessionID);
@@ -19999,7 +19997,7 @@ function createAssistantDoneHandler(ctx) {
19999
19997
  });
20000
19998
  }
20001
19999
  } catch (error45) {
20002
- log2("[assistant-done-handler] Continuation injection failed, retrying...", { sessionID, error: error45 });
20000
+ log("[assistant-done-handler] Continuation injection failed, retrying...", { sessionID, error: error45 });
20003
20001
  try {
20004
20002
  await new Promise((r) => setTimeout(r, 500));
20005
20003
  if (client?.session?.prompt) {
@@ -20009,13 +20007,13 @@ function createAssistantDoneHandler(ctx) {
20009
20007
  });
20010
20008
  }
20011
20009
  } catch (retryError) {
20012
- log2("[assistant-done-handler] Both continuation attempts failed, waiting for idle handler", {
20010
+ log("[assistant-done-handler] Both continuation attempts failed, waiting for idle handler", {
20013
20011
  sessionID,
20014
20012
  error: retryError,
20015
20013
  loopActive: isLoopActive(directory, sessionID)
20016
20014
  });
20017
20015
  if (!isLoopActive(directory, sessionID)) {
20018
- log2("[assistant-done-handler] No active loop, stopping session", { sessionID });
20016
+ log("[assistant-done-handler] No active loop, stopping session", { sessionID });
20019
20017
  session.active = false;
20020
20018
  state.missionActive = false;
20021
20019
  }
@@ -20029,16 +20027,16 @@ var require2 = createRequire(import.meta.url);
20029
20027
  var { version: PLUGIN_VERSION } = require2("../package.json");
20030
20028
  var OrchestratorPlugin = async (input) => {
20031
20029
  const { directory, client } = input;
20032
- log2(`[orchestrator] v${PLUGIN_VERSION} loaded, log: ${getLogPath()}`);
20033
- log2("[index.ts] Plugin initialized", { version: PLUGIN_VERSION, directory });
20030
+ log(`[orchestrator] v${PLUGIN_VERSION} loaded, log: ${getLogPath()}`);
20031
+ log("[index.ts] Plugin initialized", { version: PLUGIN_VERSION, directory });
20034
20032
  initToastClient(client);
20035
20033
  const taskToastManager = initTaskToastManager(client);
20036
- log2("[index.ts] Toast notifications enabled with TUI and TaskToastManager");
20034
+ log("[index.ts] Toast notifications enabled with TUI and TaskToastManager");
20037
20035
  const sessions = /* @__PURE__ */ new Map();
20038
20036
  const parallelAgentManager2 = ParallelAgentManager.getInstance(client, directory);
20039
20037
  const asyncAgentTools = createAsyncAgentTools(parallelAgentManager2, client);
20040
20038
  taskToastManager.setConcurrencyController(parallelAgentManager2.getConcurrency());
20041
- log2("[index.ts] ParallelAgentManager initialized with TaskToastManager integration");
20039
+ log("[index.ts] ParallelAgentManager initialized with TaskToastManager integration");
20042
20040
  const handlerContext = {
20043
20041
  client,
20044
20042
  directory,
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "opencode-orchestrator",
3
3
  "displayName": "OpenCode Orchestrator",
4
4
  "description": "Distributed Cognitive Architecture for OpenCode. Turns simple prompts into specialized multi-agent workflows (Planner, Coder, Reviewer).",
5
- "version": "0.9.68",
5
+ "version": "0.9.69",
6
6
  "author": "agnusdei1207",
7
7
  "license": "MIT",
8
8
  "repository": {
@@ -51,7 +51,6 @@
51
51
  "build": "shx rm -rf dist && npx esbuild src/index.ts --bundle --outfile=dist/index.js --platform=node --format=esm && tsc --emitDeclarationOnly && shx mkdir -p dist/scripts && npx esbuild scripts/postinstall.ts --bundle --outfile=dist/scripts/postinstall.js --platform=node --format=esm && npx esbuild scripts/preuninstall.ts --bundle --outfile=dist/scripts/preuninstall.js --platform=node --format=esm",
52
52
  "build:all": "npm run build && npm run rust:dist",
53
53
  "test": "vitest run --reporter=verbose",
54
- "test:watch": "vitest",
55
54
  "test:coverage": "vitest run --coverage",
56
55
  "test:unit": "vitest run tests/unit --reporter=verbose",
57
56
  "test:e2e": "vitest run tests/e2e --reporter=verbose",
@@ -62,11 +61,6 @@
62
61
  "release:patch": "npm run build && npm run rust:dist && npm version patch && git push --follow-tags && npm publish --access public",
63
62
  "release:minor": "npm run build && npm run rust:dist && npm version minor && git push --follow-tags && npm publish --access public",
64
63
  "release:major": "npm run build && npm run rust:dist && npm version major && git push --follow-tags && npm publish --access public",
65
- "dev:clean": "shx rm -rf $(npm root -g)/opencode-orchestrator /opt/homebrew/lib/node_modules/opencode-orchestrator 2>/dev/null; npm cache clean --force && echo 'Cleaned: NVM + Homebrew + cache'",
66
- "dev:link": "npm run build && npm link && /opt/homebrew/bin/npm link 2>/dev/null; echo 'SUCCESS: Linked to NVM + Homebrew. Restart OpenCode.'",
67
- "dev:unlink": "npm unlink -g opencode-orchestrator 2>/dev/null; /opt/homebrew/bin/npm unlink -g opencode-orchestrator 2>/dev/null; npm run dev:clean && echo 'SUCCESS: Unlinked from all'",
68
- "dev:status": "echo '=== NVM ===' && ls -la $(npm root -g)/opencode-orchestrator 2>/dev/null || echo 'Not linked'; echo '=== Homebrew ===' && ls -la /opt/homebrew/lib/node_modules/opencode-orchestrator 2>/dev/null || echo 'Not linked'",
69
- "dev:test": "node dist/scripts/postinstall.js && echo '---' && node dist/scripts/preuninstall.js",
70
64
  "reset:local": "brew uninstall opencode 2>/dev/null; rm -rf ~/.config/opencode ~/.opencode ~/.local/share/opencode ~/.cache/opencode/node_modules/opencode-orchestrator && echo '=== Clean done ===' && brew install opencode && echo '{\"plugin\": [\"opencode-orchestrator\"], \"$schema\": \"https://opencode.ai/config.json\"}' > ~/.config/opencode/opencode.json && echo '=== Reset (Dev) complete. Run: opencode ==='",
71
65
  "reset:prod": "brew uninstall opencode 2>/dev/null; rm -rf ~/.config/opencode ~/.opencode ~/.local/share/opencode ~/.cache/opencode/node_modules/opencode-orchestrator && echo '=== Clean done ===' && brew install opencode && echo '{\"plugin\": [\"opencode-orchestrator\"], \"$schema\": \"https://opencode.ai/config.json\"}' > ~/.config/opencode/opencode.json && npm install -g opencode-orchestrator && echo '=== Reset (Prod) complete. Run: opencode ==='",
72
66
  "ginstall": "npm install -g opencode-orchestrator",