@rexvane/piweb 0.3.14 → 0.3.16

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 (262) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +12 -9
  3. package/.next/build-manifest.json +3 -3
  4. package/.next/prerender-manifest.json +6 -6
  5. package/.next/react-loadable-manifest.json +16 -4
  6. package/.next/required-server-files.js +3 -1
  7. package/.next/required-server-files.json +3 -1
  8. package/.next/routes-manifest.json +20 -0
  9. package/.next/server/app/_global-error/page.js +2 -2
  10. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  11. package/.next/server/app/_global-error.html +1 -1
  12. package/.next/server/app/_global-error.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  15. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  16. package/.next/server/app/_not-found/page.js +1 -1
  17. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/server/app/_not-found.html +1 -1
  19. package/.next/server/app/_not-found.rsc +7 -4
  20. package/.next/server/app/_not-found.segments/_full.segment.rsc +7 -4
  21. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +5 -2
  22. package/.next/server/app/_not-found.segments/_tree.segment.rsc +5 -2
  23. package/.next/server/app/api/agent/[id]/events/route.js +2 -2
  24. package/.next/server/app/api/agent/[id]/events/route.js.nft.json +1 -1
  25. package/.next/server/app/api/agent/[id]/route.js +1 -1
  26. package/.next/server/app/api/agent/[id]/route.js.nft.json +1 -1
  27. package/.next/server/app/api/agent/[id]/tree/route.js +1 -1
  28. package/.next/server/app/api/agent/[id]/tree/route.js.nft.json +1 -1
  29. package/.next/server/app/api/agent/new/route.js +1 -1
  30. package/.next/server/app/api/agent/new/route.js.nft.json +1 -1
  31. package/.next/server/app/api/config/route.js +1 -1
  32. package/.next/server/app/api/config/route.js.nft.json +1 -1
  33. package/.next/server/app/api/files/route.js +1 -1
  34. package/.next/server/app/api/files/route.js.nft.json +1 -1
  35. package/.next/server/app/api/git/route.js +2 -2
  36. package/.next/server/app/api/git/route.js.nft.json +1 -1
  37. package/.next/server/app/api/growth/route.js +1 -1
  38. package/.next/server/app/api/growth/route.js.nft.json +1 -1
  39. package/.next/server/app/api/health/route.js +1 -1
  40. package/.next/server/app/api/models/route.js +1 -1
  41. package/.next/server/app/api/models/route.js.nft.json +1 -1
  42. package/.next/server/app/api/pi-settings/route.js +1 -1
  43. package/.next/server/app/api/pi-settings/route.js.nft.json +1 -1
  44. package/.next/server/app/api/plugins/route.js +1 -1
  45. package/.next/server/app/api/plugins/route.js.nft.json +1 -1
  46. package/.next/server/app/api/prompts/route.js +1 -1
  47. package/.next/server/app/api/prompts/route.js.nft.json +1 -1
  48. package/.next/server/app/api/security/route.js +1 -1
  49. package/.next/server/app/api/security/route.js.nft.json +1 -1
  50. package/.next/server/app/api/sessions/[id]/export/route.js +1 -1
  51. package/.next/server/app/api/sessions/[id]/export/route.js.nft.json +1 -1
  52. package/.next/server/app/api/sessions/[id]/route.js +1 -1
  53. package/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  54. package/.next/server/app/api/sessions/import/route.js +3 -3
  55. package/.next/server/app/api/sessions/import/route.js.nft.json +1 -1
  56. package/.next/server/app/api/sessions/route.js +1 -1
  57. package/.next/server/app/api/sessions/route.js.nft.json +1 -1
  58. package/.next/server/app/api/skills/route.js +2 -2
  59. package/.next/server/app/api/skills/route.js.nft.json +1 -1
  60. package/.next/server/app/api/swarm/[id]/route.js +1 -0
  61. package/.next/server/app/api/swarm/[id]/route.js.nft.json +1 -0
  62. package/.next/server/app/api/swarm/[id]/route_client-reference-manifest.js +1 -0
  63. package/.next/server/app/api/swarm/route.js +1 -0
  64. package/.next/server/app/api/swarm/route.js.nft.json +1 -0
  65. package/.next/server/app/api/swarm/route_client-reference-manifest.js +1 -0
  66. package/.next/server/app/api/tests/route.js +2 -0
  67. package/.next/server/app/api/tests/route.js.nft.json +1 -0
  68. package/.next/server/app/api/tests/route_client-reference-manifest.js +1 -0
  69. package/.next/server/app/api/update/route.js +2 -2
  70. package/.next/server/app/api/update/route.js.nft.json +1 -1
  71. package/.next/server/app/api/version/route.js +1 -1
  72. package/.next/server/app/api/version/route.js.nft.json +1 -1
  73. package/.next/server/app/api/web-auth/route.js +1 -1
  74. package/.next/server/app/api/workspaces/route.js +1 -1
  75. package/.next/server/app/api/workspaces/route.js.nft.json +1 -1
  76. package/.next/server/app/icon.svg/route.js +1 -1
  77. package/.next/server/app/index.html +1 -1
  78. package/.next/server/app/index.rsc +9 -6
  79. package/.next/server/app/index.segments/__PAGE__.segment.rsc +7 -4
  80. package/.next/server/app/index.segments/_full.segment.rsc +9 -6
  81. package/.next/server/app/index.segments/_tree.segment.rsc +5 -2
  82. package/.next/server/app/login/page.js +1 -1
  83. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  84. package/.next/server/app/login.html +1 -1
  85. package/.next/server/app/login.rsc +8 -5
  86. package/.next/server/app/login.segments/_full.segment.rsc +8 -5
  87. package/.next/server/app/login.segments/_tree.segment.rsc +5 -2
  88. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +6 -3
  89. package/.next/server/app/page.js +1 -1
  90. package/.next/server/app/page_client-reference-manifest.js +1 -1
  91. package/.next/server/app-paths-manifest.json +12 -9
  92. package/.next/server/chunks/496.js +1 -1
  93. package/.next/server/chunks/532.js +1 -1
  94. package/.next/server/chunks/686.js +6 -2
  95. package/.next/server/chunks/757.js +1 -0
  96. package/.next/server/chunks/775.js +3 -0
  97. package/.next/server/middleware-build-manifest.js +1 -1
  98. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  99. package/.next/server/pages/404.html +1 -1
  100. package/.next/server/pages/500.html +1 -1
  101. package/.next/server/server-reference-manifest.json +1 -1
  102. package/.next/static/0t1jBUAuVaTFTXxRyIo3q/_buildManifest.js +1 -0
  103. package/.next/static/chunks/2608.43c58236c9cce8e6.js +1 -0
  104. package/.next/static/chunks/{2716.a9e808190a4e2424.js → 2716.4ec42df1d51354c9.js} +1 -1
  105. package/.next/static/chunks/4632.62139b565b657aac.js +1 -0
  106. package/.next/static/chunks/{4673.d3d0a7f2599080fb.js → 4673.7796104395deb8d7.js} +1 -1
  107. package/.next/static/chunks/4686-17f21a006739a596.js +1 -0
  108. package/.next/static/chunks/7577.10af9bb661652da8.js +1 -0
  109. package/.next/static/chunks/8866.38ec4ac4ee5a1b74.js +1 -0
  110. package/.next/static/chunks/app/_global-error/page-5148173b3f55e415.js +1 -0
  111. package/.next/static/chunks/app/api/agent/[id]/events/route-5148173b3f55e415.js +1 -0
  112. package/.next/static/chunks/app/api/agent/[id]/route-5148173b3f55e415.js +1 -0
  113. package/.next/static/chunks/app/api/agent/[id]/tree/route-5148173b3f55e415.js +1 -0
  114. package/.next/static/chunks/app/api/agent/new/route-5148173b3f55e415.js +1 -0
  115. package/.next/static/chunks/app/api/config/route-5148173b3f55e415.js +1 -0
  116. package/.next/static/chunks/app/api/files/route-5148173b3f55e415.js +1 -0
  117. package/.next/static/chunks/app/api/git/route-5148173b3f55e415.js +1 -0
  118. package/.next/static/chunks/app/api/growth/route-5148173b3f55e415.js +1 -0
  119. package/.next/static/chunks/app/api/health/route-5148173b3f55e415.js +1 -0
  120. package/.next/static/chunks/app/api/models/route-5148173b3f55e415.js +1 -0
  121. package/.next/static/chunks/app/api/pi-settings/route-5148173b3f55e415.js +1 -0
  122. package/.next/static/chunks/app/api/plugins/route-5148173b3f55e415.js +1 -0
  123. package/.next/static/chunks/app/api/prompts/route-5148173b3f55e415.js +1 -0
  124. package/.next/static/chunks/app/api/security/route-5148173b3f55e415.js +1 -0
  125. package/.next/static/chunks/app/api/sessions/[id]/export/route-5148173b3f55e415.js +1 -0
  126. package/.next/static/chunks/app/api/sessions/[id]/route-5148173b3f55e415.js +1 -0
  127. package/.next/static/chunks/app/api/sessions/import/route-5148173b3f55e415.js +1 -0
  128. package/.next/static/chunks/app/api/sessions/route-5148173b3f55e415.js +1 -0
  129. package/.next/static/chunks/app/api/skills/route-5148173b3f55e415.js +1 -0
  130. package/.next/static/chunks/app/api/swarm/[id]/route-5148173b3f55e415.js +1 -0
  131. package/.next/static/chunks/app/api/swarm/route-5148173b3f55e415.js +1 -0
  132. package/.next/static/chunks/app/api/tests/route-5148173b3f55e415.js +1 -0
  133. package/.next/static/chunks/app/api/update/route-5148173b3f55e415.js +1 -0
  134. package/.next/static/chunks/app/api/version/route-5148173b3f55e415.js +1 -0
  135. package/.next/static/chunks/app/api/web-auth/route-5148173b3f55e415.js +1 -0
  136. package/.next/static/chunks/app/api/workspaces/route-5148173b3f55e415.js +1 -0
  137. package/.next/static/chunks/app/page-14379b8060d5cf07.js +1 -0
  138. package/.next/static/chunks/next/dist/client/components/builtin/app-error-5148173b3f55e415.js +1 -0
  139. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-5148173b3f55e415.js +1 -0
  140. package/.next/static/chunks/next/dist/client/components/builtin/not-found-5148173b3f55e415.js +1 -0
  141. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-5148173b3f55e415.js +1 -0
  142. package/.next/static/chunks/webpack-d1a69ad9edb38b11.js +1 -0
  143. package/.next/static/css/d0a0162cb481abe8.css +1 -0
  144. package/.next/types/app/api/swarm/[id]/route.ts +353 -0
  145. package/.next/types/app/api/swarm/route.ts +353 -0
  146. package/.next/types/app/api/tests/route.ts +353 -0
  147. package/.next/types/routes.d.ts +4 -1
  148. package/.next/types/validator.ts +27 -0
  149. package/README.md +61 -7
  150. package/assets/archive.png +0 -0
  151. package/assets/growth-1.png +0 -0
  152. package/assets/growth-2.png +0 -0
  153. package/assets/import.png +0 -0
  154. package/assets/main.png +0 -0
  155. package/assets/outline.png +0 -0
  156. package/assets/prompts-1.png +0 -0
  157. package/assets/prompts-2.png +0 -0
  158. package/assets/providers-1.png +0 -0
  159. package/assets/providers-2.png +0 -0
  160. package/assets/providers-3.png +0 -0
  161. package/assets/trace-1.png +0 -0
  162. package/assets/trace-2.png +0 -0
  163. package/assets/trace-3.png +0 -0
  164. package/assets/trace-4.png +0 -0
  165. package/assets/viewer-1.png +0 -0
  166. package/assets/viewer-2.png +0 -0
  167. package/next.config.ts +6 -2
  168. package/package.json +10 -5
  169. package/scripts/launcher.mjs +1 -1
  170. package/scripts/managed-niubash-assets.mjs +146 -0
  171. package/scripts/pick-folder.ps1 +11 -2
  172. package/scripts/prepare-niubash-packages.mjs +182 -0
  173. package/scripts/release.mjs +11 -31
  174. package/scripts/run-test-file.mjs +34 -0
  175. package/scripts/smoke-managed-niubash.mjs +62 -0
  176. package/scripts/verify-package.mjs +53 -0
  177. package/scripts/verify-release-config.mjs +24 -0
  178. package/src/app/api/config/route.ts +4 -1
  179. package/src/app/api/security/route.ts +8 -3
  180. package/src/app/api/swarm/[id]/route.ts +28 -0
  181. package/src/app/api/swarm/route.ts +24 -0
  182. package/src/app/api/tests/route.ts +27 -0
  183. package/src/app/api/update/route.ts +8 -2
  184. package/src/app/globals.css +777 -0
  185. package/src/app/layout.tsx +13 -6
  186. package/src/components/AppShell.tsx +505 -199
  187. package/src/components/ChatInput.tsx +153 -26
  188. package/src/components/ChatWindow.tsx +46 -40
  189. package/src/components/ContextMeter.tsx +11 -17
  190. package/src/components/FileViewer.tsx +1 -1
  191. package/src/components/GitPanel.tsx +13 -11
  192. package/src/components/ModelSelector.tsx +19 -6
  193. package/src/components/PiMark.tsx +5 -38
  194. package/src/components/ProjectPanel.tsx +1 -0
  195. package/src/components/PromptPanel.tsx +132 -51
  196. package/src/components/SessionImportSection.tsx +53 -37
  197. package/src/components/SessionSidebar.tsx +159 -57
  198. package/src/components/SettingsPanel.tsx +330 -193
  199. package/src/components/SwarmCoordinatorPod.tsx +1021 -0
  200. package/src/components/TestInspectorPod.tsx +549 -0
  201. package/src/components/icons.tsx +23 -0
  202. package/src/hooks/usePiWeb.ts +112 -8
  203. package/src/i18n.tsx +59 -3
  204. package/src/lib/agent-manager.ts +182 -11
  205. package/src/lib/command-validation.ts +9 -1
  206. package/src/lib/delegation.ts +93 -0
  207. package/src/lib/managed-niubash.ts +231 -0
  208. package/src/lib/pi.ts +3 -2
  209. package/src/lib/runtime-activity.ts +27 -0
  210. package/src/lib/session-import/claude.ts +13 -2
  211. package/src/lib/session-import/codex.ts +44 -8
  212. package/src/lib/session-import/files.ts +14 -0
  213. package/src/lib/session-import/grok.ts +54 -24
  214. package/src/lib/session-import/index.ts +5 -0
  215. package/src/lib/session-import/lock.ts +25 -0
  216. package/src/lib/session-import/types.ts +12 -0
  217. package/src/lib/session-import/writer.ts +8 -3
  218. package/src/lib/skills-service.ts +16 -9
  219. package/src/lib/swarm-service.ts +371 -0
  220. package/src/lib/test-run-service.ts +122 -0
  221. package/src/lib/theme.ts +68 -1
  222. package/src/lib/trajectory.ts +1 -0
  223. package/src/lib/types.ts +14 -0
  224. package/src/lib/workflow.ts +55 -0
  225. package/.next/static/LOFl9bqqMV2goBV8erESO/_buildManifest.js +0 -1
  226. package/.next/static/chunks/2608.ec8ff1f5767c9056.js +0 -1
  227. package/.next/static/chunks/4632.112d2e893d48d188.js +0 -1
  228. package/.next/static/chunks/4686-7d694def920ff093.js +0 -1
  229. package/.next/static/chunks/app/_global-error/page-f77e9ede9808b18e.js +0 -1
  230. package/.next/static/chunks/app/api/agent/[id]/events/route-f77e9ede9808b18e.js +0 -1
  231. package/.next/static/chunks/app/api/agent/[id]/route-f77e9ede9808b18e.js +0 -1
  232. package/.next/static/chunks/app/api/agent/[id]/tree/route-f77e9ede9808b18e.js +0 -1
  233. package/.next/static/chunks/app/api/agent/new/route-f77e9ede9808b18e.js +0 -1
  234. package/.next/static/chunks/app/api/config/route-f77e9ede9808b18e.js +0 -1
  235. package/.next/static/chunks/app/api/files/route-f77e9ede9808b18e.js +0 -1
  236. package/.next/static/chunks/app/api/git/route-f77e9ede9808b18e.js +0 -1
  237. package/.next/static/chunks/app/api/growth/route-f77e9ede9808b18e.js +0 -1
  238. package/.next/static/chunks/app/api/health/route-f77e9ede9808b18e.js +0 -1
  239. package/.next/static/chunks/app/api/models/route-f77e9ede9808b18e.js +0 -1
  240. package/.next/static/chunks/app/api/pi-settings/route-f77e9ede9808b18e.js +0 -1
  241. package/.next/static/chunks/app/api/plugins/route-f77e9ede9808b18e.js +0 -1
  242. package/.next/static/chunks/app/api/prompts/route-f77e9ede9808b18e.js +0 -1
  243. package/.next/static/chunks/app/api/security/route-f77e9ede9808b18e.js +0 -1
  244. package/.next/static/chunks/app/api/sessions/[id]/export/route-f77e9ede9808b18e.js +0 -1
  245. package/.next/static/chunks/app/api/sessions/[id]/route-f77e9ede9808b18e.js +0 -1
  246. package/.next/static/chunks/app/api/sessions/import/route-f77e9ede9808b18e.js +0 -1
  247. package/.next/static/chunks/app/api/sessions/route-f77e9ede9808b18e.js +0 -1
  248. package/.next/static/chunks/app/api/skills/route-f77e9ede9808b18e.js +0 -1
  249. package/.next/static/chunks/app/api/update/route-f77e9ede9808b18e.js +0 -1
  250. package/.next/static/chunks/app/api/version/route-f77e9ede9808b18e.js +0 -1
  251. package/.next/static/chunks/app/api/web-auth/route-f77e9ede9808b18e.js +0 -1
  252. package/.next/static/chunks/app/api/workspaces/route-f77e9ede9808b18e.js +0 -1
  253. package/.next/static/chunks/app/page-9a5440047c5a415c.js +0 -1
  254. package/.next/static/chunks/next/dist/client/components/builtin/app-error-f77e9ede9808b18e.js +0 -1
  255. package/.next/static/chunks/next/dist/client/components/builtin/forbidden-f77e9ede9808b18e.js +0 -1
  256. package/.next/static/chunks/next/dist/client/components/builtin/not-found-f77e9ede9808b18e.js +0 -1
  257. package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-f77e9ede9808b18e.js +0 -1
  258. package/.next/static/chunks/webpack-d28e132e1b8c100c.js +0 -1
  259. package/.next/static/css/b2d35abc828d4713.css +0 -1
  260. package/assets/showcase.png +0 -0
  261. package/bin/pi.js +0 -50
  262. /package/.next/static/{LOFl9bqqMV2goBV8erESO → 0t1jBUAuVaTFTXxRyIo3q}/_ssgManifest.js +0 -0
