chatroom-cli 1.58.0 → 1.58.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
@@ -31677,7 +31677,7 @@ function isClassifiableHarnessLogLine(line) {
31677
31677
  return true;
31678
31678
  if (line.includes(" error]"))
31679
31679
  return true;
31680
- if (!HARNESS_LOG_PREFIX.test(line))
31680
+ if (line.includes(" run-error]"))
31681
31681
  return true;
31682
31682
  return false;
31683
31683
  }
@@ -31716,7 +31716,7 @@ function formatTerminalProviderFailureMessage(logLines) {
31716
31716
  `).trim();
31717
31717
  return blob ? `Provider rate limit or quota error (non-retryable): ${blob.slice(-500)}` : "Provider rate limit or quota error (non-retryable)";
31718
31718
  }
31719
- var QUOTA_PHRASES, PROVIDER_ERROR_NAMES, HARNESS_LOG_PREFIX;
31719
+ var QUOTA_PHRASES, PROVIDER_ERROR_NAMES;
31720
31720
  var init_terminal_provider_error = __esm(() => {
31721
31721
  QUOTA_PHRASES = [
31722
31722
  "usagelimit",
@@ -31730,7 +31730,6 @@ var init_terminal_provider_error = __esm(() => {
31730
31730
  "exceeded your weekly"
31731
31731
  ];
31732
31732
  PROVIDER_ERROR_NAMES = ["ai_apicallerror", "ai_retryerror"];
31733
- HARNESS_LOG_PREFIX = /^\[[^\]]+\] role:/;
31734
31733
  });
31735
31734
 
31736
31735
  // src/infrastructure/services/remote-agents/opencode-sdk/session-event-forwarder.ts
@@ -75562,6 +75561,12 @@ Put your **complete** deliverable in the handoff message — not in session text
75562
75561
  ---`;
75563
75562
  }
75564
75563
 
75564
+ // ../../services/backend/prompts/utils/code-change-verification.ts
75565
+ var CODE_CHANGE_VERIFICATION_COMMAND = "pnpm typecheck && pnpm test", CODE_CHANGE_VERIFICATION_CONFIRMATION;
75566
+ var init_code_change_verification = __esm(() => {
75567
+ CODE_CHANGE_VERIFICATION_CONFIRMATION = `- [ ] I confirm that I have run \`${CODE_CHANGE_VERIFICATION_COMMAND}\` (only required if code changes were made)`;
75568
+ });
75569
+
75565
75570
  // ../../services/backend/prompts/teams/duo/handoff-templates/builder-to-planner.ts
75566
75571
  function getBuilderToPlannerHandoffTemplate() {
75567
75572
  return `${getHandoffRecipientVisibilityCallout("planner")}
@@ -75586,8 +75591,8 @@ function getBuilderToPlannerHandoffTemplate() {
75586
75591
  - \`path/to/file.ts\` — <what changed and why>
75587
75592
  <evidence the goal was met — list every file you modified>
75588
75593
 
75589
- ## Verification
75590
- - \`pnpm typecheck && pnpm test\` — <pass/fail + notes>
75594
+ ## Code Change Verification
75595
+ ${CODE_CHANGE_VERIFICATION_CONFIRMATION}
75591
75596
 
75592
75597
  ## Blockers / questions
75593
75598
  <anything needing planner decision, or "Not Applicable">
@@ -75596,18 +75601,18 @@ function getBuilderToPlannerHandoffTemplate() {
75596
75601
  <specific areas for planner to check, or "Not Applicable">
75597
75602
  \`\`\``;
75598
75603
  }
75599
- var init_builder_to_planner = () => {};
75604
+ var init_builder_to_planner = __esm(() => {
75605
+ init_code_change_verification();
75606
+ });
75600
75607
 
75601
75608
  // ../../services/backend/prompts/teams/duo/handoff-templates/planner-to-builder.ts
