diff --git a/packages/cli/src/commands/handlers/auth/list.ts b/packages/cli/src/commands/handlers/auth/list.ts
index 7441b77232..feb5f75113 100644
--- a/packages/cli/src/commands/handlers/auth/list.ts
+++ b/packages/cli/src/commands/handlers/auth/list.ts
@@ -3,7 +3,7 @@ import { Effect, Option } from "effect"
import { Commands } from "../../commands"
import { Runtime } from "../../../framework/runtime"
import { createClient, loadIntegrations } from "./shared"
-import { errorMessage } from "../../../ui/prompt"
+import { errorMessage } from "../../../util/error"
export default Runtime.handler(Commands.commands.auth.commands.list, (input) =>
list(input).pipe(
diff --git a/packages/cli/src/commands/handlers/console/login.ts b/packages/cli/src/commands/handlers/console/login.ts
index 0964f76dfb..a0c767c718 100644
--- a/packages/cli/src/commands/handlers/console/login.ts
+++ b/packages/cli/src/commands/handlers/console/login.ts
@@ -6,6 +6,7 @@ import { Commands } from "../../commands"
import { Runtime } from "../../../framework/runtime"
import { ServiceConfig } from "../../../services/service-config"
import { createTimelineHost, type TimelineHost } from "../../../ui/timeline"
+import { errorMessage } from "../../../util/error"
const integrationID = "opencode"
const location = { directory: process.cwd() }
@@ -24,9 +25,9 @@ export default Runtime.handler(
if (Exit.isSuccess(exit)) return
const cancelled = timeline.signal.aborted
- yield* request(() => timeline.failure(cancelled ? "Authorization cancelled" : errorMessage(exit.cause))).pipe(
- Effect.ignore,
- )
+ yield* request(() =>
+ timeline.failure(cancelled ? "Authorization cancelled" : errorMessage(Cause.squash(exit.cause))),
+ ).pipe(Effect.ignore)
process.exitCode = cancelled ? 130 : 1
}),
)
@@ -107,12 +108,3 @@ function request(task: (signal: AbortSignal) => Promise) {
function required(value: A | null | undefined, message: string) {
return value === null || value === undefined ? Effect.fail(new Error(message)) : Effect.succeed(value)
}
-
-function errorMessage(cause: Cause.Cause) {
- const error = Cause.squash(cause)
- if (error instanceof Error) return error.message
- if (typeof error === "object" && error !== null && "message" in error && typeof error.message === "string") {
- return error.message
- }
- return String(error)
-}
diff --git a/packages/cli/src/commands/handlers/debug/agents.ts b/packages/cli/src/commands/handlers/debug/agents.ts
index c178e90b45..4d81e6c8b2 100644
--- a/packages/cli/src/commands/handlers/debug/agents.ts
+++ b/packages/cli/src/commands/handlers/debug/agents.ts
@@ -9,9 +9,7 @@ import { ServiceConfig } from "../../../services/service-config"
export default Runtime.handler(
Commands.commands.debug.commands.agents,
Effect.fn("cli.debug.agents")(function* () {
- const options = yield* ServiceConfig.options()
- const found = yield* Service.discover(options)
- const endpoint = found ?? (yield* Service.ensure(options))
+ const endpoint = yield* Service.ensure(yield* ServiceConfig.options())
const client = OpenCode.make({ baseUrl: endpoint.url, headers: Service.headers(endpoint) })
const response = yield* Effect.promise(() => client.agent.list({ location: { directory: process.cwd() } }))
process.stdout.write(
diff --git a/packages/cli/src/commands/handlers/debug/config.ts b/packages/cli/src/commands/handlers/debug/config.ts
index d6ff940e76..7dd822ce84 100644
--- a/packages/cli/src/commands/handlers/debug/config.ts
+++ b/packages/cli/src/commands/handlers/debug/config.ts
@@ -9,9 +9,7 @@ import { ServiceConfig } from "../../../services/service-config"
export default Runtime.handler(
Commands.commands.debug.commands.config,
Effect.fn("cli.debug.config")(function* () {
- const options = yield* ServiceConfig.options()
- const found = yield* Service.discover(options)
- const endpoint = found ?? (yield* Service.ensure(options))
+ const endpoint = yield* Service.ensure(yield* ServiceConfig.options())
const client = OpenCode.make({ baseUrl: endpoint.url, headers: Service.headers(endpoint) })
const entries = yield* Effect.promise(() => client.config.get({ location: { directory: process.cwd() } }))
process.stdout.write(JSON.stringify(entries, null, 2) + EOL)
diff --git a/packages/cli/src/commands/handlers/export.ts b/packages/cli/src/commands/handlers/export.ts
index abeb2fb8ba..f8fbff092e 100644
--- a/packages/cli/src/commands/handlers/export.ts
+++ b/packages/cli/src/commands/handlers/export.ts
@@ -6,7 +6,7 @@ import { EOL } from "node:os"
import { Commands } from "../commands"
import { Runtime } from "../../framework/runtime"
import { ServerConnection } from "../../services/server-connection"
-import { errorMessage } from "../../ui/prompt"
+import { errorMessage } from "../../util/error"
export default Runtime.handler(
Commands.commands.export,
diff --git a/packages/cli/src/commands/handlers/mcp/auth.ts b/packages/cli/src/commands/handlers/mcp/auth.ts
index cf4f216f92..0d7fd3afd4 100644
--- a/packages/cli/src/commands/handlers/mcp/auth.ts
+++ b/packages/cli/src/commands/handlers/mcp/auth.ts
@@ -17,9 +17,7 @@ const location = { directory: process.cwd() }
export default Runtime.handler(
Commands.commands.mcp.commands.auth,
Effect.fn("cli.mcp.auth")(function* (input) {
- const options = yield* ServiceConfig.options()
- const found = yield* Service.discover(options)
- const endpoint = found ?? (yield* Service.ensure(options))
+ const endpoint = yield* Service.ensure(yield* ServiceConfig.options())
const client = OpenCode.make({ baseUrl: endpoint.url, headers: Service.headers(endpoint) })
const integration = yield* resolveIntegration(client, input.name, location)
diff --git a/packages/cli/src/commands/handlers/mcp/list.ts b/packages/cli/src/commands/handlers/mcp/list.ts
index 9572d3e1e7..d26e24e3d1 100644
--- a/packages/cli/src/commands/handlers/mcp/list.ts
+++ b/packages/cli/src/commands/handlers/mcp/list.ts
@@ -9,9 +9,7 @@ import { ServiceConfig } from "../../../services/service-config"
export default Runtime.handler(
Commands.commands.mcp.commands.list,
Effect.fn("cli.mcp.list")(function* () {
- const options = yield* ServiceConfig.options()
- const found = yield* Service.discover(options)
- const endpoint = found ?? (yield* Service.ensure(options))
+ const endpoint = yield* Service.ensure(yield* ServiceConfig.options())
const client = OpenCode.make({ baseUrl: endpoint.url, headers: Service.headers(endpoint) })
const response = yield* Effect.promise(() => client.mcp.list({ location: { directory: process.cwd() } }))
const servers = response.data.toSorted((a, b) => a.name.localeCompare(b.name))
diff --git a/packages/cli/src/commands/handlers/mcp/logout.ts b/packages/cli/src/commands/handlers/mcp/logout.ts
index 47dc3052a6..6935bc6a8a 100644
--- a/packages/cli/src/commands/handlers/mcp/logout.ts
+++ b/packages/cli/src/commands/handlers/mcp/logout.ts
@@ -12,9 +12,7 @@ const location = { directory: process.cwd() }
export default Runtime.handler(
Commands.commands.mcp.commands.logout,
Effect.fn("cli.mcp.logout")(function* (input) {
- const options = yield* ServiceConfig.options()
- const found = yield* Service.discover(options)
- const endpoint = found ?? (yield* Service.ensure(options))
+ const endpoint = yield* Service.ensure(yield* ServiceConfig.options())
const client = OpenCode.make({ baseUrl: endpoint.url, headers: Service.headers(endpoint) })
const integration = yield* resolveIntegration(client, input.name, location)
diff --git a/packages/cli/src/commands/handlers/plugin/list.ts b/packages/cli/src/commands/handlers/plugin/list.ts
index 35b6c3b4ad..a8538cd961 100644
--- a/packages/cli/src/commands/handlers/plugin/list.ts
+++ b/packages/cli/src/commands/handlers/plugin/list.ts
@@ -12,9 +12,7 @@ import { discoverTuiPlugins, tuiPluginDirectories } from "@opencode-ai/tui/plugi
export default Runtime.handler(
Commands.commands.plugin.commands.list,
Effect.fn("cli.plugin.list")(function* (input) {
- const options = yield* ServiceConfig.options()
- const found = yield* Service.discover(options)
- const endpoint = found ?? (yield* Service.ensure(options))
+ const endpoint = yield* Service.ensure(yield* ServiceConfig.options())
const client = OpenCode.make({ baseUrl: endpoint.url, headers: Service.headers(endpoint) })
const response = yield* Effect.promise(() => client.plugin.list({ location: { directory: process.cwd() } }))
const config = yield* Config.Service
diff --git a/packages/cli/src/run/run.ts b/packages/cli/src/run/run.ts
index ff1dd57f3e..737738db7c 100644
--- a/packages/cli/src/run/run.ts
+++ b/packages/cli/src/run/run.ts
@@ -10,6 +10,7 @@ import { toolInlineInfo } from "@opencode-ai/tui/mini/tool"
import { runNonInteractivePrompt } from "./noninteractive"
import { UI } from "./ui"
import { Env } from "../env"
+import { errorMessage } from "../util/error"
export type RunCommandInput = {
server: ServerConnection.Resolved
@@ -243,13 +244,6 @@ async function renderToolError(part: SessionMessageAssistantTool, directory: str
UI.println(UI.Style.TEXT_NORMAL + "✗", UI.Style.TEXT_NORMAL + `${info.title} failed`)
}
-function errorMessage(error: unknown) {
- if (error instanceof Error) return error.message
- if (typeof error === "object" && error !== null && "message" in error && typeof error.message === "string")
- return error.message
- return String(error)
-}
-
/** @internal Used by the V1 command boundary before a Session exists. */
export function reportRunError(input: Pick, message: string, sessionID?: string) {
process.exitCode = 1
diff --git a/packages/cli/src/ui/prompt.ts b/packages/cli/src/ui/prompt.ts
index 8482c16d99..f702113bac 100644
--- a/packages/cli/src/ui/prompt.ts
+++ b/packages/cli/src/ui/prompt.ts
@@ -1,5 +1,6 @@
import { cancel, isCancel, log, outro } from "@clack/prompts"
import { Effect } from "effect"
+import { errorMessage } from "../util/error"
const cancelled = Symbol("cancelled")
@@ -38,11 +39,3 @@ export function handlePromptErrors(effect: Effect.Effect) {
),
)
}
-
-export function errorMessage(error: unknown) {
- if (error instanceof Error) return error.message
- if (typeof error === "object" && error !== null && "message" in error && typeof error.message === "string") {
- return error.message
- }
- return String(error)
-}
diff --git a/packages/cli/src/util/error.ts b/packages/cli/src/util/error.ts
new file mode 100644
index 0000000000..e70f201c30
--- /dev/null
+++ b/packages/cli/src/util/error.ts
@@ -0,0 +1,7 @@
+export function errorMessage(error: unknown) {
+ if (error instanceof Error) return error.message
+ if (typeof error === "object" && error !== null && "message" in error && typeof error.message === "string") {
+ return error.message
+ }
+ return String(error)
+}
diff --git a/packages/cli/test/debug-config.test.ts b/packages/cli/test/debug-config.test.ts
index e3dacd630c..307275e9ba 100644
--- a/packages/cli/test/debug-config.test.ts
+++ b/packages/cli/test/debug-config.test.ts
@@ -33,12 +33,14 @@ describe("debug config command", () => {
},
]
let requested: URL | undefined
+ let healthProbes = 0
const authorization: Array = []
const server = Bun.serve({
port: 0,
fetch(request) {
const url = new URL(request.url)
if (url.pathname === "/api/health") {
+ healthProbes += 1
return Response.json({ healthy: true, version: OPENCODE_VERSION, pid: process.pid })
}
requested = url
@@ -60,6 +62,7 @@ describe("debug config command", () => {
expect(requested?.pathname).toBe("/api/config")
expect(requested?.searchParams.get("location[directory]")).toBe(project)
expect(authorization).toEqual([`Basic ${btoa("opencode:secret")}`])
+ expect(healthProbes).toBe(1)
} finally {
server.stop(true)
await fs.rm(root, { recursive: true, force: true })
diff --git a/packages/cli/test/import-boundaries.test.ts b/packages/cli/test/import-boundaries.test.ts
index 3634aa5aed..79773cd145 100644
--- a/packages/cli/test/import-boundaries.test.ts
+++ b/packages/cli/test/import-boundaries.test.ts
@@ -35,7 +35,9 @@ describe("CLI frontend import boundaries", () => {
test("keeps run and Mini on separate evaluation graphs", async () => {
const run = await bundleInputs("packages/cli/src/commands/handlers/run.ts")
expect(run).toContain("packages/cli/src/run/run.ts")
+ expect(run).toContain("packages/cli/src/util/error.ts")
expect(run).toContain("packages/tui/src/mini/tool.ts")
+ expect(run).not.toContain("packages/cli/src/ui/prompt.ts")
expect(run).not.toContain("packages/tui/src/mini/runtime.ts")
expect(run).not.toContain("packages/tui/src/mini/runtime.lifecycle.ts")
expect(run).not.toContain("packages/tui/src/mini/footer.ts")
diff --git a/packages/tui/src/context/theme.tsx b/packages/tui/src/context/theme.tsx
index 677ff9245c..806cd35fb2 100644
--- a/packages/tui/src/context/theme.tsx
+++ b/packages/tui/src/context/theme.tsx
@@ -291,8 +291,7 @@ const themeContext = createSimpleContext({
}, delay),
)
}
- let unsubscribeRefresh: (() => void) | undefined
- unsubscribeRefresh = themes.subscribeRefresh?.(refresh)
+ const unsubscribeRefresh = themes.subscribeRefresh?.(refresh)
onCleanup(() => {
renderer.off(CliRenderEvents.THEME_MODE, handle)
diff --git a/packages/tui/src/mini/footer.ts b/packages/tui/src/mini/footer.ts
index cb2434c842..c141905806 100644
--- a/packages/tui/src/mini/footer.ts
+++ b/packages/tui/src/mini/footer.ts
@@ -786,22 +786,8 @@ export class RunFooter implements FooterApi {
return
}
- const patch: FooterPatch = {}
-
- if ("variants" in result) {
- this.setVariants(result.variants ?? [])
- }
-
- if ("variant" in result) {
- this.setCurrentVariant(result.variant)
- }
-
- if (result.modelLabel) {
- patch.model = result.modelLabel
- }
-
- this.patch(patch)
- this.setNotice(result.status ?? "variant updated")
+ this.applySelectionResult(result)
+ if (result.status === undefined) this.setNotice("variant updated")
}
private handleModelSelect = (model: NonNullable): void => {
@@ -827,26 +813,7 @@ export class RunFooter implements FooterApi {
) {
return
}
-
- if ("variants" in result) {
- this.setVariants(result.variants ?? [])
- }
-
- if ("variant" in result) {
- this.setCurrentVariant(result.variant)
- }
-
- const patch: FooterPatch = {}
- if (result.modelLabel) {
- patch.model = result.modelLabel
- }
-
- if (patch.model) {
- this.patch(patch)
- }
- if (result.status) {
- this.setNotice(result.status)
- }
+ this.applySelectionResult(result)
})
.catch(() => {})
}
@@ -875,30 +842,18 @@ export class RunFooter implements FooterApi {
) {
return
}
-
- if ("variants" in result) {
- this.setVariants(result.variants ?? [])
- }
-
- if ("variant" in result) {
- this.setCurrentVariant(result.variant)
- }
-
- const patch: FooterPatch = {}
- if (result.modelLabel) {
- patch.model = result.modelLabel
- }
-
- if (patch.model) {
- this.patch(patch)
- }
- if (result.status) {
- this.setNotice(result.status)
- }
+ this.applySelectionResult(result)
})
.catch(() => {})
}
+ private applySelectionResult(result: CycleResult): void {
+ if ("variants" in result) this.setVariants(result.variants ?? [])
+ if ("variant" in result) this.setCurrentVariant(result.variant)
+ if (result.modelLabel) this.patch({ model: result.modelLabel })
+ if (result.status) this.setNotice(result.status)
+ }
+
private handleMiniSettingChange = async (change: MiniSettingChange): Promise => {
if (!this.options.miniSettings.update) {
this.setNotice("settings are unavailable")
diff --git a/packages/tui/src/mini/footer.view.tsx b/packages/tui/src/mini/footer.view.tsx
index 05bb17b02c..35bfa0b1b7 100644
--- a/packages/tui/src/mini/footer.view.tsx
+++ b/packages/tui/src/mini/footer.view.tsx
@@ -272,19 +272,21 @@ export function RunFooterView(props: RunFooterViewProps) {
return current.type === "composer" ? "prompt" : current.type
})
- const openCommand = () => {
- setRoute({ type: "command" })
+ const openRoute = (next: FooterPromptRoute) => {
+ setRoute(next)
props.onSubagentSelect?.(undefined)
}
+ const openCommand = () => {
+ openRoute({ type: "command" })
+ }
+
const openModel = () => {
- setRoute({ type: "model" })
- props.onSubagentSelect?.(undefined)
+ openRoute({ type: "model" })
}
const openAgent = () => {
- setRoute({ type: "agent" })
- props.onSubagentSelect?.(undefined)
+ openRoute({ type: "agent" })
}
const openSkillMenu = () => {
@@ -292,18 +294,15 @@ export function RunFooterView(props: RunFooterViewProps) {
return
}
- setRoute({ type: "skill" })
- props.onSubagentSelect?.(undefined)
+ openRoute({ type: "skill" })
}
const openVariant = () => {
- setRoute({ type: "variant" })
- props.onSubagentSelect?.(undefined)
+ openRoute({ type: "variant" })
}
const openSettings = () => {
- setRoute({ type: "settings" })
- props.onSubagentSelect?.(undefined)
+ openRoute({ type: "settings" })
}
const openSubagentMenu = () => {
@@ -311,14 +310,12 @@ export function RunFooterView(props: RunFooterViewProps) {
return
}
- setRoute({ type: "subagent-menu" })
- props.onSubagentSelect?.(undefined)
+ openRoute({ type: "subagent-menu" })
}
const openQueuedMenu = () => {
if (queue().length === 0) return
- setRoute({ type: "queued-menu" })
- props.onSubagentSelect?.(undefined)
+ openRoute({ type: "queued-menu" })
}
const closePanel = () => {
@@ -347,8 +344,7 @@ export function RunFooterView(props: RunFooterViewProps) {
}
const closeTab = () => {
- setRoute({ type: "composer" })
- props.onSubagentSelect?.(undefined)
+ openRoute({ type: "composer" })
}
const cycleTab = (dir: -1 | 1) => {
diff --git a/packages/tui/src/mini/stream-v2.subagent.ts b/packages/tui/src/mini/stream-v2.subagent.ts
index bbc0c9d4b1..e7ac374dbd 100644
--- a/packages/tui/src/mini/stream-v2.subagent.ts
+++ b/packages/tui/src/mini/stream-v2.subagent.ts
@@ -34,6 +34,7 @@ import type {
} from "./types"
import { canonicalToolName, normalizeTool, toolOutputText, toolView } from "./tool"
import { toolDisplayContent } from "../util/tool-display"
+import { isRecord } from "../util/record"
const CHILD_MESSAGE_LIMIT = 80
const CHILD_FRAME_LIMIT = 80
@@ -154,8 +155,7 @@ type DiscoveryJob = {
}
function record(value: unknown): Record | undefined {
- if (typeof value === "object" && value !== null && !Array.isArray(value)) return value as Record
- return undefined
+ return isRecord(value) ? value : undefined
}
function text(value: unknown): string | undefined {
diff --git a/packages/tui/src/mini/tool.ts b/packages/tui/src/mini/tool.ts
index 176fb900ab..4e44e775b2 100644
--- a/packages/tui/src/mini/tool.ts
+++ b/packages/tui/src/mini/tool.ts
@@ -26,6 +26,7 @@ import {
webSearchProviderLabel,
} from "../util/tool-display"
import { formatPath } from "../util/path-format"
+import { isRecord } from "../util/record"
import type { RunEntryBody, StreamCommit, ToolSnapshot } from "./types"
export { canonicalToolName } from "../util/tool-display"
@@ -138,11 +139,7 @@ type ToolRegistry = Record
type AnyToolRule = ToolRule
function dict(v: unknown): ToolDict {
- if (!v || typeof v !== "object" || Array.isArray(v)) {
- return {}
- }
-
- return { ...v }
+ return isRecord(v) ? { ...v } : {}
}
function props(frame: ToolFrame): ToolProps {
diff --git a/packages/tui/src/routes/session/composer/subagents-tab.tsx b/packages/tui/src/routes/session/composer/subagents-tab.tsx
index bbb1eb380f..afb6a7b096 100644
--- a/packages/tui/src/routes/session/composer/subagents-tab.tsx
+++ b/packages/tui/src/routes/session/composer/subagents-tab.tsx
@@ -63,10 +63,7 @@ export function SubagentsTab(props: { sessionID: string }) {
let wasActive = false
let scroll: ScrollBoxRenderable | undefined
- const selected = createMemo(() => {
- return store.selected
- })
- const selectedEntry = createMemo(() => entries()[selected()])
+ const selectedEntry = createMemo(() => entries()[store.selected])
createEffect(() => {
const active = composer.active("subagents")
@@ -95,11 +92,7 @@ export function SubagentsTab(props: { sessionID: string }) {
function moveTo(next: number, center = false) {
setStore("selected", next)
- scrollToSelection(center)
- }
-
- function scrollToSelection(center: boolean) {
- scrollToIndex(selected(), center)
+ scrollToIndex(next, center)
}
function scrollToIndex(index: number, center: boolean) {
@@ -209,7 +202,7 @@ export function SubagentsTab(props: { sessionID: string }) {
>
{(entry, index) => {
- const active = createMemo(() => index() === selected())
+ const active = createMemo(() => index() === store.selected)
const status = createMemo(() => {
if (entry.status === "running") return "Running"
return ""
diff --git a/packages/tui/src/routes/session/index.tsx b/packages/tui/src/routes/session/index.tsx
index 2cfc352fd6..c82c718547 100644
--- a/packages/tui/src/routes/session/index.tsx
+++ b/packages/tui/src/routes/session/index.tsx
@@ -108,6 +108,7 @@ import type { SessionInbox } from "@opencode-ai/schema/session-inbox"
import { generateThinkingSyntax } from "./thinking-syntax"
import { createDelayedPresence } from "../../util/delayed-presence"
import { SessionLocationMissing } from "./location-missing"
+import { isRecord } from "../../util/record"
addDefaultParsers(parsers.parsers)
@@ -131,7 +132,6 @@ const context = createContext<{
terminal: { width: number; height: number }
sessionID: string
thinkingMode: () => ThinkingMode
- showThinking: () => boolean
markdownMode: () => "source" | "rendered"
groupExploration: () => boolean
diffWrapMode: () => "word" | "none"
@@ -228,7 +228,6 @@ export function Session(props: { verticalTabsWidth: number }) {
const sidebar = createMemo(() => config.session?.sidebar ?? "auto")
const [sidebarOpen, setSidebarOpen] = createSignal(false)
const thinkingMode = createMemo(() => config.session?.thinking ?? "hide")
- const showThinking = createMemo(() => true)
const showScrollbar = createMemo(() => config.session?.scrollbar ?? false)
const markdownMode = createMemo(() => config.session?.markdown ?? "rendered")
const diffWrapMode = createMemo(() => config.diffs?.wrap ?? "word")
@@ -996,7 +995,7 @@ export function Session(props: { verticalTabsWidth: number }) {
try {
const sessionData = session()
if (!sessionData) return
- const transcript = formatSessionTranscript(sessionData, messages(), showThinking())
+ const transcript = formatSessionTranscript(sessionData, messages(), true)
await clipboard.write(transcript)
toast.show({ message: "Session transcript copied to clipboard!", variant: "success" })
} catch {
@@ -1017,7 +1016,7 @@ export function Session(props: { verticalTabsWidth: number }) {
const sessionData = session()
if (!sessionData) return
- const options = await DialogExportOptions.show(dialog, showThinking())
+ const options = await DialogExportOptions.show(dialog, true)
if (options === null) return
@@ -1152,7 +1151,6 @@ export function Session(props: { verticalTabsWidth: number }) {
},
sessionID: route.sessionID,
thinkingMode,
- showThinking,
markdownMode,
groupExploration,
diffWrapMode,
@@ -3624,8 +3622,7 @@ export function toolDisplay(tool: string) {
}
function recordValue(value: unknown): Record | undefined {
- if (typeof value !== "object" || value === null || Array.isArray(value)) return
- return value as Record
+ return isRecord(value) ? value : undefined
}
function formatSessionTranscript(session: SessionInfo, messages: SessionMessageInfo[], thinking: boolean) {