fix(worker): surface the real reason a Claude run failed instead of a generic exit-code message
StreamAnalyzer now reads subtype/terminal_reason/errors from the CLI's result event, and TaskRunner builds a specific ErrorMarkdown from them: max_turns names the turn budget and points at set_task_config + requeue, api_error passes through the provider's own message (which carries the reset time), and any other terminal_reason is appended to the previous generic text instead of staying invisible. Falls through to the old "exited with code N and no result" text when there's no terminal_reason at all (a real crash).
This commit is contained in:
@@ -13,6 +13,9 @@ public sealed class StreamResult
|
||||
public int TokensOut { get; set; }
|
||||
public int ApiRetryCount { get; set; }
|
||||
public IReadOnlyList<string> Blocks { get; set; } = Array.Empty<string>();
|
||||
public string? ResultSubtype { get; set; }
|
||||
public string? TerminalReason { get; set; }
|
||||
public IReadOnlyList<string> Errors { get; set; } = Array.Empty<string>();
|
||||
}
|
||||
|
||||
public sealed class StreamAnalyzer
|
||||
@@ -25,6 +28,9 @@ public sealed class StreamAnalyzer
|
||||
private int _tokensOut;
|
||||
private int _apiRetryCount;
|
||||
private readonly List<string> _blocks = new();
|
||||
private string? _resultSubtype;
|
||||
private string? _terminalReason;
|
||||
private readonly List<string> _errors = new();
|
||||
private const string BlockedPrefix = "CLAUDEDO_BLOCKED:";
|
||||
|
||||
public void ProcessLine(string ndjsonLine)
|
||||
@@ -48,6 +54,17 @@ public sealed class StreamAnalyzer
|
||||
_structuredOutputJson = structuredProp.ToString();
|
||||
if (root.TryGetProperty("session_id", out var sessionProp))
|
||||
_sessionId = sessionProp.GetString();
|
||||
if (root.TryGetProperty("subtype", out var resultSubtypeProp))
|
||||
_resultSubtype = resultSubtypeProp.GetString();
|
||||
if (root.TryGetProperty("terminal_reason", out var terminalReasonProp))
|
||||
_terminalReason = terminalReasonProp.GetString();
|
||||
if (root.TryGetProperty("errors", out var errorsProp) && errorsProp.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
foreach (var errorItem in errorsProp.EnumerateArray())
|
||||
if (errorItem.ValueKind == JsonValueKind.String && errorItem.GetString() is { } errorText
|
||||
&& !string.IsNullOrEmpty(errorText))
|
||||
_errors.Add(errorText);
|
||||
}
|
||||
// Authoritative token totals live on the result event.
|
||||
if (root.TryGetProperty("usage", out var resultUsage))
|
||||
{
|
||||
@@ -87,6 +104,9 @@ public sealed class StreamAnalyzer
|
||||
TokensOut = _tokensOut,
|
||||
ApiRetryCount = _apiRetryCount,
|
||||
Blocks = _blocks.Distinct().ToList(),
|
||||
ResultSubtype = _resultSubtype,
|
||||
TerminalReason = _terminalReason,
|
||||
Errors = _errors,
|
||||
};
|
||||
|
||||
private string? FallbackResult()
|
||||
|
||||
Reference in New Issue
Block a user