75602
75609
  function getPlannerToBuilderHandoffTemplate(nativeIntegration = false) {
75603
- const sessionManagement = nativeIntegration ? `**Native harnesses** (\`cursor-sdk\`, \`opencode-sdk\`): in-session context compaction is supported by the SDK runtime. \`new_session\` triggers a fresh context within the same process; the session stays active and tasks continue via injection.` : `**Native harnesses** (\`cursor-sdk\`, \`opencode-sdk\`): in-session context compaction is supported by the SDK runtime. \`new_session\` triggers a fresh context within the same process; no get-next-task rejoin needed.
75604
-
75605
- **CLI harnesses** (all others): in-session compaction is NOT supported. \`new_session\` requires a hard restart — the daemon stops the agent, cold-starts it, and the agent must rejoin via \`get-next-task\`. \`none\` resumes the prior session (\`wantResume=true\`).`;
75610
+ const sessionManagement = nativeIntegration ? `\`compact\` runs in-session context compaction via the SDK runtime. \`new_session\` starts a completely new session within the same process (not compaction). \`none\` continues the prior session. Tasks continue via injection.` : `\`compact\` is NOT supported use \`none\` or \`new_session\`. \`new_session\` requires a hard restart (daemon stops agent, cold-starts, agent rejoins via \`get-next-task\`). \`none\` resumes prior session (\`wantResume=true\`).`;
75606
75611
  return `${getHandoffRecipientVisibilityCallout("builder")}
75607
75612
 
75608
75613
  **Delegation Brief (Planner → Builder)** — paste into the handoff message and fill in EVERY field. No field is optional: if a section does not apply, write \`Not Applicable\` (do not delete the section).
75609
75614
 
75610
- **Division of labor:** You (planner) own architecture and API shape. The builder implements exactly what you specify, runs verification, and does not redesign or invent alternatives unless blocked.
75615
+ **Division of labor:** You (planner) own architecture and API shape. The builder implements exactly what you specify and does not redesign or invent alternatives unless blocked.
75611
75616
 
75612
75617
  **Detail bar:** Specify down to **every file** the builder will create or modify (full repo paths). Include code snippets — types, signatures, stubs, or target implementations — until a competent builder **cannot misinterpret** what to write. Vague layers ("update the backend", "fix the component") are not acceptable.
75613
75618
 
@@ -75659,7 +75664,6 @@ Cross-file types, interfaces, or patterns that apply beyond a single file. Write
75659
75664
 
75660
75665
  ## Requirements (acceptance criteria)
75661
75666
  - <verifiable outcome the builder can self-check>
75662
- - Verify: \`pnpm typecheck && pnpm test\`
75663
75667
 
75664
75668
  ## What to avoid
75665
75669
  - <anti-patterns, recurring mistakes, or scope creep for this slice — be explicit>
@@ -75671,11 +75675,12 @@ Cross-file types, interfaces, or patterns that apply beyond a single file. Write
75671
75675
  ## Out of scope
75672
75676
  - <files or areas the builder must NOT touch in this slice, or "Not Applicable">
75673
75677
 
75674
- ## Session Management
75675
- Valid values: \`new_session\` | \`none\`
75676
- - \`new_session\` — start a fresh agent session (default)
75678
+ ## Session Augmentation
75679
+ Valid values: \`none\` | \`compact\` | \`new_session\`
75677
75680
  - \`none\` — continue prior session context
75678
- // data:agent.compress_context=new_session
75681
+ - \`compact\` — run in-session context compaction (native SDK harnesses only)
75682
+ - \`new_session\` — start a completely new session (default)
75683
+ // data:agent.session_augmentation=new_session
75679
75684
 
75680
75685
  ${sessionManagement}
75681
75686
 
@@ -75733,14 +75738,16 @@ flowchart TD
75733
75738
  A[Component] --> B[Component]
75734
75739
  \`\`\`
75735
75740
 
75736
- ## Verification
75737
- - \`pnpm typecheck && pnpm test\` — <result>
75741
+ ## Code Change Verification
75742
+ ${CODE_CHANGE_VERIFICATION_CONFIRMATION}
75738
75743
 
75739
75744
  ## Notes / Next steps
75740
75745
  <anything the user should know, follow-ups, or open questions, or "Not Applicable">
75741
75746
  \`\`\``;
75742
75747
  }
75743
- var init_planner_to_user = () => {};
75748
+ var init_planner_to_user = __esm(() => {
75749
+ init_code_change_verification();
75750
+ });
75744
75751
 
75745
75752
  // ../../services/backend/prompts/teams/duo/handoff-templates/index.ts
