From 1ec6db4a4e1193bbbd2fe6c50a7e3486606df346 Mon Sep 17 00:00:00 2001 From: Jinwoo-H Date: Wed, 9 Sep 2026 15:34:50 -0400 Subject: [PATCH] fix mobile project payload and account fixtures Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb --- .../src/accounts-route-reset-credit.test.ts | 13 -------- ...ive-host-session-native-chat-operations.ts | 33 +++++++++++++------ .../src/tasks/host-task-project-payloads.ts | 1 - .../host-task-project-read-operations.ts | 2 +- .../host-workspace-creation-operations.ts | 15 +-------- 5 files changed, 25 insertions(+), 39 deletions(-) diff --git a/mobile/src/accounts-route-reset-credit.test.ts b/mobile/src/accounts-route-reset-credit.test.ts index 09019809bcc..2de1e96881d 100644 --- a/mobile/src/accounts-route-reset-credit.test.ts +++ b/mobile/src/accounts-route-reset-credit.test.ts @@ -54,19 +54,6 @@ vi.mock('expo-router', async () => { vi.mock('expo-crypto', () => ({ randomUUID: dependencies.randomUUID })) -// The account adapter reaches device operations for its idempotency nonce, which pulls the -// native expo modules into this module graph. -vi.mock('expo-clipboard', () => ({ setStringAsync: vi.fn() })) -vi.mock('expo-haptics', () => ({ - AndroidHaptics: {}, - ImpactFeedbackStyle: {}, - NotificationFeedbackType: {}, - impactAsync: vi.fn(), - notificationAsync: vi.fn(), - performAndroidHapticsAsync: vi.fn(), - selectionAsync: vi.fn() -})) - vi.mock('lucide-react-native', () => ({ Check: 'Check', ChevronLeft: 'ChevronLeft', diff --git a/mobile/src/session/native-host-session-native-chat-operations.ts b/mobile/src/session/native-host-session-native-chat-operations.ts index baef6fec921..3086d430649 100644 --- a/mobile/src/session/native-host-session-native-chat-operations.ts +++ b/mobile/src/session/native-host-session-native-chat-operations.ts @@ -27,6 +27,7 @@ export function nativeHostSessionNativeChatOperations( // `@` autocomplete in a second workspace suggest the first workspace's files. const legacyPathsByWorkspace = new Map() const legacyLoadByWorkspace = new Map>() + const legacyGenerationByWorkspace = new Map() return { async readability(workspaceId) { if (isFloatingWorkspaceWorktreeId(workspaceId)) { @@ -72,7 +73,10 @@ export function nativeHostSessionNativeChatOperations( resetFileSearchCache(workspaceId) { searchSupported = null legacyPathsByWorkspace.delete(workspaceId) - legacyLoadByWorkspace.delete(workspaceId) + legacyGenerationByWorkspace.set( + workspaceId, + (legacyGenerationByWorkspace.get(workspaceId) ?? 0) + 1 + ) }, async searchFiles(target, query) { if (searchSupported !== false) { @@ -98,22 +102,31 @@ export function nativeHostSessionNativeChatOperations( if (!legacyLoad) { // Older hosts expose only the full inventory RPC; overlapping queries must // share one slow local/SSH read. - legacyLoad = client + const generation = legacyGenerationByWorkspace.get(target.workspaceId) ?? 0 + const request = client .sendRequest('files.list', { worktree: `id:${target.workspaceId}` }) .then((response) => (response.ok ? extractPaths(response.result) : null)) - .finally(() => { + legacyLoad = request.finally(() => { + if (legacyLoadByWorkspace.get(target.workspaceId) === legacyLoad) { legacyLoadByWorkspace.delete(target.workspaceId) - }) + } + }) legacyLoadByWorkspace.set(target.workspaceId, legacyLoad) + const paths = await legacyLoad + if ((legacyGenerationByWorkspace.get(target.workspaceId) ?? 0) !== generation) { + return null + } + if (!paths) return null + legacyPaths = paths + legacyPathsByWorkspace.set(target.workspaceId, paths) + } else { + const paths = await legacyLoad + if (!paths) return null + legacyPaths = paths + legacyPathsByWorkspace.set(target.workspaceId, paths) } - const paths = await legacyLoad - if (!paths) { - return null - } - legacyPaths = paths - legacyPathsByWorkspace.set(target.workspaceId, paths) } return rankSuggestions(legacyPaths, query, FILE_RESULT_LIMIT) } diff --git a/mobile/src/tasks/host-task-project-payloads.ts b/mobile/src/tasks/host-task-project-payloads.ts index c17cc7c8013..984eb2d913b 100644 --- a/mobile/src/tasks/host-task-project-payloads.ts +++ b/mobile/src/tasks/host-task-project-payloads.ts @@ -27,7 +27,6 @@ export type HostTaskProjectResolveResult = { export type HostTaskProjectTablePayload = GitHubProjectRef & { viewId: string queryOverride?: string - cursor?: string } export type HostTaskProjectSlugPayload = { diff --git a/mobile/src/tasks/host-task-project-read-operations.ts b/mobile/src/tasks/host-task-project-read-operations.ts index a973bd4cb41..98fe2076d35 100644 --- a/mobile/src/tasks/host-task-project-read-operations.ts +++ b/mobile/src/tasks/host-task-project-read-operations.ts @@ -17,7 +17,7 @@ export type HostTaskProjectReadOperations = { listAccessible(host: string): Promise listViews(project: GitHubProjectRef): Promise resolveRef(payload: HostTaskProjectResolvePayload): Promise - loadTable(payload: Omit): Promise + loadTable(payload: HostTaskProjectTablePayload): Promise loadItemDetail(payload: HostTaskProjectItemDetailPayload): Promise listItemLabels(payload: HostTaskProjectSlugPayload): Promise listItemAssignableUsers( diff --git a/mobile/src/worktree/host-workspace-creation-operations.ts b/mobile/src/worktree/host-workspace-creation-operations.ts index b89c6bfd8cd..eec2753aa0e 100644 --- a/mobile/src/worktree/host-workspace-creation-operations.ts +++ b/mobile/src/worktree/host-workspace-creation-operations.ts @@ -21,20 +21,7 @@ import type { GitRemoteIdentity } from '../../../src/shared/git-remote-identity' import type { RepoIcon } from '../../../src/shared/repo-icon' import type { RetiredNameRegistry } from '../../../src/shared/worktree/retired-name-registry' -export type NewWorkspaceRepository = { - id: string - displayName: string - path: string - badgeColor?: string - connectionId?: string | null - executionHostId?: ExecutionHostId | null - executionHostLabel?: string - projectId?: string - kind?: 'git' | 'folder' - upstream?: { owner: string; repo: string; host?: string } | null - repoIcon?: RepoIcon | null - gitRemoteIdentity?: GitRemoteIdentity | null -} +export type { MobileWorkspaceRepo as NewWorkspaceRepository } from '../components/new-worktree-modal-types' export type NewWorkspaceRuntimeSettings = { defaultTuiAgent?: TuiAgent | 'blank' | null