@defai.digital/ax-cli 3.6.1 → 3.7.1

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 (137) hide show
  1. package/README.md +129 -16
  2. package/config-defaults/settings.yaml +24 -0
  3. package/dist/agent/llm-agent.d.ts +48 -3
  4. package/dist/agent/llm-agent.js +145 -40
  5. package/dist/agent/llm-agent.js.map +1 -1
  6. package/dist/agent/subagent.d.ts +6 -0
  7. package/dist/agent/subagent.js +41 -24
  8. package/dist/agent/subagent.js.map +1 -1
  9. package/dist/constants.d.ts +13 -0
  10. package/dist/constants.js +28 -0
  11. package/dist/constants.js.map +1 -1
  12. package/dist/index.js +0 -0
  13. package/dist/mcp/client.js +2 -2
  14. package/dist/mcp/client.js.map +1 -1
  15. package/dist/schemas/settings-schemas.d.ts +17 -0
  16. package/dist/schemas/settings-schemas.js +15 -0
  17. package/dist/schemas/settings-schemas.js.map +1 -1
  18. package/dist/sdk/errors.d.ts +93 -0
  19. package/dist/sdk/errors.js +124 -0
  20. package/dist/sdk/errors.js.map +1 -0
  21. package/dist/sdk/index.d.ts +116 -46
  22. package/dist/sdk/index.js +178 -57
  23. package/dist/sdk/index.js.map +1 -1
  24. package/dist/sdk/progress-reporter.d.ts +111 -0
  25. package/dist/sdk/progress-reporter.js +178 -0
  26. package/dist/sdk/progress-reporter.js.map +1 -0
  27. package/dist/sdk/testing.d.ts +184 -0
  28. package/dist/sdk/testing.js +291 -0
  29. package/dist/sdk/testing.js.map +1 -0
  30. package/dist/sdk/tool-registry.d.ts +163 -0
  31. package/dist/sdk/tool-registry.js +218 -0
  32. package/dist/sdk/tool-registry.js.map +1 -0
  33. package/dist/sdk/unified-logger.d.ts +163 -0
  34. package/dist/sdk/unified-logger.js +274 -0
  35. package/dist/sdk/unified-logger.js.map +1 -0
  36. package/dist/sdk/version.d.ts +59 -0
  37. package/dist/sdk/version.js +64 -0
  38. package/dist/sdk/version.js.map +1 -0
  39. package/dist/tools/bash.d.ts +4 -0
  40. package/dist/tools/bash.js +22 -2
  41. package/dist/tools/bash.js.map +1 -1
  42. package/dist/ui/components/chat-history.d.ts +2 -0
  43. package/dist/ui/components/chat-history.js +32 -81
  44. package/dist/ui/components/chat-history.js.map +1 -1
  45. package/dist/ui/components/chat-interface.js +3 -3
  46. package/dist/ui/components/chat-interface.js.map +1 -1
  47. package/dist/ui/components/status-bar.d.ts +2 -0
  48. package/dist/ui/components/status-bar.js +33 -9
  49. package/dist/ui/components/status-bar.js.map +1 -1
  50. package/dist/ui/components/tool-group-display.d.ts +15 -0
  51. package/dist/ui/components/tool-group-display.js +91 -0
  52. package/dist/ui/components/tool-group-display.js.map +1 -0
  53. package/dist/ui/hooks/use-enhanced-input.js +43 -6
  54. package/dist/ui/hooks/use-enhanced-input.js.map +1 -1
  55. package/dist/ui/hooks/use-input-handler.d.ts +2 -0
  56. package/dist/ui/hooks/use-input-handler.js +13 -7
  57. package/dist/ui/hooks/use-input-handler.js.map +1 -1
  58. package/dist/ui/utils/change-summarizer.d.ts +20 -0
  59. package/dist/ui/utils/change-summarizer.js +193 -0
  60. package/dist/ui/utils/change-summarizer.js.map +1 -0
  61. package/dist/ui/utils/tool-grouper.d.ts +62 -0
  62. package/dist/ui/utils/tool-grouper.js +224 -0
  63. package/dist/ui/utils/tool-grouper.js.map +1 -0
  64. package/dist/utils/config-loader.d.ts +4 -0
  65. package/dist/utils/config-loader.js.map +1 -1
  66. package/dist/utils/paste-utils.js +45 -19
  67. package/dist/utils/paste-utils.js.map +1 -1
  68. package/dist/utils/token-counter.d.ts +12 -0
  69. package/dist/utils/token-counter.js +32 -4
  70. package/dist/utils/token-counter.js.map +1 -1
  71. package/package.json +2 -2
  72. package/packages/schemas/package.json +1 -1
  73. package/.ax-cli/CUSTOM.md +0 -269
  74. package/.ax-cli/checkpoints/2025-11-20/checkpoint-11e9e0ba-c39d-4fd2-aa77-bc818811c921.json +0 -69
  75. package/.ax-cli/checkpoints/2025-11-20/checkpoint-2b260b98-b418-4c7c-9694-e2b94967e662.json +0 -24
  76. package/.ax-cli/checkpoints/2025-11-20/checkpoint-2dd84869-e62d-46c8-9885-7e45f37f36e2.json +0 -69
  77. package/.ax-cli/checkpoints/2025-11-20/checkpoint-484dc350-353f-4808-9ed1-ebb3cefdab37.json +0 -24
  78. package/.ax-cli/checkpoints/2025-11-20/checkpoint-74a18b87-6172-4215-962b-44bb9f46a662.json +0 -69
  79. package/.ax-cli/checkpoints/2025-11-20/checkpoint-7e03601e-e8ab-4cd7-9841-a74b66adf78f.json +0 -69
  80. package/.ax-cli/checkpoints/2025-11-20/checkpoint-7f9c6562-771f-4fd0-adcf-9e7e9ac34ae8.json +0 -44
  81. package/.ax-cli/checkpoints/2025-11-20/checkpoint-870a5fb9-6e82-4ff2-8ec8-af4c251cc514.json +0 -44
  82. package/.ax-cli/checkpoints/2025-11-20/checkpoint-93946601-0e83-456c-ba47-def9713124dd.json +0 -24
  83. package/.ax-cli/checkpoints/2025-11-20/checkpoint-e1ebe666-4c3a-4367-ba5c-27fe512a9c70.json +0 -24
  84. package/.ax-cli/checkpoints/2025-11-21/checkpoint-15743e7d-430c-4d76-b6fc-955d7a5c250c.json +0 -44
  85. package/.ax-cli/checkpoints/2025-11-21/checkpoint-25cf7679-0b3f-4988-83d7-704548fbba91.json +0 -69
  86. package/.ax-cli/checkpoints/2025-11-21/checkpoint-54aedbac-6db0-464e-8ebb-dbb3979e6dca.json +0 -24
  87. package/.ax-cli/checkpoints/2025-11-21/checkpoint-7658aed8-fe5d-4222-903f-1a7c63717ea7.json +0 -24
  88. package/.ax-cli/checkpoints/2025-11-21/checkpoint-c9c13497-40dc-4294-a327-6a5fc854eaa1.json +0 -69
  89. package/.ax-cli/checkpoints/metadata.json +0 -62
  90. package/.ax-cli/index.json +0 -44
  91. package/.ax-cli/memory.json +0 -62
  92. package/.ax-cli/settings.json +0 -1
  93. package/ax.config.json +0 -333
  94. package/dist/agent/chat-history-manager.d.ts +0 -56
  95. package/dist/agent/chat-history-manager.js +0 -150
  96. package/dist/agent/chat-history-manager.js.map +0 -1
  97. package/dist/agent/tool-manager.d.ts +0 -39
  98. package/dist/agent/tool-manager.js +0 -76
  99. package/dist/agent/tool-manager.js.map +0 -1
  100. package/dist/hooks/use-chat-reducer.d.ts +0 -61
  101. package/dist/hooks/use-chat-reducer.js +0 -118
  102. package/dist/hooks/use-chat-reducer.js.map +0 -1
  103. package/dist/hooks/use-enhanced-input.d.ts +0 -40
  104. package/dist/hooks/use-enhanced-input.js +0 -249
  105. package/dist/hooks/use-enhanced-input.js.map +0 -1
  106. package/dist/hooks/use-input-handler.d.ts +0 -46
  107. package/dist/hooks/use-input-handler.js +0 -1430
  108. package/dist/hooks/use-input-handler.js.map +0 -1
  109. package/dist/hooks/use-input-history.d.ts +0 -9
  110. package/dist/hooks/use-input-history.js +0 -112
  111. package/dist/hooks/use-input-history.js.map +0 -1
  112. package/dist/index.js.bak +0 -664
  113. package/dist/tools/web-search/engines/brave.d.ts +0 -16
  114. package/dist/tools/web-search/engines/brave.js +0 -99
  115. package/dist/tools/web-search/engines/brave.js.map +0 -1
  116. package/dist/tools/web-search/engines/tavily.d.ts +0 -17
  117. package/dist/tools/web-search/engines/tavily.js +0 -73
  118. package/dist/tools/web-search/engines/tavily.js.map +0 -1
  119. package/dist/utils/paste-collapse.d.ts +0 -46
  120. package/dist/utils/paste-collapse.js +0 -77
  121. package/dist/utils/paste-collapse.js.map +0 -1
  122. package/packages/schemas/dist/index.d.ts +0 -14
  123. package/packages/schemas/dist/index.d.ts.map +0 -1
  124. package/packages/schemas/dist/index.js +0 -19
  125. package/packages/schemas/dist/index.js.map +0 -1
  126. package/packages/schemas/dist/public/core/brand-types.d.ts +0 -308
  127. package/packages/schemas/dist/public/core/brand-types.d.ts.map +0 -1
  128. package/packages/schemas/dist/public/core/brand-types.js +0 -243
  129. package/packages/schemas/dist/public/core/brand-types.js.map +0 -1
  130. package/packages/schemas/dist/public/core/enums.d.ts +0 -227
  131. package/packages/schemas/dist/public/core/enums.d.ts.map +0 -1
  132. package/packages/schemas/dist/public/core/enums.js +0 -222
  133. package/packages/schemas/dist/public/core/enums.js.map +0 -1
  134. package/packages/schemas/dist/public/core/id-types.d.ts +0 -286
  135. package/packages/schemas/dist/public/core/id-types.d.ts.map +0 -1
  136. package/packages/schemas/dist/public/core/id-types.js +0 -136
  137. package/packages/schemas/dist/public/core/id-types.js.map +0 -1
