@taj-special/dravix-code 1.1.24 → 1.1.26
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/repl.js +60 -15
- package/package.json +1 -1
package/dist/cli/repl.js
CHANGED
|
@@ -2117,9 +2117,34 @@ export async function startRepl(cwd) {
|
|
|
2117
2117
|
}
|
|
2118
2118
|
// activeCwd can change when /resume loads a conversation from a different directory
|
|
2119
2119
|
let activeCwd = cwd;
|
|
2120
|
+
// Rules appended to every system prompt to enforce safe file-operation behavior
|
|
2121
|
+
const SAFE_FILE_RULES = `
|
|
2122
|
+
|
|
2123
|
+
## CRITICAL RULES — Follow these on every response
|
|
2124
|
+
|
|
2125
|
+
### Creating files
|
|
2126
|
+
- NEVER show code in code blocks when the user asks to create files or a project.
|
|
2127
|
+
- ALWAYS use <write_file path="filename"> tags to create actual files.
|
|
2128
|
+
- Code blocks are for short explanations only — they do NOT create files.
|
|
2129
|
+
- Output ALL required files in ONE response using <write_file> tags.
|
|
2130
|
+
|
|
2131
|
+
### File operations
|
|
2132
|
+
- **write_file** = CREATE only. Use it ONLY when a file does NOT exist yet.
|
|
2133
|
+
- **edit_file** = MODIFY existing files. For ANY change to an existing file, always use edit_file with <find>/<replace>.
|
|
2134
|
+
- Before editing any file: use <read_file> to see its current content first.
|
|
2135
|
+
- NEVER overwrite an existing file with write_file — it destroys user code.
|
|
2136
|
+
|
|
2137
|
+
### Scope
|
|
2138
|
+
- Only touch files the user explicitly mentioned or that are clearly required by the task.
|
|
2139
|
+
- If the user says "create X" and X already exists: STOP and ask — "I see X already exists at [path]. Do you want me to (a) modify it, or (b) create a new file?"
|
|
2140
|
+
- Do NOT restructure, rename, or "improve" anything that wasn't asked.
|
|
2141
|
+
|
|
2142
|
+
### When unsure
|
|
2143
|
+
- Ask ONE short clarifying question before writing any code.
|
|
2144
|
+
- Better to ask than to guess wrong and destroy existing work.`;
|
|
2120
2145
|
const buildSystemMsg = (dir) => ({
|
|
2121
2146
|
role: 'system',
|
|
2122
|
-
content: SYSTEM_PROMPT + '\n\nProject context:\n' + buildContext(dir),
|
|
2147
|
+
content: SYSTEM_PROMPT + SAFE_FILE_RULES + '\n\nProject context:\n' + buildContext(dir),
|
|
2123
2148
|
});
|
|
2124
2149
|
const history = [buildSystemMsg(activeCwd)];
|
|
2125
2150
|
let sessionId = generateId();
|
|
@@ -2196,8 +2221,8 @@ export async function startRepl(cwd) {
|
|
|
2196
2221
|
userReminder = `The user's request: "${display}". `;
|
|
2197
2222
|
}
|
|
2198
2223
|
const taskInstruction = userReminder
|
|
2199
|
-
? `The user's exact request was: "${rawUserMsg.slice(0, 300)}"\nNow execute THIS request and ONLY this request — nothing else. Do not invent, add, or change anything the user did not ask for. Use the file content above to find the exact text and apply the change.`
|
|
2200
|
-
: `Execute the user's request using the file content above.`;
|
|
2224
|
+
? `The user's exact request was: "${rawUserMsg.slice(0, 300)}"\nNow execute THIS request and ONLY this request — nothing else. Do not invent, add, or change anything the user did not ask for. Use <edit_file> with targeted <find>/<replace> — never use <write_file> on existing files. Use the file content above to find the exact text and apply the change.`
|
|
2225
|
+
: `Execute the user's request using the file content above. Use <edit_file> for existing files, <write_file> only for new files.`;
|
|
2201
2226
|
// Keep using FLASH_MODEL after file reads
|
|
2202
2227
|
if (readFileTurnCount > 5 && !forcedEditMode) {
|
|
2203
2228
|
forcedEditMode = true;
|
|
@@ -2435,6 +2460,16 @@ export async function startRepl(cwd) {
|
|
|
2435
2460
|
executedInlineOps.add(inlineOpFingerprint(op));
|
|
2436
2461
|
}
|
|
2437
2462
|
else {
|
|
2463
|
+
// Track existing file size to detect write_file overwrites of existing code
|
|
2464
|
+
let existingLineCount = 0;
|
|
2465
|
+
if (op.type === 'write' && op.path) {
|
|
2466
|
+
try {
|
|
2467
|
+
const fp = path.resolve(activeCwd, op.path);
|
|
2468
|
+
if (fs.existsSync(fp))
|
|
2469
|
+
existingLineCount = fs.readFileSync(fp, 'utf-8').split('\n').length;
|
|
2470
|
+
}
|
|
2471
|
+
catch { /* ignore */ }
|
|
2472
|
+
}
|
|
2438
2473
|
const previewLines = (op.type === 'write' || op.type === 'edit') ? printDiffPreview(op, activeCwd) : 0;
|
|
2439
2474
|
const allowed = await askPermission(label, key, alwaysAllowed, op.type === 'run', previewLines > 0, previewLines);
|
|
2440
2475
|
executedInlineOps.add(inlineOpFingerprint(op));
|
|
@@ -2510,11 +2545,17 @@ export async function startRepl(cwd) {
|
|
|
2510
2545
|
else if ((opResult.type === 'modified' || opResult.type === 'created') && op.path &&
|
|
2511
2546
|
(op.type === 'edit' || op.type === 'write')) {
|
|
2512
2547
|
// After a successful edit, inject a note so AI knows the file changed
|
|
2513
|
-
// This prevents subsequent <edit_file> ops from using stale <find> text
|
|
2514
2548
|
history.push({
|
|
2515
2549
|
role: 'system',
|
|
2516
|
-
content: `[File updated] ${op.path} was just modified
|
|
2550
|
+
content: `[File updated] ${op.path} was just modified. For further edits to this file, use <read_file path="${op.path}"/> first to get the current content, then <edit_file> with targeted changes.`,
|
|
2517
2551
|
});
|
|
2552
|
+
// Educate AI when it used write_file to overwrite a non-trivial existing file
|
|
2553
|
+
if (op.type === 'write' && opResult.type === 'modified' && existingLineCount > 20) {
|
|
2554
|
+
history.push({
|
|
2555
|
+
role: 'system',
|
|
2556
|
+
content: `[Rule] You used <write_file> to completely replace ${op.path} (${existingLineCount} lines of existing code). This is wrong. RULE: write_file is ONLY for creating new files. For existing files, always use <edit_file> with <find>/<replace> to make targeted changes. Never overwrite existing code with write_file.`,
|
|
2557
|
+
});
|
|
2558
|
+
}
|
|
2518
2559
|
}
|
|
2519
2560
|
}
|
|
2520
2561
|
}
|
|
@@ -2738,24 +2779,28 @@ export async function startRepl(cwd) {
|
|
|
2738
2779
|
}
|
|
2739
2780
|
const allOps = parseOps(normalized);
|
|
2740
2781
|
// ── Detect incomplete plan: AI described steps but didn't output tags ──
|
|
2741
|
-
// Pattern: response has numbered items like "2. something" or "3. something"
|
|
2742
|
-
// but very few actual file operation tags were output → force continuation
|
|
2743
2782
|
if (!readFileContinue && !streamCancelled) {
|
|
2744
2783
|
const hasAnyReadOp = allOps.some(op => op.type === 'read_file' || op.type === 'read_folder' || op.type === 'search_code');
|
|
2745
2784
|
const writeOps = allOps.filter(op => op.type !== 'read_file' && op.type !== 'read_folder' && op.type !== 'search_code').length;
|
|
2746
2785
|
const plannedSteps = (normalized.match(/^\s*[2-9]\.\s+\S/mg) ?? []).length;
|
|
2747
|
-
|
|
2786
|
+
const hasCodeFence = normalized.includes('```');
|
|
2787
|
+
const hasStepList = (normalized.match(/^\s*\d+[.)]\s+\S/mg) ?? []).length >= 2;
|
|
2788
|
+
// Case 1: AI listed numbered steps (2+) but produced zero file ops
|
|
2748
2789
|
if (plannedSteps >= 1 && writeOps === 0 && !hasAnyReadOp) {
|
|
2749
|
-
history.push({ role: 'system', content: 'You described
|
|
2790
|
+
history.push({ role: 'system', content: 'CRITICAL ERROR: You described steps but produced NO file operation tags. You MUST output <write_file> or <edit_file> tags to create/modify actual files. Do NOT show code in ``` blocks — use <write_file path="filename"> tags instead. Output all the tags NOW. No explanation.' });
|
|
2791
|
+
readFileContinue = true;
|
|
2792
|
+
// Case 2: AI showed code blocks + numbered list but no tags — regardless of language
|
|
2793
|
+
}
|
|
2794
|
+
else if (hasCodeFence && hasStepList && writeOps === 0 && allOps.length === 0) {
|
|
2795
|
+
history.push({ role: 'system', content: 'CRITICAL ERROR: You are showing code in ``` blocks instead of using <write_file> tags. This is wrong. ``` blocks do NOT create files — only <write_file> tags create files. Replace every ``` code block with a <write_file path="filename"> tag and output ALL files now.' });
|
|
2750
2796
|
readFileContinue = true;
|
|
2751
|
-
//
|
|
2797
|
+
// Case 3: Long response with code blocks but zero file ops — catch any language
|
|
2752
2798
|
}
|
|
2753
|
-
else if (writeOps === 0 && allOps.length === 0 && normalized.trim().length >
|
|
2754
|
-
const hasCodeFence = normalized.includes('```');
|
|
2755
|
-
const hasStepList = (normalized.match(/^\s*\d+[.)]\s+\S/mg) ?? []).length >= 2;
|
|
2799
|
+
else if (hasCodeFence && writeOps === 0 && allOps.length === 0 && normalized.trim().length > 400) {
|
|
2756
2800
|
const hasWouldNeed = /(?:should|would need to|need to|you(?:'d)? need to|we(?:'d)? need to)\s+(?:edit|modify|update|change|create|add|remove)/i.test(normalized);
|
|
2757
|
-
|
|
2758
|
-
|
|
2801
|
+
const looksLikeFileDump = normalized.split('```').length > 3; // 2+ code blocks
|
|
2802
|
+
if (hasWouldNeed || looksLikeFileDump) {
|
|
2803
|
+
history.push({ role: 'system', content: 'CRITICAL ERROR: You showed code in ``` blocks instead of using <write_file> tags. ``` blocks are for explanations only — they do NOT create actual files. Output all files using <write_file path="..."> tags RIGHT NOW. No text, no explanation — only tags.' });
|
|
2759
2804
|
readFileContinue = true;
|
|
2760
2805
|
}
|
|
2761
2806
|
}
|