release: v2.33.2 - Final polish and build
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@
|
||||
"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.33.1",
|
||||
"version": "2.33.2",
|
||||
"publisher": "connectailab",
|
||||
"license": "MIT",
|
||||
"icon": "assets/icon.png",
|
||||
|
||||
+182
-20
@@ -141,6 +141,12 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
case 'addBrain':
|
||||
await this._addBrainProfile();
|
||||
break;
|
||||
case 'editBrain':
|
||||
await this._editBrainProfile(data.id);
|
||||
break;
|
||||
case 'deleteBrain':
|
||||
await this._deleteBrainProfile(data.id);
|
||||
break;
|
||||
case 'setBrainProfile':
|
||||
await this._setActiveBrainProfile(data.id);
|
||||
break;
|
||||
@@ -150,6 +156,9 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
case 'updateAgent':
|
||||
await this._updateAgent(data.path, data.content, data.negativePrompt);
|
||||
break;
|
||||
case 'deleteAgent':
|
||||
await this._deleteAgent(data.path);
|
||||
break;
|
||||
case 'refreshModels':
|
||||
await this._sendModels();
|
||||
break;
|
||||
@@ -449,6 +458,23 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
});
|
||||
}
|
||||
|
||||
private _postBrainProfiles(profiles: any[], activeBrainId: string) {
|
||||
if (!this._view) return;
|
||||
this._view.webview.postMessage({
|
||||
type: 'brainProfiles',
|
||||
value: {
|
||||
activeBrainId,
|
||||
profiles: profiles.map((p: any) => ({
|
||||
id: p.id || '',
|
||||
name: p.name || '',
|
||||
path: p.localBrainPath || '',
|
||||
description: p.description || '',
|
||||
repo: p.secondBrainRepo || ''
|
||||
}))
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async _setActiveBrainProfile(profileId: string, silent: boolean = false) {
|
||||
const profiles = getBrainProfiles();
|
||||
const nextProfile = profiles.find((profile) => profile.id === profileId) || profiles[0];
|
||||
@@ -555,28 +581,90 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
await cfg.update('activeBrainId', id, vscode.ConfigurationTarget.Global);
|
||||
this._currentSessionBrainId = id;
|
||||
|
||||
// Directly post the freshly-built profile list to the webview.
|
||||
// cfg.update() is async and VSCode's config cache may not reflect the new value
|
||||
// immediately, so we avoid re-reading via getBrainProfiles() here.
|
||||
if (this._view) {
|
||||
this._view.webview.postMessage({
|
||||
type: 'brainProfiles',
|
||||
value: {
|
||||
activeBrainId: id,
|
||||
profiles: nextProfiles.map((p: any) => ({
|
||||
id: p.id || '',
|
||||
name: p.name || '',
|
||||
path: p.localBrainPath || '',
|
||||
description: p.description || '',
|
||||
repo: p.secondBrainRepo || ''
|
||||
}))
|
||||
}
|
||||
});
|
||||
}
|
||||
// immediately, so we post the freshly-built profile list directly.
|
||||
this._postBrainProfiles(nextProfiles, id);
|
||||
await this._sendBrainStatus();
|
||||
this.injectSystemMessage(`**[Brain Added]** ${name.trim()}\n\`${folder}\``);
|
||||
}
|
||||
|
||||
private async _editBrainProfile(profileId?: string) {
|
||||
const currentProfiles = getBrainProfiles();
|
||||
const target = currentProfiles.find((profile) => profile.id === profileId) || getActiveBrainProfile();
|
||||
if (!target) return;
|
||||
|
||||
const name = await vscode.window.showInputBox({
|
||||
prompt: 'Edit brain profile name',
|
||||
value: target.name,
|
||||
validateInput: (value) => value.trim() ? null : 'Brain name is required.'
|
||||
});
|
||||
if (!name) return;
|
||||
|
||||
const folder = await vscode.window.showInputBox({
|
||||
prompt: 'Edit local brain folder path',
|
||||
value: target.localBrainPath,
|
||||
validateInput: (value) => value.trim() ? null : 'Brain folder path is required.'
|
||||
});
|
||||
if (!folder) return;
|
||||
|
||||
const description = await vscode.window.showInputBox({
|
||||
prompt: 'Edit optional description shown in the G1nation sidebar',
|
||||
value: target.description || ''
|
||||
});
|
||||
|
||||
const repo = await vscode.window.showInputBox({
|
||||
prompt: 'Edit optional Second Brain Git repository URL',
|
||||
value: target.secondBrainRepo || ''
|
||||
});
|
||||
|
||||
const nextProfiles = currentProfiles.map((profile) => profile.id === target.id
|
||||
? {
|
||||
...profile,
|
||||
name: name.trim(),
|
||||
localBrainPath: folder.trim(),
|
||||
secondBrainRepo: (repo || '').trim(),
|
||||
description: (description || '').trim()
|
||||
}
|
||||
: profile
|
||||
);
|
||||
|
||||
const cfg = vscode.workspace.getConfiguration('g1nation');
|
||||
await cfg.update('brainProfiles', nextProfiles, vscode.ConfigurationTarget.Global);
|
||||
await cfg.update('activeBrainId', target.id, vscode.ConfigurationTarget.Global);
|
||||
this._currentSessionBrainId = target.id;
|
||||
this._postBrainProfiles(nextProfiles, target.id);
|
||||
await this._sendBrainStatus();
|
||||
this.injectSystemMessage(`**[Brain Updated]** ${name.trim()}\n\`${folder.trim()}\``);
|
||||
}
|
||||
|
||||
private async _deleteBrainProfile(profileId?: string) {
|
||||
const currentProfiles = getBrainProfiles();
|
||||
const target = currentProfiles.find((profile) => profile.id === profileId) || getActiveBrainProfile();
|
||||
if (!target) return;
|
||||
|
||||
if (currentProfiles.length <= 1) {
|
||||
vscode.window.showWarningMessage('At least one brain profile is required.');
|
||||
return;
|
||||
}
|
||||
|
||||
const confirm = await vscode.window.showWarningMessage(
|
||||
`Delete brain profile "${target.name}"? The folder itself will not be deleted.`,
|
||||
{ modal: true },
|
||||
'Delete Profile'
|
||||
);
|
||||
if (confirm !== 'Delete Profile') return;
|
||||
|
||||
const nextProfiles = currentProfiles.filter((profile) => profile.id !== target.id);
|
||||
const nextActive = nextProfiles[0];
|
||||
const cfg = vscode.workspace.getConfiguration('g1nation');
|
||||
await cfg.update('brainProfiles', nextProfiles, vscode.ConfigurationTarget.Global);
|
||||
await cfg.update('activeBrainId', nextActive.id, vscode.ConfigurationTarget.Global);
|
||||
this._currentSessionBrainId = nextActive.id;
|
||||
this._postBrainProfiles(nextProfiles, nextActive.id);
|
||||
await this._sendBrainStatus();
|
||||
this.injectSystemMessage(`**[Brain Deleted]** ${target.name}`);
|
||||
}
|
||||
|
||||
// --- BridgeInterface Methods ---
|
||||
|
||||
public injectSystemMessage(msg: string): void {
|
||||
@@ -741,6 +829,40 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
}
|
||||
}
|
||||
|
||||
private async _deleteAgent(agentPath: string) {
|
||||
if (!agentPath || agentPath === 'none') return;
|
||||
|
||||
try {
|
||||
const agentsDir = path.resolve(this._getAgentsDir());
|
||||
const targetPath = path.resolve(agentPath);
|
||||
if (!targetPath.startsWith(`${agentsDir}${path.sep}`) || path.extname(targetPath) !== '.md') {
|
||||
vscode.window.showErrorMessage('Selected agent skill path is not valid.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fs.existsSync(targetPath)) {
|
||||
await this._context.globalState.update(SidebarChatProvider.lastAgentStateKey, 'none');
|
||||
await this._sendAgentsList();
|
||||
return;
|
||||
}
|
||||
|
||||
const confirm = await vscode.window.showWarningMessage(
|
||||
`Delete agent skill "${path.basename(targetPath, '.md')}"?`,
|
||||
{ modal: true },
|
||||
'Delete Skill'
|
||||
);
|
||||
if (confirm !== 'Delete Skill') return;
|
||||
|
||||
fs.unlinkSync(targetPath);
|
||||
await this._context.globalState.update(SidebarChatProvider.lastAgentStateKey, 'none');
|
||||
await this._sendAgentsList();
|
||||
this._view?.webview.postMessage({ type: 'agentDeleted' });
|
||||
vscode.window.showInformationMessage('Agent skill deleted successfully.');
|
||||
} catch (err: any) {
|
||||
vscode.window.showErrorMessage(`Failed to delete agent: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async _handlePrompt(data: any) {
|
||||
if (!this._view) return;
|
||||
|
||||
@@ -942,6 +1064,7 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
|
||||
.header-actions,
|
||||
.tool-strip,
|
||||
.tool-group,
|
||||
.select-stack,
|
||||
.select-line,
|
||||
.status-pill {
|
||||
@@ -951,6 +1074,13 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
|
||||
.header-actions { gap: 6px; flex-shrink: 0; }
|
||||
.tool-strip { gap: 6px; flex-wrap: wrap; }
|
||||
.tool-group {
|
||||
gap: 4px;
|
||||
padding: 3px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
}
|
||||
.select-stack { flex-direction: column; gap: 6px; min-width: 0; }
|
||||
.select-line { gap: 6px; width: 100%; min-width: 0; }
|
||||
|
||||
@@ -1465,11 +1595,19 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
</div>
|
||||
</div>
|
||||
<div class="tool-strip">
|
||||
<button class="icon-btn" id="editAgentBtn" data-tooltip="Edit Agent Skill">✎</button>
|
||||
<button class="icon-btn" id="addAgentBtn" data-tooltip="Create Agent">+</button>
|
||||
<div class="tool-group" aria-label="Brain actions">
|
||||
<button class="icon-btn" id="addBrainBtn" data-tooltip="Add Brain">+</button>
|
||||
<button class="icon-btn" id="editBrainBtn" data-tooltip="Edit Brain">✎</button>
|
||||
<button class="icon-btn" id="deleteBrainBtn" data-tooltip="Delete Brain">−</button>
|
||||
<button class="icon-btn" id="brainBtn" data-tooltip="Sync Knowledge">↻</button>
|
||||
</div>
|
||||
<div class="tool-group" aria-label="Agent actions">
|
||||
<button class="icon-btn" id="addAgentBtn" data-tooltip="Create Agent">+</button>
|
||||
<button class="icon-btn" id="editAgentBtn" data-tooltip="Edit Agent Skill">✎</button>
|
||||
<button class="icon-btn" id="deleteAgentBtn" data-tooltip="Delete Agent Skill">−</button>
|
||||
</div>
|
||||
<button class="icon-btn" id="multiAgentBtn" data-tooltip="Multi-Agent Mode">⧉</button>
|
||||
<button class="icon-btn" id="internetBtn" data-tooltip="Internet Access">↗</button>
|
||||
<button class="icon-btn" id="brainBtn" data-tooltip="Sync Knowledge">↻</button>
|
||||
<button class="icon-btn" id="historyBtn" data-tooltip="View History">◷</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1653,6 +1791,10 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
const agentSel = document.getElementById('agentSel');
|
||||
const editAgentBtn = document.getElementById('editAgentBtn');
|
||||
const addAgentBtn = document.getElementById('addAgentBtn');
|
||||
const deleteAgentBtn = document.getElementById('deleteAgentBtn');
|
||||
const addBrainBtn = document.getElementById('addBrainBtn');
|
||||
const editBrainBtn = document.getElementById('editBrainBtn');
|
||||
const deleteBrainBtn = document.getElementById('deleteBrainBtn');
|
||||
const agentConfigPanel = document.getElementById('agentConfigPanel');
|
||||
const agentPrompt = document.getElementById('agentPrompt');
|
||||
const negativePrompt = document.getElementById('negativePrompt');
|
||||
@@ -1865,6 +2007,13 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
agentPrompt.value = msg.value;
|
||||
negativePrompt.value = msg.negativePrompt || '';
|
||||
break;
|
||||
case 'agentDeleted':
|
||||
agentConfigPanel.style.display = 'none';
|
||||
editMode = false;
|
||||
editAgentBtn.classList.remove('active');
|
||||
agentPrompt.value = '';
|
||||
negativePrompt.value = '';
|
||||
break;
|
||||
case 'error':
|
||||
thinkingBar.classList.remove('active'); sendBtn.disabled = false;
|
||||
addMsg(msg.value, 'error');
|
||||
@@ -2018,6 +2167,15 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
|
||||
const syncBrain = () => { Sound.play(550, 'sine', 0.1); vscode.postMessage({ type: 'syncBrain' }); };
|
||||
document.getElementById('brainBtn').onclick = syncBrain;
|
||||
addBrainBtn.onclick = () => vscode.postMessage({ type: 'addBrain' });
|
||||
editBrainBtn.onclick = () => {
|
||||
if (!brainSel.value || brainSel.value === 'new') return;
|
||||
vscode.postMessage({ type: 'editBrain', id: brainSel.value });
|
||||
};
|
||||
deleteBrainBtn.onclick = () => {
|
||||
if (!brainSel.value || brainSel.value === 'new') return;
|
||||
vscode.postMessage({ type: 'deleteBrain', id: brainSel.value });
|
||||
};
|
||||
document.getElementById('inputSyncBtn').onclick = syncBrain;
|
||||
document.getElementById('historyBtn').onclick = () => vscode.postMessage({ type: 'getSessions' });
|
||||
document.getElementById('historyBtn').addEventListener('click', () => historyOverlay.classList.add('visible'));
|
||||
@@ -2092,6 +2250,10 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
};
|
||||
|
||||
addAgentBtn.onclick = () => vscode.postMessage({ type: 'createAgent' });
|
||||
deleteAgentBtn.onclick = () => {
|
||||
if (agentSel.value === 'none') return;
|
||||
vscode.postMessage({ type: 'deleteAgent', path: agentSel.value });
|
||||
};
|
||||
|
||||
vscode.postMessage({ type: 'getModels' });
|
||||
vscode.postMessage({ type: 'getAgents' });
|
||||
|
||||
Reference in New Issue
Block a user