<%_* // Gemini API 키를 외부 파일에서 로드 (content 폴더 밖의 secrets.json) const secretsContent = await app.vault.adapter.read(“secrets.json”); const secrets = JSON.parse(secretsContent); const GEMINI_API_KEY = secrets.GEMINI_API_KEY; _%>
// 요약 생성을 위한 프롬프트 정의 const summary_prompt = `You are an expert at creating dense, informative summaries of technical and business content. Your task is to analyze the given Obsidian markdown note and create a highly structured summary.
Analysis Steps:
-
Content Classification:
- Document Type (기술문서/연구/회의록/분석보고서/제안서 등)
- Primary Domain (AI/개발/비즈니스/운영 등)
- Content Level (개념/구현/분석/전략 등)
-
Core Information Extraction:
- Main Theme & Purpose
- Key Technical Concepts
- Critical Findings/Decisions
- Implementation Details
- Business Impact/Value
-
Entity Recognition:
- Technical Terms (기술용어/프레임워크/도구)
- Organizations (회사명/팀/부서)
- Time References (날짜/기간/마일스톤)
- People (담당자/이해관계자)
- Resources (예산/인력/시스템)
Summary Generation Guidelines:
Format:
- First bullet: 문서의 핵심 주제와 목적을 한 문장으로 압축
- Second bullet: 주요 기술적 내용과 의사결정 사항
- Third bullet: 구현 방법론이나 해결 방안
- Fourth bullet: 비즈니스 임팩트나 실행 계획
- Last bullet: 후속 조치나 주요 고려사항
Writing Style:
- Use technical and business terminology precisely
- End sentences with 명사/~임/~함 style
- Keep each bullet under 100 characters
- Include quantitative metrics when available
- Maintain formal business writing tone
Formatting Rules:
- Start each bullet with ’-’
- No markdown or special characters
- No nested bullets
- No explanatory notes
[Output Requirements]
- ONLY include the final bullet-point summary in Korean
- NO introduction, explanation, or metadata
- NO reference to the analysis process
- Focus on density and precision of information
Remember: Your summary should serve as a comprehensive yet concise reference for both technical and business stakeholders. ` _%>
<%_*
// Gemini API를 호출하여 요약을 생성하는 함수
async function generateSummary(content) {
const model = “gemini-1.5-flash”;
const url = https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${GEMINI_API_KEY};
const full_prompt = ${summary_prompt}\n\nHere is the content of the note:\n${content};
try {
const response = await tp.obsidian.requestUrl({
method: "POST",
url: url,
contentType: "application/json",
body: JSON.stringify({
contents: [{ parts: [{ text: full_prompt }] }]
})
});
const resultText = response.json.candidates[0].content.parts[0].text;
return resultText.trim();
} catch (error) {
console.error('Gemini API 호출 중 오류 발생:', error);
if (error.response) {
console.error('Gemini API Error Response:', await error.response.text());
}
return null;
}
}
// frontmatter와 내용을 분리하는 함수 function separateFrontmatterAndContent(content) { const match = content.match(/^---\n(.?)\n---\n([\s\S])/s); if (!match) { return { frontmatter: ”, content: content }; } return { frontmatter: match[1], content: match[2] }; }
// 파일 내용을 업데이트하는 함수 async function updateFileContent(file, summary) { try { const currentContent = await tp.file.content; const { frontmatter, content } = separateFrontmatterAndContent(currentContent);
const summaryCallout = `> [!Summary]\n${summary.split('\n').map(line => `> ${line}`).join('\n')}\n\n`;
let newContent;
if (frontmatter) {
newContent = `---\n${frontmatter}\n---\n\n${summaryCallout}${content.trimStart()}`;
} else {
newContent = `${summaryCallout}${content.trimStart()}`;
}
await app.vault.modify(file, newContent);
return true;
} catch (error) { console.error(‘파일 업데이트 중 오류 발생:’, error); throw error; } }
// 메인 실행 로직 const file = tp.config.target_file; const fileContent = tp.file.content;
try { const summary = await generateSummary(fileContent); if (!summary) { throw new Error(‘요약 생성 실패’); }
await updateFileContent(file, summary); } catch (error) { console.error(‘메인 실행 중 오류 발생:’, error); } _%>