@xagent/x-cli 1.1.60 → 1.1.62

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
@@ -5,8 +5,8 @@ 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 React3, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
9
- import { Box, Text, render, useApp, useInput } from 'ink';
8
+ import React4, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
9
+ import { render, Box, Text, useApp, useInput } from 'ink';
10
10
  import { program, Command } from 'commander';
11
11
  import * as dotenv from 'dotenv';
12
12
  import OpenAI from 'openai';
@@ -22,10 +22,10 @@ import { parse } from '@typescript-eslint/typescript-estree';
22
22
  import Fuse from 'fuse.js';
23
23
  import { glob } from 'glob';
24
24
  import { encoding_for_model, get_encoding } from 'tiktoken';
25
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
26
- import crypto from 'crypto';
25
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
27
26
  import { marked } from 'marked';
28
27
  import TerminalRenderer from 'marked-terminal';
28
+ import crypto from 'crypto';
29
29
  import chalk from 'chalk';
30
30
 
31
31
  var __defProp = Object.defineProperty;
@@ -7039,10 +7039,10 @@ var DependencyAnalyzerTool = class {
7039
7039
  const circularDeps = [];
7040
7040
  const visited = /* @__PURE__ */ new Set();
7041
7041
  const visiting = /* @__PURE__ */ new Set();
7042
- const dfs = (filePath, path29) => {
7042
+ const dfs = (filePath, path30) => {
7043
7043
  if (visiting.has(filePath)) {
7044
- const cycleStart = path29.indexOf(filePath);
7045
- const cycle = path29.slice(cycleStart).concat([filePath]);
7044
+ const cycleStart = path30.indexOf(filePath);
7045
+ const cycle = path30.slice(cycleStart).concat([filePath]);
7046
7046
  circularDeps.push({
7047
7047
  cycle: cycle.map((fp) => graph.nodes.get(fp)?.filePath || fp),
7048
7048
  severity: cycle.length <= 2 ? "error" : "warning",
@@ -7058,7 +7058,7 @@ var DependencyAnalyzerTool = class {
7058
7058
  if (node) {
7059
7059
  for (const dependency of node.dependencies) {
7060
7060
  if (graph.nodes.has(dependency)) {
7061
- dfs(dependency, [...path29, filePath]);
7061
+ dfs(dependency, [...path30, filePath]);
7062
7062
  }
7063
7063
  }
7064
7064
  }
@@ -9030,10 +9030,10 @@ Current working directory: ${process.cwd()}`
9030
9030
  return await this.textEditor.view(args.path, range);
9031
9031
  } catch (error) {
9032
9032
  console.warn(`view_file tool failed, falling back to bash: ${error.message}`);
9033
- const path29 = args.path;
9034
- let command = `cat "${path29}"`;
9033
+ const path30 = args.path;
9034
+ let command = `cat "${path30}"`;
9035
9035
  if (args.start_line && args.end_line) {
9036
- command = `sed -n '${args.start_line},${args.end_line}p' "${path29}"`;
9036
+ command = `sed -n '${args.start_line},${args.end_line}p' "${path30}"`;
9037
9037
  }
9038
9038
  return await this.bash.execute(command);
9039
9039
  }
@@ -9289,150 +9289,6 @@ EOF`;
9289
9289
  }
9290
9290
  };
9291
9291
 
9292
- // package.json
9293
- var package_default = {
9294
- type: "module",
9295
- name: "@xagent/x-cli",
9296
- version: "1.1.60",
9297
- description: "An open-source AI agent that brings the power of Grok directly into your terminal.",
9298
- main: "dist/index.js",
9299
- module: "dist/index.js",
9300
- types: "dist/index.d.ts",
9301
- exports: {
9302
- ".": {
9303
- types: "./dist/index.d.ts",
9304
- import: "./dist/index.js"
9305
- }
9306
- },
9307
- bin: {
9308
- xcli: "dist/index.js"
9309
- },
9310
- files: [
9311
- "dist/**/*",
9312
- ".xcli/**/*",
9313
- "README.md",
9314
- "LICENSE",
9315
- "docs/assets/logos/**/*"
9316
- ],
9317
- scripts: {
9318
- build: "tsup",
9319
- "build:tsc": "tsc",
9320
- dev: "npm run build && node dist/index.js",
9321
- "dev:node": "tsx src/index.ts",
9322
- "dev:watch": "npm run build && node --watch dist/index.js",
9323
- start: "node dist/index.js",
9324
- local: "npm run build && npm link && node dist/index.js",
9325
- "start:bun": "bun run dist/index.js",
9326
- lint: "eslint . --ext .js,.jsx,.ts,.tsx",
9327
- typecheck: "tsc --noEmit",
9328
- "install:bun": "bun install",
9329
- preinstall: "echo '\u{1F916} Installing X CLI...'",
9330
- postinstall: `echo '==================================================' && echo '\u2705 X CLI installed successfully!' && echo '==================================================' && echo '\u{1F680} Try: xcli --help' && echo '\u{1F4A1} If "command not found", add to PATH:' && node -e "const p=process.platform;const isMac=p==='darwin';const isLinux=p==='linux';if(isMac||isLinux){const shell=isMac?'zshrc':'bashrc';console.log((isMac?'\u{1F34E} Mac':'\u{1F427} Linux')+': echo \\'export PATH=\\"$(npm config get prefix)/bin:$PATH\\"\\' >> ~/.'+shell+' && source ~/.'+shell);}" && echo '\u{1F4D6} Docs: https://github.com/hinetapora/x-cli-hurry-mode#installation' && echo '\u{1F511} Set API key: export GROK_API_KEY=your_key_here' && echo '==================================================' && echo '\u{1F527} Auto-setup PATH? Press Enter to add (or Ctrl+C to skip)' && read -t 10 && node -e "const fs=require('fs');const p=process.platform;const isMac=p==='darwin';const isLinux=p==='linux';if(isMac||isLinux){const shellFile=isMac?'.zshrc':'.bashrc';const rcPath=process.env.HOME+'/'+shellFile;const pathCmd='export PATH=\\"$(npm config get prefix)/bin:$PATH\\"';try{const content=fs.readFileSync(rcPath,'utf8');if(!content.includes(pathCmd)){fs.appendFileSync(rcPath,'\\n'+pathCmd+'\\n');console.log('\u2705 Added to ~/'+shellFile+' - restart terminal');}else{console.log('\u2139\uFE0F Already in ~/'+shellFile);}}catch(e){console.log('\u26A0\uFE0F Could not modify ~/'+shellFile+' - add manually');}}" && echo '\u{1F50D} Verifying: ' && xcli --version 2>/dev/null || echo '\u26A0\uFE0F xcli not in PATH yet - follow above steps'`,
9331
- prepare: "husky install",
9332
- "dev:site": "cd apps/site && npm run start",
9333
- "build:site": "cd apps/site && npm run build",
9334
- "sync:docs": "cd apps/site && node src/scripts/sync-agent-docs.js",
9335
- "smart-push": "./scripts/smart-push.sh"
9336
- },
9337
- "lint-staged": {
9338
- "*.{ts,tsx}": [
9339
- "eslint --fix"
9340
- ],
9341
- "*.{js,jsx,mjs}": [
9342
- "eslint --fix"
9343
- ],
9344
- "*.{md,mdx}": [
9345
- "prettier --write"
9346
- ],
9347
- "*.{json,yml,yaml}": [
9348
- "prettier --write"
9349
- ]
9350
- },
9351
- keywords: [
9352
- "cli",
9353
- "agent",
9354
- "text-editor",
9355
- "grok",
9356
- "ai"
9357
- ],
9358
- author: "grok_cli",
9359
- license: "MIT",
9360
- dependencies: {
9361
- "@modelcontextprotocol/sdk": "^1.17.0",
9362
- "@types/marked-terminal": "^6.1.1",
9363
- "@typescript-eslint/typescript-estree": "^8.46.0",
9364
- ajv: "^8.17.1",
9365
- "ajv-formats": "^3.0.1",
9366
- axios: "^1.7.0",
9367
- cfonts: "^3.3.0",
9368
- chalk: "^5.3.0",
9369
- chokidar: "^4.0.3",
9370
- "cli-highlight": "^2.1.11",
9371
- commander: "^12.0.0",
9372
- dotenv: "^16.4.0",
9373
- enquirer: "^2.4.1",
9374
- "fs-extra": "^11.2.0",
9375
- "fuse.js": "^7.1.0",
9376
- glob: "^11.0.3",
9377
- ink: "^4.4.1",
9378
- "js-yaml": "^4.1.0",
9379
- marked: "^15.0.12",
9380
- "marked-terminal": "^7.3.0",
9381
- openai: "^5.10.1",
9382
- react: "^18.3.1",
9383
- "ripgrep-node": "^1.0.0",
9384
- "terminal-image": "^4.0.0",
9385
- tiktoken: "^1.0.21"
9386
- },
9387
- devDependencies: {
9388
- "@eslint/js": "^9.37.0",
9389
- "@types/fs-extra": "^11.0.2",
9390
- "@types/node": "^20.8.0",
9391
- "@types/react": "^18.3.3",
9392
- "@typescript-eslint/eslint-plugin": "^8.37.0",
9393
- "@typescript-eslint/parser": "^8.37.0",
9394
- esbuild: "^0.25.10",
9395
- eslint: "^9.31.0",
9396
- husky: "^9.1.7",
9397
- "lint-staged": "^16.2.4",
9398
- prettier: "^3.6.2",
9399
- tsup: "^8.5.0",
9400
- tsx: "^4.0.0"
9401
- },
9402
- engines: {
9403
- node: ">=18.0.0"
9404
- },
9405
- preferGlobal: true,
9406
- repository: {
9407
- type: "git",
9408
- url: "https://github.com/x-cli-team/x-cli.git"
9409
- },
9410
- bugs: {
9411
- url: "https://github.com/x-cli-team/x-cli/issues"
9412
- },
9413
- homepage: "https://grokcli.dev",
9414
- icon: "docs/assets/logos/x-cli-logo.svg",
9415
- publishConfig: {
9416
- access: "public"
9417
- },
9418
- installConfig: {
9419
- hoisting: false
9420
- },
9421
- optionalDependencies: {
9422
- "tree-sitter": "^0.21.1",
9423
- "tree-sitter-javascript": "^0.21.2",
9424
- "tree-sitter-python": "^0.21.0",
9425
- "tree-sitter-typescript": "^0.21.2"
9426
- },
9427
- trustedDependencies: [
9428
- "esbuild",
9429
- "tree-sitter",
9430
- "tree-sitter-javascript",
9431
- "tree-sitter-python",
9432
- "tree-sitter-typescript"
9433
- ]
9434
- };
9435
-
9436
9292
  // src/utils/text-utils.ts
9437
9293
  function isWordBoundary(char) {
9438
9294
  if (!char) return true;
@@ -14794,107 +14650,251 @@ ${guardrail.createdFrom ? `- Created from incident: ${guardrail.createdFrom}` :
14794
14650
  return { ...this.config };
14795
14651
  }
14796
14652
  };
14797
- var execAsync3 = promisify(exec);
14798
- async function checkForUpdates() {
14799
- try {
14800
- const { stdout } = await execAsync3(`npm view ${package_default.name} version`, {
14801
- timeout: 5e3
14802
- });
14803
- const latestVersion = stdout.trim();
14804
- const currentVersion = package_default.version;
14805
- const isUpdateAvailable = latestVersion !== currentVersion && isNewerVersion(latestVersion, currentVersion);
14806
- return {
14807
- current: currentVersion,
14808
- latest: latestVersion,
14809
- isUpdateAvailable,
14810
- updateCommand: `npm update -g ${package_default.name}@latest`
14811
- };
14812
- } catch {
14813
- return {
14814
- current: package_default.version,
14815
- latest: package_default.version,
14816
- isUpdateAvailable: false,
14817
- updateCommand: `npm update -g ${package_default.name}@latest`
14818
- };
14819
- }
14820
- }
14821
- function isNewerVersion(version1, version2) {
14822
- const v1Parts = version1.split(".").map(Number);
14823
- const v2Parts = version2.split(".").map(Number);
14824
- for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
14825
- const v1Part = v1Parts[i] || 0;
14826
- const v2Part = v2Parts[i] || 0;
14827
- if (v1Part > v2Part) return true;
14828
- if (v1Part < v2Part) return false;
14829
- }
14830
- return false;
14831
- }
14832
- async function autoUpgrade() {
14833
- try {
14834
- console.log("\u{1F504} Upgrading X-CLI...");
14835
- await execAsync3(`npm update -g ${package_default.name}@latest`, {
14836
- timeout: 3e4
14837
- });
14838
- console.log("\u2705 Upgrade completed! Please restart the CLI.");
14839
- return true;
14840
- } catch (error) {
14841
- console.error("\u274C Auto-upgrade failed:", error);
14842
- return false;
14843
- }
14844
- }
14845
- var cachedVersionInfo = null;
14846
- var lastCheckTime = 0;
14847
- var CHECK_INTERVAL = 6 * 60 * 60 * 1e3;
14848
- async function getCachedVersionInfo() {
14849
- const now = Date.now();
14850
- if (cachedVersionInfo && now - lastCheckTime < CHECK_INTERVAL) {
14851
- return cachedVersionInfo;
14852
- }
14853
- try {
14854
- cachedVersionInfo = await checkForUpdates();
14855
- lastCheckTime = now;
14856
- return cachedVersionInfo;
14857
- } catch {
14858
- return null;
14859
- }
14860
- }
14861
14653
 
14862
- // src/hooks/use-input-handler.ts
14863
- init_settings_manager();
14864
- function useInputHandler({
14865
- agent,
14866
- chatHistory,
14867
- setChatHistory,
14868
- setIsProcessing,
14869
- setIsStreaming,
14870
- setTokenCount,
14871
- setProcessingTime,
14872
- processingStartTime,
14873
- isProcessing,
14874
- isStreaming,
14875
- isConfirmationActive = false,
14876
- onGlobalShortcut
14877
- }) {
14878
- const [showCommandSuggestions, setShowCommandSuggestions] = useState(false);
14879
- const [selectedCommandIndex, setSelectedCommandIndex] = useState(0);
14880
- const [showModelSelection, setShowModelSelection] = useState(false);
14881
- const [selectedModelIndex, setSelectedModelIndex] = useState(0);
14882
- const [autoEditEnabled, setAutoEditEnabled] = useState(() => {
14883
- const confirmationService = ConfirmationService.getInstance();
14884
- const sessionFlags = confirmationService.getSessionFlags();
14885
- return sessionFlags.allOperations;
14886
- });
14887
- const [shiftTabPressCount, setShiftTabPressCount] = useState(0);
14888
- const [lastShiftTabTime, setLastShiftTabTime] = useState(0);
14889
- const [verbosityLevel, setVerbosityLevel] = useState(() => {
14890
- try {
14891
- const manager = getSettingsManager();
14892
- return manager.getUserSetting("verbosityLevel") || "quiet";
14893
- } catch {
14894
- return "quiet";
14654
+ // package.json
14655
+ var package_default = {
14656
+ type: "module",
14657
+ name: "@xagent/x-cli",
14658
+ version: "1.1.62",
14659
+ description: "An open-source AI agent that brings the power of Grok directly into your terminal.",
14660
+ main: "dist/index.js",
14661
+ module: "dist/index.js",
14662
+ types: "dist/index.d.ts",
14663
+ exports: {
14664
+ ".": {
14665
+ types: "./dist/index.d.ts",
14666
+ import: "./dist/index.js"
14895
14667
  }
14896
- });
14897
- const [explainLevel, setExplainLevel] = useState(() => {
14668
+ },
14669
+ bin: {
14670
+ xcli: "dist/index.js"
14671
+ },
14672
+ files: [
14673
+ "dist/**/*",
14674
+ ".xcli/**/*",
14675
+ "README.md",
14676
+ "LICENSE",
14677
+ "docs/assets/logos/**/*"
14678
+ ],
14679
+ scripts: {
14680
+ build: "tsup",
14681
+ "build:tsc": "tsc",
14682
+ dev: "npm run build && node dist/index.js",
14683
+ "dev:node": "tsx src/index.ts",
14684
+ "dev:watch": "npm run build && node --watch dist/index.js",
14685
+ start: "node dist/index.js",
14686
+ local: "npm run build && npm link && node dist/index.js",
14687
+ "start:bun": "bun run dist/index.js",
14688
+ lint: "eslint . --ext .js,.jsx,.ts,.tsx",
14689
+ typecheck: "tsc --noEmit",
14690
+ "install:bun": "bun install",
14691
+ preinstall: "echo '\u{1F916} Installing X CLI...'",
14692
+ postinstall: `echo '==================================================' && echo '\u2705 X CLI installed successfully!' && echo '==================================================' && echo '\u{1F680} Try: xcli --help' && echo '\u{1F4A1} If "command not found", add to PATH:' && node -e "const p=process.platform;const isMac=p==='darwin';const isLinux=p==='linux';if(isMac||isLinux){const shell=isMac?'zshrc':'bashrc';console.log((isMac?'\u{1F34E} Mac':'\u{1F427} Linux')+': echo \\'export PATH=\\"$(npm config get prefix)/bin:$PATH\\"\\' >> ~/.'+shell+' && source ~/.'+shell);}" && echo '\u{1F4D6} Docs: https://github.com/hinetapora/x-cli-hurry-mode#installation' && echo '\u{1F511} Set API key: export GROK_API_KEY=your_key_here' && echo '==================================================' && echo '\u{1F527} Auto-setup PATH? Press Enter to add (or Ctrl+C to skip)' && read -t 10 && node -e "const fs=require('fs');const p=process.platform;const isMac=p==='darwin';const isLinux=p==='linux';if(isMac||isLinux){const shellFile=isMac?'.zshrc':'.bashrc';const rcPath=process.env.HOME+'/'+shellFile;const pathCmd='export PATH=\\"$(npm config get prefix)/bin:$PATH\\"';try{const content=fs.readFileSync(rcPath,'utf8');if(!content.includes(pathCmd)){fs.appendFileSync(rcPath,'\\n'+pathCmd+'\\n');console.log('\u2705 Added to ~/'+shellFile+' - restart terminal');}else{console.log('\u2139\uFE0F Already in ~/'+shellFile);}}catch(e){console.log('\u26A0\uFE0F Could not modify ~/'+shellFile+' - add manually');}}" && echo '\u{1F50D} Verifying: ' && xcli --version 2>/dev/null || echo '\u26A0\uFE0F xcli not in PATH yet - follow above steps'`,
14693
+ prepare: "husky install",
14694
+ "dev:site": "cd apps/site && npm run start",
14695
+ "build:site": "cd apps/site && npm run build",
14696
+ "sync:docs": "cd apps/site && node src/scripts/sync-agent-docs.js",
14697
+ "smart-push": "./scripts/smart-push.sh"
14698
+ },
14699
+ "lint-staged": {
14700
+ "*.{ts,tsx}": [
14701
+ "eslint --fix"
14702
+ ],
14703
+ "*.{js,jsx,mjs}": [
14704
+ "eslint --fix"
14705
+ ],
14706
+ "*.{md,mdx}": [
14707
+ "prettier --write"
14708
+ ],
14709
+ "*.{json,yml,yaml}": [
14710
+ "prettier --write"
14711
+ ]
14712
+ },
14713
+ keywords: [
14714
+ "cli",
14715
+ "agent",
14716
+ "text-editor",
14717
+ "grok",
14718
+ "ai"
14719
+ ],
14720
+ author: "grok_cli",
14721
+ license: "MIT",
14722
+ dependencies: {
14723
+ "@modelcontextprotocol/sdk": "^1.17.0",
14724
+ "@types/marked-terminal": "^6.1.1",
14725
+ "@typescript-eslint/typescript-estree": "^8.46.0",
14726
+ ajv: "^8.17.1",
14727
+ "ajv-formats": "^3.0.1",
14728
+ axios: "^1.7.0",
14729
+ cfonts: "^3.3.0",
14730
+ chalk: "^5.3.0",
14731
+ chokidar: "^4.0.3",
14732
+ "cli-highlight": "^2.1.11",
14733
+ commander: "^12.0.0",
14734
+ dotenv: "^16.4.0",
14735
+ enquirer: "^2.4.1",
14736
+ "fs-extra": "^11.2.0",
14737
+ "fuse.js": "^7.1.0",
14738
+ glob: "^11.0.3",
14739
+ ink: "^4.4.1",
14740
+ "js-yaml": "^4.1.0",
14741
+ marked: "^15.0.12",
14742
+ "marked-terminal": "^7.3.0",
14743
+ openai: "^5.10.1",
14744
+ react: "^18.3.1",
14745
+ "ripgrep-node": "^1.0.0",
14746
+ "terminal-image": "^4.0.0",
14747
+ tiktoken: "^1.0.21"
14748
+ },
14749
+ devDependencies: {
14750
+ "@eslint/js": "^9.37.0",
14751
+ "@types/fs-extra": "^11.0.2",
14752
+ "@types/node": "^20.8.0",
14753
+ "@types/react": "^18.3.3",
14754
+ "@typescript-eslint/eslint-plugin": "^8.37.0",
14755
+ "@typescript-eslint/parser": "^8.37.0",
14756
+ esbuild: "^0.25.10",
14757
+ eslint: "^9.31.0",
14758
+ husky: "^9.1.7",
14759
+ "lint-staged": "^16.2.4",
14760
+ prettier: "^3.6.2",
14761
+ tsup: "^8.5.0",
14762
+ tsx: "^4.0.0"
14763
+ },
14764
+ engines: {
14765
+ node: ">=18.0.0"
14766
+ },
14767
+ preferGlobal: true,
14768
+ repository: {
14769
+ type: "git",
14770
+ url: "https://github.com/x-cli-team/x-cli.git"
14771
+ },
14772
+ bugs: {
14773
+ url: "https://github.com/x-cli-team/x-cli/issues"
14774
+ },
14775
+ homepage: "https://grokcli.dev",
14776
+ icon: "docs/assets/logos/x-cli-logo.svg",
14777
+ publishConfig: {
14778
+ access: "public"
14779
+ },
14780
+ installConfig: {
14781
+ hoisting: false
14782
+ },
14783
+ optionalDependencies: {
14784
+ "tree-sitter": "^0.21.1",
14785
+ "tree-sitter-javascript": "^0.21.2",
14786
+ "tree-sitter-python": "^0.21.0",
14787
+ "tree-sitter-typescript": "^0.21.2"
14788
+ },
14789
+ trustedDependencies: [
14790
+ "esbuild",
14791
+ "tree-sitter",
14792
+ "tree-sitter-javascript",
14793
+ "tree-sitter-python",
14794
+ "tree-sitter-typescript"
14795
+ ]
14796
+ };
14797
+ var execAsync3 = promisify(exec);
14798
+ async function checkForUpdates() {
14799
+ try {
14800
+ const { stdout } = await execAsync3(`npm view ${package_default.name} version`, {
14801
+ timeout: 5e3
14802
+ });
14803
+ const latestVersion = stdout.trim();
14804
+ const currentVersion = package_default.version;
14805
+ const isUpdateAvailable = latestVersion !== currentVersion && isNewerVersion(latestVersion, currentVersion);
14806
+ return {
14807
+ current: currentVersion,
14808
+ latest: latestVersion,
14809
+ isUpdateAvailable,
14810
+ updateCommand: `npm update -g ${package_default.name}@latest`
14811
+ };
14812
+ } catch {
14813
+ return {
14814
+ current: package_default.version,
14815
+ latest: package_default.version,
14816
+ isUpdateAvailable: false,
14817
+ updateCommand: `npm update -g ${package_default.name}@latest`
14818
+ };
14819
+ }
14820
+ }
14821
+ function isNewerVersion(version1, version2) {
14822
+ const v1Parts = version1.split(".").map(Number);
14823
+ const v2Parts = version2.split(".").map(Number);
14824
+ for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
14825
+ const v1Part = v1Parts[i] || 0;
14826
+ const v2Part = v2Parts[i] || 0;
14827
+ if (v1Part > v2Part) return true;
14828
+ if (v1Part < v2Part) return false;
14829
+ }
14830
+ return false;
14831
+ }
14832
+ async function autoUpgrade() {
14833
+ try {
14834
+ console.log("\u{1F504} Upgrading X-CLI...");
14835
+ await execAsync3(`npm update -g ${package_default.name}@latest`, {
14836
+ timeout: 3e4
14837
+ });
14838
+ console.log("\u2705 Upgrade completed! Please restart the CLI.");
14839
+ return true;
14840
+ } catch (error) {
14841
+ console.error("\u274C Auto-upgrade failed:", error);
14842
+ return false;
14843
+ }
14844
+ }
14845
+ var cachedVersionInfo = null;
14846
+ var lastCheckTime = 0;
14847
+ var CHECK_INTERVAL = 6 * 60 * 60 * 1e3;
14848
+ async function getCachedVersionInfo() {
14849
+ const now = Date.now();
14850
+ if (cachedVersionInfo && now - lastCheckTime < CHECK_INTERVAL) {
14851
+ return cachedVersionInfo;
14852
+ }
14853
+ try {
14854
+ cachedVersionInfo = await checkForUpdates();
14855
+ lastCheckTime = now;
14856
+ return cachedVersionInfo;
14857
+ } catch {
14858
+ return null;
14859
+ }
14860
+ }
14861
+
14862
+ // src/hooks/use-input-handler.ts
14863
+ init_settings_manager();
14864
+ function useInputHandler({
14865
+ agent,
14866
+ chatHistory,
14867
+ setChatHistory,
14868
+ setIsProcessing,
14869
+ setIsStreaming,
14870
+ setTokenCount,
14871
+ setProcessingTime,
14872
+ processingStartTime,
14873
+ isProcessing,
14874
+ isStreaming,
14875
+ isConfirmationActive = false,
14876
+ onGlobalShortcut
14877
+ }) {
14878
+ const [showCommandSuggestions, setShowCommandSuggestions] = useState(false);
14879
+ const [selectedCommandIndex, setSelectedCommandIndex] = useState(0);
14880
+ const [showModelSelection, setShowModelSelection] = useState(false);
14881
+ const [selectedModelIndex, setSelectedModelIndex] = useState(0);
14882
+ const [autoEditEnabled, setAutoEditEnabled] = useState(() => {
14883
+ const confirmationService = ConfirmationService.getInstance();
14884
+ const sessionFlags = confirmationService.getSessionFlags();
14885
+ return sessionFlags.allOperations;
14886
+ });
14887
+ const [shiftTabPressCount, setShiftTabPressCount] = useState(0);
14888
+ const [lastShiftTabTime, setLastShiftTabTime] = useState(0);
14889
+ const [verbosityLevel, setVerbosityLevel] = useState(() => {
14890
+ try {
14891
+ const manager = getSettingsManager();
14892
+ return manager.getUserSetting("verbosityLevel") || "quiet";
14893
+ } catch {
14894
+ return "quiet";
14895
+ }
14896
+ });
14897
+ const [explainLevel, setExplainLevel] = useState(() => {
14898
14898
  try {
14899
14899
  const manager = getSettingsManager();
14900
14900
  return manager.getUserSetting("explainLevel") || "brief";
@@ -16564,842 +16564,632 @@ Operations will now ${newLevel === "off" ? "show no explanations" : newLevel ===
16564
16564
  planMode
16565
16565
  };
16566
16566
  }
16567
-
16568
- // src/ui/colors.ts
16569
- var inkColors = {
16570
- primary: "cyan",
16571
- success: "green",
16572
- warning: "yellow",
16573
- error: "red",
16574
- info: "blue",
16575
- muted: "gray",
16576
- accent: "magenta",
16577
- text: "white",
16578
- successBright: "greenBright",
16579
- accentBright: "magentaBright"
16580
- };
16581
- function getSpinnerColor(operation) {
16582
- switch (operation.toLowerCase()) {
16583
- case "search":
16584
- case "indexing":
16585
- case "scanning":
16586
- return "info";
16587
- case "process":
16588
- case "thinking":
16589
- case "analyzing":
16590
- return "warning";
16591
- case "write":
16592
- case "edit":
16593
- case "create":
16594
- return "success";
16595
- case "compact":
16596
- case "optimize":
16597
- case "memory":
16598
- return "accent";
16599
- default:
16600
- return "primary";
16601
- }
16602
- }
16603
- var operationConfig = {
16604
- thinking: {
16605
- icon: "\u{1F9E0}",
16606
- spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
16607
- messages: ["Thinking...", "Processing...", "Analyzing...", "Computing...", "Reasoning..."]
16608
- },
16609
- search: {
16610
- icon: "\u{1F50D}",
16611
- spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
16612
- messages: ["Searching...", "Scanning files...", "Finding matches...", "Indexing..."]
16613
- },
16614
- indexing: {
16615
- icon: "\u{1F4C2}",
16616
- spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
16617
- messages: ["Indexing workspace...", "Building context...", "Mapping relationships..."]
16618
- },
16619
- write: {
16620
- icon: "\u{1F4DD}",
16621
- spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
16622
- messages: ["Writing file...", "Saving changes...", "Updating content..."]
16623
- },
16624
- edit: {
16625
- icon: "\u270F\uFE0F",
16626
- spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
16627
- messages: ["Editing file...", "Applying changes...", "Modifying content..."]
16628
- },
16629
- compact: {
16630
- icon: "\u{1F504}",
16631
- spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
16632
- messages: ["Compacting context...", "Optimizing memory...", "Refreshing session..."]
16633
- },
16634
- analyze: {
16635
- icon: "\u{1F52C}",
16636
- spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
16637
- messages: ["Analyzing code...", "Understanding structure...", "Mapping dependencies..."]
16638
- },
16639
- process: {
16640
- icon: "\u26A1",
16641
- spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
16642
- messages: ["Processing...", "Working...", "Computing...", "Executing..."]
16643
- }
16644
- };
16645
- function LoadingSpinner({
16646
- isActive,
16647
- processingTime,
16648
- tokenCount,
16649
- operation = "thinking",
16650
- message,
16651
- progress
16652
- }) {
16653
- const [frameIndex, setFrameIndex] = useState(0);
16654
- const [messageIndex, setMessageIndex] = useState(0);
16655
- const config2 = operationConfig[operation];
16656
- const spinnerChar = config2.spinner[frameIndex % config2.spinner.length];
16657
- const operationMessage = message || config2.messages[messageIndex % config2.messages.length];
16658
- const color = getSpinnerColor(operation);
16659
- useEffect(() => {
16660
- if (!isActive) return;
16661
- const interval = setInterval(() => {
16662
- setFrameIndex((prev) => prev + 1);
16663
- }, 80);
16664
- return () => clearInterval(interval);
16665
- }, [isActive]);
16666
- useEffect(() => {
16667
- if (!isActive) return;
16668
- const messageInterval = setInterval(() => {
16669
- setMessageIndex((prev) => prev + 1);
16670
- }, 80 * config2.spinner.length * 3);
16671
- return () => clearInterval(messageInterval);
16672
- }, [isActive, config2.spinner.length]);
16673
- if (!isActive) return null;
16674
- const renderProgressBar = () => {
16675
- if (progress === void 0) return null;
16676
- const barLength = 20;
16677
- const filled = Math.round(progress / 100 * barLength);
16678
- const empty = barLength - filled;
16679
- const progressBar = "\u2588".repeat(filled) + "\u2591".repeat(empty);
16680
- return /* @__PURE__ */ jsxs(Text, { color: inkColors.muted, children: [
16681
- " ",
16682
- "[",
16683
- /* @__PURE__ */ jsx(Text, { color, children: progressBar }),
16684
- "] ",
16685
- progress,
16686
- "%"
16687
- ] });
16567
+ init_settings_manager();
16568
+ function ApiKeyInput({ onApiKeySet }) {
16569
+ const [input, setInput] = useState("");
16570
+ const [error, setError] = useState("");
16571
+ const [isSubmitting, setIsSubmitting] = useState(false);
16572
+ const { exit } = useApp();
16573
+ useInput((inputChar, key) => {
16574
+ if (isSubmitting) return;
16575
+ if (key.ctrl && inputChar === "c") {
16576
+ exit();
16577
+ return;
16578
+ }
16579
+ if (key.return) {
16580
+ handleSubmit();
16581
+ return;
16582
+ }
16583
+ if (key.backspace || key.delete) {
16584
+ setInput((prev) => prev.slice(0, -1));
16585
+ setError("");
16586
+ return;
16587
+ }
16588
+ if (inputChar && !key.ctrl && !key.meta) {
16589
+ setInput((prev) => prev + inputChar);
16590
+ setError("");
16591
+ }
16592
+ });
16593
+ const handleSubmit = async () => {
16594
+ if (!input.trim()) {
16595
+ setError("API key cannot be empty");
16596
+ return;
16597
+ }
16598
+ setIsSubmitting(true);
16599
+ try {
16600
+ const apiKey = input.trim();
16601
+ const agent = new GrokAgent(apiKey);
16602
+ process.env.GROK_API_KEY = apiKey;
16603
+ try {
16604
+ const manager = getSettingsManager();
16605
+ manager.updateUserSetting("apiKey", apiKey);
16606
+ console.log(`
16607
+ \u2705 API key saved to ~/.grok/user-settings.json`);
16608
+ } catch {
16609
+ console.log("\n\u26A0\uFE0F Could not save API key to settings file");
16610
+ console.log("API key set for current session only");
16611
+ }
16612
+ onApiKeySet(agent);
16613
+ } catch {
16614
+ setError("Invalid API key format");
16615
+ setIsSubmitting(false);
16616
+ }
16688
16617
  };
16689
- return /* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
16690
- /* @__PURE__ */ jsxs(Box, { children: [
16691
- /* @__PURE__ */ jsxs(Text, { color, children: [
16692
- config2.icon,
16693
- " ",
16694
- spinnerChar,
16695
- " ",
16696
- operationMessage
16697
- ] }),
16698
- renderProgressBar()
16618
+ const displayText = input.length > 0 ? isSubmitting ? "*".repeat(input.length) : "*".repeat(input.length) + "\u2588" : isSubmitting ? " " : "\u2588";
16619
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
16620
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u{1F511} Grok API Key Required" }),
16621
+ /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Please enter your Grok API key to continue:" }) }),
16622
+ /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: "blue", paddingX: 1, marginBottom: 1, children: [
16623
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u276F " }),
16624
+ /* @__PURE__ */ jsx(Text, { children: displayText })
16699
16625
  ] }),
16700
- /* @__PURE__ */ jsxs(Text, { color: inkColors.muted, children: [
16701
- " ",
16702
- "(",
16703
- processingTime,
16704
- "s \xB7 \u2191 ",
16705
- formatTokenCount(tokenCount),
16706
- " tokens \xB7 esc to interrupt)"
16707
- ] })
16626
+ error ? /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsxs(Text, { color: "red", children: [
16627
+ "\u274C ",
16628
+ error
16629
+ ] }) }) : null,
16630
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
16631
+ /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "\u2022 Press Enter to submit" }),
16632
+ /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "\u2022 Press Ctrl+C to exit" }),
16633
+ /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "Note: API key will be saved to ~/.grok/user-settings.json" })
16634
+ ] }),
16635
+ isSubmitting ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u{1F504} Validating API key..." }) }) : null
16708
16636
  ] });
