@cydm/pie 1.0.14 → 1.0.16

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/cli.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  getSettingsPath,
15
15
  getThemesDir,
16
16
  migrateConfigFromAgentDir
17
- } from "./chunks/chunk-EFG2MQFD.js";
17
+ } from "./chunks/chunk-62XU6P2H.js";
18
18
  import {
19
19
  AGENTS_CONTEXT_FILE_NAME,
20
20
  AgentSessionController,
@@ -37,11 +37,14 @@ import {
37
37
  createSharedFileSystemTools,
38
38
  createSharedWebSearchTool,
39
39
  createTodoWidgetView,
40
+ estimateContextTokens,
41
+ estimateTokens,
40
42
  evaluateTodoClosureAfterAbort,
41
43
  evaluateTodoClosureAfterCompletedTurn,
42
44
  evaluateTodoClosureAfterFailedTurn,
43
45
  findFirstKeptEntryId,
44
46
  formatSkillSummariesForPrompt,
47
+ getAutoCompactTokenLimit,
45
48
  hasInteractionHandler,
46
49
  maybeAdvanceTodoExecutionState,
47
50
  modalityForReadFileUnderstandingKind,
@@ -52,7 +55,8 @@ import {
52
55
  selectToolsForRuntimePolicy,
53
56
  shouldPreserveExecutionStateForUserText,
54
57
  supersedeExecutionState
55
- } from "./chunks/chunk-LF5Q7BVU.js";
58
+ } from "./chunks/chunk-7GAYJ6AF.js";
59
+ import "./chunks/chunk-VE2HDCNB.js";
56
60
  import {
57
61
  Deref,
58
62
  Errors,
@@ -86,7 +90,7 @@ import {
86
90
  setLogger,
87
91
  sortToolModelCandidatesByCapability,
88
92
  type_exports
89
- } from "./chunks/chunk-D7NAXU7F.js";
93
+ } from "./chunks/chunk-5DA2D3K2.js";
90
94
  import {
91
95
  resolveCliProjectRoot
92
96
  } from "./chunks/chunk-NTYHFBUA.js";
@@ -61387,7 +61391,7 @@ function bindInteractiveRuntimeEvents(host) {
61387
61391
  lastStopReason: host.agent.state.messages.at(-1)?.role === "assistant" ? host.agent.state.messages.at(-1).stopReason : void 0
61388
61392
  });
61389
61393
  const lastMessage = host.agent.state.messages[host.agent.state.messages.length - 1];
