Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions packages/cli/src/ui/commands/dreamCommand.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

import * as path from 'node:path';
import { describe, expect, it, vi } from 'vitest';
import { Storage } from '@qwen-code/qwen-code-core';
import { dreamCommand } from './dreamCommand.js';
import { createMockCommandContext } from '../../test-utils/mockCommandContext.js';

describe('dreamCommand', () => {
it('submits a consolidation prompt with the project-scoped transcript directory', async () => {
const projectRoot = path.join('tmp', 'dream-project');
const buildConsolidationPrompt = vi.fn().mockReturnValue('dream prompt');
const writeDreamManualRun = vi.fn();
const context = createMockCommandContext({
services: {
config: {
getProjectRoot: vi.fn().mockReturnValue(projectRoot),
getMemoryManager: vi.fn().mockReturnValue({
buildConsolidationPrompt,
writeDreamManualRun,
}),
getSessionId: vi.fn().mockReturnValue('session-1'),
},
},
});

const result = await dreamCommand.action?.(context, '');
const expectedTranscriptDir = path.join(
new Storage(projectRoot).getProjectDir(),
'chats',
);

expect(result).toEqual({
type: 'submit_prompt',
content: 'dream prompt',
onComplete: expect.any(Function),
});
expect(buildConsolidationPrompt).toHaveBeenCalledWith(
expect.any(String),
expectedTranscriptDir,
);
expect(expectedTranscriptDir).not.toContain(
`${path.sep}.qwen${path.sep}tmp${path.sep}`,
);
});
});
13 changes: 6 additions & 7 deletions packages/cli/src/ui/commands/dreamCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

import {
getAutoMemoryRoot,
getProjectHash,
QWEN_DIR,
} from '@qwen-code/qwen-code-core';
import * as path from 'node:path';
import { getAutoMemoryRoot, Storage } from '@qwen-code/qwen-code-core';
import { t } from '../../i18n/index.js';
import type { SlashCommand } from './types.js';
import { CommandKind } from './types.js';
Expand All @@ -31,8 +28,10 @@ export const dreamCommand: SlashCommand = {

const projectRoot = config.getProjectRoot();
const memoryRoot = getAutoMemoryRoot(projectRoot);
const projectHash = getProjectHash(projectRoot);
const transcriptDir = `${QWEN_DIR}/tmp/${projectHash}/chats`;
const transcriptDir = path.join(
new Storage(projectRoot).getProjectDir(),
'chats',
);

const prompt = config
.getMemoryManager()
Expand Down
22 changes: 21 additions & 1 deletion packages/core/src/memory/dreamAgentPlanner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ import * as os from 'node:os';
import * as path from 'node:path';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import type { Config } from '../config/config.js';
import { Storage } from '../config/storage.js';
import type { ForkedAgentResult } from '../utils/forkedAgent.js';
import { runForkedAgent } from '../utils/forkedAgent.js';
import { planManagedAutoMemoryDreamByAgent } from './dreamAgentPlanner.js';
import {
getTranscriptDir,
planManagedAutoMemoryDreamByAgent,
} from './dreamAgentPlanner.js';
import { ensureAutoMemoryScaffold } from './store.js';

vi.mock('../utils/forkedAgent.js', () => ({
Expand All @@ -38,6 +42,7 @@ describe('dreamAgentPlanner', () => {
});

afterEach(async () => {
Storage.setRuntimeBaseDir(null);
await fs.rm(tempDir, {
recursive: true,
force: true,
Expand All @@ -46,6 +51,21 @@ describe('dreamAgentPlanner', () => {
});
});

it('returns project-scoped session transcript directory', () => {
const runtimeDir = path.join(tempDir, 'runtime');
Storage.setRuntimeBaseDir(runtimeDir);

expect(getTranscriptDir(projectRoot)).toBe(
path.join(new Storage(projectRoot).getProjectDir(), 'chats'),
);
expect(getTranscriptDir(projectRoot)).toContain(
path.join(runtimeDir, 'projects'),
);
expect(getTranscriptDir(projectRoot)).not.toContain(
`${path.sep}.qwen${path.sep}tmp${path.sep}`,
);
});

it('returns the forked agent result', async () => {
const mockResult: ForkedAgentResult = {
status: 'completed',
Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/memory/dreamAgentPlanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
runForkedAgent,
type ForkedAgentResult,
} from '../utils/forkedAgent.js';
import { getProjectHash, QWEN_DIR } from '../utils/paths.js';
import * as path from 'node:path';
import { Storage } from '../config/storage.js';
import {
AUTO_MEMORY_INDEX_FILENAME,
getAutoMemoryRoot,
Expand Down Expand Up @@ -160,9 +161,8 @@ Rules:
- Keep the MEMORY.md index concise: one line per file in the format \`- [Title](relative/path.md) — one-line hook\`.
- If nothing needs consolidation, do nothing and say so.`;

function getTranscriptDir(projectRoot: string): string {
const projectHash = getProjectHash(projectRoot);
return `${QWEN_DIR}/tmp/${projectHash}/chats`;
export function getTranscriptDir(projectRoot: string): string {
return path.join(new Storage(projectRoot).getProjectDir(), 'chats');
Comment thread
LaZzyMan marked this conversation as resolved.
}

export function buildConsolidationTaskPrompt(
Expand Down
Loading