dev3000 0.0.113 → 0.0.115

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 (197) hide show
  1. package/dist/cli.js +32 -2
  2. package/dist/cli.js.map +1 -1
  3. package/dist/dev-environment.d.ts.map +1 -1
  4. package/dist/dev-environment.js +25 -4
  5. package/dist/dev-environment.js.map +1 -1
  6. package/dist/src/tui-interface-impl.tsx +175 -127
  7. package/dist/tui-interface-impl.d.ts.map +1 -1
  8. package/dist/tui-interface-impl.js +113 -74
  9. package/dist/tui-interface-impl.js.map +1 -1
  10. package/mcp-server/.next/BUILD_ID +1 -1
  11. package/mcp-server/.next/build-manifest.json +2 -2
  12. package/mcp-server/.next/fallback-build-manifest.json +2 -2
  13. package/mcp-server/.next/next-minimal-server.js.nft.json +1 -1
  14. package/mcp-server/.next/next-server.js.nft.json +1 -1
  15. package/mcp-server/.next/prerender-manifest.json +3 -3
  16. package/mcp-server/.next/required-server-files.json +4 -4
  17. package/mcp-server/.next/server/app/.well-known/workflow/v1/flow/route.js +2 -2
  18. package/mcp-server/.next/server/app/.well-known/workflow/v1/flow/route.js.nft.json +1 -1
  19. package/mcp-server/.next/server/app/.well-known/workflow/v1/step/route.js +2 -2
  20. package/mcp-server/.next/server/app/.well-known/workflow/v1/step/route.js.nft.json +1 -1
  21. package/mcp-server/.next/server/app/.well-known/workflow/v1/webhook/[token]/route.js +2 -2
  22. package/mcp-server/.next/server/app/.well-known/workflow/v1/webhook/[token]/route.js.nft.json +1 -1
  23. package/mcp-server/.next/server/app/_global-error/page.js.nft.json +1 -1
  24. package/mcp-server/.next/server/app/_global-error.html +2 -2
  25. package/mcp-server/.next/server/app/_global-error.rsc +1 -1
  26. package/mcp-server/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  27. package/mcp-server/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  28. package/mcp-server/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  29. package/mcp-server/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  30. package/mcp-server/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  31. package/mcp-server/.next/server/app/_not-found/page.js.nft.json +1 -1
  32. package/mcp-server/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  33. package/mcp-server/.next/server/app/_not-found.html +1 -1
  34. package/mcp-server/.next/server/app/_not-found.rsc +2 -2
  35. package/mcp-server/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  36. package/mcp-server/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  37. package/mcp-server/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  38. package/mcp-server/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  39. package/mcp-server/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  40. package/mcp-server/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  41. package/mcp-server/.next/server/app/api/auth/authorize/route.js.nft.json +1 -1
  42. package/mcp-server/.next/server/app/api/auth/callback/route.js.nft.json +1 -1
  43. package/mcp-server/.next/server/app/api/auth/signout/route.js.nft.json +1 -1
  44. package/mcp-server/.next/server/app/api/auth/token/route.js.nft.json +1 -1
  45. package/mcp-server/.next/server/app/api/cloud/check-pr/route.js +2 -2
  46. package/mcp-server/.next/server/app/api/cloud/check-pr/route.js.nft.json +1 -1
  47. package/mcp-server/.next/server/app/api/cloud/fix-workflow/health/route.js.nft.json +1 -1
  48. package/mcp-server/.next/server/app/api/cloud/fix-workflow/route.js +2 -2
  49. package/mcp-server/.next/server/app/api/cloud/fix-workflow/route.js.nft.json +1 -1
  50. package/mcp-server/.next/server/app/api/cloud/start-fix/route.js +2 -2
  51. package/mcp-server/.next/server/app/api/cloud/start-fix/route.js.nft.json +1 -1
  52. package/mcp-server/.next/server/app/api/integration/webhook/route.js.nft.json +1 -1
  53. package/mcp-server/.next/server/app/api/jank/[session]/route.js.nft.json +1 -1
  54. package/mcp-server/.next/server/app/api/logs/append/route.js.nft.json +1 -1
  55. package/mcp-server/.next/server/app/api/logs/head/route.js.nft.json +1 -1
  56. package/mcp-server/.next/server/app/api/logs/list/route.js.nft.json +1 -1
  57. package/mcp-server/.next/server/app/api/logs/rotate/route.js.nft.json +1 -1
  58. package/mcp-server/.next/server/app/api/logs/stream/route.js.nft.json +1 -1
  59. package/mcp-server/.next/server/app/api/logs/tail/route.js.nft.json +1 -1
  60. package/mcp-server/.next/server/app/api/orchestrator/route.js.nft.json +1 -1
  61. package/mcp-server/.next/server/app/api/projects/[projectId]/bypass-token/route.js.nft.json +1 -1
  62. package/mcp-server/.next/server/app/api/projects/branches/route.js.nft.json +1 -1
  63. package/mcp-server/.next/server/app/api/projects/check-protection/route.js.nft.json +1 -1
  64. package/mcp-server/.next/server/app/api/projects/route.js.nft.json +1 -1
  65. package/mcp-server/.next/server/app/api/screenshots/[filename]/route.js.nft.json +1 -1
  66. package/mcp-server/.next/server/app/api/screenshots/list/route.js.nft.json +1 -1
  67. package/mcp-server/.next/server/app/api/teams/route.js.nft.json +1 -1
  68. package/mcp-server/.next/server/app/api/tools/route.js.nft.json +1 -1
  69. package/mcp-server/.next/server/app/api/workflows/route.js.nft.json +1 -1
  70. package/mcp-server/.next/server/app/auth/error/page.js.nft.json +1 -1
  71. package/mcp-server/.next/server/app/auth/error/page_client-reference-manifest.js +1 -1
  72. package/mcp-server/.next/server/app/auth/error.html +1 -1
  73. package/mcp-server/.next/server/app/auth/error.rsc +2 -2
  74. package/mcp-server/.next/server/app/auth/error.segments/_full.segment.rsc +2 -2
  75. package/mcp-server/.next/server/app/auth/error.segments/_head.segment.rsc +1 -1
  76. package/mcp-server/.next/server/app/auth/error.segments/_index.segment.rsc +2 -2
  77. package/mcp-server/.next/server/app/auth/error.segments/_tree.segment.rsc +2 -2
  78. package/mcp-server/.next/server/app/auth/error.segments/auth/error/__PAGE__.segment.rsc +1 -1
  79. package/mcp-server/.next/server/app/auth/error.segments/auth/error.segment.rsc +1 -1
  80. package/mcp-server/.next/server/app/auth/error.segments/auth.segment.rsc +1 -1
  81. package/mcp-server/.next/server/app/index.html +1 -1
  82. package/mcp-server/.next/server/app/index.rsc +3 -3
  83. package/mcp-server/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  84. package/mcp-server/.next/server/app/index.segments/_full.segment.rsc +3 -3
  85. package/mcp-server/.next/server/app/index.segments/_head.segment.rsc +1 -1
  86. package/mcp-server/.next/server/app/index.segments/_index.segment.rsc +2 -2
  87. package/mcp-server/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  88. package/mcp-server/.next/server/app/logs/page.js.nft.json +1 -1
  89. package/mcp-server/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  90. package/mcp-server/.next/server/app/mcp/route.js.nft.json +1 -1
  91. package/mcp-server/.next/server/app/page.js.nft.json +1 -1
  92. package/mcp-server/.next/server/app/page_client-reference-manifest.js +1 -1
  93. package/mcp-server/.next/server/app/signin/page.js.nft.json +1 -1
  94. package/mcp-server/.next/server/app/signin/page_client-reference-manifest.js +1 -1
  95. package/mcp-server/.next/server/app/video/[session]/page.js.nft.json +1 -1
  96. package/mcp-server/.next/server/app/video/[session]/page_client-reference-manifest.js +1 -1
  97. package/mcp-server/.next/server/app/workflows/[id]/report/page.js.nft.json +1 -1
  98. package/mcp-server/.next/server/app/workflows/[id]/report/page_client-reference-manifest.js +1 -1
  99. package/mcp-server/.next/server/app/workflows/new/page.js.nft.json +1 -1
  100. package/mcp-server/.next/server/app/workflows/new/page_client-reference-manifest.js +1 -1
  101. package/mcp-server/.next/server/app/workflows/page.js.nft.json +1 -1
  102. package/mcp-server/.next/server/app/workflows/page_client-reference-manifest.js +1 -1
  103. package/mcp-server/.next/server/chunks/[root-of-the-server]__157de66b._.js +101 -36
  104. package/mcp-server/.next/server/chunks/[root-of-the-server]__157de66b._.js.map +1 -1
  105. package/mcp-server/.next/server/chunks/{[root-of-the-server]__f99bd75f._.js → [root-of-the-server]__2920484d._.js} +2 -2
  106. package/mcp-server/.next/server/chunks/{[root-of-the-server]__f99bd75f._.js.map → [root-of-the-server]__2920484d._.js.map} +1 -1
  107. package/mcp-server/.next/server/chunks/{[root-of-the-server]__d6a224bc._.js → [root-of-the-server]__71b44a42._.js} +14 -14
  108. package/mcp-server/.next/server/chunks/[root-of-the-server]__71b44a42._.js.map +1 -0
  109. package/mcp-server/.next/server/chunks/[root-of-the-server]__730a8fd0._.js +1 -1
  110. package/mcp-server/.next/server/chunks/[root-of-the-server]__730a8fd0._.js.map +1 -1
  111. package/mcp-server/.next/server/chunks/{[root-of-the-server]__c86876f8._.js → [root-of-the-server]__76031cfc._.js} +2 -2
  112. package/mcp-server/.next/server/chunks/{[root-of-the-server]__c86876f8._.js.map → [root-of-the-server]__76031cfc._.js.map} +1 -1
  113. package/mcp-server/.next/server/chunks/{[root-of-the-server]__c5e6aa23._.js → [root-of-the-server]__832ec618._.js} +2 -2
  114. package/mcp-server/.next/server/chunks/{[root-of-the-server]__c5e6aa23._.js.map → [root-of-the-server]__832ec618._.js.map} +1 -1
  115. package/mcp-server/.next/server/chunks/{[root-of-the-server]__41aa7b20._.js → [root-of-the-server]__b194d4eb._.js} +13 -13
  116. package/mcp-server/.next/server/chunks/[root-of-the-server]__b194d4eb._.js.map +1 -0
  117. package/mcp-server/.next/server/chunks/[root-of-the-server]__c1681338._.js +3 -0
  118. package/mcp-server/.next/server/chunks/[root-of-the-server]__c1681338._.js.map +1 -0
  119. package/mcp-server/.next/server/chunks/{[root-of-the-server]__d37c38d3._.js → [root-of-the-server]__e6808c21._.js} +2 -2
  120. package/mcp-server/.next/server/chunks/{[root-of-the-server]__d37c38d3._.js.map → [root-of-the-server]__e6808c21._.js.map} +1 -1
  121. package/mcp-server/.next/server/chunks/{[root-of-the-server]__446f0436._.js → [root-of-the-server]__ec6a1335._.js} +2 -2
  122. package/mcp-server/.next/server/chunks/[root-of-the-server]__ec6a1335._.js.map +1 -0
  123. package/mcp-server/.next/server/chunks/bee4f_next_dist_esm_build_templates_app-route_1ece9366.js +5 -5
  124. package/mcp-server/.next/server/chunks/bee4f_next_dist_esm_build_templates_app-route_1ece9366.js.map +1 -1
  125. package/mcp-server/.next/server/chunks/mcp-server_app_api_cloud_fix-workflow_steps_ts_b65f3271._.js +30 -16
  126. package/mcp-server/.next/server/chunks/mcp-server_app_api_cloud_fix-workflow_steps_ts_b65f3271._.js.map +1 -1
  127. package/mcp-server/.next/server/chunks/node_modules__pnpm_85ddbe9c._.js +2 -2
  128. package/mcp-server/.next/server/chunks/node_modules__pnpm_85ddbe9c._.js.map +1 -1
  129. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__2e44f0db._.js +3 -0
  130. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__2e44f0db._.js.map +1 -0
  131. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__3585c949._.js +3 -0
  132. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__3585c949._.js.map +1 -0
  133. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__477c3bbb._.js +3 -0
  134. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__477c3bbb._.js.map +1 -0
  135. package/mcp-server/.next/server/chunks/ssr/{[root-of-the-server]__570677dc._.js → [root-of-the-server]__880839a0._.js} +2 -2
  136. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__880839a0._.js.map +1 -0
  137. package/mcp-server/.next/server/chunks/ssr/_41b8f993._.js +3 -0
  138. package/mcp-server/.next/server/chunks/ssr/_41b8f993._.js.map +1 -0
  139. package/mcp-server/.next/server/chunks/ssr/_9ba0ef29._.js +3 -0
  140. package/mcp-server/.next/server/chunks/ssr/_9ba0ef29._.js.map +1 -0
  141. package/mcp-server/.next/server/chunks/ssr/_cd4dc25e._.js.map +1 -1
  142. package/mcp-server/.next/server/chunks/ssr/mcp-server_app_workflows_new_new-workflow-client_tsx_1312c046._.js +2 -2
  143. package/mcp-server/.next/server/chunks/ssr/mcp-server_app_workflows_new_new-workflow-client_tsx_1312c046._.js.map +1 -1
  144. package/mcp-server/.next/server/chunks/ssr/mcp-server_app_workflows_workflows-client_tsx_268cfd4a._.js +7 -0
  145. package/mcp-server/.next/server/chunks/ssr/mcp-server_app_workflows_workflows-client_tsx_268cfd4a._.js.map +1 -0
  146. package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_961f21c4._.js +3 -0
  147. package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_961f21c4._.js.map +1 -0
  148. package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_a82244bf._.js +3 -0
  149. package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_a82244bf._.js.map +1 -0
  150. package/mcp-server/.next/server/chunks/ssr/{node_modules__pnpm_07527699._.js → node_modules__pnpm_eb98e511._.js} +2 -2
  151. package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_eb98e511._.js.map +1 -0
  152. package/mcp-server/.next/server/middleware.js.nft.json +1 -1
  153. package/mcp-server/.next/server/server-reference-manifest.js +1 -1
  154. package/mcp-server/.next/server/server-reference-manifest.json +1 -1
  155. package/mcp-server/.next/static/chunks/000849a6a897f531.css +1 -0
  156. package/mcp-server/.next/static/chunks/048cee2510ddb1a0.js +1 -0
  157. package/mcp-server/.next/static/chunks/0622bd0e093adee7.js +3 -0
  158. package/mcp-server/.next/static/chunks/{46f60efee5f19794.js → 16359f64918a93f3.js} +1 -1
  159. package/mcp-server/.next/static/chunks/1851a3e70d7efc10.js +1 -0
  160. package/mcp-server/.next/static/chunks/{cc6addc4bb10fa11.js → 2ad16eeb719786f1.js} +1 -1
  161. package/mcp-server/.next/static/chunks/57feca7a4e06545e.js +7 -0
  162. package/mcp-server/.next/static/chunks/93db5737a327ab0c.js +6 -0
  163. package/mcp-server/.next/static/chunks/9fd3c715ecfb4d05.js +1 -0
  164. package/mcp-server/.next/static/chunks/b4b1ec6435790587.js +1 -0
  165. package/mcp-server/.next/static/chunks/cfe150cb2048b7e8.js +1 -0
  166. package/mcp-server/app/api/cloud/fix-workflow/steps.ts +267 -28
  167. package/mcp-server/app/api/cloud/fix-workflow/workflow.ts +16 -8
  168. package/mcp-server/app/api/cloud/start-fix/route.ts +2 -2
  169. package/mcp-server/app/api/workflows/route.ts +45 -1
  170. package/mcp-server/app/workflows/workflows-client.tsx +259 -100
  171. package/mcp-server/package.json +1 -1
  172. package/package.json +3 -3
  173. package/src/tui-interface-impl.tsx +175 -127
  174. package/mcp-server/.next/server/chunks/[root-of-the-server]__41aa7b20._.js.map +0 -1
  175. package/mcp-server/.next/server/chunks/[root-of-the-server]__446f0436._.js.map +0 -1
  176. package/mcp-server/.next/server/chunks/[root-of-the-server]__c508da18._.js +0 -3
  177. package/mcp-server/.next/server/chunks/[root-of-the-server]__c508da18._.js.map +0 -1
  178. package/mcp-server/.next/server/chunks/[root-of-the-server]__d6a224bc._.js.map +0 -1
  179. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__0ff05d72._.js +0 -3
  180. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__0ff05d72._.js.map +0 -1
  181. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__27cc5956._.js +0 -3
  182. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__27cc5956._.js.map +0 -1
  183. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__570677dc._.js.map +0 -1
  184. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__ef510343._.js +0 -3
  185. package/mcp-server/.next/server/chunks/ssr/[root-of-the-server]__ef510343._.js.map +0 -1
  186. package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_07527699._.js.map +0 -1
  187. package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_7cc36047._.js +0 -3
  188. package/mcp-server/.next/server/chunks/ssr/node_modules__pnpm_7cc36047._.js.map +0 -1
  189. package/mcp-server/.next/static/chunks/07848f6bd2a7e5f6.js +0 -3
  190. package/mcp-server/.next/static/chunks/637a66565f27572f.js +0 -6
  191. package/mcp-server/.next/static/chunks/aed4fb5252a4bc95.js +0 -3
  192. package/mcp-server/.next/static/chunks/e8d521464b0c96ca.css +0 -1
  193. package/mcp-server/.next/static/chunks/ff53279afa939907.js +0 -1
  194. package/mcp-server/.next/static/chunks/ffa2ecb6845be49c.js +0 -1
  195. /package/mcp-server/.next/static/{UcmWUkU-l9iLeWRnSUybj → 5zfTZk2QSS7WLdL1K8Q5I}/_buildManifest.js +0 -0
  196. /package/mcp-server/.next/static/{UcmWUkU-l9iLeWRnSUybj → 5zfTZk2QSS7WLdL1K8Q5I}/_clientMiddlewareManifest.json +0 -0
  197. /package/mcp-server/.next/static/{UcmWUkU-l9iLeWRnSUybj → 5zfTZk2QSS7WLdL1K8Q5I}/_ssgManifest.js +0 -0
