mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 21:03:19 +00:00
Updates to prompts
This commit is contained in:
parent
ffc9be8867
commit
2a7ccf0fcb
15 changed files with 911 additions and 271 deletions
170
packages/coding-agent/DEBUG.md
Normal file
170
packages/coding-agent/DEBUG.md
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
# Debug Mode Guide
|
||||
|
||||
## Enabling Debug Output
|
||||
|
||||
Debug logs are written to files in `/tmp/` to avoid interfering with TUI rendering.
|
||||
|
||||
There are three ways to enable debug output:
|
||||
|
||||
1. **CLI flag**: `--debug` or `-d`
|
||||
```bash
|
||||
coding-agent --debug --script "Hello"
|
||||
```
|
||||
This will print log file locations:
|
||||
```
|
||||
[TUI] Debug logging to: /tmp/tui-debug-1234567890.log
|
||||
[RENDERER] Debug logging to: /tmp/agent-debug-1234567890.log
|
||||
```
|
||||
|
||||
2. **Environment variables**:
|
||||
```bash
|
||||
TUI_DEBUG=1 AGENT_DEBUG=1 coding-agent
|
||||
```
|
||||
|
||||
3. **Individual components**:
|
||||
```bash
|
||||
TUI_DEBUG=1 coding-agent # Only TUI debug
|
||||
AGENT_DEBUG=1 coding-agent # Only agent/renderer debug
|
||||
```
|
||||
|
||||
## Viewing Debug Logs
|
||||
|
||||
Debug logs are written to `/tmp/` with timestamps:
|
||||
- `/tmp/tui-debug-<timestamp>.log` - TUI rendering events
|
||||
- `/tmp/agent-debug-<timestamp>.log` - Agent/renderer events
|
||||
|
||||
To tail the logs while the agent runs:
|
||||
```bash
|
||||
# In one terminal
|
||||
coding-agent --debug --script "Hello"
|
||||
|
||||
# In another terminal (use the path printed above)
|
||||
tail -f /tmp/tui-debug-*.log
|
||||
tail -f /tmp/agent-debug-*.log
|
||||
```
|
||||
|
||||
## Scripted Messages for Testing
|
||||
|
||||
Use `--script` to replay messages automatically in interactive mode:
|
||||
|
||||
```bash
|
||||
# Single scripted message
|
||||
coding-agent --debug --script "What files are in this directory?"
|
||||
|
||||
# Multiple scripted messages
|
||||
coding-agent --debug --script "Hello" --script "List the files" --script "Read package.json"
|
||||
```
|
||||
|
||||
The agent will:
|
||||
1. Type the message into the editor
|
||||
2. Submit it
|
||||
3. Wait for the agent to complete its response
|
||||
4. Move to the next message
|
||||
5. Exit after all messages are processed
|
||||
|
||||
## Debug Output Reference
|
||||
|
||||
### TUI Debug Messages
|
||||
|
||||
**`[TUI DEBUG]`** - Low-level terminal UI rendering events
|
||||
|
||||
- **`requestRender() called but TUI not started`** - Render requested before TUI initialization (usually benign)
|
||||
- **`Render queued`** - A render has been scheduled for next tick
|
||||
- **`Executing queued render`** - About to perform the actual render
|
||||
- **`renderToScreen() called: resize=X, termWidth=Y, termHeight=Z`** - Starting render cycle
|
||||
- **`Reset for resize`** - Terminal was resized, clearing buffers
|
||||
- **`Collected N render commands, total lines: M`** - Gathered all component output (N components, M total lines)
|
||||
- **`Performing initial render`** - First render (full screen write)
|
||||
- **`Performing line-based render`** - Differential render (only changed lines)
|
||||
- **`Render complete. Total renders: X, avg lines redrawn: Y`** - Render finished with performance stats
|
||||
|
||||
### Renderer Debug Messages
|
||||
|
||||
**`[RENDERER DEBUG]`** - Agent renderer (TuiRenderer) events
|
||||
|
||||
- **`handleStateUpdate: isStreaming=X, messages=N, pendingToolCalls=M`** - Agent state changed
|
||||
- `isStreaming=true` - Agent is currently responding
|
||||
- `messages=N` - Total messages in conversation
|
||||
- `pendingToolCalls=M` - Number of tool calls waiting to execute
|
||||
|
||||
- **`Adding N new stable messages`** - N messages were finalized and added to chat history
|
||||
- **`Streaming message role=X`** - Currently streaming a message with role X (user/assistant/toolResult)
|
||||
- **`Starting loading animation`** - Spinner started because agent is thinking
|
||||
- **`Creating streaming component`** - Creating UI component to show live message updates
|
||||
- **`Streaming stopped`** - Agent finished responding
|
||||
- **`Requesting render`** - Asking TUI to redraw the screen
|
||||
- **`simulateInput: "text"`** - Scripted message being typed
|
||||
- **`Triggering onInputCallback`** - Submitting the scripted message
|
||||
|
||||
### Script Debug Messages
|
||||
|
||||
**`[SCRIPT]`** - Scripted message playback
|
||||
|
||||
- **`Sending message N/M: text`** - Sending message N out of M total
|
||||
- **`All N messages completed. Exiting.`** - Finished all scripted messages
|
||||
|
||||
**`[AGENT]`** - Agent execution
|
||||
|
||||
- **`Completed response to: "text"`** - Agent finished processing this message
|
||||
|
||||
## Interpreting Debug Output
|
||||
|
||||
### Normal Message Flow
|
||||
|
||||
```
|
||||
[RENDERER DEBUG] handleStateUpdate: isStreaming=false, messages=0, pendingToolCalls=0
|
||||
[SCRIPT] Sending message 1/1: Hello
|
||||
[RENDERER DEBUG] simulateInput: "Hello"
|
||||
[RENDERER DEBUG] Triggering onInputCallback
|
||||
[RENDERER DEBUG] handleStateUpdate: isStreaming=true, messages=1, pendingToolCalls=0
|
||||
[RENDERER DEBUG] Streaming message role=user
|
||||
[RENDERER DEBUG] Starting loading animation
|
||||
[RENDERER DEBUG] Requesting render
|
||||
[TUI DEBUG] Render queued
|
||||
[TUI DEBUG] Executing queued render
|
||||
[TUI DEBUG] renderToScreen() called: resize=false, termWidth=120, termHeight=40
|
||||
[TUI DEBUG] Collected 4 render commands, total lines: 8
|
||||
[TUI DEBUG] Performing line-based render
|
||||
[TUI DEBUG] Render complete. Total renders: 5, avg lines redrawn: 12.4
|
||||
[RENDERER DEBUG] handleStateUpdate: isStreaming=true, messages=1, pendingToolCalls=0
|
||||
[RENDERER DEBUG] Streaming message role=assistant
|
||||
...
|
||||
[RENDERER DEBUG] handleStateUpdate: isStreaming=false, messages=2, pendingToolCalls=0
|
||||
[RENDERER DEBUG] Streaming stopped
|
||||
[RENDERER DEBUG] Adding 1 new stable messages
|
||||
[AGENT] Completed response to: "Hello"
|
||||
```
|
||||
|
||||
### What to Look For
|
||||
|
||||
**Rendering Issues:**
|
||||
- If `Render queued` appears but no `Executing queued render` → render loop broken
|
||||
- If `total lines` is 0 or unexpectedly small → components not rendering
|
||||
- If `avg lines redrawn` is huge → too many full redraws (performance issue)
|
||||
- If no `[TUI DEBUG]` messages → TUI debug not enabled or TUI not starting
|
||||
|
||||
**Message Flow Issues:**
|
||||
- If messages increase but no "Adding N new stable messages" → renderer not detecting changes
|
||||
- If `isStreaming=true` never becomes `false` → agent hanging
|
||||
- If `pendingToolCalls` stays > 0 → tool execution stuck
|
||||
- If `Streaming stopped` never appears → streaming never completes
|
||||
|
||||
**Scripted Message Issues:**
|
||||
- If `simulateInput` appears but no `Triggering onInputCallback` → callback not registered yet
|
||||
- If `Sending message` appears but no `Completed response` → agent not responding
|
||||
- If no `[SCRIPT]` messages → script messages not being processed
|
||||
|
||||
## Example Debug Session
|
||||
|
||||
```bash
|
||||
# Test basic rendering with a simple scripted message
|
||||
coding-agent --debug --script "Hello"
|
||||
|
||||
# Test multi-turn conversation
|
||||
coding-agent --debug --script "Hi" --script "What files are here?" --script "Thanks"
|
||||
|
||||
# Test tool execution
|
||||
coding-agent --debug --script "List all TypeScript files"
|
||||
```
|
||||
|
||||
Look for the flow: script → simulateInput → handleStateUpdate → render → completed
|
||||
|
|
@ -22,7 +22,6 @@
|
|||
"dependencies": {
|
||||
"@mariozechner/pi-agent": "^0.5.44",
|
||||
"@mariozechner/pi-ai": "^0.5.44",
|
||||
"@mariozechner/pi-tui": "^0.5.44",
|
||||
"chalk": "^5.5.0",
|
||||
"glob": "^11.0.3"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { getModel } from "@mariozechner/pi-ai";
|
|||
import chalk from "chalk";
|
||||
import { SessionManager } from "./session-manager.js";
|
||||
import { codingTools } from "./tools/index.js";
|
||||
import { TuiRenderer } from "./tui-renderer.js";
|
||||
|
||||
interface Args {
|
||||
provider?: string;
|
||||
|
|
@ -57,6 +58,9 @@ ${chalk.bold("Options:")}
|
|||
--help, -h Show this help
|
||||
|
||||
${chalk.bold("Examples:")}
|
||||
# Interactive mode (no messages = interactive TUI)
|
||||
coding-agent
|
||||
|
||||
# Single message
|
||||
coding-agent "List all .ts files in src/"
|
||||
|
||||
|
|
@ -101,6 +105,57 @@ Guidelines:
|
|||
|
||||
Current directory: ${process.cwd()}`;
|
||||
|
||||
async function runInteractiveMode(agent: Agent, _sessionManager: SessionManager): Promise<void> {
|
||||
const renderer = new TuiRenderer();
|
||||
|
||||
// Initialize TUI
|
||||
await renderer.init();
|
||||
|
||||
// Set interrupt callback
|
||||
renderer.setInterruptCallback(() => {
|
||||
agent.abort();
|
||||
});
|
||||
|
||||
// Subscribe to agent state updates
|
||||
agent.subscribe(async (event) => {
|
||||
if (event.type === "state-update") {
|
||||
await renderer.handleStateUpdate(event.state);
|
||||
}
|
||||
});
|
||||
|
||||
// Interactive loop
|
||||
while (true) {
|
||||
const userInput = await renderer.getUserInput();
|
||||
|
||||
// Process the message - agent.prompt will add user message and trigger state updates
|
||||
try {
|
||||
await agent.prompt(userInput);
|
||||
} catch (error: any) {
|
||||
// Error handling - errors should be in agent state
|
||||
console.error("Error:", error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function runSingleShotMode(agent: Agent, sessionManager: SessionManager, messages: string[]): Promise<void> {
|
||||
for (const message of messages) {
|
||||
console.log(chalk.blue(`\n> ${message}\n`));
|
||||
await agent.prompt(message);
|
||||
|
||||
// Print response
|
||||
const lastMessage = agent.state.messages[agent.state.messages.length - 1];
|
||||
if (lastMessage.role === "assistant") {
|
||||
for (const content of lastMessage.content) {
|
||||
if (content.type === "text") {
|
||||
console.log(content.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(chalk.dim(`\nSession saved to: ${sessionManager.getSessionFile()}`));
|
||||
}
|
||||
|
||||
export async function main(args: string[]) {
|
||||
const parsed = parseArgs(args);
|
||||
|
||||
|
|
@ -183,27 +238,12 @@ export async function main(args: string[]) {
|
|||
sessionManager.saveEvent(event);
|
||||
});
|
||||
|
||||
// Process messages
|
||||
if (parsed.messages.length === 0) {
|
||||
console.log(chalk.yellow("No messages provided. Use --help for usage information."));
|
||||
console.log(chalk.dim(`Session saved to: ${sessionManager.getSessionFile()}`));
|
||||
return;
|
||||
// Determine mode: interactive if no messages provided
|
||||
const isInteractive = parsed.messages.length === 0;
|
||||
|
||||
if (isInteractive) {
|
||||
await runInteractiveMode(agent, sessionManager);
|
||||
} else {
|
||||
await runSingleShotMode(agent, sessionManager, parsed.messages);
|
||||
}
|
||||
|
||||
for (const message of parsed.messages) {
|
||||
console.log(chalk.blue(`\n> ${message}\n`));
|
||||
await agent.prompt(message);
|
||||
|
||||
// Print response
|
||||
const lastMessage = agent.state.messages[agent.state.messages.length - 1];
|
||||
if (lastMessage.role === "assistant") {
|
||||
for (const content of lastMessage.content) {
|
||||
if (content.type === "text") {
|
||||
console.log(content.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(chalk.dim(`\nSession saved to: ${sessionManager.getSessionFile()}`));
|
||||
}
|
||||
|
|
|
|||
308
packages/coding-agent/src/tui-renderer.ts
Normal file
308
packages/coding-agent/src/tui-renderer.ts
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
import type { AgentState } from "@mariozechner/pi-agent";
|
||||
import type { AssistantMessage, Message } from "@mariozechner/pi-ai";
|
||||
import {
|
||||
CombinedAutocompleteProvider,
|
||||
Container,
|
||||
LoadingAnimation,
|
||||
MarkdownComponent,
|
||||
TextComponent,
|
||||
TextEditor,
|
||||
TUI,
|
||||
WhitespaceComponent,
|
||||
} from "@mariozechner/pi-tui";
|
||||
import chalk from "chalk";
|
||||
|
||||
/**
|
||||
* Component that renders a streaming message with live updates
|
||||
*/
|
||||
class StreamingMessageComponent extends Container {
|
||||
private textComponent: MarkdownComponent | null = null;
|
||||
private toolCallsContainer: Container | null = null;
|
||||
private currentContent = "";
|
||||
private currentToolCalls: any[] = [];
|
||||
|
||||
updateContent(message: Message | null) {
|
||||
if (!message) {
|
||||
this.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.role === "assistant") {
|
||||
const assistantMsg = message as AssistantMessage;
|
||||
|
||||
// Update text content
|
||||
const textContent = assistantMsg.content
|
||||
.filter((c) => c.type === "text")
|
||||
.map((c) => c.text)
|
||||
.join("");
|
||||
if (textContent !== this.currentContent) {
|
||||
this.currentContent = textContent;
|
||||
if (this.textComponent) {
|
||||
this.removeChild(this.textComponent);
|
||||
}
|
||||
if (textContent) {
|
||||
this.textComponent = new MarkdownComponent(textContent);
|
||||
this.addChild(this.textComponent);
|
||||
}
|
||||
}
|
||||
|
||||
// Update tool calls
|
||||
const toolCalls = assistantMsg.content.filter((c) => c.type === "toolCall");
|
||||
if (JSON.stringify(toolCalls) !== JSON.stringify(this.currentToolCalls)) {
|
||||
this.currentToolCalls = toolCalls;
|
||||
if (this.toolCallsContainer) {
|
||||
this.removeChild(this.toolCallsContainer);
|
||||
}
|
||||
if (toolCalls.length > 0) {
|
||||
this.toolCallsContainer = new Container();
|
||||
for (const toolCall of toolCalls) {
|
||||
const argsStr =
|
||||
typeof toolCall.arguments === "string" ? toolCall.arguments : JSON.stringify(toolCall.arguments);
|
||||
this.toolCallsContainer.addChild(
|
||||
new TextComponent(chalk.yellow(`[tool] ${toolCall.name}(${argsStr})`)),
|
||||
);
|
||||
}
|
||||
this.addChild(this.toolCallsContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TUI renderer for the coding agent
|
||||
*/
|
||||
export class TuiRenderer {
|
||||
private ui: TUI;
|
||||
private chatContainer: Container;
|
||||
private statusContainer: Container;
|
||||
private editor: TextEditor;
|
||||
private isInitialized = false;
|
||||
private onInputCallback?: (text: string) => void;
|
||||
private loadingAnimation: LoadingAnimation | null = null;
|
||||
private onInterruptCallback?: () => void;
|
||||
private lastSigintTime = 0;
|
||||
|
||||
// Message tracking
|
||||
private lastStableMessageCount = 0;
|
||||
private streamingComponent: StreamingMessageComponent | null = null;
|
||||
|
||||
constructor() {
|
||||
this.ui = new TUI();
|
||||
this.chatContainer = new Container();
|
||||
this.statusContainer = new Container();
|
||||
this.editor = new TextEditor();
|
||||
|
||||
// Setup autocomplete for file paths and slash commands
|
||||
const autocompleteProvider = new CombinedAutocompleteProvider([], process.cwd());
|
||||
this.editor.setAutocompleteProvider(autocompleteProvider);
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
if (this.isInitialized) return;
|
||||
|
||||
// Add header with instructions
|
||||
const header = new TextComponent(
|
||||
chalk.blueBright(">> coding-agent interactive <<") +
|
||||
"\n" +
|
||||
chalk.dim("Press Escape to interrupt while processing") +
|
||||
"\n" +
|
||||
chalk.dim("Press CTRL+C to clear the text editor") +
|
||||
"\n" +
|
||||
chalk.dim("Press CTRL+C twice quickly to exit"),
|
||||
{ bottom: 1 },
|
||||
);
|
||||
|
||||
// Setup UI layout
|
||||
this.ui.addChild(header);
|
||||
this.ui.addChild(this.chatContainer);
|
||||
this.ui.addChild(this.statusContainer);
|
||||
this.ui.addChild(new WhitespaceComponent(1));
|
||||
this.ui.addChild(this.editor);
|
||||
this.ui.setFocus(this.editor);
|
||||
|
||||
// Set up global key handler for Escape and Ctrl+C
|
||||
this.ui.onGlobalKeyPress = (data: string): boolean => {
|
||||
// Intercept Escape key when processing
|
||||
if (data === "\x1b" && this.loadingAnimation) {
|
||||
if (this.onInterruptCallback) {
|
||||
this.onInterruptCallback();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle Ctrl+C (raw mode sends \x03)
|
||||
if (data === "\x03") {
|
||||
const now = Date.now();
|
||||
const timeSinceLastCtrlC = now - this.lastSigintTime;
|
||||
|
||||
if (timeSinceLastCtrlC < 500) {
|
||||
// Second Ctrl+C within 500ms - exit
|
||||
this.stop();
|
||||
process.exit(0);
|
||||
} else {
|
||||
// First Ctrl+C - clear the editor
|
||||
this.clearEditor();
|
||||
this.lastSigintTime = now;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// Handle editor submission
|
||||
this.editor.onSubmit = (text: string) => {
|
||||
text = text.trim();
|
||||
if (!text) return;
|
||||
|
||||
if (this.onInputCallback) {
|
||||
this.onInputCallback(text);
|
||||
}
|
||||
};
|
||||
|
||||
// Start the UI
|
||||
this.ui.start();
|
||||
this.isInitialized = true;
|
||||
}
|
||||
|
||||
async handleStateUpdate(state: AgentState): Promise<void> {
|
||||
if (!this.isInitialized) {
|
||||
await this.init();
|
||||
}
|
||||
|
||||
// Count stable messages (exclude the streaming one if streaming)
|
||||
const stableMessageCount = state.isStreaming ? state.messages.length - 1 : state.messages.length;
|
||||
|
||||
// Add any NEW stable messages
|
||||
if (stableMessageCount > this.lastStableMessageCount) {
|
||||
for (let i = this.lastStableMessageCount; i < stableMessageCount; i++) {
|
||||
const message = state.messages[i];
|
||||
this.addMessageToChat(message);
|
||||
}
|
||||
this.lastStableMessageCount = stableMessageCount;
|
||||
}
|
||||
|
||||
// Handle streaming message
|
||||
if (state.isStreaming) {
|
||||
const streamingMessage = state.messages[state.messages.length - 1];
|
||||
|
||||
// Show loading animation if we just started streaming
|
||||
if (!this.loadingAnimation) {
|
||||
this.editor.disableSubmit = true;
|
||||
this.statusContainer.clear();
|
||||
this.loadingAnimation = new LoadingAnimation(this.ui);
|
||||
this.statusContainer.addChild(this.loadingAnimation);
|
||||
}
|
||||
|
||||
// Create or update streaming component
|
||||
if (!this.streamingComponent) {
|
||||
this.streamingComponent = new StreamingMessageComponent();
|
||||
this.chatContainer.addChild(this.streamingComponent);
|
||||
}
|
||||
this.streamingComponent.updateContent(streamingMessage);
|
||||
} else {
|
||||
// Streaming stopped
|
||||
if (this.loadingAnimation) {
|
||||
this.loadingAnimation.stop();
|
||||
this.loadingAnimation = null;
|
||||
this.statusContainer.clear();
|
||||
}
|
||||
|
||||
if (this.streamingComponent) {
|
||||
this.chatContainer.removeChild(this.streamingComponent);
|
||||
this.streamingComponent = null;
|
||||
}
|
||||
|
||||
this.editor.disableSubmit = false;
|
||||
}
|
||||
|
||||
this.ui.requestRender();
|
||||
}
|
||||
|
||||
private addMessageToChat(message: Message): void {
|
||||
if (message.role === "user") {
|
||||
this.chatContainer.addChild(new TextComponent(chalk.green("[user]")));
|
||||
const userMsg = message as any;
|
||||
const textContent = userMsg.content?.map((c: any) => c.text || "").join("") || message.content || "";
|
||||
this.chatContainer.addChild(new TextComponent(textContent, { bottom: 1 }));
|
||||
} else if (message.role === "assistant") {
|
||||
this.chatContainer.addChild(new TextComponent(chalk.hex("#FFA500")("[assistant]")));
|
||||
const assistantMsg = message as AssistantMessage;
|
||||
|
||||
// Render text content
|
||||
const textContent = assistantMsg.content
|
||||
.filter((c) => c.type === "text")
|
||||
.map((c) => c.text)
|
||||
.join("");
|
||||
if (textContent) {
|
||||
this.chatContainer.addChild(new MarkdownComponent(textContent));
|
||||
}
|
||||
|
||||
// Render tool calls
|
||||
const toolCalls = assistantMsg.content.filter((c) => c.type === "toolCall");
|
||||
for (const toolCall of toolCalls) {
|
||||
const argsStr =
|
||||
typeof toolCall.arguments === "string" ? toolCall.arguments : JSON.stringify(toolCall.arguments);
|
||||
this.chatContainer.addChild(new TextComponent(chalk.yellow(`[tool] ${toolCall.name}(${argsStr})`)));
|
||||
}
|
||||
|
||||
this.chatContainer.addChild(new WhitespaceComponent(1));
|
||||
} else if (message.role === "toolResult") {
|
||||
const toolResultMsg = message as any;
|
||||
const output = toolResultMsg.result?.output || toolResultMsg.result || "";
|
||||
|
||||
// Truncate long outputs
|
||||
const lines = output.split("\n");
|
||||
const maxLines = 10;
|
||||
const truncated = lines.length > maxLines;
|
||||
const toShow = truncated ? lines.slice(0, maxLines) : lines;
|
||||
|
||||
for (const line of toShow) {
|
||||
this.chatContainer.addChild(new TextComponent(chalk.gray(line)));
|
||||
}
|
||||
|
||||
if (truncated) {
|
||||
this.chatContainer.addChild(new TextComponent(chalk.dim(`... (${lines.length - maxLines} more lines)`)));
|
||||
}
|
||||
this.chatContainer.addChild(new WhitespaceComponent(1));
|
||||
}
|
||||
}
|
||||
|
||||
async getUserInput(): Promise<string> {
|
||||
return new Promise((resolve) => {
|
||||
this.onInputCallback = (text: string) => {
|
||||
this.onInputCallback = undefined;
|
||||
resolve(text);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
setInterruptCallback(callback: () => void): void {
|
||||
this.onInterruptCallback = callback;
|
||||
}
|
||||
|
||||
clearEditor(): void {
|
||||
this.editor.setText("");
|
||||
this.statusContainer.clear();
|
||||
const hint = new TextComponent(chalk.dim("Press Ctrl+C again to exit"));
|
||||
this.statusContainer.addChild(hint);
|
||||
this.ui.requestRender();
|
||||
|
||||
setTimeout(() => {
|
||||
this.statusContainer.clear();
|
||||
this.ui.requestRender();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
if (this.loadingAnimation) {
|
||||
this.loadingAnimation.stop();
|
||||
this.loadingAnimation = null;
|
||||
}
|
||||
if (this.isInitialized) {
|
||||
this.ui.stop();
|
||||
this.isInitialized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue