pi-usereq 0.77.0 → 0.78.0
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/README.md +1 -1
- package/package.json +1 -1
- package/src/core/debug-runtime.ts +28 -0
- package/src/index.ts +16 -1
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -891,6 +891,34 @@ export function formatPromptDebugErrorFileName(
|
|
|
891
891
|
return `${formatPromptDebugTimestamp(date)}-${getDebugPromptName(promptName)}-error-${errorCode}`;
|
|
892
892
|
}
|
|
893
893
|
|
|
894
|
+
/**
|
|
895
|
+
* @brief Resolves the failing HTTP status carried by one finalized agent message.
|
|
896
|
+
* @details Extracts the leading provider error status from one `message_end` assistant message whose `stopReason` equals `error`, accepting both pi `formatProviderError` display shapes (`"<status>: <body>"` and `"<prefix> (<status>): <body>"`) so provider APIs whose SDK clients throw before emitting `after_provider_response` for non-2xx statuses (the OpenAI-compatible family, including `zai`) still flush the captured provider request payload through the message lifecycle channel. Runtime is O(n) in the inspected error-message prefix length. No external state is mutated.
|
|
897
|
+
* @param[in] message {unknown} Finalized agent message forwarded by one `message_end` lifecycle event.
|
|
898
|
+
* @return {number | undefined} Failing HTTP status greater than or equal to `400`, or `undefined` when the message carries no provider error status.
|
|
899
|
+
* @satisfies REQ-422, REQ-423, REQ-425
|
|
900
|
+
*/
|
|
901
|
+
export function resolveProviderErrorFlushStatusFromMessage(message: unknown): number | undefined {
|
|
902
|
+
if (typeof message !== "object" || message === null) {
|
|
903
|
+
return undefined;
|
|
904
|
+
}
|
|
905
|
+
const candidateMessage = message as { role?: unknown; stopReason?: unknown; errorMessage?: unknown };
|
|
906
|
+
if (candidateMessage.role !== "assistant" || candidateMessage.stopReason !== "error") {
|
|
907
|
+
return undefined;
|
|
908
|
+
}
|
|
909
|
+
if (typeof candidateMessage.errorMessage !== "string") {
|
|
910
|
+
return undefined;
|
|
911
|
+
}
|
|
912
|
+
const unprefixedStatus = /^(\d{3}):/.exec(candidateMessage.errorMessage)?.[1];
|
|
913
|
+
const prefixedStatus = /^[^(]+\((\d{3})\): /.exec(candidateMessage.errorMessage)?.[1];
|
|
914
|
+
const statusText = unprefixedStatus ?? prefixedStatus;
|
|
915
|
+
if (statusText === undefined) {
|
|
916
|
+
return undefined;
|
|
917
|
+
}
|
|
918
|
+
const status = Number.parseInt(statusText, 10);
|
|
919
|
+
return Number.isFinite(status) && status >= 400 ? status : undefined;
|
|
920
|
+
}
|
|
921
|
+
|
|
894
922
|
/**
|
|
895
923
|
* @brief Serializes one provider request payload into deterministic text.
|
|
896
924
|
* @details Pretty-prints the payload as JSON while degrading circular references into one `[Circular]` token and bigint values into decimal strings so serialization failures never discard the capture. Runtime is O(n) in serialized payload size. No external state is mutated.
|
package/src/index.ts
CHANGED
|
@@ -150,6 +150,7 @@ import {
|
|
|
150
150
|
normalizeDebugStatusChanges,
|
|
151
151
|
normalizeDebugToolCommandsEnabled,
|
|
152
152
|
normalizeDebugWorkflowEvents,
|
|
153
|
+
resolveProviderErrorFlushStatusFromMessage,
|
|
153
154
|
setRuntimeDebugEnabled,
|
|
154
155
|
shouldLogDebugPromptWorkflowState,
|
|
155
156
|
type DebugLogOnStatus,
|
|
@@ -1448,7 +1449,7 @@ async function finalizeMatchedPromptSuccess(
|
|
|
1448
1449
|
|
|
1449
1450
|
/**
|
|
1450
1451
|
* @brief Handles one intercepted pi lifecycle hook for pi-usereq status updates.
|
|
1451
|
-
* @details Applies session-start-specific resource validation, project-config refresh, idle-time shared-tokenizer and context-file measurement pre-warm, startup-tool enablement, and selected debug-tool logging before forwarding the originating hook name and payload into the shared `updateExtensionStatus(...)` pipeline. After the status update, captures the exact `before_provider_request` provider payload for the live active or pending prompt run with a fresh config fallback when the controller has no cached config, flushes the process-scoped captured payload as one `<timestamp>-<req-command>-error-<status>` file whenever `after_provider_response` reports a status >= 400 without requiring live workflow state, and discards the capture at prompt-run end so stale payloads never reach later runs. Before `agent_start`, re-verifies any prepared prompt execution session switch. On `agent_end`, dispatches configured command-notify, sound, and prompt-specific Pushover effects, logs dedicated workflow-closure diagnostics, classifies the prompt outcome, and for every matched successful worktree-backed completion defers the restore switch, stash-assisted merge, and worktree deletion to `agent_settled` when the running pi host supports that 0.80.4+ event (because its `switchSession` awaits the active agent run to become idle and would deadlock inside `agent_end`), or executes the finalization directly at `agent_end` when the host does not emit `agent_settled`. On `agent_settled`, reuses persisted replacement-session command contexts when event contexts omit `switchSession()`, executes the deferred stash-assisted merge-and-delete finalization path, emits a warning-only notification when restored `base-path` changes are reapplied after merge, tolerates stale replacement-session notification contexts after session replacement, retains the worktree plus notifies closure failure for interrupted or failed outcomes, logs selected prompt workflow transitions, and transitions workflow state through `merging`, `error`, and `idle` as required. On `session_shutdown`, captures pre-update prompt snapshots so workflow-shutdown diagnostics and same-runtime command continuation preserve the active prompt workflow state across switch-triggered rebinding, then disposes the shared controller. Runtime is dominated by configuration loading during `session_start` and git finalization during matched successful closure handling; all other hooks are O(1). Side effects include resource checks, active-tool mutation, active-session replacement, status updates, live-ticker disposal on shutdown, optional child-process spawning, outbound HTTPS requests, branch merges, worktree deletion, and optional debug-log writes.
|
|
1452
|
+
* @details Applies session-start-specific resource validation, project-config refresh, idle-time shared-tokenizer and context-file measurement pre-warm, startup-tool enablement, and selected debug-tool logging before forwarding the originating hook name and payload into the shared `updateExtensionStatus(...)` pipeline. After the status update, captures the exact `before_provider_request` provider payload for the live active or pending prompt run with a fresh config fallback when the controller has no cached config, flushes the process-scoped captured payload as one `<timestamp>-<req-command>-error-<status>` file whenever `after_provider_response` reports a status >= 400 or whenever one finalized `message_end` assistant error message carries a leading HTTP status >= 400 (the provider-independent fallback for provider APIs whose SDK clients throw before emitting `after_provider_response` for non-2xx statuses) without requiring live workflow state, and discards the capture at prompt-run end so stale payloads never reach later runs. Before `agent_start`, re-verifies any prepared prompt execution session switch. On `agent_end`, dispatches configured command-notify, sound, and prompt-specific Pushover effects, logs dedicated workflow-closure diagnostics, classifies the prompt outcome, and for every matched successful worktree-backed completion defers the restore switch, stash-assisted merge, and worktree deletion to `agent_settled` when the running pi host supports that 0.80.4+ event (because its `switchSession` awaits the active agent run to become idle and would deadlock inside `agent_end`), or executes the finalization directly at `agent_end` when the host does not emit `agent_settled`. On `agent_settled`, reuses persisted replacement-session command contexts when event contexts omit `switchSession()`, executes the deferred stash-assisted merge-and-delete finalization path, emits a warning-only notification when restored `base-path` changes are reapplied after merge, tolerates stale replacement-session notification contexts after session replacement, retains the worktree plus notifies closure failure for interrupted or failed outcomes, logs selected prompt workflow transitions, and transitions workflow state through `merging`, `error`, and `idle` as required. On `session_shutdown`, captures pre-update prompt snapshots so workflow-shutdown diagnostics and same-runtime command continuation preserve the active prompt workflow state across switch-triggered rebinding, then disposes the shared controller. Runtime is dominated by configuration loading during `session_start` and git finalization during matched successful closure handling; all other hooks are O(1). Side effects include resource checks, active-tool mutation, active-session replacement, status updates, live-ticker disposal on shutdown, optional child-process spawning, outbound HTTPS requests, branch merges, worktree deletion, and optional debug-log writes.
|
|
1452
1453
|
* @param[in] pi {ExtensionAPI} Active extension API instance.
|
|
1453
1454
|
* @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
|
|
1454
1455
|
* @param[in] hookName {PiUsereqStatusHookName} Intercepted hook name.
|
|
@@ -1536,6 +1537,20 @@ async function handleExtensionStatusEvent(
|
|
|
1536
1537
|
flushCapturedPromptErrorPayload(providerResponseEvent.status);
|
|
1537
1538
|
}
|
|
1538
1539
|
}
|
|
1540
|
+
// Provider APIs whose SDK clients throw on non-2xx statuses (the OpenAI-compatible family,
|
|
1541
|
+
// including `zai`) never reach their `onResponse` hook for failing responses, so
|
|
1542
|
+
// `after_provider_response` stays silent exactly when REQ-422 must fire. The finalized
|
|
1543
|
+
// error assistant message is the provider-independent signal: the pi agent loop emits
|
|
1544
|
+
// `message_end` for every failed provider request with the HTTP status embedded in
|
|
1545
|
+
// `errorMessage` by `formatProviderError`.
|
|
1546
|
+
if (hookName === "message_end") {
|
|
1547
|
+
const providerErrorStatus = resolveProviderErrorFlushStatusFromMessage(
|
|
1548
|
+
(event as { message?: unknown }).message,
|
|
1549
|
+
);
|
|
1550
|
+
if (providerErrorStatus !== undefined) {
|
|
1551
|
+
flushCapturedPromptErrorPayload(providerErrorStatus);
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1539
1554
|
if (hookName === "agent_end" || hookName === "agent_settled") {
|
|
1540
1555
|
discardCapturedPromptErrorPayload();
|
|
1541
1556
|
}
|