refactor(admin): drop AI connection config page for WP AI Connectors
Remove the "AI 连接配置" page under 扩展&增强 together with the theme's own OpenAI-compatible provider path. AI generation (SEO, summary, tags) now runs solely on the WordPress AI Client (wp_ai_client_prompt), with connections configured through WordPress AI Connectors. - AI.php keeps only the WP AI Client path: no provider config storage, no theme fallback, no rate limiting - Drop /ai/status, /ai/settings and legacy /ai/seo-suggest routes plus their handlers - Remove dead compat code: AISEO::suggest, AIPrompt::build_seo_prompt and the front-submit AI assist flow (its buttons were never rendered and its endpoints were never registered) - Update SEO schema/meta-box guidance that pointed at the deleted page - Add ai-config-removal contract test and refresh the toast and user-features contracts affected by the cleanup
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
'use strict';
|
||||
|
||||
/** AI 连接配置页已移除:主题只走 WordPress AI Connectors,生成能力与入口保留。 */
|
||||
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const test = require('node:test');
|
||||
|
||||
const root = path.resolve(__dirname, '..', '..');
|
||||
|
||||
const read = (rel) => fs.readFileSync(path.join(root, rel), 'utf8');
|
||||
|
||||
const ai = read('src/Ai/AI.php');
|
||||
const controller = read('src/Admin/AIController.php');
|
||||
const seoSchema = read('assets/admin/src/schema/sections/global/seo.js');
|
||||
const extensionsMenu = read('assets/admin/src/constants/sections/extensions.js');
|
||||
const apiModule = read('assets/admin/src/api/modules/extensions.js');
|
||||
const frontSubmit = read('assets/js/front-submit.js');
|
||||
const submitContext = read('templates/parts/submit/context.php');
|
||||
const submitPage = read('templates/pages/page-submit.php');
|
||||
|
||||
const removed = [
|
||||
'aksrt_ai_settings',
|
||||
'AI 连接配置',
|
||||
'AI连接配置',
|
||||
'ExtensionAI',
|
||||
'extensions-ai',
|
||||
'/ai/settings',
|
||||
'/ai/status',
|
||||
'ai-assist-btn',
|
||||
'扩展 → AI',
|
||||
];
|
||||
|
||||
const walk = (dir) => fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
|
||||
const full = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
return ['node_modules', 'build', 'dist'].includes(entry.name) ? [] : walk(full);
|
||||
}
|
||||
return [full];
|
||||
});
|
||||
|
||||
const sources = ['src', 'assets/admin/src', 'templates', 'assets/js', 'inc']
|
||||
.flatMap((dir) => walk(path.join(root, dir)));
|
||||
|
||||
test('后台菜单、路由与 API 中不再有 AI 连接配置页', () => {
|
||||
assert.doesNotMatch(extensionsMenu, /extensions-ai|ExtensionAI|AI 连接配置/);
|
||||
assert.doesNotMatch(apiModule, /getAiStatus|updateAiSettings|generateSeo|suggestSummary|suggestTags/);
|
||||
assert.ok(!fs.existsSync(path.join(root, 'assets/admin/src/pages/extensions/ExtensionAI.vue')));
|
||||
assert.ok(!fs.existsSync(path.join(root, 'assets/admin/src/router/component-loaders/extensions.js')));
|
||||
});
|
||||
|
||||
test('AI.php 只保留 WP AI Client 单路出口', () => {
|
||||
assert.doesNotMatch(ai, /PROVIDER_OPENAI|PROVIDER_NONE/);
|
||||
assert.doesNotMatch(ai, /get_config|update_config/);
|
||||
assert.doesNotMatch(ai, /generate_via_theme|normalize_api_base/);
|
||||
assert.doesNotMatch(ai, /is_theme_provider_available|resolve_backend/);
|
||||
assert.doesNotMatch(ai, /check_rate_limit|record_call/);
|
||||
assert.match(ai, /wp_ai_client_prompt/);
|
||||
assert.match(ai, /function is_wp_ai_available/);
|
||||
assert.match(ai, /function is_available/);
|
||||
});
|
||||
|
||||
test('生成路由保留,连接配置与旧草稿兼容路由移除', () => {
|
||||
assert.match(controller, /\/ai\/seo-generate/);
|
||||
assert.match(controller, /\/ai\/summary-suggest/);
|
||||
assert.match(controller, /\/ai\/tags-suggest/);
|
||||
assert.doesNotMatch(controller, /\/ai\/seo-suggest/);
|
||||
assert.doesNotMatch(controller, /function get_status|function update_settings|function seo_suggest/);
|
||||
});
|
||||
|
||||
test('残留文案不再指向已删除的配置页', () => {
|
||||
for (const [name, source] of [['AI.php', ai], ['AIController.php', controller], ['seo.js', seoSchema]]) {
|
||||
assert.doesNotMatch(source, /AI 连接配置/, `${name} 仍引用 AI 连接配置页`);
|
||||
assert.doesNotMatch(source, /扩展 → AI/, `${name} 仍引导到扩展菜单`);
|
||||
}
|
||||
});
|
||||
|
||||
test('前台投稿 AI 辅助死代码已清理', () => {
|
||||
assert.doesNotMatch(frontSubmit, /bindAi|ai-assist-btn|cfg\.ai/);
|
||||
assert.doesNotMatch(submitContext, /ai_available/);
|
||||
assert.doesNotMatch(submitPage, /'ai'\s*=>|aiGenerating|aiFailed|aiFilled|needContent/);
|
||||
});
|
||||
|
||||
test('全仓源码不再引用已删除的 AI 连接配置', () => {
|
||||
const offenders = sources.filter((file) => {
|
||||
const text = fs.readFileSync(file, 'utf8');
|
||||
return removed.some((pattern) => text.includes(pattern));
|
||||
});
|
||||
assert.deepEqual(offenders.map((file) => path.relative(root, file)), []);
|
||||
});
|
||||
@@ -379,8 +379,6 @@ test('front submit actions use direct fixed-id notyf flows', () => {
|
||||
'aksrt-front-submit-delete-draft-toast',
|
||||
'aksrt-front-submit-resource-upload-toast',
|
||||
'aksrt-front-submit-editor-media-toast',
|
||||
'aksrt-front-submit-ai-tags-toast',
|
||||
'aksrt-front-submit-ai-summary-toast',
|
||||
].forEach((id) => assert.match(source, new RegExp("['\"]" + id + "['\"]")));
|
||||
|
||||
assert.match(submit, /submit: function[\s\S]*?notyf\([^;]+?'load'[^;]+?toastId[\s\S]*?notyf\([^;]+?'success'[^;]+?toastId[\s\S]*?notyf\([^;]+?'danger'[^;]+?toastId/);
|
||||
@@ -398,8 +396,6 @@ test('front submit actions use direct fixed-id notyf flows', () => {
|
||||
// 付费下载附件选择后仅补一条成功确认,上传过程通知属于选择器。
|
||||
assert.match(downloads, /AksrtSubmitMedia\.open\([\s\S]*?'success', 5, 'aksrt-front-submit-resource-upload-toast'/);
|
||||
assert.match(editor, /aksrt-front-submit-editor-media-toast[\s\S]*?'load'[\s\S]*?'success'[\s\S]*?'danger'/);
|
||||
assert.match(submit, /aksrt-front-submit-ai-tags-toast[\s\S]*?aksrt-front-submit-ai-summary-toast[\s\S]*?'load'[\s\S]*?'success'[\s\S]*?'danger'/);
|
||||
assert.match(submit, /needContent[^;]+?'warning'/);
|
||||
assert.doesNotMatch(submit, /\b(?:window\.)?alert\s*\(/);
|
||||
|
||||
assert.match(page, /'aksrt-front-submit',[\s\S]*?'\/assets\/js\/front-submit\.js',[\s\S]*?\[[^\]]*'loader_js'[^\]]*\]/);
|
||||
|
||||
@@ -144,7 +144,6 @@ test('retired admin pages, schemas, APIs, and metadata chains are absent', () =>
|
||||
'assets/admin/src/constants/sections/extensions.js',
|
||||
'assets/admin/src/router/component-loaders/users.js',
|
||||
'assets/admin/src/router/component-loaders/tools.js',
|
||||
'assets/admin/src/router/component-loaders/extensions.js',
|
||||
'assets/admin/src/api/modules/tools.js',
|
||||
'assets/admin/src/schema/sections/tools/index.js',
|
||||
'src/Admin/Schema/SchemaTools.php',
|
||||
|
||||
Reference in New Issue
Block a user