@claude-collective/cli 0.2.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/CHANGELOG.md +178 -0
  2. package/README.md +1 -1
  3. package/dist/chunk-3HBTELJN.js +114 -0
  4. package/dist/chunk-3HBTELJN.js.map +1 -0
  5. package/dist/chunk-3ZCB5K33.js +54 -0
  6. package/dist/chunk-3ZCB5K33.js.map +1 -0
  7. package/dist/chunk-66UDJBF6.js +96 -0
  8. package/dist/chunk-66UDJBF6.js.map +1 -0
  9. package/dist/chunk-6LS7XO3H.js +31 -0
  10. package/dist/chunk-6LS7XO3H.js.map +1 -0
  11. package/dist/chunk-A3J6IAXK.js +57 -0
  12. package/dist/chunk-A3J6IAXK.js.map +1 -0
  13. package/dist/chunk-A65SBAAJ.js +69 -0
  14. package/dist/chunk-A65SBAAJ.js.map +1 -0
  15. package/dist/chunk-ALEPJ6YN.js +80 -0
  16. package/dist/chunk-ALEPJ6YN.js.map +1 -0
  17. package/dist/chunk-C4ZTIYFR.js +84 -0
  18. package/dist/chunk-C4ZTIYFR.js.map +1 -0
  19. package/dist/chunk-CIY5UBRB.js +453 -0
  20. package/dist/chunk-CIY5UBRB.js.map +1 -0
  21. package/dist/chunk-DHET7RCE.js +50 -0
  22. package/dist/chunk-DHET7RCE.js.map +1 -0
  23. package/dist/chunk-DHFFRMF6.js +31 -0
  24. package/dist/chunk-DHFFRMF6.js.map +1 -0
  25. package/dist/chunk-DKGL77IY.js +307 -0
  26. package/dist/chunk-DKGL77IY.js.map +1 -0
  27. package/dist/chunk-ED73HCW2.js +315 -0
  28. package/dist/chunk-ED73HCW2.js.map +1 -0
  29. package/dist/chunk-FNOYEXUE.js +308 -0
  30. package/dist/chunk-FNOYEXUE.js.map +1 -0
  31. package/dist/chunk-G2FBJOZG.js +141 -0
  32. package/dist/chunk-G2FBJOZG.js.map +1 -0
  33. package/dist/chunk-HNDT5QRB.js +120 -0
  34. package/dist/chunk-HNDT5QRB.js.map +1 -0
  35. package/dist/chunk-K7PTOVX4.js +158 -0
  36. package/dist/chunk-K7PTOVX4.js.map +1 -0
  37. package/dist/chunk-LQTST4WY.js +91 -0
  38. package/dist/chunk-LQTST4WY.js.map +1 -0
  39. package/dist/chunk-LVKRVFYR.js +54 -0
  40. package/dist/chunk-LVKRVFYR.js.map +1 -0
  41. package/dist/chunk-M7YCPFIX.js +108 -0
  42. package/dist/chunk-M7YCPFIX.js.map +1 -0
  43. package/dist/chunk-MJSFR562.js +57 -0
  44. package/dist/chunk-MJSFR562.js.map +1 -0
  45. package/dist/chunk-MMDXNZPF.js +69 -0
  46. package/dist/chunk-MMDXNZPF.js.map +1 -0
  47. package/dist/chunk-MYAVQ23U.js +356 -0
  48. package/dist/chunk-MYAVQ23U.js.map +1 -0
  49. package/dist/chunk-NGBFJJ7Q.js +124 -0
  50. package/dist/chunk-NGBFJJ7Q.js.map +1 -0
  51. package/dist/chunk-OLBOTK3O.js +64 -0
  52. package/dist/chunk-OLBOTK3O.js.map +1 -0
  53. package/dist/chunk-PPNTD5LO.js +330 -0
  54. package/dist/chunk-PPNTD5LO.js.map +1 -0
  55. package/dist/chunk-Q2LH2DAB.js +392 -0
  56. package/dist/chunk-Q2LH2DAB.js.map +1 -0
  57. package/dist/chunk-Q6DR5QUH.js +547 -0
  58. package/dist/chunk-Q6DR5QUH.js.map +1 -0
  59. package/dist/chunk-QESUUPOE.js +241 -0
  60. package/dist/chunk-QESUUPOE.js.map +1 -0
  61. package/dist/chunk-QGGSLMO3.js +607 -0
  62. package/dist/chunk-QGGSLMO3.js.map +1 -0
  63. package/dist/chunk-SEBPPFUW.js +478 -0
  64. package/dist/chunk-SEBPPFUW.js.map +1 -0
  65. package/dist/chunk-SYQ7R2JO.js +95 -0
  66. package/dist/chunk-SYQ7R2JO.js.map +1 -0
  67. package/dist/chunk-TOPAIL5W.js +22 -0
  68. package/dist/chunk-TOPAIL5W.js.map +1 -0
  69. package/dist/chunk-U4VYHKPM.js +110 -0
  70. package/dist/chunk-U4VYHKPM.js.map +1 -0
  71. package/dist/chunk-UOWHJ6BE.js +83 -0
  72. package/dist/chunk-UOWHJ6BE.js.map +1 -0
  73. package/dist/chunk-XKEG3SCV.js +86 -0
  74. package/dist/chunk-XKEG3SCV.js.map +1 -0
  75. package/dist/chunk-XY3XDVMI.js +15599 -0
  76. package/dist/chunk-XY3XDVMI.js.map +1 -0
  77. package/dist/chunk-Y3V43XCU.js +76 -0
  78. package/dist/chunk-Y3V43XCU.js.map +1 -0
  79. package/dist/chunk-YKXBGCFD.js +129 -0
  80. package/dist/chunk-YKXBGCFD.js.map +1 -0
  81. package/dist/cli-v2/defaults/agent-mappings.yaml +185 -0
  82. package/dist/commands/build/marketplace.js +254 -0
  83. package/dist/commands/build/marketplace.js.map +1 -0
  84. package/dist/commands/build/plugins.js +324 -0
  85. package/dist/commands/build/plugins.js.map +1 -0
  86. package/dist/commands/build/stack.js +169 -0
  87. package/dist/commands/build/stack.js.map +1 -0
  88. package/dist/commands/compile.js +461 -0
  89. package/dist/commands/compile.js.map +1 -0
  90. package/dist/commands/config/get.js +60 -0
  91. package/dist/commands/config/get.js.map +1 -0
  92. package/dist/commands/config/index.js +22 -0
  93. package/dist/commands/config/index.js.map +1 -0
  94. package/dist/commands/config/path.js +35 -0
  95. package/dist/commands/config/path.js.map +1 -0
  96. package/dist/commands/config/set-project.js +61 -0
  97. package/dist/commands/config/set-project.js.map +1 -0
  98. package/dist/commands/config/set.js +60 -0
  99. package/dist/commands/config/set.js.map +1 -0
  100. package/dist/commands/config/show.js +13 -0
  101. package/dist/commands/config/show.js.map +1 -0
  102. package/dist/commands/config/unset-project.js +57 -0
  103. package/dist/commands/config/unset-project.js.map +1 -0
  104. package/dist/commands/config/unset.js +56 -0
  105. package/dist/commands/config/unset.js.map +1 -0
  106. package/dist/commands/diff.js +755 -0
  107. package/dist/commands/diff.js.map +1 -0
  108. package/dist/commands/doctor.js +413 -0
  109. package/dist/commands/doctor.js.map +1 -0
  110. package/dist/commands/edit.js +254 -0
  111. package/dist/commands/edit.js.map +1 -0
  112. package/dist/commands/eject.js +208 -0
  113. package/dist/commands/eject.js.map +1 -0
  114. package/dist/commands/info.js +205 -0
  115. package/dist/commands/info.js.map +1 -0
  116. package/dist/commands/init.js +915 -0
  117. package/dist/commands/init.js.map +1 -0
  118. package/dist/commands/list.js +44 -0
  119. package/dist/commands/list.js.map +1 -0
  120. package/dist/commands/new/agent.js +230 -0
  121. package/dist/commands/new/agent.js.map +1 -0
  122. package/dist/commands/new/skill.js +204 -0
  123. package/dist/commands/new/skill.js.map +1 -0
  124. package/dist/commands/outdated.js +242 -0
  125. package/dist/commands/outdated.js.map +1 -0
  126. package/dist/commands/search.js +115 -0
  127. package/dist/commands/search.js.map +1 -0
  128. package/dist/commands/test-imports.js +92 -0
  129. package/dist/commands/test-imports.js.map +1 -0
  130. package/dist/commands/uninstall.js +309 -0
  131. package/dist/commands/uninstall.js.map +1 -0
  132. package/dist/commands/update.js +428 -0
  133. package/dist/commands/update.js.map +1 -0
  134. package/dist/commands/validate.js +375 -0
  135. package/dist/commands/validate.js.map +1 -0
  136. package/dist/commands/version/bump.js +95 -0
  137. package/dist/commands/version/bump.js.map +1 -0
  138. package/dist/commands/version/index.js +70 -0
  139. package/dist/commands/version/index.js.map +1 -0
  140. package/dist/commands/version/set.js +101 -0
  141. package/dist/commands/version/set.js.map +1 -0
  142. package/dist/commands/version/show.js +70 -0
  143. package/dist/commands/version/show.js.map +1 -0
  144. package/dist/components/common/confirm.js +9 -0
  145. package/dist/components/common/confirm.js.map +1 -0
  146. package/dist/components/common/message.js +24 -0
  147. package/dist/components/common/message.js.map +1 -0
  148. package/dist/components/common/spinner.js +14 -0
  149. package/dist/components/common/spinner.js.map +1 -0
  150. package/dist/components/wizard/category-grid.js +9 -0
  151. package/dist/components/wizard/category-grid.js.map +1 -0
  152. package/dist/components/wizard/category-grid.test.js +728 -0
  153. package/dist/components/wizard/category-grid.test.js.map +1 -0
  154. package/dist/components/wizard/section-progress.js +9 -0
  155. package/dist/components/wizard/section-progress.js.map +1 -0
  156. package/dist/components/wizard/section-progress.test.js +281 -0
  157. package/dist/components/wizard/section-progress.test.js.map +1 -0
  158. package/dist/components/wizard/step-approach.js +11 -0
  159. package/dist/components/wizard/step-approach.js.map +1 -0
  160. package/dist/components/wizard/step-build.js +15 -0
  161. package/dist/components/wizard/step-build.js.map +1 -0
  162. package/dist/components/wizard/step-build.test.js +729 -0
  163. package/dist/components/wizard/step-build.test.js.map +1 -0
  164. package/dist/components/wizard/step-confirm.js +9 -0
  165. package/dist/components/wizard/step-confirm.js.map +1 -0
  166. package/dist/components/wizard/step-refine.js +9 -0
  167. package/dist/components/wizard/step-refine.js.map +1 -0
  168. package/dist/components/wizard/step-refine.test.js +235 -0
  169. package/dist/components/wizard/step-refine.test.js.map +1 -0
  170. package/dist/components/wizard/step-stack-options.js +11 -0
  171. package/dist/components/wizard/step-stack-options.js.map +1 -0
  172. package/dist/components/wizard/step-stack.js +11 -0
  173. package/dist/components/wizard/step-stack.js.map +1 -0
  174. package/dist/components/wizard/wizard-tabs.js +11 -0
  175. package/dist/components/wizard/wizard-tabs.js.map +1 -0
  176. package/dist/components/wizard/wizard.js +20 -0
  177. package/dist/components/wizard/wizard.js.map +1 -0
  178. package/dist/hooks/init.js +41 -0
  179. package/dist/hooks/init.js.map +1 -0
  180. package/dist/index.js +10 -0
  181. package/dist/index.js.map +1 -0
  182. package/dist/magic-string.es-RGXYGAW3.js +1316 -0
  183. package/dist/magic-string.es-RGXYGAW3.js.map +1 -0
  184. package/dist/stores/wizard-store.js +10 -0
  185. package/dist/stores/wizard-store.js.map +1 -0
  186. package/dist/stores/wizard-store.test.js +405 -0
  187. package/dist/stores/wizard-store.test.js.map +1 -0
  188. package/package.json +44 -25
  189. package/dist/cli/index.js +0 -6314
  190. package/dist/cli/index.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli-v2/lib/agent-recompiler.ts","../src/cli-v2/lib/custom-agent-resolver.ts"],"sourcesContent":["import path from \"path\";\nimport { glob, writeFile, ensureDir, readFile, fileExists } from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\nimport { loadAllAgents, loadPluginSkills } from \"./loader\";\nimport { resolveAgents, resolveStackSkills } from \"./resolver\";\nimport { compileAgentForPlugin } from \"./stack-plugin-compiler\";\nimport { getPluginAgentsDir } from \"./plugin-finder\";\nimport { createLiquidEngine } from \"./compiler\";\nimport {\n loadProjectConfig,\n isLegacyStackConfig,\n normalizeStackConfig,\n type LoadedProjectConfig,\n} from \"./project-config\";\nimport {\n resolveCustomAgents,\n validateCustomAgentIds,\n} from \"./custom-agent-resolver\";\nimport { parse as parseYaml } from \"yaml\";\nimport type {\n CompileConfig,\n CompileAgentConfig,\n StackConfig,\n SkillReference,\n SkillDefinition,\n ProjectConfig,\n AgentDefinition,\n} from \"../../types\";\n\nexport interface RecompileAgentsOptions {\n pluginDir: string;\n sourcePath: string;\n agents?: string[];\n skills?: Record<string, SkillDefinition>;\n projectDir?: string;\n outputDir?: string;\n}\n\nexport interface RecompileAgentsResult {\n compiled: string[];\n failed: string[];\n warnings: string[];\n}\n\nasync function getExistingAgentNames(pluginDir: string): Promise<string[]> {\n const agentsDir = getPluginAgentsDir(pluginDir);\n const files = await glob(\"*.md\", agentsDir);\n return files.map((f) => path.basename(f, \".md\"));\n}\n\n/**\n * Load config from either:\n * 1. pluginDir/config.yaml (legacy plugin location)\n * 2. pluginDir/.claude/config.yaml (new project config location)\n *\n * This provides backward compatibility with existing plugins.\n */\nasync function loadConfigWithFallback(\n pluginDir: string,\n): Promise<LoadedProjectConfig | null> {\n // First try the legacy plugin location (pluginDir/config.yaml)\n const legacyConfigPath = path.join(pluginDir, \"config.yaml\");\n if (await fileExists(legacyConfigPath)) {\n try {\n const content = await readFile(legacyConfigPath);\n const parsed = parseYaml(content);\n\n if (parsed && typeof parsed === \"object\") {\n verbose(`Loaded config.yaml from ${legacyConfigPath}`);\n\n // Check if it's legacy StackConfig format\n if (isLegacyStackConfig(parsed)) {\n const normalized = normalizeStackConfig(parsed as StackConfig);\n return {\n config: normalized,\n configPath: legacyConfigPath,\n isLegacy: true,\n };\n }\n\n return {\n config: parsed as ProjectConfig,\n configPath: legacyConfigPath,\n isLegacy: false,\n };\n }\n } catch (error) {\n verbose(`Failed to parse config.yaml: ${error}`);\n }\n }\n\n // Fall back to project config location (.claude/config.yaml)\n return loadProjectConfig(pluginDir);\n}\n\n/**\n * Convert ProjectConfig to StackConfig-like structure for compatibility\n * with existing resolveStackSkills function\n */\nfunction projectConfigToStackLike(config: ProjectConfig): StackConfig {\n return {\n name: config.name,\n version: \"1.0.0\",\n author: config.author ?? \"@unknown\",\n description: config.description,\n skills:\n config.skills?.map((s) => (typeof s === \"string\" ? { id: s } : s)) ?? [],\n agents: config.agents,\n agent_skills: config.agent_skills as StackConfig[\"agent_skills\"],\n hooks: config.hooks,\n framework: config.framework,\n philosophy: config.philosophy,\n principles: config.principles,\n tags: config.tags,\n };\n}\n\nexport async function recompileAgents(\n options: RecompileAgentsOptions,\n): Promise<RecompileAgentsResult> {\n const {\n pluginDir,\n sourcePath,\n agents: specifiedAgents,\n skills: providedSkills,\n projectDir,\n outputDir,\n } = options;\n\n const result: RecompileAgentsResult = {\n compiled: [],\n failed: [],\n warnings: [],\n };\n\n // Load project config (handles both legacy plugin config and new ProjectConfig)\n const loadedConfig = await loadConfigWithFallback(pluginDir);\n const projectConfig = loadedConfig?.config ?? null;\n\n // Load built-in agents from source\n const builtinAgents = await loadAllAgents(sourcePath);\n\n // Resolve custom agents and merge with built-in agents\n let allAgents: Record<string, AgentDefinition> = { ...builtinAgents };\n if (projectConfig?.custom_agents) {\n // Validate custom agent IDs don't conflict with built-in agents\n const idConflicts = validateCustomAgentIds(\n projectConfig.custom_agents,\n builtinAgents,\n );\n if (idConflicts.length > 0) {\n for (const error of idConflicts) {\n result.warnings.push(error);\n }\n }\n\n // Resolve custom agents to AgentDefinition\n try {\n const resolvedCustomAgents = resolveCustomAgents(\n projectConfig.custom_agents,\n builtinAgents,\n );\n // Merge: custom agents can override built-in if same name (though we warn above)\n allAgents = { ...builtinAgents, ...resolvedCustomAgents };\n verbose(\n `Resolved ${Object.keys(resolvedCustomAgents).length} custom agents`,\n );\n } catch (error) {\n result.warnings.push(\n `Failed to resolve custom agents: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n // Convert to StackConfig-like for compatibility with existing functions\n const pluginConfig = projectConfig\n ? projectConfigToStackLike(projectConfig)\n : null;\n\n let agentNames: string[];\n if (specifiedAgents) {\n agentNames = specifiedAgents;\n } else if (pluginConfig?.agents) {\n agentNames = pluginConfig.agents;\n verbose(`Using agents from config.yaml: ${agentNames.join(\", \")}`);\n } else if (outputDir) {\n agentNames = Object.keys(allAgents);\n verbose(`Using all available agents from source: ${agentNames.join(\", \")}`);\n } else {\n agentNames = await getExistingAgentNames(pluginDir);\n }\n\n if (agentNames.length === 0) {\n result.warnings.push(\"No agents found to recompile\");\n return result;\n }\n\n verbose(\n `Recompiling ${agentNames.length} agents in ${outputDir ?? pluginDir}`,\n );\n\n const pluginSkills = providedSkills ?? (await loadPluginSkills(pluginDir));\n\n const compileAgents: Record<string, CompileAgentConfig> = {};\n for (const agentName of agentNames) {\n if (allAgents[agentName]) {\n // Check if this is a custom agent with its own skills defined\n const customAgentConfig = projectConfig?.custom_agents?.[agentName];\n if (customAgentConfig?.skills && customAgentConfig.skills.length > 0) {\n // Custom agent has explicit skills defined\n const skillRefs: SkillReference[] = customAgentConfig.skills.map(\n (s) => ({\n id: typeof s === \"string\" ? s : s.id,\n usage: `when working with ${(typeof s === \"string\" ? s : s.id).split(\" \")[0]}`,\n preloaded:\n (typeof s === \"object\" && \"preloaded\" in s && s.preloaded) ??\n false,\n }),\n );\n compileAgents[agentName] = { skills: skillRefs };\n verbose(\n ` Agent ${agentName}: ${skillRefs.length} skills from custom_agents`,\n );\n } else if (pluginConfig?.agent_skills?.[agentName]) {\n const skillRefs = resolveStackSkills(\n pluginConfig,\n agentName,\n pluginSkills,\n );\n compileAgents[agentName] = { skills: skillRefs };\n verbose(` Agent ${agentName}: ${skillRefs.length} skills from config`);\n } else if (pluginConfig?.skills) {\n // Fall back to all skills in the config\n const skillRefs: SkillReference[] = pluginConfig.skills.map((s) => ({\n id: s.id,\n usage: `when working with ${s.id.split(\" \")[0]}`,\n preloaded: s.preloaded ?? false,\n }));\n compileAgents[agentName] = { skills: skillRefs };\n verbose(` Agent ${agentName}: ${skillRefs.length} skills (all)`);\n } else {\n compileAgents[agentName] = {};\n }\n } else {\n result.warnings.push(\n `Agent \"${agentName}\" not found in source definitions`,\n );\n }\n }\n\n const compileConfig: CompileConfig = {\n name: pluginConfig?.name || path.basename(pluginDir),\n description: pluginConfig?.description || \"Recompiled plugin\",\n claude_md: \"\",\n agents: compileAgents,\n };\n\n const engine = await createLiquidEngine(projectDir);\n const resolvedAgents = await resolveAgents(\n allAgents,\n pluginSkills,\n compileConfig,\n sourcePath,\n );\n\n const agentsDir = outputDir ?? getPluginAgentsDir(pluginDir);\n await ensureDir(agentsDir);\n\n for (const [name, agent] of Object.entries(resolvedAgents)) {\n try {\n const output = await compileAgentForPlugin(\n name,\n agent,\n sourcePath,\n engine,\n );\n await writeFile(path.join(agentsDir, `${name}.md`), output);\n result.compiled.push(name);\n verbose(` Recompiled: ${name}`);\n } catch (error) {\n result.failed.push(name);\n result.warnings.push(\n `Failed to compile ${name}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n return result;\n}\n","import type { CustomAgentConfig, AgentDefinition } from \"../../types\";\n\n/** Default tools for standalone custom agents (no extends) */\nconst DEFAULT_TOOLS = [\"Read\", \"Grep\", \"Glob\"];\n\n/** Marker path for standalone custom agents (no extends) */\nconst CUSTOM_AGENT_PATH = \"_custom\";\n\n/**\n * Resolve a custom agent config to a full AgentDefinition.\n * If extends is specified, inherit from the base agent.\n *\n * @param agentId - The custom agent's identifier\n * @param customConfig - The custom agent configuration from config.yaml\n * @param builtinAgents - Record of built-in agent definitions to extend from\n * @returns Fully resolved AgentDefinition\n * @throws Error if extends references an unknown agent\n */\nexport function resolveCustomAgent(\n agentId: string,\n customConfig: CustomAgentConfig,\n builtinAgents: Record<string, AgentDefinition>,\n): AgentDefinition {\n let baseAgent: Partial<AgentDefinition> = {};\n\n if (customConfig.extends) {\n const base = builtinAgents[customConfig.extends];\n if (!base) {\n const availableAgents = Object.keys(builtinAgents);\n const agentList =\n availableAgents.length > 0\n ? `Available agents: ${availableAgents.slice(0, 5).join(\", \")}${availableAgents.length > 5 ? ` (and ${availableAgents.length - 5} more)` : \"\"}`\n : \"No built-in agents found\";\n throw new Error(\n `Custom agent \"${agentId}\" extends unknown agent \"${customConfig.extends}\". ${agentList}`,\n );\n }\n baseAgent = { ...base };\n }\n\n // Merge disallowed_tools: custom + inherited\n let disallowedTools: string[] | undefined;\n if (customConfig.disallowed_tools || baseAgent.disallowed_tools) {\n const merged = new Set<string>([\n ...(baseAgent.disallowed_tools || []),\n ...(customConfig.disallowed_tools || []),\n ]);\n disallowedTools = [...merged];\n }\n\n // Merge hooks: custom hooks added to inherited\n let hooks: AgentDefinition[\"hooks\"] | undefined;\n if (customConfig.hooks || baseAgent.hooks) {\n hooks = { ...baseAgent.hooks };\n if (customConfig.hooks) {\n for (const [hookType, hookDefs] of Object.entries(customConfig.hooks)) {\n if (hooks[hookType]) {\n hooks[hookType] = [...hooks[hookType], ...hookDefs];\n } else {\n hooks[hookType] = hookDefs;\n }\n }\n }\n }\n\n return {\n title: customConfig.title,\n description: customConfig.description,\n model: customConfig.model || baseAgent.model,\n tools: customConfig.tools || baseAgent.tools || DEFAULT_TOOLS,\n disallowed_tools: disallowedTools,\n permission_mode: customConfig.permission_mode || baseAgent.permission_mode,\n hooks,\n // Use extended agent's path for template resolution, or _custom for standalone\n path: baseAgent.path || CUSTOM_AGENT_PATH,\n sourceRoot: baseAgent.sourceRoot,\n };\n}\n\n/**\n * Resolve all custom agents from config to AgentDefinition records.\n *\n * @param customAgents - Record of custom agent configs from config.yaml\n * @param builtinAgents - Record of built-in agent definitions\n * @returns Record of resolved AgentDefinitions keyed by custom agent ID\n */\nexport function resolveCustomAgents(\n customAgents: Record<string, CustomAgentConfig>,\n builtinAgents: Record<string, AgentDefinition>,\n): Record<string, AgentDefinition> {\n const resolved: Record<string, AgentDefinition> = {};\n\n for (const [id, config] of Object.entries(customAgents)) {\n resolved[id] = resolveCustomAgent(id, config, builtinAgents);\n }\n\n return resolved;\n}\n\n/**\n * Check if a custom agent ID conflicts with a built-in agent ID.\n *\n * @param customAgentId - The custom agent's identifier\n * @param builtinAgents - Record of built-in agent definitions\n * @returns true if there's a conflict\n */\nexport function hasAgentIdConflict(\n customAgentId: string,\n builtinAgents: Record<string, AgentDefinition>,\n): boolean {\n return customAgentId in builtinAgents;\n}\n\n/**\n * Validate custom agents don't conflict with built-in agents.\n *\n * @param customAgents - Record of custom agent configs\n * @param builtinAgents - Record of built-in agent definitions\n * @returns Array of error messages (empty if no conflicts)\n */\nexport function validateCustomAgentIds(\n customAgents: Record<string, CustomAgentConfig>,\n builtinAgents: Record<string, AgentDefinition>,\n): string[] {\n const errors: string[] = [];\n\n for (const customId of Object.keys(customAgents)) {\n if (hasAgentIdConflict(customId, builtinAgents)) {\n errors.push(\n `Custom agent \"${customId}\" conflicts with built-in agent of the same name. Choose a unique name.`,\n );\n }\n }\n\n return errors;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ hashFile
