Remove legacy React/Ink TUI and fix TypeScript errors
- Delete old tui/ React/Ink implementation (App.tsx, components/, hooks/, store.ts) - Migrate to tui-solid/ as the sole TUI implementation - Update tui/index.ts to re-export from tui-solid and @/types/tui TypeScript fixes: - Add missing PreCompact to hook event constants - Fix path aliases (@src/ -> @/, @constants/) - Remove unused imports across service files - Add explicit type annotations to callback parameters - Replace Bun.file/write with Node.js fs/promises in mcp/registry - Fix Map.some() -> Array.from().some() in registry - Fix addServer() call signature - Add missing description to brain-mcp schema items - Fix typo in progress-bar import (@interfactes -> @interfaces)
This commit is contained in:
@@ -4,21 +4,20 @@
|
||||
*/
|
||||
|
||||
import { readFile, readdir } from "node:fs/promises";
|
||||
import { join, basename, extname } from "node:path";
|
||||
import { join, extname } from "node:path";
|
||||
import { existsSync } from "node:fs";
|
||||
import { homedir } from "node:os";
|
||||
|
||||
import type {
|
||||
AgentDefinition,
|
||||
AgentFrontmatter,
|
||||
AgentDefinitionFile,
|
||||
AgentRegistry,
|
||||
AgentLoadResult,
|
||||
AgentTier,
|
||||
AgentColor,
|
||||
} from "@src/types/agent-definition";
|
||||
import { DEFAULT_AGENT_DEFINITION, AGENT_DEFINITION_SCHEMA } from "@src/types/agent-definition";
|
||||
import { AGENT_DEFINITION, AGENT_DEFINITION_PATHS, AGENT_MESSAGES } from "@src/constants/agent-definition";
|
||||
} from "@/types/agent-definition";
|
||||
import { DEFAULT_AGENT_DEFINITION, AGENT_DEFINITION_SCHEMA } from "@/types/agent-definition";
|
||||
import { AGENT_DEFINITION, AGENT_DEFINITION_PATHS, AGENT_MESSAGES } from "@constants/agent-definition";
|
||||
|
||||
const parseFrontmatter = (content: string): { frontmatter: Record<string, unknown>; body: string } | null => {
|
||||
const delimiter = AGENT_DEFINITION.FRONTMATTER_DELIMITER;
|
||||
@@ -207,12 +206,12 @@ export const loadAllAgentDefinitions = async (
|
||||
agents.set(agent.name, agent);
|
||||
|
||||
// Index by trigger phrases
|
||||
agent.triggerPhrases?.forEach((phrase) => {
|
||||
agent.triggerPhrases?.forEach((phrase: string) => {
|
||||
byTrigger.set(phrase.toLowerCase(), agent.name);
|
||||
});
|
||||
|
||||
// Index by capabilities
|
||||
agent.capabilities?.forEach((capability) => {
|
||||
agent.capabilities?.forEach((capability: string) => {
|
||||
const existing = byCapability.get(capability) || [];
|
||||
byCapability.set(capability, [...existing, agent.name]);
|
||||
});
|
||||
@@ -245,8 +244,8 @@ export const findAgentsByCapability = (
|
||||
): ReadonlyArray<AgentDefinition> => {
|
||||
const agentNames = registry.byCapability.get(capability) || [];
|
||||
return agentNames
|
||||
.map((name) => registry.agents.get(name))
|
||||
.filter((a): a is AgentDefinition => a !== undefined);
|
||||
.map((name: string) => registry.agents.get(name))
|
||||
.filter((a: AgentDefinition | undefined): a is AgentDefinition => a !== undefined);
|
||||
};
|
||||
|
||||
export const getAgentByName = (
|
||||
@@ -273,12 +272,12 @@ export const createAgentDefinitionContent = (agent: AgentDefinition): string =>
|
||||
|
||||
if (agent.triggerPhrases && agent.triggerPhrases.length > 0) {
|
||||
frontmatter.push("triggerPhrases:");
|
||||
agent.triggerPhrases.forEach((phrase) => frontmatter.push(` - ${phrase}`));
|
||||
agent.triggerPhrases.forEach((phrase: string) => frontmatter.push(` - ${phrase}`));
|
||||
}
|
||||
|
||||
if (agent.capabilities && agent.capabilities.length > 0) {
|
||||
frontmatter.push("capabilities:");
|
||||
agent.capabilities.forEach((cap) => frontmatter.push(` - ${cap}`));
|
||||
agent.capabilities.forEach((cap: string) => frontmatter.push(` - ${cap}`));
|
||||
}
|
||||
|
||||
frontmatter.push("---");
|
||||
|
||||
@@ -19,16 +19,13 @@ import type {
|
||||
TaskError,
|
||||
TaskMetadata,
|
||||
TaskNotification,
|
||||
TaskStep,
|
||||
TaskArtifact,
|
||||
} from "@src/types/background-task";
|
||||
import { DEFAULT_BACKGROUND_TASK_CONFIG, BACKGROUND_TASK_PRIORITIES } from "@src/types/background-task";
|
||||
} from "@/types/background-task";
|
||||
import { DEFAULT_BACKGROUND_TASK_CONFIG, BACKGROUND_TASK_PRIORITIES } from "@/types/background-task";
|
||||
import {
|
||||
BACKGROUND_TASK,
|
||||
BACKGROUND_TASK_STORAGE,
|
||||
BACKGROUND_TASK_MESSAGES,
|
||||
BACKGROUND_TASK_STATUS_ICONS,
|
||||
} from "@src/constants/background-task";
|
||||
} from "@constants/background-task";
|
||||
|
||||
type TaskHandler = (task: BackgroundTask, updateProgress: (progress: Partial<TaskProgress>) => void) => Promise<TaskResult>;
|
||||
type NotificationHandler = (notification: TaskNotification) => void;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*/
|
||||
|
||||
import { createServer, type Server, type IncomingMessage, type ServerResponse } from "node:http";
|
||||
import { randomUUID } from "node:crypto";
|
||||
|
||||
import type {
|
||||
BrainMcpServerConfig,
|
||||
@@ -14,18 +13,17 @@ import type {
|
||||
BrainMcpToolName,
|
||||
McpContent,
|
||||
McpError,
|
||||
} from "@src/types/brain-mcp";
|
||||
BrainMcpTool,
|
||||
} from "@/types/brain-mcp";
|
||||
import {
|
||||
DEFAULT_BRAIN_MCP_SERVER_CONFIG,
|
||||
BRAIN_MCP_TOOLS,
|
||||
MCP_ERROR_CODES,
|
||||
} from "@src/types/brain-mcp";
|
||||
} from "@/types/brain-mcp";
|
||||
import {
|
||||
BRAIN_MCP_SERVER,
|
||||
BRAIN_MCP_MESSAGES,
|
||||
BRAIN_MCP_ERRORS,
|
||||
BRAIN_MCP_AUTH,
|
||||
} from "@src/constants/brain-mcp";
|
||||
} from "@constants/brain-mcp";
|
||||
|
||||
type BrainService = {
|
||||
recall: (query: string, limit?: number) => Promise<unknown>;
|
||||
@@ -135,7 +133,7 @@ const handleToolCall = async (
|
||||
throw createMcpError(MCP_ERROR_CODES.BRAIN_UNAVAILABLE, "Brain service not connected");
|
||||
}
|
||||
|
||||
const tool = BRAIN_MCP_TOOLS.find((t) => t.name === toolName);
|
||||
const tool = BRAIN_MCP_TOOLS.find((t: BrainMcpTool) => t.name === toolName);
|
||||
if (!tool) {
|
||||
throw createMcpError(MCP_ERROR_CODES.TOOL_NOT_FOUND, `Tool not found: ${toolName}`);
|
||||
}
|
||||
@@ -167,7 +165,7 @@ const handleToolCall = async (
|
||||
brain_stats: () => state.brainService!.getStats(),
|
||||
brain_projects: async () => {
|
||||
// Import dynamically to avoid circular dependency
|
||||
const { listProjects } = await import("@src/services/brain/project-service");
|
||||
const { listProjects } = await import("@services/brain/project-service");
|
||||
return listProjects();
|
||||
},
|
||||
};
|
||||
@@ -254,7 +252,7 @@ const handleRequest = async (
|
||||
res.writeHead(200, { "Content-Type": "application/json" });
|
||||
res.end(JSON.stringify(createMcpResponse(mcpRequest.id, content)));
|
||||
} else if (mcpRequest.method === "tools/list") {
|
||||
const tools = BRAIN_MCP_TOOLS.map((tool) => ({
|
||||
const tools = BRAIN_MCP_TOOLS.map((tool: BrainMcpTool) => ({
|
||||
name: tool.name,
|
||||
description: tool.description,
|
||||
inputSchema: tool.inputSchema,
|
||||
@@ -351,4 +349,4 @@ export const updateConfig = (config: Partial<BrainMcpServerConfig>): void => {
|
||||
};
|
||||
|
||||
export const getAvailableTools = (): ReadonlyArray<{ name: string; description: string }> =>
|
||||
BRAIN_MCP_TOOLS.map((t) => ({ name: t.name, description: t.description }));
|
||||
BRAIN_MCP_TOOLS.map((t: BrainMcpTool) => ({ name: t.name, description: t.description }));
|
||||
|
||||
@@ -18,21 +18,16 @@ import type {
|
||||
BrainProjectListResult,
|
||||
BrainProjectExport,
|
||||
BrainProjectImportResult,
|
||||
ExportedConcept,
|
||||
ExportedMemory,
|
||||
ExportedRelationship,
|
||||
} from "@src/types/brain-project";
|
||||
} from "@/types/brain-project";
|
||||
import {
|
||||
DEFAULT_BRAIN_PROJECT_SETTINGS,
|
||||
BRAIN_PROJECT_EXPORT_VERSION,
|
||||
} from "@src/types/brain-project";
|
||||
} from "@/types/brain-project";
|
||||
import {
|
||||
BRAIN_PROJECT,
|
||||
BRAIN_PROJECT_STORAGE,
|
||||
BRAIN_PROJECT_PATHS,
|
||||
BRAIN_PROJECT_MESSAGES,
|
||||
BRAIN_PROJECT_API,
|
||||
} from "@src/constants/brain-project";
|
||||
} from "@constants/brain-project";
|
||||
|
||||
interface ProjectServiceState {
|
||||
projects: Map<number, BrainProject>;
|
||||
|
||||
@@ -11,12 +11,12 @@ import type {
|
||||
FilteredResult,
|
||||
ValidationResult,
|
||||
ConfidenceFilterStats,
|
||||
} from "@src/types/confidence-filter";
|
||||
} from "@/types/confidence-filter";
|
||||
import {
|
||||
CONFIDENCE_LEVELS,
|
||||
DEFAULT_CONFIDENCE_FILTER_CONFIG,
|
||||
} from "@src/types/confidence-filter";
|
||||
import { CONFIDENCE_FILTER, CONFIDENCE_WEIGHTS } from "@src/constants/confidence-filter";
|
||||
} from "@/types/confidence-filter";
|
||||
import { CONFIDENCE_FILTER, CONFIDENCE_WEIGHTS } from "@constants/confidence-filter";
|
||||
|
||||
export const calculateConfidenceLevel = (score: number): ConfidenceLevel => {
|
||||
const levels = Object.entries(CONFIDENCE_LEVELS) as Array<[ConfidenceLevel, { min: number; max: number }]>;
|
||||
@@ -158,7 +158,7 @@ export const formatConfidenceScore = (confidence: ConfidenceScore, showFactors:
|
||||
|
||||
if (showFactors && confidence.factors.length > 0) {
|
||||
const factorLines = confidence.factors
|
||||
.map((f) => ` - ${f.name}: ${f.score}% (weight: ${f.weight})`)
|
||||
.map((f: ConfidenceFactor) => ` - ${f.name}: ${f.score}% (weight: ${f.weight})`)
|
||||
.join("\n");
|
||||
result += `\n${factorLines}`;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import {
|
||||
MCP_REGISTRY_CACHE,
|
||||
MCP_REGISTRY_SOURCES,
|
||||
MCP_REGISTRY_ERRORS,
|
||||
MCP_REGISTRY_SUCCESS,
|
||||
MCP_SEARCH_DEFAULTS,
|
||||
} from "@constants/mcp-registry";
|
||||
import { addServer, connectServer, getServerInstances } from "./manager";
|
||||
@@ -42,11 +41,9 @@ const getCacheFilePath = (): string => {
|
||||
const loadCache = async (): Promise<MCPRegistryCache | null> => {
|
||||
try {
|
||||
const cachePath = getCacheFilePath();
|
||||
const file = Bun.file(cachePath);
|
||||
if (await file.exists()) {
|
||||
const data = await file.json();
|
||||
return data as MCPRegistryCache;
|
||||
}
|
||||
const fs = await import("fs/promises");
|
||||
const content = await fs.readFile(cachePath, "utf-8");
|
||||
return JSON.parse(content) as MCPRegistryCache;
|
||||
} catch {
|
||||
// Cache doesn't exist or is invalid
|
||||
}
|
||||
@@ -59,7 +56,10 @@ const loadCache = async (): Promise<MCPRegistryCache | null> => {
|
||||
const saveCache = async (cache: MCPRegistryCache): Promise<void> => {
|
||||
try {
|
||||
const cachePath = getCacheFilePath();
|
||||
await Bun.write(cachePath, JSON.stringify(cache, null, 2));
|
||||
const fs = await import("fs/promises");
|
||||
const path = await import("path");
|
||||
await fs.mkdir(path.dirname(cachePath), { recursive: true });
|
||||
await fs.writeFile(cachePath, JSON.stringify(cache, null, 2));
|
||||
} catch {
|
||||
// Ignore cache write errors
|
||||
}
|
||||
@@ -300,7 +300,7 @@ export const getServersByCategory = async (
|
||||
*/
|
||||
export const isServerInstalled = (serverId: string): boolean => {
|
||||
const instances = getServerInstances();
|
||||
return instances.some((instance) =>
|
||||
return Array.from(instances.values()).some((instance) =>
|
||||
instance.config.name === serverId ||
|
||||
instance.config.name.toLowerCase() === serverId.toLowerCase()
|
||||
);
|
||||
@@ -332,8 +332,8 @@ export const installServer = async (
|
||||
try {
|
||||
// Add server to configuration
|
||||
await addServer(
|
||||
server.id,
|
||||
{
|
||||
name: server.id,
|
||||
command: server.command,
|
||||
args: customArgs || server.args,
|
||||
transport: server.transport,
|
||||
@@ -447,10 +447,8 @@ export const clearRegistryCache = async (): Promise<void> => {
|
||||
registryCache = null;
|
||||
try {
|
||||
const cachePath = getCacheFilePath();
|
||||
const file = Bun.file(cachePath);
|
||||
if (await file.exists()) {
|
||||
await Bun.write(cachePath, "");
|
||||
}
|
||||
const fs = await import("fs/promises");
|
||||
await fs.unlink(cachePath);
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import {
|
||||
compactConversation,
|
||||
checkCompactionNeeded,
|
||||
getModelCompactionConfig,
|
||||
createCompactionSummary,
|
||||
} from "@services/auto-compaction";
|
||||
import { appStore } from "@tui-solid/context/app";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user