larkin 0.5.11 → 0.5.12

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.
@@ -1484,7 +1484,11 @@ function createHostShell({ env = process.env, runtimeHost, channelPackage, event
1484
1484
  }
1485
1485
  else {
1486
1486
  const category = message.event.errorCategory || "provider";
1487
- hostState.recordStatusError(agent, `${category}: Runtime input failed ${message.event.retryable ? "retryably" : "non-retryably"}; inspect delivery health and Runtime/provider configuration`);
1487
+ // Surface the provider's finish reason when the Runtime text names one we
1488
+ // recognize (allow-listed token only; raw Runtime text never reaches status).
1489
+ const finishReason = (0, provider_error_classifier_js_1.providerFinishReason)(message.event.message);
1490
+ const detail = finishReason ? ` (provider finish_reason=${finishReason})` : "";
1491
+ hostState.recordStatusError(agent, `${category}: Runtime input failed ${message.event.retryable ? "retryably" : "non-retryably"}${detail}; inspect delivery health and Runtime/provider configuration`);
1488
1492
  }
1489
1493
  }
1490
1494
  };
@@ -17,7 +17,7 @@ import { HostChannelBusiness } from "./host-channel-business.mjs";
17
17
  import { HostInteractionOrchestrator } from "./interaction-orchestrator.mjs";
18
18
  import { targetFor } from "./message-policy.mjs";
19
19
  import { authFailureAppliesTo, parsePersistedAuthFailure, providerAuthenticationFailureReadiness, readinessForPersistedAuthFailure, RuntimePrerequisiteError, } from "../runtime/runtime-readiness.mjs";
20
- import { safeProviderDiagnostic } from "../runtime/provider-error-classifier.mjs";
20
+ import { providerFinishReason, safeProviderDiagnostic } from "../runtime/provider-error-classifier.mjs";
21
21
  import { readDocumentCommentSubscription, verifyCallbackProbe } from "../platform/callback-capability.mjs";
22
22
  import { loadConfig, resolveInboxAuditSchedule, resolveMentionPolicy } from "../platform/config.mjs";
23
23
  import { processCommandToken } from "../app/internal-command.mjs";
@@ -1444,7 +1444,11 @@ export function createHostShell({ env = process.env, runtimeHost, channelPackage
1444
1444
  }
1445
1445
  else {
1446
1446
  const category = message.event.errorCategory || "provider";
1447
- hostState.recordStatusError(agent, `${category}: Runtime input failed ${message.event.retryable ? "retryably" : "non-retryably"}; inspect delivery health and Runtime/provider configuration`);
1447
+ // Surface the provider's finish reason when the Runtime text names one we
1448
+ // recognize (allow-listed token only; raw Runtime text never reaches status).
1449
+ const finishReason = providerFinishReason(message.event.message);
1450
+ const detail = finishReason ? ` (provider finish_reason=${finishReason})` : "";
1451
+ hostState.recordStatusError(agent, `${category}: Runtime input failed ${message.event.retryable ? "retryably" : "non-retryably"}${detail}; inspect delivery health and Runtime/provider configuration`);
1448
1452
  }
1449
1453
  }
1450
1454
  };
@@ -4,6 +4,7 @@ exports.INTERNAL_CONTEXT_WINDOW_PROJECTION_REASON = exports.CANONICAL_CONTEXT_WI
4
4
  exports.safeProviderDiagnostic = safeProviderDiagnostic;
5
5
  exports.buildStrictProviderErrorInput = buildStrictProviderErrorInput;
6
6
  exports.classifyStrictProviderError = classifyStrictProviderError;
7
+ exports.providerFinishReason = providerFinishReason;
7
8
  exports.CODEX_ERROR_PREFIX = "Codex error: ";
8
9
  exports.CANONICAL_CONTEXT_WINDOW_MESSAGE = "Your input exceeds the context window of this model. Please adjust your input and try again.";
9
10
  exports.INTERNAL_CONTEXT_WINDOW_PROJECTION_REASON = "provider rejected the input because the context window was exceeded";
@@ -51,3 +52,27 @@ function classifyStrictProviderError(error) {
51
52
  }
52
53
  return undefined;
53
54
  }
55
+ /**
56
+ * Finish reasons we are willing to quote into user-visible status. The list is
57
+ * deliberately closed: Runtime/provider text is never echoed, so only a token
58
+ * validated against this vocabulary can reach `status`.
59
+ */
60
+ const SURFACED_FINISH_REASONS = new Set([
61
+ "stop", "length", "content_filter", "tool_calls", "function_call",
62
+ "end_turn", "max_tokens", "stop_sequence", "tool_use", "refusal",
63
+ "safety", "recitation", "blocklist", "prohibited_content", "spii", "malformed_function_call", "other",
64
+ "error", "timeout", "rate_limit", "overloaded", "cancelled", "aborted",
65
+ ]);
66
+ /**
67
+ * Narrow, allow-listed extraction of a provider finish reason from Runtime text
68
+ * (e.g. "Provider finish_reason: content_filter"). Returns the validated token
69
+ * only — the surrounding payload never leaves this function, so a status line
70
+ * can say why a reply was withheld without echoing raw Runtime data.
71
+ */
72
+ function providerFinishReason(value) {
73
+ if (typeof value !== "string" || value.length === 0 || value.length > 8_192)
74
+ return null;
75
+ const match = /(?:finish[_-]?reason|rawstopreason)\s*[:=]\s*"?([A-Za-z_]{2,32})"?/i.exec(value);
76
+ const token = match?.[1]?.toLowerCase() ?? "";
77
+ return SURFACED_FINISH_REASONS.has(token) ? token : null;
78
+ }
@@ -45,3 +45,27 @@ export function classifyStrictProviderError(error) {
45
45
  }
46
46
  return undefined;
47
47
  }
48
+ /**
49
+ * Finish reasons we are willing to quote into user-visible status. The list is
50
+ * deliberately closed: Runtime/provider text is never echoed, so only a token
51
+ * validated against this vocabulary can reach `status`.
52
+ */
53
+ const SURFACED_FINISH_REASONS = new Set([
54
+ "stop", "length", "content_filter", "tool_calls", "function_call",
55
+ "end_turn", "max_tokens", "stop_sequence", "tool_use", "refusal",
56
+ "safety", "recitation", "blocklist", "prohibited_content", "spii", "malformed_function_call", "other",
57
+ "error", "timeout", "rate_limit", "overloaded", "cancelled", "aborted",
58
+ ]);
59
+ /**
60
+ * Narrow, allow-listed extraction of a provider finish reason from Runtime text
61
+ * (e.g. "Provider finish_reason: content_filter"). Returns the validated token
62
+ * only — the surrounding payload never leaves this function, so a status line
63
+ * can say why a reply was withheld without echoing raw Runtime data.
64
+ */
65
+ export function providerFinishReason(value) {
66
+ if (typeof value !== "string" || value.length === 0 || value.length > 8_192)
67
+ return null;
68
+ const match = /(?:finish[_-]?reason|rawstopreason)\s*[:=]\s*"?([A-Za-z_]{2,32})"?/i.exec(value);
69
+ const token = match?.[1]?.toLowerCase() ?? "";
70
+ return SURFACED_FINISH_REASONS.has(token) ? token : null;
71
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "larkin",
3
- "version": "0.5.11",
3
+ "version": "0.5.12",
4
4
  "private": false,
5
5
  "larkinPackageRole": "npm-published",
6
6
  "files": [