fix(scaffold): fix javascript syntax errors in dropdown and folder picker preventing category loading
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 17s
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 17s
This commit is contained in:
@@ -801,17 +801,17 @@
|
||||
<div class="col-md-12">
|
||||
<label class="form-label">Workspace Path</label>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" name="workspacePath" id="podWorkspacePathInput" placeholder="직접 폴더 경로를 입력(붙여넣기) 하거나 선택하세요" value="c:\eGovFrameDev-4.3.1-64bit\workspace-egov\dat-was-datmt">
|
||||
<button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" style="border-color: #3f3f46; color: #a1a1aa;">폴더 선택</button>
|
||||
<input type="text" class="form-control" name="workspacePath" id="podWorkspacePathInput" placeholder="직접 ?<3F>더 경로<EFBFBD>??<3F>력(붙여?<3F>기) ?<3F>거???<3F>택?<3F>세?? value="c:\eGovFrameDev-4.3.1-64bit\workspace-egov\dat-was-datmt">
|
||||
<button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" style="border-color: #3f3f46; color: #a1a1aa;">?<3F>더 ?<3F>택</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end dropdown-menu-dark" style="background-color: #18181b; border-color: #3f3f46;">
|
||||
<li><a class="dropdown-item" href="#" onclick="const input = document.getElementById('podWorkspacePathInput'); input.value='c:\\eGovFrameDev-4.3.1-64bit\\workspace-egov\\dat-was-datmt'; input.dispatchEvent(new Event('change')); return false;" style="color: #f4f4f5;">dat-was-datmt (기본)</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="const input = document.getElementById('podWorkspacePathInput'); input.value='c:\\eGovFrameDev-4.3.1-64bit\\workspace-egov\\axhub-backend-main'; input.dispatchEvent(new Event('change')); return false;" style="color: #f4f4f5;">axhub-backend-main</a></li>
|
||||
<li><hr class="dropdown-divider" style="border-color: #3f3f46;"></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="openServerFolderPicker('podWorkspacePathInput'); return false;" style="color: #f4f4f5;">폴더 선택(+)</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="openServerFolderPicker('podWorkspacePathInput'); return false;" style="color: #f4f4f5;">?<3F>더 ?<3F>택(+)</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<input type="file" id="podFolderPicker" webkitdirectory directory style="display: none;" onchange="
|
||||
if(this.files && this.files.length > 0) { alert("Path: " + this.files[0].path + ", webkitRel: " + this.files[0].webkitRelativePath + ", name: " + this.files[0].name); if(this.files[0].path) {
|
||||
if(this.files && this.files.length > 0) { if(this.files[0].path) {
|
||||
let firstFilePath = this.files[0].path;
|
||||
let relPath = this.files[0].webkitRelativePath;
|
||||
let folderPath = firstFilePath.substring(0, firstFilePath.length - relPath.length);
|
||||
@@ -823,7 +823,7 @@
|
||||
input.dispatchEvent(new Event('change'));
|
||||
}
|
||||
">
|
||||
<div class="input-hint">직접 경로를 붙여넣거나 우측 <b>[폴더 선택]</b> 버튼을 눌러 선택하세요.</div>
|
||||
<div class="input-hint">직접 경로<EFBFBD>?붙여?<3F>거???<3F>측 <b>[?<3F>더 ?<3F>택]</b> 버튼???<3F>러 ?<3F>택?<3F>세??</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
@@ -858,17 +858,17 @@
|
||||
<div class="col-md-12">
|
||||
<label class="form-label">Workspace Path</label>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" name="workspacePath" id="workspacePathInput" placeholder="직접 폴더 경로를 입력(붙여넣기) 하거나 선택하세요" value="c:\eGovFrameDev-4.3.1-64bit\workspace-egov\dat-was-datmt">
|
||||
<button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" style="border-color: #3f3f46; color: #a1a1aa;">폴더 선택</button>
|
||||
<input type="text" class="form-control" name="workspacePath" id="workspacePathInput" placeholder="직접 ?<3F>더 경로<EFBFBD>??<3F>력(붙여?<3F>기) ?<3F>거???<3F>택?<3F>세?? value="c:\eGovFrameDev-4.3.1-64bit\workspace-egov\dat-was-datmt">
|
||||
<button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" style="border-color: #3f3f46; color: #a1a1aa;">?<3F>더 ?<3F>택</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end dropdown-menu-dark" style="background-color: #18181b; border-color: #3f3f46;">
|
||||
<li><a class="dropdown-item" href="#" onclick="const input = document.getElementById('workspacePathInput'); input.value='c:\\eGovFrameDev-4.3.1-64bit\\workspace-egov\\dat-was-datmt'; input.dispatchEvent(new Event('change')); return false;" style="color: #f4f4f5;">dat-was-datmt (기본)</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="const input = document.getElementById('workspacePathInput'); input.value='c:\\eGovFrameDev-4.3.1-64bit\\workspace-egov\\axhub-backend-main'; input.dispatchEvent(new Event('change')); return false;" style="color: #f4f4f5;">axhub-backend-main</a></li>
|
||||
<li><hr class="dropdown-divider" style="border-color: #3f3f46;"></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="openServerFolderPicker('workspacePathInput'); return false;" style="color: #f4f4f5;">폴더 선택(+)</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="openServerFolderPicker('workspacePathInput'); return false;" style="color: #f4f4f5;">?<3F>더 ?<3F>택(+)</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<input type="file" id="toolFolderPicker" webkitdirectory directory style="display: none;" onchange="
|
||||
if(this.files && this.files.length > 0) { alert("Path: " + this.files[0].path + ", webkitRel: " + this.files[0].webkitRelativePath + ", name: " + this.files[0].name); if(this.files[0].path) {
|
||||
if(this.files && this.files.length > 0) { if(this.files[0].path) {
|
||||
let firstFilePath = this.files[0].path;
|
||||
let relPath = this.files[0].webkitRelativePath;
|
||||
let folderPath = firstFilePath.substring(0, firstFilePath.length - relPath.length);
|
||||
@@ -880,7 +880,7 @@
|
||||
input.dispatchEvent(new Event('change'));
|
||||
}
|
||||
">
|
||||
<div class="input-hint">직접 경로를 붙여넣거나 우측 <b>[폴더 선택]</b> 버튼을 눌러 선택하세요.</div>
|
||||
<div class="input-hint">직접 경로<EFBFBD>?붙여?<3F>거???<3F>측 <b>[?<3F>더 ?<3F>택]</b> 버튼???<3F>러 ?<3F>택?<3F>세??</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
@@ -911,11 +911,11 @@
|
||||
<div class="row g-2">
|
||||
<div class="col-md-5">
|
||||
<select id="domainCategorySelect" class="form-select">
|
||||
<option value="">새 도메인 생성</option>
|
||||
<option value="">???<3F>메???<3F>성</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<input type="text" id="domainCategoryName" class="form-control" name="categoryKey" pattern="^[a-z0-9]{3}$" maxlength="3" minlength="3" placeholder="e.g. cmm (3글자 영소문자)" oninput="this.value = this.value.toLowerCase()" required>
|
||||
<input type="text" id="domainCategoryName" class="form-control" name="categoryKey" pattern="^[a-z0-9]{3}$" maxlength="3" minlength="3" placeholder="e.g. cmm (3글???<3F>소문자)" oninput="this.value = this.value.toLowerCase()" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -931,24 +931,24 @@
|
||||
<div class="d-flex justify-content-between align-items-center gap-3">
|
||||
<div>
|
||||
<label class="form-label mb-1">Multi Tool UseCase (HTTP / MCI)</label>
|
||||
<div class="input-hint mt-0">현재 Tool을 같은 UseCase에 추가하면, Tool별 Client를 호출하는 여러 MCP Tool 메서드가 생성됩니다.</div>
|
||||
<div class="input-hint mt-0">?<3F>재 Tool??같<>? UseCase??추<>??<3F>면, Tool<EFBFBD>?Client<EFBFBD>??<3F>출?<3F>는 ?<3F>러 MCP Tool 메서?<3F><>? ?<3F>성?<3F>니??</div>
|
||||
</div>
|
||||
<button type="button" class="btn-secondary-action" onclick="addCurrentToolToGroup()">현재 Tool 묶음에 추가</button>
|
||||
<button type="button" class="btn-secondary-action" onclick="addCurrentToolToGroup()">?<3F>재 Tool 묶음??추<>?</button>
|
||||
</div>
|
||||
<div class="row g-2 mt-1">
|
||||
<div class="col-md-4"><select id="toolGroupUseCaseSelect" class="form-select"><option value="">새 UseCase 생성</option></select></div>
|
||||
<div class="col-md-5"><input id="toolGroupUseCaseName" type="text" class="form-control" placeholder="UseCase 이름 e.g. Customer"></div>
|
||||
<div class="col-md-7"><div id="toolGroupSummary" class="input-hint pt-2">묶음에 추가된 Tool 없음 — 일반 Generate Tool은 기존 단일 Tool 생성입니다.</div></div>
|
||||
<div class="col-md-4"><select id="toolGroupUseCaseSelect" class="form-select"><option value="">??UseCase ?<3F>성</option></select></div>
|
||||
<div class="col-md-5"><input id="toolGroupUseCaseName" type="text" class="form-control" placeholder="UseCase ?<3F>름 e.g. Customer"></div>
|
||||
<div class="col-md-7"><div id="toolGroupSummary" class="input-hint pt-2">묶음??추<>???Tool ?<3F>음 ???<3F>반 Generate Tool?<3F> 기존 ?<3F>일 Tool ?<3F>성?<3F>니??</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4 p-3 rounded" style="background:#18181b; border:1px solid #3f3f46;">
|
||||
<label class="form-label">AI Tool 초안 만들기</label>
|
||||
<label class="form-label">AI Tool 초안 만들<EFBFBD>?/label>
|
||||
<div class="row g-2">
|
||||
<div class="col-md-6">
|
||||
<input id="toolNaturalLanguage" type="text" class="form-control" placeholder="예: 고객번호로 계약 상태를 조회하는 Tool">
|
||||
<input id="toolNaturalLanguage" type="text" class="form-control" placeholder="?? 고객번호<EFBFBD>?계약 ?<3F>태<EFBFBD>?조회?<3F>는 Tool">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select id="aiModelSelect" class="form-select" aria-label="AI 모델 선택">
|
||||
<select id="aiModelSelect" class="form-select" aria-label="AI 모델 ?<3F>택">
|
||||
<option value="cohere/north-mini-code:free" selected>Cohere North Mini Code</option>
|
||||
<option value="inclusionai/ling-3.0-flash:free">InclusionAI Ling 3 Flash</option>
|
||||
<option value="openai/gpt-oss-20b:free">OpenAI GPT-OSS 20B</option>
|
||||
@@ -957,10 +957,10 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3 d-grid">
|
||||
<button id="toolDraftButton" type="button" class="btn-action" onclick="createAiToolDraft()">AI로 Tool 채우기</button>
|
||||
<button id="toolDraftButton" type="button" class="btn-action" onclick="createAiToolDraft()">AI<EFBFBD>?Tool 채우<EFBFBD>?/button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-hint">선택한 AI가 Tool 기본 정보와 Input/Output Fields를 채웁니다. Legacy Interface ID와 Client System Code는 실제 연계 명세를 확인해 직접 입력하세요.</div>
|
||||
<div class="input-hint">?<3F>택??AI가 Tool 기본 ?<3F>보?<3F> Input/Output Fields<EFBFBD>?채웁?<3F>다. Legacy Interface ID?<3F> Client System Code???<3F>제 ?<3F>계 명세<EBAA85>??<3F>인??직접 ?<3F>력?<3F>세??</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
@@ -988,31 +988,31 @@
|
||||
|
||||
<div class="mb-3 p-3 rounded" style="background:#18181b; border:1px solid #3f3f46;">
|
||||
<div class="form-label mb-2">Tool Schema V17 Metadata</div>
|
||||
<div class="input-hint mb-3">LLM이 Tool을 올바르게 선택하도록 기능·사용 조건·제외 조건·입출력 제한을 분리해 입력합니다.</div>
|
||||
<div class="input-hint mb-3">LLM??Tool???<3F>바르게 ?<3F>택?<3F>도<EFBFBD>?기능·?<3F>용 조건·?<3F>외 조건·?<3F>출???<3F>한??분리???<3F>력?<3F>니??</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Function Description</label>
|
||||
<textarea class="form-control" name="functionDescription" rows="2" placeholder="이 Tool이 수행하는 핵심 기능"></textarea>
|
||||
<textarea class="form-control" name="functionDescription" rows="2" placeholder="??Tool???<3F>행?<3F>는 ?<3F>심 기능"></textarea>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Display Description</label>
|
||||
<textarea class="form-control" name="displayDescription" rows="2" placeholder="Portal에 보여줄 짧은 설명"></textarea>
|
||||
<textarea class="form-control" name="displayDescription" rows="2" placeholder="Portal??보여<EBB3B4>?짧<>? ?<3F>명"></textarea>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">When To Use</label>
|
||||
<textarea class="form-control" name="whenToUse" rows="2" placeholder="어떤 사용자 요청에서 이 Tool을 사용하는지"></textarea>
|
||||
<textarea class="form-control" name="whenToUse" rows="2" placeholder="?<3F>떤 ?<3F>용???<3F>청?<3F>서 ??Tool???<3F>용?<3F>는지"></textarea>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">When Not To Use</label>
|
||||
<textarea class="form-control" name="whenNotToUse" rows="2" placeholder="이 Tool을 사용하면 안 되는 조건"></textarea>
|
||||
<textarea class="form-control" name="whenNotToUse" rows="2" placeholder="??Tool???<3F>용?<3F>면 ???<3F>는 조건"></textarea>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label">I/O Limits</label>
|
||||
<textarea class="form-control" name="ioLimits" rows="2" placeholder="허용되는 입력, 반환 범위, 건수 제한 등"></textarea>
|
||||
<textarea class="form-control" name="ioLimits" rows="2" placeholder="?<3F>용?<3F>는 ?<3F>력, 반환 범위, 건수 ?<3F>한 ??></textarea>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<label class="form-label">Example Queries (3~10)</label>
|
||||
<textarea class="form-control" name="exampleQueries" rows="3" placeholder="한 줄에 하나씩 입력\n예: 사번 10001 직원 정보를 조회해줘"></textarea>
|
||||
<textarea class="form-control" name="exampleQueries" rows="3" placeholder="??줄에 ?<3F>나???<3F>력\n?? ?<3F>번 10001 직원 ?<3F>보<EFBFBD>?조회?<3F>줘"></textarea>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Tags</label>
|
||||
@@ -1040,8 +1040,8 @@
|
||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||
<label class="form-label mb-0">Input Fields (JSON)</label>
|
||||
<div class="d-flex gap-1">
|
||||
<button type="button" class="btn-secondary-action" style="padding: 0.2rem 0.45rem; font-size: 0.72rem;" onclick="openFieldEditor('inputFields')">필드 편집</button>
|
||||
<button type="button" class="btn-secondary-action" style="padding: 0.2rem 0.45rem; font-size: 0.72rem;" onclick="loadFieldExample('inputFields')">예제 넣기</button>
|
||||
<button type="button" class="btn-secondary-action" style="padding: 0.2rem 0.45rem; font-size: 0.72rem;" onclick="openFieldEditor('inputFields')">?<3F>드 ?<3F>집</button>
|
||||
<button type="button" class="btn-secondary-action" style="padding: 0.2rem 0.45rem; font-size: 0.72rem;" onclick="loadFieldExample('inputFields')">?<3F>제 ?<3F>기</button>
|
||||
<button type="button" class="btn-secondary-action" style="padding: 0.2rem 0.45rem; font-size: 0.72rem;" onclick="copyFieldJson('inputFields')">복사</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1051,8 +1051,8 @@
|
||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||
<label class="form-label mb-0">Output Fields (JSON)</label>
|
||||
<div class="d-flex gap-1">
|
||||
<button type="button" class="btn-secondary-action" style="padding: 0.2rem 0.45rem; font-size: 0.72rem;" onclick="openFieldEditor('outputFields')">필드 편집</button>
|
||||
<button type="button" class="btn-secondary-action" style="padding: 0.2rem 0.45rem; font-size: 0.72rem;" onclick="loadFieldExample('outputFields')">예제 넣기</button>
|
||||
<button type="button" class="btn-secondary-action" style="padding: 0.2rem 0.45rem; font-size: 0.72rem;" onclick="openFieldEditor('outputFields')">?<3F>드 ?<3F>집</button>
|
||||
<button type="button" class="btn-secondary-action" style="padding: 0.2rem 0.45rem; font-size: 0.72rem;" onclick="loadFieldExample('outputFields')">?<3F>제 ?<3F>기</button>
|
||||
<button type="button" class="btn-secondary-action" style="padding: 0.2rem 0.45rem; font-size: 0.72rem;" onclick="copyFieldJson('outputFields')">복사</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1064,7 +1064,7 @@
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">HTTP API Name (Glow api-list)</label>
|
||||
<input type="text" class="form-control" name="httpApiName" pattern="^[a-zA-Z0-9_-]+$" placeholder="비우면 Tool 이름으로 자동 생성">
|
||||
<input type="text" class="form-control" name="httpApiName" pattern="^[a-zA-Z0-9_-]+$" placeholder="비우<EFBFBD>?Tool ?<3F>름?<3F>로 ?<3F>동 ?<3F>성">
|
||||
<div class="input-hint">HTTP only. Must match glow.communication.http.api-list[].name; URL and method are read from Glow YAML.</div>
|
||||
</div>
|
||||
<div class="col-md-6 mt-3 mt-md-0">
|
||||
@@ -1096,12 +1096,12 @@
|
||||
<div class="docgen-workspace">
|
||||
<section class="docgen-config">
|
||||
<h2 class="docgen-section-title">Document Generator</h2>
|
||||
<p class="docgen-section-copy">Tool Metadata를 기준으로 개발 산출물 Excel을 생성합니다. 선택된 문서만 파일과 시트에 포함됩니다.</p>
|
||||
<p class="docgen-section-copy">Tool Metadata<EFBFBD>?기<>??<3F>로 개발 ?<3F>출<EFBFBD>?Excel???<3F>성?<3F>니?? ?<3F>택??문서<EBACB8>??<3F>일<EFBFBD>??<3F>트???<3F>함?<3F>니??</p>
|
||||
|
||||
<div class="docgen-field">
|
||||
<label class="docgen-field-label" for="docgenToolSelect">Tool</label>
|
||||
<select id="docgenToolSelect" disabled><option>Tool Metadata를 불러오는 중...</option></select>
|
||||
<div id="docgenGrowToolHint" class="docgen-hint">Gateway의 ToolMetadata 목록을 조회하고 있습니다.</div>
|
||||
<select id="docgenToolSelect" disabled><option>Tool Metadata<EFBFBD>?불러?<3F>는 <20>?..</option></select>
|
||||
<div id="docgenGrowToolHint" class="docgen-hint">Gateway??ToolMetadata 목록??조회?<3F>고 ?<3F>습?<3F>다.</div>
|
||||
</div>
|
||||
|
||||
<div class="docgen-two-col docgen-field">
|
||||
@@ -1118,10 +1118,10 @@
|
||||
<div class="docgen-field">
|
||||
<label class="docgen-field-label">Included Sheets</label>
|
||||
<div class="docgen-check-grid">
|
||||
<label class="docgen-check-card"><input id="docgenProgramCheck" type="checkbox" checked><span>프로그램정의서</span></label>
|
||||
<label class="docgen-check-card"><input id="docgenProcessCheck" type="checkbox" checked><span>처리설계</span></label>
|
||||
<label class="docgen-check-card"><input id="docgenInterfaceCheck" type="checkbox" checked><span>인터페이스</span><span class="docgen-mini-badge">별도 파일</span></label>
|
||||
<label class="docgen-check-card"><input id="docgenRevisionCheck" type="checkbox" checked><span>개정이력</span></label>
|
||||
<label class="docgen-check-card"><input id="docgenProgramCheck" type="checkbox" checked><span>?<3F>로그램?<3F>의??/span></label>
|
||||
<label class="docgen-check-card"><input id="docgenProcessCheck" type="checkbox" checked><span>처리?<3F>계</span></label>
|
||||
<label class="docgen-check-card"><input id="docgenInterfaceCheck" type="checkbox" checked><span>?<3F>터?<3F>이??/span><span class="docgen-mini-badge">별도 ?<3F>일</span></label>
|
||||
<label class="docgen-check-card"><input id="docgenRevisionCheck" type="checkbox" checked><span>개정?<3F>력</span></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1136,7 +1136,7 @@
|
||||
<div class="docgen-meta-title">
|
||||
<div>
|
||||
<h2 id="docgenToolTitle" class="docgen-loading">Tool Metadata loading...</h2>
|
||||
<p id="docgenToolDescription">등록된 Tool 목록을 가져오는 중입니다.</p>
|
||||
<p id="docgenToolDescription">?<3F>록??Tool 목록??가?<3F>오??중입?<3F>다.</p>
|
||||
</div>
|
||||
<span id="docgenMetadataStatus" class="docgen-status">SYNC</span>
|
||||
</div>
|
||||
@@ -1148,16 +1148,16 @@
|
||||
</div>
|
||||
|
||||
<div class="docgen-list">
|
||||
<div id="docgenProgramRow" class="docgen-row docgen-enabled"><span class="docgen-number">01</span><div><div class="docgen-name">프로그램정의서</div><div class="docgen-description">Basic information · Runtime · Process summary</div></div><span class="docgen-mode docgen-auto">AUTO</span></div>
|
||||
<div id="docgenProcessRow" class="docgen-row docgen-enabled"><span class="docgen-number">02</span><div><div class="docgen-name">처리설계</div><div class="docgen-description">Tool metadata + common design</div></div><span class="docgen-mode docgen-mixed">MIXED</span></div>
|
||||
<div id="docgenInterfaceRow" class="docgen-row docgen-enabled"><span class="docgen-number">03</span><div><div class="docgen-name">인터페이스</div><div class="docgen-description">Request In · Response Out · 2 sheets</div></div><span class="docgen-mode docgen-separate">2 SHEETS · SEPARATE</span></div>
|
||||
<div id="docgenRevisionRow" class="docgen-row docgen-enabled"><span class="docgen-number">04</span><div><div class="docgen-name">개정이력</div><div class="docgen-description">Version · Date · Change information</div></div><span class="docgen-mode">MANUAL</span></div>
|
||||
<div id="docgenProgramRow" class="docgen-row docgen-enabled"><span class="docgen-number">01</span><div><div class="docgen-name">?<3F>로그램?<3F>의??/div><div class="docgen-description">Basic information · Runtime · Process summary</div></div><span class="docgen-mode docgen-auto">AUTO</span></div>
|
||||
<div id="docgenProcessRow" class="docgen-row docgen-enabled"><span class="docgen-number">02</span><div><div class="docgen-name">처리?<3F>계</div><div class="docgen-description">Tool metadata + common design</div></div><span class="docgen-mode docgen-mixed">MIXED</span></div>
|
||||
<div id="docgenInterfaceRow" class="docgen-row docgen-enabled"><span class="docgen-number">03</span><div><div class="docgen-name">?<3F>터?<3F>이??/div><div class="docgen-description">Request In · Response Out · 2 sheets</div></div><span class="docgen-mode docgen-separate">2 SHEETS · SEPARATE</span></div>
|
||||
<div id="docgenRevisionRow" class="docgen-row docgen-enabled"><span class="docgen-number">04</span><div><div class="docgen-name">개정?<3F>력</div><div class="docgen-description">Version · Date · Change information</div></div><span class="docgen-mode">MANUAL</span></div>
|
||||
</div>
|
||||
|
||||
<p class="docgen-legend">AUTO: Tool metadata · MIXED: Metadata + common design · MANUAL: Review required<br>Output Files · 인터페이스 정의서는 별도 Excel 파일로 생성됩니다.</p>
|
||||
<p class="docgen-legend">AUTO: Tool metadata · MIXED: Metadata + common design · MANUAL: Review required<br>Output Files · ?<3F>터?<3F>이???<3F>의?<3F>는 별도 Excel ?<3F>일<EFBFBD>??<3F>성?<3F>니??</p>
|
||||
<div class="docgen-files">
|
||||
<div id="docgenProgramFile" class="docgen-file"><div class="docgen-file-kind">PROGRAM SPEC</div><div id="docgenProgramFileName" class="docgen-file-name">tool_프로그램정의서_v1.0_YYYYMMDD.xlsx</div></div>
|
||||
<div id="docgenInterfaceFile" class="docgen-file"><div class="docgen-file-kind">INTERFACE SPEC · REQUEST IN / RESPONSE OUT</div><div id="docgenInterfaceFileName" class="docgen-file-name">tool_인터페이스정의서_v1.0_YYYYMMDD.xlsx</div></div>
|
||||
<div id="docgenProgramFile" class="docgen-file"><div class="docgen-file-kind">PROGRAM SPEC</div><div id="docgenProgramFileName" class="docgen-file-name">tool_?<3F>로그램?<3F>의??v1.0_YYYYMMDD.xlsx</div></div>
|
||||
<div id="docgenInterfaceFile" class="docgen-file"><div class="docgen-file-kind">INTERFACE SPEC · REQUEST IN / RESPONSE OUT</div><div id="docgenInterfaceFileName" class="docgen-file-name">tool_?<3F>터?<3F>이?<3F>정?<3F>서_v1.0_YYYYMMDD.xlsx</div></div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@@ -1210,26 +1210,26 @@
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="fieldEditorModalLabel">필드 편집</h5>
|
||||
<h5 class="modal-title" id="fieldEditorModalLabel">?<3F>드 ?<3F>집</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="input-hint mt-0 mb-3">행을 추가해 필드를 입력하면 저장할 때 JSON으로 자동 변환됩니다.</p>
|
||||
<p class="input-hint mt-0 mb-3">?<3F>을 추<EFBFBD>????<3F>드<EFBFBD>??<3F>력?<3F>면 ?<3F>?<3F>할 ??JSON?<3F>로 ?<3F>동 변?<3F>됩?<3F>다.</p>
|
||||
<div class="d-flex flex-wrap gap-2 align-items-center mb-3">
|
||||
<span class="input-hint mt-0 mb-0">빠른 입력:</span>
|
||||
<span class="input-hint mt-0 mb-0">빠른 ?<3F>력:</span>
|
||||
<button type="button" class="btn-secondary-action" onclick="applyFieldTemplate('customer')">고객조회</button>
|
||||
<button type="button" class="btn-secondary-action" onclick="applyFieldTemplate('list')">목록조회</button>
|
||||
<button type="button" class="btn-secondary-action" onclick="applyFieldTemplate('detail')">단건조회</button>
|
||||
<button type="button" class="btn-secondary-action" onclick="applyFieldTemplate('write')">등록/변경</button>
|
||||
<button type="button" class="btn-secondary-action" onclick="applyFieldTemplate('clear')">초기화</button>
|
||||
<button type="button" class="btn-secondary-action" onclick="applyFieldTemplate('detail')">?<3F>건조회</button>
|
||||
<button type="button" class="btn-secondary-action" onclick="applyFieldTemplate('write')">?<3F>록/변<EFBFBD>?/button>
|
||||
<button type="button" class="btn-secondary-action" onclick="applyFieldTemplate('clear')">초기??/button>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="form-label">자연어 초안 만들기</label>
|
||||
<label class="form-label">?<3F>연??초안 만들<EBA78C>?/label>
|
||||
<div class="input-group">
|
||||
<input id="fieldNaturalLanguage" type="text" class="form-control" placeholder="예: 고객번호로 계약 상태를 조회">
|
||||
<button id="fieldDraftButton" type="button" class="btn-action" onclick="createNaturalFieldDraft()">AI 초안 만들기</button>
|
||||
<input id="fieldNaturalLanguage" type="text" class="form-control" placeholder="?? 고객번호<EFBFBD>?계약 ?<3F>태<EFBFBD>?조회">
|
||||
<button id="fieldDraftButton" type="button" class="btn-action" onclick="createNaturalFieldDraft()">AI 초안 만들<EFBFBD>?/button>
|
||||
</div>
|
||||
<div class="input-hint">Chat 화면과 같은 AI 모델이 문장을 분석해 현재 Input 또는 Output 필드 초안을 만듭니다.</div>
|
||||
<div class="input-hint">Chat ?<3F>면<EFBFBD>?같<>? AI 모델??문장??분석???<3F>재 Input ?<3F>는 Output ?<3F>드 초안??만듭?<3F>다.</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table align-middle" id="fieldEditorTable">
|
||||
@@ -1241,15 +1241,15 @@
|
||||
<th style="min-width: 260px;">Object list item fields (JSON)</th>
|
||||
<th style="min-width: 210px;">Description</th>
|
||||
<th style="min-width: 150px;">Pattern (Regex)</th>
|
||||
<th style="min-width: 180px;">Examples (Enter 단위 구분)</th>
|
||||
<th style="min-width: 180px;">Examples (Enter ?<3F>위 구분)</th>
|
||||
<th style="min-width: 125px;">Required</th>
|
||||
<th style="width: 1%;">삭제</th>
|
||||
<th style="width: 1%;">??<3F><></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="fieldEditorBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<button type="button" class="btn-secondary-action" onclick="addFieldEditorRow()">+ 필드 추가</button>
|
||||
<button type="button" class="btn-secondary-action" onclick="addFieldEditorRow()">+ ?<3F>드 추<EFBFBD>?</button>
|
||||
<div class="mt-4">
|
||||
<label class="form-label">JSON 미리보기</label>
|
||||
<pre id="fieldEditorPreview" class="mb-0 p-3 rounded" style="background:#09090b; border:1px solid #27272a; color:#e4e4e7; font-size:0.78rem; max-height:190px; overflow:auto;"></pre>
|
||||
@@ -1257,7 +1257,7 @@
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn-secondary-action" data-bs-dismiss="modal" style="padding: 0.5rem 1rem; font-size: 0.875rem;">취소</button>
|
||||
<button type="button" class="btn-action" onclick="applyFieldEditor()">JSON에 적용</button>
|
||||
<button type="button" class="btn-action" onclick="applyFieldEditor()">JSON???<3F>용</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1268,7 +1268,7 @@
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">하위 필드(itemFields) 편집</h5>
|
||||
<h5 class="modal-title">?<3F>위 ?<3F>드(itemFields) ?<3F>집</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@@ -1289,7 +1289,7 @@
|
||||
<tbody id="subFieldEditorBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<button type="button" class="btn-action mt-2" onclick="addSubFieldEditorRow()">+ 하위 필드 추가</button>
|
||||
<button type="button" class="btn-action mt-2" onclick="addSubFieldEditorRow()">+ ?<3F>위 ?<3F>드 추<EFBFBD>?</button>
|
||||
<div class="mt-4">
|
||||
<label class="form-label">JSON 미리보기</label>
|
||||
<pre id="subFieldEditorPreview" class="mb-0 p-3 rounded" style="background:#09090b; border:1px solid #27272a; color:#e4e4e7; font-size:0.78rem; max-height:190px; overflow:auto;"></pre>
|
||||
@@ -1297,7 +1297,7 @@
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn-secondary-action" data-bs-dismiss="modal">취소</button>
|
||||
<button type="button" class="btn-action" onclick="applySubFieldEditor()">적용</button>
|
||||
<button type="button" class="btn-action" onclick="applySubFieldEditor()">?<3F>용</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1382,13 +1382,13 @@
|
||||
const button = dg('docgenGenerateBtn');
|
||||
select.disabled = true;
|
||||
button.disabled = true;
|
||||
dg('docgenGrowToolHint').textContent = 'Gateway의 ToolMetadata 목록을 조회하고 있습니다.';
|
||||
dg('docgenGrowToolHint').textContent = 'Gateway??ToolMetadata 목록??조회?<3F>고 ?<3F>습?<3F>다.';
|
||||
try {
|
||||
const response = await fetch('/mcp/api/v1/tools/list', { cache: 'no-store' });
|
||||
if (!response.ok) throw new Error(`Gateway HTTP ${response.status}`);
|
||||
const payload = await response.json();
|
||||
const tools = payload?.result?.tools;
|
||||
if (!Array.isArray(tools)) throw new Error('ToolMetadata 응답 형식이 올바르지 않습니다.');
|
||||
if (!Array.isArray(tools)) throw new Error('ToolMetadata ?<3F>답 ?<3F>식???<3F>바르<EBB094>? ?<3F>습?<3F>다.');
|
||||
state.tools = tools.slice().sort((a, b) =>
|
||||
(a.categoryKey || '').localeCompare(b.categoryKey || '') ||
|
||||
(a.name || '').localeCompare(b.name || '')
|
||||
@@ -1397,19 +1397,19 @@
|
||||
`<option value="${index}">[${escapeHtml(tool.categoryKey || 'etc')}] ${escapeHtml(tool.name || tool.displayName || tool.uid)}</option>`
|
||||
).join('');
|
||||
select.disabled = state.tools.length === 0;
|
||||
dg('docgenGrowToolHint').textContent = `ToolMetadata에 등록된 ${state.tools.length}개 Tool을 모두 표시합니다.`;
|
||||
dg('docgenGrowToolHint').textContent = `ToolMetadata???<3F>록??${state.tools.length}<EFBFBD>?Tool??모두 ?<3F>시?<3F>니??`;
|
||||
if (state.tools.length) {
|
||||
select.value = '0';
|
||||
selectTool();
|
||||
} else {
|
||||
showMetadataError('등록된 Tool이 없습니다.');
|
||||
showMetadataError('?<3F>록??Tool???<3F>습?<3F>다.');
|
||||
}
|
||||
} catch (error) {
|
||||
state.tools = [];
|
||||
state.selected = null;
|
||||
showMetadataError(error.message);
|
||||
select.innerHTML = '<option>Tool Metadata 조회 실패</option>';
|
||||
dg('docgenGrowToolHint').innerHTML = `<span class="docgen-error">${escapeHtml(error.message)}</span> · Gateway 실행 상태를 확인하세요.`;
|
||||
select.innerHTML = '<option>Tool Metadata 조회 ?<3F>패</option>';
|
||||
dg('docgenGrowToolHint').innerHTML = `<span class="docgen-error">${escapeHtml(error.message)}</span> · Gateway ?<3F>행 ?<3F>태<EFBFBD>??<3F>인?<3F>세??`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1420,7 +1420,7 @@
|
||||
dg('docgenVersion').value = normalizeVersion(tool.semver || dg('docgenVersion').value || '1.0');
|
||||
dg('docgenToolTitle').classList.remove('docgen-loading', 'docgen-error');
|
||||
dg('docgenToolTitle').textContent = tool.displayName || tool.name;
|
||||
dg('docgenToolDescription').textContent = tool.description || '설명이 등록되지 않은 Tool입니다.';
|
||||
dg('docgenToolDescription').textContent = tool.description || '?<3F>명???<3F>록?<3F><>? ?<3F><>? Tool?<3F>니??';
|
||||
dg('docgenCategoryTag').textContent = `Category · ${tool.categoryKey || '-'}`;
|
||||
dg('docgenInterfaceTag').textContent = `Interface · ${tool.integrationType || '-'}`;
|
||||
dg('docgenMetadataStatus').textContent = tool.enabled === false ? 'DISABLED' : 'READY';
|
||||
@@ -1442,14 +1442,14 @@
|
||||
const hasProgram = checks.program.checked || checks.process.checked || checks.revision.checked;
|
||||
dg('docgenProgramFile').classList.toggle('docgen-disabled', !hasProgram);
|
||||
dg('docgenInterfaceFile').classList.toggle('docgen-disabled', !checks.interface.checked);
|
||||
dg('docgenProgramFileName').textContent = `${toolName}_프로그램정의서_v${version}_${date}.xlsx`;
|
||||
dg('docgenInterfaceFileName').textContent = `${toolName}_인터페이스정의서_v${version}_${date}.xlsx`;
|
||||
dg('docgenProgramFileName').textContent = `${toolName}_?<3F>로그램?<3F>의??v${version}_${date}.xlsx`;
|
||||
dg('docgenInterfaceFileName').textContent = `${toolName}_?<3F>터?<3F>이?<3F>정?<3F>서_v${version}_${date}.xlsx`;
|
||||
dg('docgenGenerateBtn').disabled = !state.selected || (!hasProgram && !checks.interface.checked);
|
||||
}
|
||||
|
||||
async function generateFiles() {
|
||||
const tool = state.selected;
|
||||
if (!tool) return notify('생성할 Tool을 선택하세요.');
|
||||
if (!tool) return notify('?<3F>성??Tool???<3F>택?<3F>세??');
|
||||
const button = dg('docgenGenerateBtn');
|
||||
const version = safeVersion(dg('docgenVersion').value);
|
||||
const date = yyyymmdd();
|
||||
@@ -1468,13 +1468,13 @@
|
||||
try {
|
||||
if (hasProgram) {
|
||||
await requestDownload('/mcp/api/v1/admin/documents/program', request,
|
||||
`${toolName}_프로그램정의서_v${version}_${date}.xlsx`);
|
||||
`${toolName}_?<3F>로그램?<3F>의??v${version}_${date}.xlsx`);
|
||||
}
|
||||
if (checks.interface.checked) {
|
||||
await requestDownload('/mcp/api/v1/admin/documents/interface', request,
|
||||
`${toolName}_인터페이스정의서_v${version}_${date}.xlsx`);
|
||||
`${toolName}_?<3F>터?<3F>이?<3F>정?<3F>서_v${version}_${date}.xlsx`);
|
||||
}
|
||||
notify('선택한 Excel 문서 다운로드를 완료했습니다.');
|
||||
notify('?<3F>택??Excel 문서 ?<3F>운로드<EFBFBD>??<3F>료?<3F>습?<3F>다.');
|
||||
} catch (error) {
|
||||
notify(error.message);
|
||||
} finally {
|
||||
@@ -1490,12 +1490,12 @@
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
if (!response.ok) {
|
||||
let message = `문서 생성에 실패했습니다. (HTTP ${response.status})`;
|
||||
let message = `문서 ?<3F>성???<3F>패?<3F>습?<3F>다. (HTTP ${response.status})`;
|
||||
try {
|
||||
const error = await response.json();
|
||||
if (error?.error) message = error.error;
|
||||
} catch (_) {
|
||||
// JSON 오류 응답이 아닌 경우 기본 메시지를 사용합니다.
|
||||
// JSON ?<3F>류 ?<3F>답???<3F>닌 경우 기본 메시지<EFBFBD>??<3F>용?<3F>니??
|
||||
}
|
||||
throw new Error(message);
|
||||
}
|
||||
@@ -1556,7 +1556,7 @@
|
||||
const resultBox = document.getElementById('resultBox');
|
||||
resultBox.style.display = 'block';
|
||||
|
||||
if (result.includes('[오류]') || result.includes('오류 발생:')) {
|
||||
if (result.includes('[?<3F>류]') || result.includes('?<3F>류 발생:')) {
|
||||
resultBox.className = 'error';
|
||||
resultBox.textContent = result;
|
||||
} else {
|
||||
@@ -1622,16 +1622,16 @@
|
||||
const form = document.getElementById('toolForm');
|
||||
const data = Object.fromEntries(new FormData(form).entries());
|
||||
if (!data.baseName) {
|
||||
throw new Error('Base Name을 입력해주세요.');
|
||||
throw new Error('Base Name???<3F>력?<3F>주?<3F>요.');
|
||||
}
|
||||
if (data.routingType === 'MCI' && (!data.interfaceId || !data.clientSystemCode)) {
|
||||
throw new Error('MCI Tool은 Legacy Interface ID와 Target System Code를 입력해야 합니다.');
|
||||
throw new Error('MCI Tool?<3F> Legacy Interface ID?<3F> Target System Code<EFBFBD>??<3F>력?<3F>야 ?<3F>니??');
|
||||
}
|
||||
if (data.routingType === 'HTTP' && !data.httpApiName) {
|
||||
throw new Error('HTTP Tool은 HTTP API Name을 입력해야 합니다.');
|
||||
throw new Error('HTTP Tool?<3F> HTTP API Name???<3F>력?<3F>야 ?<3F>니??');
|
||||
}
|
||||
if (!['MCI', 'HTTP'].includes(data.routingType)) {
|
||||
throw new Error('여러 Tool UseCase는 MCI 또는 HTTP 프로토콜만 지원합니다.');
|
||||
throw new Error('?<3F>러 Tool UseCase??MCI ?<3F>는 HTTP ?<3F>로?<3F>콜<EFBFBD>?지?<3F>합?<3F>다.');
|
||||
}
|
||||
return {
|
||||
baseName: data.baseName,
|
||||
@@ -1659,7 +1659,7 @@
|
||||
try {
|
||||
const tool = currentToolDefinition();
|
||||
if (groupedTools.some(item => item.methodName === tool.methodName || item.baseName === tool.baseName)) {
|
||||
throw new Error('같은 Base Name 또는 메서드명이 이미 묶음에 있습니다.');
|
||||
throw new Error('같<EFBFBD>? Base Name ?<3F>는 메서?<3F>명???<3F><>? 묶음???<3F>습?<3F>다.');
|
||||
}
|
||||
groupedTools.push(tool);
|
||||
renderToolGroupSummary();
|
||||
@@ -1673,13 +1673,14 @@
|
||||
const workspacePath = document.querySelector('#toolForm input[name="workspacePath"]')?.value || document.querySelector('input[name="workspacePath"]')?.value || '';
|
||||
const categoryKey = document.querySelector('#toolForm [name="categoryKey"]').value.trim();
|
||||
const select = document.getElementById('toolGroupUseCaseSelect');
|
||||
select.innerHTML = '<option value="">새 UseCase 생성</option>';
|
||||
select.innerHTML = '<option value="">??UseCase ?<3F>성</option>';
|
||||
select.innerHTML = '<option value="">??UseCase ?성</option>';
|
||||
if (!/^[a-z0-9]{3}$/.test(categoryKey)) return;
|
||||
try {
|
||||
const response = await fetch(`/api/v1/scaffold/usecases?moduleName=${encodeURIComponent(moduleName)}&categoryKey=${encodeURIComponent(categoryKey)}&workspacePath=${encodeURIComponent(workspacePath)}`);
|
||||
if (!response.ok) throw new Error('UseCase 목록 조회 실패');
|
||||
if (!response.ok) throw new Error('UseCase 목록 조회 ?패');
|
||||
const useCases = await response.json();
|
||||
useCases.forEach(useCaseName => select.add(new Option(`기존 ${useCaseName}에 함수 추가`, useCaseName)));
|
||||
useCases.forEach(useCaseName => select.add(new Option(`기존 ${useCaseName} UseCase 추가`, useCaseName)));
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
}
|
||||
@@ -1690,10 +1691,10 @@
|
||||
const workspacePath = document.querySelector('#toolForm input[name="workspacePath"]')?.value || document.querySelector('input[name="workspacePath"]')?.value || '';
|
||||
const select = document.getElementById('domainCategorySelect');
|
||||
const nameInput = document.getElementById('domainCategoryName');
|
||||
select.innerHTML = '<option value="">새 도메인 생성</option>';
|
||||
select.innerHTML = '<option value="">???메???성</option>';
|
||||
try {
|
||||
const response = await fetch(`/api/v1/scaffold/categories?moduleName=${encodeURIComponent(moduleName)}&workspacePath=${encodeURIComponent(workspacePath)}`);
|
||||
if (!response.ok) throw new Error('Category 목록 조회 실패');
|
||||
if (!response.ok) throw new Error('Category 목록 조회 ?패');
|
||||
const categories = await response.json();
|
||||
categories.forEach(cat => select.add(new Option(`기존 ${cat} 도메인`, cat)));
|
||||
} catch (error) {
|
||||
@@ -1731,8 +1732,8 @@
|
||||
function renderToolGroupSummary() {
|
||||
const summary = document.getElementById('toolGroupSummary');
|
||||
summary.textContent = groupedTools.length
|
||||
? `${groupedTools.length}개 Tool: ${groupedTools.map(tool => `${tool.baseName} → ${tool.methodName}()`).join(', ')}`
|
||||
: '묶음에 추가된 Tool 없음 — 일반 Generate Tool은 기존 단일 Tool 생성입니다.';
|
||||
? `${groupedTools.length}<EFBFBD>?Tool: ${groupedTools.map(tool => `${tool.baseName} ??${tool.methodName}()`).join(', ')}`
|
||||
: '묶음??추<>???Tool ?<3F>음 ???<3F>반 Generate Tool?<3F> 기존 ?<3F>일 Tool ?<3F>성?<3F>니??';
|
||||
}
|
||||
|
||||
document.getElementById('toolForm').addEventListener('submit', function(e) {
|
||||
@@ -1741,7 +1742,7 @@
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
if (!/^[A-Z][A-Za-z0-9]*$/.test(useCaseName)) {
|
||||
alert('UseCase 이름은 PascalCase로 입력해주세요. 예: Customer');
|
||||
alert('UseCase ?<3F>름?<3F> PascalCase<EFBFBD>??<3F>력?<3F>주?<3F>요. ?? Customer');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -1751,7 +1752,7 @@
|
||||
|
||||
const btn = this.querySelector('button[type="submit"]');
|
||||
const originalText = btn.innerHTML;
|
||||
btn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> 처리중...';
|
||||
btn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> 처리<EFBFBD>?..';
|
||||
btn.disabled = true;
|
||||
|
||||
fetch('/api/v1/scaffold/tool-group', {
|
||||
@@ -1956,15 +1957,15 @@
|
||||
fields = JSON.parse(textarea.value);
|
||||
if (!Array.isArray(fields)) throw new Error('not an array');
|
||||
} catch (error) {
|
||||
alert('현재 JSON 형식이 올바르지 않습니다. JSON을 수정한 후 다시 열어주세요.');
|
||||
alert('?<3F>재 JSON ?<3F>식???<3F>바르<EBB094>? ?<3F>습?<3F>다. JSON???<3F>정?????<3F>시 ?<3F>어주세??');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fieldEditorTargetId = targetId;
|
||||
document.getElementById('fieldEditorModalLabel').textContent = targetId === 'inputFields'
|
||||
? 'Input Fields 편집'
|
||||
: 'Output Fields 편집';
|
||||
? 'Input Fields ?<3F>집'
|
||||
: 'Output Fields ?<3F>집';
|
||||
const body = document.getElementById('fieldEditorBody');
|
||||
body.replaceChildren();
|
||||
(fields.length ? fields : [{}]).forEach(addFieldEditorRow);
|
||||
@@ -2035,14 +2036,14 @@
|
||||
itemFieldsContainer.className = 'd-flex gap-1';
|
||||
|
||||
const itemFieldsInput = makeInput(field.type === 'List' && field.itemType === 'Object'
|
||||
? JSON.stringify(field.itemFields || []) : '', 'JSON 직접입력 또는 우측 편집 클릭');
|
||||
? JSON.stringify(field.itemFields || []) : '', 'JSON 직접?<3F>력 ?<3F>는 ?<3F>측 ?<3F>집 ?<3F>릭');
|
||||
itemFieldsInput.dataset.field = 'itemFields';
|
||||
itemFieldsInput.style.flex = '1';
|
||||
|
||||
const editItemBtn = document.createElement('button');
|
||||
editItemBtn.type = 'button';
|
||||
editItemBtn.className = 'btn-secondary-action';
|
||||
editItemBtn.textContent = '편집';
|
||||
editItemBtn.textContent = '?<3F>집';
|
||||
editItemBtn.style.padding = '0.2rem 0.5rem';
|
||||
editItemBtn.onclick = () => {
|
||||
if (typeof openSubFieldEditor === 'function') openSubFieldEditor(itemFieldsInput);
|
||||
@@ -2056,7 +2057,7 @@
|
||||
itemFieldsInput.disabled = !objectList;
|
||||
editItemBtn.disabled = !objectList;
|
||||
itemFieldsInput.placeholder = objectList
|
||||
? 'JSON 직접입력 또는 우측 편집 클릭'
|
||||
? 'JSON 직접?<3F>력 ?<3F>는 ?<3F>측 ?<3F>집 ?<3F>릭'
|
||||
: 'Select List > Object to enter item fields';
|
||||
if (!objectList) itemFieldsInput.value = '';
|
||||
};
|
||||
@@ -2092,7 +2093,7 @@
|
||||
const deleteButton = document.createElement('button');
|
||||
deleteButton.type = 'button';
|
||||
deleteButton.className = 'btn-secondary-action';
|
||||
deleteButton.textContent = '삭제';
|
||||
deleteButton.textContent = '??<3F><>';
|
||||
deleteButton.addEventListener('click', () => {
|
||||
row.remove();
|
||||
updateFieldEditorPreview();
|
||||
@@ -2150,12 +2151,12 @@
|
||||
async function createNaturalFieldDraft() {
|
||||
const source = document.getElementById('fieldNaturalLanguage').value.trim();
|
||||
if (!source) {
|
||||
alert('필드 초안을 만들 문장을 입력해주세요.');
|
||||
alert('?<3F>드 초안??만들 문장???<3F>력?<3F>주?<3F>요.');
|
||||
return;
|
||||
}
|
||||
const button = document.getElementById('fieldDraftButton');
|
||||
const originalLabel = button.textContent;
|
||||
button.textContent = 'AI 생성 중...';
|
||||
button.textContent = 'AI ?<3F>성 <20>?..';
|
||||
button.disabled = true;
|
||||
try {
|
||||
const response = await fetch('/api/v1/scaffold/field-draft', {
|
||||
@@ -2164,16 +2165,16 @@
|
||||
body: JSON.stringify({ description: source, target: fieldEditorTargetId, model: selectedAiModel() })
|
||||
});
|
||||
const result = await response.json();
|
||||
if (!response.ok) throw new Error(result.error || 'AI 초안 생성에 실패했습니다.');
|
||||
if (!response.ok) throw new Error(result.error || 'AI 초안 ?<3F>성???<3F>패?<3F>습?<3F>다.');
|
||||
if (!Array.isArray(result.fields) || result.fields.length === 0) {
|
||||
throw new Error('AI가 사용할 수 있는 필드를 만들지 못했습니다.');
|
||||
throw new Error('AI가 ?<3F>용?????<3F>는 ?<3F>드<EFBFBD>?만들지 못했?<3F>니??');
|
||||
}
|
||||
const body = document.getElementById('fieldEditorBody');
|
||||
body.replaceChildren();
|
||||
result.fields.forEach(addFieldEditorRow);
|
||||
updateFieldEditorPreview();
|
||||
} catch (error) {
|
||||
alert(`AI 초안 생성 실패: ${error.message}`);
|
||||
alert(`AI 초안 ?<3F>성 ?<3F>패: ${error.message}`);
|
||||
} finally {
|
||||
button.textContent = originalLabel;
|
||||
button.disabled = false;
|
||||
@@ -2187,12 +2188,12 @@
|
||||
async function createAiToolDraft() {
|
||||
const source = document.getElementById('toolNaturalLanguage').value.trim();
|
||||
if (!source) {
|
||||
alert('AI가 만들 Tool 설명을 입력해주세요.');
|
||||
alert('AI가 만들 Tool ?<3F>명???<3F>력?<3F>주?<3F>요.');
|
||||
return;
|
||||
}
|
||||
const button = document.getElementById('toolDraftButton');
|
||||
const originalLabel = button.textContent;
|
||||
button.textContent = 'AI 생성 중...';
|
||||
button.textContent = 'AI ?<3F>성 <20>?..';
|
||||
button.disabled = true;
|
||||
try {
|
||||
const response = await fetch('/api/v1/scaffold/tool-draft', {
|
||||
@@ -2201,7 +2202,7 @@
|
||||
body: JSON.stringify({ description: source, model: selectedAiModel() })
|
||||
});
|
||||
const result = await response.json();
|
||||
if (!response.ok) throw new Error(result.error || 'AI Tool 초안 생성에 실패했습니다.');
|
||||
if (!response.ok) throw new Error(result.error || 'AI Tool 초안 ?<3F>성???<3F>패?<3F>습?<3F>다.');
|
||||
|
||||
const form = document.getElementById('toolForm');
|
||||
form.elements.baseName.value = result.baseName || '';
|
||||
@@ -2225,9 +2226,9 @@
|
||||
form.elements.ownerOrg.value = result.ownerOrg || 'MCP_TOOL';
|
||||
document.getElementById('inputFields').value = JSON.stringify(result.inputFields || [], null, 2);
|
||||
document.getElementById('outputFields').value = JSON.stringify(result.outputFields || [], null, 2);
|
||||
alert('Tool 초안을 채웠습니다. Legacy Interface ID와 Client System Code는 실제 연계 명세를 확인해 입력해주세요.');
|
||||
alert('Tool 초안??채웠?<3F>니?? Legacy Interface ID?<3F> Client System Code???<3F>제 ?<3F>계 명세<EBAA85>??<3F>인???<3F>력?<3F>주?<3F>요.');
|
||||
} catch (error) {
|
||||
alert(`AI Tool 초안 생성 실패: ${error.message}`);
|
||||
alert(`AI Tool 초안 ?<3F>성 ?<3F>패: ${error.message}`);
|
||||
} finally {
|
||||
button.textContent = originalLabel;
|
||||
button.disabled = false;
|
||||
@@ -2240,11 +2241,11 @@
|
||||
for (const field of fields) {
|
||||
const name = field.name;
|
||||
if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name)) {
|
||||
alert(`필드명 "${name}"은(는) Java 필드명 형식으로 입력해주세요.`);
|
||||
alert(`?<3F>드<EFBFBD>?"${name}"?<3F>(?? Java ?<3F>드<EFBFBD>??<3F>식?<3F>로 ?<3F>력?<3F>주?<3F>요.`);
|
||||
return;
|
||||
}
|
||||
if (names.has(name)) {
|
||||
alert(`필드명 "${name}"이(가) 중복되었습니다.`);
|
||||
alert(`?<3F>드<EFBFBD>?"${name}"??가) 중복?<3F>었?<3F>니??`);
|
||||
return;
|
||||
}
|
||||
names.add(name);
|
||||
@@ -2373,7 +2374,7 @@
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(result => {
|
||||
if (result.includes('[오류]') || result.includes('오류 발생:')) {
|
||||
if (result.includes('[?<3F>류]') || result.includes('?<3F>류 발생:')) {
|
||||
alert('Error updating source:\n' + result);
|
||||
} else {
|
||||
alert('Source code updated successfully.\nPlease rebuild the Pod container to reflect changes.');
|
||||
|
||||
Reference in New Issue
Block a user