feat: align controlled AI sessions and MVP controls
This commit is contained in:
@@ -24,6 +24,7 @@ const requiredFiles = [
|
||||
'src/api/mappers.tsx',
|
||||
'src/api/search.ts',
|
||||
'src/api/inbox.ts',
|
||||
'src/api/ai.ts',
|
||||
'scripts/api-client.test.mjs',
|
||||
]
|
||||
|
||||
@@ -51,7 +52,7 @@ if (!projectRailSource.includes('projectNameLabel(project.name)')) {
|
||||
failures.push('project rail labels must derive from the project name')
|
||||
}
|
||||
|
||||
const apiFiles = ['client.ts', 'projects.ts', 'mappers.tsx', 'search.ts', 'inbox.ts'].map((name) => `src/api/${name}`)
|
||||
const apiFiles = ['client.ts', 'projects.ts', 'mappers.tsx', 'search.ts', 'inbox.ts', 'ai.ts'].map((name) => `src/api/${name}`)
|
||||
const apiSource = apiFiles.map((file) => readFileSync(file, 'utf8')).join('\n')
|
||||
for (const forbidden of [
|
||||
{ pattern: /\bID\s*\?\s*:/, label: 'optional PascalCase ID compatibility field' },
|
||||
@@ -101,6 +102,34 @@ if (!inboxSource.includes('body: { suggestionIds }')) failures.push('inbox confi
|
||||
const inboxPageSource = readFileSync('src/pages/projects/project-inbox.tsx', 'utf8')
|
||||
if (!inboxPageSource.includes('确认创建')) failures.push('project inbox must expose the single confirmation action')
|
||||
|
||||
const aiApiSource = readFileSync('src/api/ai.ts', 'utf8')
|
||||
for (const required of ['/api/v1/projects/', '/ai-sessions', 'listAISessions', 'createAISession']) {
|
||||
if (!aiApiSource.includes(required)) failures.push(`AI API must include ${required}`)
|
||||
}
|
||||
if (/\b(?:task|note|source)Id\b/.test(aiApiSource)) failures.push('AI session responses must not expose automatic formal object IDs')
|
||||
|
||||
const aiPageSource = readFileSync('src/pages/projects/project-ai.tsx', 'utf8')
|
||||
for (const required of ['AI 助手', '创建会话', 'loading', 'error']) {
|
||||
if (!aiPageSource.includes(required)) failures.push(`project AI page must include ${required}`)
|
||||
}
|
||||
for (const forbidden of ['DeepSeek V4.0 Flash', '给 DeepSeek 发送消息', 'IconAttachment', 'agent-send-button']) {
|
||||
if (aiPageSource.includes(forbidden)) failures.push(`project AI page contains unsupported chat control ${forbidden}`)
|
||||
}
|
||||
|
||||
const unsupportedControls = [
|
||||
{ file: 'src/pages/workspace-explore.tsx', required: '暂未开放', forbidden: ['同步数据源', '添加数据源', 'IconRefresh', 'IconEdit', 'IconDelete'] },
|
||||
{ file: 'src/pages/projects/project-new-channel.tsx', required: '暂未开放', forbidden: ['保存频道', '<Input', '<Select', '<TextArea'] },
|
||||
{ file: 'src/pages/projects/project-statusbar.tsx', forbidden: ['升级', '支付', 'billing-plan', '152GB', 'AI 空闲'] },
|
||||
{ file: 'src/pages/projects/project-topbar.tsx', forbidden: ['停靠左边', '停靠右边', 'DockIcon', 'isDesktopRuntime'] },
|
||||
]
|
||||
for (const check of unsupportedControls) {
|
||||
const source = readFileSync(check.file, 'utf8')
|
||||
if (check.required && !source.includes(check.required)) failures.push(`${check.file} must show ${check.required}`)
|
||||
for (const forbidden of check.forbidden) {
|
||||
if (source.includes(forbidden)) failures.push(`${check.file} contains unsupported control ${forbidden}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (existsSync('src/App.tsx')) {
|
||||
failures.push('legacy src/App.tsx should be removed after page split')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user