Files
codex-app-server/cloud/console-react/src/context.ts
T
host e5b6c45c83 console: 任务列表服务端分页 + 控制台分页面签
任务列表分页(服务端 + 前端):
- GET /tasks 新增 limit(1..100,非法回 400)、offset、
  order=desc、status/executor/q 服务端过滤;回 total(过滤后
  计数)与 status_counts(全项目统计,不受过滤与分页影响,
  数据卡片不再把当前页当成全项目);无 limit 时旧行为不变
  (全量、正序,协调子任务与旧调用不受影响)。
- 前端每页 20 条、最新在前,上一页/下一页 + 页码;筛选与
  搜索改服务端过滤(搜索防抖 300ms),切筛选/切项目/派发
  后回第 1 页,10 秒刷新与刷新按钮停在当前页;新测试
  test_task_list_pagination.py 5 项。

分页面签:
- 顶栏锚点导航改成 5 个页签:工作台(派发 + 任务列表 +
  对话 + 详情)、项目(项目 + 成员)、环境与 Workers、
  技能与自动化(技能 + 自动化 + 分诊)、管理与 Key;
  数据卡片仍在页签上方常驻。选中任务存在 App 层 store
  里,切页不丢,回来仍是同一任务、10 秒刷新续同步;
  页签同步到 location.hash(#tab-workbench 等),刷新与
  分享链接落在同一页签;窄屏工作台仍保持派发在前的顺序。
- 工作台页签仍是左(任务)右(派发/对话/详情)两栏,
  沿用等高内部滚动规则;其它页签单列堆叠。
2026-10-30 02:25:48 +08:00

51 lines
4.4 KiB
TypeScript

import { createContext, useContext } from "react";
import type { Automation, Env, Member, Project, Review, Approval, Followup, PeerMessage, Task, TaskCost, ThreadInfo, Triage, Worker, SkillItem, McpServer, Agent, DispatchBody, ReviewBody, TraceEntry, ChatHistory } from "./api/types";
export interface ConsoleCtx {
keySaved: boolean; keyState: string;
saveKeyInput: (v: string) => void; clearKeyInput: () => void;
quotaText: string;
healthText: string; refreshHealth: () => void;
adminGate: string; adminBody: boolean; adminResult: string; adminUserId: string; setAdminUserId: (v: string) => void;
adminQuota: () => void; adminSweep: () => void; adminBackup: () => void;
projects: Project[]; projectId: string; projectMsg: string;
selectProject: (id: string) => void; refreshProjects: () => void;
createProject: (name: string, repo: string) => Promise<void>;
githubRepos: Array<{ clone_url: string; repo_full_name: string }>;
workers: Worker[] | null; workersSummary: string; workersError: string; refreshWorkers: () => void;
members: Member[]; memberMsg: string; memberError: string; refreshMembers: () => void; inviteMember: (raw: string, role: string) => Promise<void>; changeMemberRole: (uid: string, role: string) => Promise<void>;
skills: SkillItem[]; apps: SkillItem[]; mcpServers: McpServer[]; skillMsg: string; skillError: string; mcpMsg: string; mcpOauthMsg: string; mcpOauthBox: string;
refreshSkills: () => void; reloadMcp: () => void; mcpOauth: (name: string) => Promise<void>;
envs: Env[]; envCount: string; envMsg: string; envRepoLine: string; envRepoBar: boolean; envRepoMsg: string; envSelect: string; setEnvSelect: (v: string) => void;
refreshEnvs: () => void; createEnv: (name: string, branch: string, executor: string) => Promise<void>; archiveEnv: (id: string) => Promise<void>; saveEnvRepo: (repo: string) => Promise<void>;
models: string[]; modelCustomVisible: boolean;
tasks: Task[]; taskCountText: string; taskError: string; refreshTasks: () => void;
statusFilter: string; setStatusFilter: (v: string) => void; executorFilter: string; setExecutorFilter: (v: string) => void; searchText: string; setSearchText: (v: string) => void;
filteredTasks: Task[];
taskPage: number; taskTotalPages: number; taskTotal: number; taskStatusCounts: Record<string, number>; goToTaskPage: (p: number) => void;
currentTask: Task | null; detailBody: string; actionMsg: string; actionReasons: string;
showDetail: (id: string) => void; doAction: (kind: string) => void; taskCost: () => void; costBox: string; costSummary: TaskCost | null | undefined;
forkVisible: boolean; setForkVisible: (v: boolean) => void; forkTask: (msg: string) => Promise<void>; forkMsg: string;
// Continue input is ContinuePanel (ChatInput); its send path is sendChatMessage below.
coordChildren: Task[]; coordText: string; agents: Agent[]; agentsNote: string;
reviews: Review[]; reviewMsg: string; reviewError: string; refreshReviews: () => void; postReview: (body: ReviewBody) => Promise<void>; submitFindings: (id: string) => void;
traceEntries: TraceEntry[]; traceNote: string; traceDone: string; traceKind: string; setTraceKind: (v: string) => void; downloadTrace: () => void; traceMsg: string;
sendChatMessage: (text: string) => Promise<void>; chatMsg: string;
chatHistory: ChatHistory | null;
followups: Followup[];
approvals: Approval[]; approvalMsg: string; refreshApprovals: () => void; decideApproval: (id: string, decision: string) => void;
peerMessages: PeerMessage[]; peerMsg: string; postPeer: (mode: string, target: string, text: string) => Promise<void>;
automations: Automation[]; autoMsg: string; refreshAutomations: () => void; createAutomation: (name: string, prompt: string, interval: string, repo: string) => Promise<void>; cancelAutomation: (id: string) => void;
triage: Triage | null; triageError: string; refreshTriage: () => void;
threadText: string; threadGateNote: string; threadMsg: string; threadList: ThreadInfo[]; threadAction: (kind: string, name: string) => void;
dispatch: (body: DispatchBody, atts: Array<{ path: string; file: File }>) => Promise<string>; dispatchMsg: string;
refreshAll: (selectFocused: boolean) => void; refreshSlow: () => void; refreshStamp: string;
}
export const ConsoleContext = createContext<ConsoleCtx | null>(null);
export function useConsole(): ConsoleCtx {
const c = useContext(ConsoleContext);
if (!c) throw new Error("ConsoleContext missing");
return c;
}