package/dist/index.js.bak DELETED
@@ -1,664 +0,0 @@
1
- #!/usr/bin/env node
2
- import React from "react";
3
- import { render } from "ink";
4
- import { program } from "commander";
5
- import * as dotenv from "dotenv";
6
- import chalk from "chalk";
7
- import { LLMAgent } from "./agent/llm-agent.js";
8
- import ChatInterface from "./ui/components/chat-interface.js";
9
- import { getSettingsManager } from "./utils/settings-manager.js";
10
- import { ConfirmationService } from "./utils/confirmation-service.js";
11
- import { extractErrorMessage } from "./utils/error-handler.js";
12
- import { createMCPCommand } from "./commands/mcp.js";
13
- import { createFrontendCommand } from "./commands/frontend.js";
14
- import { createInitCommand } from "./commands/init.js";
15
- import { createUpdateCommand } from "./commands/update.js";
16
- import { createSetupCommand } from "./commands/setup.js";
17
- import { createUsageCommand } from "./commands/usage.js";
18
- import { createTemplatesCommand } from "./commands/templates.js";
19
- import { createMemoryCommand } from "./commands/memory.js";
20
- import { createCacheCommand } from "./commands/cache.js";
21
- import { createModelsCommand } from "./commands/models.js";
22
- import { createDoctorCommand } from "./commands/doctor.js";
23
- import { getVersion } from "./utils/version.js";
24
- // Load environment variables
25
- dotenv.config();
26
- // Global agent tracker for cleanup on exit
27
- let activeAgent = null;
28
- // Disable default SIGINT handling to let Ink handle Ctrl+C
29
- // We'll handle exit through the input system instead
30
- process.on("SIGTERM", () => {
31
- // Clean up active agent if exists
32
- if (activeAgent) {
33
- activeAgent.dispose();
34
- activeAgent = null;
35
- }
36
- // Restore terminal to normal mode before exit
37
- if (process.stdin.isTTY && process.stdin.setRawMode) {
38
- try {
39
- process.stdin.setRawMode(false);
40
- }
41
- catch {
42
- // Ignore errors when setting raw mode
43
- }
44
- }
45
- console.log("\nGracefully shutting down...");
46
- process.exit(0);
47
- });
48
- // Handle uncaught exceptions to prevent hanging
49
- process.on("uncaughtException", (error) => {
50
- console.error("Uncaught exception:", error);
51
- // Clean up active agent before exit
52
- if (activeAgent) {
53
- try {
54
- activeAgent.dispose();
55
- }
56
- catch {
57
- // Ignore cleanup errors during emergency shutdown
58
- }
59
- activeAgent = null;
60
- }
61
- process.exit(1);
62
- });
63
- process.on("unhandledRejection", (reason, promise) => {
64
- console.error("Unhandled rejection at:", promise, "reason:", reason);
65
- // Clean up active agent before exit
66
- if (activeAgent) {
67
- try {
68
- activeAgent.dispose();
69
- }
70
- catch {
71
- // Ignore cleanup errors during emergency shutdown
72
- }
73
- activeAgent = null;
74
- }
75
- process.exit(1);
76
- });
77
- // Ensure user settings are initialized
78
- function ensureUserSettingsDirectory() {
79
- try {
80
- const manager = getSettingsManager();
81
- // This will create default settings if they don't exist
82
- manager.loadUserSettings();
83
- }
84
- catch {
85
- // Silently ignore errors during setup
86
- }
87
- }
88
- // Check if configuration is valid and complete
89
- function isConfigValid() {
90
- try {
91
- const manager = getSettingsManager();
92
- const apiKey = manager.getApiKey();
93
- const baseURL = manager.getBaseURL();
94
- const model = manager.getCurrentModel();
95
- // All required fields must be present and non-empty
96
- return !!(apiKey && apiKey.trim() && baseURL && baseURL.trim() && model && model.trim());
97
- }
98
- catch {
99
- return false;
100
- }
101
- }
102
- // Load API key from user settings if not in environment
103
- function loadApiKey() {
104
- const manager = getSettingsManager();
105
- return manager.getApiKey();
106
- }
107
- // Load base URL from user settings if not in environment
108
- function loadBaseURL() {
109
- const manager = getSettingsManager();
110
- return manager.getBaseURL();
111
- }
112
- // Save command line settings to user settings file
113
- async function saveCommandLineSettings(apiKey, baseURL) {
114
- try {
115
- const manager = getSettingsManager();
116
- // Update with command line values
117
- if (apiKey) {
118
- manager.updateUserSetting("apiKey", apiKey);
119
- console.log(`✅ API key saved to ${manager.getUserSettingsPath()}`);
120
- }
121
- if (baseURL) {
122
- manager.updateUserSetting("baseURL", baseURL);
123
- console.log(`✅ Base URL saved to ${manager.getUserSettingsPath()}`);
124
- }
125
- }
126
- catch (error) {
127
- console.warn("⚠️ Could not save settings to file:", error instanceof Error ? error.message : "Unknown error");
128
- }
129
- }
130
- // Load model from user settings if not in environment
131
- function loadModel() {
132
- // First check environment variables
133
- let model = process.env.AI_MODEL;
134
- if (!model) {
135
- // Use the unified model loading from settings manager
136
- try {
137
- const manager = getSettingsManager();
138
- model = manager.getCurrentModel();
139
- }
140
- catch {
141
- // Ignore errors, model will remain undefined
142
- }
143
- }
144
- return model;
145
- }
146
- // Handle commit-and-push command in headless mode
147
- async function handleCommitAndPushHeadless(apiKey, baseURL, model, maxToolRounds) {
148
- let agent = null;
149
- try {
150
- agent = new LLMAgent(apiKey, baseURL, model, maxToolRounds);
151
- // Configure confirmation service for headless mode (auto-approve all operations)
152
- const confirmationService = ConfirmationService.getInstance();
153
- confirmationService.setSessionFlag("allOperations", true);
154
- console.log("🤖 Processing commit and push...\n");
155
- console.log("> /commit-and-push\n");
156
- // First check if there are any changes at all
157
- const initialStatusResult = await agent.executeBashCommand("git status --porcelain");
158
- if (!initialStatusResult.success || !initialStatusResult.output?.trim()) {
159
- console.log("❌ No changes to commit. Working directory is clean.");
160
- process.exit(1);
161
- }
162
- console.log("✅ git status: Changes detected");
163
- // Add all changes
164
- const addResult = await agent.executeBashCommand("git add .");
165
- if (!addResult.success) {
166
- console.log(`❌ git add: ${addResult.error || "Failed to stage changes"}`);
167
- process.exit(1);
168
- }
169
- console.log("✅ git add: Changes staged");
170
- // Get staged changes for commit message generation
171
- const diffResult = await agent.executeBashCommand("git diff --cached");
172
- // Generate commit message using AI
173
- const commitPrompt = `Generate a concise, professional git commit message for these changes:
174
-
175
- Git Status:
176
- ${initialStatusResult.output}
177
-
178
- Git Diff (staged changes):
179
- ${diffResult.output || "No staged changes shown"}
180
-
181
- Follow conventional commit format (feat:, fix:, docs:, etc.) and keep it under 72 characters.
182
- Respond with ONLY the commit message, no additional text.`;
183
- console.log("🤖 Generating commit message...");
184
- const commitMessageEntries = await agent.processUserMessage(commitPrompt);
185
- let commitMessage = "";
186
- // Extract the commit message from the AI response
187
- for (const entry of commitMessageEntries) {
188
- if (entry.type === "assistant" && entry.content.trim()) {
189
- commitMessage = entry.content.trim();
190
- break;
191
- }
192
- }
193
- if (!commitMessage) {
194
- console.log("❌ Failed to generate commit message");
195
- process.exit(1);
196
- }
197
- // Clean the commit message (remove leading/trailing quotes)
198
- const cleanCommitMessage = commitMessage.replace(/^["']|["']$/g, "");
199
- // Remove newlines to ensure single-line commit message
200
- const singleLineMessage = cleanCommitMessage.replace(/\n/g, " ").trim();
201
- console.log(`✅ Generated commit message: "${singleLineMessage}"`);
202
- // Execute the commit with proper shell escaping to prevent injection
203
- // Use single quotes and escape any single quotes in the message
204
- const escapedMessage = `'${singleLineMessage.replace(/'/g, "'\\''")}'`;
205
- const commitCommand = `git commit -m ${escapedMessage}`;
206
- const commitResult = await agent.executeBashCommand(commitCommand);
207
- if (commitResult.success) {
208
- // Safely extract first line with proper fallback
209
- const firstLine = commitResult.output?.split("\n").filter(line => line.trim())?.[0];
210
- console.log(`✅ git commit: ${firstLine || "Commit successful"}`);
211
- // If commit was successful, push to remote
212
- // First try regular push, if it fails try with upstream setup
213
- let pushResult = await agent.executeBashCommand("git push");
214
- if (!pushResult.success &&
215
- pushResult.error?.includes("no upstream branch")) {
216
- console.log("🔄 Setting upstream and pushing...");
217
- pushResult = await agent.executeBashCommand("git push -u origin HEAD");
218
- }
219
- if (pushResult.success) {
220
- // Safely extract first line with proper fallback
221
- const firstLine = pushResult.output?.split("\n").filter(line => line.trim())?.[0];
222
- console.log(`✅ git push: ${firstLine || "Push successful"}`);
223
- }
224
- else {
225
- console.log(`❌ git push: ${pushResult.error || "Push failed"}`);
226
- process.exit(1);
227
- }
228
- }
229
- else {
230
- console.log(`❌ git commit: ${commitResult.error || "Commit failed"}`);
231
- process.exit(1);
232
- }
233
- }
234
- catch (error) {
235
- console.error("❌ Error during commit and push:", extractErrorMessage(error));
236
- process.exit(1);
237
- }
238
- finally {
239
- // Clean up agent resources
240
- if (agent) {
241
- agent.dispose();
242
- }
243
- }
244
- }
245
- // Build context from VSCode integration flags
246
- async function buildContextFromFlags(options) {
247
- const contextParts = [];
248
- // Add file context
249
- if (options.file) {
250
- try {
251
- const fs = await import("fs/promises");
252
- const path = await import("path");
253
- const filePath = path.resolve(options.file);
254
- let fileContent = await fs.readFile(filePath, "utf-8");
255
- // Apply line range if specified
256
- if (options.lineRange) {
257
- const match = options.lineRange.match(/^(\d+)-(\d+)$/);
258
- if (match) {
259
- const startLine = parseInt(match[1], 10);
260
- const endLine = parseInt(match[2], 10);
261
- // Validate parsed integers are valid numbers
262
- if (Number.isNaN(startLine) || Number.isNaN(endLine)) {
263
- contextParts.push(`Error: Invalid line range format. Expected format: START-END (e.g., 10-20).`);
264
- }
265
- else {
266
- const lines = fileContent.split("\n");
267
- // Validate line range
268
- if (startLine < 1 || startLine > lines.length) {
269
- contextParts.push(`Error: Invalid start line ${startLine}. File has ${lines.length} lines.`);
270
- }
271
- else if (endLine < startLine) {
272
- contextParts.push(`Error: Invalid line range ${startLine}-${endLine}. End line must be >= start line.`);
273
- }
274
- else {
275
- // Clamp endLine to file length
276
- const validEndLine = Math.min(endLine, lines.length);
277
- fileContent = lines.slice(startLine - 1, validEndLine).join("\n");
278
- contextParts.push(`File: ${filePath} (lines ${startLine}-${validEndLine}):\n\`\`\`\n${fileContent}\n\`\`\``);
279
- }
280
- }
281
- }
282
- else {
283
- contextParts.push(`File: ${filePath}:\n\`\`\`\n${fileContent}\n\`\`\``);
284
- }
285
- }
286
- else {
287
- contextParts.push(`File: ${filePath}:\n\`\`\`\n${fileContent}\n\`\`\``);
288
- }
289
- }
290
- catch (error) {
291
- contextParts.push(`Error reading file ${options.file}: ${extractErrorMessage(error)}`);
292
- }
293
- }
294
- // Add selection context
295
- if (options.selection) {
296
- contextParts.push(`Selected code:\n\`\`\`\n${options.selection}\n\`\`\``);
297
- }
298
- // Add git diff context
299
- if (options.gitDiff) {
300
- try {
301
- const { execSync } = await import("child_process");
302
- const gitDiff = execSync("git diff", {
303
- encoding: "utf-8",
304
- timeout: 10000, // 10 second timeout to prevent hanging
305
- maxBuffer: 10 * 1024 * 1024 // 10MB max buffer for large diffs
306
- });
307
- if (gitDiff.trim()) {
308
- contextParts.push(`Git diff:\n\`\`\`diff\n${gitDiff}\n\`\`\``);
309
- }
310
- }
311
- catch (error) {
312
- contextParts.push(`Error getting git diff: ${extractErrorMessage(error)}`);
313
- }
314
- }
315
- return contextParts.join("\n\n");
316
- }
317
- // Headless mode processing function
318
- async function processPromptHeadless(prompt, apiKey, baseURL, model, maxToolRounds, options) {
319
- let agent = null;
320
- try {
321
- agent = new LLMAgent(apiKey, baseURL, model, maxToolRounds);
322
- // Configure thinking mode: CLI flag takes priority, then settings
323
- if (options?.think === true) {
324
- agent.setThinkingConfig({ type: "enabled" });
325
- }
326
- else if (options?.think === false) {
327
- agent.setThinkingConfig({ type: "disabled" });
328
- }
329
- else {
330
- // No CLI flag - check settings (env > project > user)
331
- const manager = getSettingsManager();
332
- const thinkingSettings = manager.getThinkingSettings();
333
- if (thinkingSettings?.enabled === true) {
334
- agent.setThinkingConfig({ type: "enabled" });
335
- }
336
- else if (thinkingSettings?.enabled === false) {
337
- agent.setThinkingConfig({ type: "disabled" });
338
- }
339
- }
340
- // Configure confirmation service for headless mode (auto-approve all operations)
341
- const confirmationService = ConfirmationService.getInstance();
342
- confirmationService.setSessionFlag("allOperations", true);
343
- // Build context from VSCode flags
344
- let fullPrompt = prompt;
345
- if (options && (options.file || options.selection || options.gitDiff)) {
346
- const context = await buildContextFromFlags(options);
347
- if (context) {
348
- fullPrompt = `${context}\n\n${prompt}`;
349
- }
350
- }
351
- // Process the user message
352
- const chatEntries = await agent.processUserMessage(fullPrompt);
353
- // Convert chat entries to OpenAI compatible message objects
354
- const messages = [];
355
- for (const entry of chatEntries) {
356
- switch (entry.type) {
357
- case "user":
358
- messages.push({
359
- role: "user",
360
- content: entry.content,
361
- });
362
- break;
363
- case "assistant":
364
- const assistantMessage = {
365
- role: "assistant",
366
- content: entry.content,
367
- };
368
- // Add tool calls if present
369
- if (entry.toolCalls && entry.toolCalls.length > 0) {
370
- assistantMessage.tool_calls = entry.toolCalls.map((toolCall) => ({
371
- id: toolCall.id,
372
- type: "function",
373
- function: {
374
- name: toolCall.function.name,
375
- arguments: toolCall.function.arguments,
376
- },
377
- }));
378
- }
379
- messages.push(assistantMessage);
380
- break;
381
- case "tool_result":
382
- if (entry.toolCall) {
383
- messages.push({
384
- role: "tool",
385
- tool_call_id: entry.toolCall.id,
386
- content: entry.content,
387
- });
388
- }
389
- break;
390
- }
391
- }
392
- // Output based on format flag
393
- if (options?.json) {
394
- // JSON output mode for IDE integration
395
- const response = {
396
- messages: messages,
397
- model: agent.getCurrentModel(),
398
- timestamp: new Date().toISOString(),
399
- };
400
- console.log(JSON.stringify(response, null, options.vscode ? 2 : 0));
401
- }
402
- else {
403
- // Standard output (existing behavior)
404
- for (const message of messages) {
405
- console.log(JSON.stringify(message));
406
- }
407
- }
408
- }
409
- catch (error) {
410
- if (options?.json) {
411
- // JSON error output for IDE integration
412
- console.log(JSON.stringify({
413
- error: {
414
- message: error.message,
415
- type: error.constructor.name,
416
- },
417
- timestamp: new Date().toISOString(),
418
- }, null, options.vscode ? 2 : 0));
419
- }
420
- else {
421
- // Standard error output
422
- console.log(JSON.stringify({
423
- role: "assistant",
424
- content: `Error: ${error.message}`,
425
- }));
426
- }
427
- process.exit(1);
428
- }
429
- finally {
430
- // Clean up agent resources
431
- if (agent) {
432
- agent.dispose();
433
- }
434
- }
435
- }
436
- program
437
- .name("ax-cli")
438
- .description("Enterprise-Class AI Command Line Interface - Primary support for GLM (General Language Model) with multi-provider AI orchestration")
439
- .version(getVersion(), "-v, --version", "output the current version")
440
- .argument("[message...]", "Initial message to send to AI")
441
- .option("-d, --directory <dir>", "set working directory", process.cwd())
442
- .option("-k, --api-key <key>", "AI API key (or set YOUR_API_KEY env var)")
443
- .option("-u, --base-url <url>", "AI API base URL (or set AI_BASE_URL env var)")
444
- .option("-m, --model <model>", "AI model to use (e.g., glm-4.6, glm-4-air, llama3.1:8b, gpt-4) (or set AI_MODEL env var)")
445
- .option("--chat-mode", "use chat model for conversational tasks (requires dual-model configuration)")
446
- .option("-p, --prompt <prompt>", "process a single prompt and exit (headless mode)")
447
- .option("--max-tool-rounds <rounds>", "maximum number of tool execution rounds (default: 400)", "400")
448
- .option("-c, --continue", "continue the most recent conversation from the current directory")
449
- // Thinking/Reasoning Options
450
- .option("--think", "enable thinking/reasoning mode for complex tasks (GLM-4.6)")
451
- .option("--no-think", "disable thinking mode (use standard responses)")
452
- // Sampling/Reproducibility Options
453
- .option("--deterministic", "enable deterministic mode (do_sample=false) for reproducible outputs")
454
- .option("--seed <number>", "random seed for reproducible sampling (implies --deterministic)")
455
- .option("--top-p <number>", "nucleus sampling parameter (0.0-1.0, alternative to temperature)")
456
- // VSCode Integration Flags (Phase 1)
457
- .option("--json", "output responses in JSON format (for IDE integration)")
458
- .option("--file <path>", "include file context from specified path")
459
- .option("--selection <text>", "include selected text as context")
460
- .option("--line-range <range>", "include specific line range (e.g., 10-20)")
461
- .option("--git-diff", "include git diff as context")
462
- .option("--vscode", "optimize output for VSCode integration")
463
- .action(async (message, options) => {
464
- if (options.directory) {
465
- try {
466
- process.chdir(options.directory);
467
- }
468
- catch (error) {
469
- console.error(`Error changing directory to ${options.directory}:`, error.message);
470
- process.exit(1);
471
- }
472
- }
473
- try {
474
- // Check if running in interactive mode (no prompt, api-key, or base-url flags)
475
- const isInteractiveMode = !options.prompt && !options.apiKey && !options.baseUrl;
476
- // If interactive mode and config is invalid, automatically run setup
477
- if (isInteractiveMode && !isConfigValid()) {
478
- console.log("⚠️ Configuration file not found or incomplete.\n");
479
- console.log("Let's set up AX CLI first...\n");
480
- // Import and run setup command
481
- const { createSetupCommand } = await import("./commands/setup.js");
482
- const setupCommand = createSetupCommand();
483
- // Run setup command with empty args (will prompt user)
484
- await setupCommand.parseAsync(["node", "ax-cli", "setup"], { from: "user" });
485
- // After setup completes, re-check config
486
- if (!isConfigValid()) {
487
- console.error("\n❌ Setup did not complete successfully. Please try again.");
488
- process.exit(1);
489
- }
490
- console.log("\n");
491
- }
492
- // Get API key from options, environment, or user settings
493
- const apiKey = options.apiKey || loadApiKey();
494
- const baseURL = options.baseUrl || loadBaseURL();
495
- // Handle dual-model mode if --chat-mode flag is set
496
- let model = options.model || loadModel();
497
- if (options.chatMode && !options.model) {
498
- const manager = getSettingsManager();
499
- const modelForMode = manager.getModelForMode(true); // true = chat mode
500
- if (modelForMode) {
501
- model = modelForMode;
502
- console.log(chalk.cyan(`💬 Using chat model: ${model}`));
503
- }
504
- else if (manager.isDualModelEnabled()) {
505
- console.warn(chalk.yellow("⚠️ Dual-model mode is enabled but no chat model configured. Using default model."));
506
- }
507
- else {
508
- console.warn(chalk.yellow("⚠️ --chat-mode flag requires dual-model configuration. Using default model."));
509
- console.warn(chalk.dim(" Configure dual-model in ~/.ax-cli/config.json or .ax-cli/settings.json"));
510
- }
511
- }
512
- const parsedMaxToolRounds = options.maxToolRounds ? parseInt(options.maxToolRounds.toString(), 10) : 400;
513
- const maxToolRounds = Number.isFinite(parsedMaxToolRounds) && parsedMaxToolRounds > 0 ? parsedMaxToolRounds : 400;
514
- if (!apiKey) {
515
- console.error("❌ Error: API key required. Set YOUR_API_KEY environment variable, use --api-key flag, or save to ~/.ax-cli/config.json");
516
- process.exit(1);
517
- }
518
- // Save API key and base URL to user settings if provided via command line
519
- if (options.apiKey || options.baseUrl) {
520
- await saveCommandLineSettings(options.apiKey, options.baseUrl);
521
- }
522
- // Headless mode: process prompt and exit
523
- if (options.prompt) {
524
- await processPromptHeadless(options.prompt, apiKey, baseURL, model, maxToolRounds, {
525
- json: options.json,
526
- file: options.file,
527
- selection: options.selection,
528
- lineRange: options.lineRange,
529
- gitDiff: options.gitDiff,
530
- vscode: options.vscode,
531
- think: options.think,
532
- });
533
- return;
534
- }
535
- // Interactive mode: launch UI
536
- const agent = new LLMAgent(apiKey, baseURL, model, maxToolRounds);
537
- activeAgent = agent; // Track for cleanup on exit
538
- // Configure thinking mode: CLI flag takes priority, then settings
539
- if (options.think === true) {
540
- agent.setThinkingConfig({ type: "enabled" });
541
- }
542
- else if (options.think === false) {
543
- agent.setThinkingConfig({ type: "disabled" });
544
- }
545
- else {
546
- // No CLI flag - check settings (env > project > user)
547
- const manager = getSettingsManager();
548
- const thinkingSettings = manager.getThinkingSettings();
549
- if (thinkingSettings?.enabled === true) {
550
- agent.setThinkingConfig({ type: "enabled" });
551
- }
552
- else if (thinkingSettings?.enabled === false) {
553
- agent.setThinkingConfig({ type: "disabled" });
554
- }
555
- }
556
- // Handle --continue flag: load directory-specific session
557
- if (options.continue) {
558
- const currentDir = process.cwd();
559
- const { getHistoryManager } = await import("./utils/history-manager.js");
560
- // Create a new history manager instance for this project directory
561
- const historyManager = getHistoryManager(currentDir, true);
562
- const previousHistory = historyManager.loadHistory();
563
- if (previousHistory.length > 0) {
564
- console.log(`🔄 Continuing conversation from ${currentDir}`);
565
- console.log(`📜 Loaded ${previousHistory.length} previous messages\n`);
566
- }
567
- else {
568
- console.log(`💬 Starting new conversation in ${currentDir}\n`);
569
- }
570
- console.log("🤖 Starting AX CLI AI Assistant...\n");
571
- }
572
- else {
573
- console.log("🤖 Starting AX CLI AI Assistant...\n");
574
- }
575
- ensureUserSettingsDirectory();
576
- // Support variadic positional arguments for multi-word initial message
577
- const initialMessage = Array.isArray(message)
578
- ? message.join(" ")
579
- : message;
580
- const { waitUntilExit } = render(React.createElement(ChatInterface, {
581
- agent,
582
- initialMessage,
583
- loadPreviousHistory: options.continue || false,
584
- }));
585
- // Wait for app to exit and clean up
586
- await waitUntilExit();
587
- if (activeAgent) {
588
- activeAgent.dispose();
589
- activeAgent = null;
590
- }
591
- }
592
- catch (error) {
593
- console.error("❌ Error initializing AX CLI:", error.message);
594
- process.exit(1);
595
- }
596
- });
597
- // Git subcommand
598
- const gitCommand = program
599
- .command("git")
600
- .description("Git operations with AI assistance");
601
- gitCommand
602
- .command("commit-and-push")
603
- .description("Generate AI commit message and push to remote")
604
- .option("-d, --directory <dir>", "set working directory", process.cwd())
605
- .option("-k, --api-key <key>", "AI API key (or set YOUR_API_KEY env var)")
606
- .option("-u, --base-url <url>", "AI API base URL (or set AI_BASE_URL env var)")
607
- .option("-m, --model <model>", "AI model to use (e.g., glm-4.6, glm-4-air, llama3.1:8b, gpt-4) (or set AI_MODEL env var)")
608
- .option("--max-tool-rounds <rounds>", "maximum number of tool execution rounds (default: 400)", "400")
609
- .action(async (options) => {
610
- if (options.directory) {
611
- try {
612
- process.chdir(options.directory);
613
- }
614
- catch (error) {
615
- console.error(`Error changing directory to ${options.directory}:`, error.message);
616
- process.exit(1);
617
- }
618
- }
619
- try {
620
- // Get API key from options, environment, or user settings
621
- const apiKey = options.apiKey || loadApiKey();
622
- const baseURL = options.baseUrl || loadBaseURL();
623
- const model = options.model || loadModel();
624
- const parsedMaxToolRounds = options.maxToolRounds ? parseInt(options.maxToolRounds.toString(), 10) : 400;
625
- const maxToolRounds = Number.isFinite(parsedMaxToolRounds) && parsedMaxToolRounds > 0 ? parsedMaxToolRounds : 400;
626
- if (!apiKey) {
627
- console.error("❌ Error: API key required. Set YOUR_API_KEY environment variable, use --api-key flag, or save to ~/.ax-cli/config.json");
628
- process.exit(1);
629
- }
630
- // Save API key and base URL to user settings if provided via command line
631
- if (options.apiKey || options.baseUrl) {
632
- await saveCommandLineSettings(options.apiKey, options.baseUrl);
633
- }
634
- await handleCommitAndPushHeadless(apiKey, baseURL, model, maxToolRounds);
635
- }
636
- catch (error) {
637
- console.error("❌ Error during git commit-and-push:", error.message);
638
- process.exit(1);
639
- }
640
- });
641
- // MCP command
642
- program.addCommand(createMCPCommand());
643
- // Frontend command (workflows for front-end development)
644
- program.addCommand(createFrontendCommand());
645
- // Init command
646
- program.addCommand(createInitCommand());
647
- // Templates command
648
- program.addCommand(createTemplatesCommand());
649
- // Memory command
650
- program.addCommand(createMemoryCommand());
651
- // Update command
652
- program.addCommand(createUpdateCommand());
653
- // Setup command
654
- program.addCommand(createSetupCommand());
655
- // Usage command
656
- program.addCommand(createUsageCommand());
657
- // Cache command
658
- program.addCommand(createCacheCommand());
659
- // Models command
660
- program.addCommand(createModelsCommand());
661
- // Doctor command
662
- program.addCommand(createDoctorCommand());
663
- program.parse();
664
- //# sourceMappingURL=index.js.map
@@ -1,16 +0,0 @@
1
- /**
2
- * Brave Search Engine
3
- * Privacy-focused independent search
4
- * https://brave.com/search/api/
5
- */
6
- import type { SearchEngine, WebSearchResult, SearchOptions } from "../types.js";
7
- export declare class BraveSearch implements SearchEngine {
8
- readonly name = "brave";
9
- private apiKey;
10
- private baseUrl;
11
- private timeout;
12
- constructor();
13
- isAvailable(): boolean;
14
- search(query: string, options?: SearchOptions): Promise<WebSearchResult[]>;
15
- private formatResults;
16
- }