Compare commits
3
Commits
4c8b550242
...
90ef3400f6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90ef3400f6 | ||
|
|
a2c952879d | ||
|
|
b391dfdfb3 |
@@ -87,6 +87,11 @@ var fg = TryFindResource("PrimaryText") as Brush ?? Brushes.Black;
|
|||||||
- 선택형: 커스텀 Popup 드롭다운 (`[라벨: 현재값 ▾]`)
|
- 선택형: 커스텀 Popup 드롭다운 (`[라벨: 현재값 ▾]`)
|
||||||
- AI/고급 설정 항목 옆에 `?` 도움말 아이콘 + 커스텀 다크 툴팁 (`HelpTooltipStyle`)
|
- AI/고급 설정 항목 옆에 `?` 도움말 아이콘 + 커스텀 다크 툴팁 (`HelpTooltipStyle`)
|
||||||
- 설정 저장 시 `CustomMessageBox`로 완료 알림
|
- 설정 저장 시 `CustomMessageBox`로 완료 알림
|
||||||
|
- 설정에서 `on/off` 또는 숫자 입력이 필요한 신규 항목은 **기존 양식에 맞춰 통일해서 추가**해야 함
|
||||||
|
- `on/off` 항목은 예외 없이 `ToggleSwitch` 스타일을 사용하고, 기본 CheckBox/임의 토글 버튼으로 새로 만들지 않음
|
||||||
|
- 숫자 입력 항목은 가능하면 **텍스트박스 직접 입력 대신 기존 슬라이더 + 현재값 배지 패턴**을 우선 사용하며, 범위가 명확한 값은 반드시 이 패턴을 기본으로 채택
|
||||||
|
- 숫자 설정을 부득이하게 텍스트 입력으로 받을 경우에도, 먼저 기존 설정창/AX Agent 내부 설정에 같은 유형의 컨트롤이 있는지 확인하고 그 양식을 재사용해야 함
|
||||||
|
- 동일 성격의 설정은 메인 설정과 AX Agent 내부 설정에서 **표현 방식이 서로 다르면 안 되며**, 기존에 쓰던 컨트롤러/레이아웃 기준으로 맞춰 추가
|
||||||
|
|
||||||
### AX Agent 표현 수준 (필수)
|
### AX Agent 표현 수준 (필수)
|
||||||
- AX Agent UI 표현 수준은 설정에서 반드시 3단계로 제공: **`풍부하게` / `적절하게` / `간단하게`**
|
- AX Agent UI 표현 수준은 설정에서 반드시 3단계로 제공: **`풍부하게` / `적절하게` / `간단하게`**
|
||||||
|
|||||||
@@ -1469,3 +1469,22 @@ MIT License
|
|||||||
- 업데이트: 2026-04-07 09:32 (KST)
|
- 업데이트: 2026-04-07 09:32 (KST)
|
||||||
- Cowork/Code 장시간 실행 뒤 마지막 응답을 라이브 프리뷰로 붙이는 단계에서 `_streamCts` 필드를 다시 읽다가 `Object reference not set to an instance of an object.`로 실패할 수 있던 경로를 수정했습니다. 이제 실행 시작 시 캡처한 지역 토큰을 끝까지 재사용하고, 최종 타이핑 프리뷰 컨테이너가 준비되지 않으면 조용히 건너뛰도록 방어 로직을 추가했습니다.
|
- Cowork/Code 장시간 실행 뒤 마지막 응답을 라이브 프리뷰로 붙이는 단계에서 `_streamCts` 필드를 다시 읽다가 `Object reference not set to an instance of an object.`로 실패할 수 있던 경로를 수정했습니다. 이제 실행 시작 시 캡처한 지역 토큰을 끝까지 재사용하고, 최종 타이핑 프리뷰 컨테이너가 준비되지 않으면 조용히 건너뛰도록 방어 로직을 추가했습니다.
|
||||||
- 같은 실패가 다시 생기면 원인을 더 빨리 찾을 수 있도록 AX Agent 실행 예외 전체를 앱 로그에 남기도록 보강했습니다.
|
- 같은 실패가 다시 생기면 원인을 더 빨리 찾을 수 있도록 AX Agent 실행 예외 전체를 앱 로그에 남기도록 보강했습니다.
|
||||||
|
- 업데이트: 2026-04-07 09:44 (KST)
|
||||||
|
- Cowork/Chat 하단의 프리셋 안내 카드가 실제 결과를 가리던 문제를 수정했습니다. 이제 대화에 사용자/assistant 메시지가 생기거나 실행 중일 때는 해당 카드가 자동으로 숨겨집니다.
|
||||||
|
- [ChatWindow.FooterPresentation.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.FooterPresentation.cs)에 남아 있던 깨진 한글 워터마크/안내 문구를 정상 한국어로 정리했습니다.
|
||||||
|
- 라이브 타이핑 속도를 조정해 SSE 및 Cowork/Code 최종 프리뷰가 한 번에 붙는 느낌을 줄이고, 더 눈에 보이게 점진적으로 출력되도록 보정했습니다.
|
||||||
|
- 업데이트: 2026-04-08 10:12 (KST)
|
||||||
|
- 등록 모델에 `동작 프로파일`을 추가했습니다. 이제 모델별로 `균형 / 도구 호출 우선 / 추론 우선 / 읽기 속도 우선 / 문서 생성 우선` 성향을 저장할 수 있고, 편집/추가 모두 내부 설정과 일반 설정에서 같은 값으로 유지됩니다.
|
||||||
|
- Cowork/Code 루프는 현재 활성 모델의 프로파일을 읽어 no-tool 감지 임계값, 도구 미호출 재시도, 문서 생성 재시도, terminal evidence gate, 읽기 도구 병렬 배치 수를 다르게 적용합니다.
|
||||||
|
- AX Agent 내부 설정의 Temperature 항목에 `자동 / 사용자 지정` 전환을 추가했습니다. 자동일 때는 등록 모델 프로파일의 temperature 정책을 따르고, 사용자 지정일 때만 슬라이더 값이 실제 tool 호출 온도로 적용됩니다.
|
||||||
|
- 업데이트: 2026-04-08 10:38 (KST)
|
||||||
|
- 모델 실행 프로파일을 Cowork/Code 후속 게이트까지 더 깊게 연결했습니다. 이제 프로파일별로 post-tool verification, 코드 품질 게이트, 문서 검증 게이트, diff/실행 증거 게이트, final report 게이트의 강도를 다르게 적용합니다.
|
||||||
|
- `document_heavy` 프로파일은 `document_plan` 이후 장기 재시도보다 fallback 산출물 생성 쪽으로 더 빨리 전환되도록 조정했습니다.
|
||||||
|
- OpenAI/vLLM tool calling 바디에 `parallel_tool_calls` 힌트를 추가해 읽기 도구 병렬 실행 성향이 모델 요청 바디에도 반영되도록 보강했습니다.
|
||||||
|
- Cowork/Code 진행 표시에는 `계획 / 도구 / 검증 / 압축 / 폴백 / 재시도` 같은 단계 메타를 더 직접적으로 붙여, 오래 걸릴 때도 현재 단계가 더 잘 읽히게 했습니다.
|
||||||
|
- [docs/AX_AGENT_REGRESSION_PROMPTS.md](/E:/AX%20Copilot%20-%20Codex/docs/AX_AGENT_REGRESSION_PROMPTS.md)를 전면 정리해 `tool_call_strict`, `fast_readonly`, `document_heavy`, `reasoning_first` 프로파일별 회귀 시나리오를 고정했습니다.
|
||||||
|
- 업데이트: 2026-04-08 11:14 (KST)
|
||||||
|
- IBM 인증 경유 vLLM 도구 호출 경로를 강화했습니다. IBM tool body도 이제 프로파일 기반 `ResolveToolTemperature()`를 사용하고, `tool_call_strict` 프로파일에서는 더 짧고 직접적인 `tool-only` 지시를 추가해 plain text 응답으로 빠지는 경향을 줄였습니다.
|
||||||
|
- IBM 배포형 엔드포인트가 `tool_choice`를 400으로 거부하면, `tool_choice`만 제거하고 동일한 강제 지시를 유지한 채 한 번 더 재시도하는 대체 강제 전략을 넣었습니다.
|
||||||
|
- OpenAI/vLLM tool-use 응답은 이제 `stream=true` 기반 SSE 수신기로 읽으며, `delta.tool_calls`를 부분 조립해 완성된 도구 호출을 더 빨리 감지합니다.
|
||||||
|
- read-only 도구는 조립이 끝나는 즉시 조기 실행을 시작하고, 최종 루프에서는 그 결과를 재사용하도록 바꿔 도구 착수 속도를 끌어올렸습니다.
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
const JSZip = require('jszip');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// EMU to inches: 1 inch = 914400 EMU
|
||||||
|
// Slide: 9144000 x 5143500 EMU = 10" x 5.625"
|
||||||
|
const EMU = 914400;
|
||||||
|
const SLIDE_W = 9144000;
|
||||||
|
const SLIDE_H = 5143500;
|
||||||
|
const SCALE = 960 / 10; // 96px per inch (at 100%)
|
||||||
|
|
||||||
|
function emuToPx(emu) {
|
||||||
|
return (emu / EMU) * SCALE;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hexToRgb(hex) {
|
||||||
|
if (!hex || hex.length < 6) return '#888888';
|
||||||
|
return '#' + hex.slice(-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderSlideHtml(xml, slideNum) {
|
||||||
|
// Extract background color
|
||||||
|
const bgMatch = xml.match(/p:bg>.*?<a:srgbClr val="([A-Fa-f0-9]{6})"/s);
|
||||||
|
const bgColor = bgMatch ? '#' + bgMatch[1] : '#F5F7FA';
|
||||||
|
|
||||||
|
// Parse all shapes and text boxes
|
||||||
|
const shapes = [];
|
||||||
|
|
||||||
|
// Find all spTree child elements (sp = shape/textbox, pic = image)
|
||||||
|
const spPattern = /<p:sp>(.+?)<\/p:sp>/gs;
|
||||||
|
let spMatch;
|
||||||
|
while ((spMatch = spPattern.exec(xml)) !== null) {
|
||||||
|
const spXml = spMatch[1];
|
||||||
|
|
||||||
|
// Get position
|
||||||
|
const offMatch = spXml.match(/<a:off x="(-?\d+)" y="(-?\d+)"/);
|
||||||
|
const extMatch = spXml.match(/<a:ext cx="(\d+)" cy="(\d+)"/);
|
||||||
|
if (!offMatch || !extMatch) continue;
|
||||||
|
|
||||||
|
const x = emuToPx(parseInt(offMatch[1]));
|
||||||
|
const y = emuToPx(parseInt(offMatch[2]));
|
||||||
|
const w = emuToPx(parseInt(extMatch[1]));
|
||||||
|
const h = emuToPx(parseInt(extMatch[2]));
|
||||||
|
|
||||||
|
// Get fill color
|
||||||
|
const fillMatch = spXml.match(/p:spPr[\s\S]*?<a:srgbClr val="([A-Fa-f0-9]{6})"/);
|
||||||
|
const fillColor = fillMatch ? '#' + fillMatch[1] : null;
|
||||||
|
|
||||||
|
// Get text content
|
||||||
|
const texts = [];
|
||||||
|
const paraPattern = /<a:p>([\s\S]*?)<\/a:p>/g;
|
||||||
|
let paraMatch;
|
||||||
|
while ((paraMatch = paraPattern.exec(spXml)) !== null) {
|
||||||
|
const paraXml = paraMatch[1];
|
||||||
|
const textMatches = [...paraXml.matchAll(/<a:t[^>]*>([^<]*)<\/a:t>/g)];
|
||||||
|
const paraText = textMatches.map(m => m[1]).join('');
|
||||||
|
if (paraText.trim()) texts.push(paraText.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get font size
|
||||||
|
const szMatch = spXml.match(/sz="(\d+)"/);
|
||||||
|
const fontSize = szMatch ? parseInt(szMatch[1]) / 100 : 12;
|
||||||
|
|
||||||
|
// Get text color
|
||||||
|
const txtColorMatch = spXml.match(/<a:t>[\s\S]*?<a:srgbClr val="([A-Fa-f0-9]{6})"/);
|
||||||
|
const txtColor = txtColorMatch ? '#' + txtColorMatch[1] : '#FFFFFF';
|
||||||
|
|
||||||
|
shapes.push({ x, y, w, h, fillColor, texts, fontSize, txtColor });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build HTML
|
||||||
|
let shapesHtml = '';
|
||||||
|
for (const s of shapes) {
|
||||||
|
const bgStyle = s.fillColor ? `background-color: ${s.fillColor};` : '';
|
||||||
|
const textContent = s.texts.join('<br>');
|
||||||
|
shapesHtml += `<div style="position:absolute;left:${s.x.toFixed(1)}px;top:${s.y.toFixed(1)}px;width:${s.w.toFixed(1)}px;height:${s.h.toFixed(1)}px;${bgStyle}overflow:hidden;box-sizing:border-box;padding:2px 4px;">
|
||||||
|
<div style="font-size:${Math.min(s.fontSize, 20)}px;color:${s.txtColor};font-family:Arial,sans-serif;overflow:hidden;">${textContent}</div>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `<div style="position:relative;width:960px;height:540px;background-color:${bgColor};overflow:hidden;border:1px solid #333;flex-shrink:0;">
|
||||||
|
<div style="position:absolute;top:2px;right:4px;font-size:10px;color:rgba(128,128,128,0.5);z-index:999">${slideNum}</div>
|
||||||
|
${shapesHtml}
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createPreview(pptxPath, outputPath) {
|
||||||
|
const data = fs.readFileSync(pptxPath);
|
||||||
|
const zip = await JSZip.loadAsync(data);
|
||||||
|
|
||||||
|
const slideFiles = Object.keys(zip.files)
|
||||||
|
.filter(f => f.match(/^ppt\/slides\/slide\d+\.xml$/))
|
||||||
|
.sort((a, b) => {
|
||||||
|
const na = parseInt(a.match(/slide(\d+)/)[1]);
|
||||||
|
const nb = parseInt(b.match(/slide(\d+)/)[1]);
|
||||||
|
return na - nb;
|
||||||
|
});
|
||||||
|
|
||||||
|
let slidesHtml = '';
|
||||||
|
for (const sf of slideFiles) {
|
||||||
|
const slideNum = parseInt(sf.match(/slide(\d+)/)[1]);
|
||||||
|
const xml = await zip.file(sf).async('string');
|
||||||
|
slidesHtml += await renderSlideHtml(xml, slideNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
const html = `<!DOCTYPE html>
|
||||||
|
<html><head><meta charset="utf-8">
|
||||||
|
<title>${path.basename(pptxPath)}</title>
|
||||||
|
<style>
|
||||||
|
body { background: #1a1a1a; font-family: Arial; margin: 0; padding: 20px; }
|
||||||
|
h2 { color: #fff; font-size: 14px; margin-bottom: 10px; }
|
||||||
|
.slides { display: flex; flex-direction: column; gap: 16px; align-items: flex-start; }
|
||||||
|
</style>
|
||||||
|
</head><body>
|
||||||
|
<h2>${path.basename(pptxPath)}</h2>
|
||||||
|
<div class="slides">${slidesHtml}</div>
|
||||||
|
</body></html>`;
|
||||||
|
|
||||||
|
fs.writeFileSync(outputPath, html);
|
||||||
|
console.log(`Preview: ${outputPath} (${slideFiles.length} slides)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
await createPreview(
|
||||||
|
'E:/test/삼성디스플레이 vs LG디스플레이 비교 분석 보고서_20260407_1958.pptx',
|
||||||
|
'C:/Users/admin/AppData/Local/Temp/pptx_gen/preview1.html'
|
||||||
|
);
|
||||||
|
await createPreview(
|
||||||
|
'E:/test/삼성디스플레이 사업 영역 및 제품 강점 분석 보고서_20260407_1956.pptx',
|
||||||
|
'C:/Users/admin/AppData/Local/Temp/pptx_gen/preview2.html'
|
||||||
|
);
|
||||||
|
})();
|
||||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 7.3 KiB |
Vendored
BIN
Binary file not shown.
Vendored
-1319
File diff suppressed because it is too large
Load Diff
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
-19
@@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"runtimeOptions": {
|
|
||||||
"tfm": "net8.0",
|
|
||||||
"includedFrameworks": [
|
|
||||||
{
|
|
||||||
"name": "Microsoft.NETCore.App",
|
|
||||||
"version": "8.0.25"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Microsoft.WindowsDesktop.App",
|
|
||||||
"version": "8.0.25"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"configProperties": {
|
|
||||||
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
|
|
||||||
"CSWINRT_USE_WINDOWS_UI_XAML_PROJECTIONS": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user