4
+ } from "./chunk-MJSFR562.js";
5
+ import {
6
+ copy,
7
+ ensureDir,
8
+ readFile,
9
+ writeFile
10
+ } from "./chunk-MMDXNZPF.js";
11
+ import {
12
+ init_esm_shims
13
+ } from "./chunk-DHET7RCE.js";
14
+
15
+ // src/cli-v2/lib/skill-copier.ts
16
+ init_esm_shims();
17
+ import path from "path";
18
+ import { stringify as stringifyYaml, parse as parseYaml } from "yaml";
19
+ var METADATA_FILE_NAME = "metadata.yaml";
20
+ function getSkillDestPath(skill, stackDir) {
21
+ const skillRelativePath = skill.path.replace(/^skills\//, "");
22
+ return path.join(stackDir, "skills", skillRelativePath);
23
+ }
24
+ async function generateSkillHash(skillSourcePath) {
25
+ const skillMdPath = path.join(skillSourcePath, "SKILL.md");
26
+ return hashFile(skillMdPath);
27
+ }
28
+ function getCurrentDate() {
29
+ return (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
30
+ }
31
+ async function injectForkedFromMetadata(destPath, skillId, contentHash) {
32
+ const metadataPath = path.join(destPath, METADATA_FILE_NAME);
33
+ const rawContent = await readFile(metadataPath);
34
+ const lines = rawContent.split("\n");
35
+ let yamlContent = rawContent;
36
+ if (lines[0]?.startsWith("# yaml-language-server:")) {
37
+ yamlContent = lines.slice(1).join("\n");
38
+ }
39
+ const metadata = parseYaml(yamlContent);
40
+ metadata.forked_from = {
41
+ skill_id: skillId,
42
+ content_hash: contentHash,
43
+ date: getCurrentDate()
44
+ };
45
+ const newYamlContent = stringifyYaml(metadata, { lineWidth: 0 });
46
+ await writeFile(metadataPath, newYamlContent);
47
+ }
48
+ function getSkillSourcePathFromSource(skill, sourceResult) {
49
+ return path.join(sourceResult.sourcePath, "src", skill.path);
50
+ }
51
+ async function copySkillFromSource(skill, stackDir, sourceResult) {
52
+ const sourcePath = getSkillSourcePathFromSource(skill, sourceResult);
53
+ const destPath = getSkillDestPath(skill, stackDir);
54
+ const contentHash = await generateSkillHash(sourcePath);
55
+ await ensureDir(path.dirname(destPath));
56
+ await copy(sourcePath, destPath);
57
+ await injectForkedFromMetadata(destPath, skill.id, contentHash);
58
+ return {
59
+ skillId: skill.id,
60
+ contentHash,
61
+ sourcePath,
62
+ destPath
63
+ };
64
+ }
65
+ async function copySkillsToPluginFromSource(selectedSkillIds, pluginDir, matrix, sourceResult) {
66
+ const copiedSkills = [];
67
+ for (const skillId of selectedSkillIds) {
68
+ const skill = matrix.skills[skillId];
69
+ if (!skill) {
70
+ console.warn(`Warning: Skill not found in matrix: ${skillId}`);
71
+ continue;
72
+ }
73
+ if (skill.local && skill.localPath) {
74
+ const localSkillPath = path.join(process.cwd(), skill.localPath);
75
+ const contentHash = await generateSkillHash(localSkillPath);
76
+ copiedSkills.push({
77
+ skillId: skill.id,
78
+ sourcePath: skill.localPath,
79
+ destPath: skill.localPath,
80
+ contentHash,
81
+ local: true
82
+ });
83
+ continue;
84
+ }
85
+ const copied = await copySkillFromSource(skill, pluginDir, sourceResult);
86
+ copiedSkills.push(copied);
87
+ }
88
+ return copiedSkills;
89
+ }
90
+ function getFlattenedSkillDestPath(skill, localSkillsDir) {
91
+ return path.join(localSkillsDir, skill.id);
92
+ }
93
+ async function copySkillToLocalFlattened(skill, localSkillsDir, sourceResult) {
94
+ const sourcePath = getSkillSourcePathFromSource(skill, sourceResult);
95
+ const destPath = getFlattenedSkillDestPath(skill, localSkillsDir);
96
+ const contentHash = await generateSkillHash(sourcePath);
97
+ await ensureDir(path.dirname(destPath));
98
+ await copy(sourcePath, destPath);
99
+ await injectForkedFromMetadata(destPath, skill.id, contentHash);
100
+ return {
101
+ skillId: skill.id,
102
+ contentHash,
103
+ sourcePath,
104
+ destPath
105
+ };
106
+ }
107
+ async function copySkillsToLocalFlattened(selectedSkillIds, localSkillsDir, matrix, sourceResult) {
108
+ const copiedSkills = [];
109
+ for (const skillId of selectedSkillIds) {
110
+ const skill = matrix.skills[skillId];
111
+ if (!skill) {
112
+ console.warn(`Warning: Skill not found in matrix: ${skillId}`);
113
+ continue;
114
+ }
115
+ if (skill.local && skill.localPath) {
116
+ const localSkillPath = path.join(process.cwd(), skill.localPath);
117
+ const contentHash = await generateSkillHash(localSkillPath);
118
+ copiedSkills.push({
119
+ skillId: skill.id,
120
+ sourcePath: skill.localPath,
121
+ destPath: skill.localPath,
122
+ contentHash,
123
+ local: true
124
+ });
125
+ continue;
126
+ }
127
+ const copied = await copySkillToLocalFlattened(
128
+ skill,
129
+ localSkillsDir,
130
+ sourceResult
131
+ );
132
+ copiedSkills.push(copied);
133
+ }
134
+ return copiedSkills;
135
+ }
136
+
137
+ export {
138
+ copySkillsToPluginFromSource,
139
+ copySkillsToLocalFlattened
140
+ };
141
+ //# sourceMappingURL=chunk-G2FBJOZG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli-v2/lib/skill-copier.ts"],"sourcesContent":["import path from \"path\";\nimport { stringify as stringifyYaml, parse as parseYaml } from \"yaml\";\nimport { copy, ensureDir, readFile, writeFile } from \"../utils/fs\";\nimport { hashFile } from \"./versioning\";\nimport type { MergedSkillsMatrix, ResolvedSkill } from \"../types-matrix\";\nimport type { SourceLoadResult } from \"./source-loader\";\n\ninterface ForkedFromMetadata {\n skill_id: string;\n content_hash: string;\n date: string;\n}\n\ninterface SkillMetadata {\n content_hash?: string;\n forked_from?: ForkedFromMetadata;\n [key: string]: unknown;\n}\n\nconst METADATA_FILE_NAME = \"metadata.yaml\";\n\nexport interface CopiedSkill {\n skillId: string;\n contentHash: string;\n sourcePath: string;\n destPath: string;\n local?: boolean;\n}\n\nfunction getSkillSourcePath(\n skill: ResolvedSkill,\n registryRoot: string,\n): string {\n return path.join(registryRoot, \"src\", skill.path);\n}\n\nfunction getSkillDestPath(skill: ResolvedSkill, stackDir: string): string {\n const skillRelativePath = skill.path.replace(/^skills\\//, \"\");\n return path.join(stackDir, \"skills\", skillRelativePath);\n}\n\nasync function generateSkillHash(skillSourcePath: string): Promise<string> {\n const skillMdPath = path.join(skillSourcePath, \"SKILL.md\");\n return hashFile(skillMdPath);\n}\n\nfunction getCurrentDate(): string {\n return new Date().toISOString().split(\"T\")[0];\n}\n\nasync function injectForkedFromMetadata(\n destPath: string,\n skillId: string,\n contentHash: string,\n): Promise<void> {\n const metadataPath = path.join(destPath, METADATA_FILE_NAME);\n const rawContent = await readFile(metadataPath);\n\n const lines = rawContent.split(\"\\n\");\n let yamlContent = rawContent;\n\n if (lines[0]?.startsWith(\"# yaml-language-server:\")) {\n yamlContent = lines.slice(1).join(\"\\n\");\n }\n\n const metadata = parseYaml(yamlContent) as SkillMetadata;\n\n metadata.forked_from = {\n skill_id: skillId,\n content_hash: contentHash,\n date: getCurrentDate(),\n };\n\n const newYamlContent = stringifyYaml(metadata, { lineWidth: 0 });\n await writeFile(metadataPath, newYamlContent);\n}\n\nexport async function copySkill(\n skill: ResolvedSkill,\n stackDir: string,\n registryRoot: string,\n): Promise<CopiedSkill> {\n const sourcePath = getSkillSourcePath(skill, registryRoot);\n const destPath = getSkillDestPath(skill, stackDir);\n\n const contentHash = await generateSkillHash(sourcePath);\n\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n await injectForkedFromMetadata(destPath, skill.id, contentHash);\n\n return {\n skillId: skill.id,\n contentHash,\n sourcePath,\n destPath,\n };\n}\n\nfunction getSkillSourcePathFromSource(\n skill: ResolvedSkill,\n sourceResult: SourceLoadResult,\n): string {\n return path.join(sourceResult.sourcePath, \"src\", skill.path);\n}\n\nexport async function copySkillFromSource(\n skill: ResolvedSkill,\n stackDir: string,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill> {\n const sourcePath = getSkillSourcePathFromSource(skill, sourceResult);\n const destPath = getSkillDestPath(skill, stackDir);\n\n const contentHash = await generateSkillHash(sourcePath);\n\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n await injectForkedFromMetadata(destPath, skill.id, contentHash);\n\n return {\n skillId: skill.id,\n contentHash,\n sourcePath,\n destPath,\n };\n}\n\nexport async function copySkillsToPluginFromSource(\n selectedSkillIds: string[],\n pluginDir: string,\n matrix: MergedSkillsMatrix,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill[]> {\n const copiedSkills: CopiedSkill[] = [];\n\n for (const skillId of selectedSkillIds) {\n const skill = matrix.skills[skillId];\n if (!skill) {\n console.warn(`Warning: Skill not found in matrix: ${skillId}`);\n continue;\n }\n\n if (skill.local && skill.localPath) {\n const localSkillPath = path.join(process.cwd(), skill.localPath);\n const contentHash = await generateSkillHash(localSkillPath);\n\n copiedSkills.push({\n skillId: skill.id,\n sourcePath: skill.localPath,\n destPath: skill.localPath,\n contentHash,\n local: true,\n });\n continue;\n }\n\n const copied = await copySkillFromSource(skill, pluginDir, sourceResult);\n copiedSkills.push(copied);\n }\n\n return copiedSkills;\n}\n\n/**\n * Get the destination path for a skill when copying to local flattened structure.\n *\n * Uses the normalized skill ID (kebab-case) as the folder name.\n *\n * @example\n * // skill.id = \"web-framework-react\"\n * // Returns: \"{localSkillsDir}/web-framework-react\"\n */\nfunction getFlattenedSkillDestPath(\n skill: ResolvedSkill,\n localSkillsDir: string,\n): string {\n return path.join(localSkillsDir, skill.id);\n}\n\nasync function copySkillToLocalFlattened(\n skill: ResolvedSkill,\n localSkillsDir: string,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill> {\n const sourcePath = getSkillSourcePathFromSource(skill, sourceResult);\n const destPath = getFlattenedSkillDestPath(skill, localSkillsDir);\n\n const contentHash = await generateSkillHash(sourcePath);\n\n await ensureDir(path.dirname(destPath));\n await copy(sourcePath, destPath);\n\n await injectForkedFromMetadata(destPath, skill.id, contentHash);\n\n return {\n skillId: skill.id,\n contentHash,\n sourcePath,\n destPath,\n };\n}\n\nexport async function copySkillsToLocalFlattened(\n selectedSkillIds: string[],\n localSkillsDir: string,\n matrix: MergedSkillsMatrix,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill[]> {\n const copiedSkills: CopiedSkill[] = [];\n\n for (const skillId of selectedSkillIds) {\n const skill = matrix.skills[skillId];\n if (!skill) {\n console.warn(`Warning: Skill not found in matrix: ${skillId}`);\n continue;\n }\n\n if (skill.local && skill.localPath) {\n const localSkillPath = path.join(process.cwd(), skill.localPath);\n const contentHash = await generateSkillHash(localSkillPath);\n\n copiedSkills.push({\n skillId: skill.id,\n sourcePath: skill.localPath,\n destPath: skill.localPath,\n contentHash,\n local: true,\n });\n continue;\n }\n\n const copied = await copySkillToLocalFlattened(\n skill,\n localSkillsDir,\n sourceResult,\n );\n copiedSkills.push(copied);\n }\n\n return copiedSkills;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ useWizardStore
4
+ } from "./chunk-K7PTOVX4.js";
5
+ import {
6
+ init_esm_shims
7
+ } from "./chunk-DHET7RCE.js";
8
+
9
+ // src/cli-v2/components/wizard/step-stack.tsx
10
+ init_esm_shims();
11
+ import { Box, Text } from "ink";
12
+ import { Select } from "@inkjs/ui";
13
+ import { jsx, jsxs } from "react/jsx-runtime";
14
+ var BACK_VALUE = "_back";
15
+ var CONTINUE_VALUE = "_continue";
16
+ var AVAILABLE_DOMAINS = [
17
+ { id: "web", label: "Web", description: "Frontend web applications" },
18
+ { id: "api", label: "API", description: "Backend APIs and services" },
19
+ { id: "cli", label: "CLI", description: "Command-line tools" },
20
+ { id: "mobile", label: "Mobile", description: "Mobile applications" }
21
+ ];
22
+ var StackSelection = ({ matrix }) => {
23
+ const { selectStack, setStep, goBack } = useWizardStore();
24
+ const options = [
25
+ { value: BACK_VALUE, label: "\u2190 Back" },
26
+ ...matrix.suggestedStacks.map((stack) => ({
27
+ value: stack.id,
28
+ label: `${stack.name} - ${stack.description}`
29
+ }))
30
+ ];
31
+ const handleSelect = (value) => {
32
+ if (value === BACK_VALUE) {
33
+ goBack();
34
+ return;
35
+ }
36
+ const stack = matrix.suggestedStacks.find((s) => s.id === value);
37
+ if (stack) {
38
+ selectStack(stack.id);
39
+ setStep("stack-options");
40
+ }
41
+ };
42
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
43
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "Select a pre-built template:" }),
44
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
45
+ Select,
46
+ {
47
+ options,
48
+ onChange: handleSelect,
49
+ visibleOptionCount: options.length
50
+ }
51
+ ) }),
52
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
53
+ "\u2191",
54
+ "/",
55
+ "\u2193",
56
+ " navigate ENTER select ESC back"
57
+ ] }) })
58
+ ] });
59
+ };
60
+ var DomainSelection = () => {
61
+ const { selectedDomains, toggleDomain, setStep, goBack } = useWizardStore();
62
+ const domainOptions = AVAILABLE_DOMAINS.map((domain) => {
63
+ const isSelected = selectedDomains.includes(domain.id);
64
+ const checkbox = isSelected ? "[\u2713]" : "[ ]";
65
+ return {
66
+ value: domain.id,
67
+ label: `${checkbox} ${domain.label} - ${domain.description}`
68
+ };
69
+ });
70
+ const options = [
71
+ { value: BACK_VALUE, label: "\u2190 Back" },
72
+ ...domainOptions,
73
+ ...selectedDomains.length > 0 ? [
74
+ {
75
+ value: CONTINUE_VALUE,
76
+ label: `\u2192 Continue with ${selectedDomains.length} domain(s)`
77
+ }
78
+ ] : []
79
+ ];
80
+ const handleSelect = (value) => {
81
+ if (value === BACK_VALUE) {
82
+ goBack();
83
+ return;
84
+ }
85
+ if (value === CONTINUE_VALUE) {
86
+ if (selectedDomains.length > 0) {
87
+ setStep("build");
88
+ }
89
+ return;
90
+ }
91
+ toggleDomain(value);
92
+ };
93
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
94
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "Select domains to configure:" }),
95
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Select one or more domains, then continue" }),
96
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Select, { options, onChange: handleSelect }) }),
97
+ selectedDomains.length > 0 ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { children: [
98
+ "Selected: ",
99
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: selectedDomains.join(", ") })
100
+ ] }) }) : /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "yellow", children: "Please select at least one domain" }) }),
101
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
102
+ "\u2191",
103
+ "/",
104
+ "\u2193",
105
+ " navigate ENTER toggle/select ESC back"
106
+ ] }) })
107
+ ] });
108
+ };
109
+ var StepStack = ({ matrix }) => {
110
+ const { approach } = useWizardStore();
111
+ if (approach === "stack") {
112
+ return /* @__PURE__ */ jsx(StackSelection, { matrix });
113
+ }
114
+ return /* @__PURE__ */ jsx(DomainSelection, {});
115
+ };
116
+
117
+ export {
118
+ StepStack
119
+ };
120
+ //# sourceMappingURL=chunk-HNDT5QRB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli-v2/components/wizard/step-stack.tsx"],"sourcesContent":["/**\n * StepStack component - Dual-purpose step for stack selection or domain selection.\n *\n * Stack path (approach === \"stack\"):\n * - Shows list of pre-built stacks from matrix.suggestedStacks\n * - Selecting a stack populates domainSelections and goes to stack-options\n *\n * Scratch path (approach === \"scratch\"):\n * - Shows multi-select of domains (Web, API, CLI, Mobile)\n * - User selects which domains to configure\n * - Continue goes to build step for first selected domain\n */\nimport React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport { Select } from \"@inkjs/ui\";\nimport { useWizardStore } from \"../../stores/wizard-store.js\";\nimport type { MergedSkillsMatrix } from \"../../types-matrix.js\";\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nconst BACK_VALUE = \"_back\";\nconst CONTINUE_VALUE = \"_continue\";\n\n/** Available domains for scratch path */\nconst AVAILABLE_DOMAINS = [\n { id: \"web\", label: \"Web\", description: \"Frontend web applications\" },\n { id: \"api\", label: \"API\", description: \"Backend APIs and services\" },\n { id: \"cli\", label: \"CLI\", description: \"Command-line tools\" },\n { id: \"mobile\", label: \"Mobile\", description: \"Mobile applications\" },\n];\n\n// =============================================================================\n// Types\n// =============================================================================\n\ninterface StepStackProps {\n matrix: MergedSkillsMatrix;\n}\n\n// =============================================================================\n// Stack Selection Sub-component\n// =============================================================================\n\ninterface StackSelectionProps {\n matrix: MergedSkillsMatrix;\n}\n\nconst StackSelection: React.FC<StackSelectionProps> = ({ matrix }) => {\n const { selectStack, setStep, goBack } = useWizardStore();\n\n // Build options from matrix.suggestedStacks\n const options = [\n { value: BACK_VALUE, label: \"\\u2190 Back\" },\n ...matrix.suggestedStacks.map((stack) => ({\n value: stack.id,\n label: `${stack.name} - ${stack.description}`,\n })),\n ];\n\n const handleSelect = (value: string) => {\n if (value === BACK_VALUE) {\n goBack();\n return;\n }\n\n const stack = matrix.suggestedStacks.find((s) => s.id === value);\n if (stack) {\n selectStack(stack.id);\n setStep(\"stack-options\");\n }\n };\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>Select a pre-built template:</Text>\n <Box marginTop={1}>\n <Select\n options={options}\n onChange={handleSelect}\n visibleOptionCount={options.length}\n />\n </Box>\n <Box marginTop={1}>\n <Text dimColor>\n {\"\\u2191\"}/{\"\\u2193\"} navigate ENTER select ESC back\n </Text>\n </Box>\n </Box>\n );\n};\n\n// =============================================================================\n// Domain Selection Sub-component\n// =============================================================================\n\nconst DomainSelection: React.FC = () => {\n const { selectedDomains, toggleDomain, setStep, goBack } = useWizardStore();\n\n // Build options with checkboxes showing selection state\n const domainOptions = AVAILABLE_DOMAINS.map((domain) => {\n const isSelected = selectedDomains.includes(domain.id);\n const checkbox = isSelected ? \"[\\u2713]\" : \"[ ]\";\n return {\n value: domain.id,\n label: `${checkbox} ${domain.label} - ${domain.description}`,\n };\n });\n\n const options = [\n { value: BACK_VALUE, label: \"\\u2190 Back\" },\n ...domainOptions,\n ...(selectedDomains.length > 0\n ? [\n {\n value: CONTINUE_VALUE,\n label: `\\u2192 Continue with ${selectedDomains.length} domain(s)`,\n },\n ]\n : []),\n ];\n\n const handleSelect = (value: string) => {\n if (value === BACK_VALUE) {\n goBack();\n return;\n }\n\n if (value === CONTINUE_VALUE) {\n if (selectedDomains.length > 0) {\n setStep(\"build\");\n }\n return;\n }\n\n // Toggle domain selection\n toggleDomain(value);\n };\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>Select domains to configure:</Text>\n <Text dimColor>Select one or more domains, then continue</Text>\n <Box marginTop={1}>\n <Select options={options} onChange={handleSelect} />\n </Box>\n {selectedDomains.length > 0 ? (\n <Box marginTop={1}>\n <Text>\n Selected: <Text color=\"cyan\">{selectedDomains.join(\", \")}</Text>\n </Text>\n </Box>\n ) : (\n <Box marginTop={1}>\n <Text color=\"yellow\">Please select at least one domain</Text>\n </Box>\n )}\n <Box marginTop={1}>\n <Text dimColor>\n {\"\\u2191\"}/{\"\\u2193\"} navigate ENTER toggle/select ESC back\n </Text>\n </Box>\n </Box>\n );\n};\n\n// =============================================================================\n// Main Component\n// =============================================================================\n\nexport const StepStack: React.FC<StepStackProps> = ({ matrix }) => {\n const { approach } = useWizardStore();\n\n if (approach === \"stack\") {\n return <StackSelection matrix={matrix} />;\n }\n\n // approach === \"scratch\"\n return <DomainSelection />;\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ DEFAULT_PRESELECTED_SKILLS
4
+ } from "./chunk-A3J6IAXK.js";
5
+ import {
6
+ init_esm_shims
7
+ } from "./chunk-DHET7RCE.js";
8
+
9
+ // src/cli-v2/stores/wizard-store.ts
10
+ init_esm_shims();
11
+ import { create } from "zustand";
12
+ var createInitialState = () => ({
13
+ step: "approach",
14
+ approach: null,
15
+ selectedStackId: null,
16
+ stackAction: null,
17
+ selectedDomains: [],
18
+ currentDomainIndex: 0,
19
+ domainSelections: {},
20
+ focusedRow: 0,
21
+ focusedCol: 0,
22
+ currentRefineIndex: 0,
23
+ skillSources: {},
24
+ refineAction: null,
25
+ showDescriptions: false,
26
+ expertMode: false,
27
+ installMode: "local",
28
+ history: []
29
+ });
30
+ var useWizardStore = create((set, get) => ({
31
+ ...createInitialState(),
32
+ setStep: (step) => set((state) => ({
33
+ step,
34
+ history: [...state.history, state.step],
35
+ // Reset focus when changing steps
36
+ focusedRow: 0,
37
+ focusedCol: 0
38
+ })),
39
+ setApproach: (approach) => set({ approach }),
40
+ selectStack: (stackId) => set({ selectedStackId: stackId }),
41
+ setStackAction: (action) => set({ stackAction: action }),
42
+ toggleDomain: (domain) => set((state) => {
43
+ const isSelected = state.selectedDomains.includes(domain);
44
+ return {
45
+ selectedDomains: isSelected ? state.selectedDomains.filter((d) => d !== domain) : [...state.selectedDomains, domain]
46
+ };
47
+ }),
48
+ setDomainSelection: (domain, subcategory, technologies) => set((state) => ({
49
+ domainSelections: {
50
+ ...state.domainSelections,
51
+ [domain]: {
52
+ ...state.domainSelections[domain],
53
+ [subcategory]: technologies
54
+ }
55
+ }
56
+ })),
57
+ toggleTechnology: (domain, subcategory, technology, exclusive) => set((state) => {
58
+ const currentSelections = state.domainSelections[domain]?.[subcategory] || [];
59
+ const isSelected = currentSelections.includes(technology);
60
+ let newSelections;
61
+ if (exclusive) {
62
+ newSelections = isSelected ? [] : [technology];
63
+ } else {
64
+ newSelections = isSelected ? currentSelections.filter((t) => t !== technology) : [...currentSelections, technology];
65
+ }
66
+ return {
67
+ domainSelections: {
68
+ ...state.domainSelections,
69
+ [domain]: {
70
+ ...state.domainSelections[domain],
71
+ [subcategory]: newSelections
72
+ }
73
+ }
74
+ };
75
+ }),
76
+ setCurrentDomainIndex: (index) => set({ currentDomainIndex: index, focusedRow: 0, focusedCol: 0 }),
77
+ nextDomain: () => {
78
+ const state = get();
79
+ if (state.currentDomainIndex < state.selectedDomains.length - 1) {
80
+ set({
81
+ currentDomainIndex: state.currentDomainIndex + 1,
82
+ focusedRow: 0,
83
+ focusedCol: 0
84
+ });
85
+ return true;
86
+ }
87
+ return false;
88
+ },
89
+ prevDomain: () => {
90
+ const state = get();
91
+ if (state.currentDomainIndex > 0) {
92
+ set({
93
+ currentDomainIndex: state.currentDomainIndex - 1,
94
+ focusedRow: 0,
95
+ focusedCol: 0
96
+ });
97
+ return true;
98
+ }
99
+ return false;
100
+ },
101
+ setFocus: (row, col) => set({ focusedRow: row, focusedCol: col }),
102
+ setRefineAction: (action) => set({ refineAction: action }),
103
+ setSkillSource: (technology, skillId) => set((state) => ({
104
+ skillSources: {
105
+ ...state.skillSources,
106
+ [technology]: skillId
107
+ }
108
+ })),
109
+ setCurrentRefineIndex: (index) => set({ currentRefineIndex: index }),
110
+ toggleShowDescriptions: () => set((state) => ({ showDescriptions: !state.showDescriptions })),
111
+ toggleExpertMode: () => set((state) => ({ expertMode: !state.expertMode })),
112
+ toggleInstallMode: () => set((state) => ({
113
+ installMode: state.installMode === "plugin" ? "local" : "plugin"
114
+ })),
115
+ goBack: () => set((state) => {
116
+ const history = [...state.history];
117
+ const previousStep = history.pop();
118
+ return {
119
+ step: previousStep || "approach",
120
+ history,
121
+ focusedRow: 0,
122
+ focusedCol: 0
123
+ };
124
+ }),
125
+ reset: () => set(createInitialState()),
126
+ // ─────────────────────────────────────────────────────────────────
127
+ // Computed getters
128
+ // ─────────────────────────────────────────────────────────────────
129
+ getAllSelectedTechnologies: () => {
130
+ const state = get();
131
+ const technologies = [];
132
+ for (const domain of Object.keys(state.domainSelections)) {
133
+ for (const subcategory of Object.keys(state.domainSelections[domain])) {
134
+ technologies.push(...state.domainSelections[domain][subcategory]);
135
+ }
136
+ }
137
+ return technologies;
138
+ },
139
+ getCurrentDomain: () => {
140
+ const state = get();
141
+ return state.selectedDomains[state.currentDomainIndex] || null;
142
+ },
143
+ getSelectedSkills: () => {
144
+ const state = get();
145
+ const skillIds = [...DEFAULT_PRESELECTED_SKILLS];
146
+ for (const skillId of Object.values(state.skillSources)) {
147
+ if (!skillIds.includes(skillId)) {
148
+ skillIds.push(skillId);
149
+ }
150
+ }
151
+ return skillIds;
152
+ }
153
+ }));
154
+
155
+ export {
156
+ useWizardStore
157
+ };
158
+ //# sourceMappingURL=chunk-K7PTOVX4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli-v2/stores/wizard-store.ts"],"sourcesContent":["import { create } from \"zustand\";\nimport { DEFAULT_PRESELECTED_SKILLS } from \"../consts\";\n\n// Step types for the wizard\nexport type WizardStep =\n | \"approach\" // Choose stack template or build from scratch\n | \"stack\" // Select pre-built stack (if approach=stack) or domains (if approach=scratch)\n | \"stack-options\" // After stack selection: continue defaults or customize\n | \"build\" // CategoryGrid for technology selection\n | \"refine\" // Skill source selection\n | \"confirm\"; // Final confirmation\n\nexport interface WizardState {\n // ─────────────────────────────────────────────────────────────────\n // Current step\n // ─────────────────────────────────────────────────────────────────\n step: WizardStep;\n\n // ─────────────────────────────────────────────────────────────────\n // Flow tracking\n // ─────────────────────────────────────────────────────────────────\n approach: \"stack\" | \"scratch\" | null;\n selectedStackId: string | null;\n stackAction: \"defaults\" | \"customize\" | null; // For stack flow after selection\n\n // ─────────────────────────────────────────────────────────────────\n // Domain selection (scratch flow or customize flow)\n // ─────────────────────────────────────────────────────────────────\n selectedDomains: string[]; // ['web', 'api', 'cli', 'mobile']\n\n // ─────────────────────────────────────────────────────────────────\n // Build step state\n // ─────────────────────────────────────────────────────────────────\n currentDomainIndex: number; // Which domain we're configuring (0-based)\n domainSelections: Record<string, Record<string, string[]>>;\n // e.g., { web: { framework: ['react'], styling: ['scss-modules'] } }\n // Note: array supports multi-select categories\n\n // ─────────────────────────────────────────────────────────────────\n // Grid navigation state\n // ─────────────────────────────────────────────────────────────────\n focusedRow: number;\n focusedCol: number;\n\n // ─────────────────────────────────────────────────────────────────\n // Refine step state\n // ─────────────────────────────────────────────────────────────────\n currentRefineIndex: number; // Which skill we're refining\n skillSources: Record<string, string>; // technology -> selected skill ID\n refineAction: \"all-recommended\" | \"customize\" | null;\n\n // ─────────────────────────────────────────────────────────────────\n // UI state\n // ─────────────────────────────────────────────────────────────────\n showDescriptions: boolean;\n expertMode: boolean;\n\n // ─────────────────────────────────────────────────────────────────\n // Modes\n // ─────────────────────────────────────────────────────────────────\n installMode: \"plugin\" | \"local\";\n\n // ─────────────────────────────────────────────────────────────────\n // Navigation history\n // ─────────────────────────────────────────────────────────────────\n history: WizardStep[];\n\n // ─────────────────────────────────────────────────────────────────\n // Actions\n // ─────────────────────────────────────────────────────────────────\n setStep: (step: WizardStep) => void;\n setApproach: (approach: \"stack\" | \"scratch\") => void;\n selectStack: (stackId: string | null) => void;\n setStackAction: (action: \"defaults\" | \"customize\") => void;\n toggleDomain: (domain: string) => void;\n setDomainSelection: (\n domain: string,\n subcategory: string,\n technologies: string[],\n ) => void;\n toggleTechnology: (\n domain: string,\n subcategory: string,\n technology: string,\n exclusive: boolean,\n ) => void;\n setCurrentDomainIndex: (index: number) => void;\n nextDomain: () => boolean; // Returns true if moved to next domain, false if at end\n prevDomain: () => boolean; // Returns true if moved to prev domain, false if at start\n setFocus: (row: number, col: number) => void;\n setRefineAction: (action: \"all-recommended\" | \"customize\") => void;\n setSkillSource: (technology: string, skillId: string) => void;\n setCurrentRefineIndex: (index: number) => void;\n toggleShowDescriptions: () => void;\n toggleExpertMode: () => void;\n toggleInstallMode: () => void;\n goBack: () => void;\n reset: () => void;\n\n // ─────────────────────────────────────────────────────────────────\n // Computed getters (derive from state)\n // ─────────────────────────────────────────────────────────────────\n getAllSelectedTechnologies: () => string[];\n getCurrentDomain: () => string | null;\n getSelectedSkills: () => string[]; // All selected skills including preselected\n}\n\nconst createInitialState = () => ({\n step: \"approach\" as WizardStep,\n approach: null as \"stack\" | \"scratch\" | null,\n selectedStackId: null as string | null,\n stackAction: null as \"defaults\" | \"customize\" | null,\n selectedDomains: [] as string[],\n currentDomainIndex: 0,\n domainSelections: {} as Record<string, Record<string, string[]>>,\n focusedRow: 0,\n focusedCol: 0,\n currentRefineIndex: 0,\n skillSources: {} as Record<string, string>,\n refineAction: null as \"all-recommended\" | \"customize\" | null,\n showDescriptions: false,\n expertMode: false,\n installMode: \"local\" as \"plugin\" | \"local\",\n history: [] as WizardStep[],\n});\n\nexport const useWizardStore = create<WizardState>((set, get) => ({\n ...createInitialState(),\n\n setStep: (step) =>\n set((state) => ({\n step,\n history: [...state.history, state.step],\n // Reset focus when changing steps\n focusedRow: 0,\n focusedCol: 0,\n })),\n\n setApproach: (approach) => set({ approach }),\n\n selectStack: (stackId) => set({ selectedStackId: stackId }),\n\n setStackAction: (action) => set({ stackAction: action }),\n\n toggleDomain: (domain) =>\n set((state) => {\n const isSelected = state.selectedDomains.includes(domain);\n return {\n selectedDomains: isSelected\n ? state.selectedDomains.filter((d) => d !== domain)\n : [...state.selectedDomains, domain],\n };\n }),\n\n setDomainSelection: (domain, subcategory, technologies) =>\n set((state) => ({\n domainSelections: {\n ...state.domainSelections,\n [domain]: {\n ...state.domainSelections[domain],\n [subcategory]: technologies,\n },\n },\n })),\n\n toggleTechnology: (domain, subcategory, technology, exclusive) =>\n set((state) => {\n const currentSelections =\n state.domainSelections[domain]?.[subcategory] || [];\n const isSelected = currentSelections.includes(technology);\n\n let newSelections: string[];\n if (exclusive) {\n // For exclusive categories, toggle off if already selected, otherwise select only this one\n newSelections = isSelected ? [] : [technology];\n } else {\n // For multi-select categories, toggle the selection\n newSelections = isSelected\n ? currentSelections.filter((t) => t !== technology)\n : [...currentSelections, technology];\n }\n\n return {\n domainSelections: {\n ...state.domainSelections,\n [domain]: {\n ...state.domainSelections[domain],\n [subcategory]: newSelections,\n },\n },\n };\n }),\n\n setCurrentDomainIndex: (index) =>\n set({ currentDomainIndex: index, focusedRow: 0, focusedCol: 0 }),\n\n nextDomain: () => {\n const state = get();\n if (state.currentDomainIndex < state.selectedDomains.length - 1) {\n set({\n currentDomainIndex: state.currentDomainIndex + 1,\n focusedRow: 0,\n focusedCol: 0,\n });\n return true;\n }\n return false;\n },\n\n prevDomain: () => {\n const state = get();\n if (state.currentDomainIndex > 0) {\n set({\n currentDomainIndex: state.currentDomainIndex - 1,\n focusedRow: 0,\n focusedCol: 0,\n });\n return true;\n }\n return false;\n },\n\n setFocus: (row, col) => set({ focusedRow: row, focusedCol: col }),\n\n setRefineAction: (action) => set({ refineAction: action }),\n\n setSkillSource: (technology, skillId) =>\n set((state) => ({\n skillSources: {\n ...state.skillSources,\n [technology]: skillId,\n },\n })),\n\n setCurrentRefineIndex: (index) => set({ currentRefineIndex: index }),\n\n toggleShowDescriptions: () =>\n set((state) => ({ showDescriptions: !state.showDescriptions })),\n\n toggleExpertMode: () => set((state) => ({ expertMode: !state.expertMode })),\n\n toggleInstallMode: () =>\n set((state) => ({\n installMode: state.installMode === \"plugin\" ? \"local\" : \"plugin\",\n })),\n\n goBack: () =>\n set((state) => {\n const history = [...state.history];\n const previousStep = history.pop();\n return {\n step: previousStep || \"approach\",\n history,\n focusedRow: 0,\n focusedCol: 0,\n };\n }),\n\n reset: () => set(createInitialState()),\n\n // ─────────────────────────────────────────────────────────────────\n // Computed getters\n // ─────────────────────────────────────────────────────────────────\n getAllSelectedTechnologies: () => {\n const state = get();\n const technologies: string[] = [];\n for (const domain of Object.keys(state.domainSelections)) {\n for (const subcategory of Object.keys(state.domainSelections[domain])) {\n technologies.push(...state.domainSelections[domain][subcategory]);\n }\n }\n return technologies;\n },\n\n getCurrentDomain: () => {\n const state = get();\n return state.selectedDomains[state.currentDomainIndex] || null;\n },\n\n getSelectedSkills: () => {\n const state = get();\n // Include preselected methodology skills plus resolved skill sources\n const skillIds: string[] = [...DEFAULT_PRESELECTED_SKILLS];\n for (const skillId of Object.values(state.skillSources)) {\n if (!skillIds.includes(skillId)) {\n skillIds.push(skillId);\n }\n }\n return skillIds;\n },\n}));\n"],"mappings":"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","names":[]}
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ DEFAULT_VERSION
4
+ } from "./chunk-A3J6IAXK.js";
5
+ import {
6
+ ensureDir,
7
+ writeFile
8
+ } from "./chunk-MMDXNZPF.js";
9
+ import {
10
+ init_esm_shims
11
+ } from "./chunk-DHET7RCE.js";
12
+
13
+ // src/cli-v2/lib/plugin-manifest.ts
14
+ init_esm_shims();
15
+ import path from "path";
16
+ var DEFAULT_LICENSE = "MIT";
17
+ var PLUGIN_DIR_NAME = ".claude-plugin";
18
+ var PLUGIN_MANIFEST_FILE = "plugin.json";
19
+ var SKILL_PLUGIN_PREFIX = "skill-";
20
+ function buildAuthor(name, email) {
21
+ if (!name) {
22
+ return void 0;
23
+ }
24
+ const author = { name };
25
+ if (email) {
26
+ author.email = email;
27
+ }
28
+ return author;
29
+ }
30
+ function generateSkillPluginManifest(options) {
31
+ const manifest = {
32
+ name: `${SKILL_PLUGIN_PREFIX}${options.skillName}`,
33
+ version: options.version ?? DEFAULT_VERSION,
34
+ license: DEFAULT_LICENSE,
35
+ skills: "./skills/"
36
+ };
37
+ if (options.description) {
38
+ manifest.description = options.description;
39
+ }
40
+ const author = buildAuthor(options.author, options.authorEmail);
41
+ if (author) {
42
+ manifest.author = author;
43
+ }
44
+ if (options.keywords && options.keywords.length > 0) {
45
+ manifest.keywords = options.keywords;
46
+ }
47
+ return manifest;
48
+ }
49
+ function generateStackPluginManifest(options) {
50
+ const manifest = {
51
+ name: options.stackName,
52
+ version: options.version ?? DEFAULT_VERSION,
53
+ license: DEFAULT_LICENSE
54
+ };
55
+ if (options.hasSkills) {
56
+ manifest.skills = "./skills/";
57
+ }
58
+ if (options.description) {
59
+ manifest.description = options.description;
60
+ }
61
+ const author = buildAuthor(options.author, options.authorEmail);
62
+ if (author) {
63
+ manifest.author = author;
64
+ }
65
+ if (options.keywords && options.keywords.length > 0) {
66
+ manifest.keywords = options.keywords;
67
+ }
68
+ if (options.hasHooks) {
69
+ manifest.hooks = "./hooks/hooks.json";
70
+ }
71
+ return manifest;
72
+ }
73
+ async function writePluginManifest(outputDir, manifest) {
74
+ const pluginDir = path.join(outputDir, PLUGIN_DIR_NAME);
75
+ const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_FILE);
76
+ await ensureDir(pluginDir);
77
+ const content = JSON.stringify(manifest, null, 2);
78
+ await writeFile(manifestPath, content);
79
+ return manifestPath;
80
+ }
81
+ function getPluginManifestPath(outputDir) {
82
+ return path.join(outputDir, PLUGIN_DIR_NAME, PLUGIN_MANIFEST_FILE);
83
+ }
84
+
85
+ export {
86
+ generateSkillPluginManifest,
87
+ generateStackPluginManifest,
88
+ writePluginManifest,
89
+ getPluginManifestPath
90
+ };
91
+ //# sourceMappingURL=chunk-LQTST4WY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli-v2/lib/plugin-manifest.ts"],"sourcesContent":["import path from \"path\";\nimport { ensureDir, writeFile } from \"../utils/fs\";\nimport { DEFAULT_VERSION } from \"../consts\";\nimport type { PluginManifest, PluginAuthor } from \"../../types\";\n\nconst DEFAULT_LICENSE = \"MIT\";\nconst PLUGIN_DIR_NAME = \".claude-plugin\";\nconst PLUGIN_MANIFEST_FILE = \"plugin.json\";\nconst SKILL_PLUGIN_PREFIX = \"skill-\";\n\nexport interface SkillPluginOptions {\n skillName: string;\n description?: string;\n author?: string;\n authorEmail?: string;\n version?: string;\n keywords?: string[];\n}\n\nexport interface StackPluginOptions {\n stackName: string;\n description?: string;\n author?: string;\n authorEmail?: string;\n version?: string;\n keywords?: string[];\n hasSkills?: boolean;\n hasAgents?: boolean;\n hasHooks?: boolean;\n}\n\nfunction buildAuthor(name?: string, email?: string): PluginAuthor | undefined {\n if (!name) {\n return undefined;\n }\n const author: PluginAuthor = { name };\n if (email) {\n author.email = email;\n }\n return author;\n}\n\nexport function generateSkillPluginManifest(\n options: SkillPluginOptions,\n): PluginManifest {\n const manifest: PluginManifest = {\n name: `${SKILL_PLUGIN_PREFIX}${options.skillName}`,\n version: options.version ?? DEFAULT_VERSION,\n license: DEFAULT_LICENSE,\n skills: \"./skills/\",\n };\n\n if (options.description) {\n manifest.description = options.description;\n }\n\n const author = buildAuthor(options.author, options.authorEmail);\n if (author) {\n manifest.author = author;\n }\n\n if (options.keywords && options.keywords.length > 0) {\n manifest.keywords = options.keywords;\n }\n\n return manifest;\n}\n\nexport function generateStackPluginManifest(\n options: StackPluginOptions,\n): PluginManifest {\n const manifest: PluginManifest = {\n name: options.stackName,\n version: options.version ?? DEFAULT_VERSION,\n license: DEFAULT_LICENSE,\n };\n\n if (options.hasSkills) {\n manifest.skills = \"./skills/\";\n }\n\n if (options.description) {\n manifest.description = options.description;\n }\n\n const author = buildAuthor(options.author, options.authorEmail);\n if (author) {\n manifest.author = author;\n }\n\n if (options.keywords && options.keywords.length > 0) {\n manifest.keywords = options.keywords;\n }\n\n // Note: Claude Code plugins don't support agents field in manifest\n // Agents are discovered from ./agents/ directory automatically\n\n if (options.hasHooks) {\n manifest.hooks = \"./hooks/hooks.json\";\n }\n\n return manifest;\n}\n\nexport async function writePluginManifest(\n outputDir: string,\n manifest: PluginManifest,\n): Promise<string> {\n const pluginDir = path.join(outputDir, PLUGIN_DIR_NAME);\n const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_FILE);\n\n await ensureDir(pluginDir);\n\n const content = JSON.stringify(manifest, null, 2);\n await writeFile(manifestPath, content);\n\n return manifestPath;\n}\n\nexport function getPluginDir(outputDir: string): string {\n return path.join(outputDir, PLUGIN_DIR_NAME);\n}\n\nexport function getPluginManifestPath(outputDir: string): string {\n return path.join(outputDir, PLUGIN_DIR_NAME, PLUGIN_MANIFEST_FILE);\n}\n"],"mappings":";;;;;;;;;;;;;AAAA;AAAA,OAAO,UAAU;AAKjB,IAAM,kBAAkB;AACxB,IAAM,kBAAkB;AACxB,IAAM,uBAAuB;AAC7B,IAAM,sBAAsB;AAuB5B,SAAS,YAAY,MAAe,OAA0C;AAC5E,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AACA,QAAM,SAAuB,EAAE,KAAK;AACpC,MAAI,OAAO;AACT,WAAO,QAAQ;AAAA,EACjB;AACA,SAAO;AACT;AAEO,SAAS,4BACd,SACgB;AAChB,QAAM,WAA2B;AAAA,IAC/B,MAAM,GAAG,mBAAmB,GAAG,QAAQ,SAAS;AAAA,IAChD,SAAS,QAAQ,WAAW;AAAA,IAC5B,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AAEA,MAAI,QAAQ,aAAa;AACvB,aAAS,cAAc,QAAQ;AAAA,EACjC;AAEA,QAAM,SAAS,YAAY,QAAQ,QAAQ,QAAQ,WAAW;AAC9D,MAAI,QAAQ;AACV,aAAS,SAAS;AAAA,EACpB;AAEA,MAAI,QAAQ,YAAY,QAAQ,SAAS,SAAS,GAAG;AACnD,aAAS,WAAW,QAAQ;AAAA,EAC9B;AAEA,SAAO;AACT;AAEO,SAAS,4BACd,SACgB;AAChB,QAAM,WAA2B;AAAA,IAC/B,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ,WAAW;AAAA,IAC5B,SAAS;AAAA,EACX;AAEA,MAAI,QAAQ,WAAW;AACrB,aAAS,SAAS;AAAA,EACpB;AAEA,MAAI,QAAQ,aAAa;AACvB,aAAS,cAAc,QAAQ;AAAA,EACjC;AAEA,QAAM,SAAS,YAAY,QAAQ,QAAQ,QAAQ,WAAW;AAC9D,MAAI,QAAQ;AACV,aAAS,SAAS;AAAA,EACpB;AAEA,MAAI,QAAQ,YAAY,QAAQ,SAAS,SAAS,GAAG;AACnD,aAAS,WAAW,QAAQ;AAAA,EAC9B;AAKA,MAAI,QAAQ,UAAU;AACpB,aAAS,QAAQ;AAAA,EACnB;AAEA,SAAO;AACT;AAEA,eAAsB,oBACpB,WACA,UACiB;AACjB,QAAM,YAAY,KAAK,KAAK,WAAW,eAAe;AACtD,QAAM,eAAe,KAAK,KAAK,WAAW,oBAAoB;AAE9D,QAAM,UAAU,SAAS;AAEzB,QAAM,UAAU,KAAK,UAAU,UAAU,MAAM,CAAC;AAChD,QAAM,UAAU,cAAc,OAAO;AAErC,SAAO;AACT;AAMO,SAAS,sBAAsB,WAA2B;AAC/D,SAAO,KAAK,KAAK,WAAW,iBAAiB,oBAAoB;AACnE;","names":[]}