jettypod 4.4.118 → 4.4.121

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 (240) hide show
  1. package/.env +4 -3
  2. package/Cargo.lock +6450 -0
  3. package/Cargo.toml +35 -0
  4. package/README.md +5 -1
  5. package/TAURI-MIGRATION-PLAN.md +840 -0
  6. package/apps/dashboard/app/connect-claude/page.tsx +5 -6
  7. package/apps/dashboard/app/decision/[id]/page.tsx +63 -58
  8. package/apps/dashboard/app/demo/gates/page.tsx +43 -45
  9. package/apps/dashboard/app/design-system/page.tsx +868 -0
  10. package/apps/dashboard/app/globals.css +80 -4
  11. package/apps/dashboard/app/install-claude/page.tsx +4 -6
  12. package/apps/dashboard/app/login/page.tsx +72 -54
  13. package/apps/dashboard/app/page.tsx +101 -48
  14. package/apps/dashboard/app/settings/page.tsx +61 -13
  15. package/apps/dashboard/app/signup/page.tsx +242 -0
  16. package/apps/dashboard/app/subscribe/page.tsx +0 -2
  17. package/apps/dashboard/app/tests/page.tsx +37 -4
  18. package/apps/dashboard/app/welcome/page.tsx +13 -16
  19. package/apps/dashboard/app/work/[id]/page.tsx +117 -118
  20. package/apps/dashboard/app/work/[id]/proof/page.tsx +1489 -0
  21. package/apps/dashboard/components/AppShell.tsx +92 -85
  22. package/apps/dashboard/components/CardMenu.tsx +45 -12
  23. package/apps/dashboard/components/ClaudePanel.tsx +771 -850
  24. package/apps/dashboard/components/ClaudePanelInput.tsx +43 -15
  25. package/apps/dashboard/components/ConnectClaudeScreen.tsx +17 -34
  26. package/apps/dashboard/components/CopyableId.tsx +3 -4
  27. package/apps/dashboard/components/DetailReviewActions.tsx +100 -0
  28. package/apps/dashboard/components/DragContext.tsx +134 -63
  29. package/apps/dashboard/components/DraggableCard.tsx +3 -5
  30. package/apps/dashboard/components/DropZone.tsx +6 -7
  31. package/apps/dashboard/components/EditableDetailDescription.tsx +7 -13
  32. package/apps/dashboard/components/EditableDetailTitle.tsx +6 -13
  33. package/apps/dashboard/components/EditableTitle.tsx +26 -7
  34. package/apps/dashboard/components/ElapsedTimer.tsx +66 -0
  35. package/apps/dashboard/components/EpicGroup.tsx +359 -0
  36. package/apps/dashboard/components/GateCard.tsx +79 -17
  37. package/apps/dashboard/components/GateChoiceCard.tsx +15 -18
  38. package/apps/dashboard/components/InstallClaudeScreen.tsx +15 -32
  39. package/apps/dashboard/components/JettyLoader.tsx +37 -0
  40. package/apps/dashboard/components/KanbanBoard.tsx +368 -958
  41. package/apps/dashboard/components/KanbanCard.tsx +740 -0
  42. package/apps/dashboard/components/LazyCard.tsx +62 -0
  43. package/apps/dashboard/components/LazyMarkdown.tsx +11 -0
  44. package/apps/dashboard/components/MainNav.tsx +38 -73
  45. package/apps/dashboard/components/MessageBlock.tsx +468 -0
  46. package/apps/dashboard/components/ModeStartCard.tsx +15 -16
  47. package/apps/dashboard/components/OnboardingWelcome.tsx +213 -0
  48. package/apps/dashboard/components/PlaceholderCard.tsx +3 -4
  49. package/apps/dashboard/components/ProjectSwitcher.tsx +30 -30
  50. package/apps/dashboard/components/PrototypeTimeline.tsx +72 -51
  51. package/apps/dashboard/components/RealTimeKanbanWrapper.tsx +406 -388
  52. package/apps/dashboard/components/RealTimeTestsWrapper.tsx +373 -235
  53. package/apps/dashboard/components/ReviewFooter.tsx +139 -0
  54. package/apps/dashboard/components/SessionList.tsx +19 -19
  55. package/apps/dashboard/components/SubscribeContent.tsx +91 -47
  56. package/apps/dashboard/components/TestTree.tsx +16 -16
  57. package/apps/dashboard/components/TipCard.tsx +16 -17
  58. package/apps/dashboard/components/Toast.tsx +5 -6
  59. package/apps/dashboard/components/TypeIcon.tsx +55 -0
  60. package/apps/dashboard/components/ViewModeToolbar.tsx +104 -0
  61. package/apps/dashboard/components/WaveCompletionAnimation.tsx +52 -65
  62. package/apps/dashboard/components/WelcomeScreen.tsx +19 -35
  63. package/apps/dashboard/components/WorkItemHeader.tsx +4 -5
  64. package/apps/dashboard/components/WorkItemTree.tsx +11 -32
  65. package/apps/dashboard/components/settings/AccountSection.tsx +55 -35
  66. package/apps/dashboard/components/settings/AiContextSection.tsx +89 -0
  67. package/apps/dashboard/components/settings/ContextDocumentsSection.tsx +317 -0
  68. package/apps/dashboard/components/settings/EnvVarsSection.tsx +74 -152
  69. package/apps/dashboard/components/settings/GeneralSection.tsx +162 -56
  70. package/apps/dashboard/components/settings/ProjectStackSection.tsx +948 -0
  71. package/apps/dashboard/components/settings/SettingsLayout.tsx +4 -5
  72. package/apps/dashboard/components/ui/Button.tsx +104 -0
  73. package/apps/dashboard/components/ui/Input.tsx +78 -0
  74. package/apps/dashboard/components.json +1 -1
  75. package/apps/dashboard/contexts/ClaudeSessionContext.tsx +711 -418
  76. package/apps/dashboard/contexts/ConnectionStatusContext.tsx +25 -5
  77. package/apps/dashboard/contexts/UsageContext.tsx +87 -32
  78. package/apps/dashboard/dev.sh +35 -0
  79. package/apps/dashboard/eslint.config.mjs +9 -9
  80. package/apps/dashboard/hooks/useKanbanAnimation.ts +29 -0
  81. package/apps/dashboard/hooks/useKanbanUndo.ts +83 -0
  82. package/apps/dashboard/hooks/useWebSocket.ts +138 -83
  83. package/apps/dashboard/index.html +73 -0
  84. package/apps/dashboard/lib/constants.ts +43 -0
  85. package/apps/dashboard/lib/data-bridge.ts +722 -0
  86. package/apps/dashboard/lib/db.ts +69 -1265
  87. package/apps/dashboard/lib/environment-config.ts +173 -0
  88. package/apps/dashboard/lib/environment-verification.ts +119 -0
  89. package/apps/dashboard/lib/kanban-utils.ts +270 -0
  90. package/apps/dashboard/lib/proof-run.ts +495 -0
  91. package/apps/dashboard/lib/proof-scenario-runner.ts +346 -0
  92. package/apps/dashboard/lib/run-migrations.js +27 -2
  93. package/apps/dashboard/lib/service-recovery.ts +326 -0
  94. package/apps/dashboard/lib/session-state-machine.ts +1 -0
  95. package/apps/dashboard/lib/session-state-utils.ts +0 -164
  96. package/apps/dashboard/lib/session-stream-manager.ts +308 -134
  97. package/apps/dashboard/lib/shadows.ts +7 -0
  98. package/apps/dashboard/lib/stream-manager-registry.ts +46 -6
  99. package/apps/dashboard/lib/tauri-bridge.ts +102 -0
  100. package/apps/dashboard/lib/tauri.ts +106 -0
  101. package/apps/dashboard/lib/utils.ts +6 -0
  102. package/apps/dashboard/next-env.d.ts +1 -1
  103. package/apps/dashboard/package.json +21 -32
  104. package/apps/dashboard/public/bug-icon.png +0 -0
  105. package/apps/dashboard/public/buoy-icon.png +0 -0
  106. package/apps/dashboard/public/fonts/Satoshi-Variable.woff2 +0 -0
  107. package/apps/dashboard/public/fonts/Satoshi-VariableItalic.woff2 +0 -0
  108. package/apps/dashboard/public/in-flight-seagull.png +0 -0
  109. package/apps/dashboard/public/jetty-icon-loading-alt.svg +11 -0
  110. package/apps/dashboard/public/jetty-icon-loading.svg +11 -0
  111. package/apps/dashboard/public/jettypod_logo.png +0 -0
  112. package/apps/dashboard/public/pier-icon.png +0 -0
  113. package/apps/dashboard/public/star-icon.png +0 -0
  114. package/apps/dashboard/public/wrench-icon.png +0 -0
  115. package/apps/dashboard/scripts/tauri-build.js +228 -0
  116. package/apps/dashboard/scripts/upload-tauri-to-r2.js +125 -0
  117. package/apps/dashboard/scripts/ws-server.js +191 -0
  118. package/apps/dashboard/src/main.tsx +12 -0
  119. package/apps/dashboard/src/router.tsx +107 -0
  120. package/apps/dashboard/src/vite-env.d.ts +1 -0
  121. package/apps/dashboard/tsconfig.json +7 -12
  122. package/apps/dashboard/tsconfig.tsbuildinfo +1 -1
  123. package/apps/dashboard/vite.config.ts +33 -0
  124. package/apps/update-server/src/index.ts +228 -80
  125. package/claude-hooks/global-guardrails.js +14 -13
  126. package/crates/jettypod-cli/Cargo.toml +19 -0
  127. package/crates/jettypod-cli/src/commands.rs +1249 -0
  128. package/crates/jettypod-cli/src/main.rs +595 -0
  129. package/crates/jettypod-core/Cargo.toml +26 -0
  130. package/crates/jettypod-core/build.rs +98 -0
  131. package/crates/jettypod-core/migrations/V1__baseline.sql +197 -0
  132. package/crates/jettypod-core/migrations/V2__work_items_indexes.sql +6 -0
  133. package/crates/jettypod-core/migrations/V3__qa_steps.sql +2 -0
  134. package/crates/jettypod-core/src/auth.rs +294 -0
  135. package/crates/jettypod-core/src/config.rs +397 -0
  136. package/crates/jettypod-core/src/db/mod.rs +507 -0
  137. package/crates/jettypod-core/src/db/recovery.rs +114 -0
  138. package/crates/jettypod-core/src/db/startup.rs +101 -0
  139. package/crates/jettypod-core/src/db/validate.rs +149 -0
  140. package/crates/jettypod-core/src/error.rs +76 -0
  141. package/crates/jettypod-core/src/git.rs +458 -0
  142. package/crates/jettypod-core/src/lib.rs +20 -0
  143. package/crates/jettypod-core/src/sessions.rs +625 -0
  144. package/crates/jettypod-core/src/skills.rs +556 -0
  145. package/crates/jettypod-core/src/work.rs +1086 -0
  146. package/crates/jettypod-core/src/worktree.rs +628 -0
  147. package/crates/jettypod-core/src/ws.rs +767 -0
  148. package/cucumber-test.cjs +6 -0
  149. package/cucumber.js +9 -3
  150. package/docs/COMMAND_REFERENCE.md +34 -0
  151. package/hooks/post-checkout +32 -75
  152. package/hooks/post-merge +111 -10
  153. package/jest.setup.js +1 -0
  154. package/jettypod.js +145 -116
  155. package/lib/bdd-preflight.js +96 -0
  156. package/lib/chore-taxonomy.js +33 -10
  157. package/lib/database.js +36 -16
  158. package/lib/db-watcher.js +1 -1
  159. package/lib/git-hooks/pre-commit +1 -1
  160. package/lib/jettypod-backup.js +27 -4
  161. package/lib/merge-lock.js +111 -253
  162. package/lib/migrations/027-plan-at-creation-column.js +3 -1
  163. package/lib/migrations/029-remove-autoincrement.js +307 -0
  164. package/lib/migrations/029-rename-corrupted-to-cleaned.js +149 -0
  165. package/lib/migrations/030-rejection-round-columns.js +54 -0
  166. package/lib/migrations/031-session-isolation-index.js +17 -0
  167. package/lib/migrations/index.js +47 -4
  168. package/lib/schema.js +10 -5
  169. package/lib/seed-onboarding.js +1 -1
  170. package/lib/update-command/index.js +9 -175
  171. package/lib/work-commands/index.js +144 -19
  172. package/lib/work-tracking/index.js +148 -27
  173. package/lib/worktree-diagnostics.js +16 -16
  174. package/lib/worktree-facade.js +1 -1
  175. package/lib/worktree-manager.js +8 -8
  176. package/lib/worktree-reconciler.js +5 -5
  177. package/package.json +9 -2
  178. package/scripts/ndjson-to-cucumber-json.js +152 -0
  179. package/scripts/postinstall.js +25 -0
  180. package/skills-templates/bug-mode/SKILL.md +79 -20
  181. package/skills-templates/bug-planning/SKILL.md +25 -29
  182. package/skills-templates/chore-mode/SKILL.md +171 -69
  183. package/skills-templates/chore-mode/verification.js +51 -10
  184. package/skills-templates/chore-planning/SKILL.md +47 -18
  185. package/skills-templates/design-system-selection/SKILL.md +273 -0
  186. package/skills-templates/epic-planning/SKILL.md +82 -48
  187. package/skills-templates/external-transition/SKILL.md +47 -47
  188. package/skills-templates/feature-planning/SKILL.md +173 -74
  189. package/skills-templates/production-mode/SKILL.md +69 -49
  190. package/skills-templates/request-routing/SKILL.md +4 -4
  191. package/skills-templates/simple-improvement/SKILL.md +74 -29
  192. package/skills-templates/speed-mode/SKILL.md +217 -141
  193. package/skills-templates/stable-mode/SKILL.md +148 -89
  194. package/apps/dashboard/README.md +0 -36
  195. package/apps/dashboard/app/api/claude/[workItemId]/message/route.ts +0 -386
  196. package/apps/dashboard/app/api/claude/[workItemId]/pin/route.ts +0 -24
  197. package/apps/dashboard/app/api/claude/[workItemId]/route.ts +0 -167
  198. package/apps/dashboard/app/api/claude/sessions/[sessionId]/content/route.ts +0 -52
  199. package/apps/dashboard/app/api/claude/sessions/[sessionId]/message/route.ts +0 -378
  200. package/apps/dashboard/app/api/claude/sessions/[sessionId]/pin/route.ts +0 -24
  201. package/apps/dashboard/app/api/claude/sessions/cleanup/route.ts +0 -34
  202. package/apps/dashboard/app/api/claude/sessions/route.ts +0 -184
  203. package/apps/dashboard/app/api/decisions/[id]/route.ts +0 -25
  204. package/apps/dashboard/app/api/internal/set-project/route.ts +0 -17
  205. package/apps/dashboard/app/api/kanban/route.ts +0 -15
  206. package/apps/dashboard/app/api/settings/env-vars/route.ts +0 -125
  207. package/apps/dashboard/app/api/settings/general/route.ts +0 -21
  208. package/apps/dashboard/app/api/tests/route.ts +0 -9
  209. package/apps/dashboard/app/api/tests/run/route.ts +0 -82
  210. package/apps/dashboard/app/api/tests/run/stream/route.ts +0 -71
  211. package/apps/dashboard/app/api/tests/undefined/route.ts +0 -9
  212. package/apps/dashboard/app/api/usage/route.ts +0 -17
  213. package/apps/dashboard/app/api/work/[id]/description/route.ts +0 -21
  214. package/apps/dashboard/app/api/work/[id]/epic/route.ts +0 -21
  215. package/apps/dashboard/app/api/work/[id]/order/route.ts +0 -21
  216. package/apps/dashboard/app/api/work/[id]/status/route.ts +0 -21
  217. package/apps/dashboard/app/api/work/[id]/title/route.ts +0 -21
  218. package/apps/dashboard/app/layout.tsx +0 -43
  219. package/apps/dashboard/components/UpgradeBanner.tsx +0 -29
  220. package/apps/dashboard/electron/ipc-handlers.js +0 -1028
  221. package/apps/dashboard/electron/main.js +0 -2124
  222. package/apps/dashboard/electron/preload.js +0 -123
  223. package/apps/dashboard/electron/session-manager.js +0 -141
  224. package/apps/dashboard/electron-builder.config.js +0 -357
  225. package/apps/dashboard/hooks/useClaudeSessions.ts +0 -299
  226. package/apps/dashboard/lib/claude-process-manager.ts +0 -492
  227. package/apps/dashboard/lib/db-bridge.ts +0 -282
  228. package/apps/dashboard/lib/prototypes.ts +0 -202
  229. package/apps/dashboard/lib/test-results-db.ts +0 -307
  230. package/apps/dashboard/lib/tests.ts +0 -282
  231. package/apps/dashboard/next.config.js +0 -50
  232. package/apps/dashboard/postcss.config.mjs +0 -7
  233. package/apps/dashboard/public/file.svg +0 -1
  234. package/apps/dashboard/public/globe.svg +0 -1
  235. package/apps/dashboard/public/next.svg +0 -1
  236. package/apps/dashboard/public/vercel.svg +0 -1
  237. package/apps/dashboard/public/window.svg +0 -1
  238. package/apps/dashboard/scripts/download-node.js +0 -104
  239. package/apps/dashboard/scripts/upload-to-r2.js +0 -89
  240. package/docs/bdd-guidance.md +0 -390