@@ -2,10 +2,20 @@
2
2
 
3
3
  import Image from "next/image"
4
4
  import Link from "next/link"
5
- import { useState } from "react"
5
+ import { useCallback, useRef, useState } from "react"
6
6
  import { Badge } from "@/components/ui/badge"
7
7
  import { Button } from "@/components/ui/button"
8
8
  import { Card, CardContent } from "@/components/ui/card"
9
+ import { Checkbox } from "@/components/ui/checkbox"
10
+ import {
11
+ Dialog,
12
+ DialogClose,
13
+ DialogContent,
14
+ DialogDescription,
15
+ DialogFooter,
16
+ DialogHeader,
17
+ DialogTitle
18
+ } from "@/components/ui/dialog"
9
19
  import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
10
20
  import type { WorkflowRun } from "@/lib/workflow-storage"
11
21
 
@@ -23,6 +33,11 @@ interface WorkflowsClientProps {
23
33
 
24
34
  export default function WorkflowsClient({ user, initialRuns }: WorkflowsClientProps) {
25
35
  const [isSigningOut, setIsSigningOut] = useState(false)
36
+ const [runs, setRuns] = useState<WorkflowRun[]>(initialRuns)
37
+ const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set())
38
+ const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false)
39
+ const [isDeleting, setIsDeleting] = useState(false)
40
+ const lastSelectedIndex = useRef<number | null>(null)
26
41
 