61390
- if (lastMessage?.role === "assistant" && lastMessage?.stopReason === "error") {
61394
+ if (!hasControllerTurnAuthority(host) && lastMessage?.role === "assistant" && lastMessage?.stopReason === "error") {
61391
61395
  host.sessionTrace.abortTurn(String(lastMessage?.errorMessage || "agent_end"));
61392
61396
  }
61393
61397
  host.isProcessing = false;
@@ -61432,6 +61436,12 @@ function handleSemanticAgentEvent(host, event) {
61432
61436
  break;
61433
61437
  }
61434
61438
  case "turn_completed": {
61439
+ if (hasControllerTurnAuthority(host)) {
61440
+ host.logDebug("semantic:turn_completed_ignored_controller_authority", {
61441
+ turnIndex: host._semanticTurnIndex
61442
+ });
61443
+ break;
61444
+ }
61435
61445
  host.clearContinuationTimeout("turn_completed");
61436
61446
  host.emitExtensionEvent({
61437
61447
  type: "turn:completed",
@@ -61459,6 +61469,13 @@ function handleSemanticAgentEvent(host, event) {
61459
61469
  break;
61460
61470
  }
61461
61471
  case "turn_failed": {
61472
+ if (hasControllerTurnAuthority(host)) {
61473
+ host.logDebug("semantic:turn_failed_ignored_controller_authority", {
61474
+ turnIndex: host._semanticTurnIndex,
61475
+ recoveryState: host.agentSessionController?.turnRecoveryState
61476
+ });
61477
+ break;
61478
+ }
61462
61479
  host.clearContinuationTimeout("turn_failed");
61463
61480
  host.emitExtensionEvent({
61464
61481
  type: "turn:failed",
@@ -61487,6 +61504,9 @@ function handleSemanticAgentEvent(host, event) {
61487
61504
  }
61488
61505
  case "status_snapshot_changed": {
61489
61506
  const snapshot = event.snapshot;
61507
+ if (isControllerRecovering(host)) {
61508
+ break;
61509
+ }
61490
61510
  if (snapshot.phase === "idle" && !snapshot.hasPendingToolContinuation) {
61491
61511
  host.clearContinuationTimeout("status_idle");
61492
61512
  const outcome = host.executionState.markAwaitingContinuationStalled();
@@ -61508,6 +61528,13 @@ function handleSemanticAgentEvent(host, event) {
61508
61528
  }
61509
61529
  }
61510
61530
  }
61531
+ function hasControllerTurnAuthority(host) {
61532
+ return host.agentSessionController?.turnRecoveryState !== void 0;
61533
+ }
61534
+ function isControllerRecovering(host) {
61535
+ const state = host.agentSessionController?.turnRecoveryState;
61536
+ return state === "retry_pending" || state === "retrying" || state === "compacting";
61537
+ }
61511
61538
  function handleMessageStart(host, event) {
61512
61539
  if (event.message?.role === "assistant") {
61513
61540
  host.clearContinuationTimeout("assistant_message_start");
@@ -64043,84 +64070,183 @@ function buildCliSystemPrompt(options) {
64043
64070
  ].filter(Boolean).join("\n\n");
64044
64071
  }
64045
64072
 
64046
- // src/runtime/interactive-context-ui.ts
64047
- function calculateContextUsage(host) {
64048
- const messages = host.agent?.state.messages ?? [];
64049
- if (messages.length === 0) {
64050
- return { tokens: 0, input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 };
64073
+ // src/runtime/cli-auto-compaction.ts
64074
+ function calculateCliContextUsage(params) {
64075
+ const messages = stripStaleUsageBeforeCompaction(
64076
+ params.messages,
64077
+ params.latestCompactionTimestamp ?? null
64078
+ );
64079
+ const estimate = estimateContextTokens(messages);
64080
+ const usageMessage = estimate.lastUsageIndex !== null ? messages[estimate.lastUsageIndex] : void 0;
64081
+ const usage = usageMessage?.role === "assistant" ? usageMessage.usage : void 0;
64082
+ return {
64083
+ tokens: estimate.tokens,
64084
+ input: usage?.input ?? 0,
64085
+ output: usage?.output ?? 0,
64086
+ cacheRead: usage?.cacheRead ?? 0,
64087
+ cacheWrite: usage?.cacheWrite ?? 0,
64088
+ cost: usage?.cost.total ?? 0
64089
+ };
64090
+ }
64091
+ function createCliAutoCompactDecision(params) {
64092
+ const errorMessage3 = params.message?.role === "assistant" ? params.message.errorMessage : void 0;
64093
+ if (errorMessage3 && params.isContextOverflowError(errorMessage3)) {
64094
+ return { reason: "overflow", willRetry: true };
64051
64095
  }
64052
- let lastAssistantIndex = -1;
64053
- let lastUsage = null;
64054
- const latestCompactionTimestamp = host.sessionManager.getLatestCompactionTimestamp();
64055
- for (let i = messages.length - 1; i >= 0; i--) {
64056
- const msg = messages[i];
64057
- if (msg.role === "assistant") {
64058
- const assistantMsg = msg;
64059
- if (latestCompactionTimestamp !== null && assistantMsg.timestamp <= latestCompactionTimestamp) {
64060
- continue;
64061
- }
64062
- if (assistantMsg.usage && assistantMsg.stopReason !== "aborted" && assistantMsg.stopReason !== "error") {
64063
- lastAssistantIndex = i;
64064
- lastUsage = assistantMsg.usage;
64065
- break;
64066
- }
64067
- }
64096
+ if (!params.autoCompactEnabled || params.contextWindow <= 0) {
64097
+ return void 0;
64098
+ }
64099
+ const usage = calculateCliContextUsage({
64100
+ messages: params.messages,
64101
+ latestCompactionTimestamp: params.latestCompactionTimestamp
64102
+ });
64103
+ if (!usage.tokens) {
64104
+ return void 0;
64068
64105
  }
64069
- if (!lastUsage || lastAssistantIndex < 0) {
64070
- const estimated = messages.reduce((sum, msg) => sum + estimateMessageTokens(msg), 0);
64071
- return { tokens: estimated, input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 };
64106
+ const tokenLimit = getAutoCompactTokenLimit(params.contextWindow, params.reserveTokens);
64107
+ if (tokenLimit === void 0) {
64108
+ return void 0;
64072
64109
  }
64073
- const usageTokens = lastUsage.totalTokens || lastUsage.input + lastUsage.output + lastUsage.cacheRead + lastUsage.cacheWrite;
64074
- if (usageTokens <= 0) {
64075
- const estimated = messages.reduce((sum, msg) => sum + estimateMessageTokens(msg), 0);
64076
- return {
64077
- tokens: estimated,
64078
- input: lastUsage.input,
64079
- output: lastUsage.output,
64080
- cacheRead: lastUsage.cacheRead,
64081
- cacheWrite: lastUsage.cacheWrite,
64082
- cost: lastUsage.cost.total
64083
- };
64110
+ return usage.tokens > tokenLimit ? { reason: "threshold", willRetry: false } : void 0;
64111
+ }
64112
+ function shouldCliAutoCompactTokens(params) {
64113
+ if (!params.tokens || params.contextWindow <= 0) {
64114
+ return false;
64115
+ }
64116
+ const tokenLimit = getAutoCompactTokenLimit(params.contextWindow, params.reserveTokens);
64117
+ return tokenLimit !== void 0 && params.tokens > tokenLimit;
64118
+ }
64119
+ async function createCliAutoCompactionResult(params) {
64120
+ const activeEntryId = params.context.sessionManager.getActiveEntryId();
64121
+ if (!activeEntryId) {
64122
+ return { aborted: true };
64084
64123
  }
64085
- let trailingTokens = 0;
64086
- for (let i = lastAssistantIndex + 1; i < messages.length; i++) {
64087
- trailingTokens += estimateMessageTokens(messages[i]);
64124
+ const pathEntries = params.context.sessionManager.getPathToEntry(activeEntryId);
64125
+ const firstKeptEntryId = findFirstKeptEntryId(pathEntries);
64126
+ if (!firstKeptEntryId) {
64127
+ return { aborted: true };
64088
64128
  }
64129
+ const compactOptions = {
64130
+ model: params.model,
64131
+ apiKey: params.apiKey,
64132
+ systemPrompt: params.systemPrompt
64133
+ };
64134
+ const summary = await createCompactionSummary(params.context.messages, compactOptions);
64089
64135
  return {
64090
- tokens: usageTokens + trailingTokens,
64091
- input: lastUsage.input,
64092
- output: lastUsage.output,
64093
- cacheRead: lastUsage.cacheRead,
64094
- cacheWrite: lastUsage.cacheWrite,
64095
- cost: lastUsage.cost.total
64136
+ summary,
64137
+ firstKeptEntryId,
64138
+ tokensBefore: calculateTotalTokens(params.context.messages)
64096
64139
  };
64097
64140
  }
64098
- function estimateMessageTokens(msg) {
64099
- let chars = 0;
64100
- if (msg.role === "user") {
64101
- const content = msg.content;
64102
- if (typeof content === "string") {
64103
- chars = content.length;
64104
- } else if (Array.isArray(content)) {
64105
- for (const block of content) {
64106
- if (block.type === "text" && block.text) {
64107
- chars += block.text.length;
64108
- }
64109
- }
64141
+ function stripStaleUsageBeforeCompaction(messages, latestCompactionTimestamp) {
64142
+ if (latestCompactionTimestamp === null) {
64143
+ return messages;
64144
+ }
64145
+ return messages.map((message) => {
64146
+ if (message.role !== "assistant" || message.timestamp > latestCompactionTimestamp) {
64147
+ return message;
64110
64148
  }
64111
- } else if (msg.role === "assistant") {
64112
- const assistant = msg;
64113
- for (const block of assistant.content) {
64114
- if (block.type === "text") {
64115
- chars += block.text.length;
64116
- } else if (block.type === "thinking") {
64117
- chars += block.thinking.length;
64118
- } else if (block.type === "toolCall") {
64119
- chars += block.name.length + JSON.stringify(block.arguments).length;
64149
+ return {
64150
+ ...message,
64151
+ usage: {
64152
+ input: 0,
64153
+ output: 0,
64154
+ cacheRead: 0,
64155
+ cacheWrite: 0,
64156
+ totalTokens: 0,
64157
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
64120
64158
  }
64121
- }
64159
+ };
64160
+ });
64161
+ }
64162
+
64163
+ // src/runtime/retry-policy.ts
64164
+ var TRANSIENT_NETWORK_ERROR_PATTERN = /sse stream aborted|sse stream closed before end|sse stream ended before response completed|(?:read\s+)?ECONNRESET|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|ECONNREFUSED|socket hang up|request timeout|client network socket disconnected before secure TLS connection was established|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated/i;
64165
+ var PROVIDER_TRANSIENT_ERROR_PATTERN = /overloaded|rate.?limit|too many requests|\b429\b|\b500\b|\b502\b|\b503\b|\b504\b|service.?unavailable|server error|internal error|retry delay/i;
64166
+ var USER_ABORT_PATTERN = /request was aborted|local abort signal|user abort|user_interrupt|interrupted by user|esc pressed|ctrl\+c/i;
64167
+ var AUTH_CONFIG_PATTERN = /missing api key|invalid api key|api key.*invalid|unauthorized|\b401\b|\b403\b|forbidden|authentication failed|no configured model|no models? are configured/i;
64168
+ var INVALID_FILE_REFERENCE_PATTERN = /not the owner of this file|owner of this file|invalid_authentication_error/i;
64169
+ var INVALID_REQUEST_PATTERN = /bad request|\b400\b|invalid request|invalid schema|schema validation|invalid parameter|unsupported parameter|malformed/i;
64170
+ var CLI_RETRY_MAX_RETRIES = 3;
64171
+ var CLI_RETRY_BASE_DELAY_MS = 2e3;
64172
+ function isCliContextOverflowError(errorMessage3) {
64173
+ return /context length exceeded|context_length_exceeded|maximum context length|maximum context size|too many tokens|input.*too long|prompt.*too long|context window|token limit exceeded|exceeds.{0,20}context/i.test(
64174
+ errorMessage3
64175
+ );
64176
+ }
64177
+ function createClassification(kind, message, overrides) {
64178
+ return {
64179
+ kind,
64180
+ message,
64181
+ retryable: false,
64182
+ compactable: false,
64183
+ userAbort: false,
64184
+ terminal: true,
64185
+ ...overrides
64186
+ };
64187
+ }
64188
+ function classifyCliFailure(context) {
64189
+ const errorMessage3 = typeof context === "string" ? context : context.errorMessage;
64190
+ if (isCliContextOverflowError(errorMessage3)) {
64191
+ return createClassification("context_overflow", errorMessage3, {
64192
+ compactable: true,
64193
+ terminal: false
64194
+ });
64195
+ }
64196
+ if (USER_ABORT_PATTERN.test(errorMessage3)) {
64197
+ return createClassification("user_abort", errorMessage3, {
64198
+ userAbort: true,
64199
+ terminal: false
64200
+ });
64201
+ }
64202
+ if (INVALID_FILE_REFERENCE_PATTERN.test(errorMessage3)) {
64203
+ return createClassification("invalid_file_reference", errorMessage3);
64204
+ }
64205
+ if (AUTH_CONFIG_PATTERN.test(errorMessage3)) {
64206
+ return createClassification("auth_config", errorMessage3);
64207
+ }
64208
+ if (TRANSIENT_NETWORK_ERROR_PATTERN.test(errorMessage3)) {
64209
+ return createClassification("transient_network", errorMessage3, {
64210
+ retryable: true,
64211
+ terminal: false
64212
+ });
64213
+ }
64214
+ if (PROVIDER_TRANSIENT_ERROR_PATTERN.test(errorMessage3)) {
64215
+ return createClassification("provider_transient", errorMessage3, {
64216
+ retryable: true,
64217
+ terminal: false
64218
+ });
64219
+ }
64220
+ if (INVALID_REQUEST_PATTERN.test(errorMessage3)) {
64221
+ return createClassification("invalid_request", errorMessage3);
64222
+ }
64223
+ return createClassification("unknown", errorMessage3);
64224
+ }
64225
+ function isCliRetryableError(errorMessage3) {
64226
+ return classifyCliFailure(errorMessage3).retryable;
64227
+ }
64228
+ function getCliRetryBaseDelayMs() {
64229
+ const override = process.env.PIE_TEST_CLI_RETRY_BASE_DELAY_MS;
64230
+ if (!override) {
64231
+ return CLI_RETRY_BASE_DELAY_MS;
64232
+ }
64233
+ const parsed = Number(override);
64234
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : CLI_RETRY_BASE_DELAY_MS;
64235
+ }
64236
+
64237
+ // src/runtime/interactive-context-ui.ts
64238
+ function calculateContextUsage(host) {
64239
+ const messages = host.agent?.state.messages ?? [];
64240
+ if (messages.length === 0) {
64241
+ return { tokens: 0, input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0 };
64122
64242
  }
64123
- return Math.ceil(chars / 4);
64243
+ return calculateCliContextUsage({
64244
+ messages,
64245
+ latestCompactionTimestamp: host.sessionManager.getLatestCompactionTimestamp()
64246
+ });
64247
+ }
64248
+ function estimateMessageTokens(msg) {
64249
+ return estimateTokens(msg);
64124
64250
  }
64125
64251
  function buildSystemPrompt(host) {
64126
64252
  const tools = (host.agent?.state?.tools ?? host.options.tools ?? []).filter((tool) => typeof tool.name === "string").map((tool) => ({
@@ -64266,20 +64392,15 @@ function setupAutocomplete(host) {
64266
64392
  host.editor.setAutocompleteProvider(provider);
64267
64393
  }
64268
64394
  function isContextOverflowError(errorMessage3) {
64269
- return /context length exceeded|context_length_exceeded|maximum context length|maximum context size|too many tokens|input.*too long|prompt.*too long|context window|token limit exceeded|exceeds.{0,20}context/i.test(
64270
- errorMessage3
64271
- );
64395
+ return isCliContextOverflowError(errorMessage3);
64272
64396
  }
64273
64397
  function shouldAutoCompact(host, contextTokens, contextWindow) {
64274
64398
  if (!host.options.settingsManager.getAutoCompactEnabled()) return false;
64275
- if (!contextTokens || contextWindow <= 0) return false;
64276
64399
  const reserveTokens = host.options.settingsManager.getAutoCompactReserveTokens();
64277
- return contextTokens > contextWindow - reserveTokens;
64400
+ return shouldCliAutoCompactTokens({ tokens: contextTokens, contextWindow, reserveTokens });
64278
64401
  }
64279
64402
  function isRetryableError(errorMessage3) {
64280
- return /overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server error|internal error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated|retry delay/i.test(
64281
- errorMessage3
64282
- );
64403
+ return isCliRetryableError(errorMessage3);
64283
64404
  }
64284
64405
  function isInvalidFileReferenceError(errorMessage3) {
64285
64406
  return /not the owner of this file|owner of this file|invalid_authentication_error/i.test(
@@ -64721,28 +64842,6 @@ async function prepareAgentTurn(host, context) {
64721
64842
  messages: result.messages?.length ? [...context.messages, ...result.messages] : context.messages
64722
64843
  };
64723
64844
  }
64724
- async function createAutoCompactionResult(host, messages) {
64725
- const activeEntryId = host.sessionManager.getActiveEntryId();
64726
- if (!activeEntryId) {
64727
- return { aborted: true };
64728
- }
64729
- const pathEntries = host.sessionManager.getPathToEntry(activeEntryId);
64730
- const firstKeptEntryId = findFirstKeptEntryId(pathEntries);
64731
- if (!firstKeptEntryId) {
64732
- return { aborted: true };
64733
- }
64734
- const compactOptions = {
64735
- model: host.options.model,
64736
- apiKey: host.options.apiKey,
64737
- systemPrompt: host.agent.state.systemPrompt
64738
- };
64739
- const summary = await createCompactionSummary(messages, compactOptions);
64740
- return {
64741
- summary,
64742
- firstKeptEntryId,
64743
- tokensBefore: calculateTotalTokens(messages)
64744
- };
64745
- }
64746
64845
  function createInteractiveAgentSessionController(host) {
64747
64846
  return new AgentSessionController({
64748
64847
  agent: host.agent,
@@ -64762,14 +64861,16 @@ function createInteractiveAgentSessionController(host) {
64762
64861
  }
64763
64862
  return { allowed: true };
64764
64863
  },
64765
- getAutoCompactDecision: ({ message }) => {
64864
+ getAutoCompactDecision: ({ message, messages }) => {
64766
64865
  if (message?.role === "assistant" && message.stopReason === "error" && message.errorMessage) {
64767
64866
  if (host._isContextOverflowError(message.errorMessage)) {
64768
64867
  return { reason: "overflow", willRetry: true };
64769
64868
  }
64770
- return void 0;
64771
64869
  }
64772
- const contextUsage = host.calculateContextUsage();
64870
+ const contextUsage = calculateCliContextUsage({
64871
+ messages,
64872
+ latestCompactionTimestamp: host.sessionManager.getLatestCompactionTimestamp()
64873
+ });
64773
64874
  const contextWindow = host.options.model?.contextWindow ?? 0;
64774
64875
  if (host._shouldAutoCompact(contextUsage.tokens, contextWindow)) {
64775
64876
  return { reason: "threshold", willRetry: false };
@@ -64777,13 +64878,19 @@ function createInteractiveAgentSessionController(host) {
64777
64878
  return void 0;
64778
64879
  },
64779
64880
  getAutoContinueMessage: () => host.getTodoAutoContinueMessage(),
64881
+ classifyFailure: (context) => classifyCliFailure(context),
64780
64882
  retry: {
64781
- isRetryableError: (errorMessage3) => !host._isContextOverflowError(errorMessage3) && host._isRetryableError(errorMessage3),
64782
- maxRetries: 3,
64783
- baseDelayMs: 2e3
64883
+ isRetryableError: (errorMessage3) => !host._isContextOverflowError(errorMessage3) && isCliRetryableError(errorMessage3),
64884
+ maxRetries: CLI_RETRY_MAX_RETRIES,
64885
+ baseDelayMs: getCliRetryBaseDelayMs()
64784
64886
  },
64785
64887
  compaction: {
64786
- compact: async ({ messages }) => createAutoCompactionResult(host, messages)
64888
+ compact: async (context) => createCliAutoCompactionResult({
64889
+ context,
64890
+ model: host.options.model,
64891
+ apiKey: host.options.apiKey,
64892
+ systemPrompt: host.agent.state.systemPrompt
64893
+ })
64787
64894
  },
64788
64895
  onEvent: (event) => {
64789
64896
  host.sessionTrace.noteRuntimeEvent(event.type, event);
@@ -64806,11 +64913,15 @@ function createInteractiveAgentSessionController(host) {
64806
64913
  reason: event.reason,
64807
64914
  queueLength: host.agentSessionController?.pendingMessageCount ?? 0
64808
64915
  });
64809
- } else if (event.type === "retry_scheduled") {
64810
- host.showStatus(`Rate limited. Retrying in ${event.delayMs / 1e3}s... (attempt ${event.attempt}/${event.maxRetries})`);
64811
- } else if (event.type === "retry_start") {
64916
+ } else if (event.type === "turn_recovery_pending") {
64917
+ if (event.recovery === "retry") {
64918
+ host.showStatus(`Transient request error. Retrying in ${(event.delayMs ?? 0) / 1e3}s... (attempt ${event.attempt}/${event.maxRetries})`);
64919
+ } else {
64920
+ host.showStatus(event.failure.kind === "context_overflow" ? "Context overflow detected, compacting..." : "Auto-compacting context before retry...");
64921
+ }
64922
+ } else if (event.type === "turn_retry_started") {
64812
64923
  host.showStatus(`Retrying request (attempt ${event.attempt}/${event.maxRetries})...`);
64813
- } else if (event.type === "retry_succeeded") {
64924
+ } else if (event.type === "turn_retry_succeeded") {
64814
64925
  const outcome = host.executionState.resumePausedTodo();
64815
64926
  if (outcome.changed) {
64816
64927
  host.sessionTrace.noteRuntimeEvent("todo_resumed_after_retry", {
@@ -64821,12 +64932,80 @@ function createInteractiveAgentSessionController(host) {
64821
64932
  void host.refreshTodoWidget();
64822
64933
  }
64823
64934
  host.showStatus("Retry succeeded");
64824
- } else if (event.type === "retry_exhausted") {
64935
+ } else if (event.type === "turn_completed") {
64936
+ host.clearContinuationTimeout("turn_completed");
64937
+ host.emitExtensionEvent({
64938
+ type: "turn:completed",
64939
+ turnIndex: host._semanticTurnIndex,
64940
+ message: event.message,
64941
+ toolResults: event.toolResults
64942
+ });
64943
+ const outcome = host.executionState.advanceFromCompletedTurn(event.message, event.toolResults || []);
64944
+ host.logDebug("execution:turn_completed", {
64945
+ turnIndex: host._semanticTurnIndex,
64946
+ changed: outcome.changed,
64947
+ currentStepId: host.executionState.read().currentStepId,
64948
+ lifecycle: host.executionState.read().lifecycle,
64949
+ reason: outcome.cleared ? `cleared_${outcome.terminalStatus}` : outcome.changed ? "completed_turn" : "unchanged"
64950
+ });
64951
+ if (outcome.changed) {
64952
+ host.persistExecutionState();
64953
+ void host.refreshTodoWidget();
64954
+ }
64955
+ if (outcome.terminalSummary) {
64956
+ host.appendWarningSummary(outcome.terminalSummary);
64957
+ }
64958
+ host.sessionTrace.completeTurn(event.message, false);
64959
+ host._semanticTurnIndex++;
64960
+ } else if (event.type === "turn_failed_terminal") {
64961
+ host.clearContinuationTimeout("turn_failed_terminal");
64962
+ if (event.message) {
64963
+ host.emitExtensionEvent({
64964
+ type: "turn:failed",
64965
+ turnIndex: host._semanticTurnIndex,
64966
+ message: event.message,
64967
+ toolResults: []
64968
+ });
64969
+ }
64970
+ const outcome = host.executionState.handleTurnFailed();
64971
+ host.logDebug("execution:turn_failed_terminal", {
64972
+ turnIndex: host._semanticTurnIndex,
64973
+ changed: outcome.changed,
64974
+ currentStepId: host.executionState.read().currentStepId,
64975
+ lifecycle: host.executionState.read().lifecycle,
64976
+ kind: event.failure.kind
64977
+ });
64978
+ if (outcome.changed) {
64979
+ host.persistExecutionState();
64980
+ void host.refreshTodoWidget();
64981
+ }
64982
+ if (outcome.terminalSummary) {
64983
+ host.appendWarningSummary(outcome.terminalSummary);
64984
+ }
64985
+ if (event.message) {
64986
+ host.sessionTrace.completeTurn(event.message, true);
64987
+ }
64988
+ host._semanticTurnIndex++;
64825
64989
  const state = host.executionState.read();
64826
64990
  if (state.mode === "todo" && state.lifecycle === "paused" && state.steps.length > 0) {
64827
64991
  host.showStatus("Todo list preserved. Send 'continue' when you want to resume it.");
64828
64992
  }
64829
- host.showError(`Request failed after ${event.maxRetries} retries: ${event.errorMessage}`);
64993
+ host.showError(event.failure.message);
64994
+ } else if (event.type === "turn_cancelled") {
64995
+ const outcome = host.executionState.abort();
64996
+ host.logDebug("execution:turn_cancelled", {
64997
+ turnIndex: host._semanticTurnIndex,
64998
+ cleared: outcome.cleared,
64999
+ lifecycle: host.executionState.read().lifecycle,
65000
+ reason: event.reason
65001
+ });
65002
+ if (outcome.cleared || outcome.terminalSummary) {
65003
+ host.persistExecutionState();
65004
+ void host.refreshTodoWidget();
65005
+ }
65006
+ if (outcome.terminalSummary) {
65007
+ host.appendWarningSummary(outcome.terminalSummary);
65008
+ }
64830
65009
  } else if (event.type === "runtime_guard_triggered") {
64831
65010
  host.sessionTrace.noteStalled("runtime_guard_triggered", {
64832
65011
  toolName: event.toolName,
@@ -66739,7 +66918,7 @@ var InteractiveMode = class {
66739
66918
  if (savedLevel) {
66740
66919
  this.thinkingLevel = savedLevel;
66741
66920
  }
66742
- const { Agent } = await import("./chunks/src-LZC56DRG.js");
66921
+ const { Agent } = await import("./chunks/src-6WPNVGT2.js");
66743
66922
  const activeSession = this.sessionManager.getActiveSession();
66744
66923
  this.agent = new Agent({
66745
66924
  initialState: {
@@ -67303,6 +67482,12 @@ function createNoOpExtensionUIContext() {
67303
67482
  custom: async () => void 0
67304
67483
  };
67305
67484
  }
67485
+ function readAssistantError(message) {
67486
+ if (message.role !== "assistant") {
67487
+ return "";
67488
+ }
67489
+ return message.errorMessage || "assistant response failed";
67490
+ }
67306
67491
  async function loadPrintModeExtensions(params) {
67307
67492
  const uiContext = createNoOpExtensionUIContext();
67308
67493
  const executionState = new ExecutionStateManager();
@@ -67400,7 +67585,7 @@ async function runPrintMode(params) {
67400
67585
  `);
67401
67586
  console.log("Assistant: ");
67402
67587
  }
67403
- const { Agent: AgentClass } = await import("./chunks/src-LZC56DRG.js");
67588
+ const { Agent: AgentClass } = await import("./chunks/src-6WPNVGT2.js");
67404
67589
  let agent;
67405
67590
  const printModeExtensions = await loadPrintModeExtensions({
67406
67591
  cwd: runtime.cwd,
@@ -67437,8 +67622,10 @@ async function runPrintMode(params) {
67437
67622
  tools: printModeTools,
67438
67623
  thinkingLevel: "off"
67439
67624
  },
67440
- apiKey: runtime.apiKey
67625
+ apiKey: runtime.apiKey,
67626
+ streamFn: params.streamFn
67441
67627
  });
67628
+ const sessionTrace = new SessionTraceWriter(runtime.paths.sessionsDir, runtime.sessionManager);
67442
67629
  const agentSessionController = new AgentSessionController({
67443
67630
  agent,
67444
67631
  sessionManager: runtime.sessionManager,
@@ -67458,9 +67645,47 @@ async function runPrintMode(params) {
67458
67645
  systemPrompt: result.systemPrompt ?? context.baseSystemPrompt ?? baseSystemPrompt,
67459
67646
  messages: result.messages?.length ? [...context.messages, ...result.messages] : context.messages
67460
67647
  };
67648
+ },
67649
+ retry: {
67650
+ isRetryableError: isCliRetryableError,
67651
+ maxRetries: CLI_RETRY_MAX_RETRIES,
67652
+ baseDelayMs: getCliRetryBaseDelayMs()
67653
+ },
67654
+ getAutoCompactDecision: ({ message, messages }) => createCliAutoCompactDecision({
67655
+ message,
67656
+ messages,
67657
+ contextWindow: runtime.model.contextWindow ?? 0,
67658
+ autoCompactEnabled: runtime.settingsManager.getAutoCompactEnabled(),
67659
+ reserveTokens: runtime.settingsManager.getAutoCompactReserveTokens(),
67660
+ latestCompactionTimestamp: runtime.sessionManager.getLatestCompactionTimestamp(),
67661
+ isContextOverflowError: isCliContextOverflowError
67662
+ }),
67663
+ compaction: {
67664
+ compact: async (context) => createCliAutoCompactionResult({
67665
+ context,
67666
+ model: runtime.model,
67667
+ apiKey: runtime.apiKey,
67668
+ systemPrompt: agent?.state.systemPrompt ?? baseSystemPrompt
67669
+ })
67670
+ },
67671
+ classifyFailure: (context) => classifyCliFailure(context),
67672
+ onEvent: (event) => {
67673
+ sessionTrace.noteRuntimeEvent(event.type, event);
67674
+ if (event.type === "turn_recovery_pending" && event.recovery === "retry") {
67675
+ console.error(`Transient request error: ${event.failure.message}. Retrying in ${(event.delayMs ?? 0) / 1e3}s (${event.attempt}/${event.maxRetries}).`);
67676
+ } else if (event.type === "turn_recovery_pending" && event.recovery === "compaction") {
67677
+ console.error(event.failure.kind === "context_overflow" ? "Context overflow detected, compacting..." : "Auto-compacting context before retry...");
67678
+ } else if (event.type === "auto_compaction_start") {
67679
+ console.error(event.reason === "overflow" ? "Context overflow detected, compacting..." : "Auto-compacting context...");
67680
+ } else if (event.type === "turn_retry_started") {
67681
+ console.error(`Retrying request (${event.attempt}/${event.maxRetries})...`);
67682
+ } else if (event.type === "turn_retry_succeeded") {
67683
+ console.error(`Retry succeeded after ${event.attempts} attempt${event.attempts === 1 ? "" : "s"}.`);
67684
+ } else if (event.type === "turn_failed_terminal" && (event.failure.kind === "transient_network" || event.failure.kind === "provider_transient")) {
67685
+ console.error(`Request failed after ${CLI_RETRY_MAX_RETRIES} retries: ${event.failure.message}`);
67686
+ }
67461
67687
  }
67462
67688
  });
67463
- const sessionTrace = new SessionTraceWriter(runtime.paths.sessionsDir, runtime.sessionManager);
67464
67689
  sessionTrace.notePendingUserText(params.initialPrompt);
67465
67690
  attachAgentEventsToSessionTrace({ agent, trace: sessionTrace });
67466
67691
  agent.setTools(wrapToolsWithExtensions(agent.state.tools, printModeExtensions.runner));
@@ -67470,19 +67695,37 @@ async function runPrintMode(params) {
67470
67695
  await agentSessionController.prompt(params.initialPrompt, { source: "print" });
67471
67696
  sessionTrace.noteDispatchSettled({ mode: "print" });
67472
67697
  sessionTrace.noteWaitForIdleStart({ mode: "print" });
67473
- await agentSessionController.waitForIdle();
67698
+ await agentSessionController.waitForSettled();
67474
67699
  sessionTrace.noteWaitForIdleSettled({ mode: "print" });
67475
67700
  const messages = agent.state.messages;
67476
67701
  const lastMessage = messages[messages.length - 1];
67477
67702
  let assistantText = "";
67703
+ let assistantError = "";
67478
67704
  if (lastMessage?.role === "assistant") {
67479
67705
  for (const content of lastMessage.content) {
67480
67706
  if (typeof content === "object" && "type" in content && content.type === "text" && "text" in content) {
67481
67707
  assistantText += content.text;
67482
67708
  }
67483
67709
  }
67710
+ if (lastMessage.stopReason === "error" || lastMessage.stopReason === "aborted") {
67711
+ assistantError = readAssistantError(lastMessage);
67712
+ }
67484
67713
  }
67485
- if (params.jsonOutput) {
67714
+ if (assistantError) {
67715
+ process.exitCode = 1;
67716
+ if (params.jsonOutput) {
67717
+ console.log(
67718
+ JSON.stringify({
67719
+ ok: false,
67720
+ error: assistantError,
67721
+ sessionId: runtime.sessionManager.getActiveSession()?.id,
67722
+ provider: runtime.provider,
67723
+ modelId: runtime.modelId
67724
+ })
67725
+ );
67726
+ }
67727
+ console.error("Error:", assistantError);
67728
+ } else if (params.jsonOutput) {
67486
67729
  console.log(
67487
67730
  JSON.stringify({
67488
67731
  ok: true,
@@ -67598,14 +67841,25 @@ function assistantTextFromAgent(agent) {
67598
67841
  const messages = agent?.state.messages ?? [];
67599
67842
  const lastMessage = messages[messages.length - 1];
67600
67843
  if (lastMessage?.role !== "assistant") return "";
67844
+ return assistantTextFromMessage(lastMessage);
67845
+ }
67846
+ function assistantTextFromMessage(message) {
67847
+ if (message.role !== "assistant") return "";
67601
67848
  let text = "";
67602
- for (const content of lastMessage.content) {
67849
+ for (const content of message.content) {
67603
67850
  if (content.type === "text") {
67604
67851
  text += content.text;
67605
67852
  }
67606
67853
  }
67607
67854
  return text;
67608
67855
  }
67856
+ function assistantErrorFromAgent(agent) {
67857
+ const messages = agent?.state.messages ?? [];
67858
+ const lastMessage = messages[messages.length - 1];
67859
+ if (lastMessage?.role !== "assistant") return "";
67860
+ if (lastMessage.stopReason !== "error" && lastMessage.stopReason !== "aborted") return "";
67861
+ return lastMessage.errorMessage || "assistant response failed";
67862
+ }
67609
67863
  function readProgressText(value) {
67610
67864
  return typeof value === "string" ? value : "";
67611
67865
  }
@@ -67712,6 +67966,7 @@ async function runJsonEventsMode(params) {
67712
67966
  let disposeAgentSubscription;
67713
67967
  let disposeSemanticSubscription;
67714
67968
  let trace;
67969
+ let lastRetryEvent;
67715
67970
  const noProgressTimeoutMs = Number(process.env.PIE_JSON_EVENTS_NO_PROGRESS_MS || 6e5);
67716
67971
  const mockResponseDelayMs = Number(process.env.PIE_TEST_MOCK_RESPONSE_DELAY_MS || 0);
67717
67972
  writeEvent({ type: "agent.ready", sessionId });
@@ -67729,9 +67984,11 @@ async function runJsonEventsMode(params) {
67729
67984
  activeTurn.lastActivityAt = Date.now();
67730
67985
  }
67731
67986
  }
67732
- function display(chunk) {
67987
+ function display(chunk, options) {
67733
67988
  if (!activeTurn || !chunk) return;
67734
- activeTurn.summary += chunk;
67989
+ if (options?.appendToSummary !== false) {
67990
+ activeTurn.summary += chunk;
67991
+ }
67735
67992
  touch();
67736
67993
  writeEvent({
67737
67994
  type: "display.output",
@@ -67741,13 +67998,31 @@ async function runJsonEventsMode(params) {
67741
67998
  chunk
67742
67999
  });
67743
68000
  }
68001
+ function bufferAssistantOutput(chunk) {
68002
+ if (!activeTurn || !chunk) return;
68003
+ activeTurn.pendingAssistantOutput += chunk;
68004
+ touch();
68005
+ }
68006
+ function clearPendingAssistantOutput() {
68007
+ if (activeTurn) {
68008
+ activeTurn.pendingAssistantOutput = "";
68009
+ }
68010
+ }
68011
+ function flushAssistantOutput(fallbackText = "") {
68012
+ if (!activeTurn) return;
68013
+ const chunk = activeTurn.pendingAssistantOutput || fallbackText;
68014
+ activeTurn.pendingAssistantOutput = "";
68015
+ if (chunk) {
68016
+ display(chunk);
68017
+ }
68018
+ }
67744
68019
  function finalize(kind, detail) {
67745
68020
  const turn = activeTurn;
67746
68021
  if (!turn || turn.finalized) return;
67747
68022
  turn.finalized = true;
67748
68023
  switch (kind) {
67749
68024
  case "completed":
67750
- writeEvent({ type: "turn.completed", sessionId: turn.sessionId, turnId: turn.turnId, summary: turn.summary.trim() });
68025
+ writeEvent({ type: "turn.completed", sessionId: turn.sessionId, turnId: turn.turnId, summary: (detail ?? turn.summary).trim() });
67751
68026
  break;
67752
68027
  case "failed":
67753
68028
  writeEvent({ type: "turn.failed", sessionId: turn.sessionId, turnId: turn.turnId, error: detail || "turn failed" });
@@ -67764,7 +68039,7 @@ async function runJsonEventsMode(params) {
67764
68039
  if (!activeTurn || activeTurn.finalized) return;
67765
68040
  switch (event.type) {
67766
68041
  case "assistant_response_delta":
67767
- display(event.delta);
68042
+ bufferAssistantOutput(event.delta);
67768
68043
  break;
67769
68044
  case "tool_started":
67770
68045
  touch();
@@ -67783,7 +68058,7 @@ async function runJsonEventsMode(params) {
67783
68058
  const progressText = extractJsonEventsToolProgressText(event.partialResult);
67784
68059
  if (progressText) {
67785
68060
  display(progressText.endsWith("\n") ? progressText : `${progressText}
67786
- `);
68061
+ `, { appendToSummary: false });
67787
68062
  }
67788
68063
  }
67789
68064
  break;
@@ -67804,6 +68079,113 @@ async function runJsonEventsMode(params) {
67804
68079
  break;
67805
68080
  }
67806
68081
  }
68082
+ function handleControllerEvent(event) {
68083
+ trace?.noteRuntimeEvent(event.type, event);
68084
+ if (event.type === "turn_settled" && activeTurn) {
68085
+ writeEvent({
68086
+ type: "turn.settled",
68087
+ sessionId: activeTurn.sessionId,
68088
+ turnId: activeTurn.turnId
68089
+ });
68090
+ return;
68091
+ }
68092
+ if (!activeTurn || activeTurn.finalized) return;
68093
+ if (event.type === "turn_recovery_pending" && event.recovery === "retry") {
68094
+ lastRetryEvent = {
68095
+ attempt: event.attempt ?? 0,
68096
+ maxRetries: event.maxRetries ?? CLI_RETRY_MAX_RETRIES,
68097
+ delayMs: event.delayMs,
68098
+ error: event.failure.message
68099
+ };
68100
+ touch();
68101
+ writeEvent({
68102
+ type: "turn.recovery.pending",
68103
+ sessionId: activeTurn.sessionId,
68104
+ turnId: activeTurn.turnId,
68105
+ recovery: event.recovery,
68106
+ attempt: event.attempt,
68107
+ maxRetries: event.maxRetries,
68108
+ delayMs: event.delayMs,
68109
+ error: event.failure.message
68110
+ });
68111
+ } else if (event.type === "turn_recovery_pending" && event.recovery === "compaction") {
68112
+ activeTurn.summary = "";
68113
+ clearPendingAssistantOutput();
68114
+ touch();
68115
+ writeEvent({
68116
+ type: "turn.recovery.pending",
68117
+ sessionId: activeTurn.sessionId,
68118
+ turnId: activeTurn.turnId,
68119
+ recovery: event.recovery,
68120
+ error: event.failure.message
68121
+ });
68122
+ } else if (event.type === "turn_retry_started") {
68123
+ activeTurn.summary = "";
68124
+ clearPendingAssistantOutput();
68125
+ lastRetryEvent = {
68126
+ attempt: event.attempt,
68127
+ maxRetries: event.maxRetries,
68128
+ delayMs: lastRetryEvent?.delayMs,
68129
+ error: lastRetryEvent?.error
68130
+ };
68131
+ touch();
68132
+ writeEvent({
68133
+ type: "turn.retry.started",
68134
+ sessionId: activeTurn.sessionId,
68135
+ turnId: activeTurn.turnId,
68136
+ attempt: event.attempt,
68137
+ maxRetries: event.maxRetries,
68138
+ delayMs: lastRetryEvent.delayMs,
68139
+ error: lastRetryEvent.error
68140
+ });
68141
+ } else if (event.type === "turn_retry_succeeded") {
68142
+ touch();
68143
+ writeEvent({
68144
+ type: "turn.retry.succeeded",
68145
+ sessionId: activeTurn.sessionId,
68146
+ turnId: activeTurn.turnId,
68147
+ attempt: event.attempts,
68148
+ maxRetries: lastRetryEvent?.maxRetries ?? CLI_RETRY_MAX_RETRIES,
68149
+ delayMs: lastRetryEvent?.delayMs,
68150
+ error: lastRetryEvent?.error
68151
+ });
68152
+ lastRetryEvent = void 0;
68153
+ } else if (event.type === "turn_compaction_started") {
68154
+ if (event.willRetry) {
68155
+ activeTurn.summary = "";
68156
+ clearPendingAssistantOutput();
68157
+ }
68158
+ touch();
68159
+ writeEvent({
68160
+ type: "turn.compaction.started",
68161
+ sessionId: activeTurn.sessionId,
68162
+ turnId: activeTurn.turnId,
68163
+ reason: event.reason,
68164
+ willRetry: event.willRetry
68165
+ });
68166
+ } else if (event.type === "turn_completed") {
68167
+ const text = assistantTextFromMessage(event.message);
68168
+ flushAssistantOutput(text);
68169
+ finalize("completed", text || activeTurn.summary.trim());
68170
+ } else if (event.type === "turn_failed_terminal") {
68171
+ touch();
68172
+ if (lastRetryEvent) {
68173
+ writeEvent({
68174
+ type: "turn.retry.exhausted",
68175
+ sessionId: activeTurn.sessionId,
68176
+ turnId: activeTurn.turnId,
68177
+ attempt: lastRetryEvent.attempt,
68178
+ maxRetries: lastRetryEvent.maxRetries,
68179
+ delayMs: lastRetryEvent.delayMs,
68180
+ error: event.failure.message
68181
+ });
68182
+ lastRetryEvent = void 0;
68183
+ }
68184
+ finalize("failed", event.failure.message);
68185
+ } else if (event.type === "turn_cancelled") {
68186
+ finalize("cancelled", event.reason);
68187
+ }
68188
+ }
67807
68189
  async function ensureRuntime() {
67808
68190
  if (params.mockResponse !== void 0 || controller) return;
67809
68191
  const runtime = params.runtime;
@@ -67813,7 +68195,7 @@ async function runJsonEventsMode(params) {
67813
68195
  if (runtime.initialModel.unconfigured) {
67814
68196
  return;
67815
68197
  }
67816
- const { Agent: AgentClass } = await import("./chunks/src-LZC56DRG.js");
68198
+ const { Agent: AgentClass } = await import("./chunks/src-6WPNVGT2.js");
67817
68199
  const jsonModeExtensions = await loadJsonModeExtensions({ runtime, getAgent: () => agent });
67818
68200
  const tools = [...runtime.tools, ...jsonModeExtensions.extensionTools];
67819
68201
  recordCliCompositionStep(runtime.compositionTrace, {
@@ -67840,7 +68222,8 @@ async function runJsonEventsMode(params) {
67840
68222
  tools,
67841
68223
  thinkingLevel: "off"
67842
68224
  },
67843
- apiKey: runtime.apiKey
68225
+ apiKey: runtime.apiKey,
68226
+ streamFn: params.streamFn
67844
68227
  });
67845
68228
  controller = new AgentSessionController({
67846
68229
  agent,
@@ -67858,7 +68241,31 @@ async function runJsonEventsMode(params) {
67858
68241
  systemPrompt: result?.systemPrompt ?? context.baseSystemPrompt ?? baseSystemPrompt,
67859
68242
  messages: result?.messages?.length ? [...context.messages, ...result.messages] : context.messages
67860
68243
  };
67861
- }
68244
+ },
68245
+ retry: {
68246
+ isRetryableError: isCliRetryableError,
68247
+ maxRetries: CLI_RETRY_MAX_RETRIES,
68248
+ baseDelayMs: getCliRetryBaseDelayMs()
68249
+ },
68250
+ getAutoCompactDecision: ({ message, messages }) => createCliAutoCompactDecision({
68251
+ message,
68252
+ messages,
68253
+ contextWindow: runtime.model.contextWindow ?? 0,
68254
+ autoCompactEnabled: runtime.settingsManager.getAutoCompactEnabled(),
68255
+ reserveTokens: runtime.settingsManager.getAutoCompactReserveTokens(),
68256
+ latestCompactionTimestamp: runtime.sessionManager.getLatestCompactionTimestamp(),
68257
+ isContextOverflowError: isCliContextOverflowError
68258
+ }),
68259
+ compaction: {
68260
+ compact: async (context) => createCliAutoCompactionResult({
68261
+ context,
68262
+ model: runtime.model,
68263
+ apiKey: runtime.apiKey,
68264
+ systemPrompt: agent?.state.systemPrompt ?? baseSystemPrompt
68265
+ })
68266
+ },
68267
+ classifyFailure: (context) => classifyCliFailure(context),
68268
+ onEvent: handleControllerEvent
67862
68269
  });
67863
68270
  trace = new SessionTraceWriter(runtime.paths.sessionsDir, runtime.sessionManager);
67864
68271
  attachAgentEventsToSessionTrace({ agent, trace });
@@ -67894,7 +68301,8 @@ async function runJsonEventsMode(params) {
67894
68301
  interrupted: false,
67895
68302
  stalled: false,
67896
68303
  finalized: false,
67897
- summary: ""
68304
+ summary: "",
68305
+ pendingAssistantOutput: ""
67898
68306
  };
67899
68307
  const turn = activeTurn;
67900
68308
  writeEvent({ type: "turn.started", sessionId: activeTurn.sessionId, turnId: activeTurn.turnId });
@@ -67938,7 +68346,7 @@ async function runJsonEventsMode(params) {
67938
68346
  if (!turn2 || turn2.finalized) return;
67939
68347
  if (Date.now() - turn2.lastActivityAt >= noProgressTimeoutMs) {
67940
68348
  turn2.stalled = true;
67941
- agent?.abort();
68349
+ controller?.abort();
67942
68350
  finalize("stalled", "no_progress_timeout");
67943
68351
  }
67944
68352
  }, Math.max(1e3, Math.min(noProgressTimeoutMs, 1e4)));
@@ -67949,14 +68357,21 @@ async function runJsonEventsMode(params) {
67949
68357
  await controller.prompt(message.prompt, { source: "json-events" });
67950
68358
  trace?.noteDispatchSettled({ mode: "json-events" });
67951
68359
  trace?.noteWaitForIdleStart({ mode: "json-events" });
67952
- await controller.waitForIdle();
68360
+ await controller.waitForSettled();
67953
68361
  trace?.noteWaitForIdleSettled({ mode: "json-events" });
67954
68362
  if (!activeTurn?.finalized) {
67955
- const text = activeTurn?.summary.trim() || assistantTextFromAgent(agent);
67956
- if (!activeTurn?.summary && text) {
67957
- display(text);
68363
+ const finalError = assistantErrorFromAgent(agent);
68364
+ if (activeTurn?.interrupted) {
68365
+ finalize("cancelled", "user_interrupt");
68366
+ return;
67958
68367
  }
67959
- finalize(activeTurn?.interrupted ? "cancelled" : "completed", activeTurn?.interrupted ? "user_interrupt" : void 0);
68368
+ if (finalError) {
68369
+ finalize("failed", finalError);
68370
+ return;
68371
+ }
68372
+ const text = assistantTextFromAgent(agent);
68373
+ flushAssistantOutput(text);
68374
+ finalize("completed", text || activeTurn?.summary.trim());
67960
68375
  }
67961
68376
  } catch (error) {
67962
68377
  const messageText = error instanceof Error ? error.message : String(error);
@@ -68000,7 +68415,7 @@ async function runJsonEventsMode(params) {
68000
68415
  return;
68001
68416
  }
68002
68417
  activeTurn.interrupted = true;
68003
- agent?.abort();
68418
+ controller?.abort();
68004
68419
  if (params.mockResponse !== void 0) {
68005
68420
  finalize("cancelled", message.reason || "user_interrupt");
68006
68421
  activeTurn = null;
@@ -68018,7 +68433,7 @@ async function runJsonEventsMode(params) {
68018
68433
  if (message.type === "shutdown") {
68019
68434
  if (activeTurn && !activeTurn.finalized) {
68020
68435
  activeTurn.interrupted = true;
68021
- agent?.abort();
68436
+ controller?.abort();
68022
68437
  finalize("cancelled", message.reason || "shutdown");
68023
68438
  }
68024
68439
  break;
@@ -68198,6 +68613,13 @@ async function runWithJsonEventsConsoleIsolation(fn) {
68198
68613
  console.debug = originalDebug;
68199
68614
  }
68200
68615
  }
68616
+ async function createCliTestStreamFnFromEnv() {
68617
+ if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) {
68618
+ return void 0;
68619
+ }
68620
+ const { createTestStreamFnFromSequenceEnv } = await import("./chunks/test-stream-ZSKNLUEJ.js");
68621
+ return createTestStreamFnFromSequenceEnv();
68622
+ }
68201
68623
  async function startChat(initialPrompt, testCommand) {
68202
68624
  const rawOutput = process.argv.includes("--raw-output");
68203
68625
  const jsonOutput = process.argv.includes("--json-output");
@@ -68227,7 +68649,11 @@ async function startChat(initialPrompt, testCommand) {
68227
68649
  }
68228
68650
  throw error;
68229
68651
  }
68230
- await runJsonEventsMode({ runtime: runtime2, explicitSessionId });
68652
+ await runJsonEventsMode({
68653
+ runtime: runtime2,
68654
+ explicitSessionId,
68655
+ streamFn: await createCliTestStreamFnFromEnv()
68656
+ });
68231
68657
  });
68232
68658
  return;
68233
68659
  }
@@ -68256,7 +68682,13 @@ async function startChat(initialPrompt, testCommand) {
68256
68682
  throw error;
68257
68683
  }
68258
68684
  if (initialPrompt) {
68259
- await runPrintMode({ initialPrompt, rawOutput, jsonOutput, runtime });
68685
+ await runPrintMode({
68686
+ initialPrompt,
68687
+ rawOutput,
68688
+ jsonOutput,
68689
+ runtime,
68690
+ streamFn: await createCliTestStreamFnFromEnv()
68691
+ });
68260
68692
  process.exit(process.exitCode ?? 0);
68261
68693
  return;
68262
68694
  }