@xagent/x-cli 1.1.67 → 1.1.69
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 +17 -3
- package/dist/index.js +232 -23
- package/dist/index.js.map +1 -1
- package/docs/README.md +212 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- Test comment for PR creation -->
|
|
2
|
+
|
|
3
|
+
## 1.1.69 – Logo Assets & NPM Publication Complete
|
|
2
4
|
|
|
3
5
|
✅ **Live on NPM**: [@xagent/x-cli](https://www.npmjs.com/package/@xagent/x-cli) - Fully published and ready for global installation
|
|
4
6
|
|
|
@@ -45,6 +47,16 @@ A conversational AI CLI tool powered by Grok with **Claude Code-level intelligen
|
|
|
45
47
|
- **📋 User Approval Workflow**: Complete plan review and confirmation before execution
|
|
46
48
|
- **⚡ Performance Optimized**: Fast exploration (1-15 seconds) with intelligent caching and filtering
|
|
47
49
|
|
|
50
|
+
### 🚀 **P5: Research → Recommend → Execute → Auto-Doc Workflow** (Latest)
|
|
51
|
+
|
|
52
|
+
- **🤖 Research Phase**: Intelligent context loading from `.agent/` docs with Issues/Options analysis
|
|
53
|
+
- **💡 Recommend Phase**: Structured decision framework with trade-offs, effort/risk analysis, and confidence scoring
|
|
54
|
+
- **⚡ Execute Phase**: Sequential TODO execution with adaptive recovery, real-time diffs, and safety guarantees
|
|
55
|
+
- **📝 Auto-Doc Phase**: Automatic completion documentation with lesson learning and SOP candidate detection
|
|
56
|
+
- **🛡️ Safety First**: All changes have patches, backups, and git commits; adaptive error recovery
|
|
57
|
+
- **🔄 Resilient**: Handles execution failures gracefully with re-planning capabilities
|
|
58
|
+
- **📚 Knowledge Base**: Builds institutional memory through automatic documentation accumulation
|
|
59
|
+
|
|
48
60
|
### 🎨 **P4: UX Refinement - Claude Code Feel**
|
|
49
61
|
|
|
50
62
|
- **🎭 Enhanced Welcome Banner**: Professional ASCII art with context-aware status display
|
|
@@ -1078,14 +1090,14 @@ To add yourself as a contributor:
|
|
|
1078
1090
|
|
|
1079
1091
|
- **[@unblock-everything](https://github.com/unblock-everything)** — [x.ai](https://x.ai) — Cold-ass honkey 😎
|
|
1080
1092
|
- **[@Bucko89](https://github.com/Bucko89)** — [GMA](https://getmyagencies.com) — Grinding daily
|
|
1081
|
-
- **[@base-buzz](https://github.com/base-buzz)** — [
|
|
1093
|
+
- **[@base-buzz](https://github.com/base-buzz)** — [BaseBUzz](team.basebuzz.com)
|
|
1082
1094
|
|
|
1083
1095
|
_Want to see your name here? Check out our [Contributing Guide](CONTRIBUTING.md) and submit a pull request!_
|
|
1084
1096
|
|
|
1085
1097
|
### How to Contribute
|
|
1086
1098
|
|
|
1087
1099
|
1. **Fork** the repository on GitHub
|
|
1088
|
-
2. **Clone** your fork locally: `git clone https://github.com/yourusername/x-cli
|
|
1100
|
+
2. **Clone** your fork locally: `git clone https://github.com/yourusername/x-cli.git`
|
|
1089
1101
|
3. **Create** a feature branch: `git checkout -b feature/your-feature-name`
|
|
1090
1102
|
4. **Make** your changes and commit them: `git commit -m "feat: add awesome feature"`
|
|
1091
1103
|
5. **Push** to your fork: `git push origin feature/your-feature-name`
|
|
@@ -1102,3 +1114,5 @@ _Want to see your name here? Check out our [Contributing Guide](CONTRIBUTING.md)
|
|
|
1102
1114
|
- 💡 **Feature requests** - Suggest new functionality
|
|
1103
1115
|
|
|
1104
1116
|
Join our growing community of AI-powered terminal enthusiasts!
|
|
1117
|
+
|
|
1118
|
+
# Test: Branch Protection Rules Test
|
package/dist/index.js
CHANGED
|
@@ -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, path31) => {
|
|
7043
7043
|
if (visiting.has(filePath)) {
|
|
7044
|
-
const cycleStart =
|
|
7045
|
-
const cycle =
|
|
7044
|
+
const cycleStart = path31.indexOf(filePath);
|
|
7045
|
+
const cycle = path31.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, [...path31, 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 path31 = args.path;
|
|
9034
|
+
let command = `cat "${path31}"`;
|
|
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' "${path31}"`;
|
|
9037
9037
|
}
|
|
9038
9038
|
return await this.bash.execute(command);
|
|
9039
9039
|
}
|
|
@@ -14655,7 +14655,7 @@ ${guardrail.createdFrom ? `- Created from incident: ${guardrail.createdFrom}` :
|
|
|
14655
14655
|
var package_default = {
|
|
14656
14656
|
type: "module",
|
|
14657
14657
|
name: "@xagent/x-cli",
|
|
14658
|
-
version: "1.1.
|
|
14658
|
+
version: "1.1.69",
|
|
14659
14659
|
description: "An open-source AI agent that brings the power of Grok directly into your terminal.",
|
|
14660
14660
|
main: "dist/index.js",
|
|
14661
14661
|
module: "dist/index.js",
|
|
@@ -14684,6 +14684,7 @@ var package_default = {
|
|
|
14684
14684
|
"dev:watch": "npm run build && node --watch dist/index.js",
|
|
14685
14685
|
start: "node dist/index.js",
|
|
14686
14686
|
local: "npm run build && npm link && node dist/index.js",
|
|
14687
|
+
"test:workflow": "node scripts/test-workflow.js",
|
|
14687
14688
|
"start:bun": "bun run dist/index.js",
|
|
14688
14689
|
lint: "eslint . --ext .js,.jsx,.ts,.tsx",
|
|
14689
14690
|
typecheck: "tsc --noEmit",
|
|
@@ -16501,23 +16502,109 @@ ${commitMessage}`
|
|
|
16501
16502
|
setChatHistory((prev) => [...prev, commitEntry]);
|
|
16502
16503
|
if (commitResult.success) {
|
|
16503
16504
|
const pushResult = await agent.executeBashCommand("git push");
|
|
16504
|
-
|
|
16505
|
-
|
|
16506
|
-
|
|
16505
|
+
if (pushResult.success) {
|
|
16506
|
+
const pushEntry = {
|
|
16507
|
+
type: "tool_result",
|
|
16508
|
+
content: `\u{1F680} **Push Successful**: ${pushResult.output?.split("\n")[0] || "Changes pushed to remote"}`,
|
|
16509
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
16510
|
+
toolCall: {
|
|
16511
|
+
id: `git_push_${Date.now()}`,
|
|
16512
|
+
type: "function",
|
|
16513
|
+
function: {
|
|
16514
|
+
name: "bash",
|
|
16515
|
+
arguments: JSON.stringify({ command: "git push" })
|
|
16516
|
+
}
|
|
16517
|
+
},
|
|
16518
|
+
toolResult: pushResult
|
|
16519
|
+
};
|
|
16520
|
+
setChatHistory((prev) => [...prev, pushEntry]);
|
|
16521
|
+
} else {
|
|
16522
|
+
const pushError = pushResult.error || pushResult.output || "";
|
|
16523
|
+
if (pushError.includes("protected branch") || pushError.includes("Changes must be made through a pull request") || pushError.includes("GH006")) {
|
|
16524
|
+
const branchProtectionEntry = {
|
|
16525
|
+
type: "assistant",
|
|
16526
|
+
content: "\u{1F6E1}\uFE0F **Branch Protection Detected**: Direct pushes to this branch are blocked.\n\n\u{1F504} **Creating PR workflow...**",
|
|
16527
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
16528
|
+
};
|
|
16529
|
+
setChatHistory((prev) => [...prev, branchProtectionEntry]);
|
|
16530
|
+
const featureBranch = `feature/${(/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace(/[:-]/g, "").replace("T", "-")}-smart-push`;
|
|
16531
|
+
const createBranchResult = await agent.executeBashCommand(`git checkout -b ${featureBranch}`);
|
|
16532
|
+
if (createBranchResult.success) {
|
|
16533
|
+
const pushBranchResult = await agent.executeBashCommand(`git push -u origin ${featureBranch}`);
|
|
16534
|
+
if (pushBranchResult.success) {
|
|
16535
|
+
const branchSuccessEntry = {
|
|
16536
|
+
type: "tool_result",
|
|
16537
|
+
content: `\u2705 **Feature Branch Created**: \`${featureBranch}\`
|
|
16538
|
+
|
|
16539
|
+
\u{1F4CB} **Attempting to create Pull Request...**`,
|
|
16540
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
16541
|
+
};
|
|
16542
|
+
setChatHistory((prev) => [...prev, branchSuccessEntry]);
|
|
16543
|
+
const prResult = await agent.executeBashCommand(`gh pr create --title "${cleanCommitMessage}" --body "Auto-generated PR from smart-push" --head ${featureBranch} --base main`);
|
|
16544
|
+
if (prResult.success) {
|
|
16545
|
+
const prUrl = prResult.output?.match(/https:\/\/github\.com\/[^\s]+/)?.[0];
|
|
16546
|
+
const prSuccessEntry = {
|
|
16547
|
+
type: "tool_result",
|
|
16548
|
+
content: `\u2705 **Pull Request Created Successfully!**
|
|
16507
16549
|
|
|
16508
|
-
|
|
16509
|
-
|
|
16510
|
-
|
|
16511
|
-
|
|
16512
|
-
|
|
16513
|
-
|
|
16514
|
-
|
|
16515
|
-
|
|
16550
|
+
\u{1F517} **PR URL**: ${prUrl || "Check GitHub for the link"}
|
|
16551
|
+
|
|
16552
|
+
\u{1F3AF} **Next Steps**:
|
|
16553
|
+
\u2022 Review the PR on GitHub
|
|
16554
|
+
\u2022 Wait for CI checks to pass
|
|
16555
|
+
\u2022 Request approval and merge`,
|
|
16556
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
16557
|
+
};
|
|
16558
|
+
setChatHistory((prev) => [...prev, prSuccessEntry]);
|
|
16559
|
+
} else {
|
|
16560
|
+
const prManualEntry = {
|
|
16561
|
+
type: "assistant",
|
|
16562
|
+
content: `\u26A0\uFE0F **PR Creation Failed**: GitHub CLI may not be available.
|
|
16563
|
+
|
|
16564
|
+
\u{1F4A1} **Create PR Manually**:
|
|
16565
|
+
\u2022 Go to GitHub repository
|
|
16566
|
+
\u2022 Create PR from \`${featureBranch}\` \u2192 \`main\`
|
|
16567
|
+
\u2022 Title: \`${cleanCommitMessage}\``,
|
|
16568
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
16569
|
+
};
|
|
16570
|
+
setChatHistory((prev) => [...prev, prManualEntry]);
|
|
16571
|
+
}
|
|
16572
|
+
} else {
|
|
16573
|
+
const pushFailEntry = {
|
|
16574
|
+
type: "tool_result",
|
|
16575
|
+
content: `\u274C **Failed to push feature branch**: ${pushBranchResult.error}`,
|
|
16576
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
16577
|
+
};
|
|
16578
|
+
setChatHistory((prev) => [...prev, pushFailEntry]);
|
|
16579
|
+
}
|
|
16580
|
+
} else {
|
|
16581
|
+
const branchFailEntry = {
|
|
16582
|
+
type: "tool_result",
|
|
16583
|
+
content: `\u274C **Failed to create feature branch**: ${createBranchResult.error}`,
|
|
16584
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
16585
|
+
};
|
|
16586
|
+
setChatHistory((prev) => [...prev, branchFailEntry]);
|
|
16516
16587
|
}
|
|
16517
|
-
}
|
|
16518
|
-
|
|
16519
|
-
|
|
16520
|
-
|
|
16588
|
+
} else {
|
|
16589
|
+
const pushFailEntry = {
|
|
16590
|
+
type: "tool_result",
|
|
16591
|
+
content: `\u274C **Push Failed**: ${pushResult.error || "Unknown error"}
|
|
16592
|
+
|
|
16593
|
+
Try running \`git push\` manually.`,
|
|
16594
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
16595
|
+
toolCall: {
|
|
16596
|
+
id: `git_push_${Date.now()}`,
|
|
16597
|
+
type: "function",
|
|
16598
|
+
function: {
|
|
16599
|
+
name: "bash",
|
|
16600
|
+
arguments: JSON.stringify({ command: "git push" })
|
|
16601
|
+
}
|
|
16602
|
+
},
|
|
16603
|
+
toolResult: pushResult
|
|
16604
|
+
};
|
|
16605
|
+
setChatHistory((prev) => [...prev, pushFailEntry]);
|
|
16606
|
+
}
|
|
16607
|
+
}
|
|
16521
16608
|
}
|
|
16522
16609
|
} catch (error) {
|
|
16523
16610
|
const errorEntry = {
|
|
@@ -19311,6 +19398,119 @@ function createMCPCommand() {
|
|
|
19311
19398
|
});
|
|
19312
19399
|
return mcpCommand;
|
|
19313
19400
|
}
|
|
19401
|
+
var CONTEXT_BUDGET_BYTES = 280 * 1024;
|
|
19402
|
+
var MAX_SUMMARY_LENGTH = 2e3;
|
|
19403
|
+
function loadMarkdownDirectory(dirPath) {
|
|
19404
|
+
if (!fs__default.existsSync(dirPath)) {
|
|
19405
|
+
return "";
|
|
19406
|
+
}
|
|
19407
|
+
const files = fs__default.readdirSync(dirPath).filter((file) => file.endsWith(".md")).sort();
|
|
19408
|
+
let content = "";
|
|
19409
|
+
for (const file of files) {
|
|
19410
|
+
const filePath = path7__default.join(dirPath, file);
|
|
19411
|
+
try {
|
|
19412
|
+
const fileContent = fs__default.readFileSync(filePath, "utf-8");
|
|
19413
|
+
content += `
|
|
19414
|
+
|
|
19415
|
+
=== ${file} ===
|
|
19416
|
+
|
|
19417
|
+
${fileContent}`;
|
|
19418
|
+
} catch (error) {
|
|
19419
|
+
console.warn(`Failed to read ${filePath}:`, error);
|
|
19420
|
+
}
|
|
19421
|
+
}
|
|
19422
|
+
return content;
|
|
19423
|
+
}
|
|
19424
|
+
function extractDateFromFilename(filename) {
|
|
19425
|
+
const match = filename.match(/^(\d{4}-\d{2}-\d{2})/);
|
|
19426
|
+
if (match) {
|
|
19427
|
+
return new Date(match[1]);
|
|
19428
|
+
}
|
|
19429
|
+
return /* @__PURE__ */ new Date(0);
|
|
19430
|
+
}
|
|
19431
|
+
function summarizeContent(content, maxLength = MAX_SUMMARY_LENGTH) {
|
|
19432
|
+
if (content.length <= maxLength) {
|
|
19433
|
+
return content;
|
|
19434
|
+
}
|
|
19435
|
+
const truncated = content.substring(0, maxLength);
|
|
19436
|
+
const lastNewline = truncated.lastIndexOf("\n\n");
|
|
19437
|
+
if (lastNewline > maxLength * 0.8) {
|
|
19438
|
+
return truncated.substring(0, lastNewline);
|
|
19439
|
+
}
|
|
19440
|
+
return truncated + "\n\n[...content truncated for context budget...]";
|
|
19441
|
+
}
|
|
19442
|
+
function loadTaskFiles(tasksDir, maxBudget) {
|
|
19443
|
+
if (!fs__default.existsSync(tasksDir)) {
|
|
19444
|
+
return [];
|
|
19445
|
+
}
|
|
19446
|
+
const files = fs__default.readdirSync(tasksDir).filter((file) => file.endsWith(".md")).map((filename) => {
|
|
19447
|
+
const filePath = path7__default.join(tasksDir, filename);
|
|
19448
|
+
const content = fs__default.readFileSync(filePath, "utf-8");
|
|
19449
|
+
return {
|
|
19450
|
+
filename,
|
|
19451
|
+
content,
|
|
19452
|
+
size: Buffer.byteLength(content, "utf-8"),
|
|
19453
|
+
date: extractDateFromFilename(filename),
|
|
19454
|
+
isSummarized: false
|
|
19455
|
+
};
|
|
19456
|
+
}).sort((a, b) => b.date.getTime() - a.date.getTime());
|
|
19457
|
+
const result = [];
|
|
19458
|
+
let usedBudget = 0;
|
|
19459
|
+
for (const file of files) {
|
|
19460
|
+
let finalContent = file.content;
|
|
19461
|
+
let isSummarized = false;
|
|
19462
|
+
if (usedBudget + file.size > maxBudget) {
|
|
19463
|
+
finalContent = summarizeContent(file.content);
|
|
19464
|
+
const summarizedSize = Buffer.byteLength(finalContent, "utf-8");
|
|
19465
|
+
if (usedBudget + summarizedSize > maxBudget) {
|
|
19466
|
+
continue;
|
|
19467
|
+
}
|
|
19468
|
+
usedBudget += summarizedSize;
|
|
19469
|
+
isSummarized = true;
|
|
19470
|
+
} else {
|
|
19471
|
+
usedBudget += file.size;
|
|
19472
|
+
}
|
|
19473
|
+
result.push({
|
|
19474
|
+
...file,
|
|
19475
|
+
content: finalContent,
|
|
19476
|
+
isSummarized
|
|
19477
|
+
});
|
|
19478
|
+
}
|
|
19479
|
+
return result;
|
|
19480
|
+
}
|
|
19481
|
+
function loadContext(agentDir = ".agent") {
|
|
19482
|
+
const systemContent = loadMarkdownDirectory(path7__default.join(agentDir, "system"));
|
|
19483
|
+
const sopContent = loadMarkdownDirectory(path7__default.join(agentDir, "sop"));
|
|
19484
|
+
const systemSize = Buffer.byteLength(systemContent, "utf-8");
|
|
19485
|
+
const sopSize = Buffer.byteLength(sopContent, "utf-8");
|
|
19486
|
+
const taskBudget = Math.max(0, CONTEXT_BUDGET_BYTES - systemSize - sopSize);
|
|
19487
|
+
const tasks = loadTaskFiles(path7__default.join(agentDir, "tasks"), taskBudget);
|
|
19488
|
+
const totalSize = systemSize + sopSize + tasks.reduce((sum, task) => sum + Buffer.byteLength(task.content, "utf-8"), 0);
|
|
19489
|
+
const warnings = [];
|
|
19490
|
+
if (totalSize > CONTEXT_BUDGET_BYTES) {
|
|
19491
|
+
warnings.push(`Context size (${(totalSize / 1024).toFixed(1)}KB) exceeds budget (${CONTEXT_BUDGET_BYTES / 1024}KB)`);
|
|
19492
|
+
}
|
|
19493
|
+
return {
|
|
19494
|
+
system: systemContent,
|
|
19495
|
+
sop: sopContent,
|
|
19496
|
+
tasks,
|
|
19497
|
+
totalSize,
|
|
19498
|
+
warnings
|
|
19499
|
+
};
|
|
19500
|
+
}
|
|
19501
|
+
function formatContextStatus(pack) {
|
|
19502
|
+
const taskCount = pack.tasks.length;
|
|
19503
|
+
const summarizedCount = pack.tasks.filter((t) => t.isSummarized).length;
|
|
19504
|
+
const sizeKB = (pack.totalSize / 1024).toFixed(1);
|
|
19505
|
+
let status = `[x-cli] Context: loaded system docs, sop docs, ${taskCount} task docs (~${sizeKB} KB).`;
|
|
19506
|
+
if (summarizedCount > 0) {
|
|
19507
|
+
status += ` Summarized ${summarizedCount} older tasks for context budget.`;
|
|
19508
|
+
}
|
|
19509
|
+
if (pack.warnings.length > 0) {
|
|
19510
|
+
status += ` Warnings: ${pack.warnings.join("; ")}`;
|
|
19511
|
+
}
|
|
19512
|
+
return status;
|
|
19513
|
+
}
|
|
19314
19514
|
|
|
19315
19515
|
// src/index.ts
|
|
19316
19516
|
dotenv.config();
|
|
@@ -19603,6 +19803,15 @@ program.name("grok").description(
|
|
|
19603
19803
|
if (!options.quiet) {
|
|
19604
19804
|
console.log("\u{1F916} Starting X CLI Conversational Assistant...\n");
|
|
19605
19805
|
}
|
|
19806
|
+
if (!options.quiet) {
|
|
19807
|
+
try {
|
|
19808
|
+
const contextPack = loadContext();
|
|
19809
|
+
const statusMessage = formatContextStatus(contextPack);
|
|
19810
|
+
console.log(statusMessage);
|
|
19811
|
+
} catch (error) {
|
|
19812
|
+
console.warn("\u26A0\uFE0F Failed to load .agent/ context:", error instanceof Error ? error.message : String(error));
|
|
19813
|
+
}
|
|
19814
|
+
}
|
|
19606
19815
|
ensureUserSettingsDirectory();
|
|
19607
19816
|
checkAutoCompact();
|
|
19608
19817
|
checkStartupUpdates();
|