refactor(client): 四处轮询站点迁移到 use-polling,语义逐一保持
- SubagentView useSubagentLive:self-scheduling(上一请求 settle 后才排 下一次,不重叠)+ 每代 AbortSignal + signal.aborted 拦迟到写入,行为 与原 disposed 标志等价(teardown 同步置 disposed 并 abort)。 - SideChatView:立即拉取 effect 与 2s 定时拆分——输入变化(含 running 翻转)仍先拉一次转录,运行中间隔 tick 拉转录+徽章;fetchThread 自带 的逐次 abort 与卸载 abort 原样保留。 - GitLens:可见时 2s 固定静默 tick,无初始突发(mount/scope 变更的完整 刷新在别处);refresh 身份变化照旧重启间隔相位。 - ChangesTab:输入变化即拉一次(含隐藏态翻转),可见时 2.5s 固定间隔; pull 内部 pollGen 代际守卫不动。 守护 spec 全绿:subagent-live-polling + subagent-jobs-view 13/13、 sidechat-view + sidechat-transcript 29/29、git-view-worktree + changes-tab + changes-ops 13/13;断言零改动。
This commit is contained in:
@@ -69,6 +69,7 @@ import {
|
||||
type SidechatTranscriptRow,
|
||||
} from './sidechat-transcript.ts'
|
||||
import { api } from './api.ts'
|
||||
import { usePolling } from './use-polling.ts'
|
||||
import { t } from './locales.ts'
|
||||
import type { SessionScope } from './api.ts'
|
||||
import type { SidebarTab } from './state.ts'
|
||||
@@ -493,17 +494,25 @@ export function SideChatView(props: {
|
||||
}
|
||||
}, [threadId, fetchInfo])
|
||||
|
||||
// Poll while the tab is visible and the thread runs.
|
||||
// One transcript pull on every input change (attach, visibility flip,
|
||||
// run-state flip — the last one catches a thread's terminal state once it
|
||||
// stops running).
|
||||
useEffect(() => {
|
||||
if (!visible || threadId === undefined) return
|
||||
void fetchThread(threadId)
|
||||
if (!running) return
|
||||
const timer = window.setInterval(() => {
|
||||
void fetchThread(threadId)
|
||||
void fetchInfo(threadId)
|
||||
}, POLL_MS)
|
||||
return () => { window.clearInterval(timer) }
|
||||
}, [visible, threadId, running, fetchThread, fetchInfo])
|
||||
// `running` is not read here, but re-triggering this pull on run-state
|
||||
// flips is load-bearing (see above); the badge fetch rides the ticks.
|
||||
}, [visible, threadId, running, fetchThread])
|
||||
|
||||
// Poll while the tab is visible and the thread runs: transcript deltas +
|
||||
// badge refresh on a fixed cadence. Each pull self-guards (fetchThread
|
||||
// aborts its predecessor; a late settle keeps the last rows).
|
||||
const pollTick = useCallback(async (): Promise<void> => {
|
||||
if (threadId === undefined) return
|
||||
void fetchThread(threadId)
|
||||
void fetchInfo(threadId)
|
||||
}, [threadId, fetchThread, fetchInfo])
|
||||
usePolling(visible && running && threadId !== undefined, pollTick, { intervalMs: POLL_MS })
|
||||
|
||||
useEffect(() => () => { controllerRef.current?.abort() }, [])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user