@nanocollective/nanocoder 1.14.2 → 1.15.0

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 (185) hide show
  1. package/README.md +103 -5
  2. package/dist/ai-sdk-client.d.ts +22 -0
  3. package/dist/ai-sdk-client.d.ts.map +1 -0
  4. package/dist/ai-sdk-client.js +385 -0
  5. package/dist/ai-sdk-client.js.map +1 -0
  6. package/dist/app.d.ts.map +1 -1
  7. package/dist/app.js +1 -1
  8. package/dist/app.js.map +1 -1
  9. package/dist/client-factory.d.ts.map +1 -1
  10. package/dist/client-factory.js +5 -5
  11. package/dist/client-factory.js.map +1 -1
  12. package/dist/commands/index.d.ts +1 -0
  13. package/dist/commands/index.d.ts.map +1 -1
  14. package/dist/commands/index.js +1 -0
  15. package/dist/commands/index.js.map +1 -1
  16. package/dist/commands/recommendations.js +1 -1
  17. package/dist/commands/recommendations.js.map +1 -1
  18. package/dist/commands/streaming.d.ts +3 -0
  19. package/dist/commands/streaming.d.ts.map +1 -0
  20. package/dist/commands/streaming.js +23 -0
  21. package/dist/commands/streaming.js.map +1 -0
  22. package/dist/commands.d.ts.map +1 -1
  23. package/dist/commands.js +17 -3
  24. package/dist/commands.js.map +1 -1
  25. package/dist/components/assistant-message.d.ts +0 -1
  26. package/dist/components/assistant-message.d.ts.map +1 -1
  27. package/dist/components/assistant-message.js +70 -122
  28. package/dist/components/assistant-message.js.map +1 -1
  29. package/dist/components/thinking-indicator.js +1 -1
  30. package/dist/components/thinking-indicator.js.map +1 -1
  31. package/dist/components/user-input.d.ts.map +1 -1
  32. package/dist/components/user-input.js +135 -27
  33. package/dist/components/user-input.js.map +1 -1
  34. package/dist/components/user-message.d.ts.map +1 -1
  35. package/dist/components/user-message.js +34 -1
  36. package/dist/components/user-message.js.map +1 -1
  37. package/dist/config/preferences.d.ts +2 -0
  38. package/dist/config/preferences.d.ts.map +1 -1
  39. package/dist/config/preferences.js +10 -0
  40. package/dist/config/preferences.js.map +1 -1
  41. package/dist/hooks/useAppInitialization.d.ts.map +1 -1
  42. package/dist/hooks/useAppInitialization.js +2 -1
  43. package/dist/hooks/useAppInitialization.js.map +1 -1
  44. package/dist/hooks/useChatHandler.d.ts +2 -0
  45. package/dist/hooks/useChatHandler.d.ts.map +1 -1
  46. package/dist/hooks/useChatHandler.js +59 -9
  47. package/dist/hooks/useChatHandler.js.map +1 -1
  48. package/dist/mcp/mcp-client.d.ts +20 -1
  49. package/dist/mcp/mcp-client.d.ts.map +1 -1
  50. package/dist/mcp/mcp-client.js +57 -0
  51. package/dist/mcp/mcp-client.js.map +1 -1
  52. package/dist/message-handler.d.ts.map +1 -1
  53. package/dist/message-handler.js +7 -2
  54. package/dist/message-handler.js.map +1 -1
  55. package/dist/tool-calling/index.d.ts +1 -1
  56. package/dist/tool-calling/index.d.ts.map +1 -1
  57. package/dist/tool-calling/index.js +1 -1
  58. package/dist/tool-calling/index.js.map +1 -1
  59. package/dist/tool-calling/json-parser.d.ts +19 -2
  60. package/dist/tool-calling/json-parser.d.ts.map +1 -1
  61. package/dist/tool-calling/json-parser.js +65 -28
  62. package/dist/tool-calling/json-parser.js.map +1 -1
  63. package/dist/tool-calling/json-parser.spec.d.ts +2 -0
  64. package/dist/tool-calling/json-parser.spec.d.ts.map +1 -0
  65. package/dist/tool-calling/json-parser.spec.js +518 -0
  66. package/dist/tool-calling/json-parser.spec.js.map +1 -0
  67. package/dist/tool-calling/tool-parser.d.ts +20 -0
  68. package/dist/tool-calling/tool-parser.d.ts.map +1 -0
  69. package/dist/tool-calling/tool-parser.js +58 -0
  70. package/dist/tool-calling/tool-parser.js.map +1 -0
  71. package/dist/tool-calling/tool-parser.spec.d.ts +2 -0
  72. package/dist/tool-calling/tool-parser.spec.d.ts.map +1 -0
  73. package/dist/tool-calling/tool-parser.spec.js +250 -0
  74. package/dist/tool-calling/tool-parser.spec.js.map +1 -0
  75. package/dist/tool-calling/xml-parser.d.ts +17 -0
  76. package/dist/tool-calling/xml-parser.d.ts.map +1 -1
  77. package/dist/tool-calling/xml-parser.js +101 -13
  78. package/dist/tool-calling/xml-parser.js.map +1 -1
  79. package/dist/tool-calling/xml-parser.spec.d.ts +2 -0
  80. package/dist/tool-calling/xml-parser.spec.d.ts.map +1 -0
  81. package/dist/tool-calling/xml-parser.spec.js +437 -0
  82. package/dist/tool-calling/xml-parser.spec.js.map +1 -0
  83. package/dist/tools/create-file.d.ts.map +1 -1
  84. package/dist/tools/create-file.js +26 -23
  85. package/dist/tools/create-file.js.map +1 -1
  86. package/dist/tools/delete-lines.d.ts.map +1 -1
  87. package/dist/tools/delete-lines.js +29 -27
  88. package/dist/tools/delete-lines.js.map +1 -1
  89. package/dist/tools/execute-bash.d.ts.map +1 -1
  90. package/dist/tools/execute-bash.js +21 -19
  91. package/dist/tools/execute-bash.js.map +1 -1
  92. package/dist/tools/fetch-url.d.ts.map +1 -1
  93. package/dist/tools/fetch-url.js +21 -19
  94. package/dist/tools/fetch-url.js.map +1 -1
  95. package/dist/tools/index.d.ts +2 -2
  96. package/dist/tools/index.d.ts.map +1 -1
  97. package/dist/tools/index.js +8 -6
  98. package/dist/tools/index.js.map +1 -1
  99. package/dist/tools/insert-lines.d.ts.map +1 -1
  100. package/dist/tools/insert-lines.js +29 -27
  101. package/dist/tools/insert-lines.js.map +1 -1
  102. package/dist/tools/read-file.d.ts.map +1 -1
  103. package/dist/tools/read-file.js +23 -19
  104. package/dist/tools/read-file.js.map +1 -1
  105. package/dist/tools/read-many-files.d.ts.map +1 -1
  106. package/dist/tools/read-many-files.js +24 -20
  107. package/dist/tools/read-many-files.js.map +1 -1
  108. package/dist/tools/replace-lines.d.ts.map +1 -1
  109. package/dist/tools/replace-lines.js +33 -31
  110. package/dist/tools/replace-lines.js.map +1 -1
  111. package/dist/tools/search-files.d.ts.map +1 -1
  112. package/dist/tools/search-files.js +33 -31
  113. package/dist/tools/search-files.js.map +1 -1
  114. package/dist/tools/tool-manager.d.ts +35 -19
  115. package/dist/tools/tool-manager.d.ts.map +1 -1
  116. package/dist/tools/tool-manager.js +63 -33
  117. package/dist/tools/tool-manager.js.map +1 -1
  118. package/dist/tools/tool-registry.d.ts +121 -0
  119. package/dist/tools/tool-registry.d.ts.map +1 -0
  120. package/dist/tools/tool-registry.js +195 -0
  121. package/dist/tools/tool-registry.js.map +1 -0
  122. package/dist/tools/web-search.d.ts.map +1 -1
  123. package/dist/tools/web-search.js +25 -23
  124. package/dist/tools/web-search.js.map +1 -1
  125. package/dist/types/config.d.ts +2 -1
  126. package/dist/types/config.d.ts.map +1 -1
  127. package/dist/types/core.d.ts +58 -3
  128. package/dist/types/core.d.ts.map +1 -1
  129. package/dist/types/core.js +2 -0
  130. package/dist/types/core.js.map +1 -1
  131. package/dist/utils/file-autocomplete.d.ts +31 -0
  132. package/dist/utils/file-autocomplete.d.ts.map +1 -0
  133. package/dist/utils/file-autocomplete.js +156 -0
  134. package/dist/utils/file-autocomplete.js.map +1 -0
  135. package/dist/utils/file-autocomplete.spec.d.ts +2 -0
  136. package/dist/utils/file-autocomplete.spec.d.ts.map +1 -0
  137. package/dist/utils/file-autocomplete.spec.js +142 -0
  138. package/dist/utils/file-autocomplete.spec.js.map +1 -0
  139. package/dist/utils/file-content-loader.d.ts +31 -0
  140. package/dist/utils/file-content-loader.d.ts.map +1 -0
  141. package/dist/utils/file-content-loader.js +142 -0
  142. package/dist/utils/file-content-loader.js.map +1 -0
  143. package/dist/utils/file-content-loader.spec.d.ts +2 -0
  144. package/dist/utils/file-content-loader.spec.d.ts.map +1 -0
  145. package/dist/utils/file-content-loader.spec.js +140 -0
  146. package/dist/utils/file-content-loader.spec.js.map +1 -0
  147. package/dist/utils/file-mention-handler.d.ts +21 -0
  148. package/dist/utils/file-mention-handler.d.ts.map +1 -0
  149. package/dist/utils/file-mention-handler.js +59 -0
  150. package/dist/utils/file-mention-handler.js.map +1 -0
  151. package/dist/utils/file-mention-handler.spec.d.ts +2 -0
  152. package/dist/utils/file-mention-handler.spec.d.ts.map +1 -0
  153. package/dist/utils/file-mention-handler.spec.js +147 -0
  154. package/dist/utils/file-mention-handler.spec.js.map +1 -0
  155. package/dist/utils/file-mention-parser.d.ts +40 -0
  156. package/dist/utils/file-mention-parser.d.ts.map +1 -0
  157. package/dist/utils/file-mention-parser.js +122 -0
  158. package/dist/utils/file-mention-parser.js.map +1 -0
  159. package/dist/utils/file-mention-parser.spec.d.ts +2 -0
  160. package/dist/utils/file-mention-parser.spec.d.ts.map +1 -0
  161. package/dist/utils/file-mention-parser.spec.js +149 -0
  162. package/dist/utils/file-mention-parser.spec.js.map +1 -0
  163. package/dist/utils/fuzzy-matching.d.ts +13 -0
  164. package/dist/utils/fuzzy-matching.d.ts.map +1 -0
  165. package/dist/utils/fuzzy-matching.js +127 -0
  166. package/dist/utils/fuzzy-matching.js.map +1 -0
  167. package/dist/utils/fuzzy-matching.spec.d.ts +2 -0
  168. package/dist/utils/fuzzy-matching.spec.d.ts.map +1 -0
  169. package/dist/utils/fuzzy-matching.spec.js +123 -0
  170. package/dist/utils/fuzzy-matching.spec.js.map +1 -0
  171. package/dist/utils/prompt-assembly.spec.js +100 -2
  172. package/dist/utils/prompt-assembly.spec.js.map +1 -1
  173. package/dist/utils/prompt-processor.d.ts +2 -2
  174. package/dist/utils/prompt-processor.d.ts.map +1 -1
  175. package/dist/utils/prompt-processor.js +24 -41
  176. package/dist/utils/prompt-processor.js.map +1 -1
  177. package/package.json +8 -5
  178. package/dist/langgraph-client.d.ts +0 -19
  179. package/dist/langgraph-client.d.ts.map +0 -1
  180. package/dist/langgraph-client.js +0 -295
  181. package/dist/langgraph-client.js.map +0 -1
  182. package/dist/mcp/mcp-tool-adapter.d.ts +0 -22
  183. package/dist/mcp/mcp-tool-adapter.d.ts.map +0 -1
  184. package/dist/mcp/mcp-tool-adapter.js +0 -50
  185. package/dist/mcp/mcp-tool-adapter.js.map +0 -1
