返回 DeepSeek-Reasonix
sessionAvailability.ts
根目录 / desktop / frontend / src / lib / sessionAvailability.ts
1 import type { Translator } from "./i18n";
2 import type { State } from "./useController";
3 import type { RemoteSessionApi } from "./useRemoteSession";
4
5 export type SessionAvailability = {
6 kind: "ready" | "loading" | "error" | "pending";
7 source: "history" | "connection" | "runtime";
8 detail?: string;
9 };
10
11 type LocalSession = Pick<State, "meta" | "backendActivationPending" | "hydrating" | "hydrateError">;
12 type RemoteSession = Pick<RemoteSessionApi, "state" | "hydrated" | "error">;
13
14 /** Navigation, welcome and recovery must agree on the active source's readiness. */
15 export function projectSessionAvailability(input: { local?: LocalSession; remote?: RemoteSession; empty?: boolean }): SessionAvailability {
16 const { local, remote } = input;
17 if (input.empty && !remote) return { kind: "ready", source: "history" };
18 if (remote) {
19 if (["error", "serve_down", "disconnected"].includes(remote.state)) {
20 return { kind: "error", source: "connection", detail: remote.error };
21 }
22 if (!remote.hydrated && remote.error) return { kind: "error", source: "history", detail: remote.error };
23 if (remote.state !== "ready") return { kind: "loading", source: "connection" };
24 return { kind: remote.hydrated ? "ready" : "loading", source: "history" };
25 }
26 if (local?.meta?.historicalSource) return { kind: "pending", source: "runtime" };
27 if (local?.hydrateError) return { kind: "error", source: "history", detail: local.hydrateError };
28 if (local?.meta?.startupErr) return { kind: "error", source: "runtime", detail: local.meta.startupErr };
29 if (local?.hydrating) return { kind: "loading", source: "history" };
30 const ready = local?.meta?.ready === true && !local.backendActivationPending
31 && (!local.meta.runtime || local.meta.runtime.phase === "ready");
32 return { kind: ready ? "ready" : "loading", source: "runtime" };
33 }
34
35 /** The reason a disabled composer states, or none when readiness alone explains it. */
36 export function submitBlockReason(availability: SessionAvailability, t: Translator): string | undefined {
37 if (availability.kind === "pending") return t("sessionRecovery.importBeforeSend");
38 if (availability.kind !== "ready" && availability.source !== "runtime") return t("sessionRecovery.sendAfterRecovery");
39 return undefined;
40 }
41
41 lines TYPESCRIPT