mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-28 12:39:15 +00:00
Compare commits
1 Commits
v0.0.5-nig
...
release/v0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1dc8b88992 |
1
.npmrc
1
.npmrc
@@ -1 +1,2 @@
|
||||
registry=https://registry.npmjs.org
|
||||
@google:registry=https://wombat-dressing-room.appspot.com
|
||||
|
||||
2
Makefile
2
Makefile
@@ -53,7 +53,7 @@ debug:
|
||||
|
||||
|
||||
run-npx:
|
||||
npx https://github.com/QwenLM/qwen-code
|
||||
npx https://github.com/google-gemini/gemini-cli
|
||||
|
||||
create-alias:
|
||||
scripts/create_alias.sh
|
||||
|
||||
@@ -101,7 +101,7 @@ Create or edit `.qwen/settings.json` in your home directory:
|
||||
|
||||
- **`/compress`** - Compress conversation history to continue within token limits
|
||||
- **`/clear`** - Clear all conversation history and start fresh
|
||||
- **`/stats`** - Check current token usage and limits
|
||||
- **`/status`** - Check current token usage and limits
|
||||
|
||||
> 📝 **Note**: Session token limit applies to a single conversation, not cumulative API calls.
|
||||
|
||||
@@ -310,7 +310,7 @@ qwen
|
||||
- `/help` - Display available commands
|
||||
- `/clear` - Clear conversation history
|
||||
- `/compress` - Compress history to save tokens
|
||||
- `/stats` - Show current session information
|
||||
- `/status` - Show current session information
|
||||
- `/exit` or `/quit` - Exit Qwen Code
|
||||
|
||||
### Keyboard Shortcuts
|
||||
|
||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@qwen-code/qwen-code",
|
||||
"version": "0.0.5-nightly.11",
|
||||
"version": "0.0.5-nightly.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@qwen-code/qwen-code",
|
||||
"version": "0.0.5-nightly.11",
|
||||
"version": "0.0.5-nightly.6",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
@@ -11817,7 +11817,7 @@
|
||||
},
|
||||
"packages/cli": {
|
||||
"name": "@qwen-code/qwen-code",
|
||||
"version": "0.0.5-nightly.11",
|
||||
"version": "0.0.5-nightly.6",
|
||||
"dependencies": {
|
||||
"@google/genai": "1.9.0",
|
||||
"@iarna/toml": "^2.2.5",
|
||||
@@ -11894,7 +11894,7 @@
|
||||
},
|
||||
"packages/core": {
|
||||
"name": "@qwen-code/qwen-code-core",
|
||||
"version": "0.0.5-nightly.11",
|
||||
"version": "0.0.5-nightly.6",
|
||||
"dependencies": {
|
||||
"@google/genai": "1.9.0",
|
||||
"@modelcontextprotocol/sdk": "^1.11.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@qwen-code/qwen-code",
|
||||
"version": "0.0.5-nightly.11",
|
||||
"version": "0.0.5-nightly.6",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
@@ -13,7 +13,7 @@
|
||||
"url": "git+https://github.com/QwenLM/qwen-code.git"
|
||||
},
|
||||
"config": {
|
||||
"sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.0.5-nightly.11"
|
||||
"sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.0.5-nightly.6"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node scripts/start.js",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@qwen-code/qwen-code",
|
||||
"version": "0.0.5-nightly.11",
|
||||
"version": "0.0.5-nightly.6",
|
||||
"description": "Qwen Code",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -25,7 +25,7 @@
|
||||
"dist"
|
||||
],
|
||||
"config": {
|
||||
"sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.0.5-nightly.11"
|
||||
"sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.0.5-nightly.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@google/genai": "1.9.0",
|
||||
|
||||
@@ -148,7 +148,7 @@ vi.mock('@qwen-code/qwen-code-core', async (importOriginal) => {
|
||||
getUserTier: vi.fn(),
|
||||
})),
|
||||
getCheckpointingEnabled: vi.fn(() => opts.checkpointing ?? true),
|
||||
getAllGeminiMdFilenames: vi.fn(() => ['QWEN.md']),
|
||||
getAllGeminiMdFilenames: vi.fn(() => ['GEMINI.md']),
|
||||
setFlashFallbackHandler: vi.fn(),
|
||||
getSessionId: vi.fn(() => 'test-session-id'),
|
||||
getUserTier: vi.fn().mockResolvedValue(undefined),
|
||||
@@ -169,7 +169,7 @@ vi.mock('@qwen-code/qwen-code-core', async (importOriginal) => {
|
||||
...actualCore,
|
||||
Config: ConfigClassMock,
|
||||
MCPServerConfig: actualCore.MCPServerConfig,
|
||||
getAllGeminiMdFilenames: vi.fn(() => ['QWEN.md']),
|
||||
getAllGeminiMdFilenames: vi.fn(() => ['GEMINI.md']),
|
||||
ideContext: ideContextMock,
|
||||
isGitRepository: vi.fn(),
|
||||
};
|
||||
@@ -577,7 +577,7 @@ describe('App UI', () => {
|
||||
},
|
||||
});
|
||||
mockConfig.getGeminiMdFileCount.mockReturnValue(1);
|
||||
mockConfig.getAllGeminiMdFilenames.mockReturnValue(['QWEN.md']);
|
||||
mockConfig.getAllGeminiMdFilenames.mockReturnValue(['GEMINI.md']);
|
||||
|
||||
const { lastFrame, unmount } = render(
|
||||
<App
|
||||
@@ -589,13 +589,13 @@ describe('App UI', () => {
|
||||
currentUnmount = unmount;
|
||||
await Promise.resolve();
|
||||
expect(lastFrame()).toContain(
|
||||
'Using: 1 open file (ctrl+e to view) | 1 QWEN.md file',
|
||||
'Using: 1 open file (ctrl+e to view) | 1 GEMINI.md file',
|
||||
);
|
||||
});
|
||||
|
||||
it('should display default "QWEN.md" in footer when contextFileName is not set and count is 1', async () => {
|
||||
it('should display default "GEMINI.md" in footer when contextFileName is not set and count is 1', async () => {
|
||||
mockConfig.getGeminiMdFileCount.mockReturnValue(1);
|
||||
mockConfig.getAllGeminiMdFilenames.mockReturnValue(['QWEN.md']);
|
||||
mockConfig.getAllGeminiMdFilenames.mockReturnValue(['GEMINI.md']);
|
||||
// For this test, ensure showMemoryUsage is false or debugMode is false if it relies on that
|
||||
mockConfig.getDebugMode.mockReturnValue(false);
|
||||
mockConfig.getShowMemoryUsage.mockReturnValue(false);
|
||||
@@ -609,12 +609,15 @@ describe('App UI', () => {
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
await Promise.resolve(); // Wait for any async updates
|
||||
expect(lastFrame()).toContain('Using: 1 QWEN.md file');
|
||||
expect(lastFrame()).toContain('Using: 1 GEMINI.md file');
|
||||
});
|
||||
|
||||
it('should display default "QWEN.md" with plural when contextFileName is not set and count is > 1', async () => {
|
||||
it('should display default "GEMINI.md" with plural when contextFileName is not set and count is > 1', async () => {
|
||||
mockConfig.getGeminiMdFileCount.mockReturnValue(2);
|
||||
mockConfig.getAllGeminiMdFilenames.mockReturnValue(['QWEN.md', 'QWEN.md']);
|
||||
mockConfig.getAllGeminiMdFilenames.mockReturnValue([
|
||||
'GEMINI.md',
|
||||
'GEMINI.md',
|
||||
]);
|
||||
mockConfig.getDebugMode.mockReturnValue(false);
|
||||
mockConfig.getShowMemoryUsage.mockReturnValue(false);
|
||||
|
||||
@@ -627,7 +630,7 @@ describe('App UI', () => {
|
||||
);
|
||||
currentUnmount = unmount;
|
||||
await Promise.resolve();
|
||||
expect(lastFrame()).toContain('Using: 2 QWEN.md files');
|
||||
expect(lastFrame()).toContain('Using: 2 GEMINI.md files');
|
||||
});
|
||||
|
||||
it('should display custom contextFileName in footer when set and count is 1', async () => {
|
||||
@@ -724,9 +727,12 @@ describe('App UI', () => {
|
||||
expect(lastFrame()).not.toContain('ANY_FILE.MD');
|
||||
});
|
||||
|
||||
it('should display QWEN.md and MCP server count when both are present', async () => {
|
||||
it('should display GEMINI.md and MCP server count when both are present', async () => {
|
||||
mockConfig.getGeminiMdFileCount.mockReturnValue(2);
|
||||
mockConfig.getAllGeminiMdFilenames.mockReturnValue(['QWEN.md', 'QWEN.md']);
|
||||
mockConfig.getAllGeminiMdFilenames.mockReturnValue([
|
||||
'GEMINI.md',
|
||||
'GEMINI.md',
|
||||
]);
|
||||
mockConfig.getMcpServers.mockReturnValue({
|
||||
server1: {} as MCPServerConfig,
|
||||
});
|
||||
@@ -745,7 +751,7 @@ describe('App UI', () => {
|
||||
expect(lastFrame()).toContain('1 MCP server');
|
||||
});
|
||||
|
||||
it('should display only MCP server count when QWEN.md count is 0', async () => {
|
||||
it('should display only MCP server count when GEMINI.md count is 0', async () => {
|
||||
mockConfig.getGeminiMdFileCount.mockReturnValue(0);
|
||||
mockConfig.getAllGeminiMdFilenames.mockReturnValue([]);
|
||||
mockConfig.getMcpServers.mockReturnValue({
|
||||
|
||||
@@ -20,7 +20,7 @@ vi.mock('fs', () => ({
|
||||
describe('initCommand', () => {
|
||||
let mockContext: CommandContext;
|
||||
const targetDir = '/test/dir';
|
||||
const geminiMdPath = path.join(targetDir, 'QWEN.md');
|
||||
const geminiMdPath = path.join(targetDir, 'GEMINI.md');
|
||||
|
||||
beforeEach(() => {
|
||||
// Create a fresh mock context for each test
|
||||
@@ -38,7 +38,7 @@ describe('initCommand', () => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should inform the user if QWEN.md already exists', async () => {
|
||||
it('should inform the user if GEMINI.md already exists', async () => {
|
||||
// Arrange: Simulate that the file exists
|
||||
vi.mocked(fs.existsSync).mockReturnValue(true);
|
||||
|
||||
@@ -50,13 +50,13 @@ describe('initCommand', () => {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content:
|
||||
'A QWEN.md file already exists in this directory. No changes were made.',
|
||||
'A GEMINI.md file already exists in this directory. No changes were made.',
|
||||
});
|
||||
// Assert: Ensure no file was written
|
||||
expect(fs.writeFileSync).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should create QWEN.md and submit a prompt if it does not exist', async () => {
|
||||
it('should create GEMINI.md and submit a prompt if it does not exist', async () => {
|
||||
// Arrange: Simulate that the file does not exist
|
||||
vi.mocked(fs.existsSync).mockReturnValue(false);
|
||||
|
||||
@@ -70,7 +70,7 @@ describe('initCommand', () => {
|
||||
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||
{
|
||||
type: 'info',
|
||||
text: 'Empty QWEN.md created. Now analyzing the project to populate it.',
|
||||
text: 'Empty GEMINI.md created. Now analyzing the project to populate it.',
|
||||
},
|
||||
expect.any(Number),
|
||||
);
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
|
||||
export const initCommand: SlashCommand = {
|
||||
name: 'init',
|
||||
description: 'Analyzes the project and creates a tailored QWEN.md file.',
|
||||
description: 'Analyzes the project and creates a tailored GEMINI.md file.',
|
||||
kind: CommandKind.BUILT_IN,
|
||||
action: async (
|
||||
context: CommandContext,
|
||||
@@ -29,24 +29,24 @@ export const initCommand: SlashCommand = {
|
||||
};
|
||||
}
|
||||
const targetDir = context.services.config.getTargetDir();
|
||||
const geminiMdPath = path.join(targetDir, 'QWEN.md');
|
||||
const geminiMdPath = path.join(targetDir, 'GEMINI.md');
|
||||
|
||||
if (fs.existsSync(geminiMdPath)) {
|
||||
return {
|
||||
type: 'message',
|
||||
messageType: 'info',
|
||||
content:
|
||||
'A QWEN.md file already exists in this directory. No changes were made.',
|
||||
'A GEMINI.md file already exists in this directory. No changes were made.',
|
||||
};
|
||||
}
|
||||
|
||||
// Create an empty QWEN.md file
|
||||
// Create an empty GEMINI.md file
|
||||
fs.writeFileSync(geminiMdPath, '', 'utf8');
|
||||
|
||||
context.ui.addItem(
|
||||
{
|
||||
type: 'info',
|
||||
text: 'Empty QWEN.md created. Now analyzing the project to populate it.',
|
||||
text: 'Empty GEMINI.md created. Now analyzing the project to populate it.',
|
||||
},
|
||||
Date.now(),
|
||||
);
|
||||
@@ -54,7 +54,7 @@ export const initCommand: SlashCommand = {
|
||||
return {
|
||||
type: 'submit_prompt',
|
||||
content: `
|
||||
You are an AI agent that brings the power of Gemini directly into the terminal. Your task is to analyze the current directory and generate a comprehensive QWEN.md file to be used as instructional context for future interactions.
|
||||
You are an AI agent that brings the power of Gemini directly into the terminal. Your task is to analyze the current directory and generate a comprehensive GEMINI.md file to be used as instructional context for future interactions.
|
||||
|
||||
**Analysis Process:**
|
||||
|
||||
@@ -70,7 +70,7 @@ You are an AI agent that brings the power of Gemini directly into the terminal.
|
||||
* **Code Project:** Look for clues like \`package.json\`, \`requirements.txt\`, \`pom.xml\`, \`go.mod\`, \`Cargo.toml\`, \`build.gradle\`, or a \`src\` directory. If you find them, this is likely a software project.
|
||||
* **Non-Code Project:** If you don't find code-related files, this might be a directory for documentation, research papers, notes, or something else.
|
||||
|
||||
**QWEN.md Content Generation:**
|
||||
**GEMINI.md Content Generation:**
|
||||
|
||||
**For a Code Project:**
|
||||
|
||||
@@ -86,7 +86,7 @@ You are an AI agent that brings the power of Gemini directly into the terminal.
|
||||
|
||||
**Final Output:**
|
||||
|
||||
Write the complete content to the \`QWEN.md\` file. The output must be well-formatted Markdown.
|
||||
Write the complete content to the \`GEMINI.md\` file. The output must be well-formatted Markdown.
|
||||
`,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -66,8 +66,8 @@ export function createShowMemoryAction(
|
||||
type: MessageType.INFO,
|
||||
content:
|
||||
fileCount > 0
|
||||
? 'Hierarchical memory (QWEN.md or other context files) is loaded but content is empty.'
|
||||
: 'No hierarchical memory (QWEN.md or other context files) is currently loaded.',
|
||||
? 'Hierarchical memory (GEMINI.md or other context files) is loaded but content is empty.'
|
||||
: 'No hierarchical memory (GEMINI.md or other context files) is currently loaded.',
|
||||
timestamp: new Date(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@qwen-code/qwen-code-core",
|
||||
"version": "0.0.5-nightly.11",
|
||||
"version": "0.0.5-nightly.6",
|
||||
"description": "Qwen Code Core",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -60,8 +60,8 @@ vi.mock('../tools/read-many-files');
|
||||
vi.mock('../tools/memoryTool', () => ({
|
||||
MemoryTool: vi.fn(),
|
||||
setGeminiMdFilename: vi.fn(),
|
||||
getCurrentGeminiMdFilename: vi.fn(() => 'QWEN.md'), // Mock the original filename
|
||||
DEFAULT_CONTEXT_FILENAME: 'QWEN.md',
|
||||
getCurrentGeminiMdFilename: vi.fn(() => 'GEMINI.md'), // Mock the original filename
|
||||
DEFAULT_CONTEXT_FILENAME: 'GEMINI.md',
|
||||
GEMINI_CONFIG_DIR: '.gemini',
|
||||
}));
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ export const GEMINI_CONFIG_DIR = '.qwen';
|
||||
export const DEFAULT_CONTEXT_FILENAME = 'QWEN.md';
|
||||
export const MEMORY_SECTION_HEADER = '## Qwen Added Memories';
|
||||
|
||||
// This variable will hold the currently configured filename for QWEN.md context files.
|
||||
// This variable will hold the currently configured filename for GEMINI.md context files.
|
||||
// It defaults to DEFAULT_CONTEXT_FILENAME but can be overridden by setGeminiMdFilename.
|
||||
let currentGeminiMdFilename: string | string[] = DEFAULT_CONTEXT_FILENAME;
|
||||
|
||||
|
||||
@@ -202,8 +202,8 @@ describe('bfsFileSearch', () => {
|
||||
await createEmptyDir(`dir${i}`, 'subdir1', 'deep');
|
||||
if (i < 10) {
|
||||
// Add target files in some directories
|
||||
await createTestFile('content', `dir${i}`, 'QWEN.md');
|
||||
await createTestFile('content', `dir${i}`, 'subdir1', 'QWEN.md');
|
||||
await createTestFile('content', `dir${i}`, 'GEMINI.md');
|
||||
await createTestFile('content', `dir${i}`, 'subdir1', 'GEMINI.md');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ describe('bfsFileSearch', () => {
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
const searchStartTime = performance.now();
|
||||
const result = await bfsFileSearch(testRootDir, {
|
||||
fileName: 'QWEN.md',
|
||||
fileName: 'GEMINI.md',
|
||||
maxDirs: 200,
|
||||
debug: false,
|
||||
});
|
||||
@@ -242,7 +242,7 @@ describe('bfsFileSearch', () => {
|
||||
console.log(
|
||||
`📊 Min/Max Duration: ${minDuration.toFixed(2)}ms / ${maxDuration.toFixed(2)}ms`,
|
||||
);
|
||||
console.log(`📁 Found ${foundFiles} QWEN.md files`);
|
||||
console.log(`📁 Found ${foundFiles} GEMINI.md files`);
|
||||
console.log(
|
||||
`🏎️ Processing ~${Math.round(200 / (avgDuration / 1000))} dirs/second`,
|
||||
);
|
||||
|
||||
@@ -365,7 +365,7 @@ My code memory
|
||||
|
||||
it('should load extension context file paths', async () => {
|
||||
const extensionFilePath = await createTestFile(
|
||||
path.join(testRootDir, 'extensions/ext1/QWEN.md'),
|
||||
path.join(testRootDir, 'extensions/ext1/GEMINI.md'),
|
||||
'Extension memory content',
|
||||
);
|
||||
|
||||
|
||||
@@ -252,7 +252,7 @@ function concatenateInstructions(
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads hierarchical QWEN.md files and concatenates their content.
|
||||
* Loads hierarchical GEMINI.md files and concatenates their content.
|
||||
* This function is intended for use by the server.
|
||||
*/
|
||||
export async function loadServerHierarchicalMemory(
|
||||
@@ -282,7 +282,7 @@ export async function loadServerHierarchicalMemory(
|
||||
maxDirs,
|
||||
);
|
||||
if (filePaths.length === 0) {
|
||||
if (debugMode) logger.debug('No QWEN.md files found in hierarchy.');
|
||||
if (debugMode) logger.debug('No GEMINI.md files found in hierarchy.');
|
||||
return { memoryContent: '', fileCount: 0 };
|
||||
}
|
||||
const contentsWithPaths = await readGeminiMdFiles(
|
||||
|
||||
@@ -191,7 +191,7 @@ function findCodeRegions(content: string): Array<[number, number]> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes import statements in QWEN.md content
|
||||
* Processes import statements in GEMINI.md content
|
||||
* Supports @path/to/file syntax for importing content from other files
|
||||
* @param content - The content to process for imports
|
||||
* @param basePath - The directory path where the current file is located
|
||||
|
||||
Reference in New Issue
Block a user