codesavant 1.1.0 → 1.2.0
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 +142 -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
|
// ============================================================
|
|
@@ -5584,7 +5641,39 @@ Format the findings clearly for the user. Include:
|
|
|
5584
5641
|
- Ignoring subagent output and exploring from scratch
|
|
5585
5642
|
- Continuing without specific focus areas
|
|
5586
5643
|
- Exceeding 3 continuation rounds
|
|
5587
|
-
- Passing vague instructions like "explore more"
|
|
5644
|
+
- Passing vague instructions like "explore more"
|
|
5645
|
+
|
|
5646
|
+
## Project Creation Guide
|
|
5647
|
+
|
|
5648
|
+
When creating new projects, use these proven commands for each framework:
|
|
5649
|
+
|
|
5650
|
+
### React Projects
|
|
5651
|
+
- **Vite + React + TypeScript** (RECOMMENDED): \`npm create vite@latest my-app -- --template react-ts\`
|
|
5652
|
+
- **Create React App**: \`npx create-react-app my-app --template typescript\`
|
|
5653
|
+
|
|
5654
|
+
### Next.js Projects
|
|
5655
|
+
- \`npx create-next-app@latest my-app --typescript --tailwind --eslint --app --src-dir\`
|
|
5656
|
+
|
|
5657
|
+
### Vue Projects
|
|
5658
|
+
- **Vite + Vue**: \`npm create vite@latest my-app -- --template vue-ts\`
|
|
5659
|
+
- **Vue CLI**: \`npx @vue/cli create my-app\`
|
|
5660
|
+
|
|
5661
|
+
### Adding Tailwind CSS
|
|
5662
|
+
After project creation, install Tailwind:
|
|
5663
|
+
\`\`\`bash
|
|
5664
|
+
npm install -D tailwindcss postcss autoprefixer
|
|
5665
|
+
npx tailwindcss init -p
|
|
5666
|
+
\`\`\`
|
|
5667
|
+
|
|
5668
|
+
Then configure tailwind.config.js and add Tailwind directives to CSS.
|
|
5669
|
+
|
|
5670
|
+
### Project Creation Rules
|
|
5671
|
+
1. ALWAYS create projects in the current working directory or a subdirectory
|
|
5672
|
+
2. NEVER use /tmp or system directories for project creation
|
|
5673
|
+
3. Use the --template flag with Vite for TypeScript support
|
|
5674
|
+
4. Run \`npm install\` after project creation if it fails during setup
|
|
5675
|
+
5. If npm install fails, try: \`npm cache clean --force\` then retry
|
|
5676
|
+
6. Check package.json exists before running npm commands`;
|
|
5588
5677
|
async function loadConfig() {
|
|
5589
5678
|
const configPath = path.join(os.homedir(), ".codesavant", "config.json");
|
|
5590
5679
|
let fileConfig = {};
|
|
@@ -15631,6 +15720,20 @@ function validateWritePath(filePath, baseDir) {
|
|
|
15631
15720
|
// src/tools/executor.ts
|
|
15632
15721
|
var execAsync2 = promisify2(exec2);
|
|
15633
15722
|
var executorConfig = null;
|
|
15723
|
+
function checkPathGuidance(targetPath) {
|
|
15724
|
+
const cwd = process.cwd();
|
|
15725
|
+
const absolutePath = path9.isAbsolute(targetPath) ? targetPath : path9.resolve(cwd, targetPath);
|
|
15726
|
+
const unexpectedPaths = ["/tmp", "/var/tmp", "/temp", "/var/folders"];
|
|
15727
|
+
for (const unexpectedPath of unexpectedPaths) {
|
|
15728
|
+
if (absolutePath.startsWith(unexpectedPath)) {
|
|
15729
|
+
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.`;
|
|
15730
|
+
}
|
|
15731
|
+
}
|
|
15732
|
+
if (!absolutePath.startsWith(cwd) && !absolutePath.startsWith(path9.resolve(cwd))) {
|
|
15733
|
+
return `[PATH NOTE]: Writing to ${absolutePath} which is outside your working directory (${cwd}). This is allowed, but make sure this is intentional.`;
|
|
15734
|
+
}
|
|
15735
|
+
return null;
|
|
15736
|
+
}
|
|
15634
15737
|
var subagentFindingsCache = /* @__PURE__ */ new Map();
|
|
15635
15738
|
function getTaskKey(task) {
|
|
15636
15739
|
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 +16118,20 @@ async function writeFile(input) {
|
|
|
16015
16118
|
error: `Path validation failed: ${pathValidation.reason}`
|
|
16016
16119
|
};
|
|
16017
16120
|
}
|
|
16121
|
+
const pathGuidance = checkPathGuidance(filePath);
|
|
16018
16122
|
const absolutePath = path9.resolve(filePath);
|
|
16019
16123
|
await checkpointManager.backupFileBeforeWrite(absolutePath);
|
|
16020
16124
|
await fs10.ensureDir(path9.dirname(absolutePath));
|
|
16021
16125
|
await fs10.writeFile(absolutePath, content);
|
|
16126
|
+
let output = `Wrote ${content.length} bytes to ${filePath}`;
|
|
16127
|
+
if (pathGuidance) {
|
|
16128
|
+
output += `
|
|
16129
|
+
|
|
16130
|
+
${pathGuidance}`;
|
|
16131
|
+
}
|
|
16022
16132
|
return {
|
|
16023
16133
|
success: true,
|
|
16024
|
-
output
|
|
16134
|
+
output
|
|
16025
16135
|
};
|
|
16026
16136
|
}
|
|
16027
16137
|
async function editFile(input) {
|
|
@@ -30020,7 +30130,7 @@ function InputBoxView({
|
|
|
30020
30130
|
] }),
|
|
30021
30131
|
/* @__PURE__ */ jsx4(Text4, { color: colors.primary, children: "Ctrl+C" }),
|
|
30022
30132
|
/* @__PURE__ */ jsx4(Text4, { color: colors.muted, children: " cancel" }),
|
|
30023
|
-
|
|
30133
|
+
currentPermissionMode && /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
30024
30134
|
/* @__PURE__ */ jsxs4(Text4, { color: colors.muted, children: [
|
|
30025
30135
|
" ",
|
|
30026
30136
|
icons.boxV,
|
|
@@ -30028,7 +30138,7 @@ function InputBoxView({
|
|
|
30028
30138
|
] }),
|
|
30029
30139
|
/* @__PURE__ */ jsxs4(Text4, { color: colors.info, children: [
|
|
30030
30140
|
"[",
|
|
30031
|
-
|
|
30141
|
+
currentPermissionMode,
|
|
30032
30142
|
"]"
|
|
30033
30143
|
] })
|
|
30034
30144
|
] })
|
|
@@ -30061,6 +30171,7 @@ function App({
|
|
|
30061
30171
|
const lastEscapeRef = useRef(0);
|
|
30062
30172
|
const [renderedMessageCount, setRenderedMessageCount] = useState5(0);
|
|
30063
30173
|
const permissionModes = ["prompt", "auto-edit", "auto-full", "deny"];
|
|
30174
|
+
const [currentPermissionMode2, setCurrentPermissionMode] = useState5(permissionMode);
|
|
30064
30175
|
useEffect2(() => {
|
|
30065
30176
|
if (sessionId2) actions.setSessionId(sessionId2);
|
|
30066
30177
|
if (provider && model) actions.setProvider(provider, model);
|
|
@@ -30139,11 +30250,14 @@ function App({
|
|
|
30139
30250
|
setHistorySearchMatch(null);
|
|
30140
30251
|
return;
|
|
30141
30252
|
}
|
|
30142
|
-
if (key.shift && key.tab
|
|
30143
|
-
const currentIndex = permissionModes.indexOf(
|
|
30253
|
+
if (key.shift && key.tab) {
|
|
30254
|
+
const currentIndex = permissionModes.indexOf(currentPermissionMode2);
|
|
30144
30255
|
const nextIndex = (currentIndex + 1) % permissionModes.length;
|
|
30145
30256
|
const nextMode = permissionModes[nextIndex];
|
|
30146
|
-
|
|
30257
|
+
setCurrentPermissionMode(nextMode);
|
|
30258
|
+
if (onPermissionModeChange) {
|
|
30259
|
+
onPermissionModeChange(nextMode);
|
|
30260
|
+
}
|
|
30147
30261
|
actions.addMessage({
|
|
30148
30262
|
type: "system",
|
|
30149
30263
|
content: `Permission mode: ${nextMode}`
|
|
@@ -30311,7 +30425,7 @@ function App({
|
|
|
30311
30425
|
historyIndex: state.historyIndex,
|
|
30312
30426
|
onHistoryNavigate: handleHistoryNavigate,
|
|
30313
30427
|
theme,
|
|
30314
|
-
permissionMode,
|
|
30428
|
+
permissionMode: currentPermissionMode2,
|
|
30315
30429
|
historySearchMode,
|
|
30316
30430
|
historySearchQuery,
|
|
30317
30431
|
historySearchMatch,
|
|
@@ -30578,22 +30692,18 @@ function createInkREPL(replConfig) {
|
|
|
30578
30692
|
}
|
|
30579
30693
|
case "glob": {
|
|
30580
30694
|
const pattern = toolInput?.pattern || "*";
|
|
30581
|
-
const
|
|
30582
|
-
|
|
30583
|
-
matchCount,
|
|
30584
|
-
pattern,
|
|
30585
|
-
preview: output.slice(0, 300)
|
|
30586
|
-
};
|
|
30587
|
-
return formatGlobResult(result, { collapsed: true });
|
|
30695
|
+
const files = output ? output.split("\n").filter((l) => l.trim()) : [];
|
|
30696
|
+
return formatGlobResult(files, pattern, { collapsed: true });
|
|
30588
30697
|
}
|
|
30589
30698
|
case "bash": {
|
|
30699
|
+
const command = toolInput?.command || "bash command";
|
|
30590
30700
|
const result = {
|
|
30591
30701
|
exitCode: success ? 0 : 1,
|
|
30592
30702
|
output: output.slice(0, 500),
|
|
30593
30703
|
truncated: output.length > 500,
|
|
30594
30704
|
totalLines: lineCount
|
|
30595
30705
|
};
|
|
30596
|
-
return formatBashResult(result, { collapsed: true });
|
|
30706
|
+
return formatBashResult(result, command, { collapsed: true });
|
|
30597
30707
|
}
|
|
30598
30708
|
default:
|
|
30599
30709
|
if (success) {
|
|
@@ -31880,13 +31990,13 @@ Type /help for available commands.`);
|
|
|
31880
31990
|
mcpTools: mcpToolCount,
|
|
31881
31991
|
workingDir: projectPath
|
|
31882
31992
|
});
|
|
31883
|
-
let
|
|
31993
|
+
let currentPermissionMode2 = agent.getPermissionManager().getMode();
|
|
31884
31994
|
appController = renderApp({
|
|
31885
31995
|
sessionId: sessionId2,
|
|
31886
31996
|
provider: defaultProvider?.name,
|
|
31887
31997
|
model: defaultProvider?.model,
|
|
31888
31998
|
welcomeMessage,
|
|
31889
|
-
permissionMode:
|
|
31999
|
+
permissionMode: currentPermissionMode2,
|
|
31890
32000
|
onSubmit: (input) => {
|
|
31891
32001
|
if (!isProcessing) {
|
|
31892
32002
|
processAgentStream(input);
|
|
@@ -31922,7 +32032,7 @@ Type /help for available commands.`);
|
|
|
31922
32032
|
const validModes = ["prompt", "auto-edit", "auto-full", "deny"];
|
|
31923
32033
|
if (validModes.includes(mode)) {
|
|
31924
32034
|
agent.getPermissionManager().setMode(mode);
|
|
31925
|
-
|
|
32035
|
+
currentPermissionMode2 = mode;
|
|
31926
32036
|
}
|
|
31927
32037
|
}
|
|
31928
32038
|
});
|
|
@@ -32374,6 +32484,19 @@ program.argument("[prompt]", "Initial prompt to send").option("-p, --print", "Pr
|
|
|
32374
32484
|
systemPrompt += "\n\n" + options.appendSystemPrompt;
|
|
32375
32485
|
}
|
|
32376
32486
|
}
|
|
32487
|
+
const workingDirContext = `
|
|
32488
|
+
## Working Directory Context
|
|
32489
|
+
|
|
32490
|
+
**IMPORTANT**: Your current working directory is: ${projectPath}
|
|
32491
|
+
|
|
32492
|
+
When the user asks to create projects, files, or directories:
|
|
32493
|
+
- ALWAYS create them in or relative to this working directory (${projectPath})
|
|
32494
|
+
- Do NOT use /tmp or other system directories unless explicitly requested
|
|
32495
|
+
- Use relative paths when possible (e.g., "./my-project" instead of absolute paths)
|
|
32496
|
+
- If the user specifies a path, resolve it relative to the working directory
|
|
32497
|
+
|
|
32498
|
+
All file operations (read, write, edit, bash) execute in this directory by default.`;
|
|
32499
|
+
systemPrompt += workingDirContext;
|
|
32377
32500
|
const allowedTools = options.allowedTools ? options.allowedTools.split(",").map((t) => t.trim()) : void 0;
|
|
32378
32501
|
const disallowedTools = options.disallowedTools ? options.disallowedTools.split(",").map((t) => t.trim()) : void 0;
|
|
32379
32502
|
const maxTurns = options.maxTurns ? parseInt(options.maxTurns, 10) : void 0;
|