Skip to content

Commit 0156f3c

Browse files
committed
ui improvements
1 parent 0a3095c commit 0156f3c

8 files changed

Lines changed: 109 additions & 27 deletions

File tree

src/agent/super-agent.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import { PerplexityProvider } from "../core/providers/perplexity";
2020
import { AnthropicProvider } from "../core/providers/anthropic";
2121
import { getSettingsManager } from "../utils/settings-manager";
2222
import { TogetherProvider } from "../core/providers/together";
23+
import { DeepSeekProvider } from "../core/providers/deepseek";
2324
import { OpenAIProvider } from "../core/providers/openai";
25+
import { OllamaProvider } from "../core/providers/ollama";
2426
import { GeminiProvider } from "../core/providers/gemini";
2527
import { CohereProvider } from "../core/providers/cohere";
2628
import { GrokProvider } from "../core/providers/grok";
@@ -141,6 +143,18 @@ export class SuperAgent extends EventEmitter {
141143
effectiveBaseURL,
142144
effectiveModel,
143145
);
146+
} else if (providerType === "deepseek") {
147+
this.superAgentClient = new DeepSeekProvider(
148+
effectiveApiKey,
149+
effectiveBaseURL,
150+
effectiveModel,
151+
);
152+
} else if (providerType === "ollama") {
153+
this.superAgentClient = new OllamaProvider(
154+
effectiveApiKey,
155+
effectiveBaseURL,
156+
effectiveModel,
157+
);
144158
} else {
145159
// Default to OpenAI Compatible for all other providers (mistral, openrouter, etc.)
146160
this.superAgentClient = new OpenAICompatibleProvider(
@@ -335,6 +349,18 @@ Current working directory: ${process.cwd()}`,
335349
effectiveBaseURL,
336350
effectiveModel,
337351
);
352+
} else if (providerType === "deepseek") {
353+
this.superAgentClient = new DeepSeekProvider(
354+
effectiveApiKey,
355+
effectiveBaseURL,
356+
effectiveModel,
357+
);
358+
} else if (providerType === "ollama") {
359+
this.superAgentClient = new OllamaProvider(
360+
effectiveApiKey,
361+
effectiveBaseURL,
362+
effectiveModel,
363+
);
338364
} else {
339365
this.superAgentClient = new OpenAICompatibleProvider(
340366
effectiveApiKey,

src/core/providers/deepseek.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { OpenAICompatibleProvider } from "./openai-compatible";
2+
3+
export class DeepSeekProvider extends OpenAICompatibleProvider {
4+
constructor(apiKey: string, baseURL?: string, model?: string) {
5+
super(
6+
apiKey,
7+
baseURL || "https://api.deepseek.com/v1",
8+
model || "deepseek-coder",
9+
"deepseek",
10+
);
11+
}
12+
}

src/core/providers/ollama.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { OpenAICompatibleProvider } from "./openai-compatible";
2+
3+
export class OllamaProvider extends OpenAICompatibleProvider {
4+
constructor(apiKey: string, baseURL?: string, model?: string) {
5+
super(
6+
apiKey || "ollama",
7+
baseURL || "http://localhost:11434/v1",
8+
model || "llama3",
9+
"ollama",
10+
);
11+
}
12+
}

src/hooks/use-input-handler.ts

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -439,18 +439,33 @@ export function useInputHandler({
439439
filteredSuggestions.length - 1,
440440
);
441441
const selectedCommand = filteredSuggestions[safeIndex];
442-
// If the command has arguments placeholders (e.g. <name>), strip them for the actual input
443-
// Or keep them? Usually we just want the command base.
444-
// But if the user defined command as "/mcp <action>", we probably want "/mcp ".
445-
// Let's check how other commands are defined.
446-
// "/chat save <name>" -> we probably want "/chat save "?
447-
// The current logic uses the full string.
448-
449-
// Actually, let's keep it simple first: just ensure cursor goes to end.
450-
const newInput = selectedCommand.command + " ";
451-
// By passing the cursor position to setInput, we avoid the stale closure issue
452-
// where setCursorPosition would clamp based on the old input length.
453-
setInput(newInput, newInput.length);
442+
443+
// Strip placeholders like <name>, [action], etc.
444+
// Examples: "/chat save <name>" -> "/chat save ", "/mcp <action>" -> "/mcp "
445+
let completedCommand = selectedCommand.command;
446+
447+
// Remove everything starting from the first space followed by a placeholder
448+
// or just placeholders themselves
449+
completedCommand = completedCommand
450+
.replace(/\s*<[^>]+>/g, "")
451+
.replace(/\s*\[[^\]]+\]/g, "");
452+
453+
// If it doesn't end with a space and it was a placeholder-heavy command, add a space
454+
if (
455+
!completedCommand.endsWith(" ") &&
456+
selectedCommand.command.includes("<")
457+
) {
458+
completedCommand += " ";
459+
} else if (!completedCommand.endsWith(" ")) {
460+
completedCommand += " ";
461+
}
462+
463+
// Preserve any text that might be after the cursor if we're in the middle of input
464+
const afterCursor = input.slice(cursorPosition);
465+
const newInput = completedCommand + afterCursor;
466+
467+
// Set input and position cursor at the end of the completed command part
468+
setInput(newInput, completedCommand.length);
454469

455470
setShowCommandSuggestions(false);
456471
setSelectedCommandIndex(0);

src/ui/components/chat-history.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ export function ChatHistory({
225225

226226
return (
227227
<Box flexDirection="column">
228-
{filteredEntries.slice(-20).map((entry, index) => (
228+
{filteredEntries.slice(-50).map((entry, index) => (
229229
<MemoizedChatEntry
230230
key={`${entry.timestamp.getTime()}-${index}`}
231231
entry={entry}

src/ui/components/chat-input.tsx

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
import React, { useEffect, useState } from "react";
12
import { Box, Text } from "ink";
2-
import React from "react";
33

44
interface ChatInputProps {
55
input: string;
@@ -14,6 +14,22 @@ export function ChatInput({
1414
isProcessing,
1515
isStreaming,
1616
}: ChatInputProps) {
17+
const [blink, setBlink] = useState(true);
18+
19+
// Blinking cursor effect
20+
useEffect(() => {
21+
if (isProcessing || isStreaming) {
22+
setBlink(false);
23+
return;
24+
}
25+
26+
const interval = setInterval(() => {
27+
setBlink(prev => !prev);
28+
}, 530);
29+
30+
return () => clearInterval(interval);
31+
}, [isProcessing, isStreaming]);
32+
1733
const beforeCursor = input.slice(0, cursorPosition);
1834
const afterCursor = input.slice(cursorPosition);
1935

@@ -67,7 +83,10 @@ export function ChatInput({
6783
<Text>
6884
{beforeCursorInLine}
6985
{showCursor && (
70-
<Text backgroundColor="white" color="black">
86+
<Text
87+
backgroundColor={blink ? "white" : undefined}
88+
color={blink ? "black" : "white"}
89+
>
7190
{cursorChar}
7291
</Text>
7392
)}
@@ -109,7 +128,10 @@ export function ChatInput({
109128
{placeholderText}
110129
</Text>
111130
{showCursor && (
112-
<Text backgroundColor="white" color="black">
131+
<Text
132+
backgroundColor={blink ? "white" : undefined}
133+
color={blink ? "black" : "white"}
134+
>
113135
{" "}
114136
</Text>
115137
)}
@@ -118,7 +140,10 @@ export function ChatInput({
118140
<Text>
119141
{beforeCursor}
120142
{showCursor && (
121-
<Text backgroundColor="white" color="black">
143+
<Text
144+
backgroundColor={blink ? "white" : undefined}
145+
color={blink ? "black" : "white"}
146+
>
122147
{cursorChar}
123148
</Text>
124149
)}

src/ui/components/chat-interface.tsx

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -408,15 +408,7 @@ function ChatInterfaceWithAgent({
408408
</Box>
409409
)}
410410

411-
<Box
412-
flexDirection="column"
413-
ref={scrollRef}
414-
key={
415-
chatHistory.length > 0
416-
? `chat-history-${chatHistory[chatHistory.length - 1]?.timestamp.getTime()}`
417-
: "chat-history-empty"
418-
}
419-
>
411+
<Box flexDirection="column" ref={scrollRef}>
420412
<ChatHistory
421413
entries={chatHistory}
422414
isConfirmationActive={!!confirmationOptions}

src/ui/components/command-suggestions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ interface CommandSuggestionsProps {
1313
isVisible: boolean;
1414
}
1515

16-
export const MAX_SUGGESTIONS = 8;
16+
export const MAX_SUGGESTIONS = 30;
1717

1818
export function filterCommandSuggestions<T extends { command: string }>(
1919
suggestions: T[],

0 commit comments

Comments
 (0)