fix(app-builder): repair migrations and stale sessions - #5784
fix(app-builder): repair migrations and stale sessions#5784evanjacobson wants to merge 1 commit into
Conversation
|
|
||
| export const MigrateToGithubRequestSchema = z.object({ | ||
| githubRepo: z.string().regex(/^[^/]+\/[^/]+$/, 'Must be in "owner/repo" format'), | ||
| userId: z.string().uuid(), |
There was a problem hiding this comment.
Users with non-UUID Kilo User IDs fail due to the parsing here
| ? sessionInfos.find(s => s.cloud_agent_session_id === project.session_id) | ||
| : undefined; | ||
|
|
||
| const orderedSessionInfos = activeInfo |
There was a problem hiding this comment.
project.session_id is authoritative, but existing chat and feedback consumers treat the final array entry as active. Moving the canonical session to the end keeps those consumers aligned while older/orphaned sessions remain available as history.
| } | ||
|
|
||
| const effectiveModel = model ?? store.getState().model; | ||
| const isRecoveringSession = store.getState().isRecoveringSession; |
There was a problem hiding this comment.
Capture the mode before clearing pendingNewSession: a failed mandatory recovery must remain non-cancelable, while a failed user-requested New Chat must remain optional and cancellable.
| : undefined; | ||
|
|
||
| if (activeProjectSessionInfo?.initiated === false) { | ||
| if (activeProjectSessionInfo?.prepared === true && activeProjectSessionInfo.initiated === false) { |
There was a problem hiding this comment.
This deliberately distinguishes a prepared-but-not-started session from a missing session. Only the former can be started in place; missing sessions must use the replacement-session flow.
| const data = await response.json().catch(() => undefined); | ||
| const parsed = MigrateToGithubResponseSchema.safeParse(data); | ||
|
|
||
| if (parsed.success && !parsed.data.success) { |
There was a problem hiding this comment.
Worker domain failures intentionally use non-2xx statuses while still returning this typed envelope. Parse that contract before generic HTTP handling so callers retain the actual failure category.
| ); | ||
| sessionInitiated = null; | ||
| sessionPrepared = null; | ||
| sessionPrepared = isDefinitiveSessionNotFoundError(err) ? false : null; |
There was a problem hiding this comment.
false means the backend session is definitively absent and enables replacement recovery. Transient Cloud Agent failures stay null so a temporary outage does not abandon an otherwise valid session.
| if (!migrateResult.success) { | ||
| throw new MigrationError('push_failed', { cause: migrateResult }); | ||
| throw new MigrationError( | ||
| migrateResult.error === 'push_failed' ? 'push_failed' : 'internal_error', |
There was a problem hiding this comment.
Only push_failed means a Git push was actually attempted and failed. Validation, token, transport, and unexpected Worker failures are surfaced as internal_error rather than showing misleading push-failure UI.
| @@ -469,7 +469,6 @@ export function createV2StreamingCoordinator(config: V2StreamingConfig): V2Strea | |||
| } | |||
|
|
|||
| logger.log('Connecting to existing V2 session', { sessionId }); | |||
There was a problem hiding this comment.
A successful transport connection does not mean the agent is working. Replayed busy events now establish streaming state, so a zero-event reconnect cannot leave the UI on Building... indefinitely.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (17 files)
Reviewed by grok-4.6 · Input: 222K · Output: 22.5K · Cached: 1.4M Review guidance: REVIEW.md from base branch |
Summary
Building....Verification
git diff --checkVisual Changes
No layout changes. Missing sessions now show a required fresh-chat state instead of an indefinite
Building...state.Reviewer Notes
Migration implementation
userIdvalues while retaining UUID validation fororgId.push_failedonly for actual push failures; map validation, token, transport, and internal failures tointernal_error.Session recovery implementation
NOT_FOUNDresponses as unprepared sessions while leaving transient failures unknown.project.session_idas the canonical active session and preserve it as the final session consumed by the UI.forceNewSession, keep mandatory recovery non-cancelable and retryable, and preserve normal optional New Chat behavior.