feat: improve project agent onboarding
This commit is contained in:
1 parent
a4fc3a5251
commit
df02680f9d
15 files changed
+826
-74
No files matched your search
@@ -6,6 +6,10 @@ import { useAuthStore } from '@/stores/auth';
|
||||
import { useProviderStore } from '@/stores/providers';
|
||||
import { useSettingsStore } from '@/stores/settings';
|
||||
import { useUserSyncStore } from '@/stores/user-sync';
|
||||
import { codingWorkspaceStore } from '@/stores/coding-workspace';
|
||||
import { useProjectConfigStore } from '@/stores/project-config';
|
||||
import { createCodingProjectConfigV2 } from '@electron/coding-projects/project-config';
|
||||
import type { CodingProjectAgent } from '@/types/coding-project';
|
||||
|
||||
vi.mock('@/components/layout/MainLayout', () => ({
|
||||
MainLayout: () => (
|
||||
@@ -39,11 +43,41 @@ vi.mock('@/pages/Settings', () => ({
|
||||
Settings: () => <div>Global settings</div>,
|
||||
}));
|
||||
|
||||
vi.mock('@/pages/ProjectConfiguration', () => ({
|
||||
ProjectConfiguration: () => <div>Project configuration</div>,
|
||||
}));
|
||||
|
||||
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',
|
||||
};
|
||||
|
||||
describe('App programming provider initialization gate', () => {
|
||||
const initProviders = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
codingWorkspaceStore.setState(codingWorkspaceStore.getInitialState(), true);
|
||||
useProjectConfigStore.setState(useProjectConfigStore.getInitialState(), true);
|
||||
useSettingsStore.setState({
|
||||
setupComplete: true,
|
||||
init: vi.fn(),
|
||||
@@ -95,6 +129,56 @@ describe('App programming provider initialization gate', () => {
|
||||
await waitFor(() => expect(initProviders).toHaveBeenCalledTimes(1));
|
||||
});
|
||||
|
||||
it('redirects a legacy initialized project without a usable Agent to configuration', async () => {
|
||||
const project = {
|
||||
id: 'local-project',
|
||||
path: '/tmp/local-project',
|
||||
name: 'local-project',
|
||||
createdAt: '',
|
||||
updatedAt: '',
|
||||
lastOpenedAt: '',
|
||||
};
|
||||
const config = { ...createCodingProjectConfigV2(), initialized: true, agents: [] };
|
||||
codingWorkspaceStore.setState({
|
||||
activeProjectId: project.id,
|
||||
activeProject: project,
|
||||
load: vi.fn().mockResolvedValue(undefined),
|
||||
});
|
||||
useProjectConfigStore.setState({
|
||||
load: vi.fn().mockResolvedValue({ status: 'valid', config, knowledgeFiles: [] }),
|
||||
});
|
||||
|
||||
await renderAt('/chat');
|
||||
|
||||
expect(await screen.findByText('Project configuration')).toBeInTheDocument();
|
||||
expect(screen.queryByText('Programming workspace')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('opens chat when the project has a fully configured Agent', async () => {
|
||||
const project = {
|
||||
id: 'local-project',
|
||||
path: '/tmp/local-project',
|
||||
name: 'local-project',
|
||||
createdAt: '',
|
||||
updatedAt: '',
|
||||
lastOpenedAt: '',
|
||||
};
|
||||
const config = { ...createCodingProjectConfigV2(), initialized: true, agents: [readyAgent] };
|
||||
codingWorkspaceStore.setState({
|
||||
activeProjectId: project.id,
|
||||
activeProject: project,
|
||||
load: vi.fn().mockResolvedValue(undefined),
|
||||
});
|
||||
useProjectConfigStore.setState({
|
||||
load: vi.fn().mockResolvedValue({ status: 'valid', config, knowledgeFiles: [] }),
|
||||
});
|
||||
|
||||
await renderAt('/chat');
|
||||
|
||||
expect(await screen.findByText('Programming workspace')).toBeInTheDocument();
|
||||
expect(screen.queryByText('Project configuration')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('redirects an orphaned token without a user identity away from a direct workspace route', async () => {
|
||||
useAuthStore.setState({
|
||||
initialized: true,
|
||||
|
||||
Reference in new issue
Block a user