@shepai/cli 1.92.1-pr278.e659c75 → 1.92.1-pr278.eb2eaaa

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 (139) hide show
  1. package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.js +2 -2
  2. package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.d.ts.map +1 -1
  3. package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.js +69 -40
  4. package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.stories.js +1 -1
  5. package/dist/tsconfig.build.tsbuildinfo +1 -1
  6. package/package.json +1 -1
  7. package/web/.next/BUILD_ID +1 -1
  8. package/web/.next/build-manifest.json +2 -2
  9. package/web/.next/fallback-build-manifest.json +2 -2
  10. package/web/.next/prerender-manifest.json +3 -3
  11. package/web/.next/required-server-files.js +1 -1
  12. package/web/.next/required-server-files.json +1 -1
  13. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +19 -19
  14. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  15. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  16. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +24 -24
  17. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  18. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  19. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +24 -24
  20. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  21. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  22. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +17 -17
  23. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  24. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  25. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +19 -19
  26. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  27. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  28. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +24 -24
  29. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  30. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  31. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +24 -24
  32. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  33. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  34. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +17 -17
  35. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  36. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  37. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +17 -17
  38. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  39. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  40. package/web/.next/server/app/_global-error.html +2 -2
  41. package/web/.next/server/app/_global-error.rsc +1 -1
  42. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  43. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  44. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  45. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  46. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  47. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  48. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  49. package/web/.next/server/app/settings/page/server-reference-manifest.json +5 -5
  50. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  51. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  52. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  53. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  54. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  55. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  56. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  57. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  58. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  59. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  60. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_002ab1c0.js +1 -1
  61. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_002ab1c0.js.map +1 -1
  62. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_1bab40be.js +1 -1
  63. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_1bab40be.js.map +1 -1
  64. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +1 -1
  65. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js.map +1 -1
  66. package/web/.next/server/chunks/ssr/[root-of-the-server]__22751bba._.js +1 -1
  67. package/web/.next/server/chunks/ssr/[root-of-the-server]__22751bba._.js.map +1 -1
  68. package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js +2 -2
  69. package/web/.next/server/chunks/ssr/[root-of-the-server]__31fc8960._.js +1 -1
  70. package/web/.next/server/chunks/ssr/[root-of-the-server]__31fc8960._.js.map +1 -1
  71. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  72. package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +1 -1
  73. package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js +2 -2
  74. package/web/.next/server/chunks/ssr/[root-of-the-server]__9497d008._.js +1 -1
  75. package/web/.next/server/chunks/ssr/[root-of-the-server]__9497d008._.js.map +1 -1
  76. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
  77. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  78. package/web/.next/server/chunks/ssr/[root-of-the-server]__e630cc47._.js +1 -1
  79. package/web/.next/server/chunks/ssr/[root-of-the-server]__e630cc47._.js.map +1 -1
  80. package/web/.next/server/chunks/ssr/[root-of-the-server]__fb487740._.js +1 -1
  81. package/web/.next/server/chunks/ssr/[root-of-the-server]__fb487740._.js.map +1 -1
  82. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +1 -1
  83. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js.map +1 -1
  84. package/web/.next/server/chunks/ssr/_11d16daf._.js +3 -0
  85. package/web/.next/server/chunks/ssr/_11d16daf._.js.map +1 -0
  86. package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
  87. package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
  88. package/web/.next/server/chunks/ssr/_8dacd1e7._.js +1 -1
  89. package/web/.next/server/chunks/ssr/_8dacd1e7._.js.map +1 -1
  90. package/web/.next/server/chunks/ssr/{_42d717e9._.js → _94aa7a90._.js} +2 -2
  91. package/web/.next/server/chunks/ssr/{_42d717e9._.js.map → _94aa7a90._.js.map} +1 -1
  92. package/web/.next/server/chunks/ssr/_b3687a24._.js +3 -0
  93. package/web/.next/server/chunks/ssr/_b3687a24._.js.map +1 -0
  94. package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
  95. package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
  96. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  97. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  98. package/web/.next/server/chunks/ssr/src_presentation_web_3a8fc63d._.js +2 -2
  99. package/web/.next/server/chunks/ssr/src_presentation_web_3a8fc63d._.js.map +1 -1
  100. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_1695630c.js +1 -1
  101. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_1695630c.js.map +1 -1
  102. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
  103. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
  104. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
  105. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
  106. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
  107. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
  108. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  109. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  110. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  111. package/web/.next/server/chunks/ssr/src_presentation_web_f16e6874._.js +2 -2
  112. package/web/.next/server/chunks/ssr/src_presentation_web_f16e6874._.js.map +1 -1
  113. package/web/.next/server/pages/500.html +2 -2
  114. package/web/.next/server/server-reference-manifest.js +1 -1
  115. package/web/.next/server/server-reference-manifest.json +29 -29
  116. package/web/.next/static/chunks/{1204eca6bcfa0d91.js → 36006a93ea31f774.js} +1 -1
  117. package/web/.next/static/chunks/{b9aa44f4ae7cff2c.js → 6101077c28c9be05.js} +1 -1
  118. package/web/.next/static/chunks/633900bb27d59b41.js +1 -0
  119. package/web/.next/static/chunks/{82bc40eb13750b22.js → 7def5ff4308d9a4c.js} +1 -1
  120. package/web/.next/static/chunks/{76d20d5cc5750310.js → 9e06d69201673a16.js} +1 -1
  121. package/web/.next/static/chunks/{857b67d726d491be.js → bdfe7e3ba8d6e348.js} +1 -1
  122. package/web/.next/static/chunks/c83b2280adda5e97.js +1 -0
  123. package/web/.next/static/chunks/ca0371dce88829fd.js +1 -0
  124. package/web/.next/static/chunks/d10c356ebeeca835.css +2 -0
  125. package/web/.next/static/chunks/e38dc0ac10bb577f.js +1 -0
  126. package/web/.next/static/chunks/{5ec5b2d125fcf404.js → eb11390cbbc60374.js} +1 -1
  127. package/web/.next/static/chunks/{d517923e1f743a20.js → f0d32a6dd45ccef1.js} +1 -1
  128. package/web/.next/server/chunks/ssr/_12259d8f._.js +0 -3
  129. package/web/.next/server/chunks/ssr/_12259d8f._.js.map +0 -1
  130. package/web/.next/server/chunks/ssr/_25e25a5c._.js +0 -3
  131. package/web/.next/server/chunks/ssr/_25e25a5c._.js.map +0 -1
  132. package/web/.next/static/chunks/22ce70698a96441b.js +0 -1
  133. package/web/.next/static/chunks/37b4993507880f84.css +0 -2
  134. package/web/.next/static/chunks/7b3210ed80a750a4.js +0 -1
  135. package/web/.next/static/chunks/980d70fe7dd93db1.js +0 -1
  136. package/web/.next/static/chunks/9e64c6e926a5fc72.js +0 -1
  137. /package/web/.next/static/{xI3YfrsT7xbsvGfXX5Uy2 → WKNwGUFI5YJOhqCAE4EOf}/_buildManifest.js +0 -0
  138. /package/web/.next/static/{xI3YfrsT7xbsvGfXX5Uy2 → WKNwGUFI5YJOhqCAE4EOf}/_clientMiddlewareManifest.json +0 -0
  139. /package/web/.next/static/{xI3YfrsT7xbsvGfXX5Uy2 → WKNwGUFI5YJOhqCAE4EOf}/_ssgManifest.js +0 -0
