@wular/coder 0.4.2 → 0.4.3

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 (320) hide show
  1. package/dist/actions-FzDNxMFf.js +20 -0
  2. package/dist/{adapter-BKVzTDnn.js → adapter-7SEiVsmp.js} +1 -1
  3. package/dist/{adapter-B0oYCI0S.js → adapter-BLEfUqoQ.js} +1 -1
  4. package/dist/{adapter-DPInwbJG.js → adapter-H4GlcKQz.js} +1 -1
  5. package/dist/{add-DRsPpQFl.js → add-B50dIJGd.js} +1 -1
  6. package/dist/{add-DkpUwhtO.js → add-D7X3gxap.js} +1 -1
  7. package/dist/{add-C2y-mVzl.js → add-DOEUHIe7.js} +1 -1
  8. package/dist/{add-CLYTF_up.js → add-QExQhTzi.js} +1 -1
  9. package/dist/{add-json-5uPnWPoD.js → add-json-Ck4KIZrT.js} +1 -1
  10. package/dist/{agent-r5mMcehf.js → agent-BPtnEf1q.js} +1 -1
  11. package/dist/{agent-hw3zKw8y.js → agent-BlQ_dNNm.js} +2 -2
  12. package/dist/{alias-_0Rwf2cA.js → alias-BwQBovke.js} +1 -1
  13. package/dist/{app-oE8G1-bi.js → app-y6BYm2eH.js} +1 -1
  14. package/dist/{approvals-DbVrsxec.js → approvals-Cc9cq5T1.js} +2 -2
  15. package/dist/{approve-DeAhFL-m.js → approve-oO9k2fnK.js} +2 -2
  16. package/dist/{apps-eujHiNca.js → apps-CU2YalX8.js} +1 -1
  17. package/dist/{archive-BCUfymIB.js → archive-C5c_HQS1.js} +2 -2
  18. package/dist/{archive-DZ6vpMHb.js → archive-CemlWlVY.js} +2 -2
  19. package/dist/archive-sweep-ehg-fWIt.js +1 -0
  20. package/dist/{args-BOEEdpWk.js → args-DcBCtXhz.js} +1 -1
  21. package/dist/{ask-BU2WVxVM.js → ask-Chu7Twu_.js} +2 -2
  22. package/dist/auth-BOyXPOtu.js +1 -0
  23. package/dist/auth-XbqKSbcD.js +1 -0
  24. package/dist/{chat-bridge-BS9WtP3X.js → chat-bridge-DXgZItGP.js} +1 -1
  25. package/dist/{chat-B_yhNTo0.js → chat-cknlIhVh.js} +1 -1
  26. package/dist/{cli-DWCR7iqa.js → cli-B1ObVrL4.js} +5 -5
  27. package/dist/cli.d.ts +1 -1
  28. package/dist/cli.js +1 -1
  29. package/dist/{client-D9IoAuDD.js → client-31YzOj-i.js} +1 -1
  30. package/dist/{config-12pK4qW7.js → config-DAE_qHYA.js} +1 -1
  31. package/dist/{create-D3f6q0Yq.js → create-CM8B8JxD.js} +1 -1
  32. package/dist/credentials-BXD4Qptk.js +1 -0
  33. package/dist/dash/manifest.json +949 -915
  34. package/dist/dash/public/assets/chunks/{agent-pills-dd0b7643e125bbf1.js → agent-pills-b6a6da91c9559d9f.js} +1 -1
  35. package/dist/dash/public/assets/chunks/{agent-settings-form-45ae6aeaaed2b568.js → agent-settings-form-b615c677046cd6f2.js} +1 -1
  36. package/dist/dash/public/assets/chunks/agents-grid-f2e7b4ff9e11b6e3.js +1 -0
  37. package/dist/dash/public/assets/chunks/{badge-676b01e0c615bf7b.js → badge-215c7b2631dafc69.js} +1 -1
  38. package/dist/dash/public/assets/chunks/{card-e0901d68b79dfa93.js → card-e86dcc81326d2b14.js} +1 -1
  39. package/dist/dash/public/assets/chunks/{combo-952a457d52360d88.js → combo-09e246dc9a517fa8.js} +1 -1
  40. package/dist/dash/public/assets/chunks/composer-417166b029f48c47.js +1 -0
  41. package/dist/dash/public/assets/chunks/composer-645ae8fa97a35280.js +1 -0
  42. package/dist/dash/public/assets/chunks/{confirm-f2fe4ba9905a89c6.js → confirm-5ae484241ad888fd.js} +1 -1
  43. package/dist/dash/public/assets/chunks/{connect-apps-661f3b3a85f1776a.js → connect-apps-4147c45f45fde2b1.js} +1 -1
  44. package/dist/dash/public/assets/chunks/{connect-repositories-5389ec8701a3deac.js → connect-repositories-77591110836bdf03.js} +1 -1
  45. package/dist/dash/public/assets/chunks/credentials-list-e005a0783ec93465.js +2 -0
  46. package/dist/dash/public/assets/chunks/{custom-range-03ba6fb2ade7d282.js → custom-range-463e119af4681c61.js} +1 -1
  47. package/dist/dash/public/assets/chunks/{editor-34cb529d6d8a4b09.js → editor-804b84f4fe6539cd.js} +4 -4
  48. package/dist/dash/public/assets/chunks/{engines-list-2f1acee3ecc8461a.js → engines-list-ceab51f13c690e8c.js} +1 -1
  49. package/dist/dash/public/assets/chunks/{field-901f1f35c18c39c9.js → field-aa0a4b98a976781e.js} +1 -1
  50. package/dist/dash/public/assets/chunks/filter-91144ac2eec6297f.js +1 -0
  51. package/dist/dash/public/assets/chunks/format-105c706345987fb2.js +1 -0
  52. package/dist/dash/public/assets/chunks/heads-a42817b32d2d7f08.js +1 -0
  53. package/dist/dash/public/assets/chunks/{instructions-052fa45a9daf6db6.js → instructions-3a1dcaff2d868aa5.js} +1 -1
  54. package/dist/dash/public/assets/chunks/instructions-6c6f981fffaa31e4.js +1 -0
  55. package/dist/dash/public/assets/chunks/{list-87b359bebd26986a.js → list-7270361464fc3c04.js} +1 -1
  56. package/dist/dash/public/assets/chunks/{mcp-list-b42f0d2ee463b37d.js → mcp-list-2e715d48666b54ad.js} +1 -1
  57. package/dist/dash/public/assets/chunks/{models-list-0669d26fd662aec3.js → models-list-d3c40f94c761a6e5.js} +1 -1
  58. package/dist/dash/public/assets/chunks/paged-3ddb6077bef42752.js +1 -0
  59. package/dist/dash/public/assets/chunks/{platform-actions-c92ca3c6198a9387.js → platform-actions-271ec3b99a64280b.js} +1 -1
  60. package/dist/dash/public/assets/chunks/runners-list-767e49c7d0ec833a.js +1 -0
  61. package/dist/dash/public/assets/chunks/{segmented-358ff2b4992b8384.js → segmented-de4386ccaac7304d.js} +1 -1
  62. package/dist/dash/public/assets/chunks/{select-1013702bdfb1ade4.js → select-a90307706cffa6e0.js} +1 -1
  63. package/dist/dash/public/assets/chunks/{sentinel-c972a33dc69a5135.js → sentinel-b5e032b38604dfd3.js} +1 -1
  64. package/dist/dash/public/assets/chunks/shared-init-7f81ae7bc8c82438.js +2 -0
  65. package/dist/dash/public/assets/chunks/shared-init-933c7f9ee85be766.js +5 -0
  66. package/dist/dash/public/assets/chunks/{tail-7c27aab8ba268bd9.js → tail-4891e727ee526792.js} +1 -1
  67. package/dist/dash/public/assets/chunks/task-actions-ce854925a2dc78fd.js +1 -0
  68. package/dist/dash/public/assets/chunks/task-ddfddeaf07fb684c.js +1 -0
  69. package/dist/dash/public/assets/chunks/task-view-c37dcee08f21a279.js +5 -0
  70. package/dist/dash/public/assets/chunks/tasks-list-baef587999f322d8.js +1 -0
  71. package/dist/dash/public/assets/chunks/{toolbar-f964fa864699f095.js → toolbar-8d98313606ad8a2d.js} +1 -1
  72. package/dist/dash/public/assets/chunks/{versions-list-fc2e0d2a7382e049.js → versions-list-532690efd9f1b0ea.js} +1 -1
  73. package/dist/dash/public/assets/{dash-account-96fc41be318839fa.css → dash-account-edc56e85dbaaabe0.css} +1 -1
  74. package/dist/dash/public/assets/dash-agents-edba57b67e4005d0.css +1 -0
  75. package/dist/dash/public/assets/dash-agents-new-fe22253fbada2fbf.css +1 -0
  76. package/dist/dash/public/assets/dash-agents-param-slug-adf52e9dacb2d825.css +1 -0
  77. package/dist/dash/public/assets/dash-agents-param-slug-edit-a2937a347689ef29.css +1 -0
  78. package/dist/dash/public/assets/dash-agents-param-slug-platforms-265ba13db32a460d.css +1 -0
  79. package/dist/dash/public/assets/dash-agents-param-slug-settings-8afc52eb0372bc4b.css +1 -0
  80. package/dist/dash/public/assets/dash-agents-param-slug-tasks-6193e646be68dbd2.css +1 -0
  81. package/dist/dash/public/assets/dash-agents-param-slug-usage-ceadb3a1c911c402.css +1 -0
  82. package/dist/dash/public/assets/{dash-settings-53b8e6a8f656fa1a.css → dash-settings-cf1997cd7f72e518.css} +1 -1
  83. package/dist/dash/public/assets/dash-settings-param-tab-b44dac8e79a560e6.css +1 -0
  84. package/dist/dash/public/assets/dash-tasks-916c7100a8058aa3.css +1 -0
  85. package/dist/dash/public/assets/dash-tasks-param-id-194a6ffc20e872f2.css +1 -0
  86. package/dist/dash/public/assets/{dash-usage-884943221f76ad93.css → dash-usage-40940b289f85e0b6.css} +1 -1
  87. package/dist/dash/public/assets/pnext-client-13aee92bef5c9e3f.js +1 -0
  88. package/dist/dash/public/assets/pnext-client-1f2686b2044f0df6.js +1 -0
  89. package/dist/dash/public/assets/pnext-client-26130234ebad7067.js +1 -0
  90. package/dist/dash/public/assets/pnext-client-311e35b0076bf406.js +1 -0
  91. package/dist/dash/public/assets/pnext-client-4ade1bf75c9c3d87.js +1 -0
  92. package/dist/dash/public/assets/pnext-client-61cd31b687ede1da.js +1 -0
  93. package/dist/dash/public/assets/{pnext-client-2693db10b197ade1.js → pnext-client-61db65dc4223217a.js} +1 -1
  94. package/dist/dash/public/assets/pnext-client-6ea656e7705e3f2a.js +1 -0
  95. package/dist/dash/public/assets/pnext-client-7fd0f793f0322cb9.js +1 -0
  96. package/dist/dash/public/assets/pnext-client-88159c0840fcfa4a.js +1 -0
  97. package/dist/dash/public/assets/pnext-client-b03f0c47c066b4f3.js +1 -0
  98. package/dist/dash/public/assets/{pnext-client-1afa4148bea69ad2.js → pnext-client-d6478835f543f901.js} +1 -1
  99. package/dist/dash/public/assets/pnext-client-dadb8359021ed590.js +1 -0
  100. package/dist/dash/public/assets/pnext-client-de07532d6aaebf2c.js +1 -0
  101. package/dist/dash/public/assets/pnext-client-f87a31890c8ff224.js +1 -0
  102. package/dist/dash/public/assets/pnext-client-ffe1c123a8e2a350.js +1 -0
  103. package/dist/{default-CwQXCtoB.js → default-BMvUMTFp.js} +1 -1
  104. package/dist/default-B_nKaX0-.js +1 -0
  105. package/dist/{delete-cS01oOIb.js → delete-Bjteibld.js} +2 -2
  106. package/dist/{delete-BD6AnCLg.js → delete-riCIKZwj.js} +2 -2
  107. package/dist/{disable-BMWWeYFQ.js → disable-DQC56YFy.js} +1 -1
  108. package/dist/{discover-Dvr_3_Xr.js → discover-Qanr5TEO.js} +1 -1
  109. package/dist/{discover-Cfx5RPU7.js → discover-lgTYwoQp.js} +2 -2
  110. package/dist/dispatch-BsW_1m7e.js +14 -0
  111. package/dist/{docs-DWegDRiu.js → docs-DFs7lOJp.js} +1 -1
  112. package/dist/{docs-BX65z2Iu.js → docs-DKROso-4.js} +2 -2
  113. package/dist/{enable-Cfzeau2x.js → enable-D2DqZvcU.js} +1 -1
  114. package/dist/{env-CRf6wkM2.js → env-YRY3I60r.js} +1 -1
  115. package/dist/exec-DuUkLMqg.js +11 -0
  116. package/dist/executor-vMppVLB6.js +10 -0
  117. package/dist/flow/builtin/review.js +1 -1
  118. package/dist/flow/index.d.ts +1 -1
  119. package/dist/flow/index.js +1 -1
  120. package/dist/{flow-kAxxVOiR.js → flow-DmERAnR8.js} +1 -1
  121. package/dist/{github-actions-DwUzm4hC.js → github-actions-C_NkHVJq.js} +1 -1
  122. package/dist/http-D01Udu4u.js +1 -0
  123. package/dist/{index-CZjFX5zV.d.ts → index-B1L4zXZH.d.ts} +2 -1
  124. package/dist/{init-C4tDFH4G.js → init-Bd6JHzBc.js} +1 -1
  125. package/dist/integrations-B2CavXR1.js +5 -0
  126. package/dist/integrations-D1Dwy1kt.js +1 -0
  127. package/dist/lib/broker.js +2 -2
  128. package/dist/{list-DuPqU3fk.js → list-4Uo-0v9s.js} +1 -1
  129. package/dist/{list-COAo7eZd.js → list-B0ujEZhd.js} +3 -3
  130. package/dist/{list-5Ljf9TxF.js → list-B5oa1Bhy.js} +2 -2
  131. package/dist/{list-vOvIpbOH.js → list-BjE_l6la.js} +1 -1
  132. package/dist/{list-J8d_zh-o.js → list-Ck9ibCs1.js} +1 -1
  133. package/dist/{list-vpyS-hv8.js → list-DhgK4Zc4.js} +1 -1
  134. package/dist/{list-way5oLO0.js → list-KvL7AUhD.js} +2 -2
  135. package/dist/{list-DzGuMkQy.js → list-byYLBl1U.js} +1 -1
  136. package/dist/{load-BpEsAn51.js → load-SnZd7xG1.js} +1 -1
  137. package/dist/{local-H3uvqEbq.js → local-BRy1EUq2.js} +1 -1
  138. package/dist/log-view-DeJstSkw.js +3 -0
  139. package/dist/{login-BBw95-S3.js → login-C-ahtDKV.js} +1 -1
  140. package/dist/{login-CNmeRAL7.js → login-zpwke8g1.js} +1 -1
  141. package/dist/{logout-j0dTo_Ib.js → logout-CI6Kf-T6.js} +1 -1
  142. package/dist/{maintenance-DkLVtqM7.js → maintenance-BAzr9Jlr.js} +1 -1
  143. package/dist/{match-CXAjDhg7.js → match-DxV1d49D.js} +1 -1
  144. package/dist/{mcp-BgKb2Cdk.js → mcp-CmcL1MCG.js} +1 -1
  145. package/dist/{mcp-CsmBtlW9.js → mcp-mhXwtGQT.js} +1 -1
  146. package/dist/{migrate-N-85_N7J.js → migrate-Czh3TEK5.js} +1 -1
  147. package/dist/{migrate-D4nzYhk8.js → migrate-w7KfzUAR.js} +1 -1
  148. package/dist/{model-B79MFtRV.js → model-JRoTH9QK.js} +1 -1
  149. package/dist/models-C-S7HqSb.js +1 -0
  150. package/dist/{prompt-CEuBMNhk.js → prompt-CMXmt2l9.js} +4 -4
  151. package/dist/{push-DbdnbZYt.js → push-B8BhTyZs.js} +1 -1
  152. package/dist/queue-CirjEskI.js +117 -0
  153. package/dist/refresh-Bmy2r1Ee.js +1 -0
  154. package/dist/{remote-miQNTVRa.js → remote-CxFnEjZl.js} +1 -1
  155. package/dist/{remove-BNzbUhaK.js → remove-C15WLaXT.js} +1 -1
  156. package/dist/{remove-D-QeeZQL.js → remove-CTZYjjSr.js} +1 -1
  157. package/dist/{remove-CLpL12Ya.js → remove-CTl-H0f0.js} +1 -1
  158. package/dist/{remove-CaYH9Cna.js → remove-DX2FVo5b.js} +1 -1
  159. package/dist/rename-D1g4TnHQ.js +1 -0
  160. package/dist/{result-BfTfJayl.js → result-D49VN8PM.js} +3 -3
  161. package/dist/result-DGWyUHYU.js +18 -0
  162. package/dist/{resume-aZ8yWDBh.js → resume-ywzc7z6A.js} +2 -2
  163. package/dist/{review-BEhDcX4b.js → review-ZC0xG8XY.js} +2 -2
  164. package/dist/{rotate-key-BqnKhTK8.js → rotate-key-Bf8_99ck.js} +1 -1
  165. package/dist/{run-BWbabvub.js → run-D7SJ-ieT.js} +2 -2
  166. package/dist/run-DoRQSC_K.js +2 -0
  167. package/dist/{run-BdPjxaZU.js → run-ukCf2Mdy.js} +1 -1
  168. package/dist/runner-D-REfOUe.js +1 -0
  169. package/dist/{runner-sUpWJ_k0.js → runner-wDYhkVsM.js} +1 -1
  170. package/dist/schema-DoNO0dPh.js +1 -0
  171. package/dist/sdk.d.ts +4 -2
  172. package/dist/sdk.js +1 -1
  173. package/dist/serve-BJ_Mbm2m.js +8 -0
  174. package/dist/{serve-C0WC-QrV.js → serve-C1MMhM1F.js} +2 -2
  175. package/dist/{serve-CcObDKKQ.js → serve-DtrOHaoS.js} +2 -2
  176. package/dist/{serve-Ck95047c.js → serve-P9pFkEnE.js} +1 -1
  177. package/dist/{serve-BTeomYxW.js → serve-yjSw0B1a.js} +1 -1
  178. package/dist/{server-BxLFZL80.js → server-DDWTnmbx.js} +1 -1
  179. package/dist/{setup-host-DLd_j2Uw.js → setup-host-L6Rnn5Cz.js} +1 -1
  180. package/dist/{shared-BLkGRKty.js → shared-XsUX_ZZb.js} +1 -1
  181. package/dist/{show-DzoQIs75.js → show-CU-jqJ90.js} +1 -1
  182. package/dist/{show-FC3dJcD-.js → show-DVJmB2u-.js} +1 -1
  183. package/dist/{status-BU3DR1XU.js → status-CBydR7LE.js} +1 -1
  184. package/dist/{steer-P_38hRRD.js → steer-Cm_sHZqs.js} +2 -2
  185. package/dist/{stop-BJGDRPsp.js → stop-DJS7DAPJ.js} +1 -1
  186. package/dist/{stop-BWY6k6v5.js → stop-TrebIIuv.js} +2 -2
  187. package/dist/store-BrNMqJgk.js +42 -0
  188. package/dist/store-j8icrG0v.js +19 -0
  189. package/dist/task-C8lmcNsf.js +1 -0
  190. package/dist/{task-DeglY79z.js → task-CpUI19o2.js} +4 -4
  191. package/dist/task-CvSqiwxo.js +1 -0
  192. package/dist/{test-BrSrhop9.js → test-CDKz4jY_.js} +1 -1
  193. package/dist/{tools-CgswhJzh.js → tools-DBFeoosk.js} +1 -1
  194. package/dist/{types-I5Cwtl_K.d.ts → types-DMGBYB_K.d.ts} +3 -1
  195. package/dist/{unalias-mMHXqok7.js → unalias-BfQFBnuK.js} +1 -1
  196. package/dist/{update-DbOWToPy.js → update-C4FFOie8.js} +1 -1
  197. package/dist/{upgrade-D6oC9HQI.js → upgrade-DLJqMnUQ.js} +2 -2
  198. package/dist/{usage-Cb8Dtv9V.js → usage-CSh-xwQ2.js} +1 -1
  199. package/dist/{usage-DMs-IIJC.js → usage-D8mc4qXK.js} +1 -1
  200. package/dist/{watch-BcMQXGYO.js → watch-CQu-tJKZ.js} +2 -2
  201. package/dist/{watch-eE2XiwsC.js → watch-DmwaEvoi.js} +2 -2
  202. package/dist/{wire-BeT1Axeo.js → wire-DzGLZ3-O.js} +1 -1
  203. package/dist/worker-BLKTMLqa.js +1 -0
  204. package/dist/worker-nHemduM_.js +9 -0
  205. package/dist/{workflow-Cshghoas.js → workflow-IrouAus_.js} +1 -1
  206. package/docs/mcp.md +1 -1
  207. package/migrations/0000_initial.sql +8 -0
  208. package/migrations/meta/0000_snapshot.json +75 -1
  209. package/migrations/meta/_journal.json +1 -1
  210. package/package.json +1 -1
  211. package/plugins/agents/skills/coder/SKILL.md +1 -0
  212. package/plugins/claude/.claude-plugin/plugin.json +1 -1
  213. package/plugins/claude/skills/dispatch/SKILL.md +1 -1
  214. package/plugins/cursor/.cursor-plugin/plugin.json +1 -1
  215. package/plugins/cursor/skills/coder/SKILL.md +1 -0
  216. package/src/client/index.ts +10 -2
  217. package/src/client/types.ts +18 -0
  218. package/src/core/defaults.ts +11 -0
  219. package/src/core/task/log-view.ts +120 -6
  220. package/src/server/dash/app/dash/agents/(list)/agent-menu.tsx +4 -0
  221. package/src/server/dash/app/dash/agents/(list)/agents-grid.tsx +18 -35
  222. package/src/server/dash/app/dash/agents/(list)/loading.tsx +7 -1
  223. package/src/server/dash/app/dash/agents/[slug]/(tabs)/layout.tsx +2 -1
  224. package/src/server/dash/app/dash/layout.tsx +13 -3
  225. package/src/server/dash/app/dash/settings/[tab]/credentials-list.tsx +20 -13
  226. package/src/server/dash/app/dash/settings/[tab]/runners-list.tsx +13 -12
  227. package/src/server/dash/app/dash/tasks/[id]/activity.tsx +49 -4
  228. package/src/server/dash/app/dash/tasks/[id]/task-actions.tsx +43 -6
  229. package/src/server/dash/app/dash/tasks/[id]/task-view.css +52 -31
  230. package/src/server/dash/app/dash/tasks/[id]/task-view.tsx +143 -51
  231. package/src/server/dash/app/dash/tasks/composer.css +4 -0
  232. package/src/server/dash/app/dash/tasks/composer.tsx +6 -5
  233. package/src/server/dash/app/dash/tasks/list/task.ts +29 -1
  234. package/src/server/dash/app/dash/tasks/list/tasks-list.css +20 -7
  235. package/src/server/dash/app/dash/tasks/list/tasks-list.tsx +256 -109
  236. package/src/server/dash/app/dash/tasks/list/tasks-section.tsx +9 -13
  237. package/src/server/dash/app/dash/tasks/page.tsx +3 -35
  238. package/src/server/dash/comps/frame/loading-card.tsx +4 -3
  239. package/src/server/dash/comps/frame/page-head.css +10 -0
  240. package/src/server/dash/comps/frame/page-head.tsx +3 -2
  241. package/src/server/dash/comps/frame/task-toasts.tsx +196 -50
  242. package/src/server/dash/comps/nav/side-toggle.tsx +15 -4
  243. package/src/server/dash/comps/ui/card.css +1 -0
  244. package/src/server/dash/comps/ui/filter.css +64 -0
  245. package/src/server/dash/comps/ui/filter.tsx +336 -0
  246. package/src/server/dash/comps/ui/icons.ts +2 -0
  247. package/src/server/dash/comps/ui/menu.tsx +4 -0
  248. package/src/server/dash/comps/ui/select.tsx +2 -2
  249. package/src/server/dash/comps/ui/toolbar.css +14 -0
  250. package/src/server/dash/utils/client.ts +21 -0
  251. package/src/server/dash/utils/format.ts +12 -4
  252. package/src/server/dash/utils/paged.ts +14 -6
  253. package/dist/actions-Mk3FSlpJ.js +0 -20
  254. package/dist/archive-sweep-Cxbh8yAI.js +0 -1
  255. package/dist/auth-CBWTmAPA.js +0 -1
  256. package/dist/auth-Dmn2U7rr.js +0 -1
  257. package/dist/credentials-l6dsrZLL.js +0 -1
  258. package/dist/dash/public/assets/chunks/agents-grid-b906da80c31fc035.js +0 -1
  259. package/dist/dash/public/assets/chunks/composer-49f9e7c5c4dfda3b.js +0 -1
  260. package/dist/dash/public/assets/chunks/composer-f331d00837143aee.js +0 -1
  261. package/dist/dash/public/assets/chunks/credentials-list-e6177d0943517929.js +0 -2
  262. package/dist/dash/public/assets/chunks/format-eb03fc9d9744d960.js +0 -1
  263. package/dist/dash/public/assets/chunks/heads-1570a3a6db331979.js +0 -1
  264. package/dist/dash/public/assets/chunks/instructions-d0a4b0d95009c262.js +0 -1
  265. package/dist/dash/public/assets/chunks/paged-bc6fa0c2b9d52ed7.js +0 -1
  266. package/dist/dash/public/assets/chunks/runners-list-9fffa50432c470c9.js +0 -1
  267. package/dist/dash/public/assets/chunks/shared-init-20e199043ff5d00f.js +0 -2
  268. package/dist/dash/public/assets/chunks/shared-init-88cce66bb3cfe1e5.js +0 -5
  269. package/dist/dash/public/assets/chunks/task-actions-a9603d520434baab.js +0 -1
  270. package/dist/dash/public/assets/chunks/task-fa8b82e95e771c4a.js +0 -1
  271. package/dist/dash/public/assets/chunks/task-view-f7039cb330bcb0b5.js +0 -3
  272. package/dist/dash/public/assets/chunks/tasks-list-2a905b4a0c3a9042.js +0 -1
  273. package/dist/dash/public/assets/dash-agents-290a7b21c7dc0c92.css +0 -1
  274. package/dist/dash/public/assets/dash-agents-new-a7a07bf4ebda24c2.css +0 -1
  275. package/dist/dash/public/assets/dash-agents-param-slug-69a72fb0bbd14cc2.css +0 -1
  276. package/dist/dash/public/assets/dash-agents-param-slug-edit-397bdfb2f0ca328c.css +0 -1
  277. package/dist/dash/public/assets/dash-agents-param-slug-platforms-a7b3b7247c27f1d2.css +0 -1
  278. package/dist/dash/public/assets/dash-agents-param-slug-settings-8389b7d0555e8ccf.css +0 -1
  279. package/dist/dash/public/assets/dash-agents-param-slug-tasks-5987b8aea5e8f30d.css +0 -1
  280. package/dist/dash/public/assets/dash-agents-param-slug-usage-19abc69e1d4e6b0a.css +0 -1
  281. package/dist/dash/public/assets/dash-settings-param-tab-ac61fdfdd6fd533f.css +0 -1
  282. package/dist/dash/public/assets/dash-tasks-cc0b1d32874b731c.css +0 -1
  283. package/dist/dash/public/assets/dash-tasks-param-id-02b8c7bd99cc1090.css +0 -1
  284. package/dist/dash/public/assets/pnext-client-17ba55bb57a1f4da.js +0 -1
  285. package/dist/dash/public/assets/pnext-client-43f52a07f8067b1b.js +0 -1
  286. package/dist/dash/public/assets/pnext-client-4594b693fe612835.js +0 -1
  287. package/dist/dash/public/assets/pnext-client-73f73e24f8141fb6.js +0 -1
  288. package/dist/dash/public/assets/pnext-client-7574da4651b40eae.js +0 -1
  289. package/dist/dash/public/assets/pnext-client-7b3a2c1092cbbb02.js +0 -1
  290. package/dist/dash/public/assets/pnext-client-816fe5fc96d3f768.js +0 -1
  291. package/dist/dash/public/assets/pnext-client-86cb956b448b0887.js +0 -1
  292. package/dist/dash/public/assets/pnext-client-8b64e3c030164288.js +0 -1
  293. package/dist/dash/public/assets/pnext-client-8f6161084c595a22.js +0 -1
  294. package/dist/dash/public/assets/pnext-client-9203ec11926e5d04.js +0 -1
  295. package/dist/dash/public/assets/pnext-client-a38b446f941d44df.js +0 -1
  296. package/dist/dash/public/assets/pnext-client-bd8d51aaa095e8a4.js +0 -1
  297. package/dist/dash/public/assets/pnext-client-e9821d1f1bdb281d.js +0 -1
  298. package/dist/default-De8FXiWz.js +0 -1
  299. package/dist/dispatch-BKeAch9E.js +0 -14
  300. package/dist/exec-RZFLclKX.js +0 -11
  301. package/dist/executor-BvAA7Cgw.js +0 -10
  302. package/dist/http-Bkg_OQ6r.js +0 -1
  303. package/dist/integrations-BAgdVDhj.js +0 -5
  304. package/dist/integrations-D-L3uQRj.js +0 -1
  305. package/dist/log-view-dg0TlKLA.js +0 -1
  306. package/dist/models-_5LVGC3m.js +0 -1
  307. package/dist/queue-C9fSdE_X.js +0 -116
  308. package/dist/refresh-BDmap1RA.js +0 -1
  309. package/dist/rename-Bhcb4t9F.js +0 -1
  310. package/dist/result-D8DsvJDu.js +0 -15
  311. package/dist/run-Dqe38jX8.js +0 -2
  312. package/dist/runner-BPpiJvHx.js +0 -1
  313. package/dist/schema-CU2iFkp8.js +0 -1
  314. package/dist/serve-DA5I2qXj.js +0 -4
  315. package/dist/store-B3ZHoBJY.js +0 -8
  316. package/dist/store-BLi19UDE.js +0 -42
  317. package/dist/task-C6VAg5WU.js +0 -1
  318. package/dist/task-b2BK481M.js +0 -1
  319. package/dist/worker-CXndxmGF.js +0 -9
  320. package/dist/worker-DrucI22w.js +0 -1
