compare_old_new
Compare old and new versions of Korean national laws. Use law serial number, ID, or promulgation date to retrieve a side-by-side comparison of changes.
Instructions
[비교] 신구법 대조표 조회.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| mst | No | 법령일련번호 | |
| lawId | No | 법령ID | |
| ld | No | 공포일자 (YYYYMMDD) | |
| ln | No | 공포번호 | |
| apiKey | No | 법제처 Open API 인증키(OC). 사용자가 제공한 경우 전달 |
Implementation Reference
- src/tools/comparison.ts:23-126 (handler)Main handler that fetches old vs new law comparison data via API, parses XML response to extract old/new articles, and formats them as a side-by-side comparison text.
export async function compareOldNew( apiClient: LawApiClient, input: CompareOldNewInput ): Promise<{ content: Array<{ type: string, text: string }>, isError?: boolean }> { try { const xmlText = await apiClient.compareOldNew({ mst: input.mst, lawId: input.lawId, ld: input.ld, ln: input.ln, apiKey: input.apiKey }) const parser = new DOMParser() const doc = parser.parseFromString(xmlText, "text/xml") const lawName = doc.getElementsByTagName("법령명")[0]?.textContent || "알 수 없음" const oldInfo = doc.getElementsByTagName("구조문_기본정보")[0] const newInfo = doc.getElementsByTagName("신조문_기본정보")[0] const oldDate = oldInfo?.getElementsByTagName("공포일자")[0]?.textContent || "" const newDate = newInfo?.getElementsByTagName("공포일자")[0]?.textContent || "" const revisionType = newInfo?.getElementsByTagName("제개정구분명")[0]?.textContent || "" let resultText = `법령명: ${lawName}\n` if (revisionType) resultText += `개정구분: ${revisionType}\n` if (oldDate) resultText += `구법 공포일: ${oldDate}\n` if (newDate) resultText += `신법 공포일: ${newDate}\n` resultText += `\n━━━━━━━━━━━━━━━━━━━━━━\n` resultText += `신구법 대조\n` resultText += `━━━━━━━━━━━━━━━━━━━━━━\n\n` // 구조문목록과 신조문목록 파싱 const oldArticleList = doc.getElementsByTagName("구조문목록")[0] const newArticleList = doc.getElementsByTagName("신조문목록")[0] if (!oldArticleList || !newArticleList) { return { content: [{ type: "text", text: resultText + "개정 이력이 없거나 신구법 대조 데이터가 없습니다." }] } } const oldArticles = oldArticleList.getElementsByTagName("조문") const newArticles = newArticleList.getElementsByTagName("조문") if (oldArticles.length === 0 && newArticles.length === 0) { return { content: [{ type: "text", text: resultText + "개정 이력이 없거나 신구법 대조 데이터가 없습니다." }] } } // 구/신 조문을 쌍으로 매칭 (동일 인덱스 기반 — API가 대응 쌍을 순서대로 반환) const maxArticles = Math.max(oldArticles.length, newArticles.length) const displayCount = Math.min(maxArticles, 30) for (let i = 0; i < displayCount; i++) { const oldArticle = oldArticles[i] const newArticle = newArticles[i] const oldContent = oldArticle?.textContent?.trim() || "" const newContent = newArticle?.textContent?.trim() || "" // 조문 번호 추출 시도 const articleNumMatch = (newContent || oldContent).match(/제\d+조(?:의\d+)?/) const articleLabel = articleNumMatch ? articleNumMatch[0] : `조문 ${i + 1}` resultText += `\n━━━━━━━━━━━━━━━━━━━━━━\n` resultText += `${articleLabel}\n` resultText += `━━━━━━━━━━━━━━━━━━━━━━\n\n` if (oldContent) { resultText += `[개정 전]\n${oldContent}\n\n` } else { resultText += `[개정 전] (신설)\n\n` } if (newContent) { resultText += `[개정 후]\n${newContent}\n\n` } else { resultText += `[개정 후] (삭제)\n\n` } } if (maxArticles > displayCount) { resultText += `\n... 외 ${maxArticles - displayCount}개 조문 (생략)\n` resultText += `💡 전체 ${maxArticles}개 조문 중 ${displayCount}개만 표시합니다.\n` } return { content: [{ type: "text", text: truncateResponse(resultText) }] } } catch (error) { return formatToolError(error, "compare_old_new") } } - src/tools/comparison.ts:11-19 (schema)Zod schema for input validation: accepts optional mst, lawId, ld, ln, apiKey fields, requiring either mst or lawId.
export const CompareOldNewSchema = z.object({ mst: z.string().optional().describe("법령일련번호"), lawId: z.string().optional().describe("법령ID"), ld: z.string().optional().describe("공포일자 (YYYYMMDD)"), ln: z.string().optional().describe("공포번호"), apiKey: z.string().optional().describe("법제처 Open API 인증키(OC). 사용자가 제공한 경우 전달") }).refine(data => data.mst || data.lawId, { message: "mst 또는 lawId 중 하나는 필수입니다" }) - src/tool-registry.ts:196-201 (registration)Tool registration entry mapping the name 'compare_old_new' to its schema and handler function.
{ name: "compare_old_new", description: "[비교] 신구법 대조표 조회.", schema: CompareOldNewSchema, handler: compareOldNew }, - src/lib/api-client.ts:155-175 (helper)API client method that constructs the REST call to the law service endpoint with target=oldAndNew, passing optional MST, ID, LD, LN parameters.
async compareOldNew(params: { mst?: string lawId?: string ld?: string ln?: string apiKey?: string }): Promise<string> { const apiParams = new URLSearchParams({ target: "oldAndNew", OC: this.getApiKey(params.apiKey), type: "XML", }) if (params.mst) apiParams.append("MST", String(params.mst)) if (params.lawId) apiParams.append("ID", String(params.lawId)) if (params.ld) apiParams.append("LD", String(params.ld)) if (params.ln) apiParams.append("LN", String(params.ln)) const url = `${LAW_API_BASE}/lawService.do?${apiParams.toString()}` return await this.fetchText(url, "compareOldNew") }