mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 00:02:31 +00:00
fix(agents): refresh remote detection on new launch surfaces (#21659)
This commit is contained in:
@@ -237,6 +237,22 @@ describe('useDetectedAgents (ssh call site)', () => {
|
||||
expect(detectRemoteAgents).toHaveBeenCalledTimes(2)
|
||||
expect(useAppStore.getState().remoteDetectedAgentIds['ssh-1']).toEqual(['kilo'])
|
||||
})
|
||||
|
||||
it('refreshes a non-empty SSH cache when a new launch surface opens', async () => {
|
||||
useAppStore.setState({ remoteDetectedAgentIds: { 'ssh-1': ['claude'] } })
|
||||
detectRemoteAgents.mockResolvedValueOnce(['claude', 'devin'])
|
||||
|
||||
const root = await renderProbe({ kind: 'ssh', connectionId: 'ssh-1' })
|
||||
|
||||
expect(detectRemoteAgents).toHaveBeenCalledTimes(1)
|
||||
expect(useAppStore.getState().remoteDetectedAgentIds['ssh-1']).toEqual(['claude', 'devin'])
|
||||
|
||||
await act(async () => {
|
||||
root.render(createElement(HookProbe, { target: { kind: 'ssh', connectionId: 'ssh-1' } }))
|
||||
})
|
||||
await flushEffects()
|
||||
expect(detectRemoteAgents).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('useDetectedAgents (unresolved target)', () => {
|
||||
@@ -283,6 +299,56 @@ describe('useDetectedAgents (runtime call site)', () => {
|
||||
).toHaveLength(2)
|
||||
})
|
||||
|
||||
it('refreshes a non-empty runtime cache when a new launch surface opens', async () => {
|
||||
useAppStore.setState({ runtimeDetectedAgentIds: { 'env-1': ['claude'] } })
|
||||
runtimeEnvironmentCall.mockImplementation(({ method }: { method: string }) => {
|
||||
const result =
|
||||
method === 'status.get'
|
||||
? {
|
||||
runtimeId: 'remote-runtime',
|
||||
rendererGraphEpoch: 1,
|
||||
graphStatus: 'ready',
|
||||
authoritativeWindowId: null,
|
||||
liveTabCount: 0,
|
||||
liveLeafCount: 0,
|
||||
runtimeProtocolVersion: RUNTIME_PROTOCOL_VERSION,
|
||||
minCompatibleRuntimeClientVersion: MIN_COMPATIBLE_RUNTIME_CLIENT_VERSION
|
||||
}
|
||||
: {
|
||||
agents: ['claude', 'devin'],
|
||||
addedPathSegments: [],
|
||||
shellHydrationOk: true,
|
||||
pathSource: 'shell_hydrate',
|
||||
pathFailureReason: 'none'
|
||||
}
|
||||
return Promise.resolve({
|
||||
id: method,
|
||||
ok: true,
|
||||
result,
|
||||
_meta: { runtimeId: 'remote-runtime' }
|
||||
})
|
||||
})
|
||||
|
||||
const root = await renderProbe({ kind: 'runtime', environmentId: 'env-1' })
|
||||
|
||||
expect(
|
||||
runtimeEnvironmentCall.mock.calls.filter(
|
||||
([{ method }]) => method === 'preflight.refreshAgents'
|
||||
)
|
||||
).toHaveLength(1)
|
||||
expect(useAppStore.getState().runtimeDetectedAgentIds['env-1']).toEqual(['claude', 'devin'])
|
||||
|
||||
await act(async () => {
|
||||
root.render(createElement(HookProbe, { target: { kind: 'runtime', environmentId: 'env-1' } }))
|
||||
})
|
||||
await flushEffects()
|
||||
expect(
|
||||
runtimeEnvironmentCall.mock.calls.filter(
|
||||
([{ method }]) => method === 'preflight.refreshAgents'
|
||||
)
|
||||
).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('does not re-probe after an explicit refresh finds no agents', async () => {
|
||||
useAppStore.setState({
|
||||
runtimeDetectedAgentIds: { 'env-1': ['claude'] },
|
||||
@@ -324,16 +390,18 @@ describe('useDetectedAgents (runtime call site)', () => {
|
||||
})
|
||||
})
|
||||
|
||||
await renderProbe({ kind: 'runtime', environmentId: 'env-1' })
|
||||
await renderProbe({ kind: 'runtime', environmentId: 'env-1' })
|
||||
await act(async () => {
|
||||
await latestHookResult?.refresh()
|
||||
})
|
||||
const root = await renderProbe({ kind: 'runtime', environmentId: 'env-1' })
|
||||
await flushEffects()
|
||||
|
||||
expect(refreshCalls).toBe(1)
|
||||
expect(detectCalls).toBe(0)
|
||||
expect(useAppStore.getState().runtimeDetectedAgentIds['env-1']).toEqual([])
|
||||
|
||||
await act(async () => {
|
||||
root.render(createElement(HookProbe, { target: { kind: 'runtime', environmentId: 'env-1' } }))
|
||||
})
|
||||
await flushEffects()
|
||||
expect(refreshCalls).toBe(1)
|
||||
})
|
||||
|
||||
it('retries a cached empty runtime result when the launch surface is reopened', async () => {
|
||||
|
||||
@@ -155,17 +155,23 @@ export function useDetectedAgents(
|
||||
if (targetKind === 'ssh' && targetId) {
|
||||
if (detectedIds === null) {
|
||||
void state.ensureRemoteDetectedAgents(targetId)
|
||||
} else if (detectedIds.length === 0 && isNewRemoteTarget) {
|
||||
// Why: a newly opened remote launch surface should get one fresh probe
|
||||
// after a prior empty result, but must not spin while the host has no agents.
|
||||
} else if (isNewRemoteTarget && detectedIds.length > 0) {
|
||||
// Why: a host can install an agent after its cached list was populated;
|
||||
// refresh once when a new launch surface first observes that host.
|
||||
void state.refreshRemoteDetectedAgents(targetId)
|
||||
} else if (isNewRemoteTarget) {
|
||||
// Empty results are intentionally retryable through the normal probe.
|
||||
void state.ensureRemoteDetectedAgents(targetId)
|
||||
}
|
||||
} else if (targetKind === 'runtime' && targetId) {
|
||||
if (detectedIds === null) {
|
||||
void state.ensureRuntimeDetectedAgents(targetId)
|
||||
} else if (detectedIds.length === 0 && isNewRemoteTarget) {
|
||||
// Why: remote `orca serve` users can install/fix PATH without reconnecting;
|
||||
// retry once per mounted surface so the menu can pick that up.
|
||||
} else if (isNewRemoteTarget && detectedIds.length > 0) {
|
||||
// Why: a host can install an agent after its cached list was populated;
|
||||
// refresh once when a new launch surface first observes that host.
|
||||
void state.refreshRuntimeDetectedAgents(targetId)
|
||||
} else if (isNewRemoteTarget) {
|
||||
// Empty results are intentionally retryable through the normal probe.
|
||||
void state.ensureRuntimeDetectedAgents(targetId)
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user