Files
connectai/package.json
T
koriweb eeb527c242 feat(datacollect): /youtube 개편·/wikify 신규·출력 위생 (v2.2.48)
- /youtube: 4-렌즈 분석 → 대본(스크립트) 역기획서 포맷으로 개편, 보고서
  앞에 영상 전체 스크립트(Full Script) 출력, 명령어 보조 컨텍스트 지원
- /wikify: 신규 슬래시 명령 — 웹사이트 본문(/api/web-extract)을 P-Reinforce
  v3.0 위키 문서로 합성. 여러 링크 순차 배치 처리, 명세 문서 완전성 규칙,
  위키링크 자동 교정
- Self-Reflector Phase A 기본 비활성화 — [Self-Reflector Check] 내부 검증
  로그가 사용자 답변에 노출되지 않도록
- 슬래시 합성·일반 채팅 시스템 프롬프트에 출력 위생 규칙 추가 — 한·영 토큰
  깨짐 정제, 내부 검증 로그 출력 금지

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 18:34:07 +09:00

627 lines
32 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"name": "astra",
"displayName": "Astra",
"description": "The personal intelligence layer for Antigravity and VS Code. A private cognitive partner for deep project context, memory, and proactive strategic decision-making.",
"version": "2.2.48",
"publisher": "g1nation",
"license": "MIT",
"icon": "assets/icon.png",
"repository": {
"type": "git",
"url": "https://github.com/g1nations/locallm"
},
"engines": {
"vscode": "^1.80.0"
},
"categories": [
"Machine Learning",
"Programming Languages",
"Chat"
],
"keywords": [
"ai",
"local",
"ollama",
"gemma",
"llama",
"deepseek",
"offline",
"agent",
"code-generation",
"astra",
"copilot"
],
"activationEvents": [
"onStartupFinished"
],
"main": "./out/extension.js",
"contributes": {
"commands": [
{
"command": "g1nation.newChat",
"title": "Astra: New Chat",
"icon": "$(add)"
},
{
"command": "g1nation.exportChat",
"title": "Astra: Export Chat as Markdown"
},
{
"command": "g1nation.explainSelection",
"title": "Astra: Explain Selected Code"
},
{
"command": "g1nation.focusChat",
"title": "Astra: Focus Chat Input"
},
{
"command": "g1nation.showBrainNetwork",
"title": "Astra: Show Brain Topology"
},
{
"command": "g1nation.approval.focus",
"title": "Astra: Focus Approval Panel"
},
{
"command": "g1nation.scaffoldProject",
"title": "Astra: Scaffold New Project"
},
{
"command": "g1nation.telegram.setBotToken",
"title": "Astra: Set Telegram Bot Token"
},
{
"command": "g1nation.telegram.clearBotToken",
"title": "Astra: Clear Telegram Bot Token"
},
{
"command": "g1nation.telegram.testConnection",
"title": "Astra: Test Telegram Connection"
},
{
"command": "g1nation.settings.focus",
"title": "Astra: Open Settings Panel"
},
{
"command": "g1nation.skills.editKnowledgeMap",
"title": "Astra: Edit Agent ↔ Knowledge Map"
},
{
"command": "g1nation.openChat",
"title": "Astra: Open Chat (Editor Column)",
"icon": "$(comment-discussion)"
},
{
"command": "g1nation.lesson.create",
"title": "Astra: New Lesson (Experience Memory)"
},
{
"command": "g1nation.lesson.fromConversation",
"title": "Astra: New Lesson from Current Conversation"
},
{
"command": "g1nation.lesson.manage",
"title": "Astra: Browse / Manage Lessons"
},
{
"command": "g1nation.architecture.refresh",
"title": "Astra: Refresh Project Architecture Context"
},
{
"command": "g1nation.architecture.detach",
"title": "Astra: Detach Project Architecture Context"
},
{
"command": "g1nation.architecture.attach",
"title": "Astra: Attach Project Architecture Context"
},
{
"command": "g1nation.architecture.open",
"title": "Astra: Open Project Architecture Doc"
},
{
"command": "g1nation.company.toggle",
"title": "Astra: Toggle 1인 기업 Mode"
},
{
"command": "g1nation.company.manage",
"title": "Astra: Manage 1인 기업 Agents"
},
{
"command": "g1nation.company.openSessions",
"title": "Astra: Open 1인 기업 Sessions Folder"
},
{
"command": "g1nation.company.pixelOffice.open",
"title": "Astra: Open Pixel Office (Full Screen)"
},
{
"command": "g1nation.calendar.connect",
"title": "Astra: Google Calendar (iCal) 연결 📅"
},
{
"command": "g1nation.calendar.refresh",
"title": "Astra: Google Calendar 새로고침 📅"
},
{
"command": "g1nation.calendar.connectOAuth",
"title": "Astra: Google Calendar OAuth 연결 (쓰기) 🔐"
},
{
"command": "g1nation.devilAgent.toggle",
"title": "Astra: Toggle Devil Agent 🎭"
}
],
"keybindings": [
{
"command": "g1nation.focusChat",
"key": "cmd+l",
"mac": "cmd+l"
}
],
"menus": {
"editor/context": [
{
"command": "g1nation.explainSelection",
"when": "editorHasSelection",
"group": "1_modification"
}
]
},
"viewsContainers": {
"activitybar": [
{
"id": "g1nation-astra-activity",
"title": "Astra (g1nation)",
"icon": "assets/icon-activitybar.svg"
}
]
},
"views": {
"g1nation-astra-activity": [
{
"id": "g1nation-astra-launcher",
"name": "Astra (g1nation) Launcher"
}
]
},
"viewsWelcome": [
{
"view": "g1nation-astra-launcher",
"contents": "✦ **Astra** — 로컬 AI 인텔리전스 레이어\n\nChat 탭을 닫았을 때 여기서 다시 열 수 있습니다.\n\n[$(comment-discussion) Open Chat](command:g1nation.openChat)\n[$(add) New Chat](command:g1nation.newChat)\n[$(gear) Settings](command:g1nation.settings.focus)\n\n---\n\n**1인 기업 모드**\n\n[$(organization) Manage Agents](command:g1nation.company.manage)\n[$(folder-opened) Open Sessions Folder](command:g1nation.company.openSessions)\n\n---\n\n**Project Architecture**\n\n[$(file-text) Open Architecture Doc](command:g1nation.architecture.open)\n[$(refresh) Refresh Architecture](command:g1nation.architecture.refresh)\n\n---\n\n**Lessons / Knowledge**\n\n[$(lightbulb) Manage Lessons](command:g1nation.lesson.manage)\n[$(edit) Edit Agent ↔ Knowledge Map](command:g1nation.skills.editKnowledgeMap)"
}
],
"configuration": {
"title": "Astra",
"properties": {
"g1nation.multiAgentEnabled": {
"type": "boolean",
"default": false,
"description": "Enable Multi-Agent Workflow (Planner -> Researcher -> Writer) for complex tasks."
},
"g1nation.datacollectBridgeUrl": {
"type": "string",
"default": "http://127.0.0.1:3002",
"description": "Wiki/Datacollect MCP Bridge URL. /research, /benchmark, /youtube chat slash commands route here. The Bridge must be running (`npm run bridge` in the Datacollect project)."
},
"g1nation.datacollectSavePath": {
"type": "string",
"default": "",
"markdownDescription": "`/benchmark` 등 Datacollect slash 명령 결과물(markdown)을 저장할 폴더. **비워두면** Bridge 기본 위치(Bridge의 `WIKI_RAW_PATH` 환경변수)에 저장됩니다 — 코드/설정 어디에도 절대경로가 박히지 않습니다. 특정 폴더로 저장하려면 절대경로를 입력하세요. Astra Settings 패널의 'Datacollect' 섹션에서도 편집 가능."
},
"g1nation.datacollectCrawlDepth": {
"type": "number",
"default": 1,
"minimum": 0,
"maximum": 3,
"markdownDescription": "`/benchmark` 사이트맵 크롤 깊이 기본값. 0=루트만, 1=직속 자식, 2=손자, 3=깊은 크롤. 명령어에서 `depth=N`으로 그때그때 덮어쓸 수 있습니다. (단일 페이지 SPA는 깊이를 올려도 1페이지)"
},
"g1nation.datacollectMaxPages": {
"type": "number",
"default": 8,
"minimum": 1,
"maximum": 20,
"markdownDescription": "`/benchmark` 스캔 최대 페이지 수 기본값. 명령어에서 `pages=N`으로 덮어쓸 수 있습니다. Bridge에서 20으로 상한이 적용됩니다."
},
"g1nation.datacollectSynthesisTemperature": {
"type": "number",
"default": 0.1,
"minimum": 0,
"maximum": 2,
"markdownDescription": "`/benchmark` LLM 4-렌즈 합성의 temperature. 낮을수록(0.1) 환각·깨진 문자가 줄고 결과가 결정적이며, 높을수록 표현이 다양해집니다. 기본 0.1 권장."
},
"g1nation.memoryEnabled": {
"type": "boolean",
"default": true,
"description": "Enable layered memory injection before each model response."
},
"g1nation.memoryShortTermMessages": {
"type": "number",
"default": 8,
"minimum": 0,
"description": "Number of recent conversation messages included as short-term memory."
},
"g1nation.memoryMediumTermSessions": {
"type": "number",
"default": 5,
"minimum": 0,
"description": "Number of recent saved chat sessions included as medium-term memory."
},
"g1nation.memoryLongTermFiles": {
"type": "number",
"default": 6,
"minimum": 0,
"description": "Number of relevant Second Brain markdown files included as long-term memory."
},
"g1nation.ollamaUrl": {
"type": "string",
"default": "http://127.0.0.1:11434",
"description": "Base URL for Ollama or LM Studio. Default: http://127.0.0.1:11434"
},
"g1nation.defaultModel": {
"type": "string",
"default": "gemma4:e2b",
"description": "Default model name to use for chat requests."
},
"g1nation.requestTimeout": {
"type": "number",
"default": 300,
"description": "Request timeout in seconds. Default: 300"
},
"g1nation.contextLength": {
"type": "number",
"default": 32768,
"minimum": 2048,
"description": "Model context window in tokens (prompt + generation combined). Set this to the value your loaded model is actually running with in LM Studio / Ollama. Astra budgets prompt and output against this so it never overflows. Default: 32768"
},
"g1nation.maxOutputTokens": {
"type": "number",
"default": 4096,
"minimum": 256,
"description": "Upper bound on tokens generated per response. The effective limit is reduced automatically when the prompt is large so input + output stays within g1nation.contextLength. Default: 4096"
},
"g1nation.contextSafetyMargin": {
"type": "number",
"default": 2048,
"minimum": 0,
"description": "Tokens kept free as a safety buffer for token-count estimation error. Default: 2048"
},
"g1nation.contextOverflowPolicy": {
"type": "string",
"enum": [
"stopAtLimit",
"truncateMiddle",
"rollingWindow"
],
"default": "stopAtLimit",
"description": "Fallback behavior (LM Studio) if the prompt still exceeds the context window after Astra's own budgeting. 'stopAtLimit' fails clearly so you notice; 'truncateMiddle'/'rollingWindow' drop content silently. Default: stopAtLimit"
},
"g1nation.autoCompactHistory": {
"type": "boolean",
"default": true,
"description": "Automatically drop the oldest conversation messages from the request when the prompt would exceed the context budget (the on-screen chat history is unaffected). Default: true"
},
"g1nation.smallModelContextCap": {
"type": "number",
"default": 0,
"minimum": 0,
"description": "Optional safety knob, OFF by default (0). Some very small models (≤3B) emit an empty/EOS response when given a prompt near their context window even though it nominally fits. If you observe that with a tiny model, set this to e.g. 819216384: for ≤3B models only, Astra then budgets the prompt against this smaller effective window instead of g1nation.contextLength. Never applies to 4B+ models. Leave 0 unless you actually hit the issue — it reduces the output-token budget. Default: 0 (disabled)"
},
"g1nation.autoContinueOnOutputLimit": {
"type": "boolean",
"default": true,
"description": "When a reply is cut off because it hit the output-token limit, Astra continues it internally (compressed request — original question + the answer so far, not the whole context again) and shows one merged answer, instead of asking you to say \"이어서 작성해줘\". Default: true"
},
"g1nation.maxAutoContinuations": {
"type": "number",
"default": 4,
"minimum": 0,
"maximum": 10,
"description": "Maximum number of automatic continuation rounds per reply (prevents runaway loops). Raise it (e.g. 56) for long-form answers on slow local models; set 0 to disable auto-continuation. Default: 4"
},
"g1nation.finalOnlyRetryOnThoughtLeak": {
"type": "boolean",
"default": true,
"description": "If the model emits only hidden reasoning (<think>, <|channel|>thought, \"Thinking Process:\" …) and no user-visible answer, Astra silently re-asks it for the final answer only. Hidden reasoning is never shown either way. Default: true"
},
"g1nation.lmStudio.idleTimeoutMs": {
"type": "number",
"default": 300000,
"minimum": 0,
"description": "Auto-eject the loaded LM Studio model after this many milliseconds of inactivity. Set to 0 to disable. Default: 300000 (5 minutes)."
},
"g1nation.lmStudio.autoLoadOnSelect": {
"type": "boolean",
"default": true,
"description": "Automatically load LM Studio models into memory when selected from the Astra sidebar."
},
"g1nation.localBrainPath": {
"type": "string",
"default": "",
"description": "Folder path for your local Second Brain knowledge base. Leave empty to use the default folder."
},
"g1nation.brainProfiles": {
"type": "array",
"default": [],
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stable brain profile id."
},
"name": {
"type": "string",
"description": "Display name shown in the Astra brain selector."
},
"localBrainPath": {
"type": "string",
"description": "Local folder path used as this brain's markdown knowledge base."
},
"secondBrainRepo": {
"type": "string",
"description": "Optional Git repository URL for this brain."
},
"description": {
"type": "string",
"description": "Short note shown under the active brain status."
}
}
},
"description": "Multiple brain profiles. Each item supports id, name, localBrainPath, secondBrainRepo, and description."
},
"g1nation.activeBrainId": {
"type": "string",
"default": "",
"description": "Active brain profile id used for the current chat context."
},
"g1nation.secondBrainRepo": {
"type": "string",
"default": "",
"description": "Optional GitHub repository URL used for Second Brain sync."
},
"g1nation.autoPushBrain": {
"type": "boolean",
"default": false,
"description": "Automatically commit and push Second Brain changes after updates."
},
"g1nation.maxContextSize": {
"type": "number",
"default": 32000,
"description": "Maximum character count for active file context. Default: 32000"
},
"g1nation.maxAutoSteps": {
"type": "number",
"default": 50,
"description": "Maximum autonomous steps the agent can take per request. Default: 50"
},
"g1nation.dryRun": {
"type": "boolean",
"default": false,
"description": "If enabled, the agent will ask for approval before committing any file changes."
},
"g1nation.telegram.enabled": {
"type": "boolean",
"default": false,
"description": "Enable the Telegram bot integration. When on, Astra polls a bot you configure and replies to incoming messages. Off by default — Astra remains 100% local until you opt in."
},
"g1nation.telegram.allowedChatIds": {
"type": "array",
"default": [],
"items": { "type": "number" },
"description": "Optional allowlist of Telegram chat IDs that may message the bot. When empty, every chat that messages the bot is accepted (use with caution)."
},
"g1nation.telegram.defaultAgent": {
"type": "string",
"default": "",
"description": "Agent name (matches an entry in the Agent ↔ Knowledge map) used to scope Second Brain retrieval for Telegram replies. Empty falls back to the map's defaultAgent, then to whole-brain search."
},
"g1nation.telegram.agentByChatId": {
"type": "object",
"default": {},
"additionalProperties": { "type": "string" },
"description": "Per-chat override of the Telegram agent. Keys are stringified chat IDs, values are agent names from the knowledge map. Overrides telegram.defaultAgent for the listed chats."
},
"g1nation.telegram.contextChunks": {
"type": "number",
"default": 6,
"minimum": 0,
"maximum": 20,
"description": "How many Second Brain excerpts to inject into Telegram replies. Set 0 to disable RAG (plain prompt only)."
},
"g1nation.skillKnowledgeMapPath": {
"type": "string",
"default": "",
"description": "Absolute path to the agent ↔ knowledge mapping JSON. When empty, defaults to '<workspace>/.astra/agent-knowledge-map.json'."
},
"g1nation.skillKnowledgeMap": {
"type": "object",
"default": {},
"description": "Inline fallback for the agent ↔ knowledge mapping. Used only when the JSON file is missing. Shape: { defaultAgent?, agents: [{ name, knowledgeFolders, model?, description? }] }. Folder paths can be absolute, ~-prefixed, or relative to the active brain root."
},
"g1nation.agentSkillsPath": {
"type": "string",
"default": "",
"description": "Absolute path to the agent skills folder (`.agent/skills/*.md`). When empty, defaults to '<workspace>/.agent/skills'. Use this on Windows or when your skills live outside the workspace."
},
"g1nation.embeddingModel": {
"type": "string",
"default": "",
"description": "Embedding model registered in LM Studio / Ollama (e.g. 'text-embedding-bge-small-en-v1.5', 'nomic-embed-text', 'multilingual-e5-small'). When empty, Astra uses TF-IDF only. When set, the brain is embedded lazily in the background and retrieval blends TF-IDF + cosine similarity for synonym / paraphrase matching. Multilingual models are recommended for Korean content."
},
"g1nation.embeddingBlendAlpha": {
"type": "number",
"default": 0.5,
"minimum": 0,
"maximum": 1,
"description": "Hybrid score blend: 0 = pure TF-IDF (sparse / keyword), 1 = pure embedding cosine (dense / semantic), 0.5 = balanced. Only used when g1nation.embeddingModel is set. Default 0.5."
},
"g1nation.knowledgeMix.secondBrainWeight": {
"type": "number",
"default": 50,
"minimum": 0,
"maximum": 100,
"description": "Knowledge Mix (0100): how heavily the assistant should lean on Second Brain evidence vs. its own general knowledge. 0 = Second Brain disabled (model knowledge only). 50 = balanced (legacy default). 100 = Second Brain is the primary evidence; model knowledge only fills harmless background. Per-agent overrides in the Agent Mapping panel win over this global value."
},
"g1nation.enableReflection": {
"type": "boolean",
"default": true,
"description": "Insert a Self-Reflection (Reflector) stage between Researcher and Writer in the multi-agent workflow. The Reflector critically reviews the plan and research output (gaps, contradictions, unsupported claims, drift from the original objective) and feeds a structured critique to the Writer, which must address it before producing the final report. Reflection failures are non-fatal (the Writer still runs with empty critique). Disable to save one LLM call per mission if you prioritize latency or are running on a very small model."
},
"g1nation.autoLessonFromReflection": {
"type": "boolean",
"default": true,
"description": "Persist substantive Reflector critiques to the active brain as lesson cards under `lessons/auto-reflector/`. Future missions automatically retrieve these cards (via the existing Experience-Memory pipeline) and inject them as [⚠ ACTIVE LESSONS — verify these BEFORE finalizing] guardrails into Planner/Researcher/Writer context. A repeated critique (similar title) bumps `occurrences` and escalates `severity` (low→medium→high) instead of duplicating the card, so recurring patterns get louder over time. Disable to keep critiques single-mission only."
},
"g1nation.company.intentClassifierModel": {
"type": "string",
"default": "",
"description": "Model used to classify whether an incoming chat message in 1인 기업 모드 is a (a) casual chat / question, (b) follow-up on the previous round, or (c) a brand-new task that should trigger the full work pipeline. Empty → uses g1nation.defaultModel. Pick a fast small model (e.g. gemma 4 e2b) so the classifier doesn't add latency before every chat send. The classifier runs once per user message and returns a one-token-ish JSON verdict, so even slow hardware sees minimal overhead."
},
"g1nation.company.disableIntentClassifier": {
"type": "boolean",
"default": false,
"description": "Bypass the intent classifier and always run the full work pipeline on every chat message in 1인 기업 모드 (legacy behaviour). Enable this only if you want every input — including 'thanks', 'show me X again' — to dispatch all agents. Off by default because most chat messages aren't new work and shouldn't burn a full pipeline."
},
"g1nation.company.autoSelectPipeline": {
"type": "boolean",
"default": true,
"description": "Let the intent classifier *automatically switch* to the pipeline it recommends for this turn (e.g. short '기획서까지만' for a planning ask, full '풀 프로덕트' for an end-to-end product). Your explicitly-activated pipeline is bypassed for the round but the activation itself isn't changed. On by default — the classifier's read of the user's intent (especially explicit signals like '기획만'·'디자인만') should be honoured. Set to false if you'd rather always run the pipeline you activated yourself."
},
"g1nation.company.intentAlignmentMode": {
"type": "string",
"enum": ["off", "smart", "strict"],
"default": "smart",
"description": "Intent Alignment — turn user prompts into an explicit Requirement Contract (C-G-C-F-Q) before dispatching a pipeline. 'off' = legacy, pipeline runs immediately. 'smart' (default) = run when confidence is high, else show a confirmation card; ask up to N rounds of clarifying questions if information is missing. 'strict' = always show the contract card and require user confirmation, regardless of confidence. Goal: stop agents from silently guessing at the user's mental model."
},
"g1nation.company.intentAlignmentMaxRounds": {
"type": "number",
"minimum": 1,
"maximum": 5,
"default": 3,
"description": "Maximum back-and-forth rounds the Intent Alignment analyzer is allowed to ask before forcing a 'confirm or cancel' card (it stops asking new questions and shows the current contract for user approval). Each round = one LLM call. Default 3."
},
"g1nation.selfReflector.enabled": {
"type": "boolean",
"default": false,
"description": "Self-Reflector Phase A — append a [Self-Reflector Check] block at the end of every substantive LLM answer (Consistency / Completeness / Accuracy, plus References / Paths for code answers). Zero extra LLM calls — the rule lives in the system prompt and the model self-imposes the checklist. OFF by default: the check block is an internal verification log that leaks into the user-facing answer and reads as unpolished. Enable only if you want that transparency block visible."
},
"g1nation.selfReflector.externalVerification": {
"type": "boolean",
"default": false,
"description": "Self-Reflector Phase B — after every 1인 기업 specialist response, run a *separate* LLM call to verify the output from an outside-context perspective (catches the 'same model self-validates' blind spot). Failed checks trigger one auto-revise round. Off by default — adds +1 LLM call per dispatched stage."
},
"g1nation.selfReflector.executionVerification": {
"type": "boolean",
"default": false,
"description": "Self-Reflector Phase C — after a code file is created via <create_file>, automatically run the language's syntax check (Python: py_compile, JS: node --check, TS: project tsc --noEmit). Failures are surfaced in the action report so the user (and the agent on a follow-up) can see exactly what broke. Requires the language toolchain installed on the user's machine. Off by default."
},
"g1nation.company.pixelOffice.enabled": {
"type": "boolean",
"default": true,
"description": "Show the Pixel Office visualisation panel above the chat — a small pixel-office-style display that mirrors the agent's current pipeline status (analyzing, need_clarification, executing, reviewing, waiting_approval, done, etc.) and the current task / contract / open questions. UI layer only; turning it off does not change any agent behaviour."
},
"g1nation.company.pixelOffice.bubbles": {
"type": "boolean",
"default": true,
"description": "Show short comic-style speech bubbles above the Pixel Office character on status changes / key events (e.g. '코드 들어간다', '잠깐, 이건 다시 보자', '좋아, 끝났다!'). Bubbles are purely narrative — they never influence the agent's decisions. Disable for a quieter UI."
},
"g1nation.google.clientId": {
"type": "string",
"default": "",
"scope": "machine",
"markdownDescription": "Google OAuth Client ID — `console.cloud.google.com/apis/credentials` → OAuth 2.0 Client ID (Desktop app) 생성 후 복사. **`Astra: Google Calendar OAuth 연결 (쓰기) 🔐`** 명령을 한 번 실행하면 이 값이 자동으로 채워집니다. Calendar + Sheets 둘 다 이 자격증명을 공유.\n\n_scope: machine — Settings Sync 로 다른 기기에 공유되지 않음._"
},
"g1nation.google.clientSecret": {
"type": "string",
"default": "",
"scope": "machine",
"markdownDescription": "Google OAuth Client Secret — Client ID 와 같은 페이지에서 발급. Desktop app OAuth 의 secret 은 Google 가이드상 *진짜 비밀이 아닌 식별자* 지만, settings.json 에 그대로 들어가므로 git 커밋 / 화면 공유 시 주의.\n\n_scope: machine — Settings Sync 안 됨._"
},
"g1nation.google.calendarId": {
"type": "string",
"default": "primary",
"markdownDescription": "일정을 등록할 Google Calendar 식별자. 기본 `primary` (본인 메인 캘린더). 특정 캘린더 쓰려면 Calendar 설정 → 캘린더 통합 → 'Calendar ID' 복사 (예: `xxxxxxx@group.calendar.google.com`)."
},
"g1nation.google.defaultEventDurationMinutes": {
"type": "number",
"default": 60,
"minimum": 5,
"maximum": 1440,
"description": "end / duration 둘 다 없는 일정의 기본 길이 (분). agent 가 회의록에서 시각만 추출하고 종료 시각은 명시 안 했을 때 적용."
},
"g1nation.google.icalUrl": {
"type": "string",
"default": "",
"scope": "machine",
"markdownDescription": "Google Calendar **비공개 iCal URL** — 읽기 전용 모드용. `calendar.google.com/calendar/u/0/r/settings` → 본인 캘린더 → '캘린더 통합' → '비공개 주소(iCal 형식)' 복사. **이 URL 을 가진 사람은 본인 캘린더 모든 일정을 볼 수 있으니 절대 공개 금지.**\n\n_scope: machine — Settings Sync 안 됨. OAuth 와는 별개 — 둘 다 셋업해도 되고 한 쪽만 해도 됨._"
},
"g1nation.google.icalDaysAhead": {
"type": "number",
"default": 14,
"minimum": 1,
"maximum": 90,
"description": "iCal 캐시에 포함할 다가오는 일정 기간 (일). default 14 = 2주치."
},
"g1nation.providers.openrouter.enabled": {
"type": "boolean",
"default": false,
"description": "OpenRouter cloud provider 활성화 — Claude/Gemini/GPT 등 100+ 모델을 OpenAI 호환 API 로 사용. API key 는 Astra Settings 패널에서 등록 (Secret Storage 사용, settings.json 비저장)."
},
"g1nation.providers.openrouter.defaultModel": {
"type": "string",
"default": "",
"description": "OpenRouter 의 기본 모델 (예: 'anthropic/claude-3.5-sonnet'). 모델 선택 시 'openrouter:<model>' 형식으로 사이드바 dropdown 에 표시."
},
"g1nation.providers.anthropic.enabled": {
"type": "boolean",
"default": false,
"description": "Anthropic Claude 직접 API 활성화. OpenRouter 보다 마진 적고 prompt caching 등 native 기능 사용 가능. API key 는 Secret Storage."
},
"g1nation.providers.anthropic.defaultModel": {
"type": "string",
"default": "claude-3-5-sonnet-20241022",
"description": "Anthropic 의 기본 모델. 예: 'claude-3-5-sonnet-20241022', 'claude-3-5-haiku-20241022'."
},
"g1nation.providers.gemini.enabled": {
"type": "boolean",
"default": false,
"description": "Google Gemini 직접 API 활성화. 1M context (gemini-1.5-pro), 무료 tier 등 native 기능 사용. API key 는 Secret Storage."
},
"g1nation.providers.gemini.defaultModel": {
"type": "string",
"default": "gemini-2.0-flash-exp",
"description": "Gemini 의 기본 모델. 예: 'gemini-2.0-flash-exp', 'gemini-1.5-pro', 'gemini-1.5-flash'."
},
"g1nation.devilAgent.enabled": {
"type": "boolean",
"default": false,
"markdownDescription": "**Devil's Advocate (도현) 활성화** — 매 답변 직후 별도 LLM 호출로 *비판적 sparring partner* 가 한 문단 반박. 사용자의 사고를 *수동적 수용 → 능동적 방어* 로 전환시키는 게 목표. Local LLM 동일 모델 재사용, ~10-15% 추가 비용."
}
}
}
},
"scripts": {
"vscode:prepublish": "npm run test && npm run compile",
"compile": "esbuild src/extension.ts --bundle --platform=node --external:vscode --outfile=out/extension.js",
"watch": "tsc -watch -p ./",
"test": "jest --no-cache --forceExit",
"test:engine": "jest tests/agentEngine.test.ts --verbose --no-cache",
"pretest": "npm run compile"
},
"devDependencies": {
"@types/jest": "^29.5.14",
"@types/node": "18.x",
"@types/vscode": "^1.80.0",
"@vercel/ncc": "^0.38.4",
"esbuild": "^0.28.0",
"jest": "^29.7.0",
"ts-jest": "^29.4.9",
"typescript": "^5.1.3"
},
"dependencies": {
"@lmstudio/sdk": "^1.5.0",
"pdf-parse": "^2.4.5"
}
}