diff --git a/mateclaw-ui/src/api/index.ts b/mateclaw-ui/src/api/index.ts index 0f7076f4..b57354f1 100644 --- a/mateclaw-ui/src/api/index.ts +++ b/mateclaw-ui/src/api/index.ts @@ -758,7 +758,7 @@ export const wikiApi = { http.put(`/wiki/knowledge-bases/${id}/config`, { content }), // Directory Scan - setSourceDirectory: (id: number, path: string) => + setSourceDirectory: (id: string | number, path: string) => http.put(`/wiki/knowledge-bases/${id}/source-directory`, { path }), scanDirectory: (id: number) => http.post(`/wiki/knowledge-bases/${id}/scan`), @@ -903,6 +903,51 @@ export const wikiApi = { http.post(`/wiki/transformations/runs/${runId}/save-as-page`), cancelTransformationRun: (runId: number) => http.post(`/wiki/transformations/runs/${runId}/cancel`), + + // ---- PageType Profile (REQ-1) ---- + getPageTypeProfile: (kbId: string | number) => + http.get(`/wiki/knowledge-bases/${kbId}/page-type-profile`), + savePageTypeProfile: (kbId: string | number, config: string, name?: string) => + http.put(`/wiki/knowledge-bases/${kbId}/page-type-profile`, { config, name }), + validatePageTypeProfile: (kbId: string | number, config: string) => + http.post(`/wiki/knowledge-bases/${kbId}/page-type-profile/validate`, { config }), + resetPageTypeProfile: (kbId: string | number) => + http.post(`/wiki/knowledge-bases/${kbId}/page-type-profile/reset-default`), + + // ---- Agent pageType permissions (REQ-3) ---- + listPageTypePermissions: (kbId: string | number, agentId: string | number) => + http.get(`/wiki/knowledge-bases/${kbId}/agents/${agentId}/page-type-permissions`), + savePageTypePermission: (kbId: string | number, agentId: string | number, row: { + pageType: string + canRead?: number + canCreate?: number + canUpdate?: number + canDelete?: number + writePolicy?: 'allow' | 'deny' | 'approval_required' + }) => + http.post(`/wiki/knowledge-bases/${kbId}/agents/${agentId}/page-type-permissions`, row), + deletePageTypePermission: (kbId: string | number, agentId: string | number, id: string | number) => + http.delete(`/wiki/knowledge-bases/${kbId}/agents/${agentId}/page-type-permissions/${id}`), + + // ---- Source watcher (REQ-4) ---- + getSourceWatcher: (kbId: string | number) => + http.get(`/wiki/knowledge-bases/${kbId}/source-watcher`), + triggerSourceWatcher: (kbId: string | number) => + http.post(`/wiki/knowledge-bases/${kbId}/source-watcher/scan`), + + // ---- Pipelines (REQ-5) ---- + listPipelines: (kbId: string | number) => + http.get(`/wiki/knowledge-bases/${kbId}/pipelines`), + savePipeline: (kbId: string | number, config: string, format: 'yaml' | 'json' = 'yaml') => + http.post(`/wiki/knowledge-bases/${kbId}/pipelines`, { config, format }), + validatePipeline: (kbId: string | number, config: string, format: 'yaml' | 'json' = 'yaml') => + http.post(`/wiki/knowledge-bases/${kbId}/pipelines/validate`, { config, format }), + deletePipeline: (kbId: string | number, id: string | number) => + http.delete(`/wiki/knowledge-bases/${kbId}/pipelines/${id}`), + listPipelineRuns: (kbId: string | number, id: string | number) => + http.get(`/wiki/knowledge-bases/${kbId}/pipelines/${id}/runs`), + getPipelineRun: (kbId: string | number, runId: string | number) => + http.get(`/wiki/knowledge-bases/${kbId}/pipeline-runs/${runId}`), } // ==================== Workspace (Team) ==================== diff --git a/mateclaw-ui/src/i18n/locales/en-US.ts b/mateclaw-ui/src/i18n/locales/en-US.ts index f383e704..a9b92949 100644 --- a/mateclaw-ui/src/i18n/locales/en-US.ts +++ b/mateclaw-ui/src/i18n/locales/en-US.ts @@ -2113,6 +2113,81 @@ export default { lastError: 'Last error', footer: 'Toggling wiki.hot_cache.enabled off short-circuits the injection path. The "Rebuild now" button bypasses the debounce window for easier debugging.', }, + adv: { + tab: 'Advanced', + validate: 'Validate', + validOk: 'Validation passed', + profile: { + tab: 'Page Types', + title: 'Page Type Profile', + desc: 'Define this KB\'s page types, their knowledge layer, route/create/merge stage instructions and content templates. Injected into the ingest pipeline prompts.', + builtin: 'Built-in default', + placeholder: 'Paste the pageType profile JSON here…', + reset: 'Reset to default', + resetConfirm: 'Reset to the built-in default profile? Your custom config will be cleared.', + }, + layers: { + tab: 'Layers & Stale', + title: 'Knowledge Layers & Stale State', + desc: 'When a fact-layer page is updated, experience pages that depend on it are marked stale to flag they need review.', + fact: 'Fact', + experience: 'Experience', + other: 'Other', + stale: 'Stale', + empty: 'This knowledge base has no pages yet.', + page: 'Page', + layer: 'Layer', + status: 'Status', + staleTag: 'Needs review', + fresh: 'Fresh', + }, + perm: { + tab: 'Permissions', + title: 'Agent Page Type Permissions', + desc: 'Configure per-pageType read/create/update/delete access for an agent in this KB; writes can require approval. No rules = allow all; once any rule exists, uncovered types are fail-safe denied.', + agent: 'Agent', + selectAgent: 'Select an agent…', + pageType: 'Page Type', + policy: 'Write policy', + noRows: 'This agent has no permission rules (allow all).', + pageTypeHint: 'page type, * for default', + addRule: 'Add rule', + deleteConfirm: 'Delete the permission rule for "{type}"?', + }, + watcher: { + tab: 'Watcher', + title: 'Source Directory Watcher', + desc: 'Bind a local directory as a knowledge source; the watcher scans for new/changed files at an interval and ingests them automatically. You can also trigger a one-off scan.', + enabled: 'Watcher enabled', + active: 'Active', + interval: 'Scan interval', + sourceType: 'Source type', + directory: 'Source directory', + dirHint: 'absolute path, e.g. /data/docs', + availableTypes: 'Available source types', + scanNow: 'Scan now', + scanDone: 'Scan complete', + scanResult: 'Scanned {scanned}, added {added}, skipped {skipped}, errors {errors}', + }, + pipeline: { + tab: 'Pipelines', + title: 'Custom Pipelines', + desc: 'Define triggers (e.g. a page type reaching a count threshold, page created) and multi-step processing (llm / skill) in YAML. Once saved, the backend runs them on the trigger condition.', + name: 'Name', + trigger: 'Trigger', + enabled: 'Enabled', + runs: 'Runs', + empty: 'No pipeline definitions yet.', + editor: 'YAML definition', + editorHint: 'name: my-pipeline\ntrigger:\n type: page_type_count\n page_type: episode\n threshold: 10\nsteps:\n - executor: llm\n prompt: …', + saveDef: 'Save definition', + deleteConfirm: 'Delete pipeline "{name}"?', + runsFor: 'Runs for "{name}"', + status: 'Status', + startedAt: 'Started at', + noRuns: 'No runs yet.', + }, + }, searchPages: 'Search pages...', dropFiles: 'Drop files here or click to upload', dropToUpload: 'Release to upload', diff --git a/mateclaw-ui/src/i18n/locales/zh-CN.ts b/mateclaw-ui/src/i18n/locales/zh-CN.ts index 4739f9d8..fde0e7d8 100644 --- a/mateclaw-ui/src/i18n/locales/zh-CN.ts +++ b/mateclaw-ui/src/i18n/locales/zh-CN.ts @@ -2125,6 +2125,81 @@ export default { lastError: '最近一次错误', footer: '关闭 wiki.hot_cache.enabled 后注入路径短路;该面板的"立即重建"会绕过去抖,方便调试。', }, + adv: { + tab: '高级管理', + validate: '校验', + validOk: '校验通过', + profile: { + tab: '页面类型', + title: '页面类型 Profile', + desc: '定义本知识库的页面类型(pageType)、所属知识分层、路由/创建/合并阶段指令与内容模板。会注入到摄取流水线的各阶段提示词。', + builtin: '内置默认', + placeholder: '在此粘贴 pageType profile 的 JSON…', + reset: '重置为默认', + resetConfirm: '确认重置为内置默认 profile?当前自定义配置会被清除。', + }, + layers: { + tab: '分层 & 失效', + title: '知识分层与失效状态', + desc: 'fact(事实)层更新后会把依赖它的 experience(经验)页面标记为 stale,提示需要复核。', + fact: '事实层', + experience: '经验层', + other: '其它', + stale: '已失效', + empty: '该知识库暂无页面。', + page: '页面', + layer: '分层', + status: '状态', + staleTag: '待复核', + fresh: '正常', + }, + perm: { + tab: '权限 & 审批', + title: 'Agent 页面类型权限', + desc: '为指定 Agent 配置在本知识库下按 pageType 的读/创建/更新/删除权限;写操作可设为需审批。无规则时默认放行,一旦存在规则则未覆盖的类型按失败安全(拒绝)处理。', + agent: 'Agent', + selectAgent: '选择一个 Agent…', + pageType: '页面类型', + policy: '写策略', + noRows: '该 Agent 暂无权限规则(默认放行)。', + pageTypeHint: '页面类型,* 表示默认', + addRule: '新增规则', + deleteConfirm: '删除 "{type}" 的权限规则?', + }, + watcher: { + tab: '变更监测', + title: '源目录变更监测', + desc: '关联一个本地目录作为知识来源,监测器会按间隔扫描新增/变更文件并自动摄取。也可手动触发一次扫描。', + enabled: '监测开关', + active: '已激活', + interval: '扫描间隔', + sourceType: '源类型', + directory: '源目录', + dirHint: '绝对路径,例如 /data/docs', + availableTypes: '可用源类型', + scanNow: '立即扫描', + scanDone: '扫描完成', + scanResult: '扫描 {scanned} 个,新增 {added},跳过 {skipped},错误 {errors}', + }, + pipeline: { + tab: '流水线', + title: '自定义流水线', + desc: '用 YAML 定义触发器(如某类型页面累计到阈值、页面创建)与多步处理(llm / skill)。保存后由后台按触发条件自动执行。', + name: '名称', + trigger: '触发器', + enabled: '启用', + runs: '运行记录', + empty: '暂无流水线定义。', + editor: 'YAML 定义', + editorHint: 'name: my-pipeline\ntrigger:\n type: page_type_count\n page_type: episode\n threshold: 10\nsteps:\n - executor: llm\n prompt: …', + saveDef: '保存定义', + deleteConfirm: '删除流水线 "{name}"?', + runsFor: '"{name}" 的运行记录', + status: '状态', + startedAt: '开始时间', + noRuns: '暂无运行记录。', + }, + }, searchPages: '搜索页面...', dropFiles: '拖拽文件到此处或点击上传', dropToUpload: '松开即开始上传', diff --git a/mateclaw-ui/src/views/Wiki/components/WikiAdvancedPanel.vue b/mateclaw-ui/src/views/Wiki/components/WikiAdvancedPanel.vue new file mode 100644 index 00000000..eb8f9c6a --- /dev/null +++ b/mateclaw-ui/src/views/Wiki/components/WikiAdvancedPanel.vue @@ -0,0 +1,507 @@ + + + + + diff --git a/mateclaw-ui/src/views/Wiki/components/WikiWorkspace.vue b/mateclaw-ui/src/views/Wiki/components/WikiWorkspace.vue index f2385224..dcef5e98 100644 --- a/mateclaw-ui/src/views/Wiki/components/WikiWorkspace.vue +++ b/mateclaw-ui/src/views/Wiki/components/WikiWorkspace.vue @@ -55,6 +55,10 @@
+ +
+ +
@@ -72,6 +76,7 @@ import WikiConfig from './WikiConfig.vue' import WikiGraphView from './WikiGraphView.vue' import HotCachePanel from './HotCachePanel.vue' import TransformationsPanel from './TransformationsPanel.vue' +import WikiAdvancedPanel from './WikiAdvancedPanel.vue' import WikiWorkspaceHeader from './WikiWorkspaceHeader.vue' import WikiPageSidebar from './WikiPageSidebar.vue' import WikiBrokenLinksBanner from './WikiBrokenLinksBanner.vue' @@ -107,6 +112,7 @@ const tabs = computed(() => { if (canManageWiki.value) { list.push({ key: 'config', label: t('wiki.config') }) list.push({ key: 'transformations', label: t('wiki.transformations.tab') }) + list.push({ key: 'advanced', label: t('wiki.adv.tab') }) } list.push({ key: 'hotCache', label: t('wiki.hotCache.tab') }) return list