@@ -32,9 +32,9 @@ export function ControlCenterEmptyState({ onRepositorySelect, className, }) {
32
32
  const handleAgentSetupComplete = useCallback(() => {
33
33
  setAgentReady(true);
34
34
  }, []);
35
- return (_jsxs("div", { "data-testid": "control-center-empty-state", className: cn('relative h-full w-full', className), children: [_jsx("div", { className: "absolute inset-0 [background-image:radial-gradient(circle,_var(--color-border)_1px,_transparent_1px)] [background-size:24px_24px]" }), _jsxs("div", { className: "absolute top-8 left-8 z-10", children: [_jsx("h1", { className: "text-4xl font-bold tracking-tight", children: "Features" }), _jsx("p", { className: "text-muted-foreground text-3xl font-light", children: "Control Center" })] }), _jsx("div", { className: "relative z-10 flex h-full items-center justify-center", children: _jsx("div", { className: "flex max-w-lg flex-col items-center gap-6", children: !agentReady ? (
35
+ return (_jsxs("div", { "data-testid": "control-center-empty-state", className: cn('relative h-full w-full', className), children: [_jsx("div", { className: "absolute inset-0 [background-image:radial-gradient(circle,_var(--color-border)_1px,_transparent_1px)] [background-size:24px_24px]" }), _jsxs("div", { className: "absolute top-8 left-8 z-10", children: [_jsx("h1", { className: "text-4xl font-bold tracking-tight", children: "Features" }), _jsx("p", { className: "text-muted-foreground text-3xl font-light", children: "Control Center" })] }), _jsx("div", { className: "relative z-10 flex h-full items-center justify-center", children: _jsx("div", { className: "flex w-72 flex-col items-center gap-4", children: !agentReady ? (
36
36
  /* Step 1: Agent setup */
37
37
  _jsx(WelcomeAgentSetup, { onComplete: handleAgentSetupComplete })) : (
38
38
  /* Step 2: Add repository (shown after agent is configured) */
39
- _jsxs(_Fragment, { children: [_jsxs("div", { className: "text-muted-foreground flex items-center gap-2", children: [_jsx(Github, { className: "h-4 w-4" }), _jsx("span", { className: "text-xs font-semibold tracking-widest uppercase", children: "Repositories" })] }), _jsxs("button", { type: "button", "data-testid": "empty-state-add-repository", onClick: handlePickerClick, disabled: loading, className: "border-muted-foreground/30 hover:border-primary hover:text-primary flex cursor-pointer items-center gap-3 rounded-lg border-2 border-dashed px-8 py-4 transition-colors disabled:cursor-wait disabled:opacity-60", children: [loading ? (_jsx(Loader2, { className: "h-5 w-5 animate-spin" })) : (_jsx(Plus, { className: "h-5 w-5" })), _jsx("span", { className: "text-sm font-medium", children: loading ? 'Opening...' : 'Add Repository' })] }), _jsxs("div", { className: "text-muted-foreground flex items-center gap-3", children: [_jsx("div", { className: "bg-border h-px w-16" }), _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(TerminalSquare, { className: "h-3.5 w-3.5" }), _jsx("span", { className: "text-xs font-semibold tracking-widest uppercase", children: "Or start from the command line" })] }), _jsx("div", { className: "bg-border h-px w-16" })] }), _jsxs("div", { "data-testid": "cli-code-block", className: "relative w-full rounded-lg bg-zinc-900 px-5 py-4 font-mono text-sm text-zinc-100", children: [_jsx("button", { type: "button", "data-testid": "cli-code-block-copy", onClick: handleCopy, className: "absolute top-3 right-3 cursor-pointer rounded p-1.5 text-zinc-400 transition-colors hover:bg-zinc-800 hover:text-zinc-200", "aria-label": "Copy commands", children: copied ? _jsx(Check, { className: "h-4 w-4" }) : _jsx(Copy, { className: "h-4 w-4" }) }), _jsx("div", { className: "space-y-1", children: commands.map((cmd) => (_jsxs("div", { children: [_jsx("span", { className: "text-zinc-500 select-none", children: "$ " }), _jsx("span", { children: cmd })] }, cmd))) })] }), _jsx("p", { className: "text-muted-foreground text-sm", children: "Feature will appear on canvas once created" })] })) }) })] }));
39
+ _jsxs(_Fragment, { children: [_jsxs("div", { className: "text-muted-foreground flex items-center gap-2", children: [_jsx(Github, { className: "h-3.5 w-3.5" }), _jsx("span", { className: "text-[10px] font-semibold tracking-widest uppercase", children: "Repositories" })] }), _jsxs("button", { type: "button", "data-testid": "empty-state-add-repository", onClick: handlePickerClick, disabled: loading, className: "border-border hover:border-foreground/40 flex w-full cursor-pointer items-center gap-2.5 rounded-md border border-dashed px-4 py-2.5 transition-colors disabled:cursor-wait disabled:opacity-50", children: [loading ? (_jsx(Loader2, { className: "text-muted-foreground h-4 w-4 animate-spin" })) : (_jsx(Plus, { className: "text-muted-foreground h-4 w-4" })), _jsx("span", { className: "text-xs font-medium", children: loading ? 'Opening' : 'Add Repository' })] }), _jsxs("div", { className: "text-muted-foreground flex items-center gap-2", children: [_jsx("div", { className: "bg-border h-px w-10" }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(TerminalSquare, { className: "h-3 w-3" }), _jsx("span", { className: "text-[10px] font-semibold tracking-widest uppercase", children: "Or via CLI" })] }), _jsx("div", { className: "bg-border h-px w-10" })] }), _jsxs("div", { "data-testid": "cli-code-block", className: "relative w-full rounded-md bg-zinc-900 px-3 py-2 font-mono text-[11px] text-zinc-300", children: [_jsx("button", { type: "button", "data-testid": "cli-code-block-copy", onClick: handleCopy, className: "absolute top-2 right-2 cursor-pointer rounded p-1 text-zinc-500 transition-colors hover:bg-zinc-800 hover:text-zinc-300", "aria-label": "Copy commands", children: copied ? _jsx(Check, { className: "h-3 w-3" }) : _jsx(Copy, { className: "h-3 w-3" }) }), _jsx("div", { className: "space-y-0.5", children: commands.map((cmd) => (_jsxs("div", { children: [_jsx("span", { className: "text-zinc-500 select-none", children: "$ " }), _jsx("span", { children: cmd })] }, cmd))) })] }), _jsx("p", { className: "text-muted-foreground text-[10px]", children: "Feature will appear on canvas once created" })] })) }) })] }));
40
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"welcome-agent-setup.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/welcome-agent-setup.tsx"],"names":[],"mappings":"AAuBA,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,iBAAiB,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,sBAAsB,2CA8MlF"}
1
+ {"version":3,"file":"welcome-agent-setup.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/welcome-agent-setup.tsx"],"names":[],"mappings":"AAwBA,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AASD,wBAAgB,iBAAiB,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,sBAAsB,2CA4OlF"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useState, useEffect, useCallback } from 'react';
4
- import { Check, ChevronRight, ChevronLeft, Download, Loader2, CheckCircle2, Circle, AlertCircle, } from 'lucide-react';
3
+ import { useState, useEffect, useCallback, useRef } from 'react';
4
+ import { Check, ChevronRight, ChevronLeft, Download, Loader2, CheckCircle2, Circle, AlertCircle, Bot, } from 'lucide-react';
5
5
  import { getAllAgentModels } from '../../../app/actions/get-all-agent-models.js';