16709
16637
  }
16710
- function ModelSelection({
16711
- models,
16712
- selectedIndex,
16713
- isVisible,
16714
- currentModel
16715
- }) {
16716
- if (!isVisible) return null;
16717
- return /* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
16718
- /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
16719
- "Select Grok Model (current: ",
16720
- currentModel,
16721
- "):"
16722
- ] }) }),
16723
- models.map((modelOption, index) => /* @__PURE__ */ jsx(Box, { paddingLeft: 1, children: /* @__PURE__ */ jsx(
16724
- Text,
16725
- {
16726
- color: index === selectedIndex ? "black" : "white",
16727
- backgroundColor: index === selectedIndex ? "cyan" : void 0,
16728
- children: modelOption.model
16638
+ function useContextInfo(agent) {
16639
+ const [contextInfo, setContextInfo] = useState({
16640
+ workspaceFiles: 0,
16641
+ indexSize: "0 MB",
16642
+ sessionFiles: 0,
16643
+ activeTokens: 0,
16644
+ lastActivity: "Now",
16645
+ memoryPressure: "low",
16646
+ isLoading: true,
16647
+ messagesCount: 0,
16648
+ loadedFiles: [],
16649
+ contextHealth: "optimal"
16650
+ });
16651
+ const updateContextInfo = async () => {
16652
+ try {
16653
+ let tokenUsage;
16654
+ let messagesCount = 0;
16655
+ let loadedFiles = [];
16656
+ let contextHealth = "optimal";
16657
+ if (agent) {
16658
+ const modelName = agent.getCurrentModel?.() || "grok-code-fast-1";
16659
+ const maxTokens = getMaxTokensForModel(modelName);
16660
+ const estimatedTokens = Math.floor(Math.random() * 1e3) + 500;
16661
+ messagesCount = Math.floor(Math.random() * 10) + 1;
16662
+ const tokenPercent = Math.round(estimatedTokens / maxTokens * 100);
16663
+ tokenUsage = {
16664
+ current: estimatedTokens,
16665
+ max: maxTokens,
16666
+ percent: tokenPercent
16667
+ };
16668
+ if (tokenPercent >= 95) contextHealth = "critical";
16669
+ else if (tokenPercent >= 80) contextHealth = "degraded";
16670
+ else contextHealth = "optimal";
16671
+ loadedFiles = [];
16729
16672
  }
16730
- ) }, index)),
16731
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "\u2191\u2193 navigate \u2022 Enter/Tab select \u2022 Esc cancel" }) })
16732
- ] });
16733
- }
16734
-
16735
- // src/ui/utils/colors.ts
16736
- var Colors = {
16737
- AccentYellow: "yellow",
16738
- Gray: "gray"};
16739
- var MaxSizedBox = ({
16740
- maxHeight: _maxHeight,
16741
- maxWidth: _maxWidth,
16742
- children,
16743
- ...props
16744
- }) => {
16745
- return /* @__PURE__ */ jsx(
16746
- Box,
16747
- {
16748
- flexDirection: "column",
16749
- ...props,
16750
- children
16751
- }
16752
- );
16753
- };
16754
- function parseDiffWithLineNumbers(diffContent) {
16755
- const lines = diffContent.split("\n");
16756
- const result = [];
16757
- let currentOldLine = 0;
16758
- let currentNewLine = 0;
16759
- let inHunk = false;
16760
- const hunkHeaderRegex = /^@@ -(\d+),?\d* \+(\d+),?\d* @@/;
16761
- for (const line of lines) {
16762
- const hunkMatch = line.match(hunkHeaderRegex);
16763
- if (hunkMatch) {
16764
- currentOldLine = parseInt(hunkMatch[1], 10);
16765
- currentNewLine = parseInt(hunkMatch[2], 10);
16766
- inHunk = true;
16767
- result.push({ type: "hunk", content: line });
16768
- currentOldLine--;
16769
- currentNewLine--;
16770
- continue;
16771
- }
16772
- if (!inHunk) {
16773
- if (line.startsWith("--- ") || line.startsWith("+++ ") || line.startsWith("diff --git") || line.startsWith("index ") || line.startsWith("similarity index") || line.startsWith("rename from") || line.startsWith("rename to") || line.startsWith("new file mode") || line.startsWith("deleted file mode"))
16774
- continue;
16775
- continue;
16673
+ const info = {
16674
+ workspaceFiles: await getWorkspaceFileCount(),
16675
+ indexSize: await getIndexSize(),
16676
+ sessionFiles: await getSessionFileCount(),
16677
+ activeTokens: tokenUsage?.current || 0,
16678
+ lastActivity: "Now",
16679
+ gitBranch: await getGitBranch(),
16680
+ projectName: await getProjectName(),
16681
+ memoryPressure: getMemoryPressure(),
16682
+ isLoading: false,
16683
+ tokenUsage,
16684
+ messagesCount,
16685
+ loadedFiles,
16686
+ contextHealth
16687
+ };
16688
+ setContextInfo(info);
16689
+ } catch (error) {
16690
+ console.warn("[ContextInfo] Failed to update context:", error);
16691
+ setContextInfo((prev) => ({ ...prev, isLoading: false }));
16776
16692
  }
16777
- if (line.startsWith("+")) {
16778
- currentNewLine++;
16779
- result.push({
16780
- type: "add",
16781
- newLine: currentNewLine,
16782
- content: line.substring(1)
16783
- });
16784
- } else if (line.startsWith("-")) {
16785
- currentOldLine++;
16786
- result.push({
16787
- type: "del",
16788
- oldLine: currentOldLine,
16789
- content: line.substring(1)
16790
- });
16791
- } else if (line.startsWith(" ")) {
16792
- currentOldLine++;
16793
- currentNewLine++;
16794
- result.push({
16795
- type: "context",
16796
- oldLine: currentOldLine,
16797
- newLine: currentNewLine,
16798
- content: line.substring(1)
16799
- });
16800
- } else if (line.startsWith("\\")) {
16801
- result.push({ type: "other", content: line });
16693
+ };
16694
+ useEffect(() => {
16695
+ updateContextInfo();
16696
+ const interval = setInterval(updateContextInfo, 1e4);
16697
+ return () => clearInterval(interval);
16698
+ }, []);
16699
+ return {
16700
+ contextInfo,
16701
+ updateContextInfo,
16702
+ refreshContext: updateContextInfo
16703
+ };
16704
+ }
16705
+ async function getWorkspaceFileCount() {
16706
+ try {
16707
+ const cwd = process.cwd();
16708
+ const entries = await fs__default.promises.readdir(cwd, { withFileTypes: true });
16709
+ let count = 0;
16710
+ for (const entry of entries) {
16711
+ if (entry.isFile() && !shouldIgnoreFile(entry.name)) {
16712
+ count++;
16713
+ } else if (entry.isDirectory() && !shouldIgnoreDirectory(entry.name)) {
16714
+ try {
16715
+ const subEntries = await fs__default.promises.readdir(path7__default.join(cwd, entry.name), { withFileTypes: true });
16716
+ count += subEntries.filter((sub) => sub.isFile() && !shouldIgnoreFile(sub.name)).length;
16717
+ } catch {
16718
+ }
16719
+ }
16802
16720
  }
16721
+ return count;
16722
+ } catch {
16723
+ return 0;
16803
16724
  }
16804
- return result;
16805
16725
  }
16806
- var DEFAULT_TAB_WIDTH = 4;
16807
- var DiffRenderer = ({
16808
- diffContent,
16809
- filename,
16810
- tabWidth = DEFAULT_TAB_WIDTH,
16811
- availableTerminalHeight,
16812
- terminalWidth = 80
16813
- }) => {
16814
- if (!diffContent || typeof diffContent !== "string") {
16815
- return /* @__PURE__ */ jsx(Text, { color: Colors.AccentYellow, children: "No diff content." });
16816
- }
16817
- const lines = diffContent.split("\n");
16818
- const firstLine = lines[0];
16819
- let actualDiffContent = diffContent;
16820
- if (firstLine && (firstLine.startsWith("Updated ") || firstLine.startsWith("Created "))) {
16821
- actualDiffContent = lines.slice(1).join("\n");
16726
+ function shouldIgnoreFile(filename) {
16727
+ return filename.startsWith(".") || filename.endsWith(".log") || filename.includes(".tmp");
16728
+ }
16729
+ function shouldIgnoreDirectory(dirname5) {
16730
+ const ignoreDirs = ["node_modules", ".git", "dist", "build", ".next", "coverage"];
16731
+ return ignoreDirs.includes(dirname5) || dirname5.startsWith(".");
16732
+ }
16733
+ async function getIndexSize() {
16734
+ try {
16735
+ const indexPath = path7__default.join(process.cwd(), ".grok", "index.json");
16736
+ if (fs__default.existsSync(indexPath)) {
16737
+ const stats = await fs__default.promises.stat(indexPath);
16738
+ const mb = stats.size / (1024 * 1024);
16739
+ return mb > 1 ? `${mb.toFixed(1)} MB` : `${(stats.size / 1024).toFixed(1)} KB`;
16740
+ }
16741
+ } catch {
16822
16742
  }
16823
- const parsedLines = parseDiffWithLineNumbers(actualDiffContent);
16824
- if (parsedLines.length === 0) {
16825
- return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No changes detected." });
16743
+ return "0 MB";
16744
+ }
16745
+ async function getSessionFileCount() {
16746
+ try {
16747
+ const sessionPath = path7__default.join(os__default.homedir(), ".grok", "session.log");
16748
+ if (fs__default.existsSync(sessionPath)) {
16749
+ const content = await fs__default.promises.readFile(sessionPath, "utf8");
16750
+ return content.split("\n").filter((line) => line.trim()).length;
16751
+ }
16752
+ } catch {
16826
16753
  }
16827
- const renderedOutput = renderDiffContent(
16828
- parsedLines,
16829
- filename,
16830
- tabWidth,
16831
- availableTerminalHeight,
16832
- terminalWidth
16833
- );
16834
- return /* @__PURE__ */ jsx(Fragment, { children: renderedOutput });
16835
- };
16836
- var renderDiffContent = (parsedLines, filename, tabWidth = DEFAULT_TAB_WIDTH, availableTerminalHeight, terminalWidth) => {
16837
- const normalizedLines = parsedLines.map((line) => ({
16838
- ...line,
16839
- content: line.content.replace(/\t/g, " ".repeat(tabWidth))
16840
- }));
16841
- const displayableLines = normalizedLines.filter(
16842
- (l) => l.type !== "hunk" && l.type !== "other"
16843
- );
16844
- if (displayableLines.length === 0) {
16845
- return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No changes detected." });
16754
+ return 0;
16755
+ }
16756
+ async function getGitBranch() {
16757
+ try {
16758
+ const gitPath = path7__default.join(process.cwd(), ".git", "HEAD");
16759
+ if (fs__default.existsSync(gitPath)) {
16760
+ const content = await fs__default.promises.readFile(gitPath, "utf8");
16761
+ const match = content.match(/ref: refs\/heads\/(.+)/);
16762
+ return match ? match[1].trim() : "detached";
16763
+ }
16764
+ } catch {
16846
16765
  }
16847
- let baseIndentation = Infinity;
16848
- for (const line of displayableLines) {
16849
- if (line.content.trim() === "") continue;
16850
- const firstCharIndex = line.content.search(/\S/);
16851
- const currentIndent = firstCharIndex === -1 ? 0 : firstCharIndex;
16852
- baseIndentation = Math.min(baseIndentation, currentIndent);
16766
+ return void 0;
16767
+ }
16768
+ async function getProjectName() {
16769
+ try {
16770
+ const packagePath = path7__default.join(process.cwd(), "package.json");
16771
+ if (fs__default.existsSync(packagePath)) {
16772
+ const content = await fs__default.promises.readFile(packagePath, "utf8");
16773
+ const pkg = JSON.parse(content);
16774
+ return pkg.name;
16775
+ }
16776
+ } catch {
16853
16777
  }
16854
- if (!isFinite(baseIndentation)) {
16855
- baseIndentation = 0;
16778
+ return path7__default.basename(process.cwd());
16779
+ }
16780
+ function getMemoryPressure() {
16781
+ try {
16782
+ const memUsage = process.memoryUsage();
16783
+ const heapUsedMB = memUsage.heapUsed / 1024 / 1024;
16784
+ if (heapUsedMB > 200) return "high";
16785
+ if (heapUsedMB > 100) return "medium";
16786
+ return "low";
16787
+ } catch {
16788
+ return "low";
16856
16789
  }
16857
- const key = filename ? `diff-box-${filename}` : `diff-box-${crypto.createHash("sha1").update(JSON.stringify(parsedLines)).digest("hex")}`;
16858
- let lastLineNumber = null;
16859
- const MAX_CONTEXT_LINES_WITHOUT_GAP = 5;
16860
- return /* @__PURE__ */ jsx(
16861
- MaxSizedBox,
16862
- {
16863
- maxHeight: availableTerminalHeight,
16864
- maxWidth: terminalWidth,
16865
- children: displayableLines.reduce((acc, line, index) => {
16866
- let relevantLineNumberForGapCalc = null;
16867
- if (line.type === "add" || line.type === "context") {
16868
- relevantLineNumberForGapCalc = line.newLine ?? null;
16869
- } else if (line.type === "del") {
16870
- relevantLineNumberForGapCalc = line.oldLine ?? null;
16871
- }
16872
- if (lastLineNumber !== null && relevantLineNumberForGapCalc !== null && relevantLineNumberForGapCalc > lastLineNumber + MAX_CONTEXT_LINES_WITHOUT_GAP + 1) {
16873
- acc.push(
16874
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { wrap: "truncate", children: "\u2550".repeat(terminalWidth) }) }, `gap-${index}`)
16875
- );
16790
+ }
16791
+ function getMaxTokensForModel(modelName) {
16792
+ const modelLimits = {
16793
+ "grok-code-fast-1": 128e3,
16794
+ "grok-4-latest": 2e5,
16795
+ "grok-3-latest": 2e5,
16796
+ "grok-3-fast": 128e3,
16797
+ "grok-3-mini-fast": 64e3,
16798
+ "claude-sonnet-4": 2e5,
16799
+ "claude-opus-4": 2e5,
16800
+ "gpt-4o": 128e3,
16801
+ "gpt-4": 32e3
16802
+ };
16803
+ return modelLimits[modelName] || 128e3;
16804
+ }
16805
+ function useAutoRead(setChatHistory) {
16806
+ useEffect(() => {
16807
+ if (fs__default.existsSync(".agent")) {
16808
+ const initialMessages = [];
16809
+ let docsRead = 0;
16810
+ let config2 = null;
16811
+ const configPaths = [
16812
+ path7__default.join(".xcli", "auto-read-config.json"),
16813
+ // User config (distributed)
16814
+ path7__default.join(".agent", "auto-read-config.json")
16815
+ // Dev override (gitignored)
16816
+ ];
16817
+ for (const configPath of configPaths) {
16818
+ if (fs__default.existsSync(configPath)) {
16819
+ try {
16820
+ const configContent = fs__default.readFileSync(configPath, "utf8");
16821
+ config2 = JSON.parse(configContent);
16822
+ break;
16823
+ } catch (_error) {
16824
+ }
16876
16825
  }
16877
- const lineKey = `diff-line-${index}`;
16878
- let gutterNumStr = "";
16879
- let backgroundColor = void 0;
16880
- let prefixSymbol = " ";
16881
- let dim = false;
16882
- switch (line.type) {
16883
- case "add":
16884
- gutterNumStr = (line.newLine ?? "").toString();
16885
- backgroundColor = "#86efac";
16886
- prefixSymbol = "+";
16887
- lastLineNumber = line.newLine ?? null;
16888
- break;
16889
- case "del":
16890
- gutterNumStr = (line.oldLine ?? "").toString();
16891
- backgroundColor = "redBright";
16892
- prefixSymbol = "-";
16893
- if (line.oldLine !== void 0) {
16894
- lastLineNumber = line.oldLine;
16895
- }
16896
- break;
16897
- case "context":
16898
- gutterNumStr = (line.newLine ?? "").toString();
16899
- dim = true;
16900
- prefixSymbol = " ";
16901
- lastLineNumber = line.newLine ?? null;
16902
- break;
16903
- default:
16904
- return acc;
16905
- }
16906
- const displayContent = line.content.substring(baseIndentation);
16907
- acc.push(
16908
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
16909
- /* @__PURE__ */ jsx(Text, { color: Colors.Gray, dimColor: dim, children: gutterNumStr.padEnd(4) }),
16910
- /* @__PURE__ */ jsxs(Text, { color: backgroundColor ? "#000000" : void 0, backgroundColor, dimColor: !backgroundColor && dim, children: [
16911
- prefixSymbol,
16912
- " "
16913
- ] }),
16914
- /* @__PURE__ */ jsx(Text, { color: backgroundColor ? "#000000" : void 0, backgroundColor, dimColor: !backgroundColor && dim, wrap: "wrap", children: displayContent })
16915
- ] }, lineKey)
16916
- );
16917
- return acc;
16918
- }, [])
16919
- },
16920
- key
16921
- );
16922
- };
16923
- marked.setOptions({
16924
- renderer: new TerminalRenderer()
16925
- });
16926
- function MarkdownRenderer({ content }) {
16927
- try {
16928
- const result = marked.parse(content);
16929
- const rendered = typeof result === "string" ? result : content;
16930
- return /* @__PURE__ */ jsx(Text, { children: rendered });
16931
- } catch (error) {
16932
- console.error("Markdown rendering error:", error);
16933
- return /* @__PURE__ */ jsx(Text, { children: content });
16934
- }
16935
- }
16936
- var truncateContent = (content, maxLength = 100) => {
16937
- if (process.env.COMPACT !== "1") return content;
16938
- return content.length > maxLength ? content.substring(0, maxLength) + "..." : content;
16939
- };
16940
- var handleLongContent = (content, maxLength = 5e3) => {
16941
- if (content.length <= maxLength) {
16942
- return { content, isTruncated: false };
16943
- }
16944
- const truncated = content.substring(0, maxLength);
16945
- const summary = `
16946
-
16947
- [Content truncated - ${content.length - maxLength} characters remaining. Full content available in chat history.]`;
16948
- return {
16949
- content: truncated + summary,
16950
- isTruncated: true
16951
- };
16952
- };
16953
- var MemoizedChatEntry = React3.memo(
16954
- ({ entry, index, verbosityLevel, explainLevel }) => {
16955
- const getExplanation = (toolName, filePath, _isExecuting) => {
16956
- if (explainLevel === "off") return null;
16957
- const explanations = {
16958
- view_file: {
16959
- brief: `Reading ${filePath} to examine its contents`,
16960
- detailed: `Reading the file ${filePath} to examine its current contents, structure, and implementation details for analysis or modification.`
16961
- },
16962
- str_replace_editor: {
16963
- brief: `Updating ${filePath} with changes`,
16964
- detailed: `Applying targeted modifications to ${filePath} using precise string replacement to update specific code sections while preserving the rest of the file structure.`
16965
- },
16966
- create_file: {
16967
- brief: `Creating new file ${filePath}`,
16968
- detailed: `Creating a new file at ${filePath} with the specified content, establishing the initial structure and implementation for this component or module.`
16969
- },
16970
- bash: {
16971
- brief: `Executing command: ${filePath}`,
16972
- detailed: `Running the shell command "${filePath}" to perform system operations, file management, or external tool execution as requested.`
16826
+ }
16827
+ const isEnabled = config2?.enabled !== false;
16828
+ const showLoadingMessage = config2?.showLoadingMessage !== false;
16829
+ const showSummaryMessage = config2?.showSummaryMessage !== false;
16830
+ const showFileContents = config2?.showFileContents === true;
16831
+ if (!isEnabled) {
16832
+ return;
16833
+ }
16834
+ if (showLoadingMessage) {
16835
+ initialMessages.push({
16836
+ type: "assistant",
16837
+ content: "\u{1F4DA} Reading core documentation into memory...",
16838
+ timestamp: /* @__PURE__ */ new Date()
16839
+ });
16840
+ }
16841
+ const folders = config2?.folders || [
16842
+ {
16843
+ name: "system",
16844
+ priority: 1,
16845
+ files: [
16846
+ { name: "architecture.md", title: "System Architecture", icon: "\u{1F4CB}", required: true },
16847
+ { name: "critical-state.md", title: "Critical State", icon: "\u{1F3D7}\uFE0F", required: false },
16848
+ { name: "installation.md", title: "Installation", icon: "\u{1F3D7}\uFE0F", required: false },
16849
+ { name: "api-schema.md", title: "API Schema", icon: "\u{1F3D7}\uFE0F", required: false },
16850
+ { name: "auto-read-system.md", title: "Auto-Read System", icon: "\u{1F3D7}\uFE0F", required: false }
16851
+ ]
16973
16852
  },
16974
- search: {
16975
- brief: `Searching for: ${filePath}`,
16976
- detailed: `Performing a comprehensive search across the codebase for "${filePath}" to locate relevant files, functions, or code patterns that match the query.`
16977
- }
16978
- };
16979
- const explanation = explanations[toolName];
16980
- if (!explanation) return null;
16981
- return explainLevel === "detailed" ? explanation.detailed : explanation.brief;
16982
- };
16983
- const renderDiff = (diffContent, filename) => {
16984
- return /* @__PURE__ */ jsx(
16985
- DiffRenderer,
16986
16853
  {
16987
- diffContent,
16988
- filename,
16989
- terminalWidth: 80
16854
+ name: "sop",
16855
+ priority: 2,
16856
+ files: [
16857
+ { name: "git-workflow.md", title: "Git Workflow SOP", icon: "\u{1F527}", required: true },
16858
+ { name: "release-management.md", title: "Release Management SOP", icon: "\u{1F4D6}", required: false },
16859
+ { name: "automation-protection.md", title: "Automation Protection SOP", icon: "\u{1F4D6}", required: false },
16860
+ { name: "npm-publishing-troubleshooting.md", title: "NPM Publishing Troubleshooting", icon: "\u{1F4D6}", required: false }
16861
+ ]
16990
16862
  }
16991
- );
16992
- };
16993
- const renderFileContent = (content) => {
16994
- const lines = content.split("\n");
16995
- let baseIndentation = Infinity;
16996
- for (const line of lines) {
16997
- if (line.trim() === "") continue;
16998
- const firstCharIndex = line.search(/\S/);
16999
- const currentIndent = firstCharIndex === -1 ? 0 : firstCharIndex;
17000
- baseIndentation = Math.min(baseIndentation, currentIndent);
17001
- }
17002
- if (!isFinite(baseIndentation)) {
17003
- baseIndentation = 0;
16863
+ ];
16864
+ if (config2?.customFolders) {
16865
+ folders.push(...config2.customFolders);
17004
16866
  }
17005
- return lines.map((line, index2) => {
17006
- const displayContent = line.substring(baseIndentation);
17007
- return /* @__PURE__ */ jsx(Text, { color: "gray", children: displayContent }, index2);
17008
- });
17009
- };
17010
- switch (entry.type) {
17011
- case "user":
17012
- const displayText = entry.isPasteSummary ? entry.displayContent || entry.content : entry.content;
17013
- const textColor = entry.isPasteSummary ? "cyan" : "gray";
17014
- return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: textColor, children: [
17015
- ">",
17016
- " ",
17017
- truncateContent(displayText)
17018
- ] }) }) }, index);
17019
- case "assistant":
17020
- const { content: processedContent, isTruncated } = handleLongContent(entry.content);
17021
- return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "flex-start", children: [
17022
- /* @__PURE__ */ jsx(Text, { color: "white", children: "\u23FA " }),
17023
- /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [
17024
- entry.toolCalls ? (
17025
- // If there are tool calls, just show plain text
17026
- /* @__PURE__ */ jsx(Text, { color: "white", children: processedContent.trim() })
17027
- ) : (
17028
- // If no tool calls, render as markdown
17029
- /* @__PURE__ */ jsx(MarkdownRenderer, { content: processedContent.trim() })
17030
- ),
17031
- entry.isStreaming && /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u2588" }),
17032
- isTruncated && /* @__PURE__ */ jsx(Text, { color: "yellow", italic: true, children: "[Response truncated for performance - full content in session log]" })
17033
- ] })
17034
- ] }) }, index);
17035
- case "tool_call":
17036
- case "tool_result":
17037
- const getToolActionName = (toolName2) => {
17038
- if (toolName2.startsWith("mcp__")) {
17039
- const parts = toolName2.split("__");
17040
- if (parts.length >= 3) {
17041
- const serverName = parts[1];
17042
- const actualToolName = parts.slice(2).join("__");
17043
- return `${serverName.charAt(0).toUpperCase() + serverName.slice(1)}(${actualToolName.replace(/_/g, " ")})`;
17044
- }
17045
- }
17046
- switch (toolName2) {
17047
- case "view_file":
17048
- return "Read";
17049
- case "str_replace_editor":
17050
- return "Update";
17051
- case "create_file":
17052
- return "Create";
17053
- case "bash":
17054
- return "Bash";
17055
- case "search":
17056
- return "Search";
17057
- case "create_todo_list":
17058
- return "Created Todo";
17059
- case "update_todo_list":
17060
- return "Updated Todo";
17061
- default:
17062
- return "Tool";
16867
+ folders.sort((a, b) => (a.priority || 999) - (b.priority || 999));
16868
+ for (const folder of folders) {
16869
+ const folderPath = path7__default.join(".agent", folder.name);
16870
+ if (!fs__default.existsSync(folderPath)) {
16871
+ continue;
16872
+ }
16873
+ for (const file of folder.files) {
16874
+ let filePaths = [];
16875
+ if (file.pattern) {
16876
+ continue;
16877
+ } else {
16878
+ filePaths = [file.name];
17063
16879
  }
17064
- };
17065
- const toolName = entry.toolCall?.function?.name || "unknown";
17066
- const actionName = getToolActionName(toolName);
17067
- const getFilePath = (toolCall) => {
17068
- if (toolCall?.function?.arguments) {
17069
- try {
17070
- const args = JSON.parse(toolCall.function.arguments);
17071
- if (toolCall.function.name === "search") {
17072
- return args.query;
17073
- }
17074
- return args.path || args.file_path || args.command || "";
17075
- } catch {
17076
- return "";
16880
+ for (const fileName of filePaths) {
16881
+ const filePath = path7__default.join(folderPath, fileName);
16882
+ if (!fs__default.existsSync(filePath)) {
16883
+ if (file.required) ;
16884
+ continue;
17077
16885
  }
17078
- }
17079
- return "";
17080
- };
17081
- const filePath = getFilePath(entry.toolCall);
17082
- const isExecuting = entry.type === "tool_call" || !entry.toolResult;
17083
- const formatToolContent = (content, toolName2) => {
17084
- const truncated = truncateContent(content, 200);
17085
- if (toolName2.startsWith("mcp__")) {
17086
16886
  try {
17087
- const parsed = JSON.parse(truncated);
17088
- if (Array.isArray(parsed)) {
17089
- return `Found ${parsed.length} items`;
17090
- } else if (typeof parsed === "object") {
17091
- return JSON.stringify(parsed, null, 2);
16887
+ const content = fs__default.readFileSync(filePath, "utf8");
16888
+ const displayTitle = file.title || fileName.replace(".md", "").replace("-", " ").toUpperCase();
16889
+ const icon = file.icon || "\u{1F4C4}";
16890
+ if (showFileContents) {
16891
+ initialMessages.push({
16892
+ type: "assistant",
16893
+ content: `${icon} **${displayTitle} (from .agent/${folder.name}/${fileName})**
16894
+
16895
+ ${content}`,
16896
+ timestamp: /* @__PURE__ */ new Date()
16897
+ });
17092
16898
  }
17093
- } catch {
17094
- return truncated;
16899
+ docsRead++;
16900
+ } catch (_error) {
17095
16901
  }
17096
16902
  }
17097
- return truncated;
17098
- };
17099
- const shouldShowDiff = entry.toolCall?.function?.name === "str_replace_editor" && entry.toolResult?.success && entry.content.includes("Updated") && entry.content.includes("---") && entry.content.includes("+++");
17100
- const shouldShowFileContent = (entry.toolCall?.function?.name === "view_file" || entry.toolCall?.function?.name === "create_file") && entry.toolResult?.success && !shouldShowDiff;
17101
- const shouldShowToolContent = verbosityLevel !== "quiet";
17102
- const shouldShowFullContent = verbosityLevel === "normal" || verbosityLevel === "verbose";
17103
- const explanation = getExplanation(toolName, filePath);
17104
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
17105
- /* @__PURE__ */ jsxs(Box, { children: [
17106
- /* @__PURE__ */ jsx(Text, { color: "magenta", children: "\u23FA" }),
17107
- /* @__PURE__ */ jsxs(Text, { color: "white", children: [
17108
- " ",
17109
- filePath ? `${actionName}(${filePath})` : actionName
17110
- ] })
17111
- ] }),
17112
- explanation && /* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsxs(Text, { color: "blue", italic: true, children: [
17113
- "\u{1F4A1} ",
17114
- explanation
17115
- ] }) }),
17116
- 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: [
17117
- /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u23BF File contents:" }),
17118
- /* @__PURE__ */ jsx(Box, { marginLeft: 2, flexDirection: "column", children: renderFileContent(entry.content) })
17119
- ] }) : shouldShowDiff && shouldShowFullContent ? (
17120
- // For diff results, show only the summary line, not the raw content
17121
- /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
17122
- "\u23BF ",
17123
- entry.content.split("\n")[0]
17124
- ] })
17125
- ) : !shouldShowFullContent ? /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u23BF Completed" }) : /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
17126
- "\u23BF ",
17127
- formatToolContent(entry.content, toolName)
17128
- ] }) }),
17129
- shouldShowDiff && !isExecuting && shouldShowFullContent && /* @__PURE__ */ jsx(Box, { marginLeft: 4, flexDirection: "column", children: renderDiff(entry.content, filePath) })
17130
- ] }, index);
17131
- default:
17132
- return null;
16903
+ }
16904
+ }
16905
+ if (showSummaryMessage && docsRead > 0) {
16906
+ initialMessages.push({
16907
+ type: "assistant",
16908
+ content: `\u2705 ${docsRead} documentation files read - I have a complete understanding of the current architecture and operational procedures.`,
16909
+ timestamp: /* @__PURE__ */ new Date()
16910
+ });
16911
+ }
16912
+ if (initialMessages.length > 0) {
16913
+ setChatHistory(initialMessages);
16914
+ }
17133
16915
  }
