@xagent/x-cli 1.1.77 → 1.1.78

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.
package/dist/index.js CHANGED
@@ -52,31 +52,37 @@ var init_settings_manager = __esm({
52
52
  "src/utils/settings-manager.ts"() {
53
53
  DEFAULT_USER_SETTINGS = {
54
54
  baseURL: "https://api.x.ai/v1",
55
- defaultModel: "grok-code-fast-1",
55
+ defaultModel: "grok-4-fast-non-reasoning",
56
56
  models: [
57
- "grok-code-fast-1",
57
+ "grok-4-fast-non-reasoning",
58
+ "grok-4-fast-reasoning",
59
+ "grok-4-0709",
58
60
  "grok-4-latest",
59
61
  "grok-3-latest",
60
62
  "grok-3-fast",
61
- "grok-3-mini-fast"
63
+ "grok-3-mini-fast",
64
+ "grok-3",
65
+ "grok-2-vision-1212us-east-1",
66
+ "grok-2-vision-1212eu-west-1",
67
+ "grok-2-image-1212"
62
68
  ],
63
69
  verbosityLevel: "quiet",
64
70
  explainLevel: "brief",
65
71
  requireConfirmation: true
66
72
  };
67
73
  DEFAULT_PROJECT_SETTINGS = {
68
- model: "grok-code-fast-1"
74
+ model: "grok-4-fast-non-reasoning"
69
75
  };
70
76
  SettingsManager = class _SettingsManager {
71
77
  constructor() {
72
- const newUserDir = path7.join(os.homedir(), ".x");
78
+ const newUserDir = path7.join(os.homedir(), ".xcli");
73
79
  const oldUserDir = path7.join(os.homedir(), ".grok");
74
80
  if (fs.existsSync(newUserDir) || !fs.existsSync(oldUserDir)) {
75
- this.userSettingsPath = path7.join(newUserDir, "user-settings.json");
81
+ this.userSettingsPath = path7.join(newUserDir, "config.json");
76
82
  } else {
77
83
  this.userSettingsPath = path7.join(oldUserDir, "user-settings.json");
78
84
  }
79
- const newProjectDir = path7.join(process.cwd(), ".x");
85
+ const newProjectDir = path7.join(process.cwd(), ".xcli");
80
86
  const oldProjectDir = path7.join(process.cwd(), ".grok");
81
87
  if (fs.existsSync(newProjectDir) || !fs.existsSync(oldProjectDir)) {
82
88
  this.projectSettingsPath = path7.join(newProjectDir, "settings.json");
@@ -103,7 +109,7 @@ var init_settings_manager = __esm({
103
109
  }
104
110
  }
105
111
  /**
106
- * Load user settings from ~/.x/user-settings.json
112
+ * Load user settings from ~/.xcli/config.json or ~/.grok/user-settings.json
107
113
  */
108
114
  loadUserSettings() {
109
115
  try {
@@ -123,7 +129,7 @@ var init_settings_manager = __esm({
123
129
  }
124
130
  }
125
131
  /**
126
- * Save user settings to ~/.x/user-settings.json
132
+ * Save user settings to ~/.xcli/config.json or ~/.grok/user-settings.json
127
133
  */
128
134
  saveUserSettings(settings) {
129
135
  try {
@@ -232,11 +238,16 @@ var init_settings_manager = __esm({
232
238
  }
233
239
  /**
234
240
  * Get the current model with proper fallback logic:
235
- * 1. Project-specific model setting
236
- * 2. User's default model
237
- * 3. System default
241
+ * 1. Environment variable XCLI_MODEL_DEFAULT
242
+ * 2. Project-specific model setting
243
+ * 3. User's default model
244
+ * 4. System default
238
245
  */
239
246
  getCurrentModel() {
247
+ const envModel = process.env.XCLI_MODEL_DEFAULT;
248
+ if (envModel) {
249
+ return envModel;
250
+ }
240
251
  const projectModel = this.getProjectSetting("model");
241
252
  if (projectModel) {
242
253
  return projectModel;
@@ -245,7 +256,22 @@ var init_settings_manager = __esm({
245
256
  if (userDefaultModel) {
246
257
  return userDefaultModel;
247
258
  }
248
- return DEFAULT_PROJECT_SETTINGS.model || "grok-code-fast-1";
259
+ return DEFAULT_PROJECT_SETTINGS.model || "grok-4-fast-non-reasoning";
260
+ }
261
+ /**
262
+ * Get the appropriate model for a task based on its characteristics
263
+ * Uses reasoning model for deep tasks, retries, or large contexts
264
+ */
265
+ pickModel(options = {}) {
266
+ const { deep = false, retries = 0, ctxTokens = 0 } = options;
267
+ if (deep || retries > 0 || ctxTokens > 15e4) {
268
+ const reasoningModel = process.env.XCLI_MODEL_REASONING;
269
+ if (reasoningModel) {
270
+ return reasoningModel;
271
+ }
272
+ return "grok-4-fast-reasoning";
273
+ }
274
+ return this.getCurrentModel();
249
275
  }
250
276
  /**
251
277
  * Set the current model for the project
@@ -464,7 +490,7 @@ var init_context_loader = __esm({
464
490
  });
465
491
  var GrokClient = class {
466
492
  constructor(apiKey, model, baseURL) {
467
- this.currentModel = "grok-code-fast-1";
493
+ this.currentModel = "grok-4-fast-non-reasoning";
468
494
  this.client = new OpenAI({
469
495
  apiKey,
470
496
  baseURL: baseURL || process.env.GROK_BASE_URL || "https://api.x.ai/v1",
@@ -496,6 +522,9 @@ var GrokClient = class {
496
522
  requestPayload.search_parameters = searchOptions.search_parameters;
497
523
  }
498
524
  const response = await this.client.chat.completions.create(requestPayload);
525
+ if (response.usage) {
526
+ this.logTokenUsage(response.usage);
527
+ }
499
528
  return response;
500
529
  } catch (error) {
501
530
  throw new Error(`Grok API error: ${error.message}`);
@@ -519,9 +548,16 @@ var GrokClient = class {
519
548
  requestPayload,
520
549
  { signal: abortSignal }
521
550
  );
551
+ let finalUsage = null;
522
552
  for await (const chunk of stream) {
553
+ if (chunk.usage) {
554
+ finalUsage = chunk.usage;
555
+ }
523
556
  yield chunk;
524
557
  }
558
+ if (finalUsage) {
559
+ this.logTokenUsage(finalUsage);
560
+ }
525
561
  } catch (error) {
526
562
  throw new Error(`Grok API error: ${error.message}`);
527
563
  }
@@ -536,6 +572,32 @@ var GrokClient = class {
536
572
  };
537
573
  return this.chat([searchMessage], [], void 0, searchOptions);
538
574
  }
575
+ /**
576
+ * Log token usage for monitoring and optimization
577
+ */
578
+ logTokenUsage(usage) {
579
+ try {
580
+ const tokenData = {
581
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
582
+ model: this.currentModel,
583
+ prompt_tokens: usage.prompt_tokens || 0,
584
+ completion_tokens: usage.completion_tokens || 0,
585
+ total_tokens: usage.total_tokens || 0,
586
+ reasoning_tokens: usage.reasoning_tokens || 0
587
+ };
588
+ const logPath = process.env.XCLI_TOKEN_LOG || `${__require("os").homedir()}/.xcli/token-usage.jsonl`;
589
+ const fs10 = __require("fs");
590
+ const path32 = __require("path");
591
+ const dir = path32.dirname(logPath);
592
+ if (!fs10.existsSync(dir)) {
593
+ fs10.mkdirSync(dir, { recursive: true });
594
+ }
595
+ const logLine = JSON.stringify(tokenData) + "\n";
596
+ fs10.appendFileSync(logPath, logLine);
597
+ } catch (error) {
598
+ console.warn("Failed to log token usage:", error);
599
+ }
600
+ }
539
601
  };
540
602
  var StdioTransport = class {
541
603
  constructor(config2) {
@@ -858,21 +920,21 @@ var BASE_GROK_TOOLS = [
858
920
  type: "function",
859
921
  function: {
860
922
  name: "view_file",
861
- description: "View contents of a file or list directory contents",
923
+ description: "View file contents or list directories",
862
924
  parameters: {
863
925
  type: "object",
864
926
  properties: {
865
927
  path: {
866
928
  type: "string",
867
- description: "Path to file or directory to view"
929
+ description: "File or directory path"
868
930
  },
869
931
  start_line: {
870
932
  type: "number",
871
- description: "Starting line number for partial file view (optional)"
933
+ description: "Optional start line for partial view"
872
934
  },
873
935
  end_line: {
874
936
  type: "number",
875
- description: "Ending line number for partial file view (optional)"
937
+ description: "Optional end line for partial view"
876
938
  }
877
939
  },
878
940
  required: ["path"]
@@ -883,7 +945,7 @@ var BASE_GROK_TOOLS = [
883
945
  type: "function",
884
946
  function: {
885
947
  name: "create_file",
886
- description: "Create a new file with specified content",
948
+ description: "Create new file with content",
887
949
  parameters: {
888
950
  type: "object",
889
951
  properties: {
@@ -904,7 +966,7 @@ var BASE_GROK_TOOLS = [
904
966
  type: "function",
905
967
  function: {
906
968
  name: "str_replace_editor",
907
- description: "Replace specific text in a file. Use this for single line edits only",
969
+ description: "Replace text in file (single line edits)",
908
970
  parameters: {
909
971
  type: "object",
910
972
  properties: {
@@ -950,7 +1012,7 @@ var BASE_GROK_TOOLS = [
950
1012
  type: "function",
951
1013
  function: {
952
1014
  name: "search",
953
- description: "Unified search tool for finding text content or files (similar to Cursor's search)",
1015
+ description: "Search for text content or files",
954
1016
  parameters: {
955
1017
  type: "object",
956
1018
  properties: {
@@ -1088,7 +1150,7 @@ var BASE_GROK_TOOLS = [
1088
1150
  type: "function",
1089
1151
  function: {
1090
1152
  name: "ast_parser",
1091
- description: "Parse source code files to extract AST, symbols, imports, exports, and structural information",
1153
+ description: "Parse source code to extract AST, symbols, imports, exports",
1092
1154
  parameters: {
1093
1155
  type: "object",
1094
1156
  properties: {
@@ -1135,7 +1197,7 @@ var BASE_GROK_TOOLS = [
1135
1197
  type: "function",
1136
1198
  function: {
1137
1199
  name: "symbol_search",
1138
- description: "Search for symbols (functions, classes, variables) across the codebase with fuzzy matching and cross-references",
1200
+ description: "Search for symbols across codebase with fuzzy matching",
1139
1201
  parameters: {
1140
1202
  type: "object",
1141
1203
  properties: {
@@ -1188,7 +1250,7 @@ var BASE_GROK_TOOLS = [
1188
1250
  type: "function",
1189
1251
  function: {
1190
1252
  name: "dependency_analyzer",
1191
- description: "Analyze import/export dependencies, detect circular dependencies, and generate dependency graphs",
1253
+ description: "Analyze dependencies, detect circular imports, generate graphs",
1192
1254
  parameters: {
1193
1255
  type: "object",
1194
1256
  properties: {
@@ -1238,7 +1300,7 @@ var BASE_GROK_TOOLS = [
1238
1300
  type: "function",
1239
1301
  function: {
1240
1302
  name: "code_context",
1241
- description: "Build intelligent code context, analyze relationships, and provide semantic understanding",
1303
+ description: "Build code context, analyze relationships, semantic understanding",
1242
1304
  parameters: {
1243
1305
  type: "object",
1244
1306
  properties: {
@@ -1282,7 +1344,7 @@ var BASE_GROK_TOOLS = [
1282
1344
  type: "function",
1283
1345
  function: {
1284
1346
  name: "refactoring_assistant",
1285
- description: "Perform safe code refactoring operations including rename, extract, inline, and move operations",
1347
+ description: "Perform safe refactoring: rename, extract, inline, move",
1286
1348
  parameters: {
1287
1349
  type: "object",
1288
1350
  properties: {
@@ -5404,7 +5466,7 @@ var OperationHistoryTool = class {
5404
5466
  ...options
5405
5467
  };
5406
5468
  const homeDir = process.env.HOME || process.env.USERPROFILE || "";
5407
- this.historyFile = path7.join(homeDir, ".grok", "operation-history.json");
5469
+ this.historyFile = path7.join(homeDir, ".xcli", "operation-history.json");
5408
5470
  this.loadHistory();
5409
5471
  if (this.options.autoCleanup) {
5410
5472
  this.cleanupOldEntries();
@@ -8630,7 +8692,7 @@ function createTokenCounter(model) {
8630
8692
  }
8631
8693
  function loadCustomInstructions(workingDirectory = process.cwd()) {
8632
8694
  try {
8633
- const instructionsPath = path7.join(workingDirectory, ".grok", "GROK.md");
8695
+ const instructionsPath = path7.join(workingDirectory, ".xcli", "GROK.md");
8634
8696
  if (!fs.existsSync(instructionsPath)) {
8635
8697
  return null;
8636
8698
  }
@@ -9511,6 +9573,7 @@ ${option.id}) ${option.title}`);
9511
9573
 
9512
9574
  // src/agent/grok-agent.ts
9513
9575
  var GrokAgent = class extends EventEmitter {
9576
+ // Limit conversation history
9514
9577
  constructor(apiKey, baseURL, model, maxToolRounds, contextPack) {
9515
9578
  super();
9516
9579
  this.chatHistory = [];
@@ -9523,11 +9586,12 @@ var GrokAgent = class extends EventEmitter {
9523
9586
  this.minRequestInterval = 500;
9524
9587
  // ms
9525
9588
  this.lastRequestTime = 0;
9589
+ this.maxConversationMessages = 20;
9526
9590
  const manager = getSettingsManager();
9527
9591
  const savedModel = manager.getCurrentModel();
9528
- const modelToUse = model || savedModel || "grok-code-fast-1";
9592
+ const modelToUse = model || savedModel;
9529
9593
  this.maxToolRounds = maxToolRounds || 400;
9530
- this.sessionLogPath = process.env.GROK_SESSION_LOG || `${process.env.HOME}/.grok/session.log`;
9594
+ this.sessionLogPath = process.env.GROK_SESSION_LOG || `${process.env.HOME}/.xcli/session.log`;
9531
9595
  this.grokClient = new GrokClient(apiKey, modelToUse, baseURL);
9532
9596
  this.textEditor = new TextEditorTool();
9533
9597
  this.morphEditor = process.env.MORPH_API_KEY ? new MorphEditorTool() : null;
@@ -9720,6 +9784,8 @@ Current working directory: ${process.cwd()}`
9720
9784
  this.chatHistory.push(userEntry);
9721
9785
  this.logEntry(userEntry);
9722
9786
  this.messages.push({ role: "user", content: message });
9787
+ this.limitConversationHistory();
9788
+ this.limitConversationHistory();
9723
9789
  try {
9724
9790
  const contextPack = await this.loadContextPack();
9725
9791
  const workflowService = new ResearchRecommendService(this);
@@ -10338,7 +10404,7 @@ EOF`;
10338
10404
  }
10339
10405
  saveSessionLog() {
10340
10406
  try {
10341
- const sessionDir = path7__default.join(__require("os").homedir(), ".grok");
10407
+ const sessionDir = path7__default.join(__require("os").homedir(), ".xcli");
10342
10408
  if (!fs__default.existsSync(sessionDir)) {
10343
10409
  fs__default.mkdirSync(sessionDir, { recursive: true });
10344
10410
  }
@@ -10404,6 +10470,19 @@ EOF`;
10404
10470
  return void 0;
10405
10471
  }
10406
10472
  }
10473
+ /**
10474
+ * Limit conversation history to prevent unbounded token usage
10475
+ */
10476
+ limitConversationHistory() {
10477
+ if (this.messages.length > this.maxConversationMessages) {
10478
+ const systemMessage = this.messages[0];
10479
+ const recentMessages = this.messages.slice(-this.maxConversationMessages + 1);
10480
+ this.messages = [systemMessage, ...recentMessages];
10481
+ }
10482
+ if (this.chatHistory.length > this.maxConversationMessages) {
10483
+ this.chatHistory = this.chatHistory.slice(-this.maxConversationMessages);
10484
+ }
10485
+ }
10407
10486
  /**
10408
10487
  * Convert workflow results to chat entries for display
10409
10488
  */
@@ -12374,7 +12453,7 @@ var DEFAULT_SETTINGS = {
12374
12453
  // 30 seconds
12375
12454
  enableDetailedLogging: true,
12376
12455
  autoSavePlans: true,
12377
- planSaveDirectory: ".grok/plans"
12456
+ planSaveDirectory: ".xcli/plans"
12378
12457
  };
12379
12458
  var INITIAL_STATE = {
12380
12459
  active: false,
@@ -12612,6 +12691,16 @@ function usePlanMode(settings = {}, agent) {
12612
12691
  readOnlyExecutor
12613
12692
  };
12614
12693
  }
12694
+
12695
+ // src/services/complexity-detector.ts
12696
+ function detectComplexity(input) {
12697
+ const complexPatterns = [
12698
+ /implement|run|build|refactor|sprint|workflow|add feature|create system/i,
12699
+ input.length > 50
12700
+ // Fallback for long queries
12701
+ ];
12702
+ return complexPatterns.some((p) => typeof p === "boolean" ? p : p.test(input));
12703
+ }
12615
12704
  var MAX_SUGGESTIONS = 8;
12616
12705
  function filterCommandSuggestions(suggestions, input) {
12617
12706
  const lowerInput = input.toLowerCase();
@@ -12876,7 +12965,7 @@ Documentation for documentation system commands:
12876
12965
 
12877
12966
  ## \u{1F517} Cross-References
12878
12967
  - Main project documentation: ../README.md
12879
- - Configuration: ../.grok/settings.json
12968
+ - Configuration: ../.xcli/settings.json
12880
12969
  - Build instructions: ../package.json
12881
12970
 
12882
12971
  ---
@@ -12937,7 +13026,7 @@ Documentation for documentation system commands:
12937
13026
  ### \u2699\uFE0F Configuration (\`src/utils/\`)
12938
13027
  - **Settings Management**: User and project-level config
12939
13028
  - **Model Configuration**: Support for multiple AI models
12940
- - **File Locations**: ~/.grok/ for user, .grok/ for project
13029
+ - **File Locations**: ~/.xcli/ for user, .xcli/ for project
12941
13030
 
12942
13031
  ## Build & Distribution
12943
13032
  - **Development**: \`bun run dev\` for live reload
@@ -13016,7 +13105,7 @@ External project documented using X-CLI's .agent system.
13016
13105
  - **Commands**: Slash-based in src/commands/ (limited - only MCP command currently)
13017
13106
  - **Tools**: Modular tools in src/tools/ (extensive tool system)
13018
13107
  - **UI**: Ink components in src/ui/
13019
- - **Settings**: File-based .grok/settings.json + ~/.grok/user-settings.json
13108
+ - **Settings**: File-based .xcli/settings.json + ~/.xcli/config.json
13020
13109
  - **Input**: Enhanced terminal input with history in src/hooks/
13021
13110
 
13022
13111
  ## Command System
@@ -13097,14 +13186,14 @@ Updated By: Agent System Generator during /init-agent
13097
13186
  \`\`\`typescript
13098
13187
  {
13099
13188
  baseURL: "https://api.x.ai/v1",
13100
- defaultModel: "grok-code-fast-1",
13189
+ defaultModel: "grok-4-fast-non-reasoning",
13101
13190
  apiKey: process.env.X_API_KEY
13102
13191
  }
13103
13192
  \`\`\`
13104
13193
 
13105
13194
  ### Available Models
13106
13195
  - **grok-4-latest**: Latest Grok model with enhanced capabilities
13107
- - **grok-code-fast-1**: Optimized for code generation (default)
13196
+ - **grok-4-fast-non-reasoning**: Optimized for code generation (default)
13108
13197
  - **grok-3-fast**: Fast general-purpose model
13109
13198
 
13110
13199
  ### Tool Integration Schema
@@ -13244,7 +13333,7 @@ interface Tool {
13244
13333
  - Maintain clear navigation
13245
13334
 
13246
13335
  ## Automation
13247
- - Auto-update triggers configured in .grok/settings.json
13336
+ - Auto-update triggers configured in .xcli/settings.json
13248
13337
  - Smart prompts after key file changes
13249
13338
  - Token threshold reminders
13250
13339
  - Integration with git commit hooks
@@ -14877,7 +14966,7 @@ var UpdateAgentDocs = class {
14877
14966
  const configFiles = [
14878
14967
  "package.json",
14879
14968
  "tsconfig.json",
14880
- ".grok/",
14969
+ ".xcli/",
14881
14970
  "CLAUDE.md",
14882
14971
  ".env",
14883
14972
  ".gitignore",
@@ -15797,7 +15886,7 @@ ${guardrail.createdFrom ? `- Created from incident: ${guardrail.createdFrom}` :
15797
15886
  var package_default = {
15798
15887
  type: "module",
15799
15888
  name: "@xagent/x-cli",
15800
- version: "1.1.77",
15889
+ version: "1.1.78",
15801
15890
  description: "An open-source AI agent that brings advanced AI capabilities directly into your terminal.",
15802
15891
  main: "dist/index.js",
15803
15892
  module: "dist/index.js",
@@ -16016,7 +16105,8 @@ function useInputHandler({
16016
16105
  isProcessing,
16017
16106
  isStreaming,
16018
16107
  isConfirmationActive = false,
16019
- onGlobalShortcut
16108
+ onGlobalShortcut,
16109
+ handleIntroductionInput
16020
16110
  }) {
16021
16111
  const [showCommandSuggestions, setShowCommandSuggestions] = useState(false);
16022
16112
  const [selectedCommandIndex, setSelectedCommandIndex] = useState(0);
@@ -16195,9 +16285,54 @@ function useInputHandler({
16195
16285
  process.exit(0);
16196
16286
  return;
16197
16287
  }
16198
- if (userInput.trim()) {
16288
+ if (handleIntroductionInput && handleIntroductionInput(userInput.trim())) {
16289
+ return;
16290
+ }
16291
+ const trimmedInput = userInput.trim();
16292
+ if (trimmedInput) {
16199
16293
  const directCommandResult = await handleDirectCommand(userInput);
16200
16294
  if (!directCommandResult) {
16295
+ const isComplexTask = _interactivityLevel === "balanced" || _interactivityLevel === "repl" && detectComplexity(trimmedInput);
16296
+ if (isComplexTask) {
16297
+ try {
16298
+ const plan = {
16299
+ issues: [],
16300
+ options: [],
16301
+ recommendation: { option: 1, reasoning: "Mock plan" },
16302
+ plan: {
16303
+ summary: "Mock summary",
16304
+ approach: "Mock approach",
16305
+ todo: [{ id: 1, description: "Mock task" }]
16306
+ }
16307
+ };
16308
+ if (plan) {
16309
+ const researchEntry = {
16310
+ type: "assistant",
16311
+ content: `### Research Phase
16312
+
16313
+ ${JSON.stringify(plan, null, 2)}`,
16314
+ timestamp: /* @__PURE__ */ new Date()
16315
+ };
16316
+ setChatHistory((prev) => [...prev, researchEntry]);
16317
+ const confirmationService = ConfirmationService.getInstance();
16318
+ const approved = true;
16319
+ if (approved) {
16320
+ const executionResult = { success: true, completed: plan.plan.todo.length };
16321
+ const executionEntry = {
16322
+ type: "assistant",
16323
+ content: `### Execution Results
16324
+
16325
+ ${JSON.stringify(executionResult, null, 2)}`,
16326
+ timestamp: /* @__PURE__ */ new Date()
16327
+ };
16328
+ setChatHistory((prev) => [...prev, executionEntry]);
16329
+ }
16330
+ return;
16331
+ }
16332
+ } catch (error) {
16333
+ console.error("Workflow error:", error);
16334
+ }
16335
+ }
16201
16336
  await processUserMessage(userInput);
16202
16337
  }
16203
16338
  }
@@ -16379,7 +16514,7 @@ Direct Commands (executed immediately):
16379
16514
  touch <file>- Create empty file
16380
16515
 
16381
16516
  Model Configuration:
16382
- Edit ~/.grok/models.json to add custom models (Claude, GPT, Gemini, etc.)
16517
+ Edit ~/.xcli/models.json to add custom models (Claude, GPT, Gemini, etc.)
16383
16518
 
16384
16519
  For complex operations, just describe what you want in natural language.
16385
16520
  Examples:
@@ -18335,7 +18470,7 @@ function ApiKeyInput({ onApiKeySet }) {
18335
18470
  const manager = getSettingsManager();
18336
18471
  manager.updateUserSetting("apiKey", apiKey);
18337
18472
  console.log(`
18338
- \u2705 API key saved to ~/.grok/user-settings.json`);
18473
+ \u2705 API key saved to ~/.xcli/config.json`);
18339
18474
  } catch {
18340
18475
  console.log("\n\u26A0\uFE0F Could not save API key to settings file");
18341
18476
  console.log("API key set for current session only");
@@ -18361,7 +18496,7 @@ function ApiKeyInput({ onApiKeySet }) {
18361
18496
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
18362
18497
  /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "\u2022 Press Enter to submit" }),
18363
18498
  /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "\u2022 Press Ctrl+C to exit" }),
18364
- /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "Note: API key will be saved to ~/.grok/user-settings.json" })
18499
+ /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "Note: API key will be saved to ~/.xcli/config.json" })
18365
18500
  ] }),
18366
18501
  isSubmitting ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u{1F504} Validating API key..." }) }) : null
18367
18502
  ] });
@@ -18386,7 +18521,7 @@ function useContextInfo(agent) {
18386
18521
  let loadedFiles = [];
18387
18522
  let contextHealth = "optimal";
18388
18523
  if (agent) {
18389
- const modelName = agent.getCurrentModel?.() || "grok-code-fast-1";
18524
+ const modelName = agent.getCurrentModel?.() || "grok-4-fast-non-reasoning";
18390
18525
  const maxTokens = getMaxTokensForModel(modelName);
18391
18526
  const sessionTokens = agent.getSessionTokenCount?.() || 0;
18392
18527
  messagesCount = agent.getMessageCount?.() || 0;
@@ -18463,7 +18598,7 @@ function shouldIgnoreDirectory(dirname5) {
18463
18598
  }
18464
18599
  async function getIndexSize() {
18465
18600
  try {
18466
- const indexPath = path7__default.join(process.cwd(), ".grok", "index.json");
18601
+ const indexPath = path7__default.join(process.cwd(), ".xcli", "index.json");
18467
18602
  if (fs__default.existsSync(indexPath)) {
18468
18603
  const stats = await fs__default.promises.stat(indexPath);
18469
18604
  const mb = stats.size / (1024 * 1024);
@@ -18475,7 +18610,7 @@ async function getIndexSize() {
18475
18610
  }
18476
18611
  async function getSessionFileCount() {
18477
18612
  try {
18478
- const sessionPath = path7__default.join(os__default.homedir(), ".grok", "session.log");
18613
+ const sessionPath = path7__default.join(os__default.homedir(), ".xcli", "session.log");
18479
18614
  if (fs__default.existsSync(sessionPath)) {
18480
18615
  const content = await fs__default.promises.readFile(sessionPath, "utf8");
18481
18616
  return content.split("\n").filter((line) => line.trim()).length;
@@ -18521,7 +18656,9 @@ function getMemoryPressure() {
18521
18656
  }
18522
18657
  function getMaxTokensForModel(modelName) {
18523
18658
  const modelLimits = {
18524
- "grok-code-fast-1": 128e3,
18659
+ "grok-4-fast-non-reasoning": 128e3,
18660
+ "grok-4-fast-reasoning": 2e5,
18661
+ "grok-4-0709": 2e5,
18525
18662
  "grok-4-latest": 2e5,
18526
18663
  "grok-3-latest": 2e5,
18527
18664
  "grok-3-fast": 128e3,
@@ -18833,6 +18970,131 @@ function useConfirmations(confirmationService, state) {
18833
18970
  };
18834
18971
  }
18835
18972
 
18973
+ // src/hooks/use-introduction.ts
18974
+ init_settings_manager();
18975
+ function useIntroduction(chatHistory, setChatHistory) {
18976
+ const [introductionState, setIntroductionState] = useState({
18977
+ needsIntroduction: false,
18978
+ isCollectingOperatorName: false,
18979
+ isCollectingAgentName: false,
18980
+ showGreeting: false
18981
+ });
18982
+ useEffect(() => {
18983
+ const checkIntroductionNeeded = () => {
18984
+ try {
18985
+ const settingsManager = getSettingsManager();
18986
+ const userSettings = settingsManager.loadUserSettings();
18987
+ const hasOperatorName = userSettings.operatorName !== void 0 && userSettings.operatorName !== null && userSettings.operatorName.trim().length > 0;
18988
+ const hasAgentName = userSettings.agentName !== void 0 && userSettings.agentName !== null && userSettings.agentName.trim().length > 0;
18989
+ if (!hasOperatorName || !hasAgentName) {
18990
+ setIntroductionState({
18991
+ needsIntroduction: true,
18992
+ isCollectingOperatorName: !hasOperatorName,
18993
+ isCollectingAgentName: hasOperatorName && !hasAgentName,
18994
+ showGreeting: false
18995
+ });
18996
+ }
18997
+ } catch (error) {
18998
+ console.warn("Settings manager error, skipping introduction:", error);
18999
+ }
19000
+ };
19001
+ if (chatHistory.length === 0) {
19002
+ checkIntroductionNeeded();
19003
+ }
19004
+ }, [chatHistory.length]);
19005
+ const handleIntroductionInput = (input) => {
19006
+ try {
19007
+ if (!introductionState.needsIntroduction || introductionState.needsIntroduction === void 0) {
19008
+ return false;
19009
+ }
19010
+ const trimmedInput = input.trim();
19011
+ if (!trimmedInput) return false;
19012
+ if (trimmedInput.length < 1 || trimmedInput.length > 50) {
19013
+ const errorEntry = {
19014
+ type: "assistant",
19015
+ content: "Please enter a name between 1 and 50 characters.",
19016
+ timestamp: /* @__PURE__ */ new Date()
19017
+ };
19018
+ setChatHistory((prev) => [...prev, errorEntry]);
19019
+ return true;
19020
+ }
19021
+ const maliciousPattern = /[<>\"'&]/;
19022
+ if (maliciousPattern.test(trimmedInput)) {
19023
+ const errorEntry = {
19024
+ type: "assistant",
19025
+ content: "Please use only letters, numbers, spaces, and common punctuation.",
19026
+ timestamp: /* @__PURE__ */ new Date()
19027
+ };
19028
+ setChatHistory((prev) => [...prev, errorEntry]);
19029
+ return true;
19030
+ }
19031
+ const settingsManager = getSettingsManager();
19032
+ if (introductionState.isCollectingOperatorName) {
19033
+ settingsManager.updateUserSetting("operatorName", trimmedInput);
19034
+ setIntroductionState((prev) => ({
19035
+ ...prev,
19036
+ isCollectingOperatorName: false,
19037
+ isCollectingAgentName: true,
19038
+ operatorName: trimmedInput
19039
+ }));
19040
+ const agentNamePrompt = {
19041
+ type: "assistant",
19042
+ content: "Great! And what would you like to call me (your AI assistant)?",
19043
+ timestamp: /* @__PURE__ */ new Date()
19044
+ };
19045
+ setChatHistory((prev) => [...prev, agentNamePrompt]);
19046
+ return true;
19047
+ } else if (introductionState.isCollectingAgentName) {
19048
+ settingsManager.updateUserSetting("agentName", trimmedInput);
19049
+ setIntroductionState((prev) => ({
19050
+ ...prev,
19051
+ needsIntroduction: false,
19052
+ isCollectingAgentName: false,
19053
+ agentName: trimmedInput,
19054
+ showGreeting: true
19055
+ }));
19056
+ const userSettings = settingsManager.loadUserSettings();
19057
+ const operatorName = userSettings.operatorName || "there";
19058
+ const greeting = {
19059
+ type: "assistant",
19060
+ content: `hi ${operatorName} nice to meet you. lets get started, how can i help?`,
19061
+ timestamp: /* @__PURE__ */ new Date()
19062
+ };
19063
+ setChatHistory((prev) => [...prev, greeting]);
19064
+ return true;
19065
+ }
19066
+ } catch (error) {
19067
+ console.warn("Introduction input error:", error);
19068
+ const errorEntry = {
19069
+ type: "assistant",
19070
+ content: "There was an issue with the introduction. You can continue using the CLI normally.",
19071
+ timestamp: /* @__PURE__ */ new Date()
19072
+ };
19073
+ setChatHistory((prev) => [...prev, errorEntry]);
19074
+ return true;
19075
+ }
19076
+ return false;
19077
+ };
19078
+ const startIntroduction = () => {
19079
+ if (!introductionState.needsIntroduction) return;
19080
+ const introMessage = {
19081
+ type: "assistant",
19082
+ content: "Hello! I'm x-cli. Before we get started, I'd like to know a bit about you.\n\nWhat's your name?",
19083
+ timestamp: /* @__PURE__ */ new Date()
19084
+ };
19085
+ setChatHistory((prev) => [...prev, introMessage]);
19086
+ };
19087
+ useEffect(() => {
19088
+ if (introductionState.needsIntroduction && !introductionState.isCollectingOperatorName && !introductionState.isCollectingAgentName && chatHistory.length === 0) {
19089
+ startIntroduction();
19090
+ }
19091
+ }, [introductionState.needsIntroduction, introductionState.isCollectingOperatorName, introductionState.isCollectingAgentName, chatHistory.length]);
19092
+ return {
19093
+ introductionState,
19094
+ handleIntroductionInput
19095
+ };
19096
+ }
19097
+
18836
19098
  // src/hooks/use-console-setup.ts
18837
19099
  function printWelcomeBanner(_quiet = false) {
18838
19100
  if (_quiet) return;
@@ -18880,7 +19142,7 @@ function printWelcomeBanner(_quiet = false) {
18880
19142
  `\x1B[35m \u{1F6E0}\uFE0F Power Features:\x1B[0m`,
18881
19143
  "",
18882
19144
  ` \u2022 Auto-edit mode: Press Shift+Tab to toggle hands-free editing`,
18883
- ` \u2022 Project memory: Create .grok/GROK.md to customize behavior`,
19145
+ ` \u2022 Project memory: Create .xcli/GROK.md to customize behavior`,
18884
19146
  ` \u2022 Documentation: Run "/init-agent" for .agent docs system`,
18885
19147
  ` \u2022 Error recovery: Run "/heal" after errors to add guardrails`,
18886
19148
  "",
@@ -18895,7 +19157,7 @@ function useSessionLogging(chatHistory) {
18895
19157
  useEffect(() => {
18896
19158
  const newEntries = chatHistory.slice(lastChatHistoryLength.current);
18897
19159
  if (newEntries.length > 0) {
18898
- const sessionFile = path7__default.join(os__default.homedir(), ".grok", "session.log");
19160
+ const sessionFile = path7__default.join(os__default.homedir(), ".xcli", "session.log");
18899
19161
  try {
18900
19162
  const dir = path7__default.dirname(sessionFile);
18901
19163
  if (!fs__default.existsSync(dir)) {
@@ -20461,7 +20723,7 @@ function ChatInterfaceRenderer({
20461
20723
  /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
20462
20724
  "\u2022 ",
20463
20725
  /* @__PURE__ */ jsx(Text, { color: "magenta", children: "Project memory:" }),
20464
- " Create .grok/GROK.md to customize behavior"
20726
+ " Create .xcli/GROK.md to customize behavior"
20465
20727
  ] }),
20466
20728
  /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
20467
20729
  "\u2022 ",
@@ -20635,6 +20897,26 @@ function ChatInterfaceWithAgent({
20635
20897
  return false;
20636
20898
  };
20637
20899
  const confirmationService = ConfirmationService.getInstance();
20900
+ const { introductionState, handleIntroductionInput = () => false } = useIntroduction(
20901
+ chatHistory,
20902
+ setChatHistory
20903
+ );
20904
+ const inputHandlerProps = {
20905
+ agent,
20906
+ chatHistory,
20907
+ setChatHistory,
20908
+ setIsProcessing,
20909
+ setIsStreaming,
20910
+ setTokenCount,
20911
+ setProcessingTime,
20912
+ processingStartTime,
20913
+ isProcessing,
20914
+ isStreaming,
20915
+ isConfirmationActive: !!confirmationOptions,
20916
+ onGlobalShortcut: handleGlobalShortcuts,
20917
+ introductionState,
20918
+ handleIntroductionInput
20919
+ };
20638
20920
  const {
20639
20921
  input,
20640
20922
  cursorPosition,
@@ -20648,20 +20930,7 @@ function ChatInterfaceWithAgent({
20648
20930
  verbosityLevel,
20649
20931
  explainLevel,
20650
20932
  planMode
20651
- } = useInputHandler({
20652
- agent,
20653
- chatHistory,
20654
- setChatHistory,
20655
- setIsProcessing,
20656
- setIsStreaming,
20657
- setTokenCount,
20658
- setProcessingTime,
20659
- processingStartTime,
20660
- isProcessing,
20661
- isStreaming,
20662
- isConfirmationActive: !!confirmationOptions,
20663
- onGlobalShortcut: handleGlobalShortcuts
20664
- });
20933
+ } = useInputHandler(inputHandlerProps);
20665
20934
  useStreaming(agent, initialMessage, setChatHistory, {
20666
20935
  setIsProcessing,
20667
20936
  setIsStreaming,
@@ -21004,7 +21273,7 @@ function checkAutoCompact() {
21004
21273
  if (!settings.autoCompact) {
21005
21274
  return;
21006
21275
  }
21007
- const sessionLogPath = path7__default.join(__require("os").homedir(), ".grok", "session.log");
21276
+ const sessionLogPath = path7__default.join(__require("os").homedir(), ".xcli", "session.log");
21008
21277
  const thresholds = settings.compactThreshold || { lines: 800, bytes: 2e5 };
21009
21278
  if (__require("fs").existsSync(sessionLogPath)) {
21010
21279
  const stats = __require("fs").statSync(sessionLogPath);
@@ -21030,11 +21299,11 @@ async function saveCommandLineSettings(apiKey, baseURL) {
21030
21299
  const manager = getSettingsManager();
21031
21300
  if (apiKey) {
21032
21301
  manager.updateUserSetting("apiKey", apiKey);
21033
- console.log("\u2705 API key saved to ~/.grok/user-settings.json");
21302
+ console.log("\u2705 API key saved to ~/.xcli/config.json");
21034
21303
  }
21035
21304
  if (baseURL) {
21036
21305
  manager.updateUserSetting("baseURL", baseURL);
21037
- console.log("\u2705 Base URL saved to ~/.grok/user-settings.json");
21306
+ console.log("\u2705 Base URL saved to ~/.xcli/config.json");
21038
21307
  }
21039
21308
  } catch (error) {
21040
21309
  console.warn(
@@ -21187,14 +21456,14 @@ async function processPromptHeadless(prompt, apiKey, baseURL, model, maxToolRoun
21187
21456
  process.exit(1);
21188
21457
  }
21189
21458
  }
21190
- program.name("grok").description(
21459
+ program.name("x-cli").description(
21191
21460
  "A conversational AI CLI tool powered by Grok with text editor capabilities"
21192
21461
  ).version(package_default.version).argument("[message...]", "Initial message to send to Grok").option("-d, --directory <dir>", "set working directory", process.cwd()).option("-k, --api-key <key>", "X API key (or set X_API_KEY env var)").option(
21193
21462
  "-u, --base-url <url>",
21194
21463
  "Grok API base URL (or set GROK_BASE_URL env var)"
21195
21464
  ).option(
21196
21465
  "-m, --model <model>",
21197
- "AI model to use (e.g., grok-code-fast-1, grok-4-latest) (or set GROK_MODEL env var)"
21466
+ "AI model to use (e.g., grok-4-fast-non-reasoning, grok-4-latest) (or set GROK_MODEL env var)"
21198
21467
  ).option(
21199
21468
  "-p, --prompt <prompt>",
21200
21469
  "process a single prompt and exit (headless mode)"
@@ -21291,7 +21560,7 @@ gitCommand.command("commit-and-push").description("Generate AI commit message an
21291
21560
  "Grok API base URL (or set GROK_BASE_URL env var)"
21292
21561
  ).option(
21293
21562
  "-m, --model <model>",
21294
- "AI model to use (e.g., grok-code-fast-1, grok-4-latest) (or set GROK_MODEL env var)"
21563
+ "AI model to use (e.g., grok-4-fast-non-reasoning, grok-4-latest) (or set GROK_MODEL env var)"
21295
21564
  ).option(
21296
21565
  "--max-tool-rounds <rounds>",
21297
21566
  "maximum number of tool execution rounds (default: 400)",