feat: improve project agent onboarding

This commit is contained in:
2026-09-06 13:54:20 +08:00
parent a4fc3a5251
commit df02680f9d
15 changed files with 826 additions and 74 deletions

View File

@@ -6,9 +6,34 @@ import { codingWorkspaceStore } from '@/stores/coding-workspace';
import { useProjectConfigStore } from '@/stores/project-config';
import { useSettingsStore } from '@/stores/settings';
import { createCodingProjectConfigV2 } from '@electron/coding-projects/project-config';
import type { CodingProjectAgent } from '@/types/coding-project';
const learningIpcMock = vi.hoisted(() => vi.fn());
const readyAgent: CodingProjectAgent = {
id: 'agent-1',
avatarId: 'avatar-01',
roleName: '项目智能体',
name: 'Builder',
builtIn: false,
enabled: true,
model: { accountId: 'account-1', modelId: 'model-1', thinkingLevel: 'off' },
modelResolution: 'resolved',
skillIds: [],
responsibility: {
mission: '完成项目工作',
owns: [],
boundaries: [],
collaborators: [],
principles: [],
},
prompt: '',
archivedAt: null,
pinned: false,
createdAt: '2026-09-06T00:00:00.000Z',
updatedAt: '2026-09-06T00:00:00.000Z',
};
vi.mock('@/components/layout/Sidebar', () => ({
Sidebar: ({ sidebarCollapsedOverride }: { sidebarCollapsedOverride?: boolean }) => (
<aside data-testid="sidebar-stub" data-sidebar-collapsed={sidebarCollapsedOverride === undefined ? 'unset' : String(sidebarCollapsedOverride)} />
@@ -105,6 +130,34 @@ describe('MainLayout module isolation', () => {
expect(screen.getByTestId('titlebar-stub')).toHaveAttribute('data-overlay', 'false');
});
it('keeps the gate when a legacy config says initialized but has no usable Agent', () => {
const project = codingWorkspaceStore.getState().activeProject!;
useProjectConfigStore.setState({
configsByProjectId: {
[project.id]: { ...createCodingProjectConfigV2(), initialized: true, agents: [] },
},
});
renderLayout('/chat');
expect(screen.getByTestId('project-initialization-gate')).toBeVisible();
expect(screen.getByText('项目还差一步')).toBeVisible();
});
it('allows programming routes when the project has a fully configured Agent', () => {
const project = codingWorkspaceStore.getState().activeProject!;
useProjectConfigStore.setState({
configsByProjectId: {
[project.id]: { ...createCodingProjectConfigV2(), initialized: true, agents: [readyAgent] },
},
});
renderLayout('/chat');
expect(screen.queryByTestId('project-initialization-gate')).not.toBeInTheDocument();
expect(screen.getByTestId('route-content')).toBeVisible();
});
it('keeps the canonical plugin workspace outside the local project initialization gate', () => {
renderLayout('/plugins');