package/README.md CHANGED
@@ -8,7 +8,7 @@ A local-first CLI coding agent that brings the power of agentic coding tools lik
8
8
 
9
9
  - [FAQs](#faqs)
10
10
  - [Installation](#installation)
11
- - [For Users (Recommended)](#for-users-recommended)
11
+ - [For Users](#for-users)
12
12
  - [For Development](#for-development)
13
13
  - [Configuration](#configuration)
14
14
  - [AI Provider Setup](#ai-provider-setup)
@@ -45,7 +45,9 @@ Firstly, we would love for you to be involved. You can get started contributing
45
45
 
46
46
  ## Installation
47
47
 
48
- ### For Users (Recommended)
48
+ ### For Users
49
+
50
+ #### NPM
49
51
 
50
52
  Install globally and use anywhere:
51
53
 
@@ -59,6 +61,59 @@ Then run in any directory:
59
61
  nanocoder
60
62
  ```
61
63
 
64
+ #### Homebrew (macOS/Linux)
65
+
66
+ Install using Homebrew tap:
67
+
68
+ ```bash
69
+ brew install nano-collective/nanocoder/nanocoder
70
+ ```
71
+
72
+ Then run in any directory:
73
+
74
+ ```bash
75
+ nanocoder
76
+ ```
77
+
78
+ To update:
79
+
80
+ ```bash
81
+ brew upgrade nanocoder
82
+ ```
83
+
84
+ #### Nix Flakes
85
+
86
+ Run Nanocoder directly using:
87
+
88
+ ```bash
89
+ # If you have flakes enabled in your Nix config:
90
+ nix run github:Nano-Collective/nanocoder
91
+
92
+ # If you don't have flakes enabled:
93
+ nix run --extra-experimental-features 'nix-command flakes' github:Nano-Collective/nanocoder
94
+ ```
95
+
96
+ Or install from `packages` output:
97
+
98
+ ```nix
99
+ # flake.nix
100
+ {
101
+ inputs = {
102
+ nanocoder = {
103
+ url = "github:Nano-Collective/nanocoder";
104
+ inputs.nixpkgs.follows = "nixpkgs";
105
+ };
106
+ };
107
+ }
108
+
109
+ # configuration.nix
110
+ { pkgs, inputs, system, ... }: {
111
+ environment.systemPackages = [
112
+ inputs.nanocoder.packages."${system}".default
113
+ ];
114
+ }
115
+ ```
116
+
62
117
  ### For Development
63
118
 
64
119
  If you want to contribute or modify Nanocoder:
@@ -100,7 +155,35 @@ npm run dev
100
155
 
101
156
  ### AI Provider Setup
102
157
 
103
- Nanocoder supports any OpenAI-compatible API through a unified provider configuration. Create `agents.config.json` in your **working directory** (where you run `nanocoder`):
158
+ Nanocoder supports any OpenAI-compatible API through a unified provider configuration.
159
+
160
+ **Configuration Methods:**
161
+
162
+ 1. **Interactive Setup (Recommended for new users)**: Run `/setup-config` inside Nanocoder for a guided wizard with provider templates
163
+ 2. **Manual Configuration**: Create an `agents.config.json` file (see below for locations)
164
+
165
+ **Configuration File Locations:**
166
+
167
+ Nanocoder looks for configuration in the following order (first found wins):
168
+
169
+ 1. **Project-level** (highest priority): `agents.config.json` in your current working directory
170
+
171
+ - Use this for project-specific providers, models, or API keys
172
+ - Perfect for team sharing or repository-specific configurations
173
+
174
+ 2. **User-level (preferred)**: Platform-specific application data directory
175
+
176
+ - **macOS**: `~/Library/Preferences/nanocoder/agents.config.json`
177
+ - **Linux/Unix**: `~/.config/nanocoder/agents.config.json`
178
+ - **Windows**: `%APPDATA%\nanocoder\agents.config.json`
179
+ - Your global default configuration
180
+ - Used when no project-level config exists
181
+
182
+ 3. **User-level (legacy)**: `~/.agents.config.json`
183
+ - Supported for backward compatibility
184
+ - Recommended to migrate to platform-specific location above
185
+
186
+ **Example Configuration** (`agents.config.json`):
104
187
 
105
188
  ```json
106
189
  {
@@ -277,11 +360,22 @@ Popular MCP servers:
277
360
  - **Memory**: Persistent context storage
278
361
  - [View more MCP servers](https://github.com/modelcontextprotocol/servers)
279
362
 
280
- > **Note**: The default save place for configuration is `~/config/nanocoder/`. You can also place an `agents.config.json` where you run Nanocoder. This will **override** the default for project-by-project configuration with different models or API keys per repository.
363
+ > **Note**: MCP server configuration follows the same location hierarchy as AI provider setup above. Use `/setup-config` for an interactive configuration wizard, or manually edit `agents.config.json` at the project level (current directory) or user level (platform-specific paths listed above).
281
364
 
282
365
  ### User Preferences
283
366
 
284
- Nanocoder automatically saves your preferences to remember your choices across sessions. Preferences are stored in `~/config/nanocoder/nanocoder-preferences.json`. You can also place a `nanocoder-preferences.json` where you run Nanocoder. This will **override** the default for project-by-project configuration.
367
+ Nanocoder automatically saves your preferences to remember your choices across sessions.
368
+
369
+ **Preferences File Locations:**
370
+
371
+ Preferences follow the same location hierarchy as configuration files:
372
+
373
+ 1. **Project-level**: `nanocoder-preferences.json` in your current working directory (overrides user-level)
374
+ 2. **User-level**: Platform-specific application data directory:
375
+ - **macOS**: `~/Library/Preferences/nanocoder/nanocoder-preferences.json`
376
+ - **Linux/Unix**: `~/.config/nanocoder/nanocoder-preferences.json`
377
+ - **Windows**: `%APPDATA%\nanocoder\nanocoder-preferences.json`
378
+ 3. **Legacy**: `~/.nanocoder-preferences.json` (backward compatibility)
285
379
 
286
380
  **What gets saved automatically:**
287
381
 
@@ -289,6 +383,7 @@ Nanocoder automatically saves your preferences to remember your choices across s
289
383
  - **Last model per provider**: Your preferred model for each provider
290
384
  - **Session continuity**: Automatically switches back to your preferred provider/model when restarting
291
385
  - **Last theme used**: The theme you last selected
386
+ - **Streaming preference**: Whether response streaming is enabled (toggle with `/streaming` command)
292
387
 
293
388
  **Manual management:**
294
389
 
@@ -306,6 +401,7 @@ Nanocoder automatically saves your preferences to remember your choices across s
306
401
  - `/model` - Switch between available models
307
402
  - `/provider` - Switch between configured AI providers
308
403
  - `/status` - Display current status (CWD, provider, model, theme, available updates, AGENTS setup)
404
+ - `/streaming` - Toggle response streaming on/off (streams tokens in real-time when enabled)
309
405
  - `/recommendations` - Get AI model recommendations based on your system capabilities (RAM, GPU, network)
310
406
  - `/mcp` - Show connected MCP servers and their tools
311
407
  - `/custom-commands` - List all custom commands
@@ -314,6 +410,7 @@ Nanocoder automatically saves your preferences to remember your choices across s
314
410
  - `/theme` - Select a theme for the Nanocoder CLI
315
411
  - `/update` - Update Nanocoder to the latest version
316
412
  - `!command` - Execute bash commands directly without leaving Nanocoder (output becomes context for the LLM)
413
+ - `@file` - Include file contents in messages automatically via fuzzy search as you type.
317
414
 
318
415
  #### Custom Commands
319
416
 
@@ -387,6 +484,7 @@ Generate comprehensive unit tests for {{component}}. Include:
387
484
  - **Smart autocomplete**: Tab completion for commands with real-time suggestions
388
485
  - **Colorized output**: Syntax highlighting and structured display
389
486
  - **Session persistence**: Maintains context and preferences across sessions
487
+ - **Real-time streaming**: Live token-by-token streaming of AI responses (toggle with `/streaming`)
390
488
  - **Real-time indicators**: Shows token usage, timing, and processing status
391
489
  - **First-time directory security disclaimer**: Prompts on first run and stores a per-project trust decision to prevent accidental exposure of local code or secrets.
392
490
  - **Development modes**: Three modes to control tool execution behavior (toggle with Shift+Tab)
@@ -0,0 +1,22 @@
1
+ import type { AIProviderConfig, LLMChatResponse, LLMClient, Message, AISDKCoreTool, StreamCallbacks } from './types/index.js';
2
+ export declare class AISDKClient implements LLMClient {
3
+ private provider;
4
+ private currentModel;
5
+ private availableModels;
6
+ private providerConfig;
7
+ private undiciAgent;
8
+ constructor(providerConfig: AIProviderConfig);
9
+ static create(providerConfig: AIProviderConfig): Promise<AISDKClient>;
10
+ private createProvider;
11
+ setModel(model: string): void;
12
+ getCurrentModel(): string;
13
+ getContextSize(): number;
14
+ getAvailableModels(): Promise<string[]>;
15
+ chat(messages: Message[], tools: Record<string, AISDKCoreTool>, signal?: AbortSignal): Promise<LLMChatResponse>;
16
+ /**
17
+ * Stream chat with real-time token updates
18
+ */
19
+ chatStream(messages: Message[], tools: Record<string, AISDKCoreTool>, callbacks: StreamCallbacks, signal?: AbortSignal): Promise<LLMChatResponse>;
20
+ clearContext(): Promise<void>;
21
+ }
22
+ //# sourceMappingURL=ai-sdk-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-sdk-client.d.ts","sourceRoot":"","sources":["../source/ai-sdk-client.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACX,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,OAAO,EAEP,aAAa,EACb,eAAe,EACf,MAAM,eAAe,CAAC;AAwHvB,qBAAa,WAAY,YAAW,SAAS;IAC5C,OAAO,CAAC,QAAQ,CAA4C;IAC5D,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAW;IAClC,OAAO,CAAC,cAAc,CAAmB;IACzC,OAAO,CAAC,WAAW,CAAQ;gBAEf,cAAc,EAAE,gBAAgB;IA0B5C,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;IAKrE,OAAO,CAAC,cAAc;IAgCtB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B,eAAe,IAAI,MAAM;IAIzB,cAAc,IAAI,MAAM;IAMxB,kBAAkB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAIjC,IAAI,CACT,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,EACpC,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,eAAe,CAAC;IA8G3B;;OAEG;IACG,UAAU,CACf,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,EACpC,SAAS,EAAE,eAAe,EAC1B,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,eAAe,CAAC;IAiIrB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CAGnC"}
@@ -0,0 +1,385 @@
1
+ import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
2
+ import { generateText, streamText } from 'ai';
3
+ import { Agent, fetch as undiciFetch } from 'undici';
4
+ import { XMLToolCallParser } from './tool-calling/xml-parser.js';
5
+ /**
6
+ * Parses API errors into user-friendly messages
7
+ */
8
+ function parseAPIError(error) {
9
+ if (!(error instanceof Error)) {
10
+ return 'An unknown error occurred while communicating with the model';
11
+ }
12
+ const errorMessage = error.message;
13
+ // Extract status code and clean message from common error patterns
14
+ const statusMatch = errorMessage.match(/(?:Error: )?(\d{3})\s+(?:\d{3}\s+)?(?:Bad Request|[^:]+):\s*(.+)/i);
15
+ if (statusMatch) {
16
+ const [, statusCode, message] = statusMatch;
17
+ const cleanMessage = message.trim();
18
+ switch (statusCode) {
19
+ case '400':
20
+ return `Bad request: ${cleanMessage}`;
21
+ case '401':
22
+ return 'Authentication failed: Invalid API key or credentials';
23
+ case '403':
24
+ return 'Access forbidden: Check your API permissions';
25
+ case '404':
26
+ return 'Model not found: The requested model may not exist or is unavailable';
27
+ case '429':
28
+ return 'Rate limit exceeded: Too many requests. Please wait and try again';
29
+ case '500':
30
+ case '502':
31
+ case '503':
32
+ return `Server error: ${cleanMessage}`;
33
+ default:
34
+ return `Request failed (${statusCode}): ${cleanMessage}`;
35
+ }
36
+ }
37
+ // Handle timeout errors
38
+ if (errorMessage.includes('timeout') || errorMessage.includes('ETIMEDOUT')) {
39
+ return 'Request timed out: The model took too long to respond';
40
+ }
41
+ // Handle network errors
42
+ if (errorMessage.includes('ECONNREFUSED') ||
43
+ errorMessage.includes('connect')) {
44
+ return 'Connection failed: Unable to reach the model server';
45
+ }
46
+ // Handle context length errors
47
+ if (errorMessage.includes('context length') ||
48
+ errorMessage.includes('too many tokens')) {
49
+ return 'Context too large: Please reduce the conversation length or message size';
50
+ }
51
+ // Handle token limit errors
52
+ if (errorMessage.includes('reduce the number of tokens')) {
53
+ return 'Too many tokens: Please shorten your message or clear conversation history';
54
+ }
55
+ // If we can't parse it, return a cleaned up version
56
+ return errorMessage.replace(/^Error:\s*/i, '').split('\n')[0];
57
+ }
58
+ /**
59
+ * Convert our Message format to AI SDK v5 ModelMessage format
60
+ *
61
+ * Tool messages: Converted to user messages with [Tool: name] prefix.
62
+ * This approach is simpler and avoids issues with orphaned tool results
63
+ * in multi-turn conversations.
64
+ */
65
+ function convertToModelMessages(messages) {
66
+ return messages.map((msg) => {
67
+ if (msg.role === 'tool') {
68
+ // Convert tool results to user messages with clear labeling
69
+ const toolName = msg.name || 'unknown_tool';
70
+ return {
71
+ role: 'user',
72
+ content: `[Tool: ${toolName}]\n${msg.content}`,
73
+ };
74
+ }
75
+ if (msg.role === 'system') {
76
+ return {
77
+ role: 'system',
78
+ content: msg.content,
79
+ };
80
+ }
81
+ if (msg.role === 'user') {
82
+ return {
83
+ role: 'user',
84
+ content: msg.content,
85
+ };
86
+ }
87
+ if (msg.role === 'assistant') {
88
+ return {
89
+ role: 'assistant',
90
+ content: msg.content,
91
+ // Note: tool_calls are handled separately by AI SDK
92
+ // They come from the response, not the input messages
93
+ };
94
+ }
95
+ // Fallback - should never happen
96
+ return {
97
+ role: 'user',
98
+ content: msg.content,
99
+ };
100
+ });
101
+ }
102
+ export class AISDKClient {
103
+ provider;
104
+ currentModel;
105
+ availableModels;
106
+ providerConfig;
107
+ undiciAgent;
108
+ constructor(providerConfig) {
109
+ this.providerConfig = providerConfig;
110
+ this.availableModels = providerConfig.models;
111
+ this.currentModel = providerConfig.models[0] || '';
112
+ const { requestTimeout, socketTimeout, connectionPool } = this.providerConfig;
113
+ const resolvedSocketTimeout = socketTimeout === -1
114
+ ? 0
115
+ : socketTimeout || requestTimeout === -1
116
+ ? 0
117
+ : requestTimeout || 120000;
118
+ this.undiciAgent = new Agent({
119
+ connect: {
120
+ timeout: resolvedSocketTimeout,
121
+ },
122
+ bodyTimeout: resolvedSocketTimeout,
123
+ headersTimeout: resolvedSocketTimeout,
124
+ keepAliveTimeout: connectionPool?.idleTimeout,
125
+ keepAliveMaxTimeout: connectionPool?.cumulativeMaxIdleTimeout,
126
+ });
127
+ this.provider = this.createProvider();
128
+ }
129
+ static create(providerConfig) {
130
+ const client = new AISDKClient(providerConfig);
131
+ return Promise.resolve(client);
132
+ }
133
+ createProvider() {
134
+ const { config } = this.providerConfig;
135
+ // Custom fetch using undici
136
+ const customFetch = (url, options) => {
137
+ // Type cast to string | URL since undici's fetch accepts these types
138
+ // Request objects are converted to URL internally by the fetch spec
139
+ return undiciFetch(url, {
140
+ ...options,
141
+ dispatcher: this.undiciAgent,
142
+ });
143
+ };
144
+ // Add OpenRouter-specific headers for app attribution
145
+ const headers = {};
146
+ if (this.providerConfig.name.toLowerCase() === 'openrouter') {
147
+ headers['HTTP-Referer'] = 'https://github.com/Nano-Collective/nanocoder';
148
+ headers['X-Title'] = 'Nanocoder';
149
+ }
150
+ return createOpenAICompatible({
151
+ name: this.providerConfig.name,
152
+ baseURL: config.baseURL ?? '',
153
+ apiKey: config.apiKey ?? 'dummy-key',
154
+ fetch: customFetch,
155
+ headers,
156
+ });
157
+ }
158
+ setModel(model) {
159
+ this.currentModel = model;
160
+ }
161
+ getCurrentModel() {
162
+ return this.currentModel;
163
+ }
164
+ getContextSize() {
165
+ // Context size is not available without external model metadata service
166
+ // This method is kept for LLMClient interface compatibility but always returns 0
167
+ return 0;
168
+ }
169
+ getAvailableModels() {
170
+ return Promise.resolve(this.availableModels);
171
+ }
172
+ async chat(messages, tools, signal) {
173
+ // Check if already aborted before starting
174
+ if (signal?.aborted) {
175
+ throw new Error('Operation was cancelled');
176
+ }
177
+ try {
178
+ // Get the language model instance from the provider
179
+ const model = this.provider(this.currentModel);
180
+ // Tools are already in AI SDK format - use directly
181
+ const aiTools = Object.keys(tools).length > 0 ? tools : undefined;
182
+ // Convert messages to AI SDK v5 ModelMessage format
183
+ const modelMessages = convertToModelMessages(messages);
184
+ // Use generateText for non-streaming
185
+ const result = await generateText({
186
+ model,
187
+ messages: modelMessages,
188
+ tools: aiTools,
189
+ abortSignal: signal,
190
+ });
191
+ // Extract tool calls from result
192
+ const toolCalls = [];
193
+ if (result.toolCalls && result.toolCalls.length > 0) {
194
+ for (const toolCall of result.toolCalls) {
195
+ toolCalls.push({
196
+ id: toolCall.toolCallId,
197
+ function: {
198
+ name: toolCall.toolName,
199
+ // AI SDK v5 uses 'input' for tool arguments
200
+ arguments: toolCall.input,
201
+ },
202
+ });
203
+ }
204
+ }
205
+ // If no native tool calls but tools are available, try XML parsing
206
+ let content = result.text;
207
+ if (Object.keys(tools).length > 0 && toolCalls.length === 0 && content) {
208
+ // First check for malformed XML tool calls
209
+ const malformedError = XMLToolCallParser.detectMalformedToolCall(content);
210
+ if (malformedError) {
211
+ // Return malformed tool call with validation error
212
+ // This mimics how validators work - returns tool call that will show error
213
+ toolCalls.push({
214
+ id: 'malformed_xml_validation',
215
+ function: {
216
+ name: '__xml_validation_error__',
217
+ arguments: {
218
+ error: malformedError.error,
219
+ },
220
+ },
221
+ });
222
+ content = ''; // Clear content since it was malformed
223
+ }
224
+ else if (XMLToolCallParser.hasToolCalls(content)) {
225
+ // Try to parse well-formed XML tool calls
226
+ const parsedToolCalls = XMLToolCallParser.parseToolCalls(content);
227
+ const xmlToolCalls = XMLToolCallParser.convertToToolCalls(parsedToolCalls);
228
+ const cleanedContent = XMLToolCallParser.removeToolCallsFromContent(content);
229
+ content = cleanedContent;
230
+ toolCalls.push(...xmlToolCalls);
231
+ }
232
+ }
233
+ return {
234
+ choices: [
235
+ {
236
+ message: {
237
+ role: 'assistant',
238
+ content,
239
+ tool_calls: toolCalls.length > 0 ? toolCalls : undefined,
240
+ },
241
+ },
242
+ ],
243
+ };
244
+ }
245
+ catch (error) {
246
+ // Check if this was a cancellation
247
+ if (error instanceof Error && error.name === 'AbortError') {
248
+ throw new Error('Operation was cancelled');
249
+ }
250
+ // Check for AI SDK's NoOutputGeneratedError (thrown when stream is aborted)
251
+ if (error instanceof Error &&
252
+ (error.name === 'AI_NoOutputGeneratedError' ||
253
+ error.message.includes('No output generated'))) {
254
+ throw new Error('Operation was cancelled');
255
+ }
256
+ // Log detailed error for debugging
257
+ console.error('AI SDK Error:', error);
258
+ if (error instanceof Error) {
259
+ console.error('Error message:', error.message);
260
+ console.error('Error stack:', error.stack);
261
+ }
262
+ // Parse and throw a user-friendly error
263
+ const userMessage = parseAPIError(error);
264
+ throw new Error(userMessage);
265
+ }
266
+ }
267
+ /**
268
+ * Stream chat with real-time token updates
269
+ */
270
+ async chatStream(messages, tools, callbacks, signal) {
271
+ // Check if already aborted before starting
272
+ if (signal?.aborted) {
273
+ throw new Error('Operation was cancelled');
274
+ }
275
+ try {
276
+ // Get the language model instance from the provider
277
+ const model = this.provider(this.currentModel);
278
+ // Tools are already in AI SDK format - use directly
279
+ const aiTools = Object.keys(tools).length > 0 ? tools : undefined;
280
+ // Convert messages to AI SDK v5 ModelMessage format
281
+ const modelMessages = convertToModelMessages(messages);
282
+ // Use streamText for streaming
283
+ const result = streamText({
284
+ model,
285
+ messages: modelMessages,
286
+ tools: aiTools,
287
+ abortSignal: signal,
288
+ });
289
+ // Stream tokens
290
+ let fullText = '';
291
+ for await (const chunk of result.textStream) {
292
+ fullText += chunk;
293
+ callbacks.onToken?.(chunk);
294
+ }
295
+ // Wait for completion to get tool calls
296
+ const toolCallsResult = await result.toolCalls;
297
+ // Extract tool calls
298
+ const toolCalls = [];
299
+ if (toolCallsResult && toolCallsResult.length > 0) {
300
+ for (const toolCall of toolCallsResult) {
301
+ const tc = {
302
+ id: toolCall.toolCallId,
303
+ function: {
304
+ name: toolCall.toolName,
305
+ // AI SDK v5 uses 'input' for tool arguments
306
+ arguments: toolCall.input,
307
+ },
308
+ };
309
+ toolCalls.push(tc);
310
+ callbacks.onToolCall?.(tc);
311
+ }
312
+ }
313
+ // Check for XML tool calls if no native ones
314
+ let content = fullText;
315
+ if (Object.keys(tools).length > 0 && toolCalls.length === 0 && content) {
316
+ // First check for malformed XML tool calls
317
+ const malformedError = XMLToolCallParser.detectMalformedToolCall(content);
318
+ if (malformedError) {
319
+ // Return malformed tool call with validation error
320
+ // This mimics how validators work - returns tool call that will show error
321
+ const malformedCall = {
322
+ id: 'malformed_xml_validation',
323
+ function: {
324
+ name: '__xml_validation_error__',
325
+ arguments: {
326
+ error: malformedError.error,
327
+ },
328
+ },
329
+ };
330
+ toolCalls.push(malformedCall);
331
+ callbacks.onToolCall?.(malformedCall);
332
+ content = ''; // Clear content since it was malformed
333
+ }
334
+ else if (XMLToolCallParser.hasToolCalls(content)) {
335
+ // Try to parse well-formed XML tool calls
336
+ const parsedToolCalls = XMLToolCallParser.parseToolCalls(content);
337
+ const xmlToolCalls = XMLToolCallParser.convertToToolCalls(parsedToolCalls);
338
+ const cleanedContent = XMLToolCallParser.removeToolCallsFromContent(content);
339
+ content = cleanedContent;
340
+ for (const tc of xmlToolCalls) {
341
+ toolCalls.push(tc);
342
+ callbacks.onToolCall?.(tc);
343
+ }
344
+ }
345
+ }
346
+ callbacks.onFinish?.();
347
+ return {
348
+ choices: [
349
+ {
350
+ message: {
351
+ role: 'assistant',
352
+ content,
353
+ tool_calls: toolCalls.length > 0 ? toolCalls : undefined,
354
+ },
355
+ },
356
+ ],
357
+ };
358
+ }
359
+ catch (error) {
360
+ // Check if this was a cancellation
361
+ if (error instanceof Error && error.name === 'AbortError') {
362
+ throw new Error('Operation was cancelled');
363
+ }
364
+ // Check for AI SDK's NoOutputGeneratedError (thrown when stream is aborted)
365
+ if (error instanceof Error &&
366
+ (error.name === 'AI_NoOutputGeneratedError' ||
367
+ error.message.includes('No output generated'))) {
368
+ throw new Error('Operation was cancelled');
369
+ }
370
+ // Log detailed error for debugging
371
+ console.error('AI SDK Error:', error);
372
+ if (error instanceof Error) {
373
+ console.error('Error message:', error.message);
374
+ console.error('Error stack:', error.stack);
375
+ }
376
+ // Parse and throw a user-friendly error
377
+ const userMessage = parseAPIError(error);
378
+ throw new Error(userMessage);
379
+ }
380
+ }
381
+ async clearContext() {
382
+ // No internal state to clear
383
+ }
384
+ }
385
+ //# sourceMappingURL=ai-sdk-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-sdk-client.js","sourceRoot":"","sources":["../source/ai-sdk-client.ts"],"names":[],"mappings":"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"}
package/dist/app.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../source/app.tsx"],"names":[],"mappings":"AAqCA,MAAM,CAAC,OAAO,UAAU,GAAG,4CAyW1B"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../source/app.tsx"],"names":[],"mappings":"AAqCA,MAAM,CAAC,OAAO,UAAU,GAAG,4CAoX1B"}
package/dist/app.js CHANGED
@@ -225,7 +225,7 @@ export default function App() {
225
225
  if (!isTrusted) {
226
226
  return (_jsx(SecurityDisclaimer, { onConfirm: handleConfirmTrust, onExit: handleExit }));
227
227
  }
228
- return (_jsx(ThemeContext.Provider, { value: themeContextValue, children: _jsx(UIStateProvider, { children: _jsxs(Box, { flexDirection: "column", padding: 1, width: "100%", children: [_jsx(Box, { flexGrow: 1, flexDirection: "column", minHeight: 0, children: appState.startChat && (_jsx(ChatQueue, { staticComponents: staticComponents, queuedComponents: appState.chatComponents })) }), appState.startChat && (_jsxs(Box, { flexDirection: "column", marginLeft: -1, children: [appState.isCancelling ? (_jsx(CancellingIndicator, {})) : appState.isThinking ? (_jsx(ThinkingIndicator, {})) : null, appState.isModelSelectionMode ? (_jsx(ModelSelector, { client: appState.client, currentModel: appState.currentModel, onModelSelect: model => void modeHandlers.handleModelSelect(model), onCancel: modeHandlers.handleModelSelectionCancel })) : appState.isProviderSelectionMode ? (_jsx(ProviderSelector, { currentProvider: appState.currentProvider, onProviderSelect: provider => void modeHandlers.handleProviderSelect(provider), onCancel: modeHandlers.handleProviderSelectionCancel })) : appState.isThemeSelectionMode ? (_jsx(ThemeSelector, { onThemeSelect: modeHandlers.handleThemeSelect, onCancel: modeHandlers.handleThemeSelectionCancel })) : appState.isRecommendationsMode ? (_jsx(RecommendationsDisplay, { onCancel: modeHandlers.handleRecommendationsCancel })) : appState.isConfigWizardMode ? (_jsx(ConfigWizard, { projectDir: process.cwd(), onComplete: configPath => void modeHandlers.handleConfigWizardComplete(configPath), onCancel: modeHandlers.handleConfigWizardCancel })) : appState.isToolConfirmationMode &&
228
+ return (_jsx(ThemeContext.Provider, { value: themeContextValue, children: _jsx(UIStateProvider, { children: _jsxs(Box, { flexDirection: "column", padding: 1, width: "100%", children: [_jsx(Box, { flexGrow: 1, flexDirection: "column", minHeight: 0, children: appState.startChat && (_jsx(ChatQueue, { staticComponents: staticComponents, queuedComponents: appState.chatComponents })) }), appState.startChat && (_jsxs(Box, { flexDirection: "column", marginLeft: -1, children: [appState.isCancelling ? (_jsx(CancellingIndicator, {})) : appState.isThinking && !chatHandler.isStreaming ? (_jsx(ThinkingIndicator, {})) : null, chatHandler.isStreaming && chatHandler.streamingContent && (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: themeContextValue.colors.primary, bold: true, children: [appState.currentModel, ":"] }) }), _jsx(Text, { children: chatHandler.streamingContent })] })), appState.isModelSelectionMode ? (_jsx(ModelSelector, { client: appState.client, currentModel: appState.currentModel, onModelSelect: model => void modeHandlers.handleModelSelect(model), onCancel: modeHandlers.handleModelSelectionCancel })) : appState.isProviderSelectionMode ? (_jsx(ProviderSelector, { currentProvider: appState.currentProvider, onProviderSelect: provider => void modeHandlers.handleProviderSelect(provider), onCancel: modeHandlers.handleProviderSelectionCancel })) : appState.isThemeSelectionMode ? (_jsx(ThemeSelector, { onThemeSelect: modeHandlers.handleThemeSelect, onCancel: modeHandlers.handleThemeSelectionCancel })) : appState.isRecommendationsMode ? (_jsx(RecommendationsDisplay, { onCancel: modeHandlers.handleRecommendationsCancel })) : appState.isConfigWizardMode ? (_jsx(ConfigWizard, { projectDir: process.cwd(), onComplete: configPath => void modeHandlers.handleConfigWizardComplete(configPath), onCancel: modeHandlers.handleConfigWizardCancel })) : appState.isToolConfirmationMode &&
229
229
  appState.pendingToolCalls[appState.currentToolIndex] ? (_jsx(ToolConfirmation, { toolCall: appState.pendingToolCalls[appState.currentToolIndex], onConfirm: toolHandler.handleToolConfirmation, onCancel: toolHandler.handleToolConfirmationCancel })) : appState.isToolExecuting &&
230
230
  appState.pendingToolCalls[appState.currentToolIndex] ? (_jsx(ToolExecutionIndicator, { toolName: appState.pendingToolCalls[appState.currentToolIndex]
231
231
  .function.name, currentIndex: appState.currentToolIndex, totalTools: appState.pendingToolCalls.length })) : appState.isBashExecuting ? (_jsx(BashExecutionIndicator, { command: appState.currentBashCommand })) : appState.mcpInitialized && appState.client ? (_jsx(UserInput, { customCommands: Array.from(appState.customCommandCache.keys()), onSubmit: msg => void handleMessageSubmit(msg), disabled: appState.isThinking ||