diff --git a/package-lock.json b/package-lock.json index 8de9406..9a1ca38 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "lms", - "version": "1.2.17", + "version": "1.2.18", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "lms", - "version": "1.2.17", + "version": "1.2.18", "dependencies": { "@electron-toolkit/preload": "^3.0.1", "@electron-toolkit/utils": "^4.0.0", diff --git a/package.json b/package.json index 92c01ce..42fb9d0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lms", - "version": "1.2.17", + "version": "1.2.18", "description": "Autonomy Studio LMS Electron app", "main": "./out/main/index.js", "author": { diff --git a/scripts/test-agent-response-reveal.cjs b/scripts/test-agent-response-reveal.cjs index 1ba1892..4d3d423 100644 --- a/scripts/test-agent-response-reveal.cjs +++ b/scripts/test-agent-response-reveal.cjs @@ -92,6 +92,15 @@ function renderResponse(message, now, reducedMotion = false, extra = {}) { return renderToStaticMarkup(ProgressiveChatResponse({ message, dark: true, children: React.createElement('button', null, '승인'), ...extra })) } +test('managed agent responses display A-Copilot without an internal provider ID or duplicate model name', () => { + const html = renderResponse({ content: '분석 결과', provider: 'A_COPILOT', model: 'A-Copilot' }, 0) + assert.ok(html.includes('A-Copilot')) + assert.ok(!html.includes('A_COPILOT')) + assert.ok(!html.includes('A-Copilot · A-Copilot')) + assert.equal((html.match(/>A-Copilot<\/p>/g) ?? []).length, 1) + assert.ok(renderResponse({ content: '결과', provider: 'QWEN', model: 'qwen3.8-max' }, 0).includes('QWEN · qwen3.8-max')) +}) + test('approval controls wait for the explanation; restored history does not replay', () => { const message = { role: 'assistant', revealStartedAt: 1000, plan: { summary: '조향 설명', explanation: content }, provider: 'QWEN', model: 'test' } const first = renderResponse(message, 1000) diff --git a/scripts/test-i18n.cjs b/scripts/test-i18n.cjs index f874258..49103da 100644 --- a/scripts/test-i18n.cjs +++ b/scripts/test-i18n.cjs @@ -9,6 +9,39 @@ const { createInstance } = require('i18next') const root = path.resolve(__dirname, '../src/renderer/src') const dictionary = JSON.parse(fs.readFileSync(path.join(root, 'i18n/en.json'), 'utf8')) +test('only the default simulation description follows language; vehicle and custom text stay unchanged', () => { + const { api } = setup('ko') + const exports = {} + const source = fs.readFileSync(path.join(root, 'features/platforms/PlatformCards.tsx'), 'utf8') + const code = ts.transpileModule(source, { compilerOptions: { + module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, + jsx: ts.JsxEmit.ReactJSX, esModuleInterop: true + } }).outputText + vm.runInNewContext(code, { exports, require: name => name === '../../i18n' + ? { ...api, useLocaleRender() {} } : require(name) }) + const { createElement } = require('react') + const { renderToStaticMarkup } = require('react-dom/server') + const description = '내 PC에서 직접 개발 환경을 실행합니다.' + const platform = { id: 'local', platformKey: 'futuredrive-local-pc', title: '로컬 PC', description, state: 'ready' } + const render = value => renderToStaticMarkup(createElement(exports.PlatformOptionCard, { + platform: value, Icon: () => null, dotClassName: '', unavailable: false, + statusPending: false, displayStatus: '사용 가능', primaryAction: '연결', + actionDisabled: false, running: false, onAction() {}, onSettings() {} + })) + assert.ok(render(platform).includes(description)) + api.setLanguage('en') + assert.ok(render(platform).includes('Run the development environment directly on this PC.')) + assert.ok(!render(platform).includes(description)) + const vehicleDescription = '기초 SLAM 및 자율주행 실습 장비입니다.' + assert.ok(render({ ...platform, platformKey: 'mk-mini', description: vehicleDescription }).includes(vehicleDescription)) + assert.ok(render({ ...platform, platformKey: 'mk-mini' }).includes(description)) + assert.ok(render({ ...platform, description: '강사가 작성한 시뮬레이션 안내' }).includes('강사가 작성한 시뮬레이션 안내')) + assert.ok(render({ ...platform, description: '설정' }).includes('>설정
')) + api.setLanguage('ko') + assert.ok(render(platform).includes(description)) + assert.equal(platform.description, description) +}) + test('close studio modal translates the built-in Local PC title but preserves vehicle names', () => { const source = fs.readFileSync(path.join(root, 'App.tsx'), 'utf8') const expression = source.match(/platformTitle=\{(runningPlatformCloseTarget\.platformKey[^\n]+)\}/)?.[1] diff --git a/src/renderer/src/components/ProgressiveChatResponse.tsx b/src/renderer/src/components/ProgressiveChatResponse.tsx index 629052c..5197b96 100644 --- a/src/renderer/src/components/ProgressiveChatResponse.tsx +++ b/src/renderer/src/components/ProgressiveChatResponse.tsx @@ -21,7 +21,7 @@ export function ProgressiveChatResponse({ message, dark, children, footerAction, defaultCollapsed?: boolean }): React.JSX.Element { const content = message.plan?.explanation ?? message.content - const modelLabel = [message.provider, message.model].filter(Boolean).join(' · ') + const modelLabel = message.provider === 'A_COPILOT' ? 'A-Copilot' : [message.provider, message.model].filter(Boolean).join(' · ') const document = useMemo(() => createAgentRevealDocument(content), [content]) const [now, setNow] = useState(Date.now) const [reducedMotion, setReducedMotion] = useState(() => typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches) diff --git a/src/renderer/src/features/platforms/PlatformCards.tsx b/src/renderer/src/features/platforms/PlatformCards.tsx index d913921..674a665 100644 --- a/src/renderer/src/features/platforms/PlatformCards.tsx +++ b/src/renderer/src/features/platforms/PlatformCards.tsx @@ -105,7 +105,11 @@ export function PlatformOptionCard({{platform.description}
++ {platform.platformKey === 'futuredrive-local-pc' && platform.description === '내 PC에서 직접 개발 환경을 실행합니다.' + ? t('내 PC에서 직접 개발 환경을 실행합니다.') + : platform.description} +