Version 2.38.0 Release: Sync logic and knowledge categorization

This commit is contained in:
g1nation
2026-05-03 00:23:47 +09:00
parent d5aad75a10
commit d875ba7bc3
4 changed files with 35 additions and 37 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "g1nation", "name": "g1nation",
"version": "2.34.1", "version": "2.36.9",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "g1nation", "name": "g1nation",
"version": "2.34.1", "version": "2.36.9",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"marked": "^18.0.2" "marked": "^18.0.2"
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "g1nation", "name": "g1nation",
"displayName": "G1nation", "displayName": "G1nation",
"description": "High-performance autonomous local AI coding agent for VS Code. Features vectorized inference, asynchronous task management, and 100% offline processing.", "description": "High-performance autonomous local AI coding agent for VS Code. Features vectorized inference, asynchronous task management, and 100% offline processing.",
"version": "2.36.9", "version": "2.38.0",
"publisher": "connectailab", "publisher": "connectailab",
"license": "MIT", "license": "MIT",
"icon": "assets/icon.png", "icon": "assets/icon.png",
+24 -31
View File
@@ -3,11 +3,9 @@ import * as path from 'path';
import * as fs from 'fs'; import * as fs from 'fs';
// axios removed // axios removed
import { import {
_getBrainDir,
findBrainFiles, findBrainFiles,
getSystemPrompt, getSystemPrompt,
shouldAutoPushBrain, shouldAutoPushBrain,
getSecondBrainRepo,
buildApiUrl, buildApiUrl,
getActiveBrainProfile, getActiveBrainProfile,
logError, logError,
@@ -15,7 +13,7 @@ import {
resolveEngine, resolveEngine,
summarizeText summarizeText
} from './utils'; } from './utils';
import { getConfig, EXCLUDED_DIRS } from './config'; import { BrainProfile, getConfig, EXCLUDED_DIRS } from './config';
import { validatePath, sanitizeCommand } from './security'; import { validatePath, sanitizeCommand } from './security';
import { TransactionManager } from './core/transaction'; import { TransactionManager } from './core/transaction';
import { SessionManager } from './core/session'; import { SessionManager } from './core/session';
@@ -192,7 +190,8 @@ export class AgentExecutor {
negativePrompt?: string, negativePrompt?: string,
designerContext?: string, designerContext?: string,
secondBrainTraceEnabled?: boolean, secondBrainTraceEnabled?: boolean,
secondBrainTraceDebug?: boolean secondBrainTraceDebug?: boolean,
brainProfileId?: string
} }
) { ) {
const { const {
@@ -241,7 +240,9 @@ export class AgentExecutor {
let contextBlock = ''; let contextBlock = '';
const config = getConfig(); const config = getConfig();
const activeBrain = getActiveBrainProfile(); const activeBrain = options.brainProfileId
? (config.brainProfiles.find((profile) => profile.id === options.brainProfileId) || getActiveBrainProfile())
: getActiveBrainProfile();
const brainFiles = findBrainFiles(activeBrain.localBrainPath); const brainFiles = findBrainFiles(activeBrain.localBrainPath);
let secondBrainTrace: SecondBrainTrace | null = null; let secondBrainTrace: SecondBrainTrace | null = null;
if (options.secondBrainTraceEnabled && prompt && loopDepth === 0) { if (options.secondBrainTraceEnabled && prompt && loopDepth === 0) {
@@ -329,7 +330,7 @@ export class AgentExecutor {
const secondBrainTraceCtx = secondBrainTrace const secondBrainTraceCtx = secondBrainTrace
? `\n\n${renderSecondBrainTraceContext(secondBrainTrace)}` ? `\n\n${renderSecondBrainTraceContext(secondBrainTrace)}`
: ''; : '';
const memoryCtx = this.buildMemoryContext(prompt || ''); const memoryCtx = this.buildMemoryContext(prompt || '', activeBrain);
const fullSystemPrompt = `${agentSkillCtx}\n\n${systemPrompt}${internetCtx}${memoryCtx}${designerCtx}${secondBrainTraceCtx}\n\n[CONTEXT]\n${brainContext}\n${contextBlock}${negativeCtx}`; const fullSystemPrompt = `${agentSkillCtx}\n\n${systemPrompt}${internetCtx}${memoryCtx}${designerCtx}${secondBrainTraceCtx}\n\n[CONTEXT]\n${brainContext}\n${contextBlock}${negativeCtx}`;
const messagesForRequest: ChatMessage[] = [ const messagesForRequest: ChatMessage[] = [
@@ -431,7 +432,7 @@ export class AgentExecutor {
this.chatHistory.push(assistantMessage); this.chatHistory.push(assistantMessage);
this.statusBarManager.updateStatus(AgentStatus.Executing); this.statusBarManager.updateStatus(AgentStatus.Executing);
const report = await this.executeActions(aiResponseText, rootPath); const report = await this.executeActions(aiResponseText, rootPath, activeBrain);
if (!assistantContent.trim() && report.length === 0) { if (!assistantContent.trim() && report.length === 0) {
this.chatHistory.pop(); this.chatHistory.pop();
logError('Model returned an empty response without actions.', { model: actualModel, engine, apiUrl, loopDepth }); logError('Model returned an empty response without actions.', { model: actualModel, engine, apiUrl, loopDepth });
@@ -511,7 +512,10 @@ export class AgentExecutor {
try { try {
let brainContext = 'No specific context available'; let brainContext = 'No specific context available';
try { try {
const activeBrain = getActiveBrainProfile(); const config = getConfig();
const activeBrain = options.brainProfileId
? (config.brainProfiles.find((profile) => profile.id === options.brainProfileId) || getActiveBrainProfile())
: getActiveBrainProfile();
const brainFiles = findBrainFiles(activeBrain.localBrainPath); const brainFiles = findBrainFiles(activeBrain.localBrainPath);
brainContext = `Brain: ${activeBrain.name}, Files: ${brainFiles.length}`; brainContext = `Brain: ${activeBrain.name}, Files: ${brainFiles.length}`;
} catch (ctxErr) { } catch (ctxErr) {
@@ -826,7 +830,7 @@ export class AgentExecutor {
}); });
} }
private buildMemoryContext(currentPrompt: string): string { private buildMemoryContext(currentPrompt: string, activeBrain: BrainProfile): string {
const config = getConfig(); const config = getConfig();
if (!config.memoryEnabled) return ''; if (!config.memoryEnabled) return '';
@@ -848,7 +852,7 @@ export class AgentExecutor {
}) })
.join('\n'); .join('\n');
const longTerm = this.findRelevantBrainMemory(currentPrompt, config.memoryLongTermFiles); const longTerm = this.findRelevantBrainMemory(currentPrompt, config.memoryLongTermFiles, activeBrain);
const sections = [ const sections = [
shortTerm ? `### Short-Term Memory\n${shortTerm}` : '', shortTerm ? `### Short-Term Memory\n${shortTerm}` : '',
mediumTerm ? `### Medium-Term Memory\n${mediumTerm}` : '', mediumTerm ? `### Medium-Term Memory\n${mediumTerm}` : '',
@@ -865,11 +869,10 @@ export class AgentExecutor {
].join('\n'); ].join('\n');
} }
private findRelevantBrainMemory(currentPrompt: string, limit: number): string { private findRelevantBrainMemory(currentPrompt: string, limit: number, activeBrain: BrainProfile): string {
if (limit <= 0) return ''; if (limit <= 0) return '';
try { try {
const activeBrain = getActiveBrainProfile();
const files = findBrainFiles(activeBrain.localBrainPath); const files = findBrainFiles(activeBrain.localBrainPath);
const terms = currentPrompt const terms = currentPrompt
.toLowerCase() .toLowerCase()
@@ -1043,9 +1046,10 @@ export class AgentExecutor {
return candidates; return candidates;
} }
private async executeActions(aiMessage: string, rootPath: string): Promise<string[]> { private async executeActions(aiMessage: string, rootPath: string, activeBrain: BrainProfile): Promise<string[]> {
const report: string[] = []; const report: string[] = [];
let brainModified = false; let brainModified = false;
const activeBrainDir = activeBrain.localBrainPath;
let firstCreatedFile: string | undefined; let firstCreatedFile: string | undefined;
try { try {
@@ -1066,7 +1070,7 @@ export class AgentExecutor {
report.push(`✅ Created: ${relPath}`); report.push(`✅ Created: ${relPath}`);
if (!firstCreatedFile) firstCreatedFile = absPath; if (!firstCreatedFile) firstCreatedFile = absPath;
if (absPath.startsWith(_getBrainDir())) brainModified = true; if (absPath.startsWith(activeBrainDir)) brainModified = true;
} catch (err: any) { } catch (err: any) {
throw new FileSystemError(`Failed to create file ${relPath}: ${err.message}`, relPath, err); throw new FileSystemError(`Failed to create file ${relPath}: ${err.message}`, relPath, err);
} }
@@ -1099,7 +1103,7 @@ export class AgentExecutor {
fs.writeFileSync(absPath, editContent, 'utf-8'); fs.writeFileSync(absPath, editContent, 'utf-8');
report.push(`📝 Updated (Full): ${relPath}`); report.push(`📝 Updated (Full): ${relPath}`);
} }
if (absPath.startsWith(_getBrainDir())) brainModified = true; if (absPath.startsWith(activeBrainDir)) brainModified = true;
} else { } else {
report.push(`❌ File not found: ${relPath}`); report.push(`❌ File not found: ${relPath}`);
} }
@@ -1184,7 +1188,7 @@ export class AgentExecutor {
while ((match = listBrainRegex.exec(aiMessage)) !== null) { while ((match = listBrainRegex.exec(aiMessage)) !== null) {
const relPath = match[1].trim() || '.'; const relPath = match[1].trim() || '.';
try { try {
const brainDir = _getBrainDir(); const brainDir = activeBrainDir;
const absPath = path.join(brainDir, relPath); const absPath = path.join(brainDir, relPath);
if (fs.existsSync(absPath) && fs.statSync(absPath).isDirectory()) { if (fs.existsSync(absPath) && fs.statSync(absPath).isDirectory()) {
const entries = fs.readdirSync(absPath, { withFileTypes: true }); const entries = fs.readdirSync(absPath, { withFileTypes: true });
@@ -1209,7 +1213,7 @@ export class AgentExecutor {
while ((match = brainRegex.exec(aiMessage)) !== null) { while ((match = brainRegex.exec(aiMessage)) !== null) {
const fileName = match[1].trim(); const fileName = match[1].trim();
try { try {
const brainDir = _getBrainDir(); const brainDir = activeBrainDir;
const files = findBrainFiles(brainDir); const files = findBrainFiles(brainDir);
const targetFile = files.find((f: string) => path.basename(f) === fileName || f.endsWith(fileName)); const targetFile = files.find((f: string) => path.basename(f) === fileName || f.endsWith(fileName));
@@ -1242,8 +1246,8 @@ export class AgentExecutor {
} }
// Brain Sync Logic // Brain Sync Logic
if (brainModified && shouldAutoPushBrain() && getSecondBrainRepo()) { if (brainModified && shouldAutoPushBrain() && activeBrain.secondBrainRepo) {
this.syncBrain(); this.syncBrain(activeBrainDir);
} }
const config = getConfig(); const config = getConfig();
@@ -1262,22 +1266,11 @@ export class AgentExecutor {
// We return the report with the failure message instead of throwing // We return the report with the failure message instead of throwing
// so the agent can see the failure and decide what to do next // so the agent can see the failure and decide what to do next
} }
if (firstCreatedFile) {
vscode.window.showTextDocument(vscode.Uri.file(firstCreatedFile), { preview: false });
}
// Brain Sync Logic
if (brainModified && shouldAutoPushBrain() && getSecondBrainRepo()) {
this.syncBrain();
}
return report; return report;
} }
private syncBrain() { private syncBrain(brainDir: string) {
try { try {
const brainDir = _getBrainDir();
const { execSync } = require('child_process'); const { execSync } = require('child_process');
execSync(`git add .`, { cwd: brainDir }); execSync(`git add .`, { cwd: brainDir });
execSync(`git commit -m "[G1nation] Knowledge Update"`, { cwd: brainDir }); execSync(`git commit -m "[G1nation] Knowledge Update"`, { cwd: brainDir });
+8 -3
View File
@@ -1649,9 +1649,12 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
private async _handlePrompt(data: any) { private async _handlePrompt(data: any) {
if (!this._view) return; if (!this._view) return;
const { value, model, internet, files, agentFile, negativePrompt, designerGuard, secondBrainTrace, secondBrainTraceDebug } = data; const { value, model, internet, files, agentFile, negativePrompt, designerGuard, secondBrainTrace, secondBrainTraceDebug, brainProfileId } = data;
this._currentNegativePrompt = negativePrompt || ''; this._currentNegativePrompt = negativePrompt || '';
this._currentSessionBrainId = getActiveBrainProfile().id; const selectedBrainId = typeof brainProfileId === 'string' && brainProfileId && brainProfileId !== 'new'
? brainProfileId
: getActiveBrainProfile().id;
this._currentSessionBrainId = selectedBrainId;
let agentSkillContext = undefined; let agentSkillContext = undefined;
if (agentFile && fs.existsSync(agentFile)) { if (agentFile && fs.existsSync(agentFile)) {
@@ -1668,7 +1671,8 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
negativePrompt, negativePrompt,
designerContext, designerContext,
secondBrainTraceEnabled: secondBrainTrace !== false, secondBrainTraceEnabled: secondBrainTrace !== false,
secondBrainTraceDebug: !!secondBrainTraceDebug secondBrainTraceDebug: !!secondBrainTraceDebug,
brainProfileId: selectedBrainId
}); });
} catch (error: any) { } catch (error: any) {
logError('Prompt handling failed in sidebar provider.', { error: error?.message || String(error), promptPreview: summarizeText(value || '', 200) }); logError('Prompt handling failed in sidebar provider.', { error: error?.message || String(error), promptPreview: summarizeText(value || '', 200) });
@@ -3039,6 +3043,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
internet: internetEnabled, internet: internetEnabled,
files: pendingFiles.length > 0 ? pendingFiles : undefined, files: pendingFiles.length > 0 ? pendingFiles : undefined,
agentFile: agentSel.value === 'none' ? undefined : agentSel.value, agentFile: agentSel.value === 'none' ? undefined : agentSel.value,
brainProfileId: brainSel.value && brainSel.value !== 'new' ? brainSel.value : undefined,
negativePrompt: negativePrompt.value.trim() || undefined, negativePrompt: negativePrompt.value.trim() || undefined,
designerGuard: designerGuardEnabled, designerGuard: designerGuardEnabled,
secondBrainTrace: secondBrainTraceEnabled, secondBrainTrace: secondBrainTraceEnabled,