mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-05 01:50:27 +08:00
feat: Enhance A2UI with RadioGroup and Markdown support
- Added support for RadioGroup component in A2UI, allowing single selection from multiple options. - Implemented Markdown parsing in A2UIPopupCard for better content rendering. - Updated A2UIPopupCard to handle different question types and improved layout for multi-select and single-select questions. - Introduced new utility functions for handling disabled items during installation. - Enhanced installation process to restore previously disabled skills and commands. - Updated notification store and related tests to accommodate new features. - Adjusted Vite configuration for better development experience.
This commit is contained in:
@@ -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")],};
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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": {
|
||||
|
||||
@@ -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<string, unknown> | 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 (
|
||||
<div className={cn('prose prose-sm dark:prose-invert max-w-none', className)}>
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm]}
|
||||
components={{
|
||||
// Customize rendered elements
|
||||
p: ({ children }) => <p className="mb-2 last:mb-0">{children}</p>,
|
||||
ul: ({ children }) => <ul className="list-disc pl-4 mb-2">{children}</ul>,
|
||||
ol: ({ children }) => <ol className="list-decimal pl-4 mb-2">{children}</ol>,
|
||||
li: ({ children }) => <li className="mb-1">{children}</li>,
|
||||
code: ({ children, className }) => {
|
||||
const isInline = !className;
|
||||
return isInline ? (
|
||||
<code className="px-1 py-0.5 bg-muted rounded text-sm">{children}</code>
|
||||
) : (
|
||||
<code className={cn('block p-2 bg-muted rounded text-sm overflow-x-auto', className)}>
|
||||
{children}
|
||||
</code>
|
||||
);
|
||||
},
|
||||
a: ({ href, children }) => (
|
||||
<a href={href} target="_blank" rel="noopener noreferrer" className="text-primary underline">
|
||||
{children}
|
||||
</a>
|
||||
),
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// ========== 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 (
|
||||
<Dialog open onOpenChange={handleOpenChange}>
|
||||
<DialogContent
|
||||
className={cn(
|
||||
// Minimalist style: no heavy borders, light shadow, rounded corners
|
||||
'sm:max-w-[420px] max-h-[80vh] overflow-y-auto',
|
||||
'bg-card p-6 rounded-xl shadow-md border-0',
|
||||
// Base styles
|
||||
dialogWidth,
|
||||
'max-h-[80vh] overflow-y-auto',
|
||||
'bg-card p-6 rounded-xl shadow-lg border border-border/50',
|
||||
// Animation classes
|
||||
'data-[state=open]:animate-in data-[state=closed]:animate-out',
|
||||
'data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0',
|
||||
'data-[state=open]:zoom-in-95 data-[state=closed]:zoom-out-95',
|
||||
'data-[state=open]:duration-300 data-[state=closed]:duration-200'
|
||||
)}
|
||||
onInteractOutside={(e) => {
|
||||
// Prevent closing when clicking outside
|
||||
e.preventDefault();
|
||||
}}
|
||||
onEscapeKeyDown={(e) => {
|
||||
// Prevent closing with ESC key
|
||||
e.preventDefault();
|
||||
}}
|
||||
>
|
||||
<DialogHeader className="space-y-1.5 pb-4">
|
||||
<DialogTitle className="text-lg font-semibold">{title}</DialogTitle>
|
||||
{/* Header */}
|
||||
<DialogHeader className="space-y-2 pb-4">
|
||||
<DialogTitle className="text-lg font-semibold leading-tight">{title}</DialogTitle>
|
||||
{message && (
|
||||
<div className="text-base text-foreground">
|
||||
<MarkdownContent content={message} />
|
||||
</div>
|
||||
)}
|
||||
{description && (
|
||||
<DialogDescription className="text-sm text-muted-foreground">
|
||||
{description}
|
||||
</DialogDescription>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
<MarkdownContent content={description} className="prose-muted" />
|
||||
</div>
|
||||
)}
|
||||
</DialogHeader>
|
||||
|
||||
{/* A2UI Surface Body */}
|
||||
<div className="space-y-4 py-2">
|
||||
<A2UIRenderer surface={bodySurface} onAction={handleAction} />
|
||||
</div>
|
||||
{/* Body - Interactive elements */}
|
||||
{bodyComponents.length > 0 && (
|
||||
<div className={cn(
|
||||
'py-3',
|
||||
// Add specific styling for multi-select (checkbox list)
|
||||
questionType === 'multi-select' && 'space-y-2 max-h-[300px] overflow-y-auto px-1'
|
||||
)}>
|
||||
{questionType === 'multi-select' ? (
|
||||
// Render each checkbox individually for better control
|
||||
bodyComponents.map((comp) => (
|
||||
<div key={comp.id} className="py-1">
|
||||
<A2UIRenderer
|
||||
surface={{ ...bodySurface, components: [comp] }}
|
||||
onAction={handleAction}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<A2UIRenderer surface={bodySurface} onAction={handleAction} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Footer - Action buttons */}
|
||||
{actionButtons.length > 0 && (
|
||||
<DialogFooter className="pt-4">
|
||||
<div className="flex flex-row justify-end gap-3">
|
||||
{actionButtons.map((comp) => (
|
||||
<A2UIRenderer
|
||||
key={comp.id}
|
||||
surface={{ ...actionsSurface, components: [comp] }}
|
||||
onAction={handleAction}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</DialogFooter>
|
||||
)}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -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<any> = z.union([
|
||||
TextFieldComponentSchema,
|
||||
TextAreaComponentSchema,
|
||||
CheckboxComponentSchema,
|
||||
RadioGroupComponentSchema,
|
||||
CodeBlockComponentSchema,
|
||||
ProgressComponentSchema,
|
||||
CardComponentSchema,
|
||||
@@ -202,6 +216,7 @@ export type DropdownComponent = z.infer<typeof DropdownComponentSchema>;
|
||||
export type TextFieldComponent = z.infer<typeof TextFieldComponentSchema>;
|
||||
export type TextAreaComponent = z.infer<typeof TextAreaComponentSchema>;
|
||||
export type CheckboxComponent = z.infer<typeof CheckboxComponentSchema>;
|
||||
export type RadioGroupComponent = z.infer<typeof RadioGroupComponentSchema>;
|
||||
export type CodeBlockComponent = z.infer<typeof CodeBlockComponentSchema>;
|
||||
export type ProgressComponent = z.infer<typeof ProgressComponentSchema>;
|
||||
export type CardComponent = z.infer<typeof CardComponentSchema>;
|
||||
@@ -223,6 +238,7 @@ export type A2UIComponentType =
|
||||
| 'TextField'
|
||||
| 'TextArea'
|
||||
| 'Checkbox'
|
||||
| 'RadioGroup'
|
||||
| 'CodeBlock'
|
||||
| 'Progress'
|
||||
| 'Card'
|
||||
|
||||
@@ -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<string, unknown>;
|
||||
onAction: (actionId: string, params: Record<string, unknown>) => void | Promise<void>;
|
||||
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<string | undefined>(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 (
|
||||
<RadioGroup value={selectedValue} onValueChange={handleChange} className="space-y-2">
|
||||
{radioConfig.options.map((option, idx) => {
|
||||
const labelText = resolveTextContent(option.label, resolveBinding);
|
||||
const descriptionText = option.description
|
||||
? resolveTextContent(option.description, resolveBinding)
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<div key={option.value || idx} className="flex items-start space-x-3 py-1">
|
||||
<RadioGroupItem
|
||||
value={option.value}
|
||||
id={`radio-${option.value}`}
|
||||
className="mt-0.5"
|
||||
/>
|
||||
<div className="flex flex-col">
|
||||
<Label
|
||||
htmlFor={`radio-${option.value}`}
|
||||
className="text-sm font-medium leading-none cursor-pointer"
|
||||
>
|
||||
{labelText}
|
||||
</Label>
|
||||
{descriptionText && (
|
||||
<span className="text-xs text-muted-foreground mt-1">
|
||||
{descriptionText}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</RadioGroup>
|
||||
);
|
||||
};
|
||||
@@ -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';
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -349,7 +349,7 @@ export const useNotificationStore = create<NotificationStore>()(
|
||||
}
|
||||
},
|
||||
|
||||
retryAction: async (actionKey: string, notificationId: string) => {
|
||||
retryAction: async (actionKey: string) => {
|
||||
const state = get();
|
||||
const actionState = state.actionStates.get(actionKey);
|
||||
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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<void> {
|
||||
}
|
||||
}
|
||||
|
||||
// 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<void> {
|
||||
|
||||
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<void> {
|
||||
|
||||
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<void> {
|
||||
}
|
||||
}
|
||||
|
||||
// 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)}`));
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ export class A2UIWebSocketHandler {
|
||||
}>();
|
||||
|
||||
private multiSelectSelections = new Map<string, Set<string>>();
|
||||
private singleSelectSelections = new Map<string, string>();
|
||||
|
||||
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<string>());
|
||||
} 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<string>();
|
||||
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<string>();
|
||||
return resolveAndCleanup({ questionId, value: Array.from(multiSelected), cancelled: false });
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
@@ -144,6 +144,7 @@ function generateQuestionSurface(question: Question, surfaceId: string): {
|
||||
surfaceId: string;
|
||||
components: unknown[];
|
||||
initialState: Record<string, unknown>;
|
||||
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
|
||||
|
||||
1
ccw/tsconfig.tsbuildinfo
Normal file
1
ccw/tsconfig.tsbuildinfo
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user