Update Astra: v2.80.19 - Refactoring Sidebar, LM Studio integration, and new tests

This commit is contained in:
g1nation
2026-05-08 23:14:47 +09:00
parent d083177d95
commit 5ffb472d22
28 changed files with 3125 additions and 1797 deletions
+32
View File
@@ -0,0 +1,32 @@
import { SidebarChatProvider } from '../sidebarProvider';
import { logInfo } from '../utils';
/**
* Handles agent-skill messages: the per-conversation agent picker, agent CRUD,
* and persisting the user's last selected agent.
*/
export async function handleAgentMessage(provider: SidebarChatProvider, data: any): Promise<boolean> {
switch (data.type) {
case 'getAgents':
await provider._sendAgentsList();
return true;
case 'createAgent':
await provider._createAgent();
return true;
case 'getAgentContent':
await provider._sendAgentContent(data.path);
return true;
case 'updateAgent':
await provider._updateAgent(data.path, data.content, data.negativePrompt);
return true;
case 'deleteAgent':
await provider._deleteAgent(data.path);
return true;
case 'saveAgentSelection':
await provider._context.globalState.update(SidebarChatProvider.lastAgentStateKey, data.path || 'none');
logInfo(`Agent selection saved: ${data.path}`);
return true;
default:
return false;
}
}
+33
View File
@@ -0,0 +1,33 @@
import { SidebarChatProvider } from '../sidebarProvider';
/**
* Handles brain-profile / wiki sync messages from the sidebar webview.
*/
export async function handleBrainMessage(provider: SidebarChatProvider, data: any): Promise<boolean> {
switch (data.type) {
case 'manageBrains':
await provider._manageBrains();
return true;
case 'syncBrain':
await provider.syncBrain();
await provider._sendBrainStatus();
return true;
case 'addBrain':
await provider._addBrainProfile();
return true;
case 'editBrain':
await provider._editBrainProfile(data.id);
return true;
case 'deleteBrain':
await provider._deleteBrainProfile(data.id);
return true;
case 'saveWikiRaw':
await provider._saveWikiRaw();
return true;
case 'setBrainProfile':
await provider._setActiveBrainProfile(data.id);
return true;
default:
return false;
}
}
+99
View File
@@ -0,0 +1,99 @@
import * as vscode from 'vscode';
import * as path from 'path';
import { SidebarChatProvider } from '../sidebarProvider';
import { getActiveBrainProfile, logInfo } from '../utils';
/**
* Handles chat-domain messages: prompts, model selection, sessions, streaming control,
* generic webview transport (export, settings, addMessage), action approvals, and the
* cross-cutting `ready` bootstrap.
*
* Returns true when the message was handled by this domain, false otherwise — the
* caller chains domain handlers until one accepts the message.
*/
export async function handleChatMessage(provider: SidebarChatProvider, data: any): Promise<boolean> {
switch (data.type) {
case 'prompt':
case 'promptWithFile':
provider._lmStudio?.activity.bump();
await provider._context.globalState.update(SidebarChatProvider.blankChatStateKey, false);
await provider._handlePrompt(data);
await provider._autoWriteChronicleAfterPrompt();
await provider._saveCurrentSession();
return true;
case 'activity':
provider._lmStudio?.activity.bump();
return true;
case 'ready':
await provider._sendBrainStatus();
await provider._sendBrainProfiles();
await provider._sendSessionList();
await provider._sendModels();
await provider._sendChronicleProjects();
await provider._restoreActiveSessionIntoView();
return true;
case 'getModels':
await provider._sendModels();
return true;
case 'getSessions':
await provider._sendSessionList();
return true;
case 'newChat':
provider._currentSessionId = null;
provider._currentSessionBrainId = getActiveBrainProfile().id;
provider._agent.resetConversation();
await provider._context.globalState.update(SidebarChatProvider.activeSessionStateKey, null);
await provider._context.globalState.update(SidebarChatProvider.lastVisibleChatStateKey, null);
await provider._context.globalState.update(SidebarChatProvider.blankChatStateKey, true);
provider.clearChat();
await provider._sendBrainStatus();
return true;
case 'stopGeneration':
provider._agent.stop();
return true;
case 'loadSession':
await provider._loadSession(data.id);
return true;
case 'deleteSession':
await provider._deleteSession(data.id);
return true;
case 'openSettings':
vscode.commands.executeCommand('workbench.action.openSettings', 'g1nation');
return true;
case 'addMessage':
provider._view?.webview.postMessage({ type: 'addMessage', role: data.role, value: data.value, rationale: data.rationale });
return true;
case 'refreshModels':
await provider._sendModels(true);
return true;
case 'model':
await vscode.workspace.getConfiguration('g1nation').update('defaultModel', data.value, vscode.ConfigurationTarget.Global);
logInfo(`Default model updated to: ${data.value}`);
provider._lmStudio?.lifecycle.onModelSelected(data.value);
return true;
case 'proactiveTrigger':
await provider._handleProactiveSuggestion(data.context);
return true;
case 'exportResponse': {
const workspacePath = vscode.workspace.workspaceFolders?.[0].uri.fsPath || '';
const defaultPath = path.join(workspacePath, 'g1_response.md');
const uri = await vscode.window.showSaveDialog({
defaultUri: vscode.Uri.file(defaultPath),
filters: { 'Markdown': ['md'] }
});
if (uri) {
await vscode.workspace.fs.writeFile(uri, Buffer.from(data.text, 'utf8'));
vscode.window.showInformationMessage(`✅ Exported to ${path.basename(uri.fsPath)}`);
}
return true;
}
case 'approveAction':
await provider._agent.approveTransaction();
return true;
case 'rejectAction':
await provider._agent.rejectTransaction();
return true;
default:
return false;
}
}
+52
View File
@@ -0,0 +1,52 @@
import { SidebarChatProvider } from '../sidebarProvider';
/**
* Handles Project Chronicle messages: project CRUD, record listing/opening,
* and the various chronicle-write entry points (planning, discussion, decision,
* development, bug, retrospective).
*/
export async function handleChronicleMessage(provider: SidebarChatProvider, data: any): Promise<boolean> {
switch (data.type) {
case 'getChronicleProjects':
await provider._sendChronicleProjects();
return true;
case 'createChronicleProject':
await provider._createChronicleProject();
return true;
case 'setChronicleProject':
await provider._setActiveChronicleProject(data.id);
return true;
case 'openChronicleFolder':
await provider._openChronicleFolder();
return true;
case 'getChronicleRecords':
await provider._sendChronicleRecords();
return true;
case 'openChronicleRecord':
await provider._openChronicleRecord(data.path);
return true;
case 'writeChroniclePlanning':
await provider._writeChroniclePlanningFromCurrentChat();
return true;
case 'writeChronicleDiscussion':
await provider._writeChronicleDiscussionFromCurrentChat();
return true;
case 'writeChronicleDecision':
await provider._writeChronicleDecisionFromInput();
return true;
case 'writeChronicleDevelopment':
await provider._writeChronicleDevelopmentFromCurrentChat();
return true;
case 'writeChronicleBug':
await provider._writeChronicleBugFromInput();
return true;
case 'writeChronicleRetrospective':
await provider._writeChronicleRetrospectiveFromInput();
return true;
case 'writeChronicleRecord':
await provider._writeChronicleRecord(data.recordType);
return true;
default:
return false;
}
}