@xagent/x-cli 1.1.59 → 1.1.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +2057 -1938
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/.xcli/auto-read-config.json +0 -100
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
|
|
9
|
-
import { Box, Text,
|
|
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 {
|
|
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,
|
|
7042
|
+
const dfs = (filePath, path30) => {
|
|
7043
7043
|
if (visiting.has(filePath)) {
|
|
7044
|
-
const cycleStart =
|
|
7045
|
-
const cycle =
|
|
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, [...
|
|
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
|
|
9034
|
-
let command = `cat "${
|
|
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' "${
|
|
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.59",
|
|
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
|
-
//
|
|
14863
|
-
|
|
14864
|
-
|
|
14865
|
-
|
|
14866
|
-
|
|
14867
|
-
|
|
14868
|
-
|
|
14869
|
-
|
|
14870
|
-
|
|
14871
|
-
|
|
14872
|
-
|
|
14873
|
-
|
|
14874
|
-
|
|
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.61",
|
|
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
|
-
|
|
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
|
-
|
|
16569
|
-
|
|
16570
|
-
|
|
16571
|
-
|
|
16572
|
-
|
|
16573
|
-
|
|
16574
|
-
|
|
16575
|
-
|
|
16576
|
-
|
|
16577
|
-
|
|
16578
|
-
|
|
16579
|
-
|
|
16580
|
-
|
|
16581
|
-
|
|
16582
|
-
|
|
16583
|
-
|
|
16584
|
-
|
|
16585
|
-
|
|
16586
|
-
return
|
|
16587
|
-
|
|
16588
|
-
|
|
16589
|
-
|
|
16590
|
-
|
|
16591
|
-
|
|
16592
|
-
|
|
16593
|
-
|
|
16594
|
-
|
|
16595
|
-
|
|
16596
|
-
|
|
16597
|
-
|
|
16598
|
-
|
|
16599
|
-
|
|
16600
|
-
|
|
16601
|
-
|
|
16602
|
-
|
|
16603
|
-
|
|
16604
|
-
|
|
16605
|
-
|
|
16606
|
-
|
|
16607
|
-
|
|
16608
|
-
|
|
16609
|
-
|
|
16610
|
-
|
|
16611
|
-
|
|
16612
|
-
|
|
16613
|
-
|
|
16614
|
-
|
|
16615
|
-
|
|
16616
|
-
|
|
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
|
-
|
|
16690
|
-
|
|
16691
|
-
|
|
16692
|
-
|
|
16693
|
-
|
|
16694
|
-
|
|
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:
|
|
16701
|
-
" ",
|
|
16702
|
-
|
|
16703
|
-
|
|
16704
|
-
|
|
16705
|
-
|
|
16706
|
-
"
|
|
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
|
|
16711
|
-
|
|
16712
|
-
|
|
16713
|
-
|
|
16714
|
-
|
|
16715
|
-
|
|
16716
|
-
|
|
16717
|
-
|
|
16718
|
-
|
|
16719
|
-
|
|
16720
|
-
|
|
16721
|
-
|
|
16722
|
-
|
|
16723
|
-
|
|
16724
|
-
|
|
16725
|
-
|
|
16726
|
-
|
|
16727
|
-
|
|
16728
|
-
|
|
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
|
-
|
|
16731
|
-
|
|
16732
|
-
|
|
16733
|
-
|
|
16734
|
-
|
|
16735
|
-
|
|
16736
|
-
|
|
16737
|
-
|
|
16738
|
-
|
|
16739
|
-
|
|
16740
|
-
|
|
16741
|
-
|
|
16742
|
-
|
|
16743
|
-
|
|
16744
|
-
}
|
|
16745
|
-
|
|
16746
|
-
|
|
16747
|
-
|
|
16748
|
-
|
|
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
|
-
|
|
16778
|
-
|
|
16779
|
-
|
|
16780
|
-
|
|
16781
|
-
|
|
16782
|
-
|
|
16783
|
-
|
|
16784
|
-
|
|
16785
|
-
|
|
16786
|
-
|
|
16787
|
-
|
|
16788
|
-
|
|
16789
|
-
|
|
16790
|
-
|
|
16791
|
-
|
|
16792
|
-
|
|
16793
|
-
|
|
16794
|
-
|
|
16795
|
-
|
|
16796
|
-
|
|
16797
|
-
|
|
16798
|
-
|
|
16799
|
-
|
|
16800
|
-
|
|
16801
|
-
|
|
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
|
-
|
|
16807
|
-
|
|
16808
|
-
|
|
16809
|
-
|
|
16810
|
-
|
|
16811
|
-
|
|
16812
|
-
|
|
16813
|
-
|
|
16814
|
-
|
|
16815
|
-
|
|
16816
|
-
|
|
16817
|
-
|
|
16818
|
-
|
|
16819
|
-
|
|
16820
|
-
|
|
16821
|
-
|
|
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
|
-
|
|
16824
|
-
|
|
16825
|
-
|
|
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
|
-
|
|
16828
|
-
|
|
16829
|
-
|
|
16830
|
-
|
|
16831
|
-
|
|
16832
|
-
|
|
16833
|
-
|
|
16834
|
-
|
|
16835
|
-
|
|
16836
|
-
|
|
16837
|
-
|
|
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
|
-
|
|
16848
|
-
|
|
16849
|
-
|
|
16850
|
-
|
|
16851
|
-
const
|
|
16852
|
-
|
|
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
|
-
|
|
16855
|
-
|
|
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
|
-
|
|
16858
|
-
|
|
16859
|
-
const
|
|
16860
|
-
|
|
16861
|
-
|
|
16862
|
-
|
|
16863
|
-
|
|
16864
|
-
|
|
16865
|
-
|
|
16866
|
-
|
|
16867
|
-
|
|
16868
|
-
|
|
16869
|
-
|
|
16870
|
-
|
|
16871
|
-
|
|
16872
|
-
|
|
16873
|
-
|
|
16874
|
-
|
|
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
|
-
|
|
16878
|
-
|
|
16879
|
-
|
|
16880
|
-
|
|
16881
|
-
|
|
16882
|
-
|
|
16883
|
-
|
|
16884
|
-
|
|
16885
|
-
|
|
16886
|
-
|
|
16887
|
-
|
|
16888
|
-
|
|
16889
|
-
|
|
16890
|
-
|
|
16891
|
-
|
|
16892
|
-
|
|
16893
|
-
|
|
16894
|
-
|
|
16895
|
-
|
|
16896
|
-
|
|
16897
|
-
|
|
16898
|
-
|
|
16899
|
-
|
|
16900
|
-
|
|
16901
|
-
|
|
16902
|
-
|
|
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
|
-
|
|
16988
|
-
|
|
16989
|
-
|
|
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
|
-
|
|
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
|
-
|
|
17006
|
-
|
|
17007
|
-
|
|
17008
|
-
|
|
17009
|
-
|
|
17010
|
-
|
|
17011
|
-
|
|
17012
|
-
|
|
17013
|
-
|
|
17014
|
-
|
|
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
|
-
|
|
17066
|
-
|
|
17067
|
-
|
|
17068
|
-
|
|
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
|
|
17088
|
-
|
|
17089
|
-
|
|
17090
|
-
|
|
17091
|
-
|
|
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
|
-
|
|
17094
|
-
|
|
16899
|
+
docsRead++;
|
|
16900
|
+
} catch (_error) {
|
|
17095
16901
|
}
|
|
17096
16902
|
}
|
|
17097
|
-
|
|
17098
|
-
|
|
17099
|
-
|
|
17100
|
-
|
|
17101
|
-
|
|
17102
|
-
|
|
17103
|
-
|
|
17104
|
-
|
|
17105
|
-
|
|
17106
|
-
|
|
17107
|
-
|
|
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
|
|
17159
|
-
|
|
17160
|
-
|
|
17161
|
-
|
|
17162
|
-
|
|
17163
|
-
|
|
17164
|
-
|
|
17165
|
-
|
|
17166
|
-
|
|
17167
|
-
|
|
17168
|
-
|
|
17169
|
-
|
|
17170
|
-
|
|
17171
|
-
|
|
17172
|
-
|
|
17173
|
-
|
|
17174
|
-
|
|
17175
|
-
|
|
17176
|
-
|
|
17177
|
-
|
|
17178
|
-
|
|
17179
|
-
|
|
17180
|
-
|
|
17181
|
-
|
|
17182
|
-
|
|
17183
|
-
|
|
17184
|
-
|
|
17185
|
-
|
|
17186
|
-
|
|
17187
|
-
|
|
17188
|
-
|
|
17189
|
-
|
|
17190
|
-
|
|
17191
|
-
|
|
17192
|
-
|
|
17193
|
-
|
|
17194
|
-
|
|
17195
|
-
|
|
17196
|
-
|
|
17197
|
-
|
|
17198
|
-
|
|
17199
|
-
|
|
17200
|
-
|
|
17201
|
-
|
|
17202
|
-
|
|
17203
|
-
|
|
17204
|
-
|
|
17205
|
-
|
|
17206
|
-
|
|
17207
|
-
|
|
17208
|
-
|
|
17209
|
-
|
|
17210
|
-
|
|
17211
|
-
|
|
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
|
-
|
|
17218
|
-
|
|
17219
|
-
|
|
17220
|
-
|
|
17221
|
-
|
|
17222
|
-
|
|
17223
|
-
|
|
17224
|
-
|
|
17225
|
-
|
|
17226
|
-
|
|
17227
|
-
|
|
17228
|
-
|
|
17229
|
-
|
|
17230
|
-
|
|
17231
|
-
|
|
17232
|
-
|
|
17233
|
-
|
|
17234
|
-
|
|
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
|
|
17243
|
-
const
|
|
17244
|
-
|
|
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
|
|
17247
|
-
|
|
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
|
-
|
|
17259
|
-
const interval = setInterval(updateStatus, 2e3);
|
|
17074
|
+
confirmationService.on("confirmation-requested", handleConfirmationRequest);
|
|
17260
17075
|
return () => {
|
|
17261
|
-
|
|
17262
|
-
|
|
17076
|
+
confirmationService.off(
|
|
17077
|
+
"confirmation-requested",
|
|
17078
|
+
handleConfirmationRequest
|
|
17079
|
+
);
|
|
17263
17080
|
};
|
|
17264
|
-
}, []);
|
|
17265
|
-
|
|
17266
|
-
|
|
17267
|
-
|
|
17268
|
-
|
|
17269
|
-
|
|
17270
|
-
|
|
17271
|
-
|
|
17272
|
-
|
|
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
|
+
};
|
|
17273
17099
|
}
|
|
17274
|
-
function
|
|
17275
|
-
|
|
17276
|
-
|
|
17277
|
-
|
|
17278
|
-
|
|
17279
|
-
|
|
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);
|
|
17303
|
-
}
|
|
17304
|
-
return;
|
|
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();
|
|
17305
17106
|
}
|
|
17306
|
-
|
|
17307
|
-
|
|
17308
|
-
|
|
17309
|
-
|
|
17310
|
-
|
|
17311
|
-
|
|
17312
|
-
|
|
17313
|
-
}
|
|
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");
|
|
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);
|
|
17321
17114
|
} else {
|
|
17322
|
-
|
|
17115
|
+
console.log(line);
|
|
17323
17116
|
}
|
|
17324
|
-
|
|
17325
|
-
|
|
17326
|
-
|
|
17327
|
-
|
|
17328
|
-
|
|
17329
|
-
|
|
17330
|
-
|
|
17331
|
-
|
|
17117
|
+
});
|
|
17118
|
+
console.log(" ");
|
|
17119
|
+
}, []);
|
|
17120
|
+
}
|
|
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 {
|
|
17332
17135
|
}
|
|
17136
|
+
}
|
|
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);
|
|
17333
17145
|
return;
|
|
17334
17146
|
}
|
|
17335
|
-
|
|
17336
|
-
|
|
17337
|
-
|
|
17338
|
-
|
|
17339
|
-
|
|
17340
|
-
|
|
17341
|
-
|
|
17342
|
-
|
|
17343
|
-
|
|
17344
|
-
|
|
17345
|
-
|
|
17346
|
-
|
|
17347
|
-
|
|
17348
|
-
|
|
17349
|
-
|
|
17350
|
-
|
|
17351
|
-
|
|
17352
|
-
|
|
17353
|
-
|
|
17354
|
-
|
|
17355
|
-
|
|
17147
|
+
if (processingStartTime.current === 0) {
|
|
17148
|
+
processingStartTime.current = Date.now();
|
|
17149
|
+
}
|
|
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,753 +17504,1145 @@ function ContextTooltip({ isVisible }) {
|
|
|
17881
17504
|
}
|
|
17882
17505
|
);
|
|
17883
17506
|
}
|
|
17884
|
-
|
|
17885
|
-
|
|
17886
|
-
|
|
17887
|
-
|
|
17888
|
-
|
|
17889
|
-
|
|
17890
|
-
|
|
17891
|
-
|
|
17892
|
-
|
|
17893
|
-
|
|
17894
|
-
|
|
17895
|
-
|
|
17896
|
-
|
|
17897
|
-
|
|
17898
|
-
|
|
17899
|
-
|
|
17900
|
-
|
|
17901
|
-
|
|
17902
|
-
|
|
17903
|
-
|
|
17904
|
-
|
|
17905
|
-
|
|
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
|
-
|
|
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
|
-
|
|
17911
|
-
|
|
17912
|
-
|
|
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
|
|
17944
|
-
|
|
17945
|
-
|
|
17946
|
-
|
|
17947
|
-
|
|
17948
|
-
|
|
17949
|
-
|
|
17950
|
-
const
|
|
17951
|
-
|
|
17952
|
-
|
|
17953
|
-
|
|
17954
|
-
|
|
17955
|
-
|
|
17956
|
-
|
|
17957
|
-
|
|
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
|
-
|
|
17960
|
-
|
|
17961
|
-
|
|
17962
|
-
|
|
17963
|
-
|
|
17964
|
-
|
|
17965
|
-
|
|
17966
|
-
|
|
17967
|
-
|
|
17968
|
-
|
|
17969
|
-
|
|
17970
|
-
|
|
17971
|
-
|
|
17972
|
-
|
|
17973
|
-
|
|
17974
|
-
|
|
17975
|
-
|
|
17976
|
-
|
|
17977
|
-
|
|
17978
|
-
|
|
17979
|
-
|
|
17980
|
-
|
|
17981
|
-
|
|
17982
|
-
|
|
17983
|
-
|
|
17984
|
-
|
|
17985
|
-
|
|
17986
|
-
|
|
17987
|
-
|
|
17988
|
-
|
|
17989
|
-
|
|
17990
|
-
|
|
17991
|
-
|
|
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
|
-
|
|
18022
|
-
|
|
18023
|
-
|
|
18024
|
-
|
|
18025
|
-
|
|
18026
|
-
|
|
18027
|
-
|
|
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
|
|
18030
|
-
|
|
18031
|
-
|
|
18032
|
-
|
|
18033
|
-
|
|
18034
|
-
|
|
18035
|
-
|
|
18036
|
-
|
|
18037
|
-
|
|
18038
|
-
|
|
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
|
-
|
|
18044
|
-
|
|
18045
|
-
|
|
18046
|
-
}
|
|
18047
|
-
|
|
18048
|
-
|
|
18049
|
-
if (
|
|
18050
|
-
|
|
18051
|
-
|
|
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
|
|
18054
|
-
|
|
18055
|
-
|
|
18056
|
-
|
|
18057
|
-
|
|
18058
|
-
|
|
18059
|
-
|
|
18060
|
-
|
|
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
|
|
17827
|
+
return "Tool";
|
|
18063
17828
|
}
|
|
18064
17829
|
};
|
|
18065
|
-
const
|
|
18066
|
-
|
|
18067
|
-
|
|
18068
|
-
|
|
18069
|
-
|
|
18070
|
-
|
|
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
|
|
17844
|
+
return "";
|
|
18073
17845
|
};
|
|
18074
|
-
const
|
|
18075
|
-
|
|
18076
|
-
|
|
18077
|
-
|
|
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
|
-
|
|
18080
|
-
|
|
18081
|
-
|
|
18082
|
-
|
|
18083
|
-
|
|
18084
|
-
|
|
18085
|
-
|
|
18086
|
-
|
|
18087
|
-
|
|
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
|
-
|
|
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
|
|
18256
|
-
|
|
18257
|
-
|
|
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
|
|
18260
|
-
|
|
18261
|
-
|
|
18262
|
-
const
|
|
18263
|
-
|
|
18264
|
-
|
|
18265
|
-
|
|
18266
|
-
|
|
18267
|
-
|
|
18268
|
-
|
|
18269
|
-
|
|
18270
|
-
|
|
18271
|
-
|
|
18272
|
-
|
|
18273
|
-
|
|
18274
|
-
|
|
18275
|
-
|
|
18276
|
-
|
|
18277
|
-
|
|
18278
|
-
|
|
18279
|
-
|
|
18280
|
-
|
|
18281
|
-
|
|
18282
|
-
|
|
18283
|
-
|
|
18284
|
-
|
|
18285
|
-
|
|
18286
|
-
|
|
18287
|
-
|
|
18288
|
-
|
|
18289
|
-
|
|
18290
|
-
|
|
18291
|
-
|
|
18292
|
-
|
|
18293
|
-
|
|
18294
|
-
|
|
18295
|
-
|
|
18296
|
-
|
|
18297
|
-
|
|
18298
|
-
|
|
18299
|
-
|
|
18300
|
-
|
|
18301
|
-
|
|
18302
|
-
|
|
18303
|
-
|
|
18304
|
-
|
|
18305
|
-
|
|
18306
|
-
|
|
18307
|
-
|
|
18308
|
-
|
|
18309
|
-
|
|
18310
|
-
|
|
18311
|
-
|
|
18312
|
-
|
|
18313
|
-
|
|
18314
|
-
|
|
18315
|
-
|
|
18316
|
-
|
|
18317
|
-
|
|
18318
|
-
|
|
18319
|
-
|
|
18320
|
-
|
|
18321
|
-
|
|
18322
|
-
|
|
18323
|
-
|
|
18324
|
-
|
|
18325
|
-
|
|
18326
|
-
|
|
18327
|
-
|
|
18328
|
-
|
|
18329
|
-
|
|
18330
|
-
|
|
18331
|
-
|
|
18332
|
-
|
|
18333
|
-
|
|
18334
|
-
|
|
18335
|
-
|
|
18336
|
-
|
|
18337
|
-
|
|
18338
|
-
|
|
18339
|
-
|
|
18340
|
-
|
|
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
|
-
if (!isEnabled) {
|
|
18348
|
-
return;
|
|
18349
|
-
}
|
|
18350
|
-
if (showLoadingMessage) {
|
|
18351
|
-
initialMessages.push({
|
|
18352
|
-
type: "assistant",
|
|
18353
|
-
content: "\u{1F4DA} Reading core documentation into memory...",
|
|
18354
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
18355
|
-
});
|
|
18221
|
+
})
|
|
18356
18222
|
}
|
|
18357
|
-
|
|
18358
|
-
|
|
18359
|
-
|
|
18360
|
-
|
|
18361
|
-
|
|
18362
|
-
|
|
18363
|
-
|
|
18364
|
-
|
|
18365
|
-
|
|
18366
|
-
|
|
18367
|
-
|
|
18368
|
-
|
|
18369
|
-
|
|
18370
|
-
|
|
18371
|
-
|
|
18372
|
-
|
|
18373
|
-
|
|
18374
|
-
|
|
18375
|
-
|
|
18376
|
-
|
|
18377
|
-
|
|
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
|
+
});
|
|
18378
18262
|
}
|
|
18379
|
-
|
|
18380
|
-
if (config2?.customFolders) {
|
|
18381
|
-
folders.push(...config2.customFolders);
|
|
18263
|
+
} catch {
|
|
18382
18264
|
}
|
|
18383
|
-
|
|
18384
|
-
|
|
18385
|
-
|
|
18386
|
-
|
|
18387
|
-
|
|
18388
|
-
|
|
18389
|
-
|
|
18390
|
-
|
|
18391
|
-
|
|
18392
|
-
|
|
18393
|
-
|
|
18394
|
-
|
|
18395
|
-
|
|
18396
|
-
|
|
18397
|
-
|
|
18398
|
-
|
|
18399
|
-
|
|
18400
|
-
|
|
18401
|
-
|
|
18402
|
-
|
|
18403
|
-
|
|
18404
|
-
|
|
18405
|
-
|
|
18406
|
-
|
|
18407
|
-
|
|
18408
|
-
|
|
18409
|
-
|
|
18410
|
-
|
|
18411
|
-
|
|
18412
|
-
|
|
18413
|
-
|
|
18414
|
-
|
|
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()
|
|
18415
18410
|
}
|
|
18416
|
-
|
|
18417
|
-
}
|
|
18418
|
-
|
|
18419
|
-
|
|
18420
|
-
|
|
18421
|
-
|
|
18422
|
-
|
|
18423
|
-
|
|
18424
|
-
|
|
18425
|
-
|
|
18426
|
-
|
|
18427
|
-
|
|
18428
|
-
|
|
18429
|
-
|
|
18430
|
-
|
|
18431
|
-
|
|
18432
|
-
|
|
18433
|
-
|
|
18434
|
-
|
|
18435
|
-
|
|
18436
|
-
|
|
18437
|
-
|
|
18438
|
-
|
|
18439
|
-
|
|
18440
|
-
|
|
18441
|
-
|
|
18442
|
-
|
|
18443
|
-
|
|
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
|
+
]
|
|
18444
18463
|
}
|
|
18445
|
-
|
|
18446
|
-
|
|
18447
|
-
|
|
18448
|
-
|
|
18449
|
-
|
|
18450
|
-
|
|
18451
|
-
|
|
18452
|
-
|
|
18453
|
-
|
|
18454
|
-
|
|
18455
|
-
|
|
18456
|
-
|
|
18457
|
-
|
|
18458
|
-
|
|
18459
|
-
|
|
18460
|
-
|
|
18461
|
-
|
|
18462
|
-
|
|
18463
|
-
|
|
18464
|
-
|
|
18465
|
-
|
|
18466
|
-
|
|
18467
|
-
|
|
18468
|
-
|
|
18469
|
-
|
|
18470
|
-
|
|
18471
|
-
|
|
18472
|
-
|
|
18473
|
-
|
|
18474
|
-
|
|
18475
|
-
|
|
18476
|
-
|
|
18477
|
-
|
|
18478
|
-
|
|
18479
|
-
|
|
18480
|
-
|
|
18481
|
-
|
|
18482
|
-
|
|
18483
|
-
|
|
18484
|
-
|
|
18485
|
-
|
|
18486
|
-
|
|
18487
|
-
|
|
18488
|
-
|
|
18489
|
-
|
|
18490
|
-
|
|
18491
|
-
|
|
18492
|
-
|
|
18493
|
-
|
|
18494
|
-
|
|
18495
|
-
|
|
18496
|
-
|
|
18497
|
-
|
|
18498
|
-
|
|
18499
|
-
|
|
18500
|
-
|
|
18501
|
-
|
|
18502
|
-
};
|
|
18503
|
-
newHistory.push(toolCallEntry);
|
|
18504
|
-
});
|
|
18505
|
-
pendingToolCalls = null;
|
|
18506
|
-
}
|
|
18507
|
-
if (pendingToolResults.length > 0) {
|
|
18508
|
-
newHistory = newHistory.map((entry) => {
|
|
18509
|
-
if (entry.isStreaming) {
|
|
18510
|
-
return { ...entry, isStreaming: false };
|
|
18511
|
-
}
|
|
18512
|
-
const matchingResult = pendingToolResults.find(
|
|
18513
|
-
(result) => entry.type === "tool_call" && entry.toolCall?.id === result.toolCall.id
|
|
18514
|
-
);
|
|
18515
|
-
if (matchingResult) {
|
|
18516
|
-
return {
|
|
18517
|
-
...entry,
|
|
18518
|
-
type: "tool_result",
|
|
18519
|
-
content: matchingResult.toolResult.success ? matchingResult.toolResult.output || "Success" : matchingResult.toolResult.error || "Error occurred",
|
|
18520
|
-
toolResult: matchingResult.toolResult
|
|
18521
|
-
};
|
|
18522
|
-
}
|
|
18523
|
-
return entry;
|
|
18524
|
-
});
|
|
18525
|
-
streamingEntry = null;
|
|
18526
|
-
pendingToolResults = [];
|
|
18527
|
-
}
|
|
18528
|
-
return newHistory;
|
|
18529
|
-
});
|
|
18530
|
-
if (lastTokenCount !== 0) {
|
|
18531
|
-
setTokenCount(lastTokenCount);
|
|
18532
|
-
}
|
|
18533
|
-
lastUpdateTime = now;
|
|
18534
|
-
};
|
|
18535
|
-
for await (const chunk of agent.processUserMessageStream(initialMessage)) {
|
|
18536
|
-
switch (chunk.type) {
|
|
18537
|
-
case "content":
|
|
18538
|
-
if (chunk.content) {
|
|
18539
|
-
accumulatedContent += chunk.content;
|
|
18540
|
-
}
|
|
18541
|
-
break;
|
|
18542
|
-
case "token_count":
|
|
18543
|
-
if (chunk.tokenCount !== void 0) {
|
|
18544
|
-
lastTokenCount = chunk.tokenCount;
|
|
18545
|
-
}
|
|
18546
|
-
break;
|
|
18547
|
-
case "tool_calls":
|
|
18548
|
-
if (chunk.toolCalls) {
|
|
18549
|
-
pendingToolCalls = chunk.toolCalls;
|
|
18550
|
-
}
|
|
18551
|
-
break;
|
|
18552
|
-
case "tool_result":
|
|
18553
|
-
if (chunk.toolCall && chunk.toolResult) {
|
|
18554
|
-
pendingToolResults.push({ toolCall: chunk.toolCall, toolResult: chunk.toolResult });
|
|
18555
|
-
}
|
|
18556
|
-
break;
|
|
18557
|
-
case "done":
|
|
18558
|
-
flushUpdates();
|
|
18559
|
-
break;
|
|
18560
|
-
}
|
|
18561
|
-
flushUpdates();
|
|
18562
|
-
}
|
|
18563
|
-
flushUpdates();
|
|
18564
|
-
if (streamingEntry) {
|
|
18565
|
-
setChatHistory(
|
|
18566
|
-
(prev) => prev.map(
|
|
18567
|
-
(entry) => entry.isStreaming ? { ...entry, isStreaming: false } : entry
|
|
18568
|
-
)
|
|
18569
|
-
);
|
|
18570
|
-
}
|
|
18571
|
-
setIsStreaming(false);
|
|
18572
|
-
} catch (error) {
|
|
18573
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
18574
|
-
const errorEntry = {
|
|
18575
|
-
type: "assistant",
|
|
18576
|
-
content: `Error: ${errorMessage}`,
|
|
18577
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
18578
|
-
};
|
|
18579
|
-
setChatHistory((prev) => [...prev, errorEntry]);
|
|
18580
|
-
setIsStreaming(false);
|
|
18581
|
-
}
|
|
18582
|
-
setIsProcessing(false);
|
|
18583
|
-
processingStartTime.current = 0;
|
|
18584
|
-
};
|
|
18585
|
-
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;
|
|
18586
18521
|
}
|
|
18587
|
-
|
|
18588
|
-
|
|
18589
|
-
const handleConfirmationRequest = (options) => {
|
|
18590
|
-
setConfirmationOptions(options);
|
|
18591
|
-
};
|
|
18592
|
-
confirmationService.on("confirmation-requested", handleConfirmationRequest);
|
|
18593
|
-
return () => {
|
|
18594
|
-
confirmationService.off(
|
|
18595
|
-
"confirmation-requested",
|
|
18596
|
-
handleConfirmationRequest
|
|
18597
|
-
);
|
|
18598
|
-
};
|
|
18599
|
-
}, [confirmationService]);
|
|
18600
|
-
useEffect(() => {
|
|
18601
|
-
if (!isProcessing && !isStreaming) {
|
|
18602
|
-
setProcessingTime(0);
|
|
18522
|
+
if (key.upArrow || key.shift && key.tab) {
|
|
18523
|
+
setSelectedOption((prev) => prev > 0 ? prev - 1 : options.length - 1);
|
|
18603
18524
|
return;
|
|
18604
18525
|
}
|
|
18605
|
-
if (
|
|
18606
|
-
|
|
18526
|
+
if (key.downArrow || key.tab) {
|
|
18527
|
+
setSelectedOption((prev) => (prev + 1) % options.length);
|
|
18528
|
+
return;
|
|
18607
18529
|
}
|
|
18608
|
-
|
|
18609
|
-
|
|
18610
|
-
|
|
18611
|
-
)
|
|
18612
|
-
|
|
18613
|
-
|
|
18614
|
-
|
|
18615
|
-
|
|
18616
|
-
|
|
18617
|
-
|
|
18618
|
-
|
|
18619
|
-
|
|
18620
|
-
|
|
18621
|
-
|
|
18622
|
-
|
|
18623
|
-
|
|
18624
|
-
|
|
18625
|
-
|
|
18626
|
-
|
|
18627
|
-
|
|
18628
|
-
|
|
18629
|
-
|
|
18630
|
-
|
|
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
|
+
}) {
|
|
18631
18646
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, children: [
|
|
18632
18647
|
chatHistory.length === 0 && !confirmationOptions && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
18633
18648
|
/* @__PURE__ */ jsx(
|
|
@@ -18690,7 +18705,7 @@ ${content}`,
|
|
|
18690
18705
|
] })
|
|
18691
18706
|
] }),
|
|
18692
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." }) }),
|
|
18693
|
-
/* @__PURE__ */ jsx(Box, { flexDirection: "column",
|
|
18708
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsx(
|
|
18694
18709
|
ChatHistory,
|
|
18695
18710
|
{
|
|
18696
18711
|
entries: chatHistory,
|
|
@@ -18728,7 +18743,7 @@ ${content}`,
|
|
|
18728
18743
|
progress: void 0
|
|
18729
18744
|
}
|
|
18730
18745
|
),
|
|
18731
|
-
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(
|
|
18732
18747
|
PlanModeIndicator,
|
|
18733
18748
|
{
|
|
18734
18749
|
isActive: planMode.isActive,
|
|
@@ -18765,17 +18780,17 @@ ${content}`,
|
|
|
18765
18780
|
"\u224B ",
|
|
18766
18781
|
agent.getCurrentModel()
|
|
18767
18782
|
] }) }),
|
|
18768
|
-
/* @__PURE__ */ jsx(Box, { marginRight: 2, children: /* @__PURE__ */ jsx(
|
|
18783
|
+
/* @__PURE__ */ jsx(Box, { marginRight: 2, children: planMode.currentPhase && planMode.progress !== void 0 ? /* @__PURE__ */ jsx(
|
|
18769
18784
|
PlanModeStatusIndicator,
|
|
18770
18785
|
{
|
|
18771
18786
|
isActive: planMode.isActive,
|
|
18772
18787
|
phase: planMode.currentPhase,
|
|
18773
18788
|
progress: planMode.progress
|
|
18774
18789
|
}
|
|
18775
|
-
) }),
|
|
18790
|
+
) : /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "Plan Mode: Off" }) }),
|
|
18776
18791
|
/* @__PURE__ */ jsx(MCPStatus, {})
|
|
18777
18792
|
] }),
|
|
18778
|
-
contextInfo.tokenUsage && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
|
|
18793
|
+
contextInfo.tokenUsage && contextInfo.loadedFiles && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
|
|
18779
18794
|
ContextIndicator,
|
|
18780
18795
|
{
|
|
18781
18796
|
state: {
|
|
@@ -18783,7 +18798,8 @@ ${content}`,
|
|
|
18783
18798
|
memoryPressure: contextInfo.memoryPressure,
|
|
18784
18799
|
loadedFiles: contextInfo.loadedFiles,
|
|
18785
18800
|
messagesCount: contextInfo.messagesCount,
|
|
18786
|
-
contextHealth:
|
|
18801
|
+
contextHealth: "optimal",
|
|
18802
|
+
// TODO: implement context health check
|
|
18787
18803
|
fileCount: contextInfo.loadedFiles.length
|
|
18788
18804
|
},
|
|
18789
18805
|
compact: true
|
|
@@ -18810,6 +18826,109 @@ ${content}`,
|
|
|
18810
18826
|
] })
|
|
18811
18827
|
] });
|
|
18812
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
|
+
}
|
|
18813
18932
|
function ChatInterface({
|
|
18814
18933
|
agent,
|
|
18815
18934
|
initialMessage
|
|
@@ -19315,7 +19434,7 @@ program.name("grok").description(
|
|
|
19315
19434
|
checkAutoCompact();
|
|
19316
19435
|
checkStartupUpdates();
|
|
19317
19436
|
const initialMessage = Array.isArray(message) ? message.join(" ") : message;
|
|
19318
|
-
const app = render(
|
|
19437
|
+
const app = render(React4.createElement(ChatInterface, { agent, initialMessage }));
|
|
19319
19438
|
const cleanup = () => {
|
|
19320
19439
|
app.unmount();
|
|
19321
19440
|
agent.abortCurrentOperation();
|