Files
connectai/package.json
T
g1nation 4153f640c2 feat: v2.2.83 → v2.2.91 — info prompt 강화 + 사용자 노출 설정 + 답변 포맷 정리
[v2.2.83] /youtube info 프롬프트 강화
- 비유 방향 보존 룰 (Hugging Face=자료실 같은 짝 뒤집기 방지)
- 신뢰도 라벨 4종 ([근거 명시] / [화자 주장] / [가정] / [정리자 추론])
- 타임스탬프 fail 룰 (인용·구간 요약 모두 mm:ss 필수)
- "정리자 노트" 별도 섹션으로 추론 격리

[v2.2.85] polishPersona self-check 5가지
- 정리·리뷰·요약 답변 출력 직전 머릿속 체크:
  (1) 사실 오류  (2) 없는 내용 추가  (3) 뉘앙스 유지
  (4) 중요도 비례  (5) 중복 제거

[v2.2.86] chunkedSwitchTokens 절대 임계값 게이트
- 입력 < 50k 토큰이면 키워드·길이 트리거 무시하고 단일 호출
- 큰 컨텍스트 모델(131k+)에서 chunked 과잉 발동 방지

[v2.2.87] MAX_SECTIONS 5→3 cap
- 총 호출 7회 → 5회 (outline + 3 section + polish)
- 사용자 피드백 "6+회는 과하다"

[v2.2.88] 이모지 사용 금지 룰
- polishPersona / directPersona / sectionPersona 모두 적용
- 사용자 피드백 "이모지는 시각 노이즈"

[v2.2.89] 사용자 노출 설정 두 항목
- chunkedMaxSections config 신규 (default 3, 1~10 clamp)
- MAX_SECTIONS_HARD_CEILING (10) 으로 안전망 격상
- Astra Settings 패널 "고급" 섹션에 두 슬라이더 노출

[v2.2.90] 가이드 문구 단순화
- "작은 모델은 낮추라" 문구 빼고 일관되게 50000 권장으로

[v2.2.91] 답변 포맷 가독성 fix
- persona 의 "TL;DR" 표현 전부 "한 줄 요약" 으로 단일화
- stripMarkdownFormatting 에 헤더 후 빈 줄 강제 삽입
  (marked.parse 가 라벨·본문을 별도 단락으로 인식 → 시각 분리)

[테스트] 400/400 통과 (resilience_stress + chunked flow + MAX_SECTIONS cap 등)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 14:12:56 +09:00

