snow-ai 0.3.4 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/api/anthropic.js +38 -13
  2. package/dist/api/types.d.ts +1 -0
  3. package/dist/hooks/useConversation.js +226 -59
  4. package/dist/hooks/useSnapshotState.d.ts +2 -0
  5. package/dist/hooks/useToolConfirmation.js +1 -1
  6. package/dist/mcp/subagent.d.ts +35 -0
  7. package/dist/mcp/subagent.js +64 -0
  8. package/dist/ui/components/ChatInput.d.ts +1 -2
  9. package/dist/ui/components/ChatInput.js +47 -39
  10. package/dist/ui/components/FileRollbackConfirmation.d.ts +3 -2
  11. package/dist/ui/components/FileRollbackConfirmation.js +81 -22
  12. package/dist/ui/components/MessageList.d.ts +7 -1
  13. package/dist/ui/components/MessageList.js +16 -5
  14. package/dist/ui/components/ToolResultPreview.js +21 -1
  15. package/dist/ui/pages/ChatScreen.js +29 -20
  16. package/dist/ui/pages/ConfigScreen.js +47 -46
  17. package/dist/ui/pages/ProxyConfigScreen.js +1 -1
  18. package/dist/ui/pages/SubAgentConfigScreen.d.ts +9 -0
  19. package/dist/ui/pages/SubAgentConfigScreen.js +352 -0
  20. package/dist/ui/pages/SubAgentListScreen.d.ts +9 -0
  21. package/dist/ui/pages/SubAgentListScreen.js +114 -0
  22. package/dist/ui/pages/WelcomeScreen.js +30 -2
  23. package/dist/utils/incrementalSnapshot.d.ts +7 -0
  24. package/dist/utils/incrementalSnapshot.js +34 -0
  25. package/dist/utils/mcpToolsManager.js +41 -1
  26. package/dist/utils/retryUtils.js +5 -0
  27. package/dist/utils/sessionConverter.d.ts +1 -0
  28. package/dist/utils/sessionConverter.js +192 -89
  29. package/dist/utils/subAgentConfig.d.ts +43 -0
  30. package/dist/utils/subAgentConfig.js +126 -0
  31. package/dist/utils/subAgentExecutor.d.ts +29 -0
  32. package/dist/utils/subAgentExecutor.js +272 -0
  33. package/dist/utils/toolExecutor.d.ts +10 -2
  34. package/dist/utils/toolExecutor.js +46 -5
  35. package/package.json +1 -1
  36. package/dist/ui/pages/ConfigProfileScreen.d.ts +0 -7
  37. package/dist/ui/pages/ConfigProfileScreen.js +0 -300
