Add Chat Completions API support and expand REPL debugging

- Add NearAiChatProvider using /v1/chat/completions endpoint with API key auth
- Add NEARAI_API_KEY and NEARAI_API_MODE config options
- Auto-detect API mode from presence of API key
- Keep existing Responses API (NearAiProvider) for session-based auth
- Fix response parsing to accept input_text/output_text/text content types
- Expand REPL with /help, /debug toggle, colored output
- Better tool status display (dots vs verbose based on debug mode)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
Illia Polosukhin
2026-02-03 21:55:05 -08:00
co-authored by Claude Opus 4.5
parent 74d94d33b0
commit 7ef6362d83
8 changed files with 665 additions and 42 deletions
+4 -2
View File
@@ -228,8 +228,10 @@ impl AppState {
/// Add an error message to the chat.
pub fn add_error_message(&mut self, content: impl Into<String>) {
self.messages
.push(ChatMessage::system(format!("Error: {}", content.into())).with_status(MessageStatus::Error));
self.messages.push(
ChatMessage::system(format!("Error: {}", content.into()))
.with_status(MessageStatus::Error),
);
self.scroll_to_bottom();
}
+11 -8
View File
@@ -163,7 +163,9 @@ fn render_model_selector_inline(frame: &mut Frame, app: &AppState, area: Rect) {
if models.is_empty() {
spans.push(Span::styled(
"Loading models...",
Style::default().fg(Color::DarkGray).add_modifier(Modifier::ITALIC),
Style::default()
.fg(Color::DarkGray)
.add_modifier(Modifier::ITALIC),
));
} else {
for (i, model) in models.iter().enumerate() {
@@ -189,12 +191,14 @@ fn render_model_selector_inline(frame: &mut Frame, app: &AppState, area: Rect) {
}
let content = Paragraph::new(Line::from(spans))
.block(
Block::default()
.borders(Borders::ALL)
.title(Span::styled("Select Model", Style::default().fg(Color::Cyan))),
)
.scroll((0, calculate_model_scroll(overlay, area.width.saturating_sub(2))));
.block(Block::default().borders(Borders::ALL).title(Span::styled(
"Select Model",
Style::default().fg(Color::Cyan),
)))
.scroll((
0,
calculate_model_scroll(overlay, area.width.saturating_sub(2)),
));
frame.render_widget(content, area);
}
@@ -335,4 +339,3 @@ fn render_approval_overlay(frame: &mut Frame, app: &AppState) {
frame.render_widget(content, overlay_area);
}