export type TemplateId = | 'meeting' | 'lecture' | 'one_on_one' | 'brainstorm' | 'interview' | 'raw' | 'custom' export type SummaryDepth = 'concise' | 'standard' | 'detailed' export interface Template { id: TemplateId name: string icon: string description: string defaultDepth: SummaryDepth liveSupported: boolean depthAdjustable: boolean basePrompt: string } export const DEFAULT_TEMPLATE_ID: TemplateId = 'meeting' export const DEFAULT_DEPTH: SummaryDepth = 'standard' export const TEMPLATES: Record, Template> = { meeting: { id: 'meeting', name: '회의둝', icon: 'πŸ—‚οΈ', description: 'μ°Έμ„μž / μ•‘μ…˜ μ•„μ΄ν…œ 쀑심', defaultDepth: 'standard', liveSupported: true, depthAdjustable: true, basePrompt: `당신은 회의둝 μž‘μ„± μ „λ¬Έκ°€μž…λ‹ˆλ‹€. μ•„λž˜ λ°œν™” λ‚΄μš©μ„ λΆ„μ„ν•˜μ—¬ λ§ˆν¬λ‹€μš΄ νšŒμ˜λ‘μ„ μž‘μ„±ν•˜μ„Έμš”. 포함할 μ„Ήμ…˜: ## μš”μ•½ (3~5쀄 핡심 λ‚΄μš©) ## μ£Όμš” λ…Όμ˜ 사항 1. 순번 λ§€κΈ°κΈ° ## μ•‘μ…˜ μ•„μ΄ν…œ - [ ] λ‹΄λ‹Ήμžμ™€ κΈ°ν•œμ΄ λͺ…ν™•ν•œ ν•­λͺ©λ§Œ ## κ²°μ • 사항 - ν•©μ˜ λ˜λŠ” ν™•μ •λœ κ²ƒλ§Œ ν•œκ΅­μ–΄λ‘œ μž‘μ„±ν•˜μ„Έμš”.`, }, lecture: { id: 'lecture', name: 'κ°•μ˜Β·μ„Έλ―Έλ‚˜ λ…ΈνŠΈ', icon: 'πŸŽ“', description: 'μ£Όμ œλ³„ 핡심 κ°œλ…κ³Ό μ˜ˆμ‹œ', defaultDepth: 'detailed', liveSupported: true, depthAdjustable: true, basePrompt: `당신은 ν•™μŠ΅μš© λ…ΈνŠΈλ₯Ό μž‘μ„±ν•˜λŠ” μ „λ¬Έκ°€μž…λ‹ˆλ‹€. κ°•μ˜/μ„Έλ―Έλ‚˜ λ…Ήμ·¨λ₯Ό κ΅¬μ‘°ν™”λœ ν•™μŠ΅ 자료둜 μ •λ¦¬ν•˜μ„Έμš”. 포함할 μ„Ήμ…˜: ## μ£Όμš” 주제 (ν•œ 쀄 μš”μ•½) ## 핡심 κ°œλ… 각 κ°œλ…λ§ˆλ‹€ ### μ†Œμ œλͺ© + μ„€λͺ… + ꡬ체 μ˜ˆμ‹œ ## κΈ°μ–΅ν•  μΈμš©Β·μ˜ˆμ‹œ > μ€‘μš”ν•œ λ¬Έμž₯ 인용 ν˜•μ‹μœΌλ‘œ ## 후속 질문 - 슀슀둜 탐ꡬ해볼 λ§Œν•œ 질문 ν•œκ΅­μ–΄λ‘œ μž‘μ„±ν•˜μ„Έμš”.`, }, one_on_one: { id: 'one_on_one', name: '1:1 λ―ΈνŒ…', icon: '🀝', description: 'κ³ λ―Ό / ν”Όλ“œλ°± / λ‹€μŒ μ•‘μ…˜', defaultDepth: 'standard', liveSupported: true, depthAdjustable: true, basePrompt: `당신은 1:1 λ―ΈνŒ… 정리 μ „λ¬Έκ°€μž…λ‹ˆλ‹€. 개인적이고 μ‹ λ’° 기반의 λŒ€ν™”μž„μ„ μ‘΄μ€‘ν•˜λ©° μ •λ¦¬ν•˜μ„Έμš”. 포함할 μ„Ήμ…˜: ## 이번 μ„Έμ…˜ μš”μ§€ (2~3쀄) ## λ…Όμ˜ν•œ 주제 - μ£Όμš” λŒ€ν™” 흐름 ## κ³ λ―ΌΒ·λΈ”λ‘œμ»€ - 곡유된 어렀움 ## λ°›μ€Β·μ œκ³΅ν•œ ν”Όλ“œλ°± - 건섀적 ν”Όλ“œλ°± μœ„μ£Ό ## λ‹€μŒ λ―ΈνŒ…κΉŒμ§€ ν•  일 - [ ] ν•©μ˜λœ 후속 쑰치 ν•œκ΅­μ–΄λ‘œ μž‘μ„±ν•˜μ„Έμš”.`, }, brainstorm: { id: 'brainstorm', name: 'λΈŒλ ˆμΈμŠ€ν† λ°', icon: 'πŸ’‘', description: '아이디어 μΉ΄ν…Œκ³ λ¦¬ν™” + μš°μ„ μˆœμœ„', defaultDepth: 'detailed', liveSupported: true, depthAdjustable: true, basePrompt: `당신은 λΈŒλ ˆμΈμŠ€ν† λ° μ„Έμ…˜μ„ μ •λ¦¬ν•˜λŠ” μ „λ¬Έκ°€μž…λ‹ˆλ‹€. λ‚˜μ˜¨ 아이디어λ₯Ό λΆ„λ₯˜ν•˜κ³  μ‹€ν–‰ κ°€λŠ₯μ„± κ΄€μ μ—μ„œ μ •λ¦¬ν•˜μ„Έμš”. 포함할 μ„Ήμ…˜: ## μ„Έμ…˜ κ°œμš” (1~2쀄 β€” 주제/λͺ©ν‘œ) ## 아이디어 (μΉ΄ν…Œκ³ λ¦¬λ³„) ### [μΉ΄ν…Œκ³ λ¦¬ 이름] - 아이디어 μš”μ•½ ## μ¦‰μ‹œ μ‹œλ„ κ°€λŠ₯ - λΉ λ₯΄κ²Œ 검증 κ°€λŠ₯ν•œ 것 ## 보λ₯˜Β·νƒˆλ½ - μ‚¬μœ  κ°„λ‹¨νžˆ ## λ‹€μŒ μŠ€ν… - ꡬ체적인 후속 행동 ν•œκ΅­μ–΄λ‘œ μž‘μ„±ν•˜μ„Έμš”.`, }, interview: { id: 'interview', name: '인터뷰', icon: '🎀', description: 'Q&A 포맷 + 인상적 λ°œμ–Έ', defaultDepth: 'standard', liveSupported: false, depthAdjustable: true, basePrompt: `당신은 인터뷰 λ…Ήμ·¨λ₯Ό Q&A ν˜•μ‹μœΌλ‘œ μ •λ¦¬ν•˜λŠ” μ „λ¬Έκ°€μž…λ‹ˆλ‹€. 포함할 μ„Ήμ…˜: ## κ°œμš” (인터뷰 λŒ€μƒ/주제 1~2쀄) ## Q&A **Q: [질문]** A: [λ‹΅λ³€ μš”μ•½] (μ˜λ―ΈμžˆλŠ” Q&A μŒμ„ μˆœμ„œλŒ€λ‘œ) ## 인상적 λ°œμ–Έ > 직접 인용 ## μ’…ν•© 인상 - μ „λ°˜μ  ν…Œλ§ˆ / λ†“μΉ˜μ§€ 말 것 ν•œκ΅­μ–΄λ‘œ μž‘μ„±ν•˜μ„Έμš”.`, }, raw: { id: 'raw', name: '원문 정리', icon: 'πŸ“', description: 'μš”μ•½ 없이 λ¬Έλ‹¨ν™”Β·μ˜€νƒˆμž μ •λ¦¬λ§Œ', defaultDepth: 'detailed', liveSupported: false, depthAdjustable: false, basePrompt: `당신은 μŒμ„± 인식 ν…μŠ€νŠΈμ˜ νŽΈμ§‘μžμž…λ‹ˆλ‹€. μš”μ•½μ΄λ‚˜ μž¬ν•΄μ„ 없이 λ‹€μŒλ§Œ μˆ˜ν–‰ν•˜μ„Έμš”: - λ¬Έμž₯을 μžμ—°μŠ€λŸ¬μš΄ λ¬Έλ‹¨μœΌλ‘œ λ¬ΆκΈ° - λͺ…λ°±ν•œ μ˜€νƒˆμž ꡐ정 - 의미 μ—†λŠ” 반볡 / ꡰ더더기 μ΅œμ†Œν•œ 제거 - μ‹œκ°„ μˆœμ„œ μœ μ§€ μ—„κ²©ν•œ κ·œμΉ™: - λ‚΄μš©μ„ μ‚­μ œν•˜κ±°λ‚˜ μΆ•μ•½ν•˜μ§€ λ§ˆμ„Έμš” - ꡬ쑰적 제λͺ©(## μ„Ήμ…˜)을 덧뢙이지 λ§ˆμ„Έμš” - νƒ€μž„μŠ€νƒ¬ν”„κ°€ 있으면 κ·ΈλŒ€λ‘œ μœ μ§€ν•˜μ„Έμš” - ν•œκ΅­μ–΄λ‘œ μž‘μ„±ν•˜μ„Έμš”.`, }, } const DEPTH_MODIFIERS: Record = { concise: 'μž‘μ„± 강도: **κ°„κ²°**. 각 μ„Ήμ…˜μ€ 3쀄 μ΄λ‚΄λ‘œ ν•΅μ‹¬λ§Œ. λΆ€μ—° μ„€λͺ…κ³Ό λ§₯락은 μƒλž΅ν•˜μ„Έμš”.', standard: 'μž‘μ„± 강도: **ν‘œμ€€**. μ½λŠ” μ‚¬λžŒμ΄ λ§₯락을 이해할 수 μžˆλ„λ‘ μ μ ˆν•œ μƒμ„Έλ„λ‘œ μž‘μ„±ν•˜μ„Έμš”.', detailed: 'μž‘μ„± 강도: **상세**. μ›λ¬Έμ˜ μ£Όμš” μ„ΈλΆ€μ‚¬ν•­Β·μˆ˜μΉ˜Β·κ³ μœ λͺ…사λ₯Ό λˆ„λ½ 없이 ν¬ν•¨ν•˜μ„Έμš”. ꡬ쑰만 λ°”κΎΈκ³  λ‚΄μš©μ€ μ΅œλŒ€ν•œ λ³΄μ‘΄ν•©λ‹ˆλ‹€.', } const LIVE_MODIFIER = `νšŒμ˜κ°€ 아직 μ§„ν–‰ μ€‘μž…λ‹ˆλ‹€. μ§€κΈˆκΉŒμ§€μ˜ λ‚΄μš©μ„ 기반으둜 **쀑간 정리**λ₯Ό μž‘μ„±ν•˜μ„Έμš”. ν™•μ •λ˜μ§€ μ•Šμ€ 결정은 "(λ…Όμ˜ 쀑)"으둜 ν‘œμ‹œν•˜μ„Έμš”.` export interface BuildPromptArgs { templateId: TemplateId depth: SummaryDepth transcript: string live?: boolean customPrompt?: string } export function getTemplate(id: TemplateId): Template | null { if (id === 'custom') return null return TEMPLATES[id] ?? null } export function resolveDepth( templateId: TemplateId, depth?: SummaryDepth, ): SummaryDepth { if (templateId === 'custom') return depth ?? DEFAULT_DEPTH const template = TEMPLATES[templateId] if (!template) return DEFAULT_DEPTH if (!template.depthAdjustable) return template.defaultDepth return depth ?? template.defaultDepth } export function buildPrompt(args: BuildPromptArgs): string { const { templateId, depth, transcript, live = false, customPrompt } = args let instruction: string if (templateId === 'custom') { const custom = customPrompt?.trim() if (!custom) { instruction = TEMPLATES.meeting.basePrompt } else { instruction = custom } } else { const template = TEMPLATES[templateId] ?? TEMPLATES.meeting const parts: string[] = [template.basePrompt] if (template.depthAdjustable) { parts.push(DEPTH_MODIFIERS[depth]) } if (live && template.liveSupported) { parts.push(LIVE_MODIFIER) } instruction = parts.join('\n\n') } return `${instruction}\n\n---\nμŒμ„± 인식 ν…μŠ€νŠΈ:\n${transcript}` } export function liveEnabledFor(templateId: TemplateId): boolean { if (templateId === 'custom') return true return TEMPLATES[templateId]?.liveSupported ?? true } export function depthAdjustableFor(templateId: TemplateId): boolean { if (templateId === 'custom') return false return TEMPLATES[templateId]?.depthAdjustable ?? true }