Compare commits

..

1 Commits

Author SHA1 Message Date
dayuan.jiang
3ec735970f ci: exclude public/ from Biome and disable automerge for Biome updates
Biome 2.5.7 (auto-merged by Renovate in #904 with failing checks) started
parsing SVG files, breaking lint on generated assets in public/. Exclude
the whole public/ directory instead of just *.svg so future parser
changes can't hit generated files again.

Biome minor updates can also introduce new lint rules for source code,
so require manual review for its Renovate PRs instead of automerge.
2026-08-08 12:23:03 +09:00
4 changed files with 16 additions and 20 deletions

View File

@@ -493,9 +493,9 @@ IMPORTANT: The "Current diagram XML" is the SINGLE SOURCE OF TRUTH for what's on
const result = streamText({ const result = streamText({
model, model,
abortSignal: req.signal, abortSignal: req.signal,
// Must be sent: unset means the provider's own default, and Bedrock's is 4096 — ...(process.env.MAX_OUTPUT_TOKENS && {
// enough for a small diagram, so larger ones were cut off mid-attribute. maxOutputTokens: parseInt(process.env.MAX_OUTPUT_TOKENS, 10),
maxOutputTokens: Number(process.env.MAX_OUTPUT_TOKENS) || 16000, }),
stopWhen: stepCountIs(5), stopWhen: stepCountIs(5),
// Repair truncated tool calls when maxOutputTokens is reached mid-JSON // Repair truncated tool calls when maxOutputTokens is reached mid-JSON
experimental_repairToolCall: async ({ toolCall, error }) => { experimental_repairToolCall: async ({ toolCall, error }) => {

View File

@@ -830,6 +830,10 @@ export default function ChatPanel({
let chartXml = await onFetchChart() let chartXml = await onFetchChart()
chartXml = formatXML(chartXml) chartXml = formatXML(chartXml)
// Update ref directly to avoid race condition with React's async state update
// This ensures edit_diagram has the correct XML before AI responds
chartXMLRef.current = chartXml
// Build user text by concatenating input with pre-extracted text // Build user text by concatenating input with pre-extracted text
// (Backend only reads first text part, so we must combine them) // (Backend only reads first text part, so we must combine them)
const parts: any[] = [] const parts: any[] = []

View File

@@ -2,7 +2,7 @@
import type React from "react" import type React from "react"
import { createContext, useContext, useEffect, useRef, useState } from "react" import { createContext, useContext, useEffect, useRef, useState } from "react"
import type { DrawIoEmbedRef, EventExport } from "react-drawio" import type { DrawIoEmbedRef } from "react-drawio"
import { toast } from "sonner" import { toast } from "sonner"
import type { ExportFormat } from "@/components/save-dialog" import type { ExportFormat } from "@/components/save-dialog"
import { getApiEndpoint } from "@/lib/base-path" import { getApiEndpoint } from "@/lib/base-path"
@@ -22,7 +22,7 @@ interface DiagramContextType {
handleExportWithoutHistory: () => void handleExportWithoutHistory: () => void
resolverRef: React.MutableRefObject<((value: string) => void) | null> resolverRef: React.MutableRefObject<((value: string) => void) | null>
drawioRef: React.MutableRefObject<DrawIoEmbedRef | null> drawioRef: React.MutableRefObject<DrawIoEmbedRef | null>
handleDiagramExport: (data: EventExport) => void handleDiagramExport: (data: any) => void
handleDiagramAutoSave: (data: { xml?: string }) => void handleDiagramAutoSave: (data: { xml?: string }) => void
clearDiagram: () => void clearDiagram: () => void
saveDiagramToFile: ( saveDiagramToFile: (
@@ -83,7 +83,7 @@ export function DiagramProvider({ children }: { children: React.ReactNode }) {
// Track if we're expecting an export for file save (stores raw export data) // Track if we're expecting an export for file save (stores raw export data)
const saveResolverRef = useRef<{ const saveResolverRef = useRef<{
resolver: ((data: string, fullDiagramXML?: string) => void) | null resolver: ((data: string) => void) | null
format: ExportFormat | null format: ExportFormat | null
}>({ resolver: null, format: null }) }>({ resolver: null, format: null })
@@ -204,7 +204,7 @@ export function DiagramProvider({ children }: { children: React.ReactNode }) {
return null return null
} }
const handleDiagramExport = (data: EventExport) => { const handleDiagramExport = (data: any) => {
// Handle PNG export for VLM validation // Handle PNG export for VLM validation
if (pngResolverRef.current && data.data?.startsWith("data:image/png")) { if (pngResolverRef.current && data.data?.startsWith("data:image/png")) {
pngResolverRef.current(data.data) pngResolverRef.current(data.data)
@@ -215,7 +215,7 @@ export function DiagramProvider({ children }: { children: React.ReactNode }) {
// Handle save to file if requested (process raw data before extraction) // Handle save to file if requested (process raw data before extraction)
if (saveResolverRef.current.resolver) { if (saveResolverRef.current.resolver) {
const format = saveResolverRef.current.format const format = saveResolverRef.current.format
saveResolverRef.current.resolver(data.data, data.xml) saveResolverRef.current.resolver(data.data)
saveResolverRef.current = { resolver: null, format: null } saveResolverRef.current = { resolver: null, format: null }
// For non-xmlsvg formats, skip XML extraction as it will fail // For non-xmlsvg formats, skip XML extraction as it will fail
// Only drawio (which uses xmlsvg internally) has the content attribute // Only drawio (which uses xmlsvg internally) has the content attribute
@@ -225,11 +225,8 @@ export function DiagramProvider({ children }: { children: React.ReactNode }) {
} }
} }
// Don't write chartXML here: exports don't change the diagram, and
// data.xml from xmlsvg exports has compressed <diagram> payloads that
// would break edit_diagram/display_diagram. Autosave keeps chartXML
// up to date with the full uncompressed multi-page document (#879).
const extractedXML = extractDiagramXML(data.data) const extractedXML = extractDiagramXML(data.data)
setChartXML(extractedXML)
setLatestSvg(data.data) setLatestSvg(data.data)
// Only add to history if this was a user-initiated export // Only add to history if this was a user-initiated export
@@ -291,16 +288,14 @@ export function DiagramProvider({ children }: { children: React.ReactNode }) {
// Set up the resolver before triggering export // Set up the resolver before triggering export
saveResolverRef.current = { saveResolverRef.current = {
resolver: (exportData: string, fullDiagramXML?: string) => { resolver: (exportData: string) => {
let fileContent: string | Blob let fileContent: string | Blob
let mimeType: string let mimeType: string
let extension: string let extension: string
if (format === "drawio") { if (format === "drawio") {
// Prefer the complete document from the export event so all pages are saved. // Extract XML from SVG for .drawio format
const xml = fullDiagramXML?.trim() const xml = extractDiagramXML(exportData)
? fullDiagramXML
: extractDiagramXML(exportData)
let xmlContent = xml let xmlContent = xml
if (!xml.includes("<mxfile")) { if (!xml.includes("<mxfile")) {
xmlContent = `<mxfile><diagram name="Page-1" id="page-1">${xml}</diagram></mxfile>` xmlContent = `<mxfile><diagram name="Page-1" id="page-1">${xml}</diagram></mxfile>`

View File

@@ -11,9 +11,6 @@ AI_PROVIDER=bedrock
# Example: AI_MODEL=doubao-seed-1-8-251215,doubao-seed-1-6-flash,doubao-seed-1-6-pro # Example: AI_MODEL=doubao-seed-1-8-251215,doubao-seed-1-6-flash,doubao-seed-1-6-pro
AI_MODEL=global.anthropic.claude-sonnet-4-5-20250929-v1:0 AI_MODEL=global.anthropic.claude-sonnet-4-5-20250929-v1:0
# Output limit, all providers (default: 16000). Raise it if large diagrams arrive cut off.
# MAX_OUTPUT_TOKENS=16000
# AWS Bedrock Configuration # AWS Bedrock Configuration
# AWS_REGION=us-east-1 # AWS_REGION=us-east-1
# AWS_ACCESS_KEY_ID=your-access-key-id # AWS_ACCESS_KEY_ID=your-access-key-id