mirror of
https://github.com/murashit/codex-panel.git
synced 2026-07-22 17:30:31 +00:00
Extract chat view models
This commit is contained in:
parent
42f1a0698f
commit
770c280147
3 changed files with 326 additions and 103 deletions
182
src/features/chat/view-model.ts
Normal file
182
src/features/chat/view-model.ts
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
import type { Thread } from "../../generated/app-server/v2/Thread";
|
||||
import type { RuntimeSnapshot } from "../../runtime/state";
|
||||
import {
|
||||
autoReviewActive,
|
||||
currentModel,
|
||||
currentReasoningEffort,
|
||||
currentServiceTier,
|
||||
runtimeOverrideLabel,
|
||||
runtimeSummaryLabel,
|
||||
serviceTierLabel,
|
||||
supportedReasoningEfforts,
|
||||
} from "../../runtime/state";
|
||||
import { readRuntimeConfig } from "../../runtime/config";
|
||||
import { compactContextLabel } from "../../runtime/settings";
|
||||
import { contextSummary, effectiveConfigSections, rateLimitSummary } from "../../runtime/view";
|
||||
import { getThreadTitle } from "../../domain/threads/model";
|
||||
import { connectionDiagnosticSections, diagnosticAlertLevel } from "./diagnostics";
|
||||
import type { ChatState } from "./chat-state";
|
||||
import { statusValue, usageLimitStatusLines } from "./status-lines";
|
||||
import type { ToolbarChoice, ToolbarThreadRow, ToolbarViewModel } from "./ui/toolbar";
|
||||
|
||||
export interface RuntimeSnapshotInput {
|
||||
state: ChatState;
|
||||
}
|
||||
|
||||
export interface ToolbarViewModelInput {
|
||||
state: ChatState;
|
||||
snapshot: RuntimeSnapshot;
|
||||
connected: boolean;
|
||||
turnBusy: boolean;
|
||||
vaultPath: string;
|
||||
configuredCommand: string;
|
||||
archiveConfirmThreadId: string | null;
|
||||
archiveExportEnabled: boolean;
|
||||
modelChoices: ToolbarChoice[];
|
||||
effortChoices: ToolbarChoice[];
|
||||
renameState: (threadId: string) => ToolbarThreadRow["rename"];
|
||||
}
|
||||
|
||||
export interface ConnectionDiagnosticsModelInput {
|
||||
state: ChatState;
|
||||
connected: boolean;
|
||||
configuredCommand: string;
|
||||
}
|
||||
|
||||
export function runtimeSnapshotForChatState({ state }: RuntimeSnapshotInput): RuntimeSnapshot {
|
||||
return {
|
||||
effectiveConfig: state.effectiveConfig,
|
||||
activeThreadId: state.activeThreadId,
|
||||
activeModel: state.activeModel,
|
||||
activeReasoningEffort: state.activeReasoningEffort,
|
||||
activeCollaborationMode: state.activeCollaborationMode,
|
||||
activeServiceTier: state.activeServiceTier,
|
||||
activeApprovalPolicy: state.activeApprovalPolicy,
|
||||
activeApprovalsReviewer: state.activeApprovalsReviewer,
|
||||
activePermissionProfile: state.activePermissionProfile,
|
||||
requestedModel: state.requestedModel,
|
||||
requestedReasoningEffort: state.requestedReasoningEffort,
|
||||
requestedApprovalsReviewer: state.requestedApprovalsReviewer,
|
||||
requestedCollaborationMode: state.requestedCollaborationMode,
|
||||
requestedServiceTier: state.requestedServiceTier,
|
||||
tokenUsage: state.tokenUsage,
|
||||
rateLimit: state.rateLimit,
|
||||
hasThreadTurns: state.displayItems.some((item) => item.turnId),
|
||||
availableModels: state.availableModels,
|
||||
};
|
||||
}
|
||||
|
||||
export function toolbarViewModel(input: ToolbarViewModelInput): ToolbarViewModel {
|
||||
const { state, snapshot } = input;
|
||||
const config = readRuntimeConfig(state.effectiveConfig);
|
||||
const context = contextSummary(snapshot);
|
||||
const limit = rateLimitSummary(snapshot);
|
||||
const historyOpen = state.openDetails.has("history");
|
||||
const statusPanelOpen = state.openDetails.has("status-panel");
|
||||
const runtimeOpen = state.runtimePicker !== null;
|
||||
const statusState = input.turnBusy ? "running" : input.connected ? "connected" : "offline";
|
||||
const model = currentModel(snapshot, config);
|
||||
const effort = currentReasoningEffort(snapshot, config);
|
||||
return {
|
||||
connected: input.connected,
|
||||
status: state.status,
|
||||
statusState,
|
||||
historyOpen,
|
||||
statusPanelOpen,
|
||||
runtimeOpen,
|
||||
planActive: state.requestedCollaborationMode === "plan",
|
||||
autoReviewActive: autoReviewActive(snapshot, config),
|
||||
fastActive: currentServiceTier(snapshot, config) === "fast",
|
||||
runtimeSummary: runtimeSummaryLabel(model, effort),
|
||||
runtimeTitle: `Model: ${model ?? "(Codex default)"}; Effort: ${effort ?? "(Codex default)"}`,
|
||||
runtimeEmphasized: false,
|
||||
context: context ? { ...context, label: compactContextLabel(context.percent, context.label) } : null,
|
||||
rateLimit: limit,
|
||||
configSections: effectiveConfigSections(snapshot, input.vaultPath),
|
||||
openPanel: historyOpen ? "history" : runtimeOpen ? "runtime" : statusPanelOpen ? "status" : null,
|
||||
threads: toolbarThreadRows({
|
||||
threads: state.listedThreads,
|
||||
activeThreadId: state.activeThreadId,
|
||||
turnBusy: input.turnBusy,
|
||||
archiveConfirmThreadId: input.archiveConfirmThreadId,
|
||||
archiveExportEnabled: input.archiveExportEnabled,
|
||||
renameState: input.renameState,
|
||||
}),
|
||||
modelChoices: input.modelChoices,
|
||||
effortChoices: input.effortChoices,
|
||||
connectLabel: input.connected ? "Reconnect" : "Connect",
|
||||
diagnostics: connectionDiagnosticsModel({
|
||||
state,
|
||||
connected: input.connected,
|
||||
configuredCommand: input.configuredCommand,
|
||||
}),
|
||||
diagnosticAlertLevel: diagnosticAlertLevel(state.appServerDiagnostics),
|
||||
};
|
||||
}
|
||||
|
||||
export function connectionDiagnosticsModel(input: ConnectionDiagnosticsModelInput): ReturnType<typeof connectionDiagnosticSections> {
|
||||
return connectionDiagnosticSections({
|
||||
connected: input.connected,
|
||||
configuredCommand: input.configuredCommand,
|
||||
initializeResponse: input.state.initializeResponse,
|
||||
activeThreadCreationCliVersion: input.state.activeThreadCreationCliVersion,
|
||||
diagnostics: input.state.appServerDiagnostics,
|
||||
});
|
||||
}
|
||||
|
||||
export function statusSummaryLines(state: ChatState, snapshot: RuntimeSnapshot): string[] {
|
||||
const context = contextSummary(snapshot);
|
||||
const limit = rateLimitSummary(snapshot);
|
||||
return [
|
||||
"Thread status",
|
||||
`Thread: ${state.activeThreadId ?? "(none)"}`,
|
||||
context ? context.title : "Context: not available",
|
||||
...(limit ? usageLimitStatusLines(limit) : ["Usage limits: not available"]),
|
||||
];
|
||||
}
|
||||
|
||||
export function modelStatusLines(state: ChatState, snapshot: RuntimeSnapshot, collaborationModeLabel: string): string[] {
|
||||
const config = readRuntimeConfig(state.effectiveConfig);
|
||||
return [
|
||||
`Model: ${currentModel(snapshot, config) ?? "(Codex default)"}`,
|
||||
`Override: ${runtimeOverrideLabel(state.requestedModel)}`,
|
||||
`Provider: ${statusValue(config.modelProvider, "(Codex default)")}`,
|
||||
`Effort: ${currentReasoningEffort(snapshot, config) ?? "(Codex default)"}`,
|
||||
`Mode: ${collaborationModeLabel}`,
|
||||
`Service tier: ${serviceTierLabel(snapshot, config)}`,
|
||||
];
|
||||
}
|
||||
|
||||
export function effortStatusLines(state: ChatState, snapshot: RuntimeSnapshot): string[] {
|
||||
const config = readRuntimeConfig(state.effectiveConfig);
|
||||
return [
|
||||
`Effort: ${currentReasoningEffort(snapshot, config) ?? "(Codex default)"}`,
|
||||
`Override: ${runtimeOverrideLabel(state.requestedReasoningEffort)}`,
|
||||
`Supported: ${supportedReasoningEfforts(snapshot).join(", ")}`,
|
||||
];
|
||||
}
|
||||
|
||||
function toolbarThreadRows(input: {
|
||||
threads: readonly Thread[];
|
||||
activeThreadId: string | null;
|
||||
turnBusy: boolean;
|
||||
archiveConfirmThreadId: string | null;
|
||||
archiveExportEnabled: boolean;
|
||||
renameState: (threadId: string) => ToolbarThreadRow["rename"];
|
||||
}): ToolbarThreadRow[] {
|
||||
return input.threads.map((thread) => {
|
||||
const threadId = thread.id;
|
||||
return {
|
||||
title: getThreadTitle(thread),
|
||||
threadId,
|
||||
selected: threadId === input.activeThreadId,
|
||||
disabled: input.turnBusy && threadId !== input.activeThreadId,
|
||||
canArchive: true,
|
||||
archiveConfirm: {
|
||||
active: input.archiveConfirmThreadId === threadId,
|
||||
defaultSaveMarkdown: input.archiveExportEnabled,
|
||||
},
|
||||
rename: input.renameState(threadId),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
@ -23,8 +23,6 @@ import {
|
|||
nextCollaborationMode,
|
||||
} from "../../runtime/collaboration-mode";
|
||||
import { ChatController } from "./chat-controller";
|
||||
import { connectionDiagnosticSections, diagnosticAlertLevel } from "./diagnostics";
|
||||
import { contextSummary, effectiveConfigSections, rateLimitSummary } from "../../runtime/view";
|
||||
import {
|
||||
autoReviewActive,
|
||||
currentModel,
|
||||
|
|
@ -32,20 +30,16 @@ import {
|
|||
currentServiceTier,
|
||||
requestedTurnRuntimeSettings,
|
||||
runtimeOverridePayload,
|
||||
runtimeOverrideLabel,
|
||||
runtimeSummaryLabel,
|
||||
serviceTierLabel,
|
||||
supportedReasoningEfforts,
|
||||
type RuntimeSnapshot,
|
||||
} from "../../runtime/state";
|
||||
import { readRuntimeConfig } from "../../runtime/config";
|
||||
import { sortedAvailableModels } from "../../runtime/model";
|
||||
import { compactContextLabel, modelOverrideMessage, reasoningEffortOverrideMessage } from "../../runtime/settings";
|
||||
import { modelOverrideMessage, reasoningEffortOverrideMessage } from "../../runtime/settings";
|
||||
import { executeSlashCommand as runSlashCommand, type SlashCommandExecutionResult } from "./slash-commands";
|
||||
import type { ThreadReferenceInput } from "./slash-commands";
|
||||
import { mcpStatusLines } from "./mcp-status";
|
||||
import { ChatAppServerController } from "./chat-app-server-controller";
|
||||
import { statusValue, usageLimitStatusLines } from "./status-lines";
|
||||
import { ThreadHistoryLoader } from "./thread-history";
|
||||
import { ThreadRenameController } from "./thread-rename";
|
||||
import { pendingRequestsSignature as requestStateSignature, userInputDraftKey, userInputOtherDraftKey } from "./request-state";
|
||||
|
|
@ -78,6 +72,14 @@ import type { OpenCodexPanelSnapshot } from "../../runtime/open-panel-snapshot";
|
|||
import type { SharedAppServerMetadata } from "../../runtime/shared-app-server-state";
|
||||
import { ChatThreadActionController } from "./thread-actions";
|
||||
import { unmountReactRoot } from "../../shared/ui/react-root";
|
||||
import {
|
||||
connectionDiagnosticsModel,
|
||||
effortStatusLines as buildEffortStatusLines,
|
||||
modelStatusLines as buildModelStatusLines,
|
||||
runtimeSnapshotForChatState,
|
||||
statusSummaryLines as buildStatusSummaryLines,
|
||||
toolbarViewModel as buildToolbarViewModel,
|
||||
} from "./view-model";
|
||||
import {
|
||||
ChatViewDeferredTasks,
|
||||
transitionChatConnectionLifecycle,
|
||||
|
|
@ -1338,55 +1340,19 @@ export class CodexChatView extends ItemView {
|
|||
}
|
||||
|
||||
private toolbarViewModel(): ToolbarViewModel {
|
||||
const snapshot = this.runtimeSnapshot();
|
||||
const config = readRuntimeConfig(this.state.effectiveConfig);
|
||||
const context = contextSummary(snapshot);
|
||||
const limit = rateLimitSummary(snapshot);
|
||||
const historyOpen = this.state.openDetails.has("history");
|
||||
const statusPanelOpen = this.state.openDetails.has("status-panel");
|
||||
const runtimeOpen = this.state.runtimePicker !== null;
|
||||
const statusState = this.turnBusy ? "running" : this.connection.isConnected() ? "connected" : "offline";
|
||||
const model = currentModel(snapshot, config);
|
||||
const effort = currentReasoningEffort(snapshot, config);
|
||||
const threads = this.state.listedThreads;
|
||||
return {
|
||||
return buildToolbarViewModel({
|
||||
state: this.state,
|
||||
snapshot: this.runtimeSnapshot(),
|
||||
connected: this.connection.isConnected(),
|
||||
status: this.state.status,
|
||||
statusState,
|
||||
historyOpen,
|
||||
statusPanelOpen,
|
||||
runtimeOpen,
|
||||
planActive: this.state.requestedCollaborationMode === "plan",
|
||||
autoReviewActive: autoReviewActive(snapshot, config),
|
||||
fastActive: currentServiceTier(snapshot, config) === "fast",
|
||||
runtimeSummary: runtimeSummaryLabel(model, effort),
|
||||
runtimeTitle: `Model: ${model ?? "(Codex default)"}; Effort: ${effort ?? "(Codex default)"}`,
|
||||
runtimeEmphasized: false,
|
||||
context: context ? { ...context, label: compactContextLabel(context.percent, context.label) } : null,
|
||||
rateLimit: limit,
|
||||
configSections: effectiveConfigSections(snapshot, this.plugin.vaultPath),
|
||||
openPanel: historyOpen ? "history" : runtimeOpen ? "runtime" : statusPanelOpen ? "status" : null,
|
||||
threads: threads.map((thread) => {
|
||||
const threadId = thread.id;
|
||||
return {
|
||||
title: getThreadTitle(thread),
|
||||
threadId,
|
||||
selected: threadId === this.state.activeThreadId,
|
||||
disabled: this.turnBusy && threadId !== this.state.activeThreadId,
|
||||
canArchive: true,
|
||||
archiveConfirm: {
|
||||
active: this.archiveConfirmThreadId === threadId,
|
||||
defaultSaveMarkdown: this.plugin.settings.archiveExportEnabled,
|
||||
},
|
||||
rename: this.threadRename.editState(threadId),
|
||||
};
|
||||
}),
|
||||
turnBusy: this.turnBusy,
|
||||
vaultPath: this.plugin.vaultPath,
|
||||
configuredCommand: this.plugin.settings.codexPath,
|
||||
archiveConfirmThreadId: this.archiveConfirmThreadId,
|
||||
archiveExportEnabled: this.plugin.settings.archiveExportEnabled,
|
||||
modelChoices: this.modelToolbarChoices(),
|
||||
effortChoices: this.effortToolbarChoices(),
|
||||
connectLabel: this.connection.isConnected() ? "Reconnect" : "Connect",
|
||||
diagnostics: this.connectionDiagnosticSections(),
|
||||
diagnosticAlertLevel: diagnosticAlertLevel(this.state.appServerDiagnostics),
|
||||
};
|
||||
renameState: (threadId) => this.threadRename.editState(threadId),
|
||||
});
|
||||
}
|
||||
|
||||
private async reconnectFromToolbar(): Promise<void> {
|
||||
|
|
@ -1540,47 +1506,22 @@ export class CodexChatView extends ItemView {
|
|||
}
|
||||
|
||||
private statusSummaryLines(): string[] {
|
||||
const snapshot = this.runtimeSnapshot();
|
||||
const context = contextSummary(snapshot);
|
||||
const limit = rateLimitSummary(snapshot);
|
||||
return [
|
||||
"Thread status",
|
||||
`Thread: ${this.state.activeThreadId ?? "(none)"}`,
|
||||
context ? context.title : "Context: not available",
|
||||
...(limit ? usageLimitStatusLines(limit) : ["Usage limits: not available"]),
|
||||
];
|
||||
return buildStatusSummaryLines(this.state, this.runtimeSnapshot());
|
||||
}
|
||||
|
||||
private modelStatusLines(): string[] {
|
||||
const snapshot = this.runtimeSnapshot();
|
||||
const config = readRuntimeConfig(this.state.effectiveConfig);
|
||||
return [
|
||||
`Model: ${currentModel(snapshot, config) ?? "(Codex default)"}`,
|
||||
`Override: ${runtimeOverrideLabel(this.state.requestedModel)}`,
|
||||
`Provider: ${statusValue(config.modelProvider, "(Codex default)")}`,
|
||||
`Effort: ${currentReasoningEffort(snapshot, config) ?? "(Codex default)"}`,
|
||||
`Mode: ${this.collaborationModeLabel()}`,
|
||||
`Service tier: ${serviceTierLabel(snapshot, config)}`,
|
||||
];
|
||||
return buildModelStatusLines(this.state, this.runtimeSnapshot(), this.collaborationModeLabel());
|
||||
}
|
||||
|
||||
private effortStatusLines(): string[] {
|
||||
const snapshot = this.runtimeSnapshot();
|
||||
const config = readRuntimeConfig(this.state.effectiveConfig);
|
||||
return [
|
||||
`Effort: ${currentReasoningEffort(snapshot, config) ?? "(Codex default)"}`,
|
||||
`Override: ${runtimeOverrideLabel(this.state.requestedReasoningEffort)}`,
|
||||
`Supported: ${supportedReasoningEfforts(snapshot).join(", ")}`,
|
||||
];
|
||||
return buildEffortStatusLines(this.state, this.runtimeSnapshot());
|
||||
}
|
||||
|
||||
private connectionDiagnosticSections() {
|
||||
return connectionDiagnosticSections({
|
||||
return connectionDiagnosticsModel({
|
||||
state: this.state,
|
||||
connected: this.connection.isConnected(),
|
||||
configuredCommand: this.plugin.settings.codexPath,
|
||||
initializeResponse: this.state.initializeResponse,
|
||||
activeThreadCreationCliVersion: this.state.activeThreadCreationCliVersion,
|
||||
diagnostics: this.state.appServerDiagnostics,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1612,26 +1553,7 @@ export class CodexChatView extends ItemView {
|
|||
}
|
||||
|
||||
private runtimeSnapshotForState(state: ChatState): RuntimeSnapshot {
|
||||
return {
|
||||
effectiveConfig: state.effectiveConfig,
|
||||
activeThreadId: state.activeThreadId,
|
||||
activeModel: state.activeModel,
|
||||
activeReasoningEffort: state.activeReasoningEffort,
|
||||
activeCollaborationMode: state.activeCollaborationMode,
|
||||
activeServiceTier: state.activeServiceTier,
|
||||
activeApprovalPolicy: state.activeApprovalPolicy,
|
||||
activeApprovalsReviewer: state.activeApprovalsReviewer,
|
||||
activePermissionProfile: state.activePermissionProfile,
|
||||
requestedModel: state.requestedModel,
|
||||
requestedReasoningEffort: state.requestedReasoningEffort,
|
||||
requestedApprovalsReviewer: state.requestedApprovalsReviewer,
|
||||
requestedCollaborationMode: state.requestedCollaborationMode,
|
||||
requestedServiceTier: state.requestedServiceTier,
|
||||
tokenUsage: state.tokenUsage,
|
||||
rateLimit: state.rateLimit,
|
||||
hasThreadTurns: state.displayItems.some((item) => item.turnId),
|
||||
availableModels: state.availableModels,
|
||||
};
|
||||
return runtimeSnapshotForChatState({ state });
|
||||
}
|
||||
|
||||
private pendingRequestMessageNode() {
|
||||
|
|
|
|||
119
tests/features/chat/view-model.test.ts
Normal file
119
tests/features/chat/view-model.test.ts
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { createAppServerDiagnostics } from "../../../src/app-server/compatibility";
|
||||
import { createChatState } from "../../../src/features/chat/chat-state";
|
||||
import {
|
||||
effortStatusLines,
|
||||
modelStatusLines,
|
||||
runtimeSnapshotForChatState,
|
||||
statusSummaryLines,
|
||||
toolbarViewModel,
|
||||
} from "../../../src/features/chat/view-model";
|
||||
import type { Model } from "../../../src/generated/app-server/v2/Model";
|
||||
import type { Thread } from "../../../src/generated/app-server/v2/Thread";
|
||||
import type { ConfigReadResponse } from "../../../src/generated/app-server/v2/ConfigReadResponse";
|
||||
|
||||
describe("chat view model", () => {
|
||||
it("builds toolbar rows from immutable chat state snapshots", () => {
|
||||
const state = createChatState();
|
||||
state.activeThreadId = "thread-1";
|
||||
state.listedThreads = [threadFixture("thread-1", "Active"), threadFixture("thread-2", "Other")];
|
||||
state.turnLifecycle = { kind: "running", turnId: "turn" };
|
||||
state.openDetails = new Set(["history"]);
|
||||
state.effectiveConfig = effectiveConfigFixture({ model: "gpt-5.5", model_reasoning_effort: "high" });
|
||||
state.appServerDiagnostics = createAppServerDiagnostics();
|
||||
|
||||
const model = toolbarViewModel({
|
||||
state,
|
||||
snapshot: runtimeSnapshotForChatState({ state }),
|
||||
connected: true,
|
||||
turnBusy: true,
|
||||
vaultPath: "/vault",
|
||||
configuredCommand: "codex",
|
||||
archiveConfirmThreadId: "thread-2",
|
||||
archiveExportEnabled: true,
|
||||
modelChoices: [{ label: "gpt-5.5", selected: true, onClick: () => undefined }],
|
||||
effortChoices: [{ label: "high", selected: true, onClick: () => undefined }],
|
||||
renameState: (threadId) => (threadId === "thread-1" ? { draft: "Active", generating: false } : null),
|
||||
});
|
||||
|
||||
expect(model.statusState).toBe("running");
|
||||
expect(model.openPanel).toBe("history");
|
||||
expect(model.threads).toMatchObject([
|
||||
{ threadId: "thread-1", title: "Active", selected: true, disabled: false, rename: { draft: "Active" } },
|
||||
{ threadId: "thread-2", title: "Other", selected: false, disabled: true, archiveConfirm: { active: true } },
|
||||
]);
|
||||
expect(model.modelChoices).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("builds slash-command status lines from chat state", () => {
|
||||
const state = createChatState();
|
||||
state.activeThreadId = "thread-1";
|
||||
state.effectiveConfig = effectiveConfigFixture({
|
||||
model: "gpt-5.5",
|
||||
model_provider: "openai",
|
||||
model_reasoning_effort: "high",
|
||||
service_tier: "fast",
|
||||
});
|
||||
state.availableModels = [modelFixture("gpt-5.5")];
|
||||
const snapshot = runtimeSnapshotForChatState({ state });
|
||||
|
||||
expect(statusSummaryLines(state, snapshot)[1]).toBe("Thread: thread-1");
|
||||
expect(modelStatusLines(state, snapshot, "Default")).toContain("Model: gpt-5.5");
|
||||
expect(modelStatusLines(state, snapshot, "Default")).toContain("Mode: Default");
|
||||
expect(effortStatusLines(state, snapshot)).toContain("Supported: high");
|
||||
});
|
||||
});
|
||||
|
||||
function effectiveConfigFixture(config: Record<string, unknown>): ConfigReadResponse {
|
||||
return {
|
||||
config: config as ConfigReadResponse["config"],
|
||||
origins: {},
|
||||
layers: null,
|
||||
};
|
||||
}
|
||||
|
||||
function threadFixture(id: string, name: string): Thread {
|
||||
return {
|
||||
id,
|
||||
sessionId: "session",
|
||||
forkedFromId: null,
|
||||
preview: "",
|
||||
ephemeral: false,
|
||||
modelProvider: "openai",
|
||||
createdAt: 1,
|
||||
updatedAt: 1,
|
||||
status: { type: "idle" },
|
||||
path: null,
|
||||
cwd: "/vault",
|
||||
cliVersion: "0.0.0",
|
||||
source: "appServer",
|
||||
threadSource: null,
|
||||
agentNickname: null,
|
||||
agentRole: null,
|
||||
gitInfo: null,
|
||||
name,
|
||||
turns: [],
|
||||
};
|
||||
}
|
||||
|
||||
function modelFixture(model: string): Model {
|
||||
return {
|
||||
id: model,
|
||||
model,
|
||||
upgrade: null,
|
||||
upgradeInfo: null,
|
||||
availabilityNux: null,
|
||||
displayName: model,
|
||||
description: "",
|
||||
hidden: false,
|
||||
supportedReasoningEfforts: [{ reasoningEffort: "high", description: "" }],
|
||||
defaultReasoningEffort: "high",
|
||||
inputModalities: [],
|
||||
supportsPersonality: false,
|
||||
additionalSpeedTiers: [],
|
||||
serviceTiers: [],
|
||||
defaultServiceTier: null,
|
||||
isDefault: true,
|
||||
};
|
||||
}
|
||||
Loading…
Reference in a new issue