Version 2.55.0 Release: Rebranding to Astra

This commit is contained in:
g1nation
2026-05-03 20:40:40 +09:00
parent d8ae0b5964
commit a5f3e383d4
19 changed files with 140 additions and 67 deletions
+5 -5
View File
@@ -1,6 +1,6 @@
# G1nation
# Astra
G1nation은 로컬 인프라를 기반으로 작동하는 고성능 자율 AI 코딩 에이전트입니다. VS Code 환경에서 복잡한 개발 작업을 수행하며, 프로젝트 아키텍처 분석부터 코드 생성, 시스템 명령 실행까지 전 과정을 자동화합니다.
Astra는 로컬 인프라를 기반으로 작동하는 자비스형 프로젝트 운영 비서입니다. VS Code 환경에서 프로젝트 기억, 제2뇌, 코드/문서 맥락, 도구 실행을 하나의 목소리로 연결해 사용자의 생각 정리와 다음 행동 결정을 돕습니다.
## 핵심 기술 아키텍처
@@ -35,7 +35,7 @@ NumPy 기반의 행렬 연산을 활용하여 기존의 반복문 기반 검색
### 소스 빌드 환경
```bash
git clone https://github.com/g1nations/locallm.git
cd connect-ai
cd locallm
npm install
npm run compile
npx vsce package
@@ -43,7 +43,7 @@ npx vsce package
## 데이터 보안 및 개인정보 보호
G1nation은 100% 로컬 추론 환경에서 작동하도록 설계되었습니다.
Astra는 100% 로컬 추론 환경에서 작동하도록 설계되었습니다.
- 모든 연산은 사용자 로컬 머신의 자원을 사용하여 처리됩니다.
- 코드 및 지식 데이터는 외부 클라우드 서버로 전송되지 않습니다.
@@ -51,4 +51,4 @@ G1nation은 100% 로컬 추론 환경에서 작동하도록 설계되었습니
---
Designed for high-performance autonomous engineering.
Copyright (C) G1nation. All rights reserved.
Copyright (C) Astra. All rights reserved.
@@ -1,6 +1,6 @@
# Advanced Features Implementation Guide
이 문서는 ConnectAI(G1nation)의 '지능형 협업 시스템' 구현을 위한 기술 가이드라인입니다.
이 문서는 Astra의 '지능형 협업 시스템' 구현을 위한 기술 가이드라인입니다.
---
+1 -1
View File
@@ -1,6 +1,6 @@
# UX/UI Consistency Guidelines
이 문서는 ConnectAI(G1nation) 프로젝트의 UI 일관성과 사용자 경험을 유지하기 위한 핵심 규칙을 정의합니다. 모든 신규 기능 및 UI 수정은 이 가이드라인을 준수해야 합니다.
이 문서는 Astra 프로젝트의 UI 일관성과 사용자 경험을 유지하기 위한 핵심 규칙을 정의합니다. 모든 신규 기능 및 UI 수정은 이 가이드라인을 준수해야 합니다.
---
+3 -3
View File
@@ -1,9 +1,9 @@
# ConnectAI Project Chronicle Records
# Astra Project Chronicle Records
This folder stores planning, decision, development, bug, and retrospective records for ConnectAI.
This folder stores planning, decision, development, bug, and retrospective records for Astra.
## Project
- Name: ConnectAI
- Name: Astra
- Root: `/Volumes/Data/project/Antigravity/ConnectAI`
- Record root: `docs/records/ConnectAI`
@@ -1,11 +1,11 @@
# ConnectAI Project Knowledge Overview
# Astra Project Knowledge Overview
Date: 2026-05-02T16:14:59.756Z
Project: ConnectAI
Project: Astra
Repository: `/Volumes/Data/project/Antigravity/ConnectAI`
## Purpose
ConnectAI는 VS Code 안에서 로컬 AI 에이전트, Second Brain, 프로젝트 기록, 에이전트 스킬을 연결하는 개발 보조 프로젝트다.
Astra는 VS Code 안에서 로컬 AI 에이전트, Second Brain, 프로젝트 기록, 에이전트 스킬을 연결하는 개발 보조 프로젝트다.
## Confirmed Structure
- `src/agent.ts`: 에이전트 실행, 로컬 경로 프리플라이트, Second Brain Trace, 액션 실행 흐름의 중심.
@@ -1,11 +1,11 @@
# ConnectAI Project Knowledge Overview
# Astra Project Knowledge Overview
Date: 2026-05-03T01:34:15.597Z
Project: ConnectAI
Project: Astra
Repository: `/Volumes/Data/project/Antigravity/ConnectAI`
## Purpose
ConnectAI는 VS Code 안에서 로컬 AI 에이전트, Second Brain, 프로젝트 기록, 에이전트 스킬을 연결하는 개발 보조 프로젝트다.
Astra는 VS Code 안에서 로컬 AI 에이전트, Second Brain, 프로젝트 기록, 에이전트 스킬을 연결하는 개발 보조 프로젝트다.
## Confirmed Structure
- `src/agent.ts`: 에이전트 실행, 로컬 경로 프리플라이트, Second Brain Trace, 액션 실행 흐름의 중심.
+2 -2
View File
@@ -1,10 +1,10 @@
# Project Profile
## Project Name
ConnectAI
Astra
## Purpose
Provide a local AI assistant experience inside VS Code with chat, local knowledge, agent skills, and project-oriented development support.
Provide a Jarvis-style local project operating assistant inside VS Code with chat, local knowledge, agent skills, and project-oriented development support.
## Core Users
- Project developer
+13 -13
View File
@@ -1,8 +1,8 @@
{
"name": "g1nation",
"displayName": "G1nation",
"description": "High-performance autonomous local AI coding agent for VS Code. Features vectorized inference, asynchronous task management, and 100% offline processing.",
"version": "2.54.0",
"name": "astra",
"displayName": "Astra",
"description": "A local Jarvis-style project operating assistant for VS Code. Connects memory, project context, tools, and a single thinking-partner voice.",
"version": "2.55.0",
"publisher": "connectailab",
"license": "MIT",
"icon": "assets/icon.png",
@@ -28,7 +28,7 @@
"offline",
"agent",
"code-generation",
"g1nation",
"astra",
"copilot"
],
"activationEvents": [],
@@ -37,24 +37,24 @@
"commands": [
{
"command": "g1nation.newChat",
"title": "G1nation: New Chat",
"title": "Astra: New Chat",
"icon": "$(add)"
},
{
"command": "g1nation.exportChat",
"title": "G1nation: Export Chat as Markdown"
"title": "Astra: Export Chat as Markdown"
},
{
"command": "g1nation.explainSelection",
"title": "G1nation: Explain Selected Code"
"title": "Astra: Explain Selected Code"
},
{
"command": "g1nation.focusChat",
"title": "G1nation: Focus Chat Input"
"title": "Astra: Focus Chat Input"
},
{
"command": "g1nation.showBrainNetwork",
"title": "G1nation: Show Brain Topology"
"title": "Astra: Show Brain Topology"
}
],
"keybindings": [
@@ -77,7 +77,7 @@
"activitybar": [
{
"id": "g1nation-sidebar",
"title": "G1nation",
"title": "Astra",
"icon": "$(hubot)"
}
]
@@ -93,7 +93,7 @@
]
},
"configuration": {
"title": "G1nation",
"title": "Astra",
"properties": {
"g1nation.multiAgentEnabled": {
"type": "boolean",
@@ -155,7 +155,7 @@
},
"name": {
"type": "string",
"description": "Display name shown in the G1nation brain selector."
"description": "Display name shown in the Astra brain selector."
},
"localBrainPath": {
"type": "string",
+58 -10
View File
@@ -207,7 +207,7 @@ export class AgentExecutor {
// Decide whether to use Multi-Agent Workflow (for complex requests)
const isComplex = prompt && (prompt.length > 100 || /(분석|보고서|설계|기획|정리)/.test(prompt));
if (isComplex && loopDepth === 0 && multiAgentEnabled) {
if (isComplex && loopDepth === 0 && multiAgentEnabled && !this.isAstraModeArchitectureQuestion(prompt)) {
return this.executeMultiAgentWorkflow(prompt!, modelName, options);
}
@@ -293,6 +293,12 @@ export class AgentExecutor {
if (projectBriefContext) {
contextBlock += `\n\n${projectBriefContext}`;
}
const modeArchitectureContext = prompt && loopDepth === 0
? this.buildAstraModeArchitectureContext(prompt)
: '';
if (modeArchitectureContext) {
contextBlock += `\n\n${modeArchitectureContext}`;
}
// 2. Setup History
if (prompt !== null) {
@@ -792,6 +798,40 @@ export class AgentExecutor {
return /(어떤\s*거?\s*같|어때|어떻게\s*생각|의견|판단|방향|설계|아키텍처|구조|자비스|생각.*정리|갈림길|architecture|design|direction|opinion|think|judge)/i.test(prompt);
}
private isAstraModeArchitectureQuestion(prompt: string): boolean {
const mentionsGuard = /\bguard\b|가드|Guard|Chronicle Guard|Project Chronicle/i.test(prompt);
const mentionsMultiAgent = /\bMA\b|multi[-\s]?agent|멀티\s*에이전트|다중\s*에이전트|Planner|Researcher|Writer/i.test(prompt);
const asksDecision = /(분리|통합|모드|사용|좋을까|맞을까|구조|설계|아키텍처|의견|판단|어때|어떤\s*거?\s*같|separate|combine|mode|architecture|design|opinion)/i.test(prompt);
return asksDecision && mentionsGuard && mentionsMultiAgent;
}
private buildAstraModeArchitectureContext(prompt: string): string {
if (!this.isAstraModeArchitectureQuestion(prompt)) {
return '';
}
return [
'[ASTRA MODE ARCHITECTURE DECISION CONTEXT]',
'The user is asking about Astra itself, specifically whether Guard mode and MA/Multi-Agent mode should remain separate.',
'',
'Confirmed implementation facts from the current codebase:',
'- Guard is currently exposed as a sidebar toggle, but it defaults to enabled in the webview UI.',
'- Guard context is built by buildProjectChronicleGuardContext(activeProject) and passed into AgentExecutor as designerContext.',
'- In the normal single-agent path, designerContext is injected into the system prompt as [PROJECT CHRONICLE GUARD].',
'- In the Multi-Agent path, designerContext is appended as Project Chronicle Guard context for the workflow manager.',
'- Multi-Agent is controlled by the g1nation.multiAgentEnabled config and is only used for complex prompts.',
'- Current risk: when Multi-Agent starts, it returns early before the normal path builds local project preflight, Second Brain Trace, recent project knowledge context, and thinking-partner context.',
'',
'Product decision guidance:',
'- Do not treat Guard and MA as two equal user-facing modes.',
'- Guard should be an always-on policy/context layer: project target, evidence discipline, record hygiene, tone, and decision logging.',
'- MA should be an optional execution strategy chosen automatically for genuinely complex tasks.',
'- Recommended UX: hide or de-emphasize the Guard toggle, show it as Auto/On by default, and let Astra route between single-agent and MA internally.',
'- Recommended answer: give a clear verdict that separating them as peer modes is not ideal; separate them internally by responsibility instead.',
'- Mention the concrete risk that MA can currently bypass richer context assembly, so unifying the context preparation before routing is the next engineering step.'
].join('\n');
}
private buildJarvisProjectBriefContext(prompt: string, localPathContext: string, recentProjectKnowledgeContext: string): string {
if (!this.isThinkingPartnerRequest(prompt)) {
return '';
@@ -1102,6 +1142,7 @@ export class AgentExecutor {
private buildProjectKnowledgeFallbackAnswer(localPathContext: string, record?: { filePath: string; relativePath: string } | null): string {
const pathMatch = localPathContext.match(/Path:\s*(.+)/);
const projectPath = pathMatch?.[1]?.trim() || '제공된 로컬 프로젝트 경로';
const projectDisplayName = this.getProjectDisplayName(projectPath);
const treeMatch = localPathContext.match(/Scanned tree:\n([\s\S]*?)(?:\nPriority file previews:|$)/);
const treePreview = treeMatch?.[1]?.trim().split('\n').slice(0, 18).join('\n') || '';
const priorityMatches = this.extractPriorityPreviewFiles(localPathContext).slice(0, 10);
@@ -1123,10 +1164,10 @@ export class AgentExecutor {
'',
'## 바로 만들 지식 초안',
'```markdown',
'# ConnectAI Project Knowledge Overview',
`# ${projectDisplayName} Project Knowledge Overview`,
'',
'## Purpose',
'ConnectAI는 VS Code 안에서 로컬 AI 에이전트, Second Brain, 프로젝트 기록, 에이전트 스킬을 연결하는 개발 보조 프로젝트다.',
`${projectDisplayName}는 VS Code 안에서 로컬 AI 에이전트, Second Brain, 프로젝트 기록, 에이전트 스킬을 연결하는 개발 보조 프로젝트다.`,
'',
'## Confirmed Structure',
'- `src/agent.ts`: 에이전트 실행, 로컬 경로 프리플라이트, Second Brain Trace, 액션 실행 흐름의 중심.',
@@ -1140,7 +1181,7 @@ export class AgentExecutor {
'- 전체 아키텍처는 파일 구조와 일부 프리뷰 기준으로 파악 가능하지만, 세부 동작 지식은 `src/agent.ts`, `src/sidebarProvider.ts`, `secondBrainTrace.ts`, `projectChronicle` 순서로 심화 분석해 보강해야 한다.',
'',
'## Recommended Next Record',
'- `docs/records/ConnectAI/development/YYYY-MM-DD_connectai_project_knowledge_overview.md`',
`- \`docs/records/${path.basename(projectPath)}/development/YYYY-MM-DD_${projectDisplayName.toLowerCase()}_project_knowledge_overview.md\``,
'```',
'',
'## 다음 액션',
@@ -1170,8 +1211,9 @@ export class AgentExecutor {
try {
const projectName = path.basename(projectPath);
const projectDisplayName = this.getProjectDisplayName(projectPath);
const today = new Date().toISOString().slice(0, 10);
const slug = projectName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || 'project';
const slug = projectDisplayName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || 'project';
const relativePath = path.join('docs', 'records', projectName, 'development', `${today}_${slug}_project_knowledge_overview.md`);
const filePath = path.join(projectPath, relativePath);
fs.mkdirSync(path.dirname(filePath), { recursive: true });
@@ -1187,19 +1229,20 @@ export class AgentExecutor {
const pathMatch = localPathContext.match(/Path:\s*(.+)/);
const projectPath = pathMatch?.[1]?.trim() || 'Unknown project path';
const projectName = path.basename(projectPath);
const projectDisplayName = this.getProjectDisplayName(projectPath);
const treeMatch = localPathContext.match(/Scanned tree:\n([\s\S]*?)(?:\nPriority file previews:|$)/);
const treePreview = treeMatch?.[1]?.trim().split('\n').slice(0, 80).join('\n') || '';
const priorityFiles = this.extractPriorityPreviewFiles(localPathContext);
return [
`# ${projectName} Project Knowledge Overview`,
`# ${projectDisplayName} Project Knowledge Overview`,
'',
`Date: ${new Date().toISOString()}`,
`Project: ${projectName}`,
`Project: ${projectDisplayName}`,
`Repository: \`${projectPath}\``,
'',
'## Purpose',
`${projectName}는 VS Code 안에서 로컬 AI 에이전트, Second Brain, 프로젝트 기록, 에이전트 스킬을 연결하는 개발 보조 프로젝트다.`,
`${projectDisplayName}는 VS Code 안에서 로컬 AI 에이전트, Second Brain, 프로젝트 기록, 에이전트 스킬을 연결하는 개발 보조 프로젝트다.`,
'',
'## Confirmed Structure',
'- `src/agent.ts`: 에이전트 실행, 로컬 경로 프리플라이트, Second Brain Trace, 액션 실행 흐름의 중심.',
@@ -1227,6 +1270,11 @@ export class AgentExecutor {
].join('\n');
}
private getProjectDisplayName(projectPath: string): string {
const projectName = path.basename(projectPath);
return /^connectai$/i.test(projectName) ? 'Astra' : projectName;
}
private listProjectTree(root: string, current: string, depth: number, maxDepth: number, limit: number): string {
if (limit <= 0 || depth > maxDepth) {
return '';
@@ -1646,7 +1694,7 @@ export class AgentExecutor {
const cmd = match[1].trim();
try {
const safeCmd = sanitizeCommand(cmd);
const terminal = vscode.window.terminals.find(t => t.name === 'G1nation Terminal') || vscode.window.createTerminal({ name: 'G1nation Terminal', cwd: rootPath });
const terminal = vscode.window.terminals.find(t => t.name === 'Astra Terminal') || vscode.window.createTerminal({ name: 'Astra Terminal', cwd: rootPath });
terminal.show();
terminal.sendText(safeCmd);
report.push(`🚀 Executed: ${safeCmd}`);
@@ -1766,7 +1814,7 @@ export class AgentExecutor {
try {
const { execSync } = require('child_process');
execSync(`git add .`, { cwd: brainDir });
execSync(`git commit -m "[G1nation] Knowledge Update"`, { cwd: brainDir });
execSync(`git commit -m "[Astra] Knowledge Update"`, { cwd: brainDir });
execSync(`git push`, { cwd: brainDir });
} catch (err) {
logError('Second Brain sync failed.', err);
+1 -1
View File
@@ -20,7 +20,7 @@ export interface BridgeInterface {
/**
* BridgeServer:
* 외부 툴(EZER, A.U 등)과 G1nation 확장을 연결하는 통신 브릿지.
* 외부 툴(EZER, A.U 등)과 Astra 확장을 연결하는 통신 브릿지.
* 서비스 레이어(AIService, BrainService)를 통해 비즈니스 로직을 분리하여 유지보수성을 극대화했습니다.
*/
export class BridgeServer {
+1 -1
View File
@@ -44,7 +44,7 @@ export class HealthCheckMonitor {
if (reports.length > 0) {
logWarn(`Health Check Warnings: ${reports.join(' | ')}`);
vscode.window.showWarningMessage(`ConnectAI Health Warning: ${reports[0]}`);
vscode.window.showWarningMessage(`Astra Health Warning: ${reports[0]}`);
}
return {
+1 -1
View File
@@ -43,7 +43,7 @@ export class StatusBarManager {
break;
}
this.statusBarItem.text = `${icon} G1nation: ${status}`;
this.statusBarItem.text = `${icon} Astra: ${status}`;
this.statusBarItem.tooltip = detail || `Current State: ${status}`;
if (status === AgentStatus.Success || status === AgentStatus.Error) {
+5 -5
View File
@@ -18,10 +18,10 @@ import { SidebarChatProvider } from './sidebarProvider';
import { HealthCheckMonitor } from './core/health';
/**
* G1nation Extension Entry Point
* Astra Extension Entry Point
*/
export async function activate(context: vscode.ExtensionContext) {
logInfo('ConnectAI activating...');
logInfo('Astra activating...');
// Start Environment Health Monitoring
HealthCheckMonitor.runAllChecks();
@@ -30,7 +30,7 @@ export async function activate(context: vscode.ExtensionContext) {
// 0. Validate Configuration
const validation = validateConfig();
if (!validation.valid) {
vscode.window.showErrorMessage(`G1nation Configuration Error: ${validation.errors.join(' ')}`);
vscode.window.showErrorMessage(`Astra Configuration Error: ${validation.errors.join(' ')}`);
logError('Configuration validation failed.', { errors: validation.errors });
}
@@ -144,12 +144,12 @@ async function _ensureBrainDir(context: vscode.ExtensionContext): Promise<string
try {
fs.mkdirSync(defaultDir, { recursive: true });
// Create a welcome file
fs.writeFileSync(path.join(defaultDir, 'Welcome.md'), "# Welcome to your Second Brain\n\nG1nation will store and retrieve knowledge from here.");
fs.writeFileSync(path.join(defaultDir, 'Welcome.md'), "# Welcome to your Second Brain\n\nAstra will store and retrieve knowledge from here.");
} catch (e) {}
}
return defaultDir;
}
/**
* G1nation Extension Entry Point
* Astra Extension Entry Point
*/
@@ -38,6 +38,10 @@ export function buildProjectChronicleGuardContext(project: ProjectProfile | null
'- Do not mark a decision as accepted until the user confirms it.',
'- Before confirmation, call decisions "candidates" or "pending".',
'- Prefer "reduced adoption" when the idea is useful but too large for the MVP.',
'- For Astra mode-design questions, do not treat Guard and MA/Multi-Agent as two equal user-facing modes.',
'- Treat Guard as a policy/context layer for evidence, project target, record hygiene, and thinking-partner tone.',
'- Treat MA/Multi-Agent as an execution strategy that may be selected automatically for complex tasks.',
'- If asked whether Guard and MA should be separated, recommend internal responsibility separation but a simpler Auto user experience.',
'',
'Evidence policy:',
'- No Evidence, No Project Claim: do not state that the current project has a technical structure unless it is supported by user-provided facts, source code, design docs, project docs, or project records.',
+13 -13
View File
@@ -626,7 +626,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
if (!name) return;
const description = await vscode.window.showInputBox({
prompt: 'Optional description shown in the G1nation sidebar',
prompt: 'Optional description shown in the Astra sidebar',
value: ''
});
@@ -687,7 +687,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
if (!folder) return;
const description = await vscode.window.showInputBox({
prompt: 'Edit optional description shown in the G1nation sidebar',
prompt: 'Edit optional description shown in the Astra sidebar',
value: target.description || ''
});
@@ -819,7 +819,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
`title: "${this._escapeYamlString(this._summarizeForTitle(firstUserMessage))}"`,
`category: "${this._escapeYamlString(meta.category)}"`,
`created_at: "${meta.createdAt}"`,
`source: "ConnectAI conversation"`,
`source: "Astra conversation"`,
`brain: "${this._escapeYamlString(meta.activeBrainName)}"`,
'status: raw',
'---',
@@ -874,7 +874,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
private _summarizeForTitle(value: string): string {
const normalized = value.replace(/\s+/g, ' ').trim();
if (!normalized) return 'ConnectAI Conversation Raw Data';
if (!normalized) return 'Astra Conversation Raw Data';
return normalized.length > 80 ? `${normalized.slice(0, 80)}...` : normalized;
}
@@ -930,7 +930,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
}
vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: "G1nation: Syncing Second Brain...",
title: "Astra: Syncing Second Brain...",
cancellable: false
}, async () => {
try {
@@ -1573,7 +1573,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
this._chronicle.appendTimeline(profile, [`Auto ${recordType} record created: ${result.relativePath}`], createdAt);
await this._context.globalState.update(SidebarChatProvider.lastAutoChronicleSignatureStateKey, signature);
await this._sendChronicleRecords();
vscode.window.setStatusBarMessage(`G1nation: Chronicle auto-saved ${recordType}`, 3500);
vscode.window.setStatusBarMessage(`Astra: Chronicle auto-saved ${recordType}`, 3500);
} catch (err: any) {
logError('Automatic Chronicle record write failed.', { error: err?.message || String(err), recordType });
}
@@ -1944,7 +1944,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>G1nation</title>
<title>Astra</title>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<style>
:root {
@@ -2558,7 +2558,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
<body>
<div class="header">
<div class="header-top">
<div class="brand"><div class="logo">✦</div> G1nation</div>
<div class="brand"><div class="logo">✦</div> Astra</div>
<div class="header-actions">
<button class="icon-btn" id="newChatBtn" data-tooltip="New Chat">New</button>
<button class="icon-btn" id="saveWikiRawBtn" data-tooltip="Save Wiki Raw">Wiki</button>
@@ -2639,7 +2639,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
<div class="chat" id="chat">
<div class="welcome">
<div class="welcome-logo">✦</div>
<div class="welcome-title">Welcome to G1nation</div>
<div class="welcome-title">Welcome to Astra</div>
<p>Your premium local AI assistant.<br>Ready to analyze projects and build reports.</p>
</div>
</div>
@@ -2686,7 +2686,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
// [State Persistence - Tier 0] 즉시 복원 (Instant Restore from WebView State)
const previousState = vscode.getState();
if (previousState && previousState.history && previousState.history.length > 0) {
console.log('[G1nation] Restoring from Webview State...');
console.log('[Astra] Restoring from Webview State...');
renderHistory(previousState.history);
}
@@ -2899,7 +2899,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
const head = document.createElement('div');
head.className = 'msg-head';
head.innerHTML = isUser ? '<div class="av av-user">U</div> You' : '<div class="av av-ai">✦</div> G1nation';
head.innerHTML = isUser ? '<div class="av av-user">U</div> You' : '<div class="av av-ai">✦</div> Astra';
const body = document.createElement('div');
body.className = 'msg-body markdown-body';
@@ -2985,7 +2985,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
historyOverlay.classList.remove('visible');
break;
case 'clearChat':
chat.innerHTML = '<div class="welcome"><div class="welcome-logo">✦</div><div class="welcome-title">Welcome to G1nation</div><p>Your premium local AI assistant.<br>Ready to analyze projects and build reports.</p></div>';
chat.innerHTML = '<div class="welcome"><div class="welcome-logo">✦</div><div class="welcome-title">Welcome to Astra</div><p>Your premium local AI assistant.<br>Ready to analyze projects and build reports.</p></div>';
break;
case 'focusInput':
input.focus();
@@ -3325,7 +3325,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
try {
localStorage.setItem('g1nation_last_model', _selectedModel);
} catch(e) {
console.warn('[G1nation] LocalStorage 저장 실패:', e);
console.warn('[Astra] LocalStorage 저장 실패:', e);
}
// [State Persistence - Tier 1] VS Code 전역 설정에 동기화 (영구 저장)
vscode.postMessage({ type: 'model', value: _selectedModel });
+3 -2
View File
@@ -7,7 +7,7 @@ import { getConfig, BrainProfile, EXCLUDED_DIRS } from './config';
export type EngineKind = 'lmstudio' | 'ollama';
const outputChannel = vscode.window.createOutputChannel('Connect AI');
const outputChannel = vscode.window.createOutputChannel('Astra');
function timestamp() {
return new Date().toISOString();
@@ -137,7 +137,8 @@ export function findBrainFiles(dir: string): string[] {
return results;
}
const BASE_SYSTEM_PROMPT = `You are G1nation, also called Steve when the user asks your name.
const BASE_SYSTEM_PROMPT = `You are Astra, a Jarvis-style local project operating assistant.
If the user asks your name, say you are Astra.
Reply naturally in the user's language.
Core behavior:
+19 -2
View File
@@ -83,6 +83,23 @@ describe('local project path preflight', () => {
expect(agent.isThinkingPartnerRequest(prompt)).toBe(true);
});
it('adds concrete Astra mode architecture context for Guard and MA design questions', () => {
const context: any = {
globalStorageUri: { fsPath: path.join(root, '.storage') },
workspaceState: stateStore(),
globalState: stateStore()
};
const agent = new AgentExecutor(context) as any;
const prompt = '지금 우리는 guard 모드가 있고 MA 모드가 있는데 굳이 이렇게 모드를 분리해서 사용하는게 좋을까?';
expect(agent.isAstraModeArchitectureQuestion(prompt)).toBe(true);
const modeContext = agent.buildAstraModeArchitectureContext(prompt);
expect(modeContext).toContain('Confirmed implementation facts');
expect(modeContext).toContain('Guard should be an always-on policy/context layer');
expect(modeContext).toContain('MA should be an optional execution strategy');
expect(modeContext).toContain('bypass richer context assembly');
});
it('removes file-structure requests when knowledge creation path access already succeeded', () => {
const context: any = {
globalStorageUri: { fsPath: path.join(root, '.storage') },
@@ -123,7 +140,7 @@ describe('local project path preflight', () => {
expect(agent.isBlockingProjectKnowledgeAnswer(answer)).toBe(true);
const fallback = agent.buildProjectKnowledgeFallbackAnswer(localPathContext);
expect(fallback).toContain('추가 질문으로 멈출 필요 없이');
expect(fallback).toContain('ConnectAI Project Knowledge Overview');
expect(fallback).toContain('Astra Project Knowledge Overview');
expect(fallback).not.toContain('어떤 기능 영역을 가장 먼저');
});
@@ -261,7 +278,7 @@ describe('local project path preflight', () => {
'[RECENT LOCAL PROJECT KNOWLEDGE]',
`Use this recently generated project knowledge record as project evidence: ${recordPath}`,
'',
'# ConnectAI Project Knowledge Overview',
'# Astra Project Knowledge Overview',
'',
'## Evidence Files',
'- `package.json`',
@@ -36,6 +36,9 @@ describe('buildProjectChronicleGuardContext', () => {
expect(context).toContain('Later expansion');
expect(context).toContain('Candidate records for this discussion');
expect(context).toContain('Do not mark a decision as accepted until the user confirms it');
expect(context).toContain('Guard and MA/Multi-Agent');
expect(context).toContain('policy/context layer');
expect(context).toContain('execution strategy');
expect(context).toContain('Markdown, JSON, local files');
});
+1 -1
View File
@@ -288,7 +288,7 @@ describe('Second Brain Trace', () => {
fs.writeFileSync(
path.join(root, 'Project_Logs', '2026-05-02-ConnectAI_Project_Knowledge.md'),
[
'# ConnectAI Project Knowledge',
'# Astra Project Knowledge',
'',
'Project: ConnectAI',
'Repository: `/Volumes/Data/project/Antigravity/ConnectAI`',