@hienlh/ppm 0.8.2 → 0.8.4
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/CHANGELOG.md +11 -0
- package/package.json +1 -1
- package/src/providers/claude-agent-sdk.ts +42 -1
- package/src/server/ws/chat.ts +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.8.4] - 2026-03-23
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- **Poisoned session auto-recovery**: When resuming an existing SDK session fails with an assistant error (e.g. `unknown`), automatically retry as a fresh session instead of hanging for minutes — fixes projects stuck on a bad session
|
|
7
|
+
|
|
8
|
+
## [0.8.3] - 2026-03-23
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **WSL timeout diagnostics**: Connection timeout error now detects WSL environment and suggests specific DNS/proxy troubleshooting steps
|
|
12
|
+
- **No-credentials warning**: Log warning when no account and no API key in env — helps diagnose why SDK subprocess hangs
|
|
13
|
+
|
|
3
14
|
## [0.8.2] - 2026-03-23
|
|
4
15
|
|
|
5
16
|
### Fixed
|
package/package.json
CHANGED
|
@@ -553,6 +553,14 @@ export class ClaudeAgentSdkProvider implements AIProvider {
|
|
|
553
553
|
yield { type: "account_info" as const, accountId: account.id, accountLabel: account.label ?? account.email ?? "Unknown" };
|
|
554
554
|
}
|
|
555
555
|
const queryEnv = this.buildQueryEnv(meta.projectPath, account);
|
|
556
|
+
|
|
557
|
+
// Pre-flight: warn if no credentials at all (avoids 2-minute silent timeout)
|
|
558
|
+
if (!account) {
|
|
559
|
+
const hasApiKey = !!(queryEnv.ANTHROPIC_API_KEY || queryEnv.CLAUDE_CODE_OAUTH_TOKEN);
|
|
560
|
+
if (!hasApiKey) {
|
|
561
|
+
console.warn(`[sdk] session=${sessionId} no account and no API key in env — Claude CLI will use its own auth (if any)`);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
556
564
|
console.log(`[sdk] query: session=${sessionId} sdkId=${sdkId} isFirst=${isFirstMessage} fork=${shouldFork} cwd=${effectiveCwd} platform=${process.platform} accountMode=${!!account} permissionMode=${permissionMode} isBypass=${isBypass}`);
|
|
557
565
|
|
|
558
566
|
// TODO: Remove when TS SDK fixes Windows stdin pipe buffering (see queryDirectCli() JSDoc for tracking issues)
|
|
@@ -791,6 +799,40 @@ export class ClaudeAgentSdkProvider implements AIProvider {
|
|
|
791
799
|
// SDK assistant messages can carry an error field for auth/billing/rate-limit failures
|
|
792
800
|
const assistantError = (msg as any).error as string | undefined;
|
|
793
801
|
if (assistantError) {
|
|
802
|
+
console.error(`[sdk] session=${sessionId} assistant error: ${assistantError} (isFirst=${isFirstMessage})`);
|
|
803
|
+
// If resuming an existing session and it errors → retry as fresh session
|
|
804
|
+
if (!isFirstMessage && retryCount < MAX_RETRIES) {
|
|
805
|
+
retryCount++;
|
|
806
|
+
console.warn(`[sdk] session=${sessionId} resume failed with assistant error "${assistantError}" — retrying as fresh session`);
|
|
807
|
+
yield { type: "text" as const, content: `Session resume failed (${assistantError}). Retrying with a fresh session...` };
|
|
808
|
+
// Re-create query without resume
|
|
809
|
+
const freshQ = query({
|
|
810
|
+
prompt: message,
|
|
811
|
+
options: {
|
|
812
|
+
cwd: effectiveCwd,
|
|
813
|
+
systemPrompt: systemPromptOpt,
|
|
814
|
+
settingSources: ["user", "project"],
|
|
815
|
+
env: queryEnv,
|
|
816
|
+
settings: { permissions: { allow: [], deny: [] } },
|
|
817
|
+
allowedTools,
|
|
818
|
+
permissionMode,
|
|
819
|
+
allowDangerouslySkipPermissions: isBypass,
|
|
820
|
+
...(permissionHooks && { hooks: permissionHooks }),
|
|
821
|
+
...(providerConfig.model && { model: providerConfig.model }),
|
|
822
|
+
...(providerConfig.effort && { effort: providerConfig.effort }),
|
|
823
|
+
maxTurns: providerConfig.max_turns ?? 100,
|
|
824
|
+
...(providerConfig.max_budget_usd && { maxBudgetUsd: providerConfig.max_budget_usd }),
|
|
825
|
+
...(providerConfig.thinking_budget_tokens != null && {
|
|
826
|
+
thinkingBudgetTokens: providerConfig.thinking_budget_tokens,
|
|
827
|
+
}),
|
|
828
|
+
canUseTool,
|
|
829
|
+
includePartialMessages: true,
|
|
830
|
+
} as any,
|
|
831
|
+
});
|
|
832
|
+
this.activeQueries.set(sessionId, freshQ);
|
|
833
|
+
eventSource = freshQ;
|
|
834
|
+
continue retryLoop;
|
|
835
|
+
}
|
|
794
836
|
const errorHints: Record<string, string> = {
|
|
795
837
|
authentication_failed: "API authentication failed. Check your account credentials in Settings → Accounts.",
|
|
796
838
|
billing_error: "Billing error on this account. Check your subscription status.",
|
|
@@ -800,7 +842,6 @@ export class ClaudeAgentSdkProvider implements AIProvider {
|
|
|
800
842
|
unknown: "API connection failed. Possible causes: network unreachable, expired OAuth token, or API outage. Try: 1) Check connectivity (`curl -s https://api.anthropic.com`), 2) Re-add account in Settings, 3) Create a new chat session.",
|
|
801
843
|
};
|
|
802
844
|
const hint = errorHints[assistantError] ?? `API error: ${assistantError}`;
|
|
803
|
-
console.error(`[sdk] session=${sessionId} assistant error: ${assistantError}`);
|
|
804
845
|
yield { type: "error", message: hint };
|
|
805
846
|
}
|
|
806
847
|
const content = (msg as any).message?.content;
|
package/src/server/ws/chat.ts
CHANGED
|
@@ -130,9 +130,14 @@ async function runStreamLoop(sessionId: string, providerId: string, content: str
|
|
|
130
130
|
clearInterval(heartbeat);
|
|
131
131
|
console.error(`[chat] session=${sessionId} SDK connection timeout after ${elapsed}s`);
|
|
132
132
|
logSessionEvent(sessionId, "ERROR", `SDK connection timeout after ${elapsed}s — subprocess may have failed to start`);
|
|
133
|
+
const projectPath = entry?.projectPath ?? "";
|
|
134
|
+
const isWSL = projectPath.startsWith("/home/") || projectPath.startsWith("/mnt/");
|
|
135
|
+
const wslHint = isWSL
|
|
136
|
+
? "\n\nWSL detected — this is likely a network issue. Try from your WSL terminal:\n curl -s https://api.anthropic.com\nIf that fails, check WSL DNS settings (/etc/resolv.conf) or proxy configuration."
|
|
137
|
+
: "";
|
|
133
138
|
safeSend(sessionId, {
|
|
134
139
|
type: "error",
|
|
135
|
-
message: `Claude SDK failed to respond after ${elapsed}s. Check
|
|
140
|
+
message: `Claude SDK failed to respond after ${elapsed}s. The API may be unreachable from this machine.${wslHint}\n\nGeneral troubleshooting:\n• Check internet connectivity\n• Run \`claude\` in your terminal to verify it works\n• Try: ppm start -f`,
|
|
136
141
|
});
|
|
137
142
|
abortController.abort();
|
|
138
143
|
return;
|