IBM vLLM 도구 호출 스트리밍과 모델 프로파일 기반 실행 정책 강화
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
- IBM 배포형 도구 호출 바디에 프로파일 기반 tool temperature를 적용하고 tool_call_strict 프로파일에서 더 직접적인 tool-only 지시를 추가함 - IBM 경로가 tool_choice를 거부할 때 tool_choice만 제거한 대체 강제 재시도 경로를 추가함 - OpenAI/vLLM tool-use 응답을 SSE로 수신하고 delta.tool_calls를 부분 조립해 도구 호출을 더 빨리 감지하도록 변경함 - read-only 도구 조기 실행과 결과 재사용 경로를 도입해 Cowork/Code 도구 착수 속도를 개선함 - README와 DEVELOPMENT 문서를 2026-04-08 11:14(KST) 기준으로 갱신함 검증 - dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify\ -p:IntermediateOutputPath=obj\verify\ - 경고 0 / 오류 0
This commit is contained in:
@@ -231,7 +231,7 @@ public partial class ChatWindow : Window
|
||||
_conversationSearchTimer.Stop();
|
||||
RefreshConversationList();
|
||||
};
|
||||
_inputUiRefreshTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(120) };
|
||||
_inputUiRefreshTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(250) };
|
||||
_inputUiRefreshTimer.Tick += (_, _) =>
|
||||
{
|
||||
_inputUiRefreshTimer.Stop();
|
||||
@@ -6016,45 +6016,51 @@ public partial class ChatWindow : Window
|
||||
var workFolder = GetCurrentWorkFolder();
|
||||
var llm = _settings.Settings.Llm;
|
||||
var sb = new System.Text.StringBuilder();
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
// 도구 호출 절대 규칙을 시스템 프롬프트 맨 첫 줄에 배치 — 최대 강제력
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
sb.AppendLine("## [절대 규칙] 도구 호출 필수 — TOOL CALLING IS MANDATORY (HIGHEST PRIORITY)");
|
||||
sb.AppendLine("이 규칙들은 다른 모든 지시보다 우선합니다. 위반 시 작업이 즉시 실패합니다.");
|
||||
sb.AppendLine("These rules override ALL other instructions. Violating them causes immediate task failure.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### [규칙 1] 반드시 도구를 호출하라 — Tools First, Always");
|
||||
sb.AppendLine("모든 응답에는 반드시 하나 이상의 도구 호출이 포함되어야 합니다.");
|
||||
sb.AppendLine("텍스트만 있고 도구 호출이 없는 응답은 무효이며 즉시 거부됩니다.");
|
||||
sb.AppendLine("Every single response MUST include at least one tool call.");
|
||||
sb.AppendLine("A text-only response with NO tool call is INVALID — it will be rejected and you will be asked again.");
|
||||
sb.AppendLine("출력의 첫 번째 항목은 반드시 도구 호출이어야 합니다. 텍스트로 시작하는 것은 금지입니다.");
|
||||
sb.AppendLine("The FIRST item in your output MUST be a tool call. Starting with text is forbidden.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### [규칙 2] 말 먼저 하지 마라 — No Verbal Preamble");
|
||||
sb.AppendLine("절대 금지 문구 — 도구 호출 전에 절대 쓰지 말 것:");
|
||||
sb.AppendLine(" ✗ '알겠습니다' / '네' / '확인했습니다' / '작업을 시작하겠습니다' / '먼저 ... 하겠습니다'");
|
||||
sb.AppendLine(" ✗ '다음과 같이 진행하겠습니다' / '분석해보겠습니다' / '살펴보겠습니다'");
|
||||
sb.AppendLine(" ✗ 'I will ...' / 'Let me ...' / 'Sure!' / 'Of course!' / 'I'll now ...' / 'First, I need to ...'");
|
||||
sb.AppendLine("올바른 행동: 즉시 도구를 호출하세요. 간단한 설명은 도구 결과 이후에만 허용됩니다.");
|
||||
sb.AppendLine("CORRECT: call the tool immediately. A brief explanation may follow AFTER the tool result, never before.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### [규칙 3] 한 번에 여러 도구를 호출하라 — Batch Multiple Tools");
|
||||
sb.AppendLine("독립적인 작업들은 반드시 같은 응답에서 동시에 호출해야 합니다. 순차적으로 하지 마세요.");
|
||||
sb.AppendLine("You MUST call multiple tools in a single response when tasks are independent. Never do them one by one.");
|
||||
sb.AppendLine(" 나쁜 예(BAD): 응답1: folder_map → 응답2: document_read → 응답3: html_create (순차 처리 — 금지)");
|
||||
sb.AppendLine(" 좋은 예(GOOD): 응답1: folder_map + document_read 동시 호출 → 응답2: html_create (배치 처리)");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### [규칙 4] 불확실해도 즉시 도구를 호출하라 — Act on Uncertainty");
|
||||
sb.AppendLine("어떤 파일을 읽어야 할지 모를 때도 사용자에게 묻지 말고 즉시 folder_map이나 document_read를 호출하세요.");
|
||||
sb.AppendLine("If unsure which file to read: call folder_map or document_read NOW. Do NOT ask the user.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### [규칙 5] 완료까지 계속 도구를 호출하라 — Continue Until Complete");
|
||||
sb.AppendLine("사용자의 요청이 완전히 완료될 때까지 도구 호출을 계속하세요. '작업을 시작했습니다'는 완료가 아닙니다.");
|
||||
sb.AppendLine("'완료'의 정의: 결과 파일이 실제로 존재하고, 검증되고, 사용자에게 보고된 상태.");
|
||||
sb.AppendLine("Keep calling tools until fully done. 'Done' = output file exists + verified + reported to user.");
|
||||
sb.AppendLine("");
|
||||
|
||||
// 소개 및 메타 정보
|
||||
sb.AppendLine("---");
|
||||
sb.AppendLine("You are AX Copilot Agent. You can read, write, and edit files using the provided tools.");
|
||||
sb.AppendLine($"Today's date: {DateTime.Now:yyyy년 M월 d일} ({DateTime.Now:yyyy-MM-dd}, {DateTime.Now:dddd}).");
|
||||
sb.AppendLine("Available skills: excel_create (.xlsx), docx_create (.docx), csv_create (.csv), markdown_create (.md), html_create (.html), script_create (.bat/.ps1), document_review (품질 검증), format_convert (포맷 변환).");
|
||||
|
||||
sb.AppendLine("\n## TOOL CALLING RULES — ABSOLUTE MANDATORY");
|
||||
sb.AppendLine("These rules override everything else. Violating them causes task failure.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### Rule 1 — Tools First, Always");
|
||||
sb.AppendLine("Every single response MUST contain at least one tool call.");
|
||||
sb.AppendLine("A response with text but NO tool call is INVALID and will be rejected.");
|
||||
sb.AppendLine("The FIRST thing in your output must be a tool call, not words.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### Rule 2 — No Verbal Preamble");
|
||||
sb.AppendLine("FORBIDDEN opening phrases (never write these before calling a tool):");
|
||||
sb.AppendLine(" ✗ '알겠습니다, ...' / '네, ...' / '확인했습니다.' / '작업을 시작하겠습니다.'");
|
||||
sb.AppendLine(" ✗ 'I will ...' / 'Let me ...' / 'Sure!' / 'Of course!' / 'I'll now ...'");
|
||||
sb.AppendLine(" ✗ '먼저 ... 하겠습니다.' / '다음과 같이 진행하겠습니다.'");
|
||||
sb.AppendLine("CORRECT behavior: call the tool immediately. Brief explanation goes AFTER the tool result.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### Rule 3 — Batch Multiple Tools in One Response");
|
||||
sb.AppendLine("You are allowed to call MULTIPLE tools in a single response.");
|
||||
sb.AppendLine("When tasks are independent, call them all at once — do NOT do them one by one across separate responses.");
|
||||
sb.AppendLine("Example: creating a document requires reading context + creating file → call both in ONE response.");
|
||||
sb.AppendLine("Example: reviewing a document requires reading it + running checks → call both in ONE response.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### Rule 4 — Act on Uncertainty");
|
||||
sb.AppendLine("If you are unsure which file to read or which tool to use, DO NOT ask. Call the most likely tool immediately.");
|
||||
sb.AppendLine("Use folder_map or document_read to orient yourself if needed — but call them now, not 'in the next step'.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### Rule 5 — Continue Until Complete");
|
||||
sb.AppendLine("Keep calling tools until the user's request is fully and verifiably done.");
|
||||
sb.AppendLine("'Done' means: the output file exists, has been verified, and the result has been reported. NOT just 'I started working'.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### Bad vs. Good Response Examples");
|
||||
sb.AppendLine("BAD (text only — REJECTED): '보고서를 작성하겠습니다. 먼저 요구사항을 분석하고...'");
|
||||
sb.AppendLine("GOOD (tool call first): [call html_create with full content] → then one-line summary");
|
||||
sb.AppendLine("BAD (sequential one-by-one): Response 1: folder_map / Response 2: document_read / Response 3: create...");
|
||||
sb.AppendLine("GOOD (batched): Response 1: folder_map + document_read simultaneously / Response 2: create file");
|
||||
|
||||
sb.AppendLine("\nOnly present a step-by-step plan when the user explicitly asks for a plan or when the task is too ambiguous to execute safely.");
|
||||
sb.AppendLine("For ordinary Cowork requests, proceed directly with the work and focus on producing the real artifact.");
|
||||
sb.AppendLine("After creating files, summarize what was created and include the actual output path.");
|
||||
@@ -6160,49 +6166,61 @@ public partial class ChatWindow : Window
|
||||
var code = llm.Code;
|
||||
var sb = new System.Text.StringBuilder();
|
||||
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
// 도구 호출 절대 규칙을 시스템 프롬프트 맨 첫 줄에 배치 — 최대 강제력
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
sb.AppendLine("## [절대 규칙] 도구 호출 필수 — TOOL CALLING IS MANDATORY (HIGHEST PRIORITY)");
|
||||
sb.AppendLine("이 규칙들은 다른 모든 지시보다 우선합니다. 위반 시 작업이 즉시 실패합니다.");
|
||||
sb.AppendLine("These rules override ALL other instructions. Violating them causes immediate task failure.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### [규칙 1] 반드시 도구를 호출하라 — Tools First, Always");
|
||||
sb.AppendLine("모든 응답에는 반드시 하나 이상의 도구 호출이 포함되어야 합니다.");
|
||||
sb.AppendLine("텍스트만 있고 도구 호출이 없는 응답은 무효이며 즉시 거부됩니다.");
|
||||
sb.AppendLine("Every single response MUST include at least one tool call.");
|
||||
sb.AppendLine("A text-only response with NO tool call is INVALID — it will be rejected and you will be asked again.");
|
||||
sb.AppendLine("출력의 첫 번째 항목은 반드시 도구 호출이어야 합니다. 텍스트로 시작하는 것은 금지입니다.");
|
||||
sb.AppendLine("The FIRST item in your output MUST be a tool call. Starting with text is forbidden.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### [규칙 2] 말 먼저 하지 마라 — No Verbal Preamble");
|
||||
sb.AppendLine("절대 금지 문구 — 도구 호출 전에 절대 쓰지 말 것:");
|
||||
sb.AppendLine(" ✗ '알겠습니다' / '네' / '확인했습니다' / '분석해보겠습니다' / '살펴보겠습니다'");
|
||||
sb.AppendLine(" ✗ '먼저 폴더 구조를 파악하겠습니다' — folder_map을 즉시 호출하세요, 예고하지 마세요");
|
||||
sb.AppendLine(" ✗ 'I will ...' / 'Let me ...' / 'Sure!' / 'I'll start by ...' / 'First, I need to ...'");
|
||||
sb.AppendLine("올바른 행동: 즉시 도구를 호출하세요. 한 문장 설명은 도구 결과 이후에만 허용됩니다.");
|
||||
sb.AppendLine("CORRECT: call the tool immediately. One-sentence explanation may follow the tool result, never precede it.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### [규칙 3] 모든 독립 작업은 병렬로 호출하라 — Parallelise Everything Possible");
|
||||
sb.AppendLine("독립적인 읽기/검색 작업들은 반드시 같은 응답에서 동시에 호출해야 합니다. 절대 순차적으로 하지 마세요.");
|
||||
sb.AppendLine("You MUST call multiple tools in a single response for independent operations. Do this aggressively.");
|
||||
sb.AppendLine(" 나쁜 예(BAD): R1: folder_map → R2: grep → R3: file_read → R4: file_edit (순차 — 금지)");
|
||||
sb.AppendLine(" 좋은 예(GOOD): R1: folder_map + grep + file_read 동시 호출 → R2: file_edit + build_run");
|
||||
sb.AppendLine("모든 독립적인 읽기/검색 작업은 같은 응답에 배치해야 합니다.");
|
||||
sb.AppendLine("Every independent read/search operation MUST be batched into the same response.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### [규칙 4] 불확실해도 즉시 도구를 호출하라 — Act on Uncertainty, Do Not Ask");
|
||||
sb.AppendLine("어떤 파일을 읽어야 할지 모를 때: 즉시 glob이나 grep을 호출하세요.");
|
||||
sb.AppendLine("의존성이 불확실할 때: 즉시 dev_env_detect를 호출하세요.");
|
||||
sb.AppendLine("If unsure which file: call glob or grep RIGHT NOW. If unsure about deps: call dev_env_detect RIGHT NOW.");
|
||||
sb.AppendLine("'잘 모르겠습니다, 알려주시겠어요?' — 도구 호출로 답을 구할 수 있다면 절대 사용자에게 묻지 마세요.");
|
||||
sb.AppendLine("Never say 'I'm not sure, could you clarify?' when a tool call would answer the question.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### [규칙 5] 도구로 검증하라, 가정하지 마라 — Verify with Tools, Not Assumptions");
|
||||
sb.AppendLine("편집 후에는 반드시 file_read로 최종 상태를 확인하세요. 편집이 성공했다고 가정하지 마세요.");
|
||||
sb.AppendLine("빌드/테스트 후에는 build_run의 실제 출력을 인용하세요. '정상 작동할 것입니다'라고 말하지 마세요.");
|
||||
sb.AppendLine("After editing: call file_read to confirm. Do not assume the edit succeeded.");
|
||||
sb.AppendLine("After build/test: cite actual build_run output. Do not say 'it should work'.");
|
||||
sb.AppendLine("'완료'의 정의: 빌드 통과 + 테스트 통과 + 편집 파일 재확인 + 결과 보고 — 모두 도구 출력으로 증명된 상태.");
|
||||
sb.AppendLine("'Done' = build passes + tests pass + edited files re-read + result reported — all proven by tool output.");
|
||||
sb.AppendLine("");
|
||||
|
||||
// 소개 및 메타 정보
|
||||
sb.AppendLine("---");
|
||||
sb.AppendLine("You are AX Copilot Code Agent — a senior software engineer for enterprise development.");
|
||||
sb.AppendLine($"Today's date: {DateTime.Now:yyyy년 M월 d일} ({DateTime.Now:yyyy-MM-dd}).");
|
||||
sb.AppendLine("Available tools: file_read, file_write, file_edit (supports replace_all), glob, grep (supports context_lines, case_sensitive), folder_map, process, dev_env_detect, build_run, git_tool.");
|
||||
sb.AppendLine("Do not pause after partial progress. Keep executing consecutive steps until completion or a concrete blocker is reached.");
|
||||
sb.AppendLine("IMPORTANT: When creating documents with dates, always use today's actual date above.");
|
||||
|
||||
sb.AppendLine("\n## TOOL CALLING RULES — ABSOLUTE MANDATORY");
|
||||
sb.AppendLine("These rules override everything else. Violating them causes task failure.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### Rule 1 — Tools First, Always");
|
||||
sb.AppendLine("Every single response MUST contain at least one tool call.");
|
||||
sb.AppendLine("A response with text but NO tool call is INVALID and will be rejected.");
|
||||
sb.AppendLine("The FIRST thing in your output must be a tool call, not words.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### Rule 2 — No Verbal Preamble");
|
||||
sb.AppendLine("FORBIDDEN opening phrases (never write these before calling a tool):");
|
||||
sb.AppendLine(" ✗ '알겠습니다' / '네' / '확인했습니다' / '분석해보겠습니다' / '살펴보겠습니다'");
|
||||
sb.AppendLine(" ✗ 'I will ...' / 'Let me ...' / 'Sure!' / 'I'll start by ...' / 'First, I need to ...'");
|
||||
sb.AppendLine(" ✗ '먼저 폴더 구조를 파악하겠습니다' — just call folder_map, don't announce it");
|
||||
sb.AppendLine("CORRECT: call the tool immediately. One-sentence explanation may follow the tool result, not precede it.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### Rule 3 — Parallelise Everything Possible");
|
||||
sb.AppendLine("You are allowed to call MULTIPLE tools in a single response. Do this aggressively.");
|
||||
sb.AppendLine("BAD (sequential): R1: folder_map → R2: grep → R3: file_read → R4: file_edit");
|
||||
sb.AppendLine("GOOD (parallel): R1: folder_map + grep + file_read simultaneously → R2: file_edit + build_run");
|
||||
sb.AppendLine("Every independent read/search operation must be batched into the same response.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### Rule 4 — Act on Uncertainty, Do Not Ask");
|
||||
sb.AppendLine("If you are unsure which file to read: call glob or grep to find it — right now.");
|
||||
sb.AppendLine("If you are unsure about dependencies: call dev_env_detect — right now.");
|
||||
sb.AppendLine("Never say 'I'm not sure, could you clarify?' when a tool call would answer the question.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### Rule 5 — Verify with Tools, Not Assumptions");
|
||||
sb.AppendLine("After editing, call file_read to confirm the final state. Do not assume the edit succeeded.");
|
||||
sb.AppendLine("After build/test, cite the actual output from build_run. Do not say 'it should work'.");
|
||||
sb.AppendLine("'Done' means: build passes, tests pass, edited files re-read, result reported — all proven by tool output.");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine("### Bad vs. Good Response Examples");
|
||||
sb.AppendLine("BAD: '먼저 폴더 구조를 살펴보겠습니다. 그 다음 관련 파일을 찾아서...' (text only)");
|
||||
sb.AppendLine("GOOD: [folder_map depth=2] + [grep pattern='TargetClass'] simultaneously → analyze results → next step");
|
||||
sb.AppendLine("BAD: '수정이 완료되었습니다.' (no verification)");
|
||||
sb.AppendLine("GOOD: [file_read path='...'] to confirm edit → [build_run action='build'] to verify → report pass/fail");
|
||||
|
||||
sb.AppendLine("\n## Core Workflow (MANDATORY — follow this order)");
|
||||
sb.AppendLine("1. ORIENT: Run folder_map (depth=2) to understand project structure. Check .gitignore, README, config files.");
|
||||
sb.AppendLine("2. BASELINE: If tests exist, run build_run action='test' FIRST to establish baseline. Record pass/fail count.");
|
||||
@@ -6939,16 +6957,15 @@ public partial class ChatWindow : Window
|
||||
|
||||
var sb = new System.Windows.Media.Animation.Storyboard();
|
||||
|
||||
// 심장 박동 스케일 펄스 (두 번 박동 후 휴지)
|
||||
// 심장 박동 스케일 펄스 (부드러운 단일 박동 — 레이아웃 부하 경감)
|
||||
var scaleAnimX = new System.Windows.Media.Animation.DoubleAnimationUsingKeyFrames
|
||||
{
|
||||
RepeatBehavior = System.Windows.Media.Animation.RepeatBehavior.Forever,
|
||||
Duration = new System.Windows.Duration(TimeSpan.FromSeconds(2.6)),
|
||||
Duration = new System.Windows.Duration(TimeSpan.FromSeconds(3.0)),
|
||||
};
|
||||
var beatTimes = new (double t, double v)[]
|
||||
{
|
||||
(0.00, 1.00), (0.12, 1.28), (0.27, 0.96),
|
||||
(0.40, 1.14), (0.55, 1.00), (2.60, 1.00),
|
||||
(0.00, 1.00), (0.18, 1.15), (0.40, 1.00), (3.00, 1.00),
|
||||
};
|
||||
foreach (var (t, v) in beatTimes)
|
||||
{
|
||||
@@ -6968,19 +6985,19 @@ public partial class ChatWindow : Window
|
||||
System.Windows.Media.Animation.Storyboard.SetTargetProperty(scaleAnimY, new PropertyPath("ScaleY"));
|
||||
sb.Children.Add(scaleAnimY);
|
||||
|
||||
// 픽셀 교차 페이드 (파란→초록→빨간 색상이 교대로 빛남)
|
||||
// 픽셀 교차 페이드 (파란→초록→빨간 색상이 교대로 빛남, 부드럽게)
|
||||
var pixels = new System.Windows.Shapes.Rectangle?[]
|
||||
{ StatusPixelBlue, StatusPixelGreen1, StatusPixelGreen2, StatusPixelRed };
|
||||
for (int i = 0; i < pixels.Length; i++)
|
||||
{
|
||||
if (pixels[i] == null) continue;
|
||||
var fade = new System.Windows.Media.Animation.DoubleAnimation(
|
||||
fromValue: 1.0, toValue: 0.45,
|
||||
duration: new System.Windows.Duration(TimeSpan.FromSeconds(0.85)))
|
||||
fromValue: 1.0, toValue: 0.55,
|
||||
duration: new System.Windows.Duration(TimeSpan.FromSeconds(1.2)))
|
||||
{
|
||||
AutoReverse = true,
|
||||
RepeatBehavior = System.Windows.Media.Animation.RepeatBehavior.Forever,
|
||||
BeginTime = TimeSpan.FromSeconds(i * 0.22),
|
||||
BeginTime = TimeSpan.FromSeconds(i * 0.30),
|
||||
EasingFunction = new System.Windows.Media.Animation.SineEase
|
||||
{ EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut },
|
||||
};
|
||||
@@ -8925,6 +8942,12 @@ public partial class ChatWindow : Window
|
||||
activeCts.Cancel();
|
||||
else
|
||||
foreach (var cts in _tabStreamCts.Values) cts.Cancel();
|
||||
|
||||
// 즉시 UI 상태 정리 — 에이전트 루프의 finally가 비동기로 도달할 때까지 대기하지 않음
|
||||
StopLiveAgentProgressHints();
|
||||
RemoveAgentLiveCard();
|
||||
HideStickyProgress();
|
||||
StopRainbowGlow();
|
||||
}
|
||||
|
||||
// ─── 대화 내보내기 ──────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user