chatroom-cli 1.101.5 → 1.102.1

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
@@ -27764,6 +27764,30 @@ var init_base_cli_agent_service = __esm(() => {
27764
27764
  retrySchedule = exports_Schedule.exponential(exports_Duration.millis(DETECTION_RETRY_POLICY.initialDelayMs), DETECTION_RETRY_POLICY.backoffFactor).pipe(exports_Schedule.either(exports_Schedule.spaced(exports_Duration.millis(DETECTION_RETRY_POLICY.maxDelayMs))), exports_Schedule.compose(exports_Schedule.recurs(DETECTION_RETRY_POLICY.maxAttempts - 1)));
27765
27765
  });
27766
27766
 
27767
+ // src/daemon/infrastructure/agent-process-manager/harness-activity-emitter.ts
27768
+ function createHarnessActivityEmitter() {
27769
+ let progressReportedForTurn = false;
27770
+ const listeners = new Set;
27771
+ return {
27772
+ beginTurn: () => {
27773
+ progressReportedForTurn = false;
27774
+ },
27775
+ emit: (event) => {
27776
+ const isFirstForTurn = event.kind === "progress" && !progressReportedForTurn;
27777
+ if (event.kind === "progress")
27778
+ progressReportedForTurn = true;
27779
+ const signal = { ...event, isFirstForTurn };
27780
+ for (const cb of listeners)
27781
+ cb(signal);
27782
+ },
27783
+ onActivity: (cb) => {
27784
+ listeners.add(cb);
27785
+ return () => listeners.delete(cb);
27786
+ }
27787
+ };
27788
+ }
27789
+ var init_harness_activity_emitter = () => {};
27790
+
27767
27791
  // src/daemon/infrastructure/local/harness/services/session-log-callbacks.ts
