mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-17 03:03:48 +00:00
docs: add mcp and skill session config (#106)
This commit is contained in:
parent
d236edf35c
commit
4c8d93e077
95 changed files with 10014 additions and 1342 deletions
|
|
@ -1,16 +1,15 @@
|
|||
import { MessageSquare, PauseCircle, PlayCircle, Plus, Square, Terminal } from "lucide-react";
|
||||
import { MessageSquare, Plus, Square, Terminal } from "lucide-react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import type { AgentInfo, AgentModelInfo, AgentModeInfo, PermissionEventData, QuestionEventData } from "sandbox-agent";
|
||||
import type { AgentInfo, AgentModelInfo, AgentModeInfo, PermissionEventData, QuestionEventData, SkillSource } from "sandbox-agent";
|
||||
import type { McpServerEntry } from "../../App";
|
||||
import ApprovalsTab from "../debug/ApprovalsTab";
|
||||
import SessionCreateMenu, { type SessionConfig } from "../SessionCreateMenu";
|
||||
import ChatInput from "./ChatInput";
|
||||
import ChatMessages from "./ChatMessages";
|
||||
import ChatSetup from "./ChatSetup";
|
||||
import type { TimelineEntry } from "./types";
|
||||
|
||||
const ChatPanel = ({
|
||||
sessionId,
|
||||
polling,
|
||||
turnStreaming,
|
||||
transcriptEntries,
|
||||
sessionError,
|
||||
message,
|
||||
|
|
@ -18,35 +17,18 @@ const ChatPanel = ({
|
|||
onSendMessage,
|
||||
onKeyDown,
|
||||
onCreateSession,
|
||||
onSelectAgent,
|
||||
agents,
|
||||
agentsLoading,
|
||||
agentsError,
|
||||
messagesEndRef,
|
||||
agentId,
|
||||
agentLabel,
|
||||
agentMode,
|
||||
permissionMode,
|
||||
model,
|
||||
variant,
|
||||
modelOptions,
|
||||
defaultModel,
|
||||
modelsLoading,
|
||||
modelsError,
|
||||
variantOptions,
|
||||
defaultVariant,
|
||||
supportsVariants,
|
||||
streamMode,
|
||||
activeModes,
|
||||
currentAgentVersion,
|
||||
hasSession,
|
||||
modesLoading,
|
||||
modesError,
|
||||
onAgentModeChange,
|
||||
onPermissionModeChange,
|
||||
onModelChange,
|
||||
onVariantChange,
|
||||
onStreamModeChange,
|
||||
onToggleStream,
|
||||
sessionModel,
|
||||
sessionVariant,
|
||||
sessionPermissionMode,
|
||||
sessionMcpServerCount,
|
||||
sessionSkillSourceCount,
|
||||
onEndSession,
|
||||
eventError,
|
||||
questionRequests,
|
||||
|
|
@ -55,47 +37,40 @@ const ChatPanel = ({
|
|||
onSelectQuestionOption,
|
||||
onAnswerQuestion,
|
||||
onRejectQuestion,
|
||||
onReplyPermission
|
||||
onReplyPermission,
|
||||
modesByAgent,
|
||||
modelsByAgent,
|
||||
defaultModelByAgent,
|
||||
modesLoadingByAgent,
|
||||
modelsLoadingByAgent,
|
||||
modesErrorByAgent,
|
||||
modelsErrorByAgent,
|
||||
mcpServers,
|
||||
onMcpServersChange,
|
||||
mcpConfigError,
|
||||
skillSources,
|
||||
onSkillSourcesChange
|
||||
}: {
|
||||
sessionId: string;
|
||||
polling: boolean;
|
||||
turnStreaming: boolean;
|
||||
transcriptEntries: TimelineEntry[];
|
||||
sessionError: string | null;
|
||||
message: string;
|
||||
onMessageChange: (value: string) => void;
|
||||
onSendMessage: () => void;
|
||||
onKeyDown: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void;
|
||||
onCreateSession: (agentId: string) => void;
|
||||
onCreateSession: (agentId: string, config: SessionConfig) => void;
|
||||
onSelectAgent: (agentId: string) => void;
|
||||
agents: AgentInfo[];
|
||||
agentsLoading: boolean;
|
||||
agentsError: string | null;
|
||||
messagesEndRef: React.RefObject<HTMLDivElement>;
|
||||
agentId: string;
|
||||
agentLabel: string;
|
||||
agentMode: string;
|
||||
permissionMode: string;
|
||||
model: string;
|
||||
variant: string;
|
||||
modelOptions: AgentModelInfo[];
|
||||
defaultModel: string;
|
||||
modelsLoading: boolean;
|
||||
modelsError: string | null;
|
||||
variantOptions: string[];
|
||||
defaultVariant: string;
|
||||
supportsVariants: boolean;
|
||||
streamMode: "poll" | "sse" | "turn";
|
||||
activeModes: AgentModeInfo[];
|
||||
currentAgentVersion?: string | null;
|
||||
hasSession: boolean;
|
||||
modesLoading: boolean;
|
||||
modesError: string | null;
|
||||
onAgentModeChange: (value: string) => void;
|
||||
onPermissionModeChange: (value: string) => void;
|
||||
onModelChange: (value: string) => void;
|
||||
onVariantChange: (value: string) => void;
|
||||
onStreamModeChange: (value: "poll" | "sse" | "turn") => void;
|
||||
onToggleStream: () => void;
|
||||
sessionModel?: string | null;
|
||||
sessionVariant?: string | null;
|
||||
sessionPermissionMode?: string | null;
|
||||
sessionMcpServerCount: number;
|
||||
sessionSkillSourceCount: number;
|
||||
onEndSession: () => void;
|
||||
eventError: string | null;
|
||||
questionRequests: QuestionEventData[];
|
||||
|
|
@ -105,6 +80,18 @@ const ChatPanel = ({
|
|||
onAnswerQuestion: (request: QuestionEventData) => void;
|
||||
onRejectQuestion: (requestId: string) => void;
|
||||
onReplyPermission: (requestId: string, reply: "once" | "always" | "reject") => void;
|
||||
modesByAgent: Record<string, AgentModeInfo[]>;
|
||||
modelsByAgent: Record<string, AgentModelInfo[]>;
|
||||
defaultModelByAgent: Record<string, string>;
|
||||
modesLoadingByAgent: Record<string, boolean>;
|
||||
modelsLoadingByAgent: Record<string, boolean>;
|
||||
modesErrorByAgent: Record<string, string | null>;
|
||||
modelsErrorByAgent: Record<string, string | null>;
|
||||
mcpServers: McpServerEntry[];
|
||||
onMcpServersChange: (servers: McpServerEntry[]) => void;
|
||||
mcpConfigError: string | null;
|
||||
skillSources: SkillSource[];
|
||||
onSkillSourcesChange: (sources: SkillSource[]) => void;
|
||||
}) => {
|
||||
const [showAgentMenu, setShowAgentMenu] = useState(false);
|
||||
const menuRef = useRef<HTMLDivElement | null>(null);
|
||||
|
|
@ -121,18 +108,7 @@ const ChatPanel = ({
|
|||
return () => document.removeEventListener("mousedown", handler);
|
||||
}, [showAgentMenu]);
|
||||
|
||||
const agentLabels: Record<string, string> = {
|
||||
claude: "Claude Code",
|
||||
codex: "Codex",
|
||||
opencode: "OpenCode",
|
||||
amp: "Amp",
|
||||
mock: "Mock"
|
||||
};
|
||||
|
||||
const hasApprovals = questionRequests.length > 0 || permissionRequests.length > 0;
|
||||
const isTurnMode = streamMode === "turn";
|
||||
const isStreaming = isTurnMode ? turnStreaming : polling;
|
||||
const turnLabel = turnStreaming ? "Streaming" : "On Send";
|
||||
|
||||
return (
|
||||
<div className="chat-panel">
|
||||
|
|
@ -141,12 +117,6 @@ const ChatPanel = ({
|
|||
<MessageSquare className="button-icon" />
|
||||
<span className="panel-title">{sessionId ? "Session" : "No Session"}</span>
|
||||
{sessionId && <span className="session-id-display">{sessionId}</span>}
|
||||
{sessionId && (
|
||||
<span className="session-agent-display">
|
||||
{agentLabel}
|
||||
{currentAgentVersion && <span className="session-agent-version">v{currentAgentVersion}</span>}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="panel-header-right">
|
||||
{sessionId && (
|
||||
|
|
@ -160,42 +130,6 @@ const ChatPanel = ({
|
|||
End
|
||||
</button>
|
||||
)}
|
||||
<div className="setup-stream">
|
||||
<select
|
||||
className="setup-select-small"
|
||||
value={streamMode}
|
||||
onChange={(e) => onStreamModeChange(e.target.value as "poll" | "sse" | "turn")}
|
||||
title="Stream Mode"
|
||||
disabled={!sessionId}
|
||||
>
|
||||
<option value="poll">Poll</option>
|
||||
<option value="sse">SSE</option>
|
||||
<option value="turn">Turn</option>
|
||||
</select>
|
||||
<button
|
||||
className={`setup-stream-btn ${isStreaming ? "active" : ""}`}
|
||||
onClick={onToggleStream}
|
||||
title={isTurnMode ? "Turn streaming starts on send" : polling ? "Stop streaming" : "Start streaming"}
|
||||
disabled={!sessionId || isTurnMode}
|
||||
>
|
||||
{isTurnMode ? (
|
||||
<>
|
||||
<PlayCircle size={14} />
|
||||
<span>{turnLabel}</span>
|
||||
</>
|
||||
) : polling ? (
|
||||
<>
|
||||
<PauseCircle size={14} />
|
||||
<span>Pause</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<PlayCircle size={14} />
|
||||
<span>Resume</span>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -213,32 +147,27 @@ const ChatPanel = ({
|
|||
<Plus className="button-icon" />
|
||||
Create Session
|
||||
</button>
|
||||
{showAgentMenu && (
|
||||
<div className="empty-state-menu">
|
||||
{agentsLoading && <div className="sidebar-add-status">Loading agents...</div>}
|
||||
{agentsError && <div className="sidebar-add-status error">{agentsError}</div>}
|
||||
{!agentsLoading && !agentsError && agents.length === 0 && (
|
||||
<div className="sidebar-add-status">No agents available.</div>
|
||||
)}
|
||||
{!agentsLoading && !agentsError &&
|
||||
agents.map((agent) => (
|
||||
<button
|
||||
key={agent.id}
|
||||
className="sidebar-add-option"
|
||||
onClick={() => {
|
||||
onCreateSession(agent.id);
|
||||
setShowAgentMenu(false);
|
||||
}}
|
||||
>
|
||||
<div className="agent-option-left">
|
||||
<span className="agent-option-name">{agentLabels[agent.id] ?? agent.id}</span>
|
||||
{agent.version && <span className="agent-badge version">v{agent.version}</span>}
|
||||
</div>
|
||||
{agent.installed && <span className="agent-badge installed">Installed</span>}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<SessionCreateMenu
|
||||
agents={agents}
|
||||
agentsLoading={agentsLoading}
|
||||
agentsError={agentsError}
|
||||
modesByAgent={modesByAgent}
|
||||
modelsByAgent={modelsByAgent}
|
||||
defaultModelByAgent={defaultModelByAgent}
|
||||
modesLoadingByAgent={modesLoadingByAgent}
|
||||
modelsLoadingByAgent={modelsLoadingByAgent}
|
||||
modesErrorByAgent={modesErrorByAgent}
|
||||
modelsErrorByAgent={modelsErrorByAgent}
|
||||
mcpServers={mcpServers}
|
||||
onMcpServersChange={onMcpServersChange}
|
||||
mcpConfigError={mcpConfigError}
|
||||
skillSources={skillSources}
|
||||
onSkillSourcesChange={onSkillSourcesChange}
|
||||
onSelectAgent={onSelectAgent}
|
||||
onCreateSession={onCreateSession}
|
||||
open={showAgentMenu}
|
||||
onClose={() => setShowAgentMenu(false)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : transcriptEntries.length === 0 && !sessionError ? (
|
||||
|
|
@ -246,7 +175,7 @@ const ChatPanel = ({
|
|||
<Terminal className="empty-state-icon" />
|
||||
<div className="empty-state-title">Ready to Chat</div>
|
||||
<p className="empty-state-text">Send a message to start a conversation with the agent.</p>
|
||||
{agentId === "mock" && (
|
||||
{agentLabel === "Mock" && (
|
||||
<div className="mock-agent-hint">
|
||||
The mock agent simulates agent responses for testing the inspector UI without requiring API credentials. Send <code>help</code> for available commands.
|
||||
</div>
|
||||
|
|
@ -283,30 +212,37 @@ const ChatPanel = ({
|
|||
onSendMessage={onSendMessage}
|
||||
onKeyDown={onKeyDown}
|
||||
placeholder={sessionId ? "Send a message..." : "Select or create a session first"}
|
||||
disabled={!sessionId || turnStreaming}
|
||||
disabled={!sessionId}
|
||||
/>
|
||||
|
||||
<ChatSetup
|
||||
agentMode={agentMode}
|
||||
permissionMode={permissionMode}
|
||||
model={model}
|
||||
variant={variant}
|
||||
modelOptions={modelOptions}
|
||||
defaultModel={defaultModel}
|
||||
modelsLoading={modelsLoading}
|
||||
modelsError={modelsError}
|
||||
variantOptions={variantOptions}
|
||||
defaultVariant={defaultVariant}
|
||||
supportsVariants={supportsVariants}
|
||||
activeModes={activeModes}
|
||||
modesLoading={modesLoading}
|
||||
modesError={modesError}
|
||||
onAgentModeChange={onAgentModeChange}
|
||||
onPermissionModeChange={onPermissionModeChange}
|
||||
onModelChange={onModelChange}
|
||||
onVariantChange={onVariantChange}
|
||||
hasSession={hasSession}
|
||||
/>
|
||||
{sessionId && (
|
||||
<div className="session-config-bar">
|
||||
<div className="session-config-field">
|
||||
<span className="session-config-label">Agent</span>
|
||||
<span className="session-config-value">{agentLabel}</span>
|
||||
</div>
|
||||
<div className="session-config-field">
|
||||
<span className="session-config-label">Model</span>
|
||||
<span className="session-config-value">{sessionModel || "-"}</span>
|
||||
</div>
|
||||
<div className="session-config-field">
|
||||
<span className="session-config-label">Variant</span>
|
||||
<span className="session-config-value">{sessionVariant || "-"}</span>
|
||||
</div>
|
||||
<div className="session-config-field">
|
||||
<span className="session-config-label">Permission</span>
|
||||
<span className="session-config-value">{sessionPermissionMode || "-"}</span>
|
||||
</div>
|
||||
<div className="session-config-field">
|
||||
<span className="session-config-label">MCP Servers</span>
|
||||
<span className="session-config-value">{sessionMcpServerCount}</span>
|
||||
</div>
|
||||
<div className="session-config-field">
|
||||
<span className="session-config-label">Skills</span>
|
||||
<span className="session-config-value">{sessionSkillSourceCount}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue