fix(knowledge): align embedding configuration with Yuxi
This commit is contained in:
@@ -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.
|
||||
@@ -9,7 +9,7 @@ Makelore 是一个面向软件、视觉创作、智能机器人与个人云智
|
||||
- `Makelore Code|AI 编程`:管理本地项目、项目智能体、对话、文件上下文、代码变更和运行时。
|
||||
- `Makelore Agents|AI 智能体`:配置个人云智能体并试聊,发布后正式对话、按账号分享或创建应用 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 保管操作恢复记录,重开界面不会自动重发绑定或执行请求;验证码不写入恢复记录,已移除的联系人权限操作记录只能丢弃。用户与应用分享不属于微信渠道账号管理范围。
|
||||
|
||||
|
||||
@@ -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>}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user