27768
27792
  function createSessionLogCallbacks() {
27769
27793
  let logCb;
@@ -27779,6 +27803,7 @@ function createSessionLogCallbacks() {
27779
27803
  // src/daemon/infrastructure/local/harness/services/opencode/opencode-agent-service.ts
27780
27804
  var OPENCODE_COMMAND = "opencode", OpenCodeAgentService;
27781
27805
  var init_opencode_agent_service = __esm(() => {
27806
+ init_harness_activity_emitter();
27782
27807
  init_base_cli_agent_service();
27783
27808
  OpenCodeAgentService = class OpenCodeAgentService extends BaseCLIAgentService {
27784
27809
  id = "opencode";
@@ -27808,6 +27833,8 @@ var init_opencode_agent_service = __esm(() => {
27808
27833
  const fullPrompt = options.systemPrompt ? `${options.systemPrompt}
27809
27834
 
27810
27835
  ${options.prompt}` : options.prompt;
27836
+ const activityEmitter = createHarnessActivityEmitter();
27837
+ activityEmitter.beginTurn();
27811
27838
  const childProcess = this.deps.spawn(OPENCODE_COMMAND, args2, {
27812
27839
  cwd: options.workingDir,
27813
27840
  stdio: ["pipe", "pipe", "pipe"],
@@ -27822,9 +27849,18 @@ ${options.prompt}` : options.prompt;
27822
27849
  const entry = this.registerProcess(pid, context5);
27823
27850
  const { onLogLine, emitFormatted } = createSessionLogCallbacks();
27824
27851
  const outputCallbacks = [];
27852
+ let processFailureEmitted = false;
27853
+ const emitActivity = (kind, source) => {
27854
+ activityEmitter.emit({ kind, source, at: Date.now() });
27855
+ };
27825
27856
  if (childProcess.stdout) {
27826
27857
  childProcess.stdout.on("data", (chunk2) => {
27827
- emitFormatted(chunk2.toString("utf8"), "stdout");
27858
+ const text = chunk2.toString("utf8");
27859
+ emitActivity("transport", "opencode-cli.stdout");
27860
+ if (text.trim().length > 0) {
27861
+ emitActivity("progress", "opencode-cli.assistant.text");
27862
+ }
27863
+ emitFormatted(text, "stdout");
27828
27864
  entry.lastOutputAt = Date.now();
27829
27865
  for (const cb of outputCallbacks)
27830
27866
  cb();
@@ -27832,6 +27868,7 @@ ${options.prompt}` : options.prompt;
27832
27868
  }
27833
27869
  if (childProcess.stderr) {
27834
27870
  childProcess.stderr.on("data", (chunk2) => {
27871
+ emitActivity("transport", "opencode-cli.stderr");
27835
27872
  emitFormatted(chunk2.toString("utf8"), "stderr");
27836
27873
  entry.lastOutputAt = Date.now();
27837
27874
  for (const cb of outputCallbacks)
@@ -27840,9 +27877,14 @@ ${options.prompt}` : options.prompt;
27840
27877
  }
27841
27878
  return {
27842
27879
  pid,
27880
+ activityEmitter,
27843
27881
  onExit: (cb) => {
27844
27882
  childProcess.on("exit", (code2, signal) => {
27845
27883
  this.deleteProcess(pid);
27884
+ if (!processFailureEmitted && (code2 !== null && code2 !== 0 || signal !== null)) {
27885
+ processFailureEmitted = true;
27886
+ emitActivity("failure", "opencode-cli.process");
27887
+ }
27846
27888
  cb({ code: code2, signal, context: context5 });
27847
27889
  });
27848
27890
  },
@@ -27906,10 +27948,19 @@ class PiRpcReader {
27906
27948
  } catch {
27907
27949
  return;
27908
27950
  }
27951
+ const metadata = {
27952
+ type: typeof event["type"] === "string" ? event["type"] : "unknown",
27953
+ isError: this._isErrorEvent(event)
27954
+ };
27909
27955
  for (const cb of this.anyEventCallbacks)
27910
- cb();
27956
+ cb(metadata);
27911
27957
  this._dispatchEvent(event);
27912
27958
  }
27959
+ _isErrorEvent(event) {
27960
+ if (event["is_error"] === true || event["isError"] === true)
27961
+ return true;
27962
+ return "error" in event && event["error"] !== undefined;
27963
+ }
27913
27964
  eventHandlers = {
27914
27965
  response: (event) => {
27915
27966
  if (event["command"] === "get_state")
@@ -28066,6 +28117,14 @@ var BASH_TOOL_KIND = "tool: bash", BASH_RUNNING_PREFIX = "running:";
28066
28117
 
28067
28118
  // src/daemon/infrastructure/local/harness/services/pi/pi-agent-service.ts
28068
28119
  import { join as join6 } from "node:path";
28120
+ function isExplicitToolError(result) {
28121
+ if (result === null || typeof result !== "object")
28122
+ return false;
28123
+ const obj = result;
28124
+ if (obj.is_error === true || obj.isError === true)
28125
+ return true;
28126
+ return "error" in obj && obj.error !== undefined;
28127
+ }
28069
28128
  function getPiSessionDir(workingDir) {
28070
28129
  return join6(workingDir, ".chatroom", "pi-sessions");
28071
28130
  }
@@ -28073,6 +28132,7 @@ var PI_COMMAND = "pi", GET_STATE_TIMEOUT_MS = 5000, SPAWN_READY_DELAY_MS2 = 500,
28073
28132
  var init_pi_agent_service = __esm(() => {
28074
28133
  init_pi_rpc_reader();
28075
28134
  init_spawn_env();
28135
+ init_harness_activity_emitter();
28076
28136
  init_base_cli_agent_service();
28077
28137
  PiAgentService = class PiAgentService extends BaseCLIAgentService {
28078
28138
  id = "pi";
@@ -28120,14 +28180,17 @@ var init_pi_agent_service = __esm(() => {
28120
28180
  if (!childProcess.stdout) {
28121
28181
  throw new Error("Pi RPC process has no stdout");
28122
28182
  }
28183
+ const activityEmitter = createHarnessActivityEmitter();
28123
28184
  const reader = new PiRpcReader(childProcess.stdout);
28124
28185
  const harnessSessionId = await this.querySessionId(reader, childProcess.stdin);
28186
+ activityEmitter.beginTurn();
28125
28187
  await this.writePrompt(childProcess, prompt);
28126
28188
  return this.wireRpcProcess({
28127
28189
  childProcess,
28128
28190
  context: context5,
28129
28191
  harnessSessionId,
28130
- reader
28192
+ reader,
28193
+ activityEmitter
28131
28194
  });
28132
28195
  }
28133
28196
  spawnPiRpcProcess(args2) {
@@ -28184,7 +28247,7 @@ var init_pi_agent_service = __esm(() => {
28184
28247
  });
28185
28248
  }
28186
28249
  wireRpcProcess(args2) {
28187
- const { childProcess, context: context5, harnessSessionId } = args2;
28250
+ const { childProcess, context: context5, harnessSessionId, activityEmitter } = args2;
28188
28251
  const pid = childProcess.pid;
28189
28252
  if (pid == null) {
28190
28253
  throw new Error("Pi RPC process has no PID");
@@ -28216,12 +28279,17 @@ var init_pi_agent_service = __esm(() => {
28216
28279
  const baseResult = {
28217
28280
  pid,
28218
28281
  harnessSessionId,
28282
+ activityEmitter,
28219
28283
  onExit: onExit4,
28220
28284
  onOutput,
28221
28285
  onLogLine
28222
28286
  };
28223
28287
  const log4 = createAgentLogWriter(logPrefix, { emitLogLine, suppressConsole: true });
28288
+ const emitActivity = (kind, source) => {
28289
+ activityEmitter.emit({ kind, source, at: Date.now() });
28290
+ };
28224
28291
  const onStderrData = (chunk2) => {
28292
+ emitActivity("transport", "pi-cli.stderr");
28225
28293
  entry.lastOutputAt = Date.now();
28226
28294
  for (const cb of outputCallbacks)
28227
28295
  cb();
@@ -28256,6 +28324,7 @@ var init_pi_agent_service = __esm(() => {
28256
28324
  cb();
28257
28325
  };
28258
28326
  reader.onTextDelta((delta) => {
28327
+ emitActivity("progress", "pi-cli.assistant.text");
28259
28328
  flushThinking();
28260
28329
  textBuffer += delta;
28261
28330
  if (textBuffer.includes(`
@@ -28264,6 +28333,7 @@ var init_pi_agent_service = __esm(() => {
28264
28333
  notifyOutput();
28265
28334
  });
28266
28335
  reader.onThinkingDelta((delta) => {
28336
+ emitActivity("progress", "pi-cli.assistant.thinking");
28267
28337
  flushText();
28268
28338
  thinkingBuffer += delta;
28269
28339
  if (thinkingBuffer.includes(`
@@ -28271,8 +28341,12 @@ var init_pi_agent_service = __esm(() => {
28271
28341
  flushThinking();
28272
28342
  notifyOutput();
28273
28343
  });
28274
- reader.onAnyEvent(() => {
28344
+ reader.onAnyEvent((metadata) => {
28275
28345
  notifyOutput();
28346
+ emitActivity("transport", "pi-cli.message");
28347
+ if (metadata.isError) {
28348
+ emitActivity("failure", "pi-cli.message");
28349
+ }
28276
28350
  });
28277
28351
  reader.onAgentEnd(() => {
28278
28352
  flushText();
@@ -28282,6 +28356,8 @@ var init_pi_agent_service = __esm(() => {
28282
28356
  cb();
28283
28357
  });
28284
28358
  reader.onToolCall((name, toolArgs) => {
28359
+ emitActivity("progress", "pi-cli.tool-call");
28360
+ emitActivity("waiting", "pi-cli.tool-call");
28285
28361
  flushText();
28286
28362
  flushThinking();
28287
28363
  const bashCmd = resolveBashCommandForLog(name, toolArgs);
@@ -28293,6 +28369,10 @@ var init_pi_agent_service = __esm(() => {
28293
28369
  log4.write("tool", `${name}${argsStr}`);
28294
28370
  });
28295
28371
  reader.onToolResult((name, result) => {
28372
+ emitActivity("progress", "pi-cli.tool-result");
28373
+ if (isExplicitToolError(result)) {
28374
+ emitActivity("failure", "pi-cli.tool-result");
28375
+ }
28296
28376
  const resultStr = typeof result === "string" ? result : JSON.stringify(result);
28297
28377
  log4.write("tool_result", `${name} result: ${resultStr}`);
28298
28378
  });
@@ -28353,10 +28433,23 @@ class CursorStreamReader {
28353
28433
  } catch {
28354
28434
  return;
28355
28435
  }
28436
+ const metadata = {
28437
+ type: typeof event["type"] === "string" ? event["type"] : "unknown",
28438
+ subtype: typeof event["subtype"] === "string" ? event["subtype"] : undefined,
28439
+ isError: this._isErrorEvent(event)
28440
+ };
28356
28441
  for (const cb of this.anyEventCallbacks)
28357
- cb();
28442
+ cb(metadata);
28358
28443
  this._dispatchEvent(event);
28359
28444
  }
28445
+ _isErrorEvent(event) {
28446
+ if (event["is_error"] === true)
28447
+ return true;
28448
+ if (event["type"] === "result") {
28449
+ return event["subtype"] !== "success";
28450
+ }
28451
+ return false;
28452
+ }
28360
28453
  _dispatchEvent(event) {
28361
28454
  const type = event["type"];
28362
28455
  if (type === "assistant") {
@@ -28548,13 +28641,6 @@ function prefixCatalogModelsWithInfer(infer, models) {
28548
28641
  var init_model_provider = () => {};
28549
28642
 
28550
28643
  // src/daemon/infrastructure/local/harness/services/cursor-sdk/cursor-sdk-package.ts
28551
- var exports_cursor_sdk_package = {};
28552
- __export(exports_cursor_sdk_package, {
28553
- importBundledCursorSdk: () => importBundledCursorSdk,
28554
- getBundledCursorSdkVersion: () => getBundledCursorSdkVersion,
28555
- formatCursorSdkLoadError: () => formatCursorSdkLoadError,
28556
- formatCursorSdkError: () => formatCursorSdkError
28557
- });
28558
28644
  import { existsSync, readFileSync as readFileSync3 } from "node:fs";
28559
28645
  import { createRequire as createRequire3 } from "node:module";
28560
28646
  import { dirname as dirname2, join as join7 } from "node:path";
@@ -28773,6 +28859,14 @@ var init_cursor_models = __esm(() => {
28773
28859
  });
28774
28860
 
28775
28861
  // src/daemon/infrastructure/local/harness/services/cursor/cursor-agent-service.ts
28862
+ function isExplicitToolError2(toolCall) {
28863
+ if (toolCall === null || typeof toolCall !== "object")
28864
+ return false;
28865
+ const obj = toolCall;
28866
+ if (obj.is_error === true || obj.isError === true)
28867
+ return true;
28868
+ return "error" in obj && obj.error !== undefined;
28869
+ }
28776
28870
  function resolveCursorCliModel(model) {
28777
28871
  const prefix = `${CURSOR_PROVIDER2}/`;
28778
28872
  return model.startsWith(prefix) ? model.slice(prefix.length) : model;
@@ -28780,6 +28874,7 @@ function resolveCursorCliModel(model) {
28780
28874
  var CURSOR_COMMAND = "agent", CURSOR_PROVIDER2 = "cursor", NO_SUBAGENT_DIRECTIVE = "NEVER spawn subagents. Follow the chatroom instructions strictly.", CursorAgentService;
28781
28875
  var init_cursor_agent_service = __esm(() => {
28782
28876
  init_cursor_stream_reader();
28877
+ init_harness_activity_emitter();
28783
28878
  init_base_cli_agent_service();
28784
28879
  init_cursor_models();
28785
28880
  init_cursor_sdk_model_catalog();
@@ -28811,6 +28906,8 @@ ${options.systemPrompt}` : NO_SUBAGENT_DIRECTIVE;
28811
28906
  const fullPrompt = `${systemPrompt}
28812
28907
 
28813
28908
  ${options.prompt}`;
28909
+ const activityEmitter = createHarnessActivityEmitter();
28910
+ activityEmitter.beginTurn();
28814
28911
  const childProcess = this.deps.spawn(CURSOR_COMMAND, args2, {
28815
28912
  cwd: options.workingDir,
28816
28913
  stdio: ["pipe", "pipe", "pipe"],
@@ -28835,6 +28932,9 @@ ${options.prompt}`;
28835
28932
  if (childProcess.stdout) {
28836
28933
  const reader = new CursorStreamReader(childProcess.stdout);
28837
28934
  let textBuffer = "";
28935
+ const emitActivity = (kind, source) => {
28936
+ activityEmitter.emit({ kind, source, at: Date.now() });
28937
+ };
28838
28938
  const flushText = () => {
28839
28939
  if (!textBuffer)
28840
28940
  return;
@@ -28846,6 +28946,7 @@ ${options.prompt}`;
28846
28946
  textBuffer = "";
28847
28947
  };
28848
28948
  reader.onText((text) => {
28949
+ emitActivity("progress", "cursor-cli.assistant.text");
28849
28950
  textBuffer += text;
28850
28951
  if (textBuffer.includes(`
28851
28952
  `))
@@ -28854,8 +28955,12 @@ ${options.prompt}`;
28854
28955
  for (const cb of outputCallbacks)
28855
28956
  cb();
28856
28957
  });
28857
- reader.onAnyEvent(() => {
28958
+ reader.onAnyEvent((metadata) => {
28858
28959
  entry.lastOutputAt = Date.now();
28960
+ emitActivity("transport", "cursor-cli.message");
28961
+ if (metadata.isError) {
28962
+ emitActivity("failure", "cursor-cli.message");
28963
+ }
28859
28964
  for (const cb of outputCallbacks)
28860
28965
  cb();
28861
28966
  });
@@ -28865,6 +28970,8 @@ ${options.prompt}`;
28865
28970
  `);
28866
28971
  });
28867
28972
  reader.onToolCall((callId, toolCall) => {
28973
+ emitActivity("progress", "cursor-cli.tool-call");
28974
+ emitActivity("waiting", "cursor-cli.tool-call");
28868
28975
  flushText();
28869
28976
  const bashCmd = extractBashCommandFromCursorToolCall(toolCall);
28870
28977
  if (bashCmd !== null) {
@@ -28873,7 +28980,11 @@ ${options.prompt}`;
28873
28980
  }
28874
28981
  emitLog(formatAgentLogLine(logPrefix, "tool", `${callId} ${JSON.stringify(toolCall)}`));
28875
28982
  });
28876
- reader.onToolResult((callId) => {
28983
+ reader.onToolResult((callId, toolCall) => {
28984
+ emitActivity("progress", "cursor-cli.tool-result");
28985
+ if (isExplicitToolError2(toolCall)) {
28986
+ emitActivity("failure", "cursor-cli.tool-result");
28987
+ }
28877
28988
  flushText();
28878
28989
  process.stdout.write(`${formatAgentLogLine(logPrefix, "tool_result", callId)}
28879
28990
  `);
@@ -28881,6 +28992,7 @@ ${options.prompt}`;
28881
28992
  if (childProcess.stderr) {
28882
28993
  childProcess.stderr.pipe(process.stderr, { end: false });
28883
28994
  childProcess.stderr.on("data", () => {
28995
+ activityEmitter.emit({ kind: "transport", source: "cursor-cli.stderr", at: Date.now() });
28884
28996
  entry.lastOutputAt = Date.now();
28885
28997
  for (const cb of outputCallbacks)
28886
28998
  cb();
@@ -28888,6 +29000,7 @@ ${options.prompt}`;
28888
29000
  }
28889
29001
  return {
28890
29002
  pid,
29003
+ activityEmitter,
28891
29004
  onExit: (cb) => {
28892
29005
  childProcess.on("exit", (code2, signal) => {
28893
29006
  this.deleteProcess(pid);
@@ -28906,6 +29019,7 @@ ${options.prompt}`;
28906
29019
  if (childProcess.stderr) {
28907
29020
  childProcess.stderr.pipe(process.stderr, { end: false });
28908
29021
  childProcess.stderr.on("data", () => {
29022
+ activityEmitter.emit({ kind: "transport", source: "cursor-cli.stderr", at: Date.now() });
28909
29023
  entry.lastOutputAt = Date.now();
28910
29024
  for (const cb of outputCallbacks)
28911
29025
  cb();
@@ -28913,6 +29027,7 @@ ${options.prompt}`;
28913
29027
  }
28914
29028
  return {
28915
29029
  pid,
29030
+ activityEmitter,
28916
29031
  onExit: (cb) => {
28917
29032
  childProcess.on("exit", (code2, signal) => {
28918
29033
  this.deleteProcess(pid);
@@ -28993,6 +29108,7 @@ function resolveCopilotSpawnModel(model) {
28993
29108
  var COPILOT_COMMAND = "copilot", CopilotAgentService;
28994
29109
  var init_copilot_agent_service = __esm(() => {
28995
29110
  init_model_provider();
29111
+ init_harness_activity_emitter();
28996
29112
  init_base_cli_agent_service();
28997
29113
  init_copilot_stream_reader();
28998
29114
  CopilotAgentService = class CopilotAgentService extends BaseCLIAgentService {
@@ -29020,6 +29136,8 @@ var init_copilot_agent_service = __esm(() => {
29020
29136
  }
29021
29137
  args2.push("--allow-all");
29022
29138
  args2.push(prompt);
29139
+ const activityEmitter = createHarnessActivityEmitter();
29140
+ activityEmitter.beginTurn();
29023
29141
  const childProcess = this.deps.spawn(COPILOT_COMMAND, args2, {
29024
29142
  cwd: options.workingDir,
29025
29143
  stdio: ["pipe", "pipe", "pipe"],
@@ -29035,13 +29153,19 @@ var init_copilot_agent_service = __esm(() => {
29035
29153
  const logPrefix = `[copilot:${roleTag}${chatroomSuffix}]`;
29036
29154
  const { onLogLine, emitFormatted } = createSessionLogCallbacks();
29037
29155
  const outputCallbacks = [];
29156
+ let processFailureEmitted = false;
29157
+ const emitActivity = (kind, source) => {
29158
+ activityEmitter.emit({ kind, source, at: Date.now() });
29159
+ };
29038
29160
  if (childProcess.stdout) {
29039
29161
  const reader = new CopilotStreamReader(childProcess.stdout);
29040
29162
  reader.onText((text) => {
29163
+ emitActivity("progress", "copilot-cli.assistant.text");
29041
29164
  emitFormatted(`${logPrefix} ${text}`);
29042
29165
  });
29043
29166
  reader.onAnyEvent(() => {
29044
29167
  entry.lastOutputAt = Date.now();
29168
+ emitActivity("transport", "copilot-cli.message");
29045
29169
  for (const cb of outputCallbacks)
29046
29170
  cb();
29047
29171
  });
@@ -29051,6 +29175,7 @@ var init_copilot_agent_service = __esm(() => {
29051
29175
  }
29052
29176
  if (childProcess.stderr) {
29053
29177
  childProcess.stderr.on("data", (chunk2) => {
29178
+ emitActivity("transport", "copilot-cli.stderr");
29054
29179
  emitFormatted(chunk2.toString("utf8"), "stderr");
29055
29180
  entry.lastOutputAt = Date.now();
29056
29181
  for (const cb of outputCallbacks)
@@ -29059,9 +29184,14 @@ var init_copilot_agent_service = __esm(() => {
29059
29184
  }
29060
29185
  return {
29061
29186
  pid,
29187
+ activityEmitter,
29062
29188
  onExit: (cb) => {
29063
29189
  childProcess.on("exit", (code2, signal) => {
29064
29190
  this.deleteProcess(pid);
29191
+ if (!processFailureEmitted && (code2 !== null && code2 !== 0 || signal !== null)) {
29192
+ processFailureEmitted = true;
29193
+ emitActivity("failure", "copilot-cli.process");
29194
+ }
29065
29195
  cb({ code: code2, signal, context: context5 });
29066
29196
  });
29067
29197
  },
@@ -29161,6 +29291,7 @@ class ClaudeStreamReader {
29161
29291
  thinkingCallbacks = [];
29162
29292
  endCallbacks = [];
29163
29293
  toolUseCallbacks = [];
29294
+ anyEventCallbacks = [];
29164
29295
  constructor(stream) {
29165
29296
  attachLineReader(stream, (line) => this._handleLine(line));
29166
29297
  }
@@ -29176,14 +29307,33 @@ class ClaudeStreamReader {
29176
29307
  onToolUse(cb) {
29177
29308
  this.toolUseCallbacks.push(cb);
29178
29309
  }
29310
+ onAnyEvent(cb) {
29311
+ this.anyEventCallbacks.push(cb);
29312
+ }
29179
29313
  _handleLine(line) {
29180
29314
  if (!line.trim())
29181
29315
  return;
29182
29316
  try {
29183
29317
  const event = JSON.parse(line);
29318
+ const metadata = {
29319
+ type: typeof event.type === "string" ? event.type : "unknown",
29320
+ subtype: typeof event.subtype === "string" ? event.subtype : undefined,
29321
+ isError: this._isErrorEvent(event)
29322
+ };
29323
+ for (const cb of this.anyEventCallbacks)
29324
+ cb(metadata);
29184
29325
  this._dispatchEvent(event);
29185
29326
  } catch {}
29186
29327
  }
29328
+ _isErrorEvent(event) {
29329
+ if (event.is_error === true)
29330
+ return true;
29331
+ if (event.type === "assistant") {
29332
+ const err = event.error ?? event.message?.error;
29333
+ return typeof err === "string" && err.length > 0;
29334
+ }
29335
+ return false;
29336
+ }
29187
29337
  _dispatchEvent(event) {
29188
29338
  const { type } = event;
29189
29339
  if (type === "system")
@@ -29249,6 +29399,7 @@ var CLAUDE_COMMAND = "claude", DEFAULT_MAX_TURNS = 200, ClaudeCodeAgentService;
29249
29399
  var init_claude_code_agent_service = __esm(() => {
29250
29400
  init_claude_models();
29251
29401
  init_claude_stream_reader();
29402
+ init_harness_activity_emitter();
29252
29403
  init_base_cli_agent_service();
29253
29404
  ClaudeCodeAgentService = class ClaudeCodeAgentService extends BaseCLIAgentService {
29254
29405
  id = "claude";
@@ -29282,6 +29433,8 @@ var init_claude_code_agent_service = __esm(() => {
29282
29433
  args2.push("--system-prompt", systemPrompt);
29283
29434
  }
29284
29435
  args2.push(prompt);
29436
+ const activityEmitter = createHarnessActivityEmitter();
29437
+ activityEmitter.beginTurn();
29285
29438
  const childProcess = this.deps.spawn(CLAUDE_COMMAND, args2, {
29286
29439
  cwd: options.workingDir,
29287
29440
  stdio: ["ignore", "pipe", "pipe"],
@@ -29299,6 +29452,9 @@ var init_claude_code_agent_service = __esm(() => {
29299
29452
  const reader = new ClaudeStreamReader(childProcess.stdout);
29300
29453
  let textBuffer = "";
29301
29454
  let thinkingBuffer = "";
29455
+ const emitActivity = (kind, source) => {
29456
+ activityEmitter.emit({ kind, source, at: Date.now() });
29457
+ };
29302
29458
  const flushText = () => {
29303
29459
  if (!textBuffer)
29304
29460
  return;
@@ -29320,6 +29476,7 @@ var init_claude_code_agent_service = __esm(() => {
29320
29476
  thinkingBuffer = "";
29321
29477
  };
29322
29478
  reader.onText((text) => {
29479
+ emitActivity("progress", "claude-cli.assistant.text");
29323
29480
  entry.lastOutputAt = Date.now();
29324
29481
  textBuffer += text;
29325
29482
  if (text.includes(`
@@ -29332,6 +29489,7 @@ var init_claude_code_agent_service = __esm(() => {
29332
29489
  cb();
29333
29490
  });
29334
29491
  reader.onThinking((thinking) => {
29492
+ emitActivity("progress", "claude-cli.assistant.thinking");
29335
29493
  entry.lastOutputAt = Date.now();
29336
29494
  thinkingBuffer += thinking;
29337
29495
  if (thinking.includes(`
@@ -29344,6 +29502,8 @@ var init_claude_code_agent_service = __esm(() => {
29344
29502
  cb();
29345
29503
  });
29346
29504
  reader.onToolUse((name, input) => {
29505
+ emitActivity("progress", "claude-cli.tool-use");
29506
+ emitActivity("waiting", "claude-cli.tool-use");
29347
29507
  entry.lastOutputAt = Date.now();
29348
29508
  const bashCmd = extractBashCommandFromToolInput(name, input);
29349
29509
  if (bashCmd !== null) {
@@ -29364,9 +29524,19 @@ var init_claude_code_agent_service = __esm(() => {
29364
29524
  for (const cb of outputCallbacks)
29365
29525
  cb();
29366
29526
  });
29527
+ reader.onAnyEvent((metadata) => {
29528
+ entry.lastOutputAt = Date.now();
29529
+ emitActivity("transport", "claude-cli.message");
29530
+ if (metadata.isError) {
29531
+ emitActivity("failure", "claude-cli.message");
29532
+ }
29533
+ for (const cb of outputCallbacks)
29534
+ cb();
29535
+ });
29367
29536
  }
29368
29537
  if (childProcess.stderr) {
29369
29538
  childProcess.stderr.on("data", (chunk2) => {
29539
+ activityEmitter.emit({ kind: "transport", source: "claude-cli.stderr", at: Date.now() });
29370
29540
  emitFormatted(chunk2.toString("utf8"), "stderr");
29371
29541
  entry.lastOutputAt = Date.now();
29372
29542
  for (const cb of outputCallbacks)
@@ -29375,6 +29545,7 @@ var init_claude_code_agent_service = __esm(() => {
29375
29545
  }
29376
29546
  return {
29377
29547
  pid,
29548
+ activityEmitter,
29378
29549
  onExit: (cb) => {
29379
29550
  childProcess.on("exit", (code2, signal) => {
29380
29551
  this.deleteProcess(pid);
@@ -29396,13 +29567,6 @@ var init_claude = __esm(() => {
29396
29567
  });
29397
29568
 
29398
29569
  // src/daemon/infrastructure/local/harness/services/claude-sdk/claude-sdk-package.ts
29399
- var exports_claude_sdk_package = {};
29400
- __export(exports_claude_sdk_package, {
29401
- resolvePathToClaudeCodeExecutable: () => resolvePathToClaudeCodeExecutable,
29402
- importBundledClaudeSdk: () => importBundledClaudeSdk,
29403
- getBundledClaudeSdkVersion: () => getBundledClaudeSdkVersion,
29404
- formatClaudeSdkLoadError: () => formatClaudeSdkLoadError
29405
- });
29406
29570
  import { existsSync as existsSync2, readFileSync as readFileSync4 } from "node:fs";
29407
29571
  import { createRequire as createRequire4 } from "node:module";
29408
29572
  import { dirname as dirname3, join as join8 } from "node:path";
@@ -29542,9 +29706,11 @@ class NativeStreamAdapterBase {
29542
29706
  outputCallbacks = [];
29543
29707
  agentEndEmitted = false;
29544
29708
  assistantTextCapture = createAssistantTextCapture();
29545
- constructor(logPrefix, emitLogLine) {
29709
+ activityEmitter;
29710
+ constructor(logPrefix, emitLogLine, activityEmitter = createHarnessActivityEmitter()) {
29546
29711
  this.logPrefix = logPrefix;
29547
29712
  this.emitLogLine = emitLogLine;
29713
+ this.activityEmitter = activityEmitter;
29548
29714
  }
29549
29715
  setAssistantTextCapture(cb) {
29550
29716
  this.assistantTextCapture.setAssistantTextCapture(cb);
@@ -29555,15 +29721,43 @@ class NativeStreamAdapterBase {
29555
29721
  onOutput(cb) {
29556
29722
  this.outputCallbacks.push(cb);
29557
29723
  }
29558
- notifyOutput() {
29724
+ notifyOutput(source = "native-sdk.event") {
29725
+ this.activityEmitter.emit({
29726
+ kind: "transport",
29727
+ source,
29728
+ at: Date.now()
29729
+ });
29559
29730
  for (const cb of this.outputCallbacks)
29560
29731
  cb();
29561
29732
  }
29733
+ notifyProgress(source) {
29734
+ this.activityEmitter.emit({
29735
+ kind: "progress",
29736
+ source,
29737
+ at: Date.now()
29738
+ });
29739
+ }
29740
+ notifyWaiting(source) {
29741
+ this.activityEmitter.emit({
29742
+ kind: "waiting",
29743
+ source,
29744
+ at: Date.now()
29745
+ });
29746
+ }
29747
+ notifyFailure(source) {
29748
+ this.activityEmitter.emit({
29749
+ kind: "failure",
29750
+ source,
29751
+ at: Date.now()
29752
+ });
29753
+ }
29562
29754
  writeLine(line) {
29563
29755
  this.emitLogLine?.(line);
29564
29756
  }
29565
29757
  }
29566
- var init_native_stream_adapter_base = () => {};
29758
+ var init_native_stream_adapter_base = __esm(() => {
29759
+ init_harness_activity_emitter();
29760
+ });
29567
29761
 
29568
29762
  // src/daemon/infrastructure/local/harness/services/claude-sdk/claude-sdk-stream-adapter.ts
29569
29763
  var ClaudeSdkStreamAdapter;
@@ -29572,29 +29766,39 @@ var init_claude_sdk_stream_adapter = __esm(() => {
29572
29766
  ClaudeSdkStreamAdapter = class ClaudeSdkStreamAdapter extends NativeStreamAdapterBase {
29573
29767
  textBuffer = "";
29574
29768
  thinkingBuffer = "";
29769
+ constructor(logPrefix, emitLogLine, activityEmitter) {
29770
+ super(logPrefix, emitLogLine, activityEmitter);
29771
+ }
29575
29772
  handleMessage(message) {
29576
- this.notifyOutput();
29773
+ this.notifyOutput("claude-sdk.message");
29577
29774
  switch (message.type) {
29578
29775
  case "stream_event":
29579
29776
  this.handleStreamEvent(message);
29580
29777
  break;
29581
29778
  case "assistant":
29779
+ this.notifyProgress("claude-sdk.assistant");
29780
+ if (message.error) {
29781
+ this.notifyFailure("claude-sdk.assistant");
29782
+ }
29582
29783
  this.handleAssistant(message);
29583
29784
  break;
29584
29785
  case "user":
29585
29786
  this.handleUser(message);
29586
29787
  break;
29587
29788
  case "system":
29588
- if (message.subtype === "init") {
29589
- this.writeLine(formatAgentLogLine(this.logPrefix, "system: init"));
29590
- }
29789
+ this.handleSystem(message);
29591
29790
  break;
29592
29791
  case "result":
29593
29792
  if (message.is_error) {
29793
+ this.notifyFailure("claude-sdk.result");
29594
29794
  const errors2 = "errors" in message && Array.isArray(message.errors) ? message.errors.join("; ") : "turn failed";
29595
29795
  this.writeLine(formatAgentLogLine(this.logPrefix, "run-error", errors2));
29596
29796
  }
29597
29797
  break;
29798
+ case "tool_progress":
29799
+ this.notifyProgress("claude-sdk.tool-progress");
29800
+ this.notifyWaiting("claude-sdk.tool-progress");
29801
+ break;
29598
29802
  default:
29599
29803
  break;
29600
29804
  }
@@ -29609,9 +29813,22 @@ var init_claude_sdk_stream_adapter = __esm(() => {
29609
29813
  if (event.type === "content_block_delta") {
29610
29814
  const delta = event.delta;
29611
29815
  if (delta.type === "text_delta") {
29816
+ this.notifyProgress("claude-sdk.stream.text-delta");
29612
29817
  this.appendText(delta.text);
29613
29818
  } else if (delta.type === "thinking_delta") {
29819
+ this.notifyProgress("claude-sdk.stream.thinking-delta");
29614
29820
  this.appendThinking(delta.thinking);
29821
+ } else if (delta.type === "input_json_delta") {
29822
+ this.notifyProgress("claude-sdk.stream.tool-input");
29823
+ this.notifyWaiting("claude-sdk.stream.tool-input");
29824
+ }
29825
+ return;
29826
+ }
29827
+ if (event.type === "content_block_start") {
29828
+ const block = event.content_block;
29829
+ if (block.type === "tool_use") {
29830
+ this.notifyProgress("claude-sdk.stream.tool-use");
29831
+ this.notifyWaiting("claude-sdk.stream.tool-use");
29615
29832
  }
29616
29833
  }
29617
29834
  }
@@ -29627,6 +29844,7 @@ var init_claude_sdk_stream_adapter = __esm(() => {
29627
29844
  this.appendThinking(block.thinking);
29628
29845
  this.flushThinking();
29629
29846
  } else if (block.type === "tool_use") {
29847
+ this.notifyWaiting("claude-sdk.assistant.tool-use");
29630
29848
  this.flushText();
29631
29849
  this.flushThinking();
29632
29850
  const bashCmd = resolveBashCommandForLog(block.name, block.input);
@@ -29648,11 +29866,35 @@ var init_claude_sdk_stream_adapter = __esm(() => {
29648
29866
  if (typeof block === "string")
29649
29867
  continue;
29650
29868
  if (block.type === "tool_result") {
29869
+ this.notifyProgress("claude-sdk.user.tool-result");
29870
+ if (block.is_error === true) {
29871
+ this.notifyFailure("claude-sdk.user.tool-result");
29872
+ }
29651
29873
  const resultStr = typeof block.content === "string" ? block.content : JSON.stringify(block.content);
29652
29874
  this.writeLine(formatAgentLogLine(this.logPrefix, "tool_result", `tool result: ${resultStr}`));
29653
29875
  }
29654
29876
  }
29655
29877
  }
29878
+ handleSystem(message) {
29879
+ switch (message.subtype) {
29880
+ case "init":
29881
+ this.writeLine(formatAgentLogLine(this.logPrefix, "system: init"));
29882
+ break;
29883
+ case "task_started":
29884
+ case "task_progress":
29885
+ this.notifyProgress("claude-sdk.task-progress");
29886
+ this.notifyWaiting("claude-sdk.task-progress");
29887
+ break;
29888
+ case "task_updated":
29889
+ this.notifyProgress("claude-sdk.task-progress");
29890
+ break;
29891
+ case "permission_denied":
29892
+ this.notifyFailure("claude-sdk.permission-denied");
29893
+ break;
29894
+ default:
29895
+ break;
29896
+ }
29897
+ }
29656
29898
  emitAgentEnd() {
29657
29899
  if (this.agentEndEmitted)
29658
29900
  return;
@@ -29822,6 +30064,7 @@ var init_claude_sdk_agent_service = __esm(() => {
29822
30064
  init_esm();
29823
30065
  init_claude_sdk_package();
29824
30066
  init_claude_sdk_stream_adapter();
30067
+ init_harness_activity_emitter();
29825
30068
  init_base_cli_agent_service();
29826
30069
  init_claude_models();
29827
30070
  init_detection_result();
@@ -29922,6 +30165,7 @@ var init_claude_sdk_agent_service = __esm(() => {
29922
30165
  resumedProviderSessionId
29923
30166
  } = args2;
29924
30167
  const entry = this.registerProcess(pid, context5);
30168
+ const activityEmitter = createHarnessActivityEmitter();
29925
30169
  const logPrefix = buildAgentLogPrefix("claude-sdk", context5);
29926
30170
  const sdkSession = {
29927
30171
  keeper,
@@ -29965,7 +30209,8 @@ var init_claude_sdk_agent_service = __esm(() => {
29965
30209
  outputCallbacks,
29966
30210
  agentEndCallbacks,
29967
30211
  assistantTextCallbacks,
29968
- emitLogLine
30212
+ emitLogLine,
30213
+ activityEmitter
29969
30214
  });
29970
30215
  return {
29971
30216
  pid,
@@ -29994,7 +30239,8 @@ var init_claude_sdk_agent_service = __esm(() => {
29994
30239
  source: "provider_allocated"
29995
30240
  });
29996
30241
  }
29997
- }
30242
+ },
30243
+ activityEmitter
29998
30244
  };
29999
30245
  }
30000
30246
  runTurnLoop(args2) {
@@ -30014,7 +30260,8 @@ var init_claude_sdk_agent_service = __esm(() => {
30014
30260
  outputCallbacks,
30015
30261
  agentEndCallbacks,
30016
30262
  assistantTextCallbacks,
30017
- emitLogLine
30263
+ emitLogLine,
30264
+ activityEmitter
30018
30265
  } = args2;
30019
30266
  let exited = false;
30020
30267
  this.executeTurnLoop({
@@ -30034,6 +30281,7 @@ var init_claude_sdk_agent_service = __esm(() => {
30034
30281
  agentEndCallbacks,
30035
30282
  assistantTextCallbacks,
30036
30283
  emitLogLine,
30284
+ activityEmitter,
30037
30285
  isExited: () => exited,
30038
30286
  markExited: () => {
30039
30287
  exited = true;
@@ -30067,6 +30315,7 @@ var init_claude_sdk_agent_service = __esm(() => {
30067
30315
  agentEndCallbacks,
30068
30316
  assistantTextCallbacks,
30069
30317
  emitLogLine,
30318
+ activityEmitter,
30070
30319
  isExited,
30071
30320
  markExited
30072
30321
  } = args2;
@@ -30089,7 +30338,8 @@ var init_claude_sdk_agent_service = __esm(() => {
30089
30338
  }
30090
30339
  nextPrompt = deferredResume;
30091
30340
  }
30092
- const adapter = new ClaudeSdkStreamAdapter(logPrefix, emitLogLine);
30341
+ activityEmitter.beginTurn();
30342
+ const adapter = new ClaudeSdkStreamAdapter(logPrefix, emitLogLine, activityEmitter);
30093
30343
  wireNativeStreamAdapter({
30094
30344
  adapter,
30095
30345
  assistantTextCallbacks,
@@ -30619,12 +30869,16 @@ var init_codex_sdk_stream_adapter = __esm(() => {
30619
30869
  init_native_stream_adapter_base();
30620
30870
  CodexSdkStreamAdapter = class CodexSdkStreamAdapter extends NativeStreamAdapterBase {
30621
30871
  textBuffer = "";
30872
+ constructor(logPrefix, emitLogLine, activityEmitter) {
30873
+ super(logPrefix, emitLogLine, activityEmitter);
30874
+ }
30622
30875
  handleEvent(event) {
30623
- this.notifyOutput();
30876
+ this.notifyOutput(`codex-sdk.${event.type}`);
30624
30877
  switch (event.type) {
30625
30878
  case "item.started":
30626
30879
  case "item.updated":
30627
30880
  case "item.completed":
30881
+ this.notifyItemActivity(event.type, event.item);
30628
30882
  this.handleItem(event.item);
30629
30883
  break;
30630
30884
  case "turn.completed":
@@ -30633,11 +30887,13 @@ var init_codex_sdk_stream_adapter = __esm(() => {
30633
30887
  this.flushText();
30634
30888
  this.writeProviderUnavailableMarker(event.error.message);
30635
30889
  this.writeLine(formatAgentLogLine(this.logPrefix, "run-error", event.error.message));
30890
+ this.notifyFailure("codex-sdk.turn.failed");
30636
30891
  break;
30637
30892
  case "error":
30638
30893
  this.flushText();
30639
30894
  this.writeProviderUnavailableMarker(event.message);
30640
30895
  this.writeLine(formatAgentLogLine(this.logPrefix, "run-error", event.message));
30896
+ this.notifyFailure("codex-sdk.error");
30641
30897
  break;
30642
30898
  case "thread.started":
30643
30899
  case "turn.started":
@@ -30649,6 +30905,50 @@ var init_codex_sdk_stream_adapter = __esm(() => {
30649
30905
  this.flushText();
30650
30906
  this.emitAgentEnd();
30651
30907
  }
30908
+ notifyItemActivity(lifecycle, item) {
30909
+ switch (item.type) {
30910
+ case "agent_message":
30911
+ this.notifyProgress("codex-sdk.item.agent-message");
30912
+ break;
30913
+ case "reasoning":
30914
+ this.notifyProgress("codex-sdk.item.reasoning");
30915
+ break;
30916
+ case "command_execution":
30917
+ this.notifyProgress("codex-sdk.item.command-execution");
30918
+ if (item.status === "in_progress") {
30919
+ this.notifyWaiting("codex-sdk.item.command-execution");
30920
+ }
30921
+ break;
30922
+ case "file_change":
30923
+ this.notifyProgress("codex-sdk.item.file-change");
30924
+ if (item.status === "failed") {
30925
+ this.notifyFailure("codex-sdk.item.file-change");
30926
+ }
30927
+ break;
30928
+ case "mcp_tool_call":
30929
+ this.notifyProgress("codex-sdk.item.mcp-tool-call");
30930
+ if (item.status === "in_progress") {
30931
+ this.notifyWaiting("codex-sdk.item.mcp-tool-call");
30932
+ }
30933
+ if (item.status === "failed" || item.error) {
30934
+ this.notifyFailure("codex-sdk.item.mcp-tool-call");
30935
+ }
30936
+ break;
30937
+ case "web_search":
30938
+ this.notifyProgress("codex-sdk.item.web-search");
30939
+ if (lifecycle === "item.started") {
30940
+ this.notifyWaiting("codex-sdk.item.web-search");
30941
+ }
30942
+ break;
30943
+ case "error":
30944
+ this.notifyFailure("codex-sdk.item.error");
30945
+ break;
30946
+ case "todo_list":
30947
+ break;
30948
+ default:
30949
+ break;
30950
+ }
30951
+ }
30652
30952
  handleItem(item) {
30653
30953
  switch (item.type) {
30654
30954
  case "agent_message":
@@ -30851,6 +31151,7 @@ var init_codex_sdk_agent_service = __esm(() => {
30851
31151
  init_codex_sdk_package();
30852
31152
  init_codex_sdk_stream_adapter();
30853
31153
  init_spawn_env();
31154
+ init_harness_activity_emitter();
30854
31155
  init_base_cli_agent_service();
30855
31156
  init_detection_result();
30856
31157
  CodexSdkAgentService = class CodexSdkAgentService extends BaseCLIAgentService {
@@ -30970,6 +31271,7 @@ var init_codex_sdk_agent_service = __esm(() => {
30970
31271
  };
30971
31272
  this.sessions.set(pid, session2);
30972
31273
  const callbacks = this.buildSessionCallbacks(pid, context5);
31274
+ const activityEmitter = createHarnessActivityEmitter();
30973
31275
  this.runTurnLoop({
30974
31276
  session: session2,
30975
31277
  correlationId: harnessSessionId,
@@ -30982,7 +31284,8 @@ var init_codex_sdk_agent_service = __esm(() => {
30982
31284
  outputCallbacks: callbacks.outputCallbacks,
30983
31285
  agentEndCallbacks: callbacks.agentEndCallbacks,
30984
31286
  assistantTextCallbacks: callbacks.assistantTextCallbacks,
30985
- emitLogLine: callbacks.emitLogLine
31287
+ emitLogLine: callbacks.emitLogLine,
31288
+ activityEmitter
30986
31289
  });
30987
31290
  return this.buildSpawnResult({
30988
31291
  pid,
@@ -30993,7 +31296,8 @@ var init_codex_sdk_agent_service = __esm(() => {
30993
31296
  agentEndCallbacks: callbacks.agentEndCallbacks,
30994
31297
  logLineCallbacks: callbacks.logLineCallbacks,
30995
31298
  assistantTextCallbacks: callbacks.assistantTextCallbacks,
30996
- sessionIdUpdatedCallbacks: callbacks.sessionIdUpdatedCallbacks
31299
+ sessionIdUpdatedCallbacks: callbacks.sessionIdUpdatedCallbacks,
31300
+ activityEmitter
30997
31301
  });
30998
31302
  }
30999
31303
  buildSessionCallbacks(pid, context5) {
@@ -31035,11 +31339,13 @@ var init_codex_sdk_agent_service = __esm(() => {
31035
31339
  agentEndCallbacks,
31036
31340
  logLineCallbacks,
31037
31341
  assistantTextCallbacks,
31038
- sessionIdUpdatedCallbacks
31342
+ sessionIdUpdatedCallbacks,
31343
+ activityEmitter
31039
31344
  } = args2;
31040
31345
  return {
31041
31346
  pid,
31042
31347
  harnessSessionId,
31348
+ activityEmitter,
31043
31349
  onExit: (cb) => {
31044
31350
  exitCallbacks.push(cb);
31045
31351
  },
@@ -31080,7 +31386,8 @@ var init_codex_sdk_agent_service = __esm(() => {
31080
31386
  outputCallbacks,
31081
31387
  agentEndCallbacks,
31082
31388
  assistantTextCallbacks,
31083
- emitLogLine
31389
+ emitLogLine,
31390
+ activityEmitter
31084
31391
  } = args2;
31085
31392
  let exited = false;
31086
31393
  (async () => {
@@ -31116,7 +31423,8 @@ ${deferredResume}` : deferredResume;
31116
31423
  outputCallbacks,
31117
31424
  agentEndCallbacks,
31118
31425
  assistantTextCallbacks,
31119
- emitLogLine
31426
+ emitLogLine,
31427
+ activityEmitter
31120
31428
  });
31121
31429
  nextPrompt = null;
31122
31430
  } catch (turnErr) {
@@ -31166,9 +31474,11 @@ ${deferredResume}` : deferredResume;
31166
31474
  outputCallbacks,
31167
31475
  agentEndCallbacks,
31168
31476
  assistantTextCallbacks,
31169
- emitLogLine
31477
+ emitLogLine,
31478
+ activityEmitter
31170
31479
  } = args2;
31171
- const adapter = new CodexSdkStreamAdapter(logPrefix, emitLogLine);
31480
+ activityEmitter.beginTurn();
31481
+ const adapter = new CodexSdkStreamAdapter(logPrefix, emitLogLine, activityEmitter);
31172
31482
  wireNativeStreamAdapter({
31173
31483
  adapter,
31174
31484
  assistantTextCallbacks,
@@ -31314,6 +31624,7 @@ var init_command_code_stream_reader = () => {};
31314
31624
  var COMMANDCODE_COMMAND = "cmd", COMMANDCODE_MODELS, CommandCodeAgentService;
31315
31625
  var init_command_code_agent_service = __esm(() => {
31316
31626
  init_model_provider();
31627
+ init_harness_activity_emitter();
31317
31628
  init_base_cli_agent_service();
31318
31629
  init_command_code_stream_reader();
31319
31630
  COMMANDCODE_MODELS = [
@@ -31356,12 +31667,21 @@ var init_command_code_agent_service = __esm(() => {
31356
31667
  async listModels() {
31357
31668
  return COMMANDCODE_MODELS.map((model) => prefixModelWithProvider(inferCommandCodeModelProvider(model), model));
31358
31669
  }
31359
- createExitSubscription(childProcess, pid, context5) {
31670
+ createExitSubscription(childProcess, pid, context5, activityEmitter) {
31360
31671
  let exitInfo = null;
31672
+ let failureEmitted = false;
31361
31673
  const exitCallbacks = [];
31362
31674
  childProcess.on("exit", (code2, signal) => {
31363
31675
  this.deleteProcess(pid);
31364
31676
  exitInfo = { code: code2, signal };
31677
+ if (activityEmitter && !failureEmitted && (code2 !== null && code2 !== 0 || signal !== null)) {
31678
+ failureEmitted = true;
31679
+ activityEmitter.emit({
31680
+ kind: "failure",
31681
+ source: "commandcode-cli.process",
31682
+ at: Date.now()
31683
+ });
31684
+ }
31365
31685
  for (const cb of exitCallbacks) {
31366
31686
  cb({ code: code2, signal, context: context5 });
31367
31687
  }
@@ -31382,6 +31702,8 @@ var init_command_code_agent_service = __esm(() => {
31382
31702
  const fullPrompt = options.systemPrompt ? `${options.systemPrompt}
31383
31703
 
31384
31704
  ${options.prompt}` : options.prompt;
31705
+ const activityEmitter = createHarnessActivityEmitter();
31706
+ activityEmitter.beginTurn();
31385
31707
  const childProcess = this.deps.spawn(COMMANDCODE_COMMAND, args2, {
31386
31708
  cwd: options.workingDir,
31387
31709
  stdio: ["pipe", "pipe", "pipe"],
@@ -31399,6 +31721,9 @@ ${options.prompt}` : options.prompt;
31399
31721
  const logPrefix = `[commandcode:${roleTag}${chatroomSuffix}`;
31400
31722
  const { onLogLine, emitFormatted } = createSessionLogCallbacks();
31401
31723
  const outputCallbacks = [];
31724
+ const emitActivity = (kind, source) => {
31725
+ activityEmitter.emit({ kind, source, at: Date.now() });
31726
+ };
31402
31727
  if (childProcess.stdout) {
31403
31728
  const reader = new CommandCodeStreamReader(childProcess.stdout);
31404
31729
  let textBuffer = "";
@@ -31413,6 +31738,7 @@ ${options.prompt}` : options.prompt;
31413
31738
  textBuffer = "";
31414
31739
  };
31415
31740
  reader.onText((text) => {
31741
+ emitActivity("progress", "commandcode-cli.assistant.text");
31416
31742
  textBuffer += text;
31417
31743
  if (textBuffer.includes(`
31418
31744
  `))
@@ -31423,6 +31749,7 @@ ${options.prompt}` : options.prompt;
31423
31749
  });
31424
31750
  reader.onAnyEvent(() => {
31425
31751
  entry.lastOutputAt = Date.now();
31752
+ emitActivity("transport", "commandcode-cli.message");
31426
31753
  for (const cb of outputCallbacks)
31427
31754
  cb();
31428
31755
  });
@@ -31432,15 +31759,17 @@ ${options.prompt}` : options.prompt;
31432
31759
  });
31433
31760
  if (childProcess.stderr) {
31434
31761
  childProcess.stderr.on("data", (chunk2) => {
31762
+ emitActivity("transport", "commandcode-cli.stderr");
31435
31763
  emitFormatted(chunk2.toString("utf8"), "stderr");
31436
31764
  entry.lastOutputAt = Date.now();
31437
31765
  for (const cb of outputCallbacks)
31438
31766
  cb();
31439
31767
  });
31440
31768
  }
31441
- const onExit5 = this.createExitSubscription(childProcess, pid, context5);
31769
+ const onExit5 = this.createExitSubscription(childProcess, pid, context5, activityEmitter);
31442
31770
  return {
31443
31771
  pid,
31772
+ activityEmitter,
31444
31773
  onExit: onExit5,
31445
31774
  onOutput: (cb) => {
31446
31775
  outputCallbacks.push(cb);
@@ -31451,9 +31780,10 @@ ${options.prompt}` : options.prompt;
31451
31780
  onLogLine
31452
31781
  };
31453
31782
  }
31454
- const onExit4 = this.createExitSubscription(childProcess, pid, context5);
31783
+ const onExit4 = this.createExitSubscription(childProcess, pid, context5, activityEmitter);
31455
31784
  if (childProcess.stderr) {
31456
31785
  childProcess.stderr.on("data", (chunk2) => {
31786
+ emitActivity("transport", "commandcode-cli.stderr");
31457
31787
  emitFormatted(chunk2.toString("utf8"), "stderr");
31458
31788
  entry.lastOutputAt = Date.now();
31459
31789
  for (const cb of outputCallbacks)
@@ -31462,6 +31792,7 @@ ${options.prompt}` : options.prompt;
31462
31792
  }
31463
31793
  return {
31464
31794
  pid,
31795
+ activityEmitter,
31465
31796
  onExit: onExit4,
31466
31797
  onOutput: (cb) => {
31467
31798
  outputCallbacks.push(cb);
@@ -31511,13 +31842,23 @@ var init_cursor_sdk_stream_adapter = __esm(() => {
31511
31842
  CursorSdkStreamAdapter = class CursorSdkStreamAdapter extends NativeStreamAdapterBase {
31512
31843
  textBuffer = "";
31513
31844
  sawTextDelta = false;
31845
+ constructor(logPrefix, emitLogLine, activityEmitter) {
31846
+ super(logPrefix, emitLogLine, activityEmitter);
31847
+ }
31514
31848
  handleMessage(message) {
31515
- this.notifyOutput();
31849
+ this.notifyOutput("cursor-sdk.message");
31516
31850
  switch (message.type) {
31517
31851
  case "assistant":
31852
+ this.notifyProgress("cursor-sdk.assistant");
31518
31853
  this.handleAssistant(message);
31519
31854
  break;
31520
31855
  case "tool_call": {
31856
+ this.notifyProgress("cursor-sdk.tool_call");
31857
+ if (message.status === "running") {
31858
+ this.notifyWaiting("cursor-sdk.tool_call");
31859
+ } else if (message.status === "error") {
31860
+ this.notifyFailure("cursor-sdk.tool_call");
31861
+ }
31521
31862
  this.flushText();
31522
31863
  if (message.status === "error") {
31523
31864
  const detail = message.result !== undefined ? JSON.stringify(message.result) : "no result";
@@ -31533,11 +31874,17 @@ var init_cursor_sdk_stream_adapter = __esm(() => {
31533
31874
  break;
31534
31875
  }
31535
31876
  case "status": {
31877
+ if (message.status === "RUNNING") {
31878
+ this.notifyProgress("cursor-sdk.status");
31879
+ } else if (message.status === "ERROR") {
31880
+ this.notifyFailure("cursor-sdk.status");
31881
+ }
31536
31882
  const payload = message.message ? `${message.status}: ${message.message}` : message.status;
31537
31883
  this.writeLine(formatAgentLogLine(this.logPrefix, "status", payload));
31538
31884
  break;
31539
31885
  }
31540
31886
  case "thinking":
31887
+ this.notifyProgress("cursor-sdk.thinking");
31541
31888
  break;
31542
31889
  case "system":
31543
31890
  if (message.subtype === "init") {
@@ -31545,6 +31892,7 @@ var init_cursor_sdk_stream_adapter = __esm(() => {
31545
31892
  }
31546
31893
  break;
31547
31894
  case "task":
31895
+ this.notifyProgress("cursor-sdk.task");
31548
31896
  this.writeLine(formatAgentLogLine(this.logPrefix, "task", [message.status, message.text].filter(Boolean).join(": ")));
31549
31897
  break;
31550
31898
  case "usage":
@@ -31559,36 +31907,56 @@ var init_cursor_sdk_stream_adapter = __esm(() => {
31559
31907
  }
31560
31908
  }
31561
31909
  handleInteractionDelta(update5) {
31562
- this.notifyOutput();
31910
+ this.notifyOutput("cursor-sdk.interaction");
31563
31911
  switch (update5.type) {
31564
31912
  case "text-delta":
31913
+ this.notifyProgress("cursor-sdk.interaction.text-delta");
31565
31914
  this.sawTextDelta = true;
31566
31915
  this.appendAssistantText(update5.text);
31567
31916
  break;
31568
31917
  case "thinking-delta":
31918
+ this.notifyProgress("cursor-sdk.interaction.thinking-delta");
31569
31919
  this.writeLine(formatAgentLogLine(this.logPrefix, "thinking", update5.text));
31570
31920
  break;
31571
31921
  case "tool-call-started":
31922
+ this.notifyProgress("cursor-sdk.interaction.tool-call-started");
31923
+ this.notifyWaiting("cursor-sdk.interaction.tool-call-started");
31572
31924
  this.flushText();
31573
31925
  this.logToolCallStarted(update5);
31574
31926
  break;
31575
31927
  case "tool-call-completed":
31928
+ this.notifyProgress("cursor-sdk.interaction.tool-call-completed");
31576
31929
  this.flushText();
31577
31930
  break;
31578
31931
  case "tool-call-delta":
31932
+ this.notifyProgress("cursor-sdk.interaction.tool-call-delta");
31579
31933
  this.handleToolCallDelta(update5);
31580
31934
  break;
31581
- case "turn-ended":
31582
- case "thinking-completed":
31583
- case "token-delta":
31584
- case "summary-started":
31585
- case "summary-completed":
31586
- case "summary":
31587
- case "user-message-appended":
31588
31935
  case "partial-tool-call":
31936
+ this.notifyProgress("cursor-sdk.interaction.partial-tool-call");
31937
+ break;
31589
31938
  case "shell-output-delta":
31939
+ this.notifyProgress("cursor-sdk.interaction.shell-output-delta");
31940
+ break;
31590
31941
  case "step-started":
31942
+ this.notifyProgress("cursor-sdk.interaction.step-started");
31943
+ break;
31591
31944
  case "step-completed":
31945
+ this.notifyProgress("cursor-sdk.interaction.step-completed");
31946
+ break;
31947
+ case "summary-started":
31948
+ this.notifyProgress("cursor-sdk.interaction.summary-started");
31949
+ break;
31950
+ case "summary-completed":
31951
+ this.notifyProgress("cursor-sdk.interaction.summary-completed");
31952
+ break;
31953
+ case "summary":
31954
+ this.notifyProgress("cursor-sdk.interaction.summary");
31955
+ break;
31956
+ case "turn-ended":
31957
+ case "thinking-completed":
31958
+ case "token-delta":
31959
+ case "user-message-appended":
31592
31960
  break;
31593
31961
  default:
31594
31962
  logUnhandledInteractionDelta(this.logPrefix, update5, (line) => this.writeLine(line));
@@ -31624,6 +31992,8 @@ var init_cursor_sdk_stream_adapter = __esm(() => {
31624
31992
  this.appendAssistantText(nested2.text);
31625
31993
  break;
31626
31994
  case "tool-call-started":
31995
+ this.notifyProgress("cursor-sdk.interaction.tool-call-started");
31996
+ this.notifyWaiting("cursor-sdk.interaction.tool-call-started");
31627
31997
  this.flushText();
31628
31998
  this.logToolCallStarted(nested2);
31629
31999
  break;
@@ -31669,25 +32039,6 @@ var init_cursor_sdk_stream_adapter = __esm(() => {
31669
32039
  };
31670
32040
  });
31671
32041
 
31672
- // src/daemon/infrastructure/agent-process-manager/harness-activity-emitter.ts
31673
- function createHarnessActivityEmitter() {
31674
- const listeners = new Set;
31675
- return {
31676
- onActivity: (cb) => {
31677
- listeners.add(cb);
31678
- },
31679
- emit: (kind) => {
31680
- for (const cb of listeners)
31681
- cb(kind);
31682
- },
31683
- subscribe: (cb) => {
31684
- listeners.add(cb);
31685
- return () => listeners.delete(cb);
31686
- }
31687
- };
31688
- }
31689
- var init_harness_activity_emitter = () => {};
31690
-
31691
32042
  // src/daemon/infrastructure/local/harness/services/tap-process-stream-writes.ts
31692
32043
  function tapProcessStreamWrites(onWrite) {
31693
32044
  const stdoutOriginal = process.stdout.write.bind(process.stdout);
@@ -32051,19 +32402,17 @@ ${deferredResume}` : deferredResume;
32051
32402
  isFirstTurn = true;
32052
32403
  }
32053
32404
  }
32054
- let turnActivityReported = false;
32055
- const notifyTurnActivityOnce = () => {
32056
- if (turnActivityReported)
32057
- return;
32058
- turnActivityReported = true;
32059
- activityEmitter.emit("busy");
32060
- };
32061
32405
  const notifyHarnessOutput = () => {
32062
32406
  entry.lastOutputAt = Date.now();
32063
- notifyTurnActivityOnce();
32407
+ activityEmitter.emit({
32408
+ kind: "transport",
32409
+ source: "cursor-sdk.process-stream",
32410
+ at: Date.now()
32411
+ });
32064
32412
  for (const cb of outputCallbacks)
32065
32413
  cb();
32066
32414
  };
32415
+ activityEmitter.beginTurn();
32067
32416
  const restoreStreamTap = tapProcessStreamWrites(notifyHarnessOutput);
32068
32417
  try {
32069
32418
  let adapter;
@@ -32076,7 +32425,7 @@ ${deferredResume}` : deferredResume;
32076
32425
  }), SEND_TIMEOUT_MS, "agent.send");
32077
32426
  session2.run = run3;
32078
32427
  isFirstTurn = false;
32079
- adapter = new CursorSdkStreamAdapter(logPrefix, emitLogLine);
32428
+ adapter = new CursorSdkStreamAdapter(logPrefix, emitLogLine, activityEmitter);
32080
32429
  wireNativeStreamAdapter({
32081
32430
  adapter,
32082
32431
  assistantTextCallbacks,
@@ -32084,9 +32433,6 @@ ${deferredResume}` : deferredResume;
32084
32433
  agentEndCallbacks,
32085
32434
  entry
32086
32435
  });
32087
- adapter.onOutput(() => {
32088
- notifyTurnActivityOnce();
32089
- });
32090
32436
  try {
32091
32437
  for await (const message of run3.stream()) {
32092
32438
  if (session2.aborted)
@@ -34271,6 +34617,26 @@ function startSessionEventForwarder(client4, options) {
34271
34617
  recentLogLines.shift();
34272
34618
  }
34273
34619
  }
34620
+ function emitActivity(kind, source) {
34621
+ options.onActivity?.({ kind, source, at: Date.now() });
34622
+ }
34623
+ function semanticSourceForLogKind(kind) {
34624
+ switch (kind) {
34625
+ case "text":
34626
+ return "opencode.message.part.updated.text";
34627
+ case "thinking":
34628
+ return "opencode.message.part.updated.reasoning";
34629
+ case "file":
34630
+ return "opencode.file.edited";
34631
+ case "compacted":
34632
+ return "opencode.session.compacted";
34633
+ default:
34634
+ if (kind.startsWith("tool:")) {
34635
+ return "opencode.message.part.updated.tool";
34636
+ }
34637
+ return;
34638
+ }
34639
+ }
34274
34640
  function isAgentActivityKind(kind) {
34275
34641
  return kind === "text" || kind === "thinking" || kind === "file" || kind === "compacted" || kind.startsWith("tool:");
34276
34642
  }
@@ -34283,7 +34649,10 @@ function startSessionEventForwarder(client4, options) {
34283
34649
  `);
34284
34650
  recordRecentLogLine(line);
34285
34651
  if (isAgentActivityKind(kind)) {
34286
- options.onActivity?.();
34652
+ const source = semanticSourceForLogKind(kind);
34653
+ if (source) {
34654
+ emitActivity("progress", source);
34655
+ }
34287
34656
  }
34288
34657
  }
34289
34658
  function clearRetryIdleTimeout() {
@@ -34428,6 +34797,7 @@ function startSessionEventForwarder(client4, options) {
34428
34797
  abortTerminalProviderError();
34429
34798
  return;
34430
34799
  }
34800
+ emitActivity("waiting", "opencode.session.status.retry");
34431
34801
  scheduleRetryIdleTimeout();
34432
34802
  return;
34433
34803
  }
@@ -34438,7 +34808,7 @@ function startSessionEventForwarder(client4, options) {
34438
34808
  }
34439
34809
  case "busy": {
34440
34810
  clearRetryIdleTimeout();
34441
- options.onActivity?.();
34811
+ emitActivity("progress", "opencode.session.status.busy");
34442
34812
  return;
34443
34813
  }
34444
34814
  default: {
@@ -34447,6 +34817,7 @@ function startSessionEventForwarder(client4, options) {
34447
34817
  }
34448
34818
  }
34449
34819
  async function handleSessionError(props) {
34820
+ emitActivity("failure", "opencode.session.error");
34450
34821
  const err = props?.error;
34451
34822
  const errMsg = formatErrorName(err);
34452
34823
  const context5 = formatErrorContext(props);
@@ -34482,6 +34853,7 @@ function startSessionEventForwarder(client4, options) {
34482
34853
  const eventSession = eventSessionId(event);
34483
34854
  if (!shouldProcessEvent(event, eventSession))
34484
34855
  return;
34856
+ emitActivity("transport", `opencode.event.${event.type}`);
34485
34857
  if (!sessionStarted) {
34486
34858
  sessionStarted = true;
34487
34859
  logLine(target, "session] Started", `role: ${options.role}`);
@@ -34666,11 +35038,13 @@ var init_opencode_sdk_agent_service = __esm(() => {
34666
35038
  init_session_event_forwarder();
34667
35039
  init_session_metadata_store();
34668
35040
  init_spawn_env();
35041
+ init_harness_activity_emitter();
34669
35042
  init_binary_agent_service();
34670
35043
  OpenCodeSdkAgentService = class OpenCodeSdkAgentService extends OpenCodeBinaryAgentService {
34671
35044
  agentEndCallbacksByPid = new Map;
34672
35045
  assistantTextCallbacksByPid = new Map;
34673
35046
  outputCallbacksByPid = new Map;
35047
+ activityEmittersByPid = new Map;
34674
35048
  id = "opencode-sdk";
34675
35049
  displayName = "OpenCode (SDK)";
34676
35050
  listModelsHarnessId = "opencode-sdk";
@@ -34738,10 +35112,15 @@ var init_opencode_sdk_agent_service = __esm(() => {
34738
35112
  baseUrl
34739
35113
  };
34740
35114
  }
34741
- wireChildOutput(childProcess, pid, entry, emitLogLine, outputCallbacks) {
35115
+ wireChildOutput(childProcess, pid, entry, emitLogLine, outputCallbacks, activityEmitter) {
34742
35116
  if (childProcess.stdout) {
34743
35117
  childProcess.stdout.on("data", () => {
34744
35118
  entry.lastOutputAt = Date.now();
35119
+ activityEmitter.emit({
35120
+ kind: "transport",
35121
+ source: "opencode.process.stdout",
35122
+ at: Date.now()
35123
+ });
34745
35124
  for (const cb of outputCallbacks)
34746
35125
  cb();
34747
35126
  });
@@ -34753,6 +35132,11 @@ var init_opencode_sdk_agent_service = __esm(() => {
34753
35132
  });
34754
35133
  childProcess.stderr.on("data", (chunk2) => {
34755
35134
  entry.lastOutputAt = Date.now();
35135
+ activityEmitter.emit({
35136
+ kind: "transport",
35137
+ source: "opencode.process.stderr",
35138
+ at: Date.now()
35139
+ });
34756
35140
  for (const cb of outputCallbacks)
34757
35141
  cb();
34758
35142
  stderrBuffer.append(chunk2.toString());
@@ -34762,15 +35146,18 @@ var init_opencode_sdk_agent_service = __esm(() => {
34762
35146
  });
34763
35147
  }
34764
35148
  }
34765
- createSessionForwarder(client4, sessionId, context5, emitLogLine, emitAssistantText, outputCallbacks) {
35149
+ createSessionForwarder(client4, sessionId, context5, emitLogLine, emitAssistantText, outputCallbacks, activityEmitter) {
34766
35150
  return startSessionEventForwarder(client4, {
34767
35151
  sessionId,
34768
35152
  role: context5.role,
34769
35153
  onLogLine: emitLogLine,
34770
35154
  onAssistantText: emitAssistantText,
34771
- onActivity: () => {
34772
- for (const cb of outputCallbacks)
34773
- cb();
35155
+ onActivity: (event) => {
35156
+ activityEmitter.emit(event);
35157
+ if (event.kind === "progress") {
35158
+ for (const cb of outputCallbacks)
35159
+ cb();
35160
+ }
34774
35161
  }
34775
35162
  });
34776
35163
  }
@@ -34809,8 +35196,9 @@ var init_opencode_sdk_agent_service = __esm(() => {
34809
35196
  if (args2.outputCallbacks) {
34810
35197
  this.outputCallbacksByPid.set(pid, args2.outputCallbacks);
34811
35198
  }
35199
+ this.activityEmittersByPid.set(pid, args2.activityEmitter);
34812
35200
  const outputCallbacks = args2.outputCallbacks ?? [];
34813
- this.wireChildOutput(childProcess, pid, entry, emitLogLine, outputCallbacks);
35201
+ this.wireChildOutput(childProcess, pid, entry, emitLogLine, outputCallbacks, args2.activityEmitter);
34814
35202
  return {
34815
35203
  pid,
34816
35204
  harnessSessionId: sessionId,
@@ -34818,6 +35206,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
34818
35206
  agentName,
34819
35207
  ...model ? { model } : {}
34820
35208
  },
35209
+ activityEmitter: args2.activityEmitter,
34821
35210
  onExit: (cb) => {
34822
35211
  childProcess.on("exit", (code2, signal) => {
34823
35212
  const fwd = this.forwarders.get(pid);
@@ -34829,6 +35218,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
34829
35218
  this.agentEndCallbacksByPid.delete(pid);
34830
35219
  this.assistantTextCallbacksByPid.delete(pid);
34831
35220
  this.outputCallbacksByPid.delete(pid);
35221
+ this.activityEmittersByPid.delete(pid);
34832
35222
  this.deleteProcess(pid);
34833
35223
  cb({ code: code2, signal, context: context5 });
34834
35224
  });
@@ -34920,6 +35310,10 @@ var init_opencode_sdk_agent_service = __esm(() => {
34920
35310
  const newSessionId2 = sessionCreateResult.data.id;
34921
35311
  const { emitLogLine } = this.createLogLineEmitter();
34922
35312
  const pidOutputCallbacks = this.outputCallbacksByPid.get(args2.pid) ?? [];
35313
+ const activityEmitter = this.activityEmittersByPid.get(args2.pid);
35314
+ if (!activityEmitter) {
35315
+ throw new Error(`No activity emitter for pid=${args2.pid}`);
35316
+ }
34923
35317
  const forwarder = startSessionEventForwarder(client4, {
34924
35318
  sessionId: newSessionId2,
34925
35319
  role: args2.context.role,
@@ -34929,9 +35323,12 @@ var init_opencode_sdk_agent_service = __esm(() => {
34929
35323
  for (const cb of callbacks2)
34930
35324
  cb(text);
34931
35325
  },
34932
- onActivity: () => {
34933
- for (const cb of pidOutputCallbacks)
34934
- cb();
35326
+ onActivity: (event) => {
35327
+ activityEmitter.emit(event);
35328
+ if (event.kind === "progress") {
35329
+ for (const cb of pidOutputCallbacks)
35330
+ cb();
35331
+ }
34935
35332
  }
34936
35333
  });
34937
35334
  const callbacks = this.agentEndCallbacksByPid.get(args2.pid) ?? [];
@@ -34953,6 +35350,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
34953
35350
  createdAt: new Date().toISOString(),
34954
35351
  baseUrl: args2.baseUrl
34955
35352
  });
35353
+ activityEmitter.beginTurn();
34956
35354
  await this.promptSessionAsync(client4, newSessionId2, buildDisabledToolsPromptBody({
34957
35355
  agentName: args2.agentName,
34958
35356
  prompt: args2.prompt,
@@ -34967,6 +35365,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
34967
35365
  const workingDir = session2.workingDir;
34968
35366
  const { childProcess, pid, baseUrl, client: client4 } = await this.startServeAndClient(workingDir, options.resolvedConvexUrl);
34969
35367
  let forwarder;
35368
+ const activityEmitter = createHarnessActivityEmitter();
34970
35369
  const { logLineCallbacks, emitLogLine } = this.createLogLineEmitter();
34971
35370
  const { assistantTextCallbacks, emitAssistantText } = this.createAssistantTextEmitter();
34972
35371
  const outputCallbacks = [];
@@ -34975,10 +35374,11 @@ var init_opencode_sdk_agent_service = __esm(() => {
34975
35374
  if (!sessionInfo.data?.id) {
34976
35375
  throw new Error(`OpenCode session ${sessionId} not found (sessions may not survive serve restart)`);
34977
35376
  }
34978
- forwarder = this.createSessionForwarder(client4, sessionId, context5, emitLogLine, emitAssistantText, outputCallbacks);
35377
+ forwarder = this.createSessionForwarder(client4, sessionId, context5, emitLogLine, emitAssistantText, outputCallbacks, activityEmitter);
34979
35378
  const availableAgents = await this.listAvailableAgents(client4);
34980
35379
  const agentDef = availableAgents.find((a) => a.name === agentName);
34981
35380
  const composedSystem = composeSystemPrompt(agentDef?.prompt, systemPrompt);
35381
+ activityEmitter.beginTurn();
34982
35382
  await this.promptSessionAsync(client4, sessionId, buildDisabledToolsPromptBody({
34983
35383
  agentName,
34984
35384
  prompt,
@@ -35003,7 +35403,8 @@ var init_opencode_sdk_agent_service = __esm(() => {
35003
35403
  workingDir,
35004
35404
  logLineCallbacks,
35005
35405
  assistantTextCallbacks,
35006
- outputCallbacks
35406
+ outputCallbacks,
35407
+ activityEmitter
35007
35408
  });
35008
35409
  }
35009
35410
  async spawn(options) {
@@ -35014,6 +35415,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
35014
35415
  let forwarder;
35015
35416
  let agentName;
35016
35417
  let deferredSystemPrompt;
35418
+ const activityEmitter = createHarnessActivityEmitter();
35017
35419
  const { logLineCallbacks, emitLogLine } = this.createLogLineEmitter();
35018
35420
  const { assistantTextCallbacks, emitAssistantText } = this.createAssistantTextEmitter();
35019
35421
  const outputCallbacks = [];
@@ -35023,7 +35425,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
35023
35425
  throw new Error("Failed to create session");
35024
35426
  }
35025
35427
  sessionId = sessionCreateResult.data.id;
35026
- forwarder = this.createSessionForwarder(client4, sessionId, context5, emitLogLine, emitAssistantText, outputCallbacks);
35428
+ forwarder = this.createSessionForwarder(client4, sessionId, context5, emitLogLine, emitAssistantText, outputCallbacks, activityEmitter);
35027
35429
  const availableAgents = await this.listAvailableAgents(client4);
35028
35430
  const selected = selectAgent(availableAgents);
35029
35431
  agentName = selected.name;
@@ -35032,6 +35434,7 @@ var init_opencode_sdk_agent_service = __esm(() => {
35032
35434
  deferredSystemPrompt = composedSystem;
35033
35435
  }
35034
35436
  if (!deferInitialTurn) {
35437
+ activityEmitter.beginTurn();
35035
35438
  await this.promptSessionAsync(client4, sessionId, buildDisabledToolsPromptBody({
35036
35439
  agentName: selected.name,
35037
35440
  prompt,
@@ -35060,7 +35463,8 @@ var init_opencode_sdk_agent_service = __esm(() => {
35060
35463
  logLineCallbacks,
35061
35464
  assistantTextCallbacks,
35062
35465
  deferredSystemPrompt,
35063
- outputCallbacks
35466
+ outputCallbacks,
35467
+ activityEmitter
35064
35468
  });
35065
35469
  }
35066
35470
  getHarnessReconnectContext(pid) {
@@ -35081,6 +35485,8 @@ var init_opencode_sdk_agent_service = __esm(() => {
35081
35485
  return;
35082
35486
  }
35083
35487
  this.forwarders.get(pid)?.armTurnEnd();
35488
+ const activityEmitter = this.activityEmittersByPid.get(pid);
35489
+ activityEmitter?.beginTurn();
35084
35490
  const client4 = createOpencodeClient({ baseUrl: meta.baseUrl });
35085
35491
  const deferredSystem = meta.deferredSystemPrompt;
35086
35492
  const context5 = {
@@ -35120,12 +35526,6 @@ var init_opencode_sdk = __esm(() => {
35120
35526
  });
35121
35527
 
35122
35528
  // src/daemon/infrastructure/local/harness/services/pi-sdk/pi-sdk-package.ts
35123
- var exports_pi_sdk_package = {};
35124
- __export(exports_pi_sdk_package, {
35125
- importBundledPiSdk: () => importBundledPiSdk,
35126
- getBundledPiSdkVersion: () => getBundledPiSdkVersion,
35127
- formatPiSdkLoadError: () => formatPiSdkLoadError
35128
- });
35129
35529
  import { existsSync as existsSync5, readFileSync as readFileSync7 } from "node:fs";
35130
35530
  import { dirname as dirname6, join as join11 } from "node:path";
35131
35531
  import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL4 } from "node:url";
@@ -35225,10 +35625,14 @@ var init_pi_sdk_stream_adapter = __esm(() => {
35225
35625
  PiSdkStreamAdapter = class PiSdkStreamAdapter extends NativeStreamAdapterBase {
35226
35626
  textBuffer = "";
35227
35627
  thinkingBuffer = "";
35628
+ constructor(logPrefix, emitLogLine, activityEmitter) {
35629
+ super(logPrefix, emitLogLine, activityEmitter);
35630
+ }
35228
35631
  handleEvent(event) {
35229
- this.notifyOutput();
35632
+ this.notifyOutput(`pi-sdk.${event.type}`);
35230
35633
  switch (event.type) {
35231
35634
  case "message_update": {
35635
+ this.notifyProgress(`pi-sdk.message.${event.assistantMessageEvent.type}`);
35232
35636
  const assistantEvent = event.assistantMessageEvent;
35233
35637
  if (assistantEvent.type === "text_delta") {
35234
35638
  this.appendText(assistantEvent.delta);
@@ -35238,6 +35642,8 @@ var init_pi_sdk_stream_adapter = __esm(() => {
35238
35642
  break;
35239
35643
  }
35240
35644
  case "tool_execution_start": {
35645
+ this.notifyProgress("pi-sdk.tool_execution_start");
35646
+ this.notifyWaiting("pi-sdk.tool_execution_start");
35241
35647
  this.flushText();
35242
35648
  this.flushThinking();
35243
35649
  const bashCmd = resolveBashCommandForLog(event.toolName, event.args);
@@ -35250,6 +35656,10 @@ var init_pi_sdk_stream_adapter = __esm(() => {
35250
35656
  break;
35251
35657
  }
35252
35658
  case "tool_execution_end": {
35659
+ this.notifyProgress("pi-sdk.tool_execution_end");
35660
+ if (event.isError === true) {
35661
+ this.notifyFailure("pi-sdk.tool_execution_end");
35662
+ }
35253
35663
  const resultStr = typeof event.result === "string" ? event.result : JSON.stringify(event.result);
35254
35664
  this.writeLine(formatAgentLogLine(this.logPrefix, "tool_result", `${event.toolName} result: ${resultStr}`));
35255
35665
  break;
@@ -35389,6 +35799,7 @@ var init_pi_sdk_agent_service = __esm(() => {
35389
35799
  init_esm();
35390
35800
  init_pi_sdk_package();
35391
35801
  init_pi_sdk_stream_adapter();
35802
+ init_harness_activity_emitter();
35392
35803
  init_base_cli_agent_service();
35393
35804
  init_detection_result();
35394
35805
  init_pi_agent_service();
@@ -35528,6 +35939,7 @@ var init_pi_sdk_agent_service = __esm(() => {
35528
35939
  storedSystemPrompt
35529
35940
  } = args2;
35530
35941
  const entry = this.registerProcess(pid, context5);
35942
+ const activityEmitter = createHarnessActivityEmitter();
35531
35943
  const logPrefix = buildAgentLogPrefix("pi-sdk", context5);
35532
35944
  const sdkSession = {
35533
35945
  session: session2,
@@ -35563,7 +35975,8 @@ var init_pi_sdk_agent_service = __esm(() => {
35563
35975
  outputCallbacks,
35564
35976
  agentEndCallbacks,
35565
35977
  assistantTextCallbacks,
35566
- emitLogLine
35978
+ emitLogLine,
35979
+ activityEmitter
35567
35980
  });
35568
35981
  return {
35569
35982
  pid,
@@ -35582,7 +35995,8 @@ var init_pi_sdk_agent_service = __esm(() => {
35582
35995
  },
35583
35996
  onAssistantText: (cb) => {
35584
35997
  assistantTextCallbacks.push(cb);
35585
- }
35998
+ },
35999
+ activityEmitter
35586
36000
  };
35587
36001
  }
35588
36002
  runTurnLoop(args2) {
@@ -35596,7 +36010,8 @@ var init_pi_sdk_agent_service = __esm(() => {
35596
36010
  outputCallbacks,
35597
36011
  agentEndCallbacks,
35598
36012
  assistantTextCallbacks,
35599
- emitLogLine
36013
+ emitLogLine,
36014
+ activityEmitter
35600
36015
  } = args2;
35601
36016
  let exited = false;
35602
36017
  (async () => {
@@ -35622,7 +36037,8 @@ var init_pi_sdk_agent_service = __esm(() => {
35622
36037
  ${deferredResume}` : deferredResume;
35623
36038
  prependSystemOnNextResume = false;
35624
36039
  }
35625
- const adapter = new PiSdkStreamAdapter(logPrefix, emitLogLine);
36040
+ activityEmitter.beginTurn();
36041
+ const adapter = new PiSdkStreamAdapter(logPrefix, emitLogLine, activityEmitter);
35626
36042
  wireNativeStreamAdapter({
35627
36043
  adapter,
35628
36044
  assistantTextCallbacks,
@@ -84531,12 +84947,11 @@ var init_stop_agent_confirmed_adapter = __esm(() => {
84531
84947
  });
84532
84948
 
84533
84949
  // ../../services/backend/config/reliability.ts
84534
- var HARNESS_SESSION_READY_TIMEOUT_MS = 5000, DAEMON_HEARTBEAT_INTERVAL_MS, DAEMON_HEARTBEAT_TTL_MS, AGENT_REQUEST_DEADLINE_MS = 120000, MACHINE_COMMAND_LEASE_RENEWAL_INTERVAL_MS = 20000, MACHINE_COMMAND_DAEMON_ROUTINE_TTL_MS, OBSERVATION_TTL_MS = 60000, OBSERVED_SAFETY_POLL_MS = 30000, WORKSPACE_LIST_RECONCILE_MS, AGENT_STOP_TERMINAL_RETENTION_MS, SCOPE_TARGET_STOP_TIMEOUT_MS = 1e4, CONNECTION_CLOSE_REQUEST_TTL_MS, ENHANCER_TERMINAL_JOB_RETENTION_MS;
84950
+ var HARNESS_SESSION_READY_TIMEOUT_MS = 5000, DAEMON_HEARTBEAT_INTERVAL_MS, DAEMON_HEARTBEAT_TTL_MS, AGENT_REQUEST_DEADLINE_MS = 120000, MACHINE_COMMAND_LEASE_RENEWAL_INTERVAL_MS = 20000, MACHINE_COMMAND_DAEMON_ROUTINE_TTL_MS, AGENT_STOP_TERMINAL_RETENTION_MS, SCOPE_TARGET_STOP_TIMEOUT_MS = 1e4, CONNECTION_CLOSE_REQUEST_TTL_MS, ENHANCER_TERMINAL_JOB_RETENTION_MS;
84535
84951
  var init_reliability = __esm(() => {
84536
84952
  DAEMON_HEARTBEAT_INTERVAL_MS = 5 * 60000;
84537
84953
  DAEMON_HEARTBEAT_TTL_MS = 6 * DAEMON_HEARTBEAT_INTERVAL_MS;
84538
84954
  MACHINE_COMMAND_DAEMON_ROUTINE_TTL_MS = 5 * 60000;
84539
- WORKSPACE_LIST_RECONCILE_MS = 60 * 60 * 1000;
84540
84955
  AGENT_STOP_TERMINAL_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
84541
84956
  CONNECTION_CLOSE_REQUEST_TTL_MS = 10 * 60000;
84542
84957
  ENHANCER_TERMINAL_JOB_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
@@ -85390,28 +85805,6 @@ async function recoverAgentState(deps) {
85390
85805
  log4(` \uD83D\uDD00 Registered ${registeredCount} workspace(s) on recovery`);
85391
85806
  }
85392
85807
  }
85393
- try {
85394
- const managedSessions = await deps.backend.getMachineHarnessSessions();
85395
- let orphanSessionCount = 0;
85396
- let totalFailedTurns = 0;
85397
- for (const hs of managedSessions) {
85398
- const hasActiveSlot = activeSlots.some((s) => s.chatroomId === hs.chatroomId);
85399
- if (hasActiveSlot)
85400
- continue;
85401
- try {
85402
- const result = await deps.backend.markOrphanTurnsFailed(hs.harnessSessionId);
85403
- orphanSessionCount++;
85404
- totalFailedTurns += result.failedTurns;
85405
- } catch (err) {
85406
- warn(`[daemon] ⚠️ Failed to mark orphan turns for session ${hs.harnessSessionId}: ${err.message}`);
85407
- }
85408
- }
85409
- if (orphanSessionCount > 0) {
85410
- log4(` \uD83E\uDDF9 Marked ${totalFailedTurns} turns as failed across ${orphanSessionCount} orphan sessions`);
85411
- }
85412
- } catch (err) {
85413
- warn(`[daemon] ⚠️ Orphan turn cleanup failed: ${err.message}`);
85414
- }
85415
85808
  }
85416
85809
 
85417
85810
  // ../../services/backend/src/domain/usecase/agent/build-agent-restart-event.ts
@@ -100395,21 +100788,6 @@ var init_native_stale_turn_phase = __esm(() => {
100395
100788
  init_check_agent_slot();
100396
100789
  });
100397
100790
 
100398
- // src/daemon/domain/native-integration/predicates.ts
100399
- function isStaleCliGetNextTaskWaiting(task) {
100400
- const lastSeenAt = task.participant?.lastSeenAt ?? 0;
100401
- return task.participant?.lastSeenAction === GET_NEXT_TASK_STARTED_ACTION && task.createdAt > lastSeenAt;
100402
- }
100403
- function isCliIdleNotListening(task, now, thresholdMs) {
100404
- const lastSeenAt = task.participant?.lastSeenAt ?? 0;
100405
- if (lastSeenAt === 0)
100406
- return now - task.createdAt > thresholdMs;
100407
- return now - lastSeenAt > thresholdMs;
100408
- }
100409
- var init_predicates = __esm(() => {
100410
- init_participant();
100411
- });
100412
-
100413
100791
  // src/daemon/infrastructure/local/harness/services/spawn-prompt.ts
100414
100792
  function createSpawnPrompt(raw, opts) {
100415
100793
  if (opts?.nativeBootstrap) {
@@ -100438,7 +100816,6 @@ var init_spawn_policy = __esm(() => {
100438
100816
  // src/daemon/domain/native-integration/index.ts
100439
100817
  var init_native_integration = __esm(() => {
100440
100818
  init_types();
100441
- init_predicates();
100442
100819
  init_spawn_policy();
100443
100820
  });
100444
100821
 
@@ -101420,15 +101797,6 @@ function createRecoverAgentStateDeps(agentMgr, session2) {
101420
101797
  workingDir: args2.workingDir,
101421
101798
  hostname: session2.config?.hostname ?? "unknown",
101422
101799
  registeredBy: args2.registeredBy
101423
- }),
101424
- getMachineHarnessSessions: async () => session2.backend.query(api.daemon.directHarness.turns.getMachineHarnessSessions, {
101425
- sessionId: session2.sessionId,
101426
- machineId: session2.machineId
101427
- }),
101428
- markOrphanTurnsFailed: async (harnessSessionId) => session2.backend.mutation(api.daemon.directHarness.turns.markOrphanTurnsFailed, {
101429
- sessionId: session2.sessionId,
101430
- machineId: session2.machineId,
101431
- harnessSessionId
101432
101800
  })
101433
101801
  },
101434
101802
  session: {
@@ -102648,7 +103016,11 @@ async function emitNativeWaitingAfterSpawn(ctx, harness, opts) {
102648
103016
  try {
102649
103017
  if (!ctx.lifecycleOutbox)
102650
103018
  throw new Error("lifecycle outbox missing");
102651
- await ctx.lifecycleOutbox.enqueue(buildActivityLifecycleFact({ chatroomId: ctx.chatroomId, role: ctx.role, action: NATIVE_WAITING_ACTION }));
103019
+ await ctx.lifecycleOutbox.enqueue(buildActivityLifecycleFact({
103020
+ chatroomId: ctx.chatroomId,
103021
+ role: ctx.role,
103022
+ action: NATIVE_WAITING_ACTION
103023
+ }));
102652
103024
  return true;
102653
103025
  } catch (err) {
102654
103026
  const error51 = err instanceof Error ? err : new Error(String(err));
@@ -102673,7 +103045,9 @@ function wireTokenActivityReporting(opts) {
102673
103045
  if (!isTeamAgentRole(opts.role))
102674
103046
  return;
102675
103047
  if (opts.activityEmitter) {
102676
- opts.activityEmitter.onActivity(() => {
103048
+ opts.activityEmitter.onActivity((signal) => {
103049
+ if (signal.kind !== "progress" || !signal.isFirstForTurn)
103050
+ return;
102677
103051
  opts.backend.mutation(api.participants.updateTokenActivity, {
102678
103052
  sessionId: opts.sessionId,
102679
103053
  chatroomId: opts.chatroomId,
@@ -103000,6 +103374,10 @@ class AgentProcessManager {
103000
103374
  }
103001
103375
  async runHandleAgentEnd(opts) {
103002
103376
  const slot = this.slots.get(agentKey3(opts.chatroomId, opts.role));
103377
+ if (!slot || slot.pid !== opts.pid || slot.harness !== opts.harness || slot.state !== "running") {
103378
+ console.log(`[AgentProcessManager] Ignoring stale agent_end: role=${opts.role} callbackPid=${opts.pid} currentPid=${slot?.pid ?? "none"} currentState=${slot?.state ?? "none"}`);
103379
+ return;
103380
+ }
103003
103381
  const capabilities = getHarnessCapabilities(opts.harness);
103004
103382
  this.updateSlotsMirror(opts.chatroomId, opts.role, {
103005
103383
  state: slot?.state ?? "idle",
@@ -105023,31 +105401,6 @@ var init_capabilities_bridge = __esm(() => {
105023
105401
  init_models_refresh();
105024
105402
  });
105025
105403
 
105026
- // ../../services/backend/config/featureFlags.ts
105027
- function getAllowedSignupMethodsForEnvironment(nodeEnv, convexDeployment, e2eSeedingEnabled) {
105028
- if (e2eSeedingEnabled === "true") {
105029
- return ["self", "invite"];
105030
- }
105031
- if (convexDeployment?.startsWith("local:")) {
105032
- return ["self", "invite"];
105033
- }
105034
- if (nodeEnv && DEV_NODE_ENVS.has(nodeEnv)) {
105035
- return ["self", "invite"];
105036
- }
105037
- return ["invite"];
105038
- }
105039
- var DEV_NODE_ENVS, featureFlags;
105040
- var init_featureFlags = __esm(() => {
105041
- DEV_NODE_ENVS = new Set(["development", "test"]);
105042
- featureFlags = {
105043
- disableLogin: false,
105044
- directHarnessWorkers: true,
105045
- get allowedSignupMethods() {
105046
- return getAllowedSignupMethodsForEnvironment("development", process.env.CONVEX_DEPLOYMENT, process.env.E2E_SEEDING_ENABLED);
105047
- }
105048
- };
105049
- });
105050
-
105051
105404
  // ../../services/backend/prompts/agentic-query/system-prompt.ts
105052
105405
  function renderAgenticQuerySystemPrompt(params) {
105053
105406
  const completeCmd = `chatroom agentic-query complete --chatroom-id=${params.chatroomId} --query-id=${params.queryId} << 'CHATROOM_AGENTIC_QUERY_END'
@@ -106623,7 +106976,6 @@ var init_pi_sdk2 = __esm(() => {
106623
106976
  });
106624
106977
 
106625
106978
  // src/daemon/infrastructure/local/harness/bound-harness-registry.ts
106626
- import { execSync as execSync2 } from "node:child_process";
106627
106979
  async function startBoundHarness(config4) {
106628
106980
  switch (config4.harnessName) {
106629
106981
  case "opencode-sdk":
@@ -106654,58 +107006,6 @@ function createChunkExtractor(harnessName) {
106654
107006
  return createStandardSdkChunkExtractor();
106655
107007
  }
106656
107008
  }
106657
- function opencodeOnPath() {
106658
- try {
106659
- execSync2("opencode --version", { stdio: "pipe" });
106660
- return true;
106661
- } catch {
106662
- return false;
106663
- }
106664
- }
106665
- async function isCursorSdkInstalled() {
106666
- if (!process.env.CURSOR_API_KEY?.trim())
106667
- return false;
106668
- try {
106669
- const { importBundledCursorSdk: importBundledCursorSdk2 } = await Promise.resolve().then(() => (init_cursor_sdk_package(), exports_cursor_sdk_package));
106670
- await importBundledCursorSdk2();
106671
- return true;
106672
- } catch {
106673
- return false;
106674
- }
106675
- }
106676
- async function isPiSdkInstalled() {
106677
- try {
106678
- const { importBundledPiSdk: importBundledPiSdk2 } = await Promise.resolve().then(() => (init_pi_sdk_package(), exports_pi_sdk_package));
106679
- const { ModelRegistry, AuthStorage } = await importBundledPiSdk2();
106680
- const authStorage = AuthStorage.create();
106681
- const modelRegistry = ModelRegistry.create(authStorage);
106682
- return modelRegistry.getAvailable().length > 0;
106683
- } catch {
106684
- return false;
106685
- }
106686
- }
106687
- async function isClaudeSdkInstalled() {
106688
- try {
106689
- const { importBundledClaudeSdk: importBundledClaudeSdk2, resolvePathToClaudeCodeExecutable: resolvePathToClaudeCodeExecutable2 } = await Promise.resolve().then(() => (init_claude_sdk_package(), exports_claude_sdk_package));
106690
- await importBundledClaudeSdk2();
106691
- await resolvePathToClaudeCodeExecutable2();
106692
- return true;
106693
- } catch {
106694
- return false;
106695
- }
106696
- }
106697
- async function listInstalledNativeDirectHarnesses() {
106698
- const installed2 = [];
106699
- if (opencodeOnPath())
106700
- installed2.push("opencode-sdk");
106701
- if (await isCursorSdkInstalled())
106702
- installed2.push("cursor-sdk");
106703
- if (await isPiSdkInstalled())
106704
- installed2.push("pi-sdk");
106705
- if (await isClaudeSdkInstalled())
106706
- installed2.push("claude-sdk");
106707
- return installed2;
106708
- }
106709
107009
  var init_bound_harness_registry = __esm(() => {
106710
107010
  init_claude_sdk2();
106711
107011
  init_cursor_sdk2();
@@ -106717,14 +107017,26 @@ var init_bound_harness_registry = __esm(() => {
106717
107017
  function makeHarnessKey(workspaceId, harnessName) {
106718
107018
  return `${workspaceId}:${harnessName}`;
106719
107019
  }
106720
- function parseHarnessKey(key) {
106721
- const idx = key.indexOf(":");
106722
- if (idx === -1)
106723
- throw new Error(`Invalid harness key: ${key}`);
106724
- return { workspaceId: key.slice(0, idx), harnessName: key.slice(idx + 1) };
107020
+
107021
+ // src/daemon/entry/shared-harness/bind-turn-message-on-event.ts
107022
+ function bindTurnMessageOnEvent(handle, sessionRepository, logPrefix) {
107023
+ let lastBoundKey = null;
107024
+ return () => {
107025
+ const turn = handle.currentTurn;
107026
+ if (!turn)
107027
+ return;
107028
+ const messageId = turn.messageId;
107029
+ if (messageId == null)
107030
+ return;
107031
+ const key = `${turn.turnId}:${messageId}`;
107032
+ if (key === lastBoundKey)
107033
+ return;
107034
+ lastBoundKey = key;
107035
+ sessionRepository.bindTurnMessageId(turn.turnId, messageId).catch((err) => console.warn(`[${logPrefix}] bindTurnMessageId error (resume):`, err));
107036
+ };
106725
107037
  }
106726
107038
 
106727
- // src/daemon/entry/direct-harness/idle-handler.ts
107039
+ // src/daemon/entry/shared-harness/idle-handler.ts
106728
107040
  async function handleSessionIdle(handle, journal, config4, sessionRepository) {
106729
107041
  await exports_Effect.runPromise(handleSessionIdleEffect(handle, journal, config4, sessionRepository));
106730
107042
  }
@@ -106737,7 +107049,7 @@ var handleSessionIdleEffect = (handle, journal, config4, sessionRepository) => e
106737
107049
  try: () => sessionRepository.finalizeAssistantTurn(turnId),
106738
107050
  catch: (e) => e
106739
107051
  })), exports_Effect.catchAll((err) => exports_Effect.sync(() => {
106740
- console.warn(`[direct-harness] Failed to finalize turn ${turnId} for session ${rowId}:`, err instanceof Error ? err.message : String(err));
107052
+ console.warn(`[harness] Failed to finalize turn ${turnId} for session ${rowId}:`, err instanceof Error ? err.message : String(err));
106741
107053
  })));
106742
107054
  }
106743
107055
  const next4 = yield* exports_Effect.tryPromise({
@@ -106763,35 +107075,17 @@ var handleSessionIdleEffect = (handle, journal, config4, sessionRepository) => e
106763
107075
  try: () => sessionRepository.markTurnProcessed(rowId, next4.seq),
106764
107076
  catch: (e) => e
106765
107077
  })), exports_Effect.catchAll((err) => exports_Effect.gen(function* () {
106766
- console.warn(`[direct-harness] Failed to prompt queued message for session ${rowId}:`, err instanceof Error ? err.message : String(err));
107078
+ console.warn(`[harness] Failed to prompt queued message for session ${rowId}:`, err instanceof Error ? err.message : String(err));
106767
107079
  yield* exports_Effect.promise(() => sessionRepository.setGenerating(rowId, false));
106768
107080
  handle.currentTurn = null;
106769
107081
  })));
106770
107082
  }), (err) => exports_Effect.sync(() => {
106771
- console.warn(`[direct-harness] Unexpected error in handleSessionIdleEffect:`, err instanceof Error ? err.message : String(err));
107083
+ console.warn(`[harness] Unexpected error in handleSessionIdleEffect:`, err instanceof Error ? err.message : String(err));
106772
107084
  }));
106773
107085
  var init_idle_handler = __esm(() => {
106774
107086
  init_esm();
106775
107087
  });
106776
107088
 
106777
- // src/daemon/entry/shared-harness/bind-turn-message-on-event.ts
106778
- function bindTurnMessageOnEvent(handle, sessionRepository, logPrefix) {
106779
- let lastBoundKey = null;
106780
- return () => {
106781
- const turn = handle.currentTurn;
106782
- if (!turn)
106783
- return;
106784
- const messageId = turn.messageId;
106785
- if (messageId == null)
106786
- return;
106787
- const key = `${turn.turnId}:${messageId}`;
106788
- if (key === lastBoundKey)
106789
- return;
106790
- lastBoundKey = key;
106791
- sessionRepository.bindTurnMessageId(turn.turnId, messageId).catch((err) => console.warn(`[${logPrefix}] bindTurnMessageId error (resume):`, err));
106792
- };
106793
- }
106794
-
106795
107089
  // src/daemon/entry/agentic-query/prompt-drain.ts
106796
107090
  async function drainPendingAgenticQueryMessages(daemonSession, deps) {
106797
107091
  const batch = await daemonSession.backend.query(api.daemon.agenticQuery.messages.pendingForMachine, { sessionId: daemonSession.sessionId, machineId: daemonSession.machineId });
@@ -107050,10 +107344,10 @@ async function openPendingHarnessSession(daemonSession, deps, input, options) {
107050
107344
  }
107051
107345
  var init_open_pending_session = __esm(() => {
107052
107346
  init_get_or_create_bound_harness();
107347
+ init_idle_handler();
107053
107348
  init_api3();
107054
107349
  init_bound_harness_registry();
107055
107350
  init_opencode_session_events();
107056
- init_idle_handler();
107057
107351
  });
107058
107352
 
107059
107353
  // src/daemon/entry/agentic-query/session-processor.ts
@@ -108248,11 +108542,8 @@ function toSyncWorkspaces(workingDirs) {
108248
108542
  async function reconcileWorkspaceList(session2) {
108249
108543
  const workspaces = await session2.backend.query(api.workspaces.listRecentlyObservedWorkspacesForMachine, {
108250
108544
  sessionId: session2.sessionId,
108251
- machineId: session2.machineId,
108252
- recencyWindowMs: OBSERVATION_TTL_MS
108545
+ machineId: session2.machineId
108253
108546
  });
108254
- if (workspaces == null)
108255
- return;
108256
108547
  if (!session2.workspaceListStore) {
108257
108548
  session2.workspaceListStore = { workspaces: [], updatedAt: 0 };
108258
108549
  }
@@ -108263,20 +108554,13 @@ var startWorkspaceListSubscriptionEffect = () => exports_Effect.gen(function* ()
108263
108554
  const session2 = yield* DaemonSessionService;
108264
108555
  session2.workspaceListStore = { workspaces: [], updatedAt: 0 };
108265
108556
  yield* exports_Effect.promise(() => reconcileWorkspaceList(session2));
108266
- const interval = setInterval(() => {
108267
- reconcileWorkspaceList(session2).catch(() => {
108268
- return;
108269
- });
108270
- }, OBSERVED_SAFETY_POLL_MS);
108271
108557
  return {
108272
108558
  stop: () => {
108273
- clearInterval(interval);
108274
108559
  session2.workspaceListStore = undefined;
108275
108560
  }
108276
108561
  };
108277
108562
  });
108278
108563
  var init_workspace_list_subscription = __esm(() => {
108279
- init_reliability();
108280
108564
  init_esm();
108281
108565
  init_api3();
108282
108566
  init_daemon_services();
@@ -110471,772 +110755,6 @@ async function dispatchCommandInboundEvent(event) {
110471
110755
  }
110472
110756
  var handler2;
110473
110757
 
110474
- // src/daemon/entry/direct-harness/command-processor.ts
110475
- async function dispatchPendingCommand(session2, deps, cmd) {
110476
- switch (cmd.type) {
110477
- case "refreshCapabilities":
110478
- await handleRefreshCapabilities(session2, deps, cmd);
110479
- break;
110480
- case "refreshSessionTitle":
110481
- await handleRefreshSessionTitle(session2, deps, cmd);
110482
- break;
110483
- case "closeSession":
110484
- await handleCloseSession(session2, deps, cmd);
110485
- break;
110486
- default:
110487
- await markFailed(session2, cmd._id, `Unknown command type: ${cmd.type}`);
110488
- }
110489
- }
110490
- async function processPendingCommand(session2, deps, cmd, now) {
110491
- if (now - cmd.createdAt > DIRECT_HARNESS_COMMAND_TTL_MS) {
110492
- console.log(`[direct-harness] Discarding stale command ${cmd._id} (type=${cmd.type}, age=${now - cmd.createdAt}ms)`);
110493
- await markFailed(session2, cmd._id, "Command expired (TTL)");
110494
- return;
110495
- }
110496
- await dispatchPendingCommand(session2, deps, cmd);
110497
- }
110498
- async function drainPendingHarnessCommands(session2, deps, processed = new Set) {
110499
- await drain(session2, deps, processed);
110500
- }
110501
- async function drain(session2, deps, processed) {
110502
- const pending3 = await session2.backend.query(api.daemon.directHarness.commands.listPendingCommands, { sessionId: session2.sessionId, machineId: session2.machineId });
110503
- if (!pending3 || pending3.length === 0)
110504
- return;
110505
- const now = Date.now();
110506
- for (const cmd of pending3) {
110507
- if (processed.has(cmd._id))
110508
- continue;
110509
- processed.add(cmd._id);
110510
- try {
110511
- await processPendingCommand(session2, deps, cmd, now);
110512
- } catch (err) {
110513
- const message = err instanceof Error ? err.message : String(err);
110514
- console.warn(`[direct-harness] Command ${cmd._id} failed: ${message}`);
110515
- await markFailed(session2, cmd._id, message).catch(() => {});
110516
- }
110517
- }
110518
- }
110519
- async function handleRefreshCapabilities(session2, deps, cmd) {
110520
- const payload = cmd.refreshCapabilities;
110521
- console.log(`[direct-harness] Processing refreshCapabilities for workspace=${cmd.workspaceId}` + (payload ? ` (initiatedBy=${payload.initiatedBy})` : ""));
110522
- const installed2 = await listInstalledNativeDirectHarnesses();
110523
- const harnessEntries = [];
110524
- let cwd = "";
110525
- for (const harnessName of installed2) {
110526
- const harness = await deps.lifecycleManager.getOrStart(cmd.workspaceId, harnessName);
110527
- cwd = harness.cwd;
110528
- const [agents, providers] = await Promise.all([harness.listAgents(), harness.listProviders()]);
110529
- harnessEntries.push({
110530
- name: harness.type,
110531
- displayName: harness.displayName,
110532
- agents: [...agents],
110533
- providers: [...providers]
110534
- });
110535
- }
110536
- const existing = await session2.backend.query(api.daemon.directHarness.capabilities.getForMachine, { sessionId: session2.sessionId, machineId: session2.machineId });
110537
- const updatedWorkspace = {
110538
- workspaceId: cmd.workspaceId,
110539
- cwd,
110540
- name: cwd,
110541
- harnesses: harnessEntries
110542
- };
110543
- const merged = [
110544
- ...(existing?.workspaces ?? []).filter((ws) => ws.workspaceId !== cmd.workspaceId),
110545
- updatedWorkspace
110546
- ];
110547
- await deps.publisher.publish({
110548
- machineId: session2.machineId,
110549
- lastSeenAt: Date.now(),
110550
- workspaces: merged
110551
- });
110552
- await session2.backend.mutation(api.daemon.directHarness.commands.updateCommandStatus, {
110553
- sessionId: session2.sessionId,
110554
- commandId: cmd._id,
110555
- status: "done"
110556
- });
110557
- console.log(`[direct-harness] Capabilities refreshed for workspace=${cmd.workspaceId}`);
110558
- }
110559
- async function handleRefreshSessionTitle(session2, deps, cmd) {
110560
- const { harnessSessionId } = cmd.refreshSessionTitle ?? {};
110561
- if (!harnessSessionId) {
110562
- await markFailed(session2, cmd._id, "refreshSessionTitle: missing harnessSessionId");
110563
- return;
110564
- }
110565
- const sessionRow = await session2.backend.query(api.daemon.directHarness.sessions.getSession, {
110566
- harnessSessionId
110567
- });
110568
- if (!sessionRow?.opencodeSessionId) {
110569
- await session2.backend.mutation(api.daemon.directHarness.commands.updateCommandStatus, {
110570
- sessionId: session2.sessionId,
110571
- commandId: cmd._id,
110572
- status: "done"
110573
- });
110574
- return;
110575
- }
110576
- const harnessName = sessionRow.harnessName ?? "opencode-sdk";
110577
- const harness = await deps.lifecycleManager.getOrStart(sessionRow.workspaceId ?? cmd.workspaceId, harnessName);
110578
- const newTitle = await harness.fetchSessionTitle(sessionRow.opencodeSessionId);
110579
- if (newTitle) {
110580
- await session2.backend.mutation(api.daemon.directHarness.sessions.updateSessionTitle, {
110581
- sessionId: session2.sessionId,
110582
- harnessSessionId,
110583
- sessionTitle: newTitle
110584
- });
110585
- console.log(`[direct-harness] Refreshed title for session ${harnessSessionId}: "${newTitle}"`);
110586
- }
110587
- await session2.backend.mutation(api.daemon.directHarness.commands.updateCommandStatus, {
110588
- sessionId: session2.sessionId,
110589
- commandId: cmd._id,
110590
- status: "done"
110591
- });
110592
- }
110593
- async function closeDisconnectedHarnessSession(deps, sessionRow, harnessSessionId) {
110594
- if (!sessionRow.opencodeSessionId) {
110595
- await deps.sessionRepository.markClosed(harnessSessionId);
110596
- return;
110597
- }
110598
- const harnessName = sessionRow.harnessName ?? "opencode-sdk";
110599
- const harness = await deps.lifecycleManager.getOrStart(sessionRow.workspaceId ?? "", harnessName);
110600
- const liveSession = await harness.resumeSession(sessionRow.opencodeSessionId, {
110601
- harnessSessionId
110602
- });
110603
- await liveSession.close();
110604
- await deps.sessionRepository.markClosed(harnessSessionId);
110605
- }
110606
- async function closeHarnessSession(session2, deps, harnessSessionId) {
110607
- const sessionRow = await session2.backend.query(api.daemon.directHarness.sessions.getSession, {
110608
- harnessSessionId
110609
- });
110610
- if (!sessionRow) {
110611
- throw new Error(`Harness session ${harnessSessionId} not found`);
110612
- }
110613
- if (sessionRow.status === "closed" || sessionRow.status === "failed") {
110614
- return;
110615
- }
110616
- const handle = deps.activeSessions.get(harnessSessionId);
110617
- if (handle) {
110618
- await handle.close();
110619
- deps.activeSessions.delete(harnessSessionId);
110620
- return;
110621
- }
110622
- await closeDisconnectedHarnessSession(deps, sessionRow, harnessSessionId);
110623
- }
110624
- async function handleCloseSession(session2, deps, cmd) {
110625
- const { harnessSessionId } = cmd.closeSession ?? {};
110626
- if (!harnessSessionId) {
110627
- await markFailed(session2, cmd._id, "closeSession: missing harnessSessionId");
110628
- return;
110629
- }
110630
- console.log(`[direct-harness] Processing closeSession for harnessSessionId=${harnessSessionId}`);
110631
- await closeHarnessSession(session2, deps, harnessSessionId);
110632
- await session2.backend.mutation(api.daemon.directHarness.commands.updateCommandStatus, {
110633
- sessionId: session2.sessionId,
110634
- commandId: cmd._id,
110635
- status: "done"
110636
- });
110637
- console.log(`[direct-harness] Closed session ${harnessSessionId}`);
110638
- }
110639
- async function markFailed(session2, commandId, errorMessage) {
110640
- await session2.backend.mutation(api.daemon.directHarness.commands.updateCommandStatus, {
110641
- sessionId: session2.sessionId,
110642
- commandId,
110643
- status: "failed",
110644
- errorMessage
110645
- });
110646
- }
110647
- var DIRECT_HARNESS_COMMAND_TTL_MS = 60000;
110648
- var init_command_processor = __esm(() => {
110649
- init_api3();
110650
- init_bound_harness_registry();
110651
- });
110652
-
110653
- // src/daemon/entry/direct-harness/harness-lifecycle-manager.ts
110654
- class HarnessLifecycleManager {
110655
- harnesses;
110656
- activeSessions;
110657
- resolveWorkspace;
110658
- resolvedConvexUrl;
110659
- idleSince = new Map;
110660
- monitorTimer = null;
110661
- constructor(harnesses, activeSessions, resolveWorkspace, resolvedConvexUrl) {
110662
- this.harnesses = harnesses;
110663
- this.activeSessions = activeSessions;
110664
- this.resolveWorkspace = resolveWorkspace;
110665
- this.resolvedConvexUrl = resolvedConvexUrl;
110666
- }
110667
- getOrStartHarnessEffect(workspaceId, harnessName) {
110668
- const key = makeHarnessKey(workspaceId, harnessName);
110669
- const existing = this.harnesses.get(key);
110670
- if (existing?.isAlive())
110671
- return exports_Effect.succeed(existing);
110672
- if (existing) {
110673
- existing.close().catch(() => {});
110674
- this.harnesses.delete(key);
110675
- }
110676
- return exports_Effect.gen(this, function* () {
110677
- const workspace = yield* exports_Effect.tryPromise({
110678
- try: () => this.resolveWorkspace(workspaceId),
110679
- catch: (e) => e instanceof Error ? e : new Error(String(e))
110680
- });
110681
- if (!workspace) {
110682
- return yield* exports_Effect.fail(new Error(`Workspace ${workspaceId} not found — cannot start harness`));
110683
- }
110684
- console.log(`[${formatTimestamp()}] \uD83D\uDD27 Auto-starting ${harnessName} for workspace=${workspaceId} (${workspace.workingDir})`);
110685
- const harness = yield* exports_Effect.tryPromise({
110686
- try: () => startBoundHarness({
110687
- harnessName,
110688
- workingDir: workspace.workingDir,
110689
- workspaceId,
110690
- resolvedConvexUrl: this.resolvedConvexUrl
110691
- }),
110692
- catch: (e) => e instanceof Error ? e : new Error(String(e))
110693
- });
110694
- this.harnesses.set(key, harness);
110695
- this.idleSince.set(key, Date.now());
110696
- return harness;
110697
- });
110698
- }
110699
- async getOrStart(workspaceId, harnessName) {
110700
- return exports_Effect.runPromise(this.getOrStartHarnessEffect(workspaceId, harnessName));
110701
- }
110702
- startMonitoring() {
110703
- if (this.monitorTimer)
110704
- return;
110705
- this.monitorTimer = setInterval(() => this.checkInactivity(), CHECK_INTERVAL_MS);
110706
- this.monitorTimer.unref();
110707
- }
110708
- stopMonitoring() {
110709
- if (this.monitorTimer) {
110710
- clearInterval(this.monitorTimer);
110711
- this.monitorTimer = null;
110712
- }
110713
- }
110714
- checkInactivity() {
110715
- const now = Date.now();
110716
- for (const key of this.harnesses.keys()) {
110717
- const { workspaceId, harnessName } = parseHarnessKey(key);
110718
- const hasActiveSessions = this.hasSessionsForHarnessKey(workspaceId, harnessName);
110719
- if (hasActiveSessions) {
110720
- this.idleSince.delete(key);
110721
- } else {
110722
- const idleStart = this.idleSince.get(key);
110723
- if (idleStart === undefined) {
110724
- this.idleSince.set(key, now);
110725
- } else if (now - idleStart >= INACTIVITY_TTL_MS) {
110726
- const idleMinutes = Math.round((now - idleStart) / 60000);
110727
- console.log(`[${formatTimestamp()}] \uD83D\uDD2A Killing idle harness ${harnessName} for workspace=${workspaceId} (idle ${idleMinutes}min)`);
110728
- this.harnesses.get(key)?.close().catch(() => {});
110729
- this.harnesses.delete(key);
110730
- this.idleSince.delete(key);
110731
- }
110732
- }
110733
- }
110734
- }
110735
- hasSessionsForHarnessKey(workspaceId, harnessName) {
110736
- for (const handle of this.activeSessions.values()) {
110737
- if (handle.workspaceId === workspaceId && handle.harnessName === harnessName) {
110738
- return true;
110739
- }
110740
- }
110741
- return false;
110742
- }
110743
- }
110744
- var INACTIVITY_TTL_MS, CHECK_INTERVAL_MS;
110745
- var init_harness_lifecycle_manager = __esm(() => {
110746
- init_esm();
110747
- init_bound_harness_registry();
110748
- INACTIVITY_TTL_MS = 15 * 60 * 1000;
110749
- CHECK_INTERVAL_MS = 60 * 1000;
110750
- });
110751
-
110752
- // src/daemon/entry/direct-harness/prompt-drain.ts
110753
- async function drainPendingHarnessMessages(session2, deps) {
110754
- const pending3 = await session2.backend.query(api.daemon.directHarness.messages.pendingForMachine, { sessionId: session2.sessionId, machineId: session2.machineId });
110755
- if (!pending3 || pending3.messages.length === 0)
110756
- return;
110757
- const bySession = new Map;
110758
- for (const msg of pending3.messages) {
110759
- const list = bySession.get(msg.harnessSessionId);
110760
- if (list) {
110761
- list.push(msg);
110762
- } else {
110763
- bySession.set(msg.harnessSessionId, [msg]);
110764
- }
110765
- }
110766
- const sessionInfo = new Map;
110767
- for (const s of pending3.sessions) {
110768
- sessionInfo.set(s._id, s);
110769
- }
110770
- for (const [rowId, messages] of bySession) {
110771
- try {
110772
- await processSessionMessages(session2, deps, rowId, messages, sessionInfo.get(rowId));
110773
- } catch (err) {
110774
- console.warn(`[direct-harness] Failed to process messages for session ${rowId}:`, err instanceof Error ? err.message : String(err));
110775
- }
110776
- }
110777
- }
110778
- async function resumeSessionHandle(session2, deps, rowId, info) {
110779
- const opencodeSessionId = info.opencodeSessionId;
110780
- if (!opencodeSessionId) {
110781
- console.warn(`[direct-harness] Session ${rowId} not yet open — waiting for session-subscriber`);
110782
- return null;
110783
- }
110784
- const workspaceId = info.workspaceId;
110785
- const harnessName = info.harnessName;
110786
- if (!workspaceId) {
110787
- console.warn(`[direct-harness] Cannot resume session ${rowId}: no workspace info`);
110788
- return null;
110789
- }
110790
- const key = makeHarnessKey(workspaceId, harnessName);
110791
- let harness = deps.harnesses.get(key);
110792
- if (harness && !harness.isAlive()) {
110793
- harness.close().catch(() => {});
110794
- deps.harnesses.delete(key);
110795
- harness = undefined;
110796
- }
110797
- if (!harness) {
110798
- const workspace = await session2.backend.query(api.workspaces.getWorkspaceById, {
110799
- sessionId: session2.sessionId,
110800
- workspaceId
110801
- });
110802
- if (!workspace) {
110803
- console.warn(`[direct-harness] Cannot resume session ${rowId}: workspace not found`);
110804
- return null;
110805
- }
110806
- harness = await startBoundHarness({
110807
- harnessName,
110808
- workingDir: workspace.workingDir,
110809
- workspaceId,
110810
- resolvedConvexUrl: session2.convexUrl
110811
- });
110812
- deps.harnesses.set(key, harness);
110813
- }
110814
- try {
110815
- return await resumeSession({
110816
- harness,
110817
- journalFactory: deps.journalFactory,
110818
- chunkExtractor: createChunkExtractor(harness.type)
110819
- }, { harnessSessionId: rowId, opencodeSessionId, workspaceId, harnessName });
110820
- } catch (err) {
110821
- const message = err instanceof Error ? err.message : String(err);
110822
- console.warn(`[direct-harness] Cannot resume session ${rowId}: ${message}`);
110823
- await deps.sessionRepository.markFailed(rowId).catch(() => {});
110824
- return null;
110825
- }
110826
- }
110827
- function wireResumedSessionEvents(handle, deps, info) {
110828
- const idleConfig = {
110829
- agent: info.lastUsedConfig.agent ?? "build",
110830
- model: info.lastUsedConfig.model
110831
- };
110832
- const bindTurnMessage = bindTurnMessageOnEvent(handle, deps.sessionRepository, "direct-harness");
110833
- handle.session.onEvent((event) => {
110834
- bindTurnMessage();
110835
- if (event.type === OPENCODE_SESSION_EVENT_TYPES[0]) {
110836
- handleSessionIdle(handle, handle.journal, idleConfig, deps.sessionRepository).catch((err) => console.warn("[direct-harness] idle handler error (resume):", err));
110837
- }
110838
- });
110839
- }
110840
- async function deliverPendingMessages(handle, deps, rowId, messages, info, _daemonSession) {
110841
- for (const msg of messages) {
110842
- const override = info?.lastUsedConfig ?? { agent: "build" };
110843
- try {
110844
- await deps.sessionRepository.setGenerating(rowId, true);
110845
- const { turnId } = await deps.sessionRepository.beginAssistantTurn(rowId);
110846
- handle.currentTurn = { turnId, messageId: null };
110847
- await handle.session.prompt({
110848
- parts: [{ type: "text", text: msg.content }],
110849
- agent: override.agent,
110850
- ...override.model ? { model: override.model } : {}
110851
- });
110852
- await deps.sessionRepository.markTurnProcessed(rowId, msg.seq);
110853
- } catch (err) {
110854
- const message = err instanceof Error ? err.message : String(err);
110855
- console.warn(`[direct-harness] Prompt failed for session ${rowId} seq=${msg.seq}: ${message}`);
110856
- await deps.sessionRepository.markIdle(rowId).catch(() => {});
110857
- deps.activeSessions.delete(rowId);
110858
- if (info?.workspaceId && info.harnessName) {
110859
- deps.harnesses.delete(makeHarnessKey(info.workspaceId, info.harnessName));
110860
- }
110861
- return;
110862
- }
110863
- }
110864
- }
110865
- async function processSessionMessages(session2, deps, rowId, messages, info) {
110866
- let handle = deps.activeSessions.get(rowId);
110867
- if (!handle) {
110868
- if (!info) {
110869
- console.warn(`[direct-harness] Session ${rowId} not yet open — waiting for session-subscriber`);
110870
- return;
110871
- }
110872
- const resumed = await resumeSessionHandle(session2, deps, rowId, info);
110873
- if (!resumed) {
110874
- return;
110875
- }
110876
- handle = resumed;
110877
- deps.activeSessions.set(rowId, handle);
110878
- await deps.sessionRepository.markActive(rowId).catch(() => {});
110879
- wireResumedSessionEvents(handle, deps, info);
110880
- }
110881
- await deliverPendingMessages(handle, deps, rowId, messages, info, session2);
110882
- }
110883
- var init_prompt_drain2 = __esm(() => {
110884
- init_idle_handler();
110885
- init_api3();
110886
- init_resume_harness_session();
110887
- init_bound_harness_registry();
110888
- init_opencode_session_events();
110889
- });
110890
-
110891
- // src/daemon/entry/direct-harness/session-processor.ts
110892
- async function processPendingHarnessSessions(daemonSession, deps) {
110893
- const pendingSessions = await daemonSession.backend.query(api.daemon.directHarness.sessions.listPendingSessionsForMachine, {
110894
- sessionId: daemonSession.sessionId,
110895
- machineId: daemonSession.machineId
110896
- });
110897
- await processPendingHarnessSessionRows(daemonSession, deps, pendingSessions);
110898
- }
110899
- async function processPendingHarnessSessionRows(daemonSession, deps, pendingSessions) {
110900
- if (!pendingSessions || pendingSessions.length === 0)
110901
- return;
110902
- for (const session2 of pendingSessions) {
110903
- const harnessName = session2.opencode?.harnessName ?? "opencode-sdk";
110904
- const agent = session2.opencode?.lastUsedConfig?.agent ?? "build";
110905
- const model = session2.opencode?.lastUsedConfig?.model;
110906
- await openPendingHarnessSession(daemonSession, deps, {
110907
- rowId: session2._id,
110908
- workspaceId: session2.workspaceId,
110909
- harnessName,
110910
- lastUsedConfig: { agent, ...model ? { model } : {} }
110911
- }, { logPrefix: "[direct-harness]", handleProviderIdEvents: true });
110912
- }
110913
- }
110914
- var init_session_processor2 = __esm(() => {
110915
- init_api3();
110916
- init_open_pending_session();
110917
- });
110918
-
110919
- // src/daemon/entry/direct-harness/shutdown-sessions.ts
110920
- async function listHarnessSessionIdsForShutdown(session2) {
110921
- const ids3 = new Set;
110922
- const managed = await session2.backend.query(api.daemon.directHarness.turns.getMachineHarnessSessions, {
110923
- sessionId: session2.sessionId,
110924
- machineId: session2.machineId
110925
- });
110926
- for (const row of managed) {
110927
- ids3.add(row.harnessSessionId);
110928
- }
110929
- const pending3 = await session2.backend.query(api.daemon.directHarness.sessions.listPendingSessionsForMachine, {
110930
- sessionId: session2.sessionId,
110931
- machineId: session2.machineId
110932
- });
110933
- for (const row of pending3) {
110934
- ids3.add(row._id);
110935
- }
110936
- return [...ids3];
110937
- }
110938
- async function closeAllMachineHarnessSessionsOnShutdown(session2, deps) {
110939
- const commandDeps = {
110940
- lifecycleManager: deps.lifecycleManager,
110941
- publisher: {},
110942
- activeSessions: deps.activeSessions,
110943
- sessionRepository: deps.sessionRepository
110944
- };
110945
- const harnessSessionIds = await listHarnessSessionIdsForShutdown(session2);
110946
- if (harnessSessionIds.length === 0)
110947
- return;
110948
- console.log(`[direct-harness] Closing ${harnessSessionIds.length} harness session(s) on daemon shutdown...`);
110949
- for (const harnessSessionId of harnessSessionIds) {
110950
- try {
110951
- await session2.backend.mutation(api.daemon.directHarness.turns.markOrphanTurnsFailed, {
110952
- sessionId: session2.sessionId,
110953
- machineId: session2.machineId,
110954
- harnessSessionId
110955
- });
110956
- } catch {}
110957
- try {
110958
- await closeHarnessSession(session2, commandDeps, harnessSessionId);
110959
- } catch (err) {
110960
- const message = err instanceof Error ? err.message : String(err);
110961
- console.warn(`[direct-harness] Failed to close session ${harnessSessionId} on shutdown: ${message}`);
110962
- try {
110963
- await deps.sessionRepository.markClosed(harnessSessionId);
110964
- } catch {}
110965
- }
110966
- }
110967
- }
110968
- var init_shutdown_sessions = __esm(() => {
110969
- init_command_processor();
110970
- init_api3();
110971
- });
110972
-
110973
- // src/infrastructure/repos/convex-capabilities-publisher.ts
110974
- class ConvexCapabilitiesPublisher {
110975
- options;
110976
- constructor(options) {
110977
- this.options = options;
110978
- }
110979
- async publish(caps) {
110980
- const { backend: backend2, sessionId } = this.options;
110981
- await backend2.mutation(api.daemon.directHarness.capabilities.publishMachineCapabilities, {
110982
- sessionId,
110983
- machineId: caps.machineId,
110984
- workspaces: caps.workspaces.map((ws) => ({
110985
- workspaceId: ws.workspaceId,
110986
- cwd: ws.cwd,
110987
- name: ws.name,
110988
- harnesses: ws.harnesses.map((h) => ({
110989
- name: h.name,
110990
- displayName: h.displayName,
110991
- agents: h.agents.map((a) => ({
110992
- name: a.name,
110993
- mode: a.mode,
110994
- ...a.model ? { model: a.model } : {},
110995
- ...a.description ? { description: a.description } : {}
110996
- })),
110997
- providers: h.providers.map((p) => ({
110998
- providerID: p.providerID,
110999
- name: p.name,
111000
- models: p.models.map((m) => ({ modelID: m.modelID, name: m.name }))
111001
- })),
111002
- ...h.configSchema !== undefined ? { configSchema: h.configSchema } : {}
111003
- }))
111004
- }))
111005
- });
111006
- }
111007
- }
111008
- var init_convex_capabilities_publisher = __esm(() => {
111009
- init_api3();
111010
- });
111011
-
111012
- // src/infrastructure/repos/convex-output-repository.ts
111013
- class ConvexOutputRepository {
111014
- options;
111015
- constructor(options) {
111016
- this.options = options;
111017
- }
111018
- async appendChunks(harnessSessionId, chunks) {
111019
- const { backend: backend2, sessionId } = this.options;
111020
- if (chunks.length === 0)
111021
- return;
111022
- console.log(`[output-repo] Calling appendMessages: harnessSessionId="${harnessSessionId}", ${chunks.length} chunks`);
111023
- try {
111024
- await backend2.mutation(api.daemon.directHarness.messages.appendMessages, {
111025
- sessionId,
111026
- harnessSessionId,
111027
- chunks: chunks.map((c) => ({
111028
- content: c.content,
111029
- timestamp: c.timestamp,
111030
- messageId: c.messageId,
111031
- partType: c.partType
111032
- }))
111033
- });
111034
- console.log(`[output-repo] appendMessages succeeded for "${harnessSessionId}"`);
111035
- } catch (err) {
111036
- console.error(`[output-repo] appendMessages FAILED for "${harnessSessionId}": ${err instanceof Error ? err.message : String(err)}`);
111037
- throw err;
111038
- }
111039
- }
111040
- }
111041
- var init_convex_output_repository = __esm(() => {
111042
- init_api3();
111043
- });
111044
-
111045
- // src/infrastructure/repos/convex-session-repository.ts
111046
- class ConvexSessionRepository {
111047
- options;
111048
- constructor(options) {
111049
- this.options = options;
111050
- }
111051
- async associateOpenCodeSessionId(harnessSessionId, opencodeSessionId, sessionTitle) {
111052
- const { backend: backend2, sessionId } = this.options;
111053
- await backend2.mutation(api.daemon.directHarness.sessions.associateHarnessSessionId, {
111054
- sessionId,
111055
- harnessSessionId,
111056
- opencodeSessionId,
111057
- sessionTitle
111058
- });
111059
- }
111060
- async getOpenCodeSessionId(harnessSessionId) {
111061
- const result = await this.options.backend.query(api.daemon.directHarness.sessions.getSession, {
111062
- harnessSessionId
111063
- });
111064
- return result?.opencodeSessionId;
111065
- }
111066
- async markClosed(harnessSessionId) {
111067
- const { backend: backend2, sessionId } = this.options;
111068
- await backend2.mutation(api.daemon.directHarness.sessions.closeSession, {
111069
- sessionId,
111070
- harnessSessionId
111071
- });
111072
- }
111073
- async markIdle(harnessSessionId) {
111074
- const { backend: backend2, sessionId } = this.options;
111075
- await backend2.mutation(api.daemon.directHarness.sessions.markIdle, {
111076
- sessionId,
111077
- harnessSessionId
111078
- });
111079
- }
111080
- async markFailed(harnessSessionId) {
111081
- const { backend: backend2, sessionId } = this.options;
111082
- await backend2.mutation(api.daemon.directHarness.sessions.markFailed, {
111083
- sessionId,
111084
- harnessSessionId
111085
- });
111086
- }
111087
- async markActive(harnessSessionId) {
111088
- const { backend: backend2, sessionId } = this.options;
111089
- await backend2.mutation(api.daemon.directHarness.sessions.markActive, {
111090
- sessionId,
111091
- harnessSessionId
111092
- });
111093
- }
111094
- async markTurnProcessed(harnessSessionId, turnSeq) {
111095
- const { backend: backend2, sessionId } = this.options;
111096
- await backend2.mutation(api.daemon.directHarness.turns.markTurnProcessed, {
111097
- sessionId,
111098
- harnessSessionId,
111099
- turnSeq
111100
- });
111101
- }
111102
- async setGenerating(harnessSessionId, isGenerating) {
111103
- const { backend: backend2, sessionId } = this.options;
111104
- await backend2.mutation(api.daemon.directHarness.queue.setGenerating, {
111105
- sessionId,
111106
- harnessSessionId,
111107
- isGenerating
111108
- });
111109
- }
111110
- async dequeueNext(harnessSessionId) {
111111
- const { backend: backend2, sessionId } = this.options;
111112
- const result = await backend2.mutation(api.daemon.directHarness.queue.dequeueNext, {
111113
- sessionId,
111114
- harnessSessionId
111115
- });
111116
- if (!result)
111117
- return null;
111118
- return { content: result.content, seq: result.turnSeq };
111119
- }
111120
- async beginAssistantTurn(harnessSessionId) {
111121
- const { backend: backend2, sessionId } = this.options;
111122
- return backend2.mutation(api.daemon.directHarness.turns.beginAssistantTurn, {
111123
- sessionId,
111124
- harnessSessionId
111125
- });
111126
- }
111127
- async bindTurnMessageId(turnId, messageId) {
111128
- const { backend: backend2, sessionId } = this.options;
111129
- await backend2.mutation(api.daemon.directHarness.turns.bindTurnMessageId, {
111130
- sessionId,
111131
- turnId,
111132
- messageId
111133
- });
111134
- }
111135
- async finalizeAssistantTurn(turnId) {
111136
- const { backend: backend2, sessionId } = this.options;
111137
- await backend2.mutation(api.daemon.directHarness.turns.finalizeAssistantTurn, {
111138
- sessionId,
111139
- turnId
111140
- });
111141
- }
111142
- async updateSessionTitle(harnessSessionId, title) {
111143
- const { backend: backend2, sessionId } = this.options;
111144
- await backend2.mutation(api.daemon.directHarness.sessions.updateSessionTitle, {
111145
- sessionId,
111146
- harnessSessionId,
111147
- sessionTitle: title
111148
- });
111149
- }
111150
- }
111151
- var init_convex_session_repository = __esm(() => {
111152
- init_api3();
111153
- });
111154
-
111155
- // src/daemon/entry/direct-harness-inbound-registry.ts
111156
- function registerDirectHarnessInboundHandler(h) {
111157
- handler3 = h;
111158
- }
111159
- function unregisterDirectHarnessInboundHandler() {
111160
- handler3 = undefined;
111161
- }
111162
- async function dispatchDirectHarnessInboundEvent(event) {
111163
- if (handler3)
111164
- await handler3(event);
111165
- }
111166
- var handler3;
111167
-
111168
- // src/daemon/entry/direct-harness/start-subscriptions.ts
111169
- function startDirectHarnessSubscriptions(session2, activeSessions, harnesses) {
111170
- const sessionRepository = new ConvexSessionRepository({
111171
- backend: session2.backend,
111172
- sessionId: session2.sessionId
111173
- });
111174
- const outputRepository = new ConvexOutputRepository({
111175
- backend: session2.backend,
111176
- sessionId: session2.sessionId
111177
- });
111178
- const journalFactory = new BufferedJournalFactory({ outputRepository });
111179
- const sharedDeps = {
111180
- activeSessions,
111181
- harnesses,
111182
- sessionRepository,
111183
- journalFactory
111184
- };
111185
- const lifecycleManager = new HarnessLifecycleManager(harnesses, activeSessions, async (workspaceId) => session2.backend.query(api.workspaces.getWorkspaceById, {
111186
- sessionId: session2.sessionId,
111187
- workspaceId
111188
- }), session2.convexUrl);
111189
- lifecycleManager.startMonitoring();
111190
- const commandDeps = {
111191
- lifecycleManager,
111192
- publisher: new ConvexCapabilitiesPublisher({
111193
- backend: session2.backend,
111194
- sessionId: session2.sessionId
111195
- }),
111196
- activeSessions,
111197
- sessionRepository
111198
- };
111199
- registerDirectHarnessInboundHandler(async (event) => {
111200
- switch (event.type) {
111201
- case "direct-harness.prompt":
111202
- await drainPendingHarnessMessages(session2, sharedDeps);
111203
- break;
111204
- case "direct-harness.session-opened":
111205
- await processPendingHarnessSessions(session2, sharedDeps);
111206
- break;
111207
- case "direct-harness.command":
111208
- await drainPendingHarnessCommands(session2, commandDeps);
111209
- break;
111210
- }
111211
- });
111212
- return {
111213
- lifecycleManager,
111214
- closeSessionsOnShutdown: async () => {
111215
- unregisterDirectHarnessInboundHandler();
111216
- await closeAllMachineHarnessSessionsOnShutdown(session2, {
111217
- lifecycleManager,
111218
- activeSessions,
111219
- sessionRepository
111220
- });
111221
- },
111222
- stop: () => {
111223
- unregisterDirectHarnessInboundHandler();
111224
- lifecycleManager.stopMonitoring();
111225
- }
111226
- };
111227
- }
111228
- var init_start_subscriptions2 = __esm(() => {
111229
- init_command_processor();
111230
- init_harness_lifecycle_manager();
111231
- init_prompt_drain2();
111232
- init_session_processor2();
111233
- init_shutdown_sessions();
111234
- init_api3();
111235
- init_convex_capabilities_publisher();
111236
- init_convex_output_repository();
111237
- init_convex_session_repository();
111238
- });
111239
-
111240
110758
  // src/daemon/entry/enhancer/constants.ts
111241
110759
  var ENHANCER_AGENT_ROLE = "enhancer", ENHANCER_AGENT_END_GRACE_MS = 3000;
111242
110760
 
@@ -111418,16 +110936,16 @@ var init_wait_for_enhancer_job = __esm(() => {
111418
110936
 
111419
110937
  // src/daemon/entry/enhancer-inbound-registry.ts
111420
110938
  function registerEnhancerInboundHandler(h) {
111421
- handler4 = h;
110939
+ handler3 = h;
111422
110940
  }
111423
110941
  function unregisterEnhancerInboundHandler() {
111424
- handler4 = undefined;
110942
+ handler3 = undefined;
111425
110943
  }
111426
110944
  async function dispatchEnhancerInboundEvent(event) {
111427
- if (handler4)
111428
- await handler4(event);
110945
+ if (handler3)
110946
+ await handler3(event);
111429
110947
  }
111430
- var handler4;
110948
+ var handler3;
111431
110949
 
111432
110950
  // src/daemon/entry/enhancer/job-subscriber.ts
111433
110951
  async function processEnhancerJobForSpawn(sessionId, machineId, convexUrl, wsClient2, backend2, agentServices, job, inFlight2, logSink) {
@@ -111619,22 +111137,22 @@ var init_job_subscriber = __esm(() => {
111619
111137
  function startEnhancerSubscriptions(sessionId, machineId, convexUrl, wsClient2, backend2, agentServices, logSink) {
111620
111138
  return startEnhancerJobSubscriber(sessionId, machineId, convexUrl, wsClient2, backend2, agentServices, logSink);
111621
111139
  }
111622
- var init_start_subscriptions3 = __esm(() => {
111140
+ var init_start_subscriptions2 = __esm(() => {
111623
111141
  init_job_subscriber();
111624
111142
  });
111625
111143
 
111626
111144
  // src/daemon/entry/file-inbound-registry.ts
111627
111145
  function registerFileInboundHandler(h) {
111628
- handler5 = h;
111146
+ handler4 = h;
111629
111147
  }
111630
111148
  function unregisterFileInboundHandler() {
111631
- handler5 = undefined;
111149
+ handler4 = undefined;
111632
111150
  }
111633
111151
  async function dispatchFileInboundEvent(event) {
111634
- if (handler5)
111635
- await handler5(event);
111152
+ if (handler4)
111153
+ await handler4(event);
111636
111154
  }
111637
- var handler5;
111155
+ var handler4;
111638
111156
 
111639
111157
  // src/daemon/entry/files/file-content-classifier.ts
111640
111158
  function extensionOf(path3) {
@@ -115721,7 +115239,7 @@ function createCoalescingStateOutbox(options) {
115721
115239
  return;
115722
115240
  timer = setTimeout(() => {
115723
115241
  timer = null;
115724
- drain2().catch(() => {
115242
+ drain().catch(() => {
115725
115243
  return;
115726
115244
  });
115727
115245
  }, Math.max(0, delayMs));
@@ -115730,7 +115248,7 @@ function createCoalescingStateOutbox(options) {
115730
115248
  if (pending3) {
115731
115249
  schedule2(retryAttempt > 0 ? computeExponentialRetryDelayMs(retryAttempt - 1, retryDelayMs, maxRetryDelayMs) : 0);
115732
115250
  }
115733
- async function drain2() {
115251
+ async function drain() {
115734
115252
  if (stopped || !pending3 || inFlight2)
115735
115253
  return;
115736
115254
  const batch = pending3;
@@ -115794,7 +115312,7 @@ function createCoalescingStateOutbox(options) {
115794
115312
  });
115795
115313
  }
115796
115314
  if (pending3)
115797
- await drain2();
115315
+ await drain();
115798
115316
  };
115799
115317
  const stop4 = async () => {
115800
115318
  if (stopped)
@@ -117326,11 +116844,6 @@ var init_command_run_subscription = __esm(() => {
117326
116844
  });
117327
116845
 
117328
116846
  // src/daemon/entry/task-delivery/task-delivery-logic.ts
117329
- function isPendingAliveRunningTask(task) {
117330
- const { agentConfig, status: status3 } = task;
117331
- const op = getNativeDeliverySession()?.agentOperationalReadModel?.get(task.chatroomId, agentConfig.role);
117332
- return status3 === "pending" && (agentConfig.spawnedAgentPid != null || op?.isAlive === true) && isOperationalDesiredRunning(op);
117333
- }
117334
116847
  function isSlotUnavailableForPid(slot, pid, isPidAlive, now = Date.now()) {
117335
116848
  if (!slot) {
117336
116849
  return true;
@@ -117417,31 +116930,11 @@ function listNativePendingTasksNeedingWake(tasks, cooldown, now) {
117417
116930
  return true;
117418
116931
  });
117419
116932
  }
117420
- function shouldNudgeCliPendingTask(task, now, pendingIdleThresholdMs) {
117421
- if (!isPendingAliveRunningTask(task))
117422
- return false;
117423
- return isStaleCliGetNextTaskWaiting(task) || isCliIdleNotListening(task, now, pendingIdleThresholdMs);
117424
- }
117425
- function shouldNudgePendingTask(task, now, pendingIdleThresholdMs = PENDING_IDLE_NUDGE_MS) {
117426
- if (isNativeHarness(task.agentConfig.agentHarness)) {
117427
- return shouldNudgeNativePendingTask(task, now, pendingIdleThresholdMs);
117428
- }
117429
- return shouldNudgeCliPendingTask(task, now, pendingIdleThresholdMs);
117430
- }
117431
- function shouldNudgeNativePendingTask(task, now, pendingIdleThresholdMs, slot) {
117432
- if (!isPendingAliveRunningTask(task))
117433
- return false;
117434
- if (!isAgentReadyForNativeDelivery(task, slot))
117435
- return false;
117436
- const lastSeenAt = task.participant?.lastSeenAt ?? 0;
117437
- const idleSince = lastSeenAt > 0 ? now - lastSeenAt : now - task.createdAt;
117438
- return idleSince > pendingIdleThresholdMs;
117439
- }
117440
116933
 
117441
116934
  class RecoveryCooldown {
117442
116935
  cooldownMs;
117443
116936
  lastAttemptAt = new Map;
117444
- constructor(cooldownMs = NUDGE_COOLDOWN_MS) {
116937
+ constructor(cooldownMs = RECOVERY_COOLDOWN_MS) {
117445
116938
  this.cooldownMs = cooldownMs;
117446
116939
  }
117447
116940
  canAttempt(chatroomId, role, kind, now) {
@@ -117453,37 +116946,12 @@ class RecoveryCooldown {
117453
116946
  this.lastAttemptAt.set(`${kind}:${chatroomId}:${role}`, now);
117454
116947
  }
117455
116948
  }
117456
- function isTaskReadyForNudge(task, now, cooldown, getSlot) {
117457
- if (isNativeHarness(task.agentConfig.agentHarness)) {
117458
- const slot = getSlot?.(task.chatroomId, task.agentConfig.role);
117459
- if (!shouldNudgeNativePendingTask(task, now, PENDING_IDLE_NUDGE_MS, slot))
117460
- return false;
117461
- } else if (!shouldNudgePendingTask(task, now)) {
117462
- return false;
117463
- }
117464
- const { chatroomId, agentConfig } = task;
117465
- if (!cooldown.canAttempt(chatroomId, agentConfig.role, "nudge", now))
117466
- return false;
117467
- if (!agentConfig.workingDir)
117468
- return false;
117469
- return true;
117470
- }
117471
- function listTasksReadyForNudge(tasks, now, cooldown, getSlot) {
117472
- return tasks.filter((task) => {
117473
- if (!isTaskReadyForNudge(task, now, cooldown, getSlot))
117474
- return false;
117475
- cooldown.recordAttempt(task.chatroomId, task.agentConfig.role, "nudge", now);
117476
- return true;
117477
- });
117478
- }
117479
- var PENDING_IDLE_NUDGE_MS = 15000, NUDGE_COOLDOWN_MS = 60000;
116949
+ var RECOVERY_COOLDOWN_MS = 60000;
117480
116950
  var init_task_delivery_logic = __esm(() => {
117481
116951
  init_check_agent_slot();
117482
- init_predicates();
117483
116952
  init_agent_process_manager();
117484
116953
  init_execute_stop_targets_adapter();
117485
116954
  init_native_delivery_session_registry();
117486
- init_native_ready_invariant();
117487
116955
  init_native_task_injector_logic();
117488
116956
  });
117489
116957
 
@@ -117491,14 +116959,6 @@ var init_task_delivery_logic = __esm(() => {
117491
116959
  function resolveTaskWantResume(task) {
117492
116960
  return sessionAugmentationToWantResume(resolveSessionAugmentationForTask({ content: task.taskContent ?? "", startInNewSession: task.startInNewSession }, task.agentConfig.role));
117493
116961
  }
117494
- function buildCliNudgeLogLine(task) {
117495
- const { chatroomId, agentConfig } = task;
117496
- const { role } = agentConfig;
117497
- const lastSeenAction = task.participant?.lastSeenAction ?? "unknown";
117498
- const augmentationMode = resolveSessionAugmentationForTask({ content: task.taskContent ?? "", startInNewSession: task.startInNewSession }, role);
117499
- const wantResume = resolveTaskWantResume(task);
117500
- return `[TaskMonitor] nudging ${role}@${chatroomId} — pending task ${task.taskId}, lastSeenAction=${lastSeenAction}, session_augmentation=${augmentationMode}, wantResume=${wantResume}`;
117501
- }
117502
116962
  function resolveTaskRunnerContextFromFull(task) {
117503
116963
  const { chatroomId, agentConfig } = task;
117504
116964
  const { role } = agentConfig;
@@ -117513,58 +116973,6 @@ function resolveTaskRunnerContextFromFull(task) {
117513
116973
  wantResume: resolveTaskWantResume(task)
117514
116974
  };
117515
116975
  }
117516
- function executeCliNudge(task, runtime4, effectContext2, agentMgr, sessionDeps, machineId) {
117517
- const ctx = resolveTaskRunnerContextFromFull(task);
117518
- if (!ctx)
117519
- return;
117520
- const { chatroomId, agentConfig, role, workingDir, wantResume } = ctx;
117521
- const augmentationMode = resolveSessionAugmentationForTask({ content: task.taskContent ?? "", startInNewSession: task.startInNewSession }, role);
117522
- exports_Runtime.runFork(runtime4)(exports_Effect.gen(function* () {
117523
- yield* agentMgr.stop({
117524
- chatroomId,
117525
- role,
117526
- reason: AgentStopReasonEnum["platform.task_monitor_nudge"]
117527
- });
117528
- yield* agentMgr.ensureRunning({
117529
- chatroomId,
117530
- role,
117531
- agentHarness: agentConfig.agentHarness,
117532
- model: agentConfig.model,
117533
- workingDir,
117534
- reason: AgentStartReasonEnum["platform.task_monitor_nudge"],
117535
- wantResume,
117536
- lifecycleRevision: task.agentConfig.configLifecycleRevision,
117537
- taskId: task.taskId
117538
- });
117539
- if (shouldEmitSessionAugmentation(role, augmentationMode)) {
117540
- yield* exports_Effect.tryPromise({
117541
- try: async () => {
117542
- await logDaemonAuditEvent(sessionDeps.logEvent ?? (async () => {
117543
- return;
117544
- }), {
117545
- type: "agent.sessionAugmented",
117546
- chatroomId,
117547
- role,
117548
- machineId,
117549
- taskId: task.taskId,
117550
- mode: augmentationMode,
117551
- newSessionStarted: sessionAugmentationNewSessionStarted(augmentationMode)
117552
- });
117553
- await sessionDeps.backend.mutation(api.daemon.agentEvents.sessionAugmented, {
117554
- sessionId: sessionDeps.sessionId,
117555
- machineId,
117556
- chatroomId,
117557
- role,
117558
- taskId: task.taskId,
117559
- mode: augmentationMode,
117560
- newSessionStarted: sessionAugmentationNewSessionStarted(augmentationMode)
117561
- });
117562
- },
117563
- catch: (err) => err
117564
- }).pipe(exports_Effect.catchAll(() => exports_Effect.void));
117565
- }
117566
- }).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[TaskMonitor] nudge failed for ${role}@${chatroomId}: ${getErrorMessage(err)}`)))));
117567
- }
117568
116976
  function runNativeReviveEffect(task, runtime4, effectContext2, agentMgr) {
117569
116977
  const ctx = resolveTaskRunnerContextFromFull(task);
117570
116978
  if (!ctx)
@@ -117614,27 +117022,12 @@ async function fetchTaskForAction(sessionDeps, machineId, snapshotRow) {
117614
117022
  });
117615
117023
  return result ? mapAssignedTaskView(result) : null;
117616
117024
  }
117617
- function runCliNudgeEffect(task, runtime4, effectContext2, agentMgr, sessionDeps, machineId) {
117618
- console.log(buildCliNudgeLogLine(task));
117619
- executeCliNudge(task, runtime4, effectContext2, agentMgr, sessionDeps, machineId);
117620
- }
117621
117025
  async function clearStuckStoppingSlotIfNeeded(agentMgr, chatroomId, role) {
117622
117026
  const cleared = await agentMgr.clearStuckStoppingSlot(chatroomId, role);
117623
117027
  if (cleared) {
117624
117028
  console.log(`[TaskMonitor] cleared stuck stopping slot for ${role}@${chatroomId}`);
117625
117029
  }
117626
117030
  }
117627
- async function nudgeStuckTasks(tasks, now, cooldown, runtime4, effectContext2, agentMgr, sessionDeps, machineId) {
117628
- const getSlot = (chatroomId, role) => agentMgr.getSlot(chatroomId, role);
117629
- const cliTasks = tasks.filter((task) => !isNativeHarness(task.agentConfig.agentHarness));
117630
- for (const row of listTasksReadyForNudge(cliTasks, now, cooldown, getSlot)) {
117631
- await clearStuckStoppingSlotIfNeeded(agentMgr, row.chatroomId, row.agentConfig.role);
117632
- const full = await fetchTaskForAction(sessionDeps, machineId, row);
117633
- if (!full)
117634
- continue;
117635
- runCliNudgeEffect(full, runtime4, effectContext2, agentMgr, sessionDeps, machineId);
117636
- }
117637
- }
117638
117031
  async function reviveNativeTasks(tasks, localHealth, now, cooldown, runtime4, effectContext2, agentMgr, sessionDeps, machineId) {
117639
117032
  for (const row of listNativeTasksNeedingRevive(tasks, localHealth, now, cooldown)) {
117640
117033
  if (isRestartOrchestratorInFlight(row.chatroomId, row.agentConfig.role))
@@ -117681,14 +117074,12 @@ async function processTasksUpdate(runtime4, effectContext2, cooldown, agentMgr,
117681
117074
  sessionDeps,
117682
117075
  machineId
117683
117076
  });
117684
- await nudgeStuckTasks(filteredTasks, now, cooldown, runtime4, effectContext2, agentMgr, sessionDeps, machineId);
117685
117077
  }
117686
117078
  var init_task_delivery_processor = __esm(() => {
117687
117079
  init_agent2();
117688
117080
  init_parse_session_augmentation();
117689
117081
  init_esm();
117690
117082
  init_native_task_delivery_coordinator();
117691
- init_native_task_injector_logic();
117692
117083
  init_api3();
117693
117084
  init_convex_error();
117694
117085
  init_restart_orchestrator_in_flight();
@@ -118482,16 +117873,16 @@ var init_git_subscription = __esm(() => {
118482
117873
 
118483
117874
  // src/daemon/entry/workspace-git-inbound-registry.ts
118484
117875
  function registerWorkspaceGitInboundHandler(h) {
118485
- handler6 = h;
117876
+ handler5 = h;
118486
117877
  }
118487
117878
  function unregisterWorkspaceGitInboundHandler() {
118488
- handler6 = undefined;
117879
+ handler5 = undefined;
118489
117880
  }
118490
117881
  async function dispatchWorkspaceGitInboundEvent(event) {
118491
- if (handler6)
118492
- await handler6(event);
117882
+ if (handler5)
117883
+ await handler5(event);
118493
117884
  }
118494
- var handler6;
117885
+ var handler5;
118495
117886
 
118496
117887
  // src/events/lifecycle/on-daemon-shutdown.ts
118497
117888
  var onDaemonShutdownEffect;
@@ -118538,7 +117929,6 @@ function createDaemonRuntime(deps) {
118538
117929
  let fileTreeSubscriptionHandle = null;
118539
117930
  let workspaceListSubscriptionHandle = null;
118540
117931
  let logObserverSubscriptionHandle = null;
118541
- let directHarnessWorkerHandle = null;
118542
117932
  let agenticQueryWorkerHandle = null;
118543
117933
  let enhancerWorkerHandle = null;
118544
117934
  let taskInboxHandle = null;
@@ -118578,7 +117968,6 @@ function createDaemonRuntime(deps) {
118578
117968
  workspaceListSubscriptionHandle?.stop();
118579
117969
  taskInboxHandle?.stop();
118580
117970
  logObserverSubscriptionHandle?.stop();
118581
- directHarnessWorkerHandle?.stop();
118582
117971
  agenticQueryWorkerHandle?.stop();
118583
117972
  enhancerWorkerHandle?.stop();
118584
117973
  };
@@ -118603,12 +117992,8 @@ function createDaemonRuntime(deps) {
118603
117992
  await deps.agentLifecycleOutbox?.stopAll().catch(() => {
118604
117993
  return;
118605
117994
  });
118606
- if (directHarnessWorkerHandle) {
118607
- await withTimeout2(directHarnessWorkerHandle.closeSessionsOnShutdown(), PROCESS_KILL_TIMEOUT_MS);
118608
- } else {
118609
- for (const handle of activeSessions.values()) {
118610
- await withTimeout2(handle.close(), CLOSE_TIMEOUT_MS);
118611
- }
117995
+ for (const handle of activeSessions.values()) {
117996
+ await withTimeout2(handle.close(), CLOSE_TIMEOUT_MS);
118612
117997
  }
118613
117998
  for (const harness of harnesses.values()) {
118614
117999
  await withTimeout2(harness.close(), CLOSE_TIMEOUT_MS);
@@ -118684,21 +118069,13 @@ function createDaemonRuntime(deps) {
118684
118069
  taskInboxHandle = yield* startTaskInboxEffect(deps.wsClient);
118685
118070
  logObserverSubscriptionHandle = startLogObserverSubscription({ sessionId: session2.sessionId, machineId: session2.machineId }, deps.wsClient);
118686
118071
  const commandRunRuntime = yield* exports_Effect.runtime();
118687
- if (featureFlags.directHarnessWorkers) {
118688
- directHarnessWorkerHandle = startDirectHarnessSubscriptions({
118689
- sessionId: session2.sessionId,
118690
- machineId: session2.machineId,
118691
- backend: session2.backend,
118692
- convexUrl: session2.convexUrl
118693
- }, activeSessions, harnesses);
118694
- agenticQueryWorkerHandle = startAgenticQuerySubscriptions({
118695
- sessionId: session2.sessionId,
118696
- machineId: session2.machineId,
118697
- backend: session2.backend,
118698
- convexUrl: session2.convexUrl
118699
- }, activeSessions, harnesses);
118700
- enhancerWorkerHandle = startEnhancerSubscriptions(session2.sessionId, session2.machineId, session2.convexUrl, deps.wsClient, session2.backend, session2.agentServices, getActiveLogSink());
118701
- }
118072
+ agenticQueryWorkerHandle = startAgenticQuerySubscriptions({
118073
+ sessionId: session2.sessionId,
118074
+ machineId: session2.machineId,
118075
+ backend: session2.backend,
118076
+ convexUrl: session2.convexUrl
118077
+ }, activeSessions, harnesses);
118078
+ enhancerWorkerHandle = startEnhancerSubscriptions(session2.sessionId, session2.machineId, session2.convexUrl, deps.wsClient, session2.backend, session2.agentServices, getActiveLogSink());
118702
118079
  console.log(`
118703
118080
  Listening for commands...`);
118704
118081
  console.log(`Press Ctrl+C to stop
@@ -118725,14 +118102,12 @@ Listening for commands...`);
118725
118102
  }
118726
118103
  var PROCESS_KILL_TIMEOUT_MS = 6000, CLOSE_TIMEOUT_MS = 3000, SHUTDOWN_WATCHDOG_MS = 12000;
118727
118104
  var init_daemon_runtime = __esm(() => {
118728
- init_featureFlags();
118729
118105
  init_reliability();
118730
118106
  init_esm();
118731
118107
  init_start_subscriptions();
118732
118108
  init_command_dispatch();
118733
118109
  init_daemon_services();
118734
118110
  init_start_subscriptions2();
118735
- init_start_subscriptions3();
118736
118111
  init_file_content_subscription();
118737
118112
  init_file_tree_subscription();
118738
118113
  init_file_write_subscription();
@@ -118783,24 +118158,6 @@ function createCommandRouterDeps() {
118783
118158
  }
118784
118159
  var init_command_bridge = () => {};
118785
118160
 
118786
- // src/daemon/domain/usecase/process-direct-harness-prompt.ts
118787
- async function processDirectHarnessInbound(deps, event) {
118788
- await deps.dispatchInbound(event);
118789
- }
118790
- var init_process_direct_harness_prompt = () => {};
118791
-
118792
- // src/daemon/entry/bridge/direct-harness-bridge.ts
118793
- function createDirectHarnessRouterDeps() {
118794
- return {
118795
- deliverInbound: async (event) => {
118796
- await processDirectHarnessInbound({ dispatchInbound: dispatchDirectHarnessInboundEvent }, event);
118797
- }
118798
- };
118799
- }
118800
- var init_direct_harness_bridge = __esm(() => {
118801
- init_process_direct_harness_prompt();
118802
- });
118803
-
118804
118161
  // src/daemon/domain/usecase/process-enhancer-job.ts
118805
118162
  async function processEnhancerJobInbound(deps, event) {
118806
118163
  await deps.dispatchInbound(event);
@@ -118882,7 +118239,6 @@ var init_workspace_git_bridge = () => {};
118882
118239
  // src/daemon/entry/default-router-deps.ts
118883
118240
  function createDefaultEventRouterDeps() {
118884
118241
  return {
118885
- directHarness: createDirectHarnessRouterDeps(),
118886
118242
  command: createCommandRouterDeps(),
118887
118243
  workspaceGit: createWorkspaceGitRouterDeps(),
118888
118244
  file: createFileRouterDeps(),
@@ -118893,7 +118249,6 @@ function createDefaultEventRouterDeps() {
118893
118249
  var init_default_router_deps = __esm(() => {
118894
118250
  init_agentic_query_bridge();
118895
118251
  init_command_bridge();
118896
- init_direct_harness_bridge();
118897
118252
  init_enhancer_bridge();
118898
118253
  init_file_bridge();
118899
118254
  init_workspace_git_bridge();
@@ -118932,24 +118287,6 @@ function createAssignedTaskStatusPublisher(deps) {
118932
118287
  }
118933
118288
  var init_assigned_task_status = () => {};
118934
118289
 
118935
- // src/daemon/infrastructure/convex/publishers/capabilities.ts
118936
- function createCapabilitiesPublisher(deps) {
118937
- const capabilitiesPublisher = new ConvexCapabilitiesPublisher({
118938
- backend: deps.backend,
118939
- sessionId: deps.sessionId
118940
- });
118941
- return {
118942
- async publish(event) {
118943
- if (event.type !== "capabilities.updated")
118944
- return;
118945
- await capabilitiesPublisher.publish(event.capabilities);
118946
- }
118947
- };
118948
- }
118949
- var init_capabilities = __esm(() => {
118950
- init_convex_capabilities_publisher();
118951
- });
118952
-
118953
118290
  // src/daemon/infrastructure/convex/publishers/command-result.ts
118954
118291
  function createCommandResultPublisher(deps) {
118955
118292
  return {
@@ -119067,77 +118404,6 @@ var init_models = __esm(() => {
119067
118404
  init_api3();
119068
118405
  });
119069
118406
 
119070
- // src/daemon/infrastructure/convex/publishers/session-lifecycle.ts
119071
- function createSessionLifecyclePublisher(deps) {
119072
- const sessionRepository = new ConvexSessionRepository({
119073
- backend: deps.backend,
119074
- sessionId: deps.sessionId
119075
- });
119076
- return {
119077
- async publish(event) {
119078
- if (event.type !== "session.lifecycle")
119079
- return;
119080
- const { harnessSessionId, action, opencodeSessionId, sessionTitle } = event;
119081
- switch (action) {
119082
- case "opened":
119083
- if (!opencodeSessionId || !sessionTitle)
119084
- return;
119085
- await sessionRepository.associateOpenCodeSessionId(harnessSessionId, opencodeSessionId, sessionTitle);
119086
- break;
119087
- case "resumed":
119088
- await sessionRepository.markActive(harnessSessionId);
119089
- break;
119090
- case "idle":
119091
- await sessionRepository.markIdle(harnessSessionId);
119092
- break;
119093
- case "closed":
119094
- await sessionRepository.markClosed(harnessSessionId);
119095
- break;
119096
- case "failed":
119097
- await sessionRepository.markFailed(harnessSessionId);
119098
- break;
119099
- }
119100
- }
119101
- };
119102
- }
119103
- var init_session_lifecycle = __esm(() => {
119104
- init_convex_session_repository();
119105
- });
119106
-
119107
- // src/daemon/infrastructure/convex/publishers/turn-output.ts
119108
- function createTurnOutputPublisher(deps) {
119109
- const outputRepository = new ConvexOutputRepository({
119110
- backend: deps.backend,
119111
- sessionId: deps.sessionId
119112
- });
119113
- const sessionRepository = new ConvexSessionRepository({
119114
- backend: deps.backend,
119115
- sessionId: deps.sessionId
119116
- });
119117
- return {
119118
- async publish(event) {
119119
- if (event.type === "turn.chunk") {
119120
- await outputRepository.appendChunks(event.harnessSessionId, [
119121
- {
119122
- content: event.content,
119123
- timestamp: event.timestamp,
119124
- messageId: event.messageId,
119125
- partType: event.partType === "text" || event.partType === "reasoning" ? event.partType : undefined
119126
- }
119127
- ]);
119128
- return;
119129
- }
119130
- if (event.type === "turn.completed") {
119131
- await sessionRepository.finalizeAssistantTurn(event.turnId);
119132
- }
119133
- }
119134
- };
119135
- }
119136
- var init_turn_output = __esm(() => {
119137
- init_convex_output_repository();
119138
- init_convex_session_repository();
119139
- });
119140
-
119141
118407
  // src/daemon/infrastructure/convex/publishers/workspace-commands.ts
119142
118408
  function createWorkspaceCommandsPublisher(deps) {
119143
118409
  return {
@@ -119161,11 +118427,8 @@ var init_workspace_commands = __esm(() => {
119161
118427
  function createConvexPublishers(deps) {
119162
118428
  return {
119163
118429
  heartbeat: createDaemonHeartbeatPublisher(deps),
119164
- turnOutput: createTurnOutputPublisher(deps),
119165
- sessionLifecycle: createSessionLifecyclePublisher(deps),
119166
118430
  assignedTaskStatus: createAssignedTaskStatusPublisher(deps),
119167
118431
  gitState: createGitStatePublisher(deps),
119168
- capabilities: createCapabilitiesPublisher(deps),
119169
118432
  models: createModelsPublisher(deps),
119170
118433
  harnessFingerprint: createHarnessFingerprintPublisher(deps),
119171
118434
  commandResult: createCommandResultPublisher(deps),
@@ -119176,17 +118439,10 @@ function routeConvexEvent(publishers, event) {
119176
118439
  switch (event.type) {
119177
118440
  case "heartbeat":
119178
118441
  return publishers.heartbeat.publish(event);
119179
- case "turn.chunk":
119180
- case "turn.completed":
119181
- return publishers.turnOutput.publish(event);
119182
- case "session.lifecycle":
119183
- return publishers.sessionLifecycle.publish(event);
119184
118442
  case "task.status":
119185
118443
  return publishers.assignedTaskStatus.publish(event);
119186
118444
  case "git.state":
119187
118445
  return publishers.gitState.publish(event);
119188
- case "capabilities.updated":
119189
- return publishers.capabilities.publish(event);
119190
118446
  case "models.updated":
119191
118447
  return publishers.models.publish(event);
119192
118448
  case "harness.fingerprint.updated":
@@ -119224,14 +118480,11 @@ function createPublisherRegistry(deps = {}) {
119224
118480
  }
119225
118481
  var init_publisher_registry = __esm(() => {
119226
118482
  init_assigned_task_status();
119227
- init_capabilities();
119228
118483
  init_command_result();
119229
118484
  init_daemon_heartbeat();
119230
118485
  init_git_state();
119231
118486
  init_harness_fingerprint();
119232
118487
  init_models();
119233
- init_session_lifecycle();
119234
- init_turn_output();
119235
118488
  init_workspace_commands();
119236
118489
  });
119237
118490
 
@@ -119293,13 +118546,6 @@ async function handleCommandInbound(deps, event) {
119293
118546
  }
119294
118547
  }
119295
118548
 
119296
- // src/daemon/domain/usecase/handle-direct-harness-inbound.ts
119297
- async function handleDirectHarnessInbound(deps, event) {
119298
- if (deps.deliverInbound) {
119299
- await deps.deliverInbound(event);
119300
- }
119301
- }
119302
-
119303
118549
  // src/daemon/domain/usecase/handle-enhancer-inbound.ts
119304
118550
  async function handleEnhancerInbound(deps, event) {
119305
118551
  if (deps.deliverInbound) {
@@ -119324,11 +118570,6 @@ async function handleWorkspaceGitInbound(deps, event) {
119324
118570
  // src/daemon/entry/event-router.ts
119325
118571
  async function routeInboundEvent(deps, event) {
119326
118572
  switch (event.type) {
119327
- case "direct-harness.session-opened":
119328
- case "direct-harness.prompt":
119329
- case "direct-harness.command":
119330
- await handleDirectHarnessInbound(deps.directHarness, event);
119331
- break;
119332
118573
  case "command.received":
119333
118574
  case "command-run.updated":
119334
118575
  await handleCommandInbound(deps.command, event);
@@ -119359,7 +118600,7 @@ var init_event_router = () => {};
119359
118600
  function startAgenticQueryPromptSubscriber(deps, onEvent) {
119360
118601
  let processing = false;
119361
118602
  const emittedThisDrain = new Set;
119362
- const drain2 = (batch) => {
118603
+ const drain = (batch) => {
119363
118604
  if (!batch.messages?.length)
119364
118605
  return;
119365
118606
  const runIds = new Set(batch.messages.map((m) => m.runId));
@@ -119377,7 +118618,7 @@ function startAgenticQueryPromptSubscriber(deps, onEvent) {
119377
118618
  return;
119378
118619
  processing = true;
119379
118620
  try {
119380
- drain2(batch);
118621
+ drain(batch);
119381
118622
  } finally {
119382
118623
  processing = false;
119383
118624
  emittedThisDrain.clear();
@@ -119457,106 +118698,6 @@ var init_command_run = __esm(() => {
119457
118698
  init_api3();
119458
118699
  });
119459
118700
 
119460
- // src/daemon/infrastructure/convex/subscribers/direct-harness-command.ts
119461
- function startDirectHarnessCommandSubscriber(deps, onEvent) {
119462
- const seen = new Set;
119463
- let processing = false;
119464
- const drain2 = async () => {
119465
- const pending3 = await deps.wsClient.query(api.daemon.directHarness.commands.listPendingCommands, { sessionId: deps.sessionId, machineId: deps.machineId });
119466
- if (!pending3?.length)
119467
- return;
119468
- for (const cmd of pending3) {
119469
- if (seen.has(cmd._id))
119470
- continue;
119471
- seen.add(cmd._id);
119472
- onEvent({ type: "direct-harness.command", commandId: cmd._id });
119473
- }
119474
- };
119475
- const unsub = deps.wsClient.onUpdate(api.daemon.directHarness.commands.listPendingCommands, { sessionId: deps.sessionId, machineId: deps.machineId }, () => {
119476
- if (processing)
119477
- return;
119478
- processing = true;
119479
- drain2().catch((err) => console.warn(`[daemon] direct-harness-command drain error: ${err instanceof Error ? err.message : String(err)}`)).finally(() => {
119480
- processing = false;
119481
- });
119482
- }, (err) => {
119483
- console.warn(`[daemon] direct-harness-command subscriber error: ${err instanceof Error ? err.message : String(err)}`);
119484
- });
119485
- return {
119486
- async stop() {
119487
- unsub();
119488
- }
119489
- };
119490
- }
119491
- var init_direct_harness_command = __esm(() => {
119492
- init_api3();
119493
- });
119494
-
119495
- // src/daemon/infrastructure/convex/subscribers/direct-harness-prompt.ts
119496
- function startDirectHarnessPromptSubscriber(deps, onEvent) {
119497
- let processing = false;
119498
- const emittedForDrain = new Set;
119499
- const drain2 = async () => {
119500
- const pending3 = await deps.wsClient.query(api.daemon.directHarness.messages.pendingForMachine, { sessionId: deps.sessionId, machineId: deps.machineId });
119501
- if (!pending3?.messages.length)
119502
- return;
119503
- const sessionIds = new Set(pending3.messages.map((m) => m.harnessSessionId));
119504
- for (const harnessSessionId of sessionIds) {
119505
- if (emittedForDrain.has(harnessSessionId))
119506
- continue;
119507
- emittedForDrain.add(harnessSessionId);
119508
- onEvent({ type: "direct-harness.prompt", harnessSessionId });
119509
- }
119510
- };
119511
- const unsub = deps.wsClient.onUpdate(api.daemon.directHarness.messages.pendingForMachine, { sessionId: deps.sessionId, machineId: deps.machineId }, () => {
119512
- if (processing)
119513
- return;
119514
- processing = true;
119515
- drain2().catch((err) => console.warn(`[daemon] direct-harness-prompt drain error: ${err instanceof Error ? err.message : String(err)}`)).finally(() => {
119516
- processing = false;
119517
- emittedForDrain.clear();
119518
- });
119519
- }, (err) => {
119520
- console.warn(`[daemon] direct-harness-prompt subscriber error: ${err instanceof Error ? err.message : String(err)}`);
119521
- });
119522
- return {
119523
- async stop() {
119524
- unsub();
119525
- }
119526
- };
119527
- }
119528
- var init_direct_harness_prompt = __esm(() => {
119529
- init_api3();
119530
- });
119531
-
119532
- // src/daemon/infrastructure/convex/subscribers/direct-harness-session.ts
119533
- function startDirectHarnessSessionSubscriber(deps, onEvent) {
119534
- const seen = new Set;
119535
- const unsub = deps.wsClient.onUpdate(api.daemon.directHarness.sessions.listPendingSessionsForMachine, { sessionId: deps.sessionId, machineId: deps.machineId }, (pendingSessions) => {
119536
- if (!pendingSessions?.length)
119537
- return;
119538
- for (const session2 of pendingSessions) {
119539
- if (seen.has(session2._id))
119540
- continue;
119541
- seen.add(session2._id);
119542
- onEvent({
119543
- type: "direct-harness.session-opened",
119544
- harnessSessionId: session2._id
119545
- });
119546
- }
119547
- }, (err) => {
119548
- console.warn(`[daemon] direct-harness-session subscriber error: ${err instanceof Error ? err.message : String(err)}`);
119549
- });
119550
- return {
119551
- async stop() {
119552
- unsub();
119553
- }
119554
- };
119555
- }
119556
- var init_direct_harness_session = __esm(() => {
119557
- init_api3();
119558
- });
119559
-
119560
118701
  // src/daemon/infrastructure/convex/subscribers/enhancer-job.ts
119561
118702
  function startEnhancerJobSubscriber2(deps, onEvent) {
119562
118703
  const seen = new Set;
@@ -119775,7 +118916,7 @@ function startMachineCommandInboxSubscriber(deps, onClaimed) {
119775
118916
  let queued = false;
119776
118917
  let stopped = false;
119777
118918
  const args2 = { sessionId: deps.sessionId, machineId: deps.machineId };
119778
- const drain2 = async () => {
118919
+ const drain = async () => {
119779
118920
  if (stopped || draining) {
119780
118921
  queued = true;
119781
118922
  return;
@@ -119794,9 +118935,9 @@ function startMachineCommandInboxSubscriber(deps, onClaimed) {
119794
118935
  };
119795
118936
  const unsub = deps.wsClient.onUpdate(api.daemon.machineCommandInbox.watchNext, args2, (result) => {
119796
118937
  if (result?.commandId)
119797
- drain2();
118938
+ drain();
119798
118939
  }, (err) => console.warn(`[daemon] machine-command-inbox watch error: ${String(err)}`));
119799
- drain2();
118940
+ drain();
119800
118941
  return {
119801
118942
  async stop() {
119802
118943
  stopped = true;
@@ -119813,9 +118954,6 @@ function startAllSubscribers(deps) {
119813
118954
  const onEvent = (event) => {
119814
118955
  routeInboundEvent(deps.router, event);
119815
118956
  };
119816
- const session2 = startDirectHarnessSessionSubscriber(deps, onEvent);
119817
- const prompt = startDirectHarnessPromptSubscriber(deps, onEvent);
119818
- const directHarnessCommand = startDirectHarnessCommandSubscriber(deps, onEvent);
119819
118957
  const machineCommands = startMachineCommandInboxSubscriber(deps, async (claimed) => {
119820
118958
  await dispatchCommandInboundEvent({
119821
118959
  type: "command.received",
@@ -119835,9 +118973,6 @@ function startAllSubscribers(deps) {
119835
118973
  return {
119836
118974
  async stopAll() {
119837
118975
  await Promise.all([
119838
- session2.stop(),
119839
- prompt.stop(),
119840
- directHarnessCommand.stop(),
119841
118976
  machineCommands.stop(),
119842
118977
  commandRun.stop(),
119843
118978
  gitRequest.stop(),
@@ -119857,9 +118992,6 @@ var init_subscriber_registry = __esm(() => {
119857
118992
  init_agentic_query_prompt();
119858
118993
  init_agentic_query_session();
119859
118994
  init_command_run();
119860
- init_direct_harness_command();
119861
- init_direct_harness_prompt();
119862
- init_direct_harness_session();
119863
118995
  init_enhancer_job();
119864
118996
  init_file_content_request();
119865
118997
  init_file_tree_release_request();
@@ -122941,9 +122073,9 @@ var require_event_target2 = __commonJS((exports, module) => {
122941
122073
  }
122942
122074
  Object.defineProperty(MessageEvent.prototype, "data", { enumerable: true });
122943
122075
  var EventTarget = {
122944
- addEventListener(type, handler7, options = {}) {
122076
+ addEventListener(type, handler6, options = {}) {
122945
122077
  for (const listener of this.listeners(type)) {
122946
- if (!options[kForOnEventAttribute] && listener[kListener] === handler7 && !listener[kForOnEventAttribute]) {
122078
+ if (!options[kForOnEventAttribute] && listener[kListener] === handler6 && !listener[kForOnEventAttribute]) {
122947
122079
  return;
122948
122080
  }
122949
122081
  }
@@ -122954,7 +122086,7 @@ var require_event_target2 = __commonJS((exports, module) => {
122954
122086
  data: isBinary ? data : data.toString()
122955
122087
  });
122956
122088
  event[kTarget] = this;
122957
- callListener(handler7, this, event);
122089
+ callListener(handler6, this, event);
122958
122090
  };
122959
122091
  } else if (type === "close") {
122960
122092
  wrapper = function onClose(code2, message) {
@@ -122964,7 +122096,7 @@ var require_event_target2 = __commonJS((exports, module) => {
122964
122096
  wasClean: this._closeFrameReceived && this._closeFrameSent
122965
122097
  });
122966
122098
  event[kTarget] = this;
122967
- callListener(handler7, this, event);
122099
+ callListener(handler6, this, event);
122968
122100
  };
122969
122101
  } else if (type === "error") {
122970
122102
  wrapper = function onError3(error51) {
@@ -122973,28 +122105,28 @@ var require_event_target2 = __commonJS((exports, module) => {
122973
122105
  message: error51.message
122974
122106
  });
122975
122107
  event[kTarget] = this;
122976
- callListener(handler7, this, event);
122108
+ callListener(handler6, this, event);
122977
122109
  };
122978
122110
  } else if (type === "open") {
122979
122111
  wrapper = function onOpen() {
122980
122112
  const event = new Event2("open");
122981
122113
  event[kTarget] = this;
122982
- callListener(handler7, this, event);
122114
+ callListener(handler6, this, event);
122983
122115
  };
122984
122116
  } else {
122985
122117
  return;
122986
122118
  }
122987
122119
  wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute];
122988
- wrapper[kListener] = handler7;
122120
+ wrapper[kListener] = handler6;
122989
122121
  if (options.once) {
122990
122122
  this.once(type, wrapper);
122991
122123
  } else {
122992
122124
  this.on(type, wrapper);
122993
122125
  }
122994
122126
  },
122995
- removeEventListener(type, handler7) {
122127
+ removeEventListener(type, handler6) {
122996
122128
  for (const listener of this.listeners(type)) {
122997
- if (listener[kListener] === handler7 && !listener[kForOnEventAttribute]) {
122129
+ if (listener[kListener] === handler6 && !listener[kForOnEventAttribute]) {
122998
122130
  this.removeListener(type, listener);
122999
122131
  break;
123000
122132
  }
@@ -123523,16 +122655,16 @@ var require_websocket2 = __commonJS((exports, module) => {
123523
122655
  }
123524
122656
  return null;
123525
122657
  },
123526
- set(handler7) {
122658
+ set(handler6) {
123527
122659
  for (const listener of this.listeners(method)) {
123528
122660
  if (listener[kForOnEventAttribute]) {
123529
122661
  this.removeListener(method, listener);
123530
122662
  break;
123531
122663
  }
123532
122664
  }
123533
- if (typeof handler7 !== "function")
122665
+ if (typeof handler6 !== "function")
123534
122666
  return;
123535
- this.addEventListener(method, handler7, {
122667
+ this.addEventListener(method, handler6, {
123536
122668
  [kForOnEventAttribute]: true
123537
122669
  });
123538
122670
  }
@@ -134571,8 +133703,8 @@ import * as os2 from "os";
134571
133703
  import * as path8 from "path";
134572
133704
  async function isChatroomInstalledDefault() {
134573
133705
  try {
134574
- const { execSync: execSync3 } = await import("child_process");
134575
- execSync3("chatroom --version", { stdio: "pipe" });
133706
+ const { execSync: execSync2 } = await import("child_process");
133707
+ execSync2("chatroom --version", { stdio: "pipe" });
134576
133708
  return true;
134577
133709
  } catch {
134578
133710
  return false;
@@ -135626,4 +134758,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
135626
134758
  });
135627
134759
  program2.parse();
135628
134760
 
135629
- //# debugId=2AE77EB9BC17ACF764756E2164756E21
134761
+ //# debugId=FC425A6C08DFE01664756E2164756E21