@@ -0,0 +1,336 @@
1
+ import './filter.css';
2
+ import { Fragment, type ComponentChildren } from 'preact';
3
+ import { useEffect, useRef, useState } from 'preact/hooks';
4
+
5
+ import { FILTER_ROWS } from '@/utils/paged';
6
+ import { iLeft, iRight, iSearch, iX } from './icons';
7
+ import { Icon } from './icon';
8
+ import { Menu, MenuRadio } from './menu';
9
+ import type { Option } from './select';
10
+
11
+ const RECENT = 'coder:filters';
12
+
13
+ /** From this many options a facet's full list gets a find box. */
14
+ const FIND = 5;
15
+
16
+ /** One thing a list filters by; an empty value is its default and shows no chip. */
17
+ export interface Facet<K extends string = string> {
18
+ key: K;
19
+ label: string;
20
+ /** The picks shown before typing. */
21
+ options: Option[];
22
+ /** A fixed list, always in the menu with its default as a row; its chip is its pick alone. */
23
+ inline?: boolean;
24
+ /** Each pick's icon: an icon path or a ready element. */
25
+ icon?: (value: string) => string | ComponentChildren;
26
+ /** Finds picks on the server once something is typed, at most `limit`. */
27
+ search?: (q: string, limit: number) => Promise<Option[]>;
28
+ }
29
+
30
+ /** How many of a facet's picks the menu lists before "More". */
31
+ const SHOWN = 5;
32
+
33
+ /** The picks the menu lists for a facet: the first few, keeping the current pick in view. */
34
+ export function inlineRows(picks: Option[], value: string) {
35
+ if (picks.length <= SHOWN) return picks;
36
+ const shown = picks.slice(0, SHOWN);
37
+ const current = picks.find(([key]) => key === value);
38
+
39
+ return current && !shown.includes(current) ? [...shown.slice(0, SHOWN - 1), current] : shown;
40
+ }
41
+
42
+ /** Whether a facet's own list needs a find box. */
43
+ const findable = (facet: Facet) => facet.options.filter(([value]) => value).length >= FIND;
44
+
45
+ /** What a facet's value reads as; "Any" for its default. */
46
+ export function valueLabel<K extends string>(
47
+ facet: Facet<K>,
48
+ value: string,
49
+ seen: Record<string, string> = {},
50
+ ) {
51
+ if (!value) return 'Any';
52
+
53
+ return (
54
+ facet.options.find(([key]) => key === value)?.[1] ?? seen[`${facet.key}:${value}`] ?? value
55
+ );
56
+ }
57
+
58
+ /** The filters that are on, one chip each in facet order. */
59
+ export function filterChips<K extends string>(
60
+ facets: Facet<K>[],
61
+ values: Record<K, string>,
62
+ seen: Record<string, string> = {},
63
+ ) {
64
+ return facets
65
+ .filter(facet => values[facet.key])
66
+ .map(facet => {
67
+ const label = valueLabel(facet, values[facet.key], seen);
68
+
69
+ return { key: facet.key, text: facet.inline ? label : `${facet.label}: ${label}` };
70
+ });
71
+ }
72
+
73
+ /** A facet list's rows: recent picks that match first, then the rest, at most FILTER_ROWS. */
74
+ export function listRows(rows: Option[], recent: Option[], q: string) {
75
+ const needle = q.trim().toLowerCase();
76
+ const first = recent.filter(([, label]) => label.toLowerCase().includes(needle));
77
+ const all = [...first, ...rows.filter(([value]) => !first.some(([kept]) => kept === value))];
78
+
79
+ return { shown: all.slice(0, FILTER_ROWS), more: all.length > FILTER_ROWS };
80
+ }
81
+
82
+ function readRecent(): Record<string, Option[]> {
83
+ try {
84
+ return JSON.parse(localStorage.getItem(RECENT) ?? '{}') ?? {};
85
+ } catch {
86
+ return {};
87
+ }
88
+ }
89
+
90
+ function keepRecent(list: string, pick: Option) {
91
+ const all = readRecent();
92
+ all[list] = [pick, ...(all[list] ?? []).filter(([value]) => value !== pick[0])].slice(0, 5);
93
+ localStorage.setItem(RECENT, JSON.stringify(all));
94
+ }
95
+
96
+ /** One Filter button over every facet, and a removable chip for each filter that is on; `name` keeps each list's recent picks apart. */
97
+ export function Filter<K extends string>({
98
+ name,
99
+ facets,
100
+ values,
101
+ onChange,
102
+ }: {
103
+ name: string;
104
+ facets: Facet<K>[];
105
+ values: Record<K, string>;
106
+ onChange: (key: K, value: string) => void;
107
+ }) {
108
+ // Labels of picks the options lack, so a chip names an agent found by search.
109
+ const [seen, setSeen] = useState<Record<string, string>>({});
110
+ const remember = (key: K, rows: Option[]) =>
111
+ setSeen(current => ({
112
+ ...current,
113
+ ...Object.fromEntries(rows.map(([value, label]) => [`${key}:${value}`, label])),
114
+ }));
115
+ useEffect(() => {
116
+ const recent = readRecent();
117
+ for (const facet of facets) remember(facet.key, recent[`${name}:${facet.key}`] ?? []);
118
+ }, []);
119
+ const chips = filterChips(facets, values, seen);
120
+
121
+ return (
122
+ <>
123
+ <Menu
124
+ class="filter-more"
125
+ summaryClass={`field-btn${chips.length ? ' on' : ''}`}
126
+ summary={chips.length ? `Filter · ${chips.length}` : 'Filter'}
127
+ >
128
+ <FilterPanel
129
+ name={name}
130
+ facets={facets}
131
+ values={values}
132
+ seen={seen}
133
+ onFound={remember}
134
+ onPick={(facet, [value, label]) => {
135
+ if (!facet.inline && value !== values[facet.key]) {
136
+ keepRecent(`${name}:${facet.key}`, [value, label]);
137
+ remember(facet.key, [[value, label]]);
138
+ }
139
+ onChange(facet.key, facet.inline || value !== values[facet.key] ? value : '');
140
+ }}
141
+ />
142
+ </Menu>
143
+ <span class="filter-chips">
144
+ {chips.map(chip => (
145
+ <button
146
+ key={chip.key}
147
+ type="button"
148
+ class="chip"
149
+ title={chip.text}
150
+ aria-label={`Clear ${chip.text}`}
151
+ onClick={() => onChange(chip.key, '')}
152
+ >
153
+ <span class="grow">{chip.text}</span>
154
+ <Icon d={iX} />
155
+ </button>
156
+ ))}
157
+ </span>
158
+ </>
159
+ );
160
+ }
161
+
162
+ /** The menu's facets; a long facet opens its own list in place, and Escape steps back out of it. */
163
+ function FilterPanel<K extends string>({
164
+ name,
165
+ facets,
166
+ values,
167
+ seen,
168
+ onFound,
169
+ onPick,
170
+ }: {
171
+ name: string;
172
+ facets: Facet<K>[];
173
+ values: Record<K, string>;
174
+ seen: Record<string, string>;
175
+ onFound: (key: K, rows: Option[]) => void;
176
+ onPick: (facet: Facet<K>, pick: Option) => void;
177
+ }) {
178
+ const root = useRef<HTMLDivElement>(null);
179
+ const [open, setOpen] = useState<Facet<K>>();
180
+ const [q, setQ] = useState('');
181
+ const [found, setFound] = useState<Option[]>();
182
+ const asked = useRef(0);
183
+ const from = useRef<K>();
184
+ const typed = q.trim();
185
+
186
+ const focus = (selector: string) => root.current?.querySelector<HTMLElement>(selector)?.focus();
187
+ const show = (facet?: Facet<K>) => {
188
+ if (facet) from.current = facet.key;
189
+ setOpen(facet);
190
+ setQ('');
191
+ setFound(undefined);
192
+ };
193
+
194
+ useEffect(() => {
195
+ const pop = root.current!.closest<HTMLElement>('[popover]')!;
196
+ const toggle = (event: Event) => {
197
+ if ((event as ToggleEvent).newState === 'open') focus('.pop-item');
198
+ else show();
199
+ };
200
+ pop.addEventListener('toggle', toggle);
201
+ return () => pop.removeEventListener('toggle', toggle);
202
+ }, []);
203
+
204
+ useEffect(() => {
205
+ if (!root.current?.closest(':popover-open')) return;
206
+ focus(open ? 'input' : `[data-facet="${from.current}"]`);
207
+ }, [open]);
208
+
209
+ useEffect(() => {
210
+ if (!open?.search || !typed) return;
211
+ const ask = ++asked.current;
212
+ const timer = setTimeout(
213
+ () =>
214
+ void open.search!(typed, FILTER_ROWS + 1).then(
215
+ rows => {
216
+ if (asked.current !== ask) return;
217
+ setFound(rows);
218
+ onFound(open.key, rows);
219
+ },
220
+ () => asked.current === ask && setFound([]),
221
+ ),
222
+ 200,
223
+ );
224
+ return () => clearTimeout(timer);
225
+ }, [open, typed]);
226
+
227
+ const rows = open
228
+ ? open.search && typed
229
+ ? (found ?? [])
230
+ : open.options.filter(
231
+ ([value, label]) => value && label.toLowerCase().includes(typed.toLowerCase()),
232
+ )
233
+ : [];
234
+ const list = open
235
+ ? listRows(rows, readRecent()[`${name}:${open.key}`] ?? [], typed)
236
+ : { shown: [], more: false };
237
+ const searching = Boolean(open?.search && typed && !found);
238
+
239
+ const onKeyDown = (event: KeyboardEvent) => {
240
+ const items = [...root.current!.querySelectorAll<HTMLElement>('input, .pop-item')];
241
+ const at = items.indexOf(document.activeElement as HTMLElement);
242
+ const target = event.target as HTMLElement;
243
+ const key = event.key;
244
+ if (key === 'ArrowDown') items[(at + 1) % items.length]?.focus();
245
+ else if (key === 'ArrowUp') items[(at - 1 + items.length) % items.length]?.focus();
246
+ else if (key === 'ArrowRight' && target.dataset.facet) target.click();
247
+ else if (key === 'ArrowLeft' && open && target.tagName !== 'INPUT') show();
248
+ else if (key === 'Enter' && target.tagName === 'INPUT') focus('[role=menuitemradio]');
249
+ else if (key === 'Escape' && open) {
250
+ event.stopPropagation();
251
+ show();
252
+ } else return;
253
+ event.preventDefault();
254
+ };
255
+
256
+ return (
257
+ <div ref={root} class="filter-panel" onKeyDown={onKeyDown}>
258
+ {open ? (
259
+ <>
260
+ <button type="button" class="pop-item" data-keep onClick={() => show()}>
261
+ <Icon d={iLeft} />
262
+ <span class="grow">{open.label}</span>
263
+ </button>
264
+ {findable(open) ? (
265
+ <label class="search">
266
+ <Icon d={iSearch} />
267
+ <input
268
+ type="search"
269
+ value={q}
270
+ placeholder={`Find ${open.label.toLowerCase()}`}
271
+ aria-label={`Find ${open.label.toLowerCase()}`}
272
+ autocomplete="off"
273
+ onInput={event => setQ(event.currentTarget.value)}
274
+ />
275
+ </label>
276
+ ) : null}
277
+ <div role="group" aria-label={open.label} aria-busy={searching}>
278
+ {list.shown.map(([value, label]) => (
279
+ <MenuRadio
280
+ key={value}
281
+ icon={open.icon?.(value)}
282
+ on={values[open.key] === value}
283
+ onPick={() => onPick(open, [value, label])}
284
+ >
285
+ {label}
286
+ </MenuRadio>
287
+ ))}
288
+ </div>
289
+ {list.more ? (
290
+ <p class="pop-note">Type to find more.</p>
291
+ ) : !list.shown.length && !searching ? (
292
+ <p class="pop-note">Nothing matches.</p>
293
+ ) : null}
294
+ </>
295
+ ) : (
296
+ facets.map(facet => {
297
+ const picks = facet.options.filter(([value]) => facet.inline || value);
298
+ if (!picks.length) return null;
299
+ const shown = inlineRows(picks, values[facet.key]);
300
+
301
+ return (
302
+ <Fragment key={facet.key}>
303
+ <p class="pop-label">{facet.label}</p>
304
+ <div role="group" aria-label={facet.label}>
305
+ {shown.map(([value, label]) => (
306
+ <MenuRadio
307
+ key={value}
308
+ icon={facet.icon?.(value)}
309
+ on={values[facet.key] === value}
310
+ onPick={() => onPick(facet, [value, label])}
311
+ >
312
+ {label}
313
+ </MenuRadio>
314
+ ))}
315
+ </div>
316
+ {picks.length > shown.length ? (
317
+ <button
318
+ type="button"
319
+ class="pop-item"
320
+ data-keep
321
+ data-facet={facet.key}
322
+ aria-haspopup="true"
323
+ onClick={() => show(facet)}
324
+ >
325
+ <span class="grow">More</span>
326
+ <span class="muted">{picks.length - shown.length}</span>
327
+ <Icon d={iRight} />
328
+ </button>
329
+ ) : null}
330
+ </Fragment>
331
+ );
332
+ })
333
+ )}
334
+ </div>
335
+ );
336
+ }
@@ -38,6 +38,8 @@ export const iSearch = 'M4 11a7 7 0 1 0 14 0a7 7 0 1 0 -14 0M20 20l-3.5-3.5';
38
38
  export const iAlert =