6
6
  import { checkAgentTool } from '../../../app/actions/check-agent-tool.js';
7
7
  import { updateAgentAndModel } from '../../../app/actions/update-agent-and-model.js';
@@ -9,6 +9,9 @@ import { getAgentTypeIcon } from '../../common/feature-node/agent-type-icons.js'
9
9
  import { getModelMeta } from '../../../lib/model-metadata.js';
10
10
  import { useToolInstallStream } from '../../../hooks/use-tool-install-stream.js';
11
11
  import { cn } from '../../../lib/utils.js';
12
+ const STEPS = ['select-agent', 'select-model', 'check-tool'];
13
+ /** Fixed width for the wizard content area to prevent layout jumps */
14
+ const WIZARD_WIDTH = 'w-72';
12
15
  export function WelcomeAgentSetup({ onComplete, className }) {
13
16
  const [groups, setGroups] = useState([]);
14
17
  const [loading, setLoading] = useState(true);
@@ -18,46 +21,75 @@ export function WelcomeAgentSetup({ onComplete, className }) {
18
21
  const [toolStatus, setToolStatus] = useState(null);
19
22
  const [checkingTool, setCheckingTool] = useState(false);
20
23
  const [saving, setSaving] = useState(false);
21
- // Load available agents
24
+ const [transitioning, setTransitioning] = useState(false);
25
+ const [visible, setVisible] = useState(true);
26
+ const timeoutRef = useRef(undefined);
22
27
  useEffect(() => {
23
28
  getAllAgentModels()
24
29
  .then(setGroups)
25
30
  .finally(() => setLoading(false));
26
31
  }, []);
27
32
  const activeGroup = selectedAgent ? groups.find((g) => g.agentType === selectedAgent) : null;
33
+ /** Animate step transition: fade out → change step → fade in */
34
+ const transitionTo = useCallback((nextStep, setup) => {
35
+ setTransitioning(true);
36
+ setVisible(false);
37
+ if (timeoutRef.current)
38
+ clearTimeout(timeoutRef.current);
39
+ timeoutRef.current = setTimeout(() => {
40
+ setup?.();
41
+ setStep(nextStep);
42
+ // Small delay to let React render the new content before fading in
43
+ requestAnimationFrame(() => {
44
+ setVisible(true);
45
+ setTransitioning(false);
46
+ });
47
+ }, 150);
48
+ }, []);
49
+ useEffect(() => {
50
+ return () => {
51
+ if (timeoutRef.current)
52
+ clearTimeout(timeoutRef.current);
53
+ };
54
+ }, []);
28
55
  const handleAgentSelect = useCallback((agentType) => {
29
56
  const group = groups.find((g) => g.agentType === agentType);
30
- setSelectedAgent(agentType);
31
57
  if (group && group.models.length > 0) {
32
- setStep('select-model');
58
+ transitionTo('select-model', () => {
59
+ setSelectedAgent(agentType);
60
+ });
33
61
  }
34
62
  else {
35
- // Agent without models — go straight to tool check
36
- setSelectedModel('');
37
- setStep('check-tool');
63
+ transitionTo('check-tool', () => {
64
+ setSelectedAgent(agentType);
65
+ setSelectedModel('');
66
+ });
38
67
  }
39
- }, [groups]);
68
+ }, [groups, transitionTo]);
40
69
  const handleModelSelect = useCallback((model) => {
41
- setSelectedModel(model);
42
- setStep('check-tool');
43
- }, []);
70
+ transitionTo('check-tool', () => {
71
+ setSelectedModel(model);
72
+ });
73
+ }, [transitionTo]);
44
74
  const handleBack = useCallback(() => {
45
75
  if (step === 'select-model') {
46
- setSelectedAgent(null);
47
- setStep('select-agent');
76
+ transitionTo('select-agent', () => {
77
+ setSelectedAgent(null);
78
+ });
48
79
  }
49
80
  else if (step === 'check-tool') {
50
81
  if (activeGroup && activeGroup.models.length > 0) {
51
- setSelectedModel(null);
52
- setStep('select-model');
82
+ transitionTo('select-model', () => {
83
+ setSelectedModel(null);
84
+ });
53
85
  }
54
86
  else {
55
- setSelectedAgent(null);
56
- setStep('select-agent');
87
+ transitionTo('select-agent', () => {
88
+ setSelectedAgent(null);
89
+ });
57
90
  }
58
91
  }
59
- }, [step, activeGroup]);
60
- // Check tool status when entering check-tool step
92
+ }, [step, activeGroup, transitionTo]);
61
93
  useEffect(() => {
62
94
  if (step !== 'check-tool' || !selectedAgent)
63
95
  return;
@@ -79,18 +111,16 @@ export function WelcomeAgentSetup({ onComplete, className }) {
79
111
  }
80
112
  }, [selectedAgent, selectedModel, onComplete]);
