fixing imports
This commit is contained in:
@@ -11,23 +11,20 @@ import { batch } from "solid-js";
|
||||
import { getFiles } from "@services/file-picker/files";
|
||||
import { abortCurrentOperation } from "@services/chat-tui-service";
|
||||
import versionData from "@/version.json";
|
||||
import { ExitProvider, useExit } from "@tui-solid/context/exit";
|
||||
import { RouteProvider, useRoute } from "@tui-solid/context/route";
|
||||
import {
|
||||
ExitProvider,
|
||||
useExit,
|
||||
RouteProvider,
|
||||
useRoute,
|
||||
AppStoreProvider,
|
||||
useAppStore,
|
||||
setAppStoreRef,
|
||||
ThemeProvider,
|
||||
useTheme,
|
||||
KeybindProvider,
|
||||
DialogProvider,
|
||||
} from "@tui-solid/context";
|
||||
} from "@tui-solid/context/app";
|
||||
import { ThemeProvider, useTheme } from "@tui-solid/context/theme";
|
||||
import { KeybindProvider } from "@tui-solid/context/keybind";
|
||||
import { DialogProvider } from "@tui-solid/context/dialog";
|
||||
import { ToastProvider, Toast, useToast } from "@tui-solid/ui/toast";
|
||||
import { Home } from "@tui-solid/routes/home";
|
||||
import { Session } from "@tui-solid/routes/session";
|
||||
import type { TuiInput, TuiOutput } from "@tui-solid/types";
|
||||
import type { TuiInput, TuiOutput } from "@interfaces/index";
|
||||
import type { MCPServerDisplay } from "@/types/tui";
|
||||
import type { PermissionScope, LearningScope } from "@/types/tui";
|
||||
import type { MCPAddFormData } from "@/types/mcp";
|
||||
|
||||
@@ -170,14 +170,19 @@ export function InputArea(props: InputAreaProps) {
|
||||
}
|
||||
|
||||
// Normalize line endings (Windows ConPTY sends CR-only newlines)
|
||||
const normalizedText = event.text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
||||
const normalizedText = event.text
|
||||
.replace(/\r\n/g, "\n")
|
||||
.replace(/\r/g, "\n");
|
||||
const pastedContent = normalizedText.trim();
|
||||
|
||||
if (!pastedContent) return;
|
||||
|
||||
// Check if paste should be summarized
|
||||
const lineCount = (pastedContent.match(/\n/g)?.length ?? 0) + 1;
|
||||
if (lineCount >= MIN_PASTE_LINES || pastedContent.length > MIN_PASTE_CHARS) {
|
||||
if (
|
||||
lineCount >= MIN_PASTE_LINES ||
|
||||
pastedContent.length > MIN_PASTE_CHARS
|
||||
) {
|
||||
event.preventDefault();
|
||||
pasteText(pastedContent, `[Pasted ~${lineCount} lines]`);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ const FIELD_LABELS: Record<FormField, string> = {
|
||||
const FIELD_PLACEHOLDERS: Record<FormField, string> = {
|
||||
name: "e.g., filesystem",
|
||||
command: "e.g., npx",
|
||||
args: "e.g., -y @modelcontextprotocol/server-filesystem \"/path/to/dir\"",
|
||||
args: 'e.g., -y @modelcontextprotocol/server-filesystem "/path/to/dir"',
|
||||
scope: "",
|
||||
};
|
||||
|
||||
@@ -206,21 +206,31 @@ export function MCPAddForm(props: MCPAddFormProps) {
|
||||
<box flexDirection="row" marginBottom={1}>
|
||||
<text
|
||||
fg={isCurrentField ? theme.colors.primary : theme.colors.text}
|
||||
attributes={isCurrentField ? TextAttributes.BOLD : TextAttributes.NONE}
|
||||
attributes={
|
||||
isCurrentField ? TextAttributes.BOLD : TextAttributes.NONE
|
||||
}
|
||||
>
|
||||
{isCurrentField ? "> " : " "}
|
||||
{FIELD_LABELS[field]}:{" "}
|
||||
</text>
|
||||
<text
|
||||
fg={!isGlobal() ? theme.colors.success : theme.colors.textDim}
|
||||
attributes={!isGlobal() && isCurrentField ? TextAttributes.BOLD : TextAttributes.NONE}
|
||||
attributes={
|
||||
!isGlobal() && isCurrentField
|
||||
? TextAttributes.BOLD
|
||||
: TextAttributes.NONE
|
||||
}
|
||||
>
|
||||
[Local]
|
||||
</text>
|
||||
<text fg={theme.colors.textDim}> / </text>
|
||||
<text
|
||||
fg={isGlobal() ? theme.colors.warning : theme.colors.textDim}
|
||||
attributes={isGlobal() && isCurrentField ? TextAttributes.BOLD : TextAttributes.NONE}
|
||||
attributes={
|
||||
isGlobal() && isCurrentField
|
||||
? TextAttributes.BOLD
|
||||
: TextAttributes.NONE
|
||||
}
|
||||
>
|
||||
[Global]
|
||||
</text>
|
||||
@@ -232,7 +242,9 @@ export function MCPAddForm(props: MCPAddFormProps) {
|
||||
<box flexDirection="row" marginBottom={1}>
|
||||
<text
|
||||
fg={isCurrentField ? theme.colors.primary : theme.colors.text}
|
||||
attributes={isCurrentField ? TextAttributes.BOLD : TextAttributes.NONE}
|
||||
attributes={
|
||||
isCurrentField ? TextAttributes.BOLD : TextAttributes.NONE
|
||||
}
|
||||
>
|
||||
{isCurrentField ? "> " : " "}
|
||||
{FIELD_LABELS[field]}:{" "}
|
||||
@@ -287,9 +299,7 @@ export function MCPAddForm(props: MCPAddFormProps) {
|
||||
<text fg={theme.colors.textDim}>
|
||||
Tab/Enter next | Shift+Tab prev | ↑↓ navigate | Esc cancel
|
||||
</text>
|
||||
<text fg={theme.colors.textDim}>
|
||||
Enter on Scope to submit
|
||||
</text>
|
||||
<text fg={theme.colors.textDim}>Enter on Scope to submit</text>
|
||||
</box>
|
||||
</box>
|
||||
);
|
||||
|
||||
@@ -155,7 +155,10 @@ export function Header(props: HeaderProps) {
|
||||
[{MODE_LABELS[app.interactionMode()]}]
|
||||
</text>
|
||||
<Show when={app.currentAgent() !== "default"}>
|
||||
<text fg={theme.colors.secondary} attributes={TextAttributes.BOLD}>
|
||||
<text
|
||||
fg={theme.colors.secondary}
|
||||
attributes={TextAttributes.BOLD}
|
||||
>
|
||||
{" "}
|
||||
@{app.currentAgent()}
|
||||
</text>
|
||||
|
||||
@@ -18,11 +18,14 @@ export function StreamingMessage(props: StreamingMessageProps) {
|
||||
// This ensures proper reactivity with the store
|
||||
const [displayContent, setDisplayContent] = createSignal(props.entry.content);
|
||||
const [isActiveStreaming, setIsActiveStreaming] = createSignal(
|
||||
props.entry.metadata?.isStreaming ?? false
|
||||
props.entry.metadata?.isStreaming ?? false,
|
||||
);
|
||||
|
||||
onMount(() => {
|
||||
addDebugLog("render", `StreamingMessage mounted for entry: ${props.entry.id}`);
|
||||
addDebugLog(
|
||||
"render",
|
||||
`StreamingMessage mounted for entry: ${props.entry.id}`,
|
||||
);
|
||||
});
|
||||
|
||||
// Effect to sync content from store's streamingLog
|
||||
@@ -36,7 +39,10 @@ export function StreamingMessage(props: StreamingMessageProps) {
|
||||
// Check if this entry is the currently streaming log
|
||||
const isCurrentLog = logId === props.entry.id;
|
||||
|
||||
addDebugLog("render", `Effect: logId=${logId}, entryId=${props.entry.id}, isActive=${isActive}, contentLen=${storeContent?.length ?? 0}`);
|
||||
addDebugLog(
|
||||
"render",
|
||||
`Effect: logId=${logId}, entryId=${props.entry.id}, isActive=${isActive}, contentLen=${storeContent?.length ?? 0}`,
|
||||
);
|
||||
|
||||
if (isCurrentLog && isActive) {
|
||||
setDisplayContent(storeContent);
|
||||
|
||||
@@ -146,13 +146,17 @@ export function BrainMenu(props: BrainMenuProps) {
|
||||
// Main menu navigation
|
||||
if (view() === "main") {
|
||||
if (evt.name === "up") {
|
||||
setSelectedIndex((prev) => (prev > 0 ? prev - 1 : menuItems().length - 1));
|
||||
setSelectedIndex((prev) =>
|
||||
prev > 0 ? prev - 1 : menuItems().length - 1,
|
||||
);
|
||||
evt.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (evt.name === "down") {
|
||||
setSelectedIndex((prev) => (prev < menuItems().length - 1 ? prev + 1 : 0));
|
||||
setSelectedIndex((prev) =>
|
||||
prev < menuItems().length - 1 ? prev + 1 : 0,
|
||||
);
|
||||
evt.preventDefault();
|
||||
return;
|
||||
}
|
||||
@@ -267,7 +271,8 @@ export function BrainMenu(props: BrainMenuProps) {
|
||||
<text fg={getStatusColor()}>{getStatusText()}</text>
|
||||
<Show when={isConnected()}>
|
||||
<text fg={theme.colors.textDim}>
|
||||
{" "}({app.brain().knowledgeCount}K / {app.brain().memoryCount}M)
|
||||
{" "}
|
||||
({app.brain().knowledgeCount}K / {app.brain().memoryCount}M)
|
||||
</text>
|
||||
</Show>
|
||||
</box>
|
||||
@@ -299,13 +304,17 @@ export function BrainMenu(props: BrainMenuProps) {
|
||||
<box flexDirection="row">
|
||||
<text
|
||||
fg={isSelected() ? theme.colors.accent : undefined}
|
||||
attributes={isSelected() ? TextAttributes.BOLD : TextAttributes.NONE}
|
||||
attributes={
|
||||
isSelected() ? TextAttributes.BOLD : TextAttributes.NONE
|
||||
}
|
||||
>
|
||||
{isSelected() ? "> " : " "}
|
||||
</text>
|
||||
<text
|
||||
fg={isSelected() ? theme.colors.accent : undefined}
|
||||
attributes={isSelected() ? TextAttributes.BOLD : TextAttributes.NONE}
|
||||
attributes={
|
||||
isSelected() ? TextAttributes.BOLD : TextAttributes.NONE
|
||||
}
|
||||
>
|
||||
{item.label}
|
||||
</text>
|
||||
@@ -320,7 +329,9 @@ export function BrainMenu(props: BrainMenuProps) {
|
||||
</box>
|
||||
|
||||
<box marginTop={1} flexDirection="column">
|
||||
<text fg={theme.colors.info}>{BRAIN_BANNER.CTA}: {BRAIN_BANNER.URL}</text>
|
||||
<text fg={theme.colors.info}>
|
||||
{BRAIN_BANNER.CTA}: {BRAIN_BANNER.URL}
|
||||
</text>
|
||||
<text fg={theme.colors.textDim}>
|
||||
Arrow keys navigate | Enter select | Esc close
|
||||
</text>
|
||||
@@ -339,17 +350,19 @@ export function BrainMenu(props: BrainMenuProps) {
|
||||
</text>
|
||||
</box>
|
||||
<box marginBottom={1}>
|
||||
<text fg={theme.colors.text}>2. After logging in, copy your JWT token</text>
|
||||
<text fg={theme.colors.text}>
|
||||
2. After logging in, copy your JWT token
|
||||
</text>
|
||||
</box>
|
||||
<box marginBottom={1}>
|
||||
<text fg={theme.colors.text}>3. Press Enter to input your token</text>
|
||||
<text fg={theme.colors.text}>
|
||||
3. Press Enter to input your token
|
||||
</text>
|
||||
</box>
|
||||
</box>
|
||||
|
||||
<box marginTop={1}>
|
||||
<text fg={theme.colors.textDim}>
|
||||
Enter continue | Esc back
|
||||
</text>
|
||||
<text fg={theme.colors.textDim}>Enter continue | Esc back</text>
|
||||
</box>
|
||||
</Show>
|
||||
|
||||
|
||||
@@ -4,7 +4,14 @@
|
||||
* UI component for displaying and resolving file conflicts between agents.
|
||||
*/
|
||||
|
||||
import { For, Show, createSignal, createMemo, onMount, onCleanup } from "solid-js";
|
||||
import {
|
||||
For,
|
||||
Show,
|
||||
createSignal,
|
||||
createMemo,
|
||||
onMount,
|
||||
onCleanup,
|
||||
} from "solid-js";
|
||||
import { TextAttributes } from "@opentui/core";
|
||||
import { useTheme } from "@tui-solid/context/theme";
|
||||
import { multiAgentStore } from "@stores/core/multi-agent-store";
|
||||
@@ -46,7 +53,9 @@ export function ConflictResolver(props: ConflictResolverProps) {
|
||||
onCleanup(unsubscribe);
|
||||
});
|
||||
|
||||
const currentConflict = createMemo(() => conflicts()[selectedConflictIndex()]);
|
||||
const currentConflict = createMemo(
|
||||
() => conflicts()[selectedConflictIndex()],
|
||||
);
|
||||
|
||||
const getAgentNames = (agentIds: string[]): string[] => {
|
||||
const state = multiAgentStore.getState();
|
||||
@@ -61,7 +70,9 @@ export function ConflictResolver(props: ConflictResolverProps) {
|
||||
return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
||||
};
|
||||
|
||||
const selectedStrategy = createMemo(() => STRATEGY_OPTIONS[selectedStrategyIndex()]);
|
||||
const selectedStrategy = createMemo(
|
||||
() => STRATEGY_OPTIONS[selectedStrategyIndex()],
|
||||
);
|
||||
|
||||
return (
|
||||
<Show when={visible() && conflicts().length > 0}>
|
||||
@@ -73,7 +84,11 @@ export function ConflictResolver(props: ConflictResolverProps) {
|
||||
backgroundColor={theme.colors.background}
|
||||
>
|
||||
{/* Header */}
|
||||
<box flexDirection="row" justifyContent="space-between" marginBottom={1}>
|
||||
<box
|
||||
flexDirection="row"
|
||||
justifyContent="space-between"
|
||||
marginBottom={1}
|
||||
>
|
||||
<text fg={theme.colors.warning} attributes={TextAttributes.BOLD}>
|
||||
⚠ File Conflict Detected
|
||||
</text>
|
||||
@@ -95,7 +110,9 @@ export function ConflictResolver(props: ConflictResolverProps) {
|
||||
<box flexDirection="row" gap={1}>
|
||||
<text fg={theme.colors.textDim}>Agents:</text>
|
||||
<text fg={theme.colors.text}>
|
||||
{getAgentNames(currentConflict()!.conflictingAgentIds).join(" vs ")}
|
||||
{getAgentNames(currentConflict()!.conflictingAgentIds).join(
|
||||
" vs ",
|
||||
)}
|
||||
</text>
|
||||
</box>
|
||||
|
||||
@@ -119,15 +136,33 @@ export function ConflictResolver(props: ConflictResolverProps) {
|
||||
<box
|
||||
flexDirection="row"
|
||||
gap={1}
|
||||
backgroundColor={index() === selectedStrategyIndex() ? theme.colors.bgHighlight : undefined}
|
||||
backgroundColor={
|
||||
index() === selectedStrategyIndex()
|
||||
? theme.colors.bgHighlight
|
||||
: undefined
|
||||
}
|
||||
paddingLeft={1}
|
||||
>
|
||||
<text fg={index() === selectedStrategyIndex() ? theme.colors.primary : theme.colors.textDim}>
|
||||
<text
|
||||
fg={
|
||||
index() === selectedStrategyIndex()
|
||||
? theme.colors.primary
|
||||
: theme.colors.textDim
|
||||
}
|
||||
>
|
||||
{index() === selectedStrategyIndex() ? "▸" : " "}
|
||||
</text>
|
||||
<text
|
||||
fg={index() === selectedStrategyIndex() ? theme.colors.text : theme.colors.textDim}
|
||||
attributes={index() === selectedStrategyIndex() ? TextAttributes.BOLD : TextAttributes.NONE}
|
||||
fg={
|
||||
index() === selectedStrategyIndex()
|
||||
? theme.colors.text
|
||||
: theme.colors.textDim
|
||||
}
|
||||
attributes={
|
||||
index() === selectedStrategyIndex()
|
||||
? TextAttributes.BOLD
|
||||
: TextAttributes.NONE
|
||||
}
|
||||
>
|
||||
{option.label}
|
||||
</text>
|
||||
@@ -152,7 +187,7 @@ export function ConflictResolver(props: ConflictResolverProps) {
|
||||
{/* Actions */}
|
||||
<box flexDirection="row" gap={2} justifyContent="flex-end">
|
||||
<text fg={theme.colors.textDim}>
|
||||
[↑/↓] Select [Enter] Resolve [Esc] Dismiss
|
||||
[↑/↓] Select [Enter] Resolve [Esc] Dismiss
|
||||
</text>
|
||||
</box>
|
||||
</box>
|
||||
@@ -169,7 +204,9 @@ export function ConflictIndicator() {
|
||||
|
||||
onMount(() => {
|
||||
const unsubscribe = multiAgentStore.subscribe((state) => {
|
||||
const unresolvedCount = state.conflicts.filter((c) => !c.resolution).length;
|
||||
const unresolvedCount = state.conflicts.filter(
|
||||
(c) => !c.resolution,
|
||||
).length;
|
||||
setConflictCount(unresolvedCount);
|
||||
});
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ export function HelpDetail(props: HelpDetailProps) {
|
||||
<text fg={theme.colors.warning} attributes={TextAttributes.BOLD}>
|
||||
Usage
|
||||
</text>
|
||||
<text fg={theme.colors.success}> {currentTopic.usage}</text>
|
||||
<text fg={theme.colors.success}> {currentTopic.usage}</text>
|
||||
</Show>
|
||||
|
||||
<Show when={currentTopic.examples && currentTopic.examples.length > 0}>
|
||||
@@ -87,9 +87,7 @@ export function HelpDetail(props: HelpDetailProps) {
|
||||
Examples
|
||||
</text>
|
||||
<For each={currentTopic.examples}>
|
||||
{(example) => (
|
||||
<text fg={theme.colors.text}> • {example}</text>
|
||||
)}
|
||||
{(example) => <text fg={theme.colors.text}> • {example}</text>}
|
||||
</For>
|
||||
</Show>
|
||||
|
||||
@@ -99,17 +97,13 @@ export function HelpDetail(props: HelpDetailProps) {
|
||||
Shortcuts
|
||||
</text>
|
||||
<For each={currentTopic.shortcuts}>
|
||||
{(shortcut) => (
|
||||
<text fg={theme.colors.primary}> {shortcut}</text>
|
||||
)}
|
||||
{(shortcut) => <text fg={theme.colors.primary}> {shortcut}</text>}
|
||||
</For>
|
||||
</Show>
|
||||
|
||||
<box height={1} />
|
||||
|
||||
<text fg={theme.colors.textDim}>
|
||||
Esc/Backspace back | Enter close
|
||||
</text>
|
||||
<text fg={theme.colors.textDim}>Esc/Backspace back | Enter close</text>
|
||||
</box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,14 @@
|
||||
* Displays active agents, their status, and execution progress.
|
||||
*/
|
||||
|
||||
import { For, Show, createMemo, createSignal, onMount, onCleanup } from "solid-js";
|
||||
import {
|
||||
For,
|
||||
Show,
|
||||
createMemo,
|
||||
createSignal,
|
||||
onMount,
|
||||
onCleanup,
|
||||
} from "solid-js";
|
||||
import { TextAttributes } from "@opentui/core";
|
||||
import { useTheme } from "@tui-solid/context/theme";
|
||||
import { multiAgentStore } from "@stores/core/multi-agent-store";
|
||||
@@ -45,7 +52,9 @@ export function MultiAgentPanel(props: MultiAgentPanelProps) {
|
||||
running: all.filter((i) => i.status === "running").length,
|
||||
waiting: all.filter((i) => i.status === "waiting_conflict").length,
|
||||
completed: all.filter((i) => i.status === "completed").length,
|
||||
failed: all.filter((i) => i.status === "error" || i.status === "cancelled").length,
|
||||
failed: all.filter(
|
||||
(i) => i.status === "error" || i.status === "cancelled",
|
||||
).length,
|
||||
total: all.length,
|
||||
};
|
||||
});
|
||||
@@ -107,24 +116,16 @@ export function MultiAgentPanel(props: MultiAgentPanelProps) {
|
||||
{/* Status Summary */}
|
||||
<box flexDirection="row" gap={1} marginBottom={1}>
|
||||
<Show when={stats().running > 0}>
|
||||
<text fg={theme.colors.info}>
|
||||
● {stats().running}
|
||||
</text>
|
||||
<text fg={theme.colors.info}>● {stats().running}</text>
|
||||
</Show>
|
||||
<Show when={stats().waiting > 0}>
|
||||
<text fg={theme.colors.warning}>
|
||||
⏸ {stats().waiting}
|
||||
</text>
|
||||
<text fg={theme.colors.warning}>⏸ {stats().waiting}</text>
|
||||
</Show>
|
||||
<Show when={stats().completed > 0}>
|
||||
<text fg={theme.colors.success}>
|
||||
✓ {stats().completed}
|
||||
</text>
|
||||
<text fg={theme.colors.success}>✓ {stats().completed}</text>
|
||||
</Show>
|
||||
<Show when={stats().failed > 0}>
|
||||
<text fg={theme.colors.error}>
|
||||
✗ {stats().failed}
|
||||
</text>
|
||||
<text fg={theme.colors.error}>✗ {stats().failed}</text>
|
||||
</Show>
|
||||
</box>
|
||||
|
||||
@@ -136,7 +137,11 @@ export function MultiAgentPanel(props: MultiAgentPanelProps) {
|
||||
<box
|
||||
flexDirection="column"
|
||||
marginBottom={1}
|
||||
backgroundColor={index() === selectedIndex() ? theme.colors.bgHighlight : undefined}
|
||||
backgroundColor={
|
||||
index() === selectedIndex()
|
||||
? theme.colors.bgHighlight
|
||||
: undefined
|
||||
}
|
||||
paddingLeft={1}
|
||||
paddingRight={1}
|
||||
>
|
||||
|
||||
@@ -131,7 +131,7 @@ export function ModeSelect(props: ModeSelectProps) {
|
||||
)}
|
||||
</box>
|
||||
<box>
|
||||
<text fg={theme.colors.textDim}> {mode.description}</text>
|
||||
<text fg={theme.colors.textDim}> {mode.description}</text>
|
||||
</box>
|
||||
</box>
|
||||
);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useKeyboard } from "@opentui/solid";
|
||||
import { TextAttributes } from "@opentui/core";
|
||||
import { useTheme } from "@tui-solid/context/theme";
|
||||
import { useAppStore } from "@tui-solid/context/app";
|
||||
import type { ProviderStatus } from "@services/cascading-provider";
|
||||
import type { ProviderStatus } from "@services/cascading-provider/availability";
|
||||
|
||||
interface ProviderOption {
|
||||
id: string;
|
||||
@@ -217,7 +217,11 @@ export function ProviderSelect(props: ProviderSelectProps) {
|
||||
<box flexDirection="row" marginLeft={4}>
|
||||
<text fg={theme.colors.textDim}>{provider.description}</text>
|
||||
</box>
|
||||
<Show when={provider.id === "ollama" && provider.score !== undefined}>
|
||||
<Show
|
||||
when={
|
||||
provider.id === "ollama" && provider.score !== undefined
|
||||
}
|
||||
>
|
||||
<box flexDirection="row" marginLeft={4}>
|
||||
<text fg={theme.colors.textDim}>Quality Score: </text>
|
||||
<text fg={getScoreColor(provider.score)}>
|
||||
|
||||
@@ -190,7 +190,10 @@ interface AppContextValue {
|
||||
// MCP actions
|
||||
setMcpServers: (servers: MCPServerDisplay[]) => void;
|
||||
addMcpServer: (server: MCPServerDisplay) => void;
|
||||
updateMcpServerStatus: (id: string, status: MCPServerDisplay["status"]) => void;
|
||||
updateMcpServerStatus: (
|
||||
id: string,
|
||||
status: MCPServerDisplay["status"],
|
||||
) => void;
|
||||
|
||||
// Computed
|
||||
isInputLocked: () => boolean;
|
||||
@@ -309,7 +312,8 @@ export const { provider: AppStoreProvider, use: useAppStore } =
|
||||
// Individual property accessors for fine-grained reactivity
|
||||
const streamingLogId = (): string | null => store.streamingLog.logId;
|
||||
const streamingLogContent = (): string => store.streamingLog.content;
|
||||
const streamingLogIsActive = (): boolean => store.streamingLog.isStreaming;
|
||||
const streamingLogIsActive = (): boolean =>
|
||||
store.streamingLog.isStreaming;
|
||||
const suggestions = (): SuggestionState => store.suggestions;
|
||||
const cascadeEnabled = (): boolean => store.cascadeEnabled;
|
||||
const mcpServers = (): MCPServerDisplay[] => store.mcpServers;
|
||||
@@ -520,7 +524,10 @@ export const { provider: AppStoreProvider, use: useAppStore } =
|
||||
setStore("brain", { ...store.brain, user });
|
||||
};
|
||||
|
||||
const setBrainCounts = (knowledgeCount: number, memoryCount: number): void => {
|
||||
const setBrainCounts = (
|
||||
knowledgeCount: number,
|
||||
memoryCount: number,
|
||||
): void => {
|
||||
setStore("brain", { ...store.brain, knowledgeCount, memoryCount });
|
||||
};
|
||||
|
||||
@@ -541,7 +548,9 @@ export const { provider: AppStoreProvider, use: useAppStore } =
|
||||
setStore(
|
||||
produce((s) => {
|
||||
// Replace if exists, otherwise add
|
||||
const existingIndex = s.mcpServers.findIndex((srv) => srv.id === server.id);
|
||||
const existingIndex = s.mcpServers.findIndex(
|
||||
(srv) => srv.id === server.id,
|
||||
);
|
||||
if (existingIndex !== -1) {
|
||||
s.mcpServers[existingIndex] = server;
|
||||
} else {
|
||||
@@ -551,7 +560,10 @@ export const { provider: AppStoreProvider, use: useAppStore } =
|
||||
);
|
||||
};
|
||||
|
||||
const updateMcpServerStatus = (id: string, status: MCPServerDisplay["status"]): void => {
|
||||
const updateMcpServerStatus = (
|
||||
id: string,
|
||||
status: MCPServerDisplay["status"],
|
||||
): void => {
|
||||
setStore(
|
||||
produce((s) => {
|
||||
const server = s.mcpServers.find((srv) => srv.id === id);
|
||||
@@ -1193,7 +1205,10 @@ export const appStore = {
|
||||
storeRef.addMcpServer(server);
|
||||
},
|
||||
|
||||
updateMcpServerStatus: (id: string, status: MCPServerDisplay["status"]): void => {
|
||||
updateMcpServerStatus: (
|
||||
id: string,
|
||||
status: MCPServerDisplay["status"],
|
||||
): void => {
|
||||
if (!storeRef) return;
|
||||
storeRef.updateMcpServerStatus(id, status);
|
||||
},
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
import { Show, Switch, Match, createSignal, createMemo, onMount } from "solid-js";
|
||||
import {
|
||||
Show,
|
||||
Switch,
|
||||
Match,
|
||||
createSignal,
|
||||
createMemo,
|
||||
onMount,
|
||||
} from "solid-js";
|
||||
import { useTheme } from "@tui-solid/context/theme";
|
||||
import { useAppStore } from "@tui-solid/context/app";
|
||||
import { Header } from "@tui-solid/components/layout/header";
|
||||
@@ -23,8 +30,13 @@ import { CenteredModal } from "@tui-solid/components/modals/centered-modal";
|
||||
import { DebugLogPanel } from "@tui-solid/components/logs/debug-log-panel";
|
||||
import { BrainMenu } from "@tui-solid/components/menu/brain-menu";
|
||||
import { BRAIN_DISABLED } from "@constants/brain";
|
||||
import { initializeMCP, getServerInstances } from "@services/mcp";
|
||||
import type { PermissionScope, LearningScope, InteractionMode, MCPServerDisplay } from "@/types/tui";
|
||||
import { initializeMCP, getServerInstances } from "@services/mcp/manager";
|
||||
import type {
|
||||
PermissionScope,
|
||||
LearningScope,
|
||||
InteractionMode,
|
||||
MCPServerDisplay,
|
||||
} from "@/types/tui";
|
||||
import type { MCPAddFormData } from "@/types/mcp";
|
||||
|
||||
interface AgentOption {
|
||||
@@ -93,8 +105,12 @@ export function Session(props: SessionProps) {
|
||||
servers.push({
|
||||
id,
|
||||
name: instance.config.name || id,
|
||||
status: instance.state === "connected" ? "connected" :
|
||||
instance.state === "error" ? "error" : "disconnected",
|
||||
status:
|
||||
instance.state === "connected"
|
||||
? "connected"
|
||||
: instance.state === "error"
|
||||
? "error"
|
||||
: "disconnected",
|
||||
description: instance.config.command,
|
||||
});
|
||||
}
|
||||
@@ -112,7 +128,7 @@ export function Session(props: SessionProps) {
|
||||
|
||||
// Local state for help menu
|
||||
const [selectedHelpTopic, setSelectedHelpTopic] = createSignal<string | null>(
|
||||
null
|
||||
null,
|
||||
);
|
||||
|
||||
const handleCommandSelect = (command: string): void => {
|
||||
@@ -142,7 +158,11 @@ export function Session(props: SessionProps) {
|
||||
app.transitionFromCommandMenu("provider_select");
|
||||
return;
|
||||
}
|
||||
if (lowerCommand === "help" || lowerCommand === "h" || lowerCommand === "?") {
|
||||
if (
|
||||
lowerCommand === "help" ||
|
||||
lowerCommand === "h" ||
|
||||
lowerCommand === "?"
|
||||
) {
|
||||
app.transitionFromCommandMenu("help_menu");
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user