17134
- }
17135
- );
17136
- MemoizedChatEntry.displayName = "MemoizedChatEntry";
17137
- function ChatHistory({
17138
- entries,
17139
- isConfirmationActive = false,
17140
- verbosityLevel = "quiet",
17141
- explainLevel = "brief"
17142
- }) {
17143
- const filteredEntries = isConfirmationActive ? entries.filter(
17144
- (entry) => !(entry.type === "tool_call" && entry.content === "Executing...")
17145
- ) : entries;
17146
- const maxEntries = process.env.COMPACT === "1" ? 5 : 20;
17147
- return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: filteredEntries.slice(-maxEntries).map((entry, index) => /* @__PURE__ */ jsx(
17148
- MemoizedChatEntry,
17149
- {
17150
- entry,
17151
- index,
17152
- verbosityLevel,
17153
- explainLevel
17154
- },
17155
- `${entry.timestamp.getTime()}-${index}`
17156
- )) });
16916
+ }, [setChatHistory]);
17157
16917
  }
17158
- function ChatInput({
17159
- input,
17160
- cursorPosition,
17161
- isProcessing,
17162
- isStreaming
17163
- }) {
17164
- const beforeCursor = input.slice(0, cursorPosition);
17165
- const lines = input.split("\n");
17166
- const isMultiline = lines.length > 1;
17167
- let currentLineIndex = 0;
17168
- let currentCharIndex = 0;
17169
- let totalChars = 0;
17170
- for (let i = 0; i < lines.length; i++) {
17171
- if (totalChars + lines[i].length >= cursorPosition) {
17172
- currentLineIndex = i;
17173
- currentCharIndex = cursorPosition - totalChars;
17174
- break;
17175
- }
17176
- totalChars += lines[i].length + 1;
17177
- }
17178
- const showCursor = !isProcessing && !isStreaming;
17179
- const borderColor = isProcessing || isStreaming ? "yellow" : "blue";
17180
- const promptColor = "cyan";
17181
- const placeholderText = "Ask me anything...";
17182
- const isPlaceholder = !input;
17183
- if (isMultiline) {
17184
- return /* @__PURE__ */ jsx(
17185
- Box,
17186
- {
17187
- borderStyle: "round",
17188
- borderColor,
17189
- paddingY: 0,
17190
- marginTop: 1,
17191
- children: lines.map((line, index) => {
17192
- const isCurrentLine = index === currentLineIndex;
17193
- const promptChar = index === 0 ? "\u276F " : " ";
17194
- if (isCurrentLine) {
17195
- const beforeCursorInLine = line.slice(0, currentCharIndex);
17196
- const cursorChar2 = line.slice(currentCharIndex, currentCharIndex + 1) || " ";
17197
- const afterCursorInLine = line.slice(currentCharIndex + 1);
17198
- return /* @__PURE__ */ jsxs(Box, { children: [
17199
- /* @__PURE__ */ jsx(Text, { color: promptColor, children: promptChar }),
17200
- /* @__PURE__ */ jsxs(Text, { children: [
17201
- beforeCursorInLine,
17202
- showCursor && /* @__PURE__ */ jsx(Text, { backgroundColor: "white", color: "black", children: cursorChar2 }),
17203
- !showCursor && cursorChar2 !== " " && cursorChar2,
17204
- afterCursorInLine
17205
- ] })
17206
- ] }, index);
17207
- } else {
17208
- return /* @__PURE__ */ jsxs(Box, { children: [
17209
- /* @__PURE__ */ jsx(Text, { color: promptColor, children: promptChar }),
17210
- /* @__PURE__ */ jsx(Text, { children: line })
17211
- ] }, index);
16918
+ function useStreaming(agent, initialMessage, setChatHistory, streamingState) {
16919
+ const { setIsProcessing, setIsStreaming, setTokenCount } = streamingState;
16920
+ useEffect(() => {
16921
+ if (initialMessage && agent) {
16922
+ const userEntry = {
16923
+ type: "user",
16924
+ content: initialMessage,
16925
+ timestamp: /* @__PURE__ */ new Date()
16926
+ };
16927
+ setChatHistory(() => [userEntry]);
16928
+ const processInitialMessage = async () => {
16929
+ setIsProcessing(true);
16930
+ setIsStreaming(true);
16931
+ try {
16932
+ let streamingEntry = null;
16933
+ let accumulatedContent = "";
16934
+ let lastTokenCount = 0;
16935
+ let pendingToolCalls = null;
16936
+ let pendingToolResults = [];
16937
+ let lastUpdateTime = Date.now();
16938
+ const flushUpdates = () => {
16939
+ const now = Date.now();
16940
+ if (now - lastUpdateTime < 150) return;
16941
+ setChatHistory((prev) => {
16942
+ let newHistory = [...prev];
16943
+ if (lastTokenCount !== 0) {
16944
+ }
16945
+ if (accumulatedContent) {
16946
+ if (!streamingEntry) {
16947
+ const newStreamingEntry = {
16948
+ type: "assistant",
16949
+ content: accumulatedContent,
16950
+ timestamp: /* @__PURE__ */ new Date(),
16951
+ isStreaming: true
16952
+ };
16953
+ newHistory.push(newStreamingEntry);
16954
+ streamingEntry = newStreamingEntry;
16955
+ } else {
16956
+ const lastIdx = newHistory.length - 1;
16957
+ if (lastIdx >= 0 && newHistory[lastIdx].isStreaming) {
16958
+ newHistory[lastIdx] = { ...newHistory[lastIdx], content: newHistory[lastIdx].content + accumulatedContent };
16959
+ }
16960
+ }
16961
+ accumulatedContent = "";
16962
+ }
16963
+ if (pendingToolCalls) {
16964
+ const streamingIdx = newHistory.findIndex((entry) => entry.isStreaming);
16965
+ if (streamingIdx >= 0) {
16966
+ newHistory[streamingIdx] = { ...newHistory[streamingIdx], isStreaming: false, toolCalls: pendingToolCalls };
16967
+ }
16968
+ streamingEntry = null;
16969
+ pendingToolCalls.forEach((toolCall) => {
16970
+ const toolCallEntry = {
16971
+ type: "tool_call",
16972
+ content: "Executing...",
16973
+ timestamp: /* @__PURE__ */ new Date(),
16974
+ toolCall
16975
+ };
16976
+ newHistory.push(toolCallEntry);
16977
+ });
16978
+ pendingToolCalls = null;
16979
+ }
16980
+ if (pendingToolResults.length > 0) {
16981
+ newHistory = newHistory.map((entry) => {
16982
+ if (entry.isStreaming) {
16983
+ return { ...entry, isStreaming: false };
16984
+ }
16985
+ const matchingResult = pendingToolResults.find(
16986
+ (result) => entry.type === "tool_call" && entry.toolCall?.id === result.toolCall.id
16987
+ );
16988
+ if (matchingResult) {
16989
+ return {
16990
+ ...entry,
16991
+ type: "tool_result",
16992
+ content: matchingResult.toolResult.success ? matchingResult.toolResult.output || "Success" : matchingResult.toolResult.error || "Error occurred",
16993
+ toolResult: matchingResult.toolResult
16994
+ };
16995
+ }
16996
+ return entry;
16997
+ });
16998
+ streamingEntry = null;
16999
+ pendingToolResults = [];
17000
+ }
17001
+ return newHistory;
17002
+ });
17003
+ if (lastTokenCount !== 0) {
17004
+ setTokenCount(lastTokenCount);
17005
+ }
17006
+ lastUpdateTime = now;
17007
+ };
17008
+ for await (const chunk of agent.processUserMessageStream(initialMessage)) {
17009
+ switch (chunk.type) {
17010
+ case "content":
17011
+ if (chunk.content) {
17012
+ accumulatedContent += chunk.content;
17013
+ }
17014
+ break;
17015
+ case "token_count":
17016
+ if (chunk.tokenCount !== void 0) {
17017
+ lastTokenCount = chunk.tokenCount;
17018
+ }
17019
+ break;
17020
+ case "tool_calls":
17021
+ if (chunk.toolCalls) {
17022
+ pendingToolCalls = chunk.toolCalls;
17023
+ }
17024
+ break;
17025
+ case "tool_result":
17026
+ if (chunk.toolCall && chunk.toolResult) {
17027
+ pendingToolResults.push({ toolCall: chunk.toolCall, toolResult: chunk.toolResult });
17028
+ }
17029
+ break;
17030
+ case "done":
17031
+ flushUpdates();
17032
+ break;
17033
+ }
17034
+ flushUpdates();
17212
17035
  }
17213
- })
17214
- }
17215
- );
17216
- }
17217
- const cursorChar = input.slice(cursorPosition, cursorPosition + 1) || " ";
17218
- const afterCursorText = input.slice(cursorPosition + 1);
17219
- return /* @__PURE__ */ jsx(
17220
- Box,
17221
- {
17222
- borderStyle: "round",
17223
- borderColor,
17224
- paddingX: 1,
17225
- paddingY: 0,
17226
- marginTop: 1,
17227
- children: /* @__PURE__ */ jsxs(Box, { children: [
17228
- /* @__PURE__ */ jsx(Text, { color: promptColor, children: "\u276F " }),
17229
- isPlaceholder ? /* @__PURE__ */ jsxs(Fragment, { children: [
17230
- /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: placeholderText }),
17231
- showCursor && /* @__PURE__ */ jsx(Text, { backgroundColor: "white", color: "black", children: " " })
17232
- ] }) : /* @__PURE__ */ jsxs(Text, { children: [
17233
- beforeCursor,
17234
- showCursor && /* @__PURE__ */ jsx(Text, { backgroundColor: "white", color: "black", children: cursorChar }),
17235
- !showCursor && cursorChar !== " " && cursorChar,
17236
- afterCursorText
17237
- ] })
17238
- ] })
17036
+ flushUpdates();
17037
+ if (streamingEntry) {
17038
+ setChatHistory(
17039
+ (prev) => prev.map(
17040
+ (entry) => entry.isStreaming ? { ...entry, isStreaming: false } : entry
17041
+ )
17042
+ );
17043
+ }
17044
+ setIsStreaming(false);
17045
+ } catch (error) {
17046
+ const errorMessage = error instanceof Error ? error.message : String(error);
17047
+ const errorEntry = {
17048
+ type: "assistant",
17049
+ content: `Error: ${errorMessage}`,
17050
+ timestamp: /* @__PURE__ */ new Date()
17051
+ };
17052
+ setChatHistory((prev) => [...prev, errorEntry]);
17053
+ setIsStreaming(false);
17054
+ }
17055
+ setIsProcessing(false);
17056
+ };
17057
+ processInitialMessage();
17239
17058
  }
17240
- );
17059
+ }, [initialMessage, agent, setChatHistory, setIsProcessing, setIsStreaming, setTokenCount]);
17241
17060
  }
17242
- function MCPStatus({}) {
17243
- const [connectedServers, setConnectedServers] = useState([]);
17244
- const [_availableTools, setAvailableTools] = useState([]);
17061
+ function useConfirmations(confirmationService, state) {
17062
+ const {
17063
+ setConfirmationOptions,
17064
+ setIsProcessing,
17065
+ setIsStreaming,
17066
+ setTokenCount,
17067
+ setProcessingTime,
17068
+ processingStartTime
17069
+ } = state;
17245
17070
  useEffect(() => {
17246
- const updateStatus = () => {
17247
- try {
17248
- const manager = getMCPManager();
17249
- const servers = manager.getServers();
17250
- const tools = manager.getTools();
17251
- setConnectedServers(servers);
17252
- setAvailableTools(tools);
17253
- } catch (_error) {
17254
- setConnectedServers([]);
17255
- setAvailableTools([]);
17256
- }
17071
+ const handleConfirmationRequest = (options) => {
17072
+ setConfirmationOptions(options);
17257
17073
  };
17258
- const initialTimer = setTimeout(updateStatus, 2e3);
17259
- const interval = setInterval(updateStatus, 2e3);
17074
+ confirmationService.on("confirmation-requested", handleConfirmationRequest);
17260
17075
  return () => {
17261
- clearTimeout(initialTimer);
17262
- clearInterval(interval);
17076
+ confirmationService.off(
17077
+ "confirmation-requested",
17078
+ handleConfirmationRequest
17079
+ );
17263
17080
  };
17081
+ }, [confirmationService, setConfirmationOptions]);
17082
+ const handleConfirmation = (dontAskAgain) => {
17083
+ confirmationService.confirmOperation(true, dontAskAgain);
17084
+ setConfirmationOptions(null);
17085
+ };
17086
+ const handleRejection = (feedback) => {
17087
+ confirmationService.rejectOperation(feedback);
17088
+ setConfirmationOptions(null);
17089
+ setIsProcessing(false);
17090
+ setIsStreaming(false);
17091
+ setTokenCount(0);
17092
+ setProcessingTime(0);
17093
+ processingStartTime.current = 0;
17094
+ };
17095
+ return {
17096
+ handleConfirmation,
17097
+ handleRejection
17098
+ };
17099
+ }
17100
+ function useConsoleSetup() {
17101
+ useEffect(() => {
17102
+ const isWindows = process.platform === "win32";
17103
+ const isPowerShell = process.env.ComSpec?.toLowerCase().includes("powershell") || process.env.PSModulePath !== void 0;
17104
+ if (!isWindows || !isPowerShell) {
17105
+ console.clear();
17106
+ }
17107
+ console.log(" ");
17108
+ console.log(" ");
17109
+ const logoOutput = "X-CLI\n" + package_default.version;
17110
+ const logoLines = logoOutput.split("\n");
17111
+ logoLines.forEach((line) => {
17112
+ if (line.trim()) {
17113
+ console.log(" " + line);
17114
+ } else {
17115
+ console.log(line);
17116
+ }
17117
+ });
17118
+ console.log(" ");
17264
17119
  }, []);
17265
- if (connectedServers.length === 0) {
17266
- return null;
17267
- }
17268
- return /* @__PURE__ */ jsx(Box, { marginLeft: 1, children: /* @__PURE__ */ jsxs(Text, { color: "green", children: [
17269
- "\u2692 mcps: ",
17270
- connectedServers.length,
17271
- " "
17272
- ] }) });
17273
17120
  }
17274
- function ConfirmationDialog({
17275
- operation,
17276
- filename,
17277
- onConfirm,
17278
- onReject,
17279
- showVSCodeOpen = false,
17280
- content
17281
- }) {
17282
- const [selectedOption, setSelectedOption] = useState(0);
17283
- const [feedbackMode, setFeedbackMode] = useState(false);
17284
- const [feedback, setFeedback] = useState("");
17285
- const options = [
17286
- "Yes",
17287
- "Yes, and don't ask again this session",
17288
- "No",
17289
- "No, with feedback"
17290
- ];
17291
- useInput((input, key) => {
17292
- if (feedbackMode) {
17293
- if (key.return) {
17294
- onReject(feedback.trim());
17295
- return;
17296
- }
17297
- if (key.backspace || key.delete) {
17298
- setFeedback((prev) => prev.slice(0, -1));
17299
- return;
17300
- }
17301
- if (input && !key.ctrl && !key.meta) {
17302
- setFeedback((prev) => prev + input);
17121
+ function useSessionLogging(chatHistory) {
17122
+ const lastChatHistoryLength = useRef(0);
17123
+ useEffect(() => {
17124
+ const newEntries = chatHistory.slice(lastChatHistoryLength.current);
17125
+ if (newEntries.length > 0) {
17126
+ const sessionFile = path7__default.join(os__default.homedir(), ".grok", "session.log");
17127
+ try {
17128
+ const dir = path7__default.dirname(sessionFile);
17129
+ if (!fs__default.existsSync(dir)) {
17130
+ fs__default.mkdirSync(dir, { recursive: true });
17131
+ }
17132
+ const lines = newEntries.map((entry) => JSON.stringify(entry)).join("\n") + "\n";
17133
+ fs__default.appendFileSync(sessionFile, lines);
17134
+ } catch {
17303
17135
  }
17304
- return;
17305
- }
17306
- if (key.upArrow || key.shift && key.tab) {
17307
- setSelectedOption((prev) => prev > 0 ? prev - 1 : options.length - 1);
17308
- return;
17309
- }
17310
- if (key.downArrow || key.tab) {
17311
- setSelectedOption((prev) => (prev + 1) % options.length);
17312
- return;
17313
17136
  }
17314
- if (key.return) {
17315
- if (selectedOption === 0) {
17316
- onConfirm(false);
17317
- } else if (selectedOption === 1) {
17318
- onConfirm(true);
17319
- } else if (selectedOption === 2) {
17320
- onReject("Operation cancelled by user");
17321
- } else {
17322
- setFeedbackMode(true);
17323
- }
17137
+ lastChatHistoryLength.current = chatHistory.length;
17138
+ }, [chatHistory]);
17139
+ }
17140
+ function useProcessingTimer(isProcessing, isStreaming, setProcessingTime) {
17141
+ const processingStartTime = useRef(0);
17142
+ useEffect(() => {
17143
+ if (!isProcessing && !isStreaming) {
17144
+ setProcessingTime(0);
17324
17145
  return;
17325
17146
  }
17326
- if (key.escape) {
17327
- if (feedbackMode) {
17328
- setFeedbackMode(false);
17329
- setFeedback("");
17330
- } else {
17331
- onReject("Operation cancelled by user (pressed Escape)");
17332
- }
17333
- return;
17147
+ if (processingStartTime.current === 0) {
17148
+ processingStartTime.current = Date.now();
17334
17149
  }
17335
- });
17336
- if (feedbackMode) {
17337
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
17338
- /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Type your feedback and press Enter, or press Escape to go back." }) }),
17339
- /* @__PURE__ */ jsxs(
17340
- Box,
17341
- {
17342
- borderStyle: "round",
17343
- borderColor: "yellow",
17344
- paddingX: 1,
17345
- marginTop: 1,
17346
- children: [
17347
- /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u276F " }),
17348
- /* @__PURE__ */ jsxs(Text, { children: [
17349
- feedback,
17350
- /* @__PURE__ */ jsx(Text, { color: "white", children: "\u2588" })
17351
- ] })
17352
- ]
17353
- }
17354
- )
17355
- ] });
17150
+ const interval = setInterval(() => {
17151
+ setProcessingTime(
17152
+ Math.floor((Date.now() - processingStartTime.current) / 1e3)
17153
+ );
17154
+ }, 1e3);
17155
+ return () => clearInterval(interval);
17156
+ }, [isProcessing, isStreaming, setProcessingTime]);
17157
+ }
17158
+
17159
+ // src/ui/colors.ts
17160
+ var inkColors = {
17161
+ primary: "cyan",
17162
+ success: "green",
17163
+ warning: "yellow",
17164
+ error: "red",
17165
+ info: "blue",
17166
+ muted: "gray",
17167
+ accent: "magenta",
17168
+ text: "white",
17169
+ successBright: "greenBright",
17170
+ accentBright: "magentaBright"
17171
+ };
17172
+ function getSpinnerColor(operation) {
17173
+ switch (operation.toLowerCase()) {
17174
+ case "search":
17175
+ case "indexing":
17176
+ case "scanning":
17177
+ return "info";
17178
+ case "process":
17179
+ case "thinking":
17180
+ case "analyzing":
17181
+ return "warning";
17182
+ case "write":
17183
+ case "edit":
17184
+ case "create":
17185
+ return "success";
17186
+ case "compact":
17187
+ case "optimize":
17188
+ case "memory":
17189
+ return "accent";
17190
+ default:
17191
+ return "primary";
17356
17192
  }
17357
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
17358
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Box, { children: [
17359
- /* @__PURE__ */ jsx(Text, { color: "magenta", children: "\u23FA" }),
17360
- /* @__PURE__ */ jsxs(Text, { color: "white", children: [
17361
- " ",
17362
- operation,
17363
- "(",
17364
- filename,
17365
- ")"
17366
- ] })
17367
- ] }) }),
17368
- /* @__PURE__ */ jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [
17369
- /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u23BF Requesting user confirmation" }),
17370
- showVSCodeOpen && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u23BF Opened changes in Visual Studio Code \u29C9" }) }),
17371
- content && /* @__PURE__ */ jsxs(Fragment, { children: [
17372
- /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
17373
- "\u23BF ",
17374
- content.split("\n")[0]
17375
- ] }),
17376
- /* @__PURE__ */ jsx(Box, { marginLeft: 4, flexDirection: "column", children: /* @__PURE__ */ jsx(
17377
- DiffRenderer,
17378
- {
17379
- diffContent: content,
17380
- filename,
17381
- terminalWidth: 80
17382
- }
17383
- ) })
17384
- ] })
17385
- ] }),
17386
- /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
17387
- /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { children: "Do you want to proceed with this operation?" }) }),
17388
- /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: options.map((option, index) => /* @__PURE__ */ jsx(Box, { paddingLeft: 1, children: /* @__PURE__ */ jsxs(
17389
- Text,
17390
- {
17391
- color: selectedOption === index ? "black" : "white",
17392
- backgroundColor: selectedOption === index ? "cyan" : void 0,
17393
- children: [
17394
- index + 1,
17395
- ". ",
17396
- option
17397
- ]
17398
- }
17399
- ) }, index)) }),
17400
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "\u2191\u2193 navigate \u2022 Enter select \u2022 Esc cancel" }) })
17401
- ] })
17402
- ] });
17403
17193
  }
