refactor(tasks): 后台任务改读宿主客户端 jobs 服务,删除自建三条路由
- 新增 src/client/jobs-client.ts:结构探测 ctx.jobs(watchRows / observe / state / kill),引用计数的按会话 roster 订阅、只观测展开的那一行、 跨树去重(无主任务归到承载它的被观测会话,树外 owner 丢弃)。 - 抽屉与输出浮窗改读该服务:行来自推送 roster(状态 / 时长 / owner / 进度), 输出面换 TerminalBlock 显示宿主为观察者流的保留输出(gapBefore → 截断提示、 error → 失败提示),kill 走 jobs.kill(owner, jobId),两击确认不变。 - 自动激活(use-host-feeds)改骑同一条推送 roster;detectNewJob 增加 「观测起点时钟」参数,避免「页面打开时已在跑的任务」被当成新工作。 - 删除 src/jobs-routes.ts(+ tests/jobs-routes.spec.ts)、index.ts 的三条路由、 api.jobsList/jobOutput/jobKill 与 JobOutputResult、context-types 的 SidebarJobsService(换成 SidebarClientJobsService/SidebarJobsSnapshot/ SidebarObservedJob 镜像,SidebarJobView 补 owner/progress)、 页面里的 jobs.list 轮询与 collectTreeJobs。 - 三个 spec 改用假 ctx.jobs 服务(jobs-view 14 例 / 自动激活 12 例 / 页面 20 例):观测只在展开行、切换与关闭释放观测、watch 隐藏时不建立、 卸载时全部释放、无服务时不渲染任务面。 验证:typecheck / lint 通过;pnpm test 1240 passed / 9 skipped;pnpm build + pack 通过。 (cherry picked from commit 7d9b82e73190218f05910433ed520cb90e4d4ab2)
This commit is contained in:
@@ -41,7 +41,6 @@ import { launchExternal } from './open-external.ts'
|
||||
import * as git from './git.ts'
|
||||
import { SettingsConflictError } from '@deepseek-ai/dsh-settings'
|
||||
import { AgentOpenRegistry, registerOpenTool, type AgentOpenRequest } from './agent-opens.ts'
|
||||
import { buildJobsApi, type SidebarJobsRoutes } from './jobs-routes.ts'
|
||||
import { buildSubagentLiveApi, type SidebarSubagentLiveRoutes } from './subagent-live-route.ts'
|
||||
import { buildTeamsApi, type SidebarTeamsRoutes } from './team-routes.ts'
|
||||
import { buildWorkflowsApi, type SidebarWorkflowRoutes } from './workflow-routes.ts'
|
||||
@@ -264,12 +263,6 @@ function buildApi(
|
||||
const requested = typeof record?.worktree === 'string' && record.worktree !== '' ? record.worktree : undefined
|
||||
return { sessionId: base.sessionId, cwd: await git.resolveWorktree(base.cwd, requested) }
|
||||
}
|
||||
// Background jobs: the LIST rides the harness's `session/jobs` push
|
||||
// mirror, so these routes only replay output the model has read (from the
|
||||
// session's own event log — no DSH source is touched, the model's
|
||||
// job_output cursor is never consumed) and kill (the registry's stock
|
||||
// API). A deployment without the jobs registry downgrades kill to a 503.
|
||||
const jobsApi: SidebarJobsRoutes = buildJobsApi(ctx, resolved.readLimit)
|
||||
// Subagent live previews: one batch request instead of N per-child
|
||||
// `subagents.history` calls. The route degrades to a 503 when the host
|
||||
// subagent runtime is absent (the page has no topology to show anyway).
|
||||
@@ -484,16 +477,6 @@ function buildApi(
|
||||
const window = filtered.length > CHANGES_EVENTS_CAP ? filtered.slice(filtered.length - CHANGES_EVENTS_CAP) : filtered
|
||||
return { events: window, lastSeq: window.at(-1)?.seq ?? afterSeq }
|
||||
},
|
||||
// Background jobs: list the caller's own jobs, read one job's output (a
|
||||
// REPLAY of what the model has read so far, from the owner session's
|
||||
// event log — the model's job_output cursor is never touched, so the
|
||||
// human pane can never steal the agent's bytes), and kill one job. The
|
||||
// list route exists because DSH 0.1.7 deleted the session/jobs push
|
||||
// mirror the Tasks page used to read. Kill is fenced to the owning
|
||||
// session by the jobs registry.
|
||||
'jobs.list': (payload) => jobsApi.list(payload),
|
||||
'jobs.output': (payload) => jobsApi.output(payload),
|
||||
'jobs.kill': (payload) => jobsApi.kill(payload),
|
||||
// Subagent live previews: one batch request per refresh; the route folds
|
||||
// the newest text/tool activity of every running child in the tree.
|
||||
'subagents.live': (payload) => subagentLiveApi.live(payload),
|
||||
|
||||
Reference in New Issue
Block a user