Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions wework/src/features/workbench/WorkbenchProvider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1365,6 +1365,9 @@ function ArchiveRemoteRuntimeTaskProbe() {
>
archive remote task
</button>
<button type="button" onClick={() => void workbench.refreshWorkLists()}>
refresh work lists
</button>
</div>
)
}
Expand Down Expand Up @@ -6476,7 +6479,7 @@ describe('WorkbenchProvider runtime tasks', () => {
await waitFor(() => expect(screen.getByTestId('archive-result')).toHaveTextContent('archived'))
})

test('does not restore an archived remote task from the previous cloud snapshot', async () => {
test('archives a remote task locally without triggering a cloud sync', async () => {
const remoteRuntimeWork: RuntimeWorkListResponse = {
projects: [
{
Expand Down Expand Up @@ -6540,9 +6543,11 @@ describe('WorkbenchProvider runtime tasks', () => {
await userEvent.click(screen.getByText('archive remote task'))

await waitFor(() => expect(runtimeWorkApi.archiveConversation).toHaveBeenCalledTimes(1))
await waitFor(() => expect(cloudListRuntimeWork).toHaveBeenCalledTimes(2))
expect(screen.getByTestId('archive-remote-task-titles')).toHaveTextContent('')
expect(cloudListRuntimeWork).toHaveBeenCalledTimes(1)

await userEvent.click(screen.getByText('refresh work lists'))
await waitFor(() => expect(cloudListRuntimeWork).toHaveBeenCalledTimes(2))
postArchiveCloudWork.resolve({ projects: [], chats: [], totalTasks: 0 })
await waitFor(() =>
expect(screen.getByTestId('archive-remote-task-titles')).toHaveTextContent('')
Expand Down
2 changes: 1 addition & 1 deletion wework/src/features/workbench/WorkbenchProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ export function WorkbenchProvider({
remoteProjectSyncSignatureRef.current = signature
void executorClient.runtime
.syncRuntimeRemoteProjects({ deviceId: localRuntimeStateDeviceId, projects })
.then(refreshWorkLists)
.then(() => refreshWorkLists())
.catch(error => {
remoteProjectSyncSignatureRef.current = ''
console.warn('[Wework] Failed to sync remote projects into Codex global state', error)
Expand Down
124 changes: 66 additions & 58 deletions wework/src/features/workbench/useWorkbenchDataRefresh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -623,64 +623,72 @@ export function useWorkbenchDataRefresh({
user,
])

const refreshWorkLists = useCallback(async () => {
const [devicesResult, runtimeWorkResult] = await Promise.all([
executorClient.commands.listDevices().catch(error => {
const cachedDevices = readCachedDeviceList()
if (cachedDevices.length === 0) throw error
return cachedDevices
}),
executorClient.runtime.listRuntimeWork().catch(() => undefined),
])
const devices = resolveDeviceListWithCache(devicesResult)
const visibleDevices = resolveDeviceListWithCache(
selectVisibleDevices(devices, cloudRuntimeStateRef.current)
)
const filteredRuntimeWorkResult = runtimeWorkResult
? filterRemovedRuntimeProjects(runtimeWorkResult)
: undefined
if (filteredRuntimeWorkResult) {
localRuntimeWorkRef.current = filteredRuntimeWorkResult
}
const localRuntimeWork = filteredRuntimeWorkResult ?? state.runtimeWork ?? EMPTY_RUNTIME_WORK
if (filteredRuntimeWorkResult && !services.cloudBackgroundApi?.listRuntimeWork) {
releaseConfirmedArchivedRuntimeTasks(filteredRuntimeWorkResult)
}
const runtimeWork = filteredRuntimeWorkResult
? selectVisibleRuntimeWork(localRuntimeWork, cloudRuntimeStateRef.current, visibleDevices)
: hasCloudBackgroundApi
? localRuntimeWork
: filterDisconnectedRemoteRuntimeWork(localRuntimeWork)
debugRuntimeSidebarState('refresh-resolved', {
source: filteredRuntimeWorkResult ? 'executor' : 'current-state',
executorTaskIds: summarizeRuntimeWorkTaskIds(filteredRuntimeWorkResult ?? null),
visibleTaskIds: summarizeRuntimeWorkTaskIds(runtimeWork),
})
dispatch({
type: 'lists_refreshed',
projects: state.projects,
devices: visibleDevices,
runtimeWork,
standaloneDeviceId: getPreferredStandaloneDeviceId(visibleDevices, state.standaloneDeviceId),
})
void refreshCloudBackgroundData(devices, localRuntimeWork, {
projects: state.projects,
standaloneDeviceId: state.standaloneDeviceId,
trigger: 'manual-refresh',
}).catch(() => undefined)
}, [
dispatch,
executorClient,
filterRemovedRuntimeProjects,
refreshCloudBackgroundData,
hasCloudBackgroundApi,
releaseConfirmedArchivedRuntimeTasks,
selectVisibleRuntimeWork,
services.cloudBackgroundApi,
state.projects,
state.runtimeWork,
state.standaloneDeviceId,
])
const refreshWorkLists = useCallback(
async (options?: { syncCloud?: boolean }) => {
const [devicesResult, runtimeWorkResult] = await Promise.all([
executorClient.commands.listDevices().catch(error => {
const cachedDevices = readCachedDeviceList()
if (cachedDevices.length === 0) throw error
return cachedDevices
}),
executorClient.runtime.listRuntimeWork().catch(() => undefined),
])
const devices = resolveDeviceListWithCache(devicesResult)
const visibleDevices = resolveDeviceListWithCache(
selectVisibleDevices(devices, cloudRuntimeStateRef.current)
)
const filteredRuntimeWorkResult = runtimeWorkResult
? filterRemovedRuntimeProjects(runtimeWorkResult)
: undefined
if (filteredRuntimeWorkResult) {
localRuntimeWorkRef.current = filteredRuntimeWorkResult
}
const localRuntimeWork = filteredRuntimeWorkResult ?? state.runtimeWork ?? EMPTY_RUNTIME_WORK
if (filteredRuntimeWorkResult && !services.cloudBackgroundApi?.listRuntimeWork) {
releaseConfirmedArchivedRuntimeTasks(filteredRuntimeWorkResult)
}
const runtimeWork = filteredRuntimeWorkResult
? selectVisibleRuntimeWork(localRuntimeWork, cloudRuntimeStateRef.current, visibleDevices)
: hasCloudBackgroundApi
? localRuntimeWork
: filterDisconnectedRemoteRuntimeWork(localRuntimeWork)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
debugRuntimeSidebarState('refresh-resolved', {
source: filteredRuntimeWorkResult ? 'executor' : 'current-state',
executorTaskIds: summarizeRuntimeWorkTaskIds(filteredRuntimeWorkResult ?? null),
visibleTaskIds: summarizeRuntimeWorkTaskIds(runtimeWork),
})
dispatch({
type: 'lists_refreshed',
projects: state.projects,
devices: visibleDevices,
runtimeWork,
standaloneDeviceId: getPreferredStandaloneDeviceId(
visibleDevices,
state.standaloneDeviceId
),
})
if (options?.syncCloud !== false) {
void refreshCloudBackgroundData(devices, localRuntimeWork, {
projects: state.projects,
standaloneDeviceId: state.standaloneDeviceId,
trigger: 'manual-refresh',
}).catch(() => undefined)
}
},
[
dispatch,
executorClient,
filterRemovedRuntimeProjects,
refreshCloudBackgroundData,
hasCloudBackgroundApi,
releaseConfirmedArchivedRuntimeTasks,
selectVisibleRuntimeWork,
services.cloudBackgroundApi,
state.projects,
state.runtimeWork,
state.standaloneDeviceId,
]
)

const loadDevicesForRefresh = useCallback(
async (options?: { useCacheFallback?: boolean }): Promise<DeviceInfo[]> => {
Expand Down
5 changes: 3 additions & 2 deletions wework/src/features/workbench/useWorkbenchRuntimeTasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import type {
ArchiveRuntimeTaskOptions,
ArchiveRuntimeTaskResult,
ArchiveRuntimeConversationsResult,
RefreshWorkLists,
} from './workbenchContextTypes'
import { evictRuntimeConversation } from './runtimeConversationCache'
import type { RuntimeTaskLifecycleStore } from './runtimeTaskLifecycle'
Expand All @@ -53,7 +54,7 @@ interface UseWorkbenchRuntimeTasksOptions {
services: WorkbenchServices
lifecycleStore: RuntimeTaskLifecycleStore
markRuntimeTasksArchived: (addresses: RuntimeTaskAddress[]) => void
refreshWorkLists: () => Promise<void>
refreshWorkLists: RefreshWorkLists
}

const runtimeTranscriptRequests = new Map<string, Promise<RuntimePaneTranscript>>()
Expand Down Expand Up @@ -265,7 +266,7 @@ export function useWorkbenchRuntimeTasks({
findRuntimeTaskWorktrees(state.runtimeWork, archivedAddresses)
)
clearCurrentRuntimeTaskIfArchived(archivedAddresses)
await refreshWorkLists()
await refreshWorkLists({ syncCloud: false })
}
const failedResult = results.find(result => !result.response?.accepted)
if (!failedResult) return { status: 'archived' }
Expand Down
4 changes: 3 additions & 1 deletion wework/src/features/workbench/workbenchContextTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ export type ArchiveRuntimeTaskResult = {
status: 'archived' | 'dirty_worktree' | 'failed'
}

export type RefreshWorkLists = (options?: { syncCloud?: boolean }) => Promise<void>

export type ArchiveRuntimeConversationsResult = ArchiveRuntimeTaskResult

export interface SendCurrentInputOptions {
Expand Down Expand Up @@ -229,7 +231,7 @@ export interface WorkbenchContextValue {
address: RuntimeTaskAddress
) => Promise<RuntimeTaskIMNotificationSubscriptionResponse>
rememberExecutionDevice: (deviceId: string) => void
refreshWorkLists: () => Promise<void>
refreshWorkLists: RefreshWorkLists
refreshDevices: () => Promise<void>
getRemoteDeviceStartupCommand: () => Promise<DockerRemoteDeviceCommandResponse>
upgradeDevice: (deviceId: string) => Promise<void>
Expand Down
Loading