81
113
  if (loading) {
82
- return (_jsxs("div", { "data-testid": "welcome-agent-setup", className: cn('bg-card flex flex-col items-center justify-center gap-3 rounded-xl border p-8', className), children: [_jsx(Loader2, { className: "text-muted-foreground h-5 w-5 animate-spin" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "Loading agents..." })] }));
114
+ return (_jsxs("div", { "data-testid": "welcome-agent-setup", className: cn('flex flex-col items-center justify-center gap-3', className), children: [_jsx(Loader2, { className: "text-muted-foreground h-4 w-4 animate-spin" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Loading agents\u2026" })] }));
83
115
  }
84
- return (_jsxs("div", { "data-testid": "welcome-agent-setup", className: cn('bg-card w-full max-w-md rounded-xl border shadow-sm', className), children: [_jsxs("div", { className: "border-b px-5 py-4", children: [_jsx("h2", { className: "text-sm font-bold", children: "Set up your AI agent" }), _jsxs("p", { className: "text-muted-foreground mt-0.5 text-xs", children: [step === 'select-agent' && 'Choose the coding agent you want to use', step === 'select-model' && 'Pick a model for your agent', step === 'check-tool' && 'Verifying tool availability'] }), _jsx("div", { className: "mt-3 flex items-center gap-1.5", children: ['select-agent', 'select-model', 'check-tool'].map((s, i) => (_jsx("div", { className: cn('h-1 flex-1 rounded-full transition-colors', i <= ['select-agent', 'select-model', 'check-tool'].indexOf(step)
85
- ? 'bg-primary'
86
- : 'bg-muted') }, s))) })] }), _jsxs("div", { className: "p-2", children: [step === 'select-agent' && (_jsx("div", { "data-testid": "agent-list", children: groups.map((group) => {
116
+ const stepIndex = STEPS.indexOf(step);
117
+ return (_jsxs("div", { "data-testid": "welcome-agent-setup", className: cn('flex flex-col items-center gap-4', WIZARD_WIDTH, className), children: [_jsxs("div", { className: "text-muted-foreground flex items-center gap-2", children: [_jsx(Bot, { className: "h-3.5 w-3.5" }), _jsxs("span", { className: "text-[10px] font-semibold tracking-widest uppercase", children: [step === 'select-agent' && 'Choose your agent', step === 'select-model' && 'Pick a model', step === 'check-tool' && 'Verifying setup'] })] }), _jsx("div", { className: "flex w-32 items-center gap-1", children: STEPS.map((s, i) => (_jsx("div", { className: cn('h-0.5 flex-1 rounded-full transition-colors duration-300', i <= stepIndex ? 'bg-foreground/60' : 'bg-muted') }, s))) }), _jsxs("div", { className: cn('flex w-full flex-col items-center transition-opacity duration-150', visible && !transitioning ? 'opacity-100' : 'opacity-0'), children: [step === 'select-agent' && (_jsx("div", { "data-testid": "agent-list", className: "flex w-full flex-col gap-1.5", children: groups.map((group) => {
87
118
  const GroupIcon = getAgentTypeIcon(group.agentType);
88
- return (_jsxs("button", { type: "button", "data-testid": `agent-option-${group.agentType}`, className: "hover:bg-accent flex w-full cursor-pointer items-center gap-3 rounded-lg px-3 py-2.5 text-left transition-colors", onClick: () => handleAgentSelect(group.agentType), children: [_jsx(GroupIcon, { className: "h-5 w-5 shrink-0" }), _jsxs("div", { className: "flex-1", children: [_jsx("span", { className: "text-sm font-medium", children: group.label }), group.models.length > 0 && (_jsxs("span", { className: "text-muted-foreground ml-1.5 text-xs", children: [group.models.length, " model", group.models.length !== 1 ? 's' : ''] }))] }), _jsx(ChevronRight, { className: "text-muted-foreground h-4 w-4" })] }, group.agentType));
89
- }) })), step === 'select-model' && activeGroup ? (_jsxs("div", { "data-testid": "model-list", children: [_jsxs("button", { type: "button", className: "text-muted-foreground hover:text-foreground mb-1 flex w-full cursor-pointer items-center gap-1.5 px-3 py-1.5 text-xs font-medium transition-colors", onClick: handleBack, children: [_jsx(ChevronLeft, { className: "h-3.5 w-3.5" }), "Back to agents"] }), activeGroup.models.map((m) => {
90
- const meta = getModelMeta(m.id);
91
- return (_jsxs("button", { type: "button", "data-testid": `model-option-${m.id}`, className: "hover:bg-accent flex w-full cursor-pointer items-center gap-3 rounded-lg px-3 py-2.5 text-left transition-colors", onClick: () => handleModelSelect(m.id), children: [_jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [_jsx("span", { className: "text-sm font-medium", children: meta.displayName || m.displayName }), _jsx("span", { className: "text-muted-foreground text-xs", children: meta.description || m.description })] }), _jsx(ChevronRight, { className: "text-muted-foreground h-3.5 w-3.5" })] }, m.id));
92
- })] })) : null, step === 'check-tool' && (_jsx(ToolCheckStep, { toolStatus: toolStatus, checking: checkingTool, saving: saving, onConfirm: handleConfirm, onBack: handleBack, onToolInstalled: () => {
93
- // Re-check tool after install
119
+ return (_jsxs("button", { type: "button", "data-testid": `agent-option-${group.agentType}`, className: "border-border hover:border-foreground/40 flex w-full cursor-pointer items-center gap-2.5 rounded-md border border-dashed px-4 py-2.5 transition-colors", onClick: () => handleAgentSelect(group.agentType), children: [_jsx(GroupIcon, { className: "text-muted-foreground h-4 w-4 shrink-0" }), _jsx("span", { className: "flex-1 text-left text-xs font-medium", children: group.label }), _jsx(ChevronRight, { className: "text-muted-foreground h-3 w-3" })] }, group.agentType));
120
+ }) })), step === 'select-model' && activeGroup ? (_jsxs("div", { "data-testid": "model-list", className: "flex w-full flex-col gap-1.5", children: [_jsxs("button", { type: "button", className: "text-muted-foreground hover:text-foreground mb-0.5 flex cursor-pointer items-center gap-1 self-start text-[10px] font-medium transition-colors", onClick: handleBack, children: [_jsx(ChevronLeft, { className: "h-3 w-3" }), "Back"] }), _jsx("div", { className: "flex max-h-48 w-full flex-col gap-1.5 overflow-y-auto", children: activeGroup.models.map((m) => {
121
+ const meta = getModelMeta(m.id);
122
+ return (_jsxs("button", { type: "button", "data-testid": `model-option-${m.id}`, className: "border-border hover:border-foreground/40 flex w-full cursor-pointer items-center gap-2.5 rounded-md border border-dashed px-4 py-2.5 text-left transition-colors", onClick: () => handleModelSelect(m.id), children: [_jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [_jsx("span", { className: "text-xs font-medium", children: meta.displayName || m.displayName }), _jsx("span", { className: "text-muted-foreground text-[10px] leading-tight", children: meta.description || m.description })] }), _jsx(ChevronRight, { className: "text-muted-foreground h-3 w-3 shrink-0" })] }, m.id));
123
+ }) })] })) : null, step === 'check-tool' && (_jsx(ToolCheckStep, { toolStatus: toolStatus, checking: checkingTool, saving: saving, onConfirm: handleConfirm, onBack: handleBack, onToolInstalled: () => {
94
124
  if (selectedAgent) {
95
125
  setCheckingTool(true);
96
126
  checkAgentTool(selectedAgent)
@@ -102,18 +132,21 @@ export function WelcomeAgentSetup({ onComplete, className }) {
102
132
  /** Sub-component for the tool verification step */
103
133
  function ToolCheckStep({ toolStatus, checking, saving, onConfirm, onBack, onToolInstalled, }) {
104
134
  if (checking || !toolStatus) {
105
- return (_jsxs("div", { className: "flex flex-col items-center gap-3 px-3 py-6", children: [_jsx(Loader2, { className: "text-muted-foreground h-5 w-5 animate-spin" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "Checking tool availability..." })] }));
135
+ return (_jsxs("div", { className: "flex flex-col items-center gap-2 py-4", children: [_jsx(Loader2, { className: "text-muted-foreground h-4 w-4 animate-spin" }), _jsx("p", { className: "text-muted-foreground text-[10px]", children: "Checking tool availability\u2026" })] }));
106
136
  }
107
137
  // Agent doesn't require a tool (e.g., dev/demo)
108
138
  if (!toolStatus.toolId) {
109
- return (_jsxs("div", { className: "flex flex-col gap-3 px-3 py-4", children: [_jsxs("div", { className: "flex items-center gap-2 text-emerald-600 dark:text-emerald-400", children: [_jsx(CheckCircle2, { className: "h-4 w-4" }), _jsx("span", { className: "text-sm font-medium", children: "No additional tools required" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("button", { type: "button", className: "text-muted-foreground hover:text-foreground cursor-pointer text-xs transition-colors", onClick: onBack, children: [_jsx(ChevronLeft, { className: "mr-0.5 inline h-3.5 w-3.5" }), "Back"] }), _jsxs("button", { type: "button", "data-testid": "agent-setup-confirm", disabled: saving, className: "bg-primary text-primary-foreground hover:bg-primary/90 ml-auto flex cursor-pointer items-center gap-1.5 rounded-md px-4 py-2 text-sm font-medium transition-colors disabled:opacity-60", onClick: onConfirm, children: [saving ? (_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" })) : (_jsx(Check, { className: "h-3.5 w-3.5" })), "Continue"] })] })] }));
139
+ return (_jsxs("div", { className: "flex w-full flex-col items-center gap-3", children: [_jsxs("div", { className: "text-muted-foreground flex items-center gap-1.5", children: [_jsx(CheckCircle2, { className: "h-3.5 w-3.5" }), _jsx("span", { className: "text-xs", children: "No additional tools required" })] }), _jsx(ConfirmRow, { saving: saving, onConfirm: onConfirm, onBack: onBack })] }));
110
140
  }
111
141
  if (toolStatus.installed) {
112
- return (_jsxs("div", { className: "flex flex-col gap-3 px-3 py-4", children: [_jsxs("div", { className: "flex items-center gap-2 text-emerald-600 dark:text-emerald-400", children: [_jsx(CheckCircle2, { className: "h-4 w-4" }), _jsxs("span", { className: "text-sm font-medium", children: [toolStatus.tool?.name ?? toolStatus.toolId, " is installed"] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("button", { type: "button", className: "text-muted-foreground hover:text-foreground cursor-pointer text-xs transition-colors", onClick: onBack, children: [_jsx(ChevronLeft, { className: "mr-0.5 inline h-3.5 w-3.5" }), "Back"] }), _jsxs("button", { type: "button", "data-testid": "agent-setup-confirm", disabled: saving, className: "bg-primary text-primary-foreground hover:bg-primary/90 ml-auto flex cursor-pointer items-center gap-1.5 rounded-md px-4 py-2 text-sm font-medium transition-colors disabled:opacity-60", onClick: onConfirm, children: [saving ? (_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" })) : (_jsx(Check, { className: "h-3.5 w-3.5" })), "Continue"] })] })] }));
142
+ return (_jsxs("div", { className: "flex w-full flex-col items-center gap-3", children: [_jsxs("div", { className: "text-muted-foreground flex items-center gap-1.5", children: [_jsx(CheckCircle2, { className: "h-3.5 w-3.5" }), _jsxs("span", { className: "text-xs", children: [toolStatus.tool?.name ?? toolStatus.toolId, " is installed"] })] }), _jsx(ConfirmRow, { saving: saving, onConfirm: onConfirm, onBack: onBack })] }));
113
143
  }
114
- // Tool not installed — show install option
115
144
  return (_jsx(ToolInstallInline, { toolStatus: toolStatus, saving: saving, onConfirm: onConfirm, onBack: onBack, onInstalled: onToolInstalled }));
116
145
  }
146
+ /** Shared back + continue row */
147
+ function ConfirmRow({ saving, onConfirm, onBack, }) {
148
+ return (_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("button", { type: "button", className: "text-muted-foreground hover:text-foreground cursor-pointer text-[10px] transition-colors", onClick: onBack, children: [_jsx(ChevronLeft, { className: "mr-0.5 inline h-3 w-3" }), "Back"] }), _jsxs("button", { type: "button", "data-testid": "agent-setup-confirm", disabled: saving, className: "border-border hover:border-foreground/40 flex cursor-pointer items-center gap-1.5 rounded-md border border-dashed px-4 py-2 text-xs font-medium transition-colors disabled:opacity-50", onClick: onConfirm, children: [saving ? _jsx(Loader2, { className: "h-3 w-3 animate-spin" }) : _jsx(Check, { className: "h-3 w-3" }), "Continue"] })] }));
149
+ }
117
150
  /** Inline tool installer for the welcome wizard */
118
151
  function ToolInstallInline({ toolStatus, saving, onConfirm, onBack, onInstalled, }) {
119
152
  const toolId = toolStatus.toolId ?? '';
@@ -125,11 +158,7 @@ function ToolInstallInline({ toolStatus, saving, onConfirm, onBack, onInstalled,
125
158
  onInstalled();
126
159
  }
127
160
  }, [isInstallDone, onInstalled]);
128
- return (_jsxs("div", { className: "flex flex-col gap-3 px-3 py-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [isInstallDone ? (_jsx(CheckCircle2, { className: "h-4 w-4 text-emerald-600 dark:text-emerald-400" })) : isInstallError ? (_jsx(AlertCircle, { className: "h-4 w-4 text-red-500" })) : (_jsx(Circle, { className: "text-muted-foreground h-4 w-4" })), _jsxs("span", { className: "text-sm font-medium", children: [toolStatus.tool?.name ?? toolId, ' ', isInstallDone
129
- ? 'installed successfully'
130
- : isInstallError
131
- ? 'installation failed'
132
- : 'is not installed'] })] }), toolStatus.tool?.installCommand && status === 'idle' ? (_jsxs("div", { className: "rounded-md bg-zinc-900 px-3 py-2 font-mono text-xs text-zinc-100", children: [_jsx("span", { className: "text-zinc-500 select-none", children: "$ " }), toolStatus.tool.installCommand] })) : null, (status === 'streaming' || isInstallDone || isInstallError) && logs.length > 0 ? (_jsxs("div", { className: "max-h-32 overflow-auto rounded-md bg-zinc-900 p-2 font-mono text-[11px] leading-relaxed text-zinc-300", children: [logs.map((line, idx) => (
161
+ return (_jsxs("div", { className: "flex w-full flex-col items-center gap-3", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [isInstallDone ? (_jsx(CheckCircle2, { className: "text-muted-foreground h-3.5 w-3.5" })) : isInstallError ? (_jsx(AlertCircle, { className: "text-destructive h-3.5 w-3.5" })) : (_jsx(Circle, { className: "text-muted-foreground h-3.5 w-3.5" })), _jsxs("span", { className: "text-xs", children: [toolStatus.tool?.name ?? toolId, ' ', isInstallDone ? 'installed' : isInstallError ? 'install failed' : 'is not installed'] })] }), toolStatus.tool?.installCommand && status === 'idle' ? (_jsxs("div", { className: "w-full rounded-md bg-zinc-900 px-3 py-2 font-mono text-[11px] text-zinc-300", children: [_jsx("span", { className: "text-zinc-500 select-none", children: "$ " }), toolStatus.tool.installCommand] })) : null, (status === 'streaming' || isInstallDone || isInstallError) && logs.length > 0 ? (_jsxs("div", { className: "max-h-28 w-full overflow-auto rounded-md bg-zinc-900 px-3 py-2 font-mono text-[10px] leading-relaxed text-zinc-400", children: [logs.map((line, idx) => (
133
162
  // eslint-disable-next-line react/no-array-index-key -- logs are append-only, never reorder
134
- _jsx("div", { className: "break-all whitespace-pre-wrap", children: line }, idx))), isInstallDone ? (_jsx("div", { className: "mt-1 text-emerald-400", children: "Installation complete" })) : null, isInstallError ? (_jsx("div", { className: "mt-1 text-red-400", children: "Installation failed \u2014 try installing manually" })) : null] })) : null, _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("button", { type: "button", className: "text-muted-foreground hover:text-foreground cursor-pointer text-xs transition-colors", onClick: onBack, children: [_jsx(ChevronLeft, { className: "mr-0.5 inline h-3.5 w-3.5" }), "Back"] }), _jsxs("div", { className: "ml-auto flex items-center gap-2", children: [!isInstallDone && toolStatus.tool?.autoInstall ? (_jsxs("button", { type: "button", "data-testid": "agent-setup-install", disabled: status === 'streaming', className: "bg-primary text-primary-foreground hover:bg-primary/90 flex cursor-pointer items-center gap-1.5 rounded-md px-4 py-2 text-sm font-medium transition-colors disabled:opacity-60", onClick: startInstall, children: [status === 'streaming' ? (_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" })) : (_jsx(Download, { className: "h-3.5 w-3.5" })), status === 'streaming' ? 'Installing...' : 'Install'] })) : null, isInstallDone ? (_jsxs("button", { type: "button", "data-testid": "agent-setup-confirm", disabled: saving, className: "bg-primary text-primary-foreground hover:bg-primary/90 flex cursor-pointer items-center gap-1.5 rounded-md px-4 py-2 text-sm font-medium transition-colors disabled:opacity-60", onClick: onConfirm, children: [saving ? (_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" })) : (_jsx(Check, { className: "h-3.5 w-3.5" })), "Continue"] })) : null] })] })] }));
163
+ _jsx("div", { className: "break-all whitespace-pre-wrap", children: line }, idx))), isInstallDone ? (_jsx("div", { className: "text-muted-foreground mt-1", children: "Installation complete" })) : null, isInstallError ? (_jsx("div", { className: "text-destructive mt-1", children: "Installation failed \u2014 try manually" })) : null] })) : null, _jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("button", { type: "button", className: "text-muted-foreground hover:text-foreground cursor-pointer text-[10px] transition-colors", onClick: onBack, children: [_jsx(ChevronLeft, { className: "mr-0.5 inline h-3 w-3" }), "Back"] }), !isInstallDone && toolStatus.tool?.autoInstall ? (_jsxs("button", { type: "button", "data-testid": "agent-setup-install", disabled: status === 'streaming', className: "border-border hover:border-foreground/40 flex cursor-pointer items-center gap-1.5 rounded-md border border-dashed px-4 py-2 text-xs font-medium transition-colors disabled:opacity-50", onClick: startInstall, children: [status === 'streaming' ? (_jsx(Loader2, { className: "h-3 w-3 animate-spin" })) : (_jsx(Download, { className: "h-3 w-3" })), status === 'streaming' ? 'Installing' : 'Install'] })) : null, isInstallDone ? (_jsxs("button", { type: "button", "data-testid": "agent-setup-confirm", disabled: saving, className: "border-border hover:border-foreground/40 flex cursor-pointer items-center gap-1.5 rounded-md border border-dashed px-4 py-2 text-xs font-medium transition-colors disabled:opacity-50", onClick: onConfirm, children: [saving ? _jsx(Loader2, { className: "h-3 w-3 animate-spin" }) : _jsx(Check, { className: "h-3 w-3" }), "Continue"] })) : null] })] }));
135
164
  }
@@ -9,7 +9,7 @@ const meta = {
9
9
  layout: 'centered',
10
10
  },
11
11
  decorators: [
12
- (Story) => (_jsx("div", { style: { width: 420, padding: 24 }, children: _jsx(Story, {}) })),
12
+ (Story) => (_jsx("div", { style: { width: 480, padding: 48, display: 'flex', justifyContent: 'center' }, children: _jsx(Story, {}) })),
13
13
  ],
14
14
  };
15
15
  export default meta;