@xagent/x-cli 1.1.49 → 1.1.51

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- ## 1.1.49 – Logo Assets & NPM Publication Complete
1
+ ## 1.1.51 – Logo Assets & NPM Publication Complete
2
2
 
3
3
  ✅ **Live on NPM**: [@xagent/x-cli](https://www.npmjs.com/package/@xagent/x-cli) - Fully published and ready for global installation
4
4
 
@@ -155,6 +155,20 @@ A conversational AI CLI tool powered by Grok with **Claude Code-level intelligen
155
155
 
156
156
  ### 🚀 Quick Start
157
157
 
158
+ #### 💎 **Try it now (no installation required!)**
159
+
160
+ <div align="center">
161
+
162
+ ┌────────────────────────────────────┐
163
+ │ 🚀 One-Command Start │
164
+ ├────────────────────────────────────┤
165
+ │ npx -y @xagent/x-cli@latest │
166
+ ├────────────────────────────────────┤
167
+ │ Always latest version • Zero setup │
168
+ └────────────────────────────────────┘
169
+
170
+ </div>
171
+
158
172
  **Option 1: Run without installing (Recommended)**
159
173
 
160
174
  ```bash
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import * as path7 from 'path';
5
5
  import path7__default from 'path';
6
6
  import * as os from 'os';
7
7
  import os__default from 'os';
8
- import React2, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
8
+ import React3, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
9
9
  import { Box, Text, render, useApp, useInput } from 'ink';
10
10
  import { program, Command } from 'commander';
11
11
  import * as dotenv from 'dotenv';
@@ -58,7 +58,9 @@ var init_settings_manager = __esm({
58
58
  "grok-3-latest",
59
59
  "grok-3-fast",
60
60
  "grok-3-mini-fast"
61
- ]
61
+ ],
62
+ verbosityLevel: "quiet",
63
+ explainLevel: "brief"
62
64
  };
63
65
  DEFAULT_PROJECT_SETTINGS = {
64
66
  model: "grok-code-fast-1"
@@ -9291,7 +9293,7 @@ EOF`;
9291
9293
  var package_default = {
9292
9294
  type: "module",
9293
9295
  name: "@xagent/x-cli",
9294
- version: "1.1.49",
9296
+ version: "1.1.51",
9295
9297
  description: "An open-source AI agent that brings the power of Grok directly into your terminal.",
9296
9298
  main: "dist/index.js",
9297
9299
  module: "dist/index.js",
@@ -14883,6 +14885,22 @@ function useInputHandler({
14883
14885
  });
14884
14886
  const [shiftTabPressCount, setShiftTabPressCount] = useState(0);
14885
14887
  const [lastShiftTabTime, setLastShiftTabTime] = useState(0);
14888
+ const [verbosityLevel, setVerbosityLevel] = useState(() => {
14889
+ try {
14890
+ const manager = getSettingsManager();
14891
+ return manager.getUserSetting("verbosityLevel") || "quiet";
14892
+ } catch {
14893
+ return "quiet";
14894
+ }
14895
+ });
14896
+ const [explainLevel, setExplainLevel] = useState(() => {
14897
+ try {
14898
+ const manager = getSettingsManager();
14899
+ return manager.getUserSetting("explainLevel") || "brief";
14900
+ } catch {
14901
+ return "brief";
14902
+ }
14903
+ });
14886
14904
  const planMode = usePlanMode({}, agent);
14887
14905
  const handleSpecialKey = (key) => {
14888
14906
  if (isConfirmationActive) {
@@ -15129,6 +15147,8 @@ Built-in Commands:
15129
15147
  /clear - Clear chat history
15130
15148
  /help - Show this help
15131
15149
  /models - Switch between available models
15150
+ /verbosity - Control output verbosity (quiet/normal/verbose)
15151
+ /explain - Control operation explanations (off/brief/detailed)
15132
15152
  /version - Show version information and check for updates
15133
15153
  /upgrade - Check for updates and upgrade automatically
15134
15154
  /switch - Switch to specific version (/switch <version>)
@@ -16229,6 +16249,102 @@ Auto-compact automatically enables compact mode when conversations exceed thresh
16229
16249
  clearInput();
16230
16250
  return true;
16231
16251
  }
16252
+ if (trimmedInput === "/verbosity" || trimmedInput.startsWith("/verbosity ")) {
16253
+ const args = trimmedInput.split(" ").slice(1);
16254
+ const newLevel = args[0];
16255
+ if (!newLevel) {
16256
+ const levelEntry = {
16257
+ type: "assistant",
16258
+ content: `\u{1F50A} **Current Verbosity Level: ${verbosityLevel.toUpperCase()}**
16259
+
16260
+ **Available levels:**
16261
+ - \`quiet\` - Minimal output, suppress prefixes and extra formatting
16262
+ - \`normal\` - Current default behavior with full details
16263
+ - \`verbose\` - Additional details and debug information
16264
+
16265
+ **Usage:** \`/verbosity <level>\`
16266
+ **Example:** \`/verbosity quiet\``,
16267
+ timestamp: /* @__PURE__ */ new Date()
16268
+ };
16269
+ setChatHistory((prev) => [...prev, levelEntry]);
16270
+ } else if (["quiet", "normal", "verbose"].includes(newLevel)) {
16271
+ setVerbosityLevel(newLevel);
16272
+ try {
16273
+ const manager = getSettingsManager();
16274
+ manager.updateUserSetting("verbosityLevel", newLevel);
16275
+ } catch (_error) {
16276
+ }
16277
+ const confirmEntry = {
16278
+ type: "assistant",
16279
+ content: `\u2705 **Verbosity level set to: ${newLevel.toUpperCase()}**
16280
+
16281
+ Tool outputs will now show ${newLevel === "quiet" ? "minimal output" : newLevel === "normal" ? "full details" : "extra details and debug information"}.`,
16282
+ timestamp: /* @__PURE__ */ new Date()
16283
+ };
16284
+ setChatHistory((prev) => [...prev, confirmEntry]);
16285
+ } else {
16286
+ const errorEntry = {
16287
+ type: "assistant",
16288
+ content: `\u274C **Invalid verbosity level: ${newLevel}**
16289
+
16290
+ **Available levels:** quiet, normal, verbose
16291
+
16292
+ **Usage:** \`/verbosity <level>\``,
16293
+ timestamp: /* @__PURE__ */ new Date()
16294
+ };
16295
+ setChatHistory((prev) => [...prev, errorEntry]);
16296
+ }
16297
+ clearInput();
16298
+ return true;
16299
+ }
16300
+ if (trimmedInput === "/explain" || trimmedInput.startsWith("/explain ")) {
16301
+ const args = trimmedInput.split(" ").slice(1);
16302
+ const newLevel = args[0];
16303
+ if (!newLevel) {
16304
+ const levelEntry = {
16305
+ type: "assistant",
16306
+ content: `\u{1F4A1} **Current Explain Level: ${explainLevel.toUpperCase()}**
16307
+
16308
+ **Available levels:**
16309
+ - \`off\` - No explanations
16310
+ - \`brief\` - Short reasons for operations
16311
+ - \`detailed\` - Comprehensive explanations with context
16312
+
16313
+ **Usage:** \`/explain <level>\`
16314
+ **Example:** \`/explain brief\``,
16315
+ timestamp: /* @__PURE__ */ new Date()
16316
+ };
16317
+ setChatHistory((prev) => [...prev, levelEntry]);
16318
+ } else if (["off", "brief", "detailed"].includes(newLevel)) {
16319
+ setExplainLevel(newLevel);
16320
+ try {
16321
+ const manager = getSettingsManager();
16322
+ manager.updateUserSetting("explainLevel", newLevel);
16323
+ } catch (_error) {
16324
+ }
16325
+ const confirmEntry = {
16326
+ type: "assistant",
16327
+ content: `\u2705 **Explain level set to: ${newLevel.toUpperCase()}**
16328
+
16329
+ Operations will now ${newLevel === "off" ? "show no explanations" : newLevel === "brief" ? "show brief reasons" : "show detailed explanations with context"}.`,
16330
+ timestamp: /* @__PURE__ */ new Date()
16331
+ };
16332
+ setChatHistory((prev) => [...prev, confirmEntry]);
16333
+ } else {
16334
+ const errorEntry = {
16335
+ type: "assistant",
16336
+ content: `\u274C **Invalid explain level: ${newLevel}**
16337
+
16338
+ **Available levels:** off, brief, detailed
16339
+
16340
+ **Usage:** \`/explain <level>\``,
16341
+ timestamp: /* @__PURE__ */ new Date()
16342
+ };
16343
+ setChatHistory((prev) => [...prev, errorEntry]);
16344
+ }
16345
+ clearInput();
16346
+ return true;
16347
+ }
16232
16348
  const directBashCommands = [
16233
16349
  "ls",
16234
16350
  "pwd",
@@ -16430,6 +16546,8 @@ Auto-compact automatically enables compact mode when conversations exceed thresh
16430
16546
  availableModels,
16431
16547
  agent,
16432
16548
  autoEditEnabled,
16549
+ verbosityLevel,
16550
+ explainLevel,
16433
16551
  // Plan mode state and actions
16434
16552
  planMode
16435
16553
  };
@@ -16520,11 +16638,27 @@ function LoadingSpinner({
16520
16638
  message,
16521
16639
  progress
16522
16640
  }) {
16523
- if (!isActive) return null;
16641
+ const [frameIndex, setFrameIndex] = useState(0);
16642
+ const [messageIndex, setMessageIndex] = useState(0);
16524
16643
  const config2 = operationConfig[operation];
16525
- const spinnerChar = config2.spinner[0];
16526
- const operationMessage = message || config2.messages[0];
16644
+ const spinnerChar = config2.spinner[frameIndex % config2.spinner.length];
16645
+ const operationMessage = message || config2.messages[messageIndex % config2.messages.length];
16527
16646
  const color = getSpinnerColor(operation);
16647
+ useEffect(() => {
16648
+ if (!isActive) return;
16649
+ const interval = setInterval(() => {
16650
+ setFrameIndex((prev) => prev + 1);
16651
+ }, 80);
16652
+ return () => clearInterval(interval);
16653
+ }, [isActive]);
16654
+ useEffect(() => {
16655
+ if (!isActive) return;
16656
+ const messageInterval = setInterval(() => {
16657
+ setMessageIndex((prev) => prev + 1);
16658
+ }, 80 * config2.spinner.length * 3);
16659
+ return () => clearInterval(messageInterval);
16660
+ }, [isActive, config2.spinner.length]);
16661
+ if (!isActive) return null;
16528
16662
  const renderProgressBar = () => {
16529
16663
  if (progress === void 0) return null;
16530
16664
  const barLength = 20;
@@ -16804,8 +16938,36 @@ var handleLongContent = (content, maxLength = 5e3) => {
16804
16938
  isTruncated: true
16805
16939
  };
16806
16940
  };
16807
- var MemoizedChatEntry = React2.memo(
16808
- ({ entry, index }) => {
16941
+ var MemoizedChatEntry = React3.memo(
16942
+ ({ entry, index, verbosityLevel, explainLevel }) => {
16943
+ const getExplanation = (toolName, filePath, _isExecuting) => {
16944
+ if (explainLevel === "off") return null;
16945
+ const explanations = {
16946
+ view_file: {
16947
+ brief: `Reading ${filePath} to examine its contents`,
16948
+ detailed: `Reading the file ${filePath} to examine its current contents, structure, and implementation details for analysis or modification.`
16949
+ },
16950
+ str_replace_editor: {
16951
+ brief: `Updating ${filePath} with changes`,
16952
+ detailed: `Applying targeted modifications to ${filePath} using precise string replacement to update specific code sections while preserving the rest of the file structure.`
16953
+ },
16954
+ create_file: {
16955
+ brief: `Creating new file ${filePath}`,
16956
+ detailed: `Creating a new file at ${filePath} with the specified content, establishing the initial structure and implementation for this component or module.`
16957
+ },
16958
+ bash: {
16959
+ brief: `Executing command: ${filePath}`,
16960
+ detailed: `Running the shell command "${filePath}" to perform system operations, file management, or external tool execution as requested.`
16961
+ },
16962
+ search: {
16963
+ brief: `Searching for: ${filePath}`,
16964
+ detailed: `Performing a comprehensive search across the codebase for "${filePath}" to locate relevant files, functions, or code patterns that match the query.`
16965
+ }
16966
+ };
16967
+ const explanation = explanations[toolName];
16968
+ if (!explanation) return null;
16969
+ return explainLevel === "detailed" ? explanation.detailed : explanation.brief;
16970
+ };
16809
16971
  const renderDiff = (diffContent, filename) => {
16810
16972
  return /* @__PURE__ */ jsx(
16811
16973
  DiffRenderer,
@@ -16924,6 +17086,9 @@ var MemoizedChatEntry = React2.memo(
16924
17086
  };
16925
17087
  const shouldShowDiff = entry.toolCall?.function?.name === "str_replace_editor" && entry.toolResult?.success && entry.content.includes("Updated") && entry.content.includes("---") && entry.content.includes("+++");
16926
17088
  const shouldShowFileContent = (entry.toolCall?.function?.name === "view_file" || entry.toolCall?.function?.name === "create_file") && entry.toolResult?.success && !shouldShowDiff;
17089
+ const shouldShowToolContent = verbosityLevel !== "quiet";
17090
+ const shouldShowFullContent = verbosityLevel === "normal" || verbosityLevel === "verbose";
17091
+ const explanation = getExplanation(toolName, filePath);
16927
17092
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
16928
17093
  /* @__PURE__ */ jsxs(Box, { children: [
16929
17094
  /* @__PURE__ */ jsx(Text, { color: "magenta", children: "\u23FA" }),
@@ -16932,20 +17097,24 @@ var MemoizedChatEntry = React2.memo(
16932
17097
  filePath ? `${actionName}(${filePath})` : actionName
16933
17098
  ] })
16934
17099
  ] }),
16935
- /* @__PURE__ */ jsx(Box, { marginLeft: 2, flexDirection: "column", children: isExecuting ? /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u23BF Executing..." }) : shouldShowFileContent ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
17100
+ explanation && /* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsxs(Text, { color: "blue", italic: true, children: [
17101
+ "\u{1F4A1} ",
17102
+ explanation
17103
+ ] }) }),
17104
+ shouldShowToolContent && /* @__PURE__ */ jsx(Box, { marginLeft: 2, flexDirection: "column", children: isExecuting ? /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u23BF Executing..." }) : shouldShowFileContent && shouldShowFullContent ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
16936
17105
  /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u23BF File contents:" }),
16937
17106
  /* @__PURE__ */ jsx(Box, { marginLeft: 2, flexDirection: "column", children: renderFileContent(entry.content) })
16938
- ] }) : shouldShowDiff ? (
17107
+ ] }) : shouldShowDiff && shouldShowFullContent ? (
16939
17108
  // For diff results, show only the summary line, not the raw content
16940
17109
  /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
16941
17110
  "\u23BF ",
16942
17111
  entry.content.split("\n")[0]
16943
17112
  ] })
16944
- ) : /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
17113
+ ) : !shouldShowFullContent ? /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u23BF Completed" }) : /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
16945
17114
  "\u23BF ",
16946
17115
  formatToolContent(entry.content, toolName)
16947
17116
  ] }) }),