75746
75753
  function getDuoHandoffTemplate(query) {
@@ -75790,9 +75797,6 @@ flowchart TD
75790
75797
  A[Component] --> B[Component]
75791
75798
  \`\`\`
75792
75799
 
75793
- ## Verification
75794
- - \`pnpm typecheck && pnpm test\` — <result>
75795
-
75796
75800
  ## Notes / Next steps
75797
75801
  <anything the user should know, follow-ups, or open questions, or "Not Applicable">
75798
75802
  \`\`\``;
@@ -85789,6 +85793,9 @@ function isInjectableNativeAction(action) {
85789
85793
  return true;
85790
85794
  return action === NATIVE_WAITING_ACTION;
85791
85795
  }
85796
+ function shouldEmitNativeWaitingOnTurnEnd(lastStatus) {
85797
+ return lastStatus !== "task.acknowledged" && lastStatus !== "task.inProgress";
85798
+ }
85792
85799
  function isNativeIdleAfterTaskComplete(participant) {
85793
85800
  return participant.lastSeenAction === NATIVE_TASK_INJECTED_ACTION && participant.lastStatus === "task.completed";
85794
85801
  }
@@ -85858,13 +85865,21 @@ function shouldDeliverNativeTask(task, opts) {
85858
85865
  return isInjectableNativeAction(task.participant?.lastSeenAction) || isNativeIdleAfterTaskComplete(task.participant ?? {}) || isNativeAcknowledgedInjectionRetry(task);
85859
85866
  }
85860
85867
  function buildNativeInjectionPrompt(params) {
85861
- const { taskDeliveryOutput, compressMode } = params;
85862
- if (compressMode === "new_session") {
85868
+ const { taskDeliveryOutput, augmentationMode } = params;
85869
+ if (augmentationMode === "compact") {
85863
85870
  return [
85864
85871
  "⚠️ Context was compacted. Run `chatroom get-system-prompt` only if role instructions are missing.",
85865
85872
  "",
85866
85873
  taskDeliveryOutput
85867
85874
  ].join(`
85875
+ `);
85876
+ }
85877
+ if (augmentationMode === "new_session") {
85878
+ return [
85879
+ "⚠️ Starting a new agent session. Run `chatroom get-system-prompt` to reload role instructions if needed.",
85880
+ "",
85881
+ taskDeliveryOutput
85882
+ ].join(`
85868
85883
  `);
85869
85884
  }
85870
85885
  return taskDeliveryOutput;
@@ -85874,18 +85889,23 @@ var init_native_task_injector_logic = __esm(() => {
85874
85889
  init_native_integration();
85875
85890
  });
85876
85891
 
85877
- // ../../services/backend/src/domain/handoff/parse-compress-context.ts
85892
+ // ../../services/backend/src/domain/entities/team-agent-settings.ts
85893
+ function roleSupportsSessionAugmentation(role) {
85894
+ const normalized = role.toLowerCase();
85895
+ return SESSION_AUGMENTATION_ROLES.some((r) => r === normalized);
85896
+ }
85897
+ var SESSION_AUGMENTATION_ROLES;
85898
+ var init_team_agent_settings = __esm(() => {
85899
+ SESSION_AUGMENTATION_ROLES = ["builder"];
85900
+ });
85901
+
85902
+ // ../../services/backend/src/domain/handoff/parse-session-augmentation.ts
85878
85903
  function findSectionIndex(content, headings) {
85879
85904
  const indices = headings.map((heading) => content.indexOf(heading)).filter((idx) => idx !== -1);
85880
85905
  return indices.length === 0 ? -1 : Math.min(...indices);
85881
85906
  }
85882
85907
  function normalizeMode(raw) {
85883
- const value = raw.toLowerCase();
85884
- if (value === "reset")
85885
- return "new_session";
85886
- if (value === "none")
85887
- return value;
85888
- return DEFAULT_MODE;
85908
+ return MODE_ALIASES[raw.toLowerCase()] ?? DEFAULT_MODE;
85889
85909
  }
85890
85910
  function extractSectionBody(content, sectionIdx) {
85891
85911
  const matchedHeading = SECTION_HEADINGS.find((h) => content.indexOf(h, sectionIdx) === sectionIdx) ?? SECTION_HEADINGS[0];
@@ -85893,7 +85913,7 @@ function extractSectionBody(content, sectionIdx) {
85893
85913
  const nextHeading = afterSection.slice(matchedHeading.length).search(/\n## /);
85894
85914
  return nextHeading === -1 ? afterSection : afterSection.slice(0, matchedHeading.length + nextHeading);
85895
85915
  }
85896
- function parseCompressContext(handoffContent) {
85916
+ function parseSessionAugmentation(handoffContent) {
85897
85917
  const sectionIdx = findSectionIndex(handoffContent, SECTION_HEADINGS);
85898
85918
  if (sectionIdx === -1)
85899
85919
  return DEFAULT_MODE;
@@ -85902,13 +85922,33 @@ function parseCompressContext(handoffContent) {
85902
85922
  return DEFAULT_MODE;
85903
85923
  return normalizeMode(match17[1]);
85904
85924
  }
85905
- function compressContextToWantResume(mode) {
85906
- return mode === "none";
85925
+ function resolveSessionAugmentationForRole(handoffContent, role) {
85926
+ if (!roleSupportsSessionAugmentation(role)) {
85927
+ return "none";
85928
+ }
85929
+ return parseSessionAugmentation(handoffContent);
85907
85930
  }
85908
- var SECTION_HEADINGS, DATA_TAG, DEFAULT_MODE = "new_session";
85909
- var init_parse_compress_context = __esm(() => {
85910
- SECTION_HEADINGS = ["## Session Management", "## Restart new context"];
85911
- DATA_TAG = /\/\/\s*data:agent\.compress_context=(new_session|reset|none)\b/i;
85931
+ function sessionAugmentationToWantResume(mode) {
85932
+ return mode === "none" || mode === "compact";
85933
+ }
85934
+ function sessionAugmentationNewSessionStarted(mode) {
85935
+ return mode === "new_session";
85936
+ }
85937
+ var SECTION_HEADINGS, DATA_TAG, DEFAULT_MODE = "new_session", MODE_ALIASES;
85938
+ var init_parse_session_augmentation = __esm(() => {
85939
+ init_team_agent_settings();
85940
+ SECTION_HEADINGS = [
85941
+ "## Session Augmentation",
85942
+ "## Session Management",
85943
+ "## Restart new context"
85944
+ ];
85945
+ DATA_TAG = /\/\/\s*data:agent\.(?:session_augmentation|compress_context)=(none|compact|new_session|reset)\b/i;
85946
+ MODE_ALIASES = {
85947
+ reset: "new_session",
85948
+ none: "none",
85949
+ compact: "compact",
85950
+ new_session: "new_session"
85951
+ };
85912
85952
  });
85913
85953
 
85914
85954
  // src/commands/machine/daemon-start/native-task-injector.ts
@@ -85952,9 +85992,10 @@ function runNativeInjectionEffect(task, harnessSessionId, deps, ledger) {
85952
85992
  return yield* exports_Effect.fail(deliveryResult.left);
85953
85993
  }
85954
85994
  const delivery = deliveryResult.right;
85995
+ const augmentationMode = resolveSessionAugmentationForRole(taskContent, role);
85955
85996
  const prompt = buildNativeInjectionPrompt({
85956
85997
  taskDeliveryOutput: delivery.fullCliOutput,
85957
- compressMode: parseCompressContext(taskContent)
85998
+ augmentationMode
85958
85999
  });
85959
86000
  yield* exports_Effect.tryPromise({
85960
86001
  try: () => deps.backend.mutation(api.participants.join, {
@@ -85966,6 +86007,21 @@ function runNativeInjectionEffect(task, harnessSessionId, deps, ledger) {
85966
86007
  }),
85967
86008
  catch: (err) => err
85968
86009
  }).pipe(exports_Effect.tapError(() => exports_Effect.sync(() => ledger.clearDelivery(taskId, harnessSessionId))));
86010
+ if (roleSupportsSessionAugmentation(role)) {
86011
+ yield* exports_Effect.tryPromise({
86012
+ try: () => deps.backend.mutation(api.machines.emitSessionAugmented, {
86013
+ sessionId: deps.sessionId,
86014
+ machineId: deps.machineId,
86015
+ chatroomId,
86016
+ role,
86017
+ taskId,
86018
+ mode: augmentationMode,
86019
+ newSessionStarted: sessionAugmentationNewSessionStarted(augmentationMode),
86020
+ harnessSessionId
86021
+ }),
86022
+ catch: (err) => err
86023
+ }).pipe(exports_Effect.catchAll(() => exports_Effect.void));
86024
+ }
85969
86025
  const resumeResult = yield* exports_Effect.tryPromise({
85970
86026
  try: () => deps.agentMgr.resumeTurnForSlot({ chatroomId, role, prompt }),
85971
86027
  catch: (err) => err
@@ -85980,7 +86036,8 @@ function runNativeInjectionEffect(task, harnessSessionId, deps, ledger) {
85980
86036
  }
85981
86037
  var init_native_task_injector = __esm(() => {
85982
86038
  init_participant();
85983
- init_parse_compress_context();
86039
+ init_team_agent_settings();
86040
+ init_parse_session_augmentation();
85984
86041
  init_esm();
85985
86042
  init_native_task_injector_logic();
85986
86043
  init_api3();
@@ -86024,6 +86081,7 @@ class NativeTaskDeliveryCoordinator {
86024
86081
  return;
86025
86082
  yield* runNativeInjectionEffect(full, harnessSessionId, {
86026
86083
  sessionId: sessionDeps.sessionId,
86084
+ machineId: sessionDeps.machineId,
86027
86085
  backend: sessionDeps.backend,
86028
86086
  agentMgr: {
86029
86087
  resumeTurnForSlot: (args2) => exports_Effect.runPromise(agentMgr.resumeTurnForSlot(args2))
@@ -86221,24 +86279,12 @@ var init_agent_lifecycle = __esm(() => {
86221
86279
  init_restart_decision();
86222
86280
  });
86223
86281
 
86224
- // src/domain/agent-lifecycle/policies/cursor-sdk-run-error.ts
86225
- function isCursorSdkRunErrorInLogs(logLines) {
86226
- return logLines.some((line) => line.includes(" run-error]"));
86227
- }
86228
- function formatCursorSdkRunErrorMessage(logLines) {
86229
- const line = [...logLines].reverse().find((l) => l.includes(" run-error]"));
86230
- return line?.trim() ?? "Cursor SDK run failed";
86231
- }
86232
-
86233
86282
  // src/commands/machine/daemon-start/native-harness-session-exit.ts
86234
86283
  function isNativeHarnessSessionDiscardedOnExit(ctx) {
86235
- const { harness, harnessSessionId, stopReason, recentLogLines, supportsDaemonMemoryResume } = ctx;
86284
+ const { harness, harnessSessionId, stopReason, supportsDaemonMemoryResume } = ctx;
86236
86285
  if (!harness || !harnessSessionId) {
86237
86286
  return false;
86238
86287
  }
86239
- if (isCursorSdkRunErrorInLogs(recentLogLines ?? [])) {
86240
- return true;
86241
- }
86242
86288
  if (!supportsDaemonMemoryResume) {
86243
86289
  return true;
86244
86290
  }
@@ -86377,8 +86423,17 @@ function appendRecentLogLine(slot, line) {
86377
86423
  }
86378
86424
  var RECENT_LOG_LINE_CAP2 = 100;
86379
86425
 
86426
+ // src/domain/agent-lifecycle/policies/cursor-sdk-run-error.ts
86427
+ function isCursorSdkRunErrorInLogs(logLines) {
86428
+ return logLines.some((line) => line.includes(" run-error]"));
86429
+ }
86430
+ function formatCursorSdkRunErrorMessage(logLines) {
86431
+ const line = [...logLines].reverse().find((l) => l.includes(" run-error]"));
86432
+ return line?.trim() ?? "Cursor SDK run failed";
86433
+ }
86434
+
86380
86435
  // src/domain/agent-lifecycle/policies/cursor-sdk-session-reopen-retry.ts
86381
- var CURSOR_SDK_SESSION_REOPEN_MAX_ATTEMPTS = 20, CURSOR_SDK_SESSION_REOPEN_INTERVAL_MS = 5000, CURSOR_SDK_SESSION_REOPEN_REASON = "platform.cursor_sdk_session_reopen";
86436
+ var CURSOR_SDK_SESSION_REOPEN_MAX_ATTEMPTS = 20, CURSOR_SDK_SESSION_REOPEN_INTERVAL_MS = 5000, CURSOR_SDK_SESSION_REOPEN_REASON = "platform.cursor_sdk_session_reopen", CURSOR_SDK_SESSION_RESUME_FIRST_ATTEMPTS = 3;
86382
86437
 
86383
86438
  // src/domain/agent-lifecycle/use-cases/handle-turn-completed.ts
86384
86439
  async function handleTurnCompleted(deps, input, slot) {
@@ -86988,8 +87043,10 @@ class AgentProcessManager {
86988
87043
  console.log(`[AgentProcessManager] ⛔ Terminal provider error for ${opts.role} — emitted agent.startFailed`);
86989
87044
  return;
86990
87045
  }
86991
- await this.emitNativeWaiting(opts.chatroomId, opts.role, opts.harness);
86992
- console.log(`[AgentProcessManager] ✅ Native harness idle for ${opts.role} (native:waiting)`);
87046
+ const emitted = await this.emitNativeWaiting(opts.chatroomId, opts.role, opts.harness, "turn-end");
87047
+ if (emitted) {
87048
+ console.log(`[AgentProcessManager] ✅ Native harness idle for ${opts.role} (native:waiting)`);
87049
+ }
86993
87050
  }
86994
87051
  async handleExit(opts) {
86995
87052
  const key = agentKey3(opts.chatroomId, opts.role);
@@ -87051,14 +87108,10 @@ class AgentProcessManager {
87051
87108
  });
87052
87109
  }
87053
87110
  async preserveHarnessSessionOnExit(key, slot, ctx) {
87054
- const { harness, harnessSessionId, stopReason, recentLogLines } = ctx;
87111
+ const { harness, harnessSessionId, stopReason } = ctx;
87055
87112
  if (!harness || !harnessSessionId) {
87056
87113
  return;
87057
87114
  }
87058
- if (isCursorSdkRunErrorInLogs(recentLogLines ?? [])) {
87059
- this.clearLastHarnessSession(key);
87060
- return;
87061
- }
87062
87115
  const service3 = this.deps.agentServices.get(harness);
87063
87116
  if (!service3?.resumeFromDaemonMemory) {
87064
87117
  return;
@@ -87108,17 +87161,15 @@ class AgentProcessManager {
87108
87161
  }
87109
87162
  this.maybeRestartAgent(opts, ctx);
87110
87163
  }
87111
- clearHarnessSessionAfterRunError(key, recentLogLines) {
87164
+ hasCursorSdkRunErrorInContext(recentLogLines) {
87112
87165
  if (!isCursorSdkRunErrorInLogs(recentLogLines)) {
87113
87166
  return false;
87114
87167
  }
87115
- console.log(`[AgentProcessManager] cursor-sdk run-error — cold restarting ${key}: ${formatCursorSdkRunErrorMessage(recentLogLines)}`);
87116
- this.clearLastHarnessSession(key);
87168
+ console.log(`[AgentProcessManager] cursor-sdk run-error detected: ${formatCursorSdkRunErrorMessage(recentLogLines)}`);
87117
87169
  return true;
87118
87170
  }
87119
87171
  maybeRestartAgent(opts, ctx) {
87120
87172
  const { harness, model, workingDir, recentLogLines } = ctx;
87121
- const key = agentKey3(opts.chatroomId, opts.role);
87122
87173
  const logs = recentLogLines ?? [];
87123
87174
  if (!harness || !workingDir) {
87124
87175
  console.log(`[AgentProcessManager] ⚠️ Cannot restart — missing harness or workingDir ` + `(role: ${opts.role}, harness: ${harness ?? "none"}, workingDir: ${workingDir ?? "none"})`);
@@ -87128,9 +87179,9 @@ class AgentProcessManager {
87128
87179
  this.handlePermanentFailureForRestart(opts, recentLogLines, ctx.terminalProviderFailureHandled);
87129
87180
  return;
87130
87181
  }
87131
- const coldRestartAfterRunError = this.clearHarnessSessionAfterRunError(key, logs);
87182
+ const hadRunError = this.hasCursorSdkRunErrorInContext(logs);
87132
87183
  if (harness === "cursor-sdk") {
87133
- this.retryCursorSdkSessionReopen(opts, ctx, coldRestartAfterRunError);
87184
+ this.retryCursorSdkSessionReopen(opts, ctx, hadRunError);
87134
87185
  return;
87135
87186
  }
87136
87187
  this.ensureRunning({
@@ -87140,7 +87191,7 @@ class AgentProcessManager {
87140
87191
  model,
87141
87192
  workingDir,
87142
87193
  reason: "platform.crash_recovery",
87143
- wantResume: coldRestartAfterRunError ? false : ctx.wantResume ?? true
87194
+ wantResume: hadRunError ? false : ctx.wantResume ?? true
87144
87195
  }).then((result) => {
87145
87196
  if (!result.success) {
87146
87197
  console.log(`[AgentProcessManager] ⚠️ Agent restart did not complete for ${opts.role}: ${result.error ?? "unknown"}`);
@@ -87150,7 +87201,27 @@ class AgentProcessManager {
87150
87201
  this.emitStartFailedEvent(opts.role, opts.chatroomId, err.message);
87151
87202
  });
87152
87203
  }
87153
- async retryCursorSdkSessionReopen(opts, ctx, coldRestartAfterRunError) {
87204
+ clearHarnessSessionAfterResumePhaseFailure(key, opts) {
87205
+ const stored = this.lastHarnessSessions.get(key);
87206
+ this.clearLastHarnessSession(key);
87207
+ if (stored?.harnessSessionId) {
87208
+ notifyNativeSessionLost({
87209
+ chatroomId: opts.chatroomId,
87210
+ role: opts.role,
87211
+ harnessSessionId: stored.harnessSessionId
87212
+ });
87213
+ }
87214
+ }
87215
+ resolveCursorSdkReopenWantResume(hadRunError, attempt, ctx) {
87216
+ if (hadRunError && attempt <= CURSOR_SDK_SESSION_RESUME_FIRST_ATTEMPTS) {
87217
+ return true;
87218
+ }
87219
+ if (hadRunError) {
87220
+ return false;
87221
+ }
87222
+ return ctx.wantResume ?? true;
87223
+ }
87224
+ async retryCursorSdkSessionReopen(opts, ctx, hadRunError) {
87154
87225
  const key = agentKey3(opts.chatroomId, opts.role);
87155
87226
  if (this.sessionReopenRetryInFlight.has(key)) {
87156
87227
  return;
@@ -87159,11 +87230,14 @@ class AgentProcessManager {
87159
87230
  const harness = ctx.harness;
87160
87231
  const model = ctx.model;
87161
87232
  const workingDir = ctx.workingDir;
87162
- const wantResume = coldRestartAfterRunError ? false : ctx.wantResume ?? true;
87163
- const storedSessionId = this.lastHarnessSessions.get(key)?.harnessSessionId;
87164
87233
  let lastError = "unknown";
87165
87234
  try {
87166
87235
  for (let attempt = 1;attempt <= CURSOR_SDK_SESSION_REOPEN_MAX_ATTEMPTS; attempt++) {
87236
+ if (hadRunError && attempt === CURSOR_SDK_SESSION_RESUME_FIRST_ATTEMPTS + 1) {
87237
+ this.clearHarnessSessionAfterResumePhaseFailure(key, opts);
87238
+ }
87239
+ const wantResume = this.resolveCursorSdkReopenWantResume(hadRunError, attempt, ctx);
87240
+ const storedSessionId = this.lastHarnessSessions.get(key)?.harnessSessionId;
87167
87241
  await this.emitSessionReopenRetry(opts.chatroomId, opts.role, attempt, attempt > 1 ? lastError : undefined, storedSessionId);
87168
87242
  const result = await this.ensureRunning({
87169
87243
  chatroomId: opts.chatroomId,
@@ -87345,13 +87419,6 @@ class AgentProcessManager {
87345
87419
  try {
87346
87420
  await this.killExistingBeforeSpawn(opts.chatroomId, opts.role);
87347
87421
  const result = await this.doEnsureRunning(key, slot, opts);
87348
- if (!result.success && opts.reason === "platform.auto_restart_on_new_context") {
87349
- console.log(`[AgentProcessManager] Context auto-restart failed (${result.error ?? "unknown"}), ` + `attempting crash recovery (rate-limited)`);
87350
- return await this.doEnsureRunning(key, slot, {
87351
- ...opts,
87352
- reason: "platform.crash_recovery"
87353
- });
87354
- }
87355
87422
  return result;
87356
87423
  } finally {
87357
87424
  if (slot.pendingOperation) {
@@ -87744,9 +87811,25 @@ class AgentProcessManager {
87744
87811
  this.registerSpawnCallbacks(slot, opts, spawnResult, pid);
87745
87812
  await this.emitNativeWaiting(opts.chatroomId, opts.role, opts.agentHarness);
87746
87813
  }
87747
- async emitNativeWaiting(chatroomId, role, harness) {
87814
+ async emitNativeWaiting(chatroomId, role, harness, reason = "spawn") {
87748
87815
  if (!getHarnessCapabilities(harness).supportsNativeIntegration)
87749
- return;
87816
+ return false;
87817
+ if (reason === "turn-end") {
87818
+ try {
87819
+ const participant = await this.deps.backend.query(api.participants.getByRole, {
87820
+ sessionId: this.deps.sessionId,
87821
+ chatroomId,
87822
+ role
87823
+ });
87824
+ if (!shouldEmitNativeWaitingOnTurnEnd(participant?.lastStatus)) {
87825
+ console.log(`[AgentProcessManager] Skipping native:waiting for ${role} — active work (${participant?.lastStatus})`);
87826
+ return false;
87827
+ }
87828
+ } catch (err) {
87829
+ console.log(` ⚠️ Failed to check status before native:waiting for ${role}: ${err.message}`);
87830
+ return false;
87831
+ }
87832
+ }
87750
87833
  try {
87751
87834
  await this.deps.backend.mutation(api.participants.join, {
87752
87835
  sessionId: this.deps.sessionId,
@@ -87754,8 +87837,10 @@ class AgentProcessManager {
87754
87837
  role,
87755
87838
  action: NATIVE_WAITING_ACTION
87756
87839
  });
87840
+ return true;
87757
87841
  } catch (err) {
87758
87842
  console.log(` ⚠️ Failed to emit native:waiting for ${role}: ${err.message}`);
87843
+ return false;
87759
87844
  }
87760
87845
  }
87761
87846
  async doEnsureRunning(key, slot, opts) {
@@ -87909,11 +87994,13 @@ var init_agent_process_manager = __esm(() => {
87909
87994
  init_api3();
87910
87995
  init_orphan_tracker();
87911
87996
  init_native_harness_session_exit();
87997
+ init_native_task_delivery_coordinator();
87912
87998
  init_agent_lifecycle();
87913
87999
  init_abort_resume_storm();
87914
88000
  init_classify_resume_storm_reason();
87915
88001
  init_terminal_provider_error();
87916
88002
  init_handle_turn_completed();
88003
+ init_predicates();
87917
88004
  init_spawn_policy();
87918
88005
  init_agent_lifecycle_runtime();
87919
88006
  init_agent_lifecycle_types();
@@ -87927,7 +88014,7 @@ class SpawnRateLimiter {
87927
88014
  this.config = { ...DEFAULT_CONFIG2, ...config3 };
87928
88015
  }
87929
88016
  tryConsume(chatroomId, reason) {
87930
- if (reason.startsWith("user.") || reason === "platform.auto_restart_on_new_context" || reason === "platform.cursor_sdk_session_reopen") {
88017
+ if (reason.startsWith("user.") || reason === "platform.cursor_sdk_session_reopen") {
87931
88018
  return { allowed: true };
87932
88019
  }
87933
88020
  const bucket = this._getOrCreateBucket(chatroomId);
@@ -89278,15 +89365,15 @@ var init_assigned_task_signals = __esm(() => {
89278
89365
 
89279
89366
  // src/commands/machine/daemon-start/task-monitor.ts
89280
89367
  function resolveTaskWantResume(task) {
89281
- return compressContextToWantResume(parseCompressContext(task.taskContent ?? ""));
89368
+ return sessionAugmentationToWantResume(resolveSessionAugmentationForRole(task.taskContent ?? "", task.agentConfig.role));
89282
89369
  }
89283
89370
  function buildCliNudgeLogLine(task) {
89284
89371
  const { chatroomId, agentConfig } = task;
89285
89372
  const { role } = agentConfig;
89286
89373
  const lastSeenAction = task.participant?.lastSeenAction ?? "unknown";
89287
- const compressMode = parseCompressContext(task.taskContent ?? "");
89374
+ const augmentationMode = resolveSessionAugmentationForRole(task.taskContent ?? "", role);
89288
89375
  const wantResume = resolveTaskWantResume(task);
89289
- return `[TaskMonitor] nudging ${role}@${chatroomId} — pending task ${task.taskId}, lastSeenAction=${lastSeenAction}, compress_context=${compressMode}, wantResume=${wantResume}`;
89376
+ return `[TaskMonitor] nudging ${role}@${chatroomId} — pending task ${task.taskId}, lastSeenAction=${lastSeenAction}, session_augmentation=${augmentationMode}, wantResume=${wantResume}`;
89290
89377
  }
89291
89378
  function resolveTaskRunnerContextFromFull(task) {
89292
89379
  const { chatroomId, agentConfig } = task;
@@ -89302,11 +89389,12 @@ function resolveTaskRunnerContextFromFull(task) {
89302
89389
  wantResume: resolveTaskWantResume(task)
89303
89390
  };
89304
89391
  }
89305
- function executeCliNudge(task, runtime4, effectContext2, agentMgr) {
89392
+ function executeCliNudge(task, runtime4, effectContext2, agentMgr, sessionDeps, machineId) {
89306
89393
  const ctx = resolveTaskRunnerContextFromFull(task);
89307
89394
  if (!ctx)
89308
89395
  return;
89309
89396
  const { chatroomId, agentConfig, role, workingDir, wantResume } = ctx;
89397
+ const augmentationMode = resolveSessionAugmentationForRole(task.taskContent ?? "", role);
89310
89398
  exports_Runtime.runFork(runtime4)(exports_Effect.gen(function* () {
89311
89399
  yield* agentMgr.stop({ chatroomId, role, reason: "platform.task_monitor_nudge" });
89312
89400
  yield* agentMgr.ensureRunning({
@@ -89318,6 +89406,20 @@ function executeCliNudge(task, runtime4, effectContext2, agentMgr) {
89318
89406
  reason: "platform.task_monitor_nudge",
89319
89407
  wantResume
89320
89408
  });
89409
+ if (roleSupportsSessionAugmentation(role)) {
89410
+ yield* exports_Effect.tryPromise({
89411
+ try: () => sessionDeps.backend.mutation(api.machines.emitSessionAugmented, {
89412
+ sessionId: sessionDeps.sessionId,
89413
+ machineId,
89414
+ chatroomId,
89415
+ role,
89416
+ taskId: task.taskId,
89417
+ mode: augmentationMode,
89418
+ newSessionStarted: sessionAugmentationNewSessionStarted(augmentationMode)
89419
+ }),
89420
+ catch: (err) => err
89421
+ }).pipe(exports_Effect.catchAll(() => exports_Effect.void));
89422
+ }
89321
89423
  }).pipe(exports_Effect.provide(effectContext2), exports_Effect.catchAll((err) => exports_Effect.sync(() => console.warn(`[TaskMonitor] nudge failed for ${role}@${chatroomId}: ${getErrorMessage(err)}`)))));
89322
89424
  }
89323
89425
  function runNativeReviveEffect(task, runtime4, effectContext2, agentMgr) {
@@ -89347,16 +89449,16 @@ async function fetchTaskForAction(sessionDeps, machineId, snapshotRow) {
89347
89449
  });
89348
89450
  return result;
89349
89451
  }
89350
- function runCliNudgeEffect(task, runtime4, effectContext2, agentMgr) {
89452
+ function runCliNudgeEffect(task, runtime4, effectContext2, agentMgr, sessionDeps, machineId) {
89351
89453
  console.log(buildCliNudgeLogLine(task));
89352
- executeCliNudge(task, runtime4, effectContext2, agentMgr);
89454
+ executeCliNudge(task, runtime4, effectContext2, agentMgr, sessionDeps, machineId);
89353
89455
  }
89354
89456
  async function nudgeStuckTasks(tasks, now, cooldown, runtime4, effectContext2, agentMgr, sessionDeps, machineId) {
89355
89457
  for (const row of listTasksReadyForNudge(tasks, now, cooldown)) {
89356
89458
  const full = await fetchTaskForAction(sessionDeps, machineId, row);
89357
89459
  if (!full)
89358
89460
  continue;
89359
- runCliNudgeEffect(full, runtime4, effectContext2, agentMgr);
89461
+ runCliNudgeEffect(full, runtime4, effectContext2, agentMgr, sessionDeps, machineId);
89360
89462
  }
89361
89463
  }
89362
89464
  async function reviveNativeTasks(tasks, localHealth, now, cooldown, runtime4, effectContext2, agentMgr, sessionDeps, machineId) {
@@ -89460,7 +89562,8 @@ var startTaskMonitorEffect = (wsClient2) => exports_Effect.gen(function* () {
89460
89562
  };
89461
89563
  });
89462
89564
  var init_task_monitor = __esm(() => {
89463
- init_parse_compress_context();
89565
+ init_team_agent_settings();
89566
+ init_parse_session_augmentation();
89464
89567
  init_esm();
89465
89568
  init_daemon_services();
89466
89569
  init_native_task_delivery_coordinator();
@@ -90975,4 +91078,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
90975
91078
  });
90976
91079
  program2.parse();
90977
91080
 
90978
- //# debugId=00A3989CD8BAD93D64756E2164756E21
91081
+ //# debugId=D22ED479E2182D5A64756E2164756E21