diff --git a/ccw/docs-site/.docusaurus/registry.js b/ccw/docs-site/.docusaurus/registry.js index 440b1fda..1935039b 100644 --- a/ccw/docs-site/.docusaurus/registry.js +++ b/ccw/docs-site/.docusaurus/registry.js @@ -1,38 +1,46 @@ export default { - "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")], - "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")], - "186dcf4e": [() => import(/* webpackChunkName: "186dcf4e" */ "@site/docs/workflows/level-5-intelligent.mdx"), "@site/docs/workflows/level-5-intelligent.mdx", require.resolveWeak("@site/docs/workflows/level-5-intelligent.mdx")], - "18891827": [() => import(/* webpackChunkName: "18891827" */ "@site/docs/overview.mdx"), "@site/docs/overview.mdx", require.resolveWeak("@site/docs/overview.mdx")], - "19b64556": [() => import(/* webpackChunkName: "19b64556" */ "@site/docs/workflows/level-2-rapid.mdx"), "@site/docs/workflows/level-2-rapid.mdx", require.resolveWeak("@site/docs/workflows/level-2-rapid.mdx")], - "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")], - "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")], - "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")], - "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")], - "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")], - "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")], - "9f4ca91e": [() => import(/* webpackChunkName: "9f4ca91e" */ "@site/docs/workflows/introduction.mdx"), "@site/docs/workflows/introduction.mdx", require.resolveWeak("@site/docs/workflows/introduction.mdx")], - "a2065270": [() => import(/* webpackChunkName: "a2065270" */ "@generated/docusaurus-plugin-content-docs/default/p/docs-docs-fbb.json"), "@generated/docusaurus-plugin-content-docs/default/p/docs-docs-fbb.json", require.resolveWeak("@generated/docusaurus-plugin-content-docs/default/p/docs-docs-fbb.json")], - "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")], - "bcf6b37c": [() => import(/* webpackChunkName: "bcf6b37c" */ "@site/docs/workflows/faq.mdx"), "@site/docs/workflows/faq.mdx", require.resolveWeak("@site/docs/workflows/faq.mdx")], - "bdb2b105": [() => import(/* webpackChunkName: "bdb2b105" */ "@site/docs/workflows/level-3-standard.mdx"), "@site/docs/workflows/level-3-standard.mdx", require.resolveWeak("@site/docs/workflows/level-3-standard.mdx")], - "c5a82d8d": [() => import(/* webpackChunkName: "c5a82d8d" */ "@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")], - "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")], - "d045285b": [() => import(/* webpackChunkName: "d045285b" */ "@site/docs/workflows/level-4-brainstorm.mdx"), "@site/docs/workflows/level-4-brainstorm.mdx", require.resolveWeak("@site/docs/workflows/level-4-brainstorm.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")], - "ea313555": [() => import(/* webpackChunkName: "ea313555" */ "@site/docs/faq.mdx"), "@site/docs/faq.mdx", require.resolveWeak("@site/docs/faq.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")],}; + "__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-docsa-20-f19": [() => import(/* webpackChunkName: "__props---docs-docsa-20-f19" */ "@generated/docusaurus-plugin-content-docs/default/p/docs-docs-fbb.json"), "@generated/docusaurus-plugin-content-docs/default/p/docs-docs-fbb.json", require.resolveWeak("@generated/docusaurus-plugin-content-docs/default/p/docs-docs-fbb.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-docs-commands-cli-cli-init-056-2d3": [() => import(/* webpackChunkName: "content---docs-docs-commands-cli-cli-init-056-2d3" */ "@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-docs-commands-cli-codex-reviewf-1-b-532": [() => import(/* webpackChunkName: "content---docs-docs-commands-cli-codex-reviewf-1-b-532" */ "@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-docs-commands-general-ccw-coordinatord-55-a04": [() => import(/* webpackChunkName: "content---docs-docs-commands-general-ccw-coordinatord-55-a04" */ "@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-docs-commands-general-ccw-debug-97-c-2c8": [() => import(/* webpackChunkName: "content---docs-docs-commands-general-ccw-debug-97-c-2c8" */ "@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-docs-commands-general-ccw-plan-04-d-aa3": [() => import(/* webpackChunkName: "content---docs-docs-commands-general-ccw-plan-04-d-aa3" */ "@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-docs-commands-general-ccw-testcce-a5d": [() => import(/* webpackChunkName: "content---docs-docs-commands-general-ccw-testcce-a5d" */ "@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-docs-commands-general-ccwf-48-4f9": [() => import(/* webpackChunkName: "content---docs-docs-commands-general-ccwf-48-4f9" */ "@site/docs/commands/general/ccw.mdx"), "@site/docs/commands/general/ccw.mdx", require.resolveWeak("@site/docs/commands/general/ccw.mdx")], + "content---docs-docs-commands-general-codex-coordinatorf-92-965": [() => import(/* webpackChunkName: "content---docs-docs-commands-general-codex-coordinatorf-92-965" */ "@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-docs-commands-general-flow-createfab-5a7": [() => import(/* webpackChunkName: "content---docs-docs-commands-general-flow-createfab-5a7" */ "@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-docs-commands-issue-issue-convert-to-plan-5-c-7-428": [() => import(/* webpackChunkName: "content---docs-docs-commands-issue-issue-convert-to-plan-5-c-7-428" */ "@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-docs-commands-issue-issue-discover-1-e-3-61d": [() => import(/* webpackChunkName: "content---docs-docs-commands-issue-issue-discover-1-e-3-61d" */ "@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-docs-commands-issue-issue-executefe-8-121": [() => import(/* webpackChunkName: "content---docs-docs-commands-issue-issue-executefe-8-121" */ "@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-docs-commands-issue-issue-from-brainstorm-2-ec-ca5": [() => import(/* webpackChunkName: "content---docs-docs-commands-issue-issue-from-brainstorm-2-ec-ca5" */ "@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-docs-commands-issue-issue-new-4-ad-afb": [() => import(/* webpackChunkName: "content---docs-docs-commands-issue-issue-new-4-ad-afb" */ "@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-docs-commands-issue-issue-plana-6-c-1b0": [() => import(/* webpackChunkName: "content---docs-docs-commands-issue-issue-plana-6-c-1b0" */ "@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-docs-commands-issue-issue-queue-1-ba-06f": [() => import(/* webpackChunkName: "content---docs-docs-commands-issue-issue-queue-1-ba-06f" */ "@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-docs-commands-memory-memory-compact-7-a-1-f85": [() => import(/* webpackChunkName: "content---docs-docs-commands-memory-memory-compact-7-a-1-f85" */ "@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-docs-commands-memory-memory-docs-full-cli-4-cc-b15": [() => import(/* webpackChunkName: "content---docs-docs-commands-memory-memory-docs-full-cli-4-cc-b15" */ "@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-docs-commands-memory-memory-docs-related-cli-60-e-28a": [() => import(/* webpackChunkName: "content---docs-docs-commands-memory-memory-docs-related-cli-60-e-28a" */ "@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-docs-commands-memory-memory-load-157-920": [() => import(/* webpackChunkName: "content---docs-docs-commands-memory-memory-load-157-920" */ "@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-docs-commands-memory-memory-update-full-666-28e": [() => import(/* webpackChunkName: "content---docs-docs-commands-memory-memory-update-full-666-28e" */ "@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-docs-commands-memory-memory-update-related-611-f0a": [() => import(/* webpackChunkName: "content---docs-docs-commands-memory-memory-update-related-611-f0a" */ "@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-docs-faqea-3-29f": [() => import(/* webpackChunkName: "content---docs-docs-faqea-3-29f" */ "@site/docs/faq.mdx"), "@site/docs/faq.mdx", require.resolveWeak("@site/docs/faq.mdx")], + "content---docs-docs-overview-188-8fe": [() => import(/* webpackChunkName: "content---docs-docs-overview-188-8fe" */ "@site/docs/overview.mdx"), "@site/docs/overview.mdx", require.resolveWeak("@site/docs/overview.mdx")], + "content---docs-docs-workflows-faqbcf-a47": [() => import(/* webpackChunkName: "content---docs-docs-workflows-faqbcf-a47" */ "@site/docs/workflows/faq.mdx"), "@site/docs/workflows/faq.mdx", require.resolveWeak("@site/docs/workflows/faq.mdx")], + "content---docs-docs-workflows-introduction-9-f-4-dba": [() => import(/* webpackChunkName: "content---docs-docs-workflows-introduction-9-f-4-dba" */ "@site/docs/workflows/introduction.mdx"), "@site/docs/workflows/introduction.mdx", require.resolveWeak("@site/docs/workflows/introduction.mdx")], + "content---docs-docs-workflows-level-1-ultra-lightweightc-5-a-692": [() => import(/* webpackChunkName: "content---docs-docs-workflows-level-1-ultra-lightweightc-5-a-692" */ "@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-docs-workflows-level-2-rapid-19-b-a2f": [() => import(/* webpackChunkName: "content---docs-docs-workflows-level-2-rapid-19-b-a2f" */ "@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-docs-workflows-level-3-standardbdb-19a": [() => import(/* webpackChunkName: "content---docs-docs-workflows-level-3-standardbdb-19a" */ "@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-docs-workflows-level-4-brainstormd-04-69a": [() => import(/* webpackChunkName: "content---docs-docs-workflows-level-4-brainstormd-04-69a" */ "@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-docs-workflows-level-5-intelligent-186-435": [() => import(/* webpackChunkName: "content---docs-docs-workflows-level-5-intelligent-186-435" */ "@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-docsaba-31e": [() => import(/* webpackChunkName: "plugin---docs-docsaba-31e" */ "@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")],}; diff --git a/ccw/docs-site/.docusaurus/routes.js b/ccw/docs-site/.docusaurus/routes.js index d711bb5f..3d7e5278 100644 --- a/ccw/docs-site/.docusaurus/routes.js +++ b/ccw/docs-site/.docusaurus/routes.js @@ -2,6 +2,41 @@ import React from 'react'; 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/docs', component: ComponentCreator('/docs/docs', '942'), diff --git a/ccw/docs-site/.docusaurus/routesChunkNames.json b/ccw/docs-site/.docusaurus/routesChunkNames.json index 8f4104e8..e754b302 100644 --- a/ccw/docs-site/.docusaurus/routesChunkNames.json +++ b/ccw/docs-site/.docusaurus/routesChunkNames.json @@ -1,139 +1,182 @@ { - "/docs/docs-942": { - "__comp": "5e95c892", + "/docs/__docusaurus/debug-e58": { + "__comp": "__comp---theme-debug-config-23-a-2ff", "__context": { - "plugin": "aba21aa0" + "plugin": "plugin---docs-docusaurus-debugb-38-c84" + } + }, + "/docs/__docusaurus/debug/config-2ce": { + "__comp": "__comp---theme-debug-config-23-a-2ff", + "__context": { + "plugin": "plugin---docs-docusaurus-debugb-38-c84" + } + }, + "/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/__docusaurus/debug/globalData-f13": { + "__comp": "__comp---theme-debug-global-dataede-0fa", + "__context": { + "plugin": "plugin---docs-docusaurus-debugb-38-c84" + } + }, + "/docs/__docusaurus/debug/metadata-bff": { + "__comp": "__comp---theme-debug-site-metadata-68-e-3d4", + "__context": { + "plugin": "plugin---docs-docusaurus-debugb-38-c84" + } + }, + "/docs/__docusaurus/debug/registry-830": { + "__comp": "__comp---theme-debug-registry-679-501", + "__context": { + "plugin": "plugin---docs-docusaurus-debugb-38-c84" + } + }, + "/docs/__docusaurus/debug/routes-13e": { + "__comp": "__comp---theme-debug-routes-946-699", + "__context": { + "plugin": "plugin---docs-docusaurus-debugb-38-c84" + } + }, + "/docs/docs-942": { + "__comp": "__comp---theme-docs-root-5-e-9-0b6", + "__context": { + "plugin": "plugin---docs-docsaba-31e" } }, "/docs/docs-a90": { - "__comp": "a7bd4aaa", - "__props": "a2065270" + "__comp": "__comp---theme-doc-version-roota-7-b-5de", + "__props": "__props---docs-docsa-20-f19" }, "/docs/docs-c2e": { - "__comp": "a94703ab" + "__comp": "__comp---theme-doc-roota-94-67a" }, "/docs/docs/commands/cli/cli-init-c74": { - "__comp": "17896441", - "content": "0566a0a8" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-cli-cli-init-056-2d3" }, "/docs/docs/commands/cli/codex-review-937": { - "__comp": "17896441", - "content": "f1bf82ec" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-cli-codex-reviewf-1-b-532" }, "/docs/docs/commands/general/ccw-3fb": { - "__comp": "17896441", - "content": "f4817052" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-general-ccwf-48-4f9" }, "/docs/docs/commands/general/ccw-coordinator-a90": { - "__comp": "17896441", - "content": "d550a629" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-general-ccw-coordinatord-55-a04" }, "/docs/docs/commands/general/ccw-debug-663": { - "__comp": "17896441", - "content": "97c6e66a" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-general-ccw-debug-97-c-2c8" }, "/docs/docs/commands/general/ccw-plan-40b": { - "__comp": "17896441", - "content": "04db0a2e" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-general-ccw-plan-04-d-aa3" }, "/docs/docs/commands/general/ccw-test-99d": { - "__comp": "17896441", - "content": "ccef5d0f" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-general-ccw-testcce-a5d" }, "/docs/docs/commands/general/codex-coordinator-996": { - "__comp": "17896441", - "content": "f9222419" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-general-codex-coordinatorf-92-965" }, "/docs/docs/commands/general/flow-create-d91": { - "__comp": "17896441", - "content": "fabaf1c8" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-general-flow-createfab-5a7" }, "/docs/docs/commands/issue/issue-convert-to-plan-d90": { - "__comp": "17896441", - "content": "5c7b2278" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-issue-issue-convert-to-plan-5-c-7-428" }, "/docs/docs/commands/issue/issue-discover-2a1": { - "__comp": "17896441", - "content": "1e3006f3" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-issue-issue-discover-1-e-3-61d" }, "/docs/docs/commands/issue/issue-execute-abb": { - "__comp": "17896441", - "content": "fe8e3dcf" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-issue-issue-executefe-8-121" }, "/docs/docs/commands/issue/issue-from-brainstorm-72b": { - "__comp": "17896441", - "content": "2ecf8b4a" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-issue-issue-from-brainstorm-2-ec-ca5" }, "/docs/docs/commands/issue/issue-new-c58": { - "__comp": "17896441", - "content": "4ad7db0f" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-issue-issue-new-4-ad-afb" }, "/docs/docs/commands/issue/issue-plan-fd2": { - "__comp": "17896441", - "content": "a6c3df16" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-issue-issue-plana-6-c-1b0" }, "/docs/docs/commands/issue/issue-queue-1ce": { - "__comp": "17896441", - "content": "1bac9067" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-issue-issue-queue-1-ba-06f" }, "/docs/docs/commands/memory/memory-compact-74c": { - "__comp": "17896441", - "content": "7a1ee27c" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-memory-memory-compact-7-a-1-f85" }, "/docs/docs/commands/memory/memory-docs-full-cli-7a4": { - "__comp": "17896441", - "content": "4cc74730" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-memory-memory-docs-full-cli-4-cc-b15" }, "/docs/docs/commands/memory/memory-docs-related-cli-fb4": { - "__comp": "17896441", - "content": "60eef997" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-memory-memory-docs-related-cli-60-e-28a" }, "/docs/docs/commands/memory/memory-load-c66": { - "__comp": "17896441", - "content": "157db180" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-memory-memory-load-157-920" }, "/docs/docs/commands/memory/memory-update-full-b80": { - "__comp": "17896441", - "content": "666bb1bf" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-memory-memory-update-full-666-28e" }, "/docs/docs/commands/memory/memory-update-related-f0d": { - "__comp": "17896441", - "content": "611877e1" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-commands-memory-memory-update-related-611-f0a" }, "/docs/docs/faq-4b2": { - "__comp": "17896441", - "content": "ea313555" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-faqea-3-29f" }, "/docs/docs/overview-7df": { - "__comp": "17896441", - "content": "18891827" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-overview-188-8fe" }, "/docs/docs/workflows/faq-f47": { - "__comp": "17896441", - "content": "bcf6b37c" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-workflows-faqbcf-a47" }, "/docs/docs/workflows/introduction-4cb": { - "__comp": "17896441", - "content": "9f4ca91e" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-workflows-introduction-9-f-4-dba" }, "/docs/docs/workflows/level-1-ultra-lightweight-5c4": { - "__comp": "17896441", - "content": "c5a82d8d" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-workflows-level-1-ultra-lightweightc-5-a-692" }, "/docs/docs/workflows/level-2-rapid-ad8": { - "__comp": "17896441", - "content": "19b64556" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-workflows-level-2-rapid-19-b-a2f" }, "/docs/docs/workflows/level-3-standard-3ea": { - "__comp": "17896441", - "content": "bdb2b105" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-workflows-level-3-standardbdb-19a" }, "/docs/docs/workflows/level-4-brainstorm-f4f": { - "__comp": "17896441", - "content": "d045285b" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-workflows-level-4-brainstormd-04-69a" }, "/docs/docs/workflows/level-5-intelligent-84a": { - "__comp": "17896441", - "content": "186dcf4e" + "__comp": "__comp---theme-doc-item-178-a40", + "content": "content---docs-docs-workflows-level-5-intelligent-186-435" } } \ No newline at end of file diff --git a/ccw/docs-site/.docusaurus/site-metadata.json b/ccw/docs-site/.docusaurus/site-metadata.json index 503133f5..085f2863 100644 --- a/ccw/docs-site/.docusaurus/site-metadata.json +++ b/ccw/docs-site/.docusaurus/site-metadata.json @@ -12,9 +12,9 @@ "name": "@docusaurus/plugin-content-pages", "version": "3.9.2" }, - "docusaurus-plugin-sitemap": { + "docusaurus-plugin-debug": { "type": "package", - "name": "@docusaurus/plugin-sitemap", + "name": "@docusaurus/plugin-debug", "version": "3.9.2" }, "docusaurus-plugin-svgr": { diff --git a/ccw/frontend/src/components/a2ui/A2UIPopupCard.tsx b/ccw/frontend/src/components/a2ui/A2UIPopupCard.tsx index 725d8fbd..e332376d 100644 --- a/ccw/frontend/src/components/a2ui/A2UIPopupCard.tsx +++ b/ccw/frontend/src/components/a2ui/A2UIPopupCard.tsx @@ -3,19 +3,22 @@ // ======================================== // Centered popup dialog for A2UI surfaces with minimalist design // Used for displayMode: 'popup' surfaces (e.g., ask_question) +// Supports markdown content parsing -import { useCallback, useEffect } from 'react'; +import { useCallback, useMemo } from 'react'; import { useIntl } from 'react-intl'; +import ReactMarkdown from 'react-markdown'; +import remarkGfm from 'remark-gfm'; import { Dialog, DialogContent, DialogHeader, DialogTitle, - DialogDescription, + DialogFooter, } from '@/components/ui/Dialog'; import { A2UIRenderer } from '@/packages/a2ui-runtime/renderer'; import { useNotificationStore } from '@/stores'; -import type { SurfaceUpdate } from '@/packages/a2ui-runtime/core/A2UITypes'; +import type { SurfaceUpdate, SurfaceComponent } from '@/packages/a2ui-runtime/core/A2UITypes'; import { cn } from '@/lib/utils'; // ========== Types ========== @@ -27,46 +30,146 @@ interface A2UIPopupCardProps { onClose: () => void; } +type QuestionType = 'confirm' | 'select' | 'multi-select' | 'input' | 'unknown'; + +// ========== Helpers ========== + +/** Get text content from A2UI Text component */ +function getTextContent(component: SurfaceComponent | undefined): string { + if (!component?.component) return ''; + const comp = component.component as any; + if (!comp?.Text?.text) return ''; + const text = comp.Text.text; + if ('literalString' in text) return text.literalString; + return ''; +} + +/** Detect question type from surface */ +function detectQuestionType(surface: SurfaceUpdate): QuestionType { + const state = surface.initialState as Record | undefined; + if (state?.questionType) { + return state.questionType as QuestionType; + } + // Fallback: detect from components + const hasCheckbox = surface.components.some((c) => 'Checkbox' in (c.component as any)); + const hasRadioGroup = surface.components.some((c) => 'RadioGroup' in (c.component as any)); + const hasDropdown = surface.components.some((c) => 'Dropdown' in (c.component as any)); + const hasTextField = surface.components.some((c) => 'TextField' in (c.component as any)); + const hasConfirmCancel = surface.components.some( + (c) => c.id === 'confirm-btn' || c.id === 'cancel-btn' + ); + + if (hasCheckbox) return 'multi-select'; + if (hasRadioGroup) return 'select'; + if (hasDropdown) return 'select'; + if (hasTextField) return 'input'; + if (hasConfirmCancel) return 'confirm'; + return 'unknown'; +} + +/** Check if component is an action button */ +function isActionButton(component: SurfaceComponent): boolean { + const comp = component.component as any; + return 'Button' in comp; +} + +// ========== Markdown Component ========== + +interface MarkdownContentProps { + content: string; + className?: string; +} + +function MarkdownContent({ content, className }: MarkdownContentProps) { + return ( +
+

{children}

, + ul: ({ children }) =>
    {children}
, + ol: ({ children }) =>
    {children}
, + li: ({ children }) =>
  • {children}
  • , + code: ({ children, className }) => { + const isInline = !className; + return isInline ? ( + {children} + ) : ( + + {children} + + ); + }, + a: ({ href, children }) => ( + + {children} + + ), + }} + > + {content} +
    +
    + ); +} + // ========== Component ========== export function A2UIPopupCard({ surface, onClose }: A2UIPopupCardProps) { const { formatMessage } = useIntl(); const sendA2UIAction = useNotificationStore((state) => state.sendA2UIAction); - // Extract title and description from surface components if available + // Detect question type + const questionType = useMemo(() => detectQuestionType(surface), [surface]); + + // Extract title, message, and description from surface components const titleComponent = surface.components.find( - (c) => c.id === 'title' && 'Text' in c.component - ); - const descriptionComponent = surface.components.find( - (c) => c.id === 'description' && 'Text' in c.component + (c) => c.id === 'title' && 'Text' in (c.component as any) ); const messageComponent = surface.components.find( - (c) => c.id === 'message' && 'Text' in c.component + (c) => c.id === 'message' && 'Text' in (c.component as any) + ); + const descriptionComponent = surface.components.find( + (c) => c.id === 'description' && 'Text' in (c.component as any) ); - // Get text content from component - const getTextContent = (component: any): string => { - if (!component?.component?.Text?.text) return ''; - const text = component.component.Text.text; - if ('literalString' in text) return text.literalString; - return ''; - }; + const title = + getTextContent(titleComponent) || + formatMessage({ id: 'askQuestion.defaultTitle', defaultMessage: 'Question' }); + const message = getTextContent(messageComponent); + const description = getTextContent(descriptionComponent); - const title = getTextContent(titleComponent) || - formatMessage({ id: 'askQuestion.defaultTitle' }) || - 'Question'; - const description = getTextContent(descriptionComponent) || getTextContent(messageComponent); + // Separate body components (interactive elements) from action buttons + const { bodyComponents, actionButtons } = useMemo(() => { + const body: SurfaceComponent[] = []; + const actions: SurfaceComponent[] = []; - // Filter out title/description components for body rendering - const bodyComponents = surface.components.filter( - (c) => c.id !== 'title' && c.id !== 'description' && c.id !== 'message' + for (const comp of surface.components) { + // Skip title, message, description + if (['title', 'message', 'description'].includes(comp.id)) continue; + + // Separate action buttons (confirm, cancel, submit) + if (isActionButton(comp) && ['confirm-btn', 'cancel-btn', 'submit-btn'].includes(comp.id)) { + actions.push(comp); + } else { + body.push(comp); + } + } + + return { bodyComponents: body, actionButtons: actions }; + }, [surface.components]); + + // Create surfaces for body and actions + const bodySurface: SurfaceUpdate = useMemo( + () => ({ ...surface, components: bodyComponents }), + [surface, bodyComponents] ); - // Create a surface subset for body rendering - const bodySurface: SurfaceUpdate = { - ...surface, - components: bodyComponents, - }; + const actionsSurface: SurfaceUpdate = useMemo( + () => ({ ...surface, components: actionButtons }), + [surface, actionButtons] + ); // Handle A2UI actions const handleAction = useCallback( @@ -75,7 +178,6 @@ export function A2UIPopupCard({ surface, onClose }: A2UIPopupCardProps) { sendA2UIAction(actionId, surface.surfaceId, params); // Check if this action should close the dialog - // (confirm, cancel, submit, answer actions typically resolve the question) const resolvingActions = ['confirm', 'cancel', 'submit', 'answer']; if (resolvingActions.includes(actionId)) { onClose(); @@ -88,7 +190,6 @@ export function A2UIPopupCard({ surface, onClose }: A2UIPopupCardProps) { const handleOpenChange = useCallback( (open: boolean) => { if (!open) { - // Send cancel action when closing via ESC or overlay sendA2UIAction('cancel', surface.surfaceId, { questionId: (surface.initialState as any)?.questionId, }); @@ -98,33 +199,93 @@ export function A2UIPopupCard({ surface, onClose }: A2UIPopupCardProps) { [sendA2UIAction, surface.surfaceId, onClose] ); + // Determine dialog width based on question type + const dialogWidth = useMemo(() => { + switch (questionType) { + case 'multi-select': + return 'sm:max-w-[480px]'; + case 'input': + return 'sm:max-w-[500px]'; + default: + return 'sm:max-w-[420px]'; + } + }, [questionType]); + return ( { + // Prevent closing when clicking outside + e.preventDefault(); + }} + onEscapeKeyDown={(e) => { + // Prevent closing with ESC key + e.preventDefault(); + }} > - - {title} + {/* Header */} + + {title} + {message && ( +
    + +
    + )} {description && ( - - {description} - +
    + +
    )}
    - {/* A2UI Surface Body */} -
    - -
    + {/* Body - Interactive elements */} + {bodyComponents.length > 0 && ( +
    + {questionType === 'multi-select' ? ( + // Render each checkbox individually for better control + bodyComponents.map((comp) => ( +
    + +
    + )) + ) : ( + + )} +
    + )} + + {/* Footer - Action buttons */} + {actionButtons.length > 0 && ( + +
    + {actionButtons.map((comp) => ( + + ))} +
    +
    + )}
    ); diff --git a/ccw/frontend/src/packages/a2ui-runtime/core/A2UITypes.ts b/ccw/frontend/src/packages/a2ui-runtime/core/A2UITypes.ts index e7ad91da..1d1c44d2 100644 --- a/ccw/frontend/src/packages/a2ui-runtime/core/A2UITypes.ts +++ b/ccw/frontend/src/packages/a2ui-runtime/core/A2UITypes.ts @@ -104,6 +104,19 @@ export const CheckboxComponentSchema = z.object({ }), }); +/** RadioGroup component - single selection from multiple options */ +export const RadioGroupComponentSchema = z.object({ + RadioGroup: z.object({ + options: z.array(z.object({ + label: TextContentSchema, + value: z.string(), + description: TextContentSchema.optional(), + })), + selectedValue: TextContentSchema.optional(), + onChange: ActionSchema, + }), +}); + /** Code block component */ export const CodeBlockComponentSchema = z.object({ CodeBlock: z.object({ @@ -160,6 +173,7 @@ export const ComponentSchema: z.ZodType = z.union([ TextFieldComponentSchema, TextAreaComponentSchema, CheckboxComponentSchema, + RadioGroupComponentSchema, CodeBlockComponentSchema, ProgressComponentSchema, CardComponentSchema, @@ -202,6 +216,7 @@ export type DropdownComponent = z.infer; export type TextFieldComponent = z.infer; export type TextAreaComponent = z.infer; export type CheckboxComponent = z.infer; +export type RadioGroupComponent = z.infer; export type CodeBlockComponent = z.infer; export type ProgressComponent = z.infer; export type CardComponent = z.infer; @@ -223,6 +238,7 @@ export type A2UIComponentType = | 'TextField' | 'TextArea' | 'Checkbox' + | 'RadioGroup' | 'CodeBlock' | 'Progress' | 'Card' diff --git a/ccw/frontend/src/packages/a2ui-runtime/renderer/components/A2UIRadioGroup.tsx b/ccw/frontend/src/packages/a2ui-runtime/renderer/components/A2UIRadioGroup.tsx new file mode 100644 index 00000000..1d8cf62d --- /dev/null +++ b/ccw/frontend/src/packages/a2ui-runtime/renderer/components/A2UIRadioGroup.tsx @@ -0,0 +1,83 @@ +// ======================================== +// A2UI RadioGroup Component Renderer +// ======================================== +// Maps A2UI RadioGroup component to shadcn/ui RadioGroup +// Used for single-select questions with visible options + +import React, { useState, useCallback } from 'react'; +import { RadioGroup, RadioGroupItem } from '@/components/ui/RadioGroup'; +import { Label } from '@/components/ui/Label'; +import type { ComponentRenderer } from '../../core/A2UIComponentRegistry'; +import { resolveLiteralOrBinding, resolveTextContent } from '../A2UIRenderer'; +import type { RadioGroupComponent } from '../../core/A2UITypes'; + +interface A2UIRadioGroupProps { + component: RadioGroupComponent; + state: Record; + onAction: (actionId: string, params: Record) => void | Promise; + resolveBinding: (binding: { path: string }) => unknown; +} + +/** + * A2UI RadioGroup Component Renderer + * Single selection from visible options with onChange handler + */ +export const A2UIRadioGroup: ComponentRenderer = ({ component, state, onAction, resolveBinding }) => { + const radioGroupComp = component as RadioGroupComponent; + const { RadioGroup: radioConfig } = radioGroupComp; + + // Resolve initial selected value from binding + const getInitialValue = (): string | undefined => { + if (!radioConfig.selectedValue) return undefined; + const resolved = resolveLiteralOrBinding(radioConfig.selectedValue, resolveBinding); + return resolved ? String(resolved) : undefined; + }; + + // Local state for controlled radio group + const [selectedValue, setSelectedValue] = useState(getInitialValue()); + + // Handle change with action dispatch + const handleChange = useCallback((newValue: string) => { + setSelectedValue(newValue); + + // Trigger action with new selected value + onAction(radioConfig.onChange.actionId, { + value: newValue, + ...(radioConfig.onChange.parameters || {}), + }); + }, [radioConfig.onChange, onAction]); + + return ( + + {radioConfig.options.map((option, idx) => { + const labelText = resolveTextContent(option.label, resolveBinding); + const descriptionText = option.description + ? resolveTextContent(option.description, resolveBinding) + : undefined; + + return ( +
    + +
    + + {descriptionText && ( + + {descriptionText} + + )} +
    +
    + ); + })} +
    + ); +}; diff --git a/ccw/frontend/src/packages/a2ui-runtime/renderer/components/index.tsx b/ccw/frontend/src/packages/a2ui-runtime/renderer/components/index.tsx index 684db562..efd47675 100644 --- a/ccw/frontend/src/packages/a2ui-runtime/renderer/components/index.tsx +++ b/ccw/frontend/src/packages/a2ui-runtime/renderer/components/index.tsx @@ -14,6 +14,7 @@ import { A2UIDropdown } from './A2UIDropdown'; import { A2UITextField } from './A2UITextField'; import { A2UITextArea } from './A2UITextArea'; import { A2UICheckbox } from './A2UICheckbox'; +import { A2UIRadioGroup } from './A2UIRadioGroup'; import { A2UIProgress } from './A2UIProgress'; import { A2UICard } from './A2UICard'; import { A2UICLIOutput } from './A2UICLIOutput'; @@ -27,6 +28,7 @@ a2uiRegistry.register('Dropdown' as A2UIComponentType, A2UIDropdown); a2uiRegistry.register('TextField' as A2UIComponentType, A2UITextField); a2uiRegistry.register('TextArea' as A2UIComponentType, A2UITextArea); a2uiRegistry.register('Checkbox' as A2UIComponentType, A2UICheckbox); +a2uiRegistry.register('RadioGroup' as A2UIComponentType, A2UIRadioGroup); a2uiRegistry.register('Progress' as A2UIComponentType, A2UIProgress); a2uiRegistry.register('Card' as A2UIComponentType, A2UICard); a2uiRegistry.register('CLIOutput' as A2UIComponentType, A2UICLIOutput); @@ -39,6 +41,7 @@ export * from './A2UIDropdown'; export * from './A2UITextField'; export * from './A2UITextArea'; export * from './A2UICheckbox'; +export * from './A2UIRadioGroup'; export * from './A2UIProgress'; export * from './A2UICard'; export * from './A2UICLIOutput'; diff --git a/ccw/frontend/src/stores/__tests__/notificationStore.test.ts b/ccw/frontend/src/stores/__tests__/notificationStore.test.ts index 143afc96..701367b0 100644 --- a/ccw/frontend/src/stores/__tests__/notificationStore.test.ts +++ b/ccw/frontend/src/stores/__tests__/notificationStore.test.ts @@ -6,7 +6,7 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { renderHook, act } from '@testing-library/react'; import { useNotificationStore } from '../notificationStore'; -import type { SurfaceUpdate } from '../packages/a2ui-runtime/core/A2UITypes'; +import type { SurfaceUpdate } from '../../packages/a2ui-runtime/core/A2UITypes'; describe('NotificationStore A2UI Methods', () => { beforeEach(() => { @@ -128,7 +128,7 @@ describe('NotificationStore A2UI Methods', () => { const { result } = renderHook(() => useNotificationStore()); - let notificationId: string; + let notificationId: string = ''; act(() => { notificationId = result.current.addA2UINotification(surface); }); @@ -312,7 +312,7 @@ describe('NotificationStore A2UI Methods', () => { surfaceId: 'question-1', title: 'Test Question', questions: [ - { id: 'q1', question: 'What is your name?', type: 'text', required: true }, + { id: 'q1', question: 'What is your name?', type: 'text' as const, required: true }, ], }; @@ -329,7 +329,7 @@ describe('NotificationStore A2UI Methods', () => { const mockQuestion = { surfaceId: 'question-1', title: 'Test', - questions: [{ id: 'q1', question: 'Test?', type: 'text' }], + questions: [{ id: 'q1', question: 'Test?', type: 'text' as const, required: true }], }; act(() => { @@ -353,7 +353,7 @@ describe('NotificationStore A2UI Methods', () => { const { result } = renderHook(() => useNotificationStore()); - let notificationId: string; + let notificationId: string = ''; act(() => { notificationId = result.current.addA2UINotification(surface); }); diff --git a/ccw/frontend/src/stores/notificationStore.ts b/ccw/frontend/src/stores/notificationStore.ts index 3dac520a..632665e3 100644 --- a/ccw/frontend/src/stores/notificationStore.ts +++ b/ccw/frontend/src/stores/notificationStore.ts @@ -349,7 +349,7 @@ export const useNotificationStore = create()( } }, - retryAction: async (actionKey: string, notificationId: string) => { + retryAction: async (actionKey: string) => { const state = get(); const actionState = state.actionStates.get(actionKey); diff --git a/ccw/frontend/vite.config.ts b/ccw/frontend/vite.config.ts index 24ec3d0f..f8db327d 100644 --- a/ccw/frontend/vite.config.ts +++ b/ccw/frontend/vite.config.ts @@ -8,8 +8,9 @@ const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) // Get base path from environment variable -// Always use VITE_BASE_URL if set (for both dev and production) -const basePath = process.env.VITE_BASE_URL || '/' +// Default to /react/ for development (CCW server proxies /react/* to Vite) +// Can be overridden by VITE_BASE_URL environment variable +const basePath = process.env.VITE_BASE_URL || '/react/' // https://vite.dev/config/ export default defineConfig({ diff --git a/ccw/src/commands/install.ts b/ccw/src/commands/install.ts index 2e44dbb1..30ee7686 100644 --- a/ccw/src/commands/install.ts +++ b/ccw/src/commands/install.ts @@ -1,4 +1,4 @@ -import { existsSync, mkdirSync, readdirSync, statSync, copyFileSync, readFileSync, writeFileSync, unlinkSync, rmdirSync, appendFileSync } from 'fs'; +import { existsSync, mkdirSync, readdirSync, statSync, copyFileSync, readFileSync, writeFileSync, unlinkSync, rmdirSync, appendFileSync, renameSync } from 'fs'; import { join, dirname, basename } from 'path'; import { homedir, platform } from 'os'; import { fileURLToPath } from 'url'; @@ -45,6 +45,145 @@ interface CopyResult { directories: number; } +// Disabled item tracking for install process +interface DisabledItem { + name: string; + path: string; + type: 'skill' | 'command'; +} + +interface DisabledItems { + skills: DisabledItem[]; + commands: DisabledItem[]; +} + +/** + * Scan for disabled skills and commands before installation + * Skills: look for SKILL.md.disabled files + * Commands: look for *.md.disabled files + */ +function scanDisabledItems(installPath: string, globalPath?: string): DisabledItems { + const result: DisabledItems = { skills: [], commands: [] }; + const pathsToScan = [installPath]; + if (globalPath && globalPath !== installPath) { + pathsToScan.push(globalPath); + } + + for (const basePath of pathsToScan) { + // Scan skills + const skillsDir = join(basePath, '.claude', 'skills'); + if (existsSync(skillsDir)) { + try { + const entries = readdirSync(skillsDir, { withFileTypes: true }); + for (const entry of entries) { + if (entry.isDirectory()) { + const disabledPath = join(skillsDir, entry.name, 'SKILL.md.disabled'); + if (existsSync(disabledPath)) { + result.skills.push({ + name: entry.name, + path: disabledPath, + type: 'skill' + }); + } + } + } + } catch { + // Ignore errors + } + } + + // Scan commands recursively + const commandsDir = join(basePath, '.claude', 'commands'); + if (existsSync(commandsDir)) { + scanDisabledCommandsRecursive(commandsDir, commandsDir, result.commands); + } + } + + return result; +} + +/** + * Recursively scan for disabled command files + */ +function scanDisabledCommandsRecursive(baseDir: string, currentDir: string, results: DisabledItem[]): void { + try { + const entries = readdirSync(currentDir, { withFileTypes: true }); + for (const entry of entries) { + const fullPath = join(currentDir, entry.name); + if (entry.isDirectory()) { + scanDisabledCommandsRecursive(baseDir, fullPath, results); + } else if (entry.isFile() && entry.name.endsWith('.md.disabled')) { + const relativePath = fullPath.substring(baseDir.length + 1); + const commandName = relativePath.replace(/\.disabled$/, ''); + results.push({ + name: commandName, + path: fullPath, + type: 'command' + }); + } + } + } catch { + // Ignore errors + } +} + +/** + * Restore disabled state after installation + * For each previously disabled item, if the enabled version exists, rename it back to disabled + */ +function restoreDisabledState( + disabledItems: DisabledItems, + installPath: string, + globalPath?: string +): { skillsRestored: number; commandsRestored: number } { + let skillsRestored = 0; + let commandsRestored = 0; + + // Restore skills + for (const skill of disabledItems.skills) { + // Determine which path this skill belongs to + const skillDir = dirname(skill.path); + const enabledPath = join(skillDir, 'SKILL.md'); + const disabledPath = join(skillDir, 'SKILL.md.disabled'); + + // If enabled version was installed, rename it to disabled + if (existsSync(enabledPath)) { + try { + // Remove old disabled file if it still exists (shouldn't, but be safe) + if (existsSync(disabledPath)) { + unlinkSync(disabledPath); + } + renameSync(enabledPath, disabledPath); + skillsRestored++; + } catch { + // Ignore errors + } + } + } + + // Restore commands + for (const command of disabledItems.commands) { + const enabledPath = command.path.replace(/\.disabled$/, ''); + const disabledPath = command.path; + + // If enabled version was installed, rename it to disabled + if (existsSync(enabledPath)) { + try { + // Remove old disabled file if it still exists + if (existsSync(disabledPath)) { + unlinkSync(disabledPath); + } + renameSync(enabledPath, disabledPath); + commandsRestored++; + } catch { + // Ignore errors + } + } + } + + return { skillsRestored, commandsRestored }; +} + // Get package root directory (ccw/src/commands -> ccw) function getPackageRoot(): string { return join(__dirname, '..', '..'); @@ -204,6 +343,14 @@ export async function installCommand(options: InstallOptions): Promise { } } + // Scan for disabled items before installation + const globalPath = mode === 'Path' ? homedir() : undefined; + const disabledItems = scanDisabledItems(installPath, globalPath); + const totalDisabled = disabledItems.skills.length + disabledItems.commands.length; + if (totalDisabled > 0) { + info(`Found ${totalDisabled} disabled items (${disabledItems.skills.length} skills, ${disabledItems.commands.length} commands)`); + } + // Create manifest const manifest = createManifest(mode, installPath); @@ -213,6 +360,7 @@ export async function installCommand(options: InstallOptions): Promise { let totalFiles = 0; let totalDirs = 0; + let restoreStats = { skillsRestored: 0, commandsRestored: 0 }; try { // For Path mode, install workflows to global first @@ -259,6 +407,15 @@ export async function installCommand(options: InstallOptions): Promise { spinner.succeed('Installation complete!'); + // Restore disabled state for previously disabled items + if (totalDisabled > 0) { + restoreStats = restoreDisabledState(disabledItems, installPath, globalPath); + const totalRestored = restoreStats.skillsRestored + restoreStats.commandsRestored; + if (totalRestored > 0) { + info(`Restored ${totalRestored} disabled items (${restoreStats.skillsRestored} skills, ${restoreStats.commandsRestored} commands)`); + } + } + } catch (err) { spinner.fail('Installation failed'); const errMsg = err as Error; @@ -290,6 +447,12 @@ export async function installCommand(options: InstallOptions): Promise { } } + // Add restore stats if any disabled items were restored + if (restoreStats.skillsRestored > 0 || restoreStats.commandsRestored > 0) { + const totalRestored = restoreStats.skillsRestored + restoreStats.commandsRestored; + summaryLines.push(chalk.gray(`Disabled state restored: ${totalRestored} items`)); + } + summaryLines.push(''); summaryLines.push(chalk.gray(`Manifest: ${basename(manifestPath)}`)); diff --git a/ccw/src/core/a2ui/A2UIWebSocketHandler.ts b/ccw/src/core/a2ui/A2UIWebSocketHandler.ts index 4d3117fc..721bed71 100644 --- a/ccw/src/core/a2ui/A2UIWebSocketHandler.ts +++ b/ccw/src/core/a2ui/A2UIWebSocketHandler.ts @@ -59,6 +59,7 @@ export class A2UIWebSocketHandler { }>(); private multiSelectSelections = new Map>(); + private singleSelectSelections = new Map(); private answerCallback?: (answer: QuestionAnswer) => boolean; @@ -107,6 +108,10 @@ export class A2UIWebSocketHandler { if (questionType === 'multi-select') { // Selection state is updated via a2ui-action messages ("toggle") and resolved on "submit" this.multiSelectSelections.set(questionId, new Set()); + } else if (questionType === 'select') { + // Single selection state is updated via a2ui-action messages ("select") and resolved on "submit" + // Initialize with empty string (no selection) + this.singleSelectSelections.set(questionId, ''); } } @@ -199,6 +204,7 @@ export class A2UIWebSocketHandler { if (handled) { this.activeSurfaces.delete(answer.questionId); this.multiSelectSelections.delete(answer.questionId); + this.singleSelectSelections.delete(answer.questionId); } return handled; @@ -223,6 +229,7 @@ export class A2UIWebSocketHandler { if (handled) { this.activeSurfaces.delete(questionId); this.multiSelectSelections.delete(questionId); + this.singleSelectSelections.delete(questionId); } return handled; }; @@ -242,6 +249,16 @@ export class A2UIWebSocketHandler { return resolveAndCleanup({ questionId, value: value as string | boolean | string[], cancelled: false }); } + case 'select': { + // Single select: store the selected value (don't submit yet) + const value = params.value; + if (typeof value !== 'string') { + return false; + } + this.singleSelectSelections.set(questionId, value); + return true; + } + case 'toggle': { const value = params.value; const checked = params.checked; @@ -261,8 +278,15 @@ export class A2UIWebSocketHandler { } case 'submit': { - const selected = this.multiSelectSelections.get(questionId) ?? new Set(); - return resolveAndCleanup({ questionId, value: Array.from(selected), cancelled: false }); + // Check if this is a single-select or multi-select + const singleSelection = this.singleSelectSelections.get(questionId); + if (singleSelection !== undefined) { + // Single-select submit + return resolveAndCleanup({ questionId, value: singleSelection, cancelled: false }); + } + // Multi-select submit + const multiSelected = this.multiSelectSelections.get(questionId) ?? new Set(); + return resolveAndCleanup({ questionId, value: Array.from(multiSelected), cancelled: false }); } default: diff --git a/ccw/src/tools/ask-question.ts b/ccw/src/tools/ask-question.ts index a19dd314..e377ce2d 100644 --- a/ccw/src/tools/ask-question.ts +++ b/ccw/src/tools/ask-question.ts @@ -144,6 +144,7 @@ function generateQuestionSurface(question: Question, surfaceId: string): { surfaceId: string; components: unknown[]; initialState: Record; + displayMode?: 'popup' | 'panel'; }; } { const components: unknown[] = []; @@ -219,15 +220,43 @@ function generateQuestionSurface(question: Question, surfaceId: string): { const options = question.options?.map((opt) => ({ label: { literalString: opt.label }, value: opt.value, + description: opt.description ? { literalString: opt.description } : undefined, })) || []; + + // Use RadioGroup for direct selection display (not dropdown) components.push({ - id: 'select', + id: 'radio-group', component: { - Dropdown: { + RadioGroup: { options, selectedValue: question.defaultValue ? { literalString: String(question.defaultValue) } : undefined, - onChange: { actionId: 'answer', parameters: { questionId: question.id } }, - placeholder: question.placeholder || 'Select an option', + onChange: { actionId: 'select', parameters: { questionId: question.id } }, + }, + }, + }); + + // Add Submit/Cancel buttons to avoid accidental submission + components.push({ + id: 'submit-btn', + component: { + Button: { + onClick: { actionId: 'submit', parameters: { questionId: question.id } }, + content: { + Text: { text: { literalString: 'Submit' } }, + }, + variant: 'primary', + }, + }, + }); + components.push({ + id: 'cancel-btn', + component: { + Button: { + onClick: { actionId: 'cancel', parameters: { questionId: question.id } }, + content: { + Text: { text: { literalString: 'Cancel' } }, + }, + variant: 'secondary', }, }, }); @@ -239,21 +268,19 @@ function generateQuestionSurface(question: Question, surfaceId: string): { label: { literalString: opt.label }, value: opt.value, })) || []; - components.push({ - id: 'checkboxes', - component: { - Card: { - content: options.map((opt, idx) => ({ - id: `checkbox-${idx}`, - component: { - Checkbox: { - label: opt.label, - onChange: { actionId: 'toggle', parameters: { questionId: question.id, value: opt.value } }, - }, - }, - })), + + // Add each checkbox as a separate component for better layout control + options.forEach((opt, idx) => { + components.push({ + id: `checkbox-${idx}`, + component: { + Checkbox: { + label: opt.label, + onChange: { actionId: 'toggle', parameters: { questionId: question.id, value: opt.value } }, + checked: { literalBoolean: false }, + }, }, - }, + }); }); // Submit/cancel actions for multi-select so users can choose multiple options before resolving diff --git a/ccw/tsconfig.tsbuildinfo b/ccw/tsconfig.tsbuildinfo new file mode 100644 index 00000000..cc8cee35 --- /dev/null +++ b/ccw/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"root":["./src/cli.ts","./src/index.ts","./src/commands/cli.ts","./src/commands/core-memory.ts","./src/commands/hook.ts","./src/commands/install.ts","./src/commands/issue.ts","./src/commands/list.ts","./src/commands/loop.ts","./src/commands/memory.ts","./src/commands/serve.ts","./src/commands/session-path-resolver.ts","./src/commands/session.ts","./src/commands/stop.ts","./src/commands/tool.ts","./src/commands/uninstall.ts","./src/commands/upgrade.ts","./src/commands/view.ts","./src/commands/workflow.ts","./src/config/cli-settings-manager.ts","./src/config/litellm-api-config-manager.ts","./src/config/litellm-provider-models.ts","./src/config/provider-models.ts","./src/config/storage-paths.ts","./src/core/cache-manager.ts","./src/core/claude-freshness.ts","./src/core/core-memory-store.ts","./src/core/cors.ts","./src/core/dashboard-generator-patch.ts","./src/core/dashboard-generator.ts","./src/core/data-aggregator.ts","./src/core/history-importer.ts","./src/core/lite-scanner-complete.ts","./src/core/lite-scanner.ts","./src/core/manifest.ts","./src/core/memory-embedder-bridge.ts","./src/core/memory-store.ts","./src/core/server.ts","./src/core/session-clustering-service.ts","./src/core/session-scanner.ts","./src/core/websocket.ts","./src/core/a2ui/a2uitypes.ts","./src/core/a2ui/a2uiwebsockethandler.ts","./src/core/a2ui/index.ts","./src/core/auth/csrf-manager.ts","./src/core/auth/csrf-middleware.ts","./src/core/auth/middleware.ts","./src/core/auth/token-manager.ts","./src/core/routes/auth-routes.ts","./src/core/routes/ccw-routes.ts","./src/core/routes/claude-routes.ts","./src/core/routes/cli-routes.ts","./src/core/routes/cli-settings-routes.ts","./src/core/routes/codexlens-routes.ts","./src/core/routes/commands-routes.ts","./src/core/routes/core-memory-routes.ts","./src/core/routes/dashboard-routes.ts","./src/core/routes/discovery-routes.ts","./src/core/routes/files-routes.ts","./src/core/routes/graph-routes.ts","./src/core/routes/help-routes.ts","./src/core/routes/hooks-routes.ts","./src/core/routes/issue-routes.ts","./src/core/routes/litellm-api-routes.ts","./src/core/routes/litellm-routes.ts","./src/core/routes/loop-routes.ts","./src/core/routes/loop-v2-routes.ts","./src/core/routes/mcp-routes.ts","./src/core/routes/mcp-templates-db.ts","./src/core/routes/memory-routes.ts","./src/core/routes/nav-status-routes.ts","./src/core/routes/orchestrator-routes.ts","./src/core/routes/provider-routes.ts","./src/core/routes/rules-routes.ts","./src/core/routes/session-routes.ts","./src/core/routes/skills-routes.ts","./src/core/routes/status-routes.ts","./src/core/routes/system-routes.ts","./src/core/routes/task-routes.ts","./src/core/routes/test-loop-routes.ts","./src/core/routes/types.ts","./src/core/routes/codexlens/config-handlers.ts","./src/core/routes/codexlens/index-handlers.ts","./src/core/routes/codexlens/semantic-handlers.ts","./src/core/routes/codexlens/utils.ts","./src/core/routes/codexlens/watcher-handlers.ts","./src/core/services/api-key-tester.ts","./src/core/services/flow-executor.ts","./src/core/services/health-check-service.ts","./src/mcp-server/index.ts","./src/tools/ask-question.ts","./src/tools/classify-folders.ts","./src/tools/claude-cli-tools.ts","./src/tools/cli-config-manager.ts","./src/tools/cli-executor-core.ts","./src/tools/cli-executor-state.ts","./src/tools/cli-executor-utils.ts","./src/tools/cli-executor.ts","./src/tools/cli-history-store.ts","./src/tools/cli-output-converter.ts","./src/tools/cli-prompt-builder.ts","./src/tools/codex-lens-lsp.ts","./src/tools/codex-lens.ts","./src/tools/command-registry.ts","./src/tools/context-cache-store.ts","./src/tools/context-cache.ts","./src/tools/convert-tokens-to-css.ts","./src/tools/core-memory.ts","./src/tools/detect-changed-modules.ts","./src/tools/discover-design-files.ts","./src/tools/edit-file.ts","./src/tools/generate-module-docs.ts","./src/tools/get-modules-by-depth.ts","./src/tools/index.ts","./src/tools/litellm-client.ts","./src/tools/litellm-executor.ts","./src/tools/loop-manager.ts","./src/tools/loop-state-manager.ts","./src/tools/loop-task-manager.ts","./src/tools/memory-update-queue.js","./src/tools/native-session-discovery.ts","./src/tools/notifier.ts","./src/tools/pattern-parser.ts","./src/tools/read-file.ts","./src/tools/resume-strategy.ts","./src/tools/session-content-parser.ts","./src/tools/session-manager.ts","./src/tools/skill-context-loader.ts","./src/tools/smart-context.ts","./src/tools/smart-search.ts","./src/tools/storage-manager.ts","./src/tools/template-discovery.ts","./src/tools/ui-generate-preview.js","./src/tools/ui-instantiate-prototypes.js","./src/tools/update-module-claude.js","./src/tools/vscode-lsp.ts","./src/tools/write-file.ts","./src/types/cli-settings.ts","./src/types/config.ts","./src/types/index.ts","./src/types/litellm-api-config.ts","./src/types/loop.ts","./src/types/session.ts","./src/types/skill-types.ts","./src/types/tool.ts","./src/utils/browser-launcher.ts","./src/utils/codexlens-path.ts","./src/utils/exec-constants.ts","./src/utils/file-utils.ts","./src/utils/path-resolver.ts","./src/utils/path-validator.ts","./src/utils/project-root.ts","./src/utils/python-utils.ts","./src/utils/react-frontend.ts","./src/utils/shell-escape.ts","./src/utils/ui.ts","./src/utils/update-checker.ts","./src/utils/uv-manager.ts"],"version":"5.9.3"} \ No newline at end of file