@hienlh/ppm 0.8.3 → 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 CHANGED
@@ -1,5 +1,10 @@
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
+
3
8
  ## [0.8.3] - 2026-03-23
4
9
 
5
10
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hienlh/ppm",
3
- "version": "0.8.3",
3
+ "version": "0.8.4",
4
4
  "description": "Personal Project Manager — mobile-first web IDE with AI assistance",
5
5
  "author": "hienlh",
6
6
  "license": "MIT",
@@ -799,6 +799,40 @@ export class ClaudeAgentSdkProvider implements AIProvider {
799
799
  // SDK assistant messages can carry an error field for auth/billing/rate-limit failures
800
800
  const assistantError = (msg as any).error as string | undefined;
801
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
+ }
802
836
  const errorHints: Record<string, string> = {
803
837
  authentication_failed: "API authentication failed. Check your account credentials in Settings → Accounts.",
804
838
  billing_error: "Billing error on this account. Check your subscription status.",
@@ -808,7 +842,6 @@ export class ClaudeAgentSdkProvider implements AIProvider {
808
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.",
809
843
  };
810
844
  const hint = errorHints[assistantError] ?? `API error: ${assistantError}`;
811
- console.error(`[sdk] session=${sessionId} assistant error: ${assistantError}`);
812
845
  yield { type: "error", message: hint };
813
846
  }
814
847
  const content = (msg as any).message?.content;