Files
connectai/src/sidebar/agentHandlers.ts
T
2026-05-11 12:44:38 +09:00

150 lines
6.2 KiB
TypeScript

import * as path from 'path';
import * as vscode from 'vscode';
import { SidebarChatProvider } from '../sidebarProvider';
import { logError, logInfo } from '../utils';
import {
resolveScopeForAgent,
openKnowledgeMapEditor,
getOrCreateAgentEntry,
upsertAgentEntry,
} from '../skills/agentKnowledgeMap';
import { getActiveBrainProfile } from '../utils';
/**
* Handles agent-skill messages: the per-conversation agent picker, agent CRUD,
* persisting the user's last selected agent, and the knowledge-map dropdown.
*/
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;
case 'getKnowledgeScope': {
const view = (provider as any)._view as vscode.WebviewView | undefined;
if (!view) return true;
const brain = getActiveBrainProfile();
const brainRoot = brain?.localBrainPath || '';
const scope = resolveScopeForAgent(data.agentPath || '', brainRoot);
const folders = scope.folders.map((abs) => ({
absolute: abs,
relative: brainRoot ? path.relative(brainRoot, abs) || abs : abs,
}));
view.webview.postMessage({
type: 'knowledgeScope',
value: {
agent: scope.agent?.name ?? null,
folders,
source: scope.source,
brainRoot,
},
});
return true;
}
case 'editKnowledgeMap':
await openKnowledgeMapEditor();
return true;
case 'getAgentMap': {
const view = (provider as any)._view as vscode.WebviewView | undefined;
if (!view) return true;
try {
const entry = getOrCreateAgentEntry(data.agentPath || '');
const knowledgeMapHasEntry = entry.knowledgeFolders.length > 0 || (entry.skillFolders?.length ?? 0) > 0;
view.webview.postMessage({
type: 'agentMapData',
value: {
name: entry.name,
knowledgeFolders: entry.knowledgeFolders,
skillFolders: entry.skillFolders || [],
exists: knowledgeMapHasEntry,
},
});
} catch (e: any) {
logError('agent-map: load failed.', { error: e?.message ?? String(e) });
view.webview.postMessage({
type: 'agentMapData',
value: { name: '', knowledgeFolders: [], skillFolders: [], exists: false },
});
}
return true;
}
case 'saveAgentMap': {
const view = (provider as any)._view as vscode.WebviewView | undefined;
if (!view) return true;
const agentPath = typeof data.agentPath === 'string' ? data.agentPath : '';
const name = path.basename(agentPath).replace(/\.(md|markdown)$/i, '').trim();
const knowledgeFolders = Array.isArray(data.knowledgeFolders)
? data.knowledgeFolders.filter((f: unknown) => typeof f === 'string')
: [];
const skillFolders = Array.isArray(data.skillFolders)
? data.skillFolders.filter((f: unknown) => typeof f === 'string')
: [];
const result = upsertAgentEntry({
name,
knowledgeFolders,
skillFolders,
});
view.webview.postMessage({
type: 'agentMapSaved',
value: { ok: result.ok, path: result.path, error: result.error },
});
return true;
}
case 'pickPath': {
const view = (provider as any)._view as vscode.WebviewView | undefined;
if (!view) return true;
const kind = data.kind === 'skillFile' ? 'skillFile'
: data.kind === 'skillFolder' ? 'skillFolder'
: 'knowledgeFolder';
const isFile = kind === 'skillFile';
const label = kind === 'knowledgeFolder' ? 'Select Knowledge Folder'
: kind === 'skillFolder' ? 'Select Skill Folder'
: 'Select Skill File (.md)';
const defaultUri = (() => {
if (kind === 'knowledgeFolder') {
const brain = getActiveBrainProfile();
if (brain?.localBrainPath) return vscode.Uri.file(brain.localBrainPath);
}
return undefined;
})();
try {
const picked = await vscode.window.showOpenDialog({
canSelectFiles: isFile,
canSelectFolders: !isFile,
canSelectMany: false,
openLabel: label,
defaultUri,
filters: isFile ? { Markdown: ['md', 'markdown'] } : undefined,
});
const fsPath = picked?.[0]?.fsPath || '';
if (fsPath) {
view.webview.postMessage({
type: 'pickedPath',
value: { kind, path: fsPath },
});
}
} catch (e: any) {
logError('agent-map: pick failed.', { kind, error: e?.message ?? String(e) });
}
return true;
}
default:
return false;
}
}