- Conversation Loop:
- The system accepts user input via a CLI text prompt.
- Processes the input as an event in a stream and produces appropriate responses or actions.
- Waits for further user input after completing a round of actions, maintaining a dialog-style interaction.
- Event Types:
- User Input: Text entered by the user (e.g., questions, commands, or prompts).
- LLM Response: Response from an AI model (e.g., via xAI API or other providers).
- Tool Call: Invocation of external tools or functions (e.g., API calls, scripts).
- Tool Setup: Configuration or initialization of tools before use.
- Request User Approval: Prompt the user for confirmation (e.g., for sensitive actions).
- Command: Special CLI commands (e.g.,
login,exit,clear,free,pick model). - The system must be extensible to support additional event types.
- Event Handling:
- Events are processed asynchronously using modular handlers.
- Each event triggers a series of operations (e.g., API calls, UI updates, or state changes).
- The system supports branching logic (e.g., user input may lead to an LLM response or a command execution).
- Authentication:
- Supports authentication with the xAI API (e.g., API key or token).
- Extensible to support other LLM providers (e.g., OpenAI, Anthropic).
- Handles authentication-related events (e.g.,
logincommand, token refresh).
- Extensibility:
- New event types and actions can be added without modifying core logic.
- Modular design for integrating new tools, commands, or providers.
- Simple Async Style:
- Uses async/await for handling inputs and responses.
- Avoids complex reactive frameworks; keeps logic pure with modular functions.
- Language: TypeScript for type safety and maintainability.
- CLI Interface:
- Simple, text-based UI using Node.js (e.g.,
readlinefor input). - Clear feedback to the user (e.g., responses, errors, prompts).
- Simple, text-based UI using Node.js (e.g.,
- Performance: Low latency for user interactions; asynchronous handling of API calls.
- Error Handling: Graceful recovery from errors (e.g., API failures, invalid input).
- Modularity: Code organized for reusability and testing.
The main conversation loop is implemented as a simple async loop using readline in main.ts, where the system and user engage in a back-and-forth exchange. User input is processed directly, and the system responds with outputs like LLM responses, tool results, or prompts.
- Loop Abstraction: User inputs are handled sequentially in an async callback, with commands dispatched to handlers and prompts sent to LLM.
- Event Handling: Inputs are parsed and routed to modular functions (e.g., from
commands.ts). - Sources and Sinks:
- Sources: User input (CLI), API responses, tool outputs.
- Sinks: Console output, API requests, tool executions, state updates.
- Async Approach: Events are transformed using async functions. Side effects (e.g., printing to console, API calls) are isolated to specific modules.
Events are represented as a discriminated union in TypeScript for type safety and extensibility. Each event has a type and a payload.
The main conversation loop is driven by readline's "line" event in main.ts, merging inputs and processing them asynchronously.
The loop processes inputs directly, transforming them into outputs.
- Parse Inputs: Check if command (starts with
/) or prompt. - Dispatch to Handlers: Use modular functions for commands or LLM calls.
- Handle Side Effects: Route to console or external calls.
- Maintain State: Use simple cached variables (e.g., for config).
Keep the existing main.ts structure, extending with new handlers as needed.
- New Event Types: Add new interfaces to a potential
ParseEventunion (e.g.,CustomToolEvent). - New Handlers: Extend command map or add conditionals in the loop.
- New Providers: Update API calls to support different endpoints based on state.
- Plugins: Allow external modules to register new handlers via a registry.
- Login Command: Prompts for an API token, stores it in state.
- Provider Support: Use a provider registry (e.g.,
{ 'xAI': { url, authMethod } }) to handle different APIs. - Token Refresh: Add handling for providers requiring re-authentication.
- Invalid Input: Respond with error messages (e.g., “Invalid command”).
- API Failures: Catch and log errors.
- Loop Errors: Use try/catch in the input handler.
- Input: Use Node.js
readlinefor non-blocking input. - Output: Print responses, errors, and prompts to
stdout. - Prompt: Display a
>orParse>prompt after each response.
- Type Safety: Use TypeScript’s discriminated unions and strict typing to ensure handling is robust.
- Purity: Keep functions pure where possible; isolate side effects.
- Testing: Write unit tests for handlers using Jest.
- Modularity: Split code into modules (e.g.,
events.ts,handlers.ts). - Performance: Use async/await; debounce input if needed.