codesavant 1.1.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +150 -19
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -371,6 +371,63 @@ var init_knowledge_base = __esm({
|
|
|
371
371
|
],
|
|
372
372
|
priority: 85
|
|
373
373
|
},
|
|
374
|
+
{
|
|
375
|
+
id: "npm-network-error",
|
|
376
|
+
pattern: /npm ERR!.*network|ETIMEDOUT|ECONNREFUSED|ENOTFOUND.*registry|fetch failed/i,
|
|
377
|
+
category: "dependency",
|
|
378
|
+
subcategory: "network",
|
|
379
|
+
diagnosis: "npm network error. Cannot connect to the npm registry.",
|
|
380
|
+
suggestions: [
|
|
381
|
+
"Check your internet connection",
|
|
382
|
+
"Verify npm registry: npm config get registry",
|
|
383
|
+
"Try: npm config set registry https://registry.npmjs.org/",
|
|
384
|
+
"Check if behind a proxy and configure npm accordingly",
|
|
385
|
+
"Wait a moment and retry - registry may be temporarily unavailable"
|
|
386
|
+
],
|
|
387
|
+
priority: 90
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
id: "npm-invalid-package-json",
|
|
391
|
+
pattern: /npm ERR!.*package\.json|Invalid package\.json|unexpected end of JSON|Unexpected token.*package\.json/i,
|
|
392
|
+
category: "dependency",
|
|
393
|
+
subcategory: "config",
|
|
394
|
+
diagnosis: "Invalid package.json file. The file contains syntax errors or is malformed.",
|
|
395
|
+
suggestions: [
|
|
396
|
+
"Validate package.json syntax at https://jsonlint.com/",
|
|
397
|
+
"Check for trailing commas, missing quotes, or incorrect brackets",
|
|
398
|
+
"Recreate package.json: npm init -y"
|
|
399
|
+
],
|
|
400
|
+
priority: 95
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
id: "npx-package-not-found",
|
|
404
|
+
pattern: /npx.*command not found|npm ERR! could not determine executable|create-.*not found/i,
|
|
405
|
+
category: "dependency",
|
|
406
|
+
subcategory: "missing_package",
|
|
407
|
+
diagnosis: "npx could not find the package to execute.",
|
|
408
|
+
suggestions: [
|
|
409
|
+
"Check the package name is correct",
|
|
410
|
+
"Try installing globally first: npm install -g {package}",
|
|
411
|
+
"Clear npx cache: npx clear-npx-cache",
|
|
412
|
+
"Ensure npm is up to date: npm install -g npm"
|
|
413
|
+
],
|
|
414
|
+
priority: 85
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
id: "create-app-failed",
|
|
418
|
+
pattern: /create-react-app.*failed|create-next-app.*failed|vite.*create.*failed|project.*creation.*failed/i,
|
|
419
|
+
category: "dependency",
|
|
420
|
+
subcategory: "project_creation",
|
|
421
|
+
diagnosis: "Project scaffolding failed. The project creation tool encountered an error.",
|
|
422
|
+
suggestions: [
|
|
423
|
+
"Try with a different directory name (avoid special characters)",
|
|
424
|
+
"Ensure you have write permissions in the target directory",
|
|
425
|
+
"Clear npm cache: npm cache clean --force",
|
|
426
|
+
"Check if Node.js version is compatible with the framework",
|
|
427
|
+
"Try creating in current directory: npx create-{tool}@latest ."
|
|
428
|
+
],
|
|
429
|
+
priority: 92
|
|
430
|
+
},
|
|
374
431
|
// ============================================================
|
|
375
432
|
// GIT ERRORS (8 patterns)
|
|
376
433
|
// ============================================================
|
|
@@ -5398,6 +5455,9 @@ var init_commands = __esm({
|
|
|
5398
5455
|
// src/cli.ts
|
|
5399
5456
|
import { Command } from "commander";
|
|
5400
5457
|
import chalk20 from "chalk";
|
|
5458
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
5459
|
+
import { fileURLToPath } from "url";
|
|
5460
|
+
import { dirname, join as join3 } from "path";
|
|
5401
5461
|
|
|
5402
5462
|
// src/config.ts
|
|
5403
5463
|
import fs from "fs-extra";
|
|
@@ -5584,7 +5644,39 @@ Format the findings clearly for the user. Include:
|
|
|
5584
5644
|
- Ignoring subagent output and exploring from scratch
|
|
5585
5645
|
- Continuing without specific focus areas
|
|
5586
5646
|
- Exceeding 3 continuation rounds
|
|
5587
|
-
- Passing vague instructions like "explore more"
|
|
5647
|
+
- Passing vague instructions like "explore more"
|
|
5648
|
+
|
|
5649
|
+
## Project Creation Guide
|
|
5650
|
+
|
|
5651
|
+
When creating new projects, use these proven commands for each framework:
|
|
5652
|
+
|
|
5653
|
+
### React Projects
|
|
5654
|
+
- **Vite + React + TypeScript** (RECOMMENDED): \`npm create vite@latest my-app -- --template react-ts\`
|
|
5655
|
+
- **Create React App**: \`npx create-react-app my-app --template typescript\`
|
|
5656
|
+
|
|
5657
|
+
### Next.js Projects
|
|
5658
|
+
- \`npx create-next-app@latest my-app --typescript --tailwind --eslint --app --src-dir\`
|
|
5659
|
+
|
|
5660
|
+
### Vue Projects
|
|
5661
|
+
- **Vite + Vue**: \`npm create vite@latest my-app -- --template vue-ts\`
|
|
5662
|
+
- **Vue CLI**: \`npx @vue/cli create my-app\`
|
|
5663
|
+
|
|
5664
|
+
### Adding Tailwind CSS
|
|
5665
|
+
After project creation, install Tailwind:
|
|
5666
|
+
\`\`\`bash
|
|
5667
|
+
npm install -D tailwindcss postcss autoprefixer
|
|
5668
|
+
npx tailwindcss init -p
|
|
5669
|
+
\`\`\`
|
|
5670
|
+
|
|
5671
|
+
Then configure tailwind.config.js and add Tailwind directives to CSS.
|
|
5672
|
+
|
|
5673
|
+
### Project Creation Rules
|
|
5674
|
+
1. ALWAYS create projects in the current working directory or a subdirectory
|
|
5675
|
+
2. NEVER use /tmp or system directories for project creation
|
|
5676
|
+
3. Use the --template flag with Vite for TypeScript support
|
|
5677
|
+
4. Run \`npm install\` after project creation if it fails during setup
|
|
5678
|
+
5. If npm install fails, try: \`npm cache clean --force\` then retry
|
|
5679
|
+
6. Check package.json exists before running npm commands`;
|
|
5588
5680
|
async function loadConfig() {
|
|
5589
5681
|
const configPath = path.join(os.homedir(), ".codesavant", "config.json");
|
|
5590
5682
|
let fileConfig = {};
|
|
@@ -15631,6 +15723,20 @@ function validateWritePath(filePath, baseDir) {
|
|
|
15631
15723
|
// src/tools/executor.ts
|
|
15632
15724
|
var execAsync2 = promisify2(exec2);
|
|
15633
15725
|
var executorConfig = null;
|
|
15726
|
+
function checkPathGuidance(targetPath) {
|
|
15727
|
+
const cwd = process.cwd();
|
|
15728
|
+
const absolutePath = path9.isAbsolute(targetPath) ? targetPath : path9.resolve(cwd, targetPath);
|
|
15729
|
+
const unexpectedPaths = ["/tmp", "/var/tmp", "/temp", "/var/folders"];
|
|
15730
|
+
for (const unexpectedPath of unexpectedPaths) {
|
|
15731
|
+
if (absolutePath.startsWith(unexpectedPath)) {
|
|
15732
|
+
return `[PATH GUIDANCE]: You're writing to ${absolutePath} which is a temporary directory. Your working directory is ${cwd}. If you intended to create files in the project, use a relative path like "./" or specify the full path within ${cwd}. Files in /tmp may be deleted on system restart.`;
|
|
15733
|
+
}
|
|
15734
|
+
}
|
|
15735
|
+
if (!absolutePath.startsWith(cwd) && !absolutePath.startsWith(path9.resolve(cwd))) {
|
|
15736
|
+
return `[PATH NOTE]: Writing to ${absolutePath} which is outside your working directory (${cwd}). This is allowed, but make sure this is intentional.`;
|
|
15737
|
+
}
|
|
15738
|
+
return null;
|
|
15739
|
+
}
|
|
15634
15740
|
var subagentFindingsCache = /* @__PURE__ */ new Map();
|
|
15635
15741
|
function getTaskKey(task) {
|
|
15636
15742
|
const baseTask = task.replace(/CONTINUATION \(Round \d+ of \d+\)/gi, "").replace(/## Previous Findings[\s\S]*?(?=##|$)/gi, "").replace(/## Focus Areas[\s\S]*?(?=##|$)/gi, "").trim().slice(0, 100);
|
|
@@ -16015,13 +16121,20 @@ async function writeFile(input) {
|
|
|
16015
16121
|
error: `Path validation failed: ${pathValidation.reason}`
|
|
16016
16122
|
};
|
|
16017
16123
|
}
|
|
16124
|
+
const pathGuidance = checkPathGuidance(filePath);
|
|
16018
16125
|
const absolutePath = path9.resolve(filePath);
|
|
16019
16126
|
await checkpointManager.backupFileBeforeWrite(absolutePath);
|
|
16020
16127
|
await fs10.ensureDir(path9.dirname(absolutePath));
|
|
16021
16128
|
await fs10.writeFile(absolutePath, content);
|
|
16129
|
+
let output = `Wrote ${content.length} bytes to ${filePath}`;
|
|
16130
|
+
if (pathGuidance) {
|
|
16131
|
+
output += `
|
|
16132
|
+
|
|
16133
|
+
${pathGuidance}`;
|
|
16134
|
+
}
|
|
16022
16135
|
return {
|
|
16023
16136
|
success: true,
|
|
16024
|
-
output
|
|
16137
|
+
output
|
|
16025
16138
|
};
|
|
16026
16139
|
}
|
|
16027
16140
|
async function editFile(input) {
|
|
@@ -30061,6 +30174,7 @@ function App({
|
|
|
30061
30174
|
const lastEscapeRef = useRef(0);
|
|
30062
30175
|
const [renderedMessageCount, setRenderedMessageCount] = useState5(0);
|
|
30063
30176
|
const permissionModes = ["prompt", "auto-edit", "auto-full", "deny"];
|
|
30177
|
+
const [currentPermissionMode, setCurrentPermissionMode] = useState5(permissionMode);
|
|
30064
30178
|
useEffect2(() => {
|
|
30065
30179
|
if (sessionId2) actions.setSessionId(sessionId2);
|
|
30066
30180
|
if (provider && model) actions.setProvider(provider, model);
|
|
@@ -30139,11 +30253,14 @@ function App({
|
|
|
30139
30253
|
setHistorySearchMatch(null);
|
|
30140
30254
|
return;
|
|
30141
30255
|
}
|
|
30142
|
-
if (key.shift && key.tab
|
|
30143
|
-
const currentIndex = permissionModes.indexOf(
|
|
30256
|
+
if (key.shift && key.tab) {
|
|
30257
|
+
const currentIndex = permissionModes.indexOf(currentPermissionMode);
|
|
30144
30258
|
const nextIndex = (currentIndex + 1) % permissionModes.length;
|
|
30145
30259
|
const nextMode = permissionModes[nextIndex];
|
|
30146
|
-
|
|
30260
|
+
setCurrentPermissionMode(nextMode);
|
|
30261
|
+
if (onPermissionModeChange) {
|
|
30262
|
+
onPermissionModeChange(nextMode);
|
|
30263
|
+
}
|
|
30147
30264
|
actions.addMessage({
|
|
30148
30265
|
type: "system",
|
|
30149
30266
|
content: `Permission mode: ${nextMode}`
|
|
@@ -30311,7 +30428,7 @@ function App({
|
|
|
30311
30428
|
historyIndex: state.historyIndex,
|
|
30312
30429
|
onHistoryNavigate: handleHistoryNavigate,
|
|
30313
30430
|
theme,
|
|
30314
|
-
permissionMode,
|
|
30431
|
+
permissionMode: currentPermissionMode,
|
|
30315
30432
|
historySearchMode,
|
|
30316
30433
|
historySearchQuery,
|
|
30317
30434
|
historySearchMatch,
|
|
@@ -30578,22 +30695,18 @@ function createInkREPL(replConfig) {
|
|
|
30578
30695
|
}
|
|
30579
30696
|
case "glob": {
|
|
30580
30697
|
const pattern = toolInput?.pattern || "*";
|
|
30581
|
-
const
|
|
30582
|
-
|
|
30583
|
-
matchCount,
|
|
30584
|
-
pattern,
|
|
30585
|
-
preview: output.slice(0, 300)
|
|
30586
|
-
};
|
|
30587
|
-
return formatGlobResult(result, { collapsed: true });
|
|
30698
|
+
const files = output ? output.split("\n").filter((l) => l.trim()) : [];
|
|
30699
|
+
return formatGlobResult(files, pattern, { collapsed: true });
|
|
30588
30700
|
}
|
|
30589
30701
|
case "bash": {
|
|
30702
|
+
const command = toolInput?.command || "bash command";
|
|
30590
30703
|
const result = {
|
|
30591
30704
|
exitCode: success ? 0 : 1,
|
|
30592
30705
|
output: output.slice(0, 500),
|
|
30593
30706
|
truncated: output.length > 500,
|
|
30594
30707
|
totalLines: lineCount
|
|
30595
30708
|
};
|
|
30596
|
-
return formatBashResult(result, { collapsed: true });
|
|
30709
|
+
return formatBashResult(result, command, { collapsed: true });
|
|
30597
30710
|
}
|
|
30598
30711
|
default:
|
|
30599
30712
|
if (success) {
|
|
@@ -32085,10 +32198,10 @@ async function detectCICommands(projectPath) {
|
|
|
32085
32198
|
const fs26 = await import("fs-extra");
|
|
32086
32199
|
const path27 = await import("path");
|
|
32087
32200
|
const commands = [];
|
|
32088
|
-
const
|
|
32089
|
-
if (await fs26.pathExists(
|
|
32201
|
+
const packageJsonPath2 = path27.join(projectPath, "package.json");
|
|
32202
|
+
if (await fs26.pathExists(packageJsonPath2)) {
|
|
32090
32203
|
try {
|
|
32091
|
-
const pkg = await fs26.readJson(
|
|
32204
|
+
const pkg = await fs26.readJson(packageJsonPath2);
|
|
32092
32205
|
if (pkg.scripts?.build) {
|
|
32093
32206
|
commands.push("npm run build");
|
|
32094
32207
|
}
|
|
@@ -32121,7 +32234,7 @@ async function detectCICommands(projectPath) {
|
|
|
32121
32234
|
if (await fs26.pathExists(path27.join(projectPath, "pyproject.toml")) || await fs26.pathExists(path27.join(projectPath, "setup.py"))) {
|
|
32122
32235
|
commands.push("python -m pytest");
|
|
32123
32236
|
}
|
|
32124
|
-
if (commands.length === 0 && await fs26.pathExists(
|
|
32237
|
+
if (commands.length === 0 && await fs26.pathExists(packageJsonPath2)) {
|
|
32125
32238
|
commands.push("npm run build");
|
|
32126
32239
|
}
|
|
32127
32240
|
return commands;
|
|
@@ -32217,6 +32330,11 @@ Fix all the issues to make the CI pass. Use the available tools to read files, e
|
|
|
32217
32330
|
}
|
|
32218
32331
|
|
|
32219
32332
|
// src/cli.ts
|
|
32333
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
32334
|
+
var __dirname = dirname(__filename);
|
|
32335
|
+
var packageJsonPath = join3(__dirname, "..", "package.json");
|
|
32336
|
+
var packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
|
|
32337
|
+
var VERSION = packageJson.version;
|
|
32220
32338
|
var MAX_STDIN_SIZE = 10 * 1024 * 1024;
|
|
32221
32339
|
var MAX_STDIN_LINES = 1e5;
|
|
32222
32340
|
async function readStdinInput(format, options) {
|
|
@@ -32268,7 +32386,7 @@ async function readStdinInput(format, options) {
|
|
|
32268
32386
|
});
|
|
32269
32387
|
}
|
|
32270
32388
|
var program = new Command();
|
|
32271
|
-
program.name("codesavant").description("AI coding assistant for your terminal").version(
|
|
32389
|
+
program.name("codesavant").description("AI coding assistant for your terminal").version(VERSION).option("--verbose", "Enable verbose logging for debugging").option("--debug <categories>", 'Enable debug logging for specific categories (comma-separated: api,mcp,tool,provider,stream,session,context,permission,checkpoint,error,all). Use ! prefix to exclude: "all,!mcp"').option("--mcp-debug", "Enable MCP protocol-level debug logging").hook("preAction", (thisCommand) => {
|
|
32272
32390
|
const opts = thisCommand.opts();
|
|
32273
32391
|
if (opts.debug) {
|
|
32274
32392
|
setVerbose(true);
|
|
@@ -32374,6 +32492,19 @@ program.argument("[prompt]", "Initial prompt to send").option("-p, --print", "Pr
|
|
|
32374
32492
|
systemPrompt += "\n\n" + options.appendSystemPrompt;
|
|
32375
32493
|
}
|
|
32376
32494
|
}
|
|
32495
|
+
const workingDirContext = `
|
|
32496
|
+
## Working Directory Context
|
|
32497
|
+
|
|
32498
|
+
**IMPORTANT**: Your current working directory is: ${projectPath}
|
|
32499
|
+
|
|
32500
|
+
When the user asks to create projects, files, or directories:
|
|
32501
|
+
- ALWAYS create them in or relative to this working directory (${projectPath})
|
|
32502
|
+
- Do NOT use /tmp or other system directories unless explicitly requested
|
|
32503
|
+
- Use relative paths when possible (e.g., "./my-project" instead of absolute paths)
|
|
32504
|
+
- If the user specifies a path, resolve it relative to the working directory
|
|
32505
|
+
|
|
32506
|
+
All file operations (read, write, edit, bash) execute in this directory by default.`;
|
|
32507
|
+
systemPrompt += workingDirContext;
|
|
32377
32508
|
const allowedTools = options.allowedTools ? options.allowedTools.split(",").map((t) => t.trim()) : void 0;
|
|
32378
32509
|
const disallowedTools = options.disallowedTools ? options.disallowedTools.split(",").map((t) => t.trim()) : void 0;
|
|
32379
32510
|
const maxTurns = options.maxTurns ? parseInt(options.maxTurns, 10) : void 0;
|