@@ -1,22 +1,37 @@
1
- 'use client';
2
1
 
3
2
  import { useState } from 'react';
3
+ import { invoke } from '@/lib/tauri';
4
+ import { Input } from '@/components/ui/Input';
5
+ import { Button } from '@/components/ui/Button';
6
+ import { dataBridge } from '@/lib/data-bridge';
4
7
 
5
8
  interface MainBranchInfo {
6
9
  branch: string;
7
10
  source: 'configured' | 'detected';
8
11
  }
9
12
 
13
+ const CLAUDE_MODELS = [
14
+ { id: 'default', label: 'Default', description: 'Opus 4.6', value: null },
15
+ { id: 'sonnet', label: 'Sonnet', description: 'Sonnet 4.6', value: 'sonnet' },
16
+ { id: 'haiku', label: 'Haiku', description: 'Haiku 4.5', value: 'haiku' },
17
+ ];
18
+
10
19
  interface GeneralSectionProps {
11
20
  initialMainBranch: MainBranchInfo;
21
+ initialClaudeModel: string | null;
12
22
  }
13
23
 
14
- export function GeneralSection({ initialMainBranch }: GeneralSectionProps) {
24
+ export function GeneralSection({ initialMainBranch, initialClaudeModel }: GeneralSectionProps) {
15
25
  const [mainBranch, setMainBranch] = useState(initialMainBranch);
16
26
  const [inputValue, setInputValue] = useState(initialMainBranch.branch);
17
27
  const [isEditing, setIsEditing] = useState(false);
18
28
  const [successMessage, setSuccessMessage] = useState<string | null>(null);
19
29
 
30
+ // Claude model state
31
+ const [claudeModel, setClaudeModel] = useState<string | null>(initialClaudeModel);
32
+ const [selectedModel, setSelectedModel] = useState<string | null>(initialClaudeModel);
33
+ const [isEditingModel, setIsEditingModel] = useState(false);
34
+
20
35
  const showSuccess = (message: string) => {
21
36
  setSuccessMessage(message);
22
37
  setTimeout(() => setSuccessMessage(null), 3000);
@@ -26,19 +41,16 @@ export function GeneralSection({ initialMainBranch }: GeneralSectionProps) {
26
41
  const trimmed = inputValue.trim();
27
42
  const value = trimmed === '' ? null : trimmed;
28
43
 
29
- const res = await fetch('/api/settings/general', {
30
- method: 'POST',
31
- headers: { 'Content-Type': 'application/json' },
32
- body: JSON.stringify({ mainBranch: value }),
33
- });
34
-
35
- if (res.ok) {
36
- const data = await res.json();
37
- setMainBranch(data.mainBranch);
38
- setInputValue(data.mainBranch.branch);
39
- setIsEditing(false);
40
- showSuccess(value ? 'Main branch updated' : 'Reset to auto-detect');
44
+ if (value) {
45
+ await invoke('db_set_main_branch', { branch: value });
46
+ } else {
47
+ await invoke('db_reset_main_branch');
41
48
  }
49
+ const branch = await dataBridge.getMainBranch();
50
+ setMainBranch({ branch, source: value ? 'configured' : 'detected' });
51
+ setInputValue(branch);
52
+ setIsEditing(false);
53
+ showSuccess(value ? 'Main branch updated' : 'Reset to auto-detect');
42
54
  };
43
55
 
44
56
  const handleCancel = () => {
@@ -47,96 +59,190 @@ export function GeneralSection({ initialMainBranch }: GeneralSectionProps) {
47
59
  };
48
60
 
49
61
  const handleReset = async () => {
50
- const res = await fetch('/api/settings/general', {
51
- method: 'POST',
52
- headers: { 'Content-Type': 'application/json' },
53
- body: JSON.stringify({ mainBranch: null }),
54
- });
55
-
56
- if (res.ok) {
57
- const data = await res.json();
58
- setMainBranch(data.mainBranch);
59
- setInputValue(data.mainBranch.branch);
60
- setIsEditing(false);
61
- showSuccess('Reset to auto-detect');
62
+ await invoke('db_reset_main_branch');
63
+ const branch = await dataBridge.getMainBranch();
64
+ setMainBranch({ branch, source: 'detected' });
65
+ setInputValue(branch);
66
+ setIsEditing(false);
67
+ showSuccess('Reset to auto-detect');
68
+ };
69
+
70
+ // Claude model handlers
71
+ const handleModelSave = async () => {
72
+ if (selectedModel) {
73
+ await dataBridge.setClaudeModel(selectedModel);
74
+ } else {
75
+ await dataBridge.resetClaudeModel();
62
76
  }
77
+ setClaudeModel(selectedModel);
78
+ setIsEditingModel(false);
79
+ const modelLabel = CLAUDE_MODELS.find(m => m.value === selectedModel)?.label || 'Default';
80
+ showSuccess(`Model set to ${modelLabel}`);
81
+ };
82
+
83
+ const handleModelCancel = () => {
84
+ setSelectedModel(claudeModel);
85
+ setIsEditingModel(false);
86
+ };
87
+
88
+ const handleModelReset = async () => {
89
+ await dataBridge.resetClaudeModel();
90
+ setClaudeModel(null);
91
+ setSelectedModel(null);
92
+ setIsEditingModel(false);
93
+ showSuccess('Model reset to default');
63
94
  };
64
95
 
96
+ const currentModel = CLAUDE_MODELS.find(m => m.value === claudeModel) || CLAUDE_MODELS[0];
97
+
65
98
  return (
66
99
  <section id="general">
67
- <div className="flex items-center justify-between mb-4">
100
+ <div className="flex items-center justify-between mb-6">
68
101
  <h2 className="text-lg font-medium text-zinc-900 dark:text-zinc-100">
69
102
  General
70
103
  </h2>
71
104
  </div>
72
105
 
73
106
  {successMessage && (
74
- <div className="mb-4 px-4 py-2 bg-green-50 dark:bg-green-900/20 text-green-700 dark:text-green-300 rounded-lg text-sm">
107
+ <div className="mb-4 px-6 py-3 bg-green-50 dark:bg-green-900/20 text-green-700 dark:text-green-300 rounded-lg text-base">
75
108
  {successMessage}
76
109
  </div>
77
110
  )}
78
111
 
79
112
  {/* Main Branch Setting */}
80
- <div className="p-4 bg-zinc-50 dark:bg-zinc-800/50 rounded-lg">
113
+ <div className="p-6 bg-zinc-50 dark:bg-zinc-800/50 rounded-lg">
81
114
  <div className="flex items-center justify-between">
82
115
  <div>
83
- <label className="block text-sm font-medium text-zinc-900 dark:text-zinc-100">
116
+ <label className="block text-base font-medium text-zinc-900 dark:text-zinc-100">
84
117
  Main Branch
85
118
  </label>
86
- <p className="text-xs text-zinc-500 dark:text-zinc-400 mt-0.5">
119
+ <p className="text-base text-zinc-500 dark:text-zinc-400 mt-1">
87
120
  The branch used as the base for merges and worktrees.
88
121
  </p>
89
122
  </div>
90
123
  {!isEditing && (
91
- <div className="flex items-center gap-2">
92
- <span className="font-mono text-sm text-zinc-900 dark:text-zinc-100">
124
+ <div className="flex items-center gap-3">
125
+ <span className="font-mono text-base text-zinc-900 dark:text-zinc-100">
93
126
  {mainBranch.branch}
94
127
  </span>
95
- <span className="px-1.5 py-0.5 text-xs rounded bg-zinc-200 dark:bg-zinc-700 text-zinc-600 dark:text-zinc-400">
128
+ <span className="px-2 py-1 text-xs rounded bg-zinc-200 dark:bg-zinc-700 text-zinc-600 dark:text-zinc-400">
96
129
  {mainBranch.source}
97
130
  </span>
98
- <button
131
+ <Button
99
132
  onClick={() => setIsEditing(true)}
100
- className="px-2 py-1 text-xs text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors"
133
+ variant="ghost"
134
+ size="sm"
101
135
  >
102
136
  Edit
103
- </button>
137
+ </Button>
104
138
  </div>
105
139
  )}
106
140
  </div>
107
141
 
108
142
  {isEditing && (
109
- <div className="mt-3 space-y-3">
110
- <div className="flex gap-2">
111
- <input
143
+ <div className="mt-4 space-y-4">
144
+ <div className="flex gap-3">
145
+ <Input
112
146
  type="text"
113
147
  value={inputValue}
114
148
  onChange={(e) => setInputValue(e.target.value)}
115
- className="flex-1 px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 font-mono text-sm"
149
+ size="sm"
150
+ className="flex-1 font-mono"
116
151
  placeholder="main"
117
152
  />
118
153
  </div>
119
- <div className="flex gap-2">
120
- <button
121
- onClick={handleSave}
122
- className="px-3 py-1.5 text-sm font-medium bg-blue-600 hover:bg-blue-500 text-white rounded transition-colors"
123
- >
154
+ <div className="flex gap-3">
155
+ <Button onClick={handleSave} size="sm">
124
156
  Save
125
- </button>
157
+ </Button>
126
158
  {mainBranch.source === 'configured' && (
127
- <button
128
- onClick={handleReset}
129
- className="px-3 py-1.5 text-sm font-medium text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors"
130
- >
159
+ <Button onClick={handleReset} variant="ghost" size="sm">
131
160
  Reset to Auto-detect
132
- </button>
161
+ </Button>
133
162
  )}
134
- <button
135
- onClick={handleCancel}
136
- className="px-3 py-1.5 text-sm font-medium text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors"
163
+ <Button onClick={handleCancel} variant="ghost" size="sm">
164
+ Cancel
165
+ </Button>
166
+ </div>
167
+ </div>
168
+ )}
169
+ </div>
170
+
171
+ {/* Claude Code Model Setting */}
172
+ <div className="p-6 bg-zinc-50 dark:bg-zinc-800/50 rounded-lg mt-4">
173
+ <div className="flex items-center justify-between">
174
+ <div>
175
+ <label className="block text-base font-medium text-zinc-900 dark:text-zinc-100">
176
+ Claude Code Model
177
+ </label>
178
+ <p className="text-base text-zinc-500 dark:text-zinc-400 mt-1">
179
+ The model used for Claude Code sessions in this project.
180
+ </p>
181
+ </div>
182
+ {!isEditingModel && (
183
+ <div className="flex items-center gap-3">
184
+ <span className="text-base text-zinc-900 dark:text-zinc-100">
185
+ {currentModel.label}
186
+ </span>
187
+ <span className="px-2 py-1 text-xs rounded bg-zinc-200 dark:bg-zinc-700 text-zinc-600 dark:text-zinc-400">
188
+ {claudeModel ? 'configured' : 'default'}
189
+ </span>
190
+ <Button
191
+ onClick={() => {
192
+ setSelectedModel(claudeModel);
193
+ setIsEditingModel(true);
194
+ }}
195
+ variant="ghost"
196
+ size="sm"
137
197
  >
198
+ Edit
199
+ </Button>
200
+ </div>
201
+ )}
202
+ </div>
203
+
204
+ {isEditingModel && (
205
+ <div className="mt-4 space-y-4">
206
+ <div className="space-y-2">
207
+ {CLAUDE_MODELS.map((model) => (
208
+ <label
209
+ key={model.id}
210
+ className={`flex items-center gap-3 p-3 rounded-lg cursor-pointer transition-colors duration-200 ${
211
+ selectedModel === model.value
212
+ ? 'bg-zinc-200 dark:bg-zinc-700'
213
+ : 'hover:bg-zinc-100 dark:hover:bg-zinc-700/50'
214
+ }`}
215
+ >
216
+ <input
217
+ type="radio"
218
+ name="claude-model"
219
+ checked={selectedModel === model.value}
220
+ onChange={() => setSelectedModel(model.value)}
221
+ className="w-4 h-4 accent-[#819D9F]"
222
+ />
223
+ <div>
224
+ <span className="text-base font-medium text-zinc-900 dark:text-zinc-100">
225
+ {model.label}
226
+ </span>
227
+ <span className="text-sm text-zinc-500 dark:text-zinc-400 ml-2">
228
+ {model.description}
229
+ </span>
230
+ </div>
231
+ </label>
232
+ ))}
233
+ </div>
234
+ <div className="flex gap-3">
235
+ <Button onClick={handleModelSave} size="sm">
236
+ Save
237
+ </Button>
238
+ {claudeModel && (
239
+ <Button onClick={handleModelReset} variant="ghost" size="sm">
240
+ Reset to Default
241
+ </Button>
242
+ )}
243
+ <Button onClick={handleModelCancel} variant="ghost" size="sm">
138
244
  Cancel
139
- </button>
245
+ </Button>
140
246
  </div>
141
247
  </div>
142
248
  )}