39
39
  'm21.7 18-8-14a2 2 0 0 0-3.4 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.7-3M12 9v4M12 17h.01';
40
40
  export const iTerminal = 'm4 17 6-6-6-6M12 19h8';
41
+ export const iFolder =
42
+ 'M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.7-.9l-.8-1.2A2 2 0 0 0 7.9 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z';
41
43
  export const iClock = 'M12 7v5l3 2M3 12a9 9 0 1 0 18 0a9 9 0 1 0 -18 0';
42
44
  export const iPlug = 'M9 2v6M15 2v6M6 8h12v4a6 6 0 0 1-12 0ZM12 18v4';
43
45
  export const iCopy = 'M9 9h11v11H9ZM5 15H4V4h11v1';
@@ -135,10 +135,13 @@ export function MoreList({ label, children }: { label: string; children: Compone
135
135
  export function MenuRadio({
136
136
  on,
137
137
  onPick,
138
+ icon,
138
139
  children,
139
140
  }: {
140
141
  on: boolean;
141
142
  onPick: () => void;
143
+ /** An icon path or a ready element. */
144
+ icon?: string | ComponentChildren;
142
145
  children: ComponentChildren;
143
146
  }) {
144
147
  return (
@@ -149,6 +152,7 @@ export function MenuRadio({
149
152
  class={on ? 'pop-item on' : 'pop-item'}
150
153
  onClick={onPick}
151
154
  >
155
+ {typeof icon === 'string' ? <Icon d={icon} /> : icon}
152
156
  <span class="grow">{children}</span>
153
157
  {on ? <Icon d={iCheck} /> : null}
154
158
  </button>
@@ -135,8 +135,8 @@ export function Select({
135
135
  setPlace(
136
136
  `left:${Math.round(Math.min(box.left, innerWidth - menu.offsetWidth - 8))}px;min-width:${Math.round(box.width)}px;` +
137
137
  (up
138
- ? `bottom:${Math.round(innerHeight - box.top + 4)}px;max-height:${Math.round(Math.min(480, box.top - 12))}px`
139
- : `top:${Math.round(box.bottom + 4)}px;max-height:${Math.round(Math.min(480, below))}px`),
138
+ ? `bottom:${Math.round(innerHeight - box.top + 4)}px;max-height:${Math.round(Math.min(560, box.top - 12))}px`
139
+ : `top:${Math.round(box.bottom + 4)}px;max-height:${Math.round(Math.min(560, below))}px`),
140
140
  );
141
141
  };
142
142
  position();
@@ -24,6 +24,20 @@
24
24
  grid-row: 1;
25
25
  grid-column: 3;
26
26
  }
27
+ .page {
28
+ container-type: inline-size;
29
+ }
30
+ /* with a primary action, the filters drop under the title before they would wrap */
31
+ @container (max-width: 720px) {
32
+ .head.tools:has(> .actions) > .filters {
33
+ grid-row: auto;
34
+ grid-column: 1 / -1;
35
+ justify-content: flex-start;
36
+ }
37
+ .head.tools:has(> .actions) .search {
38
+ max-width: none;
39
+ }
40
+ }
27
41
 
28
42
  /* lists: filters above, rows load on scroll */
29
43
  .filters {
@@ -17,3 +17,24 @@ export async function signOut(): Promise<void> {
17
17
  const { url } = await client.signOut();
18
18
  location.href = url ?? '/?signed_out=1';
19
19
  }
20
+
21
+ /** Runs `work` every `ms` once the last run settles, skipping while the tab is hidden; returns its stop. */
22
+ export function poll(work: () => Promise<unknown>, ms: number): () => void {
23
+ let timer: ReturnType<typeof setTimeout>;
24
+ let stopped = false;
25
+ const next = () => {
26
+ if (!stopped) timer = setTimeout(run, ms);
27
+ };
28
+ const run = () => {
29
+ if (document.visibilityState === 'hidden') return next();
30
+ void work()
31
+ .catch(() => {})
32
+ .finally(next);
33
+ };
34
+ next();
35
+
36
+ return () => {
37
+ stopped = true;
38
+ clearTimeout(timer);
39
+ };
40
+ }
@@ -19,17 +19,25 @@ const parts = (value: number, tz: string, options: Intl.DateTimeFormatOptions) =
19
19
  );
20
20
 
21
21
  // Built from parts, so every ICU version, on the server or in the browser, prints the same text.
22
- export function formatDate(value: number | undefined, tz: string) {
22
+ /** `short` prints only the time today and leaves out this year. */
23
+ export function formatDate(value: number | undefined, tz: string, short?: boolean) {
23
24
  if (!value) return 'Not available';
24
- const p = parts(value, tz, {
25
+ const options: Intl.DateTimeFormatOptions = {
25
26
  month: 'short',
26
27
  day: 'numeric',
27
28
  year: 'numeric',
28
29
  hour: 'numeric',
29
30
  minute: '2-digit',
30
31
  hour12: true,
31
- });
32
- return `${p.month} ${p.day}, ${p.year}, ${p.hour}:${p.minute} ${p.dayPeriod}`;
32
+ };
33
+ const p = parts(value, tz, options);
34
+ const time = `${p.hour}:${p.minute} ${p.dayPeriod}`;
35
+ if (!short) return `${p.month} ${p.day}, ${p.year}, ${time}`;
36
+
37
+ const now = parts(Date.now(), tz, options);
38
+ if (p.year !== now.year) return `${p.month} ${p.day}, ${p.year}, ${time}`;
39
+
40
+ return p.month === now.month && p.day === now.day ? time : `${p.month} ${p.day}, ${time}`;
33
41
  }
34
42
 
35
43
  /** The time of day as `formatDate` prints it, with seconds. */
@@ -61,13 +61,15 @@ export function usePaged<T>({
61
61
  const sentinel = useRef<HTMLElement>(null);
62
62
  const live = useRef(state);
63
63
  live.current = state;
64
- const loading = useRef<string | undefined>(undefined);
64
+ // The load in flight; each is its own object, so an answer to an older load for the same page never passes.
65
+ const loading = useRef<{ key: string } | undefined>(undefined);
65
66
  const failed = useRef<(() => void) | undefined>(undefined);
66
67
 
67
68
  const load = (cursor: string, forQuery: string, append: boolean) => {
68
69
  const key = `${forQuery}|${cursor}`;
69
- if (loading.current === key) return;
70
- loading.current = key;
70
+ if (loading.current?.key === key) return;
71
+ const request = { key };
72
+ loading.current = request;
71
73
  setError('');
72
74
  setBusy(true);
73
75
  const since = performance.now();
@@ -77,7 +79,7 @@ export function usePaged<T>({
77
79
  void fetchPage(cursor)
78
80
  .then(held(since))
79
81
  .then(page => {
80
- if (loading.current !== key) return;
82
+ if (loading.current !== request) return;
81
83
  if (!append) firstPages.current.set(forQuery, { page, at: Date.now() });
82
84
  setError('');
83
85
  failed.current = undefined;
@@ -95,12 +97,12 @@ export function usePaged<T>({
95
97
  });
96
98
  })
97
99
  .catch(reason => {
98
- if (loading.current !== key) return;
100
+ if (loading.current !== request) return;
99
101
  failed.current = () => load(cursor, forQuery, append);
100
102
  setError(reason instanceof Error ? reason.message : String(reason));
101
103
  })
102
104
  .finally(() => {
103
- if (loading.current !== key) return;
105
+ if (loading.current !== request) return;
104
106
  loading.current = undefined;
105
107
  setBusy(false);
106
108
  });
@@ -118,6 +120,9 @@ export function usePaged<T>({
118
120
  useEffect(() => {
119
121
  if (seen.current === first) return;
120
122
  seen.current = first;
123
+ // A page still loading belongs to the rows this replaces.
124
+ loading.current = undefined;
125
+ setBusy(false);
121
126
  firstPages.current.set(initial, { page: first, at: Date.now() });
122
127
  setState(fromPage(initial, first));
123
128
  }, [first]);
@@ -182,3 +187,6 @@ export function readQuery(keys: string[]): Record<string, string> {
182
187
 
183
188
  /** Rows a list loads per page; more load as it scrolls. */
184
189
  export const LIST_PAGE = 20;
190
+
191
+ /** Rows a filter's list shows; typing finds the rest. */
192
+ export const FILTER_ROWS = 20;
@@ -1,20 +0,0 @@
1
- import{t as e}from"./rolldown-runtime-DT7IzrpZ.js";import{Bt as t,Cn as n,Et as r,Gt as i,Lt as a,M as o,Mt as s,N as c,O as l,P as u,Qt as d,Rt as f,Tt as p,Wt as m,an as h,cn as g,d as ee,ft as _,j as v,jt as y,k as b,ln as x,mt as S,nn as C,nt as te,sn as w,tn as T,tt as E,un as D,vn as O,wt as k,x as A,xt as ne,z as j,zt as M}from"./dispatch-BKeAch9E.js";import{t as re}from"./chat-bridge-BS9WtP3X.js";import N from"node:path";import P from"node:process";import F from"node:fs";import{spawn as I}from"node:child_process";import L from"node:os";function R(){let e=process.env.CLAUDE_CONFIG_DIR||N.join(L.homedir(),`.claude`);return N.join(e,`projects`)}function z(e){if(!e)return!1;let t=R(),n=!1;try{for(let r of F.readdirSync(t)){let i=N.join(t,r,`${e}.jsonl`);F.existsSync(i)&&(F.rmSync(i,{force:!0}),n=!0)}}catch{}return n}var B=e({archiveFlagged:()=>ie,askTask:()=>q,claudeAskOptions:()=>K,collectPending:()=>J,collectTasks:()=>Y,deleteTask:()=>$,sidecarPrompt:()=>G,spawnArchiveSweep:()=>Q,steerTask:()=>H,stopTask:()=>Z,streamTask:()=>X});async function V(e,t,n,r,i={}){if(t.status!==`running`)return null;let a=t.engine===`claude`?await(i.claude??b)(t.steerEndpoint,n,void 0,r):await(i.codex??c)(e,{endpoint:t.steerEndpoint,threadId:t.threadId,turnId:t.turnId,text:n,command:r});if(a.steered)return p(e,t.id,{kind:`steer`,message:`Steer accepted live:\n${n}`}),{taskId:t.id,steered:`live`};if(!a.retryable)throw p(e,t.id,{kind:`error`,message:`Live steer failed: ${a.detail}`}),Error(`Could not steer running task ${t.id}: ${a.detail}`);let o=M(e,t.id)??t;return g.includes(o.status)?(y(e,o.id,n),p(e,o.id,{kind:`steer`,message:`Steer queued for the next turn:\n${n}`}),{taskId:o.id,steered:`queued`}):null}async function H(e,t,n,r={},i={}){if(!t.threadId)throw new ne(`invalid-option`,`Task ${t.id} has no thread to steer yet (status: ${t.status}).`,{hint:`Wait for it to start: coder task watch ${t.id}`});let a=await V(e,t,n,r.command,i);if(a){let n=M(e,t.id)??t;return n.archived&&h(e,n),a}return U(e,t,n,r),{taskId:t.id,steered:`resumed`}}function U(e,t,n,r){t.archived&&h(e,t),w(e,t.id,{status:`queued`,resumedAt:new Date().toISOString(),currentPrompt:n,...r.outputSchema?{outputSchema:r.outputSchema}:{},resumeThreadId:t.threadId,steerEndpoint:null,model:r.model??t.model??null,effort:r.effort??t.effort??null,permissions:r.permissions??t.permissions,error:void 0}),p(e,t.id,{kind:`steer`,message:`Resuming with steer:\n${n}`}),ee(t.cwd??e,t.id)}const W=[`Read`,`Glob`,`Grep`];function G(e,t,n){return`You are a read-only sidecar answering a question ABOUT a coder task.
2
- You are not the task. Never continue, redo, or fix its work. Only answer the question. The task never sees this question or your answer.
3
-
4
- Task metadata:
5
- ${[`id: ${e.id}`,...e.name?[`name: ${e.name}`]:[],`status: ${e.status}`,`engine: ${e.engine}${e.model?`/${e.model}`:``}${e.effort?`/${e.effort}`:``}`,...e.cwd?[`workspace: ${e.cwd}`]:[],...e.createdAt?[`created: ${e.createdAt}`]:[],...e.completedAt?[`finished: ${e.completedAt}`]:[]].join(`
6
- `)}
7
-
8
- Task prompt:
9
- ${e.prompt??`(unknown)`}
10
-
11
- Inspect as needed (grep/read selectively; events can be large):
12
- - progress log (jsonl, one event per line): ${N.join(t,`log.jsonl`)}
13
- - final result: ${N.join(t,`result.json`)}
14
- - worker output: ${N.join(t,`worker.log`)}
15
- ${e.cwd?`- the task's workspace (its code and changes): ${e.cwd}`:``}
16
-
17
- Question: ${n}
18
-
19
- Answer the question directly and concisely.`}function K(e,t,n,r){return{prompt:n,model:r.model??e.model,effort:r.effort,permissions:`read-only`,additionalDirectories:[t],taskRoot:t,readOnlyAllowedTools:W}}async function q(e,t,n,r={}){let i=d(e,t.id),a=G(t,i,n)+(r.command?`\n\nCoder command ${j(r.command)}`:``),s=r.command?e=>{let t=N.join(i,`inbox-control`);F.mkdirSync(t,{recursive:!0}),F.appendFileSync(N.join(t,`${j(r.command)}.transcript.jsonl`),JSON.stringify({command:r.command,result:e.finalMessage??e.error?.message??``})+`
20
- `)}:void 0,c=r.effort??t.effort??null;if(t.engine===`claude`)return l(t.cwd??e,{...K(t,i,a,{model:r.model,effort:c}),command:r.command,onResult:s});let u=te(e),f=r.model??t.model,p=f?u.models?.[f]:void 0,m=p&&E(p)?p:void 0;if(m?.envKey&&!P.env[m.envKey])throw Error(`Missing environment variable: \`${m.envKey}\`.`);let h=m?await re(m,m.wireApi??`chat`):null,g=S(u,f,h??void 0);try{return await o(t.cwd??e,{prompt:a,model:g?.model??_(f??null),modelProvider:g?.modelProvider??null,configOverrides:g?.configOverrides??null,effort:c,sandbox:`read-only`,approvalPolicy:`never`,ephemeral:!0,onResult:s})}finally{await h?.close()}}function J(e){return f(e).filter(e=>g.includes(e.status)).flatMap(t=>A(d(e,t.id)).filter(e=>!e.response).map(e=>({taskId:t.id,id:e.id,summary:String(e.summary??``),createdAt:e.createdAt?String(e.createdAt):void 0})))}function Y(e,n={}){let r=n.limit===`all`?void 0:n.limit,i=e=>x.includes(e.status),o=[],s=f(e).filter(n=>{if(!i(n))return!0;let r=n.completedAt??n.updatedAt??n.createdAt;return k(r)<=6e5||(t(e,n),o.push(n.id),!1)});if(Q(e,o),n.archived?s=a(e):n.running?s=s.filter(e=>g.includes(e.status)):n.stopped&&(s=s.filter(i)),n.dir){let e=T(N.resolve(String(n.dir))),t=new Map;s=s.filter(n=>n.cwd?(t.has(n.cwd)||t.set(n.cwd,T(n.cwd)),t.get(n.cwd)===e):!1)}if(!n.archived&&!n.running&&!n.stopped){let e=e=>e.status===`failed`?0:g.includes(e.status)?1:e.status===`completed`?3:2;s=[...s].sort((t,n)=>e(t)-e(n))}let c=r===void 0?0:Math.max(0,s.length-r);return r!==void 0&&(s=s.slice(0,r)),{tasks:s,clipped:c}}async function*X(e,t,r={}){let i=new Set([`completed`,`failed`,`cancelled`]),a=M(e,t);if(!a)throw Error(`No task found for "${t}".`);let o=r.tail??1,s=n(N.join(d(e,t),`log.jsonl`)),c=!0,l=()=>{let e=s().map(e=>{try{return JSON.parse(e)}catch{return{message:e}}});return c?(c=!1,o===`all`?e:C(e,o)):e};for(yield*l();!i.has(a.status);)await new Promise(e=>setTimeout(e,400)),a=m(e,M(e,t)??a),yield*l();yield*l()}async function Z(e,t,n={}){let r=t.engine===`claude`?{detail:`claude worker terminated`}:await(n.interrupt??v)(e,{endpoint:t.steerEndpoint,threadId:t.threadId,turnId:t.turnId});if(t.engine!==`claude`&&u(t.steerEndpoint),t.pid&&t.status===`running`)try{P.kill(t.pid,`SIGTERM`)}catch{}return w(e,t.id,{status:`cancelled`,steerEndpoint:null,completedAt:new Date().toISOString()}),{taskId:t.id,status:`cancelled`,interrupt:r.detail}}function Q(e,t,n={}){if(t.length)try{I(P.execPath,[O,`task`,`archive-sweep`,`--cwd`,e,...n.flows?[`--flows`]:[],...t],{detached:!0,stdio:`ignore`}).unref()}catch{}}function $(e,t){return t.threadId&&(t.engine===`claude`?z(t.threadId):D(e,t.threadId)),i(e,t.id)}function ie(e,t){for(let n of t){let t=s(e,n);t&&x.includes(t.status)&&r(e,t)}}export{$ as a,Z as c,Y as i,X as l,q as n,Q as o,J as r,H as s,B as t};
@@ -1 +0,0 @@
1
- import{i as e}from"./cli-DWCR7iqa.js";import{n as t,s as n}from"./args-BOEEdpWk.js";const r=e({name:`task archive-sweep`,options:{cwd:n,flows:t},args:1/0,run:async({options:e,args:t,cwd:n})=>{let{archiveFlagged:r}=await import(`./actions-Mk3FSlpJ.js`).then(e=>e.t),{archiveFlaggedRuns:i}=await import(`./executor-BvAA7Cgw.js`).then(e=>e.y);return e.flows?i(t):r(n,t)}});export{r as commandArchiveSweep};
@@ -1 +0,0 @@
1
- import{s as e}from"./cli-DWCR7iqa.js";const t=e(`auth`,{login:async()=>(await import(`./login-CNmeRAL7.js`)).commandLogin,logout:async()=>(await import(`./logout-j0dTo_Ib.js`)).commandLogout,status:async()=>(await import(`./status-BU3DR1XU.js`)).commandStatus},{menu:[{usage:`login`,blurb:`sign in through the browser`},{usage:`logout`,blurb:`sign out and forget the saved session`},{usage:`status`,blurb:`show where you are signed in`}],description:[`Sign in to Coder and manage saved server sessions.`],exampleCommand:`auth login`});export{t as commandAuth};
@@ -1 +0,0 @@
1
- import{i as e,l as t}from"./http-Bkg_OQ6r.js";import{Ft as n,dn as r,un as i}from"./store-B3ZHoBJY.js";import{c as a}from"./schema-CU2iFkp8.js";import{a as o,i as s,o as c}from"./serve-DA5I2qXj.js";import{createECDH as l,hkdfSync as u}from"node:crypto";import*as d from"openid-client";import{and as f,eq as p}from"drizzle-orm";import{EncryptJWT as m,calculateJwkThumbprint as h,createRemoteJWKSet as g,jwtDecrypt as _,jwtVerify as v}from"jose";const y=(e,t)=>new Uint8Array(u(`sha256`,e,``,t,32));async function b(e){let t=y(e,`coder oidc client key`),n=l(`prime256v1`);n.setPrivateKey(t);let r=n.getPublicKey(),i={kty:`EC`,crv:`P-256`,x:Buffer.from(r.subarray(1,33)).toString(`base64url`),y:Buffer.from(r.subarray(33)).toString(`base64url`)},a=await crypto.subtle.importKey(`jwk`,{...i,d:Buffer.from(t).toString(`base64url`)},{name:`ECDSA`,namedCurve:`P-256`},!1,[`sign`]),o=await h(i);return{key:a,kid:o,jwk:{...i,kid:o,alg:`ES256`,use:`sig`}}}async function x(e){let t=[e.encryptionKey,e.previousEncryptionKey].filter(e=>!!e),n=await Promise.all(t.map(b));return{cookie:t.map(e=>y(e,`coder session cookie`)),client:n[0],jwks:{keys:n.map(e=>e.jwk)}}}const S=`${i}.session`,C=`${i}.oidc`,w=3800,T=2592e3,E=()=>Math.floor(Date.now()/1e3);function D(e){let t=new Map;for(let n of(e.get(`cookie`)??``).split(/;\s*/)){let e=n.indexOf(`=`);e>0&&t.set(n.slice(0,e),n.slice(e+1))}return t}function O(e){let t=[];for(;e.has(`${S}.${t.length}`);)t.push(`${S}.${t.length}`);return t}function k(e){let t=D(e);return t.get(S)??(O(t).map(e=>t.get(e)).join(``)||void 0)}function A(e){return Array.isArray(e)?e.flatMap(e=>typeof e?.id==`string`&&typeof e.role==`string`?[{id:e.id,slug:String(e.slug??e.id),name:String(e.name??e.slug??e.id),role:e.role}]:[]):[]}function j(e,t,n){let r=e.get(`x-coder-organization`),i=r?t.organizations.find(e=>e.slug===r||e.id===r):t.organizations.find(e=>e.id===n)??t.organizations[0];return i?{...t,organizationId:i.id,role:i.role}:r?{...t,organizationDenied:!0}:t}async function M(i,l){let u=l.auth.wular.url,h=l.publicUrl,y=new URL(h).origin,b=h.startsWith(`https:`),M=await x(l),N=`${h}${s}`,P=(e,t,n)=>`${e}=${t}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${n}${b?`; Secure`:``}`,F=(e,t)=>new m(e).setProtectedHeader({alg:`dir`,enc:`A256GCM`}).setIssuedAt().setExpirationTime(`${t}s`).encrypt(M.cookie[0]);async function I(e){if(e)for(let t of M.cookie)try{return(await _(e,t)).payload}catch{}}async function L(e,t){let n=await F(t,T),r=O(D(e));if(n.length<=w)return[P(S,n,T),...r.map(e=>P(e,``,0))];let i=n.match(RegExp(`.{1,${w}}`,`g`));return[P(S,``,0),...i.map((e,t)=>P(`${S}.${t}`,e,T)),...r.slice(i.length).map(e=>P(e,``,0))]}let R=e=>[S,...O(D(e))].map(e=>P(e,``,0)),z,B=()=>z??=d.discovery(new URL(u),`${h}${c}`,void 0,d.PrivateKeyJwt(M.client),new URL(u).protocol===`http:`?{execute:[d.allowInsecureRequests]}:void 0).catch(e=>{throw z=void 0,e}),V,H=async()=>V??=g(new URL((await B()).serverMetadata().jwks_uri));function U(e,t){let n=e.claims();if(!n)throw Error(`Wular Auth returned no ID token`);let r=A(n.organizations);return{sub:n.sub,name:typeof n.name==`string`?n.name:``,email:typeof n.email==`string`?n.email:``,orgs:r,org:r.some(e=>e.id===t?.org)?t.org:r[0]?.id,exp_at:E()+(e.expires_in??600),at:E(),rt:e.refresh_token??t?.rt,idt:e.id_token??t?.idt}}let W=new Map;function G(e){let t=e.rt;if(!t)return Promise.resolve(void 0);let n=W.get(t);return n||(n=B().then(e=>d.refreshTokenGrant(e,t)).then(t=>U(t,e)).catch(()=>{W.delete(t)}),W.set(t,n),setTimeout(()=>W.delete(t),6e4).unref?.()),n}async function K(e,t,n){let r=(await H().then(t=>v(e,t,{issuer:u,audience:y,typ:`at+jwt`})).catch(()=>void 0))?.payload;if(!r?.sub)return;let i={user:{id:r.sub,name:``,email:``},organizations:A(r.organizations)};return n&&E()-(r.iat??0)>60?{...i,stale:!0}:j(t,i)}async function q(e){let t=await B().catch(()=>void 0);if(!t)return Response.redirect(`${h}/login?error=unavailable`,302);let n={verifier:d.randomPKCECodeVerifier(),state:d.randomState(),nonce:d.randomNonce(),return:r(e.searchParams.get(`return`),y)},i=d.buildAuthorizationUrl(t,{redirect_uri:N,scope:o,code_challenge:await d.calculatePKCECodeChallenge(n.verifier),code_challenge_method:`S256`,state:n.state,nonce:n.nonce});return new Response(null,{status:302,headers:{location:i.href,"set-cookie":P(C,await F(n,600),600)}})}async function J(e,t){let n=e=>{let t=new Headers({location:`/login?error=${encodeURIComponent(e)}`});return t.append(`set-cookie`,P(C,``,0)),new Response(null,{status:302,headers:t})},r=await I(D(e.headers).get(C));if(!r)return n(`expired`);let i=t.searchParams.get(`error`);if(i)return n(i);let a;try{a=U(await d.authorizationCodeGrant(await B(),new URL(`${N}${t.search}`),{pkceCodeVerifier:r.verifier,expectedState:r.state,expectedNonce:r.nonce,idTokenExpected:!0}))}catch{return n(`sign_in_failed`)}let o=new Headers({location:r.return});o.append(`set-cookie`,P(C,``,0));for(let t of await L(e.headers,a))o.append(`set-cookie`,t);return new Response(null,{status:302,headers:o})}async function Y(t){if(!n(t,h))return e();let r=await I(k(t.headers)),i=await B().catch(()=>void 0),a=`${h}/?signed_out=1`,o=i?.serverMetadata().end_session_endpoint&&r?.idt?d.buildEndSessionUrl(i,{id_token_hint:r.idt,post_logout_redirect_uri:a}).href:a,s=Response.json({url:o});for(let e of R(t.headers))s.headers.append(`set-cookie`,e);return s}return{issuer:u,jwks:M.jwks,handler(e){let n=new URL(e.url);return n.pathname===`/api/auth/sign-in`&&e.method===`GET`?q(n):n.pathname===`/api/auth/callback`&&e.method===`GET`?J(e,n):n.pathname===`/api/auth/sign-out`&&e.method===`POST`?Y(e):Promise.resolve(t())},async session(e,t=!1){let n=e.get(`authorization`);if(n?.startsWith(`Bearer `))return K(n.slice(7),e,t);let r=await I(k(e));if(!r)return;let i;if(r.exp_at<=E()||t&&E()-r.at>60){if(r=await G(r),!r)return;i=await L(e,r)}return j(e,{user:{id:r.sub,name:r.name,email:r.email},organizations:r.orgs,...i?{cookies:i}:{}},r.org)},async setOrganization(e,t){let n=await I(k(e)),r=n?.orgs.find(e=>e.slug===t);if(!(!n||!r))return{...r,cookies:await L(e,{...n,org:r.id})}},async link(e,t,n,r={}){let o={name:e.name,email:e.email,...r.organizations?{organizations:r.organizations}:{},...r.token?{token:r.token}:{}};await i.insert(a).values({platform:t,platformUserId:n,userId:e.id,...o}).onConflictDoUpdate({target:[a.platform,a.platformUserId],set:o,setWhere:p(a.userId,e.id)});let[s]=await i.select({userId:a.userId}).from(a).where(f(p(a.platform,t),p(a.platformUserId,n)));return s?.userId===e.id?`linked`:`taken`},async linkedUser(e,t){let[n]=await i.select({id:a.userId,name:a.name,email:a.email,organizations:a.organizations,token:a.token}).from(a).where(f(p(a.platform,e),p(a.platformUserId,t)));return n&&{id:n.id,name:n.name,email:n.email,...n.organizations?{organizations:n.organizations}:{},...n.token?{token:n.token}:{}}}}}export{M as createAuth};
@@ -1 +0,0 @@
1
- import{s as e}from"./cli-DWCR7iqa.js";const t=e(`credentials`,{list:async()=>(await import(`./list-vOvIpbOH.js`)).commandCredentialsList,add:async()=>(await import(`./add-C2y-mVzl.js`)).commandCredentialsAdd,login:async()=>(await import(`./login-BBw95-S3.js`)).commandCredentialsLogin,remove:async()=>(await import(`./remove-CLpL12Ya.js`)).commandCredentialsRemove,default:async()=>(await import(`./default-CwQXCtoB.js`)).commandCredentialsDefault},void 0,{help:{usage:`coder credentials [list|add|login|remove|default] ...`,summary:`Manage engine credentials. Your personal ones are yours alone; workspace ones serve every member, and only owners and admins change them. A task runs on its requester's default for the engine, else the workspace's.`}});export{t as commandCredentials};
@@ -1 +0,0 @@
1
- "use client";import{a as h,b,c as k}from"./agent-pills-dd0b7643e125bbf1.js";import{a as C}from"./tail-7c27aab8ba268bd9.js";import{a as w,b as A,c as v,d as P}from"./toolbar-f964fa864699f095.js";import{b as y}from"./paged-bc6fa0c2b9d52ed7.js";import"./badge-676b01e0c615bf7b.js";import{b as u}from"./card-e0901d68b79dfa93.js";import{f}from"./format-eb03fc9d9744d960.js";import"./sentinel-c972a33dc69a5135.js";import{$1a as p}from"./shared-init-20e199043ff5d00f.js";import"./shared-init-20e199043ff5d00f.js";import{$4a as g,$4d as l}from"./shared-init-20e199043ff5d00f.js";import"./shared-init-20e199043ff5d00f.js";import"./shared-init-88cce66bb3cfe1e5.js";import{$0b as c}from"./shared-init-88cce66bb3cfe1e5.js";import{$2a as a}from"./shared-init-88cce66bb3cfe1e5.js";import{$1c as d}from"./shared-init-8f2ac936c95a7f7b.js";function I(){return a(p,{class:"btn",href:"/dash/agents/new",children:"New agent"})}function S({agent:t,catalog:m}){return a("li",{class:"agent-card",children:[a("div",{class:"bc-head",children:[a("span",{class:"mark",children:f(t.name)}),a("div",{class:"grow",children:[a("h3",{children:a(p,{class:"cover",href:"/dash/agents/[slug]",params:{slug:t.id},children:t.name})}),a("span",{class:"pills",children:a(k,{agent:t})})]})]}),a("div",{class:"lead-clamp",children:a("span",{children:t.description??"No description yet."})}),t.platforms.length?a("span",{class:"pfs",children:t.platforms.map(o=>a(b,{id:o.id,info:m.find(s=>s.id===o.id),state:o.state},o.id))}):a("span",{class:"pfs muted",children:"Listens nowhere yet"})]})}var K=[["","All agents"],["dashboard","Dashboard agents"],["repository","Repository agents"],["builtin","Built-in"]];function X({first:t,limit:m,filters:o,catalog:s,head:R,children:M}){let{values:n,set:i,query:N}=A(o),r=y({name:"agents",fetchPage:e=>c.agents.list({cursor:e,limit:m,...n}),query:N,first:t,initial:w(o)});return a(d,{children:[a(P,{head:R,action:a(I,{}),children:[a(v,{value:n.q,label:"Search agents",onInput:e=>i("q",e,250)}),a(g,{class:"filter-more",label:"More filters",summaryClass:`field-btn${n.platform||n.type?" on":""}`,summary:"Filter",children:[a("p",{class:"pop-label",children:"Platform"}),a("div",{role:"group","aria-label":"Platform",children:[a(l,{on:!n.platform,onPick:()=>i("platform",""),children:"All platforms"}),s.map(e=>a(l,{on:n.platform===e.id,onPick:()=>i("platform",e.id),children:a("span",{class:"pf",children:[a(h,{brand:e.brand}),e.name]})},e.id))]}),a("p",{class:"pop-label",children:"Source"}),a("div",{role:"group","aria-label":"Source",children:K.map(([e,q])=>a(l,{on:n.type===e,onPick:()=>i("type",e),children:q},e))})]})]}),M,r.rows.length?a("ul",{class:"agent-grid","aria-busy":r.stale,children:r.rows.map(e=>a(S,{agent:e,catalog:s},e.id))}):r.stale?null:a(u,{title:"No agents match",children:"Try another search or filter."}),a(C,{noun:"agents",...r})]})}export{X as AgentsGrid,K as KINDS};
@@ -1 +0,0 @@
1
- import{a as Fe}from"./connect-repositories-5389ec8701a3deac.js";import{a as ce,b as qe,c as je,e as Ke}from"./composer-data-6f7608fed13f3dd7.js";import{b as Ie,c as ae,e as le,g as G,h as Be}from"./model-options-15c53331a2f28a4f.js";import{a as H}from"./select-1013702bdfb1ade4.js";import{g as He}from"./task-fa8b82e95e771c4a.js";import{c as Pe}from"./card-e0901d68b79dfa93.js";import{b as ne}from"./field-901f1f35c18c39c9.js";import{a as Le,g as E}from"./format-eb03fc9d9744d960.js";import{$0d as Ae}from"./shared-init-20e199043ff5d00f.js";import{$6a as Ne}from"./shared-init-20e199043ff5d00f.js";import{$1a as ie}from"./shared-init-20e199043ff5d00f.js";import{$4d as se}from"./shared-init-20e199043ff5d00f.js";import{$5B as De,$5f as Se,$5o as Oe,$5p as re,$5r as Re,$5t as Me,$5w as Te}from"./shared-init-20e199043ff5d00f.js";import{$1a as C}from"./shared-init-88cce66bb3cfe1e5.js";import{$0b as h}from"./shared-init-88cce66bb3cfe1e5.js";import{$2a as t}from"./shared-init-88cce66bb3cfe1e5.js";import{$1c as g,$1g as u,$1i as U,$1j as $e,$1k as T,$1m as xe}from"./shared-init-8f2ac936c95a7f7b.js";var it=[["","Default"],["low","Low"],["medium","Medium"],["high","High"]],at=[["","Default"],["read-only","Read-only"],["workspace-write","Write"],["auto","Auto"]],J="coder:draft",V="+connect",pe="+other",de="+pick",ue="+clone",lt=/^\/(review|flow)(?:\s+(\S+))?\s*([\s\S]*)$/,ct=(l,s,i)=>[["",l],...[...new Set([s,...i])].filter(Boolean).map(a=>[a,a])],pt=(l,s,i)=>[["",l],...s&&!i.some(([a])=>a===s)?[[s,s]]:[],...i],We=(l,s,i)=>{let a=[...l.recent,...s].map(p=>p.path);return[["","No folder"],...[...new Set([...a,i])].filter(p=>p&&p!==l.current.path).map(p=>[p,He(p)]),l.picker?[de,"Choose\u2026"]:[pe,"Type a path\u2026"],[ue,"Repository\u2026"]]};function dt(l,s){let i=[["",[["",`Default \xB7 ${[ae[s.engine]??s.engine,s.engines[s.engine]?.model].filter(Boolean).join(" ")}`]]]];for(let a of Ie)l[a]?.length&&i.push([ae[a]??a,[[G(a,""),le(s.engines[a]?.model)],...l[a].map(p=>[G(a,p),p])]]);return i}var ze=(l,s)=>{let i=l.find(([a])=>a&&a===s)?.[1];return[["",le(i?.toLowerCase())],...l.slice(1)]};function ut(l){let s=l.currentTarget,i=document.querySelector(`[popovertarget="${s.id}"]`)?.getBoundingClientRect();if(l.newState!=="open"||!i)return;let a=Math.round(i.bottom+6);s.style.top=`${a}px`,s.style.right=`${Math.round(document.documentElement.clientWidth-i.right)}px`,s.style.maxHeight=`${Math.max(160,window.innerHeight-a-16)}px`}function ft(l){return Object.fromEntries(l.split(/\s+/).filter(Boolean).map(s=>{let i=s.indexOf("="),a=i<0?"true":s.slice(i+1);try{return[i<0?s:s.slice(0,i),JSON.parse(a)]}catch{return[s.slice(0,i),a]}}))}function mt({id:l,entries:s,active:i,selected:a,onActive:p}){return t(g,{children:s.flatMap((m,b)=>[m.head?t("div",{class:"pop-label",role:"presentation",children:m.head},`h:${m.key}`):null,t("div",{id:`${l}-${b}`,role:"option","aria-selected":a===void 0?b===i:m.key===a,class:b===i?"pop-item on":"pop-item",onMouseDown:r=>r.preventDefault(),onPointerMove:()=>b!==i&&p(b),onClick:m.pick,children:[t("span",{class:"grow",children:m.label}),m.hint?t("small",{children:m.hint}):null,a===void 0?null:t(C,{d:re})]},m.key)])})}var gt=(l,s,i,a)=>{let p={ArrowDown:1,ArrowUp:-1}[l.key];return!p||!i?!1:(l.preventDefault(),a((s+p+i)%i),!0)};function ht({reason:l,back:s="/dash/tasks"}){return t("div",{class:"notice slim",role:"status",children:[t(C,{d:Te}),t("span",{class:"grow",children:l||"Tasks need a model credential to run."}),t(ie,{class:"btn outline sm",href:"/dash/settings/[tab]",params:{tab:"credentials"},search:{return:s},children:"Add credential"})]})}function bt({initial:l,data:s,defaults:i,missing:a,connectLabel:p,tz:m}){let b=Ne(),[r,X]=u({...qe,...l}),[d,fe]=u(s),[w,Z]=u(),[q,me]=u(!1),[Ue,$]=u(""),[ge,Ge]=u(),[Je,Ve]=u(),[D,_]=u(""),[Xe,S]=u(!1),[Ze,j]=u(0),[Q,_e]=u([]),[O,A]=u(""),[N,he]=u(!1),be=T(null),y=T(null),we=T(null),ye=T(null),R=xe();U(()=>void(O&&ye.current?.focus()),[O]),U(()=>{let e=localStorage.getItem(J);e&&y.current&&!y.current.value&&(y.current.value=e),_(y.current?.value??""),y.current?.focus(),S(!0)},[]);let ke=D.startsWith("/");U(()=>{let e=r.repo;!ke||!e||w?.repo===e||(Z({repo:e}),h.pulls.list(e).then(o=>Z({repo:e,items:o})).catch(o=>{Z({repo:e,items:[]}),$(E(o))}),h.flows.list(e).then(o=>fe(c=>({...c,flows:o.map(n=>n.name)}))).catch(()=>{}))},[ke,r.repo]);let P=(e,o)=>{if(o===pe)return A("path");if(o===ue)return A("url");if(o===de)return void Ye();if(o===V)return void Fe("/dash/tasks").catch(c=>$(E(c)));M({[e]:o}),(e==="repo"||e==="cwd")&&y.current?.focus({preventScroll:!0})},M=e=>{let o={...r,...e};X(o),document.cookie=`compose=${encodeURIComponent(JSON.stringify(o))}; path=/; max-age=31536000; samesite=lax`},Y=e=>{if(!e.ok)return $(e.detail);$(""),A(""),_e(o=>[...o.filter(c=>c.path!==e.folder.path),e.folder]),P("cwd",e.folder.path===d.folders?.current.path?"":e.folder.path)},Qe=async e=>{e.trim()&&Y(await h.folders.check(e.trim()).catch(o=>({ok:!1,detail:E(o)})))},Ye=async()=>{document.body.style.cursor="progress";let e=await h.folders.pick().catch(o=>({ok:!1,detail:E(o)}));document.body.style.cursor="",(e.ok||e.detail)&&Y(e)},et=async e=>{if(!e.trim())return;he(!0),document.body.style.cursor="progress";let o=await h.folders.clone(e.trim()).catch(c=>({ok:!1,detail:E(c)}));document.body.style.cursor="",he(!1),Y(o)},ee=e=>{let o=y.current;o.value=e,localStorage.setItem(J,e),_(e),j(0),S(!1),o.focus(),o.setSelectionRange(e.length,e.length)},K=async e=>{let o=y.current?.value.trim()??"";if(q||N||!(o||e))return;let[,c,n="",k=""]=lt.exec(o)??[];if(!e&&c&&!(c==="flow"?n:/^#?\d+$/.test(n)))return void S(!1);let x=e??(c==="review"?Number(n.replace("#","")):void 0);if(x&&!r.repo)return $("Pick a repository first.");let{agent:I,engine:z,model:B,effort:v,permissions:te,runner:ot}=r,[nt,rt]=d.folders?["",r.cwd]:[r.repo,""],oe=Object.fromEntries(Object.entries({repo:nt,cwd:rt,engine:z,model:B,effort:v,permissions:te,runner:ot}).filter(([,L])=>L));me(!0),$("");try{let L=x?await h.review({...oe,repo:r.repo,pr:x}):c==="flow"?await h.flows.run(n,{...oe,agent:I,args:ft(k)}):await h.tasks.create({...oe,agent:I,prompt:o});(!e||c)&&localStorage.removeItem(J),Ae(L.task.id,"queued",o||`Review of #${x}`),b.push("/dash/tasks/[id]",{params:{id:L.task.id}})}catch(L){me(!1),L.status===409?Ge(E(L)):$(E(L))}},f=(()=>{let e=/^\/(\S*)$/.exec(D)?.[1]?.toLowerCase();if(e!==void 0)return{label:"Commands",entries:[{key:"review",label:"/review",hint:"Review a pull request",pick:()=>ee("/review ")},...d.flows.map(n=>({key:`flow ${n}`,label:`/flow ${n}`,hint:`Run the ${n} flow`,pick:()=>ee(`/flow ${n} `)}))].filter(n=>n.key.includes(e)),note:"No command matches."};let o=/^\/flow\s+(\S*)$/.exec(D)?.[1];if(o!==void 0)return{label:"Flows",entries:d.flows.filter(n=>n.includes(o)).map(n=>({key:n,label:n,hint:`Run the ${n} flow`,pick:()=>n===o?void K():ee(`/flow ${n} `)})),note:"No flow matches."};let c=/^\/review\s+#?(\S*)$/.exec(D)?.[1];if(c!==void 0)return r.repo?w?.items?{label:`Pull requests in ${r.repo}`,entries:[...w.items.filter(n=>String(n.number).startsWith(c)||n.title.toLowerCase().includes(c.toLowerCase())).sort((n,k)=>+(String(k.number)===c)-+(String(n.number)===c)).map(n=>({key:`#${n.number}`,label:`#${n.number} ${n.title}`,hint:[n.author,n.createdAt?Le(Date.parse(n.createdAt),m):""].filter(Boolean).join(" \xB7 "),pick:()=>void K(n.number)})),...c?[]:[{key:"",label:r.repo,hint:"Pick another repository",pick:()=>M({repo:""})}]],note:w.items.length?"No open pull request matches.":"No open pull requests."}:{label:`Pull requests in ${r.repo}`,entries:[],note:"loading"}:{label:"Pick a repository",entries:[...d.repos.filter(n=>n.includes(c)).map(n=>({key:n,label:n,pick:()=>P("repo",n)})),{key:V,label:p,pick:()=>P("repo",V)}]}})(),F=!!(f&&!Xe),W=f?Math.min(Ze,Math.max(0,f.entries.length-1)):0;$e(()=>{let e=we.current;if(!e)return;if(!F)return void(e.matches(":popover-open")&&e.hidePopover());let o=()=>{let c=be.current.getBoundingClientRect();e.style.top=`${Math.round(c.bottom+6)}px`,e.style.left=`${Math.round(c.left)}px`,e.style.width=`${Math.round(Math.min(c.width,460))}px`};return o(),e.matches(":popover-open")||e.showPopover(),addEventListener("scroll",o,!0),addEventListener("resize",o),()=>{removeEventListener("scroll",o,!0),removeEventListener("resize",o)}},[F,D]);let tt=r.engine||i.engine,ve=i.engines[tt]??{},Ee=d.agents.filter(([e])=>e!=="coder"),Ce=[r.agent!=="coder"&&r.agent,r.engine!==i.engine&&r.engine,...["model","effort","permissions"].map(e=>r[e]!==ve[e]&&r[e]),r.runner&&(d.runners.find(([e])=>e===r.runner)?.[1]??r.runner)].filter(Boolean).join(" \xB7 ");return t(g,{children:[t("form",{ref:be,class:"composer",onSubmit:e=>{e.preventDefault(),K()},children:[t("textarea",{ref:y,name:"prompt",rows:1,role:"combobox","aria-label":"What should the agent do?","aria-autocomplete":"list","aria-expanded":F,"aria-controls":`${R}-slash`,"aria-activedescendant":F&&f?.entries.length?`${R}-slash-${W}`:void 0,placeholder:ce,autofocus:!0,onFocus:()=>S(!1),onBlur:()=>S(!0),onInput:e=>{let o=e.currentTarget.value;localStorage.setItem(J,o),_(o),j(0),S(!1)},onKeyDown:e=>{if(!e.isComposing){if(F&&f){if(gt(e,W,f.entries.length,j))return;if(e.key==="Escape")return e.preventDefault(),S(!0);if(f.entries.length&&(e.key==="Enter"&&!e.shiftKey||e.key==="Tab"))return e.preventDefault(),f.entries[W].pick()}e.key!=="Enter"||e.shiftKey||(e.preventDefault(),K())}}}),t("div",{class:"composer-line",children:[d.folders?O?t(g,{children:[t("input",{class:"folder-path","aria-label":O==="url"?"Repository URL":"Folder path",ref:ye,placeholder:O==="url"?"https://github.com/owner/repo":"Absolute path or ~/\u2026",readOnly:N,"aria-busy":N,onKeyDown:e=>{if(N)return e.preventDefault();if(e.key==="Escape")return e.preventDefault(),$(""),A("");e.key!=="Enter"||e.isComposing||(e.preventDefault(),(O==="url"?et:Qe)(e.currentTarget.value))},onBlur:e=>!N&&!e.currentTarget.value.trim()&&A("")}),N?t("span",{class:"folder-busy",children:"Cloning\u2026"}):null]}):t("span",{class:"folder",title:r.cwd||d.folders.current.path,children:t(H,{label:"Folder",value:r.cwd,options:We(d.folders,Q,r.cwd),subs:Object.fromEntries(We(d.folders,Q,r.cwd).flatMap(([e])=>e&&e!==pe&&e!==de&&e!==ue?[[e,Q.find(o=>o.path===e)?.url??e]]:[])),onChange:e=>P("cwd",e)})}):t(H,{label:"Repository",value:r.repo,options:[...ct("No repository",r.repo,d.repos),[V,p]],onChange:e=>P("repo",e)}),t("button",{type:"button",class:"quiet",popovertarget:`${R}-settings`,"aria-label":"Run options",title:"Model, effort, permissions and more",children:[t(C,{d:De}),Ce?t("span",{children:Ce}):null]}),t("button",{class:"btn sm send",disabled:q||!D.trim(),"aria-busy":q,"aria-label":q?"Starting task":"Start task",title:"Start task (Enter)",children:t(C,{d:Me})})]}),O==="url"?t("small",{class:"folder-hint",children:"Uses this machine's git logins"}):null,t(ne,{value:Ue}),t("div",{id:`${R}-settings`,class:"pop composer-settings",popover:"auto",onBeforeToggle:ut,children:[t("p",{class:"pop-label",children:"Model"}),t("div",{role:"group","aria-label":"Model",class:"pop-radios",children:[dt(d.models,i).map(([e,o])=>t(g,{children:[e?t("p",{class:"pop-group",children:e}):null,o.map(([c,n])=>{let k=c===G(r.engine,r.model),x=Be(c),I=ze(it,i.engines[x.engine||i.engine]?.effort),z=k&&r.effort?I.find(([v])=>v===r.effort)?.[1]:void 0,B=Je===c;return t(g,{children:[t("div",{class:"pop-row",children:[t("button",{type:"button",role:"menuitemradio","aria-checked":k,class:k?"pop-item on":"pop-item",onClick:v=>{M({...x,effort:""}),v.currentTarget.closest("[popover]")?.hidePopover()},children:[t("span",{class:"grow",children:n}),z?t("small",{children:z.toLowerCase()}):null,k?t(C,{d:re}):null]}),t("button",{type:"button",class:"pop-chev","data-keep":!0,"aria-label":`Effort for ${n}`,"aria-expanded":B,onClick:()=>Ve(B?void 0:c),children:t(C,{d:Se})})]}),B?t("div",{role:"group","aria-label":`Effort for ${n}`,class:"pop-sub",children:I.map(([v,te])=>t(se,{on:k&&r.effort===v,onPick:()=>{M({...x,effort:v}),document.getElementById(`${R}-settings`)?.hidePopover()},children:te},v))}):null]},c)})]},e)),t(ie,{class:"pop-item add-models",href:"/dash/settings/[tab]",params:{tab:"models"},children:[t(C,{d:Re}),t("span",{class:"grow",children:"Add models"})]})]}),t("p",{class:"pop-label",children:"Permissions"}),t("div",{role:"group","aria-label":"Permissions",children:ze(at,ve.permissions??"auto").map(([e,o])=>t(se,{on:r.permissions===e,onPick:()=>M({permissions:e}),children:o},e))}),Ee.length||r.agent!=="coder"?t(g,{children:[t("p",{class:"pop-label",children:"Agent"}),t(H,{label:"Agent",value:r.agent,options:pt("coder",r.agent,Ee),onChange:e=>M({agent:e})})]}):null,d.runners.length>1?t(g,{children:[t("p",{class:"pop-label",children:"Runs on"}),t(H,{label:"Runs on",options:d.runners,value:r.runner,onChange:e=>M({runner:e})})]}):null]}),t("div",{ref:we,id:`${R}-slash`,class:"pop composer-slash",popover:"manual",role:"listbox","aria-label":f?.label??"Commands",children:f?t(g,{children:[t("div",{class:"pop-label",children:f.label}),t(mt,{id:`${R}-slash`,entries:f.entries,active:W,onActive:j}),f.note==="loading"?t(Pe,{label:"Loading pull requests",inline:!0}):f.note&&!f.entries.length?t("p",{class:"pop-note",children:f.note}):null]}):null})]}),ge===void 0||a?null:t(ht,{reason:ge})]})}function wt(){return t("div",{class:"composer","aria-hidden":"true",children:[t("textarea",{rows:1,disabled:!0,tabIndex:-1,placeholder:ce}),t("div",{class:"composer-line"})]})}function jt({agent:l}){let s=T(null),[i,a]=u(),[p,m]=u(""),[b,r]=u(!1),X=T(),d=()=>X.current??=Ke(h).then(a,w=>m(E(w)));return t(g,{children:[t("button",{type:"button",class:"btn new-task",onClick:()=>{r(!0),s.current?.showModal(),d()},onPointerEnter:d,onFocus:d,children:"New task"}),t("dialog",{ref:s,class:"compose-dialog","aria-label":`New task for ${l}`,onClose:()=>r(!1),onClick:w=>w.target===w.currentTarget&&s.current?.close(),children:[t("header",{children:[t("h2",{children:"New task"}),t("span",{class:"sub",children:l}),t("button",{type:"button",class:"icon-btn","aria-label":"Close",onClick:()=>s.current?.close(),children:t(C,{d:Oe})})]}),b?i?t(bt,{...i,initial:{...je(document.cookie),agent:l},tz:Intl.DateTimeFormat().resolvedOptions().timeZone}):p?t(ne,{value:p}):t(wt,{}):null]})]})}export{ht as a,bt as b,wt as c,jt as d};
@@ -1 +0,0 @@
1
- "use client";import{a,b,c,d}from"./composer-49f9e7c5c4dfda3b.js";import"./connect-repositories-5389ec8701a3deac.js";import"./composer-data-6f7608fed13f3dd7.js";import"./model-options-15c53331a2f28a4f.js";import"./select-1013702bdfb1ade4.js";import"./task-fa8b82e95e771c4a.js";import"./card-e0901d68b79dfa93.js";import"./field-901f1f35c18c39c9.js";import"./format-eb03fc9d9744d960.js";import"./shared-init-20e199043ff5d00f.js";import"./shared-init-20e199043ff5d00f.js";import"./wular-pnext-246221e985d863e5-0.js";import"./shared-init-20e199043ff5d00f.js";import"./shared-init-20e199043ff5d00f.js";import"./shared-init-20e199043ff5d00f.js";import"./shared-init-20e199043ff5d00f.js";import"./shared-init-88cce66bb3cfe1e5.js";import"./shared-init-88cce66bb3cfe1e5.js";import"./shared-init-88cce66bb3cfe1e5.js";import"./shared-init-246221e985d863e5-2.js";import"./shared-init-246221e985d863e5-2.js";import"./shared-init-8f2ac936c95a7f7b.js";export{b as Composer,c as LoadingComposer,a as NeedsCredential,d as NewTaskButton};