@yumiai/chat-widget 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +1 -1
- package/dist/ExcelCore-EAXQMKZT.js +10 -0
- package/dist/{ExcelViewer-3YLLYYIQ.js → ExcelViewer-OGWM52ZT.js} +2 -3
- package/dist/{ExcelViewer-3YLLYYIQ.js.map → ExcelViewer-OGWM52ZT.js.map} +1 -1
- package/dist/{GerberViewerA2UI-X5FWAD5M.js → GerberViewerA2UI-AORHOCF6.js} +2 -3
- package/dist/{GerberViewerA2UI-X5FWAD5M.js.map → GerberViewerA2UI-AORHOCF6.js.map} +1 -1
- package/dist/{GraphStatsLegend-D5bPeXB_.d.cts → GraphStatsLegend-CV0Y3-cP.d.cts} +39 -0
- package/dist/{GraphStatsLegend-D5bPeXB_.d.ts → GraphStatsLegend-CV0Y3-cP.d.ts} +39 -0
- package/dist/JsonRenderStandalone-L5ROJ6XP.js +17 -0
- package/dist/{KicadViewer-GV6ZC4AQ.js → KicadViewer-H6YY6WVC.js} +3 -4
- package/dist/{KicadViewer-GV6ZC4AQ.js.map → KicadViewer-H6YY6WVC.js.map} +1 -1
- package/dist/KicadViewerCore-XVJE2FTQ.js +10 -0
- package/dist/{PdfViewer-CHPDRK46.js → PdfViewer-GKVDDNCZ.js} +9 -10
- package/dist/{PdfViewer-CHPDRK46.js.map → PdfViewer-GKVDDNCZ.js.map} +1 -1
- package/dist/{PdfViewerCore-HJPEHSRA.js → PdfViewerCore-SUVXHXYO.js} +24 -11
- package/dist/PdfViewerCore-SUVXHXYO.js.map +1 -0
- package/dist/PowerPointCore-IZ4G6HEQ.js +10 -0
- package/dist/{PowerPointViewer-LQTO6UCU.js → PowerPointViewer-5R2KSWWJ.js} +2 -3
- package/dist/{PowerPointViewer-LQTO6UCU.js.map → PowerPointViewer-5R2KSWWJ.js.map} +1 -1
- package/dist/{StepViewerCore-7W3L3R4E.js → StepViewerCore-RORWXIRU.js} +2 -3
- package/dist/{StepViewerCore-7W3L3R4E.js.map → StepViewerCore-RORWXIRU.js.map} +1 -1
- package/dist/{ThreeViewerCore-N3QJD5QI.js → ThreeViewerCore-GTUZKD5V.js} +2 -3
- package/dist/{ThreeViewerCore-N3QJD5QI.js.map → ThreeViewerCore-GTUZKD5V.js.map} +1 -1
- package/dist/WordCore-QFG5HTYD.js +10 -0
- package/dist/{WordViewer-ZHCQMHOH.js → WordViewer-7XUQFS4A.js} +2 -3
- package/dist/{WordViewer-ZHCQMHOH.js.map → WordViewer-7XUQFS4A.js.map} +1 -1
- package/dist/{chunk-QLVPIM6R.js → chunk-3CNQONCV.js} +79 -1
- package/dist/chunk-3CNQONCV.js.map +1 -0
- package/dist/{chunk-2UC7YLVX.js → chunk-3LOSHCSH.js} +3 -3
- package/dist/chunk-5VUKEGFC.js +108 -0
- package/dist/chunk-5VUKEGFC.js.map +1 -0
- package/dist/chunk-AO4YUJQT.js +479 -0
- package/dist/chunk-AO4YUJQT.js.map +1 -0
- package/dist/{chunk-KQV7IKET.js → chunk-ASV4TISB.js} +2 -2
- package/dist/{chunk-CFKGNAJM.js → chunk-AT6VLLOO.js} +15 -15
- package/dist/{chunk-56WRZM3R.js → chunk-EYWNUJVZ.js} +3 -3
- package/dist/{chunk-K4KGNVL5.js → chunk-EZ46FGQ6.js} +3 -3
- package/dist/{chunk-GYXTSY22.js → chunk-KXPR6SRW.js} +4 -4
- package/dist/{chunk-7S67DOHQ.js → chunk-MTN6SUUQ.js} +2 -2
- package/dist/chunk-Q5PLT3AI.js +29 -0
- package/dist/chunk-Q5PLT3AI.js.map +1 -0
- package/dist/{chunk-PZXSASDY.js → chunk-R5LHMOAC.js} +3 -3
- package/dist/chunk-X67V7257.js +238 -0
- package/dist/chunk-X67V7257.js.map +1 -0
- package/dist/citationContext-CILHTO2Z.js +25 -0
- package/dist/components/JsonRender/standalone.cjs +56 -9753
- package/dist/components/JsonRender/standalone.cjs.map +1 -1
- package/dist/components/JsonRender/standalone.js +10 -11
- package/dist/components/JsonRender/standalone.js.map +1 -1
- package/dist/{gerber-2d-entry-OQ4SQRBY.js → gerber-2d-entry-HEFXQGBK.js} +5 -9
- package/dist/{gerber-2d-entry-OQ4SQRBY.js.map → gerber-2d-entry-HEFXQGBK.js.map} +1 -1
- package/dist/{gerber-3d-entry-DEHDBOO2.js → gerber-3d-entry-KVTONA37.js} +5 -9
- package/dist/{gerber-3d-entry-DEHDBOO2.js.map → gerber-3d-entry-KVTONA37.js.map} +1 -1
- package/dist/{gerber-simulation-entry-EBDX72XE.js → gerber-simulation-entry-GZ62QX5H.js} +5 -9
- package/dist/{gerber-simulation-entry-EBDX72XE.js.map → gerber-simulation-entry-GZ62QX5H.js.map} +1 -1
- package/dist/index.cjs +6690 -13472
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +776 -4
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +979 -26
- package/dist/index.d.ts +979 -26
- package/dist/index.js +4350 -1859
- package/dist/index.js.map +1 -1
- package/dist/provenance/index.cjs +78 -0
- package/dist/provenance/index.cjs.map +1 -1
- package/dist/provenance/index.d.cts +2 -2
- package/dist/provenance/index.d.ts +2 -2
- package/dist/provenance/index.js +2 -3
- package/dist/{resolveToArrayBuffer-AQIDZHSQ.js → resolveToArrayBuffer-PVSVIAII.js} +1 -3
- package/dist/{resolveToArrayBuffer-AQIDZHSQ.js.map → resolveToArrayBuffer-PVSVIAII.js.map} +1 -1
- package/dist/sseAdapter-LFXYGYC4.js +8 -0
- package/dist/sseAdapter-LFXYGYC4.js.map +1 -0
- package/package.json +4 -1
- package/dist/ExcelCore-DJOIVQMI.js +0 -11
- package/dist/JsonRenderStandalone-EIZM62JU.js +0 -18
- package/dist/KicadViewerCore-U7BWZHKJ.js +0 -11
- package/dist/PdfViewerCore-HJPEHSRA.js.map +0 -1
- package/dist/PowerPointCore-FPDR2BL4.js +0 -11
- package/dist/WordCore-JKSXK2XD.js +0 -11
- package/dist/chunk-7A4FY6FK.js +0 -10226
- package/dist/chunk-7A4FY6FK.js.map +0 -1
- package/dist/chunk-7D4SUZUM.js +0 -38
- package/dist/chunk-QLVPIM6R.js.map +0 -1
- package/dist/chunk-VXJWGLZ7.js +0 -21
- package/dist/chunk-VXJWGLZ7.js.map +0 -1
- /package/dist/{ExcelCore-DJOIVQMI.js.map → ExcelCore-EAXQMKZT.js.map} +0 -0
- /package/dist/{JsonRenderStandalone-EIZM62JU.js.map → JsonRenderStandalone-L5ROJ6XP.js.map} +0 -0
- /package/dist/{KicadViewerCore-U7BWZHKJ.js.map → KicadViewerCore-XVJE2FTQ.js.map} +0 -0
- /package/dist/{PowerPointCore-FPDR2BL4.js.map → PowerPointCore-IZ4G6HEQ.js.map} +0 -0
- /package/dist/{WordCore-JKSXK2XD.js.map → WordCore-QFG5HTYD.js.map} +0 -0
- /package/dist/{chunk-2UC7YLVX.js.map → chunk-3LOSHCSH.js.map} +0 -0
- /package/dist/{chunk-KQV7IKET.js.map → chunk-ASV4TISB.js.map} +0 -0
- /package/dist/{chunk-CFKGNAJM.js.map → chunk-AT6VLLOO.js.map} +0 -0
- /package/dist/{chunk-56WRZM3R.js.map → chunk-EYWNUJVZ.js.map} +0 -0
- /package/dist/{chunk-K4KGNVL5.js.map → chunk-EZ46FGQ6.js.map} +0 -0
- /package/dist/{chunk-GYXTSY22.js.map → chunk-KXPR6SRW.js.map} +0 -0
- /package/dist/{chunk-7S67DOHQ.js.map → chunk-MTN6SUUQ.js.map} +0 -0
- /package/dist/{chunk-PZXSASDY.js.map → chunk-R5LHMOAC.js.map} +0 -0
- /package/dist/{chunk-7D4SUZUM.js.map → citationContext-CILHTO2Z.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/FileViewer/viewers/StepViewerCore.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback } from 'react'\nimport * as THREE from 'three'\nimport { useChatWidgetI18n } from '../../../i18n'\nimport { useInteractionDispatch } from '../../../hooks/useInteractionDispatch'\nimport { useThreeScene } from './useThreeScene'\n\ninterface StepViewerCoreProps {\n src: string\n fileName: string\n}\n\nfunction isIgesFile(name: string): boolean {\n const lower = name.toLowerCase()\n return lower.endsWith('.iges') || lower.endsWith('.igs')\n}\n\nasync function fetchFileBuffer(src: string): Promise<Uint8Array> {\n const resp = await fetch(src)\n if (!resp.ok) throw new Error(`Fetch failed: ${resp.status}`)\n const ab = await resp.arrayBuffer()\n return new Uint8Array(ab)\n}\n\nconst WASM_MAGIC = [0x00, 0x61, 0x73, 0x6d]\n\nasync function fetchWasmBinary(): Promise<ArrayBuffer | undefined> {\n const candidates = [\n '/node_modules/occt-import-js/dist/occt-import-js.wasm',\n '/occt-import-js.wasm',\n ]\n for (const url of candidates) {\n try {\n const resp = await fetch(url)\n if (!resp.ok) continue\n const buf = await resp.arrayBuffer()\n const header = new Uint8Array(buf, 0, 4)\n if (WASM_MAGIC.every((b, i) => header[i] === b)) return buf\n } catch { /* try next */ }\n }\n return undefined\n}\n\nlet _occtPromise: Promise<any> | null = null\n\nfunction loadOcct(): Promise<any> {\n if (!_occtPromise) {\n _occtPromise = (async () => {\n const occtImportJs = (await import('occt-import-js')).default\n const wasmBinary = await fetchWasmBinary()\n return await occtImportJs(wasmBinary ? { wasmBinary } : undefined)\n })()\n _occtPromise.catch(() => { _occtPromise = null })\n }\n return _occtPromise\n}\n\nfunction makeBodyMaterial(color?: [number, number, number]): THREE.MeshPhysicalMaterial {\n const base = color\n ? new THREE.Color(color[0] / 255, color[1] / 255, color[2] / 255)\n : new THREE.Color(0x1a1a1e)\n const brightness = base.r * 0.299 + base.g * 0.587 + base.b * 0.114\n if (brightness < 0.08) base.lerp(new THREE.Color(0.10, 0.10, 0.12), 0.35)\n return new THREE.MeshPhysicalMaterial({\n color: base,\n metalness: 0.0,\n roughness: 0.75,\n clearcoat: 0.08,\n clearcoatRoughness: 0.6,\n side: THREE.DoubleSide,\n envMapIntensity: 0.25,\n })\n}\n\nfunction makePinMaterial(): THREE.MeshPhysicalMaterial {\n return new THREE.MeshPhysicalMaterial({\n color: 0xd6dade,\n metalness: 0.92,\n roughness: 0.15,\n clearcoat: 0.1,\n clearcoatRoughness: 0.05,\n side: THREE.DoubleSide,\n envMapIntensity: 1.8,\n })\n}\n\nfunction makePadMaterial(): THREE.MeshPhysicalMaterial {\n return new THREE.MeshPhysicalMaterial({\n color: 0xc2a55a,\n metalness: 0.9,\n roughness: 0.2,\n clearcoat: 0.1,\n clearcoatRoughness: 0.1,\n side: THREE.DoubleSide,\n envMapIntensity: 1.6,\n })\n}\n\nfunction makeCeramicMaterial(color?: [number, number, number]): THREE.MeshPhysicalMaterial {\n const base = color\n ? new THREE.Color(color[0] / 255, color[1] / 255, color[2] / 255)\n : new THREE.Color(0xc4a87a)\n return new THREE.MeshPhysicalMaterial({\n color: base,\n metalness: 0.0,\n roughness: 0.6,\n clearcoat: 0.15,\n clearcoatRoughness: 0.4,\n side: THREE.DoubleSide,\n envMapIntensity: 0.5,\n })\n}\n\nfunction makeColoredMaterial(r: number, g: number, b: number): THREE.MeshPhysicalMaterial {\n const brightness = 0.299 * r + 0.587 * g + 0.114 * b\n const saturation = (Math.max(r, g, b) - Math.min(r, g, b)) / (Math.max(r, g, b) || 1)\n if (brightness > 160 && saturation < 0.15) return makePinMaterial()\n if (brightness > 100 && saturation > 0.2 && r > g && r > b * 1.3) return makePadMaterial()\n if (brightness > 120 && saturation < 0.3) return makeCeramicMaterial([r, g, b])\n return makeBodyMaterial([r, g, b])\n}\n\ninterface ParsedMesh {\n geometry: THREE.BufferGeometry\n volume: number\n aspectRatio: number\n thinnestDim: number\n vertexCount: number\n color?: [number, number, number]\n name?: string\n}\n\nfunction analyzeMeshGeometry(geo: THREE.BufferGeometry): { volume: number; aspectRatio: number; thinnestDim: number } {\n geo.computeBoundingBox()\n const box = geo.boundingBox!\n const s = new THREE.Vector3()\n box.getSize(s)\n const dims = [s.x, s.y, s.z].sort((a, b) => b - a)\n const volume = s.x * s.y * s.z\n const aspectRatio = dims[0] / (dims[2] || 0.0001)\n return { volume, aspectRatio, thinnestDim: dims[2] }\n}\n\nfunction isLikelyEmbossedText(p: ParsedMesh, bodyThickness: number, largestVolume: number): boolean {\n const volumeRatio = p.volume / (largestVolume || 1)\n if (volumeRatio > 0.01) return false\n if (p.thinnestDim > bodyThickness * 0.08) return false\n if (p.aspectRatio > 8 && volumeRatio < 0.005) return true\n if (p.vertexCount > 30 && volumeRatio < 0.002 && p.aspectRatio > 4) return true\n return false\n}\n\nfunction classifyByGeometry(p: ParsedMesh, largestVolume: number, totalMeshCount: number): 'body' | 'pin' | 'pad' {\n const nameLower = (p.name || '').toLowerCase()\n if (/lead|pin|terminal|leg|gull/i.test(nameLower)) return 'pin'\n if (/pad|solder/i.test(nameLower)) return 'pad'\n if (/body|case|housing|package|mold|encap/i.test(nameLower)) return 'body'\n\n const volumeRatio = p.volume / (largestVolume || 1)\n\n if (volumeRatio > 0.4) return 'body'\n\n if (p.aspectRatio > 3 && volumeRatio < 0.3) return 'pin'\n\n if (totalMeshCount > 2 && volumeRatio < 0.15) return 'pin'\n\n return volumeRatio < 0.25 ? 'pin' : 'body'\n}\n\nfunction buildMeshFromResult(result: any): THREE.Group {\n const group = new THREE.Group()\n if (!result.meshes || result.meshes.length === 0) {\n throw new Error('No geometry found in file')\n }\n\n const parsed: ParsedMesh[] = []\n\n for (const meshData of result.meshes) {\n const geometry = new THREE.BufferGeometry()\n const vertices = new Float32Array(meshData.attributes.position.array)\n geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))\n\n if (meshData.attributes.normal?.array) {\n const normals = new Float32Array(meshData.attributes.normal.array)\n geometry.setAttribute('normal', new THREE.BufferAttribute(normals, 3))\n }\n if (meshData.index?.array) {\n const indices = new Uint32Array(meshData.index.array)\n geometry.setIndex(new THREE.BufferAttribute(indices, 1))\n }\n if (!meshData.attributes.normal?.array) geometry.computeVertexNormals()\n\n const { volume, aspectRatio, thinnestDim } = analyzeMeshGeometry(geometry)\n parsed.push({\n geometry,\n volume,\n aspectRatio,\n thinnestDim,\n vertexCount: meshData.attributes.position.array.length / 3,\n color: meshData.color ?? undefined,\n name: meshData.name ?? undefined,\n })\n }\n\n const sorted = [...parsed].sort((a, b) => b.volume - a.volume)\n const largestVolume = sorted[0]?.volume || 1\n const bodyMesh = sorted[0]\n const bodyThickness = bodyMesh?.thinnestDim || 1\n\n const colors = parsed.map(p => p.color).filter(Boolean) as [number, number, number][]\n const allSameColor = colors.length <= 1 || colors.every(c => {\n const [r0, g0, b0] = colors[0]\n return Math.abs(c[0] - r0) < 20 && Math.abs(c[1] - g0) < 20 && Math.abs(c[2] - b0) < 20\n })\n const useGeometry = colors.length === 0 || allSameColor\n\n for (const p of parsed) {\n if (parsed.length > 3 && isLikelyEmbossedText(p, bodyThickness, largestVolume)) continue\n\n let material: THREE.MeshPhysicalMaterial\n if (useGeometry && parsed.length > 1) {\n const role = classifyByGeometry(p, largestVolume, parsed.length)\n if (role === 'pin') material = makePinMaterial()\n else if (role === 'pad') material = makePadMaterial()\n else material = makeBodyMaterial(p.color)\n } else if (!allSameColor && colors.length > 1) {\n material = p.color\n ? makeColoredMaterial(p.color[0], p.color[1], p.color[2])\n : makeBodyMaterial()\n } else {\n material = makeBodyMaterial(p.color)\n }\n group.add(new THREE.Mesh(p.geometry, material))\n }\n\n return group\n}\n\nconst StepViewerCore: React.FC<StepViewerCoreProps> = ({ src, fileName }) => {\n const { t } = useChatWidgetI18n()\n const emitInteraction = useInteractionDispatch()\n const { containerRef, handleRef, resetView, wireframe, toggleWireframe } = useThreeScene()\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n\n useEffect(() => {\n const h = handleRef.current\n if (!h || !src) return\n\n setLoading(true)\n setError(null)\n let cancelled = false\n\n ;(async () => {\n try {\n const buffer = await fetchFileBuffer(src)\n if (cancelled) return\n\n const occt = await loadOcct()\n\n const result = isIgesFile(fileName)\n ? occt.ReadIgesFile(buffer, null)\n : occt.ReadStepFile(buffer, null)\n\n if (cancelled) return\n\n if (!result.success) {\n throw new Error('Failed to parse CAD file')\n }\n\n const group = buildMeshFromResult(result)\n h.scene.add(group)\n h.fitToScene(group)\n setLoading(false)\n } catch (e) {\n if (!cancelled) {\n setError(e instanceof Error ? e.message : String(e))\n setLoading(false)\n }\n }\n })()\n\n return () => { cancelled = true }\n }, [src, fileName, handleRef])\n\n const handleDownload = useCallback(() => {\n emitInteraction('file-download', fileName, { source: 'step-viewer' })\n const a = document.createElement('a')\n a.href = src\n a.download = fileName\n a.click()\n }, [src, fileName, emitInteraction])\n\n return (\n <div className=\"ycw-file-viewer-step\">\n <div className=\"ycw-3d-toolbar\">\n <span className=\"ycw-3d-filename\" title={fileName}>{fileName}</span>\n <div className=\"ycw-3d-toolbar-actions\">\n <button type=\"button\" className={`ycw-3d-btn${wireframe ? ' active' : ''}`} onClick={toggleWireframe} title={t('viewer.3d.wireframe')}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M12 2L2 7l10 5 10-5-10-5z\"/><path d=\"M2 17l10 5 10-5\"/><path d=\"M2 12l10 5 10-5\"/></svg>\n </button>\n <button type=\"button\" className=\"ycw-3d-btn\" onClick={resetView} title={t('viewer.3d.resetView')}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M15 3h6v6\"/><path d=\"M9 21H3v-6\"/><path d=\"M21 3l-7 7\"/><path d=\"M3 21l7-7\"/></svg>\n </button>\n <button type=\"button\" className=\"ycw-3d-btn\" onClick={handleDownload} title={t('viewer.fallback.download')}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/><polyline points=\"7 10 12 15 17 10\"/><line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\"/></svg>\n </button>\n </div>\n </div>\n <div className=\"ycw-3d-canvas\" ref={containerRef}>\n {loading && (\n <div className=\"ycw-3d-overlay\">\n <div className=\"ycw-3d-spinner\" />\n <span>{t('viewer.loadingStep')}</span>\n </div>\n )}\n {error && (\n <div className=\"ycw-3d-overlay ycw-3d-error\">\n <span>⚠️ {error}</span>\n <button type=\"button\" className=\"ycw-3d-btn\" onClick={handleDownload}>{t('viewer.fallback.download')}</button>\n </div>\n )}\n </div>\n </div>\n )\n}\n\nexport default StepViewerCore\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/components/FileViewer/viewers/StepViewerCore.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback } from 'react'\nimport * as THREE from 'three'\nimport { useChatWidgetI18n } from '../../../i18n'\nimport { useInteractionDispatch } from '../../../hooks/useInteractionDispatch'\nimport { useThreeScene } from './useThreeScene'\n\ninterface StepViewerCoreProps {\n src: string\n fileName: string\n}\n\nfunction isIgesFile(name: string): boolean {\n const lower = name.toLowerCase()\n return lower.endsWith('.iges') || lower.endsWith('.igs')\n}\n\nasync function fetchFileBuffer(src: string): Promise<Uint8Array> {\n const resp = await fetch(src)\n if (!resp.ok) throw new Error(`Fetch failed: ${resp.status}`)\n const ab = await resp.arrayBuffer()\n return new Uint8Array(ab)\n}\n\nconst WASM_MAGIC = [0x00, 0x61, 0x73, 0x6d]\n\nasync function fetchWasmBinary(): Promise<ArrayBuffer | undefined> {\n const candidates = [\n '/node_modules/occt-import-js/dist/occt-import-js.wasm',\n '/occt-import-js.wasm',\n ]\n for (const url of candidates) {\n try {\n const resp = await fetch(url)\n if (!resp.ok) continue\n const buf = await resp.arrayBuffer()\n const header = new Uint8Array(buf, 0, 4)\n if (WASM_MAGIC.every((b, i) => header[i] === b)) return buf\n } catch { /* try next */ }\n }\n return undefined\n}\n\nlet _occtPromise: Promise<any> | null = null\n\nfunction loadOcct(): Promise<any> {\n if (!_occtPromise) {\n _occtPromise = (async () => {\n const occtImportJs = (await import('occt-import-js')).default\n const wasmBinary = await fetchWasmBinary()\n return await occtImportJs(wasmBinary ? { wasmBinary } : undefined)\n })()\n _occtPromise.catch(() => { _occtPromise = null })\n }\n return _occtPromise\n}\n\nfunction makeBodyMaterial(color?: [number, number, number]): THREE.MeshPhysicalMaterial {\n const base = color\n ? new THREE.Color(color[0] / 255, color[1] / 255, color[2] / 255)\n : new THREE.Color(0x1a1a1e)\n const brightness = base.r * 0.299 + base.g * 0.587 + base.b * 0.114\n if (brightness < 0.08) base.lerp(new THREE.Color(0.10, 0.10, 0.12), 0.35)\n return new THREE.MeshPhysicalMaterial({\n color: base,\n metalness: 0.0,\n roughness: 0.75,\n clearcoat: 0.08,\n clearcoatRoughness: 0.6,\n side: THREE.DoubleSide,\n envMapIntensity: 0.25,\n })\n}\n\nfunction makePinMaterial(): THREE.MeshPhysicalMaterial {\n return new THREE.MeshPhysicalMaterial({\n color: 0xd6dade,\n metalness: 0.92,\n roughness: 0.15,\n clearcoat: 0.1,\n clearcoatRoughness: 0.05,\n side: THREE.DoubleSide,\n envMapIntensity: 1.8,\n })\n}\n\nfunction makePadMaterial(): THREE.MeshPhysicalMaterial {\n return new THREE.MeshPhysicalMaterial({\n color: 0xc2a55a,\n metalness: 0.9,\n roughness: 0.2,\n clearcoat: 0.1,\n clearcoatRoughness: 0.1,\n side: THREE.DoubleSide,\n envMapIntensity: 1.6,\n })\n}\n\nfunction makeCeramicMaterial(color?: [number, number, number]): THREE.MeshPhysicalMaterial {\n const base = color\n ? new THREE.Color(color[0] / 255, color[1] / 255, color[2] / 255)\n : new THREE.Color(0xc4a87a)\n return new THREE.MeshPhysicalMaterial({\n color: base,\n metalness: 0.0,\n roughness: 0.6,\n clearcoat: 0.15,\n clearcoatRoughness: 0.4,\n side: THREE.DoubleSide,\n envMapIntensity: 0.5,\n })\n}\n\nfunction makeColoredMaterial(r: number, g: number, b: number): THREE.MeshPhysicalMaterial {\n const brightness = 0.299 * r + 0.587 * g + 0.114 * b\n const saturation = (Math.max(r, g, b) - Math.min(r, g, b)) / (Math.max(r, g, b) || 1)\n if (brightness > 160 && saturation < 0.15) return makePinMaterial()\n if (brightness > 100 && saturation > 0.2 && r > g && r > b * 1.3) return makePadMaterial()\n if (brightness > 120 && saturation < 0.3) return makeCeramicMaterial([r, g, b])\n return makeBodyMaterial([r, g, b])\n}\n\ninterface ParsedMesh {\n geometry: THREE.BufferGeometry\n volume: number\n aspectRatio: number\n thinnestDim: number\n vertexCount: number\n color?: [number, number, number]\n name?: string\n}\n\nfunction analyzeMeshGeometry(geo: THREE.BufferGeometry): { volume: number; aspectRatio: number; thinnestDim: number } {\n geo.computeBoundingBox()\n const box = geo.boundingBox!\n const s = new THREE.Vector3()\n box.getSize(s)\n const dims = [s.x, s.y, s.z].sort((a, b) => b - a)\n const volume = s.x * s.y * s.z\n const aspectRatio = dims[0] / (dims[2] || 0.0001)\n return { volume, aspectRatio, thinnestDim: dims[2] }\n}\n\nfunction isLikelyEmbossedText(p: ParsedMesh, bodyThickness: number, largestVolume: number): boolean {\n const volumeRatio = p.volume / (largestVolume || 1)\n if (volumeRatio > 0.01) return false\n if (p.thinnestDim > bodyThickness * 0.08) return false\n if (p.aspectRatio > 8 && volumeRatio < 0.005) return true\n if (p.vertexCount > 30 && volumeRatio < 0.002 && p.aspectRatio > 4) return true\n return false\n}\n\nfunction classifyByGeometry(p: ParsedMesh, largestVolume: number, totalMeshCount: number): 'body' | 'pin' | 'pad' {\n const nameLower = (p.name || '').toLowerCase()\n if (/lead|pin|terminal|leg|gull/i.test(nameLower)) return 'pin'\n if (/pad|solder/i.test(nameLower)) return 'pad'\n if (/body|case|housing|package|mold|encap/i.test(nameLower)) return 'body'\n\n const volumeRatio = p.volume / (largestVolume || 1)\n\n if (volumeRatio > 0.4) return 'body'\n\n if (p.aspectRatio > 3 && volumeRatio < 0.3) return 'pin'\n\n if (totalMeshCount > 2 && volumeRatio < 0.15) return 'pin'\n\n return volumeRatio < 0.25 ? 'pin' : 'body'\n}\n\nfunction buildMeshFromResult(result: any): THREE.Group {\n const group = new THREE.Group()\n if (!result.meshes || result.meshes.length === 0) {\n throw new Error('No geometry found in file')\n }\n\n const parsed: ParsedMesh[] = []\n\n for (const meshData of result.meshes) {\n const geometry = new THREE.BufferGeometry()\n const vertices = new Float32Array(meshData.attributes.position.array)\n geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))\n\n if (meshData.attributes.normal?.array) {\n const normals = new Float32Array(meshData.attributes.normal.array)\n geometry.setAttribute('normal', new THREE.BufferAttribute(normals, 3))\n }\n if (meshData.index?.array) {\n const indices = new Uint32Array(meshData.index.array)\n geometry.setIndex(new THREE.BufferAttribute(indices, 1))\n }\n if (!meshData.attributes.normal?.array) geometry.computeVertexNormals()\n\n const { volume, aspectRatio, thinnestDim } = analyzeMeshGeometry(geometry)\n parsed.push({\n geometry,\n volume,\n aspectRatio,\n thinnestDim,\n vertexCount: meshData.attributes.position.array.length / 3,\n color: meshData.color ?? undefined,\n name: meshData.name ?? undefined,\n })\n }\n\n const sorted = [...parsed].sort((a, b) => b.volume - a.volume)\n const largestVolume = sorted[0]?.volume || 1\n const bodyMesh = sorted[0]\n const bodyThickness = bodyMesh?.thinnestDim || 1\n\n const colors = parsed.map(p => p.color).filter(Boolean) as [number, number, number][]\n const allSameColor = colors.length <= 1 || colors.every(c => {\n const [r0, g0, b0] = colors[0]\n return Math.abs(c[0] - r0) < 20 && Math.abs(c[1] - g0) < 20 && Math.abs(c[2] - b0) < 20\n })\n const useGeometry = colors.length === 0 || allSameColor\n\n for (const p of parsed) {\n if (parsed.length > 3 && isLikelyEmbossedText(p, bodyThickness, largestVolume)) continue\n\n let material: THREE.MeshPhysicalMaterial\n if (useGeometry && parsed.length > 1) {\n const role = classifyByGeometry(p, largestVolume, parsed.length)\n if (role === 'pin') material = makePinMaterial()\n else if (role === 'pad') material = makePadMaterial()\n else material = makeBodyMaterial(p.color)\n } else if (!allSameColor && colors.length > 1) {\n material = p.color\n ? makeColoredMaterial(p.color[0], p.color[1], p.color[2])\n : makeBodyMaterial()\n } else {\n material = makeBodyMaterial(p.color)\n }\n group.add(new THREE.Mesh(p.geometry, material))\n }\n\n return group\n}\n\nconst StepViewerCore: React.FC<StepViewerCoreProps> = ({ src, fileName }) => {\n const { t } = useChatWidgetI18n()\n const emitInteraction = useInteractionDispatch()\n const { containerRef, handleRef, resetView, wireframe, toggleWireframe } = useThreeScene()\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n\n useEffect(() => {\n const h = handleRef.current\n if (!h || !src) return\n\n setLoading(true)\n setError(null)\n let cancelled = false\n\n ;(async () => {\n try {\n const buffer = await fetchFileBuffer(src)\n if (cancelled) return\n\n const occt = await loadOcct()\n\n const result = isIgesFile(fileName)\n ? occt.ReadIgesFile(buffer, null)\n : occt.ReadStepFile(buffer, null)\n\n if (cancelled) return\n\n if (!result.success) {\n throw new Error('Failed to parse CAD file')\n }\n\n const group = buildMeshFromResult(result)\n h.scene.add(group)\n h.fitToScene(group)\n setLoading(false)\n } catch (e) {\n if (!cancelled) {\n setError(e instanceof Error ? e.message : String(e))\n setLoading(false)\n }\n }\n })()\n\n return () => { cancelled = true }\n }, [src, fileName, handleRef])\n\n const handleDownload = useCallback(() => {\n emitInteraction('file-download', fileName, { source: 'step-viewer' })\n const a = document.createElement('a')\n a.href = src\n a.download = fileName\n a.click()\n }, [src, fileName, emitInteraction])\n\n return (\n <div className=\"ycw-file-viewer-step\">\n <div className=\"ycw-3d-toolbar\">\n <span className=\"ycw-3d-filename\" title={fileName}>{fileName}</span>\n <div className=\"ycw-3d-toolbar-actions\">\n <button type=\"button\" className={`ycw-3d-btn${wireframe ? ' active' : ''}`} onClick={toggleWireframe} title={t('viewer.3d.wireframe')}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M12 2L2 7l10 5 10-5-10-5z\"/><path d=\"M2 17l10 5 10-5\"/><path d=\"M2 12l10 5 10-5\"/></svg>\n </button>\n <button type=\"button\" className=\"ycw-3d-btn\" onClick={resetView} title={t('viewer.3d.resetView')}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M15 3h6v6\"/><path d=\"M9 21H3v-6\"/><path d=\"M21 3l-7 7\"/><path d=\"M3 21l7-7\"/></svg>\n </button>\n <button type=\"button\" className=\"ycw-3d-btn\" onClick={handleDownload} title={t('viewer.fallback.download')}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/><polyline points=\"7 10 12 15 17 10\"/><line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\"/></svg>\n </button>\n </div>\n </div>\n <div className=\"ycw-3d-canvas\" ref={containerRef}>\n {loading && (\n <div className=\"ycw-3d-overlay\">\n <div className=\"ycw-3d-spinner\" />\n <span>{t('viewer.loadingStep')}</span>\n </div>\n )}\n {error && (\n <div className=\"ycw-3d-overlay ycw-3d-error\">\n <span>⚠️ {error}</span>\n <button type=\"button\" className=\"ycw-3d-btn\" onClick={handleDownload}>{t('viewer.fallback.download')}</button>\n </div>\n )}\n </div>\n </div>\n )\n}\n\nexport default StepViewerCore\n"],"mappings":"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","names":[]}
|
|
@@ -6,8 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-3R6T3LBR.js";
|
|
7
7
|
import {
|
|
8
8
|
useChatWidgetI18n
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-7D4SUZUM.js";
|
|
9
|
+
} from "./chunk-3CNQONCV.js";
|
|
11
10
|
|
|
12
11
|
// src/components/FileViewer/viewers/ThreeViewerCore.tsx
|
|
13
12
|
import { useEffect, useState, useCallback } from "react";
|
|
@@ -158,4 +157,4 @@ var ThreeViewerCore_default = ThreeViewerCore;
|
|
|
158
157
|
export {
|
|
159
158
|
ThreeViewerCore_default as default
|
|
160
159
|
};
|
|
161
|
-
//# sourceMappingURL=ThreeViewerCore-
|
|
160
|
+
//# sourceMappingURL=ThreeViewerCore-GTUZKD5V.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/FileViewer/viewers/ThreeViewerCore.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback } from 'react'\nimport * as THREE from 'three'\nimport { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js'\nimport { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'\nimport { ThreeMFLoader } from 'three/examples/jsm/loaders/3MFLoader.js'\nimport { useChatWidgetI18n } from '../../../i18n'\nimport { useInteractionDispatch } from '../../../hooks/useInteractionDispatch'\nimport { useThreeScene } from './useThreeScene'\n\ninterface ThreeViewerCoreProps {\n src: string\n fileName: string\n}\n\nconst DEFAULT_MATERIAL = new THREE.MeshPhysicalMaterial({\n color: 0x8899aa,\n metalness: 0.15,\n roughness: 0.45,\n side: THREE.DoubleSide,\n envMapIntensity: 0.8,\n})\n\nfunction getFormatFromName(name: string): string {\n const lower = name.toLowerCase()\n if (lower.endsWith('.stl')) return 'stl'\n if (lower.endsWith('.obj')) return 'obj'\n if (lower.endsWith('.glb') || lower.endsWith('.gltf')) return 'gltf'\n if (lower.endsWith('.3mf')) return '3mf'\n return 'unknown'\n}\n\nconst ThreeViewerCore: React.FC<ThreeViewerCoreProps> = ({ src, fileName }) => {\n const { t } = useChatWidgetI18n()\n const emitInteraction = useInteractionDispatch()\n const { containerRef, handleRef, resetView, wireframe, toggleWireframe } = useThreeScene()\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n\n useEffect(() => {\n const h = handleRef.current\n if (!h || !src) return\n\n setLoading(true)\n setError(null)\n\n const format = getFormatFromName(fileName)\n let cancelled = false\n\n const onLoad = (obj: THREE.Object3D) => {\n if (cancelled) return\n h.scene.add(obj)\n h.fitToScene(obj)\n setLoading(false)\n }\n\n const onError = (e: unknown) => {\n if (cancelled) return\n setError(e instanceof Error ? e.message : String(e))\n setLoading(false)\n }\n\n try {\n switch (format) {\n case 'stl': {\n const loader = new STLLoader()\n loader.load(src, (geometry) => {\n if (cancelled) return\n geometry.computeVertexNormals()\n const mesh = new THREE.Mesh(geometry, DEFAULT_MATERIAL.clone())\n onLoad(mesh)\n }, undefined, onError)\n break\n }\n case 'obj': {\n const loader = new OBJLoader()\n loader.load(src, (group) => {\n group.traverse(child => {\n if (child instanceof THREE.Mesh && !child.material) {\n child.material = DEFAULT_MATERIAL.clone()\n }\n })\n onLoad(group)\n }, undefined, onError)\n break\n }\n case 'gltf': {\n const loader = new GLTFLoader()\n loader.load(src, (gltf) => {\n onLoad(gltf.scene)\n }, undefined, onError)\n break\n }\n case '3mf': {\n const loader = new ThreeMFLoader()\n loader.load(src, (group) => {\n group.traverse(child => {\n if (child instanceof THREE.Mesh && !child.material) {\n child.material = DEFAULT_MATERIAL.clone()\n }\n })\n onLoad(group)\n }, undefined, onError)\n break\n }\n default:\n setError(`Unsupported 3D format: ${format}`)\n setLoading(false)\n }\n } catch (e) {\n onError(e)\n }\n\n return () => { cancelled = true }\n }, [src, fileName, handleRef])\n\n const handleDownload = useCallback(() => {\n emitInteraction('file-download', fileName, { source: '3d-viewer' })\n const a = document.createElement('a')\n a.href = src\n a.download = fileName\n a.click()\n }, [src, fileName, emitInteraction])\n\n return (\n <div className=\"ycw-file-viewer-3d\">\n <div className=\"ycw-3d-toolbar\">\n <span className=\"ycw-3d-filename\" title={fileName}>{fileName}</span>\n <div className=\"ycw-3d-toolbar-actions\">\n <button type=\"button\" className={`ycw-3d-btn${wireframe ? ' active' : ''}`} onClick={toggleWireframe} title={t('viewer.3d.wireframe')}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M12 2L2 7l10 5 10-5-10-5z\"/><path d=\"M2 17l10 5 10-5\"/><path d=\"M2 12l10 5 10-5\"/></svg>\n </button>\n <button type=\"button\" className=\"ycw-3d-btn\" onClick={resetView} title={t('viewer.3d.resetView')}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M15 3h6v6\"/><path d=\"M9 21H3v-6\"/><path d=\"M21 3l-7 7\"/><path d=\"M3 21l7-7\"/></svg>\n </button>\n <button type=\"button\" className=\"ycw-3d-btn\" onClick={handleDownload} title={t('viewer.fallback.download')}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/><polyline points=\"7 10 12 15 17 10\"/><line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\"/></svg>\n </button>\n </div>\n </div>\n <div className=\"ycw-3d-canvas\" ref={containerRef}>\n {loading && (\n <div className=\"ycw-3d-overlay\">\n <div className=\"ycw-3d-spinner\" />\n <span>{t('viewer.loading3d')}</span>\n </div>\n )}\n {error && (\n <div className=\"ycw-3d-overlay ycw-3d-error\">\n <span>⚠️ {error}</span>\n <button type=\"button\" className=\"ycw-3d-btn\" onClick={handleDownload}>{t('viewer.fallback.download')}</button>\n </div>\n )}\n </div>\n </div>\n )\n}\n\nexport default ThreeViewerCore\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/components/FileViewer/viewers/ThreeViewerCore.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback } from 'react'\nimport * as THREE from 'three'\nimport { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js'\nimport { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'\nimport { ThreeMFLoader } from 'three/examples/jsm/loaders/3MFLoader.js'\nimport { useChatWidgetI18n } from '../../../i18n'\nimport { useInteractionDispatch } from '../../../hooks/useInteractionDispatch'\nimport { useThreeScene } from './useThreeScene'\n\ninterface ThreeViewerCoreProps {\n src: string\n fileName: string\n}\n\nconst DEFAULT_MATERIAL = new THREE.MeshPhysicalMaterial({\n color: 0x8899aa,\n metalness: 0.15,\n roughness: 0.45,\n side: THREE.DoubleSide,\n envMapIntensity: 0.8,\n})\n\nfunction getFormatFromName(name: string): string {\n const lower = name.toLowerCase()\n if (lower.endsWith('.stl')) return 'stl'\n if (lower.endsWith('.obj')) return 'obj'\n if (lower.endsWith('.glb') || lower.endsWith('.gltf')) return 'gltf'\n if (lower.endsWith('.3mf')) return '3mf'\n return 'unknown'\n}\n\nconst ThreeViewerCore: React.FC<ThreeViewerCoreProps> = ({ src, fileName }) => {\n const { t } = useChatWidgetI18n()\n const emitInteraction = useInteractionDispatch()\n const { containerRef, handleRef, resetView, wireframe, toggleWireframe } = useThreeScene()\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n\n useEffect(() => {\n const h = handleRef.current\n if (!h || !src) return\n\n setLoading(true)\n setError(null)\n\n const format = getFormatFromName(fileName)\n let cancelled = false\n\n const onLoad = (obj: THREE.Object3D) => {\n if (cancelled) return\n h.scene.add(obj)\n h.fitToScene(obj)\n setLoading(false)\n }\n\n const onError = (e: unknown) => {\n if (cancelled) return\n setError(e instanceof Error ? e.message : String(e))\n setLoading(false)\n }\n\n try {\n switch (format) {\n case 'stl': {\n const loader = new STLLoader()\n loader.load(src, (geometry) => {\n if (cancelled) return\n geometry.computeVertexNormals()\n const mesh = new THREE.Mesh(geometry, DEFAULT_MATERIAL.clone())\n onLoad(mesh)\n }, undefined, onError)\n break\n }\n case 'obj': {\n const loader = new OBJLoader()\n loader.load(src, (group) => {\n group.traverse(child => {\n if (child instanceof THREE.Mesh && !child.material) {\n child.material = DEFAULT_MATERIAL.clone()\n }\n })\n onLoad(group)\n }, undefined, onError)\n break\n }\n case 'gltf': {\n const loader = new GLTFLoader()\n loader.load(src, (gltf) => {\n onLoad(gltf.scene)\n }, undefined, onError)\n break\n }\n case '3mf': {\n const loader = new ThreeMFLoader()\n loader.load(src, (group) => {\n group.traverse(child => {\n if (child instanceof THREE.Mesh && !child.material) {\n child.material = DEFAULT_MATERIAL.clone()\n }\n })\n onLoad(group)\n }, undefined, onError)\n break\n }\n default:\n setError(`Unsupported 3D format: ${format}`)\n setLoading(false)\n }\n } catch (e) {\n onError(e)\n }\n\n return () => { cancelled = true }\n }, [src, fileName, handleRef])\n\n const handleDownload = useCallback(() => {\n emitInteraction('file-download', fileName, { source: '3d-viewer' })\n const a = document.createElement('a')\n a.href = src\n a.download = fileName\n a.click()\n }, [src, fileName, emitInteraction])\n\n return (\n <div className=\"ycw-file-viewer-3d\">\n <div className=\"ycw-3d-toolbar\">\n <span className=\"ycw-3d-filename\" title={fileName}>{fileName}</span>\n <div className=\"ycw-3d-toolbar-actions\">\n <button type=\"button\" className={`ycw-3d-btn${wireframe ? ' active' : ''}`} onClick={toggleWireframe} title={t('viewer.3d.wireframe')}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M12 2L2 7l10 5 10-5-10-5z\"/><path d=\"M2 17l10 5 10-5\"/><path d=\"M2 12l10 5 10-5\"/></svg>\n </button>\n <button type=\"button\" className=\"ycw-3d-btn\" onClick={resetView} title={t('viewer.3d.resetView')}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M15 3h6v6\"/><path d=\"M9 21H3v-6\"/><path d=\"M21 3l-7 7\"/><path d=\"M3 21l7-7\"/></svg>\n </button>\n <button type=\"button\" className=\"ycw-3d-btn\" onClick={handleDownload} title={t('viewer.fallback.download')}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/><polyline points=\"7 10 12 15 17 10\"/><line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\"/></svg>\n </button>\n </div>\n </div>\n <div className=\"ycw-3d-canvas\" ref={containerRef}>\n {loading && (\n <div className=\"ycw-3d-overlay\">\n <div className=\"ycw-3d-spinner\" />\n <span>{t('viewer.loading3d')}</span>\n </div>\n )}\n {error && (\n <div className=\"ycw-3d-overlay ycw-3d-error\">\n <span>⚠️ {error}</span>\n <button type=\"button\" className=\"ycw-3d-btn\" onClick={handleDownload}>{t('viewer.fallback.download')}</button>\n </div>\n )}\n </div>\n </div>\n )\n}\n\nexport default ThreeViewerCore\n"],"mappings":";;;;;;;;;;;AAAA,SAAgB,WAAW,UAAU,mBAAmB;AACxD,YAAY,WAAW;AACvB,SAAS,iBAAiB;AAC1B,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB;AA0HtB,cAGI,YAHJ;AAhHR,IAAM,mBAAmB,IAAU,2BAAqB;AAAA,EACtD,OAAO;AAAA,EACP,WAAW;AAAA,EACX,WAAW;AAAA,EACX,MAAY;AAAA,EACZ,iBAAiB;AACnB,CAAC;AAED,SAAS,kBAAkB,MAAsB;AAC/C,QAAM,QAAQ,KAAK,YAAY;AAC/B,MAAI,MAAM,SAAS,MAAM,EAAG,QAAO;AACnC,MAAI,MAAM,SAAS,MAAM,EAAG,QAAO;AACnC,MAAI,MAAM,SAAS,MAAM,KAAK,MAAM,SAAS,OAAO,EAAG,QAAO;AAC9D,MAAI,MAAM,SAAS,MAAM,EAAG,QAAO;AACnC,SAAO;AACT;AAEA,IAAM,kBAAkD,CAAC,EAAE,KAAK,SAAS,MAAM;AAC7E,QAAM,EAAE,EAAE,IAAI,kBAAkB;AAChC,QAAM,kBAAkB,uBAAuB;AAC/C,QAAM,EAAE,cAAc,WAAW,WAAW,WAAW,gBAAgB,IAAI,cAAc;AACzF,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AAEtD,YAAU,MAAM;AACd,UAAM,IAAI,UAAU;AACpB,QAAI,CAAC,KAAK,CAAC,IAAK;AAEhB,eAAW,IAAI;AACf,aAAS,IAAI;AAEb,UAAM,SAAS,kBAAkB,QAAQ;AACzC,QAAI,YAAY;AAEhB,UAAM,SAAS,CAAC,QAAwB;AACtC,UAAI,UAAW;AACf,QAAE,MAAM,IAAI,GAAG;AACf,QAAE,WAAW,GAAG;AAChB,iBAAW,KAAK;AAAA,IAClB;AAEA,UAAM,UAAU,CAAC,MAAe;AAC9B,UAAI,UAAW;AACf,eAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AACnD,iBAAW,KAAK;AAAA,IAClB;AAEA,QAAI;AACF,cAAQ,QAAQ;AAAA,QACd,KAAK,OAAO;AACV,gBAAM,SAAS,IAAI,UAAU;AAC7B,iBAAO,KAAK,KAAK,CAAC,aAAa;AAC7B,gBAAI,UAAW;AACf,qBAAS,qBAAqB;AAC9B,kBAAM,OAAO,IAAU,WAAK,UAAU,iBAAiB,MAAM,CAAC;AAC9D,mBAAO,IAAI;AAAA,UACb,GAAG,QAAW,OAAO;AACrB;AAAA,QACF;AAAA,QACA,KAAK,OAAO;AACV,gBAAM,SAAS,IAAI,UAAU;AAC7B,iBAAO,KAAK,KAAK,CAAC,UAAU;AAC1B,kBAAM,SAAS,WAAS;AACtB,kBAAI,iBAAuB,cAAQ,CAAC,MAAM,UAAU;AAClD,sBAAM,WAAW,iBAAiB,MAAM;AAAA,cAC1C;AAAA,YACF,CAAC;AACD,mBAAO,KAAK;AAAA,UACd,GAAG,QAAW,OAAO;AACrB;AAAA,QACF;AAAA,QACA,KAAK,QAAQ;AACX,gBAAM,SAAS,IAAI,WAAW;AAC9B,iBAAO,KAAK,KAAK,CAAC,SAAS;AACzB,mBAAO,KAAK,KAAK;AAAA,UACnB,GAAG,QAAW,OAAO;AACrB;AAAA,QACF;AAAA,QACA,KAAK,OAAO;AACV,gBAAM,SAAS,IAAI,cAAc;AACjC,iBAAO,KAAK,KAAK,CAAC,UAAU;AAC1B,kBAAM,SAAS,WAAS;AACtB,kBAAI,iBAAuB,cAAQ,CAAC,MAAM,UAAU;AAClD,sBAAM,WAAW,iBAAiB,MAAM;AAAA,cAC1C;AAAA,YACF,CAAC;AACD,mBAAO,KAAK;AAAA,UACd,GAAG,QAAW,OAAO;AACrB;AAAA,QACF;AAAA,QACA;AACE,mBAAS,0BAA0B,MAAM,EAAE;AAC3C,qBAAW,KAAK;AAAA,MACpB;AAAA,IACF,SAAS,GAAG;AACV,cAAQ,CAAC;AAAA,IACX;AAEA,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAK;AAAA,EAClC,GAAG,CAAC,KAAK,UAAU,SAAS,CAAC;AAE7B,QAAM,iBAAiB,YAAY,MAAM;AACvC,oBAAgB,iBAAiB,UAAU,EAAE,QAAQ,YAAY,CAAC;AAClE,UAAM,IAAI,SAAS,cAAc,GAAG;AACpC,MAAE,OAAO;AACT,MAAE,WAAW;AACb,MAAE,MAAM;AAAA,EACV,GAAG,CAAC,KAAK,UAAU,eAAe,CAAC;AAEnC,SACE,qBAAC,SAAI,WAAU,sBACb;AAAA,yBAAC,SAAI,WAAU,kBACb;AAAA,0BAAC,UAAK,WAAU,mBAAkB,OAAO,UAAW,oBAAS;AAAA,MAC7D,qBAAC,SAAI,WAAU,0BACb;AAAA,4BAAC,YAAO,MAAK,UAAS,WAAW,aAAa,YAAY,YAAY,EAAE,IAAI,SAAS,iBAAiB,OAAO,EAAE,qBAAqB,GAClI,+BAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI;AAAA,8BAAC,UAAK,GAAE,6BAA2B;AAAA,UAAE,oBAAC,UAAK,GAAE,mBAAiB;AAAA,UAAE,oBAAC,UAAK,GAAE,mBAAiB;AAAA,WAAE,GAC/L;AAAA,QACA,oBAAC,YAAO,MAAK,UAAS,WAAU,cAAa,SAAS,WAAW,OAAO,EAAE,qBAAqB,GAC7F,+BAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI;AAAA,8BAAC,UAAK,GAAE,aAAW;AAAA,UAAE,oBAAC,UAAK,GAAE,cAAY;AAAA,UAAE,oBAAC,UAAK,GAAE,cAAY;AAAA,UAAE,oBAAC,UAAK,GAAE,aAAW;AAAA,WAAE,GAC1L;AAAA,QACA,oBAAC,YAAO,MAAK,UAAS,WAAU,cAAa,SAAS,gBAAgB,OAAO,EAAE,0BAA0B,GACvG,+BAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI;AAAA,8BAAC,UAAK,GAAE,6CAA2C;AAAA,UAAE,oBAAC,cAAS,QAAO,oBAAkB;AAAA,UAAE,oBAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAG;AAAA,WAAE,GACpO;AAAA,SACF;AAAA,OACF;AAAA,IACA,qBAAC,SAAI,WAAU,iBAAgB,KAAK,cACjC;AAAA,iBACC,qBAAC,SAAI,WAAU,kBACb;AAAA,4BAAC,SAAI,WAAU,kBAAiB;AAAA,QAChC,oBAAC,UAAM,YAAE,kBAAkB,GAAE;AAAA,SAC/B;AAAA,MAED,SACC,qBAAC,SAAI,WAAU,+BACb;AAAA,6BAAC,UAAK;AAAA;AAAA,UAAI;AAAA,WAAM;AAAA,QAChB,oBAAC,YAAO,MAAK,UAAS,WAAU,cAAa,SAAS,gBAAiB,YAAE,0BAA0B,GAAE;AAAA,SACvG;AAAA,OAEJ;AAAA,KACF;AAEJ;AAEA,IAAO,0BAAQ;","names":[]}
|
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
useResource,
|
|
4
4
|
useResourceContext
|
|
5
5
|
} from "./chunk-GAMA3VA7.js";
|
|
6
|
-
import "./chunk-7D4SUZUM.js";
|
|
7
6
|
|
|
8
7
|
// src/components/JsonRender/domain/WordViewer.tsx
|
|
9
8
|
import React, { useEffect } from "react";
|
|
@@ -17,7 +16,7 @@ var SHEET = `
|
|
|
17
16
|
}
|
|
18
17
|
.jr-word-viewer--error { color: var(--jr-danger, #ef4444); }
|
|
19
18
|
`;
|
|
20
|
-
var LazyWordCore = React.lazy(() => import("./WordCore-
|
|
19
|
+
var LazyWordCore = React.lazy(() => import("./WordCore-QFG5HTYD.js"));
|
|
21
20
|
var WordViewer = ({ props, emit }) => {
|
|
22
21
|
injectStyles(STYLE_ID, SHEET);
|
|
23
22
|
const res = useResource({ resource_id: props.resource_id, url: props.url });
|
|
@@ -58,4 +57,4 @@ export {
|
|
|
58
57
|
WordViewer,
|
|
59
58
|
WordViewer_default as default
|
|
60
59
|
};
|
|
61
|
-
//# sourceMappingURL=WordViewer-
|
|
60
|
+
//# sourceMappingURL=WordViewer-7XUQFS4A.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/JsonRender/domain/WordViewer.tsx"],"sourcesContent":["import React, { useEffect } from 'react'\nimport { useResource } from '../../../hooks/useResource.js'\nimport { useResourceContext } from '../../../contexts/ResourceContext.js'\nimport { injectStyles } from './injectStyles.js'\n\nconst STYLE_ID = 'jr-styles-word-viewer'\nconst SHEET = `\n.jr-word-viewer { width: 100%; min-width: 0; max-width: 100%; min-height: 400px; }\n.jr-word-viewer--loading, .jr-word-viewer--error {\n padding: 1rem; font-family: var(--jr-font, system-ui, sans-serif);\n color: var(--jr-text-muted, #64748b);\n}\n.jr-word-viewer--error { color: var(--jr-danger, #ef4444); }\n`\n\ninterface Props {\n props: {\n resource_id?: string\n url?: string\n title?: string\n }\n emit?: (event: string, data?: unknown) => void\n}\n\nconst LazyWordCore = React.lazy(() => import('../../ViewerCore/WordCore.js'))\n\nexport const WordViewer: React.FC<Props> = ({ props, emit }) => {\n injectStyles(STYLE_ID, SHEET)\n const res = useResource({ resource_id: props.resource_id, url: props.url })\n\n useEffect(() => {\n if (res.loading) return\n if (res.error) {\n emit?.('viewer:error', { resource_id: props.resource_id, error: res.error })\n } else {\n emit?.('viewer:loaded', { resource_id: props.resource_id, mimeType: res.mimeType, fileName: res.fileName })\n }\n }, [res.loading, res.error])\n\n const ctx = useResourceContext()\n\n if (res.loading) return <div className=\"jr-word-viewer jr-word-viewer--loading\">Loading…</div>\n if (res.error) return <div className=\"jr-word-viewer jr-word-viewer--error\">{res.error}</div>\n\n const src = res.url\n const isLegacy = res.fileName?.match(/\\.doc$/i)\n\n if (isLegacy && ctx?.resolvePreviewUrl && props.resource_id) {\n return <LegacyFallback resourceId={props.resource_id} ctx={ctx} />\n }\n\n if (!src) return <div className=\"jr-word-viewer jr-word-viewer--error\">No document source</div>\n\n return (\n <div className=\"jr-word-viewer ycw-word-viewer\">\n <React.Suspense fallback={<div className=\"jr-word-viewer--loading\">Loading Word viewer…</div>}>\n <LazyWordCore src={src} />\n </React.Suspense>\n </div>\n )\n}\n\nconst LegacyFallback: React.FC<{ resourceId: string; ctx: { resolvePreviewUrl?(id: string, fmt: 'html' | 'pdf'): Promise<string> } }> = ({ resourceId, ctx }) => {\n const [previewUrl, setPreviewUrl] = React.useState<string>()\n const [error, setError] = React.useState<string>()\n\n React.useEffect(() => {\n ctx.resolvePreviewUrl?.(resourceId, 'html')\n .then(url => setPreviewUrl(url))\n .catch(err => setError(String(err?.message ?? err)))\n }, [resourceId, ctx])\n\n if (error) return <div className=\"jr-word-viewer jr-word-viewer--error\">.doc preview failed: {error}</div>\n if (!previewUrl) return <div className=\"jr-word-viewer jr-word-viewer--loading\">Converting .doc…</div>\n\n return (\n <div className=\"jr-word-viewer\">\n <iframe src={previewUrl} title=\"Word Preview\" style={{ width: '100%', height: 600, border: 'none' }} />\n </div>\n )\n}\n\nexport default WordViewer\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/components/JsonRender/domain/WordViewer.tsx"],"sourcesContent":["import React, { useEffect } from 'react'\nimport { useResource } from '../../../hooks/useResource.js'\nimport { useResourceContext } from '../../../contexts/ResourceContext.js'\nimport { injectStyles } from './injectStyles.js'\n\nconst STYLE_ID = 'jr-styles-word-viewer'\nconst SHEET = `\n.jr-word-viewer { width: 100%; min-width: 0; max-width: 100%; min-height: 400px; }\n.jr-word-viewer--loading, .jr-word-viewer--error {\n padding: 1rem; font-family: var(--jr-font, system-ui, sans-serif);\n color: var(--jr-text-muted, #64748b);\n}\n.jr-word-viewer--error { color: var(--jr-danger, #ef4444); }\n`\n\ninterface Props {\n props: {\n resource_id?: string\n url?: string\n title?: string\n }\n emit?: (event: string, data?: unknown) => void\n}\n\nconst LazyWordCore = React.lazy(() => import('../../ViewerCore/WordCore.js'))\n\nexport const WordViewer: React.FC<Props> = ({ props, emit }) => {\n injectStyles(STYLE_ID, SHEET)\n const res = useResource({ resource_id: props.resource_id, url: props.url })\n\n useEffect(() => {\n if (res.loading) return\n if (res.error) {\n emit?.('viewer:error', { resource_id: props.resource_id, error: res.error })\n } else {\n emit?.('viewer:loaded', { resource_id: props.resource_id, mimeType: res.mimeType, fileName: res.fileName })\n }\n }, [res.loading, res.error])\n\n const ctx = useResourceContext()\n\n if (res.loading) return <div className=\"jr-word-viewer jr-word-viewer--loading\">Loading…</div>\n if (res.error) return <div className=\"jr-word-viewer jr-word-viewer--error\">{res.error}</div>\n\n const src = res.url\n const isLegacy = res.fileName?.match(/\\.doc$/i)\n\n if (isLegacy && ctx?.resolvePreviewUrl && props.resource_id) {\n return <LegacyFallback resourceId={props.resource_id} ctx={ctx} />\n }\n\n if (!src) return <div className=\"jr-word-viewer jr-word-viewer--error\">No document source</div>\n\n return (\n <div className=\"jr-word-viewer ycw-word-viewer\">\n <React.Suspense fallback={<div className=\"jr-word-viewer--loading\">Loading Word viewer…</div>}>\n <LazyWordCore src={src} />\n </React.Suspense>\n </div>\n )\n}\n\nconst LegacyFallback: React.FC<{ resourceId: string; ctx: { resolvePreviewUrl?(id: string, fmt: 'html' | 'pdf'): Promise<string> } }> = ({ resourceId, ctx }) => {\n const [previewUrl, setPreviewUrl] = React.useState<string>()\n const [error, setError] = React.useState<string>()\n\n React.useEffect(() => {\n ctx.resolvePreviewUrl?.(resourceId, 'html')\n .then(url => setPreviewUrl(url))\n .catch(err => setError(String(err?.message ?? err)))\n }, [resourceId, ctx])\n\n if (error) return <div className=\"jr-word-viewer jr-word-viewer--error\">.doc preview failed: {error}</div>\n if (!previewUrl) return <div className=\"jr-word-viewer jr-word-viewer--loading\">Converting .doc…</div>\n\n return (\n <div className=\"jr-word-viewer\">\n <iframe src={previewUrl} title=\"Word Preview\" style={{ width: '100%', height: 600, border: 'none' }} />\n </div>\n )\n}\n\nexport default WordViewer\n"],"mappings":";;;;;;;AAAA,OAAO,SAAS,iBAAiB;AAyCP,cA+BN,YA/BM;AApC1B,IAAM,WAAW;AACjB,IAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBd,IAAM,eAAe,MAAM,KAAK,MAAM,OAAO,wBAA8B,CAAC;AAErE,IAAM,aAA8B,CAAC,EAAE,OAAO,KAAK,MAAM;AAC9D,eAAa,UAAU,KAAK;AAC5B,QAAM,MAAM,YAAY,EAAE,aAAa,MAAM,aAAa,KAAK,MAAM,IAAI,CAAC;AAE1E,YAAU,MAAM;AACd,QAAI,IAAI,QAAS;AACjB,QAAI,IAAI,OAAO;AACb,aAAO,gBAAgB,EAAE,aAAa,MAAM,aAAa,OAAO,IAAI,MAAM,CAAC;AAAA,IAC7E,OAAO;AACL,aAAO,iBAAiB,EAAE,aAAa,MAAM,aAAa,UAAU,IAAI,UAAU,UAAU,IAAI,SAAS,CAAC;AAAA,IAC5G;AAAA,EACF,GAAG,CAAC,IAAI,SAAS,IAAI,KAAK,CAAC;AAE3B,QAAM,MAAM,mBAAmB;AAE/B,MAAI,IAAI,QAAS,QAAO,oBAAC,SAAI,WAAU,0CAAyC,2BAAQ;AACxF,MAAI,IAAI,MAAO,QAAO,oBAAC,SAAI,WAAU,wCAAwC,cAAI,OAAM;AAEvF,QAAM,MAAM,IAAI;AAChB,QAAM,WAAW,IAAI,UAAU,MAAM,SAAS;AAE9C,MAAI,YAAY,KAAK,qBAAqB,MAAM,aAAa;AAC3D,WAAO,oBAAC,kBAAe,YAAY,MAAM,aAAa,KAAU;AAAA,EAClE;AAEA,MAAI,CAAC,IAAK,QAAO,oBAAC,SAAI,WAAU,wCAAuC,gCAAkB;AAEzF,SACE,oBAAC,SAAI,WAAU,kCACb,8BAAC,MAAM,UAAN,EAAe,UAAU,oBAAC,SAAI,WAAU,2BAA0B,uCAAoB,GACrF,8BAAC,gBAAa,KAAU,GAC1B,GACF;AAEJ;AAEA,IAAM,iBAAkI,CAAC,EAAE,YAAY,IAAI,MAAM;AAC/J,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAiB;AAC3D,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAiB;AAEjD,QAAM,UAAU,MAAM;AACpB,QAAI,oBAAoB,YAAY,MAAM,EACvC,KAAK,SAAO,cAAc,GAAG,CAAC,EAC9B,MAAM,SAAO,SAAS,OAAO,KAAK,WAAW,GAAG,CAAC,CAAC;AAAA,EACvD,GAAG,CAAC,YAAY,GAAG,CAAC;AAEpB,MAAI,MAAO,QAAO,qBAAC,SAAI,WAAU,wCAAuC;AAAA;AAAA,IAAsB;AAAA,KAAM;AACpG,MAAI,CAAC,WAAY,QAAO,oBAAC,SAAI,WAAU,0CAAyC,mCAAgB;AAEhG,SACE,oBAAC,SAAI,WAAU,kBACb,8BAAC,YAAO,KAAK,YAAY,OAAM,gBAAe,OAAO,EAAE,OAAO,QAAQ,QAAQ,KAAK,QAAQ,OAAO,GAAG,GACvG;AAEJ;AAEA,IAAO,qBAAQ;","names":[]}
|
|
@@ -272,6 +272,45 @@ var zhCN = {
|
|
|
272
272
|
"modelPicker.chip.aria": "{{title}} \u6E20\u9053",
|
|
273
273
|
"modelPicker.chip.title.available": "\u6E20\u9053 {{channel}} \xB7 \u6A21\u578B {{name}}",
|
|
274
274
|
"modelPicker.chip.title.unavailable": "\u6E20\u9053 {{channel}} \xB7 \u5F53\u524D\u4E0D\u53EF\u7528",
|
|
275
|
+
"modelPicker.search.placeholder": "\u641C\u7D22\u6A21\u578B\uFF0C\u5982 gpt5\u3001claude opus\u2026",
|
|
276
|
+
"modelPicker.search.aria": "\u641C\u7D22\u6A21\u578B",
|
|
277
|
+
"modelPicker.search.clear.aria": "\u6E05\u7A7A\u641C\u7D22",
|
|
278
|
+
"modelPicker.modality.aria": "\u6309\u80FD\u529B\u7B5B\u9009",
|
|
279
|
+
"modelPicker.modality.all": "\u5168\u90E8",
|
|
280
|
+
"modelPicker.modality.chat": "\u5BF9\u8BDD",
|
|
281
|
+
"modelPicker.modality.image": "\u56FE\u50CF",
|
|
282
|
+
"modelPicker.modality.video": "\u89C6\u9891",
|
|
283
|
+
"modelPicker.modality.audio": "\u8BED\u97F3",
|
|
284
|
+
"modelPicker.modality.embedding": "\u5411\u91CF",
|
|
285
|
+
"modelPicker.modality.realtime": "\u5B9E\u65F6",
|
|
286
|
+
"modelPicker.section.recent": "\u6700\u8FD1\u4F7F\u7528",
|
|
287
|
+
"modelPicker.section.vendor": "{{vendor}}",
|
|
288
|
+
"modelPicker.section.toggle.expand": "\u5C55\u5F00 {{vendor}}",
|
|
289
|
+
"modelPicker.section.toggle.collapse": "\u6298\u53E0 {{vendor}}",
|
|
290
|
+
"modelPicker.empty.title": "\u6CA1\u6709\u5339\u914D\u7684\u6A21\u578B",
|
|
291
|
+
"modelPicker.empty.hint": "\u8BD5\u8BD5\u6E05\u7A7A\u641C\u7D22\u6216\u6362\u4E00\u4E2A\u80FD\u529B\u5206\u7C7B",
|
|
292
|
+
"modelPicker.vendor.openai": "OpenAI",
|
|
293
|
+
"modelPicker.vendor.anthropic": "Anthropic",
|
|
294
|
+
"modelPicker.vendor.google": "Google",
|
|
295
|
+
"modelPicker.vendor.xai": "xAI",
|
|
296
|
+
"modelPicker.vendor.alibaba": "\u963F\u91CC",
|
|
297
|
+
"modelPicker.vendor.zhipu": "\u667A\u8C31",
|
|
298
|
+
"modelPicker.vendor.moonshot": "\u6708\u4E4B\u6697\u9762",
|
|
299
|
+
"modelPicker.vendor.bytedance": "\u5B57\u8282",
|
|
300
|
+
"modelPicker.vendor.deepseek": "DeepSeek",
|
|
301
|
+
"modelPicker.vendor.minimax": "MiniMax",
|
|
302
|
+
"modelPicker.vendor.openrouter": "OpenRouter",
|
|
303
|
+
"modelPicker.vendor.xiaomi": "\u5C0F\u7C73",
|
|
304
|
+
"modelPicker.vendor.other": "\u5176\u4ED6",
|
|
305
|
+
"modelPicker.cap.aria": "\u6A21\u578B\u80FD\u529B",
|
|
306
|
+
"modelPicker.cap.image.title": "\u56FE\u50CF\u7406\u89E3\uFF08\u53EF\u8BFB\u53D6\u56FE\u7247\u8F93\u5165\uFF09",
|
|
307
|
+
"modelPicker.cap.video.native.title": "\u539F\u751F\u89C6\u9891\u63A8\u7406",
|
|
308
|
+
"modelPicker.cap.video.derived.title": "\u89C6\u9891\u63A8\u7406\uFF08\u901A\u8FC7\u56FE\u50CF\u7406\u89E3\u80FD\u529B\u884D\u751F\uFF0C\u6309\u5E27\u91C7\u6837\u5904\u7406\uFF09",
|
|
309
|
+
"modelPicker.cap.audio.title": "\u8BED\u97F3\u8F93\u5165\u7406\u89E3",
|
|
310
|
+
"modelPicker.cap.tools.title": "\u5DE5\u5177\u8C03\u7528 / Function Call",
|
|
311
|
+
"modelPicker.cap.imageGen.title": "\u56FE\u50CF\u751F\u6210",
|
|
312
|
+
"modelPicker.cap.videoGen.title": "\u89C6\u9891\u751F\u6210",
|
|
313
|
+
"modelPicker.cap.audioGen.title": "\u97F3\u9891\u751F\u6210 / TTS / \u97F3\u4E50\u5408\u6210",
|
|
275
314
|
"jr.confirmDialog.cancel": "\u53D6\u6D88",
|
|
276
315
|
"jr.confirmDialog.confirm": "\u786E\u8BA4",
|
|
277
316
|
"jr.confirmDialog.loading": "\u5904\u7406\u4E2D"
|
|
@@ -549,6 +588,45 @@ var enUS = {
|
|
|
549
588
|
"modelPicker.chip.aria": "{{title}} channels",
|
|
550
589
|
"modelPicker.chip.title.available": "Channel {{channel}} \xB7 model {{name}}",
|
|
551
590
|
"modelPicker.chip.title.unavailable": "Channel {{channel}} \xB7 currently unavailable",
|
|
591
|
+
"modelPicker.search.placeholder": "Search models \u2014 e.g. gpt5, claude opus\u2026",
|
|
592
|
+
"modelPicker.search.aria": "Search models",
|
|
593
|
+
"modelPicker.search.clear.aria": "Clear search",
|
|
594
|
+
"modelPicker.modality.aria": "Filter by capability",
|
|
595
|
+
"modelPicker.modality.all": "All",
|
|
596
|
+
"modelPicker.modality.chat": "Chat",
|
|
597
|
+
"modelPicker.modality.image": "Image",
|
|
598
|
+
"modelPicker.modality.video": "Video",
|
|
599
|
+
"modelPicker.modality.audio": "Audio",
|
|
600
|
+
"modelPicker.modality.embedding": "Embedding",
|
|
601
|
+
"modelPicker.modality.realtime": "Realtime",
|
|
602
|
+
"modelPicker.section.recent": "Recent",
|
|
603
|
+
"modelPicker.section.vendor": "{{vendor}}",
|
|
604
|
+
"modelPicker.section.toggle.expand": "Expand {{vendor}}",
|
|
605
|
+
"modelPicker.section.toggle.collapse": "Collapse {{vendor}}",
|
|
606
|
+
"modelPicker.empty.title": "No models match",
|
|
607
|
+
"modelPicker.empty.hint": "Try clearing the search or switching capability",
|
|
608
|
+
"modelPicker.vendor.openai": "OpenAI",
|
|
609
|
+
"modelPicker.vendor.anthropic": "Anthropic",
|
|
610
|
+
"modelPicker.vendor.google": "Google",
|
|
611
|
+
"modelPicker.vendor.xai": "xAI",
|
|
612
|
+
"modelPicker.vendor.alibaba": "Alibaba",
|
|
613
|
+
"modelPicker.vendor.zhipu": "Zhipu",
|
|
614
|
+
"modelPicker.vendor.moonshot": "Moonshot",
|
|
615
|
+
"modelPicker.vendor.bytedance": "ByteDance",
|
|
616
|
+
"modelPicker.vendor.deepseek": "DeepSeek",
|
|
617
|
+
"modelPicker.vendor.minimax": "MiniMax",
|
|
618
|
+
"modelPicker.vendor.openrouter": "OpenRouter",
|
|
619
|
+
"modelPicker.vendor.xiaomi": "Xiaomi",
|
|
620
|
+
"modelPicker.vendor.other": "Other",
|
|
621
|
+
"modelPicker.cap.aria": "Model capabilities",
|
|
622
|
+
"modelPicker.cap.image.title": "Vision (accepts image input)",
|
|
623
|
+
"modelPicker.cap.video.native.title": "Native video understanding",
|
|
624
|
+
"modelPicker.cap.video.derived.title": "Video understanding (derived from vision via frame sampling)",
|
|
625
|
+
"modelPicker.cap.audio.title": "Audio input understanding",
|
|
626
|
+
"modelPicker.cap.tools.title": "Tool calling / function call",
|
|
627
|
+
"modelPicker.cap.imageGen.title": "Image generation",
|
|
628
|
+
"modelPicker.cap.videoGen.title": "Video generation",
|
|
629
|
+
"modelPicker.cap.audioGen.title": "Audio generation / TTS / music synthesis",
|
|
552
630
|
"jr.confirmDialog.cancel": "Cancel",
|
|
553
631
|
"jr.confirmDialog.confirm": "Confirm",
|
|
554
632
|
"jr.confirmDialog.loading": "Processing"
|
|
@@ -592,4 +670,4 @@ export {
|
|
|
592
670
|
I18nContext,
|
|
593
671
|
useChatWidgetI18n
|
|
594
672
|
};
|
|
595
|
-
//# sourceMappingURL=chunk-
|
|
673
|
+
//# sourceMappingURL=chunk-3CNQONCV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/i18n/messages.ts","../src/i18n/context.ts"],"sourcesContent":["export interface ChatWidgetMessages {\n 'header.title': string\n 'header.icon': string\n 'status.connecting': string\n 'status.running': string\n 'status.compressing': string\n 'status.error': string\n 'status.idle': string\n 'empty.waiting': string\n 'empty.icon': string\n 'round.separator': string\n 'round.status.running': string\n 'round.status.completed': string\n 'round.status.error': string\n 'round.noMessage': string\n 'footer.attribution': string\n 'selection.ask': string\n 'viewer.loading': string\n 'viewer.error': string\n 'viewer.back': string\n 'viewer.defaultTitle': string\n 'viewer.copyFull': string\n 'viewer.copyFullTitle': string\n 'viewer.referenceFile': string\n 'viewer.referenceFileTitle': string\n 'viewer.referencePage': string\n 'viewer.referencePageTitle': string\n 'viewer.download': string\n 'viewer.fullscreen': string\n 'viewer.fullscreenExit': string\n 'viewer.close': string\n 'viewer.unknownType': string\n 'viewer.iframeHint': string\n 'viewer.copySnippet': string\n 'viewer.loadingPdf': string\n 'viewer.pdfPages': string\n 'viewer.loadingKicad': string\n 'viewer.loading3d': string\n 'viewer.loadingStep': string\n 'viewer.3d.wireframe': string\n 'viewer.3d.resetView': string\n 'viewer.gerberTitle': string\n 'viewer.gerberBlobWarning': string\n 'viewer.gerberNoHttpUrl': string\n 'viewer.pdfPreview': string\n 'viewer.htmlPreview': string\n 'viewer.htmlProjectLoading': string\n 'viewer.htmlProjectNoEntry': string\n 'viewer.htmlProjectSizeLimit': string\n 'viewer.htmlStrategyForcedInlineWarning': string\n 'viewer.htmlStrategyFallbackCspWarning': string\n 'viewer.copyFullKicadTitle': string\n 'viewer.zoomIn': string\n 'viewer.zoomOut': string\n 'viewer.zoomReset': string\n 'viewer.loadingWord': string\n 'viewer.loadingExcel': string\n 'viewer.loadingPowerPoint': string\n 'viewer.pptPrev': string\n 'viewer.pptNext': string\n 'viewer.pptSlide': string\n 'viewer.pptThumbnails': string\n 'viewer.excelRows': string\n 'viewer.excelColumns': string\n 'childAgent.status.running': string\n 'childAgent.status.completed': string\n 'hitl.form.defaultTitle': string\n 'hitl.wait.default': string\n 'todo.completed.count': string\n 'todo.blocked.count': string\n 'todo.more': string\n 'todo.header.done': string\n 'tool.phase.generating': string\n 'tool.phase.executing': string\n 'tool.phase.complete': string\n 'tool.phase.error': string\n 'tool.executing': string\n 'tool.mcp.running': string\n 'tool.mcp.success': string\n 'tool.mcp.error': string\n 'form.placeholder.select': string\n 'form.required.default': string\n 'form.submit.submit': string\n 'form.submit.submitting': string\n 'form.requestId': string\n 'pinned.label': string\n 'plan.title': string\n 'plan.step': string\n 'thinking.inProgress': string\n 'thinking.completed': string\n 'split.unreadCount': string\n 'split.askQuestion': string\n 'split.exitFullscreen': string\n 'context.inputPlaceholder': string\n 'context.inputPlaceholderWithFile': string\n 'context.send': string\n 'context.removeReference': string\n 'split.home': string\n 'split.workspace': string\n 'split.annotation': string\n 'split.tabClose': string\n 'split.tabNew': string\n 'workspace.title': string\n 'workspace.searchPlaceholder': string\n 'workspace.empty': string\n 'workspace.downloadAll': string\n 'workspace.recent': string\n 'workspace.open': string\n 'workspace.openInNewTab': string\n 'workspace.download': string\n 'workspace.copyPath': string\n 'workspace.expandAll': string\n 'workspace.collapseAll': string\n 'annotation.title': string\n 'annotation.empty': string\n 'annotation.fileLevelTitle': string\n 'annotation.fileLevelPlaceholder': string\n 'annotation.anchoredPlaceholder': string\n 'annotation.inlineInputPlaceholder': string\n 'annotation.replyPlaceholder': string\n 'annotation.anchorLabel': string\n 'annotation.close': string\n 'annotation.fabLabel': string\n 'annotation.fabHeader': string\n 'annotation.messageCount': string\n 'annotation.anchorInvalid': string\n 'annotation.errorRetry': string\n 'annotation.queuedHint': string\n 'annotation.selectionLabel': string\n 'agentControl.pause': string\n 'agentControl.resume': string\n 'agentControl.stop': string\n 'agentControl.paused': string\n 'agentControl.groupTitle': string\n 'aria.fileNavigation': string\n 'kicad.loadFailed': string\n 'kicad.urlNotReady': string\n 'kicad.loadingEngine': string\n 'kicad.sidebarTitle': string\n 'kicad.sidebarPcb': string\n 'kicad.sidebarSch': string\n 'kicad.sidebarGeneric': string\n 'kicad.viewVisual': string\n 'kicad.viewSource': string\n 'provenance.filter.type.agent': string\n 'provenance.filter.type.action': string\n 'provenance.filter.type.file': string\n 'provenance.filter.type.task': string\n 'provenance.filter.type.reasoning': string\n 'provenance.filter.depth': string\n 'provenance.toolbar.zoomToFit': string\n 'provenance.toolbar.resetCamera': string\n 'provenance.toolbar.refresh': string\n 'provenance.legend.reasoning': string\n 'provenance.legend.action': string\n 'provenance.legend.file': string\n 'provenance.legend.task': string\n 'provenance.legend.references': string\n 'provenance.legend.edges': string\n 'provenance.legend.depth': string\n 'provenance.detail.title': string\n 'provenance.detail.noSelection': string\n 'provenance.detail.label.name': string\n 'provenance.detail.label.id': string\n 'provenance.detail.label.timestamp': string\n 'provenance.detail.label.agentId': string\n 'provenance.detail.label.instanceId': string\n 'provenance.detail.label.level': string\n 'provenance.detail.label.status': string\n 'provenance.detail.label.tool': string\n 'provenance.detail.label.purpose': string\n 'provenance.detail.label.duration': string\n 'provenance.detail.label.path': string\n 'provenance.detail.label.operation': string\n 'provenance.detail.label.taskId': string\n 'provenance.detail.label.description': string\n 'provenance.detail.label.model': string\n 'provenance.detail.label.tokenCount': string\n 'provenance.detail.label.reasoningPreview': string\n 'provenance.detail.relatedEdges': string\n 'provenance.page.noSessionHint': string\n 'provenance.page.loading': string\n 'provenance.page.emptyGraph': string\n 'provenance.drawer.emptyGraph': string\n 'provenance.graph.edgeType.references': string\n 'toolResult.label': string\n 'toolResult.expandAll': string\n 'toolResult.searchSummary': string\n 'toolResult.scrapeSummary': string\n 'toolResult.more': string\n 'plan.status.active': string\n 'pinned.noMessage': string\n 'viewer.fallback.unknownType': string\n 'viewer.fallback.download': string\n 'fileSize.B': string\n 'fileSize.KB': string\n 'fileSize.MB': string\n 'thinking.title': string\n 'thinking.step': string\n 'viewer.stepHint': string\n 'viewer.threeHint': string\n 'reference.header': string\n 'history.noMessage': string\n 'agent.defaultName': string\n 'error.unknown': string\n 'locale': string\n 'skill.inlineLabel': string\n 'skill.empty': string\n 'skill.searchPlaceholder': string\n 'skill.removeLabel': string\n 'skill.loading': string\n 'skill.loadError': string\n 'skill.loadMore': string\n 'skill.selectorLabel': string\n 'pool.idle': string\n 'pool.collaborating': string\n /** JETP-083 WS3.7.7 follow-up: badge text when at least one agent is\n * paused on a HIL response (no RUNNING agents). ``{{count}}`` = number\n * of paused agents. */\n 'pool.awaiting': string\n 'pool.title': string\n 'pool.empty': string\n 'pool.state.running': string\n /** JETP-083 WS3.7.7 follow-up: agent-row state label for an agent that\n * is blocked inside ``_await_genui_blocking`` waiting on a human HIL\n * reply. Distinguishes from ``running`` / ``completed`` / ``lost``;\n * mapped from backend ``state=\"PAUSED\"``. */\n 'pool.state.paused': string\n 'pool.state.completed': string\n 'pool.state.lost': string\n 'pool.state.unknown': string\n 'input.placeholder': string\n 'input.placeholderLoading': string\n 'discussion.title': string\n 'discussion.empty': string\n 'discussion.active': string\n 'discussion.resolved': string\n 'discussion.archived': string\n 'round.foreign.label': string\n 'round.foreign.unread': string\n 'round.foreign.expand': string\n 'sidebar.mainChat': string\n 'sidebar.chat': string\n 'sidebar.fileQA': string\n 'sidebar.selectionQA': string\n 'sessionList.title': string\n 'sessionList.newSession': string\n 'sessionList.logout': string\n 'sessionList.loading': string\n 'sessionList.empty': string\n 'sessionList.unsupported': string\n 'sessionList.untitled': string\n 'sessionList.deleteTitle': string\n 'sessionList.deleteConfirm': string\n 'sessionList.prevPage': string\n 'sessionList.nextPage': string\n 'sessionList.pageInfo': string\n // ModelPicker (composer 内的\"本次发送使用的模型\"切换器)\n 'modelPicker.menu.head': string\n 'modelPicker.menu.aria': string\n 'modelPicker.auto.title': string\n 'modelPicker.auto.hint.knownChannel': string\n 'modelPicker.auto.hint.knownBasename': string\n 'modelPicker.auto.hint.fallback': string\n 'modelPicker.row.hint.channelMulti': string\n 'modelPicker.row.hint.channelSingle': string\n 'modelPicker.row.hint.versionMulti': string\n 'modelPicker.fallback.placeholder': string\n 'modelPicker.inert.title': string\n 'modelPicker.guestLocked.label': string\n 'modelPicker.guestLocked.title': string\n 'modelPicker.loadingList': string\n 'modelPicker.trigger.title.stale': string\n 'modelPicker.trigger.title.agentDefault.withChannel': string\n 'modelPicker.trigger.title.agentDefault': string\n 'modelPicker.trigger.title.current': string\n 'modelPicker.row.title.pickDefault': string\n 'modelPicker.row.title.pick': string\n 'modelPicker.chip.aria': string\n 'modelPicker.chip.title.available': string\n 'modelPicker.chip.title.unavailable': string\n // ── Picker UX v2:搜索 + 模态 tab + 最近 + 家族分组 ──\n 'modelPicker.search.placeholder': string\n 'modelPicker.search.aria': string\n 'modelPicker.search.clear.aria': string\n 'modelPicker.modality.aria': string\n 'modelPicker.modality.all': string\n 'modelPicker.modality.chat': string\n 'modelPicker.modality.image': string\n 'modelPicker.modality.video': string\n 'modelPicker.modality.audio': string\n 'modelPicker.modality.embedding': string\n 'modelPicker.modality.realtime': string\n 'modelPicker.section.recent': string\n 'modelPicker.section.vendor': string\n 'modelPicker.section.toggle.expand': string\n 'modelPicker.section.toggle.collapse': string\n 'modelPicker.empty.title': string\n 'modelPicker.empty.hint': string\n 'modelPicker.vendor.openai': string\n 'modelPicker.vendor.anthropic': string\n 'modelPicker.vendor.google': string\n 'modelPicker.vendor.xai': string\n 'modelPicker.vendor.alibaba': string\n 'modelPicker.vendor.zhipu': string\n 'modelPicker.vendor.moonshot': string\n 'modelPicker.vendor.bytedance': string\n 'modelPicker.vendor.deepseek': string\n 'modelPicker.vendor.minimax': string\n 'modelPicker.vendor.openrouter': string\n 'modelPicker.vendor.xiaomi': string\n 'modelPicker.vendor.other': string\n // Capability badges (v2.x: 每个模型尾部的小图标)\n 'modelPicker.cap.aria': string\n 'modelPicker.cap.image.title': string\n 'modelPicker.cap.video.native.title': string\n 'modelPicker.cap.video.derived.title': string\n 'modelPicker.cap.audio.title': string\n 'modelPicker.cap.tools.title': string\n 'modelPicker.cap.imageGen.title': string\n 'modelPicker.cap.videoGen.title': string\n 'modelPicker.cap.audioGen.title': string\n // CWRF-013 Phase 4 P2-T00 — `jr-primitives` i18n namespace\n // (spec drift D-I18N-01: rather than pull in `react-i18next` + `i18next`\n // as the spec D9 originally proposed, we extend the existing chat-widget\n // in-house i18n. Same key semantics, zero new dependency.)\n 'jr.confirmDialog.cancel': string\n 'jr.confirmDialog.confirm': string\n 'jr.confirmDialog.loading': string\n}\n\nexport const zhCN: ChatWidgetMessages = {\n 'header.title': 'YumiAI',\n 'header.icon': '',\n 'status.connecting': '连接中...',\n 'status.running': '执行中...',\n 'status.compressing': '上下文压缩中...',\n 'status.error': '连接错误',\n 'status.idle': '待命',\n 'empty.waiting': '等待对话开始...',\n 'empty.icon': '',\n 'round.separator': '上一轮对话',\n 'round.status.running': '执行中',\n 'round.status.completed': '已完成',\n 'round.status.error': '执行失败',\n 'round.noMessage': '(无消息)',\n 'footer.attribution': '',\n 'selection.ask': '问一下',\n 'viewer.loading': '加载中...',\n 'viewer.error': '无法获取文件内容',\n 'viewer.back': '← 返回',\n 'viewer.defaultTitle': '文件预览',\n 'viewer.copyFull': '复制全文',\n 'viewer.copyFullTitle': '复制全文到剪贴板并引用',\n 'viewer.referenceFile': '引用此文件',\n 'viewer.referenceFileTitle': '引用此文件',\n 'viewer.referencePage': '引用当前页面',\n 'viewer.referencePageTitle': '引用当前页面到对话',\n 'viewer.download': '下载',\n 'viewer.fullscreen': '全屏 (⌘L)',\n 'viewer.fullscreenExit': '退出全屏',\n 'viewer.close': '关闭',\n 'viewer.unknownType': '未知类型',\n 'viewer.iframeHint': 'iframe 内容无法直接选中文本,请使用上方「引用此文件」按钮',\n 'viewer.copySnippet': '复制片段',\n 'viewer.loadingPdf': '加载 PDF 查看器...',\n 'viewer.pdfPages': '共 {{count}} 页',\n 'viewer.loadingKicad': '加载 KiCad 查看器...',\n 'viewer.loading3d': '加载 3D 查看器...',\n 'viewer.loadingStep': '加载 STEP 查看器...',\n 'viewer.gerberTitle': 'DFX Copilot — Gerber 预览',\n 'viewer.gerberBlobWarning':\n 'DFX Copilot 需要从公网可访问的地址拉取文件。当前为本地 blob/data URL,iframe 内无法使用。请在 Adapter 中返回 content_url,或实现 getResourceUrl 提供 HTTPS 预签名链接。',\n 'viewer.gerberNoHttpUrl':\n '当前资源地址不是 http(s),无法嵌入 DFX Copilot。请使用直链或预签名 URL。',\n 'viewer.pdfPreview': 'PDF 预览',\n 'viewer.htmlPreview': 'HTML 预览',\n 'viewer.htmlProjectLoading': '正在加载 HTML 项目文件…',\n 'viewer.htmlProjectNoEntry': 'HTML 项目缺少入口文件(如 index.html),无法预览',\n 'viewer.htmlProjectSizeLimit': 'HTML 项目超出大小限制,仅显示入口文件',\n 'viewer.htmlStrategyForcedInlineWarning': '检测到 ESM 模块,但已强制 inline 策略,可能加载失败',\n 'viewer.htmlStrategyFallbackCspWarning': '宿主 CSP 禁止 blob:,已自动降级到 inline 策略',\n 'viewer.copyFullKicadTitle': '复制全文 KiCad 原文到剪贴板并引用,粘贴到输入框即可带入',\n 'viewer.zoomIn': '放大',\n 'viewer.zoomOut': '缩小',\n 'viewer.zoomReset': '重置',\n 'viewer.loadingWord': '加载 Word 查看器...',\n 'viewer.loadingExcel': '加载 Excel 查看器...',\n 'viewer.loadingPowerPoint': '加载 PowerPoint 查看器...',\n 'viewer.pptPrev': '‹ 上一页',\n 'viewer.pptNext': '下一页 ›',\n 'viewer.pptSlide': '幻灯片',\n 'viewer.pptThumbnails': '缩略图',\n 'viewer.excelRows': '行',\n 'viewer.excelColumns': '列',\n 'childAgent.status.running': '执行中',\n 'childAgent.status.completed': '已完成',\n 'hitl.form.defaultTitle': '请填写表单',\n 'hitl.wait.default': '等待用户输入...',\n 'todo.completed.count': '已完成 {{completed}}/{{total}}',\n 'todo.blocked.count': '{{count}} 项阻塞',\n 'todo.more': '+ {{count}} 更多',\n 'todo.header.done': '已完成',\n 'tool.phase.generating': '生成中',\n 'tool.phase.executing': '执行中',\n 'tool.phase.complete': '完成',\n 'tool.phase.error': '失败',\n 'tool.executing': '执行工具: {{name}}',\n 'tool.mcp.running': '执行中',\n 'tool.mcp.success': '完成',\n 'tool.mcp.error': '失败',\n 'form.placeholder.select': '请选择',\n 'form.required.default': '此项为必填项',\n 'form.submit.submit': '提交',\n 'form.submit.submitting': '提交中...',\n 'form.requestId': '请求 ID: ',\n 'pinned.label': '置顶',\n 'plan.title': '执行计划',\n 'plan.step': '步骤 {{index}}',\n 'thinking.inProgress': '思考中...',\n 'thinking.completed': '思考完成',\n 'split.unreadCount': '{{count}} 条新消息',\n 'split.askQuestion': '提问 (⌘/)',\n 'split.exitFullscreen': '退出全屏 (Esc)',\n 'context.inputPlaceholder': '在这里提问…',\n 'context.inputPlaceholderWithFile': '关于 {{fileName}} 提问…',\n 'context.send': '发送',\n 'context.removeReference': '移除引用',\n 'split.home': '主对话',\n 'split.workspace': '工作空间',\n 'split.annotation': '批注',\n 'split.tabClose': '关闭标签页',\n 'split.tabNew': '新标签页',\n 'workspace.title': '工作空间',\n 'workspace.searchPlaceholder': '搜索文件…',\n 'workspace.empty': '暂无文件',\n 'workspace.downloadAll': '打包下载全部文件',\n 'workspace.recent': '最近修改',\n 'workspace.open': '打开',\n 'workspace.openInNewTab': '在新标签页打开',\n 'workspace.download': '下载',\n 'workspace.copyPath': '复制路径',\n 'workspace.expandAll': '展开全部',\n 'workspace.collapseAll': '折叠全部',\n 'annotation.title': '批注',\n 'annotation.empty': '暂无批注',\n 'annotation.fileLevelTitle': '文件对话',\n 'annotation.fileLevelPlaceholder': '关于此文件提问…',\n 'annotation.anchoredPlaceholder': '关于所选内容提问…',\n 'annotation.inlineInputPlaceholder': '就此处提问…',\n 'annotation.replyPlaceholder': '继续追问…',\n 'annotation.anchorLabel': '锚点: {{text}}',\n 'annotation.close': '关闭',\n 'annotation.fabLabel': '文件批注',\n 'annotation.fabHeader': '{{fileName}} · 文件对话',\n 'annotation.messageCount': '{{count}} 条消息',\n 'annotation.anchorInvalid': '锚点已失效',\n 'annotation.errorRetry': '发送失败,点击重试',\n 'annotation.queuedHint': '排队中,请稍候…',\n 'annotation.selectionLabel': '选中内容',\n 'agentControl.pause': '暂停',\n 'agentControl.resume': '继续',\n 'agentControl.stop': '停止',\n 'agentControl.paused': '已暂停',\n 'agentControl.groupTitle': '工作组',\n 'aria.fileNavigation': '文件导航',\n 'kicad.loadFailed': 'KiCanvas 加载失败,已切换至源码视图',\n 'kicad.urlNotReady': '资源 URL 未就绪,当前显示源码',\n 'kicad.loadingEngine': '加载 KiCanvas 可视化引擎...',\n 'kicad.sidebarTitle': 'KiCanvas 侧栏提供:属性、符号/封装列表、文档信息等',\n 'kicad.sidebarPcb': 'PCB:侧栏可查属性、封装列表',\n 'kicad.sidebarSch': 'SCH:侧栏可查符号/子图属性',\n 'kicad.sidebarGeneric': '侧栏查看属性',\n 'kicad.viewVisual': '可视化',\n 'kicad.viewSource': '源码',\n 'provenance.filter.type.agent': '智能体',\n 'provenance.filter.type.action': '工具',\n 'provenance.filter.type.file': '文件',\n 'provenance.filter.type.task': '任务',\n 'provenance.filter.type.reasoning': '推理',\n 'provenance.filter.depth': '深度:',\n 'provenance.toolbar.zoomToFit': '自适应',\n 'provenance.toolbar.resetCamera': '重置视角',\n 'provenance.toolbar.refresh': '刷新',\n 'provenance.legend.reasoning': '推理',\n 'provenance.legend.action': '工具',\n 'provenance.legend.file': '文件',\n 'provenance.legend.task': '任务',\n 'provenance.legend.references': '引用',\n 'provenance.legend.edges': '边: ',\n 'provenance.legend.depth': '深度: ',\n 'provenance.detail.title': '节点详情',\n 'provenance.detail.noSelection': '未选中节点',\n 'provenance.detail.label.name': '名称',\n 'provenance.detail.label.id': 'ID',\n 'provenance.detail.label.timestamp': '时间',\n 'provenance.detail.label.agentId': 'Agent ID',\n 'provenance.detail.label.instanceId': '实例 ID',\n 'provenance.detail.label.level': '层级',\n 'provenance.detail.label.status': '状态',\n 'provenance.detail.label.tool': '工具',\n 'provenance.detail.label.purpose': '目的',\n 'provenance.detail.label.duration': '耗时',\n 'provenance.detail.label.path': '路径',\n 'provenance.detail.label.operation': '操作',\n 'provenance.detail.label.taskId': '任务 ID',\n 'provenance.detail.label.description': '描述',\n 'provenance.detail.label.model': '模型',\n 'provenance.detail.label.tokenCount': 'Token 数',\n 'provenance.detail.label.reasoningPreview': '推理预览',\n 'provenance.detail.relatedEdges': '关联边 ({{count}})',\n 'provenance.page.noSessionHint': '请通过 URL 参数指定会话: ?session_id=NNN',\n 'provenance.page.loading': '加载推理图谱...',\n 'provenance.page.emptyGraph': '当前会话暂无图谱数据',\n 'provenance.drawer.emptyGraph': '暂无图谱数据',\n 'provenance.graph.edgeType.references': '引用',\n 'toolResult.label': '执行结果',\n 'toolResult.expandAll': '展开全部 ({{count}} 行)',\n 'toolResult.searchSummary': '搜索结果 · {{count}} 条',\n 'toolResult.scrapeSummary': '抓取结果 · {{title}}',\n 'toolResult.more': '+{{count}} more',\n 'plan.status.active': '执行中',\n 'pinned.noMessage': '(无消息内容)',\n 'viewer.fallback.unknownType': '未知类型',\n 'viewer.fallback.download': '下载文件',\n 'fileSize.B': '{{size}} B',\n 'fileSize.KB': '{{size}} KB',\n 'fileSize.MB': '{{size}} MB',\n 'thinking.title': '思考推理',\n 'thinking.step': '步骤 {{step}}',\n 'viewer.stepHint': '鼠标拖拽旋转,滚轮缩放,右键平移',\n 'viewer.threeHint': '鼠标拖拽旋转,滚轮缩放,右键平移',\n 'viewer.3d.wireframe': '线框模式',\n 'viewer.3d.resetView': '重置视角',\n 'reference.header': '[引用文件: {{fileName}}]',\n 'history.noMessage': '(历史消息)',\n 'agent.defaultName': '助手',\n 'error.unknown': '未知错误',\n 'locale': 'zh-CN',\n 'skill.inlineLabel': '先查看并使用{{name}}技能,去解决:',\n 'skill.empty': '暂无可用技能',\n 'skill.searchPlaceholder': '搜索技能...',\n 'skill.removeLabel': '移除技能',\n 'skill.loading': '加载中...',\n 'skill.loadError': '加载技能失败',\n 'skill.loadMore': '加载更多',\n 'skill.selectorLabel': '技能选择',\n 'pool.idle': '待命',\n 'pool.collaborating': '{{count}} 协作中',\n 'pool.awaiting': '{{count}} 等待人工',\n 'pool.title': '智能体池',\n 'pool.empty': '暂无活跃智能体',\n 'pool.state.running': '执行中',\n 'pool.state.paused': '等待人工',\n 'pool.state.completed': '已完成',\n 'pool.state.lost': '已失联',\n 'pool.state.unknown': '未知',\n 'input.placeholder': '输入消息,/ 选择技能',\n 'input.placeholderLoading': '等待回复中…',\n 'discussion.title': '讨论',\n 'discussion.empty': '暂无讨论',\n 'discussion.active': '进行中',\n 'discussion.resolved': '已结论',\n 'discussion.archived': '已归档',\n 'round.foreign.label': '来自其他窗口的对话',\n 'round.foreign.unread': '{{count}} 条新消息',\n 'round.foreign.expand': '点击展开',\n 'sidebar.mainChat': '主对话',\n 'sidebar.chat': '对话',\n 'sidebar.fileQA': '文件问答',\n 'sidebar.selectionQA': '选区问答',\n 'sessionList.title': '历史会话',\n 'sessionList.newSession': '+ 新会话',\n 'sessionList.logout': '退出',\n 'sessionList.loading': '加载中...',\n 'sessionList.empty': '暂无会话',\n 'sessionList.unsupported': '当前 adapter 未实现 listSessions',\n 'sessionList.untitled': '无标题',\n 'sessionList.deleteTitle': '删除会话',\n 'sessionList.deleteConfirm': '确定删除该会话?',\n 'sessionList.prevPage': '←',\n 'sessionList.nextPage': '→',\n 'sessionList.pageInfo': '第 {page} / {totalPages} 页',\n 'modelPicker.menu.head': '本次使用的模型',\n 'modelPicker.menu.aria': '选择本次使用的模型',\n 'modelPicker.auto.title': '默认(跟随 Agent)',\n 'modelPicker.auto.hint.knownChannel': '当前 Agent 默认:{{name}} · {{channel}}',\n 'modelPicker.auto.hint.knownBasename': '当前 Agent 默认:{{name}}',\n 'modelPicker.auto.hint.fallback': '使用 Agent 注册的默认模型,跨子 Agent 自动切换',\n 'modelPicker.row.hint.channelMulti': '{{available}}/{{total}} 个渠道可用',\n 'modelPicker.row.hint.channelSingle': '渠道:{{channel}}',\n 'modelPicker.row.hint.versionMulti': '{{count}} 个版本可用',\n 'modelPicker.fallback.placeholder': '默认模型',\n 'modelPicker.inert.title': '模型选择当前不可用',\n 'modelPicker.guestLocked.label': '默认模型 · 登录后可选',\n 'modelPicker.guestLocked.title': '登录后可在多个模型间切换;游客先用默认模型即可开干。',\n 'modelPicker.loadingList': '加载模型清单…',\n 'modelPicker.trigger.title.stale': '{{name}}(已不在清单中,发送时仍会尝试使用)',\n 'modelPicker.trigger.title.agentDefault.withChannel':\n '当前 Agent 默认:{{name}} · {{channel}}(发送时跟随 Agent)',\n 'modelPicker.trigger.title.agentDefault': '当前 Agent 默认:{{name}}(发送时跟随 Agent)',\n 'modelPicker.trigger.title.current': '当前模型:{{name}}',\n 'modelPicker.row.title.pickDefault': '选默认渠道({{hint}})',\n 'modelPicker.row.title.pick': '选用 {{name}}',\n 'modelPicker.chip.aria': '{{title}} 渠道',\n 'modelPicker.chip.title.available': '渠道 {{channel}} · 模型 {{name}}',\n 'modelPicker.chip.title.unavailable': '渠道 {{channel}} · 当前不可用',\n 'modelPicker.search.placeholder': '搜索模型,如 gpt5、claude opus…',\n 'modelPicker.search.aria': '搜索模型',\n 'modelPicker.search.clear.aria': '清空搜索',\n 'modelPicker.modality.aria': '按能力筛选',\n 'modelPicker.modality.all': '全部',\n 'modelPicker.modality.chat': '对话',\n 'modelPicker.modality.image': '图像',\n 'modelPicker.modality.video': '视频',\n 'modelPicker.modality.audio': '语音',\n 'modelPicker.modality.embedding': '向量',\n 'modelPicker.modality.realtime': '实时',\n 'modelPicker.section.recent': '最近使用',\n 'modelPicker.section.vendor': '{{vendor}}',\n 'modelPicker.section.toggle.expand': '展开 {{vendor}}',\n 'modelPicker.section.toggle.collapse': '折叠 {{vendor}}',\n 'modelPicker.empty.title': '没有匹配的模型',\n 'modelPicker.empty.hint': '试试清空搜索或换一个能力分类',\n 'modelPicker.vendor.openai': 'OpenAI',\n 'modelPicker.vendor.anthropic': 'Anthropic',\n 'modelPicker.vendor.google': 'Google',\n 'modelPicker.vendor.xai': 'xAI',\n 'modelPicker.vendor.alibaba': '阿里',\n 'modelPicker.vendor.zhipu': '智谱',\n 'modelPicker.vendor.moonshot': '月之暗面',\n 'modelPicker.vendor.bytedance': '字节',\n 'modelPicker.vendor.deepseek': 'DeepSeek',\n 'modelPicker.vendor.minimax': 'MiniMax',\n 'modelPicker.vendor.openrouter': 'OpenRouter',\n 'modelPicker.vendor.xiaomi': '小米',\n 'modelPicker.vendor.other': '其他',\n 'modelPicker.cap.aria': '模型能力',\n 'modelPicker.cap.image.title': '图像理解(可读取图片输入)',\n 'modelPicker.cap.video.native.title': '原生视频推理',\n 'modelPicker.cap.video.derived.title': '视频推理(通过图像理解能力衍生,按帧采样处理)',\n 'modelPicker.cap.audio.title': '语音输入理解',\n 'modelPicker.cap.tools.title': '工具调用 / Function Call',\n 'modelPicker.cap.imageGen.title': '图像生成',\n 'modelPicker.cap.videoGen.title': '视频生成',\n 'modelPicker.cap.audioGen.title': '音频生成 / TTS / 音乐合成',\n 'jr.confirmDialog.cancel': '取消',\n 'jr.confirmDialog.confirm': '确认',\n 'jr.confirmDialog.loading': '处理中',\n}\n\nexport const enUS: ChatWidgetMessages = {\n 'header.title': 'AI Assistant',\n 'header.icon': '',\n 'status.connecting': 'Connecting...',\n 'status.running': 'Running...',\n 'status.compressing': 'Compressing context...',\n 'status.error': 'Connection error',\n 'status.idle': 'Idle',\n 'empty.waiting': 'Waiting for conversation...',\n 'empty.icon': '',\n 'round.separator': 'Previous round',\n 'round.status.running': 'Running',\n 'round.status.completed': 'Completed',\n 'round.status.error': 'Failed',\n 'round.noMessage': '(no message)',\n 'footer.attribution': '',\n 'selection.ask': 'Ask',\n 'viewer.loading': 'Loading...',\n 'viewer.error': 'Failed to load file content',\n 'viewer.back': '← Back',\n 'viewer.defaultTitle': 'File Preview',\n 'viewer.copyFull': 'Copy full',\n 'viewer.copyFullTitle': 'Copy full content to clipboard',\n 'viewer.referenceFile': 'Reference file',\n 'viewer.referenceFileTitle': 'Reference this file',\n 'viewer.referencePage': 'Reference page',\n 'viewer.referencePageTitle': 'Reference this page in chat',\n 'viewer.download': 'Download',\n 'viewer.fullscreen': 'Fullscreen (⌘L)',\n 'viewer.fullscreenExit': 'Exit fullscreen',\n 'viewer.close': 'Close',\n 'viewer.unknownType': 'Unknown type',\n 'viewer.iframeHint': 'iframe content cannot be selected directly. Use the \"Reference file\" button above.',\n 'viewer.copySnippet': 'Copy snippet',\n 'viewer.loadingPdf': 'Loading PDF viewer...',\n 'viewer.pdfPages': '{{count}} pages',\n 'viewer.loadingKicad': 'Loading KiCad viewer...',\n 'viewer.loading3d': 'Loading 3D viewer...',\n 'viewer.loadingStep': 'Loading STEP viewer...',\n 'viewer.gerberTitle': 'DFX Copilot — Gerber preview',\n 'viewer.gerberBlobWarning':\n 'DFX Copilot must fetch the file from a public URL. Local blob/data URLs cannot be used inside a cross-origin iframe. Return content_url from getResourceContent or implement getResourceUrl with an HTTPS presigned link.',\n 'viewer.gerberNoHttpUrl':\n 'The resource URL is not http(s); it cannot be passed to DFX Copilot. Use a direct or presigned URL.',\n 'viewer.pdfPreview': 'PDF Preview',\n 'viewer.htmlPreview': 'HTML Preview',\n 'viewer.htmlProjectLoading': 'Loading HTML project files…',\n 'viewer.htmlProjectNoEntry': 'HTML project is missing an entry file (e.g. index.html); cannot render',\n 'viewer.htmlProjectSizeLimit': 'HTML project exceeds size limit; only the entry file is rendered',\n 'viewer.htmlStrategyForcedInlineWarning': 'ESM modules detected, but inline strategy is forced; imports may fail',\n 'viewer.htmlStrategyFallbackCspWarning': 'Host CSP blocks blob: URLs; automatically falling back to inline strategy',\n 'viewer.copyFullKicadTitle': 'Copy full KiCad source to clipboard and reference',\n 'viewer.zoomIn': 'Zoom in',\n 'viewer.zoomOut': 'Zoom out',\n 'viewer.zoomReset': 'Reset',\n 'viewer.loadingWord': 'Loading Word viewer...',\n 'viewer.loadingExcel': 'Loading Excel viewer...',\n 'viewer.loadingPowerPoint': 'Loading PowerPoint viewer...',\n 'viewer.pptPrev': '‹ Prev',\n 'viewer.pptNext': 'Next ›',\n 'viewer.pptSlide': 'Slide',\n 'viewer.pptThumbnails': 'Thumbnails',\n 'viewer.excelRows': 'rows',\n 'viewer.excelColumns': 'columns',\n 'childAgent.status.running': 'Running',\n 'childAgent.status.completed': 'Completed',\n 'hitl.form.defaultTitle': 'Please fill the form',\n 'hitl.wait.default': 'Waiting for user input...',\n 'todo.completed.count': '{{completed}}/{{total}} completed',\n 'todo.blocked.count': '{{count}} blocked',\n 'todo.more': '+ {{count}} more',\n 'todo.header.done': 'Done',\n 'tool.phase.generating': 'Generating',\n 'tool.phase.executing': 'Executing',\n 'tool.phase.complete': 'Complete',\n 'tool.phase.error': 'Failed',\n 'tool.executing': 'Execute tool: {{name}}',\n 'tool.mcp.running': 'Running',\n 'tool.mcp.success': 'Complete',\n 'tool.mcp.error': 'Failed',\n 'form.placeholder.select': 'Please select',\n 'form.required.default': 'This field is required',\n 'form.submit.submit': 'Submit',\n 'form.submit.submitting': 'Submitting...',\n 'form.requestId': 'Request ID: ',\n 'pinned.label': 'Pinned',\n 'plan.title': 'Execution Plan',\n 'plan.step': 'Step {{index}}',\n 'thinking.inProgress': 'Thinking...',\n 'thinking.completed': 'Thinking completed',\n 'split.unreadCount': '{{count}} new messages',\n 'split.askQuestion': 'Ask (⌘/)',\n 'split.exitFullscreen': 'Exit fullscreen (Esc)',\n 'context.inputPlaceholder': 'Ask here...',\n 'context.inputPlaceholderWithFile': 'Ask about {{fileName}}...',\n 'context.send': 'Send',\n 'context.removeReference': 'Remove reference',\n 'split.home': 'Main Chat',\n 'split.workspace': 'Workspace',\n 'split.annotation': 'Annotations',\n 'split.tabClose': 'Close tab',\n 'split.tabNew': 'New tab',\n 'workspace.title': 'Workspace',\n 'workspace.searchPlaceholder': 'Search files...',\n 'workspace.empty': 'No files yet',\n 'workspace.downloadAll': 'Download all files as zip',\n 'workspace.recent': 'Recent changes',\n 'workspace.open': 'Open',\n 'workspace.openInNewTab': 'Open in new tab',\n 'workspace.download': 'Download',\n 'workspace.copyPath': 'Copy path',\n 'workspace.expandAll': 'Expand all',\n 'workspace.collapseAll': 'Collapse all',\n 'annotation.title': 'Annotations',\n 'annotation.empty': 'No annotations',\n 'annotation.fileLevelTitle': 'File Conversation',\n 'annotation.fileLevelPlaceholder': 'Ask about this file...',\n 'annotation.anchoredPlaceholder': 'Ask about selection...',\n 'annotation.inlineInputPlaceholder': 'Ask about this...',\n 'annotation.replyPlaceholder': 'Follow up...',\n 'annotation.anchorLabel': 'Anchor: {{text}}',\n 'annotation.close': 'Close',\n 'annotation.fabLabel': 'File annotation',\n 'annotation.fabHeader': '{{fileName}} · File Conversation',\n 'annotation.messageCount': '{{count}} messages',\n 'annotation.anchorInvalid': 'Anchor invalidated',\n 'annotation.errorRetry': 'Send failed, click to retry',\n 'annotation.queuedHint': 'Queued, please wait...',\n 'annotation.selectionLabel': 'Selected text',\n 'agentControl.pause': 'Pause',\n 'agentControl.resume': 'Resume',\n 'agentControl.stop': 'Stop',\n 'agentControl.paused': 'Paused',\n 'agentControl.groupTitle': 'Agent Group',\n 'aria.fileNavigation': 'File navigation',\n 'kicad.loadFailed': 'KiCanvas load failed, switched to source view',\n 'kicad.urlNotReady': 'Resource URL not ready, showing source',\n 'kicad.loadingEngine': 'Loading KiCanvas engine...',\n 'kicad.sidebarTitle': 'KiCanvas sidebar: properties, symbol/footprint list, docs',\n 'kicad.sidebarPcb': 'PCB: view properties, footprint list',\n 'kicad.sidebarSch': 'SCH: view symbol/sub-sheet properties',\n 'kicad.sidebarGeneric': 'View properties',\n 'kicad.viewVisual': 'Visual',\n 'kicad.viewSource': 'Source',\n 'provenance.filter.type.agent': 'Agent',\n 'provenance.filter.type.action': 'Action',\n 'provenance.filter.type.file': 'File',\n 'provenance.filter.type.task': 'Task',\n 'provenance.filter.type.reasoning': 'Reasoning',\n 'provenance.filter.depth': 'Depth:',\n 'provenance.toolbar.zoomToFit': 'Zoom to fit',\n 'provenance.toolbar.resetCamera': 'Reset camera',\n 'provenance.toolbar.refresh': 'Refresh',\n 'provenance.legend.reasoning': 'Reasoning',\n 'provenance.legend.action': 'Action',\n 'provenance.legend.file': 'File',\n 'provenance.legend.task': 'Task',\n 'provenance.legend.references': 'References',\n 'provenance.legend.edges': 'Edges: ',\n 'provenance.legend.depth': 'Depth: ',\n 'provenance.detail.title': 'Node details',\n 'provenance.detail.noSelection': 'No node selected',\n 'provenance.detail.label.name': 'Name',\n 'provenance.detail.label.id': 'ID',\n 'provenance.detail.label.timestamp': 'Timestamp',\n 'provenance.detail.label.agentId': 'Agent ID',\n 'provenance.detail.label.instanceId': 'Instance ID',\n 'provenance.detail.label.level': 'Level',\n 'provenance.detail.label.status': 'Status',\n 'provenance.detail.label.tool': 'Tool',\n 'provenance.detail.label.purpose': 'Purpose',\n 'provenance.detail.label.duration': 'Duration',\n 'provenance.detail.label.path': 'Path',\n 'provenance.detail.label.operation': 'Operation',\n 'provenance.detail.label.taskId': 'Task ID',\n 'provenance.detail.label.description': 'Description',\n 'provenance.detail.label.model': 'Model',\n 'provenance.detail.label.tokenCount': 'Token count',\n 'provenance.detail.label.reasoningPreview': 'Reasoning preview',\n 'provenance.detail.relatedEdges': 'Related edges ({{count}})',\n 'provenance.page.noSessionHint': 'Please specify session via URL: ?session_id=NNN',\n 'provenance.page.loading': 'Loading provenance graph...',\n 'provenance.page.emptyGraph': 'No graph data for this session',\n 'provenance.drawer.emptyGraph': 'No graph data',\n 'provenance.graph.edgeType.references': 'References',\n 'toolResult.label': 'Result',\n 'toolResult.expandAll': 'Expand all ({{count}} lines)',\n 'toolResult.searchSummary': 'Search results · {{count}}',\n 'toolResult.scrapeSummary': 'Scrape result · {{title}}',\n 'toolResult.more': '+{{count}} more',\n 'plan.status.active': 'Running',\n 'pinned.noMessage': '(no message content)',\n 'viewer.fallback.unknownType': 'Unknown type',\n 'viewer.fallback.download': 'Download file',\n 'fileSize.B': '{{size}} B',\n 'fileSize.KB': '{{size}} KB',\n 'fileSize.MB': '{{size}} MB',\n 'thinking.title': 'Thinking',\n 'thinking.step': 'Step {{step}}',\n 'viewer.stepHint': 'Drag to rotate, scroll to zoom, right-click to pan',\n 'viewer.threeHint': 'Drag to rotate, scroll to zoom, right-click to pan',\n 'viewer.3d.wireframe': 'Wireframe',\n 'viewer.3d.resetView': 'Reset view',\n 'reference.header': '[Reference: {{fileName}}]',\n 'history.noMessage': '(history message)',\n 'agent.defaultName': 'Assistant',\n 'error.unknown': 'Unknown error',\n 'locale': 'en-US',\n 'skill.inlineLabel': 'First check and use the {{name}} skill to solve: ',\n 'skill.empty': 'No skills available',\n 'skill.searchPlaceholder': 'Search skills...',\n 'skill.removeLabel': 'Remove skill',\n 'skill.loading': 'Loading...',\n 'skill.loadError': 'Failed to load skills',\n 'skill.loadMore': 'Load more',\n 'skill.selectorLabel': 'Skill selector',\n 'pool.idle': 'Idle',\n 'pool.collaborating': '{{count}} working',\n 'pool.awaiting': '{{count}} awaiting human',\n 'pool.title': 'Agent Pool',\n 'pool.empty': 'No active agents',\n 'pool.state.running': 'Running',\n 'pool.state.paused': 'Awaiting human',\n 'pool.state.completed': 'Completed',\n 'pool.state.lost': 'Lost',\n 'pool.state.unknown': 'Unknown',\n 'input.placeholder': 'Type a message, / for skills',\n 'input.placeholderLoading': 'Waiting for response…',\n 'discussion.title': 'Discussions',\n 'discussion.empty': 'No discussions',\n 'discussion.active': 'Active',\n 'discussion.resolved': 'Resolved',\n 'discussion.archived': 'Archived',\n 'round.foreign.label': 'Conversation from another tab',\n 'round.foreign.unread': '{{count}} new messages',\n 'round.foreign.expand': 'Click to expand',\n 'sidebar.mainChat': 'Main chat',\n 'sidebar.chat': 'Chat',\n 'sidebar.fileQA': 'File Q&A',\n 'sidebar.selectionQA': 'Selection Q&A',\n 'sessionList.title': 'Sessions',\n 'sessionList.newSession': '+ New chat',\n 'sessionList.logout': 'Logout',\n 'sessionList.loading': 'Loading...',\n 'sessionList.empty': 'No sessions yet',\n 'sessionList.unsupported': 'Adapter does not implement listSessions',\n 'sessionList.untitled': 'Untitled',\n 'sessionList.deleteTitle': 'Delete session',\n 'sessionList.deleteConfirm': 'Delete this session?',\n 'sessionList.prevPage': '←',\n 'sessionList.nextPage': '→',\n 'sessionList.pageInfo': 'Page {page} / {totalPages}',\n 'modelPicker.menu.head': 'Model for this turn',\n 'modelPicker.menu.aria': 'Choose the model for this turn',\n 'modelPicker.auto.title': 'Default (follow agent)',\n 'modelPicker.auto.hint.knownChannel': 'Agent default: {{name}} · {{channel}}',\n 'modelPicker.auto.hint.knownBasename': 'Agent default: {{name}}',\n 'modelPicker.auto.hint.fallback':\n \"Use the agent's registered default model; sub-agents follow automatically\",\n 'modelPicker.row.hint.channelMulti': '{{available}} of {{total}} channels available',\n 'modelPicker.row.hint.channelSingle': 'Channel: {{channel}}',\n 'modelPicker.row.hint.versionMulti': '{{count}} versions available',\n 'modelPicker.fallback.placeholder': 'Default model',\n 'modelPicker.inert.title': 'Model picker is unavailable',\n 'modelPicker.guestLocked.label': 'Default model · sign in to choose',\n 'modelPicker.guestLocked.title':\n 'Signed-in users can switch among multiple models. As a guest you start with the default — sign in any time to swap.',\n 'modelPicker.loadingList': 'Loading model list…',\n 'modelPicker.trigger.title.stale':\n '{{name}} (no longer listed — will still be attempted on send)',\n 'modelPicker.trigger.title.agentDefault.withChannel':\n 'Agent default: {{name}} · {{channel}} (sent value follows the agent)',\n 'modelPicker.trigger.title.agentDefault':\n 'Agent default: {{name}} (sent value follows the agent)',\n 'modelPicker.trigger.title.current': 'Current model: {{name}}',\n 'modelPicker.row.title.pickDefault': 'Use default channel ({{hint}})',\n 'modelPicker.row.title.pick': 'Use {{name}}',\n 'modelPicker.chip.aria': '{{title}} channels',\n 'modelPicker.chip.title.available': 'Channel {{channel}} · model {{name}}',\n 'modelPicker.chip.title.unavailable': 'Channel {{channel}} · currently unavailable',\n 'modelPicker.search.placeholder': 'Search models — e.g. gpt5, claude opus…',\n 'modelPicker.search.aria': 'Search models',\n 'modelPicker.search.clear.aria': 'Clear search',\n 'modelPicker.modality.aria': 'Filter by capability',\n 'modelPicker.modality.all': 'All',\n 'modelPicker.modality.chat': 'Chat',\n 'modelPicker.modality.image': 'Image',\n 'modelPicker.modality.video': 'Video',\n 'modelPicker.modality.audio': 'Audio',\n 'modelPicker.modality.embedding': 'Embedding',\n 'modelPicker.modality.realtime': 'Realtime',\n 'modelPicker.section.recent': 'Recent',\n 'modelPicker.section.vendor': '{{vendor}}',\n 'modelPicker.section.toggle.expand': 'Expand {{vendor}}',\n 'modelPicker.section.toggle.collapse': 'Collapse {{vendor}}',\n 'modelPicker.empty.title': 'No models match',\n 'modelPicker.empty.hint': 'Try clearing the search or switching capability',\n 'modelPicker.vendor.openai': 'OpenAI',\n 'modelPicker.vendor.anthropic': 'Anthropic',\n 'modelPicker.vendor.google': 'Google',\n 'modelPicker.vendor.xai': 'xAI',\n 'modelPicker.vendor.alibaba': 'Alibaba',\n 'modelPicker.vendor.zhipu': 'Zhipu',\n 'modelPicker.vendor.moonshot': 'Moonshot',\n 'modelPicker.vendor.bytedance': 'ByteDance',\n 'modelPicker.vendor.deepseek': 'DeepSeek',\n 'modelPicker.vendor.minimax': 'MiniMax',\n 'modelPicker.vendor.openrouter': 'OpenRouter',\n 'modelPicker.vendor.xiaomi': 'Xiaomi',\n 'modelPicker.vendor.other': 'Other',\n 'modelPicker.cap.aria': 'Model capabilities',\n 'modelPicker.cap.image.title': 'Vision (accepts image input)',\n 'modelPicker.cap.video.native.title': 'Native video understanding',\n 'modelPicker.cap.video.derived.title': 'Video understanding (derived from vision via frame sampling)',\n 'modelPicker.cap.audio.title': 'Audio input understanding',\n 'modelPicker.cap.tools.title': 'Tool calling / function call',\n 'modelPicker.cap.imageGen.title': 'Image generation',\n 'modelPicker.cap.videoGen.title': 'Video generation',\n 'modelPicker.cap.audioGen.title': 'Audio generation / TTS / music synthesis',\n 'jr.confirmDialog.cancel': 'Cancel',\n 'jr.confirmDialog.confirm': 'Confirm',\n 'jr.confirmDialog.loading': 'Processing',\n}\n\nexport type ChatWidgetLocale = 'zh-CN' | 'en-US'\n\nconst builtinMessages: Record<ChatWidgetLocale, ChatWidgetMessages> = {\n 'zh-CN': zhCN,\n 'en-US': enUS,\n}\n\nexport function resolveMessages(\n locale: ChatWidgetLocale = 'zh-CN',\n overrides?: Partial<ChatWidgetMessages>,\n): ChatWidgetMessages {\n const base = builtinMessages[locale] ?? zhCN\n if (!overrides) return base\n return { ...base, ...overrides }\n}\n\nexport function interpolate(\n template: string,\n params?: Record<string, string | number>,\n): string {\n if (!params) return template\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key) =>\n String(params[key] ?? ''),\n )\n}\n","import { createContext, useContext, useCallback } from 'react'\nimport type { ChatWidgetMessages, ChatWidgetLocale } from './messages.js'\nimport { zhCN, interpolate } from './messages.js'\n\nexport const I18nContext = createContext<ChatWidgetMessages>(zhCN)\n\nexport function useChatWidgetI18n() {\n const messages = useContext(I18nContext)\n\n const locale: ChatWidgetLocale = (messages['locale'] as ChatWidgetLocale) || 'zh-CN'\n\n const t = useCallback(\n (key: keyof ChatWidgetMessages, params?: Record<string, string | number>): string => {\n const template = messages[key] ?? key\n return interpolate(template, params)\n },\n [messages],\n )\n\n return { messages, t, locale }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useXrefChips
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-EYWNUJVZ.js";
|
|
4
4
|
import {
|
|
5
5
|
useRevokeBlobUrl
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-Q5PLT3AI.js";
|
|
7
7
|
|
|
8
8
|
// src/components/ViewerCore/PdfCore.tsx
|
|
9
9
|
import "react";
|
|
@@ -315,4 +315,4 @@ export {
|
|
|
315
315
|
AudioCore,
|
|
316
316
|
PdfCore
|
|
317
317
|
};
|
|
318
|
-
//# sourceMappingURL=chunk-
|
|
318
|
+
//# sourceMappingURL=chunk-3LOSHCSH.js.map
|