17404
17194
  function ContextStatus({
17405
17195
  workspaceFiles = 0,
@@ -17635,173 +17425,6 @@ function Banner({
17635
17425
  ] })
17636
17426
  ] });
17637
17427
  }
17638
- function useContextInfo(agent) {
17639
- const [contextInfo, setContextInfo] = useState({
17640
- workspaceFiles: 0,
17641
- indexSize: "0 MB",
17642
- sessionFiles: 0,
17643
- activeTokens: 0,
17644
- lastActivity: "Now",
17645
- memoryPressure: "low",
17646
- isLoading: true,
17647
- messagesCount: 0,
17648
- loadedFiles: [],
17649
- contextHealth: "optimal"
17650
- });
17651
- const updateContextInfo = async () => {
17652
- try {
17653
- let tokenUsage;
17654
- let messagesCount = 0;
17655
- let loadedFiles = [];
17656
- let contextHealth = "optimal";
17657
- if (agent) {
17658
- const modelName = agent.getCurrentModel?.() || "grok-code-fast-1";
17659
- const maxTokens = getMaxTokensForModel(modelName);
17660
- const estimatedTokens = Math.floor(Math.random() * 1e3) + 500;
17661
- messagesCount = Math.floor(Math.random() * 10) + 1;
17662
- const tokenPercent = Math.round(estimatedTokens / maxTokens * 100);
17663
- tokenUsage = {
17664
- current: estimatedTokens,
17665
- max: maxTokens,
17666
- percent: tokenPercent
17667
- };
17668
- if (tokenPercent >= 95) contextHealth = "critical";
17669
- else if (tokenPercent >= 80) contextHealth = "degraded";
17670
- else contextHealth = "optimal";
17671
- loadedFiles = [];
17672
- }
17673
- const info = {
17674
- workspaceFiles: await getWorkspaceFileCount(),
17675
- indexSize: await getIndexSize(),
17676
- sessionFiles: await getSessionFileCount(),
17677
- activeTokens: tokenUsage?.current || 0,
17678
- lastActivity: "Now",
17679
- gitBranch: await getGitBranch(),
17680
- projectName: await getProjectName(),
17681
- memoryPressure: getMemoryPressure(),
17682
- isLoading: false,
17683
- tokenUsage,
17684
- messagesCount,
17685
- loadedFiles,
17686
- contextHealth
17687
- };
17688
- setContextInfo(info);
17689
- } catch (error) {
17690
- console.warn("[ContextInfo] Failed to update context:", error);
17691
- setContextInfo((prev) => ({ ...prev, isLoading: false }));
17692
- }
17693
- };
17694
- useEffect(() => {
17695
- updateContextInfo();
17696
- const interval = setInterval(updateContextInfo, 1e4);
17697
- return () => clearInterval(interval);
17698
- }, []);
17699
- return {
17700
- contextInfo,
17701
- updateContextInfo,
17702
- refreshContext: updateContextInfo
17703
- };
17704
- }
17705
- async function getWorkspaceFileCount() {
17706
- try {
17707
- const cwd = process.cwd();
17708
- const entries = await fs__default.promises.readdir(cwd, { withFileTypes: true });
17709
- let count = 0;
17710
- for (const entry of entries) {
17711
- if (entry.isFile() && !shouldIgnoreFile(entry.name)) {
17712
- count++;
17713
- } else if (entry.isDirectory() && !shouldIgnoreDirectory(entry.name)) {
17714
- try {
17715
- const subEntries = await fs__default.promises.readdir(path7__default.join(cwd, entry.name), { withFileTypes: true });
17716
- count += subEntries.filter((sub) => sub.isFile() && !shouldIgnoreFile(sub.name)).length;
17717
- } catch {
17718
- }
17719
- }
17720
- }
17721
- return count;
17722
- } catch {
17723
- return 0;
17724
- }
17725
- }
17726
- function shouldIgnoreFile(filename) {
17727
- return filename.startsWith(".") || filename.endsWith(".log") || filename.includes(".tmp");
17728
- }
17729
- function shouldIgnoreDirectory(dirname5) {
17730
- const ignoreDirs = ["node_modules", ".git", "dist", "build", ".next", "coverage"];
17731
- return ignoreDirs.includes(dirname5) || dirname5.startsWith(".");
17732
- }
17733
- async function getIndexSize() {
17734
- try {
17735
- const indexPath = path7__default.join(process.cwd(), ".grok", "index.json");
17736
- if (fs__default.existsSync(indexPath)) {
17737
- const stats = await fs__default.promises.stat(indexPath);
17738
- const mb = stats.size / (1024 * 1024);
17739
- return mb > 1 ? `${mb.toFixed(1)} MB` : `${(stats.size / 1024).toFixed(1)} KB`;
17740
- }
17741
- } catch {
17742
- }
17743
- return "0 MB";
17744
- }
17745
- async function getSessionFileCount() {
17746
- try {
17747
- const sessionPath = path7__default.join(os__default.homedir(), ".grok", "session.log");
17748
- if (fs__default.existsSync(sessionPath)) {
17749
- const content = await fs__default.promises.readFile(sessionPath, "utf8");
17750
- return content.split("\n").filter((line) => line.trim()).length;
17751
- }
17752
- } catch {
17753
- }
17754
- return 0;
17755
- }
17756
- async function getGitBranch() {
17757
- try {
17758
- const gitPath = path7__default.join(process.cwd(), ".git", "HEAD");
17759
- if (fs__default.existsSync(gitPath)) {
17760
- const content = await fs__default.promises.readFile(gitPath, "utf8");
17761
- const match = content.match(/ref: refs\/heads\/(.+)/);
17762
- return match ? match[1].trim() : "detached";
17763
- }
17764
- } catch {
17765
- }
17766
- return void 0;
17767
- }
17768
- async function getProjectName() {
17769
- try {
17770
- const packagePath = path7__default.join(process.cwd(), "package.json");
17771
- if (fs__default.existsSync(packagePath)) {
17772
- const content = await fs__default.promises.readFile(packagePath, "utf8");
17773
- const pkg = JSON.parse(content);
17774
- return pkg.name;
17775
- }
17776
- } catch {
17777
- }
17778
- return path7__default.basename(process.cwd());
17779
- }
17780
- function getMemoryPressure() {
17781
- try {
17782
- const memUsage = process.memoryUsage();
17783
- const heapUsedMB = memUsage.heapUsed / 1024 / 1024;
17784
- if (heapUsedMB > 200) return "high";
17785
- if (heapUsedMB > 100) return "medium";
17786
- return "low";
17787
- } catch {
17788
- return "low";
17789
- }
17790
- }
17791
- function getMaxTokensForModel(modelName) {
17792
- const modelLimits = {
17793
- "grok-code-fast-1": 128e3,
17794
- "grok-4-latest": 2e5,
17795
- "grok-3-latest": 2e5,
17796
- "grok-3-fast": 128e3,
17797
- "grok-3-mini-fast": 64e3,
17798
- "claude-sonnet-4": 2e5,
17799
- "claude-opus-4": 2e5,
17800
- "gpt-4o": 128e3,
17801
- "gpt-4": 32e3
17802
- };
17803
- return modelLimits[modelName] || 128e3;
17804
- }
17805
17428
  function ContextTooltip({ isVisible }) {
17806
17429
  const { contextInfo } = useContextInfo();
17807
17430
  if (!isVisible) return null;
@@ -17881,756 +17504,1145 @@ function ContextTooltip({ isVisible }) {
17881
17504
  }
17882
17505
  );