@@ -282,6 +282,7 @@ export async function* createStreamingAnthropicCompletion(options, abortSignal,
282
282
  let hasToolCalls = false;
283
283
  let usageData;
284
284
  let blockIndexToId = new Map();
285
+ let completedToolBlocks = new Set(); // Track which tool blocks have finished streaming
285
286
  for await (const event of parseSSEStream(response.body.getReader())) {
286
287
  if (abortSignal?.aborted) {
287
288
  return;
@@ -297,7 +298,7 @@ export async function* createStreamingAnthropicCompletion(options, abortSignal,
297
298
  type: 'function',
298
299
  function: {
299
300
  name: block.name,
300
- arguments: '{}'
301
+ arguments: ''
301
302
  }
302
303
  });
303
304
  yield {
@@ -323,20 +324,28 @@ export async function* createStreamingAnthropicCompletion(options, abortSignal,
323
324
  if (toolId) {
324
325
  const toolCall = toolCallsBuffer.get(toolId);
325
326
  if (toolCall) {
326
- if (toolCall.function.arguments === '{}') {
327
- toolCall.function.arguments = jsonDelta;
327
+ // Filter out any XML-like tags that might be mixed in the JSON delta
328
+ // This can happen when the model output contains XML that gets interpreted as JSON
329
+ const cleanedDelta = jsonDelta.replace(/<\/?parameter[^>]*>/g, '');
330
+ if (cleanedDelta) {
331
+ toolCall.function.arguments += cleanedDelta;
332
+ yield {
333
+ type: 'tool_call_delta',
334
+ delta: cleanedDelta
335
+ };
328
336
  }
329
- else {
330
- toolCall.function.arguments += jsonDelta;
331
- }
332
- yield {
333
- type: 'tool_call_delta',
334
- delta: jsonDelta
335
- };
336
337
  }
337
338
  }
338
339
  }
339
340
  }
341
+ else if (event.type === 'content_block_stop') {
342
+ // Mark this block as completed
343
+ const blockIndex = event.index;
344
+ const toolId = blockIndexToId.get(blockIndex);
345
+ if (toolId) {
346
+ completedToolBlocks.add(toolId);
347
+ }
348
+ }
340
349
  else if (event.type === 'message_start') {
341
350
  if (event.message.usage) {
342
351
  usageData = {
@@ -371,14 +380,30 @@ export async function* createStreamingAnthropicCompletion(options, abortSignal,
371
380
  if (hasToolCalls && toolCallsBuffer.size > 0) {
372
381
  const toolCalls = Array.from(toolCallsBuffer.values());
373
382
  for (const toolCall of toolCalls) {
383
+ // Normalize the arguments
384
+ let args = toolCall.function.arguments.trim();
385
+ // If arguments is empty, use empty object
386
+ if (!args) {
387
+ args = '{}';
388
+ }
389
+ // Try to parse the JSON
374
390
  try {
375
- const args = toolCall.function.arguments.trim() || '{}';
376
391
  JSON.parse(args);
377
392
  toolCall.function.arguments = args;
378
393
  }
379
394
  catch (e) {
380
- const errorMsg = e instanceof Error ? e.message : 'Unknown error';
381
- throw new Error(`Incomplete tool call JSON for ${toolCall.function.name}: ${toolCall.function.arguments} (${errorMsg})`);
395
+ // Only throw error if this tool block was marked as completed
396
+ // This prevents errors from incomplete streaming
397
+ if (completedToolBlocks.has(toolCall.id)) {
398
+ const errorMsg = e instanceof Error ? e.message : 'Unknown error';
399
+ throw new Error(`Invalid tool call JSON for ${toolCall.function.name}: ${args} (${errorMsg})`);
400
+ }
401
+ else {
402
+ // Tool block wasn't completed, likely interrupted stream
403
+ // Use partial data or empty object
404
+ console.warn(`Warning: Tool call ${toolCall.function.name} (${toolCall.id}) was incomplete. Using partial data.`);
405
+ toolCall.function.arguments = '{}';
406
+ }
382
407
  }
383
408
  }
384
409
  yield {
@@ -20,6 +20,7 @@ export interface ChatMessage {
20
20
  tool_call_id?: string;
21
21
  tool_calls?: ToolCall[];
22
22
  images?: ImageContent[];
23
+ subAgentInternal?: boolean;
23
24
  }
24
25
  export interface ChatCompletionTool {
25
26
  type: 'function';
@@ -46,10 +46,13 @@ export async function handleConversationWithTools(options) {
46
46
  }
47
47
  // Add history messages from session (includes tool_calls and tool results)
48
48
  // Load from session to get complete conversation history with tool interactions
49
+ // Filter out internal sub-agent messages (marked with subAgentInternal: true)
49
50
  const session = sessionManager.getCurrentSession();
50
51
  if (session && session.messages.length > 0) {
51
52
  // Use session messages directly (they are already in API format)
52
- conversationMessages.push(...session.messages);
53
+ // Filter out sub-agent internal messages before sending to API
54
+ const filteredMessages = session.messages.filter(msg => !msg.subAgentInternal);
55
+ conversationMessages.push(...filteredMessages);
53
56
  }
54
57
  // Add current user message
55
58
  conversationMessages.push({
@@ -336,8 +339,171 @@ export async function handleConversationWithTools(options) {
336
339
  // Add all tools to approved list
337
340
  approvedTools.push(...toolsNeedingConfirmation);
338
341
  }
339
- // Execute approved tools
340
- const toolResults = await executeToolCalls(approvedTools, controller.signal, setStreamTokenCount);
342
+ // Execute approved tools with sub-agent message callback
343
+ const toolResults = await executeToolCalls(approvedTools, controller.signal, setStreamTokenCount, async (subAgentMessage) => {
344
+ // Handle sub-agent messages - display and save to session
345
+ setMessages(prev => {
346
+ // Handle tool calls from sub-agent
347
+ if (subAgentMessage.message.type === 'tool_calls') {
348
+ const toolCalls = subAgentMessage.message.tool_calls;
349
+ if (toolCalls && toolCalls.length > 0) {
350
+ // Add tool call messages for each tool
351
+ const toolMessages = toolCalls.map((toolCall) => {
352
+ const toolDisplay = formatToolCallMessage(toolCall);
353
+ let toolArgs;
354
+ try {
355
+ toolArgs = JSON.parse(toolCall.function.arguments);
356
+ }
357
+ catch (e) {
358
+ toolArgs = {};
359
+ }
360
+ const uiMsg = {
361
+ role: 'subagent',
362
+ content: `\x1b[38;2;184;122;206m⚇⚡ ${toolDisplay.toolName}\x1b[0m`,
363
+ streaming: false,
364
+ toolCall: {
365
+ name: toolCall.function.name,
366
+ arguments: toolArgs,
367
+ },
368
+ toolDisplay,
369
+ toolCallId: toolCall.id,
370
+ toolPending: true,
371
+ subAgent: {
372
+ agentId: subAgentMessage.agentId,
373
+ agentName: subAgentMessage.agentName,
374
+ isComplete: false,
375
+ },
376
+ subAgentInternal: true, // Mark as internal sub-agent message
377
+ };
378
+ // Save to session as 'assistant' role for API compatibility
379
+ const sessionMsg = {
380
+ role: 'assistant',
381
+ content: `⚇⚡ ${toolDisplay.toolName}`,
382
+ subAgentInternal: true,
383
+ tool_calls: [toolCall],
384
+ };
385
+ saveMessage(sessionMsg).catch(err => console.error('Failed to save sub-agent tool call:', err));
386
+ return uiMsg;
387
+ });
388
+ return [...prev, ...toolMessages];
389
+ }
390
+ }
391
+ // Handle tool results from sub-agent
392
+ if (subAgentMessage.message.type === 'tool_result') {
393
+ const msg = subAgentMessage.message;
394
+ const isError = msg.content.startsWith('Error:');
395
+ const statusIcon = isError ? '✗' : '✓';
396
+ const statusText = isError ? `\n └─ ${msg.content}` : '';
397
+ // For terminal-execute, try to extract terminal result data
398
+ let terminalResultData;
399
+ if (msg.tool_name === 'terminal-execute' && !isError) {
400
+ try {
401
+ const resultData = JSON.parse(msg.content);
402
+ if (resultData.stdout !== undefined ||
403
+ resultData.stderr !== undefined) {
404
+ terminalResultData = {
405
+ stdout: resultData.stdout,
406
+ stderr: resultData.stderr,
407
+ exitCode: resultData.exitCode,
408
+ command: resultData.command,
409
+ };
410
+ }
411
+ }
412
+ catch (e) {
413
+ // If parsing fails, just show regular result
414
+ }
415
+ }
416
+ // Create completed tool result message for UI
417
+ const uiMsg = {
418
+ role: 'subagent',
419
+ content: `\x1b[38;2;0;186;255m⚇${statusIcon} ${msg.tool_name}\x1b[0m${statusText}`,
420
+ streaming: false,
421
+ toolResult: !isError ? msg.content : undefined,
422
+ terminalResult: terminalResultData,
423
+ toolCall: terminalResultData
424
+ ? {
425
+ name: msg.tool_name,
426
+ arguments: terminalResultData,
427
+ }
428
+ : undefined,
429
+ subAgent: {
430
+ agentId: subAgentMessage.agentId,
431
+ agentName: subAgentMessage.agentName,
432
+ isComplete: false,
433
+ },
434
+ subAgentInternal: true,
435
+ };
436
+ // Save to session as 'tool' role for API compatibility
437
+ const sessionMsg = {
438
+ role: 'tool',
439
+ tool_call_id: msg.tool_call_id,
440
+ content: msg.content,
441
+ subAgentInternal: true,
442
+ };
443
+ saveMessage(sessionMsg).catch(err => console.error('Failed to save sub-agent tool result:', err));
444
+ // Add completed tool result message
445
+ return [...prev, uiMsg];
446
+ }
447
+ // Check if we already have a message for this agent
448
+ const existingIndex = prev.findIndex(m => m.role === 'subagent' &&
449
+ m.subAgent?.agentId === subAgentMessage.agentId &&
450
+ !m.subAgent?.isComplete &&
451
+ !m.toolCall);
452
+ // Extract content from the sub-agent message
453
+ let content = '';
454
+ if (subAgentMessage.message.type === 'content') {
455
+ content = subAgentMessage.message.content;
456
+ }
457
+ else if (subAgentMessage.message.type === 'done') {
458
+ // Mark as complete
459
+ if (existingIndex !== -1) {
460
+ const updated = [...prev];
461
+ const existing = updated[existingIndex];
462
+ if (existing && existing.subAgent) {
463
+ updated[existingIndex] = {
464
+ ...existing,
465
+ subAgent: {
466
+ ...existing.subAgent,
467
+ isComplete: true,
468
+ },
469
+ };
470
+ }
471
+ return updated;
472
+ }
473
+ return prev;
474
+ }
475
+ if (existingIndex !== -1) {
476
+ // Update existing message
477
+ const updated = [...prev];
478
+ const existing = updated[existingIndex];
479
+ if (existing) {
480
+ updated[existingIndex] = {
481
+ ...existing,
482
+ content: (existing.content || '') + content,
483
+ streaming: true,
484
+ };
485
+ }
486
+ return updated;
487
+ }
488
+ else if (content) {
489
+ // Add new sub-agent message
490
+ return [
491
+ ...prev,
492
+ {
493
+ role: 'subagent',
494
+ content,
495
+ streaming: true,
496
+ subAgent: {
497
+ agentId: subAgentMessage.agentId,
498
+ agentName: subAgentMessage.agentName,
499
+ isComplete: false,
500
+ },
501
+ },
502
+ ];
503
+ }
504
+ return prev;
505
+ });
506
+ }, requestToolConfirmation, isToolAutoApproved, yoloMode);
341
507
  // Check if aborted during tool execution
342
508
  if (controller.signal.aborted) {
343
509
  freeEncoder();
@@ -355,10 +521,40 @@ export async function handleConversationWithTools(options) {
355
521
  }
356
522
  }
357
523
  }
524
+ // Remove only streaming sub-agent content messages (not tool-related messages)
525
+ // Keep sub-agent tool call and tool result messages for display
526
+ setMessages(prev => prev.filter(m => m.role !== 'subagent' ||
527
+ m.toolCall !== undefined ||
528
+ m.toolResult !== undefined ||
529
+ m.subAgentInternal === true));
358
530
  // Update existing tool call messages with results
359
531
  for (const result of toolResults) {
360
532
  const toolCall = receivedToolCalls.find(tc => tc.id === result.tool_call_id);
361
533
  if (toolCall) {
534
+ // Special handling for sub-agent tools - show completion message
535
+ // Pass the full JSON result to ToolResultPreview for proper parsing
536
+ if (toolCall.function.name.startsWith('subagent-')) {
537
+ const isError = result.content.startsWith('Error:');
538
+ const statusIcon = isError ? '✗' : '✓';
539
+ const statusText = isError ? `\n └─ ${result.content}` : '';
540
+ // Display subagent completion message in main flow
541
+ setMessages(prev => [
542
+ ...prev,
543
+ {
544
+ role: 'assistant',
545
+ content: `${statusIcon} ${toolCall.function.name}${statusText}`,
546
+ streaming: false,
547
+ // Pass the full result.content for ToolResultPreview to parse
548
+ toolResult: !isError ? result.content : undefined,
549
+ },
550
+ ]);
551
+ // Save the tool result to conversation history
552
+ conversationMessages.push(result);
553
+ saveMessage(result).catch(error => {
554
+ console.error('Failed to save tool result:', error);
555
+ });
556
+ continue;
557
+ }
362
558
  const isError = result.content.startsWith('Error:');
363
559
  const statusIcon = isError ? '✗' : '✓';
364
560
  const statusText = isError ? `\n └─ ${result.content}` : '';
@@ -384,63 +580,34 @@ export async function handleConversationWithTools(options) {
384
580
  // If parsing fails, just show regular result
385
581
  }
386
582
  }
387
- // Check if this is a terminal execution result
388
- let terminalResultData;
389
- if (toolCall.function.name === 'terminal-execute' && !isError) {
390
- try {
391
- const resultData = JSON.parse(result.content);
392
- if (resultData.command !== undefined) {
393
- terminalResultData = {
394
- stdout: resultData.stdout || '',
395
- stderr: resultData.stderr || '',
396
- exitCode: resultData.exitCode || 0,
397
- command: resultData.command,
398
- };
399
- }
400
- }
401
- catch (e) {
402
- // If parsing fails, just show regular result
403
- }
404
- }
405
- // Check if this tool should show preview (websearch, ace, filesystem-read, etc.)
406
- const shouldShowPreview = toolCall.function.name.startsWith('websearch-') ||
407
- toolCall.function.name.startsWith('ace-') ||
408
- toolCall.function.name === 'filesystem-read' ||
409
- toolCall.function.name === 'filesystem-list' ||
410
- toolCall.function.name === 'filesystem-create' ||
411
- toolCall.function.name === 'filesystem-write';
412
- // Update the existing pending message instead of adding a new one
413
- setMessages(prev => prev.map(msg => {
414
- if (msg.toolCallId === toolCall.id && msg.toolPending) {
415
- return {
416
- ...msg,
417
- content: `${statusIcon} ${toolCall.function.name}${statusText}`,
418
- toolPending: false,
419
- toolCall: editDiffData
420
- ? {
421
- name: toolCall.function.name,
422
- arguments: editDiffData,
423
- }
424
- : terminalResultData
425
- ? {
426
- name: toolCall.function.name,
427
- arguments: terminalResultData,
428
- }
429
- : shouldShowPreview
430
- ? undefined // Clear toolCall for preview-enabled tools
431
- : msg.toolCall, // Keep original toolCall for other tools
432
- // Store tool result for preview rendering
433
- toolResult: !isError ? result.content : undefined,
434
- };
435
- }
436
- return msg;
437
- }));
583
+ // Append completed message to static area (don't remove pending message)
584
+ // Static area doesn't support deletion, only append
585
+ // Completed message only shows diff data (for edit tools), no other parameters
586
+ setMessages(prev => [
587
+ ...prev,
588
+ // Add new completed message
589
+ {
590
+ role: 'assistant',
591
+ content: `${statusIcon} ${toolCall.function.name}${statusText}`,
592
+ streaming: false,
593
+ toolCall: editDiffData
594
+ ? {
595
+ name: toolCall.function.name,
596
+ arguments: editDiffData,
597
+ }
598
+ : undefined, // Don't show arguments for completed tools (already shown in pending)
599
+ // Store tool result for preview rendering
600
+ toolResult: !isError ? result.content : undefined,
601
+ },
602
+ ]);
603
+ }
604
+ // Add tool result to conversation history and save (skip if already saved above)
605
+ if (toolCall && !toolCall.function.name.startsWith('subagent-')) {
606
+ conversationMessages.push(result);
607
+ saveMessage(result).catch(error => {
608
+ console.error('Failed to save tool result:', error);
609
+ });
438
610
  }
439
- // Add tool result to conversation history and save
440
- conversationMessages.push(result);
441
- saveMessage(result).catch(error => {
442
- console.error('Failed to save tool result:', error);
443
- });
444
611
  }
445
612
  // After all tool results are processed, show TODO panel if there were todo-update calls
446
613
  if (hasTodoUpdateTools) {
@@ -4,9 +4,11 @@ export declare function useSnapshotState(messagesLength: number): {
4
4
  pendingRollback: {
5
5
  messageIndex: number;
6
6
  fileCount: number;
7
+ filePaths?: string[];
7
8
  } | null;
8
9
  setPendingRollback: import("react").Dispatch<import("react").SetStateAction<{
9
10
  messageIndex: number;
10
11
  fileCount: number;
12
+ filePaths?: string[];
11
13
  } | null>>;
12
14
  };
@@ -25,7 +25,7 @@ export function useToolConfirmation() {
25
25
  * Check if a tool is auto-approved
26
26
  */
27
27
  const isToolAutoApproved = (toolName) => {
28
- return alwaysApprovedTools.has(toolName) || toolName.startsWith('todo-');
28
+ return alwaysApprovedTools.has(toolName) || toolName.startsWith('todo-') || toolName.startsWith('subagent-');
29
29
  };
30
30
  /**
31
31
  * Add a tool to the always-approved list
@@ -0,0 +1,35 @@
1
+ import type { SubAgentMessage } from '../utils/subAgentExecutor.js';
2
+ import type { ToolCall } from '../utils/toolExecutor.js';
3
+ export interface SubAgentToolExecutionOptions {
4
+ agentId: string;
5
+ prompt: string;
6
+ onMessage?: (message: SubAgentMessage) => void;
7
+ abortSignal?: AbortSignal;
8
+ requestToolConfirmation?: (toolCall: ToolCall, batchToolNames?: string, allTools?: ToolCall[]) => Promise<string>;
9
+ isToolAutoApproved?: (toolName: string) => boolean;
10
+ yoloMode?: boolean;
11
+ }
12
+ /**
13
+ * Sub-Agent MCP Service
14
+ * Provides tools for executing sub-agents with their own specialized system prompts and tool access
15
+ */
16
+ export declare class SubAgentService {
17
+ /**
18
+ * Execute a sub-agent as a tool
19
+ */
20
+ execute(options: SubAgentToolExecutionOptions): Promise<any>;
21
+ /**
22
+ * Get all available sub-agents as MCP tools
23
+ */
24
+ getTools(): Array<{
25
+ name: string;
26
+ description: string;
27
+ inputSchema: any;
28
+ }>;
29
+ }
30
+ export declare const subAgentService: SubAgentService;
31
+ export declare function getMCPTools(): Array<{
32
+ name: string;
33
+ description: string;
34
+ inputSchema: any;
35
+ }>;
@@ -0,0 +1,64 @@
1
+ import { executeSubAgent } from '../utils/subAgentExecutor.js';
2
+ import { getSubAgents } from '../utils/subAgentConfig.js';
3
+ /**
4
+ * Sub-Agent MCP Service
5
+ * Provides tools for executing sub-agents with their own specialized system prompts and tool access
6
+ */
7
+ export class SubAgentService {
8
+ /**
9
+ * Execute a sub-agent as a tool
10
+ */
11
+ async execute(options) {
12
+ const { agentId, prompt, onMessage, abortSignal, requestToolConfirmation, isToolAutoApproved, yoloMode, } = options;
13
+ // Create a tool confirmation adapter for sub-agent if needed
14
+ const subAgentToolConfirmation = requestToolConfirmation
15
+ ? async (toolName, toolArgs) => {
16
+ // Create a fake tool call for confirmation
17
+ const fakeToolCall = {
18
+ id: 'subagent-tool',
19
+ type: 'function',
20
+ function: {
21
+ name: toolName,
22
+ arguments: JSON.stringify(toolArgs),
23
+ },
24
+ };
25
+ return await requestToolConfirmation(fakeToolCall);
26
+ }
27
+ : undefined;
28
+ const result = await executeSubAgent(agentId, prompt, onMessage, abortSignal, subAgentToolConfirmation, isToolAutoApproved, yoloMode);
29
+ if (!result.success) {
30
+ throw new Error(result.error || 'Sub-agent execution failed');
31
+ }
32
+ return {
33
+ success: true,
34
+ result: result.result,
35
+ };
36
+ }
37
+ /**
38
+ * Get all available sub-agents as MCP tools
39
+ */
40
+ getTools() {
41
+ const subAgents = getSubAgents();
42
+ return subAgents.map(agent => ({
43
+ name: agent.id,
44
+ description: `${agent.name}: ${agent.description}`,
45
+ inputSchema: {
46
+ type: 'object',
47
+ properties: {
48
+ prompt: {
49
+ type: 'string',
50
+ description: 'The task prompt to send to the sub-agent',
51
+ },
52
+ },
53
+ required: ['prompt'],
54
+ },
55
+ }));
56
+ }
57
+ }
58
+ // Export a default instance
59
+ export const subAgentService = new SubAgentService();
60
+ // MCP Tool definitions (dynamically generated from configuration)
61
+ // Note: These are generated at runtime, so we export a function instead of a constant
62
+ export function getMCPTools() {
63
+ return subAgentService.getTools();
64
+ }
@@ -20,7 +20,6 @@ type Props = {
20
20
  cacheReadTokens?: number;
21
21
  cachedTokens?: number;
22
22
  };
23
- snapshotFileCount?: Map<number, number>;
24
23
  };
25
- export default function ChatInput({ onSubmit, onCommand, placeholder, disabled, chatHistory, onHistorySelect, yoloMode, contextUsage, snapshotFileCount, }: Props): React.JSX.Element;
24
+ export default function ChatInput({ onSubmit, onCommand, placeholder, disabled, chatHistory, onHistorySelect, yoloMode, contextUsage, }: Props): React.JSX.Element;
26
25
  export {};