@taj-special/dravix-code 1.1.24 → 1.1.25

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.
Files changed (2) hide show
  1. package/dist/cli/repl.js +40 -5
  2. package/package.json +1 -1
package/dist/cli/repl.js CHANGED
@@ -2117,9 +2117,28 @@ 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
+ ### File operations
2126
+ - **write_file** = CREATE only. Use it ONLY when a file does NOT exist yet.
2127
+ - **edit_file** = MODIFY existing files. For ANY change to an existing file, always use edit_file with <find>/<replace>.
2128
+ - Before editing any file: use <read_file> to see its current content first.
2129
+ - NEVER overwrite an existing file with write_file — it destroys user code.
2130
+
2131
+ ### Scope
2132
+ - Only touch files the user explicitly mentioned or that are clearly required by the task.
2133
+ - 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?"
2134
+ - Do NOT restructure, rename, or "improve" anything that wasn't asked.
2135
+
2136
+ ### When unsure
2137
+ - Ask ONE short clarifying question before writing any code.
2138
+ - Better to ask than to guess wrong and destroy existing work.`;
2120
2139
  const buildSystemMsg = (dir) => ({
2121
2140
  role: 'system',
2122
- content: SYSTEM_PROMPT + '\n\nProject context:\n' + buildContext(dir),
2141
+ content: SYSTEM_PROMPT + SAFE_FILE_RULES + '\n\nProject context:\n' + buildContext(dir),
2123
2142
  });
2124
2143
  const history = [buildSystemMsg(activeCwd)];
2125
2144
  let sessionId = generateId();
@@ -2196,8 +2215,8 @@ export async function startRepl(cwd) {
2196
2215
  userReminder = `The user's request: "${display}". `;
2197
2216
  }
2198
2217
  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.`;
2218
+ ? `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.`
2219
+ : `Execute the user's request using the file content above. Use <edit_file> for existing files, <write_file> only for new files.`;
2201
2220
  // Keep using FLASH_MODEL after file reads
2202
2221
  if (readFileTurnCount > 5 && !forcedEditMode) {
2203
2222
  forcedEditMode = true;
@@ -2435,6 +2454,16 @@ export async function startRepl(cwd) {
2435
2454
  executedInlineOps.add(inlineOpFingerprint(op));
2436
2455
  }
2437
2456
  else {
2457
+ // Track existing file size to detect write_file overwrites of existing code
2458
+ let existingLineCount = 0;
2459
+ if (op.type === 'write' && op.path) {
2460
+ try {
2461
+ const fp = path.resolve(activeCwd, op.path);
2462
+ if (fs.existsSync(fp))
2463
+ existingLineCount = fs.readFileSync(fp, 'utf-8').split('\n').length;
2464
+ }
2465
+ catch { /* ignore */ }
2466
+ }
2438
2467
  const previewLines = (op.type === 'write' || op.type === 'edit') ? printDiffPreview(op, activeCwd) : 0;
2439
2468
  const allowed = await askPermission(label, key, alwaysAllowed, op.type === 'run', previewLines > 0, previewLines);
2440
2469
  executedInlineOps.add(inlineOpFingerprint(op));
@@ -2510,11 +2539,17 @@ export async function startRepl(cwd) {
2510
2539
  else if ((opResult.type === 'modified' || opResult.type === 'created') && op.path &&
2511
2540
  (op.type === 'edit' || op.type === 'write')) {
2512
2541
  // 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
2542
  history.push({
2515
2543
  role: 'system',
2516
- content: `[File updated] ${op.path} was just modified by a previous operation in this response. If you have more edits for this file, use <read_file path="${op.path}"/> first to get the current content before using <edit_file>, or use <write_file> with the complete new content.`,
2544
+ 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
2545
  });
2546
+ // Educate AI when it used write_file to overwrite a non-trivial existing file
2547
+ if (op.type === 'write' && opResult.type === 'modified' && existingLineCount > 20) {
2548
+ history.push({
2549
+ role: 'system',
2550
+ 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.`,
2551
+ });
2552
+ }
2518
2553
  }
2519
2554
  }
2520
2555
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taj-special/dravix-code",
3
- "version": "1.1.24",
3
+ "version": "1.1.25",
4
4
  "description": "AI-powered coding assistant CLI — Dravix Code",
5
5
  "type": "module",
6
6
  "bin": {