17883
17506
  }
17884
- function VersionNotification({ isVisible = true }) {
17885
- const [versionInfo, setVersionInfo] = useState(null);
17886
- useEffect(() => {
17887
- const checkVersion = async () => {
17888
- try {
17889
- const info = await getCachedVersionInfo();
17890
- if (info?.isUpdateAvailable) {
17891
- setVersionInfo({
17892
- isUpdateAvailable: info.isUpdateAvailable,
17893
- current: info.current,
17894
- latest: info.latest
17895
- });
17896
- }
17897
- } catch {
17898
- }
17899
- };
17900
- checkVersion();
17901
- const interval = setInterval(checkVersion, 6 * 60 * 60 * 1e3);
17902
- return () => clearInterval(interval);
17903
- }, []);
17904
- if (!isVisible || !versionInfo?.isUpdateAvailable) {
17905
- return null;
17507
+ var truncateContent = (content, maxLength = 100) => {
17508
+ if (process.env.COMPACT !== "1") return content;
17509
+ return content.length > maxLength ? content.substring(0, maxLength) + "..." : content;
17510
+ };
17511
+ function UserMessageEntry({ entry, verbosityLevel: _verbosityLevel }) {
17512
+ const displayText = entry.isPasteSummary ? entry.displayContent || entry.content : entry.content;
17513
+ const textColor = entry.isPasteSummary ? "cyan" : "gray";
17514
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: textColor, children: [
17515
+ ">",
17516
+ " ",
17517
+ truncateContent(displayText)
17518
+ ] }) }) });
17519
+ }
17520
+ marked.setOptions({
17521
+ renderer: new TerminalRenderer()
17522
+ });
17523
+ function MarkdownRenderer({ content }) {
17524
+ try {
17525
+ const result = marked.parse(content);
17526
+ const rendered = typeof result === "string" ? result : content;
17527
+ return /* @__PURE__ */ jsx(Text, { children: rendered });
17528
+ } catch (error) {
17529
+ console.error("Markdown rendering error:", error);
17530
+ return /* @__PURE__ */ jsx(Text, { children: content });
17906
17531
  }
17907
- return /* @__PURE__ */ jsx(Box, { marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ jsxs(
17532
+ }
17533
+ var handleLongContent = (content, maxLength = 5e3) => {
17534
+ if (content.length <= maxLength) {
17535
+ return { content, isTruncated: false };
17536
+ }
17537
+ const truncated = content.substring(0, maxLength);
17538
+ const summary = `
17539
+
17540
+ [Content truncated - ${content.length - maxLength} characters remaining. Full content available in chat history.]`;
17541
+ return {
17542
+ content: truncated + summary,
17543
+ isTruncated: true
17544
+ };
17545
+ };
17546
+ function AssistantMessageEntry({ entry, verbosityLevel: _verbosityLevel }) {
17547
+ const { content: processedContent, isTruncated } = handleLongContent(entry.content);
17548
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "flex-start", children: [
17549
+ /* @__PURE__ */ jsx(Text, { color: "white", children: "\u23FA " }),
17550
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [
17551
+ entry.toolCalls ? (
17552
+ // If there are tool calls, just show plain text
17553
+ /* @__PURE__ */ jsx(Text, { color: "white", children: processedContent.trim() })
17554
+ ) : (
17555
+ // If no tool calls, render as markdown
17556
+ /* @__PURE__ */ jsx(MarkdownRenderer, { content: processedContent.trim() })
17557
+ ),
17558
+ entry.isStreaming && /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u2588" }),
17559
+ isTruncated && /* @__PURE__ */ jsx(Text, { color: "yellow", italic: true, children: "[Response truncated for performance - full content in session log]" })
17560
+ ] })
17561
+ ] }) });
17562
+ }
17563
+
17564
+ // src/ui/utils/colors.ts
17565
+ var Colors = {
17566
+ AccentYellow: "yellow",
17567
+ Gray: "gray"};
17568
+ var MaxSizedBox = ({
17569
+ maxHeight: _maxHeight,
17570
+ maxWidth: _maxWidth,
17571
+ children,
17572
+ ...props
17573
+ }) => {
17574
+ return /* @__PURE__ */ jsx(
17908
17575
  Box,
17909
17576
  {
17910
- borderStyle: "round",
17911
- borderColor: inkColors.warning,
17912
- paddingX: 2,
17913
- paddingY: 0,
17914
- children: [
17915
- /* @__PURE__ */ jsxs(Text, { color: inkColors.warning, children: [
17916
- "\u{1F504} Update available: v",
17917
- versionInfo.latest,
17918
- " (current: v",
17919
- versionInfo.current,
17920
- ")"
17921
- ] }),
17922
- /* @__PURE__ */ jsx(Text, { color: inkColors.muted, children: " - Use '/upgrade' to update" })
17923
- ]
17577
+ flexDirection: "column",
17578
+ ...props,
17579
+ children
17924
17580
  }
17925
- ) });
17926
- }
17927
- var PHASE_DISPLAY = {
17928
- inactive: { label: "Inactive", color: "gray", symbol: "\u25CB" },
17929
- analysis: { label: "Analyzing", color: "blue", symbol: "\u{1F50D}" },
17930
- strategy: { label: "Planning", color: "yellow", symbol: "\u{1F9E0}" },
17931
- presentation: { label: "Presenting", color: "cyan", symbol: "\u{1F4CB}" },
17932
- approved: { label: "Approved", color: "green", symbol: "\u2705" },
17933
- rejected: { label: "Rejected", color: "red", symbol: "\u274C" }
17934
- };
17935
- var PHASE_DESCRIPTIONS = {
17936
- inactive: "Press Shift+Tab twice to enter Plan Mode",
17937
- analysis: "Exploring codebase and gathering insights",
17938
- strategy: "Formulating implementation strategy",
17939
- presentation: "Presenting plan for your review",
17940
- approved: "Plan approved - ready for execution",
17941
- rejected: "Plan rejected - please provide feedback"
17581
+ );
17942
17582
  };
17943
- function PlanModeIndicator({
17944
- isActive,
17945
- phase,
17946
- progress,
17947
- sessionDuration,
17948
- detailed = false
17949
- }) {
17950
- const phaseInfo = PHASE_DISPLAY[phase];
17951
- const phaseDescription = PHASE_DESCRIPTIONS[phase];
17952
- const formatDuration = (ms) => {
17953
- const seconds = Math.floor(ms / 1e3);
17954
- const minutes = Math.floor(seconds / 60);
17955
- const remainingSeconds = seconds % 60;
17956
- if (minutes > 0) {
17957
- return `${minutes}m ${remainingSeconds}s`;
17583
+ function parseDiffWithLineNumbers(diffContent) {
17584
+ const lines = diffContent.split("\n");
17585
+ const result = [];
17586
+ let currentOldLine = 0;
17587
+ let currentNewLine = 0;
17588
+ let inHunk = false;
17589
+ const hunkHeaderRegex = /^@@ -(\d+),?\d* \+(\d+),?\d* @@/;
17590
+ for (const line of lines) {
17591
+ const hunkMatch = line.match(hunkHeaderRegex);
17592
+ if (hunkMatch) {
17593
+ currentOldLine = parseInt(hunkMatch[1], 10);
17594
+ currentNewLine = parseInt(hunkMatch[2], 10);
17595
+ inHunk = true;
17596
+ result.push({ type: "hunk", content: line });
17597
+ currentOldLine--;
17598
+ currentNewLine--;
17599
+ continue;
17958
17600
  }
17959
- return `${remainingSeconds}s`;
17960
- };
17961
- const formatProgressBar = (progress2, width = 20) => {
17962
- const filled = Math.round(progress2 * width);
17963
- const empty = width - filled;
17964
- return "\u2588".repeat(filled) + "\u2591".repeat(empty);
17965
- };
17966
- if (!isActive) {
17967
- return detailed ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 1, children: [
17968
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "center", children: [
17969
- /* @__PURE__ */ jsx(Text, { color: "gray", children: phaseInfo.symbol }),
17970
- /* @__PURE__ */ jsx(Box, { marginLeft: 1, children: /* @__PURE__ */ jsxs(Text, { color: "gray", bold: true, children: [
17971
- "Plan Mode: ",
17972
- phaseInfo.label
17973
- ] }) })
17974
- ] }),
17975
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: phaseDescription }) })
17976
- ] }) : null;
17977
- }
17978
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: phaseInfo.color, padding: 1, children: [
17979
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "center", justifyContent: "space-between", children: [
17980
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "center", children: [
17981
- /* @__PURE__ */ jsx(Text, { color: phaseInfo.color, children: phaseInfo.symbol }),
17982
- /* @__PURE__ */ jsx(Box, { marginLeft: 1, children: /* @__PURE__ */ jsxs(Text, { color: phaseInfo.color, bold: true, children: [
17983
- "Plan Mode: ",
17984
- phaseInfo.label
17985
- ] }) })
17986
- ] }),
17987
- /* @__PURE__ */ jsx(Box, { flexDirection: "row", alignItems: "center", children: /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: formatDuration(sessionDuration) }) })
17988
- ] }),
17989
- phase !== "inactive" && phase !== "approved" && phase !== "rejected" && /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "center", marginTop: 1, children: [
17990
- /* @__PURE__ */ jsx(Box, { marginRight: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "Progress:" }) }),
17991
- /* @__PURE__ */ jsx(Text, { color: phaseInfo.color, children: formatProgressBar(progress) }),
17992
- /* @__PURE__ */ jsx(Box, { marginLeft: 1, children: /* @__PURE__ */ jsxs(Text, { color: "gray", dimColor: true, children: [
17993
- Math.round(progress * 100),
17994
- "%"
17995
- ] }) })
17996
- ] }),
17997
- detailed && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: phaseDescription }) }),
17998
- detailed && phase === "analysis" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
17999
- /* @__PURE__ */ jsx(Text, { color: "blue", dimColor: true, children: "\u2022 Reading project structure" }),
18000
- /* @__PURE__ */ jsx(Text, { color: "blue", dimColor: true, children: "\u2022 Analyzing dependencies" }),
18001
- /* @__PURE__ */ jsx(Text, { color: "blue", dimColor: true, children: "\u2022 Identifying key components" })
18002
- ] }),
18003
- detailed && phase === "strategy" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
18004
- /* @__PURE__ */ jsx(Text, { color: "yellow", dimColor: true, children: "\u2022 Evaluating implementation approaches" }),
18005
- /* @__PURE__ */ jsx(Text, { color: "yellow", dimColor: true, children: "\u2022 Assessing risks and dependencies" }),
18006
- /* @__PURE__ */ jsx(Text, { color: "yellow", dimColor: true, children: "\u2022 Estimating effort and timeline" })
18007
- ] }),
18008
- detailed && phase === "presentation" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
18009
- /* @__PURE__ */ jsx(Text, { color: "cyan", dimColor: true, children: "\u2022 Preparing implementation plan" }),
18010
- /* @__PURE__ */ jsx(Text, { color: "cyan", dimColor: true, children: "\u2022 Organizing steps and dependencies" }),
18011
- /* @__PURE__ */ jsx(Text, { color: "cyan", dimColor: true, children: "\u2022 Ready for your review" })
18012
- ] }),
18013
- !detailed && /* @__PURE__ */ jsx(Box, { flexDirection: "row", marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { color: "gray", dimColor: true, children: [
18014
- phase === "presentation" && "\u2022 Press Enter to review plan",
18015
- phase === "approved" && '\u2022 Type "execute" to start implementation',
18016
- phase === "rejected" && "\u2022 Provide feedback to regenerate plan",
18017
- (phase === "analysis" || phase === "strategy") && "\u2022 Plan mode is analyzing..."
18018
- ] }) })
18019
- ] });
17601
+ if (!inHunk) {
17602
+ if (line.startsWith("--- ") || line.startsWith("+++ ") || line.startsWith("diff --git") || line.startsWith("index ") || line.startsWith("similarity index") || line.startsWith("rename from") || line.startsWith("rename to") || line.startsWith("new file mode") || line.startsWith("deleted file mode"))
17603
+ continue;
17604
+ continue;
17605
+ }
17606
+ if (line.startsWith("+")) {
17607
+ currentNewLine++;
17608
+ result.push({
17609
+ type: "add",
17610
+ newLine: currentNewLine,
17611
+ content: line.substring(1)
17612
+ });
17613
+ } else if (line.startsWith("-")) {
17614
+ currentOldLine++;
17615
+ result.push({
17616
+ type: "del",
17617
+ oldLine: currentOldLine,
17618
+ content: line.substring(1)
17619
+ });
17620
+ } else if (line.startsWith(" ")) {
17621
+ currentOldLine++;
17622
+ currentNewLine++;
17623
+ result.push({
17624
+ type: "context",
17625
+ oldLine: currentOldLine,
17626
+ newLine: currentNewLine,
17627
+ content: line.substring(1)
17628
+ });
17629
+ } else if (line.startsWith("\\")) {
17630
+ result.push({ type: "other", content: line });
17631
+ }
17632
+ }
17633
+ return result;
18020
17634
  }
18021
- function PlanModeStatusIndicator({
18022
- isActive,
18023
- phase,
18024
- progress
18025
- }) {
18026
- if (!isActive) {
18027
- return /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "Plan Mode: Off" });
17635
+ var DEFAULT_TAB_WIDTH = 4;
17636
+ var DiffRenderer = ({
17637
+ diffContent,
17638
+ filename,
17639
+ tabWidth = DEFAULT_TAB_WIDTH,
17640
+ availableTerminalHeight,
17641
+ terminalWidth = 80
17642
+ }) => {
17643
+ if (!diffContent || typeof diffContent !== "string") {
17644
+ return /* @__PURE__ */ jsx(Text, { color: Colors.AccentYellow, children: "No diff content." });
18028
17645
  }
18029
- const phaseInfo = PHASE_DISPLAY[phase];
18030
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "center", children: [
18031
- /* @__PURE__ */ jsx(Text, { color: phaseInfo.color, children: phaseInfo.symbol }),
18032
- /* @__PURE__ */ jsx(Box, { marginLeft: 1, children: /* @__PURE__ */ jsxs(Text, { color: phaseInfo.color, children: [
18033
- "Plan: ",
18034
- phaseInfo.label
18035
- ] }) }),
18036
- phase !== "inactive" && phase !== "approved" && phase !== "rejected" && /* @__PURE__ */ jsx(Box, { marginLeft: 1, children: /* @__PURE__ */ jsxs(Text, { color: "gray", dimColor: true, children: [
18037
- "(",
18038
- Math.round(progress * 100),
18039
- "%)"
18040
- ] }) })
18041
- ] });
17646
+ const lines = diffContent.split("\n");
17647
+ const firstLine = lines[0];
17648
+ let actualDiffContent = diffContent;
17649
+ if (firstLine && (firstLine.startsWith("Updated ") || firstLine.startsWith("Created "))) {
17650
+ actualDiffContent = lines.slice(1).join("\n");
17651
+ }
17652
+ const parsedLines = parseDiffWithLineNumbers(actualDiffContent);
17653
+ if (parsedLines.length === 0) {
17654
+ return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No changes detected." });
17655
+ }
17656
+ const renderedOutput = renderDiffContent(
17657
+ parsedLines,
17658
+ filename,
17659
+ tabWidth,
17660
+ availableTerminalHeight,
17661
+ terminalWidth
17662
+ );
17663
+ return /* @__PURE__ */ jsx(Fragment, { children: renderedOutput });
17664
+ };
17665
+ var renderDiffContent = (parsedLines, filename, tabWidth = DEFAULT_TAB_WIDTH, availableTerminalHeight, terminalWidth) => {
17666
+ const normalizedLines = parsedLines.map((line) => ({
17667
+ ...line,
17668
+ content: line.content.replace(/\t/g, " ".repeat(tabWidth))
17669
+ }));
17670
+ const displayableLines = normalizedLines.filter(
17671
+ (l) => l.type !== "hunk" && l.type !== "other"
17672
+ );
17673
+ if (displayableLines.length === 0) {
17674
+ return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "No changes detected." });
17675
+ }
17676
+ let baseIndentation = Infinity;
17677
+ for (const line of displayableLines) {
17678
+ if (line.content.trim() === "") continue;
17679
+ const firstCharIndex = line.content.search(/\S/);
17680
+ const currentIndent = firstCharIndex === -1 ? 0 : firstCharIndex;
17681
+ baseIndentation = Math.min(baseIndentation, currentIndent);
17682
+ }
17683
+ if (!isFinite(baseIndentation)) {
17684
+ baseIndentation = 0;
17685
+ }
17686
+ const key = filename ? `diff-box-${filename}` : `diff-box-${crypto.createHash("sha1").update(JSON.stringify(parsedLines)).digest("hex")}`;
17687
+ let lastLineNumber = null;
17688
+ const MAX_CONTEXT_LINES_WITHOUT_GAP = 5;
17689
+ return /* @__PURE__ */ jsx(
17690
+ MaxSizedBox,
17691
+ {
17692
+ maxHeight: availableTerminalHeight,
17693
+ maxWidth: terminalWidth,
17694
+ children: displayableLines.reduce((acc, line, index) => {
17695
+ let relevantLineNumberForGapCalc = null;
17696
+ if (line.type === "add" || line.type === "context") {
17697
+ relevantLineNumberForGapCalc = line.newLine ?? null;
17698
+ } else if (line.type === "del") {
17699
+ relevantLineNumberForGapCalc = line.oldLine ?? null;
17700
+ }
17701
+ if (lastLineNumber !== null && relevantLineNumberForGapCalc !== null && relevantLineNumberForGapCalc > lastLineNumber + MAX_CONTEXT_LINES_WITHOUT_GAP + 1) {
17702
+ acc.push(
17703
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { wrap: "truncate", children: "\u2550".repeat(terminalWidth) }) }, `gap-${index}`)
17704
+ );
17705
+ }
17706
+ const lineKey = `diff-line-${index}`;
17707
+ let gutterNumStr = "";
17708
+ let backgroundColor = void 0;
17709
+ let prefixSymbol = " ";
17710
+ let dim = false;
17711
+ switch (line.type) {
17712
+ case "add":
17713
+ gutterNumStr = (line.newLine ?? "").toString();
17714
+ backgroundColor = "#86efac";
17715
+ prefixSymbol = "+";
17716
+ lastLineNumber = line.newLine ?? null;
17717
+ break;
17718
+ case "del":
17719
+ gutterNumStr = (line.oldLine ?? "").toString();
17720
+ backgroundColor = "redBright";
17721
+ prefixSymbol = "-";
17722
+ if (line.oldLine !== void 0) {
17723
+ lastLineNumber = line.oldLine;
17724
+ }
17725
+ break;
17726
+ case "context":
17727
+ gutterNumStr = (line.newLine ?? "").toString();
17728
+ dim = true;
17729
+ prefixSymbol = " ";
17730
+ lastLineNumber = line.newLine ?? null;
17731
+ break;
17732
+ default:
17733
+ return acc;
17734
+ }
17735
+ const displayContent = line.content.substring(baseIndentation);
17736
+ acc.push(
17737
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
17738
+ /* @__PURE__ */ jsx(Text, { color: Colors.Gray, dimColor: dim, children: gutterNumStr.padEnd(4) }),
17739
+ /* @__PURE__ */ jsxs(Text, { color: backgroundColor ? "#000000" : void 0, backgroundColor, dimColor: !backgroundColor && dim, children: [
17740
+ prefixSymbol,
17741
+ " "
17742
+ ] }),
17743
+ /* @__PURE__ */ jsx(Text, { color: backgroundColor ? "#000000" : void 0, backgroundColor, dimColor: !backgroundColor && dim, wrap: "wrap", children: displayContent })
17744
+ ] }, lineKey)
17745
+ );
17746
+ return acc;
17747
+ }, [])
17748
+ },
17749
+ key
17750
+ );
17751
+ };
17752
+ function FileContentRenderer({ content }) {
17753
+ const lines = content.split("\n");
17754
+ let baseIndentation = Infinity;
17755
+ for (const line of lines) {
17756
+ if (line.trim() === "") continue;
17757
+ const firstCharIndex = line.search(/\S/);
17758
+ const currentIndent = firstCharIndex === -1 ? 0 : firstCharIndex;
17759
+ baseIndentation = Math.min(baseIndentation, currentIndent);
17760
+ }
17761
+ if (!isFinite(baseIndentation)) {
17762
+ baseIndentation = 0;
17763
+ }
17764
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: lines.map((line, index) => {
17765
+ const displayContent = line.substring(baseIndentation);
17766
+ return /* @__PURE__ */ jsx(Text, { color: "gray", children: displayContent }, index);
17767
+ }) });
18042
17768
  }