747 lines
39 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.91",
"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.setupDatacollect",
"title": "Astra: Setup Datacollect Dependencies (yt-dlp, youtube-transcript-api)",
"icon": "$(cloud-download)"
},
{
"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.chatTemperature": {
"type": "number",
"default": 0.3,
"minimum": 0,
"maximum": 2,
"markdownDescription": "채팅 응답 생성의 temperature. 낮을수록(0.2~0.3) 한국어 오타·깨진 토큰·환각이 줄고 결과가 안정적이며, 높을수록 표현이 다양해집니다. 분석·업무용은 0.3 권장."
},
"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.lmStudio.sampling.topP": {
"type": "number",
"default": 0.9,
"minimum": 0,
"maximum": 1,
"description": "Nucleus sampling cutoff. Small / quantized models often spew wrong-neighbour tokens (한글 깨짐: 붕괴→붕점) when the tail is wide. Lower (0.80.9) tightens; 1.0 disables. Applied to both SDK and REST paths."
},
"g1nation.lmStudio.sampling.topK": {
"type": "number",
"default": 20,
"minimum": 0,
"description": "Top-K sampling cutoff. 0 disables. Default 20 — tighter for small models, raise to 4080 for large models that already sample well."
},
"g1nation.lmStudio.sampling.minP": {
"type": "number",
"default": 0.05,
"minimum": 0,
"maximum": 1,
"description": "Min-P floor — discards tokens with probability below this fraction of the top token. Good defence against rare-token glitches. 0 disables."
},
"g1nation.lmStudio.sampling.repeatPenalty": {
"type": "number",
"default": 1.1,
"minimum": 1,
"maximum": 2,
"description": "Repeat / frequency penalty to curb stutter (것입니다서입니다…). 1.0 disables. Values 1.051.2 are typical."
},
"g1nation.lmStudio.statsInBudget": {
"type": "boolean",
"default": true,
"description": "Show token/s and time-to-first-token from LM Studio prediction stats in the context-budget badge after each turn (SDK path only)."
},
"g1nation.lmStudio.draftModel": {
"type": "string",
"default": "",
"description": "[Speculative decoding] LM Studio model key of a small draft model (e.g. 'gemma-2b-it') used to accelerate the main model. Empty disables. 1.53x throughput on large models. The draft must be downloaded in LM Studio (load is automatic on first use)."
},
"g1nation.lmStudio.load.flashAttention": {
"type": "boolean",
"default": true,
"description": "[Load option] Enable Flash Attention when loading models. Faster generation + lower memory on compatible hardware, especially helpful for long contexts. Default: true."
},
"g1nation.lmStudio.load.gpuOffloadRatio": {
"type": "string",
"default": "max",
"description": "[Load option] How much of the model to offload to GPU. 'max' = all (default), 'off' = CPU only, or a number 01 (e.g. '0.5' = half). Numeric strings are parsed."
},
"g1nation.lmStudio.load.offloadKVCacheToGpu": {
"type": "boolean",
"default": true,
"description": "[Load option] Keep KV cache on GPU memory. Faster but requires VRAM headroom. Default: true."
},
"g1nation.lmStudio.load.keepModelInMemory": {
"type": "boolean",
"default": true,
"description": "[Load option] Prevent the model from being swapped out of system memory. Improves interactive responsiveness; raises RAM use. Default: true."
},
"g1nation.lmStudio.load.useFp16ForKVCache": {
"type": "boolean",
"default": false,
"description": "[Load option] Store KV cache in FP16 (halves cache memory). Tiny quality impact for most models — try if you run out of VRAM at long contexts. Default: false."
},
"g1nation.lmStudio.load.evalBatchSize": {
"type": "number",
"default": 0,
"minimum": 0,
"description": "[Load option] Token batch size during evaluation. 0 = engine default. Higher (5121024) improves prefill speed on GPU at the cost of memory."
},
"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.workflow.multiAgentMode": {
"type": "string",
"enum": ["auto", "always", "off"],
"default": "auto",
"markdownDescription": "Multi-Agent(5단계) 파이프라인 발동 모드.\n\n- `auto` (기본): 작은 모델(≤4B) 감지, 큰 prompt(컨텍스트의 30%+), 명시적 키워드(보고서/리뷰/심층 분석…), 또는 사용자가 `multiAgentEnabled`를 켰을 때 자동으로 발동. 짧은 인사·잡담은 제외.\n- `always`: 인사·잡담을 제외한 모든 요청에 5단계 파이프라인 사용. 작은 모델로도 답변이 한 번에 끝나지 않는다면 이 모드가 안정적.\n- `off`: 기존 키워드/길이 휴리스틱 + 수동 `multiAgentEnabled` 토글만 사용 (legacy 동작)."
},
"g1nation.workflow.autoCtxFractionThreshold": {
"type": "number",
"default": 0.30,
"minimum": 0.05,
"maximum": 0.95,
"markdownDescription": "`workflow.multiAgentMode = auto` 일 때, prompt 토큰이 효과적 context window 의 이 비율(0~1)을 넘으면 5단계 파이프라인을 강제 발동. 기본 0.30 — 작은 모델이 input으로 컨텍스트의 30% 이상을 먹기 시작하면 한 번에 답하려다 EOS/잘림이 잘 발생한다."
},
"g1nation.chunkedSwitchTokens": {
"type": "number",
"default": 50000,
"minimum": 1000,
"markdownDescription": "**입력 prompt 가 이 토큰 수 *미만* 이면 Multi-Agent(chunked) 파이프라인 발동 안 함** — 모델이 단일 호출로 처리.\n\n키워드(\"요약\", \"리뷰\", \"보고서\" 등) 나 길이(>240자) 같은 트리거가 있어도 입력이 이 임계값 미만이면 무시되고 한 번에 답변 → 답변 속도 크게 향상.\n\n기본 **50000** — 대부분의 사용 환경에 적합. 매우 작은 컨텍스트 모델로 큰 입력을 자주 다룬다면 OOM 방지 차원에서 이 값을 낮출 수 있음."
},
"g1nation.chunkedMaxSections": {
"type": "number",
"default": 3,
"minimum": 1,
"maximum": 10,
"markdownDescription": "**Chunked 파이프라인이 답변을 쪼갤 수 있는 최대 섹션 수.**\n\n실제 LLM 호출 횟수 = `1 (outline) + N (sections) + 1 (polish)` = **2 + N 회**.\n- `1` → 총 3회 (가장 빠름, 답변이 단순할 때만 적합)\n- `3` (기본) → 총 5회\n- `5` → 총 7회 (세분화 필요할 때만)\n\n작을수록 답변 속도 빠름, 클수록 답변이 더 세분화돼서 복잡한 보고서·기획서에 유리. 기본 3 — 일반 채팅에 적합."
},
"g1nation.liveStreamTokens": {
"type": "boolean",
"default": true,
"markdownDescription": "모델 토큰을 받는 즉시 채팅 버블에 흘려보낼지 여부.\n\n- `true` (기본): 토큰을 받는 즉시 표시 → TTFT 체감 속도 향상. 생성이 끝나면 sanitize 된 최종 답변으로 `streamReplace` 가 한 번에 교체하므로 control token 노출은 잠깐만 가능.\n- `false`: 토큰을 내부에서만 누적, sanitize(`<|channel|>thought` / `<think>` / `Thinking Process:` 등 제거) 끝난 **최종 답변만 한 번에** 표시. 모델의 control token 이 잠깐이라도 화면에 노출되는 누설을 원천 차단."
},
"g1nation.outputFormat": {
"type": "string",
"enum": ["plain", "markdown"],
"default": "plain",
"markdownDescription": "최종 답변 표시 방식.\n\n- `plain` (기본): 모델이 무심코 내보낸 마크다운 마커(`##`, `**`, `__`, `> `, `* ` 등)를 후처리로 모두 제거. 섹션 라벨 텍스트(예: `핵심 요약`)는 유지되지만 헤더 마커는 사라져 깔끔한 plain text 로 보임. 작은 로컬 모델이 학습된 습관으로 `## 다음 한 수` 같은 마커를 흘리는 문제 차단.\n- `markdown`: legacy 동작. 모델 출력을 그대로 렌더러에 넘김."
},
"g1nation.chronicleAutoRecord": {
"type": "boolean",
"default": true,
"markdownDescription": "자동 기록 (Project Chronicle Auto-Record).\n\n- `true` (기본): 매 chat turn 후 의미 있는 대화(planning / decision / bug / development / discussion 유형 자동 판별)를 활성 프로젝트의 Chronicle 폴더에 자동 저장.\n- `false`: 자동 저장 OFF. 수동 기록 (도구 ▾ 의 기록 항목, `/wiki` 등) 은 계속 가능.\n\n사이드바 **도구 ▾** 메뉴의 `자동 기록` 토글로 즉시 전환 가능 — 설정 패널까지 들어갈 필요 없음."
},
"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"
}
}