fix: vscode runtime stability and cli connection

This commit is contained in:
Bohdan Triapitsyn
2025-12-24 03:31:07 +02:00
parent b850a04e21
commit 8e98a72ddf
6 changed files with 525 additions and 236 deletions
@@ -1,5 +1,6 @@
import React from 'react';
import { useSessionStore } from '@openchamber/ui/stores/useSessionStore';
import { useConfigStore } from '@openchamber/ui/stores/useConfigStore';
import { useNavigation } from '../hooks/useNavigation';
import { VSCodeHeader } from './VSCodeHeader';
import { SimpleMessageRenderer } from './SimpleMessageRenderer';
@@ -15,6 +16,7 @@ export function ChatPanel() {
const sendMessage = useSessionStore((s) => s.sendMessage);
const abortCurrentOperation = useSessionStore((s) => s.abortCurrentOperation);
const streamingMessageIds = useSessionStore((s) => s.streamingMessageIds);
const { currentProviderId, currentModelId, currentAgentName } = useConfigStore();
const [inputValue, setInputValue] = React.useState('');
const [isSending, setIsSending] = React.useState(false);
@@ -33,11 +35,17 @@ export function ChatPanel() {
if (!inputValue.trim() || !currentSessionId || isSending) return;
const messageText = inputValue.trim();
if (!currentProviderId || !currentModelId) {
console.warn('Missing provider or model selection for sendMessage');
return;
}
setInputValue('');
setIsSending(true);
try {
await sendMessage(messageText);
await sendMessage(messageText, currentProviderId, currentModelId, currentAgentName);
} catch (error) {
console.error('Failed to send message:', error);
setInputValue(messageText); // Restore input on error
@@ -55,7 +63,7 @@ export function ChatPanel() {
const handleAbort = () => {
if (currentSessionId) {
abortCurrentOperation(currentSessionId);
void abortCurrentOperation();
}
};
@@ -1,5 +1,5 @@
import React from 'react';
import type { Message, Part } from '@opencode-ai/sdk';
import type { Message, Part, ToolPart } from '@opencode-ai/sdk';
interface SimpleMessageRendererProps {
message: { info: Message; parts: Part[] };
@@ -16,7 +16,7 @@ export function SimpleMessageRenderer({ message }: SimpleMessageRendererProps) {
.join('\n');
// Check for tool calls
const toolParts = parts.filter((part) => part.type === 'tool-invocation' || part.type === 'tool-result');
const toolParts = parts.filter((part): part is ToolPart => part.type === 'tool');
return (
<div className={`flex ${isUser ? 'justify-end' : 'justify-start'}`}>
@@ -57,32 +57,20 @@ export function SimpleMessageRenderer({ message }: SimpleMessageRendererProps) {
);
}
function ToolPartRenderer({ part }: { part: Part }) {
if (part.type === 'tool-invocation') {
const toolName = part.toolInvocation?.toolName || 'tool';
const state = part.toolInvocation?.state || 'pending';
function ToolPartRenderer({ part }: { part: ToolPart }) {
const toolName = typeof part.tool === 'string' ? part.tool : 'tool';
const status = typeof part.state?.status === 'string' ? part.state.status : 'pending';
return (
<div className="flex items-center gap-2 text-xs text-muted-foreground">
{state === 'pending' || state === 'streaming' ? (
<span className="inline-block w-3 h-3 border-2 border-current border-t-transparent rounded-full animate-spin" />
) : state === 'result' ? (
<span className="text-green-500">✓</span>
) : (
<span className="text-red-500">✗</span>
)}
<span className="font-mono">{toolName}</span>
</div>
);
}
if (part.type === 'tool-result') {
return (
<div className="text-xs text-muted-foreground font-mono truncate">
Result: {typeof part.result === 'string' ? part.result.slice(0, 50) : '...'}
</div>
);
}
return null;
return (
<div className="flex items-center gap-2 text-xs text-muted-foreground">
{status === 'running' || status === 'pending' ? (
<span className="inline-block w-3 h-3 border-2 border-current border-t-transparent rounded-full animate-spin" />
) : status === 'completed' ? (
<span className="text-green-500">✓</span>
) : (
<span className="text-red-500">✗</span>
)}
<span className="font-mono">{toolName}</span>
</div>
);
}