27
42
  async function handleSignOut() {
28
43
  setIsSigningOut(true)
@@ -35,16 +50,100 @@ export default function WorkflowsClient({ user, initialRuns }: WorkflowsClientPr
35
50
  }
36
51
  }
37
52
 
53
+ const handleSelectAll = useCallback(
54
+ (checked: boolean) => {
55
+ if (checked) {
56
+ setSelectedIds(new Set(runs.map((run) => run.id)))
57
+ } else {
58
+ setSelectedIds(new Set())
59
+ }
60
+ lastSelectedIndex.current = null
61
+ },
62
+ [runs]
63
+ )
64
+
65
+ const handleSelectRow = useCallback(
66
+ (runId: string, index: number, event: React.MouseEvent) => {
67
+ setSelectedIds((prev) => {
68
+ const newSelected = new Set(prev)
69
+
70
+ // Handle shift-click for range selection
71
+ if (event.shiftKey && lastSelectedIndex.current !== null) {
72
+ const start = Math.min(lastSelectedIndex.current, index)
73
+ const end = Math.max(lastSelectedIndex.current, index)
74
+
75
+ // Select all items in the range
76
+ for (let i = start; i <= end; i++) {
77
+ newSelected.add(runs[i].id)
78
+ }
79
+ } else {
80
+ // Regular click - toggle selection
81
+ if (newSelected.has(runId)) {
82
+ newSelected.delete(runId)
83
+ } else {
84
+ newSelected.add(runId)
85
+ }
86
+ }
87
+
88
+ return newSelected
89
+ })
90
+
91
+ lastSelectedIndex.current = index
92
+ },
93
+ [runs]
94
+ )
95
+
96
+ const handleDelete = async () => {
97
+ setIsDeleting(true)
98
+ try {
99
+ const response = await fetch("/api/workflows", {
100
+ method: "DELETE",
101
+ headers: {
102
+ "Content-Type": "application/json"
103
+ },
104
+ body: JSON.stringify({
105
+ userId: user.id,
106
+ runIds: Array.from(selectedIds)
107
+ })
108
+ })
109
+
110
+ const result = await response.json()
111
+
112
+ if (result.success) {
113
+ // Remove deleted runs from state
114
+ setRuns((prev) => prev.filter((run) => !selectedIds.has(run.id)))
115
+ setSelectedIds(new Set())
116
+ setIsDeleteDialogOpen(false)
117
+ } else {
118
+ console.error("Failed to delete workflows:", result.error)
119
+ alert(`Failed to delete workflows: ${result.error}`)
120
+ }
121
+ } catch (error) {
122
+ console.error("Failed to delete workflows:", error)
123
+ alert("Failed to delete workflows. Please try again.")
124
+ } finally {
125
+ setIsDeleting(false)
126
+ }
127
+ }
128
+
129
+ const allSelected = runs.length > 0 && selectedIds.size === runs.length
130
+ const someSelected = selectedIds.size > 0 && selectedIds.size < runs.length
131
+
38
132
  return (
39
- <div className="min-h-screen bg-gray-50 py-8">
40
- <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
41
- <div className="mb-8 flex justify-between items-start">
133
+ <div className="h-screen flex flex-col bg-gray-50">
134
+ <div className="flex-shrink-0 px-4 sm:px-6 lg:px-8 pt-8 pb-4 max-w-7xl mx-auto w-full">
135
+ <div className="flex justify-between items-start">
42
136
  <div>
43
137
  <h1 className="text-3xl font-bold text-gray-900">d3k Workflow Runs</h1>
44
138
  <p className="mt-2 text-gray-600">View all your d3k workflow fix proposals and PRs</p>
45
139
  <p className="mt-1 text-sm text-gray-500">Signed in as {user.email}</p>
46
140
  </div>
47
141
  <div className="flex gap-3">
142
+ {selectedIds.size > 0 && (
143
+ <Button variant="destructive" onClick={() => setIsDeleteDialogOpen(true)}>
144
+ Delete {selectedIds.size} selected
145
+ </Button>
146
+ )}
48
147
  <Button asChild>
49
148
  <Link href="/workflows/new">New Workflow</Link>
50
149
  </Button>
@@ -53,8 +152,10 @@ export default function WorkflowsClient({ user, initialRuns }: WorkflowsClientPr
53
152
  </Button>
54
153
  </div>
55
154
  </div>
155
+ </div>
56
156
 
57
- {initialRuns.length === 0 ? (
157
+ <div className="flex-1 min-h-0 px-4 sm:px-6 lg:px-8 pb-8 max-w-7xl mx-auto w-full">
158
+ {runs.length === 0 ? (
58
159
  <Card className="p-12 text-center">
59
160
  <CardContent>
60
161
  <p className="text-muted-foreground">No workflow runs yet</p>
@@ -62,105 +163,163 @@ export default function WorkflowsClient({ user, initialRuns }: WorkflowsClientPr
62
163
  </CardContent>
63
164
  </Card>
64
165
  ) : (
65
- <Card>
66
- <Table>
67
- <TableHeader>
68
- <TableRow>
69
- <TableHead>Project</TableHead>
70
- <TableHead>Status</TableHead>
71
- <TableHead>Timestamp</TableHead>
72
- <TableHead>Before</TableHead>
73
- <TableHead>After</TableHead>
74
- <TableHead>Report</TableHead>
75
- <TableHead>PR</TableHead>
76
- </TableRow>
77
- </TableHeader>
78
- <TableBody>
79
- {initialRuns.map((run) => (
80
- <TableRow key={`${run.id}-${run.timestamp}`}>
81
- <TableCell>
82
- <div className="font-medium">{run.projectName}</div>
83
- <div className="text-xs text-muted-foreground">{run.id}</div>
84
- </TableCell>
85
- <TableCell>
86
- <Badge
87
- variant={
88
- run.status === "success" ? "secondary" : run.status === "running" ? "default" : "destructive"
89
- }
90
- className={
91
- run.status === "success"
92
- ? "bg-green-100 text-green-800 hover:bg-green-100"
93
- : run.status === "running"
94
- ? "bg-blue-100 text-blue-800 hover:bg-blue-100"
95
- : ""
96
- }
97
- >
98
- {run.status}
99
- </Badge>
100
- </TableCell>
101
- <TableCell className="text-muted-foreground">{new Date(run.timestamp).toLocaleString()}</TableCell>
102
- <TableCell>
103
- {run.beforeScreenshotUrl ? (
104
- <a href={run.beforeScreenshotUrl} target="_blank" rel="noopener noreferrer">
105
- <Image
106
- src={run.beforeScreenshotUrl}
107
- alt="Before"
108
- width={64}
109
- height={40}
110
- className="object-cover rounded border hover:opacity-80 transition-opacity"
111
- unoptimized
112
- />
113
- </a>
114
- ) : (
115
- <span className="text-muted-foreground text-xs">-</span>
116
- )}
117
- </TableCell>
118
- <TableCell>
119
- {run.afterScreenshotUrl ? (
120
- <a href={run.afterScreenshotUrl} target="_blank" rel="noopener noreferrer">
121
- <Image
122
- src={run.afterScreenshotUrl}
123
- alt="After"
124
- width={64}
125
- height={40}
126
- className="object-cover rounded border hover:opacity-80 transition-opacity"
127
- unoptimized
128
- />
129
- </a>
130
- ) : (
131
- <span className="text-muted-foreground text-xs">-</span>
132
- )}
133
- </TableCell>
134
- <TableCell>
135
- {run.reportBlobUrl ? (
136
- <Link href={`/workflows/${run.id}/report`} className="text-primary hover:underline">
137
- View Report
138
- </Link>
139
- ) : (
140
- <span className="text-muted-foreground">No report</span>
141
- )}
142
- </TableCell>
143
- <TableCell>
144
- {run.prUrl ? (
145
- <a
146
- href={run.prUrl}
147
- target="_blank"
148
- rel="noopener noreferrer"
149
- className="text-primary hover:underline"
150
- >
151
- View PR
152
- </a>
153
- ) : (
154
- <span className="text-muted-foreground">No PR</span>
155
- )}
156
- </TableCell>
166
+ <Card className="h-full flex flex-col overflow-hidden">
167
+ <div className="overflow-auto flex-1 [&_[data-slot=table-container]]:overflow-visible">
168
+ <Table>
169
+ <TableHeader className="sticky top-0 bg-card z-10 shadow-[0_1px_3px_-1px_rgba(0,0,0,0.1)]">
170
+ <TableRow>
171
+ <TableHead className="w-8 pr-0">
172
+ <Checkbox
173
+ checked={allSelected}
174
+ ref={(el) => {
175
+ if (el) {
176
+ // Set indeterminate state for "some selected"
177
+ const input = el.querySelector("button") as HTMLButtonElement
178
+ if (input) {
179
+ input.dataset.state = someSelected
180
+ ? "indeterminate"
181
+ : allSelected
182
+ ? "checked"
183
+ : "unchecked"
184
+ }
185
+ }
186
+ }}
187
+ onCheckedChange={handleSelectAll}
188
+ aria-label="Select all"
189
+ />
190
+ </TableHead>
191
+ <TableHead>Project ({runs.length})</TableHead>
192
+ <TableHead>Status</TableHead>
193
+ <TableHead>Timestamp</TableHead>
194
+ <TableHead>Before</TableHead>
195
+ <TableHead>After</TableHead>
196
+ <TableHead>Report</TableHead>
197
+ <TableHead>PR</TableHead>
157
198
  </TableRow>
158
- ))}
159
- </TableBody>
160
- </Table>
199
+ </TableHeader>
200
+ <TableBody>
201
+ {runs.map((run, index) => (
202
+ <TableRow
203
+ key={`${run.id}-${run.timestamp}`}
204
+ className={selectedIds.has(run.id) ? "bg-muted/50" : undefined}
205
+ >
206
+ <TableCell className="pr-0">
207
+ <Checkbox
208
+ checked={selectedIds.has(run.id)}
209
+ onClick={(e) => handleSelectRow(run.id, index, e)}
210
+ onCheckedChange={() => {}}
211
+ aria-label={`Select ${run.projectName}`}
212
+ />
213
+ </TableCell>
214
+ <TableCell>
215
+ <div className="font-medium">{run.projectName}</div>
216
+ <div className="text-xs text-muted-foreground">{run.id}</div>
217
+ </TableCell>
218
+ <TableCell>
219
+ <Badge
220
+ variant={
221
+ run.status === "done" ? "secondary" : run.status === "running" ? "default" : "destructive"
222
+ }
223
+ className={
224
+ run.status === "done"
225
+ ? "bg-green-100 text-green-800 hover:bg-green-100"
226
+ : run.status === "running"
227
+ ? "bg-blue-100 text-blue-800 hover:bg-blue-100"
228
+ : ""
229
+ }
230
+ >
231
+ {run.status}
232
+ </Badge>
233
+ </TableCell>
234
+ <TableCell className="text-muted-foreground">
235
+ {new Date(run.timestamp).toLocaleString()}
236
+ </TableCell>
237
+ <TableCell>
238
+ {run.beforeScreenshotUrl ? (
239
+ <a href={run.beforeScreenshotUrl} target="_blank" rel="noopener noreferrer">
240
+ <Image
241
+ src={run.beforeScreenshotUrl}
242
+ alt="Before"
243
+ width={64}
244
+ height={40}
245
+ className="object-cover rounded border hover:opacity-80 transition-opacity"
246
+ unoptimized
247
+ />
248
+ </a>
249
+ ) : (
250
+ <span className="text-muted-foreground text-xs">-</span>
251
+ )}
252
+ </TableCell>
253
+ <TableCell>
254
+ {run.afterScreenshotUrl ? (
255
+ <a href={run.afterScreenshotUrl} target="_blank" rel="noopener noreferrer">
256
+ <Image
257
+ src={run.afterScreenshotUrl}
258
+ alt="After"
259
+ width={64}
260
+ height={40}
261
+ className="object-cover rounded border hover:opacity-80 transition-opacity"
262
+ unoptimized
263
+ />
264
+ </a>
265
+ ) : (
266
+ <span className="text-muted-foreground text-xs">-</span>
267
+ )}
268
+ </TableCell>
269
+ <TableCell>
270
+ {run.reportBlobUrl ? (
271
+ <Link href={`/workflows/${run.id}/report`} className="text-primary hover:underline">
272
+ View Report
273
+ </Link>
274
+ ) : (
275
+ <span className="text-muted-foreground">No report</span>
276
+ )}
277
+ </TableCell>
278
+ <TableCell>
279
+ {run.prUrl ? (
280
+ <a
281
+ href={run.prUrl}
282
+ target="_blank"
283
+ rel="noopener noreferrer"
284
+ className="text-primary hover:underline"
285
+ >
286
+ View PR
287
+ </a>
288
+ ) : (
289
+ <span className="text-muted-foreground">No PR</span>
290
+ )}
291
+ </TableCell>
292
+ </TableRow>
293
+ ))}
294
+ </TableBody>
295
+ </Table>
296
+ </div>
161
297
  </Card>
162
298
  )}
163
299
  </div>
300
+
301
+ <Dialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>
302
+ <DialogContent>
303
+ <DialogHeader>
304
+ <DialogTitle>Delete Workflow Runs</DialogTitle>
305
+ <DialogDescription>
306
+ Are you sure you want to delete {selectedIds.size} workflow run{selectedIds.size === 1 ? "" : "s"}? This
307
+ will permanently delete all associated data including screenshots and reports. This action cannot be
308
+ undone.
309
+ </DialogDescription>
310
+ </DialogHeader>
311
+ <DialogFooter>
312
+ <DialogClose asChild>
313
+ <Button variant="outline" disabled={isDeleting}>
314
+ Cancel
315
+ </Button>
316
+ </DialogClose>
317
+ <Button variant="destructive" onClick={handleDelete} disabled={isDeleting}>
318
+ {isDeleting ? "Deleting..." : `Delete ${selectedIds.size} run${selectedIds.size === 1 ? "" : "s"}`}
319
+ </Button>
320
+ </DialogFooter>
321
+ </DialogContent>
322
+ </Dialog>
164
323
  </div>
165
324
  )
166
325
  }
@@ -35,7 +35,7 @@
35
35
  "react-dom": "19.3.0-canary-09f05694-20251201",
36
36
  "react-markdown": "^10.1.0",
37
37
  "tailwind-merge": "catalog:",
38
- "workflow": "4.0.1-beta.23",
38
+ "workflow": "4.0.1-beta.26",
39
39
  "ws": "^8.18.3",
40
40
  "zod": "^3.22.4"
41
41
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dev3000",
3
- "version": "0.0.113",
3
+ "version": "0.0.115",
4
4
  "description": "AI-powered development tools with browser monitoring and MCP server integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -67,7 +67,6 @@
67
67
  "ink": "^6.3.1",
68
68
  "ink-spinner": "^5.0.0",
69
69
  "ms": "^2.1.3",
70
- "next": "16.0.0-canary.18",
71
70
  "ora": "^9.0.0",
72
71
  "package-manager-detector": "^1.3.0",
73
72
  "react": "^19.1.1",
@@ -89,7 +88,8 @@
89
88
  "pnpm": {
90
89
  "overrides": {
91
90
  "@types/react": "19.1.17",
92
- "@types/react-dom": "19.1.11"
91
+ "@types/react-dom": "19.1.11",
92
+ "next": "16.1.0-canary.9"
93
93
  }
94
94
  },
95
95
  "engines": {