fix(knowledge): align embedding configuration with Yuxi

This commit is contained in:
2026-09-14 23:37:16 +08:00
parent f92753329c
commit 5ed21835ae
5 changed files with 61 additions and 12 deletions

View File

@@ -0,0 +1,46 @@
# Task: 知识库向量配置改由Yuxi维护
## Identity
- Task ID: 20260914-yuxi-embedding-ml-a174ed62
- Mode: Feature
- Branch: codex/20260914-yuxi-embedding-ml-a174ed62-yuxi-embedding
- Worktree: D:\Datas\OthersProjects\.codex-worktrees\makelore\20260914-yuxi-embedding-ml-a174ed62
- Base commit: f92753329c511d60f61c156172fdf81eab2790d5
- Owner: codex
- Status: Ready for Integration
## Scope
- Update the MakeLore cloud Agent knowledge-base empty state and README configuration guidance so Yuxi is the sole embedding-model owner.
- Keep the existing `knowledge` Host API response shape (`databases` plus embedding models with `id`, `name`, and `dimension`) and make the client state use that shared contract.
- Verify that the client has no embedding-specific dependency on the Works Square or one-api model catalogs; do not change chat-model routing, account, billing, or server behavior.
## Intent And Constraints
- Concurrent Task Gate passed through the official project-docs check/start/status flow. This feature worktree is isolated from the MakeLore main checkout and other active tasks; the UX integration base is already present at the recorded base commit.
- The user decided that Yuxi maintains embedding providers, endpoint/API key, enabled embedding models, and dimensions. one-api does not configure embeddings; Works Square remains the creator Token Point ledger only.
- The client should tell administrators to configure the provider and model in Yuxi, then refresh the knowledge/model directory. Remove the old Works Square activation, one-api vector-interface, and cross-end model-ID matching instructions.
- Scope is limited to the client knowledge configuration copy, shared client typing where needed to retain `dimension`, focused test fixtures/assertions, and synchronized README wording. No Yuxi, Works Square, AgentBus, authentication, payment, installation, or deployment changes.
## Outcome
- The knowledge panel and README now describe Yuxi-owned embedding configuration. The old Works Square activation, one-api vector-interface, and cross-end model-ID matching instructions were removed. The client catalog state now uses the shared model contract, including `dimension`; no embedding-specific Works/one-api filtering was present or added.
## Verification
- `pnpm install --frozen-lockfile --offline` completed with the pinned `pnpm@10.33.4`; the install did not change manifests or the lockfile.
- `pnpm exec vitest run tests/unit/cloud-knowledge-catalog.test.tsx --maxWorkers=1` passed 5/5 tests.
- `pnpm run typecheck` passed; scoped ESLint for the changed client and test files passed; `git diff --check` passed.
- `pnpm run build:vite` passed Renderer, Main, Preload, and utility targets with the repository's existing Browserslist, chunk-size, and mixed-import warnings.
- `pnpm exec playwright test tests/e2e/cloud-agents.spec.ts` passed 1/1 scenario, including the updated Yuxi-only empty-catalog guidance.
- The fresh independent Reviewer completed the shared three-service review with Standards PASS and Spec PASS. The MakeLore client, README, and focused test changes had no blocking findings and require no further product changes; the review record is `D:\\Datas\\OthersProjects\\.codex-worktrees\\makelore\\20260914-embedding-review-ml-4e8b\\.project-docs\\30-worklog\\tasks\\20260914-embedding-review-ml-4e8b.md`.
- No live Yuxi/Works request, production configuration, packaging, deployment, or remote push was performed.
## Follow-ups
- Integration must include the resulting source commit. A rebuilt client is required before users see the updated guidance.
## Promotion Candidates
- The README and in-product empty-state wording are the product-facing record of the accepted Yuxi embedding ownership decision; no separate canonical ADR or architecture change is proposed by this feature task.

View File