16948
- shouldShowDiff && !isExecuting && /* @__PURE__ */ jsx(Box, { marginLeft: 4, flexDirection: "column", children: renderDiff(entry.content, filePath) })
17117
+ shouldShowDiff && !isExecuting && shouldShowFullContent && /* @__PURE__ */ jsx(Box, { marginLeft: 4, flexDirection: "column", children: renderDiff(entry.content, filePath) })
16949
17118
  ] }, index);
16950
17119
  default:
16951
17120
  return null;
@@ -16955,7 +17124,9 @@ var MemoizedChatEntry = React2.memo(
16955
17124
  MemoizedChatEntry.displayName = "MemoizedChatEntry";
16956
17125
  function ChatHistory({
16957
17126
  entries,
16958
- isConfirmationActive = false
17127
+ isConfirmationActive = false,
17128
+ verbosityLevel = "quiet",
17129
+ explainLevel = "brief"
16959
17130
  }) {
16960
17131
  const filteredEntries = isConfirmationActive ? entries.filter(
16961
17132
  (entry) => !(entry.type === "tool_call" && entry.content === "Executing...")
@@ -16965,7 +17136,9 @@ function ChatHistory({
16965
17136
  MemoizedChatEntry,
16966
17137
  {
16967
17138
  entry,
16968
- index
17139
+ index,
17140
+ verbosityLevel,
17141
+ explainLevel
16969
17142
  },
16970
17143
  `${entry.timestamp.getTime()}-${index}`
16971
17144
  )) });
@@ -18100,6 +18273,8 @@ function ChatInterfaceWithAgent({
18100
18273
  commandSuggestions,
18101
18274
  availableModels,
18102
18275
  autoEditEnabled,
18276
+ verbosityLevel,
18277
+ explainLevel,
18103
18278
  planMode
18104
18279
  } = useInputHandler({
18105
18280
  agent,
@@ -18401,7 +18576,9 @@ function ChatInterfaceWithAgent({
18401
18576
  ChatHistory,
18402
18577
  {
18403
18578
  entries: chatHistory,
18404
- isConfirmationActive: !!confirmationOptions
18579
+ isConfirmationActive: !!confirmationOptions,
18580
+ verbosityLevel,
18581
+ explainLevel
18405
18582
  }
18406
18583
  ) }),
18407
18584
  /* @__PURE__ */ jsx(
@@ -18433,7 +18610,6 @@ function ChatInterfaceWithAgent({
18433
18610
  progress: void 0
18434
18611
  }
18435
18612
  ),
18436
- /* @__PURE__ */ jsx(VersionNotification, { isVisible: !isProcessing && !isStreaming }),
18437
18613
  planMode.isActive && /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(
18438
18614
  PlanModeIndicator,
18439
18615
  {
@@ -18453,6 +18629,7 @@ function ChatInterfaceWithAgent({
18453
18629
  isStreaming
18454
18630
  }
18455
18631
  ),
18632
+ /* @__PURE__ */ jsx(VersionNotification, { isVisible: !isProcessing && !isStreaming }),
18456
18633
  /* @__PURE__ */ jsxs(Box, { flexDirection: "row", marginTop: 1, children: [
18457
18634
  /* @__PURE__ */ jsxs(Box, { marginRight: 2, children: [
18458
18635
  /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
@@ -19020,7 +19197,7 @@ program.name("grok").description(
19020
19197
  checkAutoCompact();
19021
19198
  checkStartupUpdates();
19022
19199
  const initialMessage = Array.isArray(message) ? message.join(" ") : message;
19023
- const app = render(React2.createElement(ChatInterface, { agent, initialMessage }));
19200
+ const app = render(React3.createElement(ChatInterface, { agent, initialMessage }));
19024
19201
  const cleanup = () => {
19025
19202
  app.unmount();
19026
19203
  agent.abortCurrentOperation();