18043
- function ContextIndicator({
18044
- state,
18045
- compact = false
18046
- }) {
18047
- const getTokenColor = (percent) => {
18048
- if (percent >= 90) return inkColors.error;
18049
- if (percent >= 80) return inkColors.warning;
18050
- if (percent >= 60) return inkColors.info;
18051
- return inkColors.success;
17769
+ var truncateContent2 = (content, maxLength = 100) => {
17770
+ if (process.env.COMPACT !== "1") return content;
17771
+ return content.length > maxLength ? content.substring(0, maxLength) + "..." : content;
17772
+ };
17773
+ function ToolCallEntry({ entry, verbosityLevel, explainLevel }) {
17774
+ const getExplanation = (toolName2, filePath2, _isExecuting) => {
17775
+ if (explainLevel === "off") return null;
17776
+ const explanations = {
17777
+ view_file: {
17778
+ brief: `Reading ${filePath2} to examine its contents`,
17779
+ detailed: `Reading the file ${filePath2} to examine its current contents, structure, and implementation details for analysis or modification.`
17780
+ },
17781
+ str_replace_editor: {
17782
+ brief: `Updating ${filePath2} with changes`,
17783
+ detailed: `Applying targeted modifications to ${filePath2} using precise string replacement to update specific code sections while preserving the rest of the file structure.`
17784
+ },
17785
+ create_file: {
17786
+ brief: `Creating new file ${filePath2}`,
17787
+ detailed: `Creating a new file at ${filePath2} with the specified content, establishing the initial structure and implementation for this component or module.`
17788
+ },
17789
+ bash: {
17790
+ brief: `Executing command: ${filePath2}`,
17791
+ detailed: `Running the shell command "${filePath2}" to perform system operations, file management, or external tool execution as requested.`
17792
+ },
17793
+ search: {
17794
+ brief: `Searching for: ${filePath2}`,
17795
+ detailed: `Performing a comprehensive search across the codebase for "${filePath2}" to locate relevant files, functions, or code patterns that match the query.`
17796
+ }
17797
+ };
17798
+ const explanation2 = explanations[toolName2];
17799
+ if (!explanation2) return null;
17800
+ return explainLevel === "detailed" ? explanation2.detailed : explanation2.brief;
18052
17801
  };
18053
- const getMemoryPressureColor = (pressure) => {
18054
- switch (pressure) {
18055
- case "critical":
18056
- return inkColors.error;
18057
- case "high":
18058
- return inkColors.warning;
18059
- case "medium":
18060
- return inkColors.info;
17802
+ const getToolActionName = (toolName2) => {
17803
+ if (toolName2.startsWith("mcp__")) {
17804
+ const parts = toolName2.split("__");
17805
+ if (parts.length >= 3) {
17806
+ const serverName = parts[1];
17807
+ const actualToolName = parts.slice(2).join("__");
17808
+ return `${serverName.charAt(0).toUpperCase() + serverName.slice(1)}(${actualToolName.replace(/_/g, " ")})`;
17809
+ }
17810
+ }
17811
+ switch (toolName2) {
17812
+ case "view_file":
17813
+ return "Read";
17814
+ case "str_replace_editor":
17815
+ return "Update";
17816
+ case "create_file":
17817
+ return "Create";
17818
+ case "bash":
17819
+ return "Bash";
17820
+ case "search":
17821
+ return "Search";
17822
+ case "create_todo_list":
17823
+ return "Created Todo";
17824
+ case "update_todo_list":
17825
+ return "Updated Todo";
18061
17826
  default:
18062
- return inkColors.success;
17827
+ return "Tool";
18063
17828
  }
18064
17829
  };
18065
- const formatTokenCount2 = (count) => {
18066
- if (count >= 1e6) {
18067
- return `${(count / 1e6).toFixed(1)}M`;
18068
- }
18069
- if (count >= 1e3) {
18070
- return `${(count / 1e3).toFixed(1)}k`;
17830
+ const toolName = entry.toolCall?.function?.name || "unknown";
17831
+ const actionName = getToolActionName(toolName);
17832
+ const getFilePath = (toolCall) => {
17833
+ if (toolCall?.function?.arguments) {
17834
+ try {
17835
+ const args = JSON.parse(toolCall.function.arguments);
17836
+ if (toolCall.function.name === "search") {
17837
+ return args.query;
17838
+ }
17839
+ return args.path || args.file_path || args.command || "";
17840
+ } catch {
17841
+ return "";
17842
+ }
18071
17843
  }
18072
- return count.toString();
17844
+ return "";
18073
17845
  };
18074
- const getProgressBar = (percent, width = 20) => {
18075
- const filled = Math.round(percent / 100 * width);
18076
- const empty = width - filled;
18077
- return "\u2588".repeat(filled) + "\u2592".repeat(empty);
17846
+ const filePath = getFilePath(entry.toolCall);
17847
+ const isExecuting = entry.type === "tool_call" || !entry.toolResult;
17848
+ const formatToolContent = (content, toolName2) => {
17849
+ const truncated = truncateContent2(content, 200);
17850
+ if (toolName2.startsWith("mcp__")) {
17851
+ try {
17852
+ const parsed = JSON.parse(truncated);
17853
+ if (Array.isArray(parsed)) {
17854
+ return `Found ${parsed.length} items`;
17855
+ } else if (typeof parsed === "object") {
17856
+ return JSON.stringify(parsed, null, 2);
17857
+ }
17858
+ } catch {
17859
+ return truncated;
17860
+ }
17861
+ }
17862
+ return truncated;
18078
17863
  };
18079
- if (compact) {
18080
- return /* @__PURE__ */ jsxs(Box, { children: [
18081
- /* @__PURE__ */ jsxs(Text, { color: getTokenColor(state.tokenUsage.percent), children: [
18082
- "\u{1F9E0} ",
18083
- formatTokenCount2(state.tokenUsage.current),
18084
- "/",
18085
- formatTokenCount2(state.tokenUsage.max),
18086
- " (",
18087
- state.tokenUsage.percent,
18088
- "%)"
18089
- ] }),
18090
- /* @__PURE__ */ jsx(Text, { color: inkColors.muted, children: " \u2502 " }),
18091
- /* @__PURE__ */ jsxs(Text, { color: inkColors.info, children: [
18092
- "\u{1F4C1} ",
18093
- state.fileCount,
18094
- " files"
18095
- ] }),
18096
- /* @__PURE__ */ jsx(Text, { color: inkColors.muted, children: " \u2502 " }),
18097
- /* @__PURE__ */ jsxs(Text, { color: inkColors.info, children: [
18098
- "\u{1F4AC} ",
18099
- state.messagesCount,
18100
- " msgs"
18101
- ] }),
18102
- state.memoryPressure !== "low" && /* @__PURE__ */ jsxs(Fragment, { children: [
18103
- /* @__PURE__ */ jsx(Text, { color: inkColors.muted, children: " \u2502 " }),
18104
- /* @__PURE__ */ jsxs(Text, { color: getMemoryPressureColor(state.memoryPressure), children: [
18105
- "\u26A0\uFE0F ",
18106
- state.memoryPressure,
18107
- " pressure"
18108
- ] })
17864
+ const shouldShowDiff = entry.toolCall?.function?.name === "str_replace_editor" && entry.toolResult?.success && entry.content.includes("Updated") && entry.content.includes("---") && entry.content.includes("+++");
17865
+ const shouldShowFileContent = (entry.toolCall?.function?.name === "view_file" || entry.toolCall?.function?.name === "create_file") && entry.toolResult?.success && !shouldShowDiff;
17866
+ const shouldShowToolContent = verbosityLevel !== "quiet";
17867
+ const shouldShowFullContent = verbosityLevel === "normal" || verbosityLevel === "verbose";
17868
+ const explanation = getExplanation(toolName, filePath);
17869
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
17870
+ /* @__PURE__ */ jsxs(Box, { children: [
17871
+ /* @__PURE__ */ jsx(Text, { color: "magenta", children: "\u23FA" }),
17872
+ /* @__PURE__ */ jsxs(Text, { color: "white", children: [
17873
+ " ",
17874
+ filePath ? `${actionName}(${filePath})` : actionName
18109
17875
  ] })
18110
- ] });
18111
- }
18112
- return /* @__PURE__ */ jsxs(
18113
- Box,
18114
- {
18115
- flexDirection: "column",
18116
- borderStyle: "round",
18117
- borderColor: state.contextHealth === "critical" ? "red" : state.contextHealth === "degraded" ? "yellow" : "green",
18118
- paddingX: 1,
18119
- paddingY: 0,
18120
- children: [
18121
- /* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", children: [
18122
- /* @__PURE__ */ jsx(Text, { bold: true, color: inkColors.primary, children: "\u{1F9E0} Context Status" }),
18123
- /* @__PURE__ */ jsx(
18124
- Text,
18125
- {
18126
- color: state.contextHealth === "critical" ? inkColors.error : state.contextHealth === "degraded" ? inkColors.warning : inkColors.success,
18127
- children: state.contextHealth.toUpperCase()
18128
- }
18129
- )
18130
- ] }),
18131
- /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
18132
- /* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", children: [
18133
- /* @__PURE__ */ jsx(Text, { color: inkColors.info, children: "Memory Usage:" }),
18134
- /* @__PURE__ */ jsxs(Text, { color: getTokenColor(state.tokenUsage.percent), children: [
18135
- formatTokenCount2(state.tokenUsage.current),
18136
- "/",
18137
- formatTokenCount2(state.tokenUsage.max),
18138
- " (",
18139
- state.tokenUsage.percent,
18140
- "%)"
18141
- ] })
18142
- ] }),
18143
- /* @__PURE__ */ jsx(Box, { marginTop: 0, children: /* @__PURE__ */ jsx(Text, { color: getTokenColor(state.tokenUsage.percent), children: getProgressBar(state.tokenUsage.percent, 40) }) })
18144
- ] }),
18145
- /* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", marginTop: 1, children: [
18146
- /* @__PURE__ */ jsxs(Box, { children: [
18147
- /* @__PURE__ */ jsx(Text, { color: inkColors.info, children: "\u{1F4C1} Files: " }),
18148
- /* @__PURE__ */ jsx(Text, { color: inkColors.accent, children: state.fileCount })
18149
- ] }),
18150
- /* @__PURE__ */ jsxs(Box, { children: [
18151
- /* @__PURE__ */ jsx(Text, { color: inkColors.info, children: "\u{1F4AC} Messages: " }),
18152
- /* @__PURE__ */ jsx(Text, { color: inkColors.accent, children: state.messagesCount })
18153
- ] }),
18154
- /* @__PURE__ */ jsxs(Box, { children: [
18155
- /* @__PURE__ */ jsx(Text, { color: inkColors.info, children: "\u{1F525} Pressure: " }),
18156
- /* @__PURE__ */ jsx(Text, { color: getMemoryPressureColor(state.memoryPressure), children: state.memoryPressure })
18157
- ] })
18158
- ] }),
18159
- state.tokenUsage.percent >= 80 && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: inkColors.warning, children: "\u26A0\uFE0F Approaching context limit. Consider using /compact or /clear" }) }),
18160
- state.memoryPressure === "critical" && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: inkColors.error, children: "\u{1F6A8} Critical memory pressure! Performance may degrade. Use /clear immediately." }) }),
18161
- state.loadedFiles.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
18162
- /* @__PURE__ */ jsx(Text, { color: inkColors.info, bold: true, children: "Recent Files:" }),
18163
- state.loadedFiles.slice(0, 3).map((file, index) => /* @__PURE__ */ jsxs(Box, { children: [
18164
- /* @__PURE__ */ jsx(Text, { color: inkColors.muted, children: "\u2022 " }),
18165
- /* @__PURE__ */ jsx(Text, { color: inkColors.accent, children: file.path }),
18166
- /* @__PURE__ */ jsxs(Text, { color: inkColors.muted, children: [
18167
- " ",
18168
- "(",
18169
- formatTokenCount2(file.tokens),
18170
- " tokens)"
18171
- ] })
18172
- ] }, index)),
18173
- state.loadedFiles.length > 3 && /* @__PURE__ */ jsxs(Text, { color: inkColors.muted, children: [
18174
- "... and ",
18175
- state.loadedFiles.length - 3,
18176
- " more files"
18177
- ] })
18178
- ] }),
18179
- /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: inkColors.muted, children: "\u{1F4A1} Use /context for details, /compact to optimize, /clear to reset" }) })
18180
- ]
18181
- }
18182
- );
18183
- }
18184
- init_settings_manager();
18185
- function ApiKeyInput({ onApiKeySet }) {
18186
- const [input, setInput] = useState("");
18187
- const [error, setError] = useState("");
18188
- const [isSubmitting, setIsSubmitting] = useState(false);
18189
- const { exit } = useApp();
18190
- useInput((inputChar, key) => {
18191
- if (isSubmitting) return;
18192
- if (key.ctrl && inputChar === "c") {
18193
- exit();
18194
- return;
18195
- }
18196
- if (key.return) {
18197
- handleSubmit();
18198
- return;
18199
- }
18200
- if (key.backspace || key.delete) {
18201
- setInput((prev) => prev.slice(0, -1));
18202
- setError("");
18203
- return;
18204
- }
18205
- if (inputChar && !key.ctrl && !key.meta) {
18206
- setInput((prev) => prev + inputChar);
18207
- setError("");
18208
- }
18209
- });
18210
- const handleSubmit = async () => {
18211
- if (!input.trim()) {
18212
- setError("API key cannot be empty");
18213
- return;
18214
- }
18215
- setIsSubmitting(true);
18216
- try {
18217
- const apiKey = input.trim();
18218
- const agent = new GrokAgent(apiKey);
18219
- process.env.GROK_API_KEY = apiKey;
18220
- try {
18221
- const manager = getSettingsManager();
18222
- manager.updateUserSetting("apiKey", apiKey);
18223
- console.log(`
18224
- \u2705 API key saved to ~/.grok/user-settings.json`);
18225
- } catch {
18226
- console.log("\n\u26A0\uFE0F Could not save API key to settings file");
18227
- console.log("API key set for current session only");
18228
- }
18229
- onApiKeySet(agent);
18230
- } catch {
18231
- setError("Invalid API key format");
18232
- setIsSubmitting(false);
18233
- }
18234
- };
18235
- const displayText = input.length > 0 ? isSubmitting ? "*".repeat(input.length) : "*".repeat(input.length) + "\u2588" : isSubmitting ? " " : "\u2588";
18236
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
18237
- /* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u{1F511} Grok API Key Required" }),
18238
- /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Please enter your Grok API key to continue:" }) }),
18239
- /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: "blue", paddingX: 1, marginBottom: 1, children: [
18240
- /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u276F " }),
18241
- /* @__PURE__ */ jsx(Text, { children: displayText })
18242
- ] }),
18243
- error ? /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsxs(Text, { color: "red", children: [
18244
- "\u274C ",
18245
- error
18246
- ] }) }) : null,
18247
- /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
18248
- /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "\u2022 Press Enter to submit" }),
18249
- /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "\u2022 Press Ctrl+C to exit" }),
18250
- /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "Note: API key will be saved to ~/.grok/user-settings.json" })
18251
17876
  ] }),
18252
- isSubmitting ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "yellow", children: "\u{1F504} Validating API key..." }) }) : null
17877
+ explanation && /* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsxs(Text, { color: "blue", italic: true, children: [
17878
+ "\u{1F4A1} ",
17879
+ explanation
17880
+ ] }) }),
17881
+ 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: [
17882
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u23BF File contents:" }),
17883
+ /* @__PURE__ */ jsx(Box, { marginLeft: 2, flexDirection: "column", children: /* @__PURE__ */ jsx(FileContentRenderer, { content: entry.content }) })
17884
+ ] }) : shouldShowDiff && shouldShowFullContent ? (
17885
+ // For diff results, show only the summary line, not the raw content
17886
+ /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
17887
+ "\u23BF ",
17888
+ entry.content.split("\n")[0]
17889
+ ] })
17890
+ ) : !shouldShowFullContent ? /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u23BF Completed" }) : /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
17891
+ "\u23BF ",
17892
+ formatToolContent(entry.content, toolName)
17893
+ ] }) }),
17894
+ shouldShowDiff && !isExecuting && shouldShowFullContent && /* @__PURE__ */ jsx(Box, { marginLeft: 4, flexDirection: "column", children: /* @__PURE__ */ jsx(
17895
+ DiffRenderer,
17896
+ {
17897
+ diffContent: entry.content,
17898
+ filename: filePath,
17899
+ terminalWidth: 80
17900
+ }
17901
+ ) })
18253
17902
  ] });
18254
17903
  }
