diff --git a/src-tauri/src/commands/settings.rs b/src-tauri/src/commands/settings.rs index 49d295a..b7c051e 100644 --- a/src-tauri/src/commands/settings.rs +++ b/src-tauri/src/commands/settings.rs @@ -67,7 +67,9 @@ pub async fn settings_set( Ok(enabled) => { #[cfg(target_os = "macos")] { - startup_manager::set_launch_at_login(enabled)?; + if let Err(error) = startup_manager::set_launch_at_login(enabled) { + tracing::warn!(error = %error, "failed to update launch at login via SMAppService (non-fatal)"); + } } #[cfg(not(target_os = "macos"))] diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index 5166ad0..7c27d13 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -793,6 +793,11 @@ const en: Record = { "worktree.error.selectBranch": "Please select a branch", "contextCompressing": "Compressing context…", + // ── Artifact Card ───────────────────────────────────────── + "artifact.collapseCode": "Collapse code", + "artifact.expandCode": "Expand code", + "artifact.preview": "Preview", + // ── Long message preview ────────────────────────────────── "longMessage.collapseAll": "Collapse", "longMessage.expandAll": "Expand", diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts index 324a55e..18c85e1 100644 --- a/src/i18n/locales/zh-CN.ts +++ b/src/i18n/locales/zh-CN.ts @@ -831,6 +831,11 @@ const zhCN = { "worktree.error.selectBranch": "请选择一个分支", "contextCompressing": "正在压缩上下文…", + // ── Artifact Card ───────────────────────────────────────── + "artifact.collapseCode": "收起代码", + "artifact.expandCode": "展开代码", + "artifact.preview": "点击预览", + // ── Long message preview ────────────────────────────────── "longMessage.collapseAll": "收起全文", "longMessage.expandAll": "展开全文", diff --git a/src/modules/workbench-shell/ui/runtime-thread-surface.tsx b/src/modules/workbench-shell/ui/runtime-thread-surface.tsx index fd26b1a..afc08b3 100644 --- a/src/modules/workbench-shell/ui/runtime-thread-surface.tsx +++ b/src/modules/workbench-shell/ui/runtime-thread-surface.tsx @@ -644,6 +644,11 @@ export function RuntimeThreadSurface({ const message = error instanceof Error ? error.message : String(error); setLoadError(message); threadStore.setState({ runtimeContextUsage: null }); + // Reset run machine so the optimistic "running" state doesn't permanently + // block the pending run effect when the snapshot IPC fails. + // Use "failed" rather than "idle" because Guard 2 in threadStore rejects + // idle/null writes when an optimistic running state with a real runId exists. + if (threadId) runMachine.reset("failed", { runId: null, errorMessage: message, retryCount: 0 }); setSnapshotReady(true); setSnapshotThreadId(threadId); } finally { diff --git a/src/modules/workbench-shell/ui/thread-chart-artifact-card.tsx b/src/modules/workbench-shell/ui/thread-chart-artifact-card.tsx index 7d0ad7a..217117a 100644 --- a/src/modules/workbench-shell/ui/thread-chart-artifact-card.tsx +++ b/src/modules/workbench-shell/ui/thread-chart-artifact-card.tsx @@ -1,6 +1,6 @@ import { Component, useEffect, useMemo, useRef, useState } from "react"; import type { ErrorInfo, ReactNode } from "react"; -import { AlertCircleIcon, BarChart3Icon, CodeIcon, EyeIcon } from "lucide-react"; +import { AlertCircleIcon, BarChart3Icon, ChevronsUpDownIcon, CodeIcon, EyeIcon } from "lucide-react"; import { useTheme } from "@/app/providers/theme-provider"; import { CodeBlock } from "@/components/ai-elements/code-block"; import { MessageResponse } from "@/components/ai-elements/message"; @@ -8,6 +8,7 @@ import type { SurfaceChartMessagePart } from "@/modules/workbench-shell/ui/runti import { cn } from "@/shared/lib/utils"; import { validateSpec } from "@/modules/workbench-shell/ui/chart-spec-validation"; import { FilePreviewSurface } from "@/modules/workbench-shell/ui/file-preview-surface"; +import { useT } from "@/i18n"; type ThreadChartArtifactCardProps = { part: SurfaceChartMessagePart; @@ -105,7 +106,8 @@ function VegaLiteRenderer({ spec }: { spec: unknown }) { return
; } -function HtmlSvgRenderer({ source }: { source: string; library: string }) { +function HtmlSvgRenderer({ source, collapsed }: { source: string; collapsed: boolean }) { + if (collapsed) return null; return ( JSON.stringify(part.spec, null, 2), [part.spec]); const validationError = !isHtmlSvg && part.status !== "loading" ? validateSpec(part.spec) : null; return ( <> -
-
+
+
{getStatusLabel(part.status, part.library)} - + {part.library}
@@ -150,18 +159,8 @@ export function ThreadChartArtifactCard({ part }: ThreadChartArtifactCardProps)

{part.caption}

) : null}
-
- {isHtmlSvg && part.source ? ( - - ) : null} - {!isHtmlSvg && ( + {!isHtmlSvg && ( +
- )} -
+
+ )}
@@ -184,12 +183,32 @@ export function ThreadChartArtifactCard({ part }: ThreadChartArtifactCardProps) ) : null} {part.status === "loading" ? ( -
+
Generating…
) : isHtmlSvg ? ( part.source ? ( - + <> + +
+ + +
+ ) : ( ) @@ -211,7 +230,7 @@ export function ThreadChartArtifactCard({ part }: ThreadChartArtifactCardProps) "rounded-xl border px-2 py-2", part.status === "error" ? "border-app-danger/25 bg-app-danger/5" - : "border-app-border/20 bg-app-surface/35", + : "border-blue-400/15 dark:border-blue-500/12 bg-blue-50/15 dark:bg-blue-950/10", )} >