@@ -9,7 +9,7 @@ Makelore 是一个面向软件、视觉创作、智能机器人与个人云智
- `Makelore CodeAI 编程`:管理本地项目、项目智能体、对话、文件上下文、代码变更和运行时。
- `Makelore AgentsAI 智能体`:配置个人云智能体并试聊,发布后正式对话、按账号分享或创建应用 API Key。支持流式回复、审批、排队请求、附件与产物、自动任务和活动历史重新进入时恢复最近智能体与对话未确认操作可按原输入重试。聊天可提出日程建议由创建者核对能力、时间和费用后启用。知识库支持上传、索引、替换、删除及导入本人会话附件个人 MCP 凭据、Skills、子智能体可自助管理。支持智能体和会话归档、发布版本比较及恢复为草稿。所有模型调用由创建者个人词元点数支付可按智能体设置每次任务和每日上限费用按时间、来源、应用分页统计分享/API 调用者保有自己的内容空间。Main 管理云会话和本机文件Renderer 通过 Host API 操作。配套服务接入见 [Yuxi MakeLore 说明](https://xerrors.github.io/Yuxi/advanced/makelore-agents.html)。 编辑采用全高桌面分栏,支持拖动调整与展开、独立滚动、小窗口配置/试用切换。首次创建按选用途、说要求、试一试引导,提供科学问答、故事、英语和笔记整理起点;回答方式可多选,特别要求直接编辑,仍以草稿的 system_prompt 保存。新助手预选云端目录的第一个可用模型并明确显示可自行更换已有助手不自动换模型。能力、知识与限制折叠到高级设置。草稿明确保存Ctrl/⌘+S保存与切换页面保留当前试用及未发送文字“保存并重新试用”使用最新保存的要求保留上次试用供对比并可复用上次问题不自动发送。示例问题仅填入输入框有运行、排队、审批或未确认操作时先处理当前试用。工具确认先展示实际操作说明与参数完整技术详情可展开。确认“开始使用”会创建仅自己可用的发布版本并进入独立对话分享与应用仍单独开启。费用上限在限制中独立保存。Enter 发送、Shift+Enter 换行F6 切换面板焦点、Esc 恢复分栏。
云知识库的向量模型由平台管理员配置:Yuxi 后台「智能体管理 → 模型供应商」启用 embedding 模型并填写实际维度;Works Square 运营后台「模型管理」从 one-api 刷新并激活相同模型 ID。one-api 必须支持该模型的向量接口。客户端区分目录加载中、加载失败与无可用模型,空状态提供管理员配置说明;「刷新知识库与模型」保留未提交名称,未确认的创建请求沿用原操作身份。
云知识库的向量模型由平台管理员Yuxi 后台维护:在「智能体管理 → 模型供应商」启用供应商,按供应商要求填写有效的服务地址和 API Key添加并启用 embedding 模型并填写实际向量维度;one-api 不参与向量模型配置Works Square 只负责创建者词元点数账本。客户端区分目录加载中、加载失败与无可用模型,空状态提供管理员配置说明;「刷新知识库与模型」保留未提交名称,未确认的创建请求沿用原操作身份。
Agents 侧栏的「渠道」统一管理个人微信账号。每个账号由唯一扫码微信身份连接可以在发布智能体前先扫码之后选择或更换目标智能体多个微信账号可以使用同一个已发布智能体切换目标不需要重新扫码。账号可单独启用、暂停、重新连接或断开不提供联系人邀请或授权调用者管理。Agent 的「使用与分享」只展示已关联渠道并提供定位入口。选中账号的二级详情保留运行/投递活动、失败文件补发和微信对话;对话可审批、停止、新开一段并保存实际产物,不同账号的会话相互隔离。自动任务可明确选择把结果发送到已经开始对话的微信账号,暂停保留目标;所有模型调用仍由智能体创建者支付,费用统计包含微信渠道。渠道需要配套版本的 AgentBus Core/微信 Adapter、Yuxi 和 Works Square桌面用户无需填写服务凭据。Main 保管操作恢复记录,重开界面不会自动重发绑定或执行请求;验证码不写入恢复记录,已移除的联系人权限操作记录只能丢弃。用户与应用分享不属于微信渠道账号管理范围。

View File

@@ -3,14 +3,15 @@ import { cloudAgentsApi } from '@/lib/cloud-agents-api';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { usePendingCloudInput } from './CloudPending';
import type { CloudKnowledge, CloudKnowledgeFile, CloudThread, CloudAttachment } from '../../../shared/cloud-agents';
import type { CloudAgentOperations, CloudKnowledge, CloudKnowledgeFile, CloudThread, CloudAttachment } from '../../../shared/cloud-agents';
const statusName: Record<string, string> = {
uploaded: '待解析', parsing: '解析中', parsed: '待索引', indexing: '索引中', indexed: '可检索',
error_parsing: '解析失败', error_indexing: '索引失败',
};
export function CloudKnowledgePanel({ slug, onCreated, onDeleted }: { slug: string; onCreated: (kb: CloudKnowledge) => void; onDeleted?: (id: string) => void }) {
const [catalog, setCatalog] = useState<{ databases: CloudKnowledge[]; models: { id: string; name: string }[] } | null>(null);
type CloudEmbeddingModel = CloudAgentOperations['knowledge']['output']['models'][number];
const [catalog, setCatalog] = useState<{ databases: CloudKnowledge[]; models: CloudEmbeddingModel[] } | null>(null);
const [kbId, setKbId] = useState('');
const [files, setFiles] = useState<CloudKnowledgeFile[]>([]);
const [next, setNext] = useState<number | null>(null);
@@ -84,13 +85,13 @@ export function CloudKnowledgePanel({ slug, onCreated, onDeleted }: { slug: stri
{catalog?.models.map(m => <option key={m.id} value={m.id}>{m.name}</option>)}
</select>
{!catalogLoading && !catalogError && catalog && !catalog.models.length && <div className="space-y-2 text-xs leading-5 text-muted-foreground">
<p></p>
<p> Yuxi </p>
<details>
<summary className="cursor-pointer font-medium text-foreground"></summary>
<ol className="mt-2 list-decimal space-y-1 pl-5">
<li>Yuxi embedding </li>
<li>Works Square one-api </li>
<li> ID one-api </li>
<li>Yuxi API Key</li>
<li> embedding </li>
<li></li>
</ol>
</details>
</div>}

View File

@@ -38,7 +38,7 @@ test('personal cloud Agent creation, draft save and leave protection in Electron
if (path.endsWith('/actions')) {
const input = body.input ?? {};
if (body.operation === 'catalog') return result({ models: [{ id: 'test-model', name: '创作模型' }], resources: {}, pricing: null });
if (body.operation === 'knowledge') return result({ databases: [], models: ++knowledgeCatalogLoads === 1 ? [] : [{ id: 'fixture:test-embedding', name: '资料向量模型' }] });
if (body.operation === 'knowledge') return result({ databases: [], models: ++knowledgeCatalogLoads === 1 ? [] : [{ id: 'fixture:test-embedding', name: '资料向量模型', dimension: 1024 }] });
if (body.operation === 'resources') return result({ mcps: [], skills: [], subagents: [] });
if (body.operation === 'budget' || body.operation === 'saveBudget') {
if (body.operation === 'saveBudget') limits = input;
@@ -104,7 +104,8 @@ test('personal cloud Agent creation, draft save and leave protection in Electron
await expect(page.getByLabel('向量模型', { exact: true })).toBeDisabled();
await page.getByText('管理员配置说明', { exact: true }).click();
await expect(page.getByText(/Yuxi 后台/)).toContainText('智能体管理 → 模型供应商');
await expect(page.getByText(/Works Square 运营后台/)).toBeVisible();
await expect(page.getByText(/Yuxi 后台/)).toContainText('服务地址和 API Key');
await expect(page.getByText(/Works Square 运营后台|one-api/)).toHaveCount(0);
await page.getByLabel('知识库名称', { exact: true }).fill('我的创作资料');
await page.screenshot({ path: testInfo.outputPath('knowledge-empty.png') });
await page.getByRole('button', { name: '刷新知识库与模型', exact: true }).click();

View File

@@ -6,7 +6,7 @@ const api = vi.hoisted(() => ({ call: vi.fn() }));
vi.mock('@/lib/cloud-agents-api', () => ({ cloudAgentsApi: api }));
const slug = 'ml-' + 'a'.repeat(32);
const empty = { databases: [], models: [] };
const available = { ...empty, models: [{ id: 'relay:fixture-embedding', name: '资料向量模型' }] };
const available = { ...empty, models: [{ id: 'relay:fixture-embedding', name: '资料向量模型', dimension: 1024 }] };
beforeEach(() => vi.resetAllMocks());
afterEach(cleanup);
@@ -20,11 +20,12 @@ function openCreation() {
it('explains who configures an empty embedding catalog and refreshes without losing the name', async () => {
api.call.mockResolvedValueOnce(empty).mockResolvedValueOnce(available);
openCreation();
expect(await screen.findByText('暂时没有可用的向量模型。请联系平台管理员完成云端配置,然后刷新。')).toBeVisible();
expect(await screen.findByText('暂时没有可用的向量模型。请联系平台管理员在 Yuxi 完成配置,然后刷新。')).toBeVisible();
expect(screen.getByRole('combobox', { name: '向量模型' })).toBeDisabled();
fireEvent.click(screen.getByText('管理员配置说明'));
expect(screen.getByText(/Yuxi 后台/)).toHaveTextContent('智能体管理 → 模型供应商');
expect(screen.getByText(/Works Square 运营后台/)).toHaveTextContent('模型管理');
expect(screen.getByText(/Yuxi 后台/)).toHaveTextContent('服务地址和 API Key');
expect(screen.queryByText(/Works Square 运营后台|one-api/)).not.toBeInTheDocument();
fireEvent.change(screen.getByRole('textbox', { name: '知识库名称' }), { target: { value: '创作资料' } });
fireEvent.click(screen.getByRole('button', { name: '刷新知识库与模型' }));
expect(await screen.findByRole('option', { name: '资料向量模型' })).toBeInTheDocument();