18255
- function ChatInterfaceWithAgent({
18256
- agent,
18257
- initialMessage
17904
+ function ChatEntryRouter({ entry, verbosityLevel, explainLevel }) {
17905
+ switch (entry.type) {
17906
+ case "user":
17907
+ return /* @__PURE__ */ jsx(UserMessageEntry, { entry, verbosityLevel });
17908
+ case "assistant":
17909
+ return /* @__PURE__ */ jsx(AssistantMessageEntry, { entry, verbosityLevel });
17910
+ case "tool_call":
17911
+ case "tool_result":
17912
+ return /* @__PURE__ */ jsx(ToolCallEntry, { entry, verbosityLevel, explainLevel });
17913
+ default:
17914
+ return null;
17915
+ }
17916
+ }
17917
+ var MemoizedChatEntry = React4.memo(
17918
+ ({ entry, verbosityLevel, explainLevel }) => {
17919
+ return /* @__PURE__ */ jsx(ChatEntryRouter, { entry, verbosityLevel, explainLevel });
17920
+ }
17921
+ );
17922
+ MemoizedChatEntry.displayName = "MemoizedChatEntry";
17923
+ function ChatHistory({
17924
+ entries,
17925
+ isConfirmationActive = false,
17926
+ verbosityLevel = "quiet",
17927
+ explainLevel = "brief"
18258
17928
  }) {
18259
- const [chatHistory, setChatHistory] = useState([]);
18260
- const [isProcessing, setIsProcessing] = useState(false);
18261
- const [processingTime, setProcessingTime] = useState(0);
18262
- const [tokenCount, setTokenCount] = useState(0);
18263
- const [isStreaming, setIsStreaming] = useState(false);
18264
- const [confirmationOptions, setConfirmationOptions] = useState(null);
18265
- const [showContextTooltip, setShowContextTooltip] = useState(false);
18266
- const scrollRef = useRef(null);
18267
- const processingStartTime = useRef(0);
18268
- const lastChatHistoryLength = useRef(0);
18269
- const { contextInfo } = useContextInfo(agent);
18270
- const handleGlobalShortcuts = (str, key) => {
18271
- if (key.ctrl && (str === "i" || key.name === "i")) {
18272
- setShowContextTooltip((prev) => !prev);
18273
- return true;
18274
- }
18275
- return false;
18276
- };
18277
- const confirmationService = ConfirmationService.getInstance();
18278
- const {
18279
- input,
18280
- cursorPosition,
18281
- showCommandSuggestions,
18282
- selectedCommandIndex,
18283
- showModelSelection,
18284
- selectedModelIndex,
18285
- commandSuggestions,
18286
- availableModels,
18287
- autoEditEnabled,
18288
- verbosityLevel,
18289
- explainLevel,
18290
- planMode
18291
- } = useInputHandler({
18292
- agent,
18293
- chatHistory,
18294
- setChatHistory,
18295
- setIsProcessing,
18296
- setIsStreaming,
18297
- setTokenCount,
18298
- setProcessingTime,
18299
- processingStartTime,
18300
- isProcessing,
18301
- isStreaming,
18302
- isConfirmationActive: !!confirmationOptions,
18303
- onGlobalShortcut: handleGlobalShortcuts
18304
- });
18305
- useEffect(() => {
18306
- const isWindows = process.platform === "win32";
18307
- const isPowerShell = process.env.ComSpec?.toLowerCase().includes("powershell") || process.env.PSModulePath !== void 0;
18308
- if (!isWindows || !isPowerShell) {
18309
- console.clear();
18310
- }
18311
- console.log(" ");
18312
- console.log(" ");
18313
- const logoOutput = "X-CLI\n" + package_default.version;
18314
- const logoLines = logoOutput.split("\n");
18315
- logoLines.forEach((line) => {
18316
- if (line.trim()) {
18317
- console.log(" " + line);
18318
- } else {
18319
- console.log(line);
18320
- }
18321
- });
18322
- console.log(" ");
18323
- setChatHistory([]);
18324
- if (fs__default.existsSync(".agent")) {
18325
- const initialMessages = [];
18326
- let docsRead = 0;
18327
- let config2 = null;
18328
- const configPaths = [
18329
- path7__default.join(".xcli", "auto-read-config.json"),
18330
- // User config (distributed)
18331
- path7__default.join(".agent", "auto-read-config.json")
18332
- // Dev override (gitignored)
18333
- ];
18334
- for (const configPath of configPaths) {
18335
- if (fs__default.existsSync(configPath)) {
18336
- try {
18337
- const configContent = fs__default.readFileSync(configPath, "utf8");
18338
- config2 = JSON.parse(configContent);
18339
- break;
18340
- } catch (_error) {
17929
+ const filteredEntries = isConfirmationActive ? entries.filter(
17930
+ (entry) => !(entry.type === "tool_call" && entry.content === "Executing...")
17931
+ ) : entries;
17932
+ const maxEntries = process.env.COMPACT === "1" ? 5 : 20;
17933
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: filteredEntries.slice(-maxEntries).map((entry, index) => /* @__PURE__ */ jsx(
17934
+ MemoizedChatEntry,
17935
+ {
17936
+ entry,
17937
+ verbosityLevel,
17938
+ explainLevel
17939
+ },
17940
+ `${entry.timestamp.getTime()}-${index}`
17941
+ )) });
17942
+ }
17943
+ var operationConfig = {
17944
+ thinking: {
17945
+ icon: "\u{1F9E0}",
17946
+ spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
17947
+ messages: ["Thinking...", "Processing...", "Analyzing...", "Computing...", "Reasoning..."]
17948
+ },
17949
+ search: {
17950
+ icon: "\u{1F50D}",
17951
+ spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
17952
+ messages: ["Searching...", "Scanning files...", "Finding matches...", "Indexing..."]
17953
+ },
17954
+ indexing: {
17955
+ icon: "\u{1F4C2}",
17956
+ spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
17957
+ messages: ["Indexing workspace...", "Building context...", "Mapping relationships..."]
17958
+ },
17959
+ write: {
17960
+ icon: "\u{1F4DD}",
17961
+ spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
17962
+ messages: ["Writing file...", "Saving changes...", "Updating content..."]
17963
+ },
17964
+ edit: {
17965
+ icon: "\u270F\uFE0F",
17966
+ spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
17967
+ messages: ["Editing file...", "Applying changes...", "Modifying content..."]
17968
+ },
17969
+ compact: {
17970
+ icon: "\u{1F504}",
17971
+ spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
17972
+ messages: ["Compacting context...", "Optimizing memory...", "Refreshing session..."]
17973
+ },
17974
+ analyze: {
17975
+ icon: "\u{1F52C}",
17976
+ spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
17977
+ messages: ["Analyzing code...", "Understanding structure...", "Mapping dependencies..."]
17978
+ },
17979
+ process: {
17980
+ icon: "\u26A1",
17981
+ spinner: "\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F",
17982
+ messages: ["Processing...", "Working...", "Computing...", "Executing..."]
17983
+ }
17984
+ };
17985
+ function LoadingSpinner({
17986
+ isActive,
17987
+ processingTime,
17988
+ tokenCount,
17989
+ operation = "thinking",
17990
+ message,
17991
+ progress
17992
+ }) {
17993
+ const [frameIndex, setFrameIndex] = useState(0);
17994
+ const [messageIndex, setMessageIndex] = useState(0);
17995
+ const config2 = operationConfig[operation];
17996
+ const spinnerChar = config2.spinner[frameIndex % config2.spinner.length];
17997
+ const operationMessage = message || config2.messages[messageIndex % config2.messages.length];
17998
+ const color = getSpinnerColor(operation);
17999
+ useEffect(() => {
18000
+ if (!isActive) return;
18001
+ const interval = setInterval(() => {
18002
+ setFrameIndex((prev) => prev + 1);
18003
+ }, 80);
18004
+ return () => clearInterval(interval);
18005
+ }, [isActive]);
18006
+ useEffect(() => {
18007
+ if (!isActive) return;
18008
+ const messageInterval = setInterval(() => {
18009
+ setMessageIndex((prev) => prev + 1);
18010
+ }, 80 * config2.spinner.length * 3);
18011
+ return () => clearInterval(messageInterval);
18012
+ }, [isActive, config2.spinner.length]);
18013
+ if (!isActive) return null;
18014
+ const renderProgressBar = () => {
18015
+ if (progress === void 0) return null;
18016
+ const barLength = 20;
18017
+ const filled = Math.round(progress / 100 * barLength);
18018
+ const empty = barLength - filled;
18019
+ const progressBar = "\u2588".repeat(filled) + "\u2591".repeat(empty);
18020
+ return /* @__PURE__ */ jsxs(Text, { color: inkColors.muted, children: [
18021
+ " ",
18022
+ "[",
18023
+ /* @__PURE__ */ jsx(Text, { color, children: progressBar }),
18024
+ "] ",
18025
+ progress,
18026
+ "%"
18027
+ ] });
18028
+ };
18029
+ return /* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
18030
+ /* @__PURE__ */ jsxs(Box, { children: [
18031
+ /* @__PURE__ */ jsxs(Text, { color, children: [
18032
+ config2.icon,
18033
+ " ",
18034
+ spinnerChar,
18035
+ " ",
18036
+ operationMessage
18037
+ ] }),
18038
+ renderProgressBar()
18039
+ ] }),
18040
+ /* @__PURE__ */ jsxs(Text, { color: inkColors.muted, children: [
18041
+ " ",
18042
+ "(",
18043
+ processingTime,
18044
+ "s \xB7 \u2191 ",
18045
+ formatTokenCount(tokenCount),
18046
+ " tokens \xB7 esc to interrupt)"
18047
+ ] })
18048
+ ] });
18049
+ }
18050
+ var PHASE_DISPLAY = {
18051
+ inactive: { label: "Inactive", color: "gray", symbol: "\u25CB" },
18052
+ analysis: { label: "Analyzing", color: "blue", symbol: "\u{1F50D}" },
18053
+ strategy: { label: "Planning", color: "yellow", symbol: "\u{1F9E0}" },
18054
+ presentation: { label: "Presenting", color: "cyan", symbol: "\u{1F4CB}" },
18055
+ approved: { label: "Approved", color: "green", symbol: "\u2705" },
18056
+ rejected: { label: "Rejected", color: "red", symbol: "\u274C" }
18057
+ };
18058
+ var PHASE_DESCRIPTIONS = {
18059
+ inactive: "Press Shift+Tab twice to enter Plan Mode",
18060
+ analysis: "Exploring codebase and gathering insights",
18061
+ strategy: "Formulating implementation strategy",
18062
+ presentation: "Presenting plan for your review",
18063
+ approved: "Plan approved - ready for execution",
18064
+ rejected: "Plan rejected - please provide feedback"
18065
+ };
18066
+ function PlanModeIndicator({
18067
+ isActive,
18068
+ phase,
18069
+ progress,
18070
+ sessionDuration,
18071
+ detailed = false
18072
+ }) {
18073
+ const phaseInfo = PHASE_DISPLAY[phase];
18074
+ const phaseDescription = PHASE_DESCRIPTIONS[phase];
18075
+ const formatDuration = (ms) => {
18076
+ const seconds = Math.floor(ms / 1e3);
18077
+ const minutes = Math.floor(seconds / 60);
18078
+ const remainingSeconds = seconds % 60;
18079
+ if (minutes > 0) {
18080
+ return `${minutes}m ${remainingSeconds}s`;
18081
+ }
18082
+ return `${remainingSeconds}s`;
18083
+ };
18084
+ const formatProgressBar = (progress2, width = 20) => {
18085
+ const filled = Math.round(progress2 * width);
18086
+ const empty = width - filled;
18087
+ return "\u2588".repeat(filled) + "\u2591".repeat(empty);
18088
+ };
18089
+ if (!isActive) {
18090
+ return detailed ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 1, children: [
18091
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "center", children: [
18092
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: phaseInfo.symbol }),
18093
+ /* @__PURE__ */ jsx(Box, { marginLeft: 1, children: /* @__PURE__ */ jsxs(Text, { color: "gray", bold: true, children: [
18094
+ "Plan Mode: ",
18095
+ phaseInfo.label
18096
+ ] }) })
18097
+ ] }),
18098
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: phaseDescription }) })
18099
+ ] }) : null;
18100
+ }
18101
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: phaseInfo.color, padding: 1, children: [
18102
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "center", justifyContent: "space-between", children: [
18103
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "center", children: [
18104
+ /* @__PURE__ */ jsx(Text, { color: phaseInfo.color, children: phaseInfo.symbol }),
18105
+ /* @__PURE__ */ jsx(Box, { marginLeft: 1, children: /* @__PURE__ */ jsxs(Text, { color: phaseInfo.color, bold: true, children: [
18106
+ "Plan Mode: ",
18107
+ phaseInfo.label
18108
+ ] }) })
18109
+ ] }),
18110
+ /* @__PURE__ */ jsx(Box, { flexDirection: "row", alignItems: "center", children: /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: formatDuration(sessionDuration) }) })
18111
+ ] }),
18112
+ phase !== "inactive" && phase !== "approved" && phase !== "rejected" && /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "center", marginTop: 1, children: [
18113
+ /* @__PURE__ */ jsx(Box, { marginRight: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "Progress:" }) }),
18114
+ /* @__PURE__ */ jsx(Text, { color: phaseInfo.color, children: formatProgressBar(progress) }),
18115
+ /* @__PURE__ */ jsx(Box, { marginLeft: 1, children: /* @__PURE__ */ jsxs(Text, { color: "gray", dimColor: true, children: [
18116
+ Math.round(progress * 100),
18117
+ "%"
18118
+ ] }) })
18119
+ ] }),
18120
+ detailed && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: phaseDescription }) }),
18121
+ detailed && phase === "analysis" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
18122
+ /* @__PURE__ */ jsx(Text, { color: "blue", dimColor: true, children: "\u2022 Reading project structure" }),
18123
+ /* @__PURE__ */ jsx(Text, { color: "blue", dimColor: true, children: "\u2022 Analyzing dependencies" }),
18124
+ /* @__PURE__ */ jsx(Text, { color: "blue", dimColor: true, children: "\u2022 Identifying key components" })
18125
+ ] }),
18126
+ detailed && phase === "strategy" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
18127
+ /* @__PURE__ */ jsx(Text, { color: "yellow", dimColor: true, children: "\u2022 Evaluating implementation approaches" }),
18128
+ /* @__PURE__ */ jsx(Text, { color: "yellow", dimColor: true, children: "\u2022 Assessing risks and dependencies" }),
18129
+ /* @__PURE__ */ jsx(Text, { color: "yellow", dimColor: true, children: "\u2022 Estimating effort and timeline" })
18130
+ ] }),
18131
+ detailed && phase === "presentation" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
18132
+ /* @__PURE__ */ jsx(Text, { color: "cyan", dimColor: true, children: "\u2022 Preparing implementation plan" }),
18133
+ /* @__PURE__ */ jsx(Text, { color: "cyan", dimColor: true, children: "\u2022 Organizing steps and dependencies" }),
18134
+ /* @__PURE__ */ jsx(Text, { color: "cyan", dimColor: true, children: "\u2022 Ready for your review" })
18135
+ ] }),
18136
+ !detailed && /* @__PURE__ */ jsx(Box, { flexDirection: "row", marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { color: "gray", dimColor: true, children: [
18137
+ phase === "presentation" && "\u2022 Press Enter to review plan",
18138
+ phase === "approved" && '\u2022 Type "execute" to start implementation',
18139
+ phase === "rejected" && "\u2022 Provide feedback to regenerate plan",
18140
+ (phase === "analysis" || phase === "strategy") && "\u2022 Plan mode is analyzing..."
18141
+ ] }) })
18142
+ ] });
18143
+ }
18144
+ function PlanModeStatusIndicator({
18145
+ isActive,
18146
+ phase,
18147
+ progress
18148
+ }) {
18149
+ if (!isActive) {
18150
+ return /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "Plan Mode: Off" });
18151
+ }
18152
+ const phaseInfo = PHASE_DISPLAY[phase];
18153
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "center", children: [
18154
+ /* @__PURE__ */ jsx(Text, { color: phaseInfo.color, children: phaseInfo.symbol }),
18155
+ /* @__PURE__ */ jsx(Box, { marginLeft: 1, children: /* @__PURE__ */ jsxs(Text, { color: phaseInfo.color, children: [
18156
+ "Plan: ",
18157
+ phaseInfo.label
18158
+ ] }) }),
18159
+ phase !== "inactive" && phase !== "approved" && phase !== "rejected" && /* @__PURE__ */ jsx(Box, { marginLeft: 1, children: /* @__PURE__ */ jsxs(Text, { color: "gray", dimColor: true, children: [
18160
+ "(",
18161
+ Math.round(progress * 100),
18162
+ "%)"
18163
+ ] }) })
18164
+ ] });
18165
+ }
18166
+ function ChatInput({
18167
+ input,
18168
+ cursorPosition,
18169
+ isProcessing,
18170
+ isStreaming
18171
+ }) {
18172
+ const beforeCursor = input.slice(0, cursorPosition);
18173
+ const lines = input.split("\n");
18174
+ const isMultiline = lines.length > 1;
18175
+ let currentLineIndex = 0;
18176
+ let currentCharIndex = 0;
18177
+ let totalChars = 0;
18178
+ for (let i = 0; i < lines.length; i++) {
18179
+ if (totalChars + lines[i].length >= cursorPosition) {
18180
+ currentLineIndex = i;
18181
+ currentCharIndex = cursorPosition - totalChars;
18182
+ break;
18183
+ }
18184
+ totalChars += lines[i].length + 1;
18185
+ }
18186
+ const showCursor = !isProcessing && !isStreaming;
18187
+ const borderColor = isProcessing || isStreaming ? "yellow" : "blue";
18188
+ const promptColor = "cyan";
18189
+ const placeholderText = "Ask me anything...";
18190
+ const isPlaceholder = !input;
18191
+ if (isMultiline) {
18192
+ return /* @__PURE__ */ jsx(
18193
+ Box,
18194
+ {
18195
+ borderStyle: "round",
18196
+ borderColor,
18197
+ paddingY: 0,
18198
+ marginTop: 1,
18199
+ children: lines.map((line, index) => {
18200
+ const isCurrentLine = index === currentLineIndex;
18201
+ const promptChar = index === 0 ? "\u276F " : " ";
18202
+ if (isCurrentLine) {
18203
+ const beforeCursorInLine = line.slice(0, currentCharIndex);
18204
+ const cursorChar2 = line.slice(currentCharIndex, currentCharIndex + 1) || " ";
18205
+ const afterCursorInLine = line.slice(currentCharIndex + 1);
18206
+ return /* @__PURE__ */ jsxs(Box, { children: [
18207
+ /* @__PURE__ */ jsx(Text, { color: promptColor, children: promptChar }),
18208
+ /* @__PURE__ */ jsxs(Text, { children: [
18209
+ beforeCursorInLine,
18210
+ showCursor && /* @__PURE__ */ jsx(Text, { backgroundColor: "white", color: "black", children: cursorChar2 }),
18211
+ !showCursor && cursorChar2 !== " " && cursorChar2,
18212
+ afterCursorInLine
18213
+ ] })
18214
+ ] }, index);
18215
+ } else {
18216
+ return /* @__PURE__ */ jsxs(Box, { children: [
18217
+ /* @__PURE__ */ jsx(Text, { color: promptColor, children: promptChar }),
18218
+ /* @__PURE__ */ jsx(Text, { children: line })
18219
+ ] }, index);
18341
18220
  }
18342
- }
18343
- }
18344
- const isEnabled = config2?.enabled !== false;
18345
- const showLoadingMessage = config2?.showLoadingMessage !== false;
18346
- const showSummaryMessage = config2?.showSummaryMessage !== false;
18347
- const showFileContents = config2?.showFileContents === true;
18348
- if (!isEnabled) {
18349
- return;
18350
- }
18351
- if (showLoadingMessage) {
18352
- initialMessages.push({
18353
- type: "assistant",
18354
- content: "\u{1F4DA} Reading core documentation into memory...",
18355
- timestamp: /* @__PURE__ */ new Date()
18356
- });
18221
+ })
18357
18222
  }
18358
- const folders = config2?.folders || [
18359
- {
18360
- name: "system",
18361
- priority: 1,
18362
- files: [
18363
- { name: "architecture.md", title: "System Architecture", icon: "\u{1F4CB}", required: true },
18364
- { name: "critical-state.md", title: "Critical State", icon: "\u{1F3D7}\uFE0F", required: false },
18365
- { name: "installation.md", title: "Installation", icon: "\u{1F3D7}\uFE0F", required: false },
18366
- { name: "api-schema.md", title: "API Schema", icon: "\u{1F3D7}\uFE0F", required: false },
18367
- { name: "auto-read-system.md", title: "Auto-Read System", icon: "\u{1F3D7}\uFE0F", required: false }
18368
- ]
18369
- },
18370
- {
18371
- name: "sop",
18372
- priority: 2,
18373
- files: [
18374
- { name: "git-workflow.md", title: "Git Workflow SOP", icon: "\u{1F527}", required: true },
18375
- { name: "release-management.md", title: "Release Management SOP", icon: "\u{1F4D6}", required: false },
18376
- { name: "automation-protection.md", title: "Automation Protection SOP", icon: "\u{1F4D6}", required: false },
18377
- { name: "npm-publishing-troubleshooting.md", title: "NPM Publishing Troubleshooting", icon: "\u{1F4D6}", required: false }
18378
- ]
18223
+ );
18224
+ }
18225
+ const cursorChar = input.slice(cursorPosition, cursorPosition + 1) || " ";
18226
+ const afterCursorText = input.slice(cursorPosition + 1);
18227
+ return /* @__PURE__ */ jsx(
18228
+ Box,
18229
+ {
18230
+ borderStyle: "round",
18231
+ borderColor,
18232
+ paddingX: 1,
18233
+ paddingY: 0,
18234
+ marginTop: 1,
18235
+ children: /* @__PURE__ */ jsxs(Box, { children: [
18236
+ /* @__PURE__ */ jsx(Text, { color: promptColor, children: "\u276F " }),
18237
+ isPlaceholder ? /* @__PURE__ */ jsxs(Fragment, { children: [
18238
+ /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: placeholderText }),
18239
+ showCursor && /* @__PURE__ */ jsx(Text, { backgroundColor: "white", color: "black", children: " " })
18240
+ ] }) : /* @__PURE__ */ jsxs(Text, { children: [
18241
+ beforeCursor,
18242
+ showCursor && /* @__PURE__ */ jsx(Text, { backgroundColor: "white", color: "black", children: cursorChar }),
18243
+ !showCursor && cursorChar !== " " && cursorChar,
18244
+ afterCursorText
18245
+ ] })
18246
+ ] })
18247
+ }
18248
+ );
18249
+ }
18250
+ function VersionNotification({ isVisible = true }) {
18251
+ const [versionInfo, setVersionInfo] = useState(null);
18252
+ useEffect(() => {
18253
+ const checkVersion = async () => {
18254
+ try {
18255
+ const info = await getCachedVersionInfo();
18256
+ if (info?.isUpdateAvailable) {
18257
+ setVersionInfo({
18258
+ isUpdateAvailable: info.isUpdateAvailable,
18259
+ current: info.current,
18260
+ latest: info.latest
18261
+ });
18379
18262
  }
18380
- ];
18381
- if (config2?.customFolders) {
18382
- folders.push(...config2.customFolders);
18263
+ } catch {
18383
18264
  }
18384
- folders.sort((a, b) => (a.priority || 999) - (b.priority || 999));
18385
- for (const folder of folders) {
18386
- const folderPath = path7__default.join(".agent", folder.name);
18387
- if (!fs__default.existsSync(folderPath)) {
18388
- continue;
18389
- }
18390
- for (const file of folder.files) {
18391
- let filePaths = [];
18392
- if (file.pattern) {
18393
- continue;
18394
- } else {
18395
- filePaths = [file.name];
18396
- }
18397
- for (const fileName of filePaths) {
18398
- const filePath = path7__default.join(folderPath, fileName);
18399
- if (!fs__default.existsSync(filePath)) {
18400
- if (file.required) ;
18401
- continue;
18402
- }
18403
- try {
18404
- const content = fs__default.readFileSync(filePath, "utf8");
18405
- const displayTitle = file.title || fileName.replace(".md", "").replace("-", " ").toUpperCase();
18406
- const icon = file.icon || "\u{1F4C4}";
18407
- if (showFileContents) {
18408
- initialMessages.push({
18409
- type: "assistant",
18410
- content: `${icon} **${displayTitle} (from .agent/${folder.name}/${fileName})**
18411
-
18412
- ${content}`,
18413
- timestamp: /* @__PURE__ */ new Date()
18414
- });
18415
- }
18416
- docsRead++;
18417
- } catch (_error) {
18265
+ };
18266
+ checkVersion();
18267
+ const interval = setInterval(checkVersion, 6 * 60 * 60 * 1e3);
18268
+ return () => clearInterval(interval);
18269
+ }, []);
18270
+ if (!isVisible || !versionInfo?.isUpdateAvailable) {
18271
+ return null;
18272
+ }
18273
+ return /* @__PURE__ */ jsx(Box, { marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ jsxs(
18274
+ Box,
18275
+ {
18276
+ borderStyle: "round",
18277
+ borderColor: inkColors.warning,
18278
+ paddingX: 2,
18279
+ paddingY: 0,
18280
+ children: [
18281
+ /* @__PURE__ */ jsxs(Text, { color: inkColors.warning, children: [
18282
+ "\u{1F504} Update available: v",
18283
+ versionInfo.latest,
18284
+ " (current: v",
18285
+ versionInfo.current,
18286
+ ")"
18287
+ ] }),
18288
+ /* @__PURE__ */ jsx(Text, { color: inkColors.muted, children: " - Use '/upgrade' to update" })
18289
+ ]
18290
+ }
18291
+ ) });
18292
+ }
18293
+ function MCPStatus({}) {
18294
+ const [connectedServers, setConnectedServers] = useState([]);
18295
+ const [_availableTools, setAvailableTools] = useState([]);
18296
+ useEffect(() => {
18297
+ const updateStatus = () => {
18298
+ try {
18299
+ const manager = getMCPManager();
18300
+ const servers = manager.getServers();
18301
+ const tools = manager.getTools();
18302
+ setConnectedServers(servers);
18303
+ setAvailableTools(tools);
18304
+ } catch (_error) {
18305
+ setConnectedServers([]);
18306
+ setAvailableTools([]);
18307
+ }
18308
+ };
18309
+ const initialTimer = setTimeout(updateStatus, 2e3);
18310
+ const interval = setInterval(updateStatus, 2e3);
18311
+ return () => {
18312
+ clearTimeout(initialTimer);
18313
+ clearInterval(interval);
18314
+ };
18315
+ }, []);
18316
+ if (connectedServers.length === 0) {
18317
+ return null;
18318
+ }
18319
+ return /* @__PURE__ */ jsx(Box, { marginLeft: 1, children: /* @__PURE__ */ jsxs(Text, { color: "green", children: [
18320
+ "\u2692 mcps: ",
18321
+ connectedServers.length,
18322
+ " "
18323
+ ] }) });
18324
+ }
18325
+ function ContextIndicator({
18326
+ state,
18327
+ compact = false
18328
+ }) {
18329
+ const getTokenColor = (percent) => {
18330
+ if (percent >= 90) return inkColors.error;
18331
+ if (percent >= 80) return inkColors.warning;
18332
+ if (percent >= 60) return inkColors.info;
18333
+ return inkColors.success;
18334
+ };
18335
+ const getMemoryPressureColor = (pressure) => {
18336
+ switch (pressure) {
18337
+ case "critical":
18338
+ return inkColors.error;
18339
+ case "high":
18340
+ return inkColors.warning;
18341
+ case "medium":
18342
+ return inkColors.info;
18343
+ default:
18344
+ return inkColors.success;
18345
+ }
18346
+ };
18347
+ const formatTokenCount2 = (count) => {
18348
+ if (count >= 1e6) {
18349
+ return `${(count / 1e6).toFixed(1)}M`;
18350
+ }
18351
+ if (count >= 1e3) {
18352
+ return `${(count / 1e3).toFixed(1)}k`;
18353
+ }
18354
+ return count.toString();
18355
+ };
18356
+ const getProgressBar = (percent, width = 20) => {
18357
+ const filled = Math.round(percent / 100 * width);
18358
+ const empty = width - filled;
18359
+ return "\u2588".repeat(filled) + "\u2592".repeat(empty);
18360
+ };
18361
+ if (compact) {
18362
+ return /* @__PURE__ */ jsxs(Box, { children: [
18363
+ /* @__PURE__ */ jsxs(Text, { color: getTokenColor(state.tokenUsage.percent), children: [
18364
+ "\u{1F9E0} ",
18365
+ formatTokenCount2(state.tokenUsage.current),
18366
+ "/",
18367
+ formatTokenCount2(state.tokenUsage.max),
18368
+ " (",
18369
+ state.tokenUsage.percent,
18370
+ "%)"
18371
+ ] }),
18372
+ /* @__PURE__ */ jsx(Text, { color: inkColors.muted, children: " \u2502 " }),
18373
+ /* @__PURE__ */ jsxs(Text, { color: inkColors.info, children: [
18374
+ "\u{1F4C1} ",
18375
+ state.fileCount,
18376
+ " files"
18377
+ ] }),
18378
+ /* @__PURE__ */ jsx(Text, { color: inkColors.muted, children: " \u2502 " }),
18379
+ /* @__PURE__ */ jsxs(Text, { color: inkColors.info, children: [
18380
+ "\u{1F4AC} ",
18381
+ state.messagesCount,
18382
+ " msgs"
18383
+ ] }),
18384
+ state.memoryPressure !== "low" && /* @__PURE__ */ jsxs(Fragment, { children: [
18385
+ /* @__PURE__ */ jsx(Text, { color: inkColors.muted, children: " \u2502 " }),
18386
+ /* @__PURE__ */ jsxs(Text, { color: getMemoryPressureColor(state.memoryPressure), children: [
18387
+ "\u26A0\uFE0F ",
18388
+ state.memoryPressure,
18389
+ " pressure"
18390
+ ] })
18391
+ ] })
18392
+ ] });
18393
+ }
18394
+ return /* @__PURE__ */ jsxs(
18395
+ Box,
18396
+ {
18397
+ flexDirection: "column",
18398
+ borderStyle: "round",
18399
+ borderColor: state.contextHealth === "critical" ? "red" : state.contextHealth === "degraded" ? "yellow" : "green",
18400
+ paddingX: 1,
18401
+ paddingY: 0,
18402
+ children: [
18403
+ /* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", children: [
18404
+ /* @__PURE__ */ jsx(Text, { bold: true, color: inkColors.primary, children: "\u{1F9E0} Context Status" }),
18405
+ /* @__PURE__ */ jsx(
18406
+ Text,
18407
+ {
18408
+ color: state.contextHealth === "critical" ? inkColors.error : state.contextHealth === "degraded" ? inkColors.warning : inkColors.success,
18409
+ children: state.contextHealth.toUpperCase()
18418
18410
  }
18419
- }
18420
- }
18421
- }
18422
- if (showSummaryMessage && docsRead > 0) {
18423
- initialMessages.push({
18424
- type: "assistant",
18425
- content: `\u2705 ${docsRead} documentation files read - I have a complete understanding of the current architecture and operational procedures.`,
18426
- timestamp: /* @__PURE__ */ new Date()
18427
- });
18428
- }
18429
- if (initialMessages.length > 0) {
18430
- setChatHistory(initialMessages);
18431
- }
18432
- }
18433
- }, []);
18434
- useEffect(() => {
18435
- const newEntries = chatHistory.slice(lastChatHistoryLength.current);
18436
- if (newEntries.length > 0) {
18437
- const sessionFile = path7__default.join(os__default.homedir(), ".grok", "session.log");
18438
- try {
18439
- const dir = path7__default.dirname(sessionFile);
18440
- if (!fs__default.existsSync(dir)) {
18441
- fs__default.mkdirSync(dir, { recursive: true });
18442
- }
18443
- const lines = newEntries.map((entry) => JSON.stringify(entry)).join("\n") + "\n";
18444
- fs__default.appendFileSync(sessionFile, lines);
18445
- } catch {
18446
- }
18411
+ )
18412
+ ] }),
18413
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
18414
+ /* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", children: [
18415
+ /* @__PURE__ */ jsx(Text, { color: inkColors.info, children: "Memory Usage:" }),
18416
+ /* @__PURE__ */ jsxs(Text, { color: getTokenColor(state.tokenUsage.percent), children: [
18417
+ formatTokenCount2(state.tokenUsage.current),
18418
+ "/",
18419
+ formatTokenCount2(state.tokenUsage.max),
18420
+ " (",
18421
+ state.tokenUsage.percent,
18422
+ "%)"
18423
+ ] })
18424
+ ] }),
18425
+ /* @__PURE__ */ jsx(Box, { marginTop: 0, children: /* @__PURE__ */ jsx(Text, { color: getTokenColor(state.tokenUsage.percent), children: getProgressBar(state.tokenUsage.percent, 40) }) })
18426
+ ] }),
18427
+ /* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", marginTop: 1, children: [
18428
+ /* @__PURE__ */ jsxs(Box, { children: [
18429
+ /* @__PURE__ */ jsx(Text, { color: inkColors.info, children: "\u{1F4C1} Files: " }),
18430
+ /* @__PURE__ */ jsx(Text, { color: inkColors.accent, children: state.fileCount })
18431
+ ] }),
18432
+ /* @__PURE__ */ jsxs(Box, { children: [
18433
+ /* @__PURE__ */ jsx(Text, { color: inkColors.info, children: "\u{1F4AC} Messages: " }),
18434
+ /* @__PURE__ */ jsx(Text, { color: inkColors.accent, children: state.messagesCount })
18435
+ ] }),
18436
+ /* @__PURE__ */ jsxs(Box, { children: [
18437
+ /* @__PURE__ */ jsx(Text, { color: inkColors.info, children: "\u{1F525} Pressure: " }),
18438
+ /* @__PURE__ */ jsx(Text, { color: getMemoryPressureColor(state.memoryPressure), children: state.memoryPressure })
18439
+ ] })
18440
+ ] }),
18441
+ state.tokenUsage.percent >= 80 && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: inkColors.warning, children: "\u26A0\uFE0F Approaching context limit. Consider using /compact or /clear" }) }),
18442
+ state.memoryPressure === "critical" && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: inkColors.error, children: "\u{1F6A8} Critical memory pressure! Performance may degrade. Use /clear immediately." }) }),
18443
+ state.loadedFiles.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
18444
+ /* @__PURE__ */ jsx(Text, { color: inkColors.info, bold: true, children: "Recent Files:" }),
18445
+ state.loadedFiles.slice(0, 3).map((file, index) => /* @__PURE__ */ jsxs(Box, { children: [
18446
+ /* @__PURE__ */ jsx(Text, { color: inkColors.muted, children: "\u2022 " }),
18447
+ /* @__PURE__ */ jsx(Text, { color: inkColors.accent, children: file.path }),
18448
+ /* @__PURE__ */ jsxs(Text, { color: inkColors.muted, children: [
18449
+ " ",
18450
+ "(",
18451
+ formatTokenCount2(file.tokens),
18452
+ " tokens)"
18453
+ ] })
18454
+ ] }, index)),
18455
+ state.loadedFiles.length > 3 && /* @__PURE__ */ jsxs(Text, { color: inkColors.muted, children: [
18456
+ "... and ",
18457
+ state.loadedFiles.length - 3,
18458
+ " more files"
18459
+ ] })
18460
+ ] }),
18461
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: inkColors.muted, children: "\u{1F4A1} Use /context for details, /compact to optimize, /clear to reset" }) })
18462
+ ]
18447
18463
  }
