diff --git a/.pi/prompts/is.md b/.pi/prompts/is.md new file mode 100644 index 00000000..f57561f6 --- /dev/null +++ b/.pi/prompts/is.md @@ -0,0 +1,21 @@ +--- +description: Analyze GitHub issues (bugs or feature requests) +--- +Analyze GitHub issue(s): $ARGUMENTS + +For each issue: + +1. Read the issue in full, including all comments and linked issues/PRs. + +2. **For bugs**: + - Ignore any root cause analysis in the issue (likely wrong) + - Read all related code files in full (no truncation) + - Trace the code path and identify the actual root cause + - Propose a fix + +3. **For feature requests**: + - Read all related code files in full (no truncation) + - Propose the most concise implementation approach + - List affected files and changes needed + +Do NOT implement unless explicitly asked. Analyze and propose only. diff --git a/.pi/prompts/pr.md b/.pi/prompts/pr.md new file mode 100644 index 00000000..e5c41884 --- /dev/null +++ b/.pi/prompts/pr.md @@ -0,0 +1,35 @@ +--- +description: Review PRs from URLs with structured issue and code analysis +--- +You are given one or more GitHub PR URLs: $@ + +For each PR URL, do the following in order: +1. Read the PR page in full. Include description, all comments, all commits, and all changed files. +2. Identify any linked issues referenced in the PR body, comments, commit messages, or cross links. Read each issue in full, including all comments. +3. Analyze the PR diff. Read all relevant code files in full with no truncation. Include related code paths that are not in the diff but are required to validate behavior. +4. Check for a changelog entry in the relevant `packages/*/CHANGELOG.md` files. Report whether an entry exists. If missing, state that a changelog entry is required before merge and that you will add it if the user decides to merge. Follow the changelog format rules in AGENTS.md. +5. Provide a structured review with these sections: + - Good: solid choices or improvements + - Bad: concrete issues, regressions, missing tests, or risks + - Ugly: subtle or high impact problems +6. Add Questions or Assumptions if anything is unclear. +7. Add Change summary and Tests. + +Output format per PR: +PR: +Changelog: +- ... +Good: +- ... +Bad: +- ... +Ugly: +- ... +Questions or Assumptions: +- ... +Change summary: +- ... +Tests: +- ... + +If no issues are found, say so under Bad and Ugly. \ No newline at end of file diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 7dea01b7..c49128e3 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixed - Queued steering/follow-up messages no longer wipe unsent editor input ([#503](https://github.com/badlogic/pi-mono/pull/503) by [@tmustier](https://github.com/tmustier)) +- OAuth token refresh failure no longer crashes app at startup, allowing user to `/login` to re-authenticate ([#498](https://github.com/badlogic/pi-mono/issues/498)) ## [0.37.3] - 2026-01-06 diff --git a/packages/coding-agent/src/core/auth-storage.ts b/packages/coding-agent/src/core/auth-storage.ts index 8ac63dd7..09c0ac02 100644 --- a/packages/coding-agent/src/core/auth-storage.ts +++ b/packages/coding-agent/src/core/auth-storage.ts @@ -326,7 +326,7 @@ export class AuthStorage { if (result) { return result.apiKey; } - } catch (err) { + } catch { // Refresh failed - re-read file to check if another instance succeeded this.reload(); const updatedCred = this.data[provider]; @@ -339,13 +339,9 @@ export class AuthStorage { : updatedCred.access; } - // Refresh truly failed - DO NOT remove credentials - // User can retry or re-authenticate manually - const errorMessage = err instanceof Error ? err.message : String(err); - throw new Error( - `OAuth token refresh failed for ${provider}: ${errorMessage}. ` + - `Please try again or re-authenticate with /login.`, - ); + // Refresh truly failed - return undefined so model discovery skips this provider + // User can /login to re-authenticate (credentials preserved for retry) + return undefined; } } else { // Token not expired, use current access token diff --git a/packages/coding-agent/src/main.ts b/packages/coding-agent/src/main.ts index eaa164cd..92754958 100644 --- a/packages/coding-agent/src/main.ts +++ b/packages/coding-agent/src/main.ts @@ -171,12 +171,35 @@ function getChangelogForDisplay(parsed: Args, settingsManager: SettingsManager): return undefined; } +/** + * Resolve a session argument to a file path. + * If it looks like a path, use as-is. Otherwise try to match as session ID prefix. + */ +function resolveSessionPath(sessionArg: string, cwd: string, sessionDir?: string): string { + // If it looks like a file path, use as-is + if (sessionArg.includes("/") || sessionArg.includes("\\") || sessionArg.endsWith(".jsonl")) { + return sessionArg; + } + + // Try to match as session ID (full or partial UUID) + const sessions = SessionManager.list(cwd, sessionDir); + const matches = sessions.filter((s) => s.id.startsWith(sessionArg)); + + if (matches.length >= 1) { + return matches[0].path; // Already sorted by modified time (most recent first) + } + + // No match - return original (will create new session) + return sessionArg; +} + function createSessionManager(parsed: Args, cwd: string): SessionManager | undefined { if (parsed.noSession) { return SessionManager.inMemory(); } if (parsed.session) { - return SessionManager.open(parsed.session, parsed.sessionDir); + const resolvedPath = resolveSessionPath(parsed.session, cwd, parsed.sessionDir); + return SessionManager.open(resolvedPath, parsed.sessionDir); } if (parsed.continue) { return SessionManager.continueRecent(cwd, parsed.sessionDir); diff --git a/packages/coding-agent/src/modes/interactive/components/session-selector.ts b/packages/coding-agent/src/modes/interactive/components/session-selector.ts index 317c72a5..8bb7fe9d 100644 --- a/packages/coding-agent/src/modes/interactive/components/session-selector.ts +++ b/packages/coding-agent/src/modes/interactive/components/session-selector.ts @@ -42,7 +42,11 @@ class SessionList implements Component { } private filterSessions(query: string): void { - this.filteredSessions = fuzzyFilter(this.allSessions, query, (session) => session.allMessagesText); + this.filteredSessions = fuzzyFilter( + this.allSessions, + query, + (session) => `${session.id} ${session.allMessagesText}`, + ); this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredSessions.length - 1)); } diff --git a/pi-test.sh b/pi-test.sh new file mode 100755 index 00000000..fa78e54f --- /dev/null +++ b/pi-test.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail + +npx tsx packages/coding-agent/src/cli.ts "$@"