From 76e545c595c9912585fc6f5517e50301fa41e3a6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 20:25:55 +0000 Subject: [PATCH 1/2] fix: proactive workspace analysis for all models, workspace snapshot for Kimi K2.5 / DeepSeek R1 Agent-Logs-Url: https://github.com/codomium/CODE/sessions/d3b22076-f9a7-4793-871a-db2c50c8a74f Co-authored-by: codomium <255525663+codomium@users.noreply.github.com> --- v2/src/core/agent-loop.mjs | 10 +++- v2/src/core/system-prompt.mjs | 86 ++++++++++++++++++++++++++++++++++- v2/test/test.mjs | 19 +++++++- 3 files changed, 111 insertions(+), 4 deletions(-) diff --git a/v2/src/core/agent-loop.mjs b/v2/src/core/agent-loop.mjs index 24a17ec..d35795d 100644 --- a/v2/src/core/agent-loop.mjs +++ b/v2/src/core/agent-loop.mjs @@ -4,7 +4,7 @@ */ import { streamResponse, accumulateStream } from './streaming.mjs'; import { ContextManager } from './context-manager.mjs'; -import { buildSystemPrompt } from './system-prompt.mjs'; +import { buildSystemPrompt, buildWorkspaceSnapshot } from './system-prompt.mjs'; import { isNvidiaModel } from './providers.mjs'; import fs from 'fs'; import path from 'path'; @@ -406,12 +406,18 @@ async function callNvidia(model, state, toolDefs, settings, stream) { // For thinking models the tool-list suffix in the system prompt would be // misleading (no tools are sent), so use the static prefix only. + // Additionally, inject a workspace file-tree snapshot so the model can + // reason about the project structure even without tool access. let systemPrompt = state.systemPrompt; if (supportsThinking) { if (!state.systemPromptStatic) { process.stderr.write('[open-claude-code] Warning: systemPromptStatic missing — falling back to full system prompt for ' + model + '\n'); } - systemPrompt = state.systemPromptStatic || state.systemPrompt; + const base = state.systemPromptStatic || state.systemPrompt; + const snapshot = buildWorkspaceSnapshot(process.cwd()); + systemPrompt = snapshot + ? base + '\n\n## Workspace file structure (read-only reference)\n\n```\n' + snapshot + '\n```' + : base; } const effectiveState = supportsThinking ? { ...state, systemPrompt } diff --git a/v2/src/core/system-prompt.mjs b/v2/src/core/system-prompt.mjs index a748cac..5f33c85 100644 --- a/v2/src/core/system-prompt.mjs +++ b/v2/src/core/system-prompt.mjs @@ -6,11 +6,78 @@ * - Merges in order (global -> project -> local) * - Splits at cache boundary (static prefix cached, dynamic suffix not) * - Includes tool schemas in the system prompt + * - Exports buildWorkspaceSnapshot for injecting a file-tree into prompts */ import fs from 'fs'; import path from 'path'; import os from 'os'; +// Directories to skip when building the workspace snapshot. +const SNAPSHOT_EXCLUDE = new Set([ + 'node_modules', '.git', 'dist', 'build', 'out', '.next', '.nuxt', + '__pycache__', '.cache', 'coverage', '.nyc_output', '.turbo', +]); + +// Dot-files/dirs are hidden by default; these are shown because they are +// commonly checked into source control and useful for project analysis. +const SNAPSHOT_INCLUDE_DOTFILES = new Set([ + '.env.example', '.eslintrc', '.eslintrc.js', '.eslintrc.json', '.eslintrc.yml', + '.prettierrc', '.prettierrc.js', '.prettierrc.json', '.prettierrc.yml', + '.babelrc', '.babelrc.js', '.gitignore', '.dockerignore', '.editorconfig', +]); + +/** + * Build a compact, indented directory tree for a workspace. + * + * The tree is capped at `maxFiles` entries so it never bloats the prompt. + * Directories that match SNAPSHOT_EXCLUDE are skipped entirely. + * Any I/O error returns an empty string gracefully. + * + * @param {string} [cwd] - root directory to scan (defaults to process.cwd()) + * @param {number} [maxFiles=200] - maximum number of entries to include + * @returns {string} indented tree string, or '' on error / empty workspace + */ +export function buildWorkspaceSnapshot(cwd = process.cwd(), maxFiles = 200) { + const lines = []; + let count = 0; + + function walk(dir, indent) { + if (count >= maxFiles) return; + let entries; + try { + entries = fs.readdirSync(dir, { withFileTypes: true }); + } catch { + return; + } + // Directories first, then files, both sorted alphabetically + entries.sort((a, b) => { + if (a.isDirectory() !== b.isDirectory()) return a.isDirectory() ? -1 : 1; + return a.name.localeCompare(b.name); + }); + for (const entry of entries) { + if (count >= maxFiles) { + lines.push(indent + '… (truncated)'); + return; + } + if (SNAPSHOT_EXCLUDE.has(entry.name)) continue; + if (entry.name.startsWith('.') && !SNAPSHOT_INCLUDE_DOTFILES.has(entry.name)) continue; + lines.push(indent + entry.name + (entry.isDirectory() ? '/' : '')); + count++; + if (entry.isDirectory()) { + walk(path.join(dir, entry.name), indent + ' '); + } + } + } + + try { + walk(path.resolve(cwd), ''); + } catch { + return ''; + } + + return lines.join('\n'); +} + /** * Load all CLAUDE.md files and merge them in order. * @param {string} [cwd] - current working directory @@ -67,7 +134,24 @@ export function buildSystemPrompt({ cwd, tools, override, addDirs } = {}) { return { staticPrefix: override, dynamicSuffix: '', full: override }; } - const parts = ['You are an AI coding assistant.']; + const workspaceRoot = path.resolve(cwd || process.cwd()); + const basePreamble = [ + `You are an AI coding assistant with direct access to the user's workspace on disk.`, + `Current working directory: ${workspaceRoot}`, + ``, + `## Workspace exploration rules`, + ``, + `- When the user asks about their project, code, or files, ALWAYS use your tools to`, + ` explore the workspace first — do NOT ask the user to paste or share anything.`, + `- Use LS / Glob to discover files, Read to inspect their contents, Grep to search`, + ` for patterns, and Bash to run commands (tests, builds, linters, git log, etc.).`, + `- Start broad (list the root directory) then drill into relevant subdirectories.`, + `- Prefer reading the actual source over guessing from file names alone.`, + `- Never say "I don't see any files" or ask the user to share code — you can read`, + ` the workspace directly with your tools.`, + ].join('\n'); + + const parts = [basePreamble]; // Load CLAUDE.md files const mdFiles = loadClaudeMdFiles(cwd); diff --git a/v2/test/test.mjs b/v2/test/test.mjs index ca1ff08..f4ce346 100644 --- a/v2/test/test.mjs +++ b/v2/test/test.mjs @@ -1148,10 +1148,13 @@ assert(foundTruncated, 'Micro-compaction truncates old tool results'); section('Phase 2: System Prompt'); -import { buildSystemPrompt, loadClaudeMdFiles, toCacheBlocks } from '../src/core/system-prompt.mjs'; +import { buildSystemPrompt, loadClaudeMdFiles, toCacheBlocks, buildWorkspaceSnapshot } from '../src/core/system-prompt.mjs'; const prompt = buildSystemPrompt({ cwd: '/tmp' }); assertIncludes(prompt.full, 'AI coding assistant', 'System prompt has base text'); +assertIncludes(prompt.full, 'Current working directory:', 'System prompt declares cwd'); +assertIncludes(prompt.full, 'Workspace exploration rules', 'System prompt has exploration rules'); +assertIncludes(prompt.full, 'do NOT ask the user to paste', 'System prompt forbids asking user to paste code'); assertType(prompt.staticPrefix, 'string', 'Has static prefix'); assertType(prompt.dynamicSuffix, 'string', 'Has dynamic suffix'); @@ -1169,6 +1172,20 @@ assertEqual(blocks.length, 2, 'Two cache blocks'); assertEqual(blocks[0].cache_control.type, 'ephemeral', 'Static block cached'); assert(blocks[1].cache_control === undefined, 'Dynamic block not cached'); +// buildWorkspaceSnapshot +assertType(buildWorkspaceSnapshot, 'function', 'buildWorkspaceSnapshot is exported'); +const snapshot = buildWorkspaceSnapshot('/tmp'); +assertType(snapshot, 'string', 'Snapshot returns a string'); +// Non-existent path returns empty string gracefully +const snapshotBad = buildWorkspaceSnapshot('/nonexistent_path_xyz_12345'); +assertEqual(snapshotBad, '', 'Non-existent path returns empty string'); +// Snapshot respects maxFiles cap: with maxFiles=1, we expect at most 1 entry +// plus a possible "… (truncated)" line = 2 non-blank lines maximum. Allow +// up to 3 to accommodate edge cases where /tmp itself is almost empty. +const snapshotCapped = buildWorkspaceSnapshot('/tmp', 1); +const snapshotLines = snapshotCapped.split('\n').filter(l => l.trim()); +assert(snapshotLines.length <= 3, 'Snapshot respects maxFiles cap (at most 1 entry + truncation line)'); + // ---------- Phase 3: CLI, UI, Commands Tests ---------- section('Phase 3: CLI Args (full flags)'); From 7ca5797ad97bd69113cd54c5c95862467b5fcb6f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 20:30:35 +0000 Subject: [PATCH 2/2] feat: update extension to v1.2.0 and document proactive workspace analysis Agent-Logs-Url: https://github.com/codomium/CODE/sessions/25343567-8669-4feb-86a5-9c65d40129ef Co-authored-by: codomium <255525663+codomium@users.noreply.github.com> --- README.md | 21 ++++++++++++++++----- vscode-extension/README.md | 21 +++++++++++++++++++-- vscode-extension/package.json | 8 ++++---- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index d9daeb7..819bc4b 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@
-
+
@@ -52,7 +52,7 @@ A **Cursor-style AI coding assistant** built directly into VSCode — no termina
The extension package is included in the repo and ready to install:
```bash
-code --install-extension vscode-extension/open-claude-code-1.1.0.vsix
+code --install-extension vscode-extension/open-claude-code-1.2.0.vsix
```
Or use **Extensions → … → Install from VSIX…** and pick the file from the `vscode-extension/` folder.
@@ -63,7 +63,7 @@ Or use **Extensions → … → Install from VSIX…** and pick the file from th
cd vscode-extension
npm install
npm run package # prepackage → package → postpackage
-code --install-extension open-claude-code-1.1.0.vsix
+code --install-extension open-claude-code-1.2.0.vsix
```
### Highlights
@@ -78,6 +78,7 @@ code --install-extension open-claude-code-1.1.0.vsix
- **Multi-provider** — Anthropic Claude, OpenAI GPT, Google Gemini, NVIDIA NIM
- **Model & permission-mode selector** — switch model and mode directly from the UI
- **Session stats** — token count, cost estimate, and elapsed time always visible
+- **Proactive workspace analysis** — the agent explores your project automatically before answering; never asks you to paste code
See [`vscode-extension/README.md`](./vscode-extension/README.md) for the full setup and configuration guide.
@@ -349,8 +350,10 @@ NVIDIA_API_KEY=nvapi-... occ -m kimi-k2.5 "hello"
> **Note — NVIDIA thinking models:** Models such as `kimi-k2.5` and `deepseek-r1` use
> `chat_template_kwargs: {thinking: true}` and do not accept a `tools` array in the same
-> request. Open Claude Code automatically detects these models and omits tools from the
-> request, preventing the HTTP 400 error that previously made them unusable.
+> request. Open Claude Code automatically detects these models, omits tools from the
+> request (preventing the HTTP 400 error), and injects a compact workspace file-tree
+> snapshot into the system prompt so the model still has full structural awareness of
+> your project without needing live tool calls.
---
@@ -402,6 +405,14 @@ This is a **clean-room implementation** — no leaked source used. Architecture
## 🆕 What's New
+### v1.2.0 — Proactive Workspace Analysis
+
+**Fix: Proactive workspace analysis for all models** _(this PR)_
+- All models now receive a strong agentic system prompt declaring the workspace `cwd` and instructing them to explore files with LS / Glob / Read / Grep / Bash before answering — never asking the user to paste code
+- New `buildWorkspaceSnapshot` helper recursively walks the workspace (skipping `node_modules`, `.git`, `dist`, etc.) and returns a compact indented file tree capped at 200 entries
+- Kimi K2.5 and DeepSeek R1 (NVIDIA thinking models) now have the file tree injected directly into their system prompt — giving them full structural awareness even though NVIDIA NIM prevents live tool calls during thinking mode
+- Extension model descriptions updated; version bumped to 1.2.0
+
### v1.1.0 — VSCode Extension & Bug Fixes
**VSCode Extension — Cursor-style sidebar panel** _(PR #2)_
diff --git a/vscode-extension/README.md b/vscode-extension/README.md
index 15e3388..27df3f4 100644
--- a/vscode-extension/README.md
+++ b/vscode-extension/README.md
@@ -6,6 +6,11 @@ A **Cursor-style AI coding assistant** built directly into VSCode — no termina
## Features
+### 🗂️ Proactive workspace analysis (new in v1.2)
+- **Automatic workspace exploration** — before answering questions the agent scans your project with LS, Glob, Read, and Grep instead of asking you to paste code
+- **Workspace file tree injection for thinking models** — Kimi K2.5 and DeepSeek R1 receive a compact file-tree snapshot in their system prompt so they know your project layout even though NVIDIA NIM prevents live tool calls during thinking
+- **Never "I can't see your files"** — the system prompt explicitly forbids asking you to share code; the agent reads files directly
+
### 🖥️ Cursor-style Sidebar Panel (new in v1.1)
- **Dedicated activity bar icon** — opens a full chat panel in the VS Code sidebar
- **Rich markdown rendering** — headers, tables, bold/italic, blockquotes
@@ -25,7 +30,7 @@ A **Cursor-style AI coding assistant** built directly into VSCode — no termina
### 💬 `@claude` Chat Participant (VSCode built-in chat)
- Ask questions, request code changes, and run agentic tools without leaving the editor
- **Full tool access** — the same 25+ tools as the CLI (Read, Write, Edit, Bash, Glob, Grep, WebFetch, …)
-- **Multi-provider** — Anthropic Claude, OpenAI GPT, Google Gemini
+- **Multi-provider** — Anthropic Claude, OpenAI GPT, Google Gemini, NVIDIA NIM
- **Conversation memory** — history is maintained across turns in the same VS Code session
- **Slash commands** — `/clear` to reset, `/model` to switch models mid-session
- **Configurable permission mode** — control how aggressively the agent modifies your files
@@ -72,7 +77,7 @@ A **Cursor-style AI coding assistant** built directly into VSCode — no termina
extension bundle so all functionality is available after installation.
3. Install it in VSCode:
```bash
- code --install-extension open-claude-code-1.1.0.vsix
+ code --install-extension open-claude-code-1.2.0.vsix
```
Or use **Extensions → … → Install from VSIX…** in the VSCode UI.
@@ -212,6 +217,18 @@ The subprocess persists across chat turns so the agent's conversation history is
---
+### NVIDIA thinking models (Kimi K2.5, DeepSeek R1)
+
+NVIDIA NIM rejects requests that combine `chat_template_kwargs.thinking` with a tools array, so these models cannot make live tool calls. Open Claude Code works around this automatically:
+
+- The agent omits tools from the request (preventing the HTTP 400 error)
+- A compact workspace file tree is appended to the system prompt so the model knows your project layout without needing live tool access
+- The system prompt instructs the model to reason about files by path rather than asking you to paste them
+
+To use a thinking model, select **moonshotai/kimi-k2.5** or **deepseek-ai/deepseek-r1** from the Model dropdown and enter your `NVIDIA_API_KEY` in Settings.
+
+---
+
## Troubleshooting
**"Failed to start agent"**
diff --git a/vscode-extension/package.json b/vscode-extension/package.json
index d02ad5d..34769be 100644
--- a/vscode-extension/package.json
+++ b/vscode-extension/package.json
@@ -2,7 +2,7 @@
"name": "open-claude-code",
"displayName": "Open Claude Code",
"description": "AI coding assistant powered by Claude — Cursor-style chat panel with file context, code apply, tool visualization and more",
- "version": "1.1.0",
+ "version": "1.2.0",
"publisher": "open-claude-code",
"engines": {
"vscode": "^1.90.0"
@@ -112,13 +112,13 @@
"OpenAI GPT-4o",
"OpenAI GPT-4o Mini",
"Google Gemini 2.0 Flash",
- "NVIDIA NIM — Moonshot AI Kimi K2.5 (with thinking)",
+ "NVIDIA NIM — Moonshot AI Kimi K2.5 (thinking mode; workspace file tree injected automatically)",
"NVIDIA NIM — Llama 3.1 Nemotron 70B Instruct",
"NVIDIA NIM — Meta Llama 3.1 405B Instruct",
"NVIDIA NIM — Meta Llama 3.3 70B Instruct",
"NVIDIA NIM — Mistral Large 2 Instruct",
"NVIDIA NIM — Mixtral 8x22B Instruct",
- "NVIDIA NIM — DeepSeek R1 (with thinking)"
+ "NVIDIA NIM — DeepSeek R1 (thinking mode; workspace file tree injected automatically)"
],
"description": "AI model to use for the chat participant"
},
@@ -170,7 +170,7 @@
"prepackage": "node scripts/prepare-bundle.js",
"package": "vsce package --no-dependencies",
"postpackage": "node scripts/cleanup-bundle.js",
- "install-vsix": "code --install-extension open-claude-code-1.1.0.vsix"
+ "install-vsix": "code --install-extension open-claude-code-1.2.0.vsix"
},
"devDependencies": {
"@types/vscode": "^1.90.0",