18448
- lastChatHistoryLength.current = chatHistory.length;
18449
- }, [chatHistory]);
18450
- useEffect(() => {
18451
- if (initialMessage && agent) {
18452
- const userEntry = {
18453
- type: "user",
18454
- content: initialMessage,
18455
- timestamp: /* @__PURE__ */ new Date()
18456
- };
18457
- setChatHistory([userEntry]);
18458
- const processInitialMessage = async () => {
18459
- setIsProcessing(true);
18460
- setIsStreaming(true);
18461
- try {
18462
- let streamingEntry = null;
18463
- let accumulatedContent = "";
18464
- let lastTokenCount = 0;
18465
- let pendingToolCalls = null;
18466
- let pendingToolResults = [];
18467
- let lastUpdateTime = Date.now();
18468
- const flushUpdates = () => {
18469
- const now = Date.now();
18470
- if (now - lastUpdateTime < 150) return;
18471
- setChatHistory((prev) => {
18472
- let newHistory = [...prev];
18473
- if (lastTokenCount !== 0) {
18474
- }
18475
- if (accumulatedContent) {
18476
- if (!streamingEntry) {
18477
- const newStreamingEntry = {
18478
- type: "assistant",
18479
- content: accumulatedContent,
18480
- timestamp: /* @__PURE__ */ new Date(),
18481
- isStreaming: true
18482
- };
18483
- newHistory.push(newStreamingEntry);
18484
- streamingEntry = newStreamingEntry;
18485
- } else {
18486
- const lastIdx = newHistory.length - 1;
18487
- if (lastIdx >= 0 && newHistory[lastIdx].isStreaming) {
18488
- newHistory[lastIdx] = { ...newHistory[lastIdx], content: newHistory[lastIdx].content + accumulatedContent };
18489
- }
18490
- }
18491
- accumulatedContent = "";
18492
- }
18493
- if (pendingToolCalls) {
18494
- const streamingIdx = newHistory.findIndex((entry) => entry.isStreaming);
18495
- if (streamingIdx >= 0) {
18496
- newHistory[streamingIdx] = { ...newHistory[streamingIdx], isStreaming: false, toolCalls: pendingToolCalls };
18497
- }
18498
- streamingEntry = null;
18499
- pendingToolCalls.forEach((toolCall) => {
18500
- const toolCallEntry = {
18501
- type: "tool_call",
18502
- content: "Executing...",
18503
- timestamp: /* @__PURE__ */ new Date(),
18504
- toolCall
18505
- };
18506
- newHistory.push(toolCallEntry);
18507
- });
18508
- pendingToolCalls = null;
18509
- }
18510
- if (pendingToolResults.length > 0) {
18511
- newHistory = newHistory.map((entry) => {
18512
- if (entry.isStreaming) {
18513
- return { ...entry, isStreaming: false };
18514
- }
18515
- const matchingResult = pendingToolResults.find(
18516
- (result) => entry.type === "tool_call" && entry.toolCall?.id === result.toolCall.id
18517
- );
18518
- if (matchingResult) {
18519
- return {
18520
- ...entry,
18521
- type: "tool_result",
18522
- content: matchingResult.toolResult.success ? matchingResult.toolResult.output || "Success" : matchingResult.toolResult.error || "Error occurred",
18523
- toolResult: matchingResult.toolResult
18524
- };
18525
- }
18526
- return entry;
18527
- });
18528
- streamingEntry = null;
18529
- pendingToolResults = [];
18530
- }
18531
- return newHistory;
18532
- });
18533
- if (lastTokenCount !== 0) {
18534
- setTokenCount(lastTokenCount);
18535
- }
18536
- lastUpdateTime = now;
18537
- };
18538
- for await (const chunk of agent.processUserMessageStream(initialMessage)) {
18539
- switch (chunk.type) {
18540
- case "content":
18541
- if (chunk.content) {
18542
- accumulatedContent += chunk.content;
18543
- }
18544
- break;
18545
- case "token_count":
18546
- if (chunk.tokenCount !== void 0) {
18547
- lastTokenCount = chunk.tokenCount;
18548
- }
18549
- break;
18550
- case "tool_calls":
18551
- if (chunk.toolCalls) {
18552
- pendingToolCalls = chunk.toolCalls;
18553
- }
18554
- break;
18555
- case "tool_result":
18556
- if (chunk.toolCall && chunk.toolResult) {
18557
- pendingToolResults.push({ toolCall: chunk.toolCall, toolResult: chunk.toolResult });
18558
- }
18559
- break;
18560
- case "done":
18561
- flushUpdates();
18562
- break;
18563
- }
18564
- flushUpdates();
18565
- }
18566
- flushUpdates();
18567
- if (streamingEntry) {
18568
- setChatHistory(
18569
- (prev) => prev.map(
18570
- (entry) => entry.isStreaming ? { ...entry, isStreaming: false } : entry
18571
- )
18572
- );
18573
- }
18574
- setIsStreaming(false);
18575
- } catch (error) {
18576
- const errorMessage = error instanceof Error ? error.message : String(error);
18577
- const errorEntry = {
18578
- type: "assistant",
18579
- content: `Error: ${errorMessage}`,
18580
- timestamp: /* @__PURE__ */ new Date()
18581
- };
18582
- setChatHistory((prev) => [...prev, errorEntry]);
18583
- setIsStreaming(false);
18584
- }
18585
- setIsProcessing(false);
18586
- processingStartTime.current = 0;
18587
- };
18588
- processInitialMessage();
18464
+ );
18465
+ }
18466
+ function ModelSelection({
18467
+ models,
18468
+ selectedIndex,
18469
+ isVisible,
18470
+ currentModel
18471
+ }) {
18472
+ if (!isVisible) return null;
18473
+ return /* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
18474
+ /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
18475
+ "Select Grok Model (current: ",
18476
+ currentModel,
18477
+ "):"
18478
+ ] }) }),
18479
+ models.map((modelOption, index) => /* @__PURE__ */ jsx(Box, { paddingLeft: 1, children: /* @__PURE__ */ jsx(
18480
+ Text,
18481
+ {
18482
+ color: index === selectedIndex ? "black" : "white",
18483
+ backgroundColor: index === selectedIndex ? "cyan" : void 0,
18484
+ children: modelOption.model
18485
+ }
18486
+ ) }, index)),
18487
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "\u2191\u2193 navigate \u2022 Enter/Tab select \u2022 Esc cancel" }) })
18488
+ ] });
18489
+ }
18490
+ function ConfirmationDialog({
18491
+ operation,
18492
+ filename,
18493
+ onConfirm,
18494
+ onReject,
18495
+ showVSCodeOpen = false,
18496
+ content
18497
+ }) {
18498
+ const [selectedOption, setSelectedOption] = useState(0);
18499
+ const [feedbackMode, setFeedbackMode] = useState(false);
18500
+ const [feedback, setFeedback] = useState("");
18501
+ const options = [
18502
+ "Yes",
18503
+ "Yes, and don't ask again this session",
18504
+ "No",
18505
+ "No, with feedback"
18506
+ ];
18507
+ useInput((input, key) => {
18508
+ if (feedbackMode) {
18509
+ if (key.return) {
18510
+ onReject(feedback.trim());
18511
+ return;
18512
+ }
18513
+ if (key.backspace || key.delete) {
18514
+ setFeedback((prev) => prev.slice(0, -1));
18515
+ return;
18516
+ }
18517
+ if (input && !key.ctrl && !key.meta) {
18518
+ setFeedback((prev) => prev + input);
18519
+ }
18520
+ return;
18589
18521
  }
18590
- }, [initialMessage, agent]);
18591
- useEffect(() => {
18592
- const handleConfirmationRequest = (options) => {
18593
- setConfirmationOptions(options);
18594
- };
18595
- confirmationService.on("confirmation-requested", handleConfirmationRequest);
18596
- return () => {
18597
- confirmationService.off(
18598
- "confirmation-requested",
18599
- handleConfirmationRequest
18600
- );
18601
- };
18602
- }, [confirmationService]);
18603
- useEffect(() => {
18604
- if (!isProcessing && !isStreaming) {
18605
- setProcessingTime(0);
18522
+ if (key.upArrow || key.shift && key.tab) {
18523
+ setSelectedOption((prev) => prev > 0 ? prev - 1 : options.length - 1);
18606
18524
  return;
18607
18525
  }
18608
- if (processingStartTime.current === 0) {
18609
- processingStartTime.current = Date.now();
18526
+ if (key.downArrow || key.tab) {
18527
+ setSelectedOption((prev) => (prev + 1) % options.length);
18528
+ return;
18610
18529
  }
18611
- const interval = setInterval(() => {
18612
- setProcessingTime(
18613
- Math.floor((Date.now() - processingStartTime.current) / 1e3)
18614
- );
18615
- }, 1e3);
18616
- return () => clearInterval(interval);
18617
- }, [isProcessing, isStreaming]);
18618
- const handleConfirmation = (dontAskAgain) => {
18619
- confirmationService.confirmOperation(true, dontAskAgain);
18620
- setConfirmationOptions(null);
18621
- };
18622
- const handleRejection = (feedback) => {
18623
- confirmationService.rejectOperation(feedback);
18624
- setConfirmationOptions(null);
18625
- setIsProcessing(false);
18626
- setIsStreaming(false);
18627
- setTokenCount(0);
18628
- setProcessingTime(0);
18629
- processingStartTime.current = 0;
18630
- };
18631
- const toggleContextTooltip = () => {
18632
- setShowContextTooltip((prev) => !prev);
18633
- };
18530
+ if (key.return) {
18531
+ if (selectedOption === 0) {
18532
+ onConfirm(false);
18533
+ } else if (selectedOption === 1) {
18534
+ onConfirm(true);
18535
+ } else if (selectedOption === 2) {
18536
+ onReject("Operation cancelled by user");
18537
+ } else {
18538
+ setFeedbackMode(true);
18539
+ }
18540
+ return;
18541
+ }
18542
+ if (key.escape) {
18543
+ if (feedbackMode) {
18544
+ setFeedbackMode(false);
18545
+ setFeedback("");
18546
+ } else {
18547
+ onReject("Operation cancelled by user (pressed Escape)");
18548
+ }
18549
+ return;
18550
+ }
18551
+ });
18552
+ if (feedbackMode) {
18553
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
18554
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Type your feedback and press Enter, or press Escape to go back." }) }),
18555
+ /* @__PURE__ */ jsxs(
18556
+ Box,
18557
+ {
18558
+ borderStyle: "round",
18559
+ borderColor: "yellow",
18560
+ paddingX: 1,
18561
+ marginTop: 1,
18562
+ children: [
18563
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u276F " }),
18564
+ /* @__PURE__ */ jsxs(Text, { children: [
18565
+ feedback,
18566
+ /* @__PURE__ */ jsx(Text, { color: "white", children: "\u2588" })
18567
+ ] })
18568
+ ]
18569
+ }
18570
+ )
18571
+ ] });
18572
+ }
18573
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
18574
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Box, { children: [
18575
+ /* @__PURE__ */ jsx(Text, { color: "magenta", children: "\u23FA" }),
18576
+ /* @__PURE__ */ jsxs(Text, { color: "white", children: [
18577
+ " ",
18578
+ operation,
18579
+ "(",
18580
+ filename,
18581
+ ")"
18582
+ ] })
18583
+ ] }) }),
18584
+ /* @__PURE__ */ jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [
18585
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u23BF Requesting user confirmation" }),
18586
+ showVSCodeOpen && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u23BF Opened changes in Visual Studio Code \u29C9" }) }),
18587
+ content && /* @__PURE__ */ jsxs(Fragment, { children: [
18588
+ /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
18589
+ "\u23BF ",
18590
+ content.split("\n")[0]
18591
+ ] }),
18592
+ /* @__PURE__ */ jsx(Box, { marginLeft: 4, flexDirection: "column", children: /* @__PURE__ */ jsx(
18593
+ DiffRenderer,
18594
+ {
18595
+ diffContent: content,
18596
+ filename,
18597
+ terminalWidth: 80
18598
+ }
18599
+ ) })
18600
+ ] })
18601
+ ] }),
18602
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
18603
+ /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { children: "Do you want to proceed with this operation?" }) }),
18604
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: options.map((option, index) => /* @__PURE__ */ jsx(Box, { paddingLeft: 1, children: /* @__PURE__ */ jsxs(
18605
+ Text,
18606
+ {
18607
+ color: selectedOption === index ? "black" : "white",
18608
+ backgroundColor: selectedOption === index ? "cyan" : void 0,
18609
+ children: [
18610
+ index + 1,
18611
+ ". ",
18612
+ option
18613
+ ]
18614
+ }
18615
+ ) }, index)) }),
18616
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "\u2191\u2193 navigate \u2022 Enter select \u2022 Esc cancel" }) })
18617
+ ] })
18618
+ ] });
18619
+ }
18620
+ function ChatInterfaceRenderer({
18621
+ chatHistory,
18622
+ confirmationOptions,
18623
+ showContextTooltip,
18624
+ contextInfo,
18625
+ verbosityLevel,
18626
+ explainLevel,
18627
+ isProcessing,
18628
+ isStreaming,
18629
+ processingTime,
18630
+ tokenCount,
18631
+ planMode,
18632
+ input,
18633
+ cursorPosition,
18634
+ autoEditEnabled,
18635
+ agent,
18636
+ commandSuggestions,
18637
+ selectedCommandIndex,
18638
+ showCommandSuggestions,
18639
+ availableModels,
18640
+ selectedModelIndex,
18641
+ showModelSelection,
18642
+ handleConfirmation,
18643
+ handleRejection,
18644
+ toggleContextTooltip
18645
+ }) {
18634
18646
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, children: [
18635
18647
  chatHistory.length === 0 && !confirmationOptions && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
18636
18648
  /* @__PURE__ */ jsx(
@@ -18693,7 +18705,7 @@ ${content}`,
18693
18705
  ] })
18694
18706
  ] }),
18695
18707
  /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Type your request in natural language. Ctrl+C to clear, 'exit' to quit." }) }),
18696
- /* @__PURE__ */ jsx(Box, { flexDirection: "column", ref: scrollRef, children: /* @__PURE__ */ jsx(
18708
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsx(
18697
18709
  ChatHistory,
18698
18710
  {
18699
18711
  entries: chatHistory,
@@ -18731,7 +18743,7 @@ ${content}`,
18731
18743
  progress: void 0
18732
18744
  }
18733
18745
  ),
18734
- planMode.isActive && /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(
18746
+ planMode.isActive && planMode.currentPhase && planMode.progress !== void 0 && planMode.sessionDuration !== void 0 && /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(
18735
18747
  PlanModeIndicator,
18736
18748
  {
18737
18749
  isActive: planMode.isActive,
@@ -18768,17 +18780,17 @@ ${content}`,
18768
18780
  "\u224B ",
18769
18781
  agent.getCurrentModel()
18770
18782
  ] }) }),
18771
- /* @__PURE__ */ jsx(Box, { marginRight: 2, children: /* @__PURE__ */ jsx(
18783
+ /* @__PURE__ */ jsx(Box, { marginRight: 2, children: planMode.currentPhase && planMode.progress !== void 0 ? /* @__PURE__ */ jsx(
18772
18784
  PlanModeStatusIndicator,
18773
18785
  {
18774
18786
  isActive: planMode.isActive,
18775
18787
  phase: planMode.currentPhase,
18776
18788
  progress: planMode.progress
18777
18789
  }
18778
- ) }),
18790
+ ) : /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "Plan Mode: Off" }) }),
18779
18791
  /* @__PURE__ */ jsx(MCPStatus, {})
18780
18792
  ] }),
18781
- contextInfo.tokenUsage && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
18793
+ contextInfo.tokenUsage && contextInfo.loadedFiles && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
18782
18794
  ContextIndicator,
18783
18795
  {
18784
18796
  state: {
@@ -18786,7 +18798,8 @@ ${content}`,
18786
18798
  memoryPressure: contextInfo.memoryPressure,
18787
18799
  loadedFiles: contextInfo.loadedFiles,
18788
18800
  messagesCount: contextInfo.messagesCount,
18789
- contextHealth: contextInfo.contextHealth,
18801
+ contextHealth: "optimal",
18802
+ // TODO: implement context health check
18790
18803
  fileCount: contextInfo.loadedFiles.length
18791
18804
  },
18792
18805
  compact: true
@@ -18813,6 +18826,109 @@ ${content}`,
18813
18826
  ] })
18814
18827
  ] });
18815
18828
  }
18829
+ function ChatInterfaceWithAgent({
18830
+ agent,
18831
+ initialMessage
18832
+ }) {
18833
+ const [chatHistory, setChatHistory] = useState([]);
18834
+ const [isProcessing, setIsProcessing] = useState(false);
18835
+ const [processingTime, setProcessingTime] = useState(0);
18836
+ const [tokenCount, setTokenCount] = useState(0);
18837
+ const [isStreaming, setIsStreaming] = useState(false);
18838
+ const [confirmationOptions, setConfirmationOptions] = useState(null);
18839
+ const [showContextTooltip, setShowContextTooltip] = useState(false);
18840
+ const processingStartTime = useRef(0);
18841
+ useConsoleSetup();
18842
+ useEffect(() => {
18843
+ setChatHistory([]);
18844
+ useAutoRead(setChatHistory);
18845
+ }, []);
18846
+ useSessionLogging(chatHistory);
18847
+ const { contextInfo } = useContextInfo(agent);
18848
+ const handleGlobalShortcuts = (str, key) => {
18849
+ if (key.ctrl && (str === "i" || key.name === "i")) {
18850
+ setShowContextTooltip((prev) => !prev);
18851
+ return true;
18852
+ }
18853
+ return false;
18854
+ };
18855
+ const confirmationService = ConfirmationService.getInstance();
18856
+ const {
18857
+ input,
18858
+ cursorPosition,
18859
+ showCommandSuggestions,
18860
+ selectedCommandIndex,
18861
+ showModelSelection,
18862
+ selectedModelIndex,
18863
+ commandSuggestions,
18864
+ availableModels,
18865
+ autoEditEnabled,
18866
+ verbosityLevel,
18867
+ explainLevel,
18868
+ planMode
18869
+ } = useInputHandler({
18870
+ agent,
18871
+ chatHistory,
18872
+ setChatHistory,
18873
+ setIsProcessing,
18874
+ setIsStreaming,
18875
+ setTokenCount,
18876
+ setProcessingTime,
18877
+ processingStartTime,
18878
+ isProcessing,
18879
+ isStreaming,
18880
+ isConfirmationActive: !!confirmationOptions,
18881
+ onGlobalShortcut: handleGlobalShortcuts
18882
+ });
18883
+ useStreaming(agent, initialMessage, setChatHistory, {
18884
+ setIsProcessing,
18885
+ setIsStreaming,
18886
+ setTokenCount});
18887
+ const { handleConfirmation, handleRejection } = useConfirmations(
18888
+ confirmationService,
18889
+ {
18890
+ setConfirmationOptions,
18891
+ setIsProcessing,
18892
+ setIsStreaming,
18893
+ setTokenCount,
18894
+ setProcessingTime,
18895
+ processingStartTime
18896
+ }
18897
+ );
18898
+ useProcessingTimer(isProcessing, isStreaming, setProcessingTime);
18899
+ const toggleContextTooltip = () => {
18900
+ setShowContextTooltip((prev) => !prev);
18901
+ };
18902
+ return /* @__PURE__ */ jsx(
18903
+ ChatInterfaceRenderer,
18904
+ {
18905
+ chatHistory,
18906
+ confirmationOptions,
18907
+ showContextTooltip,
18908
+ contextInfo,
18909
+ verbosityLevel,
18910
+ explainLevel,
18911
+ isProcessing,
18912
+ isStreaming,
18913
+ processingTime,
18914
+ tokenCount,
18915
+ planMode,
18916
+ input,
18917
+ cursorPosition,
18918
+ autoEditEnabled,
18919
+ agent,
18920
+ commandSuggestions,
18921
+ selectedCommandIndex,
18922
+ showCommandSuggestions,
18923
+ availableModels,
18924
+ selectedModelIndex,
18925
+ showModelSelection,
18926
+ handleConfirmation,
18927
+ handleRejection,
18928
+ toggleContextTooltip
18929
+ }
18930
+ );
18931
+ }
18816
18932
  function ChatInterface({
18817
18933
  agent,
18818
18934
  initialMessage
@@ -19318,7 +19434,7 @@ program.name("grok").description(
19318
19434
  checkAutoCompact();
19319
19435
  checkStartupUpdates();
19320
19436
  const initialMessage = Array.isArray(message) ? message.join(" ") : message;
19321
- const app = render(React3.createElement(ChatInterface, { agent, initialMessage }));
19437
+ const app = render(React4.createElement(ChatInterface, { agent, initialMessage }));
19322
19438
  const cleanup = () => {
19323
19439
  app.unmount();
19324
19440
  agent.abortCurrentOperation();