@@ -0,0 +1,28 @@
1
+ import { NextResponse } from "next/server";
2
+ import { BoundaryError } from "@/lib/path-security";
3
+ import { acceptSwarmTask, cancelSwarm, getSwarm } from "@/lib/swarm-service";
4
+
5
+ export const dynamic = "force-dynamic";
6
+
7
+ export async function GET(_req: Request, { params }: { params: Promise<{ id: string }> }) {
8
+ try {
9
+ return NextResponse.json({ success: true, data: await getSwarm((await params).id) });
10
+ } catch (error) {
11
+ return NextResponse.json({ success: false, error: String((error as Error).message ?? error) }, { status: error instanceof BoundaryError ? 400 : 500 });
12
+ }
13
+ }
14
+
15
+ export async function POST(req: Request, { params }: { params: Promise<{ id: string }> }) {
16
+ try {
17
+ const body = await req.json();
18
+ const id = (await params).id;
19
+ const data = body?.action === "cancel"
20
+ ? await cancelSwarm(id, body?.cwd)
21
+ : body?.action === "accept"
22
+ ? await acceptSwarmTask(id, body?.index, body?.cwd)
23
+ : (() => { throw new BoundaryError("invalid swarm action"); })();
24
+ return NextResponse.json({ success: true, data });
25
+ } catch (error) {
26
+ return NextResponse.json({ success: false, error: String((error as Error).message ?? error) }, { status: error instanceof BoundaryError || error instanceof SyntaxError ? 400 : 500 });
27
+ }
28
+ }
@@ -0,0 +1,24 @@
1
+ import { NextResponse } from "next/server";
2
+ import { BoundaryError } from "@/lib/path-security";
3
+ import { listSwarms, startSwarm } from "@/lib/swarm-service";
4
+ import { RuntimeBusyError } from "@/lib/runtime-activity";
5
+
6
+ export const dynamic = "force-dynamic";
7
+
8
+ export async function GET(req: Request) {
9
+ try {
10
+ const cwd = new URL(req.url).searchParams.get("cwd");
11
+ return NextResponse.json({ success: true, data: await listSwarms(cwd) });
12
+ } catch (error) {
13
+ return NextResponse.json({ success: false, error: String((error as Error).message ?? error) }, { status: error instanceof BoundaryError ? 400 : 500 });
14
+ }
15
+ }
16
+
17
+ export async function POST(req: Request) {
18
+ try {
19
+ const body = await req.json();
20
+ return NextResponse.json({ success: true, data: await startSwarm(body?.cwd, body?.tasks) }, { status: 202 });
21
+ } catch (error) {
22
+ return NextResponse.json({ success: false, error: String((error as Error).message ?? error) }, { status: error instanceof RuntimeBusyError ? 409 : error instanceof BoundaryError || error instanceof SyntaxError ? 400 : 500 });
23
+ }
24
+ }
@@ -0,0 +1,27 @@
1
+ import { NextResponse } from "next/server";
2
+ import { BoundaryError } from "@/lib/path-security";
3
+ import { listTestFiles, readTestFile, runTestFile } from "@/lib/test-run-service";
4
+ import { RuntimeBusyError } from "@/lib/runtime-activity";
5
+
6
+ export const dynamic = "force-dynamic";
7
+
8
+ export async function GET(req: Request) {
9
+ try {
10
+ const params = new URL(req.url).searchParams;
11
+ const cwd = params.get("cwd");
12
+ const file = params.get("file");
13
+ const data = file ? await readTestFile(cwd, file) : { files: await listTestFiles(cwd), runner: "vitest" };
14
+ return NextResponse.json({ success: true, data });
15
+ } catch (error) {
16
+ return NextResponse.json({ success: false, error: String((error as Error).message ?? error) }, { status: error instanceof BoundaryError ? 400 : 500 });
17
+ }
18
+ }
19
+
20
+ export async function POST(req: Request) {
21
+ try {
22
+ const body = await req.json();
23
+ return NextResponse.json({ success: true, data: await runTestFile(body?.cwd, body?.file) });
24
+ } catch (error) {
25
+ return NextResponse.json({ success: false, error: String((error as Error).message ?? error) }, { status: error instanceof RuntimeBusyError ? 409 : error instanceof BoundaryError || error instanceof SyntaxError ? 400 : 500 });
26
+ }
27
+ }
@@ -1,6 +1,7 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import { checkForUpdate, runUpdate, UpdateBusyError, type UpdateTarget } from "@/lib/update-service";
3
3
  import { activeStatus } from "@/lib/agent-manager";
4
+ import { beginMaintenance, RuntimeBusyError } from "@/lib/runtime-activity";
4
5
 
5
6
  export const dynamic = "force-dynamic";
6
7
 
@@ -24,10 +25,15 @@ export async function POST(req: Request) {
24
25
  };
25
26
  // Check before even taking a release lock; rechecked before each mutating step.
26
27
  await assertIdle();
27
- return NextResponse.json({ success: true, data: await runUpdate(target, { assertIdle }) });
28
+ const releaseMaintenance = beginMaintenance();
29
+ try {
30
+ return NextResponse.json({ success: true, data: await runUpdate(target, { assertIdle }) });
31
+ } finally {
32
+ releaseMaintenance();
33
+ }
28
34
  } catch (error) {
29
35
  return NextResponse.json({ success: false, error: error instanceof Error ? error.message : String(error) }, {
30
- status: error instanceof UpdateBusyError ? 409 : 500,
36
+ status: error instanceof UpdateBusyError || error instanceof RuntimeBusyError ? 409 : 500,
31
37
  });
32
38
  }
33
39
  }