mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-10 02:24:35 +08:00
feat: enhance MCP server management and system settings
- Added functionality to save MCP server configurations as templates in the MCP Manager. - Implemented new hooks for managing system settings including Chinese response, Windows platform, and Codex CLI enhancements. - Updated API calls to support fetching and toggling system settings. - Introduced UI components for displaying and managing response language settings and system status. - Enhanced error handling and notifications for server deletion and template saving actions. - Updated localization files for new settings and descriptions in English and Chinese.
This commit is contained in:
@@ -1 +1,84 @@
|
||||
{}
|
||||
{
|
||||
"theme.AnnouncementBar.closeButtonAriaLabel": "关闭",
|
||||
"theme.BackToTopButton.buttonAriaLabel": "回到顶部",
|
||||
"theme.CodeBlock.copied": "复制成功",
|
||||
"theme.CodeBlock.copy": "复制",
|
||||
"theme.CodeBlock.copyButtonAriaLabel": "复制代码到剪贴板",
|
||||
"theme.CodeBlock.wordWrapToggle": "切换自动换行",
|
||||
"theme.DocSidebarItem.collapseCategoryAriaLabel": "折叠侧边栏分类 '{label}'",
|
||||
"theme.DocSidebarItem.expandCategoryAriaLabel": "展开侧边栏分类 '{label}'",
|
||||
"theme.ErrorPageContent.title": "页面已崩溃。",
|
||||
"theme.ErrorPageContent.tryAgain": "重试",
|
||||
"theme.IconExternalLink.ariaLabel": "(opens in new tab)",
|
||||
"theme.NavBar.navAriaLabel": "主导航",
|
||||
"theme.NotFound.p1": "我们找不到您要找的页面。",
|
||||
"theme.NotFound.p2": "请联系原始链接来源网站的所有者,并告知他们链接已损坏。",
|
||||
"theme.NotFound.title": "找不到页面",
|
||||
"theme.TOCCollapsible.toggleButtonLabel": "本页总览",
|
||||
"theme.admonition.caution": "警告",
|
||||
"theme.admonition.danger": "危险",
|
||||
"theme.admonition.info": "信息",
|
||||
"theme.admonition.note": "备注",
|
||||
"theme.admonition.tip": "提示",
|
||||
"theme.admonition.warning": "注意",
|
||||
"theme.blog.archive.description": "历史博文",
|
||||
"theme.blog.archive.title": "历史博文",
|
||||
"theme.blog.author.noPosts": "该作者尚未撰写任何文章。",
|
||||
"theme.blog.author.pageTitle": "{authorName} - {nPosts}",
|
||||
"theme.blog.authorsList.pageTitle": "作者",
|
||||
"theme.blog.authorsList.viewAll": "查看所有作者",
|
||||
"theme.blog.paginator.navAriaLabel": "博文列表分页导航",
|
||||
"theme.blog.paginator.newerEntries": "较新的博文",
|
||||
"theme.blog.paginator.olderEntries": "较旧的博文",
|
||||
"theme.blog.post.paginator.navAriaLabel": "博文分页导航",
|
||||
"theme.blog.post.paginator.newerPost": "较新一篇",
|
||||
"theme.blog.post.paginator.olderPost": "较旧一篇",
|
||||
"theme.blog.post.plurals": "{count} 篇博文",
|
||||
"theme.blog.post.readMore": "阅读更多",
|
||||
"theme.blog.post.readMoreLabel": "阅读 {title} 的全文",
|
||||
"theme.blog.post.readingTime.plurals": "阅读需 {readingTime} 分钟",
|
||||
"theme.blog.sidebar.navAriaLabel": "最近博文导航",
|
||||
"theme.blog.tagTitle": "{nPosts} 含有标签「{tagName}」",
|
||||
"theme.colorToggle.ariaLabel": "切换浅色/暗黑模式(当前为{mode})",
|
||||
"theme.colorToggle.ariaLabel.mode.dark": "暗黑模式",
|
||||
"theme.colorToggle.ariaLabel.mode.light": "浅色模式",
|
||||
"theme.colorToggle.ariaLabel.mode.system": "system mode",
|
||||
"theme.common.editThisPage": "编辑此页",
|
||||
"theme.common.headingLinkTitle": "{heading}的直接链接",
|
||||
"theme.common.skipToMainContent": "跳到主要内容",
|
||||
"theme.contentVisibility.draftBanner.message": "此页面是草稿,仅在开发环境中可见,不会包含在正式版本中。",
|
||||
"theme.contentVisibility.draftBanner.title": "草稿页",
|
||||
"theme.contentVisibility.unlistedBanner.message": "此页面未列出。搜索引擎不会对其索引,只有拥有直接链接的用户才能访问。",
|
||||
"theme.contentVisibility.unlistedBanner.title": "未列出页",
|
||||
"theme.docs.DocCard.categoryDescription.plurals": "{count} 个项目",
|
||||
"theme.docs.breadcrumbs.home": "主页面",
|
||||
"theme.docs.breadcrumbs.navAriaLabel": "页面路径",
|
||||
"theme.docs.paginator.navAriaLabel": "文件选项卡",
|
||||
"theme.docs.paginator.next": "下一页",
|
||||
"theme.docs.paginator.previous": "上一页",
|
||||
"theme.docs.sidebar.closeSidebarButtonAriaLabel": "关闭导航栏",
|
||||
"theme.docs.sidebar.collapseButtonAriaLabel": "收起侧边栏",
|
||||
"theme.docs.sidebar.collapseButtonTitle": "收起侧边栏",
|
||||
"theme.docs.sidebar.expandButtonAriaLabel": "展开侧边栏",
|
||||
"theme.docs.sidebar.expandButtonTitle": "展开侧边栏",
|
||||
"theme.docs.sidebar.navAriaLabel": "文档侧边栏",
|
||||
"theme.docs.sidebar.toggleSidebarButtonAriaLabel": "切换导航栏",
|
||||
"theme.docs.tagDocListPageTitle": "{nDocsTagged}「{tagName}」",
|
||||
"theme.docs.tagDocListPageTitle.nDocsTagged": "{count} 篇文档带有标签",
|
||||
"theme.docs.versionBadge.label": "版本:{versionLabel}",
|
||||
"theme.docs.versions.latestVersionLinkLabel": "最新版本",
|
||||
"theme.docs.versions.latestVersionSuggestionLabel": "最新的文档请参阅 {latestVersionLink} ({versionLabel})。",
|
||||
"theme.docs.versions.unmaintainedVersionLabel": "此为 {siteTitle} {versionLabel} 版的文档,现已不再积极维护。",
|
||||
"theme.docs.versions.unreleasedVersionLabel": "此为 {siteTitle} {versionLabel} 版尚未发行的文档。",
|
||||
"theme.lastUpdated.atDate": "于 {date} ",
|
||||
"theme.lastUpdated.byUser": "由 {user} ",
|
||||
"theme.lastUpdated.lastUpdatedAtBy": "最后{byUser}{atDate}更新",
|
||||
"theme.navbar.mobileDropdown.collapseButton.collapseAriaLabel": "Collapse the dropdown",
|
||||
"theme.navbar.mobileDropdown.collapseButton.expandAriaLabel": "Expand the dropdown",
|
||||
"theme.navbar.mobileLanguageDropdown.label": "选择语言",
|
||||
"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": "← 回到主菜单",
|
||||
"theme.navbar.mobileVersionsDropdown.label": "选择版本",
|
||||
"theme.tags.tagsListLabel": "标签:",
|
||||
"theme.tags.tagsPageLink": "查看所有标签",
|
||||
"theme.tags.tagsPageTitle": "标签"
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
{"options":{"path":"docs","routeBasePath":"/","sidebarPath":"D:\\Claude_dms3\\ccw\\docs-site\\sidebars.ts","editUrl":"https://github.com/ccw/docs/tree/main/","editCurrentVersion":false,"editLocalizedFiles":false,"tagsBasePath":"tags","include":["**/*.{md,mdx}"],"exclude":["**/_*.{js,jsx,ts,tsx,md,mdx}","**/_*/**","**/*.test.{js,jsx,ts,tsx}","**/__tests__/**"],"sidebarCollapsible":true,"sidebarCollapsed":true,"docsRootComponent":"@theme/DocsRoot","docVersionRootComponent":"@theme/DocVersionRoot","docRootComponent":"@theme/DocRoot","docItemComponent":"@theme/DocItem","docTagsListComponent":"@theme/DocTagsListPage","docTagDocListComponent":"@theme/DocTagDocListPage","docCategoryGeneratedIndexComponent":"@theme/DocCategoryGeneratedIndexPage","remarkPlugins":[],"rehypePlugins":[],"recmaPlugins":[],"beforeDefaultRemarkPlugins":[],"beforeDefaultRehypePlugins":[],"admonitions":true,"showLastUpdateTime":false,"showLastUpdateAuthor":false,"includeCurrentVersion":true,"disableVersioning":false,"versions":{},"breadcrumbs":true,"onInlineTags":"warn","id":"default"},"versionsMetadata":[{"versionName":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","path":"/docs/","tagsPath":"/docs/tags","editUrl":"https://github.com/ccw/docs/tree/main/docs","isLast":true,"routePriority":-1,"sidebarFilePath":"D:\\Claude_dms3\\ccw\\docs-site\\sidebars.ts","contentPath":"D:\\Claude_dms3\\ccw\\docs-site\\docs"}]}
|
||||
{"options":{"path":"docs","routeBasePath":"/","sidebarPath":"D:\\Claude_dms3\\ccw\\docs-site\\sidebars.ts","editUrl":"https://github.com/ccw/docs/tree/main/","editCurrentVersion":false,"editLocalizedFiles":false,"tagsBasePath":"tags","include":["**/*.{md,mdx}"],"exclude":["**/_*.{js,jsx,ts,tsx,md,mdx}","**/_*/**","**/*.test.{js,jsx,ts,tsx}","**/__tests__/**"],"sidebarCollapsible":true,"sidebarCollapsed":true,"docsRootComponent":"@theme/DocsRoot","docVersionRootComponent":"@theme/DocVersionRoot","docRootComponent":"@theme/DocRoot","docItemComponent":"@theme/DocItem","docTagsListComponent":"@theme/DocTagsListPage","docTagDocListComponent":"@theme/DocTagDocListPage","docCategoryGeneratedIndexComponent":"@theme/DocCategoryGeneratedIndexPage","remarkPlugins":[],"rehypePlugins":[],"recmaPlugins":[],"beforeDefaultRemarkPlugins":[],"beforeDefaultRehypePlugins":[],"admonitions":true,"showLastUpdateTime":false,"showLastUpdateAuthor":false,"includeCurrentVersion":true,"disableVersioning":false,"versions":{},"breadcrumbs":true,"onInlineTags":"warn","id":"default"},"versionsMetadata":[{"versionName":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","path":"/docs/zh/","tagsPath":"/docs/zh/tags","editUrl":"https://github.com/ccw/docs/tree/main/docs","editUrlLocalized":"https://github.com/ccw/docs/tree/main/i18n/zh/docusaurus-plugin-content-docs/current","isLast":true,"routePriority":-1,"sidebarFilePath":"D:\\Claude_dms3\\ccw\\docs-site\\sidebars.ts","contentPath":"D:\\Claude_dms3\\ccw\\docs-site\\docs","contentPathLocalized":"D:\\Claude_dms3\\ccw\\docs-site\\i18n\\zh\\docusaurus-plugin-content-docs\\current"}]}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/cli/cli-init.mdx",
|
||||
"sourceDirName": "commands/cli",
|
||||
"slug": "/commands/cli/cli-init",
|
||||
"permalink": "/docs/commands/cli/cli-init",
|
||||
"permalink": "/docs/zh/commands/cli/cli-init",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/cli/cli-init.mdx",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "issue:convert-to-plan",
|
||||
"permalink": "/docs/commands/issue/issue-convert-to-plan"
|
||||
"permalink": "/docs/zh/commands/issue/issue-convert-to-plan"
|
||||
},
|
||||
"next": {
|
||||
"title": "/cli:codex-review",
|
||||
"permalink": "/docs/commands/cli/codex-review"
|
||||
"permalink": "/docs/zh/commands/cli/codex-review"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/cli/codex-review.mdx",
|
||||
"sourceDirName": "commands/cli",
|
||||
"slug": "/commands/cli/codex-review",
|
||||
"permalink": "/docs/commands/cli/codex-review",
|
||||
"permalink": "/docs/zh/commands/cli/codex-review",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/cli/codex-review.mdx",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "/cli:cli-init",
|
||||
"permalink": "/docs/commands/cli/cli-init"
|
||||
"permalink": "/docs/zh/commands/cli/cli-init"
|
||||
},
|
||||
"next": {
|
||||
"title": "/memory:update-full",
|
||||
"permalink": "/docs/commands/memory/memory-update-full"
|
||||
"permalink": "/docs/zh/commands/memory/memory-update-full"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/general/ccw-coordinator.mdx",
|
||||
"sourceDirName": "commands/general",
|
||||
"slug": "/commands/general/ccw-coordinator",
|
||||
"permalink": "/docs/commands/general/ccw-coordinator",
|
||||
"permalink": "/docs/zh/commands/general/ccw-coordinator",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/general/ccw-coordinator.mdx",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "/ccw-test",
|
||||
"permalink": "/docs/commands/general/ccw-test"
|
||||
"permalink": "/docs/zh/commands/general/ccw-test"
|
||||
},
|
||||
"next": {
|
||||
"title": "/ccw-debug",
|
||||
"permalink": "/docs/commands/general/ccw-debug"
|
||||
"permalink": "/docs/zh/commands/general/ccw-debug"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/general/ccw-debug.mdx",
|
||||
"sourceDirName": "commands/general",
|
||||
"slug": "/commands/general/ccw-debug",
|
||||
"permalink": "/docs/commands/general/ccw-debug",
|
||||
"permalink": "/docs/zh/commands/general/ccw-debug",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/general/ccw-debug.mdx",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "/ccw-coordinator",
|
||||
"permalink": "/docs/commands/general/ccw-coordinator"
|
||||
"permalink": "/docs/zh/commands/general/ccw-coordinator"
|
||||
},
|
||||
"next": {
|
||||
"title": "/flow-create",
|
||||
"permalink": "/docs/commands/general/flow-create"
|
||||
"permalink": "/docs/zh/commands/general/flow-create"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/general/ccw.mdx",
|
||||
"sourceDirName": "commands/general",
|
||||
"slug": "/commands/general/ccw",
|
||||
"permalink": "/docs/commands/general/ccw",
|
||||
"permalink": "/docs/zh/commands/general/ccw",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/general/ccw.mdx",
|
||||
@@ -20,11 +20,11 @@
|
||||
},
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "Overview",
|
||||
"permalink": "/docs/overview"
|
||||
"title": "概览",
|
||||
"permalink": "/docs/zh/overview"
|
||||
},
|
||||
"next": {
|
||||
"title": "/ccw-plan",
|
||||
"permalink": "/docs/commands/general/ccw-plan"
|
||||
"permalink": "/docs/zh/commands/general/ccw-plan"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/general/ccw-plan.mdx",
|
||||
"sourceDirName": "commands/general",
|
||||
"slug": "/commands/general/ccw-plan",
|
||||
"permalink": "/docs/commands/general/ccw-plan",
|
||||
"permalink": "/docs/zh/commands/general/ccw-plan",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/general/ccw-plan.mdx",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "/ccw",
|
||||
"permalink": "/docs/commands/general/ccw"
|
||||
"permalink": "/docs/zh/commands/general/ccw"
|
||||
},
|
||||
"next": {
|
||||
"title": "/ccw-test",
|
||||
"permalink": "/docs/commands/general/ccw-test"
|
||||
"permalink": "/docs/zh/commands/general/ccw-test"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/general/ccw-test.mdx",
|
||||
"sourceDirName": "commands/general",
|
||||
"slug": "/commands/general/ccw-test",
|
||||
"permalink": "/docs/commands/general/ccw-test",
|
||||
"permalink": "/docs/zh/commands/general/ccw-test",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/general/ccw-test.mdx",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "/ccw-plan",
|
||||
"permalink": "/docs/commands/general/ccw-plan"
|
||||
"permalink": "/docs/zh/commands/general/ccw-plan"
|
||||
},
|
||||
"next": {
|
||||
"title": "/ccw-coordinator",
|
||||
"permalink": "/docs/commands/general/ccw-coordinator"
|
||||
"permalink": "/docs/zh/commands/general/ccw-coordinator"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/general/codex-coordinator.mdx",
|
||||
"sourceDirName": "commands/general",
|
||||
"slug": "/commands/general/codex-coordinator",
|
||||
"permalink": "/docs/commands/general/codex-coordinator",
|
||||
"permalink": "/docs/zh/commands/general/codex-coordinator",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/general/codex-coordinator.mdx",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "/flow-create",
|
||||
"permalink": "/docs/commands/general/flow-create"
|
||||
"permalink": "/docs/zh/commands/general/flow-create"
|
||||
},
|
||||
"next": {
|
||||
"title": "issue:new",
|
||||
"permalink": "/docs/commands/issue/issue-new"
|
||||
"permalink": "/docs/zh/commands/issue/issue-new"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/general/flow-create.mdx",
|
||||
"sourceDirName": "commands/general",
|
||||
"slug": "/commands/general/flow-create",
|
||||
"permalink": "/docs/commands/general/flow-create",
|
||||
"permalink": "/docs/zh/commands/general/flow-create",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/general/flow-create.mdx",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "/ccw-debug",
|
||||
"permalink": "/docs/commands/general/ccw-debug"
|
||||
"permalink": "/docs/zh/commands/general/ccw-debug"
|
||||
},
|
||||
"next": {
|
||||
"title": "/codex-coordinator",
|
||||
"permalink": "/docs/commands/general/codex-coordinator"
|
||||
"permalink": "/docs/zh/commands/general/codex-coordinator"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/issue/issue-convert-to-plan.md",
|
||||
"sourceDirName": "commands/issue",
|
||||
"slug": "/commands/issue/issue-convert-to-plan",
|
||||
"permalink": "/docs/commands/issue/issue-convert-to-plan",
|
||||
"permalink": "/docs/zh/commands/issue/issue-convert-to-plan",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/issue/issue-convert-to-plan.md",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "issue:from-brainstorm",
|
||||
"permalink": "/docs/commands/issue/issue-from-brainstorm"
|
||||
"permalink": "/docs/zh/commands/issue/issue-from-brainstorm"
|
||||
},
|
||||
"next": {
|
||||
"title": "/cli:cli-init",
|
||||
"permalink": "/docs/commands/cli/cli-init"
|
||||
"permalink": "/docs/zh/commands/cli/cli-init"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/issue/issue-discover.md",
|
||||
"sourceDirName": "commands/issue",
|
||||
"slug": "/commands/issue/issue-discover",
|
||||
"permalink": "/docs/commands/issue/issue-discover",
|
||||
"permalink": "/docs/zh/commands/issue/issue-discover",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/issue/issue-discover.md",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "issue:new",
|
||||
"permalink": "/docs/commands/issue/issue-new"
|
||||
"permalink": "/docs/zh/commands/issue/issue-new"
|
||||
},
|
||||
"next": {
|
||||
"title": "issue:plan",
|
||||
"permalink": "/docs/commands/issue/issue-plan"
|
||||
"permalink": "/docs/zh/commands/issue/issue-plan"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/issue/issue-execute.md",
|
||||
"sourceDirName": "commands/issue",
|
||||
"slug": "/commands/issue/issue-execute",
|
||||
"permalink": "/docs/commands/issue/issue-execute",
|
||||
"permalink": "/docs/zh/commands/issue/issue-execute",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/issue/issue-execute.md",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "issue:queue",
|
||||
"permalink": "/docs/commands/issue/issue-queue"
|
||||
"permalink": "/docs/zh/commands/issue/issue-queue"
|
||||
},
|
||||
"next": {
|
||||
"title": "issue:from-brainstorm",
|
||||
"permalink": "/docs/commands/issue/issue-from-brainstorm"
|
||||
"permalink": "/docs/zh/commands/issue/issue-from-brainstorm"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/issue/issue-from-brainstorm.md",
|
||||
"sourceDirName": "commands/issue",
|
||||
"slug": "/commands/issue/issue-from-brainstorm",
|
||||
"permalink": "/docs/commands/issue/issue-from-brainstorm",
|
||||
"permalink": "/docs/zh/commands/issue/issue-from-brainstorm",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/issue/issue-from-brainstorm.md",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "issue:execute",
|
||||
"permalink": "/docs/commands/issue/issue-execute"
|
||||
"permalink": "/docs/zh/commands/issue/issue-execute"
|
||||
},
|
||||
"next": {
|
||||
"title": "issue:convert-to-plan",
|
||||
"permalink": "/docs/commands/issue/issue-convert-to-plan"
|
||||
"permalink": "/docs/zh/commands/issue/issue-convert-to-plan"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/issue/issue-new.md",
|
||||
"sourceDirName": "commands/issue",
|
||||
"slug": "/commands/issue/issue-new",
|
||||
"permalink": "/docs/commands/issue/issue-new",
|
||||
"permalink": "/docs/zh/commands/issue/issue-new",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/issue/issue-new.md",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "/codex-coordinator",
|
||||
"permalink": "/docs/commands/general/codex-coordinator"
|
||||
"permalink": "/docs/zh/commands/general/codex-coordinator"
|
||||
},
|
||||
"next": {
|
||||
"title": "issue:discover",
|
||||
"permalink": "/docs/commands/issue/issue-discover"
|
||||
"permalink": "/docs/zh/commands/issue/issue-discover"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/issue/issue-plan.md",
|
||||
"sourceDirName": "commands/issue",
|
||||
"slug": "/commands/issue/issue-plan",
|
||||
"permalink": "/docs/commands/issue/issue-plan",
|
||||
"permalink": "/docs/zh/commands/issue/issue-plan",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/issue/issue-plan.md",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "issue:discover",
|
||||
"permalink": "/docs/commands/issue/issue-discover"
|
||||
"permalink": "/docs/zh/commands/issue/issue-discover"
|
||||
},
|
||||
"next": {
|
||||
"title": "issue:queue",
|
||||
"permalink": "/docs/commands/issue/issue-queue"
|
||||
"permalink": "/docs/zh/commands/issue/issue-queue"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/issue/issue-queue.md",
|
||||
"sourceDirName": "commands/issue",
|
||||
"slug": "/commands/issue/issue-queue",
|
||||
"permalink": "/docs/commands/issue/issue-queue",
|
||||
"permalink": "/docs/zh/commands/issue/issue-queue",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/issue/issue-queue.md",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "issue:plan",
|
||||
"permalink": "/docs/commands/issue/issue-plan"
|
||||
"permalink": "/docs/zh/commands/issue/issue-plan"
|
||||
},
|
||||
"next": {
|
||||
"title": "issue:execute",
|
||||
"permalink": "/docs/commands/issue/issue-execute"
|
||||
"permalink": "/docs/zh/commands/issue/issue-execute"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/memory/memory-compact.mdx",
|
||||
"sourceDirName": "commands/memory",
|
||||
"slug": "/commands/memory/memory-compact",
|
||||
"permalink": "/docs/commands/memory/memory-compact",
|
||||
"permalink": "/docs/zh/commands/memory/memory-compact",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/memory/memory-compact.mdx",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "/memory:docs-related-cli",
|
||||
"permalink": "/docs/commands/memory/memory-docs-related-cli"
|
||||
"permalink": "/docs/zh/commands/memory/memory-docs-related-cli"
|
||||
},
|
||||
"next": {
|
||||
"title": "Introduction",
|
||||
"permalink": "/docs/workflows/introduction"
|
||||
"permalink": "/docs/zh/workflows/introduction"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/memory/memory-docs-full-cli.mdx",
|
||||
"sourceDirName": "commands/memory",
|
||||
"slug": "/commands/memory/memory-docs-full-cli",
|
||||
"permalink": "/docs/commands/memory/memory-docs-full-cli",
|
||||
"permalink": "/docs/zh/commands/memory/memory-docs-full-cli",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/memory/memory-docs-full-cli.mdx",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "/memory:load",
|
||||
"permalink": "/docs/commands/memory/memory-load"
|
||||
"permalink": "/docs/zh/commands/memory/memory-load"
|
||||
},
|
||||
"next": {
|
||||
"title": "/memory:docs-related-cli",
|
||||
"permalink": "/docs/commands/memory/memory-docs-related-cli"
|
||||
"permalink": "/docs/zh/commands/memory/memory-docs-related-cli"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/memory/memory-docs-related-cli.mdx",
|
||||
"sourceDirName": "commands/memory",
|
||||
"slug": "/commands/memory/memory-docs-related-cli",
|
||||
"permalink": "/docs/commands/memory/memory-docs-related-cli",
|
||||
"permalink": "/docs/zh/commands/memory/memory-docs-related-cli",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/memory/memory-docs-related-cli.mdx",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "/memory:docs-full-cli",
|
||||
"permalink": "/docs/commands/memory/memory-docs-full-cli"
|
||||
"permalink": "/docs/zh/commands/memory/memory-docs-full-cli"
|
||||
},
|
||||
"next": {
|
||||
"title": "/memory:compact",
|
||||
"permalink": "/docs/commands/memory/memory-compact"
|
||||
"permalink": "/docs/zh/commands/memory/memory-compact"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/memory/memory-load.mdx",
|
||||
"sourceDirName": "commands/memory",
|
||||
"slug": "/commands/memory/memory-load",
|
||||
"permalink": "/docs/commands/memory/memory-load",
|
||||
"permalink": "/docs/zh/commands/memory/memory-load",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/memory/memory-load.mdx",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "/memory:update-related",
|
||||
"permalink": "/docs/commands/memory/memory-update-related"
|
||||
"permalink": "/docs/zh/commands/memory/memory-update-related"
|
||||
},
|
||||
"next": {
|
||||
"title": "/memory:docs-full-cli",
|
||||
"permalink": "/docs/commands/memory/memory-docs-full-cli"
|
||||
"permalink": "/docs/zh/commands/memory/memory-docs-full-cli"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/memory/memory-update-full.mdx",
|
||||
"sourceDirName": "commands/memory",
|
||||
"slug": "/commands/memory/memory-update-full",
|
||||
"permalink": "/docs/commands/memory/memory-update-full",
|
||||
"permalink": "/docs/zh/commands/memory/memory-update-full",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/memory/memory-update-full.mdx",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "/cli:codex-review",
|
||||
"permalink": "/docs/commands/cli/codex-review"
|
||||
"permalink": "/docs/zh/commands/cli/codex-review"
|
||||
},
|
||||
"next": {
|
||||
"title": "/memory:update-related",
|
||||
"permalink": "/docs/commands/memory/memory-update-related"
|
||||
"permalink": "/docs/zh/commands/memory/memory-update-related"
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": "@site/docs/commands/memory/memory-update-related.mdx",
|
||||
"sourceDirName": "commands/memory",
|
||||
"slug": "/commands/memory/memory-update-related",
|
||||
"permalink": "/docs/commands/memory/memory-update-related",
|
||||
"permalink": "/docs/zh/commands/memory/memory-update-related",
|
||||
"draft": false,
|
||||
"unlisted": false,
|
||||
"editUrl": "https://github.com/ccw/docs/tree/main/docs/commands/memory/memory-update-related.mdx",
|
||||
@@ -21,10 +21,10 @@
|
||||
"sidebar": "docs",
|
||||
"previous": {
|
||||
"title": "/memory:update-full",
|
||||
"permalink": "/docs/commands/memory/memory-update-full"
|
||||
"permalink": "/docs/zh/commands/memory/memory-update-full"
|
||||
},
|
||||
"next": {
|
||||
"title": "/memory:load",
|
||||
"permalink": "/docs/commands/memory/memory-load"
|
||||
"permalink": "/docs/zh/commands/memory/memory-load"
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ export default {
|
||||
"tagline": "Professional Workflow Automation Platform",
|
||||
"favicon": "img/favicon.svg",
|
||||
"url": "http://localhost:3001",
|
||||
"baseUrl": "/docs/",
|
||||
"baseUrl": "/docs/zh/",
|
||||
"organizationName": "ccw",
|
||||
"projectName": "docs",
|
||||
"trailingSlash": false,
|
||||
@@ -48,9 +48,9 @@ export default {
|
||||
],
|
||||
"themeConfig": {
|
||||
"navbar": {
|
||||
"title": "CCW Help",
|
||||
"title": "CCW 帮助",
|
||||
"logo": {
|
||||
"alt": "CCW Logo",
|
||||
"alt": "CCW 标志",
|
||||
"src": "img/logo.svg"
|
||||
},
|
||||
"items": [
|
||||
@@ -65,7 +65,7 @@ export default {
|
||||
},
|
||||
"footer": {
|
||||
"style": "dark",
|
||||
"copyright": "Copyright © 2026 CCW. Built with Docusaurus.",
|
||||
"copyright": "版权 © 2026 CCW。使用 Docusaurus 构建。",
|
||||
"links": []
|
||||
},
|
||||
"prism": {
|
||||
|
||||
@@ -1,172 +1,172 @@
|
||||
{
|
||||
"docusaurus-plugin-content-docs": {
|
||||
"default": {
|
||||
"path": "/docs/",
|
||||
"path": "/docs/zh/",
|
||||
"versions": [
|
||||
{
|
||||
"name": "current",
|
||||
"label": "Next",
|
||||
"label": "当前",
|
||||
"isLast": true,
|
||||
"path": "/docs/",
|
||||
"path": "/docs/zh/",
|
||||
"mainDocId": "index",
|
||||
"docs": [
|
||||
{
|
||||
"id": "commands/cli/cli-init",
|
||||
"path": "/docs/commands/cli/cli-init",
|
||||
"path": "/docs/zh/commands/cli/cli-init",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/cli/codex-review",
|
||||
"path": "/docs/commands/cli/codex-review",
|
||||
"path": "/docs/zh/commands/cli/codex-review",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/general/ccw",
|
||||
"path": "/docs/commands/general/ccw",
|
||||
"path": "/docs/zh/commands/general/ccw",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/general/ccw-coordinator",
|
||||
"path": "/docs/commands/general/ccw-coordinator",
|
||||
"path": "/docs/zh/commands/general/ccw-coordinator",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/general/ccw-debug",
|
||||
"path": "/docs/commands/general/ccw-debug",
|
||||
"path": "/docs/zh/commands/general/ccw-debug",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/general/ccw-plan",
|
||||
"path": "/docs/commands/general/ccw-plan",
|
||||
"path": "/docs/zh/commands/general/ccw-plan",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/general/ccw-test",
|
||||
"path": "/docs/commands/general/ccw-test",
|
||||
"path": "/docs/zh/commands/general/ccw-test",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/general/codex-coordinator",
|
||||
"path": "/docs/commands/general/codex-coordinator",
|
||||
"path": "/docs/zh/commands/general/codex-coordinator",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/general/flow-create",
|
||||
"path": "/docs/commands/general/flow-create",
|
||||
"path": "/docs/zh/commands/general/flow-create",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/issue/issue-convert-to-plan",
|
||||
"path": "/docs/commands/issue/issue-convert-to-plan",
|
||||
"path": "/docs/zh/commands/issue/issue-convert-to-plan",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/issue/issue-discover",
|
||||
"path": "/docs/commands/issue/issue-discover",
|
||||
"path": "/docs/zh/commands/issue/issue-discover",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/issue/issue-execute",
|
||||
"path": "/docs/commands/issue/issue-execute",
|
||||
"path": "/docs/zh/commands/issue/issue-execute",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/issue/issue-from-brainstorm",
|
||||
"path": "/docs/commands/issue/issue-from-brainstorm",
|
||||
"path": "/docs/zh/commands/issue/issue-from-brainstorm",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/issue/issue-new",
|
||||
"path": "/docs/commands/issue/issue-new",
|
||||
"path": "/docs/zh/commands/issue/issue-new",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/issue/issue-plan",
|
||||
"path": "/docs/commands/issue/issue-plan",
|
||||
"path": "/docs/zh/commands/issue/issue-plan",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/issue/issue-queue",
|
||||
"path": "/docs/commands/issue/issue-queue",
|
||||
"path": "/docs/zh/commands/issue/issue-queue",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/memory/memory-compact",
|
||||
"path": "/docs/commands/memory/memory-compact",
|
||||
"path": "/docs/zh/commands/memory/memory-compact",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/memory/memory-docs-full-cli",
|
||||
"path": "/docs/commands/memory/memory-docs-full-cli",
|
||||
"path": "/docs/zh/commands/memory/memory-docs-full-cli",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/memory/memory-docs-related-cli",
|
||||
"path": "/docs/commands/memory/memory-docs-related-cli",
|
||||
"path": "/docs/zh/commands/memory/memory-docs-related-cli",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/memory/memory-load",
|
||||
"path": "/docs/commands/memory/memory-load",
|
||||
"path": "/docs/zh/commands/memory/memory-load",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/memory/memory-update-full",
|
||||
"path": "/docs/commands/memory/memory-update-full",
|
||||
"path": "/docs/zh/commands/memory/memory-update-full",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "commands/memory/memory-update-related",
|
||||
"path": "/docs/commands/memory/memory-update-related",
|
||||
"path": "/docs/zh/commands/memory/memory-update-related",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "faq",
|
||||
"path": "/docs/faq",
|
||||
"path": "/docs/zh/faq",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "index",
|
||||
"path": "/docs/",
|
||||
"path": "/docs/zh/",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "overview",
|
||||
"path": "/docs/overview",
|
||||
"path": "/docs/zh/overview",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "workflows/faq",
|
||||
"path": "/docs/workflows/faq"
|
||||
"path": "/docs/zh/workflows/faq"
|
||||
},
|
||||
{
|
||||
"id": "workflows/introduction",
|
||||
"path": "/docs/workflows/introduction",
|
||||
"path": "/docs/zh/workflows/introduction",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "workflows/level-1-ultra-lightweight",
|
||||
"path": "/docs/workflows/level-1-ultra-lightweight",
|
||||
"path": "/docs/zh/workflows/level-1-ultra-lightweight",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "workflows/level-2-rapid",
|
||||
"path": "/docs/workflows/level-2-rapid",
|
||||
"path": "/docs/zh/workflows/level-2-rapid",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "workflows/level-3-standard",
|
||||
"path": "/docs/workflows/level-3-standard",
|
||||
"path": "/docs/zh/workflows/level-3-standard",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "workflows/level-4-brainstorm",
|
||||
"path": "/docs/workflows/level-4-brainstorm",
|
||||
"path": "/docs/zh/workflows/level-4-brainstorm",
|
||||
"sidebar": "docs"
|
||||
},
|
||||
{
|
||||
"id": "workflows/level-5-intelligent",
|
||||
"path": "/docs/workflows/level-5-intelligent",
|
||||
"path": "/docs/zh/workflows/level-5-intelligent",
|
||||
"sidebar": "docs"
|
||||
}
|
||||
],
|
||||
@@ -174,7 +174,7 @@
|
||||
"sidebars": {
|
||||
"docs": {
|
||||
"link": {
|
||||
"path": "/docs/",
|
||||
"path": "/docs/zh/",
|
||||
"label": "Home"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"zh"
|
||||
],
|
||||
"path": "i18n",
|
||||
"currentLocale": "en",
|
||||
"currentLocale": "zh",
|
||||
"localeConfigs": {
|
||||
"en": {
|
||||
"label": "English",
|
||||
|
||||
@@ -1,47 +1,39 @@
|
||||
export default {
|
||||
"__comp---theme-debug-config-23-a-2ff": [() => import(/* webpackChunkName: "__comp---theme-debug-config-23-a-2ff" */ "@theme/DebugConfig"), "@theme/DebugConfig", require.resolveWeak("@theme/DebugConfig")],
|
||||
"__comp---theme-debug-contentba-8-ce7": [() => import(/* webpackChunkName: "__comp---theme-debug-contentba-8-ce7" */ "@theme/DebugContent"), "@theme/DebugContent", require.resolveWeak("@theme/DebugContent")],
|
||||
"__comp---theme-debug-global-dataede-0fa": [() => import(/* webpackChunkName: "__comp---theme-debug-global-dataede-0fa" */ "@theme/DebugGlobalData"), "@theme/DebugGlobalData", require.resolveWeak("@theme/DebugGlobalData")],
|
||||
"__comp---theme-debug-registry-679-501": [() => import(/* webpackChunkName: "__comp---theme-debug-registry-679-501" */ "@theme/DebugRegistry"), "@theme/DebugRegistry", require.resolveWeak("@theme/DebugRegistry")],
|
||||
"__comp---theme-debug-routes-946-699": [() => import(/* webpackChunkName: "__comp---theme-debug-routes-946-699" */ "@theme/DebugRoutes"), "@theme/DebugRoutes", require.resolveWeak("@theme/DebugRoutes")],
|
||||
"__comp---theme-debug-site-metadata-68-e-3d4": [() => import(/* webpackChunkName: "__comp---theme-debug-site-metadata-68-e-3d4" */ "@theme/DebugSiteMetadata"), "@theme/DebugSiteMetadata", require.resolveWeak("@theme/DebugSiteMetadata")],
|
||||
"__comp---theme-doc-item-178-a40": [() => import(/* webpackChunkName: "__comp---theme-doc-item-178-a40" */ "@theme/DocItem"), "@theme/DocItem", require.resolveWeak("@theme/DocItem")],
|
||||
"__comp---theme-doc-roota-94-67a": [() => import(/* webpackChunkName: "__comp---theme-doc-roota-94-67a" */ "@theme/DocRoot"), "@theme/DocRoot", require.resolveWeak("@theme/DocRoot")],
|
||||
"__comp---theme-doc-version-roota-7-b-5de": [() => import(/* webpackChunkName: "__comp---theme-doc-version-roota-7-b-5de" */ "@theme/DocVersionRoot"), "@theme/DocVersionRoot", require.resolveWeak("@theme/DocVersionRoot")],
|
||||
"__comp---theme-docs-root-5-e-9-0b6": [() => import(/* webpackChunkName: "__comp---theme-docs-root-5-e-9-0b6" */ "@theme/DocsRoot"), "@theme/DocsRoot", require.resolveWeak("@theme/DocsRoot")],
|
||||
"__props---docs-11-b-f70": [() => import(/* webpackChunkName: "__props---docs-11-b-f70" */ "@generated/docusaurus-plugin-content-docs/default/p/docs-7fc.json"), "@generated/docusaurus-plugin-content-docs/default/p/docs-7fc.json", require.resolveWeak("@generated/docusaurus-plugin-content-docs/default/p/docs-7fc.json")],
|
||||
"__props---docs-docusaurus-debug-content-344-8d5": [() => import(/* webpackChunkName: "__props---docs-docusaurus-debug-content-344-8d5" */ "@generated/docusaurus-plugin-debug/default/p/docs-docusaurus-debug-content-a52.json"), "@generated/docusaurus-plugin-debug/default/p/docs-docusaurus-debug-content-a52.json", require.resolveWeak("@generated/docusaurus-plugin-debug/default/p/docs-docusaurus-debug-content-a52.json")],
|
||||
"content---docs-4-ed-831": [() => import(/* webpackChunkName: "content---docs-4-ed-831" */ "@site/docs/index.mdx"), "@site/docs/index.mdx", require.resolveWeak("@site/docs/index.mdx")],
|
||||
"content---docs-commands-cli-cli-init-056-ce1": [() => import(/* webpackChunkName: "content---docs-commands-cli-cli-init-056-ce1" */ "@site/docs/commands/cli/cli-init.mdx"), "@site/docs/commands/cli/cli-init.mdx", require.resolveWeak("@site/docs/commands/cli/cli-init.mdx")],
|
||||
"content---docs-commands-cli-codex-reviewf-1-b-55f": [() => import(/* webpackChunkName: "content---docs-commands-cli-codex-reviewf-1-b-55f" */ "@site/docs/commands/cli/codex-review.mdx"), "@site/docs/commands/cli/codex-review.mdx", require.resolveWeak("@site/docs/commands/cli/codex-review.mdx")],
|
||||
"content---docs-commands-general-ccw-coordinatord-55-c6b": [() => import(/* webpackChunkName: "content---docs-commands-general-ccw-coordinatord-55-c6b" */ "@site/docs/commands/general/ccw-coordinator.mdx"), "@site/docs/commands/general/ccw-coordinator.mdx", require.resolveWeak("@site/docs/commands/general/ccw-coordinator.mdx")],
|
||||
"content---docs-commands-general-ccw-debug-97-c-a72": [() => import(/* webpackChunkName: "content---docs-commands-general-ccw-debug-97-c-a72" */ "@site/docs/commands/general/ccw-debug.mdx"), "@site/docs/commands/general/ccw-debug.mdx", require.resolveWeak("@site/docs/commands/general/ccw-debug.mdx")],
|
||||
"content---docs-commands-general-ccw-plan-04-d-fe0": [() => import(/* webpackChunkName: "content---docs-commands-general-ccw-plan-04-d-fe0" */ "@site/docs/commands/general/ccw-plan.mdx"), "@site/docs/commands/general/ccw-plan.mdx", require.resolveWeak("@site/docs/commands/general/ccw-plan.mdx")],
|
||||
"content---docs-commands-general-ccw-testcce-912": [() => import(/* webpackChunkName: "content---docs-commands-general-ccw-testcce-912" */ "@site/docs/commands/general/ccw-test.mdx"), "@site/docs/commands/general/ccw-test.mdx", require.resolveWeak("@site/docs/commands/general/ccw-test.mdx")],
|
||||
"content---docs-commands-general-ccwf-48-8c4": [() => import(/* webpackChunkName: "content---docs-commands-general-ccwf-48-8c4" */ "@site/docs/commands/general/ccw.mdx"), "@site/docs/commands/general/ccw.mdx", require.resolveWeak("@site/docs/commands/general/ccw.mdx")],
|
||||
"content---docs-commands-general-codex-coordinatorf-92-1dc": [() => import(/* webpackChunkName: "content---docs-commands-general-codex-coordinatorf-92-1dc" */ "@site/docs/commands/general/codex-coordinator.mdx"), "@site/docs/commands/general/codex-coordinator.mdx", require.resolveWeak("@site/docs/commands/general/codex-coordinator.mdx")],
|
||||
"content---docs-commands-general-flow-createfab-98a": [() => import(/* webpackChunkName: "content---docs-commands-general-flow-createfab-98a" */ "@site/docs/commands/general/flow-create.mdx"), "@site/docs/commands/general/flow-create.mdx", require.resolveWeak("@site/docs/commands/general/flow-create.mdx")],
|
||||
"content---docs-commands-issue-issue-convert-to-plan-5-c-7-184": [() => import(/* webpackChunkName: "content---docs-commands-issue-issue-convert-to-plan-5-c-7-184" */ "@site/docs/commands/issue/issue-convert-to-plan.md"), "@site/docs/commands/issue/issue-convert-to-plan.md", require.resolveWeak("@site/docs/commands/issue/issue-convert-to-plan.md")],
|
||||
"content---docs-commands-issue-issue-discover-1-e-3-569": [() => import(/* webpackChunkName: "content---docs-commands-issue-issue-discover-1-e-3-569" */ "@site/docs/commands/issue/issue-discover.md"), "@site/docs/commands/issue/issue-discover.md", require.resolveWeak("@site/docs/commands/issue/issue-discover.md")],
|
||||
"content---docs-commands-issue-issue-executefe-8-c03": [() => import(/* webpackChunkName: "content---docs-commands-issue-issue-executefe-8-c03" */ "@site/docs/commands/issue/issue-execute.md"), "@site/docs/commands/issue/issue-execute.md", require.resolveWeak("@site/docs/commands/issue/issue-execute.md")],
|
||||
"content---docs-commands-issue-issue-from-brainstorm-2-ec-eeb": [() => import(/* webpackChunkName: "content---docs-commands-issue-issue-from-brainstorm-2-ec-eeb" */ "@site/docs/commands/issue/issue-from-brainstorm.md"), "@site/docs/commands/issue/issue-from-brainstorm.md", require.resolveWeak("@site/docs/commands/issue/issue-from-brainstorm.md")],
|
||||
"content---docs-commands-issue-issue-new-4-ad-3f0": [() => import(/* webpackChunkName: "content---docs-commands-issue-issue-new-4-ad-3f0" */ "@site/docs/commands/issue/issue-new.md"), "@site/docs/commands/issue/issue-new.md", require.resolveWeak("@site/docs/commands/issue/issue-new.md")],
|
||||
"content---docs-commands-issue-issue-plana-6-c-fbd": [() => import(/* webpackChunkName: "content---docs-commands-issue-issue-plana-6-c-fbd" */ "@site/docs/commands/issue/issue-plan.md"), "@site/docs/commands/issue/issue-plan.md", require.resolveWeak("@site/docs/commands/issue/issue-plan.md")],
|
||||
"content---docs-commands-issue-issue-queue-1-ba-55f": [() => import(/* webpackChunkName: "content---docs-commands-issue-issue-queue-1-ba-55f" */ "@site/docs/commands/issue/issue-queue.md"), "@site/docs/commands/issue/issue-queue.md", require.resolveWeak("@site/docs/commands/issue/issue-queue.md")],
|
||||
"content---docs-commands-memory-memory-compact-7-a-1-41c": [() => import(/* webpackChunkName: "content---docs-commands-memory-memory-compact-7-a-1-41c" */ "@site/docs/commands/memory/memory-compact.mdx"), "@site/docs/commands/memory/memory-compact.mdx", require.resolveWeak("@site/docs/commands/memory/memory-compact.mdx")],
|
||||
"content---docs-commands-memory-memory-docs-full-cli-4-cc-96f": [() => import(/* webpackChunkName: "content---docs-commands-memory-memory-docs-full-cli-4-cc-96f" */ "@site/docs/commands/memory/memory-docs-full-cli.mdx"), "@site/docs/commands/memory/memory-docs-full-cli.mdx", require.resolveWeak("@site/docs/commands/memory/memory-docs-full-cli.mdx")],
|
||||
"content---docs-commands-memory-memory-docs-related-cli-60-e-dd0": [() => import(/* webpackChunkName: "content---docs-commands-memory-memory-docs-related-cli-60-e-dd0" */ "@site/docs/commands/memory/memory-docs-related-cli.mdx"), "@site/docs/commands/memory/memory-docs-related-cli.mdx", require.resolveWeak("@site/docs/commands/memory/memory-docs-related-cli.mdx")],
|
||||
"content---docs-commands-memory-memory-load-157-952": [() => import(/* webpackChunkName: "content---docs-commands-memory-memory-load-157-952" */ "@site/docs/commands/memory/memory-load.mdx"), "@site/docs/commands/memory/memory-load.mdx", require.resolveWeak("@site/docs/commands/memory/memory-load.mdx")],
|
||||
"content---docs-commands-memory-memory-update-full-666-002": [() => import(/* webpackChunkName: "content---docs-commands-memory-memory-update-full-666-002" */ "@site/docs/commands/memory/memory-update-full.mdx"), "@site/docs/commands/memory/memory-update-full.mdx", require.resolveWeak("@site/docs/commands/memory/memory-update-full.mdx")],
|
||||
"content---docs-commands-memory-memory-update-related-611-8d3": [() => import(/* webpackChunkName: "content---docs-commands-memory-memory-update-related-611-8d3" */ "@site/docs/commands/memory/memory-update-related.mdx"), "@site/docs/commands/memory/memory-update-related.mdx", require.resolveWeak("@site/docs/commands/memory/memory-update-related.mdx")],
|
||||
"content---docs-faqea-3-888": [() => import(/* webpackChunkName: "content---docs-faqea-3-888" */ "@site/docs/faq.mdx"), "@site/docs/faq.mdx", require.resolveWeak("@site/docs/faq.mdx")],
|
||||
"content---docs-overview-188-429": [() => import(/* webpackChunkName: "content---docs-overview-188-429" */ "@site/docs/overview.mdx"), "@site/docs/overview.mdx", require.resolveWeak("@site/docs/overview.mdx")],
|
||||
"content---docs-workflows-faqbcf-045": [() => import(/* webpackChunkName: "content---docs-workflows-faqbcf-045" */ "@site/docs/workflows/faq.mdx"), "@site/docs/workflows/faq.mdx", require.resolveWeak("@site/docs/workflows/faq.mdx")],
|
||||
"content---docs-workflows-introduction-9-f-4-275": [() => import(/* webpackChunkName: "content---docs-workflows-introduction-9-f-4-275" */ "@site/docs/workflows/introduction.mdx"), "@site/docs/workflows/introduction.mdx", require.resolveWeak("@site/docs/workflows/introduction.mdx")],
|
||||
"content---docs-workflows-level-1-ultra-lightweightc-5-a-5db": [() => import(/* webpackChunkName: "content---docs-workflows-level-1-ultra-lightweightc-5-a-5db" */ "@site/docs/workflows/level-1-ultra-lightweight.mdx"), "@site/docs/workflows/level-1-ultra-lightweight.mdx", require.resolveWeak("@site/docs/workflows/level-1-ultra-lightweight.mdx")],
|
||||
"content---docs-workflows-level-2-rapid-19-b-095": [() => import(/* webpackChunkName: "content---docs-workflows-level-2-rapid-19-b-095" */ "@site/docs/workflows/level-2-rapid.mdx"), "@site/docs/workflows/level-2-rapid.mdx", require.resolveWeak("@site/docs/workflows/level-2-rapid.mdx")],
|
||||
"content---docs-workflows-level-3-standardbdb-61a": [() => import(/* webpackChunkName: "content---docs-workflows-level-3-standardbdb-61a" */ "@site/docs/workflows/level-3-standard.mdx"), "@site/docs/workflows/level-3-standard.mdx", require.resolveWeak("@site/docs/workflows/level-3-standard.mdx")],
|
||||
"content---docs-workflows-level-4-brainstormd-04-14f": [() => import(/* webpackChunkName: "content---docs-workflows-level-4-brainstormd-04-14f" */ "@site/docs/workflows/level-4-brainstorm.mdx"), "@site/docs/workflows/level-4-brainstorm.mdx", require.resolveWeak("@site/docs/workflows/level-4-brainstorm.mdx")],
|
||||
"content---docs-workflows-level-5-intelligent-186-b05": [() => import(/* webpackChunkName: "content---docs-workflows-level-5-intelligent-186-b05" */ "@site/docs/workflows/level-5-intelligent.mdx"), "@site/docs/workflows/level-5-intelligent.mdx", require.resolveWeak("@site/docs/workflows/level-5-intelligent.mdx")],
|
||||
"plugin---docs-aba-4f5": [() => import(/* webpackChunkName: "plugin---docs-aba-4f5" */ "@generated/docusaurus-plugin-content-docs/default/__plugin.json"), "@generated/docusaurus-plugin-content-docs/default/__plugin.json", require.resolveWeak("@generated/docusaurus-plugin-content-docs/default/__plugin.json")],
|
||||
"plugin---docs-docusaurus-debugb-38-c84": [() => import(/* webpackChunkName: "plugin---docs-docusaurus-debugb-38-c84" */ "@generated/docusaurus-plugin-debug/default/__plugin.json"), "@generated/docusaurus-plugin-debug/default/__plugin.json", require.resolveWeak("@generated/docusaurus-plugin-debug/default/__plugin.json")],};
|
||||
"04db0a2e": [() => import(/* webpackChunkName: "04db0a2e" */ "@site/docs/commands/general/ccw-plan.mdx"), "@site/docs/commands/general/ccw-plan.mdx", require.resolveWeak("@site/docs/commands/general/ccw-plan.mdx")],
|
||||
"05467734": [() => import(/* webpackChunkName: "05467734" */ "@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-2-rapid.mdx"), "@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-2-rapid.mdx", require.resolveWeak("@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-2-rapid.mdx")],
|
||||
"0566a0a8": [() => import(/* webpackChunkName: "0566a0a8" */ "@site/docs/commands/cli/cli-init.mdx"), "@site/docs/commands/cli/cli-init.mdx", require.resolveWeak("@site/docs/commands/cli/cli-init.mdx")],
|
||||
"157db180": [() => import(/* webpackChunkName: "157db180" */ "@site/docs/commands/memory/memory-load.mdx"), "@site/docs/commands/memory/memory-load.mdx", require.resolveWeak("@site/docs/commands/memory/memory-load.mdx")],
|
||||
"17896441": [() => import(/* webpackChunkName: "17896441" */ "@theme/DocItem"), "@theme/DocItem", require.resolveWeak("@theme/DocItem")],
|
||||
"1bac9067": [() => import(/* webpackChunkName: "1bac9067" */ "@site/docs/commands/issue/issue-queue.md"), "@site/docs/commands/issue/issue-queue.md", require.resolveWeak("@site/docs/commands/issue/issue-queue.md")],
|
||||
"1e3006f3": [() => import(/* webpackChunkName: "1e3006f3" */ "@site/docs/commands/issue/issue-discover.md"), "@site/docs/commands/issue/issue-discover.md", require.resolveWeak("@site/docs/commands/issue/issue-discover.md")],
|
||||
"2a5e3eff": [() => import(/* webpackChunkName: "2a5e3eff" */ "@site/i18n/zh/docusaurus-plugin-content-docs/current/faq.mdx"), "@site/i18n/zh/docusaurus-plugin-content-docs/current/faq.mdx", require.resolveWeak("@site/i18n/zh/docusaurus-plugin-content-docs/current/faq.mdx")],
|
||||
"2ecf8b4a": [() => import(/* webpackChunkName: "2ecf8b4a" */ "@site/docs/commands/issue/issue-from-brainstorm.md"), "@site/docs/commands/issue/issue-from-brainstorm.md", require.resolveWeak("@site/docs/commands/issue/issue-from-brainstorm.md")],
|
||||
"3f1fe4a1": [() => import(/* webpackChunkName: "3f1fe4a1" */ "@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-3-standard.mdx"), "@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-3-standard.mdx", require.resolveWeak("@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-3-standard.mdx")],
|
||||
"46f40178": [() => import(/* webpackChunkName: "46f40178" */ "@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/faq.mdx"), "@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/faq.mdx", require.resolveWeak("@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/faq.mdx")],
|
||||
"4ad7db0f": [() => import(/* webpackChunkName: "4ad7db0f" */ "@site/docs/commands/issue/issue-new.md"), "@site/docs/commands/issue/issue-new.md", require.resolveWeak("@site/docs/commands/issue/issue-new.md")],
|
||||
"4cc74730": [() => import(/* webpackChunkName: "4cc74730" */ "@site/docs/commands/memory/memory-docs-full-cli.mdx"), "@site/docs/commands/memory/memory-docs-full-cli.mdx", require.resolveWeak("@site/docs/commands/memory/memory-docs-full-cli.mdx")],
|
||||
"562bb8cb": [() => import(/* webpackChunkName: "562bb8cb" */ "@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-5-intelligent.mdx"), "@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-5-intelligent.mdx", require.resolveWeak("@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-5-intelligent.mdx")],
|
||||
"5c7b2278": [() => import(/* webpackChunkName: "5c7b2278" */ "@site/docs/commands/issue/issue-convert-to-plan.md"), "@site/docs/commands/issue/issue-convert-to-plan.md", require.resolveWeak("@site/docs/commands/issue/issue-convert-to-plan.md")],
|
||||
"5e95c892": [() => import(/* webpackChunkName: "5e95c892" */ "@theme/DocsRoot"), "@theme/DocsRoot", require.resolveWeak("@theme/DocsRoot")],
|
||||
"60eef997": [() => import(/* webpackChunkName: "60eef997" */ "@site/docs/commands/memory/memory-docs-related-cli.mdx"), "@site/docs/commands/memory/memory-docs-related-cli.mdx", require.resolveWeak("@site/docs/commands/memory/memory-docs-related-cli.mdx")],
|
||||
"611877e1": [() => import(/* webpackChunkName: "611877e1" */ "@site/docs/commands/memory/memory-update-related.mdx"), "@site/docs/commands/memory/memory-update-related.mdx", require.resolveWeak("@site/docs/commands/memory/memory-update-related.mdx")],
|
||||
"666bb1bf": [() => import(/* webpackChunkName: "666bb1bf" */ "@site/docs/commands/memory/memory-update-full.mdx"), "@site/docs/commands/memory/memory-update-full.mdx", require.resolveWeak("@site/docs/commands/memory/memory-update-full.mdx")],
|
||||
"6ab014e9": [() => import(/* webpackChunkName: "6ab014e9" */ "@site/i18n/zh/docusaurus-plugin-content-docs/current/index.mdx"), "@site/i18n/zh/docusaurus-plugin-content-docs/current/index.mdx", require.resolveWeak("@site/i18n/zh/docusaurus-plugin-content-docs/current/index.mdx")],
|
||||
"775938bf": [() => import(/* webpackChunkName: "775938bf" */ "@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-4-brainstorm.mdx"), "@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-4-brainstorm.mdx", require.resolveWeak("@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-4-brainstorm.mdx")],
|
||||
"7a1ee27c": [() => import(/* webpackChunkName: "7a1ee27c" */ "@site/docs/commands/memory/memory-compact.mdx"), "@site/docs/commands/memory/memory-compact.mdx", require.resolveWeak("@site/docs/commands/memory/memory-compact.mdx")],
|
||||
"8a7e39ed": [() => import(/* webpackChunkName: "8a7e39ed" */ "@site/i18n/zh/docusaurus-plugin-content-docs/current/overview.mdx"), "@site/i18n/zh/docusaurus-plugin-content-docs/current/overview.mdx", require.resolveWeak("@site/i18n/zh/docusaurus-plugin-content-docs/current/overview.mdx")],
|
||||
"97c6e66a": [() => import(/* webpackChunkName: "97c6e66a" */ "@site/docs/commands/general/ccw-debug.mdx"), "@site/docs/commands/general/ccw-debug.mdx", require.resolveWeak("@site/docs/commands/general/ccw-debug.mdx")],
|
||||
"9cf7cb6b": [() => import(/* webpackChunkName: "9cf7cb6b" */ "@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-1-ultra-lightweight.mdx"), "@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-1-ultra-lightweight.mdx", require.resolveWeak("@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/level-1-ultra-lightweight.mdx")],
|
||||
"a6c3df16": [() => import(/* webpackChunkName: "a6c3df16" */ "@site/docs/commands/issue/issue-plan.md"), "@site/docs/commands/issue/issue-plan.md", require.resolveWeak("@site/docs/commands/issue/issue-plan.md")],
|
||||
"a7bd4aaa": [() => import(/* webpackChunkName: "a7bd4aaa" */ "@theme/DocVersionRoot"), "@theme/DocVersionRoot", require.resolveWeak("@theme/DocVersionRoot")],
|
||||
"a94703ab": [() => import(/* webpackChunkName: "a94703ab" */ "@theme/DocRoot"), "@theme/DocRoot", require.resolveWeak("@theme/DocRoot")],
|
||||
"aba21aa0": [() => import(/* webpackChunkName: "aba21aa0" */ "@generated/docusaurus-plugin-content-docs/default/__plugin.json"), "@generated/docusaurus-plugin-content-docs/default/__plugin.json", require.resolveWeak("@generated/docusaurus-plugin-content-docs/default/__plugin.json")],
|
||||
"b17e4002": [() => import(/* webpackChunkName: "b17e4002" */ "@generated/docusaurus-plugin-content-docs/default/p/docs-zh-d2a.json"), "@generated/docusaurus-plugin-content-docs/default/p/docs-zh-d2a.json", require.resolveWeak("@generated/docusaurus-plugin-content-docs/default/p/docs-zh-d2a.json")],
|
||||
"ccef5d0f": [() => import(/* webpackChunkName: "ccef5d0f" */ "@site/docs/commands/general/ccw-test.mdx"), "@site/docs/commands/general/ccw-test.mdx", require.resolveWeak("@site/docs/commands/general/ccw-test.mdx")],
|
||||
"d550a629": [() => import(/* webpackChunkName: "d550a629" */ "@site/docs/commands/general/ccw-coordinator.mdx"), "@site/docs/commands/general/ccw-coordinator.mdx", require.resolveWeak("@site/docs/commands/general/ccw-coordinator.mdx")],
|
||||
"e5f6eee3": [() => import(/* webpackChunkName: "e5f6eee3" */ "@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/introduction.mdx"), "@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/introduction.mdx", require.resolveWeak("@site/i18n/zh/docusaurus-plugin-content-docs/current/workflows/introduction.mdx")],
|
||||
"f1bf82ec": [() => import(/* webpackChunkName: "f1bf82ec" */ "@site/docs/commands/cli/codex-review.mdx"), "@site/docs/commands/cli/codex-review.mdx", require.resolveWeak("@site/docs/commands/cli/codex-review.mdx")],
|
||||
"f4817052": [() => import(/* webpackChunkName: "f4817052" */ "@site/docs/commands/general/ccw.mdx"), "@site/docs/commands/general/ccw.mdx", require.resolveWeak("@site/docs/commands/general/ccw.mdx")],
|
||||
"f9222419": [() => import(/* webpackChunkName: "f9222419" */ "@site/docs/commands/general/codex-coordinator.mdx"), "@site/docs/commands/general/codex-coordinator.mdx", require.resolveWeak("@site/docs/commands/general/codex-coordinator.mdx")],
|
||||
"fabaf1c8": [() => import(/* webpackChunkName: "fabaf1c8" */ "@site/docs/commands/general/flow-create.mdx"), "@site/docs/commands/general/flow-create.mdx", require.resolveWeak("@site/docs/commands/general/flow-create.mdx")],
|
||||
"fe8e3dcf": [() => import(/* webpackChunkName: "fe8e3dcf" */ "@site/docs/commands/issue/issue-execute.md"), "@site/docs/commands/issue/issue-execute.md", require.resolveWeak("@site/docs/commands/issue/issue-execute.md")],};
|
||||
|
||||
@@ -3,240 +3,205 @@ import ComponentCreator from '@docusaurus/ComponentCreator';
|
||||
|
||||
export default [
|
||||
{
|
||||
path: '/docs/__docusaurus/debug',
|
||||
component: ComponentCreator('/docs/__docusaurus/debug', 'e58'),
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/docs/__docusaurus/debug/config',
|
||||
component: ComponentCreator('/docs/__docusaurus/debug/config', '2ce'),
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/docs/__docusaurus/debug/content',
|
||||
component: ComponentCreator('/docs/__docusaurus/debug/content', '11b'),
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/docs/__docusaurus/debug/globalData',
|
||||
component: ComponentCreator('/docs/__docusaurus/debug/globalData', 'f13'),
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/docs/__docusaurus/debug/metadata',
|
||||
component: ComponentCreator('/docs/__docusaurus/debug/metadata', 'bff'),
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/docs/__docusaurus/debug/registry',
|
||||
component: ComponentCreator('/docs/__docusaurus/debug/registry', '830'),
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/docs/__docusaurus/debug/routes',
|
||||
component: ComponentCreator('/docs/__docusaurus/debug/routes', '13e'),
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/docs/',
|
||||
component: ComponentCreator('/docs/', 'a3f'),
|
||||
path: '/docs/zh/',
|
||||
component: ComponentCreator('/docs/zh/', 'b34'),
|
||||
routes: [
|
||||
{
|
||||
path: '/docs/',
|
||||
component: ComponentCreator('/docs/', 'fa7'),
|
||||
path: '/docs/zh/',
|
||||
component: ComponentCreator('/docs/zh/', 'a8e'),
|
||||
routes: [
|
||||
{
|
||||
path: '/docs/',
|
||||
component: ComponentCreator('/docs/', '294'),
|
||||
path: '/docs/zh/',
|
||||
component: ComponentCreator('/docs/zh/', '632'),
|
||||
routes: [
|
||||
{
|
||||
path: '/docs/commands/cli/cli-init',
|
||||
component: ComponentCreator('/docs/commands/cli/cli-init', '159'),
|
||||
path: '/docs/zh/commands/cli/cli-init',
|
||||
component: ComponentCreator('/docs/zh/commands/cli/cli-init', 'fe3'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/cli/codex-review',
|
||||
component: ComponentCreator('/docs/commands/cli/codex-review', 'c66'),
|
||||
path: '/docs/zh/commands/cli/codex-review',
|
||||
component: ComponentCreator('/docs/zh/commands/cli/codex-review', 'e65'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/general/ccw',
|
||||
component: ComponentCreator('/docs/commands/general/ccw', '3c1'),
|
||||
path: '/docs/zh/commands/general/ccw',
|
||||
component: ComponentCreator('/docs/zh/commands/general/ccw', '83a'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/general/ccw-coordinator',
|
||||
component: ComponentCreator('/docs/commands/general/ccw-coordinator', '3b4'),
|
||||
path: '/docs/zh/commands/general/ccw-coordinator',
|
||||
component: ComponentCreator('/docs/zh/commands/general/ccw-coordinator', 'f35'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/general/ccw-debug',
|
||||
component: ComponentCreator('/docs/commands/general/ccw-debug', 'e0c'),
|
||||
path: '/docs/zh/commands/general/ccw-debug',
|
||||
component: ComponentCreator('/docs/zh/commands/general/ccw-debug', 'b0a'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/general/ccw-plan',
|
||||
component: ComponentCreator('/docs/commands/general/ccw-plan', '9ae'),
|
||||
path: '/docs/zh/commands/general/ccw-plan',
|
||||
component: ComponentCreator('/docs/zh/commands/general/ccw-plan', '39d'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/general/ccw-test',
|
||||
component: ComponentCreator('/docs/commands/general/ccw-test', 'e6f'),
|
||||
path: '/docs/zh/commands/general/ccw-test',
|
||||
component: ComponentCreator('/docs/zh/commands/general/ccw-test', '765'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/general/codex-coordinator',
|
||||
component: ComponentCreator('/docs/commands/general/codex-coordinator', 'e7d'),
|
||||
path: '/docs/zh/commands/general/codex-coordinator',
|
||||
component: ComponentCreator('/docs/zh/commands/general/codex-coordinator', '486'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/general/flow-create',
|
||||
component: ComponentCreator('/docs/commands/general/flow-create', '507'),
|
||||
path: '/docs/zh/commands/general/flow-create',
|
||||
component: ComponentCreator('/docs/zh/commands/general/flow-create', 'd53'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/issue/issue-convert-to-plan',
|
||||
component: ComponentCreator('/docs/commands/issue/issue-convert-to-plan', 'a36'),
|
||||
path: '/docs/zh/commands/issue/issue-convert-to-plan',
|
||||
component: ComponentCreator('/docs/zh/commands/issue/issue-convert-to-plan', '0df'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/issue/issue-discover',
|
||||
component: ComponentCreator('/docs/commands/issue/issue-discover', '5ae'),
|
||||
path: '/docs/zh/commands/issue/issue-discover',
|
||||
component: ComponentCreator('/docs/zh/commands/issue/issue-discover', '9b4'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/issue/issue-execute',
|
||||
component: ComponentCreator('/docs/commands/issue/issue-execute', '20b'),
|
||||
path: '/docs/zh/commands/issue/issue-execute',
|
||||
component: ComponentCreator('/docs/zh/commands/issue/issue-execute', 'cfd'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/issue/issue-from-brainstorm',
|
||||
component: ComponentCreator('/docs/commands/issue/issue-from-brainstorm', '10c'),
|
||||
path: '/docs/zh/commands/issue/issue-from-brainstorm',
|
||||
component: ComponentCreator('/docs/zh/commands/issue/issue-from-brainstorm', 'd2f'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/issue/issue-new',
|
||||
component: ComponentCreator('/docs/commands/issue/issue-new', 'abb'),
|
||||
path: '/docs/zh/commands/issue/issue-new',
|
||||
component: ComponentCreator('/docs/zh/commands/issue/issue-new', '7f9'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/issue/issue-plan',
|
||||
component: ComponentCreator('/docs/commands/issue/issue-plan', '57f'),
|
||||
path: '/docs/zh/commands/issue/issue-plan',
|
||||
component: ComponentCreator('/docs/zh/commands/issue/issue-plan', 'ed4'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/issue/issue-queue',
|
||||
component: ComponentCreator('/docs/commands/issue/issue-queue', '316'),
|
||||
path: '/docs/zh/commands/issue/issue-queue',
|
||||
component: ComponentCreator('/docs/zh/commands/issue/issue-queue', 'a4b'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/memory/memory-compact',
|
||||
component: ComponentCreator('/docs/commands/memory/memory-compact', 'fbd'),
|
||||
path: '/docs/zh/commands/memory/memory-compact',
|
||||
component: ComponentCreator('/docs/zh/commands/memory/memory-compact', '8dc'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/memory/memory-docs-full-cli',
|
||||
component: ComponentCreator('/docs/commands/memory/memory-docs-full-cli', '8b8'),
|
||||
path: '/docs/zh/commands/memory/memory-docs-full-cli',
|
||||
component: ComponentCreator('/docs/zh/commands/memory/memory-docs-full-cli', '1a7'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/memory/memory-docs-related-cli',
|
||||
component: ComponentCreator('/docs/commands/memory/memory-docs-related-cli', '707'),
|
||||
path: '/docs/zh/commands/memory/memory-docs-related-cli',
|
||||
component: ComponentCreator('/docs/zh/commands/memory/memory-docs-related-cli', 'f28'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/memory/memory-load',
|
||||
component: ComponentCreator('/docs/commands/memory/memory-load', '1db'),
|
||||
path: '/docs/zh/commands/memory/memory-load',
|
||||
component: ComponentCreator('/docs/zh/commands/memory/memory-load', 'aee'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/memory/memory-update-full',
|
||||
component: ComponentCreator('/docs/commands/memory/memory-update-full', '3fa'),
|
||||
path: '/docs/zh/commands/memory/memory-update-full',
|
||||
component: ComponentCreator('/docs/zh/commands/memory/memory-update-full', '2a1'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/commands/memory/memory-update-related',
|
||||
component: ComponentCreator('/docs/commands/memory/memory-update-related', 'c50'),
|
||||
path: '/docs/zh/commands/memory/memory-update-related',
|
||||
component: ComponentCreator('/docs/zh/commands/memory/memory-update-related', '991'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/faq',
|
||||
component: ComponentCreator('/docs/faq', '296'),
|
||||
path: '/docs/zh/faq',
|
||||
component: ComponentCreator('/docs/zh/faq', 'd6c'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/overview',
|
||||
component: ComponentCreator('/docs/overview', 'f90'),
|
||||
path: '/docs/zh/overview',
|
||||
component: ComponentCreator('/docs/zh/overview', '2d1'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/workflows/faq',
|
||||
component: ComponentCreator('/docs/workflows/faq', '58c'),
|
||||
path: '/docs/zh/workflows/faq',
|
||||
component: ComponentCreator('/docs/zh/workflows/faq', '319'),
|
||||
exact: true
|
||||
},
|
||||
{
|
||||
path: '/docs/workflows/introduction',
|
||||
component: ComponentCreator('/docs/workflows/introduction', '702'),
|
||||
path: '/docs/zh/workflows/introduction',
|
||||
component: ComponentCreator('/docs/zh/workflows/introduction', 'dc8'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/workflows/level-1-ultra-lightweight',
|
||||
component: ComponentCreator('/docs/workflows/level-1-ultra-lightweight', 'b4b'),
|
||||
path: '/docs/zh/workflows/level-1-ultra-lightweight',
|
||||
component: ComponentCreator('/docs/zh/workflows/level-1-ultra-lightweight', '4d3'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/workflows/level-2-rapid',
|
||||
component: ComponentCreator('/docs/workflows/level-2-rapid', 'fe1'),
|
||||
path: '/docs/zh/workflows/level-2-rapid',
|
||||
component: ComponentCreator('/docs/zh/workflows/level-2-rapid', 'e2a'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/workflows/level-3-standard',
|
||||
component: ComponentCreator('/docs/workflows/level-3-standard', '65f'),
|
||||
path: '/docs/zh/workflows/level-3-standard',
|
||||
component: ComponentCreator('/docs/zh/workflows/level-3-standard', '936'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/workflows/level-4-brainstorm',
|
||||
component: ComponentCreator('/docs/workflows/level-4-brainstorm', 'fae'),
|
||||
path: '/docs/zh/workflows/level-4-brainstorm',
|
||||
component: ComponentCreator('/docs/zh/workflows/level-4-brainstorm', '87d'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/workflows/level-5-intelligent',
|
||||
component: ComponentCreator('/docs/workflows/level-5-intelligent', 'fa9'),
|
||||
path: '/docs/zh/workflows/level-5-intelligent',
|
||||
component: ComponentCreator('/docs/zh/workflows/level-5-intelligent', 'b09'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
},
|
||||
{
|
||||
path: '/docs/',
|
||||
component: ComponentCreator('/docs/', '6df'),
|
||||
path: '/docs/zh/',
|
||||
component: ComponentCreator('/docs/zh/', '0e3'),
|
||||
exact: true,
|
||||
sidebar: "docs"
|
||||
}
|
||||
|
||||
@@ -1,186 +1,143 @@
|
||||
{
|
||||
"/docs/__docusaurus/debug-e58": {
|
||||
"__comp": "__comp---theme-debug-config-23-a-2ff",
|
||||
"/docs/zh/-b34": {
|
||||
"__comp": "5e95c892",
|
||||
"__context": {
|
||||
"plugin": "plugin---docs-docusaurus-debugb-38-c84"
|
||||
"plugin": "aba21aa0"
|
||||
}
|
||||
},
|
||||
"/docs/__docusaurus/debug/config-2ce": {
|
||||
"__comp": "__comp---theme-debug-config-23-a-2ff",
|
||||
"__context": {
|
||||
"plugin": "plugin---docs-docusaurus-debugb-38-c84"
|
||||
}
|
||||
"/docs/zh/-a8e": {
|
||||
"__comp": "a7bd4aaa",
|
||||
"__props": "b17e4002"
|
||||
},
|
||||
"/docs/__docusaurus/debug/content-11b": {
|
||||
"__comp": "__comp---theme-debug-contentba-8-ce7",
|
||||
"__context": {
|
||||
"plugin": "plugin---docs-docusaurus-debugb-38-c84"
|
||||
},
|
||||
"__props": "__props---docs-docusaurus-debug-content-344-8d5"
|
||||
"/docs/zh/-632": {
|
||||
"__comp": "a94703ab"
|
||||
},
|
||||
"/docs/__docusaurus/debug/globalData-f13": {
|
||||
"__comp": "__comp---theme-debug-global-dataede-0fa",
|
||||
"__context": {
|
||||
"plugin": "plugin---docs-docusaurus-debugb-38-c84"
|
||||
}
|
||||
"/docs/zh/commands/cli/cli-init-fe3": {
|
||||
"__comp": "17896441",
|
||||
"content": "0566a0a8"
|
||||
},
|
||||
"/docs/__docusaurus/debug/metadata-bff": {
|
||||
"__comp": "__comp---theme-debug-site-metadata-68-e-3d4",
|
||||
"__context": {
|
||||
"plugin": "plugin---docs-docusaurus-debugb-38-c84"
|
||||
}
|
||||
"/docs/zh/commands/cli/codex-review-e65": {
|
||||
"__comp": "17896441",
|
||||
"content": "f1bf82ec"
|
||||
},
|
||||
"/docs/__docusaurus/debug/registry-830": {
|
||||
"__comp": "__comp---theme-debug-registry-679-501",
|
||||
"__context": {
|
||||
"plugin": "plugin---docs-docusaurus-debugb-38-c84"
|
||||
}
|
||||
"/docs/zh/commands/general/ccw-83a": {
|
||||
"__comp": "17896441",
|
||||
"content": "f4817052"
|
||||
},
|
||||
"/docs/__docusaurus/debug/routes-13e": {
|
||||
"__comp": "__comp---theme-debug-routes-946-699",
|
||||
"__context": {
|
||||
"plugin": "plugin---docs-docusaurus-debugb-38-c84"
|
||||
}
|
||||
"/docs/zh/commands/general/ccw-coordinator-f35": {
|
||||
"__comp": "17896441",
|
||||
"content": "d550a629"
|
||||
},
|
||||
"/docs/-a3f": {
|
||||
"__comp": "__comp---theme-docs-root-5-e-9-0b6",
|
||||
"__context": {
|
||||
"plugin": "plugin---docs-aba-4f5"
|
||||
}
|
||||
"/docs/zh/commands/general/ccw-debug-b0a": {
|
||||
"__comp": "17896441",
|
||||
"content": "97c6e66a"
|
||||
},
|
||||
"/docs/-fa7": {
|
||||
"__comp": "__comp---theme-doc-version-roota-7-b-5de",
|
||||
"__props": "__props---docs-11-b-f70"
|
||||
"/docs/zh/commands/general/ccw-plan-39d": {
|
||||
"__comp": "17896441",
|
||||
"content": "04db0a2e"
|
||||
},
|
||||
"/docs/-294": {
|
||||
"__comp": "__comp---theme-doc-roota-94-67a"
|
||||
"/docs/zh/commands/general/ccw-test-765": {
|
||||
"__comp": "17896441",
|
||||
"content": "ccef5d0f"
|
||||
},
|
||||
"/docs/commands/cli/cli-init-159": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-cli-cli-init-056-ce1"
|
||||
"/docs/zh/commands/general/codex-coordinator-486": {
|
||||
"__comp": "17896441",
|
||||
"content": "f9222419"
|
||||
},
|
||||
"/docs/commands/cli/codex-review-c66": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-cli-codex-reviewf-1-b-55f"
|
||||
"/docs/zh/commands/general/flow-create-d53": {
|
||||
"__comp": "17896441",
|
||||
"content": "fabaf1c8"
|
||||
},
|
||||
"/docs/commands/general/ccw-3c1": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-general-ccwf-48-8c4"
|
||||
"/docs/zh/commands/issue/issue-convert-to-plan-0df": {
|
||||
"__comp": "17896441",
|
||||
"content": "5c7b2278"
|
||||
},
|
||||
"/docs/commands/general/ccw-coordinator-3b4": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-general-ccw-coordinatord-55-c6b"
|
||||
"/docs/zh/commands/issue/issue-discover-9b4": {
|
||||
"__comp": "17896441",
|
||||
"content": "1e3006f3"
|
||||
},
|
||||
"/docs/commands/general/ccw-debug-e0c": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-general-ccw-debug-97-c-a72"
|
||||
"/docs/zh/commands/issue/issue-execute-cfd": {
|
||||
"__comp": "17896441",
|
||||
"content": "fe8e3dcf"
|
||||
},
|
||||
"/docs/commands/general/ccw-plan-9ae": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-general-ccw-plan-04-d-fe0"
|
||||
"/docs/zh/commands/issue/issue-from-brainstorm-d2f": {
|
||||
"__comp": "17896441",
|
||||
"content": "2ecf8b4a"
|
||||
},
|
||||
"/docs/commands/general/ccw-test-e6f": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-general-ccw-testcce-912"
|
||||
"/docs/zh/commands/issue/issue-new-7f9": {
|
||||
"__comp": "17896441",
|
||||
"content": "4ad7db0f"
|
||||
},
|
||||
"/docs/commands/general/codex-coordinator-e7d": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-general-codex-coordinatorf-92-1dc"
|
||||
"/docs/zh/commands/issue/issue-plan-ed4": {
|
||||
"__comp": "17896441",
|
||||
"content": "a6c3df16"
|
||||
},
|
||||
"/docs/commands/general/flow-create-507": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-general-flow-createfab-98a"
|
||||
"/docs/zh/commands/issue/issue-queue-a4b": {
|
||||
"__comp": "17896441",
|
||||
"content": "1bac9067"
|
||||
},
|
||||
"/docs/commands/issue/issue-convert-to-plan-a36": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-issue-issue-convert-to-plan-5-c-7-184"
|
||||
"/docs/zh/commands/memory/memory-compact-8dc": {
|
||||
"__comp": "17896441",
|
||||
"content": "7a1ee27c"
|
||||
},
|
||||
"/docs/commands/issue/issue-discover-5ae": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-issue-issue-discover-1-e-3-569"
|
||||
"/docs/zh/commands/memory/memory-docs-full-cli-1a7": {
|
||||
"__comp": "17896441",
|
||||
"content": "4cc74730"
|
||||
},
|
||||
"/docs/commands/issue/issue-execute-20b": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-issue-issue-executefe-8-c03"
|
||||
"/docs/zh/commands/memory/memory-docs-related-cli-f28": {
|
||||
"__comp": "17896441",
|
||||
"content": "60eef997"
|
||||
},
|
||||
"/docs/commands/issue/issue-from-brainstorm-10c": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-issue-issue-from-brainstorm-2-ec-eeb"
|
||||
"/docs/zh/commands/memory/memory-load-aee": {
|
||||
"__comp": "17896441",
|
||||
"content": "157db180"
|
||||
},
|
||||
"/docs/commands/issue/issue-new-abb": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-issue-issue-new-4-ad-3f0"
|
||||
"/docs/zh/commands/memory/memory-update-full-2a1": {
|
||||
"__comp": "17896441",
|
||||
"content": "666bb1bf"
|
||||
},
|
||||
"/docs/commands/issue/issue-plan-57f": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-issue-issue-plana-6-c-fbd"
|
||||
"/docs/zh/commands/memory/memory-update-related-991": {
|
||||
"__comp": "17896441",
|
||||
"content": "611877e1"
|
||||
},
|
||||
"/docs/commands/issue/issue-queue-316": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-issue-issue-queue-1-ba-55f"
|
||||
"/docs/zh/faq-d6c": {
|
||||
"__comp": "17896441",
|
||||
"content": "2a5e3eff"
|
||||
},
|
||||
"/docs/commands/memory/memory-compact-fbd": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-memory-memory-compact-7-a-1-41c"
|
||||
"/docs/zh/overview-2d1": {
|
||||
"__comp": "17896441",
|
||||
"content": "8a7e39ed"
|
||||
},
|
||||
"/docs/commands/memory/memory-docs-full-cli-8b8": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-memory-memory-docs-full-cli-4-cc-96f"
|
||||
"/docs/zh/workflows/faq-319": {
|
||||
"__comp": "17896441",
|
||||
"content": "46f40178"
|
||||
},
|
||||
"/docs/commands/memory/memory-docs-related-cli-707": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-memory-memory-docs-related-cli-60-e-dd0"
|
||||
"/docs/zh/workflows/introduction-dc8": {
|
||||
"__comp": "17896441",
|
||||
"content": "e5f6eee3"
|
||||
},
|
||||
"/docs/commands/memory/memory-load-1db": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-memory-memory-load-157-952"
|
||||
"/docs/zh/workflows/level-1-ultra-lightweight-4d3": {
|
||||
"__comp": "17896441",
|
||||
"content": "9cf7cb6b"
|
||||
},
|
||||
"/docs/commands/memory/memory-update-full-3fa": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-memory-memory-update-full-666-002"
|
||||
"/docs/zh/workflows/level-2-rapid-e2a": {
|
||||
"__comp": "17896441",
|
||||
"content": "05467734"
|
||||
},
|
||||
"/docs/commands/memory/memory-update-related-c50": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-commands-memory-memory-update-related-611-8d3"
|
||||
"/docs/zh/workflows/level-3-standard-936": {
|
||||
"__comp": "17896441",
|
||||
"content": "3f1fe4a1"
|
||||
},
|
||||
"/docs/faq-296": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-faqea-3-888"
|
||||
"/docs/zh/workflows/level-4-brainstorm-87d": {
|
||||
"__comp": "17896441",
|
||||
"content": "775938bf"
|
||||
},
|
||||
"/docs/overview-f90": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-overview-188-429"
|
||||
"/docs/zh/workflows/level-5-intelligent-b09": {
|
||||
"__comp": "17896441",
|
||||
"content": "562bb8cb"
|
||||
},
|
||||
"/docs/workflows/faq-58c": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-workflows-faqbcf-045"
|
||||
},
|
||||
"/docs/workflows/introduction-702": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-workflows-introduction-9-f-4-275"
|
||||
},
|
||||
"/docs/workflows/level-1-ultra-lightweight-b4b": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-workflows-level-1-ultra-lightweightc-5-a-5db"
|
||||
},
|
||||
"/docs/workflows/level-2-rapid-fe1": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-workflows-level-2-rapid-19-b-095"
|
||||
},
|
||||
"/docs/workflows/level-3-standard-65f": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-workflows-level-3-standardbdb-61a"
|
||||
},
|
||||
"/docs/workflows/level-4-brainstorm-fae": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-workflows-level-4-brainstormd-04-14f"
|
||||
},
|
||||
"/docs/workflows/level-5-intelligent-fa9": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-workflows-level-5-intelligent-186-b05"
|
||||
},
|
||||
"/docs/-6df": {
|
||||
"__comp": "__comp---theme-doc-item-178-a40",
|
||||
"content": "content---docs-4-ed-831"
|
||||
"/docs/zh/-0e3": {
|
||||
"__comp": "17896441",
|
||||
"content": "6ab014e9"
|
||||
}
|
||||
}
|
||||
@@ -12,9 +12,9 @@
|
||||
"name": "@docusaurus/plugin-content-pages",
|
||||
"version": "3.9.2"
|
||||
},
|
||||
"docusaurus-plugin-debug": {
|
||||
"docusaurus-plugin-sitemap": {
|
||||
"type": "package",
|
||||
"name": "@docusaurus/plugin-debug",
|
||||
"name": "@docusaurus/plugin-sitemap",
|
||||
"version": "3.9.2"
|
||||
},
|
||||
"docusaurus-plugin-svgr": {
|
||||
|
||||
@@ -56,6 +56,7 @@ interface NavGroupDef {
|
||||
icon: React.ElementType;
|
||||
badge?: number | string;
|
||||
badgeVariant?: 'default' | 'success' | 'warning' | 'info';
|
||||
end?: boolean;
|
||||
}>;
|
||||
}
|
||||
|
||||
@@ -110,7 +111,7 @@ const navGroupDefinitions: NavGroupDef[] = [
|
||||
items: [
|
||||
{ path: '/settings/codexlens', labelKey: 'navigation.main.codexlens', icon: Sparkles },
|
||||
{ path: '/api-settings', labelKey: 'navigation.main.apiSettings', icon: Server },
|
||||
{ path: '/settings', labelKey: 'navigation.main.settings', icon: Settings },
|
||||
{ path: '/settings', labelKey: 'navigation.main.settings', icon: Settings, end: true },
|
||||
{ path: '/help', labelKey: 'navigation.main.help', icon: HelpCircle },
|
||||
],
|
||||
},
|
||||
|
||||
@@ -115,6 +115,7 @@ export function CcwToolsMcpCard({
|
||||
mutationFn: installCcwMcp,
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: mcpServersKeys.all });
|
||||
queryClient.invalidateQueries({ queryKey: ['ccwMcpConfig'] });
|
||||
onInstall();
|
||||
},
|
||||
});
|
||||
@@ -123,8 +124,12 @@ export function CcwToolsMcpCard({
|
||||
mutationFn: uninstallCcwMcp,
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: mcpServersKeys.all });
|
||||
queryClient.invalidateQueries({ queryKey: ['ccwMcpConfig'] });
|
||||
onInstall();
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error('Failed to uninstall CCW MCP:', error);
|
||||
},
|
||||
});
|
||||
|
||||
const updateConfigMutation = useMutation({
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
createMcpServer,
|
||||
updateMcpServer,
|
||||
fetchMcpServers,
|
||||
saveMcpTemplate,
|
||||
type McpServer,
|
||||
type McpProjectConfigType,
|
||||
} from '@/lib/api';
|
||||
@@ -95,6 +96,7 @@ export function McpServerDialog({
|
||||
const [argsInput, setArgsInput] = useState('');
|
||||
const [envInput, setEnvInput] = useState('');
|
||||
const [configType, setConfigType] = useState<McpConfigType>('mcp-json');
|
||||
const [saveAsTemplate, setSaveAsTemplate] = useState(false);
|
||||
const projectConfigType: McpProjectConfigType = configType === 'claude-json' ? 'claude' : 'mcp';
|
||||
|
||||
// Initialize form from server prop (edit mode)
|
||||
@@ -128,6 +130,7 @@ export function McpServerDialog({
|
||||
setEnvInput('');
|
||||
}
|
||||
setSelectedTemplate('');
|
||||
setSaveAsTemplate(false);
|
||||
setErrors({});
|
||||
}, [server, mode, open]);
|
||||
|
||||
@@ -261,6 +264,23 @@ export function McpServerDialog({
|
||||
return;
|
||||
}
|
||||
|
||||
// Save as template if checked
|
||||
if (saveAsTemplate) {
|
||||
try {
|
||||
await saveMcpTemplate({
|
||||
name: formData.name,
|
||||
category: 'custom',
|
||||
serverConfig: {
|
||||
command: formData.command,
|
||||
args: formData.args.length > 0 ? formData.args : undefined,
|
||||
env: Object.keys(formData.env).length > 0 ? formData.env : undefined,
|
||||
},
|
||||
});
|
||||
} catch {
|
||||
// Template save failure should not block server creation
|
||||
}
|
||||
}
|
||||
|
||||
if (mode === 'add') {
|
||||
createMutation.mutate({
|
||||
server: {
|
||||
@@ -501,6 +521,20 @@ export function McpServerDialog({
|
||||
{formatMessage({ id: 'mcp.dialog.form.enabled' })}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{/* Save as Template */}
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="save-as-template"
|
||||
checked={saveAsTemplate}
|
||||
onChange={(e) => setSaveAsTemplate(e.target.checked)}
|
||||
className="w-4 h-4"
|
||||
/>
|
||||
<label htmlFor="save-as-template" className="text-sm font-medium text-foreground cursor-pointer">
|
||||
{formatMessage({ id: 'mcp.templates.actions.saveAsTemplate' })}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
|
||||
@@ -58,17 +58,18 @@ import type { McpTemplate } from '@/types/store';
|
||||
export interface McpTemplatesSectionProps {
|
||||
/** Callback when template is installed (opens McpServerDialog) */
|
||||
onInstallTemplate?: (template: McpTemplate) => void;
|
||||
/** Callback when current server should be saved as template */
|
||||
onSaveAsTemplate?: (serverName: string, config: { command: string; args: string[]; env?: Record<string, string> }) => void;
|
||||
/** Callback when saving a new template */
|
||||
onSaveAsTemplate?: (name: string, category: string, description: string, serverConfig: { command: string; args: string[]; env: Record<string, string> }) => void;
|
||||
}
|
||||
|
||||
interface TemplateSaveDialogProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onSave: (name: string, category: string, description: string) => void;
|
||||
onSave: (name: string, category: string, description: string, serverConfig: { command: string; args: string[]; env: Record<string, string> }) => void;
|
||||
defaultName?: string;
|
||||
defaultCommand?: string;
|
||||
defaultArgs?: string[];
|
||||
defaultEnv?: Record<string, string>;
|
||||
}
|
||||
|
||||
interface TemplateCardProps {
|
||||
@@ -181,18 +182,26 @@ function TemplateCard({ template, onInstall, onDelete, isInstalling, isDeleting
|
||||
/**
|
||||
* Template Save Dialog - Save current server configuration as template
|
||||
*/
|
||||
function TemplateSaveDialog({
|
||||
export function TemplateSaveDialog({
|
||||
open,
|
||||
onClose,
|
||||
onSave,
|
||||
defaultName = '',
|
||||
defaultCommand = '',
|
||||
defaultArgs = [],
|
||||
defaultEnv = {},
|
||||
}: TemplateSaveDialogProps) {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const [name, setName] = useState(defaultName);
|
||||
const [category, setCategory] = useState('');
|
||||
const [description, setDescription] = useState('');
|
||||
const [errors, setErrors] = useState<{ name?: string }>({});
|
||||
const [command, setCommand] = useState(defaultCommand);
|
||||
const [argsInput, setArgsInput] = useState(defaultArgs.join(', '));
|
||||
const [envInput, setEnvInput] = useState(
|
||||
Object.entries(defaultEnv).map(([k, v]) => `${k}=${v}`).join('\n')
|
||||
);
|
||||
const [errors, setErrors] = useState<{ name?: string; command?: string }>({});
|
||||
|
||||
// Reset form when dialog opens
|
||||
useEffect(() => {
|
||||
@@ -200,25 +209,52 @@ function TemplateSaveDialog({
|
||||
setName(defaultName || '');
|
||||
setCategory('');
|
||||
setDescription('');
|
||||
setCommand(defaultCommand || '');
|
||||
setArgsInput((defaultArgs || []).join(', '));
|
||||
setEnvInput(
|
||||
Object.entries(defaultEnv || {}).map(([k, v]) => `${k}=${v}`).join('\n')
|
||||
);
|
||||
setErrors({});
|
||||
}
|
||||
}, [open, defaultName]);
|
||||
}, [open, defaultName, defaultCommand, defaultArgs, defaultEnv]);
|
||||
|
||||
const handleSave = () => {
|
||||
const newErrors: { name?: string; command?: string } = {};
|
||||
if (!name.trim()) {
|
||||
setErrors({ name: formatMessage({ id: 'mcp.templates.saveDialog.validation.nameRequired' }) });
|
||||
newErrors.name = formatMessage({ id: 'mcp.templates.saveDialog.validation.nameRequired' });
|
||||
}
|
||||
if (!command.trim()) {
|
||||
newErrors.command = formatMessage({ id: 'mcp.dialog.validation.commandRequired' });
|
||||
}
|
||||
if (Object.keys(newErrors).length > 0) {
|
||||
setErrors(newErrors);
|
||||
return;
|
||||
}
|
||||
onSave(name.trim(), category.trim(), description.trim());
|
||||
setName('');
|
||||
setCategory('');
|
||||
setDescription('');
|
||||
setErrors({});
|
||||
|
||||
const args = argsInput
|
||||
.split(',')
|
||||
.map((a) => a.trim())
|
||||
.filter((a) => a.length > 0);
|
||||
|
||||
const env: Record<string, string> = {};
|
||||
for (const line of envInput.split('\n')) {
|
||||
const trimmed = line.trim();
|
||||
if (trimmed && trimmed.includes('=')) {
|
||||
const [key, ...valParts] = trimmed.split('=');
|
||||
if (key) env[key.trim()] = valParts.join('=').trim();
|
||||
}
|
||||
}
|
||||
|
||||
onSave(name.trim(), category.trim(), description.trim(), {
|
||||
command: command.trim(),
|
||||
args,
|
||||
env,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onClose}>
|
||||
<DialogContent className="max-w-md">
|
||||
<DialogContent className="max-w-md max-h-[85vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
{formatMessage({ id: 'mcp.templates.saveDialog.title' })}
|
||||
@@ -235,7 +271,7 @@ function TemplateSaveDialog({
|
||||
value={name}
|
||||
onChange={(e) => {
|
||||
setName(e.target.value);
|
||||
if (errors.name) setErrors({});
|
||||
if (errors.name) setErrors((prev) => ({ ...prev, name: undefined }));
|
||||
}}
|
||||
placeholder={formatMessage({ id: 'mcp.templates.saveDialog.namePlaceholder' })}
|
||||
error={!!errors.name}
|
||||
@@ -245,6 +281,54 @@ function TemplateSaveDialog({
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Command */}
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-foreground">
|
||||
{formatMessage({ id: 'mcp.dialog.form.command' })}
|
||||
<span className="text-destructive ml-1">*</span>
|
||||
</label>
|
||||
<Input
|
||||
value={command}
|
||||
onChange={(e) => {
|
||||
setCommand(e.target.value);
|
||||
if (errors.command) setErrors((prev) => ({ ...prev, command: undefined }));
|
||||
}}
|
||||
placeholder={formatMessage({ id: 'mcp.dialog.form.commandPlaceholder' })}
|
||||
error={!!errors.command}
|
||||
/>
|
||||
{errors.command && (
|
||||
<p className="text-sm text-destructive">{errors.command}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Args */}
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-foreground">
|
||||
{formatMessage({ id: 'mcp.dialog.form.args' })}
|
||||
</label>
|
||||
<Input
|
||||
value={argsInput}
|
||||
onChange={(e) => setArgsInput(e.target.value)}
|
||||
placeholder={formatMessage({ id: 'mcp.dialog.form.argsPlaceholder' })}
|
||||
/>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{formatMessage({ id: 'mcp.dialog.form.argsHint' })}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Environment Variables */}
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-foreground">
|
||||
{formatMessage({ id: 'mcp.dialog.form.env' })}
|
||||
</label>
|
||||
<textarea
|
||||
value={envInput}
|
||||
onChange={(e) => setEnvInput(e.target.value)}
|
||||
placeholder={formatMessage({ id: 'mcp.dialog.form.envPlaceholder' })}
|
||||
className="flex min-h-[60px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm font-mono ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Category */}
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-foreground">
|
||||
@@ -273,7 +357,7 @@ function TemplateSaveDialog({
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
placeholder={formatMessage({ id: 'mcp.templates.saveDialog.descriptionPlaceholder' })}
|
||||
className="flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
className="flex min-h-[60px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -374,8 +458,8 @@ export function McpTemplatesSection({ onInstallTemplate, onSaveAsTemplate }: Mcp
|
||||
}
|
||||
}, [templateToDelete, deleteMutation]);
|
||||
|
||||
const handleSaveTemplate = useCallback((_name: string, _category: string, _description: string) => {
|
||||
onSaveAsTemplate?.(_name, { command: '', args: [] });
|
||||
const handleSaveTemplate = useCallback((_name: string, _category: string, _description: string, _serverConfig: { command: string; args: string[]; env: Record<string, string> }) => {
|
||||
onSaveAsTemplate?.(_name, _category, _description, _serverConfig);
|
||||
setSaveDialogOpen(false);
|
||||
}, [onSaveAsTemplate]);
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ export interface NavItem {
|
||||
icon: React.ElementType;
|
||||
badge?: number | string;
|
||||
badgeVariant?: 'default' | 'success' | 'warning' | 'info';
|
||||
/** When true, only exact path match activates this item (no prefix matching) */
|
||||
end?: boolean;
|
||||
}
|
||||
|
||||
export interface NavGroupProps {
|
||||
@@ -54,10 +56,10 @@ export function NavGroup({
|
||||
{items.map((item) => {
|
||||
const ItemIcon = item.icon;
|
||||
const [basePath] = item.path.split('?');
|
||||
// More precise matching: exact match or basePath followed by '/' to avoid parent/child conflicts
|
||||
const isActive =
|
||||
location.pathname === basePath ||
|
||||
(basePath !== '/' && location.pathname.startsWith(basePath + '/'));
|
||||
const isActive = item.end
|
||||
? location.pathname === basePath
|
||||
: location.pathname === basePath ||
|
||||
(basePath !== '/' && location.pathname.startsWith(basePath + '/'));
|
||||
|
||||
return (
|
||||
<NavLink
|
||||
@@ -94,10 +96,10 @@ export function NavGroup({
|
||||
{items.map((item) => {
|
||||
const ItemIcon = item.icon;
|
||||
const [basePath, searchParams] = item.path.split('?');
|
||||
// More precise matching: exact match or basePath followed by '/' to avoid parent/child conflicts
|
||||
const isActive =
|
||||
location.pathname === basePath ||
|
||||
(basePath !== '/' && location.pathname.startsWith(basePath + '/'));
|
||||
const isActive = item.end
|
||||
? location.pathname === basePath
|
||||
: location.pathname === basePath ||
|
||||
(basePath !== '/' && location.pathname.startsWith(basePath + '/'));
|
||||
const isQueryParamActive =
|
||||
searchParams && location.search.includes(searchParams);
|
||||
|
||||
|
||||
406
ccw/frontend/src/components/shared/SkillCreateDialog.tsx
Normal file
406
ccw/frontend/src/components/shared/SkillCreateDialog.tsx
Normal file
@@ -0,0 +1,406 @@
|
||||
// ========================================
|
||||
// Skill Create Dialog Component
|
||||
// ========================================
|
||||
// Modal dialog for creating/importing skills with two modes:
|
||||
// - Import: import existing skill folder
|
||||
// - CLI Generate: AI-generated skill from description
|
||||
|
||||
import { useState, useCallback } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import {
|
||||
Folder,
|
||||
User,
|
||||
FolderInput,
|
||||
Sparkles,
|
||||
CheckCircle,
|
||||
XCircle,
|
||||
Loader2,
|
||||
Info,
|
||||
} from 'lucide-react';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogFooter,
|
||||
DialogTitle,
|
||||
DialogDescription,
|
||||
} from '@/components/ui/Dialog';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Input } from '@/components/ui/Input';
|
||||
import { Textarea } from '@/components/ui/Textarea';
|
||||
import { Label } from '@/components/ui/Label';
|
||||
import { validateSkillImport, createSkill } from '@/lib/api';
|
||||
import { useWorkflowStore, selectProjectPath } from '@/stores/workflowStore';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
export interface SkillCreateDialogProps {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
onCreated: () => void;
|
||||
}
|
||||
|
||||
type CreateMode = 'import' | 'cli-generate';
|
||||
type SkillLocation = 'project' | 'user';
|
||||
|
||||
interface ValidationResult {
|
||||
valid: boolean;
|
||||
errors?: string[];
|
||||
skillInfo?: { name: string; description: string; version?: string; supportingFiles?: string[] };
|
||||
}
|
||||
|
||||
export function SkillCreateDialog({ open, onOpenChange, onCreated }: SkillCreateDialogProps) {
|
||||
const { formatMessage } = useIntl();
|
||||
const projectPath = useWorkflowStore(selectProjectPath);
|
||||
|
||||
const [mode, setMode] = useState<CreateMode>('import');
|
||||
const [location, setLocation] = useState<SkillLocation>('project');
|
||||
|
||||
// Import mode state
|
||||
const [sourcePath, setSourcePath] = useState('');
|
||||
const [customName, setCustomName] = useState('');
|
||||
const [validationResult, setValidationResult] = useState<ValidationResult | null>(null);
|
||||
const [isValidating, setIsValidating] = useState(false);
|
||||
|
||||
// CLI Generate mode state
|
||||
const [skillName, setSkillName] = useState('');
|
||||
const [description, setDescription] = useState('');
|
||||
|
||||
const [isCreating, setIsCreating] = useState(false);
|
||||
|
||||
const resetState = useCallback(() => {
|
||||
setMode('import');
|
||||
setLocation('project');
|
||||
setSourcePath('');
|
||||
setCustomName('');
|
||||
setValidationResult(null);
|
||||
setIsValidating(false);
|
||||
setSkillName('');
|
||||
setDescription('');
|
||||
setIsCreating(false);
|
||||
}, []);
|
||||
|
||||
const handleOpenChange = useCallback((open: boolean) => {
|
||||
if (!open) {
|
||||
resetState();
|
||||
}
|
||||
onOpenChange(open);
|
||||
}, [onOpenChange, resetState]);
|
||||
|
||||
const handleValidate = useCallback(async () => {
|
||||
if (!sourcePath.trim()) return;
|
||||
|
||||
setIsValidating(true);
|
||||
setValidationResult(null);
|
||||
|
||||
try {
|
||||
const result = await validateSkillImport(sourcePath.trim());
|
||||
setValidationResult(result);
|
||||
} catch (err) {
|
||||
setValidationResult({
|
||||
valid: false,
|
||||
errors: [err instanceof Error ? err.message : String(err)],
|
||||
});
|
||||
} finally {
|
||||
setIsValidating(false);
|
||||
}
|
||||
}, [sourcePath]);
|
||||
|
||||
const handleCreate = useCallback(async () => {
|
||||
if (mode === 'import') {
|
||||
if (!sourcePath.trim()) return;
|
||||
if (!validationResult?.valid) return;
|
||||
} else {
|
||||
if (!skillName.trim()) return;
|
||||
if (!description.trim()) return;
|
||||
}
|
||||
|
||||
setIsCreating(true);
|
||||
|
||||
try {
|
||||
await createSkill({
|
||||
mode,
|
||||
location,
|
||||
sourcePath: mode === 'import' ? sourcePath.trim() : undefined,
|
||||
skillName: mode === 'import' ? (customName.trim() || undefined) : skillName.trim(),
|
||||
description: mode === 'cli-generate' ? description.trim() : undefined,
|
||||
generationType: mode === 'cli-generate' ? 'description' : undefined,
|
||||
projectPath,
|
||||
});
|
||||
|
||||
handleOpenChange(false);
|
||||
onCreated();
|
||||
} catch (err) {
|
||||
console.error('Failed to create skill:', err);
|
||||
if (mode === 'import') {
|
||||
setValidationResult({
|
||||
valid: false,
|
||||
errors: [err instanceof Error ? err.message : formatMessage({ id: 'skills.create.createError' })],
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
setIsCreating(false);
|
||||
}
|
||||
}, [mode, location, sourcePath, customName, skillName, description, validationResult, projectPath, handleOpenChange, onCreated, formatMessage]);
|
||||
|
||||
const canCreate = mode === 'import'
|
||||
? sourcePath.trim() && validationResult?.valid && !isCreating
|
||||
: skillName.trim() && description.trim() && !isCreating;
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={handleOpenChange}>
|
||||
<DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{formatMessage({ id: 'skills.create.title' })}</DialogTitle>
|
||||
<DialogDescription>
|
||||
{formatMessage({ id: 'skills.description' })}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-5 py-2">
|
||||
{/* Location Selection */}
|
||||
<div className="space-y-2">
|
||||
<Label>{formatMessage({ id: 'skills.create.location' })}</Label>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
'px-4 py-3 text-left border-2 rounded-lg transition-all',
|
||||
location === 'project'
|
||||
? 'border-primary bg-primary/10'
|
||||
: 'border-border hover:border-primary/50'
|
||||
)}
|
||||
onClick={() => setLocation('project')}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Folder className="w-5 h-5" />
|
||||
<div>
|
||||
<div className="font-medium text-sm">{formatMessage({ id: 'skills.create.locationProject' })}</div>
|
||||
<div className="text-xs text-muted-foreground">{formatMessage({ id: 'skills.create.locationProjectHint' })}</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
'px-4 py-3 text-left border-2 rounded-lg transition-all',
|
||||
location === 'user'
|
||||
? 'border-primary bg-primary/10'
|
||||
: 'border-border hover:border-primary/50'
|
||||
)}
|
||||
onClick={() => setLocation('user')}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<User className="w-5 h-5" />
|
||||
<div>
|
||||
<div className="font-medium text-sm">{formatMessage({ id: 'skills.create.locationUser' })}</div>
|
||||
<div className="text-xs text-muted-foreground">{formatMessage({ id: 'skills.create.locationUserHint' })}</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mode Selection */}
|
||||
<div className="space-y-2">
|
||||
<Label>{formatMessage({ id: 'skills.create.mode' })}</Label>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
'px-4 py-3 text-left border-2 rounded-lg transition-all',
|
||||
mode === 'import'
|
||||
? 'border-primary bg-primary/10'
|
||||
: 'border-border hover:border-primary/50'
|
||||
)}
|
||||
onClick={() => setMode('import')}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<FolderInput className="w-5 h-5" />
|
||||
<div>
|
||||
<div className="font-medium text-sm">{formatMessage({ id: 'skills.create.modeImport' })}</div>
|
||||
<div className="text-xs text-muted-foreground">{formatMessage({ id: 'skills.create.modeImportHint' })}</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
'px-4 py-3 text-left border-2 rounded-lg transition-all',
|
||||
mode === 'cli-generate'
|
||||
? 'border-primary bg-primary/10'
|
||||
: 'border-border hover:border-primary/50'
|
||||
)}
|
||||
onClick={() => setMode('cli-generate')}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Sparkles className="w-5 h-5" />
|
||||
<div>
|
||||
<div className="font-medium text-sm">{formatMessage({ id: 'skills.create.modeGenerate' })}</div>
|
||||
<div className="text-xs text-muted-foreground">{formatMessage({ id: 'skills.create.modeGenerateHint' })}</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Import Mode Content */}
|
||||
{mode === 'import' && (
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="sourcePath">{formatMessage({ id: 'skills.create.sourcePath' })}</Label>
|
||||
<Input
|
||||
id="sourcePath"
|
||||
value={sourcePath}
|
||||
onChange={(e) => {
|
||||
setSourcePath(e.target.value);
|
||||
setValidationResult(null);
|
||||
}}
|
||||
placeholder={formatMessage({ id: 'skills.create.sourcePathPlaceholder' })}
|
||||
className="font-mono text-sm"
|
||||
/>
|
||||
<p className="text-xs text-muted-foreground">{formatMessage({ id: 'skills.create.sourcePathHint' })}</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="customName">
|
||||
{formatMessage({ id: 'skills.create.customName' })}
|
||||
<span className="text-muted-foreground ml-1">({formatMessage({ id: 'skills.create.customNameHint' })})</span>
|
||||
</Label>
|
||||
<Input
|
||||
id="customName"
|
||||
value={customName}
|
||||
onChange={(e) => setCustomName(e.target.value)}
|
||||
placeholder={formatMessage({ id: 'skills.create.customNamePlaceholder' })}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Validation Result */}
|
||||
{isValidating && (
|
||||
<div className="flex items-center gap-2 p-3 bg-muted/50 rounded-lg">
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
<span className="text-sm text-muted-foreground">{formatMessage({ id: 'skills.create.validating' })}</span>
|
||||
</div>
|
||||
)}
|
||||
{validationResult && !isValidating && (
|
||||
validationResult.valid ? (
|
||||
<div className="p-4 bg-green-500/10 border border-green-500/20 rounded-lg">
|
||||
<div className="flex items-center gap-2 text-green-600 mb-2">
|
||||
<CheckCircle className="w-5 h-5" />
|
||||
<span className="font-medium">{formatMessage({ id: 'skills.create.validSkill' })}</span>
|
||||
</div>
|
||||
{validationResult.skillInfo && (
|
||||
<div className="space-y-1 text-sm">
|
||||
<div>
|
||||
<span className="text-muted-foreground">{formatMessage({ id: 'skills.card.description' })}: </span>
|
||||
<span>{validationResult.skillInfo.name}</span>
|
||||
</div>
|
||||
{validationResult.skillInfo.description && (
|
||||
<div>
|
||||
<span className="text-muted-foreground">{formatMessage({ id: 'skills.card.description' })}: </span>
|
||||
<span>{validationResult.skillInfo.description}</span>
|
||||
</div>
|
||||
)}
|
||||
{validationResult.skillInfo.version && (
|
||||
<div>
|
||||
<span className="text-muted-foreground">{formatMessage({ id: 'skills.card.version' })}: </span>
|
||||
<span>{validationResult.skillInfo.version}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="p-4 bg-destructive/10 border border-destructive/20 rounded-lg">
|
||||
<div className="flex items-center gap-2 text-destructive mb-2">
|
||||
<XCircle className="w-5 h-5" />
|
||||
<span className="font-medium">{formatMessage({ id: 'skills.create.invalidSkill' })}</span>
|
||||
</div>
|
||||
{validationResult.errors && (
|
||||
<ul className="space-y-1 text-sm">
|
||||
{validationResult.errors.map((error, i) => (
|
||||
<li key={i} className="text-destructive">{error}</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* CLI Generate Mode Content */}
|
||||
{mode === 'cli-generate' && (
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="skillName">
|
||||
{formatMessage({ id: 'skills.create.skillName' })} <span className="text-destructive">*</span>
|
||||
</Label>
|
||||
<Input
|
||||
id="skillName"
|
||||
value={skillName}
|
||||
onChange={(e) => setSkillName(e.target.value)}
|
||||
placeholder={formatMessage({ id: 'skills.create.skillNamePlaceholder' })}
|
||||
/>
|
||||
<p className="text-xs text-muted-foreground">{formatMessage({ id: 'skills.create.skillNameHint' })}</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="description">
|
||||
{formatMessage({ id: 'skills.create.descriptionLabel' })} <span className="text-destructive">*</span>
|
||||
</Label>
|
||||
<Textarea
|
||||
id="description"
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
placeholder={formatMessage({ id: 'skills.create.descriptionPlaceholder' })}
|
||||
rows={6}
|
||||
/>
|
||||
<p className="text-xs text-muted-foreground">{formatMessage({ id: 'skills.create.descriptionHint' })}</p>
|
||||
</div>
|
||||
|
||||
<div className="p-3 bg-blue-500/10 border border-blue-500/20 rounded-lg">
|
||||
<div className="flex items-start gap-2">
|
||||
<Info className="w-4 h-4 text-blue-600 mt-0.5" />
|
||||
<div className="text-sm text-blue-600">
|
||||
<p className="font-medium">{formatMessage({ id: 'skills.create.generateInfo' })}</p>
|
||||
<p className="text-xs mt-1">{formatMessage({ id: 'skills.create.generateTimeHint' })}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<DialogFooter className="gap-2">
|
||||
<Button variant="outline" onClick={() => handleOpenChange(false)} disabled={isCreating}>
|
||||
{formatMessage({ id: 'skills.actions.cancel' })}
|
||||
</Button>
|
||||
{mode === 'import' && (
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={handleValidate}
|
||||
disabled={!sourcePath.trim() || isValidating || isCreating}
|
||||
>
|
||||
{isValidating && <Loader2 className="w-4 h-4 mr-2 animate-spin" />}
|
||||
{formatMessage({ id: 'skills.create.validate' })}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
onClick={handleCreate}
|
||||
disabled={!canCreate}
|
||||
>
|
||||
{isCreating && <Loader2 className="w-4 h-4 mr-2 animate-spin" />}
|
||||
{isCreating
|
||||
? formatMessage({ id: 'skills.create.creating' })
|
||||
: mode === 'import'
|
||||
? formatMessage({ id: 'skills.create.import' })
|
||||
: formatMessage({ id: 'skills.create.generate' })
|
||||
}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default SkillCreateDialog;
|
||||
@@ -19,6 +19,9 @@ export type { SkillCardProps } from './SkillCard';
|
||||
export { SkillDetailPanel } from './SkillDetailPanel';
|
||||
export type { SkillDetailPanelProps } from './SkillDetailPanel';
|
||||
|
||||
export { SkillCreateDialog } from './SkillCreateDialog';
|
||||
export type { SkillCreateDialogProps } from './SkillCreateDialog';
|
||||
|
||||
export { StatCard, StatCardSkeleton } from './StatCard';
|
||||
export type { StatCardProps } from './StatCard';
|
||||
|
||||
|
||||
@@ -196,6 +196,27 @@ export type {
|
||||
UseRulesReturn,
|
||||
} from './useCli';
|
||||
|
||||
// ========== System Settings ==========
|
||||
export {
|
||||
useChineseResponseStatus,
|
||||
useToggleChineseResponse,
|
||||
useWindowsPlatformStatus,
|
||||
useToggleWindowsPlatform,
|
||||
useCodexCliEnhancementStatus,
|
||||
useToggleCodexCliEnhancement,
|
||||
useRefreshCodexCliEnhancement,
|
||||
useCcwInstallStatus,
|
||||
useCliToolStatus,
|
||||
systemSettingsKeys,
|
||||
} from './useSystemSettings';
|
||||
export type {
|
||||
UseChineseResponseStatusReturn,
|
||||
UseWindowsPlatformStatusReturn,
|
||||
UseCodexCliEnhancementStatusReturn,
|
||||
UseCcwInstallStatusReturn,
|
||||
UseCliToolStatusReturn,
|
||||
} from './useSystemSettings';
|
||||
|
||||
// ========== CLI Execution ==========
|
||||
export {
|
||||
useCliExecutionDetail,
|
||||
|
||||
@@ -189,6 +189,7 @@ export function useDeleteMcpServer(): UseDeleteMcpServerReturn {
|
||||
deleteMcpServer(serverName, scope, { projectPath: projectPath ?? undefined }),
|
||||
onSettled: () => {
|
||||
queryClient.invalidateQueries({ queryKey: mcpServersKeys.all });
|
||||
queryClient.invalidateQueries({ queryKey: ['ccwMcpConfig'] });
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
238
ccw/frontend/src/hooks/useSystemSettings.ts
Normal file
238
ccw/frontend/src/hooks/useSystemSettings.ts
Normal file
@@ -0,0 +1,238 @@
|
||||
// ========================================
|
||||
// useSystemSettings Hook
|
||||
// ========================================
|
||||
// TanStack Query hooks for system settings (language, install status, tool status)
|
||||
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import {
|
||||
fetchChineseResponseStatus,
|
||||
toggleChineseResponse,
|
||||
fetchWindowsPlatformStatus,
|
||||
toggleWindowsPlatform,
|
||||
fetchCodexCliEnhancementStatus,
|
||||
toggleCodexCliEnhancement,
|
||||
refreshCodexCliEnhancement,
|
||||
fetchAggregatedStatus,
|
||||
fetchCliToolStatus,
|
||||
type ChineseResponseStatus,
|
||||
type WindowsPlatformStatus,
|
||||
type CodexCliEnhancementStatus,
|
||||
type CcwInstallStatus,
|
||||
} from '../lib/api';
|
||||
|
||||
// Query key factory
|
||||
export const systemSettingsKeys = {
|
||||
all: ['systemSettings'] as const,
|
||||
chineseResponse: () => [...systemSettingsKeys.all, 'chineseResponse'] as const,
|
||||
windowsPlatform: () => [...systemSettingsKeys.all, 'windowsPlatform'] as const,
|
||||
codexCliEnhancement: () => [...systemSettingsKeys.all, 'codexCliEnhancement'] as const,
|
||||
aggregatedStatus: () => [...systemSettingsKeys.all, 'aggregatedStatus'] as const,
|
||||
cliToolStatus: () => [...systemSettingsKeys.all, 'cliToolStatus'] as const,
|
||||
};
|
||||
|
||||
const STALE_TIME = 60 * 1000; // 1 minute
|
||||
|
||||
// ========================================
|
||||
// Chinese Response Hooks
|
||||
// ========================================
|
||||
|
||||
export interface UseChineseResponseStatusReturn {
|
||||
data: ChineseResponseStatus | undefined;
|
||||
isLoading: boolean;
|
||||
error: Error | null;
|
||||
refetch: () => void;
|
||||
}
|
||||
|
||||
export function useChineseResponseStatus(): UseChineseResponseStatusReturn {
|
||||
const query = useQuery({
|
||||
queryKey: systemSettingsKeys.chineseResponse(),
|
||||
queryFn: fetchChineseResponseStatus,
|
||||
staleTime: STALE_TIME,
|
||||
retry: 1,
|
||||
});
|
||||
|
||||
return {
|
||||
data: query.data,
|
||||
isLoading: query.isLoading,
|
||||
error: query.error,
|
||||
refetch: () => { query.refetch(); },
|
||||
};
|
||||
}
|
||||
|
||||
export function useToggleChineseResponse() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: ({ enabled, target }: { enabled: boolean; target: 'claude' | 'codex' }) =>
|
||||
toggleChineseResponse(enabled, target),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: systemSettingsKeys.chineseResponse() });
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
toggle: (enabled: boolean, target: 'claude' | 'codex') =>
|
||||
mutation.mutateAsync({ enabled, target }),
|
||||
isPending: mutation.isPending,
|
||||
error: mutation.error,
|
||||
};
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Windows Platform Hooks
|
||||
// ========================================
|
||||
|
||||
export interface UseWindowsPlatformStatusReturn {
|
||||
data: WindowsPlatformStatus | undefined;
|
||||
isLoading: boolean;
|
||||
error: Error | null;
|
||||
refetch: () => void;
|
||||
}
|
||||
|
||||
export function useWindowsPlatformStatus(): UseWindowsPlatformStatusReturn {
|
||||
const query = useQuery({
|
||||
queryKey: systemSettingsKeys.windowsPlatform(),
|
||||
queryFn: fetchWindowsPlatformStatus,
|
||||
staleTime: STALE_TIME,
|
||||
retry: 1,
|
||||
});
|
||||
|
||||
return {
|
||||
data: query.data,
|
||||
isLoading: query.isLoading,
|
||||
error: query.error,
|
||||
refetch: () => { query.refetch(); },
|
||||
};
|
||||
}
|
||||
|
||||
export function useToggleWindowsPlatform() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: (enabled: boolean) => toggleWindowsPlatform(enabled),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: systemSettingsKeys.windowsPlatform() });
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
toggle: mutation.mutateAsync,
|
||||
isPending: mutation.isPending,
|
||||
error: mutation.error,
|
||||
};
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Codex CLI Enhancement Hooks
|
||||
// ========================================
|
||||
|
||||
export interface UseCodexCliEnhancementStatusReturn {
|
||||
data: CodexCliEnhancementStatus | undefined;
|
||||
isLoading: boolean;
|
||||
error: Error | null;
|
||||
refetch: () => void;
|
||||
}
|
||||
|
||||
export function useCodexCliEnhancementStatus(): UseCodexCliEnhancementStatusReturn {
|
||||
const query = useQuery({
|
||||
queryKey: systemSettingsKeys.codexCliEnhancement(),
|
||||
queryFn: fetchCodexCliEnhancementStatus,
|
||||
staleTime: STALE_TIME,
|
||||
retry: 1,
|
||||
});
|
||||
|
||||
return {
|
||||
data: query.data,
|
||||
isLoading: query.isLoading,
|
||||
error: query.error,
|
||||
refetch: () => { query.refetch(); },
|
||||
};
|
||||
}
|
||||
|
||||
export function useToggleCodexCliEnhancement() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: (enabled: boolean) => toggleCodexCliEnhancement(enabled),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: systemSettingsKeys.codexCliEnhancement() });
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
toggle: mutation.mutateAsync,
|
||||
isPending: mutation.isPending,
|
||||
error: mutation.error,
|
||||
};
|
||||
}
|
||||
|
||||
export function useRefreshCodexCliEnhancement() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: () => refreshCodexCliEnhancement(),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: systemSettingsKeys.codexCliEnhancement() });
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
refresh: mutation.mutateAsync,
|
||||
isPending: mutation.isPending,
|
||||
error: mutation.error,
|
||||
};
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Aggregated Status / CCW Install Hooks
|
||||
// ========================================
|
||||
|
||||
export interface UseCcwInstallStatusReturn {
|
||||
data: CcwInstallStatus | undefined;
|
||||
isLoading: boolean;
|
||||
error: Error | null;
|
||||
refetch: () => void;
|
||||
}
|
||||
|
||||
export function useCcwInstallStatus(): UseCcwInstallStatusReturn {
|
||||
const query = useQuery({
|
||||
queryKey: systemSettingsKeys.aggregatedStatus(),
|
||||
queryFn: fetchAggregatedStatus,
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
retry: 1,
|
||||
});
|
||||
|
||||
return {
|
||||
data: query.data?.ccwInstall,
|
||||
isLoading: query.isLoading,
|
||||
error: query.error,
|
||||
refetch: () => { query.refetch(); },
|
||||
};
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// CLI Tool Status Hooks
|
||||
// ========================================
|
||||
|
||||
export interface UseCliToolStatusReturn {
|
||||
data: Record<string, { available: boolean; path?: string; version?: string }> | undefined;
|
||||
isLoading: boolean;
|
||||
error: Error | null;
|
||||
refetch: () => void;
|
||||
}
|
||||
|
||||
export function useCliToolStatus(): UseCliToolStatusReturn {
|
||||
const query = useQuery({
|
||||
queryKey: systemSettingsKeys.cliToolStatus(),
|
||||
queryFn: fetchCliToolStatus,
|
||||
staleTime: 2 * 60 * 1000, // 2 minutes
|
||||
retry: 1,
|
||||
});
|
||||
|
||||
return {
|
||||
data: query.data,
|
||||
isLoading: query.isLoading,
|
||||
error: query.error,
|
||||
refetch: () => { query.refetch(); },
|
||||
};
|
||||
}
|
||||
@@ -993,22 +993,36 @@ export interface SkillsResponse {
|
||||
* @param projectPath - Optional project path to filter data by workspace
|
||||
*/
|
||||
export async function fetchSkills(projectPath?: string): Promise<SkillsResponse> {
|
||||
// Response type from backend when includeDisabled=true
|
||||
interface ExtendedSkillsResponse {
|
||||
skills?: Skill[];
|
||||
projectSkills?: Skill[];
|
||||
userSkills?: Skill[];
|
||||
disabledProjectSkills?: Skill[];
|
||||
disabledUserSkills?: Skill[];
|
||||
}
|
||||
|
||||
// Helper to add location and enabled status to skills
|
||||
// Backend only returns enabled skills (with SKILL.md), so we set enabled: true
|
||||
const addMetadata = (skills: Skill[], location: 'project' | 'user'): Skill[] =>
|
||||
const addEnabledMetadata = (skills: Skill[], location: 'project' | 'user'): Skill[] =>
|
||||
skills.map(skill => ({ ...skill, location, enabled: true }));
|
||||
|
||||
const addDisabledMetadata = (skills: Skill[], location: 'project' | 'user'): Skill[] =>
|
||||
skills.map(skill => ({ ...skill, location, enabled: false }));
|
||||
|
||||
const buildSkillsList = (data: ExtendedSkillsResponse): Skill[] => {
|
||||
const projectSkillsEnabled = addEnabledMetadata(data.projectSkills ?? [], 'project');
|
||||
const userSkillsEnabled = addEnabledMetadata(data.userSkills ?? [], 'user');
|
||||
const projectSkillsDisabled = addDisabledMetadata(data.disabledProjectSkills ?? [], 'project');
|
||||
const userSkillsDisabled = addDisabledMetadata(data.disabledUserSkills ?? [], 'user');
|
||||
return [...projectSkillsEnabled, ...userSkillsEnabled, ...projectSkillsDisabled, ...userSkillsDisabled];
|
||||
};
|
||||
|
||||
// Try with project path first, fall back to global on 403/404
|
||||
if (projectPath) {
|
||||
try {
|
||||
const url = `/api/skills?path=${encodeURIComponent(projectPath)}`;
|
||||
const data = await fetchApi<{ skills?: Skill[]; projectSkills?: Skill[]; userSkills?: Skill[] }>(url);
|
||||
const projectSkillsWithMetadata = addMetadata(data.projectSkills ?? [], 'project');
|
||||
const userSkillsWithMetadata = addMetadata(data.userSkills ?? [], 'user');
|
||||
const allSkills = [...projectSkillsWithMetadata, ...userSkillsWithMetadata];
|
||||
return {
|
||||
skills: data.skills ?? allSkills,
|
||||
};
|
||||
const url = `/api/skills?path=${encodeURIComponent(projectPath)}&includeDisabled=true`;
|
||||
const data = await fetchApi<ExtendedSkillsResponse>(url);
|
||||
return { skills: buildSkillsList(data) };
|
||||
} catch (error: unknown) {
|
||||
const apiError = error as ApiError;
|
||||
if (apiError.status === 403 || apiError.status === 404) {
|
||||
@@ -1020,13 +1034,8 @@ export async function fetchSkills(projectPath?: string): Promise<SkillsResponse>
|
||||
}
|
||||
}
|
||||
// Fallback: fetch global skills
|
||||
const data = await fetchApi<{ skills?: Skill[]; projectSkills?: Skill[]; userSkills?: Skill[] }>('/api/skills');
|
||||
const projectSkillsWithMetadata = addMetadata(data.projectSkills ?? [], 'project');
|
||||
const userSkillsWithMetadata = addMetadata(data.userSkills ?? [], 'user');
|
||||
const allSkills = [...projectSkillsWithMetadata, ...userSkillsWithMetadata];
|
||||
return {
|
||||
skills: data.skills ?? allSkills,
|
||||
};
|
||||
const data = await fetchApi<ExtendedSkillsResponse>('/api/skills?includeDisabled=true');
|
||||
return { skills: buildSkillsList(data) };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1074,6 +1083,38 @@ export async function fetchSkillDetail(
|
||||
return fetchApi<{ skill: Skill }>(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a skill folder for import
|
||||
*/
|
||||
export async function validateSkillImport(sourcePath: string): Promise<{
|
||||
valid: boolean;
|
||||
errors?: string[];
|
||||
skillInfo?: { name: string; description: string; version?: string; supportingFiles?: string[] };
|
||||
}> {
|
||||
return fetchApi('/api/skills/validate-import', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ sourcePath }),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create/import a skill
|
||||
*/
|
||||
export async function createSkill(params: {
|
||||
mode: 'import' | 'cli-generate';
|
||||
location: 'project' | 'user';
|
||||
sourcePath?: string;
|
||||
skillName?: string;
|
||||
description?: string;
|
||||
generationType?: 'description' | 'template';
|
||||
projectPath?: string;
|
||||
}): Promise<{ skillName: string; path: string }> {
|
||||
return fetchApi('/api/skills/create', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
// ========== Commands API ==========
|
||||
|
||||
export interface Command {
|
||||
@@ -5062,3 +5103,142 @@ export async function fetchExecutionLogs(
|
||||
const queryString = params.toString();
|
||||
return fetchApi(`/api/orchestrator/executions/${encodeURIComponent(execId)}/logs${queryString ? `?${queryString}` : ''}`);
|
||||
}
|
||||
|
||||
// ========== System Settings API ==========
|
||||
|
||||
/**
|
||||
* Chinese response setting status
|
||||
*/
|
||||
export interface ChineseResponseStatus {
|
||||
enabled: boolean;
|
||||
claudeEnabled: boolean;
|
||||
codexEnabled: boolean;
|
||||
codexNeedsMigration: boolean;
|
||||
guidelinesPath: string;
|
||||
guidelinesExists: boolean;
|
||||
userClaudeMdExists: boolean;
|
||||
userCodexAgentsExists: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch Chinese response setting status
|
||||
*/
|
||||
export async function fetchChineseResponseStatus(): Promise<ChineseResponseStatus> {
|
||||
return fetchApi('/api/language/chinese-response');
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle Chinese response setting
|
||||
*/
|
||||
export async function toggleChineseResponse(
|
||||
enabled: boolean,
|
||||
target: 'claude' | 'codex' = 'claude'
|
||||
): Promise<{ success: boolean; enabled: boolean; target: string }> {
|
||||
return fetchApi('/api/language/chinese-response', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ enabled, target }),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Windows platform setting status
|
||||
*/
|
||||
export interface WindowsPlatformStatus {
|
||||
enabled: boolean;
|
||||
guidelinesPath: string;
|
||||
guidelinesExists: boolean;
|
||||
userClaudeMdExists: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch Windows platform setting status
|
||||
*/
|
||||
export async function fetchWindowsPlatformStatus(): Promise<WindowsPlatformStatus> {
|
||||
return fetchApi('/api/language/windows-platform');
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle Windows platform setting
|
||||
*/
|
||||
export async function toggleWindowsPlatform(
|
||||
enabled: boolean
|
||||
): Promise<{ success: boolean; enabled: boolean }> {
|
||||
return fetchApi('/api/language/windows-platform', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ enabled }),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Codex CLI Enhancement setting status
|
||||
*/
|
||||
export interface CodexCliEnhancementStatus {
|
||||
enabled: boolean;
|
||||
guidelinesPath: string;
|
||||
guidelinesExists: boolean;
|
||||
userCodexAgentsExists: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch Codex CLI Enhancement setting status
|
||||
*/
|
||||
export async function fetchCodexCliEnhancementStatus(): Promise<CodexCliEnhancementStatus> {
|
||||
return fetchApi('/api/language/codex-cli-enhancement');
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle Codex CLI Enhancement setting
|
||||
*/
|
||||
export async function toggleCodexCliEnhancement(
|
||||
enabled: boolean
|
||||
): Promise<{ success: boolean; enabled: boolean }> {
|
||||
return fetchApi('/api/language/codex-cli-enhancement', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ enabled }),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh Codex CLI Enhancement content
|
||||
*/
|
||||
export async function refreshCodexCliEnhancement(): Promise<{ success: boolean; refreshed: boolean }> {
|
||||
return fetchApi('/api/language/codex-cli-enhancement', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ action: 'refresh' }),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* CCW Install status
|
||||
*/
|
||||
export interface CcwInstallStatus {
|
||||
installed: boolean;
|
||||
workflowsInstalled: boolean;
|
||||
missingFiles: string[];
|
||||
installPath: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregated status response
|
||||
*/
|
||||
export interface AggregatedStatus {
|
||||
cli: Record<string, { available: boolean; path?: string; version?: string }>;
|
||||
codexLens: { ready: boolean };
|
||||
semantic: { available: boolean; backend: string | null };
|
||||
ccwInstall: CcwInstallStatus;
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch aggregated system status (includes CCW install status)
|
||||
*/
|
||||
export async function fetchAggregatedStatus(): Promise<AggregatedStatus> {
|
||||
return fetchApi('/api/status/all');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch CLI tool availability status
|
||||
*/
|
||||
export async function fetchCliToolStatus(): Promise<Record<string, { available: boolean; path?: string; version?: string }>> {
|
||||
return fetchApi('/api/cli/status');
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
"cliTools": "CLI Tools",
|
||||
"display": "Display Settings",
|
||||
"language": "Language",
|
||||
"responseLanguage": "Response Language",
|
||||
"systemStatus": "System Status",
|
||||
"hooks": "Git Hooks",
|
||||
"rules": "Rules",
|
||||
"about": "About"
|
||||
@@ -48,6 +50,35 @@
|
||||
"displayLanguage": "Display Language",
|
||||
"chooseLanguage": "Choose your preferred language for the interface"
|
||||
},
|
||||
"responseLanguage": {
|
||||
"title": "Response Language Settings",
|
||||
"chineseClaude": "Chinese Response",
|
||||
"chineseClaudeDesc": "Enable Chinese response guidelines in ~/.claude/CLAUDE.md",
|
||||
"chineseCodex": "Chinese Response",
|
||||
"chineseCodexDesc": "Enable Chinese response guidelines in ~/.codex/AGENTS.md",
|
||||
"windowsPlatform": "Windows Platform",
|
||||
"windowsPlatformDesc": "Enable Windows path format conventions in global CLAUDE.md",
|
||||
"cliEnhancement": "CLI Enhancement",
|
||||
"cliEnhancementDesc": "Enable multi-CLI tool invocation for Codex",
|
||||
"cliEnhancementHint": "After config changes, click refresh to update content",
|
||||
"refreshConfig": "Refresh Config",
|
||||
"migrationWarning": "Old format detected, please disable and re-enable to migrate",
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled"
|
||||
},
|
||||
"systemStatus": {
|
||||
"title": "System Status",
|
||||
"ccwInstall": "CCW Installation",
|
||||
"installed": "Installed",
|
||||
"incomplete": "Incomplete",
|
||||
"notInstalled": "Not Installed",
|
||||
"missingFiles": "Missing Files",
|
||||
"runToFix": "Run to fix",
|
||||
"toolStatus": "Tool Availability",
|
||||
"available": "Available",
|
||||
"unavailable": "Unavailable",
|
||||
"checking": "Checking..."
|
||||
},
|
||||
"dataRefresh": {
|
||||
"title": "Data Refresh",
|
||||
"autoRefresh": "Auto Refresh",
|
||||
|
||||
@@ -65,5 +65,45 @@
|
||||
"emptyState": {
|
||||
"title": "No Skills Found",
|
||||
"message": "No skills match your current filter."
|
||||
},
|
||||
"create": {
|
||||
"title": "Create Skill",
|
||||
"location": "Location",
|
||||
"locationProject": "Project Skills",
|
||||
"locationProjectHint": ".claude/skills/",
|
||||
"locationUser": "Global Skills",
|
||||
"locationUserHint": "~/.claude/skills/",
|
||||
"mode": "Creation Mode",
|
||||
"modeImport": "Import Folder",
|
||||
"modeImportHint": "Import skill from existing folder",
|
||||
"modeGenerate": "AI Generate",
|
||||
"modeGenerateHint": "Generate skill using AI",
|
||||
"sourcePath": "Source Folder Path",
|
||||
"sourcePathPlaceholder": "Enter absolute path to skill folder",
|
||||
"sourcePathHint": "Folder must contain a SKILL.md file",
|
||||
"customName": "Custom Name",
|
||||
"customNamePlaceholder": "Leave empty to use original name",
|
||||
"customNameHint": "Optional, overrides default skill name",
|
||||
"skillName": "Skill Name",
|
||||
"skillNamePlaceholder": "Enter skill name",
|
||||
"skillNameHint": "Used as the skill folder name",
|
||||
"descriptionLabel": "Skill Description",
|
||||
"descriptionPlaceholder": "Describe what this skill should do...",
|
||||
"descriptionHint": "AI will generate skill content based on this description",
|
||||
"generateInfo": "AI will use CLI tools to generate the skill",
|
||||
"generateTimeHint": "Generation may take some time",
|
||||
"validate": "Validate",
|
||||
"import": "Import",
|
||||
"generate": "Generate",
|
||||
"validating": "Validating...",
|
||||
"validSkill": "Validation passed",
|
||||
"invalidSkill": "Validation failed",
|
||||
"creating": "Creating...",
|
||||
"created": "Skill \"{name}\" created successfully",
|
||||
"createError": "Failed to create skill",
|
||||
"sourcePathRequired": "Please enter source folder path",
|
||||
"skillNameRequired": "Please enter skill name",
|
||||
"descriptionRequired": "Please enter skill description",
|
||||
"validateFirst": "Please validate the skill folder first"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
"cliTools": "CLI 工具",
|
||||
"display": "显示设置",
|
||||
"language": "语言",
|
||||
"responseLanguage": "回复语言设置",
|
||||
"systemStatus": "系统状态",
|
||||
"hooks": "Git 钩子",
|
||||
"rules": "规则",
|
||||
"about": "关于"
|
||||
@@ -48,6 +50,35 @@
|
||||
"displayLanguage": "显示语言",
|
||||
"chooseLanguage": "选择界面的首选语言"
|
||||
},
|
||||
"responseLanguage": {
|
||||
"title": "回复语言设置",
|
||||
"chineseClaude": "中文回复",
|
||||
"chineseClaudeDesc": "在 ~/.claude/CLAUDE.md 中启用中文回复准则",
|
||||
"chineseCodex": "中文回复",
|
||||
"chineseCodexDesc": "在 ~/.codex/AGENTS.md 中启用中文回复准则",
|
||||
"windowsPlatform": "Windows 平台规范",
|
||||
"windowsPlatformDesc": "在全局 CLAUDE.md 中启用 Windows 路径格式规范",
|
||||
"cliEnhancement": "CLI 调用增强",
|
||||
"cliEnhancementDesc": "为 Codex 启用多 CLI 工具调用功能",
|
||||
"cliEnhancementHint": "配置文件变更后,点击刷新按钮更新内容",
|
||||
"refreshConfig": "刷新配置",
|
||||
"migrationWarning": "检测到旧格式,请关闭后重新启用以迁移",
|
||||
"enabled": "已启用",
|
||||
"disabled": "已禁用"
|
||||
},
|
||||
"systemStatus": {
|
||||
"title": "系统状态",
|
||||
"ccwInstall": "CCW 安装状态",
|
||||
"installed": "已安装",
|
||||
"incomplete": "不完整",
|
||||
"notInstalled": "未安装",
|
||||
"missingFiles": "缺失文件",
|
||||
"runToFix": "运行以下命令修复",
|
||||
"toolStatus": "工具可用性",
|
||||
"available": "可用",
|
||||
"unavailable": "不可用",
|
||||
"checking": "检测中..."
|
||||
},
|
||||
"dataRefresh": {
|
||||
"title": "数据刷新",
|
||||
"autoRefresh": "自动刷新",
|
||||
|
||||
@@ -65,5 +65,45 @@
|
||||
"emptyState": {
|
||||
"title": "未找到技能",
|
||||
"message": "没有符合当前筛选条件的技能。"
|
||||
},
|
||||
"create": {
|
||||
"title": "创建技能",
|
||||
"location": "存储位置",
|
||||
"locationProject": "项目技能",
|
||||
"locationProjectHint": ".claude/skills/",
|
||||
"locationUser": "全局技能",
|
||||
"locationUserHint": "~/.claude/skills/",
|
||||
"mode": "创建方式",
|
||||
"modeImport": "导入文件夹",
|
||||
"modeImportHint": "从现有文件夹导入技能",
|
||||
"modeGenerate": "AI 生成",
|
||||
"modeGenerateHint": "使用 AI 生成技能",
|
||||
"sourcePath": "源文件夹路径",
|
||||
"sourcePathPlaceholder": "输入技能文件夹的绝对路径",
|
||||
"sourcePathHint": "文件夹中需要包含 SKILL.md 文件",
|
||||
"customName": "自定义名称",
|
||||
"customNamePlaceholder": "留空则使用原始名称",
|
||||
"customNameHint": "可选,用于覆盖默认技能名称",
|
||||
"skillName": "技能名称",
|
||||
"skillNamePlaceholder": "输入技能名称",
|
||||
"skillNameHint": "用作技能文件夹名称",
|
||||
"descriptionLabel": "技能描述",
|
||||
"descriptionPlaceholder": "描述这个技能应该做什么...",
|
||||
"descriptionHint": "AI 将根据描述生成技能内容",
|
||||
"generateInfo": "AI 将使用 CLI 工具生成技能",
|
||||
"generateTimeHint": "生成过程可能需要一些时间",
|
||||
"validate": "验证",
|
||||
"import": "导入",
|
||||
"generate": "生成",
|
||||
"validating": "验证中...",
|
||||
"validSkill": "验证通过",
|
||||
"invalidSkill": "验证失败",
|
||||
"creating": "创建中...",
|
||||
"created": "技能 \"{name}\" 创建成功",
|
||||
"createError": "创建技能失败",
|
||||
"sourcePathRequired": "请输入源文件夹路径",
|
||||
"skillNameRequired": "请输入技能名称",
|
||||
"descriptionRequired": "请输入技能描述",
|
||||
"validateFirst": "请先验证技能文件夹"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
Trash2,
|
||||
ChevronDown,
|
||||
ChevronUp,
|
||||
BookmarkPlus,
|
||||
} from 'lucide-react';
|
||||
import { Card } from '@/components/ui/Card';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
@@ -29,20 +30,21 @@ import { McpServerDialog } from '@/components/mcp/McpServerDialog';
|
||||
import { CliModeToggle, type CliMode } from '@/components/mcp/CliModeToggle';
|
||||
import { CodexMcpEditableCard } from '@/components/mcp/CodexMcpEditableCard';
|
||||
import { CcwToolsMcpCard } from '@/components/mcp/CcwToolsMcpCard';
|
||||
import { McpTemplatesSection } from '@/components/mcp/McpTemplatesSection';
|
||||
import { McpTemplatesSection, TemplateSaveDialog } from '@/components/mcp/McpTemplatesSection';
|
||||
import { RecommendedMcpSection } from '@/components/mcp/RecommendedMcpSection';
|
||||
import { WindowsCompatibilityWarning } from '@/components/mcp/WindowsCompatibilityWarning';
|
||||
import { CrossCliCopyButton } from '@/components/mcp/CrossCliCopyButton';
|
||||
import { AllProjectsTable } from '@/components/mcp/AllProjectsTable';
|
||||
import { OtherProjectsSection } from '@/components/mcp/OtherProjectsSection';
|
||||
import { TabsNavigation } from '@/components/ui/TabsNavigation';
|
||||
import { useMcpServers, useMcpServerMutations } from '@/hooks';
|
||||
import { useMcpServers, useMcpServerMutations, useNotifications } from '@/hooks';
|
||||
import {
|
||||
fetchCodexMcpServers,
|
||||
fetchCcwMcpConfig,
|
||||
updateCcwConfig,
|
||||
codexRemoveServer,
|
||||
codexToggleServer,
|
||||
saveMcpTemplate,
|
||||
type McpServer,
|
||||
type CcwMcpConfig,
|
||||
} from '@/lib/api';
|
||||
@@ -57,9 +59,10 @@ interface McpServerCardProps {
|
||||
onToggle: (serverName: string, enabled: boolean) => void;
|
||||
onEdit: (server: McpServer) => void;
|
||||
onDelete: (server: McpServer) => void;
|
||||
onSaveAsTemplate: (server: McpServer) => void;
|
||||
}
|
||||
|
||||
function McpServerCard({ server, isExpanded, onToggleExpand, onToggle, onEdit, onDelete }: McpServerCardProps) {
|
||||
function McpServerCard({ server, isExpanded, onToggleExpand, onToggle, onEdit, onDelete, onSaveAsTemplate }: McpServerCardProps) {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
return (
|
||||
@@ -115,6 +118,18 @@ function McpServerCard({ server, isExpanded, onToggleExpand, onToggle, onEdit, o
|
||||
>
|
||||
{server.enabled ? <Power className="w-4 h-4 text-green-600" /> : <PowerOff className="w-4 h-4" />}
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-8 w-8 p-0"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onSaveAsTemplate(server);
|
||||
}}
|
||||
title={formatMessage({ id: 'mcp.templates.actions.saveAsTemplate' })}
|
||||
>
|
||||
<BookmarkPlus className="w-4 h-4 text-primary" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
@@ -206,6 +221,10 @@ export function McpManagerPage() {
|
||||
const [editingServer, setEditingServer] = useState<McpServer | undefined>(undefined);
|
||||
const [cliMode, setCliMode] = useState<CliMode>('claude');
|
||||
const [codexExpandedServers, setCodexExpandedServers] = useState<Set<string>>(new Set());
|
||||
const [saveTemplateDialogOpen, setSaveTemplateDialogOpen] = useState(false);
|
||||
const [serverToSaveAsTemplate, setServerToSaveAsTemplate] = useState<McpServer | undefined>(undefined);
|
||||
|
||||
const notifications = useNotifications();
|
||||
|
||||
const {
|
||||
servers,
|
||||
@@ -269,9 +288,22 @@ export function McpManagerPage() {
|
||||
toggleServer(serverName, enabled);
|
||||
};
|
||||
|
||||
const handleDelete = (server: McpServer) => {
|
||||
const handleDelete = async (server: McpServer) => {
|
||||
if (confirm(formatMessage({ id: 'mcp.deleteConfirm' }, { name: server.name }))) {
|
||||
deleteServer(server.name, server.scope);
|
||||
try {
|
||||
await deleteServer(server.name, server.scope);
|
||||
notifications.success(
|
||||
formatMessage({ id: 'mcp.actions.delete' }),
|
||||
server.name
|
||||
);
|
||||
refetch();
|
||||
} catch (error) {
|
||||
console.error('Failed to delete MCP server:', error);
|
||||
notifications.error(
|
||||
formatMessage({ id: 'mcp.actions.delete' }),
|
||||
error instanceof Error ? error.message : String(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -339,19 +371,64 @@ export function McpManagerPage() {
|
||||
setDialogOpen(true);
|
||||
};
|
||||
|
||||
const handleSaveAsTemplate = (serverName: string, config: { command: string; args: string[] }) => {
|
||||
// This would open a dialog to save current server as template
|
||||
// For now, just log it
|
||||
console.log('Save as template:', serverName, config);
|
||||
const handleSaveServerAsTemplate = (server: McpServer) => {
|
||||
setServerToSaveAsTemplate(server);
|
||||
setSaveTemplateDialogOpen(true);
|
||||
};
|
||||
|
||||
const handleSaveAsTemplate = async (
|
||||
name: string,
|
||||
category: string,
|
||||
description: string,
|
||||
serverConfig: { command: string; args: string[]; env: Record<string, string> },
|
||||
) => {
|
||||
try {
|
||||
const result = await saveMcpTemplate({
|
||||
name,
|
||||
description: description || undefined,
|
||||
category: category || 'custom',
|
||||
serverConfig: {
|
||||
command: serverConfig.command,
|
||||
args: serverConfig.args.length > 0 ? serverConfig.args : undefined,
|
||||
env: Object.keys(serverConfig.env).length > 0 ? serverConfig.env : undefined,
|
||||
},
|
||||
});
|
||||
if (result.success) {
|
||||
notifications.success(
|
||||
formatMessage({ id: 'mcp.templates.feedback.saveSuccess' }),
|
||||
name
|
||||
);
|
||||
setSaveTemplateDialogOpen(false);
|
||||
setServerToSaveAsTemplate(undefined);
|
||||
} else {
|
||||
notifications.error(
|
||||
formatMessage({ id: 'mcp.templates.feedback.saveError' }),
|
||||
result.error || ''
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
notifications.error(
|
||||
formatMessage({ id: 'mcp.templates.feedback.saveError' }),
|
||||
error instanceof Error ? error.message : String(error)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Codex MCP handlers
|
||||
const handleCodexRemove = async (serverName: string) => {
|
||||
try {
|
||||
await codexRemoveServer(serverName);
|
||||
notifications.success(
|
||||
formatMessage({ id: 'mcp.actions.delete' }),
|
||||
serverName
|
||||
);
|
||||
codexQuery.refetch();
|
||||
} catch (error) {
|
||||
console.error('Failed to remove Codex MCP server:', error);
|
||||
notifications.error(
|
||||
formatMessage({ id: 'mcp.actions.delete' }),
|
||||
error instanceof Error ? error.message : String(error)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -592,6 +669,7 @@ export function McpManagerPage() {
|
||||
onToggle={handleToggle}
|
||||
onEdit={handleEdit}
|
||||
onDelete={handleDelete}
|
||||
onSaveAsTemplate={handleSaveServerAsTemplate}
|
||||
/>
|
||||
)
|
||||
))}
|
||||
@@ -646,6 +724,20 @@ export function McpManagerPage() {
|
||||
onSave={handleDialogSave}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Save as Template Dialog */}
|
||||
<TemplateSaveDialog
|
||||
open={saveTemplateDialogOpen}
|
||||
onClose={() => {
|
||||
setSaveTemplateDialogOpen(false);
|
||||
setServerToSaveAsTemplate(undefined);
|
||||
}}
|
||||
onSave={handleSaveAsTemplate}
|
||||
defaultName={serverToSaveAsTemplate?.name}
|
||||
defaultCommand={serverToSaveAsTemplate?.command}
|
||||
defaultArgs={serverToSaveAsTemplate?.args}
|
||||
defaultEnv={serverToSaveAsTemplate?.env as Record<string, string>}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ import {
|
||||
ChevronUp,
|
||||
Languages,
|
||||
Plus,
|
||||
MessageSquareText,
|
||||
Monitor,
|
||||
Terminal,
|
||||
AlertTriangle,
|
||||
} from 'lucide-react';
|
||||
import { Card } from '@/components/ui/Card';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
@@ -29,6 +33,17 @@ import { useConfigStore, selectCliTools, selectDefaultCliTool, selectUserPrefere
|
||||
import type { CliToolConfig, UserPreferences } from '@/types/store';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { LanguageSwitcher } from '@/components/layout/LanguageSwitcher';
|
||||
import {
|
||||
useChineseResponseStatus,
|
||||
useToggleChineseResponse,
|
||||
useWindowsPlatformStatus,
|
||||
useToggleWindowsPlatform,
|
||||
useCodexCliEnhancementStatus,
|
||||
useToggleCodexCliEnhancement,
|
||||
useRefreshCodexCliEnhancement,
|
||||
useCcwInstallStatus,
|
||||
useCliToolStatus,
|
||||
} from '@/hooks/useSystemSettings';
|
||||
|
||||
// ========== CLI Tool Card Component ==========
|
||||
|
||||
@@ -37,6 +52,7 @@ interface CliToolCardProps {
|
||||
config: CliToolConfig;
|
||||
isDefault: boolean;
|
||||
isExpanded: boolean;
|
||||
toolAvailable?: boolean;
|
||||
onToggleExpand: () => void;
|
||||
onToggleEnabled: () => void;
|
||||
onSetDefault: () => void;
|
||||
@@ -51,6 +67,7 @@ function CliToolCard({
|
||||
config,
|
||||
isDefault,
|
||||
isExpanded,
|
||||
toolAvailable,
|
||||
onToggleExpand,
|
||||
onToggleEnabled,
|
||||
onSetDefault,
|
||||
@@ -125,6 +142,12 @@ function CliToolCard({
|
||||
<Badge variant="default" className="text-xs">{formatMessage({ id: 'settings.cliTools.default' })}</Badge>
|
||||
)}
|
||||
<Badge variant="outline" className="text-xs">{config.type}</Badge>
|
||||
{toolAvailable !== undefined && (
|
||||
<span className={cn(
|
||||
'inline-block w-2 h-2 rounded-full',
|
||||
toolAvailable ? 'bg-green-500' : 'bg-red-400'
|
||||
)} title={toolAvailable ? 'Available' : 'Unavailable'} />
|
||||
)}
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-0.5">
|
||||
{config.primaryModel}
|
||||
@@ -345,6 +368,266 @@ function CliToolCard({
|
||||
);
|
||||
}
|
||||
|
||||
// ========== Response Language Section ==========
|
||||
|
||||
function ResponseLanguageSection() {
|
||||
const { formatMessage } = useIntl();
|
||||
const { data: chineseStatus, isLoading: chineseLoading } = useChineseResponseStatus();
|
||||
const { toggle: toggleChinese, isPending: chineseToggling } = useToggleChineseResponse();
|
||||
const { data: windowsStatus, isLoading: windowsLoading } = useWindowsPlatformStatus();
|
||||
const { toggle: toggleWindows, isPending: windowsToggling } = useToggleWindowsPlatform();
|
||||
const { data: cliEnhStatus, isLoading: cliEnhLoading } = useCodexCliEnhancementStatus();
|
||||
const { toggle: toggleCliEnh, isPending: cliEnhToggling } = useToggleCodexCliEnhancement();
|
||||
const { refresh: refreshCliEnh, isPending: refreshing } = useRefreshCodexCliEnhancement();
|
||||
|
||||
return (
|
||||
<Card className="p-6">
|
||||
<h2 className="text-lg font-semibold text-foreground flex items-center gap-2 mb-4">
|
||||
<MessageSquareText className="w-5 h-5" />
|
||||
{formatMessage({ id: 'settings.sections.responseLanguage' })}
|
||||
</h2>
|
||||
<div className="grid gap-4 md:grid-cols-2">
|
||||
{/* Chinese Response - Claude */}
|
||||
<div className="rounded-lg border border-border p-4 space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm font-medium">{formatMessage({ id: 'settings.responseLanguage.chineseClaude' })}</span>
|
||||
<Badge variant="default" className="text-xs">Claude</Badge>
|
||||
</div>
|
||||
<Button
|
||||
variant={chineseStatus?.claudeEnabled ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
className="h-7"
|
||||
disabled={chineseLoading || chineseToggling}
|
||||
onClick={() => toggleChinese(!chineseStatus?.claudeEnabled, 'claude')}
|
||||
>
|
||||
{chineseStatus?.claudeEnabled
|
||||
? formatMessage({ id: 'settings.responseLanguage.enabled' })
|
||||
: formatMessage({ id: 'settings.responseLanguage.disabled' })}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{formatMessage({ id: 'settings.responseLanguage.chineseClaudeDesc' })}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Chinese Response - Codex */}
|
||||
<div className="rounded-lg border border-border p-4 space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm font-medium">{formatMessage({ id: 'settings.responseLanguage.chineseCodex' })}</span>
|
||||
<Badge variant="secondary" className="text-xs">Codex</Badge>
|
||||
</div>
|
||||
<Button
|
||||
variant={chineseStatus?.codexEnabled ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
className="h-7"
|
||||
disabled={chineseLoading || chineseToggling}
|
||||
onClick={() => toggleChinese(!chineseStatus?.codexEnabled, 'codex')}
|
||||
>
|
||||
{chineseStatus?.codexEnabled
|
||||
? formatMessage({ id: 'settings.responseLanguage.enabled' })
|
||||
: formatMessage({ id: 'settings.responseLanguage.disabled' })}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{formatMessage({ id: 'settings.responseLanguage.chineseCodexDesc' })}
|
||||
</p>
|
||||
{chineseStatus?.codexNeedsMigration && (
|
||||
<p className="text-xs text-yellow-500">
|
||||
<AlertTriangle className="w-3 h-3 inline mr-1" />
|
||||
{formatMessage({ id: 'settings.responseLanguage.migrationWarning' })}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Windows Platform */}
|
||||
<div className="rounded-lg border border-border p-4 space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<Monitor className="w-4 h-4 text-muted-foreground" />
|
||||
<span className="text-sm font-medium">{formatMessage({ id: 'settings.responseLanguage.windowsPlatform' })}</span>
|
||||
</div>
|
||||
<Button
|
||||
variant={windowsStatus?.enabled ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
className="h-7"
|
||||
disabled={windowsLoading || windowsToggling}
|
||||
onClick={() => toggleWindows(!windowsStatus?.enabled)}
|
||||
>
|
||||
{windowsStatus?.enabled
|
||||
? formatMessage({ id: 'settings.responseLanguage.enabled' })
|
||||
: formatMessage({ id: 'settings.responseLanguage.disabled' })}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{formatMessage({ id: 'settings.responseLanguage.windowsPlatformDesc' })}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* CLI Enhancement - Codex */}
|
||||
<div className="rounded-lg border border-border p-4 space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="w-4 h-4 text-muted-foreground" />
|
||||
<span className="text-sm font-medium">{formatMessage({ id: 'settings.responseLanguage.cliEnhancement' })}</span>
|
||||
<Badge variant="secondary" className="text-xs">Codex</Badge>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
{cliEnhStatus?.enabled && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-7 w-7 p-0"
|
||||
disabled={cliEnhLoading || refreshing}
|
||||
onClick={() => refreshCliEnh()}
|
||||
title={formatMessage({ id: 'settings.responseLanguage.refreshConfig' })}
|
||||
>
|
||||
<RefreshCw className={cn('w-3.5 h-3.5', refreshing && 'animate-spin')} />
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant={cliEnhStatus?.enabled ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
className="h-7"
|
||||
disabled={cliEnhLoading || cliEnhToggling}
|
||||
onClick={() => toggleCliEnh(!cliEnhStatus?.enabled)}
|
||||
>
|
||||
{cliEnhStatus?.enabled
|
||||
? formatMessage({ id: 'settings.responseLanguage.enabled' })
|
||||
: formatMessage({ id: 'settings.responseLanguage.disabled' })}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{formatMessage({ id: 'settings.responseLanguage.cliEnhancementDesc' })}
|
||||
</p>
|
||||
{cliEnhStatus?.enabled && (
|
||||
<p className="text-xs text-muted-foreground/70">
|
||||
{formatMessage({ id: 'settings.responseLanguage.cliEnhancementHint' })}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
// ========== System Status Section ==========
|
||||
|
||||
function SystemStatusSection() {
|
||||
const { formatMessage } = useIntl();
|
||||
const { data: ccwInstall, isLoading: installLoading } = useCcwInstallStatus();
|
||||
|
||||
// Don't show if installed or still loading
|
||||
if (installLoading || ccwInstall?.installed) return null;
|
||||
|
||||
return (
|
||||
<Card className="p-6 border-yellow-500/50">
|
||||
<h2 className="text-lg font-semibold text-foreground flex items-center gap-2 mb-4">
|
||||
<AlertTriangle className="w-5 h-5 text-yellow-500" />
|
||||
{formatMessage({ id: 'settings.systemStatus.title' })}
|
||||
</h2>
|
||||
|
||||
{/* CCW Install Status */}
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm font-medium">{formatMessage({ id: 'settings.systemStatus.ccwInstall' })}</span>
|
||||
<Badge variant="outline" className="text-yellow-500 border-yellow-500/50">
|
||||
{formatMessage({ id: 'settings.systemStatus.incomplete' })}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
{ccwInstall && ccwInstall.missingFiles.length > 0 && (
|
||||
<div className="space-y-2">
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{formatMessage({ id: 'settings.systemStatus.missingFiles' })}:
|
||||
</p>
|
||||
<ul className="text-xs text-muted-foreground/70 list-disc list-inside">
|
||||
{ccwInstall.missingFiles.slice(0, 5).map((file) => (
|
||||
<li key={file}>{file}</li>
|
||||
))}
|
||||
{ccwInstall.missingFiles.length > 5 && (
|
||||
<li>+{ccwInstall.missingFiles.length - 5} more...</li>
|
||||
)}
|
||||
</ul>
|
||||
<div className="bg-muted/50 rounded-md p-3 mt-2">
|
||||
<p className="text-xs font-medium mb-1">
|
||||
{formatMessage({ id: 'settings.systemStatus.runToFix' })}:
|
||||
</p>
|
||||
<code className="text-xs bg-background px-2 py-1 rounded block font-mono">
|
||||
ccw install
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
// ========== CLI Tools with Status Enhancement ==========
|
||||
|
||||
interface CliToolsWithStatusProps {
|
||||
cliTools: Record<string, CliToolConfig>;
|
||||
defaultCliTool: string;
|
||||
expandedTools: Set<string>;
|
||||
onToggleExpand: (toolId: string) => void;
|
||||
onToggleEnabled: (toolId: string) => void;
|
||||
onSetDefault: (toolId: string) => void;
|
||||
onUpdateModel: (toolId: string, field: 'primaryModel' | 'secondaryModel', value: string) => void;
|
||||
onUpdateTags: (toolId: string, tags: string[]) => void;
|
||||
onUpdateAvailableModels: (toolId: string, models: string[]) => void;
|
||||
onUpdateSettingsFile: (toolId: string, settingsFile: string | undefined) => void;
|
||||
formatMessage: ReturnType<typeof useIntl>['formatMessage'];
|
||||
}
|
||||
|
||||
function CliToolsWithStatus({
|
||||
cliTools,
|
||||
defaultCliTool,
|
||||
expandedTools,
|
||||
onToggleExpand,
|
||||
onToggleEnabled,
|
||||
onSetDefault,
|
||||
onUpdateModel,
|
||||
onUpdateTags,
|
||||
onUpdateAvailableModels,
|
||||
onUpdateSettingsFile,
|
||||
formatMessage,
|
||||
}: CliToolsWithStatusProps) {
|
||||
const { data: toolStatus } = useCliToolStatus();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className="text-sm text-muted-foreground mb-4">
|
||||
{formatMessage({ id: 'settings.cliTools.description' })} <strong className="text-foreground">{defaultCliTool}</strong>
|
||||
</p>
|
||||
<div className="space-y-3">
|
||||
{Object.entries(cliTools).map(([toolId, config]) => {
|
||||
const status = toolStatus?.[toolId];
|
||||
return (
|
||||
<CliToolCard
|
||||
key={toolId}
|
||||
toolId={toolId}
|
||||
config={config}
|
||||
isDefault={toolId === defaultCliTool}
|
||||
isExpanded={expandedTools.has(toolId)}
|
||||
toolAvailable={status?.available}
|
||||
onToggleExpand={() => onToggleExpand(toolId)}
|
||||
onToggleEnabled={() => onToggleEnabled(toolId)}
|
||||
onSetDefault={() => onSetDefault(toolId)}
|
||||
onUpdateModel={(field, value) => onUpdateModel(toolId, field, value)}
|
||||
onUpdateTags={(tags) => onUpdateTags(toolId, tags)}
|
||||
onUpdateAvailableModels={(models) => onUpdateAvailableModels(toolId, models)}
|
||||
onUpdateSettingsFile={(settingsFile) => onUpdateSettingsFile(toolId, settingsFile)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// ========== Main Page Component ==========
|
||||
|
||||
export function SettingsPage() {
|
||||
@@ -466,33 +749,31 @@ export function SettingsPage() {
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Response Language Settings */}
|
||||
<ResponseLanguageSection />
|
||||
|
||||
{/* System Status */}
|
||||
<SystemStatusSection />
|
||||
|
||||
{/* CLI Tools Configuration */}
|
||||
<Card className="p-6">
|
||||
<h2 className="text-lg font-semibold text-foreground flex items-center gap-2 mb-4">
|
||||
<Cpu className="w-5 h-5" />
|
||||
{formatMessage({ id: 'settings.sections.cliTools' })}
|
||||
</h2>
|
||||
<p className="text-sm text-muted-foreground mb-4">
|
||||
{formatMessage({ id: 'settings.cliTools.description' })} <strong className="text-foreground">{defaultCliTool}</strong>
|
||||
</p>
|
||||
<div className="space-y-3">
|
||||
{Object.entries(cliTools).map(([toolId, config]) => (
|
||||
<CliToolCard
|
||||
key={toolId}
|
||||
toolId={toolId}
|
||||
config={config}
|
||||
isDefault={toolId === defaultCliTool}
|
||||
isExpanded={expandedTools.has(toolId)}
|
||||
onToggleExpand={() => toggleToolExpand(toolId)}
|
||||
onToggleEnabled={() => handleToggleToolEnabled(toolId)}
|
||||
onSetDefault={() => handleSetDefaultTool(toolId)}
|
||||
onUpdateModel={(field, value) => handleUpdateModel(toolId, field, value)}
|
||||
onUpdateTags={(tags) => handleUpdateTags(toolId, tags)}
|
||||
onUpdateAvailableModels={(models) => handleUpdateAvailableModels(toolId, models)}
|
||||
onUpdateSettingsFile={(settingsFile) => handleUpdateSettingsFile(toolId, settingsFile)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<CliToolsWithStatus
|
||||
cliTools={cliTools}
|
||||
defaultCliTool={defaultCliTool}
|
||||
expandedTools={expandedTools}
|
||||
onToggleExpand={toggleToolExpand}
|
||||
onToggleEnabled={handleToggleToolEnabled}
|
||||
onSetDefault={handleSetDefaultTool}
|
||||
onUpdateModel={handleUpdateModel}
|
||||
onUpdateTags={handleUpdateTags}
|
||||
onUpdateAvailableModels={handleUpdateAvailableModels}
|
||||
onUpdateSettingsFile={handleUpdateSettingsFile}
|
||||
formatMessage={formatMessage}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
{/* Data Refresh Settings */}
|
||||
|
||||
@@ -38,7 +38,7 @@ import {
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
} from '@/components/ui';
|
||||
import { SkillCard, SkillDetailPanel } from '@/components/shared';
|
||||
import { SkillCard, SkillDetailPanel, SkillCreateDialog } from '@/components/shared';
|
||||
import { useSkills, useSkillMutations } from '@/hooks';
|
||||
import { fetchSkillDetail } from '@/lib/api';
|
||||
import { useWorkflowStore, selectProjectPath } from '@/stores/workflowStore';
|
||||
@@ -118,6 +118,9 @@ export function SkillsManagerPage() {
|
||||
const [confirmDisable, setConfirmDisable] = useState<{ skill: Skill; enable: boolean } | null>(null);
|
||||
const [locationFilter, setLocationFilter] = useState<'project' | 'user'>('project');
|
||||
|
||||
// Skill create dialog state
|
||||
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
|
||||
|
||||
// Skill detail panel state
|
||||
const [selectedSkill, setSelectedSkill] = useState<Skill | null>(null);
|
||||
const [isDetailLoading, setIsDetailLoading] = useState(false);
|
||||
@@ -243,7 +246,7 @@ export function SkillsManagerPage() {
|
||||
<RefreshCw className={cn('w-4 h-4 mr-2', isFetching && 'animate-spin')} />
|
||||
{formatMessage({ id: 'common.actions.refresh' })}
|
||||
</Button>
|
||||
<Button>
|
||||
<Button onClick={() => setIsCreateDialogOpen(true)}>
|
||||
<Plus className="w-4 h-4 mr-2" />
|
||||
{formatMessage({ id: 'skills.actions.install' })}
|
||||
</Button>
|
||||
@@ -470,6 +473,13 @@ export function SkillsManagerPage() {
|
||||
onClose={handleCloseDetailPanel}
|
||||
isLoading={isDetailLoading}
|
||||
/>
|
||||
|
||||
{/* Skill Create Dialog */}
|
||||
<SkillCreateDialog
|
||||
open={isCreateDialogOpen}
|
||||
onOpenChange={setIsCreateDialogOpen}
|
||||
onCreated={() => refetch()}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -726,13 +726,23 @@ function toggleMcpServerEnabled(projectPath: string, serverName: string, enable:
|
||||
const content = readFileSync(CLAUDE_CONFIG_PATH, 'utf8');
|
||||
const config = JSON.parse(content);
|
||||
|
||||
const normalizedPath = normalizeProjectPathForConfig(projectPath, config);
|
||||
|
||||
if (!config.projects || !config.projects[normalizedPath]) {
|
||||
return { error: `Project not found: ${normalizedPath}` };
|
||||
// Find matching project key by normalizing both input and config keys
|
||||
const normalizedInput = normalizeProjectPathForConfig(projectPath, config);
|
||||
let matchedKey: string | null = null;
|
||||
if (config.projects) {
|
||||
for (const key of Object.keys(config.projects)) {
|
||||
if (normalizeProjectPathForConfig(key) === normalizedInput) {
|
||||
matchedKey = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const projectConfig = config.projects[normalizedPath];
|
||||
if (!matchedKey || !config.projects[matchedKey]) {
|
||||
return { error: `Project not found: ${normalizedInput}` };
|
||||
}
|
||||
|
||||
const projectConfig = config.projects[matchedKey];
|
||||
|
||||
// Ensure disabledMcpServers array exists
|
||||
if (!projectConfig.disabledMcpServers) {
|
||||
@@ -865,11 +875,20 @@ function removeMcpServerFromProject(projectPath: string, serverName: string) {
|
||||
const content = readFileSync(CLAUDE_CONFIG_PATH, 'utf8');
|
||||
const config = JSON.parse(content);
|
||||
|
||||
// Get normalized path that matches existing config format
|
||||
const normalizedPath = normalizeProjectPathForConfig(projectPath, config);
|
||||
// Find matching project key by normalizing both input path and config keys
|
||||
const normalizedInput = normalizeProjectPathForConfig(projectPath, config);
|
||||
let matchedKey: string | null = null;
|
||||
if (config.projects) {
|
||||
for (const key of Object.keys(config.projects)) {
|
||||
if (normalizeProjectPathForConfig(key) === normalizedInput) {
|
||||
matchedKey = key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.projects && config.projects[normalizedPath]) {
|
||||
const projectConfig = config.projects[normalizedPath];
|
||||
if (matchedKey && config.projects[matchedKey]) {
|
||||
const projectConfig = config.projects[matchedKey];
|
||||
|
||||
if (projectConfig.mcpServers && projectConfig.mcpServers[serverName]) {
|
||||
// Remove the server
|
||||
|
||||
Reference in New Issue
Block a user