From 1d26e73556c036edc67bf8f04973937794e9d6f9 Mon Sep 17 00:00:00 2001 From: yiliang114 Date: Mon, 24 Aug 2026 17:41:25 +0800 Subject: [PATCH 01/10] refactor(core,cli): rename Gemini residue in memory/spinner/leaf ids PR 1 of #4063 item 6 (de-Google naming). Renames three independent families plus the leaf LLM types: - Memory filename: GeminiMd* -> Memory* (project memory file, not an LLM client) - UI spinners: GeminiRespondingSpinner/GeminiSpinner -> RespondingSpinner/Spinner - Leaf types: GeminiCodeRequest/GeminiChatSendOptions/GeminiErrorEventValue/GeminiFinishedEventValue -> Llm* - geminiRequest.ts -> llm-request.ts (and its collocated test) No behavior change. Renamed symbols typecheck clean in core+cli; eslint clean on renamed files. Refs #4063 --- .../2026-08-22-rename-gemini-fork-residue.md | 140 ++++++++++++++++++ .../cli/src/acp-integration/acpAgent.test.ts | 2 +- packages/cli/src/acp-integration/acpAgent.ts | 6 +- packages/cli/src/config/config.test.ts | 24 +-- packages/cli/src/config/config.ts | 10 +- packages/cli/src/core/initializer.test.ts | 4 +- packages/cli/src/core/initializer.ts | 2 +- packages/cli/src/gemini.test.tsx | 20 +-- packages/cli/src/serve/capabilities.ts | 2 +- packages/cli/src/serve/run-qwen-serve.ts | 2 +- .../cli/src/serve/workspace-memory.test.ts | 4 +- packages/cli/src/serve/workspace-memory.ts | 4 +- packages/cli/src/ui/AppContainer.tsx | 16 +- .../src/ui/commands/directoryCommand.test.tsx | 4 +- .../cli/src/ui/commands/directoryCommand.tsx | 4 +- packages/cli/src/ui/commands/initCommand.ts | 4 +- packages/cli/src/ui/commands/types.ts | 2 +- packages/cli/src/ui/components/Footer.tsx | 6 +- .../ui/components/LoadingIndicator.test.tsx | 6 +- .../src/ui/components/LoadingIndicator.tsx | 4 +- .../cli/src/ui/components/MemoryDialog.tsx | 12 +- ...er.test.tsx => RespondingSpinner.test.tsx} | 12 +- ...ndingSpinner.tsx => RespondingSpinner.tsx} | 16 +- .../agent-view/AgentChatContent.tsx | 4 +- .../components/agent-view/AgentComposer.tsx | 2 +- .../messages/CompactToolGroupDisplay.test.tsx | 2 +- .../components/messages/ToolMessage.test.tsx | 4 +- .../components/shared/ToolStatusIndicator.tsx | 4 +- .../ui/hooks/slashCommandProcessor.test.ts | 4 +- .../cli/src/ui/hooks/slashCommandProcessor.ts | 6 +- .../ui/hooks/useAutoAcceptIndicator.test.ts | 4 +- packages/cli/src/ui/hooks/useGeminiStream.ts | 4 +- .../src/ui/hooks/useShowMemoryCommand.test.ts | 2 +- .../cli/src/ui/hooks/useShowMemoryCommand.ts | 2 +- .../src/ui/noninteractive/nonInteractiveUi.ts | 2 +- .../src/config/config-session-env.test.ts | 2 +- .../core/src/config/config.safe-mode.test.ts | 2 +- packages/core/src/config/config.test.ts | 22 +-- packages/core/src/config/config.ts | 12 +- .../config.workflow-registration.test.ts | 2 +- .../core/src/config/config.workflows.test.ts | 2 +- packages/core/src/core/geminiChat.ts | 4 +- ...iniRequest.test.ts => llm-request.test.ts} | 2 +- .../core/{geminiRequest.ts => llm-request.ts} | 4 +- packages/core/src/core/turn.ts | 8 +- packages/core/src/index.ts | 2 +- packages/core/src/memory/const.test.ts | 52 +++---- .../core/src/memory/memoryDiscovery.test.ts | 12 +- packages/core/src/memory/memoryDiscovery.ts | 22 +-- packages/core/src/memory/refresh.test.ts | 6 +- packages/core/src/memory/refresh.ts | 4 +- .../core/src/memory/writeContextFile.test.ts | 12 +- packages/core/src/memory/writeContextFile.ts | 8 +- .../core/src/permissions/autoMode.test.ts | 6 +- packages/core/src/permissions/autoMode.ts | 4 +- packages/core/src/tools/edit.test.ts | 4 +- packages/core/src/tools/glob.test.ts | 2 +- packages/core/src/tools/memory-config.ts | 6 +- packages/core/src/tools/notebook-edit.test.ts | 4 +- packages/core/src/tools/write-file.test.ts | 4 +- .../core/src/utils/ignorePatterns.test.ts | 2 +- packages/core/src/utils/ignorePatterns.ts | 4 +- packages/core/src/utils/memory-constants.ts | 26 ++-- 63 files changed, 363 insertions(+), 223 deletions(-) create mode 100644 docs/design/2026-08-22-rename-gemini-fork-residue.md rename packages/cli/src/ui/components/{GeminiRespondingSpinner.test.tsx => RespondingSpinner.test.tsx} (70%) rename packages/cli/src/ui/components/{GeminiRespondingSpinner.tsx => RespondingSpinner.tsx} (86%) rename packages/core/src/core/{geminiRequest.test.ts => llm-request.test.ts} (97%) rename packages/core/src/core/{geminiRequest.ts => llm-request.ts} (81%) diff --git a/docs/design/2026-08-22-rename-gemini-fork-residue.md b/docs/design/2026-08-22-rename-gemini-fork-residue.md new file mode 100644 index 00000000000..74bd7aa04cc --- /dev/null +++ b/docs/design/2026-08-22-rename-gemini-fork-residue.md @@ -0,0 +1,140 @@ +# Rename `Gemini` fork-residue identifiers to `Llm` + +## Problem + +`#4063` item 6: the codebase still carries the `Gemini` prefix inherited from +the upstream Gemini CLI fork. Measured on `origin/main` (`43d46be912f4`): + +- **~271 files** contain a `Gemini` token. +- **~4000 `Gemini` token occurrences** across `packages/core/src` and + `packages/cli/src`, split into two shapes: + - **PascalCase type/component names** (token-prefix): `GeminiClient`, + `GeminiChat`, `GeminiEventType`, … + - **camelCase function/variable names** (token-infix): `getGeminiClient`, + `convertGeminiRequestToOpenAI`, `useGeminiStream`, `setGeminiMdFilename`, … + +`GeminiClient` is the generic LLM client, not a Gemini-specific type, and the +repo has already adopted the `Llm` prefix elsewhere (`BaseLlmClient`, +`LlmRewriter`, `LlmContent`, `LlmOutputLanguage`, `LlmSpan`). The `Gemini` +residue is brand mismatch that confuses contributors and blocks a coherent +naming scheme. + +## Proposal + +Rename the local `Gemini` identifiers to `Llm`, with these exceptions: + +1. **Memory filename** — `GeminiMdFilename` (+ `set/get/getAll/getCurrent`, + `GeminiMdFileCount`) is the project memory file (`QWEN.md`), a memory + concept, not an LLM client. → `Memory*`. +2. **UI spinners** — `GeminiRespondingSpinner` / `GeminiSpinner` drop the + prefix. → `RespondingSpinner` / `Spinner`. +3. **Gemini extension format (keep as-is)** — `packages/core/src/extension/ + gemini-converter.ts` converts *upstream Gemini CLI extension* configs + (`GeminiExtensionConfig`, `convertGeminiToQwenConfig`, + `convertGeminiExtensionPackage`, `isGeminiExtensionConfig`). The `Gemini` + here denotes a real external format, not the generic LLM client. **Not part + of this rename.** +4. **`@google/genai` SDK types (out of scope)** — `Content`, + `GenerateContentParameters`, `Part`, … are imported from `@google/genai` + (mostly `cli/src/acp-integration`). These belong to `#4063` item 1 + (de-Google the type system), not this rename. + +## Symbol map + +Local type/class/enum names (PascalCase, → `Llm*`): + +| Current | Definition | New | +|---|---|---| +| `GeminiClient` | `core/src/core/client.ts:375` class | `LlmClient` | +| `GeminiChat` | `core/src/core/geminiChat.ts:1853` class | `LlmChat` | +| `GeminiEventType` | `core/src/core/turn.ts:62` **and** `cli/src/ui/types.ts:42` (two enums) | `LlmEventType` | +| `GeminiContentGenerator` | `core/src/core/geminiContentGenerator/geminiContentGenerator.ts:61` class | `LlmContentGenerator` | +| `GeminiCodeRequest` | `core/src/core/geminiRequest.ts:15` type | `LlmCodeRequest` | +| `GeminiChatSendOptions` | `core/src/core/geminiChat.ts:448` interface | `LlmChatSendOptions` | +| `GeminiErrorEventValue` / `GeminiFinishedEventValue` | `core/src/core/turn.ts:112/122` | `LlmErrorEventValue` / `LlmFinishedEventValue` | +| `GeminiRespondingSpinner` / `GeminiSpinner` | `cli/src/ui/components/GeminiRespondingSpinner.tsx:32/59` | `RespondingSpinner` / `Spinner` | + +camelCase functions/variables (token-infix, → `Llm*`), highest-frequency first: + +| Current | New | +|---|---| +| `getGeminiClient` | `getLlmClient` | +| `mockGeminiClient` | `mockLlmClient` | +| `convertOpenAIChunkToGemini` | `convertOpenAIChunkToLlm` | +| `convertGeminiRequestToOpenAI` | `convertLlmRequestToOpenAI` | +| `convertOpenAIResponseToGemini` | `convertOpenAIResponseToLlm` | +| `responseSubmittedToGemini` | `responseSubmittedToLlm` | +| `useGeminiStream` | `useLlmStream` | +| `convertGeminiRequestToAnthropic` | `convertLlmRequestToAnthropic` | +| `setGeminiMdFilename` / `getAllGeminiMdFilenames` / `getCurrentGeminiMdFilename` / `getGeminiMdFileCount` / `setGeminiMdFileCount` | `setMemoryFilename` / `getAllMemoryFilenames` / `getCurrentMemoryFilename` / `getMemoryFileCount` / `setMemoryFileCount` | +| `mockGeminiResponse` / `mockGeminiClientInstance` / `MockedGeminiClientClass` | `mockLlmResponse` / `mockLlmClientInstance` / `MockedLlmClientClass` | +| `convertGeminiToolsToOpenAI` / `convertGeminiToolsToAnthropic` | `convertLlmToolsToOpenAI` / `convertLlmToolsToAnthropic` | +| `convertGeminiToolParametersToOpenAI` | `convertLlmToolParametersToOpenAI` | +| `newGeminiMessageBuffer` / `makeGeminiHistoryItem` / `extractGeminiContent` / `buildGeminiChunk` / `recordGeminiChunk` | `newLlmMessageBuffer` / `makeLlmHistoryItem` / `extractLlmContent` / `buildLlmChunk` / `recordLlmChunk` | +| `createInitializedGeminiClient` / `createGeminiContentGenerator` | `createInitializedLlmClient` / `createLlmContentGenerator` | +| `mapAnthropicFinishReasonToGemini` / `convertAnthropicResponseToGemini` | `mapAnthropicFinishReasonToLlm` / `convertAnthropicResponseToLlm` | +| `pendingGeminiHistoryItems` / `skipGeminiInitialization` / `loadHierarchicalGeminiMemory` | `pendingLlmHistoryItems` / `skipLlmInitialization` / `loadHierarchicalLlmMemory` | + +## File renames + +Non-test files; `gemini-converter.ts` is intentionally NOT renamed (see above). + +| Current | New | +|---|---| +| `packages/cli/src/gemini.tsx` | `packages/cli/src/llm.tsx` | +| `packages/cli/src/ui/components/GeminiRespondingSpinner.tsx` | `packages/cli/src/ui/components/RespondingSpinner.tsx` | +| `packages/cli/src/ui/hooks/useGeminiStream.ts` | `packages/cli/src/ui/hooks/use-llm-stream.ts` | +| `packages/core/src/core/geminiChat.ts` | `packages/core/src/core/llm-chat.ts` | +| `packages/core/src/core/geminiContentGenerator/geminiContentGenerator.ts` | `packages/core/src/core/llm-content-generator/llm-content-generator.ts` | +| `packages/core/src/core/geminiContentGenerator/index.ts` | `packages/core/src/core/llm-content-generator/index.ts` | +| `packages/core/src/core/geminiRequest.ts` | `packages/core/src/core/llm-request.ts` | + +## Phasing + +Two pull requests. The core LLM symbols are strongly coupled (`GeminiClient` +holds a `GeminiChat`, converters reference `GeminiEventType`), so the core must +move as one atomic PR. + +**PR 1 — independent small families** (no cross-package risk, small diff): + +- Memory filename: `GeminiMdFilename` family → `Memory*`. +- UI spinners: `GeminiRespondingSpinner` / `GeminiSpinner` → + `RespondingSpinner` / `Spinner`, and `GeminiRespondingSpinner.tsx` → + `RespondingSpinner.tsx`. +- Leaf types: `GeminiCodeRequest`, `GeminiChatSendOptions`, + `GeminiErrorEventValue`, `GeminiFinishedEventValue`, and `geminiRequest.ts` → + `llm-request.ts`. + +**PR 2 — core LLM layer (atomic)**: + +- `GeminiClient` → `LlmClient` (barrel + 4 importing packages) and all + `get/mock/create…GeminiClient`. +- `GeminiChat` → `LlmChat` (`geminiChat.ts` → `llm-chat.ts`), + `GeminiContentGenerator` → `LlmContentGenerator` + (`geminiContentGenerator/` → `llm-content-generator/`). +- `GeminiEventType` (both enums) → `LlmEventType`. +- Stream layer: `useGeminiStream` → `useLlmStream` (`use-llm-stream.ts`), + `gemini.tsx` → `llm.tsx`. +- Protocol converters: `convert*ToGemini*` / `convertGemini*To*` → `Llm`. + +## Risks + +- **git blame loss**: every rename loses history (noted in AGENTS.md). Accept + the cost once; do not rename the same file twice. +- **Cross-package barrel**: `GeminiClient` and `GeminiEventType` are exported via + the `@qwen-code/qwen-code-core` barrel. `sdk-typescript` and `acp-bridge` + import them; PR 2 must update those packages. +- **Two `GeminiEventType` enums**: `core/src/core/turn.ts` and + `cli/src/ui/types.ts` define the same name. Rename both and verify their + relationship (distinct enums vs re-export) before PR 2. +- **Test mock coupling**: when a module moves or a symbol renames, both the + `vi.mock(...)` first argument AND the `typeof import(...)` type annotation + must be updated together (lesson from `#9146`). +- **License headers**: moved files keep the original `2025 Google LLC` header. + +## Verification + +- `cd packages/core && npx tsc --noEmit` +- `cd packages/cli && npx tsc --noEmit` +- Targeted unit tests per renamed module +- `npm run lint` (kebab-case filenames are enforced) diff --git a/packages/cli/src/acp-integration/acpAgent.test.ts b/packages/cli/src/acp-integration/acpAgent.test.ts index 191812d9843..a68e9ccd0b9 100644 --- a/packages/cli/src/acp-integration/acpAgent.test.ts +++ b/packages/cli/src/acp-integration/acpAgent.test.ts @@ -572,7 +572,7 @@ vi.mock('@qwen-code/qwen-code-core', async (importOriginal) => ({ }, ), clearCachedCredentialFile: vi.fn(), - getAllGeminiMdFilenames: vi.fn(() => ['QWEN.md', 'AGENTS.md']), + getAllMemoryFilenames: vi.fn(() => ['QWEN.md', 'AGENTS.md']), getAutoMemoryRoot: vi.fn( (projectRoot: string) => `${projectRoot}/.qwen/memory`, ), diff --git a/packages/cli/src/acp-integration/acpAgent.ts b/packages/cli/src/acp-integration/acpAgent.ts index c8aad29652c..c6e2c5e21c6 100644 --- a/packages/cli/src/acp-integration/acpAgent.ts +++ b/packages/cli/src/acp-integration/acpAgent.ts @@ -19,7 +19,7 @@ import { createDebugLogger, generateSessionRecap, findProviderById, - getAllGeminiMdFilenames, + getAllMemoryFilenames, getAutoMemoryRoot, getUserAutoMemoryRoot, getDefaultBaseUrlForProtocol, @@ -2304,7 +2304,7 @@ async function resolvePreferredMemoryFile( dir: string, fallbackFilename: string, ): Promise { - for (const filename of getAllGeminiMdFilenames()) { + for (const filename of getAllMemoryFilenames()) { const filePath = path.join(dir, filename); try { await fs.access(filePath); @@ -2321,7 +2321,7 @@ async function resolveQwenMemoryPaths(params: { cwd: string; projectRoot: string; }): Promise { - const fallbackFilename = getAllGeminiMdFilenames()[0] ?? 'QWEN.md'; + const fallbackFilename = getAllMemoryFilenames()[0] ?? 'QWEN.md'; const userMemoryFile = await resolvePreferredMemoryFile( Storage.getGlobalQwenDir(), fallbackFilename, diff --git a/packages/cli/src/config/config.test.ts b/packages/cli/src/config/config.test.ts index 34f724ec56d..45552fd5e72 100644 --- a/packages/cli/src/config/config.test.ts +++ b/packages/cli/src/config/config.test.ts @@ -1169,15 +1169,15 @@ describe('loadCliConfig', () => { process.argv = ['node', 'script.js']; const argv = await parseArguments(); const settings: Settings = {}; - const setGeminiMdFilenameSpy = vi.spyOn( + const setMemoryFilenameSpy = vi.spyOn( ServerConfig, - 'setGeminiMdFilename', + 'setMemoryFilename', ); await loadCliConfig(settings, argv); - expect(setGeminiMdFilenameSpy).toHaveBeenCalledTimes(1); - expect(setGeminiMdFilenameSpy).toHaveBeenCalledWith([ + expect(setMemoryFilenameSpy).toHaveBeenCalledTimes(1); + expect(setMemoryFilenameSpy).toHaveBeenCalledWith([ ServerConfig.DEFAULT_CONTEXT_FILENAME, ServerConfig.AGENT_CONTEXT_FILENAME, ]); @@ -1270,15 +1270,15 @@ describe('loadCliConfig', () => { fileName: 'CUSTOM_AGENTS.md', }, }; - const setGeminiMdFilenameSpy = vi.spyOn( + const setMemoryFilenameSpy = vi.spyOn( ServerConfig, - 'setGeminiMdFilename', + 'setMemoryFilename', ); await loadCliConfig(settings, argv); - expect(setGeminiMdFilenameSpy).toHaveBeenCalledTimes(1); - expect(setGeminiMdFilenameSpy).toHaveBeenCalledWith('CUSTOM_AGENTS.md'); + expect(setMemoryFilenameSpy).toHaveBeenCalledTimes(1); + expect(setMemoryFilenameSpy).toHaveBeenCalledWith('CUSTOM_AGENTS.md'); }); it('should propagate stream-json formats to config', async () => { @@ -2100,9 +2100,9 @@ describe('loadCliConfig', () => { const settings: Settings = {}; const defaultContextFiles = ['QWEN.md', 'AGENTS.md']; const getAllSpy = vi - .spyOn(ServerConfig, 'getAllGeminiMdFilenames') + .spyOn(ServerConfig, 'getAllMemoryFilenames') .mockReturnValue(defaultContextFiles); - const setFilenameSpy = vi.spyOn(ServerConfig, 'setGeminiMdFilename'); + const setFilenameSpy = vi.spyOn(ServerConfig, 'setMemoryFilename'); await loadCliConfig(settings, argv); @@ -2114,8 +2114,8 @@ describe('loadCliConfig', () => { process.argv = ['node', 'script.js']; const argv = await parseArguments(); const settings: Settings = { context: { fileName: 'CUSTOM_CONTEXT.md' } }; - const getAllSpy = vi.spyOn(ServerConfig, 'getAllGeminiMdFilenames'); - const setFilenameSpy = vi.spyOn(ServerConfig, 'setGeminiMdFilename'); + const getAllSpy = vi.spyOn(ServerConfig, 'getAllMemoryFilenames'); + const setFilenameSpy = vi.spyOn(ServerConfig, 'setMemoryFilename'); await loadCliConfig(settings, argv); diff --git a/packages/cli/src/config/config.ts b/packages/cli/src/config/config.ts index 78d166edfb8..c8b74cb59b9 100755 --- a/packages/cli/src/config/config.ts +++ b/packages/cli/src/config/config.ts @@ -12,11 +12,11 @@ import { Config, DEFAULT_QWEN_EMBEDDING_MODEL, FileDiscoveryService, - getAllGeminiMdFilenames, + getAllMemoryFilenames, loadServerHierarchicalMemory, type LoadServerHierarchicalMemoryOptions, type LoadServerHierarchicalMemoryResponse, - setGeminiMdFilename as setServerGeminiMdFilename, + setMemoryFilename as setServerMemoryFilename, resolveTelemetrySettings, FatalConfigError, Storage, @@ -1613,13 +1613,13 @@ export async function loadCliConfig( // Set the context filename in the server's memoryTool module BEFORE loading memory // TODO(b/343434939): This is a bit of a hack. The contextFileName should ideally be passed - // directly to the Config constructor in core, and have core handle setGeminiMdFilename. + // directly to the Config constructor in core, and have core handle setMemoryFilename. // However, loadHierarchicalGeminiMemory is called *before* createServerConfig. if (settings.context?.fileName) { - setServerGeminiMdFilename(settings.context.fileName); + setServerMemoryFilename(settings.context.fileName); } else { // Reset to default context filenames if not provided in settings. - setServerGeminiMdFilename(getAllGeminiMdFilenames()); + setServerMemoryFilename(getAllMemoryFilenames()); } // Automatically load output-language.md if it exists diff --git a/packages/cli/src/core/initializer.test.ts b/packages/cli/src/core/initializer.test.ts index f57a1d8f6e2..84c33fe8460 100644 --- a/packages/cli/src/core/initializer.test.ts +++ b/packages/cli/src/core/initializer.test.ts @@ -44,7 +44,7 @@ describe('initializeApp', () => { let mockConfig: { getModelsConfig: ReturnType; getIdeMode: ReturnType; - getGeminiMdFileCount: ReturnType; + getMemoryFileCount: ReturnType; }; let mockSettings: { merged: Record; @@ -60,7 +60,7 @@ describe('initializeApp', () => { wasAuthTypeExplicitlyProvided: vi.fn().mockReturnValue(false), }), getIdeMode: vi.fn().mockReturnValue(false), - getGeminiMdFileCount: vi.fn().mockReturnValue(0), + getMemoryFileCount: vi.fn().mockReturnValue(0), }; mockSettings = { diff --git a/packages/cli/src/core/initializer.ts b/packages/cli/src/core/initializer.ts index 0e256b2aa79..a67626aa513 100644 --- a/packages/cli/src/core/initializer.ts +++ b/packages/cli/src/core/initializer.ts @@ -82,6 +82,6 @@ export async function initializeApp( authError, themeError, shouldOpenAuthDialog, - geminiMdFileCount: config.getGeminiMdFileCount(), + geminiMdFileCount: config.getMemoryFileCount(), }; } diff --git a/packages/cli/src/gemini.test.tsx b/packages/cli/src/gemini.test.tsx index 583ba0715b4..85cc346974a 100644 --- a/packages/cli/src/gemini.test.tsx +++ b/packages/cli/src/gemini.test.tsx @@ -414,7 +414,7 @@ describe('gemini.tsx main function', () => { getIdeMode: () => false, getExperimentalZedIntegration: () => false, getScreenReader: () => false, - getGeminiMdFileCount: () => 0, + getMemoryFileCount: () => 0, getProjectRoot: () => '/', getOutputFormat: () => OutputFormat.TEXT, getWarnings: () => [], @@ -811,7 +811,7 @@ describe('gemini.tsx main function', () => { getIdeMode: () => false, getExperimentalZedIntegration: () => false, getScreenReader: () => false, - getGeminiMdFileCount: () => 0, + getMemoryFileCount: () => 0, getProjectRoot: () => '/', getOutputFormat: () => OutputFormat.TEXT, getWarnings: () => [], @@ -1107,7 +1107,7 @@ describe('gemini.tsx main function', () => { getIdeMode: () => false, getExperimentalZedIntegration: () => false, getScreenReader: () => false, - getGeminiMdFileCount: () => 0, + getMemoryFileCount: () => 0, getProjectRoot: () => '/', getOutputFormat: () => OutputFormat.TEXT, getWarnings: () => (initialized ? ['late memory warning'] : []), @@ -1525,7 +1525,7 @@ describe('gemini.tsx main function', () => { getIdeMode: () => false, getExperimentalZedIntegration: () => false, getScreenReader: () => false, - getGeminiMdFileCount: () => 0, + getMemoryFileCount: () => 0, getProjectRoot: () => '/', getInputFormat: () => 'stream-json', getContentGeneratorConfig: () => ({ authType: 'test-auth' }), @@ -1721,7 +1721,7 @@ describe('gemini.tsx main function kitty protocol', () => { getIdeMode: () => false, getExperimentalZedIntegration: () => false, getScreenReader: () => false, - getGeminiMdFileCount: () => 0, + getMemoryFileCount: () => 0, getWarnings: () => [], isSafeMode: () => false, getModelsConfig: () => ({ getCurrentAuthType: () => null }), @@ -1848,7 +1848,7 @@ describe('gemini.tsx main function kitty protocol', () => { getIdeMode: () => false, getExperimentalZedIntegration: () => false, getScreenReader: () => false, - getGeminiMdFileCount: () => 0, + getMemoryFileCount: () => 0, getWarnings: () => [], isSafeMode: () => false, getModelsConfig: () => ({ getCurrentAuthType: () => null }), @@ -1974,7 +1974,7 @@ describe('gemini.tsx main function kitty protocol', () => { getIdeMode: () => false, getExperimentalZedIntegration: () => false, getScreenReader: () => false, - getGeminiMdFileCount: () => 0, + getMemoryFileCount: () => 0, getWarnings: () => [], isSafeMode: () => false, getModelsConfig: () => ({ getCurrentAuthType: () => null }), @@ -2097,7 +2097,7 @@ describe('gemini.tsx main function kitty protocol', () => { getIdeMode: () => false, getExperimentalZedIntegration: () => true, getScreenReader: () => false, - getGeminiMdFileCount: () => 0, + getMemoryFileCount: () => 0, getWarnings: () => [], isSafeMode: () => false, getModelsConfig: () => ({ getCurrentAuthType: () => null }), @@ -2239,7 +2239,7 @@ describe('gemini.tsx main function kitty protocol', () => { getIdeMode: () => false, getExperimentalZedIntegration: () => false, getScreenReader: () => false, - getGeminiMdFileCount: () => 0, + getMemoryFileCount: () => 0, getWarnings: () => [], isSafeMode: () => false, getModelsConfig: () => ({ @@ -2558,7 +2558,7 @@ describe('gemini.tsx main function kitty protocol', () => { getIdeMode: () => false, getExperimentalZedIntegration: () => false, getScreenReader: () => false, - getGeminiMdFileCount: () => 0, + getMemoryFileCount: () => 0, getWarnings: () => [], isSafeMode: () => false, getModelsConfig: () => ({ getCurrentAuthType: () => null }), diff --git a/packages/cli/src/serve/capabilities.ts b/packages/cli/src/serve/capabilities.ts index 46044d94f72..b77608d27a2 100644 --- a/packages/cli/src/serve/capabilities.ts +++ b/packages/cli/src/serve/capabilities.ts @@ -207,7 +207,7 @@ export const SERVE_CAPABILITY_REGISTRY = { // without restarting the daemon. V2 trust status exposes convergence. workspace_trust_hot_reload: { since: 'v1' }, // `POST /workspace/init` scaffolds an empty - // `QWEN.md` (or whatever `getCurrentGeminiMdFilename()` returns) at + // `QWEN.md` (or whatever `getCurrentMemoryFilename()` returns) at // the bound workspace root. Body: `{force?: boolean}`. Default // refuses with 409 when the file already exists; `force: true` // overwrites. Mechanical only — does NOT call the LLM. To AI-fill diff --git a/packages/cli/src/serve/run-qwen-serve.ts b/packages/cli/src/serve/run-qwen-serve.ts index a68cabcf1e2..9b3c6f49329 100644 --- a/packages/cli/src/serve/run-qwen-serve.ts +++ b/packages/cli/src/serve/run-qwen-serve.ts @@ -697,7 +697,7 @@ export function formatChannelWorkerDaemonUrl( * - anything else (object, number, boolean, undefined) → undefined * * Returning `undefined` is the bridge's signal to use its own - * `getCurrentGeminiMdFilename()` default — so a malformed value + * `getCurrentMemoryFilename()` default — so a malformed value * keeps the daemon alive rather than producing a garbage filename. */ export function extractContextFilename(value: unknown): string | undefined { diff --git a/packages/cli/src/serve/workspace-memory.test.ts b/packages/cli/src/serve/workspace-memory.test.ts index 861de9edb65..bd8d1bb4675 100644 --- a/packages/cli/src/serve/workspace-memory.test.ts +++ b/packages/cli/src/serve/workspace-memory.test.ts @@ -22,7 +22,7 @@ import { AGENT_CONTEXT_FILENAME, DEFAULT_CONTEXT_FILENAME, Storage, - setGeminiMdFilename, + setMemoryFilename, } from '@qwen-code/qwen-code-core'; import { createMutationGate } from './auth.js'; import { @@ -166,7 +166,7 @@ function buildApp(opts: { } function resetContextFilenames(): void { - setGeminiMdFilename([DEFAULT_CONTEXT_FILENAME, AGENT_CONTEXT_FILENAME]); + setMemoryFilename([DEFAULT_CONTEXT_FILENAME, AGENT_CONTEXT_FILENAME]); } describe('workspace memory routes', () => { diff --git a/packages/cli/src/serve/workspace-memory.ts b/packages/cli/src/serve/workspace-memory.ts index 481bcbaca59..c436f42ebcb 100644 --- a/packages/cli/src/serve/workspace-memory.ts +++ b/packages/cli/src/serve/workspace-memory.ts @@ -11,7 +11,7 @@ import { Storage, WorkspaceMemoryFileTooLargeError, WorkspaceMemoryWriteTimeoutError, - getAllGeminiMdFilenames, + getAllMemoryFilenames, writeWorkspaceContextFile, } from '@qwen-code/qwen-code-core'; import { writeStderrLine } from '../utils/stdioHelpers.js'; @@ -502,7 +502,7 @@ interface DiscoveredFile { export async function collectWorkspaceMemoryStatus( boundWorkspace: string, ): Promise { - const filenames = new Set(getAllGeminiMdFilenames()); + const filenames = new Set(getAllMemoryFilenames()); const files: DiscoveredFile[] = []; const errors: ServeWorkspaceMemoryStatus['errors'] = []; diff --git a/packages/cli/src/ui/AppContainer.tsx b/packages/cli/src/ui/AppContainer.tsx index edd9e5e15c1..87e22617d96 100644 --- a/packages/cli/src/ui/AppContainer.tsx +++ b/packages/cli/src/ui/AppContainer.tsx @@ -42,7 +42,7 @@ import { ideContextStore, createDebugLogger, getErrorMessage, - getAllGeminiMdFilenames, + getAllMemoryFilenames, ShellExecutionService, Storage, createInstructionsLoadedCallback, @@ -684,7 +684,7 @@ export const AppContainer = (props: AppContainerProps) => { const [isProcessing, setIsProcessing] = useState(false); const [embeddedShellFocused, setEmbeddedShellFocused] = useState(false); - const [geminiMdFileCount, setGeminiMdFileCount] = useState( + const [geminiMdFileCount, setMemoryFileCount] = useState( initializationResult.geminiMdFileCount, ); const [shellModeActive, setShellModeActive] = useState(false); @@ -1927,7 +1927,7 @@ export const AppContainer = (props: AppContainerProps) => { isProcessing, setIsProcessing, isIdleRef, - setGeminiMdFileCount, + setMemoryFileCount, slashCommandActions, extensionsUpdateStateInternal, isConfigInitialized, @@ -2063,12 +2063,12 @@ export const AppContainer = (props: AppContainerProps) => { // Safe mode: skip all context file loading, matching refreshHierarchicalMemory() if (config.isSafeMode()) { config.setUserMemory(''); - config.setGeminiMdFileCount(0); + config.setMemoryFileCount(0); config.setContextFilePaths([]); config.setConditionalRulesRegistry( new ConditionalRulesRegistry([], config.getWorkingDir()), ); - setGeminiMdFileCount(0); + setMemoryFileCount(0); historyManager.addItem( { type: MessageType.INFO, @@ -2112,12 +2112,12 @@ export const AppContainer = (props: AppContainerProps) => { ); config.setUserMemory(memoryContent); - config.setGeminiMdFileCount(fileCount); + config.setMemoryFileCount(fileCount); config.setContextFilePaths(contextFilePaths); config.setConditionalRulesRegistry( new ConditionalRulesRegistry(conditionalRules, projectRoot), ); - setGeminiMdFileCount(fileCount); + setMemoryFileCount(fileCount); historyManager.addItem( { @@ -3159,7 +3159,7 @@ export const AppContainer = (props: AppContainerProps) => { ? Array.isArray(fromSettings) ? fromSettings : [fromSettings] - : getAllGeminiMdFilenames(); + : getAllMemoryFilenames(); }, [settings.merged.context?.fileName]); // Initial prompt handling const initialPrompt = useMemo(() => config.getQuestion(), [config]); diff --git a/packages/cli/src/ui/commands/directoryCommand.test.tsx b/packages/cli/src/ui/commands/directoryCommand.test.tsx index a64e1c2abe3..5d44de70004 100644 --- a/packages/cli/src/ui/commands/directoryCommand.test.tsx +++ b/packages/cli/src/ui/commands/directoryCommand.test.tsx @@ -87,7 +87,7 @@ describe('directoryCommand', () => { getExtensionContextFilePaths: () => [], getFileFilteringOptions: () => ({ ignore: [], include: [] }), setUserMemory: vi.fn(), - setGeminiMdFileCount: vi.fn(), + setMemoryFileCount: vi.fn(), } as unknown as Config; mockContext = { @@ -263,7 +263,7 @@ describe('directoryCommand', () => { mockConfig.getContextRuleExcludes = vi.fn().mockReturnValue([]); mockConfig.setContextFilePaths = vi.fn(); mockConfig.setConditionalRulesRegistry = vi.fn(); - mockContext.ui.setGeminiMdFileCount = vi.fn(); + mockContext.ui.setMemoryFileCount = vi.fn(); if (!addCommand?.action) throw new Error('No action'); await addCommand.action( diff --git a/packages/cli/src/ui/commands/directoryCommand.tsx b/packages/cli/src/ui/commands/directoryCommand.tsx index b27db975830..ef8e9be1709 100644 --- a/packages/cli/src/ui/commands/directoryCommand.tsx +++ b/packages/cli/src/ui/commands/directoryCommand.tsx @@ -258,12 +258,12 @@ export const directoryCommand: SlashCommand = { config.getContextRuleExcludes(), ); config.setUserMemory(memoryContent); - config.setGeminiMdFileCount(fileCount); + config.setMemoryFileCount(fileCount); config.setContextFilePaths(contextFilePaths); config.setConditionalRulesRegistry( new ConditionalRulesRegistry(conditionalRules, projectRoot), ); - context.ui.setGeminiMdFileCount(fileCount); + context.ui.setMemoryFileCount(fileCount); messages.push( t( 'Successfully added QWEN.md files from the following directories if there are:\n- {{directories}}', diff --git a/packages/cli/src/ui/commands/initCommand.ts b/packages/cli/src/ui/commands/initCommand.ts index de879c34582..8794017fc89 100644 --- a/packages/cli/src/ui/commands/initCommand.ts +++ b/packages/cli/src/ui/commands/initCommand.ts @@ -11,7 +11,7 @@ import type { SlashCommand, SlashCommandActionReturn, } from './types.js'; -import { getCurrentGeminiMdFilename } from '@qwen-code/qwen-code-core'; +import { getCurrentMemoryFilename } from '@qwen-code/qwen-code-core'; import { CommandKind } from './types.js'; import { t } from '../../i18n/index.js'; @@ -34,7 +34,7 @@ export const initCommand: SlashCommand = { }; } const targetDir = context.services.config.getTargetDir(); - const contextFileName = getCurrentGeminiMdFilename(); + const contextFileName = getCurrentMemoryFilename(); const contextFilePath = path.join(targetDir, contextFileName); try { diff --git a/packages/cli/src/ui/commands/types.ts b/packages/cli/src/ui/commands/types.ts index 0f7b3396081..d6621dbc409 100644 --- a/packages/cli/src/ui/commands/types.ts +++ b/packages/cli/src/ui/commands/types.ts @@ -97,7 +97,7 @@ export interface CommandContext { /** Refreshes the static history display in Ink. */ refreshStatic: () => void; toggleVimEnabled: () => Promise; - setGeminiMdFileCount: (count: number) => void; + setMemoryFileCount: (count: number) => void; reloadCommands: () => void | Promise; setSessionName: (name: string | null) => void; extensionsUpdateState: Map; diff --git a/packages/cli/src/ui/components/Footer.tsx b/packages/cli/src/ui/components/Footer.tsx index 8724a987ee3..e9a52b3ccda 100644 --- a/packages/cli/src/ui/components/Footer.tsx +++ b/packages/cli/src/ui/components/Footer.tsx @@ -22,7 +22,7 @@ import { useUIState } from '../contexts/UIStateContext.js'; import { useConfig } from '../contexts/ConfigContext.js'; import { useSettings } from '../contexts/SettingsContext.js'; import { useVimModeState } from '../contexts/VimModeContext.js'; -import { GeminiSpinner } from './GeminiRespondingSpinner.js'; +import { Spinner } from './RespondingSpinner.js'; import { GoalPill, isLiveGoalSnapshot, @@ -129,11 +129,11 @@ export const Footer: React.FC = ({ containerRef }) => { ) : configInitMessage ? ( - {configInitMessage} + {configInitMessage} ) : uiState.startupIdeConnectionStatus.state === 'connecting' ? ( - {t('IDE connecting... context may be unavailable')} + {t('IDE connecting... context may be unavailable')} ) : uiState.startupIdeConnectionStatus.state === 'failed' ? ( diff --git a/packages/cli/src/ui/components/LoadingIndicator.test.tsx b/packages/cli/src/ui/components/LoadingIndicator.test.tsx index ffd32dd5729..789d3f664e1 100644 --- a/packages/cli/src/ui/components/LoadingIndicator.test.tsx +++ b/packages/cli/src/ui/components/LoadingIndicator.test.tsx @@ -13,9 +13,9 @@ import { StreamingState } from '../types.js'; import { vi } from 'vitest'; import * as useTerminalSize from '../hooks/useTerminalSize.js'; -// Mock GeminiRespondingSpinner -vi.mock('./GeminiRespondingSpinner.js', () => ({ - GeminiRespondingSpinner: ({ +// Mock RespondingSpinner +vi.mock('./RespondingSpinner.js', () => ({ + RespondingSpinner: ({ nonRespondingDisplay, }: { nonRespondingDisplay?: string; diff --git a/packages/cli/src/ui/components/LoadingIndicator.tsx b/packages/cli/src/ui/components/LoadingIndicator.tsx index fa1571be42a..cbdbec6f5c3 100644 --- a/packages/cli/src/ui/components/LoadingIndicator.tsx +++ b/packages/cli/src/ui/components/LoadingIndicator.tsx @@ -10,7 +10,7 @@ import { Box, Text } from 'ink'; import { theme } from '../semantic-colors.js'; import { useStreamingContext } from '../contexts/StreamingContext.js'; import { StreamingState } from '../types.js'; -import { GeminiRespondingSpinner } from './GeminiRespondingSpinner.js'; +import { RespondingSpinner } from './RespondingSpinner.js'; import { formatDuration, formatTokenCount } from '../utils/formatters.js'; import { useTerminalSize } from '../hooks/useTerminalSize.js'; import { useAnimationFrame } from '../hooks/useAnimationFrame.js'; @@ -126,7 +126,7 @@ export const LoadingIndicator: React.FC = ({ > - { - for (const filename of getAllGeminiMdFilenames()) { + for (const filename of getAllMemoryFilenames()) { const filePath = path.join(dir, filename); try { await fs.access(filePath); @@ -150,7 +150,7 @@ export function MemoryDialog({ onClose }: MemoryDialogProps) { () => path.join( Storage.getGlobalQwenDir(), - getAllGeminiMdFilenames()[0] ?? 'QWEN.md', + getAllMemoryFilenames()[0] ?? 'QWEN.md', ), [], ); @@ -158,7 +158,7 @@ export function MemoryDialog({ onClose }: MemoryDialogProps) { () => path.join( config.getWorkingDir(), - getAllGeminiMdFilenames()[0] ?? 'QWEN.md', + getAllMemoryFilenames()[0] ?? 'QWEN.md', ), [config], ); @@ -273,12 +273,12 @@ export function MemoryDialog({ onClose }: MemoryDialogProps) { case 'project': return resolvePreferredMemoryFile( config.getWorkingDir(), - getAllGeminiMdFilenames()[0] ?? 'QWEN.md', + getAllMemoryFilenames()[0] ?? 'QWEN.md', ); case 'global': return resolvePreferredMemoryFile( Storage.getGlobalQwenDir(), - getAllGeminiMdFilenames()[0] ?? 'QWEN.md', + getAllMemoryFilenames()[0] ?? 'QWEN.md', ); default: { const _exhaustive: never = item.value; diff --git a/packages/cli/src/ui/components/GeminiRespondingSpinner.test.tsx b/packages/cli/src/ui/components/RespondingSpinner.test.tsx similarity index 70% rename from packages/cli/src/ui/components/GeminiRespondingSpinner.test.tsx rename to packages/cli/src/ui/components/RespondingSpinner.test.tsx index 979a946de89..9596cc19524 100644 --- a/packages/cli/src/ui/components/GeminiRespondingSpinner.test.tsx +++ b/packages/cli/src/ui/components/RespondingSpinner.test.tsx @@ -7,9 +7,9 @@ import { afterEach, describe, expect, it, vi } from 'vitest'; import { render } from 'ink-testing-library'; import { Text } from 'ink'; -import { GeminiSpinner } from './GeminiRespondingSpinner.js'; +import { Spinner } from './RespondingSpinner.js'; -describe('', () => { +describe('', () => { afterEach(() => { vi.unstubAllEnvs(); }); @@ -17,13 +17,13 @@ describe('', () => { it('uses a low-frequency fixed-width indicator inside tmux', () => { vi.stubEnv('TMUX', '/tmp/tmux-1000/default,12345,0'); - const { lastFrame } = render(); + const { lastFrame } = render(); expect(lastFrame()).toContain('.'); }); - // Regression: Footer.tsx renders inside a wrapper - // ('... {msg}'). Ink forbids from being + // Regression: Footer.tsx renders inside a wrapper + // ('... {msg}'). Ink forbids from being // nested inside , so the tmux branch must return a , not a // -wrapped one — otherwise the CLI throws on startup inside tmux. it('renders without throwing when nested inside a (Footer context)', () => { @@ -32,7 +32,7 @@ describe('', () => { expect(() => render( - startup message + startup message , ), ).not.toThrow(); diff --git a/packages/cli/src/ui/components/GeminiRespondingSpinner.tsx b/packages/cli/src/ui/components/RespondingSpinner.tsx similarity index 86% rename from packages/cli/src/ui/components/GeminiRespondingSpinner.tsx rename to packages/cli/src/ui/components/RespondingSpinner.tsx index a89297d9e30..119b2998d90 100644 --- a/packages/cli/src/ui/components/GeminiRespondingSpinner.tsx +++ b/packages/cli/src/ui/components/RespondingSpinner.tsx @@ -20,7 +20,7 @@ import { theme } from '../semantic-colors.js'; const TMUX_SPINNER_INTERVAL_MS = 750; const TMUX_SPINNER_FRAMES = ['. ', '..']; -interface GeminiRespondingSpinnerProps { +interface RespondingSpinnerProps { /** * Optional string to display when not in Responding state. * If not provided and not Responding, renders null. @@ -29,14 +29,14 @@ interface GeminiRespondingSpinnerProps { spinnerType?: SpinnerName; } -export const GeminiRespondingSpinner: React.FC< - GeminiRespondingSpinnerProps +export const RespondingSpinner: React.FC< + RespondingSpinnerProps > = ({ nonRespondingDisplay, spinnerType = 'dots' }) => { const streamingState = useStreamingContext(); const isScreenReaderEnabled = useIsScreenReaderEnabled(); if (streamingState === StreamingState.Responding) { return ( - @@ -51,12 +51,12 @@ export const GeminiRespondingSpinner: React.FC< return null; }; -interface GeminiSpinnerProps { +interface SpinnerProps { spinnerType?: SpinnerName; altText?: string; } -export const GeminiSpinner: React.FC = ({ +export const Spinner: React.FC = ({ spinnerType = 'dots', altText, }) => { @@ -81,8 +81,8 @@ export const GeminiSpinner: React.FC = ({ } if (isTmux) { - // Note: must NOT wrap in here — GeminiSpinner is rendered inside a - // in Footer.tsx (`... {msg}`), and + // Note: must NOT wrap in here — Spinner is rendered inside a + // in Footer.tsx (`... {msg}`), and // Ink forbids nested inside . The 2-char fixed-width frames // already give us stable layout without an explicit width container. return ( diff --git a/packages/cli/src/ui/components/agent-view/AgentChatContent.tsx b/packages/cli/src/ui/components/agent-view/AgentChatContent.tsx index c86b79d0d81..3b017cadae6 100644 --- a/packages/cli/src/ui/components/agent-view/AgentChatContent.tsx +++ b/packages/cli/src/ui/components/agent-view/AgentChatContent.tsx @@ -27,7 +27,7 @@ import { useAgentViewActions } from '../../contexts/AgentViewContext.js'; import { HistoryItemDisplay } from '../HistoryItemDisplay.js'; import { ToolCallStatus } from '../../types.js'; import { theme } from '../../semantic-colors.js'; -import { GeminiRespondingSpinner } from '../GeminiRespondingSpinner.js'; +import { RespondingSpinner } from '../RespondingSpinner.js'; import { agentMessagesToHistoryItems } from './agentHistoryAdapter.js'; import { AgentHeader } from './AgentHeader.js'; import { buildThoughtHeadIdMap } from '../../utils/historyUtils.js'; @@ -267,7 +267,7 @@ export const AgentChatContent = ({ {/* Spinner */} {isRunning && ( - + )} diff --git a/packages/cli/src/ui/components/agent-view/AgentComposer.tsx b/packages/cli/src/ui/components/agent-view/AgentComposer.tsx index d64298d8239..f9704a04bd8 100644 --- a/packages/cli/src/ui/components/agent-view/AgentComposer.tsx +++ b/packages/cli/src/ui/components/agent-view/AgentComposer.tsx @@ -13,7 +13,7 @@ * - Keyboard events are scoped — no conflict with the main InputPrompt * * Wraps its content in a local StreamingContext.Provider so reusable - * components like LoadingIndicator and GeminiRespondingSpinner read the + * components like LoadingIndicator and RespondingSpinner read the * agent's derived streaming state instead of the main agent's. */ diff --git a/packages/cli/src/ui/components/messages/CompactToolGroupDisplay.test.tsx b/packages/cli/src/ui/components/messages/CompactToolGroupDisplay.test.tsx index a689eb2edf3..cf24d51aedd 100644 --- a/packages/cli/src/ui/components/messages/CompactToolGroupDisplay.test.tsx +++ b/packages/cli/src/ui/components/messages/CompactToolGroupDisplay.test.tsx @@ -16,7 +16,7 @@ import { import { ToolCallStatus } from '../../types.js'; import type { IndividualToolCallDisplay } from '../../types.js'; -// ToolStatusIndicator pulls in GeminiRespondingSpinner which requires +// ToolStatusIndicator pulls in RespondingSpinner which requires // StreamingContext; stub the component but keep the real constant so // height-estimation tests stay in sync with production. vi.mock('../shared/ToolStatusIndicator.js', async (importOriginal) => ({ diff --git a/packages/cli/src/ui/components/messages/ToolMessage.test.tsx b/packages/cli/src/ui/components/messages/ToolMessage.test.tsx index bbc774768e8..89d456d2fe4 100644 --- a/packages/cli/src/ui/components/messages/ToolMessage.test.tsx +++ b/packages/cli/src/ui/components/messages/ToolMessage.test.tsx @@ -89,8 +89,8 @@ vi.mock('../TerminalImage.js', () => ({ })); // Mock child components or utilities if they are complex or have side effects -vi.mock('../GeminiRespondingSpinner.js', () => ({ - GeminiRespondingSpinner: ({ +vi.mock('../RespondingSpinner.js', () => ({ + RespondingSpinner: ({ nonRespondingDisplay, }: { nonRespondingDisplay?: string; diff --git a/packages/cli/src/ui/components/shared/ToolStatusIndicator.tsx b/packages/cli/src/ui/components/shared/ToolStatusIndicator.tsx index bc888f9e59c..16163048e41 100644 --- a/packages/cli/src/ui/components/shared/ToolStatusIndicator.tsx +++ b/packages/cli/src/ui/components/shared/ToolStatusIndicator.tsx @@ -7,7 +7,7 @@ import type React from 'react'; import { Box, Text } from 'ink'; import { ToolCallStatus } from '../../types.js'; -import { GeminiRespondingSpinner } from '../GeminiRespondingSpinner.js'; +import { RespondingSpinner } from '../RespondingSpinner.js'; import { TOOL_STATUS, SHELL_COMMAND_NAME, @@ -42,7 +42,7 @@ export const ToolStatusIndicator: React.FC = ({ {TOOL_STATUS.PENDING} )} {status === ToolCallStatus.Executing && ( - diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts index 24f771a84bb..ba1bbc52d37 100644 --- a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts +++ b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts @@ -252,7 +252,7 @@ describe('useSlashCommandProcessor', () => { false, // isProcessing setIsProcessing, isIdleRef, - vi.fn(), // setGeminiMdFileCount + vi.fn(), // setMemoryFileCount createMockActions(), new Map(), // extensionsUpdateState true, // isConfigInitialized @@ -2352,7 +2352,7 @@ describe('useSlashCommandProcessor', () => { false, // isProcessing vi.fn(), // setIsProcessing { current: true }, // isIdleRef - vi.fn(), // setGeminiMdFileCount + vi.fn(), // setMemoryFileCount createMockActions(), new Map(), // extensionsUpdateState true, // isConfigInitialized diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.ts index b02ee3da803..65d43800e04 100644 --- a/packages/cli/src/ui/hooks/slashCommandProcessor.ts +++ b/packages/cli/src/ui/hooks/slashCommandProcessor.ts @@ -222,7 +222,7 @@ export const useSlashCommandProcessor = ( isProcessing: boolean, setIsProcessing: (isProcessing: boolean) => void, isIdleRef: MutableRefObject, - setGeminiMdFileCount: (count: number) => void, + setMemoryFileCount: (count: number) => void, actions: SlashCommandProcessorActions, extensionsUpdateState: Map, isConfigInitialized: boolean, @@ -539,7 +539,7 @@ export const useSlashCommandProcessor = ( btwAbortControllerRef, isIdleRef, toggleVimEnabled, - setGeminiMdFileCount, + setMemoryFileCount, reloadCommands, setSessionName: setSessionName ?? (() => {}), extensionsUpdateState, @@ -572,7 +572,7 @@ export const useSlashCommandProcessor = ( cancelBtw, toggleVimEnabled, sessionShellAllowlist, - setGeminiMdFileCount, + setMemoryFileCount, reloadCommands, setSessionName, extensionsUpdateState, diff --git a/packages/cli/src/ui/hooks/useAutoAcceptIndicator.test.ts b/packages/cli/src/ui/hooks/useAutoAcceptIndicator.test.ts index 05a397e3e63..f43d92e08af 100644 --- a/packages/cli/src/ui/hooks/useAutoAcceptIndicator.test.ts +++ b/packages/cli/src/ui/hooks/useAutoAcceptIndicator.test.ts @@ -54,7 +54,7 @@ interface MockConfigInstanceShape { getFullContext: Mock<() => boolean>; getUserAgent: Mock<() => string>; getUserMemory: Mock<() => string>; - getGeminiMdFileCount: Mock<() => number>; + getMemoryFileCount: Mock<() => number>; getToolRegistry: Mock<() => { discoverTools: Mock<() => void> }>; } @@ -110,7 +110,7 @@ describe('useAutoAcceptIndicator', () => { () => string >, getUserMemory: vi.fn().mockReturnValue('') as Mock<() => string>, - getGeminiMdFileCount: vi.fn().mockReturnValue(0) as Mock<() => number>, + getMemoryFileCount: vi.fn().mockReturnValue(0) as Mock<() => number>, getToolRegistry: vi .fn() .mockReturnValue({ discoverTools: vi.fn() }) as Mock< diff --git a/packages/cli/src/ui/hooks/useGeminiStream.ts b/packages/cli/src/ui/hooks/useGeminiStream.ts index 0b0cc0454ad..02d586c1ec2 100644 --- a/packages/cli/src/ui/hooks/useGeminiStream.ts +++ b/packages/cli/src/ui/hooks/useGeminiStream.ts @@ -26,7 +26,7 @@ import { type ThoughtSummary, type ToolCallRequestInfo, type ToolCallResponseInfo, - type GeminiErrorEventValue, + type LlmErrorEventValue, type GoalTurnPermit, type SteerInput, GeminiEventType as ServerGeminiEventType, @@ -2095,7 +2095,7 @@ export const useGeminiStream = ( const handleErrorEvent = useCallback( ( - eventValue: GeminiErrorEventValue, + eventValue: LlmErrorEventValue, userMessageTimestamp: number, submitType: SendMessageType, ) => { diff --git a/packages/cli/src/ui/hooks/useShowMemoryCommand.test.ts b/packages/cli/src/ui/hooks/useShowMemoryCommand.test.ts index aa5e9b19e51..91024679897 100644 --- a/packages/cli/src/ui/hooks/useShowMemoryCommand.test.ts +++ b/packages/cli/src/ui/hooks/useShowMemoryCommand.test.ts @@ -38,7 +38,7 @@ function createMockConfig({ return { getUserMemory: () => userMemory, getAutoMemoryPrompt: () => autoMemoryPrompt, - getGeminiMdFileCount: () => fileCount, + getMemoryFileCount: () => fileCount, } as unknown as Config; } diff --git a/packages/cli/src/ui/hooks/useShowMemoryCommand.ts b/packages/cli/src/ui/hooks/useShowMemoryCommand.ts index 47ca472e169..7f0a0e93d22 100644 --- a/packages/cli/src/ui/hooks/useShowMemoryCommand.ts +++ b/packages/cli/src/ui/hooks/useShowMemoryCommand.ts @@ -34,7 +34,7 @@ export function createShowMemoryAction( const currentMemory = [contextMemory, autoMemoryPrompt] .filter((section) => section.trim().length > 0) .join('\n\n---\n\n'); - const fileCount = config.getGeminiMdFileCount(); + const fileCount = config.getMemoryFileCount(); const contextFileName = settings.merged.context?.fileName; const contextFileNames = Array.isArray(contextFileName) ? contextFileName diff --git a/packages/cli/src/ui/noninteractive/nonInteractiveUi.ts b/packages/cli/src/ui/noninteractive/nonInteractiveUi.ts index e9380f61fb9..81cacdea815 100644 --- a/packages/cli/src/ui/noninteractive/nonInteractiveUi.ts +++ b/packages/cli/src/ui/noninteractive/nonInteractiveUi.ts @@ -28,7 +28,7 @@ export function createNonInteractiveUI(): CommandContext['ui'] { btwAbortControllerRef: { current: null }, isIdleRef: { current: true }, toggleVimEnabled: async () => false, - setGeminiMdFileCount: (_count) => {}, + setMemoryFileCount: (_count) => {}, reloadCommands: () => {}, setSessionName: () => {}, extensionsUpdateState: new Map(), diff --git a/packages/core/src/config/config-session-env.test.ts b/packages/core/src/config/config-session-env.test.ts index ff3fba98df8..a9e596a9c21 100644 --- a/packages/core/src/config/config-session-env.test.ts +++ b/packages/core/src/config/config-session-env.test.ts @@ -89,7 +89,7 @@ vi.mock('../ide/ide-client.js', () => ({ }, })); vi.mock('../utils/memory-constants.js', () => ({ - setGeminiMdFilename: vi.fn(), + setMemoryFilename: vi.fn(), })); import * as fs from 'node:fs'; diff --git a/packages/core/src/config/config.safe-mode.test.ts b/packages/core/src/config/config.safe-mode.test.ts index 954e1fc0388..cf9524f8cdf 100644 --- a/packages/core/src/config/config.safe-mode.test.ts +++ b/packages/core/src/config/config.safe-mode.test.ts @@ -469,7 +469,7 @@ describe('Config safe mode', () => { await config.initialize(); expect(config.getUserMemory()).toBe(''); expect(config.getAutoMemoryPrompt()).toBe(''); - expect(config.getGeminiMdFileCount()).toBe(0); + expect(config.getMemoryFileCount()).toBe(0); }); it('records every fixed Config startup phase in order when skipped', async () => { diff --git a/packages/core/src/config/config.test.ts b/packages/core/src/config/config.test.ts index 844ec875d45..89fc1f5e2e0 100644 --- a/packages/core/src/config/config.test.ts +++ b/packages/core/src/config/config.test.ts @@ -25,7 +25,7 @@ import { DEFAULT_MAX_TOOL_CALLS_PER_TURN } from '../services/loopDetectionServic import * as fs from 'node:fs'; import * as os from 'node:os'; import * as path from 'node:path'; -import { setGeminiMdFilename as mockSetGeminiMdFilename } from '../utils/memory-constants.js'; +import { setMemoryFilename as mockSetMemoryFilename } from '../utils/memory-constants.js'; import { DEFAULT_TELEMETRY_TARGET, DEFAULT_OTLP_ENDPOINT, @@ -289,15 +289,15 @@ vi.mock('../tools/read-many-files', () => ({ ReadManyFilesTool: createToolMock('read_many_files'), })); vi.mock('../utils/memory-constants.js', () => ({ - setGeminiMdFilename: vi.fn(), - getCurrentGeminiMdFilename: vi.fn(() => 'QWEN.md'), // Mock the original filename - getAllGeminiMdFilenames: vi.fn(() => ['QWEN.md', 'AGENTS.md']), + setMemoryFilename: vi.fn(), + getCurrentMemoryFilename: vi.fn(() => 'QWEN.md'), // Mock the original filename + getAllMemoryFilenames: vi.fn(() => ['QWEN.md', 'AGENTS.md']), DEFAULT_CONTEXT_FILENAME: 'QWEN.md', })); vi.mock('../tools/memory-config', () => ({ - setGeminiMdFilename: vi.fn(), - getCurrentGeminiMdFilename: vi.fn(() => 'QWEN.md'), - getAllGeminiMdFilenames: vi.fn(() => ['QWEN.md', 'AGENTS.md']), + setMemoryFilename: vi.fn(), + getCurrentMemoryFilename: vi.fn(() => 'QWEN.md'), + getAllMemoryFilenames: vi.fn(() => ['QWEN.md', 'AGENTS.md']), DEFAULT_CONTEXT_FILENAME: 'QWEN.md', AGENT_CONTEXT_FILENAME: 'AGENTS.md', MEMORY_SECTION_HEADER: '## Qwen Added Memories', @@ -7508,19 +7508,19 @@ describe('Server Config (config.ts)', () => { ); }); - it('Config constructor should call setGeminiMdFilename with contextFileName if provided', () => { + it('Config constructor should call setMemoryFilename with contextFileName if provided', () => { const contextFileName = 'CUSTOM_AGENTS.md'; const paramsWithContextFile: ConfigParameters = { ...baseParams, contextFileName, }; new Config(paramsWithContextFile); - expect(mockSetGeminiMdFilename).toHaveBeenCalledWith(contextFileName); + expect(mockSetMemoryFilename).toHaveBeenCalledWith(contextFileName); }); - it('Config constructor should not call setGeminiMdFilename if contextFileName is not provided', () => { + it('Config constructor should not call setMemoryFilename if contextFileName is not provided', () => { new Config(baseParams); // baseParams does not have contextFileName - expect(mockSetGeminiMdFilename).not.toHaveBeenCalled(); + expect(mockSetMemoryFilename).not.toHaveBeenCalled(); }); it('should set default file filtering settings when not provided', () => { diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index a49dce42449..52dba22629c 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -80,7 +80,7 @@ import { getMCPServerStatus, type SendSdkMcpMessage, } from '../tools/mcp-client.js'; -import { setGeminiMdFilename } from '../utils/memory-constants.js'; +import { setMemoryFilename } from '../utils/memory-constants.js'; import { canUseRipgrep } from '../utils/ripgrepUtils.js'; import { recordStartupEvent } from '../utils/startupEventSink.js'; import { ToolRegistry, type ToolFactory } from '../tools/tool-registry.js'; @@ -2573,7 +2573,7 @@ export class Config { }); this.worktreeSettings = params.worktree ?? {}; if (params.contextFileName) { - setGeminiMdFilename(params.contextFileName); + setMemoryFilename(params.contextFileName); } // Create ModelsConfig for centralized model management @@ -3581,7 +3581,7 @@ export class Config { if (this.isSafeMode()) { this.setUserMemory(''); this.autoMemoryPrompt = ''; - this.setGeminiMdFileCount(0); + this.setMemoryFileCount(0); this.setContextFilePaths([]); this.conditionalRulesRegistry = new ConditionalRulesRegistry( [], @@ -3738,7 +3738,7 @@ export class Config { this.setUserMemory(memoryContent); this.autoMemoryPrompt = ''; } - this.setGeminiMdFileCount(fileCount); + this.setMemoryFileCount(fileCount); this.setContextFilePaths(contextFilePaths); this.conditionalRulesRegistry = new ConditionalRulesRegistry( conditionalRules, @@ -6377,11 +6377,11 @@ export class Config { this.userMemory = newUserMemory; } - getGeminiMdFileCount(): number { + getMemoryFileCount(): number { return this.geminiMdFileCount; } - setGeminiMdFileCount(count: number): void { + setMemoryFileCount(count: number): void { this.geminiMdFileCount = count; } diff --git a/packages/core/src/config/config.workflow-registration.test.ts b/packages/core/src/config/config.workflow-registration.test.ts index 36091afc0dd..b63f3fe91e9 100644 --- a/packages/core/src/config/config.workflow-registration.test.ts +++ b/packages/core/src/config/config.workflow-registration.test.ts @@ -76,7 +76,7 @@ vi.mock('../ide/ide-client.js', () => ({ }, })); vi.mock('../utils/memory-constants.js', () => ({ - setGeminiMdFilename: vi.fn(), + setMemoryFilename: vi.fn(), })); import * as fs from 'node:fs'; diff --git a/packages/core/src/config/config.workflows.test.ts b/packages/core/src/config/config.workflows.test.ts index 99228299903..766dd432001 100644 --- a/packages/core/src/config/config.workflows.test.ts +++ b/packages/core/src/config/config.workflows.test.ts @@ -76,7 +76,7 @@ vi.mock('../ide/ide-client.js', () => ({ }, })); vi.mock('../utils/memory-constants.js', () => ({ - setGeminiMdFilename: vi.fn(), + setMemoryFilename: vi.fn(), })); import * as fs from 'node:fs'; diff --git a/packages/core/src/core/geminiChat.ts b/packages/core/src/core/geminiChat.ts index 1a6816768de..854f903b81c 100644 --- a/packages/core/src/core/geminiChat.ts +++ b/packages/core/src/core/geminiChat.ts @@ -445,7 +445,7 @@ export type StreamEvent = | { type: StreamEventType.COMPRESSED; info: ChatCompressionInfo } | { type: StreamEventType.MODEL_FALLBACK; info: ModelFallbackInfo }; -export interface GeminiChatSendOptions { +export interface LlmChatSendOptions { /** Skip only the configured model fallback chain for this request. */ disableModelFallbacks?: boolean; } @@ -2559,7 +2559,7 @@ export class GeminiChat { params: SendMessageParameters, prompt_id: string, goalContext?: GoalTurnPermit, - options?: GeminiChatSendOptions, + options?: LlmChatSendOptions, ): Promise> { const turnGoalContext = goalContext ? { ...goalContext } : undefined; const fullTurnRoute = model.endsWith('\0'); diff --git a/packages/core/src/core/geminiRequest.test.ts b/packages/core/src/core/llm-request.test.ts similarity index 97% rename from packages/core/src/core/geminiRequest.test.ts rename to packages/core/src/core/llm-request.test.ts index 1e5687d0e46..5450ddeac1e 100644 --- a/packages/core/src/core/geminiRequest.test.ts +++ b/packages/core/src/core/llm-request.test.ts @@ -5,7 +5,7 @@ */ import { describe, it, expect } from 'vitest'; -import { partListUnionToString } from './geminiRequest.js'; +import { partListUnionToString } from './llm-request.js'; import { type Part } from '@google/genai'; describe('partListUnionToString', () => { diff --git a/packages/core/src/core/geminiRequest.ts b/packages/core/src/core/llm-request.ts similarity index 81% rename from packages/core/src/core/geminiRequest.ts rename to packages/core/src/core/llm-request.ts index 73a1873c15e..d36694b535d 100644 --- a/packages/core/src/core/geminiRequest.ts +++ b/packages/core/src/core/llm-request.ts @@ -8,11 +8,11 @@ import type { PartListUnion } from '@google/genai'; import { partToString } from '../utils/partUtils.js'; /** - * Represents a request to be sent to the Gemini API. + * Represents a request to be sent to the LLM API. * For now, it's an alias to PartListUnion as the primary content. * This can be expanded later to include other request parameters. */ -export type GeminiCodeRequest = PartListUnion; +export type LlmCodeRequest = PartListUnion; export function partListUnionToString(value: PartListUnion): string { return partToString(value, { verbose: true }); diff --git a/packages/core/src/core/turn.ts b/packages/core/src/core/turn.ts index 1c7c593854d..850de7421e5 100644 --- a/packages/core/src/core/turn.ts +++ b/packages/core/src/core/turn.ts @@ -109,7 +109,7 @@ export interface StructuredError { status?: number; } -export interface GeminiErrorEventValue { +export interface LlmErrorEventValue { error: StructuredError; } @@ -119,7 +119,7 @@ export interface SessionTokenLimitExceededValue { message: string; } -export interface GeminiFinishedEventValue { +export interface LlmFinishedEventValue { reason: FinishReason | undefined; usageMetadata: GenerateContentResponseUsageMetadata | undefined; } @@ -345,7 +345,7 @@ export type ServerGeminiUserCancelledEvent = { export type ServerGeminiErrorEvent = { type: GeminiEventType.Error; - value: GeminiErrorEventValue; + value: LlmErrorEventValue; }; export enum CompressionStatus { @@ -417,7 +417,7 @@ export type ServerGeminiSessionTokenLimitExceededEvent = { export type ServerGeminiFinishedEvent = { type: GeminiEventType.Finished; - value: GeminiFinishedEventValue; + value: LlmFinishedEventValue; }; export type ServerGeminiLoopDetectedEvent = { diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 5453a928a14..fdf86b6e596 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -84,7 +84,7 @@ export { findPlanModeEntryBatchBoundaryIndex, } from './core/plan-mode-entry-policy.js'; export * from './core/geminiChat.js'; -export * from './core/geminiRequest.js'; +export * from './core/llm-request.js'; export * from './core/inlineMediaLimit.js'; export * from './core/insightProtocol.js'; export * from './core/logger.js'; diff --git a/packages/core/src/memory/const.test.ts b/packages/core/src/memory/const.test.ts index 867cfd0b8f3..076e88a4c7e 100644 --- a/packages/core/src/memory/const.test.ts +++ b/packages/core/src/memory/const.test.ts @@ -8,14 +8,14 @@ import { vi, describe, it, expect, beforeEach } from 'vitest'; import { AGENT_CONTEXT_FILENAME, DEFAULT_CONTEXT_FILENAME, - setGeminiMdFilename, - getCurrentGeminiMdFilename, - getAllGeminiMdFilenames, + setMemoryFilename, + getCurrentMemoryFilename, + getAllMemoryFilenames, } from '../utils/memory-constants.js'; import { - setGeminiMdFilename as setToolGeminiMdFilename, - getCurrentGeminiMdFilename as getToolCurrentGeminiMdFilename, - getAllGeminiMdFilenames as getToolAllGeminiMdFilenames, + setMemoryFilename as setToolMemoryFilename, + getCurrentMemoryFilename as getToolCurrentMemoryFilename, + getAllMemoryFilenames as getToolAllMemoryFilenames, } from '../tools/memory-config.js'; // Mock dependencies @@ -30,40 +30,40 @@ vi.mock(import('node:fs/promises'), async (importOriginal) => { vi.mock('os'); -describe('setGeminiMdFilename', () => { +describe('setMemoryFilename', () => { beforeEach(() => { - setGeminiMdFilename([DEFAULT_CONTEXT_FILENAME, AGENT_CONTEXT_FILENAME]); + setMemoryFilename([DEFAULT_CONTEXT_FILENAME, AGENT_CONTEXT_FILENAME]); }); - it('should update currentGeminiMdFilename when a valid new name is provided', () => { + it('should update currentMemoryFilename when a valid new name is provided', () => { const newName = 'CUSTOM_CONTEXT.md'; - setGeminiMdFilename(newName); - expect(getCurrentGeminiMdFilename()).toBe(newName); + setMemoryFilename(newName); + expect(getCurrentMemoryFilename()).toBe(newName); }); - it('should not update currentGeminiMdFilename if the new name is empty or whitespace', () => { - const initialName = getCurrentGeminiMdFilename(); // Get current before trying to change - setGeminiMdFilename(' '); - expect(getCurrentGeminiMdFilename()).toBe(initialName); + it('should not update currentMemoryFilename if the new name is empty or whitespace', () => { + const initialName = getCurrentMemoryFilename(); // Get current before trying to change + setMemoryFilename(' '); + expect(getCurrentMemoryFilename()).toBe(initialName); - setGeminiMdFilename(''); - expect(getCurrentGeminiMdFilename()).toBe(initialName); + setMemoryFilename(''); + expect(getCurrentMemoryFilename()).toBe(initialName); }); it('should handle an array of filenames', () => { const newNames = ['CUSTOM_CONTEXT.md', 'ANOTHER_CONTEXT.md']; - setGeminiMdFilename(newNames); - expect(getCurrentGeminiMdFilename()).toBe('CUSTOM_CONTEXT.md'); - expect(getAllGeminiMdFilenames()).toEqual(newNames); + setMemoryFilename(newNames); + expect(getCurrentMemoryFilename()).toBe('CUSTOM_CONTEXT.md'); + expect(getAllMemoryFilenames()).toEqual(newNames); }); it('shares filename state with the legacy tools memory config entrypoint', () => { - setGeminiMdFilename(['CUSTOM_CONTEXT.md', 'AGENTS.md']); - expect(getToolCurrentGeminiMdFilename()).toBe('CUSTOM_CONTEXT.md'); - expect(getToolAllGeminiMdFilenames()).toEqual(getAllGeminiMdFilenames()); + setMemoryFilename(['CUSTOM_CONTEXT.md', 'AGENTS.md']); + expect(getToolCurrentMemoryFilename()).toBe('CUSTOM_CONTEXT.md'); + expect(getToolAllMemoryFilenames()).toEqual(getAllMemoryFilenames()); - setToolGeminiMdFilename('LEGACY_CONTEXT.md'); - expect(getCurrentGeminiMdFilename()).toBe('LEGACY_CONTEXT.md'); - expect(getAllGeminiMdFilenames()).toEqual(['LEGACY_CONTEXT.md']); + setToolMemoryFilename('LEGACY_CONTEXT.md'); + expect(getCurrentMemoryFilename()).toBe('LEGACY_CONTEXT.md'); + expect(getAllMemoryFilenames()).toEqual(['LEGACY_CONTEXT.md']); }); }); diff --git a/packages/core/src/memory/memoryDiscovery.test.ts b/packages/core/src/memory/memoryDiscovery.test.ts index fcaae1e0b93..50121c4a067 100644 --- a/packages/core/src/memory/memoryDiscovery.test.ts +++ b/packages/core/src/memory/memoryDiscovery.test.ts @@ -13,7 +13,7 @@ import { formatContextFileDisplayPath, } from './memoryDiscovery.js'; import { - setGeminiMdFilename, + setMemoryFilename, DEFAULT_CONTEXT_FILENAME, LOCAL_CONTEXT_FILENAME, } from '../utils/memory-constants.js'; @@ -76,7 +76,7 @@ describe('loadServerHierarchicalMemory', () => { afterEach(async () => { vi.unstubAllEnvs(); // Some tests set this to a different value. - setGeminiMdFilename(DEFAULT_CONTEXT_FILENAME); + setMemoryFilename(DEFAULT_CONTEXT_FILENAME); // Clean up the temporary directory to prevent resource leaks. // Use maxRetries option for robust cleanup without race conditions await fsPromises.rm(testRootDir, { @@ -259,7 +259,7 @@ describe('loadServerHierarchicalMemory', () => { it('should load only the global custom context file if present and filename is changed', async () => { const customFilename = 'CUSTOM_AGENTS.md'; - setGeminiMdFilename(customFilename); + setMemoryFilename(customFilename); const customContextFile = await createTestFile( path.join(homedir, QWEN_DIR, customFilename), @@ -288,7 +288,7 @@ describe('loadServerHierarchicalMemory', () => { it('should load context files by upward traversal with custom filename', async () => { const customFilename = 'PROJECT_CONTEXT.md'; - setGeminiMdFilename(customFilename); + setMemoryFilename(customFilename); const projectContextFile = await createTestFile( path.join(projectRoot, customFilename), @@ -322,7 +322,7 @@ describe('loadServerHierarchicalMemory', () => { it('should load context files from CWD with custom filename (not subdirectories)', async () => { const customFilename = 'LOCAL_CONTEXT.md'; - setGeminiMdFilename(customFilename); + setMemoryFilename(customFilename); await createTestFile( path.join(cwd, 'subdir', customFilename), @@ -1323,7 +1323,7 @@ describe('loadServerHierarchicalMemory', () => { }); it('dedupes when an extension registers the local slot path explicitly', async () => { - // The hierarchical scan iterates `getAllGeminiMdFilenames()` + // The hierarchical scan iterates `getAllMemoryFilenames()` // (QWEN.md / AGENTS.md) and never produces a `QWEN.local.md` path, // so the dedup guard in the slot loader looks unreachable in // production paths. It IS reachable, though, via diff --git a/packages/core/src/memory/memoryDiscovery.ts b/packages/core/src/memory/memoryDiscovery.ts index 5367a2a9fe3..bb67c538784 100644 --- a/packages/core/src/memory/memoryDiscovery.ts +++ b/packages/core/src/memory/memoryDiscovery.ts @@ -9,7 +9,7 @@ import * as fsSync from 'node:fs'; import * as path from 'node:path'; import { homedir } from 'node:os'; import { - getAllGeminiMdFilenames, + getAllMemoryFilenames, LOCAL_CONTEXT_FILENAME, } from '../utils/memory-constants.js'; import type { FileDiscoveryService } from '../services/fileDiscoveryService.js'; @@ -40,7 +40,7 @@ export interface InstructionsLoadedNotification { parentFilePath?: string; } -async function getGeminiMdFilePathsInternal( +async function getMemoryFilePathsInternal( currentWorkingDirectory: string, includeDirectoriesToReadGemini: readonly string[], userHomePath: string, @@ -63,7 +63,7 @@ async function getGeminiMdFilePathsInternal( for (let i = 0; i < dirsArray.length; i += CONCURRENT_LIMIT) { const batch = dirsArray.slice(i, i + CONCURRENT_LIMIT); const batchPromises = batch.map((dir) => - getGeminiMdFilePathsInternalForEachDir( + getMemoryFilePathsInternalForEachDir( dir, userHomePath, fileService, @@ -91,7 +91,7 @@ async function getGeminiMdFilePathsInternal( return Array.from(new Set(paths)); } -async function getGeminiMdFilePathsInternalForEachDir( +async function getMemoryFilePathsInternalForEachDir( dir: string, userHomePath: string, fileService: FileDiscoveryService, @@ -100,7 +100,7 @@ async function getGeminiMdFilePathsInternalForEachDir( implicitDiscoveryEnabled: boolean = true, ): Promise { const allPaths = new Set(); - const geminiMdFilenames = getAllGeminiMdFilenames(); + const geminiMdFilenames = getAllMemoryFilenames(); for (const geminiMdFilename of geminiMdFilenames) { const resolvedHome = path.resolve(userHomePath); @@ -206,14 +206,14 @@ async function getGeminiMdFilePathsInternalForEachDir( const finalPaths = Array.from(allPaths); logger.debug( - `Final ordered ${getAllGeminiMdFilenames()} paths to read: ${JSON.stringify( + `Final ordered ${getAllMemoryFilenames()} paths to read: ${JSON.stringify( finalPaths, )}`, ); return finalPaths; } -async function readGeminiMdFiles( +async function readMemoryFiles( filePaths: string[], importFormat: 'flat' | 'tree' = 'tree', getMemoryType: (filePath: string) => InstructionMemoryType, @@ -288,7 +288,7 @@ async function readGeminiMdFiles( const message = error instanceof Error ? error.message : String(error); logger.warn( - `Warning: Could not read ${getAllGeminiMdFilenames()} file at ${filePath}. Error: ${message}`, + `Warning: Could not read ${getAllMemoryFilenames()} file at ${filePath}. Error: ${message}`, ); } logger.debug(`Failed to read: ${filePath}`); @@ -477,7 +477,7 @@ export async function loadServerHierarchicalMemory( // For the server, homedir() refers to the server process's home. // This is consistent with how MemoryTool already finds the global path. const userHomePath = homedir(); - const filePaths = await getGeminiMdFilePathsInternal( + const filePaths = await getMemoryFilePathsInternal( currentWorkingDirectory, includeDirectoriesToReadGemini, userHomePath, @@ -530,7 +530,7 @@ export async function loadServerHierarchicalMemory( if (filePaths.length > 0) { const loadReason = options.loadReason ?? 'session_start'; - const contentsWithPaths = await readGeminiMdFiles( + const contentsWithPaths = await readMemoryFiles( filePaths, importFormat, createMemoryTypeClassifier( @@ -554,7 +554,7 @@ export async function loadServerHierarchicalMemory( // (/memory count vs announcement list) may differ; aligning them at // the display site is deferred as a follow-up. const memoryFilenames = new Set([ - ...getAllGeminiMdFilenames(), + ...getAllMemoryFilenames(), LOCAL_CONTEXT_FILENAME, ]); const memoryItems = contentsWithPaths.filter((item) => diff --git a/packages/core/src/memory/refresh.test.ts b/packages/core/src/memory/refresh.test.ts index 87b33cad482..18cd74b0f92 100644 --- a/packages/core/src/memory/refresh.test.ts +++ b/packages/core/src/memory/refresh.test.ts @@ -21,7 +21,7 @@ import { import { AGENT_CONTEXT_FILENAME, DEFAULT_CONTEXT_FILENAME, - setGeminiMdFilename, + setMemoryFilename, } from '../utils/memory-constants.js'; import { didWriteManagedMemory, @@ -61,7 +61,7 @@ describe('managed memory refresh helper', () => { vi.mocked(rebuildUserAutoMemoryIndex).mockReset(); vi.mocked(rebuildManagedAutoMemoryIndex).mockResolvedValue(''); vi.mocked(rebuildUserAutoMemoryIndex).mockResolvedValue(''); - setGeminiMdFilename([DEFAULT_CONTEXT_FILENAME, AGENT_CONTEXT_FILENAME]); + setMemoryFilename([DEFAULT_CONTEXT_FILENAME, AGENT_CONTEXT_FILENAME]); }); afterEach(async () => { @@ -259,7 +259,7 @@ describe('managed memory refresh helper', () => { }); it('detects configured project context file writes', () => { - setGeminiMdFilename('PROJECT_CONTEXT.md'); + setMemoryFilename('PROJECT_CONTEXT.md'); expect( didWriteProjectContextFile( diff --git a/packages/core/src/memory/refresh.ts b/packages/core/src/memory/refresh.ts index a28b0a03b84..568c395e71a 100644 --- a/packages/core/src/memory/refresh.ts +++ b/packages/core/src/memory/refresh.ts @@ -8,7 +8,7 @@ import * as path from 'node:path'; import type { Config } from '../config/config.js'; import { ToolNames, canonicalToolName } from '../tools/tool-names.js'; import { createDebugLogger } from '../utils/debugLogger.js'; -import { getAllGeminiMdFilenames } from '../utils/memory-constants.js'; +import { getAllMemoryFilenames } from '../utils/memory-constants.js'; import { isAllowedMemoryPath } from './memory-scoped-agent-config.js'; import { rebuildManagedAutoMemoryIndex, @@ -93,7 +93,7 @@ export function didWriteProjectContextFile( projectRoot: string, ): boolean { const contextFilePaths = new Set( - getAllGeminiMdFilenames() + getAllMemoryFilenames() .map((name) => name.trim()) .filter((name) => name.length > 0) .map((name) => path.resolve(projectRoot, name)), diff --git a/packages/core/src/memory/writeContextFile.test.ts b/packages/core/src/memory/writeContextFile.test.ts index 7d08b8a8e77..68b549a114b 100644 --- a/packages/core/src/memory/writeContextFile.test.ts +++ b/packages/core/src/memory/writeContextFile.test.ts @@ -13,7 +13,7 @@ import { AGENT_CONTEXT_FILENAME, DEFAULT_CONTEXT_FILENAME, MEMORY_SECTION_HEADER, - setGeminiMdFilename, + setMemoryFilename, } from '../utils/memory-constants.js'; import { writeWorkspaceContextFile } from './writeContextFile.js'; @@ -385,15 +385,15 @@ describe('writeWorkspaceContextFile', () => { await expect(fs.access(nested)).rejects.toMatchObject({ code: 'ENOENT' }); }); - it('honors setGeminiMdFilename overrides so POST targets the same file GET surfaces', async () => { - // Round-trip the `setGeminiMdFilename` override: with the prior + it('honors setMemoryFilename overrides so POST targets the same file GET surfaces', async () => { + // Round-trip the `setMemoryFilename` override: with the prior // `DEFAULT_CONTEXT_FILENAME` hard-code, a deployment that switched // the context filename to `AGENTS.md` saw GET list the new file // but POST keep writing to `QWEN.md`. The fix routes - // `resolveContextFilePath` through `getCurrentGeminiMdFilename()` + // `resolveContextFilePath` through `getCurrentMemoryFilename()` // so both surfaces agree. try { - setGeminiMdFilename(AGENT_CONTEXT_FILENAME); + setMemoryFilename(AGENT_CONTEXT_FILENAME); const result = await writeWorkspaceContextFile({ scope: 'workspace', mode: 'append', @@ -411,7 +411,7 @@ describe('writeWorkspaceContextFile', () => { fs.access(path.join(workspace, DEFAULT_CONTEXT_FILENAME)), ).rejects.toMatchObject({ code: 'ENOENT' }); } finally { - setGeminiMdFilename(DEFAULT_CONTEXT_FILENAME); + setMemoryFilename(DEFAULT_CONTEXT_FILENAME); } }); }); diff --git a/packages/core/src/memory/writeContextFile.ts b/packages/core/src/memory/writeContextFile.ts index bc1537774d7..cab329c3993 100644 --- a/packages/core/src/memory/writeContextFile.ts +++ b/packages/core/src/memory/writeContextFile.ts @@ -14,7 +14,7 @@ import { } from 'async-mutex'; import { Storage } from '../config/storage.js'; import { - getCurrentGeminiMdFilename, + getCurrentMemoryFilename, MEMORY_SECTION_HEADER, } from '../utils/memory-constants.js'; @@ -232,15 +232,15 @@ function resolveContextFilePath( scope: WriteContextFileScope, projectRoot: string, ): string { - // Honor `setGeminiMdFilename()` overrides so POST writes to the same + // Honor `setMemoryFilename()` overrides so POST writes to the same // file GET surfaces. With the prior `DEFAULT_CONTEXT_FILENAME` hard- // code, a deployment that switched the context filename to // `AGENTS.md` would have GET listing the new file while POST kept // appending to a stale `QWEN.md` — clients then observed "I just // wrote content but it's missing from /workspace/memory". Mirrors the - // discovery path's `getAllGeminiMdFilenames()` usage in + // discovery path's `getAllMemoryFilenames()` usage in // `workspace-memory.ts:collectWorkspaceMemoryStatus`. - const filename = getCurrentGeminiMdFilename(); + const filename = getCurrentMemoryFilename(); if (scope === 'workspace') { return path.join(projectRoot, filename); } diff --git a/packages/core/src/permissions/autoMode.test.ts b/packages/core/src/permissions/autoMode.test.ts index d5aeb03acdb..389c2458f4a 100644 --- a/packages/core/src/permissions/autoMode.test.ts +++ b/packages/core/src/permissions/autoMode.test.ts @@ -29,7 +29,7 @@ import { ApprovalMode } from '../config/config.js'; import { ToolNames } from '../tools/tool-names.js'; import type { Config } from '../config/config.js'; import type { PermissionCheckContext } from './types.js'; -import { setGeminiMdFilename } from '../utils/memory-constants.js'; +import { setMemoryFilename } from '../utils/memory-constants.js'; // ─── SAFE_TOOL_ALLOWLIST contents (frozen) ─────────────────────────────── @@ -212,7 +212,7 @@ describe('isAutoModeProtectedWritePath', () => { }); it('matches configured context filenames', () => { - setGeminiMdFilename(['CUSTOM_AGENTS.md', 'docs/TEAM_CONTEXT.md']); + setMemoryFilename(['CUSTOM_AGENTS.md', 'docs/TEAM_CONTEXT.md']); try { const protectedPaths = [ '/repo/CUSTOM_AGENTS.md', @@ -224,7 +224,7 @@ describe('isAutoModeProtectedWritePath', () => { expect(isAutoModeProtectedWritePath(filePath)).toBe(true); } } finally { - setGeminiMdFilename(['QWEN.md', 'AGENTS.md']); + setMemoryFilename(['QWEN.md', 'AGENTS.md']); } }); diff --git a/packages/core/src/permissions/autoMode.ts b/packages/core/src/permissions/autoMode.ts index fdb68567f2c..6a51c1dbae2 100644 --- a/packages/core/src/permissions/autoMode.ts +++ b/packages/core/src/permissions/autoMode.ts @@ -22,7 +22,7 @@ import path from 'node:path'; import type { Content } from '@google/genai'; import { ApprovalMode, type Config } from '../config/config.js'; import { - getAllGeminiMdFilenames, + getAllMemoryFilenames, LOCAL_CONTEXT_FILENAME, } from '../utils/memory-constants.js'; import type { PermissionDeniedReason } from '../hooks/types.js'; @@ -172,7 +172,7 @@ function trimPathSlashes(filePath: string): string { } function matchesConfiguredContextFile(normalizedPath: string): boolean { - return [...getAllGeminiMdFilenames(), LOCAL_CONTEXT_FILENAME].some( + return [...getAllMemoryFilenames(), LOCAL_CONTEXT_FILENAME].some( (filename) => { const normalizedFilename = trimPathSlashes( normalizePathForAutoModePattern(filename), diff --git a/packages/core/src/tools/edit.test.ts b/packages/core/src/tools/edit.test.ts index 8957aa7469b..26e35ee93a5 100644 --- a/packages/core/src/tools/edit.test.ts +++ b/packages/core/src/tools/edit.test.ts @@ -83,8 +83,8 @@ describe('EditTool', () => { getUserAgent: () => 'test-agent', getUserMemory: () => '', setUserMemory: vi.fn(), - getGeminiMdFileCount: () => 0, - setGeminiMdFileCount: vi.fn(), + getMemoryFileCount: () => 0, + setMemoryFileCount: vi.fn(), getToolRegistry: () => ({}) as any, // Minimal mock for ToolRegistry getDefaultFileEncoding: vi.fn().mockReturnValue('utf-8'), getFileReadCache: () => fileReadCache, diff --git a/packages/core/src/tools/glob.test.ts b/packages/core/src/tools/glob.test.ts index cc4c8239182..de452bcef83 100644 --- a/packages/core/src/tools/glob.test.ts +++ b/packages/core/src/tools/glob.test.ts @@ -6,7 +6,7 @@ import type { GlobToolParams, GlobPath } from './glob.js'; import { GlobTool, sortFileEntries } from './glob.js'; -import { partListUnionToString } from '../core/geminiRequest.js'; +import { partListUnionToString } from '../core/llm-request.js'; import path from 'node:path'; import fs from 'node:fs/promises'; import os from 'node:os'; diff --git a/packages/core/src/tools/memory-config.ts b/packages/core/src/tools/memory-config.ts index 6e060453dfc..0ba210912bb 100644 --- a/packages/core/src/tools/memory-config.ts +++ b/packages/core/src/tools/memory-config.ts @@ -12,8 +12,8 @@ export { AGENT_CONTEXT_FILENAME, DEFAULT_CONTEXT_FILENAME, - getAllGeminiMdFilenames, - getCurrentGeminiMdFilename, + getAllMemoryFilenames, + getCurrentMemoryFilename, MEMORY_SECTION_HEADER, - setGeminiMdFilename, + setMemoryFilename, } from '../utils/memory-constants.js'; diff --git a/packages/core/src/tools/notebook-edit.test.ts b/packages/core/src/tools/notebook-edit.test.ts index 40de455a46b..880a3a6814b 100644 --- a/packages/core/src/tools/notebook-edit.test.ts +++ b/packages/core/src/tools/notebook-edit.test.ts @@ -65,8 +65,8 @@ describe('NotebookEditTool', () => { getUserAgent: () => 'test-agent', getUserMemory: () => '', setUserMemory: vi.fn(), - getGeminiMdFileCount: () => 0, - setGeminiMdFileCount: vi.fn(), + getMemoryFileCount: () => 0, + setMemoryFileCount: vi.fn(), getToolRegistry: () => ({}) as never, } as unknown as Config; tool = new NotebookEditTool(config); diff --git a/packages/core/src/tools/write-file.test.ts b/packages/core/src/tools/write-file.test.ts index 698c7933723..c33475dfb37 100644 --- a/packages/core/src/tools/write-file.test.ts +++ b/packages/core/src/tools/write-file.test.ts @@ -68,8 +68,8 @@ const mockConfigInternal = { getUserAgent: () => 'test-agent', getUserMemory: () => '', setUserMemory: vi.fn(), - getGeminiMdFileCount: () => 0, - setGeminiMdFileCount: vi.fn(), + getMemoryFileCount: () => 0, + setMemoryFileCount: vi.fn(), getToolRegistry: () => ({ registerTool: vi.fn(), diff --git a/packages/core/src/utils/ignorePatterns.test.ts b/packages/core/src/utils/ignorePatterns.test.ts index 8b539e342e0..61d97bcafbe 100644 --- a/packages/core/src/utils/ignorePatterns.test.ts +++ b/packages/core/src/utils/ignorePatterns.test.ts @@ -14,7 +14,7 @@ import type { Config } from '../config/config.js'; // Mock the memoryTool module vi.mock('./memory-constants.js', () => ({ - getAllGeminiMdFilenames: vi.fn(() => ['GEMINI.md', 'AGENTS.md']), + getAllMemoryFilenames: vi.fn(() => ['GEMINI.md', 'AGENTS.md']), })); describe('FileExclusions', () => { diff --git a/packages/core/src/utils/ignorePatterns.ts b/packages/core/src/utils/ignorePatterns.ts index 6d64dd474ae..67fbb24bee9 100644 --- a/packages/core/src/utils/ignorePatterns.ts +++ b/packages/core/src/utils/ignorePatterns.ts @@ -6,7 +6,7 @@ import path from 'node:path'; import type { Config } from '../config/config.js'; -import { getAllGeminiMdFilenames } from './memory-constants.js'; +import { getAllMemoryFilenames } from './memory-constants.js'; /** * Common ignore patterns used across multiple tools for basic exclusions. @@ -160,7 +160,7 @@ export class FileExclusions { // Add dynamic patterns (like context filenames) if (includeDynamicPatterns) { - for (const filename of getAllGeminiMdFilenames()) { + for (const filename of getAllMemoryFilenames()) { patterns.push(`**/${filename}`); } } diff --git a/packages/core/src/utils/memory-constants.ts b/packages/core/src/utils/memory-constants.ts index 134f314a677..d286510fbe2 100644 --- a/packages/core/src/utils/memory-constants.ts +++ b/packages/core/src/utils/memory-constants.ts @@ -29,25 +29,25 @@ export const LOCAL_CONTEXT_FILENAME = 'QWEN.local.md'; export const MEMORY_SECTION_HEADER = '## Qwen Added Memories'; // This variable will hold the currently configured filename for context files. -// It defaults to include both QWEN.md and AGENTS.md but can be overridden by setGeminiMdFilename. +// It defaults to include both QWEN.md and AGENTS.md but can be overridden by setMemoryFilename. // QWEN.md is first to maintain backward compatibility (used by /init command tool). -let currentGeminiMdFilename: string | string[] = [ +let currentMemoryFilename: string | string[] = [ DEFAULT_CONTEXT_FILENAME, AGENT_CONTEXT_FILENAME, ]; -export function setGeminiMdFilename(newFilename: string | string[]): void { +export function setMemoryFilename(newFilename: string | string[]): void { if (Array.isArray(newFilename)) { if (newFilename.length > 0) { - currentGeminiMdFilename = newFilename.map((name) => name.trim()); + currentMemoryFilename = newFilename.map((name) => name.trim()); } } else if (newFilename && newFilename.trim() !== '') { - currentGeminiMdFilename = newFilename.trim(); + currentMemoryFilename = newFilename.trim(); } } -export function getCurrentGeminiMdFilename(): string { - if (Array.isArray(currentGeminiMdFilename)) { +export function getCurrentMemoryFilename(): string { + if (Array.isArray(currentMemoryFilename)) { // (qwen-latest critical, addresses divergence // with daemon's `extractContextFilename`): skip empty / whitespace // entries so callers that pass `[' ', 'AGENTS.md']` get @@ -56,7 +56,7 @@ export function getCurrentGeminiMdFilename(): string { // process-global picker disagreed on the same input — daemon // parent would write `AGENTS.md` while the ACP child would read // `''`, leaving the init'd file orphaned. - for (const entry of currentGeminiMdFilename) { + for (const entry of currentMemoryFilename) { if (typeof entry === 'string' && entry.trim() !== '') { return entry.trim(); } @@ -65,12 +65,12 @@ export function getCurrentGeminiMdFilename(): string { // than return `undefined` (callers expect a non-empty string). return DEFAULT_CONTEXT_FILENAME; } - return currentGeminiMdFilename; + return currentMemoryFilename; } -export function getAllGeminiMdFilenames(): string[] { - if (Array.isArray(currentGeminiMdFilename)) { - return currentGeminiMdFilename; +export function getAllMemoryFilenames(): string[] { + if (Array.isArray(currentMemoryFilename)) { + return currentMemoryFilename; } - return [currentGeminiMdFilename]; + return [currentMemoryFilename]; } From 305123e34350a464b6464b6a0108db22758b3177 Mon Sep 17 00:00:00 2001 From: yiliang114 Date: Mon, 24 Aug 2026 18:10:54 +0800 Subject: [PATCH 02/10] fix(cli): resolve rename build failure --- docs/developers/daemon/02-serve-runtime.md | 4 +- docs/developers/daemon/03-acp-bridge.md | 12 ++--- docs/developers/daemon/17-configuration.md | 4 +- .../daemon/20-quickstart-operations.md | 2 +- docs/developers/qwen-serve-protocol.md | 2 +- eslint.legacy-filenames.mjs | 1 - packages/cli/src/core/initializer.test.ts | 2 +- packages/cli/src/core/initializer.ts | 4 +- packages/cli/src/gemini.test.tsx | 46 +++++++++---------- packages/cli/src/ui/AppContainer.test.tsx | 2 +- packages/cli/src/ui/AppContainer.tsx | 8 ++-- .../cli/src/ui/commands/initCommand.test.ts | 8 ++-- .../cli/src/ui/components/Composer.test.tsx | 2 +- .../components/ContextSummaryDisplay.test.tsx | 4 +- .../ui/components/ContextSummaryDisplay.tsx | 18 ++++---- .../cli/src/ui/components/Footer.test.tsx | 2 +- .../src/ui/components/MainContent.test.tsx | 2 +- .../src/ui/components/RespondingSpinner.tsx | 16 +++---- .../cli/src/ui/contexts/UIStateContext.tsx | 2 +- .../cli/src/ui/hooks/useGeminiStream.test.tsx | 2 +- .../cli/src/ui/startInteractiveUI.test.tsx | 2 +- packages/core/src/config/config.ts | 10 ++-- packages/core/src/memory/memoryDiscovery.ts | 20 ++++---- packages/core/src/tools/tool-registry.test.ts | 2 +- packages/core/src/tools/tool-search.test.ts | 2 +- 25 files changed, 88 insertions(+), 91 deletions(-) diff --git a/docs/developers/daemon/02-serve-runtime.md b/docs/developers/daemon/02-serve-runtime.md index 49bcbd76613..468084c03d7 100644 --- a/docs/developers/daemon/02-serve-runtime.md +++ b/docs/developers/daemon/02-serve-runtime.md @@ -110,7 +110,7 @@ Calling `createServeApp` directly still returns only an `Application`. An embedd | Upstream used by `serve/` | Downstream using `serve/` | | ----------------------------------------------------------------------------------------------- | ----------------------------------------- | | `@qwen-code/acp-bridge`: bridge, event bus, status types | The `qwen` CLI `serve` subcommand handler | -| `packages/core`: `loadSettings`, `getCurrentGeminiMdFilename`, `Config`, `WorkspaceContext` | Direct embedders, tests | +| `packages/core`: `loadSettings`, `getCurrentMemoryFilename`, `Config`, `WorkspaceContext` | Direct embedders, tests | | ACP SDK (`@agentclientprotocol/sdk`): `PROTOCOL_VERSION`, `ClientSideConnection` through bridge | | | Express + body-parser, `node:crypto`, `node:fs`, `node:path` | | @@ -136,7 +136,7 @@ Calling `createServeApp` directly still returns only an `Application`. An embedd | Flags | `--session-reap-interval-ms`, `--session-idle-timeout-ms` | Disconnected-session reaping control. | | Flags | `--rate-limit*` | Per-tier HTTP rate limit. | | `settings.json` | `policy.permissionStrategy`, `policy.consensusQuorum` | `MultiClientPermissionMediator` policy and quorum. | -| `settings.json` | `context.fileName` | `getCurrentGeminiMdFilename` override for the bridge. | +| `settings.json` | `context.fileName` | `getCurrentMemoryFilename` override for the bridge. | See [`17-configuration.md`](./17-configuration.md) for the merged reference. diff --git a/docs/developers/daemon/03-acp-bridge.md b/docs/developers/daemon/03-acp-bridge.md index 5915e1ba290..c86ddc8b221 100644 --- a/docs/developers/daemon/03-acp-bridge.md +++ b/docs/developers/daemon/03-acp-bridge.md @@ -184,11 +184,11 @@ sequenceDiagram ## Dependencies -| Upstream | Downstream | -| -------------------------------------------------------------------------------------------- | ---------------------------------------------- | -| `@agentclientprotocol/sdk` — `ClientSideConnection`, `PROTOCOL_VERSION`, ACP types | `packages/cli/src/serve/` (the daemon) | -| `@qwen-code/qwen-code-core` — `ApprovalMode`, `TrustGateError`, `getCurrentGeminiMdFilename` | `packages/channels/base/` (planned, F4) | -| `node:crypto`, `node:fs`, `node:path` | `packages/vscode-ide-companion/` (planned, F4) | +| Upstream | Downstream | +| ------------------------------------------------------------------------------------------ | ---------------------------------------------- | +| `@agentclientprotocol/sdk` — `ClientSideConnection`, `PROTOCOL_VERSION`, ACP types | `packages/cli/src/serve/` (the daemon) | +| `@qwen-code/qwen-code-core` — `ApprovalMode`, `TrustGateError`, `getCurrentMemoryFilename` | `packages/channels/base/` (planned, F4) | +| `node:crypto`, `node:fs`, `node:path` | `packages/vscode-ide-companion/` (planned, F4) | ## Configuration @@ -208,7 +208,7 @@ sequenceDiagram | `childEnvOverrides` | `{}` | Per-handle env additions / scrubs for the ACP child. | | `externalToolGuard` | (none) | Optional handler for the private child-to-parent pre-execution decision. The bridge accepts it only from the owning channel for the currently active Prompt. | | `persistApprovalMode`, `persistDisabledTools` | — | Settings-write hooks for the Wave 4 mutation routes. | -| `contextFilename` | from `settings.json`'s `context.fileName` | Overrides `getCurrentGeminiMdFilename`. | +| `contextFilename` | from `settings.json`'s `context.fileName` | Overrides `getCurrentMemoryFilename`. | | `statusProvider` | (none) | Daemon-host preflight cells (`DaemonStatusProvider`). | | `delegateReadTextFileToClient` | `true` | Set `false` only for same-host runtimes so every child `FileSystemService.readTextFile` consumer uses the regular CLI filesystem service. | | `fileSystem` | (none) | `BridgeFileSystem` adapter for ACP `readTextFile` / `writeTextFile`. | diff --git a/docs/developers/daemon/17-configuration.md b/docs/developers/daemon/17-configuration.md index a1d0762893c..4a63bbff534 100644 --- a/docs/developers/daemon/17-configuration.md +++ b/docs/developers/daemon/17-configuration.md @@ -105,7 +105,7 @@ The daemon constructs each workspace runtime from that workspace's merged settin | --------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `policy.permissionStrategy` | `'first-responder' \| 'designated' \| 'consensus' \| 'local-only'` | Sets `BridgeOptions.permissionPolicy`; the active value appears in `/capabilities` as `policy.permission`. **Boot validates** through `validatePolicyConfig()` against `SERVE_CAPABILITY_REGISTRY.permission_mediation.modes`. Unknown literals throw `InvalidPolicyConfigError` and fail boot explicitly. | | `policy.consensusQuorum` | positive integer | N for the `consensus` policy. **Default** is `floor(M/2) + 1` over `votersAtIssue.size` (M=2 means unanimous; larger even M means more than half). If set under a non-consensus policy, it is ignored and boot prints a stderr warning. Non-positive integers throw `InvalidPolicyConfigError`. See [`04-permission-mediation.md`](./04-permission-mediation.md). | -| `context.fileName` | string | Overrides `getCurrentGeminiMdFilename()` through `BridgeOptions.contextFilename`. | +| `context.fileName` | string | Overrides `getCurrentMemoryFilename()` through `BridgeOptions.contextFilename`. | | `tools.disabled` | string[] | Tools disabled for the next ACP child spawn. Normalized through `normalizeDisabledToolList()` (`packages/cli/src/config/normalizeDisabledTools.ts`): non-array becomes `[]`, non-string entries are skipped, whitespace is trimmed, empty entries are dropped, and duplicates are removed while preserving first occurrence. Boot and `restartMcpServer` settings refresh both run through this function. `ToolRegistry.has(name)` is exact and case-sensitive. `POST /workspace/tools/:name/enable` and `tool_toggled` update this key. | | `tools.approvalMode` | `'default' \| 'auto' \| ...` | Default session approval mode; `POST /session/:id/approval-mode` writes here when `persist: true`. | | `telemetry` | object | OTel config. Keys include `enabled`, `otlpEndpoint`, `otlpProtocol`, `otlpTracesEndpoint`, `otlpLogsEndpoint`, `otlpMetricsEndpoint`, `target`, `outfile`, `userId`, `includeSensitiveSpanAttributes`, `sensitiveSpanAttributeMaxLength`, `resourceAttributes`, and `metrics.includeSessionId`. `resolveTelemetrySettings()` reads it at boot and initializes `initializeTelemetry()`. `userId` is process-wide and must not be configured as end-user identity when the daemon serves multiple users. | @@ -149,7 +149,7 @@ The daemon constructs each workspace runtime from that workspace's merged settin | `statusProvider` | Daemon-host preflight cells. | | `childEnvOverrides` | Per-handle environment additions or removals. | | `externalToolGuard` | Optional daemon-side handler for the private child-to-parent prepare RPC. The bridge validates channel ownership and the active Prompt before and after it calls the handler. | -| `contextFilename` | Overrides `getCurrentGeminiMdFilename()`. | +| `contextFilename` | Overrides `getCurrentMemoryFilename()`. | | `channelIdleTimeoutMs` | How long to keep the ACP child alive after the last session closes, in ms; default `0`. | ## Important defaults diff --git a/docs/developers/daemon/20-quickstart-operations.md b/docs/developers/daemon/20-quickstart-operations.md index 5ba5f5241e9..8dea0cfcb0a 100644 --- a/docs/developers/daemon/20-quickstart-operations.md +++ b/docs/developers/daemon/20-quickstart-operations.md @@ -137,7 +137,7 @@ Boot calls `loadSettings(boundWorkspace)` once: | --------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `policy.permissionStrategy` | `'first-responder' \| 'designated' \| 'consensus' \| 'local-only'` | Sets `BridgeOptions.permissionPolicy`. **Boot validates with `validatePolicyConfig`**; unknown values throw `InvalidPolicyConfigError` instead of falling back silently. | | `policy.consensusQuorum` | positive integer | N for the `consensus` policy. Default is `floor(M/2)+1`. If set under a non-consensus policy, it is ignored and boot logs a stderr warning. | -| `context.fileName` | string | Overrides `getCurrentGeminiMdFilename()` and controls which file `POST /workspace/init` writes. | +| `context.fileName` | string | Overrides `getCurrentMemoryFilename()` and controls which file `POST /workspace/init` writes. | | `tools.disabled` | string[] | Normalized through `normalizeDisabledToolList()` (trim, drop empty entries, dedupe) before affecting the next ACP child spawn. | | `tools.approvalMode` | string | Default session approval mode. | | `telemetry` | object | OTel configuration: `enabled`, `otlpEndpoint`, `otlpProtocol`, per-signal endpoints, and more. See [`17-configuration.md`](./17-configuration.md). | diff --git a/docs/developers/qwen-serve-protocol.md b/docs/developers/qwen-serve-protocol.md index ee4f6bfbf81..e14eb8e4f5e 100644 --- a/docs/developers/qwen-serve-protocol.md +++ b/docs/developers/qwen-serve-protocol.md @@ -2899,7 +2899,7 @@ Target errors use `skill_not_found`, `skill_not_toggleable`, or `skill_inactive_ Capability tag: `workspace_init`. Pure file IO — no ACP roundtrip, **no LLM invocation**. -Scaffold an empty `QWEN.md` (or whatever `getCurrentGeminiMdFilename()` returns under `--memory-file-name` overrides) at the daemon's primary workspace root. Mechanical only — for AI-driven content fill, follow up with `POST /session/:id/prompt`. +Scaffold an empty `QWEN.md` (or whatever `getCurrentMemoryFilename()` returns under `--memory-file-name` overrides) at the daemon's primary workspace root. Mechanical only — for AI-driven content fill, follow up with `POST /session/:id/prompt`. Default refuses to overwrite when the target file exists with non-whitespace content. Whitespace-only files are treated as absent (matches the local `/init` slash command). diff --git a/eslint.legacy-filenames.mjs b/eslint.legacy-filenames.mjs index a2839e04beb..b1a74313992 100644 --- a/eslint.legacy-filenames.mjs +++ b/eslint.legacy-filenames.mjs @@ -134,7 +134,6 @@ export const legacyFilenames = [ 'functionHookRunner', 'geminiChat', 'geminiContentGenerator', - 'geminiRequest', 'generateContentResponseUtilities', 'generatedFiles', 'getFolderStructure', diff --git a/packages/cli/src/core/initializer.test.ts b/packages/cli/src/core/initializer.test.ts index 84c33fe8460..74aa2148aee 100644 --- a/packages/cli/src/core/initializer.test.ts +++ b/packages/cli/src/core/initializer.test.ts @@ -96,7 +96,7 @@ describe('initializeApp', () => { expect(result.authError).toBeNull(); expect(result.themeError).toBeNull(); - expect(result.geminiMdFileCount).toBe(0); + expect(result.memoryFileCount).toBe(0); }); it('should return authError when auth fails', async () => { diff --git a/packages/cli/src/core/initializer.ts b/packages/cli/src/core/initializer.ts index a67626aa513..58edb1d2269 100644 --- a/packages/cli/src/core/initializer.ts +++ b/packages/cli/src/core/initializer.ts @@ -20,7 +20,7 @@ export interface InitializationResult { authError: string | null; themeError: string | null; shouldOpenAuthDialog: boolean; - geminiMdFileCount: number; + memoryFileCount: number; } export interface InitializeAppOptions { @@ -82,6 +82,6 @@ export async function initializeApp( authError, themeError, shouldOpenAuthDialog, - geminiMdFileCount: config.getMemoryFileCount(), + memoryFileCount: config.getMemoryFileCount(), }; } diff --git a/packages/cli/src/gemini.test.tsx b/packages/cli/src/gemini.test.tsx index 85cc346974a..7c68c619187 100644 --- a/packages/cli/src/gemini.test.tsx +++ b/packages/cli/src/gemini.test.tsx @@ -195,7 +195,7 @@ vi.mock('./core/initializer.js', () => ({ authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }), })); @@ -1078,7 +1078,7 @@ describe('gemini.tsx main function', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }); vi.spyOn(startupWarningsModule, 'getStartupWarnings').mockResolvedValue([]); vi.spyOn( @@ -1477,7 +1477,7 @@ describe('gemini.tsx main function', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }); vi.spyOn(startupWarningsModule, 'getStartupWarnings').mockResolvedValue([]); vi.spyOn( @@ -1705,7 +1705,7 @@ describe('gemini.tsx main function kitty protocol', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }); vi.mocked(loadCliConfig).mockResolvedValue({ ...sessionRegistryConfigStub, @@ -1832,7 +1832,7 @@ describe('gemini.tsx main function kitty protocol', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }); vi.mocked(loadCliConfig).mockResolvedValue({ ...sessionRegistryConfigStub, @@ -1957,7 +1957,7 @@ describe('gemini.tsx main function kitty protocol', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }); vi.mocked(loadCliConfig).mockResolvedValue({ ...sessionRegistryConfigStub, @@ -2081,7 +2081,7 @@ describe('gemini.tsx main function kitty protocol', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }); vi.mocked(loadCliConfig).mockResolvedValue({ ...sessionRegistryConfigStub, @@ -2736,7 +2736,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }; await startInteractiveUI( @@ -2781,7 +2781,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }; await startInteractiveUI( @@ -2809,7 +2809,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }; await startInteractiveUI( @@ -2833,7 +2833,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }; await startInteractiveUI( @@ -2857,7 +2857,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }; await startInteractiveUI( @@ -2884,7 +2884,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }; await startInteractiveUI( @@ -2924,7 +2924,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }; await startInteractiveUI( @@ -2950,7 +2950,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }; await startInteractiveUI( @@ -2992,7 +2992,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }; await startInteractiveUI( @@ -3019,7 +3019,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }; await startInteractiveUI( @@ -3060,7 +3060,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }, ); @@ -3094,7 +3094,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }, ); @@ -3127,7 +3127,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }, ); @@ -3161,7 +3161,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }, ); @@ -3345,7 +3345,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }, ); @@ -3380,7 +3380,7 @@ describe('startInteractiveUI', () => { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, }, ); await vi.advanceTimersByTimeAsync(30_000); diff --git a/packages/cli/src/ui/AppContainer.test.tsx b/packages/cli/src/ui/AppContainer.test.tsx index 192b96d09a9..97c207df81b 100644 --- a/packages/cli/src/ui/AppContainer.test.tsx +++ b/packages/cli/src/ui/AppContainer.test.tsx @@ -486,7 +486,7 @@ describe('AppContainer State Management', () => { themeError: null, authError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, } as InitializationResult; }); diff --git a/packages/cli/src/ui/AppContainer.tsx b/packages/cli/src/ui/AppContainer.tsx index 87e22617d96..ae55e3517a5 100644 --- a/packages/cli/src/ui/AppContainer.tsx +++ b/packages/cli/src/ui/AppContainer.tsx @@ -684,8 +684,8 @@ export const AppContainer = (props: AppContainerProps) => { const [isProcessing, setIsProcessing] = useState(false); const [embeddedShellFocused, setEmbeddedShellFocused] = useState(false); - const [geminiMdFileCount, setMemoryFileCount] = useState( - initializationResult.geminiMdFileCount, + const [memoryFileCount, setMemoryFileCount] = useState( + initializationResult.memoryFileCount, ); const [shellModeActive, setShellModeActive] = useState(false); const [modelSwitchedFromQuotaError, setModelSwitchedFromQuotaError] = @@ -4510,7 +4510,7 @@ export const AppContainer = (props: AppContainerProps) => { settingInputRequests, pluginChoiceRequests, loopDetectionConfirmationRequest, - geminiMdFileCount, + memoryFileCount, streamingState, initError, pendingGeminiHistoryItems, @@ -4656,7 +4656,7 @@ export const AppContainer = (props: AppContainerProps) => { settingInputRequests, pluginChoiceRequests, loopDetectionConfirmationRequest, - geminiMdFileCount, + memoryFileCount, streamingState, initError, pendingGeminiHistoryItems, diff --git a/packages/cli/src/ui/commands/initCommand.test.ts b/packages/cli/src/ui/commands/initCommand.test.ts index 187c78ec790..72017744408 100644 --- a/packages/cli/src/ui/commands/initCommand.test.ts +++ b/packages/cli/src/ui/commands/initCommand.test.ts @@ -36,7 +36,7 @@ describe('initCommand', () => { let mockContext: CommandContext; const targetDir = '/test/dir'; const DEFAULT_CONTEXT_FILENAME = 'QWEN.md'; - const geminiMdPath = path.join(targetDir, DEFAULT_CONTEXT_FILENAME); + const memoryFilePath = path.join(targetDir, DEFAULT_CONTEXT_FILENAME); beforeEach(() => { // Create a fresh mock context for each test @@ -99,7 +99,7 @@ describe('initCommand', () => { const result = await initCommand.action!(mockContext, ''); // Assert: Check that writeFileSync was called correctly - expect(fs.writeFileSync).toHaveBeenCalledWith(geminiMdPath, '', 'utf8'); + expect(fs.writeFileSync).toHaveBeenCalledWith(memoryFilePath, '', 'utf8'); // Assert: Check that an informational message was added to the UI expect(mockContext.ui.addItem).toHaveBeenCalledWith( @@ -127,7 +127,7 @@ describe('initCommand', () => { const result = await initCommand.action!(mockContext, ''); - expect(fs.writeFileSync).toHaveBeenCalledWith(geminiMdPath, '', 'utf8'); + expect(fs.writeFileSync).toHaveBeenCalledWith(memoryFilePath, '', 'utf8'); expect(result).toEqual( expect.objectContaining({ type: 'submit_prompt', @@ -145,7 +145,7 @@ describe('initCommand', () => { const result = await initCommand.action!(mockContext, ''); // Assert: Check that writeFileSync was called correctly - expect(fs.writeFileSync).toHaveBeenCalledWith(geminiMdPath, '', 'utf8'); + expect(fs.writeFileSync).toHaveBeenCalledWith(memoryFilePath, '', 'utf8'); // Assert: Check that an informational message was added to the UI expect(mockContext.ui.addItem).toHaveBeenCalledWith( diff --git a/packages/cli/src/ui/components/Composer.test.tsx b/packages/cli/src/ui/components/Composer.test.tsx index 17da21b3a0b..db76376d343 100644 --- a/packages/cli/src/ui/components/Composer.test.tsx +++ b/packages/cli/src/ui/components/Composer.test.tsx @@ -132,7 +132,7 @@ const createMockUIState = (overrides: Partial = {}): UIState => ctrlDPressedOnce: false, showEscapePrompt: false, ideContextState: null, - geminiMdFileCount: 0, + memoryFileCount: 0, showToolDescriptions: false, sessionStats: { lastPromptTokenCount: 0, diff --git a/packages/cli/src/ui/components/ContextSummaryDisplay.test.tsx b/packages/cli/src/ui/components/ContextSummaryDisplay.test.tsx index 4b3bab5db5a..f2e003d037d 100644 --- a/packages/cli/src/ui/components/ContextSummaryDisplay.test.tsx +++ b/packages/cli/src/ui/components/ContextSummaryDisplay.test.tsx @@ -26,7 +26,7 @@ const renderWithWidth = ( describe('', () => { const baseProps = { - geminiMdFileCount: 1, + memoryFileCount: 1, contextFileNames: ['QWEN.md'], mcpServers: { 'test-server': { command: 'test' } }, showToolDescriptions: false, @@ -74,7 +74,7 @@ describe('', () => { it('should not render empty parts', () => { const props = { ...baseProps, - geminiMdFileCount: 0, + memoryFileCount: 0, mcpServers: {}, }; const { lastFrame } = renderWithWidth(60, props); diff --git a/packages/cli/src/ui/components/ContextSummaryDisplay.tsx b/packages/cli/src/ui/components/ContextSummaryDisplay.tsx index 808c0ac7866..ca48dc653d2 100644 --- a/packages/cli/src/ui/components/ContextSummaryDisplay.tsx +++ b/packages/cli/src/ui/components/ContextSummaryDisplay.tsx @@ -16,7 +16,7 @@ import { isNarrowWidth } from '../utils/isNarrowWidth.js'; import { t } from '../../i18n/index.js'; interface ContextSummaryDisplayProps { - geminiMdFileCount: number; + memoryFileCount: number; contextFileNames: string[]; mcpServers?: Record; blockedMcpServers?: Array<{ name: string; extensionName: string }>; @@ -25,7 +25,7 @@ interface ContextSummaryDisplayProps { } export const ContextSummaryDisplay: React.FC = ({ - geminiMdFileCount, + memoryFileCount, contextFileNames, mcpServers, blockedMcpServers, @@ -39,7 +39,7 @@ export const ContextSummaryDisplay: React.FC = ({ const openFileCount = ideContext?.workspaceState?.openFiles?.length ?? 0; if ( - geminiMdFileCount === 0 && + memoryFileCount === 0 && mcpServerCount === 0 && blockedMcpServerCount === 0 && openFileCount === 0 @@ -58,19 +58,19 @@ export const ContextSummaryDisplay: React.FC = ({ return `${fileText} ${t('(ctrl+g to view)')}`; })(); - const geminiMdText = (() => { - if (geminiMdFileCount === 0) { + const memoryFileText = (() => { + if (memoryFileCount === 0) { return ''; } const allNamesTheSame = new Set(contextFileNames).size < 2; const name = allNamesTheSame ? contextFileNames[0] : 'context'; - return geminiMdFileCount === 1 + return memoryFileCount === 1 ? t('{{count}} {{name}} file', { - count: String(geminiMdFileCount), + count: String(memoryFileCount), name, }) : t('{{count}} {{name}} files', { - count: String(geminiMdFileCount), + count: String(memoryFileCount), name, }); })(); @@ -118,7 +118,7 @@ export const ContextSummaryDisplay: React.FC = ({ return text; })(); - const summaryParts = [openFilesText, geminiMdText, mcpText].filter(Boolean); + const summaryParts = [openFilesText, memoryFileText, mcpText].filter(Boolean); if (isNarrow) { return ( diff --git a/packages/cli/src/ui/components/Footer.test.tsx b/packages/cli/src/ui/components/Footer.test.tsx index 9c2d5113eb7..52785712b62 100644 --- a/packages/cli/src/ui/components/Footer.test.tsx +++ b/packages/cli/src/ui/components/Footer.test.tsx @@ -97,7 +97,7 @@ const createMockUIState = (overrides: Partial = {}): UIState => }, currentModel: 'gemini-pro', branchName: undefined, - geminiMdFileCount: 0, + memoryFileCount: 0, contextFileNames: [], showToolDescriptions: false, ideContextState: undefined, diff --git a/packages/cli/src/ui/components/MainContent.test.tsx b/packages/cli/src/ui/components/MainContent.test.tsx index 8b9a89e59e4..a4f883d1495 100644 --- a/packages/cli/src/ui/components/MainContent.test.tsx +++ b/packages/cli/src/ui/components/MainContent.test.tsx @@ -172,7 +172,7 @@ const createUIState = (overrides: Partial = {}): UIState => settingInputRequests: [], pluginChoiceRequests: [], loopDetectionConfirmationRequest: null, - geminiMdFileCount: 0, + memoryFileCount: 0, streamingState: {} as UIState['streamingState'], initError: null, pendingGeminiHistoryItems: [], diff --git a/packages/cli/src/ui/components/RespondingSpinner.tsx b/packages/cli/src/ui/components/RespondingSpinner.tsx index 119b2998d90..39ade3ae114 100644 --- a/packages/cli/src/ui/components/RespondingSpinner.tsx +++ b/packages/cli/src/ui/components/RespondingSpinner.tsx @@ -7,7 +7,7 @@ import type React from 'react'; import { useEffect, useState } from 'react'; import { Text, useIsScreenReaderEnabled } from 'ink'; -import Spinner from 'ink-spinner'; +import InkSpinner from 'ink-spinner'; import type { SpinnerName } from 'cli-spinners'; import { useStreamingContext } from '../contexts/StreamingContext.js'; import { StreamingState } from '../types.js'; @@ -29,17 +29,15 @@ interface RespondingSpinnerProps { spinnerType?: SpinnerName; } -export const RespondingSpinner: React.FC< - RespondingSpinnerProps -> = ({ nonRespondingDisplay, spinnerType = 'dots' }) => { +export const RespondingSpinner: React.FC = ({ + nonRespondingDisplay, + spinnerType = 'dots', +}) => { const streamingState = useStreamingContext(); const isScreenReaderEnabled = useIsScreenReaderEnabled(); if (streamingState === StreamingState.Responding) { return ( - + ); } else if (nonRespondingDisplay) { return isScreenReaderEnabled ? ( @@ -94,7 +92,7 @@ export const Spinner: React.FC = ({ return ( - + ); }; diff --git a/packages/cli/src/ui/contexts/UIStateContext.tsx b/packages/cli/src/ui/contexts/UIStateContext.tsx index 402e4c20a2e..c544fbd66d6 100644 --- a/packages/cli/src/ui/contexts/UIStateContext.tsx +++ b/packages/cli/src/ui/contexts/UIStateContext.tsx @@ -97,7 +97,7 @@ export interface UIState { settingInputRequests: SettingInputRequest[]; pluginChoiceRequests: PluginChoiceRequest[]; loopDetectionConfirmationRequest: LoopDetectionConfirmationRequest | null; - geminiMdFileCount: number; + memoryFileCount: number; streamingState: StreamingState; initError: string | null; pendingGeminiHistoryItems: HistoryItemWithoutId[]; diff --git a/packages/cli/src/ui/hooks/useGeminiStream.test.tsx b/packages/cli/src/ui/hooks/useGeminiStream.test.tsx index a62e0b0ad80..13a6a55efdf 100644 --- a/packages/cli/src/ui/hooks/useGeminiStream.test.tsx +++ b/packages/cli/src/ui/hooks/useGeminiStream.test.tsx @@ -287,7 +287,7 @@ describe('useGeminiStream', () => { mcpServers: undefined, userAgent: 'test-agent', userMemory: '', - geminiMdFileCount: 0, + memoryFileCount: 0, alwaysSkipModificationConfirmation: false, vertexai: false, contextFileName: undefined, diff --git a/packages/cli/src/ui/startInteractiveUI.test.tsx b/packages/cli/src/ui/startInteractiveUI.test.tsx index 2ffe8318d43..04995c70019 100644 --- a/packages/cli/src/ui/startInteractiveUI.test.tsx +++ b/packages/cli/src/ui/startInteractiveUI.test.tsx @@ -79,7 +79,7 @@ const initializationResult = { authError: null, themeError: null, shouldOpenAuthDialog: false, - geminiMdFileCount: 0, + memoryFileCount: 0, } as InitializationResult; async function start(config: Config = makeConfig()): Promise { diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index 52dba22629c..f4c0e6957ae 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -1081,7 +1081,7 @@ export interface ConfigParameters { }; lspClient?: LspClient; userMemory?: string; - geminiMdFileCount?: number; + memoryFileCount?: number; approvalMode?: ApprovalMode; contextFileName?: string | string[]; accessibility?: AccessibilitySettings; @@ -2038,7 +2038,7 @@ export class Config { */ private autoMemoryPrompt = ''; private sdkMode: boolean; - private geminiMdFileCount: number; + private memoryFileCount: number; private loadedContextFilePaths: string[] = []; private conditionalRulesRegistry: ConditionalRulesRegistry | undefined; private readonly contextRuleExcludes: string[]; @@ -2341,7 +2341,7 @@ export class Config { this.sessionSubagents = params.sessionSubagents ?? []; this.sdkMode = params.sdkMode ?? false; this.userMemory = params.userMemory ?? ''; - this.geminiMdFileCount = params.geminiMdFileCount ?? 0; + this.memoryFileCount = params.memoryFileCount ?? 0; this.contextRuleExcludes = params.contextRuleExcludes ?? []; this.approvalMode = params.approvalMode ?? ApprovalMode.AUTO; this.accessibility = params.accessibility ?? {}; @@ -6378,11 +6378,11 @@ export class Config { } getMemoryFileCount(): number { - return this.geminiMdFileCount; + return this.memoryFileCount; } setMemoryFileCount(count: number): void { - this.geminiMdFileCount = count; + this.memoryFileCount = count; } /** Display paths of the currently loaded context (memory) files. */ diff --git a/packages/core/src/memory/memoryDiscovery.ts b/packages/core/src/memory/memoryDiscovery.ts index bb67c538784..e8b78745a51 100644 --- a/packages/core/src/memory/memoryDiscovery.ts +++ b/packages/core/src/memory/memoryDiscovery.ts @@ -100,24 +100,24 @@ async function getMemoryFilePathsInternalForEachDir( implicitDiscoveryEnabled: boolean = true, ): Promise { const allPaths = new Set(); - const geminiMdFilenames = getAllMemoryFilenames(); + const memoryFilenames = getAllMemoryFilenames(); - for (const geminiMdFilename of geminiMdFilenames) { + for (const memoryFilename of memoryFilenames) { const resolvedHome = path.resolve(userHomePath); const globalQwenDir = Storage.getGlobalQwenDir(); - const globalMemoryPath = path.join(globalQwenDir, geminiMdFilename); + const globalMemoryPath = path.join(globalQwenDir, memoryFilename); // Handle the case where we're in the home directory (dir is empty string or home path) const resolvedDir = dir ? path.resolve(dir) : resolvedHome; const isHomeDirectory = resolvedDir === resolvedHome; if (!implicitDiscoveryEnabled) { - const explicitContextPath = path.join(resolvedDir, geminiMdFilename); + const explicitContextPath = path.join(resolvedDir, memoryFilename); try { await fs.access(explicitContextPath, fsSync.constants.R_OK); allPaths.add(explicitContextPath); logger.debug( - `Found readable explicit ${geminiMdFilename}: ${explicitContextPath}`, + `Found readable explicit ${memoryFilename}: ${explicitContextPath}`, ); } catch { // Not found, which is okay for explicit-only discovery. @@ -128,7 +128,7 @@ async function getMemoryFilePathsInternalForEachDir( await fs.access(globalMemoryPath, fsSync.constants.R_OK); allPaths.add(globalMemoryPath); logger.debug( - `Found readable global ${geminiMdFilename}: ${globalMemoryPath}`, + `Found readable global ${memoryFilename}: ${globalMemoryPath}`, ); } catch { // It's okay if it's not found. @@ -141,13 +141,13 @@ async function getMemoryFilePathsInternalForEachDir( if (isHomeDirectory) { // For home directory, only check for QWEN.md directly in the home directory - const homeContextPath = path.join(resolvedHome, geminiMdFilename); + const homeContextPath = path.join(resolvedHome, memoryFilename); try { await fs.access(homeContextPath, fsSync.constants.R_OK); if (homeContextPath !== globalMemoryPath) { allPaths.add(homeContextPath); logger.debug( - `Found readable home ${geminiMdFilename}: ${homeContextPath}`, + `Found readable home ${memoryFilename}: ${homeContextPath}`, ); } } catch { @@ -158,7 +158,7 @@ async function getMemoryFilePathsInternalForEachDir( // if a valid currentWorkingDirectory is provided and it's not the home directory. const resolvedCwd = path.resolve(dir); logger.debug( - `Searching for ${geminiMdFilename} starting from CWD: ${resolvedCwd}`, + `Searching for ${memoryFilename} starting from CWD: ${resolvedCwd}`, ); const projectRoot = await findProjectRoot(resolvedCwd); @@ -178,7 +178,7 @@ async function getMemoryFilePathsInternalForEachDir( break; } - const potentialPath = path.join(currentDir, geminiMdFilename); + const potentialPath = path.join(currentDir, memoryFilename); try { await fs.access(potentialPath, fsSync.constants.R_OK); if (potentialPath !== globalMemoryPath) { diff --git a/packages/core/src/tools/tool-registry.test.ts b/packages/core/src/tools/tool-registry.test.ts index fcf221a4d3b..cd5664b8397 100644 --- a/packages/core/src/tools/tool-registry.test.ts +++ b/packages/core/src/tools/tool-registry.test.ts @@ -110,7 +110,7 @@ const baseConfigParams: ConfigParameters = { targetDir: '/test/dir', debugMode: false, userMemory: '', - geminiMdFileCount: 0, + memoryFileCount: 0, approvalMode: ApprovalMode.DEFAULT, }; diff --git a/packages/core/src/tools/tool-search.test.ts b/packages/core/src/tools/tool-search.test.ts index 065d7480767..0b8bac60430 100644 --- a/packages/core/src/tools/tool-search.test.ts +++ b/packages/core/src/tools/tool-search.test.ts @@ -29,7 +29,7 @@ const baseConfigParams: ConfigParameters = { targetDir: '/test/dir', debugMode: false, userMemory: '', - geminiMdFileCount: 0, + memoryFileCount: 0, approvalMode: ApprovalMode.DEFAULT, }; From 67dd620df2dbc6f9b8036a6a8776bf892d56742b Mon Sep 17 00:00:00 2001 From: yiliang114 Date: Mon, 24 Aug 2026 20:28:39 +0800 Subject: [PATCH 03/10] docs(serve): fix memory filename references --- docs/developers/daemon/02-serve-runtime.md | 4 ++-- docs/developers/daemon/03-acp-bridge.md | 11 +++++------ docs/developers/daemon/17-configuration.md | 3 +-- docs/developers/daemon/20-quickstart-operations.md | 2 +- docs/developers/qwen-serve-protocol.md | 2 +- packages/cli/src/serve/capabilities.ts | 11 +++++------ packages/cli/src/serve/run-qwen-serve.ts | 6 +++--- 7 files changed, 18 insertions(+), 21 deletions(-) diff --git a/docs/developers/daemon/02-serve-runtime.md b/docs/developers/daemon/02-serve-runtime.md index 468084c03d7..0c525099465 100644 --- a/docs/developers/daemon/02-serve-runtime.md +++ b/docs/developers/daemon/02-serve-runtime.md @@ -110,7 +110,7 @@ Calling `createServeApp` directly still returns only an `Application`. An embedd | Upstream used by `serve/` | Downstream using `serve/` | | ----------------------------------------------------------------------------------------------- | ----------------------------------------- | | `@qwen-code/acp-bridge`: bridge, event bus, status types | The `qwen` CLI `serve` subcommand handler | -| `packages/core`: `loadSettings`, `getCurrentMemoryFilename`, `Config`, `WorkspaceContext` | Direct embedders, tests | +| `packages/core`: `getAllMemoryFilenames`, `Config`, `WorkspaceContext` | Direct embedders, tests | | ACP SDK (`@agentclientprotocol/sdk`): `PROTOCOL_VERSION`, `ClientSideConnection` through bridge | | | Express + body-parser, `node:crypto`, `node:fs`, `node:path` | | @@ -136,7 +136,7 @@ Calling `createServeApp` directly still returns only an `Application`. An embedd | Flags | `--session-reap-interval-ms`, `--session-idle-timeout-ms` | Disconnected-session reaping control. | | Flags | `--rate-limit*` | Per-tier HTTP rate limit. | | `settings.json` | `policy.permissionStrategy`, `policy.consensusQuorum` | `MultiClientPermissionMediator` policy and quorum. | -| `settings.json` | `context.fileName` | `getCurrentMemoryFilename` override for the bridge. | +| `settings.json` | `context.fileName` | Workspace memory filename passed to `/workspace/init` through the workspace-service `contextFilename`. | See [`17-configuration.md`](./17-configuration.md) for the merged reference. diff --git a/docs/developers/daemon/03-acp-bridge.md b/docs/developers/daemon/03-acp-bridge.md index c86ddc8b221..51cbadf450e 100644 --- a/docs/developers/daemon/03-acp-bridge.md +++ b/docs/developers/daemon/03-acp-bridge.md @@ -184,11 +184,11 @@ sequenceDiagram ## Dependencies -| Upstream | Downstream | -| ------------------------------------------------------------------------------------------ | ---------------------------------------------- | -| `@agentclientprotocol/sdk` — `ClientSideConnection`, `PROTOCOL_VERSION`, ACP types | `packages/cli/src/serve/` (the daemon) | -| `@qwen-code/qwen-code-core` — `ApprovalMode`, `TrustGateError`, `getCurrentMemoryFilename` | `packages/channels/base/` (planned, F4) | -| `node:crypto`, `node:fs`, `node:path` | `packages/vscode-ide-companion/` (planned, F4) | +| Upstream | Downstream | +| ---------------------------------------------------------------------------------- | ---------------------------------------------- | +| `@agentclientprotocol/sdk` — `ClientSideConnection`, `PROTOCOL_VERSION`, ACP types | `packages/cli/src/serve/` (the daemon) | +| `@qwen-code/qwen-code-core` — `ApprovalMode`, `TrustGateError` | `packages/channels/base/` (planned, F4) | +| `node:crypto`, `node:fs`, `node:path` | `packages/vscode-ide-companion/` (planned, F4) | ## Configuration @@ -208,7 +208,6 @@ sequenceDiagram | `childEnvOverrides` | `{}` | Per-handle env additions / scrubs for the ACP child. | | `externalToolGuard` | (none) | Optional handler for the private child-to-parent pre-execution decision. The bridge accepts it only from the owning channel for the currently active Prompt. | | `persistApprovalMode`, `persistDisabledTools` | — | Settings-write hooks for the Wave 4 mutation routes. | -| `contextFilename` | from `settings.json`'s `context.fileName` | Overrides `getCurrentMemoryFilename`. | | `statusProvider` | (none) | Daemon-host preflight cells (`DaemonStatusProvider`). | | `delegateReadTextFileToClient` | `true` | Set `false` only for same-host runtimes so every child `FileSystemService.readTextFile` consumer uses the regular CLI filesystem service. | | `fileSystem` | (none) | `BridgeFileSystem` adapter for ACP `readTextFile` / `writeTextFile`. | diff --git a/docs/developers/daemon/17-configuration.md b/docs/developers/daemon/17-configuration.md index 4a63bbff534..f0c36c7304f 100644 --- a/docs/developers/daemon/17-configuration.md +++ b/docs/developers/daemon/17-configuration.md @@ -105,7 +105,7 @@ The daemon constructs each workspace runtime from that workspace's merged settin | --------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `policy.permissionStrategy` | `'first-responder' \| 'designated' \| 'consensus' \| 'local-only'` | Sets `BridgeOptions.permissionPolicy`; the active value appears in `/capabilities` as `policy.permission`. **Boot validates** through `validatePolicyConfig()` against `SERVE_CAPABILITY_REGISTRY.permission_mediation.modes`. Unknown literals throw `InvalidPolicyConfigError` and fail boot explicitly. | | `policy.consensusQuorum` | positive integer | N for the `consensus` policy. **Default** is `floor(M/2) + 1` over `votersAtIssue.size` (M=2 means unanimous; larger even M means more than half). If set under a non-consensus policy, it is ignored and boot prints a stderr warning. Non-positive integers throw `InvalidPolicyConfigError`. See [`04-permission-mediation.md`](./04-permission-mediation.md). | -| `context.fileName` | string | Overrides `getCurrentMemoryFilename()` through `BridgeOptions.contextFilename`. | +| `context.fileName` | string | Workspace memory filename. `qwen serve` snapshots it through `extractContextFilename()` and passes it to the workspace service as `contextFilename`; `POST /workspace/init` writes that file. | | `tools.disabled` | string[] | Tools disabled for the next ACP child spawn. Normalized through `normalizeDisabledToolList()` (`packages/cli/src/config/normalizeDisabledTools.ts`): non-array becomes `[]`, non-string entries are skipped, whitespace is trimmed, empty entries are dropped, and duplicates are removed while preserving first occurrence. Boot and `restartMcpServer` settings refresh both run through this function. `ToolRegistry.has(name)` is exact and case-sensitive. `POST /workspace/tools/:name/enable` and `tool_toggled` update this key. | | `tools.approvalMode` | `'default' \| 'auto' \| ...` | Default session approval mode; `POST /session/:id/approval-mode` writes here when `persist: true`. | | `telemetry` | object | OTel config. Keys include `enabled`, `otlpEndpoint`, `otlpProtocol`, `otlpTracesEndpoint`, `otlpLogsEndpoint`, `otlpMetricsEndpoint`, `target`, `outfile`, `userId`, `includeSensitiveSpanAttributes`, `sensitiveSpanAttributeMaxLength`, `resourceAttributes`, and `metrics.includeSessionId`. `resolveTelemetrySettings()` reads it at boot and initializes `initializeTelemetry()`. `userId` is process-wide and must not be configured as end-user identity when the daemon serves multiple users. | @@ -149,7 +149,6 @@ The daemon constructs each workspace runtime from that workspace's merged settin | `statusProvider` | Daemon-host preflight cells. | | `childEnvOverrides` | Per-handle environment additions or removals. | | `externalToolGuard` | Optional daemon-side handler for the private child-to-parent prepare RPC. The bridge validates channel ownership and the active Prompt before and after it calls the handler. | -| `contextFilename` | Overrides `getCurrentMemoryFilename()`. | | `channelIdleTimeoutMs` | How long to keep the ACP child alive after the last session closes, in ms; default `0`. | ## Important defaults diff --git a/docs/developers/daemon/20-quickstart-operations.md b/docs/developers/daemon/20-quickstart-operations.md index 8dea0cfcb0a..890c5463f40 100644 --- a/docs/developers/daemon/20-quickstart-operations.md +++ b/docs/developers/daemon/20-quickstart-operations.md @@ -137,7 +137,7 @@ Boot calls `loadSettings(boundWorkspace)` once: | --------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `policy.permissionStrategy` | `'first-responder' \| 'designated' \| 'consensus' \| 'local-only'` | Sets `BridgeOptions.permissionPolicy`. **Boot validates with `validatePolicyConfig`**; unknown values throw `InvalidPolicyConfigError` instead of falling back silently. | | `policy.consensusQuorum` | positive integer | N for the `consensus` policy. Default is `floor(M/2)+1`. If set under a non-consensus policy, it is ignored and boot logs a stderr warning. | -| `context.fileName` | string | Overrides `getCurrentMemoryFilename()` and controls which file `POST /workspace/init` writes. | +| `context.fileName` | string | Controls which file `POST /workspace/init` writes through the workspace-service `contextFilename`. | | `tools.disabled` | string[] | Normalized through `normalizeDisabledToolList()` (trim, drop empty entries, dedupe) before affecting the next ACP child spawn. | | `tools.approvalMode` | string | Default session approval mode. | | `telemetry` | object | OTel configuration: `enabled`, `otlpEndpoint`, `otlpProtocol`, per-signal endpoints, and more. See [`17-configuration.md`](./17-configuration.md). | diff --git a/docs/developers/qwen-serve-protocol.md b/docs/developers/qwen-serve-protocol.md index e14eb8e4f5e..e10167f3a84 100644 --- a/docs/developers/qwen-serve-protocol.md +++ b/docs/developers/qwen-serve-protocol.md @@ -2899,7 +2899,7 @@ Target errors use `skill_not_found`, `skill_not_toggleable`, or `skill_inactive_ Capability tag: `workspace_init`. Pure file IO — no ACP roundtrip, **no LLM invocation**. -Scaffold an empty `QWEN.md` (or whatever `getCurrentMemoryFilename()` returns under `--memory-file-name` overrides) at the daemon's primary workspace root. Mechanical only — for AI-driven content fill, follow up with `POST /session/:id/prompt`. +Scaffold an empty `QWEN.md` (or the workspace `context.fileName` settings override) at the daemon's primary workspace root. Mechanical only — for AI-driven content fill, follow up with `POST /session/:id/prompt`. Default refuses to overwrite when the target file exists with non-whitespace content. Whitespace-only files are treated as absent (matches the local `/init` slash command). diff --git a/packages/cli/src/serve/capabilities.ts b/packages/cli/src/serve/capabilities.ts index b77608d27a2..ad32423df68 100644 --- a/packages/cli/src/serve/capabilities.ts +++ b/packages/cli/src/serve/capabilities.ts @@ -206,13 +206,12 @@ export const SERVE_CAPABILITY_REGISTRY = { // Workspace trust policy changes rebuild the affected runtime generation // without restarting the daemon. V2 trust status exposes convergence. workspace_trust_hot_reload: { since: 'v1' }, - // `POST /workspace/init` scaffolds an empty - // `QWEN.md` (or whatever `getCurrentMemoryFilename()` returns) at - // the bound workspace root. Body: `{force?: boolean}`. Default + // `POST /workspace/init` scaffolds an empty `QWEN.md` (or the + // workspace `context.fileName` value injected as `contextFilename`) + // at the bound workspace root. Body: `{force?: boolean}`. Default // refuses with 409 when the file already exists; `force: true` - // overwrites. Mechanical only — does NOT call the LLM. To AI-fill - // the file, the caller should follow up with - // `POST /session/:id/prompt`. + // overwrites. Mechanical only — does NOT call the LLM. To AI-fill the + // file, the caller should follow up with `POST /session/:id/prompt`. workspace_init: { since: 'v1' }, // `POST /workspace/setup-github` installs the fixed // qwen-code-action workflow set into the bound workspace after diff --git a/packages/cli/src/serve/run-qwen-serve.ts b/packages/cli/src/serve/run-qwen-serve.ts index 9b3c6f49329..d18af2d0972 100644 --- a/packages/cli/src/serve/run-qwen-serve.ts +++ b/packages/cli/src/serve/run-qwen-serve.ts @@ -696,9 +696,9 @@ export function formatChannelWorkerDaemonUrl( * - array → first non-empty string element after trim, or undefined * - anything else (object, number, boolean, undefined) → undefined * - * Returning `undefined` is the bridge's signal to use its own - * `getCurrentMemoryFilename()` default — so a malformed value - * keeps the daemon alive rather than producing a garbage filename. + * Returning `undefined` leaves the daemon on its hard-coded `QWEN.md` + * init default — so a malformed value keeps the daemon alive rather + * than producing a garbage filename. */ export function extractContextFilename(value: unknown): string | undefined { if (typeof value === 'string') { From ed97f92ba9d194dcaaf9fbb00cd1f102c84cdaba Mon Sep 17 00:00:00 2001 From: "jinjing.zzj" Date: Mon, 24 Aug 2026 23:20:40 +0800 Subject: [PATCH 04/10] test(cli): pin primary workspace QWEN.md init fallback Assert that the primary daemon workspace service receives the hard-coded 'QWEN.md' context filename when boot settings carry no context.fileName. Previously only the secondary workspace's explicit SECONDARY.md resolution was asserted, so swapping the fallback literal at the createDaemonWorkspaceService call site survived the suite. --- packages/cli/src/serve/run-qwen-serve.test.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/cli/src/serve/run-qwen-serve.test.ts b/packages/cli/src/serve/run-qwen-serve.test.ts index dfa2feafe06..a42c9a867b6 100644 --- a/packages/cli/src/serve/run-qwen-serve.test.ts +++ b/packages/cli/src/serve/run-qwen-serve.test.ts @@ -2228,6 +2228,15 @@ describe('runQwenServe telemetry validation', () => { ([input]) => input.boundWorkspace === secondaryCwd, )?.[0], ).toMatchObject({ contextFilename: 'SECONDARY.md' }); + // bootSettings above carries no `context.fileName`, so the primary + // workspace must land on the hard-coded `QWEN.md` init default + // (`contextFilenameForInit ?? 'QWEN.md'`). Without this assertion the + // fallback literal could be swapped without any test noticing. + expect( + createWorkspaceService.mock.calls.find( + ([input]) => input.boundWorkspace === canonicalizeWorkspace(primary), + )?.[0], + ).toMatchObject({ contextFilename: 'QWEN.md' }); } finally { await handle.close(); } From 8b1d7750cb7172d086b8c173e2cd3703eae4ebcc Mon Sep 17 00:00:00 2001 From: "jinjing.zzj" Date: Tue, 25 Aug 2026 04:55:09 +0800 Subject: [PATCH 05/10] refactor(core,cli): finish Gemini residue rename in memoryDiscovery Complete the rename flagged in review: GeminiFileContent -> MemoryFileContent (module-local interface), includeDirectoriesToReadGemini -> includeDirectoriesToReadMemory (parameter only; all call sites are positional, zero cross-package impact), plus test-local variable names and the stale ORIGINAL_GEMINI_MD_FILENAME test title. --- packages/cli/src/config/config.ts | 4 +-- .../core/src/memory/memoryDiscovery.test.ts | 26 +++++++++---------- packages/core/src/memory/memoryDiscovery.ts | 22 ++++++++-------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/packages/cli/src/config/config.ts b/packages/cli/src/config/config.ts index fd77602c8e3..9bb70e8fc3d 100755 --- a/packages/cli/src/config/config.ts +++ b/packages/cli/src/config/config.ts @@ -1178,7 +1178,7 @@ export async function parseArguments(): Promise { // TODO: Consider if App.tsx should get memory via a server call or if Config should refresh itself. export async function loadHierarchicalGeminiMemory( currentWorkingDirectory: string, - includeDirectoriesToReadGemini: readonly string[] = [], + includeDirectoriesToReadMemory: readonly string[] = [], fileService: FileDiscoveryService, extensionContextFilePaths: string[] = [], folderTrust: boolean, @@ -1198,7 +1198,7 @@ export async function loadHierarchicalGeminiMemory( // Directly call the server function with the corrected path. return loadServerHierarchicalMemory( effectiveCwd, - includeDirectoriesToReadGemini, + includeDirectoriesToReadMemory, fileService, extensionContextFilePaths, folderTrust, diff --git a/packages/core/src/memory/memoryDiscovery.test.ts b/packages/core/src/memory/memoryDiscovery.test.ts index 50121c4a067..e66a1838467 100644 --- a/packages/core/src/memory/memoryDiscovery.test.ts +++ b/packages/core/src/memory/memoryDiscovery.test.ts @@ -349,12 +349,12 @@ describe('loadServerHierarchicalMemory', () => { }); }); - it('should load ORIGINAL_GEMINI_MD_FILENAME files by upward traversal from CWD to project root', async () => { - const projectRootGeminiFile = await createTestFile( + it('should load context files by upward traversal with default filename', async () => { + const projectRootMemoryFile = await createTestFile( path.join(projectRoot, DEFAULT_CONTEXT_FILENAME), 'Project root memory', ); - const srcGeminiFile = await createTestFile( + const srcMemoryFile = await createTestFile( path.join(cwd, DEFAULT_CONTEXT_FILENAME), 'Src directory memory', ); @@ -368,11 +368,11 @@ describe('loadServerHierarchicalMemory', () => { ); expect(result).toEqual({ - memoryContent: `--- Context from: ${path.relative(cwd, projectRootGeminiFile)} ---\nProject root memory\n--- End of Context from: ${path.relative(cwd, projectRootGeminiFile)} ---\n\n--- Context from: ${path.relative(cwd, srcGeminiFile)} ---\nSrc directory memory\n--- End of Context from: ${path.relative(cwd, srcGeminiFile)} ---`, + memoryContent: `--- Context from: ${path.relative(cwd, projectRootMemoryFile)} ---\nProject root memory\n--- End of Context from: ${path.relative(cwd, projectRootMemoryFile)} ---\n\n--- Context from: ${path.relative(cwd, srcMemoryFile)} ---\nSrc directory memory\n--- End of Context from: ${path.relative(cwd, srcMemoryFile)} ---`, fileCount: 2, contextFilePaths: [ - path.relative(cwd, projectRootGeminiFile), - path.relative(cwd, srcGeminiFile), + path.relative(cwd, projectRootMemoryFile), + path.relative(cwd, srcMemoryFile), ], ruleCount: 0, conditionalRules: [], @@ -414,15 +414,15 @@ describe('loadServerHierarchicalMemory', () => { path.join(homedir, QWEN_DIR, DEFAULT_CONTEXT_FILENAME), 'default context content', ); - const rootGeminiFile = await createTestFile( + const rootMemoryFile = await createTestFile( path.join(testRootDir, DEFAULT_CONTEXT_FILENAME), 'Project parent memory', ); - const projectRootGeminiFile = await createTestFile( + const projectRootMemoryFile = await createTestFile( path.join(projectRoot, DEFAULT_CONTEXT_FILENAME), 'Project root memory', ); - const cwdGeminiFile = await createTestFile( + const cwdMemoryFile = await createTestFile( path.join(cwd, DEFAULT_CONTEXT_FILENAME), 'CWD memory', ); @@ -441,13 +441,13 @@ describe('loadServerHierarchicalMemory', () => { // Subdirectory files are not loaded, only global and upward from CWD expect(result).toEqual({ - memoryContent: `--- Context from: ${path.relative(cwd, defaultContextFile)} ---\ndefault context content\n--- End of Context from: ${path.relative(cwd, defaultContextFile)} ---\n\n--- Context from: ${path.relative(cwd, rootGeminiFile)} ---\nProject parent memory\n--- End of Context from: ${path.relative(cwd, rootGeminiFile)} ---\n\n--- Context from: ${path.relative(cwd, projectRootGeminiFile)} ---\nProject root memory\n--- End of Context from: ${path.relative(cwd, projectRootGeminiFile)} ---\n\n--- Context from: ${path.relative(cwd, cwdGeminiFile)} ---\nCWD memory\n--- End of Context from: ${path.relative(cwd, cwdGeminiFile)} ---`, + memoryContent: `--- Context from: ${path.relative(cwd, defaultContextFile)} ---\ndefault context content\n--- End of Context from: ${path.relative(cwd, defaultContextFile)} ---\n\n--- Context from: ${path.relative(cwd, rootMemoryFile)} ---\nProject parent memory\n--- End of Context from: ${path.relative(cwd, rootMemoryFile)} ---\n\n--- Context from: ${path.relative(cwd, projectRootMemoryFile)} ---\nProject root memory\n--- End of Context from: ${path.relative(cwd, projectRootMemoryFile)} ---\n\n--- Context from: ${path.relative(cwd, cwdMemoryFile)} ---\nCWD memory\n--- End of Context from: ${path.relative(cwd, cwdMemoryFile)} ---`, fileCount: 4, contextFilePaths: [ path.join('~', path.relative(homedir, defaultContextFile)), - path.relative(cwd, rootGeminiFile), - path.relative(cwd, projectRootGeminiFile), - path.relative(cwd, cwdGeminiFile), + path.relative(cwd, rootMemoryFile), + path.relative(cwd, projectRootMemoryFile), + path.relative(cwd, cwdMemoryFile), ], ruleCount: 0, conditionalRules: [], diff --git a/packages/core/src/memory/memoryDiscovery.ts b/packages/core/src/memory/memoryDiscovery.ts index e8b78745a51..4fd8c3e25c5 100644 --- a/packages/core/src/memory/memoryDiscovery.ts +++ b/packages/core/src/memory/memoryDiscovery.ts @@ -27,7 +27,7 @@ import type { const logger = createDebugLogger('MEMORY_DISCOVERY'); -interface GeminiFileContent { +interface MemoryFileContent { filePath: string; content: string | null; } @@ -42,7 +42,7 @@ export interface InstructionsLoadedNotification { async function getMemoryFilePathsInternal( currentWorkingDirectory: string, - includeDirectoriesToReadGemini: readonly string[], + includeDirectoriesToReadMemory: readonly string[], userHomePath: string, fileService: FileDiscoveryService, extensionContextFilePaths: string[] = [], @@ -51,8 +51,8 @@ async function getMemoryFilePathsInternal( ): Promise { const dirs = new Set( implicitDiscoveryEnabled - ? [...includeDirectoriesToReadGemini, currentWorkingDirectory] - : [...includeDirectoriesToReadGemini], + ? [...includeDirectoriesToReadMemory, currentWorkingDirectory] + : [...includeDirectoriesToReadMemory], ); // Process directories in parallel with concurrency limit to prevent EMFILE errors @@ -221,10 +221,10 @@ async function readMemoryFiles( notification: InstructionsLoadedNotification, ) => void | Promise, loadReason: Exclude = 'session_start', -): Promise { +): Promise { // Process files in parallel with concurrency limit to prevent EMFILE errors const CONCURRENT_LIMIT = 20; // Higher limit for file reads as they're typically faster - const results: GeminiFileContent[] = []; + const results: MemoryFileContent[] = []; const notifyInstructionsLoaded = async ( notification: InstructionsLoadedNotification, ) => { @@ -241,7 +241,7 @@ async function readMemoryFiles( for (let i = 0; i < filePaths.length; i += CONCURRENT_LIMIT) { const batch = filePaths.slice(i, i + CONCURRENT_LIMIT); const batchPromises = batch.map( - async (filePath): Promise => { + async (filePath): Promise => { try { const content = await fs.readFile(filePath, 'utf-8'); @@ -347,12 +347,12 @@ export function formatContextFileDisplayPath( // The attachment rule for the system prompt: only non-blank string content // reaches it. Shared by concatenateInstructions and contextFilePaths so the // "displayed = attached" property holds by construction. -function hasAttachedContent(item: GeminiFileContent): boolean { +function hasAttachedContent(item: MemoryFileContent): boolean { return typeof item.content === 'string' && item.content.trim().length > 0; } function concatenateInstructions( - instructionContents: GeminiFileContent[], + instructionContents: MemoryFileContent[], // CWD is needed to resolve relative paths for display markers currentWorkingDirectoryForDisplay: string, ): string { @@ -461,7 +461,7 @@ function createMemoryTypeClassifier( */ export async function loadServerHierarchicalMemory( currentWorkingDirectory: string, - includeDirectoriesToReadGemini: readonly string[], + includeDirectoriesToReadMemory: readonly string[], fileService: FileDiscoveryService, extensionContextFilePaths: string[] = [], folderTrust: boolean, @@ -479,7 +479,7 @@ export async function loadServerHierarchicalMemory( const userHomePath = homedir(); const filePaths = await getMemoryFilePathsInternal( currentWorkingDirectory, - includeDirectoriesToReadGemini, + includeDirectoriesToReadMemory, userHomePath, fileService, extensionContextFilePaths, From 139e1ef48d3e0299df007042299a813fbb584af7 Mon Sep 17 00:00:00 2001 From: "jinjing.zzj" Date: Tue, 25 Aug 2026 04:55:56 +0800 Subject: [PATCH 06/10] docs(design): route loadHierarchicalGeminiMemory to Memory naming Per exception #1 the Llm prefix is reserved for the generic LLM-client surface; the symbol is a memory-file loader (thin wrapper around core's loadServerHierarchicalMemory), so the PR-2 symbol map targets loadHierarchicalMemory instead of loadHierarchicalLlmMemory. Doc-only: the code symbol is not renamed by this PR. --- .../2026-08-22-rename-gemini-fork-residue.md | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/docs/design/2026-08-22-rename-gemini-fork-residue.md b/docs/design/2026-08-22-rename-gemini-fork-residue.md index 74bd7aa04cc..c00d6e79379 100644 --- a/docs/design/2026-08-22-rename-gemini-fork-residue.md +++ b/docs/design/2026-08-22-rename-gemini-fork-residue.md @@ -29,7 +29,7 @@ Rename the local `Gemini` identifiers to `Llm`, with these exceptions: 2. **UI spinners** — `GeminiRespondingSpinner` / `GeminiSpinner` drop the prefix. → `RespondingSpinner` / `Spinner`. 3. **Gemini extension format (keep as-is)** — `packages/core/src/extension/ - gemini-converter.ts` converts *upstream Gemini CLI extension* configs +gemini-converter.ts` converts _upstream Gemini CLI extension_ configs (`GeminiExtensionConfig`, `convertGeminiToQwenConfig`, `convertGeminiExtensionPackage`, `isGeminiExtensionConfig`). The `Gemini` here denotes a real external format, not the generic LLM client. **Not part @@ -43,51 +43,51 @@ Rename the local `Gemini` identifiers to `Llm`, with these exceptions: Local type/class/enum names (PascalCase, → `Llm*`): -| Current | Definition | New | -|---|---|---| -| `GeminiClient` | `core/src/core/client.ts:375` class | `LlmClient` | -| `GeminiChat` | `core/src/core/geminiChat.ts:1853` class | `LlmChat` | -| `GeminiEventType` | `core/src/core/turn.ts:62` **and** `cli/src/ui/types.ts:42` (two enums) | `LlmEventType` | -| `GeminiContentGenerator` | `core/src/core/geminiContentGenerator/geminiContentGenerator.ts:61` class | `LlmContentGenerator` | -| `GeminiCodeRequest` | `core/src/core/geminiRequest.ts:15` type | `LlmCodeRequest` | -| `GeminiChatSendOptions` | `core/src/core/geminiChat.ts:448` interface | `LlmChatSendOptions` | -| `GeminiErrorEventValue` / `GeminiFinishedEventValue` | `core/src/core/turn.ts:112/122` | `LlmErrorEventValue` / `LlmFinishedEventValue` | -| `GeminiRespondingSpinner` / `GeminiSpinner` | `cli/src/ui/components/GeminiRespondingSpinner.tsx:32/59` | `RespondingSpinner` / `Spinner` | +| Current | Definition | New | +| ---------------------------------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------- | +| `GeminiClient` | `core/src/core/client.ts:375` class | `LlmClient` | +| `GeminiChat` | `core/src/core/geminiChat.ts:1853` class | `LlmChat` | +| `GeminiEventType` | `core/src/core/turn.ts:62` **and** `cli/src/ui/types.ts:42` (two enums) | `LlmEventType` | +| `GeminiContentGenerator` | `core/src/core/geminiContentGenerator/geminiContentGenerator.ts:61` class | `LlmContentGenerator` | +| `GeminiCodeRequest` | `core/src/core/geminiRequest.ts:15` type | `LlmCodeRequest` | +| `GeminiChatSendOptions` | `core/src/core/geminiChat.ts:448` interface | `LlmChatSendOptions` | +| `GeminiErrorEventValue` / `GeminiFinishedEventValue` | `core/src/core/turn.ts:112/122` | `LlmErrorEventValue` / `LlmFinishedEventValue` | +| `GeminiRespondingSpinner` / `GeminiSpinner` | `cli/src/ui/components/GeminiRespondingSpinner.tsx:32/59` | `RespondingSpinner` / `Spinner` | camelCase functions/variables (token-infix, → `Llm*`), highest-frequency first: -| Current | New | -|---|---| -| `getGeminiClient` | `getLlmClient` | -| `mockGeminiClient` | `mockLlmClient` | -| `convertOpenAIChunkToGemini` | `convertOpenAIChunkToLlm` | -| `convertGeminiRequestToOpenAI` | `convertLlmRequestToOpenAI` | -| `convertOpenAIResponseToGemini` | `convertOpenAIResponseToLlm` | -| `responseSubmittedToGemini` | `responseSubmittedToLlm` | -| `useGeminiStream` | `useLlmStream` | -| `convertGeminiRequestToAnthropic` | `convertLlmRequestToAnthropic` | +| Current | New | +| ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | +| `getGeminiClient` | `getLlmClient` | +| `mockGeminiClient` | `mockLlmClient` | +| `convertOpenAIChunkToGemini` | `convertOpenAIChunkToLlm` | +| `convertGeminiRequestToOpenAI` | `convertLlmRequestToOpenAI` | +| `convertOpenAIResponseToGemini` | `convertOpenAIResponseToLlm` | +| `responseSubmittedToGemini` | `responseSubmittedToLlm` | +| `useGeminiStream` | `useLlmStream` | +| `convertGeminiRequestToAnthropic` | `convertLlmRequestToAnthropic` | | `setGeminiMdFilename` / `getAllGeminiMdFilenames` / `getCurrentGeminiMdFilename` / `getGeminiMdFileCount` / `setGeminiMdFileCount` | `setMemoryFilename` / `getAllMemoryFilenames` / `getCurrentMemoryFilename` / `getMemoryFileCount` / `setMemoryFileCount` | -| `mockGeminiResponse` / `mockGeminiClientInstance` / `MockedGeminiClientClass` | `mockLlmResponse` / `mockLlmClientInstance` / `MockedLlmClientClass` | -| `convertGeminiToolsToOpenAI` / `convertGeminiToolsToAnthropic` | `convertLlmToolsToOpenAI` / `convertLlmToolsToAnthropic` | -| `convertGeminiToolParametersToOpenAI` | `convertLlmToolParametersToOpenAI` | -| `newGeminiMessageBuffer` / `makeGeminiHistoryItem` / `extractGeminiContent` / `buildGeminiChunk` / `recordGeminiChunk` | `newLlmMessageBuffer` / `makeLlmHistoryItem` / `extractLlmContent` / `buildLlmChunk` / `recordLlmChunk` | -| `createInitializedGeminiClient` / `createGeminiContentGenerator` | `createInitializedLlmClient` / `createLlmContentGenerator` | -| `mapAnthropicFinishReasonToGemini` / `convertAnthropicResponseToGemini` | `mapAnthropicFinishReasonToLlm` / `convertAnthropicResponseToLlm` | -| `pendingGeminiHistoryItems` / `skipGeminiInitialization` / `loadHierarchicalGeminiMemory` | `pendingLlmHistoryItems` / `skipLlmInitialization` / `loadHierarchicalLlmMemory` | +| `mockGeminiResponse` / `mockGeminiClientInstance` / `MockedGeminiClientClass` | `mockLlmResponse` / `mockLlmClientInstance` / `MockedLlmClientClass` | +| `convertGeminiToolsToOpenAI` / `convertGeminiToolsToAnthropic` | `convertLlmToolsToOpenAI` / `convertLlmToolsToAnthropic` | +| `convertGeminiToolParametersToOpenAI` | `convertLlmToolParametersToOpenAI` | +| `newGeminiMessageBuffer` / `makeGeminiHistoryItem` / `extractGeminiContent` / `buildGeminiChunk` / `recordGeminiChunk` | `newLlmMessageBuffer` / `makeLlmHistoryItem` / `extractLlmContent` / `buildLlmChunk` / `recordLlmChunk` | +| `createInitializedGeminiClient` / `createGeminiContentGenerator` | `createInitializedLlmClient` / `createLlmContentGenerator` | +| `mapAnthropicFinishReasonToGemini` / `convertAnthropicResponseToGemini` | `mapAnthropicFinishReasonToLlm` / `convertAnthropicResponseToLlm` | +| `pendingGeminiHistoryItems` / `skipGeminiInitialization` / `loadHierarchicalGeminiMemory` | `pendingLlmHistoryItems` / `skipLlmInitialization` / `loadHierarchicalMemory` | ## File renames Non-test files; `gemini-converter.ts` is intentionally NOT renamed (see above). -| Current | New | -|---|---| -| `packages/cli/src/gemini.tsx` | `packages/cli/src/llm.tsx` | -| `packages/cli/src/ui/components/GeminiRespondingSpinner.tsx` | `packages/cli/src/ui/components/RespondingSpinner.tsx` | -| `packages/cli/src/ui/hooks/useGeminiStream.ts` | `packages/cli/src/ui/hooks/use-llm-stream.ts` | -| `packages/core/src/core/geminiChat.ts` | `packages/core/src/core/llm-chat.ts` | +| Current | New | +| ------------------------------------------------------------------------- | ----------------------------------------------------------------------- | +| `packages/cli/src/gemini.tsx` | `packages/cli/src/llm.tsx` | +| `packages/cli/src/ui/components/GeminiRespondingSpinner.tsx` | `packages/cli/src/ui/components/RespondingSpinner.tsx` | +| `packages/cli/src/ui/hooks/useGeminiStream.ts` | `packages/cli/src/ui/hooks/use-llm-stream.ts` | +| `packages/core/src/core/geminiChat.ts` | `packages/core/src/core/llm-chat.ts` | | `packages/core/src/core/geminiContentGenerator/geminiContentGenerator.ts` | `packages/core/src/core/llm-content-generator/llm-content-generator.ts` | -| `packages/core/src/core/geminiContentGenerator/index.ts` | `packages/core/src/core/llm-content-generator/index.ts` | -| `packages/core/src/core/geminiRequest.ts` | `packages/core/src/core/llm-request.ts` | +| `packages/core/src/core/geminiContentGenerator/index.ts` | `packages/core/src/core/llm-content-generator/index.ts` | +| `packages/core/src/core/geminiRequest.ts` | `packages/core/src/core/llm-request.ts` | ## Phasing From 094e2c66108952e0cbe60a54c0e73e4ba4d3c7c0 Mon Sep 17 00:00:00 2001 From: "jinjing.zzj" Date: Tue, 25 Aug 2026 04:58:42 +0800 Subject: [PATCH 07/10] docs(cli): narrow extractContextFilename fallback description The undefined fallback first inherits the primary workspace's configured context.fileName snapshot (contextFilenameForInit) at the secondary startup and dynamically added workspace call sites, before the hard-coded QWEN.md. Describe the actual chain instead of the hard-coded default only. Comment-only: the inheritance behavior predates this PR and is unchanged. --- packages/cli/src/serve/run-qwen-serve.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/serve/run-qwen-serve.ts b/packages/cli/src/serve/run-qwen-serve.ts index d18af2d0972..6f77e399466 100644 --- a/packages/cli/src/serve/run-qwen-serve.ts +++ b/packages/cli/src/serve/run-qwen-serve.ts @@ -696,9 +696,10 @@ export function formatChannelWorkerDaemonUrl( * - array → first non-empty string element after trim, or undefined * - anything else (object, number, boolean, undefined) → undefined * - * Returning `undefined` leaves the daemon on its hard-coded `QWEN.md` - * init default — so a malformed value keeps the daemon alive rather - * than producing a garbage filename. + * Returning `undefined` leaves the workspace on the daemon's init-default + * chain — the primary workspace's configured `context.fileName` snapshot + * (`contextFilenameForInit`), then the hard-coded `QWEN.md` — so a malformed + * value keeps the daemon alive rather than producing a garbage filename. */ export function extractContextFilename(value: unknown): string | undefined { if (typeof value === 'string') { From aceb66436273ea9e16dfcfdb5e2515213bf2be62 Mon Sep 17 00:00:00 2001 From: "jinjing.zzj" Date: Tue, 25 Aug 2026 07:32:19 +0800 Subject: [PATCH 08/10] refactor(cli): rename loadHierarchicalGeminiMemory to loadHierarchicalMemory The design doc's symbol map routes the memory loader to loadHierarchicalMemory (memory family, exception #1), but no phasing bullet performed the rename and a prior round left the mixed signature. Complete the rename across the definition (config.ts), the AppContainer call site, and the AppContainer test mocks, and update the design doc's exception #1, symbol map, and PR-1 phasing bullet so the map row is no longer orphaned. --- docs/design/2026-08-22-rename-gemini-fork-residue.md | 12 +++++++++--- packages/cli/src/config/config.ts | 4 ++-- packages/cli/src/ui/AppContainer.test.tsx | 8 ++++---- packages/cli/src/ui/AppContainer.tsx | 4 ++-- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/docs/design/2026-08-22-rename-gemini-fork-residue.md b/docs/design/2026-08-22-rename-gemini-fork-residue.md index c00d6e79379..16d06b93c3c 100644 --- a/docs/design/2026-08-22-rename-gemini-fork-residue.md +++ b/docs/design/2026-08-22-rename-gemini-fork-residue.md @@ -25,7 +25,10 @@ Rename the local `Gemini` identifiers to `Llm`, with these exceptions: 1. **Memory filename** — `GeminiMdFilename` (+ `set/get/getAll/getCurrent`, `GeminiMdFileCount`) is the project memory file (`QWEN.md`), a memory - concept, not an LLM client. → `Memory*`. + concept, not an LLM client. → `Memory*`. The loader + `loadHierarchicalGeminiMemory` (a thin wrapper around core's + `loadServerHierarchicalMemory`) belongs to the same family: → + `loadHierarchicalMemory`. 2. **UI spinners** — `GeminiRespondingSpinner` / `GeminiSpinner` drop the prefix. → `RespondingSpinner` / `Spinner`. 3. **Gemini extension format (keep as-is)** — `packages/core/src/extension/ @@ -73,7 +76,8 @@ camelCase functions/variables (token-infix, → `Llm*`), highest-frequency first | `newGeminiMessageBuffer` / `makeGeminiHistoryItem` / `extractGeminiContent` / `buildGeminiChunk` / `recordGeminiChunk` | `newLlmMessageBuffer` / `makeLlmHistoryItem` / `extractLlmContent` / `buildLlmChunk` / `recordLlmChunk` | | `createInitializedGeminiClient` / `createGeminiContentGenerator` | `createInitializedLlmClient` / `createLlmContentGenerator` | | `mapAnthropicFinishReasonToGemini` / `convertAnthropicResponseToGemini` | `mapAnthropicFinishReasonToLlm` / `convertAnthropicResponseToLlm` | -| `pendingGeminiHistoryItems` / `skipGeminiInitialization` / `loadHierarchicalGeminiMemory` | `pendingLlmHistoryItems` / `skipLlmInitialization` / `loadHierarchicalMemory` | +| `pendingGeminiHistoryItems` / `skipGeminiInitialization` | `pendingLlmHistoryItems` / `skipLlmInitialization` | +| `loadHierarchicalGeminiMemory` | `loadHierarchicalMemory` (memory family, exception #1) | ## File renames @@ -97,7 +101,9 @@ move as one atomic PR. **PR 1 — independent small families** (no cross-package risk, small diff): -- Memory filename: `GeminiMdFilename` family → `Memory*`. +- Memory filename: `GeminiMdFilename` family → `Memory*`, and + `loadHierarchicalGeminiMemory` → `loadHierarchicalMemory` (memory loader, + exception #1). - UI spinners: `GeminiRespondingSpinner` / `GeminiSpinner` → `RespondingSpinner` / `Spinner`, and `GeminiRespondingSpinner.tsx` → `RespondingSpinner.tsx`. diff --git a/packages/cli/src/config/config.ts b/packages/cli/src/config/config.ts index 9bb70e8fc3d..3f5f5badb75 100755 --- a/packages/cli/src/config/config.ts +++ b/packages/cli/src/config/config.ts @@ -1176,7 +1176,7 @@ export async function parseArguments(): Promise { // This function is now a thin wrapper around the server's implementation. // It's kept in the CLI for now as App.tsx directly calls it for memory refresh. // TODO: Consider if App.tsx should get memory via a server call or if Config should refresh itself. -export async function loadHierarchicalGeminiMemory( +export async function loadHierarchicalMemory( currentWorkingDirectory: string, includeDirectoriesToReadMemory: readonly string[] = [], fileService: FileDiscoveryService, @@ -1614,7 +1614,7 @@ export async function loadCliConfig( // Set the context filename in the server's memoryTool module BEFORE loading memory // TODO(b/343434939): This is a bit of a hack. The contextFileName should ideally be passed // directly to the Config constructor in core, and have core handle setMemoryFilename. - // However, loadHierarchicalGeminiMemory is called *before* createServerConfig. + // However, loadHierarchicalMemory is called *before* createServerConfig. if (settings.context?.fileName) { setServerMemoryFilename(settings.context.fileName); } else { diff --git a/packages/cli/src/ui/AppContainer.test.tsx b/packages/cli/src/ui/AppContainer.test.tsx index 97c207df81b..168e5ba931d 100644 --- a/packages/cli/src/ui/AppContainer.test.tsx +++ b/packages/cli/src/ui/AppContainer.test.tsx @@ -187,12 +187,12 @@ vi.mock('../utils/events.js'); vi.mock('./handleAutoUpdate.js'); vi.mock('../utils/cleanup.js'); -const mockLoadHierarchicalGeminiMemory = vi.hoisted(() => vi.fn()); +const mockLoadHierarchicalMemory = vi.hoisted(() => vi.fn()); vi.mock('../config/config.js', async (importOriginal) => { const actual = await importOriginal(); return { ...actual, - loadHierarchicalGeminiMemory: mockLoadHierarchicalGeminiMemory, + loadHierarchicalMemory: mockLoadHierarchicalMemory, }; }); @@ -6652,7 +6652,7 @@ describe('AppContainer State Management', () => { }); it('performMemoryRefresh anchors on config.getWorkingDir() and updates contextFilePaths', async () => { - mockLoadHierarchicalGeminiMemory.mockResolvedValue({ + mockLoadHierarchicalMemory.mockResolvedValue({ memoryContent: 'content', fileCount: 1, contextFilePaths: ['/custom/QWEN.md'], @@ -6697,7 +6697,7 @@ describe('AppContainer State Management', () => { await performMemoryRefresh(); }); - expect(mockLoadHierarchicalGeminiMemory).toHaveBeenCalledWith( + expect(mockLoadHierarchicalMemory).toHaveBeenCalledWith( '/custom/workspace', expect.anything(), expect.anything(), diff --git a/packages/cli/src/ui/AppContainer.tsx b/packages/cli/src/ui/AppContainer.tsx index ae55e3517a5..05be5d67251 100644 --- a/packages/cli/src/ui/AppContainer.tsx +++ b/packages/cli/src/ui/AppContainer.tsx @@ -87,7 +87,7 @@ import { getStickyTodosRenderKey, } from './utils/todoSnapshot.js'; import type { TodoItem } from './components/TodoDisplay.js'; -import { loadHierarchicalGeminiMemory } from '../config/config.js'; +import { loadHierarchicalMemory } from '../config/config.js'; import { profileCheckpoint, finalizeStartupProfile, @@ -2093,7 +2093,7 @@ export const AppContainer = (props: AppContainerProps) => { contextFilePaths, conditionalRules, projectRoot, - } = await loadHierarchicalGeminiMemory( + } = await loadHierarchicalMemory( config.getWorkingDir(), settings.merged.context?.loadFromIncludeDirectories ? config.getWorkspaceContext().getDirectories() From 2c53c53dd5311720aed1d966e7bc5888ddfc16de Mon Sep 17 00:00:00 2001 From: yiliang114 Date: Wed, 26 Aug 2026 14:50:11 +0800 Subject: [PATCH 09/10] fix(core): preserve Gemini rename compatibility --- .../2026-08-22-rename-gemini-fork-residue.md | 15 +++++++++++++ eslint.legacy-filenames.mjs | 1 + packages/core/src/config/config.test.ts | 22 +++++++++++++++++++ packages/core/src/config/config.ts | 15 ++++++++++++- packages/core/src/core/geminiChat.ts | 6 ++++- packages/core/src/core/geminiRequest.ts | 8 +++++++ packages/core/src/core/llm-request.test.ts | 5 +++++ packages/core/src/core/llm-request.ts | 6 +++++ packages/core/src/core/turn.ts | 6 +++++ packages/core/src/memory/const.test.ts | 8 +++++++ packages/core/src/tools/memory-config.ts | 3 +++ packages/core/src/utils/memory-constants.ts | 9 ++++++++ 12 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 packages/core/src/core/geminiRequest.ts diff --git a/docs/design/2026-08-22-rename-gemini-fork-residue.md b/docs/design/2026-08-22-rename-gemini-fork-residue.md index 16d06b93c3c..ba86ffc3e22 100644 --- a/docs/design/2026-08-22-rename-gemini-fork-residue.md +++ b/docs/design/2026-08-22-rename-gemini-fork-residue.md @@ -42,6 +42,11 @@ gemini-converter.ts` converts _upstream Gemini CLI extension_ configs (mostly `cli/src/acp-integration`). These belong to `#4063` item 1 (de-Google the type system), not this rename. +`@qwen-code/qwen-code-core` is also published as a standalone package. Names +already exported from its root barrel, `Config`, or supported deep-import paths +remain as deprecated aliases for one release; repository consumers use only +the new names. + ## Symbol map Local type/class/enum names (PascalCase, → `Llm*`): @@ -93,6 +98,8 @@ Non-test files; `gemini-converter.ts` is intentionally NOT renamed (see above). | `packages/core/src/core/geminiContentGenerator/index.ts` | `packages/core/src/core/llm-content-generator/index.ts` | | `packages/core/src/core/geminiRequest.ts` | `packages/core/src/core/llm-request.ts` | +The old `geminiRequest.ts` path remains as a one-release re-export shim. + ## Phasing Two pull requests. The core LLM symbols are strongly coupled (`GeminiClient` @@ -110,6 +117,9 @@ move as one atomic PR. - Leaf types: `GeminiCodeRequest`, `GeminiChatSendOptions`, `GeminiErrorEventValue`, `GeminiFinishedEventValue`, and `geminiRequest.ts` → `llm-request.ts`. +- One-release deprecated aliases for the public core exports, `Config` memory + count input/accessors, memory filename helpers, and the old request module + path. **PR 2 — core LLM layer (atomic)**: @@ -130,6 +140,9 @@ move as one atomic PR. - **Cross-package barrel**: `GeminiClient` and `GeminiEventType` are exported via the `@qwen-code/qwen-code-core` barrel. `sdk-typescript` and `acp-bridge` import them; PR 2 must update those packages. +- **Published package compatibility**: renamed public symbols remain as + deprecated aliases for one release. Remove those aliases only after a stable + release has shipped the replacement names. - **Two `GeminiEventType` enums**: `core/src/core/turn.ts` and `cli/src/ui/types.ts` define the same name. Rename both and verify their relationship (distinct enums vs re-export) before PR 2. @@ -143,4 +156,6 @@ move as one atomic PR. - `cd packages/core && npx tsc --noEmit` - `cd packages/cli && npx tsc --noEmit` - Targeted unit tests per renamed module +- Legacy-name grep results are confined to the documented compatibility aliases + and `geminiRequest.ts` shim; active repository consumers use the new names. - `npm run lint` (kebab-case filenames are enforced) diff --git a/eslint.legacy-filenames.mjs b/eslint.legacy-filenames.mjs index b1a74313992..a2839e04beb 100644 --- a/eslint.legacy-filenames.mjs +++ b/eslint.legacy-filenames.mjs @@ -134,6 +134,7 @@ export const legacyFilenames = [ 'functionHookRunner', 'geminiChat', 'geminiContentGenerator', + 'geminiRequest', 'generateContentResponseUtilities', 'generatedFiles', 'getFolderStructure', diff --git a/packages/core/src/config/config.test.ts b/packages/core/src/config/config.test.ts index 9f0330e2181..1b9eec828a9 100644 --- a/packages/core/src/config/config.test.ts +++ b/packages/core/src/config/config.test.ts @@ -607,6 +607,28 @@ describe('Server Config (config.ts)', () => { }); }); + describe('memory file count compatibility', () => { + it('keeps the legacy parameter and accessors working for one release', () => { + const config = new Config({ ...baseParams, geminiMdFileCount: 2 }); + + expect(config.getMemoryFileCount()).toBe(2); + expect(config.getGeminiMdFileCount()).toBe(2); + + config.setGeminiMdFileCount(3); + expect(config.getMemoryFileCount()).toBe(3); + }); + + it('prefers the renamed parameter when both names are present', () => { + const config = new Config({ + ...baseParams, + geminiMdFileCount: 2, + memoryFileCount: 4, + }); + + expect(config.getMemoryFileCount()).toBe(4); + }); + }); + describe('getMemoryAgentTimeoutMinutes', () => { it('returns undefined when unset', () => { expect( diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index a82b7424135..be4309c91e1 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -1082,6 +1082,8 @@ export interface ConfigParameters { lspClient?: LspClient; userMemory?: string; memoryFileCount?: number; + /** @deprecated Use `memoryFileCount`; retained for one release. */ + geminiMdFileCount?: number; approvalMode?: ApprovalMode; contextFileName?: string | string[]; accessibility?: AccessibilitySettings; @@ -2335,7 +2337,8 @@ export class Config { this.sessionSubagents = params.sessionSubagents ?? []; this.sdkMode = params.sdkMode ?? false; this.userMemory = params.userMemory ?? ''; - this.memoryFileCount = params.memoryFileCount ?? 0; + this.memoryFileCount = + params.memoryFileCount ?? params.geminiMdFileCount ?? 0; this.contextRuleExcludes = params.contextRuleExcludes ?? []; this.approvalMode = params.approvalMode ?? ApprovalMode.AUTO; this.accessibility = params.accessibility ?? {}; @@ -6376,6 +6379,16 @@ export class Config { this.memoryFileCount = count; } + /** @deprecated Use `getMemoryFileCount`; retained for one release. */ + getGeminiMdFileCount(): number { + return this.getMemoryFileCount(); + } + + /** @deprecated Use `setMemoryFileCount`; retained for one release. */ + setGeminiMdFileCount(count: number): void { + this.setMemoryFileCount(count); + } + /** Display paths of the currently loaded context (memory) files. */ getContextFilePaths(): string[] { return this.loadedContextFilePaths; diff --git a/packages/core/src/core/geminiChat.ts b/packages/core/src/core/geminiChat.ts index 5b7934c28ca..a97ed784555 100644 --- a/packages/core/src/core/geminiChat.ts +++ b/packages/core/src/core/geminiChat.ts @@ -450,6 +450,9 @@ export interface LlmChatSendOptions { disableModelFallbacks?: boolean; } +/** @deprecated Use `LlmChatSendOptions`; retained for one release. */ +export type GeminiChatSendOptions = LlmChatSendOptions; + interface TryCompressOptions { originalTokenCountOverride?: number; trigger?: CompactTrigger; @@ -1942,7 +1945,8 @@ export class GeminiChat { */ private pendingPartialAssistantTurnIndex: number | null = null; private pendingPartialAssistantRecord: - Parameters[0] | null = null; + | Parameters[0] + | null = null; private readonly imagePayloadStore = new InMemoryImagePayloadStore(); diff --git a/packages/core/src/core/geminiRequest.ts b/packages/core/src/core/geminiRequest.ts new file mode 100644 index 00000000000..3ef85cb3272 --- /dev/null +++ b/packages/core/src/core/geminiRequest.ts @@ -0,0 +1,8 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @deprecated Import from `llm-request.js`; retained for one release. */ +export * from './llm-request.js'; diff --git a/packages/core/src/core/llm-request.test.ts b/packages/core/src/core/llm-request.test.ts index 5450ddeac1e..4fa17c2e1b1 100644 --- a/packages/core/src/core/llm-request.test.ts +++ b/packages/core/src/core/llm-request.test.ts @@ -6,9 +6,14 @@ import { describe, it, expect } from 'vitest'; import { partListUnionToString } from './llm-request.js'; +import { partListUnionToString as legacyPartListUnionToString } from './geminiRequest.js'; import { type Part } from '@google/genai'; describe('partListUnionToString', () => { + it('keeps the legacy module path working during the rename window', () => { + expect(legacyPartListUnionToString('hello')).toBe('hello'); + }); + it('should return the string value if the input is a string', () => { const result = partListUnionToString('hello'); expect(result).toBe('hello'); diff --git a/packages/core/src/core/llm-request.ts b/packages/core/src/core/llm-request.ts index d36694b535d..3315869d54f 100644 --- a/packages/core/src/core/llm-request.ts +++ b/packages/core/src/core/llm-request.ts @@ -14,6 +14,12 @@ import { partToString } from '../utils/partUtils.js'; */ export type LlmCodeRequest = PartListUnion; +/** + * @deprecated Use `LlmCodeRequest`. Kept for one release so standalone core + * package consumers can migrate without a breaking rename. + */ +export type GeminiCodeRequest = LlmCodeRequest; + export function partListUnionToString(value: PartListUnion): string { return partToString(value, { verbose: true }); } diff --git a/packages/core/src/core/turn.ts b/packages/core/src/core/turn.ts index 850de7421e5..3e147e5b4eb 100644 --- a/packages/core/src/core/turn.ts +++ b/packages/core/src/core/turn.ts @@ -124,6 +124,12 @@ export interface LlmFinishedEventValue { usageMetadata: GenerateContentResponseUsageMetadata | undefined; } +/** @deprecated Use `LlmErrorEventValue`; retained for one release. */ +export type GeminiErrorEventValue = LlmErrorEventValue; + +/** @deprecated Use `LlmFinishedEventValue`; retained for one release. */ +export type GeminiFinishedEventValue = LlmFinishedEventValue; + export interface ToolCallRequestInfo { callId: string; /** diff --git a/packages/core/src/memory/const.test.ts b/packages/core/src/memory/const.test.ts index 076e88a4c7e..23f3894a289 100644 --- a/packages/core/src/memory/const.test.ts +++ b/packages/core/src/memory/const.test.ts @@ -13,9 +13,11 @@ import { getAllMemoryFilenames, } from '../utils/memory-constants.js'; import { + getAllGeminiMdFilenames as getToolAllGeminiMdFilenames, setMemoryFilename as setToolMemoryFilename, getCurrentMemoryFilename as getToolCurrentMemoryFilename, getAllMemoryFilenames as getToolAllMemoryFilenames, + setGeminiMdFilename as setToolGeminiMdFilename, } from '../tools/memory-config.js'; // Mock dependencies @@ -66,4 +68,10 @@ describe('setMemoryFilename', () => { expect(getCurrentMemoryFilename()).toBe('LEGACY_CONTEXT.md'); expect(getAllMemoryFilenames()).toEqual(['LEGACY_CONTEXT.md']); }); + + it('keeps the legacy public names wired to the renamed state', () => { + setToolGeminiMdFilename('LEGACY_NAME.md'); + expect(getCurrentMemoryFilename()).toBe('LEGACY_NAME.md'); + expect(getToolAllGeminiMdFilenames()).toEqual(['LEGACY_NAME.md']); + }); }); diff --git a/packages/core/src/tools/memory-config.ts b/packages/core/src/tools/memory-config.ts index 0ba210912bb..6adff0ac01e 100644 --- a/packages/core/src/tools/memory-config.ts +++ b/packages/core/src/tools/memory-config.ts @@ -12,8 +12,11 @@ export { AGENT_CONTEXT_FILENAME, DEFAULT_CONTEXT_FILENAME, + getAllGeminiMdFilenames, getAllMemoryFilenames, + getCurrentGeminiMdFilename, getCurrentMemoryFilename, MEMORY_SECTION_HEADER, + setGeminiMdFilename, setMemoryFilename, } from '../utils/memory-constants.js'; diff --git a/packages/core/src/utils/memory-constants.ts b/packages/core/src/utils/memory-constants.ts index d286510fbe2..d6f0cf86af1 100644 --- a/packages/core/src/utils/memory-constants.ts +++ b/packages/core/src/utils/memory-constants.ts @@ -74,3 +74,12 @@ export function getAllMemoryFilenames(): string[] { } return [currentMemoryFilename]; } + +/** @deprecated Use `setMemoryFilename`; retained for one release. */ +export const setGeminiMdFilename = setMemoryFilename; + +/** @deprecated Use `getCurrentMemoryFilename`; retained for one release. */ +export const getCurrentGeminiMdFilename = getCurrentMemoryFilename; + +/** @deprecated Use `getAllMemoryFilenames`; retained for one release. */ +export const getAllGeminiMdFilenames = getAllMemoryFilenames; From 74bf7922c4fc26f0eb1303b842b5062ca9ad02b9 Mon Sep 17 00:00:00 2001 From: yiliang114 Date: Wed, 26 Aug 2026 14:53:33 +0800 Subject: [PATCH 10/10] docs(core): extend Gemini deprecation window --- .../2026-08-22-rename-gemini-fork-residue.md | 17 +++++++++-------- packages/core/src/config/config.test.ts | 2 +- packages/core/src/config/config.ts | 6 +++--- packages/core/src/core/geminiChat.ts | 2 +- packages/core/src/core/geminiRequest.ts | 2 +- packages/core/src/core/llm-request.ts | 4 ++-- packages/core/src/core/turn.ts | 4 ++-- packages/core/src/utils/memory-constants.ts | 6 +++--- 8 files changed, 22 insertions(+), 21 deletions(-) diff --git a/docs/design/2026-08-22-rename-gemini-fork-residue.md b/docs/design/2026-08-22-rename-gemini-fork-residue.md index ba86ffc3e22..397518c101e 100644 --- a/docs/design/2026-08-22-rename-gemini-fork-residue.md +++ b/docs/design/2026-08-22-rename-gemini-fork-residue.md @@ -44,8 +44,8 @@ gemini-converter.ts` converts _upstream Gemini CLI extension_ configs `@qwen-code/qwen-code-core` is also published as a standalone package. Names already exported from its root barrel, `Config`, or supported deep-import paths -remain as deprecated aliases for one release; repository consumers use only -the new names. +remain as deprecated aliases until a future major release; repository consumers +use only the new names. ## Symbol map @@ -98,7 +98,8 @@ Non-test files; `gemini-converter.ts` is intentionally NOT renamed (see above). | `packages/core/src/core/geminiContentGenerator/index.ts` | `packages/core/src/core/llm-content-generator/index.ts` | | `packages/core/src/core/geminiRequest.ts` | `packages/core/src/core/llm-request.ts` | -The old `geminiRequest.ts` path remains as a one-release re-export shim. +The old `geminiRequest.ts` path remains as a deprecated re-export shim until a +future major release. ## Phasing @@ -117,9 +118,9 @@ move as one atomic PR. - Leaf types: `GeminiCodeRequest`, `GeminiChatSendOptions`, `GeminiErrorEventValue`, `GeminiFinishedEventValue`, and `geminiRequest.ts` → `llm-request.ts`. -- One-release deprecated aliases for the public core exports, `Config` memory - count input/accessors, memory filename helpers, and the old request module - path. +- Deprecated compatibility aliases for the public core exports, `Config` + memory count input/accessors, memory filename helpers, and the old request + module path. **PR 2 — core LLM layer (atomic)**: @@ -141,8 +142,8 @@ move as one atomic PR. the `@qwen-code/qwen-code-core` barrel. `sdk-typescript` and `acp-bridge` import them; PR 2 must update those packages. - **Published package compatibility**: renamed public symbols remain as - deprecated aliases for one release. Remove those aliases only after a stable - release has shipped the replacement names. + deprecated aliases until a future major release. Remove them only in a planned + major release after consumers have had time to migrate. - **Two `GeminiEventType` enums**: `core/src/core/turn.ts` and `cli/src/ui/types.ts` define the same name. Rename both and verify their relationship (distinct enums vs re-export) before PR 2. diff --git a/packages/core/src/config/config.test.ts b/packages/core/src/config/config.test.ts index 1b9eec828a9..6ab4d076290 100644 --- a/packages/core/src/config/config.test.ts +++ b/packages/core/src/config/config.test.ts @@ -608,7 +608,7 @@ describe('Server Config (config.ts)', () => { }); describe('memory file count compatibility', () => { - it('keeps the legacy parameter and accessors working for one release', () => { + it('keeps the legacy parameter and accessors until a future major release', () => { const config = new Config({ ...baseParams, geminiMdFileCount: 2 }); expect(config.getMemoryFileCount()).toBe(2); diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index be4309c91e1..f283a83b86e 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -1082,7 +1082,7 @@ export interface ConfigParameters { lspClient?: LspClient; userMemory?: string; memoryFileCount?: number; - /** @deprecated Use `memoryFileCount`; retained for one release. */ + /** @deprecated Use `memoryFileCount`; retained until a future major release. */ geminiMdFileCount?: number; approvalMode?: ApprovalMode; contextFileName?: string | string[]; @@ -6379,12 +6379,12 @@ export class Config { this.memoryFileCount = count; } - /** @deprecated Use `getMemoryFileCount`; retained for one release. */ + /** @deprecated Use `getMemoryFileCount`; retained until a future major release. */ getGeminiMdFileCount(): number { return this.getMemoryFileCount(); } - /** @deprecated Use `setMemoryFileCount`; retained for one release. */ + /** @deprecated Use `setMemoryFileCount`; retained until a future major release. */ setGeminiMdFileCount(count: number): void { this.setMemoryFileCount(count); } diff --git a/packages/core/src/core/geminiChat.ts b/packages/core/src/core/geminiChat.ts index a97ed784555..fe5d04404cd 100644 --- a/packages/core/src/core/geminiChat.ts +++ b/packages/core/src/core/geminiChat.ts @@ -450,7 +450,7 @@ export interface LlmChatSendOptions { disableModelFallbacks?: boolean; } -/** @deprecated Use `LlmChatSendOptions`; retained for one release. */ +/** @deprecated Use `LlmChatSendOptions`; retained until a future major release. */ export type GeminiChatSendOptions = LlmChatSendOptions; interface TryCompressOptions { diff --git a/packages/core/src/core/geminiRequest.ts b/packages/core/src/core/geminiRequest.ts index 3ef85cb3272..e0f89a7b76a 100644 --- a/packages/core/src/core/geminiRequest.ts +++ b/packages/core/src/core/geminiRequest.ts @@ -4,5 +4,5 @@ * SPDX-License-Identifier: Apache-2.0 */ -/** @deprecated Import from `llm-request.js`; retained for one release. */ +/** @deprecated Import from `llm-request.js`; retained until a future major release. */ export * from './llm-request.js'; diff --git a/packages/core/src/core/llm-request.ts b/packages/core/src/core/llm-request.ts index 3315869d54f..a69e4c52d67 100644 --- a/packages/core/src/core/llm-request.ts +++ b/packages/core/src/core/llm-request.ts @@ -15,8 +15,8 @@ import { partToString } from '../utils/partUtils.js'; export type LlmCodeRequest = PartListUnion; /** - * @deprecated Use `LlmCodeRequest`. Kept for one release so standalone core - * package consumers can migrate without a breaking rename. + * @deprecated Use `LlmCodeRequest`. Retained until a future major release so + * standalone core package consumers can migrate without a breaking rename. */ export type GeminiCodeRequest = LlmCodeRequest; diff --git a/packages/core/src/core/turn.ts b/packages/core/src/core/turn.ts index 3e147e5b4eb..5d805fd652e 100644 --- a/packages/core/src/core/turn.ts +++ b/packages/core/src/core/turn.ts @@ -124,10 +124,10 @@ export interface LlmFinishedEventValue { usageMetadata: GenerateContentResponseUsageMetadata | undefined; } -/** @deprecated Use `LlmErrorEventValue`; retained for one release. */ +/** @deprecated Use `LlmErrorEventValue`; retained until a future major release. */ export type GeminiErrorEventValue = LlmErrorEventValue; -/** @deprecated Use `LlmFinishedEventValue`; retained for one release. */ +/** @deprecated Use `LlmFinishedEventValue`; retained until a future major release. */ export type GeminiFinishedEventValue = LlmFinishedEventValue; export interface ToolCallRequestInfo { diff --git a/packages/core/src/utils/memory-constants.ts b/packages/core/src/utils/memory-constants.ts index d6f0cf86af1..4025dcb699c 100644 --- a/packages/core/src/utils/memory-constants.ts +++ b/packages/core/src/utils/memory-constants.ts @@ -75,11 +75,11 @@ export function getAllMemoryFilenames(): string[] { return [currentMemoryFilename]; } -/** @deprecated Use `setMemoryFilename`; retained for one release. */ +/** @deprecated Use `setMemoryFilename`; retained until a future major release. */ export const setGeminiMdFilename = setMemoryFilename; -/** @deprecated Use `getCurrentMemoryFilename`; retained for one release. */ +/** @deprecated Use `getCurrentMemoryFilename`; retained until a future major release. */ export const getCurrentGeminiMdFilename = getCurrentMemoryFilename; -/** @deprecated Use `getAllMemoryFilenames`; retained for one release. */ +/** @deprecated Use `getAllMemoryFilenames`; retained until a future major release. */ export const getAllGeminiMdFilenames = getAllMemoryFilenames;