@wular/coder 0.4.1 → 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 (378) hide show
  1. package/README.md +69 -70
  2. package/dist/actions-FzDNxMFf.js +20 -0
  3. package/dist/{adapter-BKVzTDnn.js → adapter-7SEiVsmp.js} +1 -1
  4. package/dist/{adapter-B0oYCI0S.js → adapter-BLEfUqoQ.js} +1 -1
  5. package/dist/{adapter-DPInwbJG.js → adapter-H4GlcKQz.js} +1 -1
  6. package/dist/{add-CE-70LFs.js → add-B50dIJGd.js} +1 -1
  7. package/dist/{add-BxpLHnvD.js → add-D7X3gxap.js} +1 -1
  8. package/dist/{add-ej0X9e3a.js → add-DOEUHIe7.js} +1 -1
  9. package/dist/{add-U-pty9qJ.js → add-QExQhTzi.js} +1 -1
  10. package/dist/{add-json-CEa-6luW.js → add-json-Ck4KIZrT.js} +1 -1
  11. package/dist/{agent-JdtZozvP.js → agent-BPtnEf1q.js} +1 -1
  12. package/dist/{agent-BsYx3Odz.js → agent-BlQ_dNNm.js} +2 -2
  13. package/dist/{alias-DX-Bm86x.js → alias-BwQBovke.js} +1 -1
  14. package/dist/{app-BT5f7zL5.js → app-y6BYm2eH.js} +1 -1
  15. package/dist/{approvals-C-AvFt6s.js → approvals-Cc9cq5T1.js} +2 -2
  16. package/dist/{approve-DOmpQRNd.js → approve-oO9k2fnK.js} +2 -2
  17. package/dist/{apps-CjfrZyM5.js → apps-CU2YalX8.js} +1 -1
  18. package/dist/{archive-BziJ1rQ-.js → archive-C5c_HQS1.js} +2 -2
  19. package/dist/{archive-BUB8gFKD.js → archive-CemlWlVY.js} +2 -2
  20. package/dist/archive-sweep-ehg-fWIt.js +1 -0
  21. package/dist/{args-BOEEdpWk.js → args-DcBCtXhz.js} +1 -1
  22. package/dist/{ask-dE3U3ss2.js → ask-Chu7Twu_.js} +2 -2
  23. package/dist/auth-BOyXPOtu.js +1 -0
  24. package/dist/auth-XbqKSbcD.js +1 -0
  25. package/dist/{chat-bridge-BS9WtP3X.js → chat-bridge-DXgZItGP.js} +1 -1
  26. package/dist/{chat-B_yhNTo0.js → chat-cknlIhVh.js} +1 -1
  27. package/dist/{cli-BilSDkvE.js → cli-B1ObVrL4.js} +5 -5
  28. package/dist/cli.d.ts +1 -1
  29. package/dist/cli.js +1 -1
  30. package/dist/{client-D9IoAuDD.js → client-31YzOj-i.js} +1 -1
  31. package/dist/{config-Da_cwoxI.js → config-DAE_qHYA.js} +1 -1
  32. package/dist/{create-C_iMJV4Y.js → create-CM8B8JxD.js} +1 -1
  33. package/dist/credentials-BXD4Qptk.js +1 -0
  34. package/dist/dash/manifest.json +934 -1014
  35. package/dist/dash/public/assets/chunks/{agent-pills-c9c4ac4d4a10df83.js → agent-pills-b6a6da91c9559d9f.js} +1 -1
  36. package/dist/dash/public/assets/chunks/{agent-settings-form-8be2ddab074aba6d.js → agent-settings-form-b615c677046cd6f2.js} +1 -1
  37. package/dist/dash/public/assets/chunks/agents-grid-f2e7b4ff9e11b6e3.js +1 -0
  38. package/dist/dash/public/assets/chunks/{badge-676b01e0c615bf7b.js → badge-215c7b2631dafc69.js} +1 -1
  39. package/dist/dash/public/assets/chunks/{card-e0901d68b79dfa93.js → card-e86dcc81326d2b14.js} +1 -1
  40. package/dist/dash/public/assets/chunks/{combo-41234c24668b1db1.js → combo-09e246dc9a517fa8.js} +1 -1
  41. package/dist/dash/public/assets/chunks/composer-417166b029f48c47.js +1 -0
  42. package/dist/dash/public/assets/chunks/composer-645ae8fa97a35280.js +1 -0
  43. package/dist/dash/public/assets/chunks/{confirm-f2fe4ba9905a89c6.js → confirm-5ae484241ad888fd.js} +1 -1
  44. package/dist/dash/public/assets/chunks/{connect-apps-aa2a3d82e48ed8c3.js → connect-apps-4147c45f45fde2b1.js} +1 -1
  45. package/dist/dash/public/assets/chunks/{connect-repositories-5389ec8701a3deac.js → connect-repositories-77591110836bdf03.js} +1 -1
  46. package/dist/dash/public/assets/chunks/credentials-list-e005a0783ec93465.js +2 -0
  47. package/dist/dash/public/assets/chunks/{custom-range-4761ab14f05149df.js → custom-range-463e119af4681c61.js} +1 -1
  48. package/dist/dash/public/assets/chunks/{editor-bfe8cd854f8001be.js → editor-804b84f4fe6539cd.js} +4 -4
  49. package/dist/dash/public/assets/chunks/{engines-list-f1191390f5715b39.js → engines-list-ceab51f13c690e8c.js} +1 -1
  50. package/dist/dash/public/assets/chunks/{field-901f1f35c18c39c9.js → field-aa0a4b98a976781e.js} +1 -1
  51. package/dist/dash/public/assets/chunks/filter-91144ac2eec6297f.js +1 -0
  52. package/dist/dash/public/assets/chunks/format-105c706345987fb2.js +1 -0
  53. package/dist/dash/public/assets/chunks/heads-a42817b32d2d7f08.js +1 -0
  54. package/dist/dash/public/assets/chunks/{instructions-052fa45a9daf6db6.js → instructions-3a1dcaff2d868aa5.js} +1 -1
  55. package/dist/dash/public/assets/chunks/instructions-6c6f981fffaa31e4.js +1 -0
  56. package/dist/dash/public/assets/chunks/{list-1d259660d7612c5f.js → list-7270361464fc3c04.js} +1 -1
  57. package/dist/dash/public/assets/chunks/{mcp-list-e3bebbbe831393b8.js → mcp-list-2e715d48666b54ad.js} +1 -1
  58. package/dist/dash/public/assets/chunks/{models-list-44f857a469ca04d5.js → models-list-d3c40f94c761a6e5.js} +1 -1
  59. package/dist/dash/public/assets/chunks/paged-3ddb6077bef42752.js +1 -0
  60. package/dist/dash/public/assets/chunks/{platform-actions-d1426602049926d2.js → platform-actions-271ec3b99a64280b.js} +1 -1
  61. package/dist/dash/public/assets/chunks/runners-list-767e49c7d0ec833a.js +1 -0
  62. package/dist/dash/public/assets/chunks/{segmented-358ff2b4992b8384.js → segmented-de4386ccaac7304d.js} +1 -1
  63. package/dist/dash/public/assets/chunks/{select-7ae25fd8a7d6c338.js → select-a90307706cffa6e0.js} +1 -1
  64. package/dist/dash/public/assets/chunks/{sentinel-c972a33dc69a5135.js → sentinel-b5e032b38604dfd3.js} +1 -1
  65. package/dist/dash/public/assets/chunks/shared-init-7f81ae7bc8c82438.js +2 -0
  66. package/dist/dash/public/assets/chunks/shared-init-933c7f9ee85be766.js +5 -0
  67. package/dist/dash/public/assets/chunks/{tail-7c27aab8ba268bd9.js → tail-4891e727ee526792.js} +1 -1
  68. package/dist/dash/public/assets/chunks/task-actions-ce854925a2dc78fd.js +1 -0
  69. package/dist/dash/public/assets/chunks/task-ddfddeaf07fb684c.js +1 -0
  70. package/dist/dash/public/assets/chunks/task-view-c37dcee08f21a279.js +5 -0
  71. package/dist/dash/public/assets/chunks/tasks-list-baef587999f322d8.js +1 -0
  72. package/dist/dash/public/assets/chunks/{toolbar-a75d2570f07cbb70.js → toolbar-8d98313606ad8a2d.js} +1 -1
  73. package/dist/dash/public/assets/chunks/{versions-list-fc2e0d2a7382e049.js → versions-list-532690efd9f1b0ea.js} +1 -1
  74. package/dist/dash/public/assets/dash-49ca85b59ac65c20.css +1 -0
  75. package/dist/dash/public/assets/dash-account-edc56e85dbaaabe0.css +1 -0
  76. package/dist/dash/public/assets/dash-agents-edba57b67e4005d0.css +1 -0
  77. package/dist/dash/public/assets/dash-agents-new-fe22253fbada2fbf.css +1 -0
  78. package/dist/dash/public/assets/dash-agents-param-slug-adf52e9dacb2d825.css +1 -0
  79. package/dist/dash/public/assets/dash-agents-param-slug-edit-a2937a347689ef29.css +1 -0
  80. package/dist/dash/public/assets/dash-agents-param-slug-platforms-265ba13db32a460d.css +1 -0
  81. package/dist/dash/public/assets/dash-agents-param-slug-settings-8afc52eb0372bc4b.css +1 -0
  82. package/dist/dash/public/assets/dash-agents-param-slug-tasks-6193e646be68dbd2.css +1 -0
  83. package/dist/dash/public/assets/dash-agents-param-slug-usage-ceadb3a1c911c402.css +1 -0
  84. package/dist/dash/public/assets/dash-settings-cf1997cd7f72e518.css +1 -0
  85. package/dist/dash/public/assets/dash-settings-param-tab-b44dac8e79a560e6.css +1 -0
  86. package/dist/dash/public/assets/dash-tasks-916c7100a8058aa3.css +1 -0
  87. package/dist/dash/public/assets/dash-tasks-param-id-194a6ffc20e872f2.css +1 -0
  88. package/dist/dash/public/assets/dash-usage-40940b289f85e0b6.css +1 -0
  89. package/dist/dash/public/assets/pnext-client-13aee92bef5c9e3f.js +1 -0
  90. package/dist/dash/public/assets/pnext-client-1f2686b2044f0df6.js +1 -0
  91. package/dist/dash/public/assets/pnext-client-26130234ebad7067.js +1 -0
  92. package/dist/dash/public/assets/pnext-client-311e35b0076bf406.js +1 -0
  93. package/dist/dash/public/assets/pnext-client-4ade1bf75c9c3d87.js +1 -0
  94. package/dist/dash/public/assets/pnext-client-61cd31b687ede1da.js +1 -0
  95. package/dist/dash/public/assets/pnext-client-61db65dc4223217a.js +1 -0
  96. package/dist/dash/public/assets/pnext-client-6ea656e7705e3f2a.js +1 -0
  97. package/dist/dash/public/assets/pnext-client-7fd0f793f0322cb9.js +1 -0
  98. package/dist/dash/public/assets/pnext-client-88159c0840fcfa4a.js +1 -0
  99. package/dist/dash/public/assets/pnext-client-b03f0c47c066b4f3.js +1 -0
  100. package/dist/dash/public/assets/{pnext-client-1b9ab0963a8ff77b.js → pnext-client-d6478835f543f901.js} +1 -1
  101. package/dist/dash/public/assets/pnext-client-dadb8359021ed590.js +1 -0
  102. package/dist/dash/public/assets/pnext-client-de07532d6aaebf2c.js +1 -0
  103. package/dist/dash/public/assets/pnext-client-f87a31890c8ff224.js +1 -0
  104. package/dist/dash/public/assets/pnext-client-ffe1c123a8e2a350.js +1 -0
  105. package/dist/dash/server/bundle-0.1.6-b29ec45cb963d47f/entry.js +2 -0
  106. package/dist/{default-vYPT26DR.js → default-BMvUMTFp.js} +1 -1
  107. package/dist/default-B_nKaX0-.js +1 -0
  108. package/dist/{delete-D8gEwoOj.js → delete-Bjteibld.js} +2 -2
  109. package/dist/{delete-z1_86nf6.js → delete-riCIKZwj.js} +2 -2
  110. package/dist/{disable-DVKd-0Xb.js → disable-DQC56YFy.js} +1 -1
  111. package/dist/{discover-Dvr_3_Xr.js → discover-Qanr5TEO.js} +1 -1
  112. package/dist/{discover-Df-a8K4R.js → discover-lgTYwoQp.js} +2 -2
  113. package/dist/dispatch-BsW_1m7e.js +14 -0
  114. package/dist/{docs-DKJnqZqt.js → docs-DFs7lOJp.js} +1 -1
  115. package/dist/{docs-BX65z2Iu.js → docs-DKROso-4.js} +2 -2
  116. package/dist/{enable-C8Zf_wpN.js → enable-D2DqZvcU.js} +1 -1
  117. package/dist/{env-CRf6wkM2.js → env-YRY3I60r.js} +1 -1
  118. package/dist/exec-DuUkLMqg.js +11 -0
  119. package/dist/executor-vMppVLB6.js +10 -0
  120. package/dist/flow/builtin/review.js +1 -1
  121. package/dist/flow/index.d.ts +1 -1
  122. package/dist/flow/index.js +1 -1
  123. package/dist/{flow-17k25MHt.js → flow-DmERAnR8.js} +1 -1
  124. package/dist/{github-actions-DwUzm4hC.js → github-actions-C_NkHVJq.js} +1 -1
  125. package/dist/http-D01Udu4u.js +1 -0
  126. package/dist/{index-CZjFX5zV.d.ts → index-B1L4zXZH.d.ts} +2 -1
  127. package/dist/{init-CoMfFxbG.js → init-Bd6JHzBc.js} +1 -1
  128. package/dist/integrations-B2CavXR1.js +5 -0
  129. package/dist/integrations-D1Dwy1kt.js +1 -0
  130. package/dist/lib/broker.js +2 -2
  131. package/dist/{list-DX-z3SBp.js → list-4Uo-0v9s.js} +1 -1
  132. package/dist/{list-BAKvxSbh.js → list-B0ujEZhd.js} +3 -3
  133. package/dist/{list-BYiG8Zav.js → list-B5oa1Bhy.js} +2 -2
  134. package/dist/{list-BxEywhHU.js → list-BjE_l6la.js} +1 -1
  135. package/dist/{list-VToARh3C.js → list-Ck9ibCs1.js} +1 -1
  136. package/dist/{list-CIW2joV1.js → list-DhgK4Zc4.js} +1 -1
  137. package/dist/{list-DpCf4G-H.js → list-KvL7AUhD.js} +2 -2
  138. package/dist/{list-C5w01-8q.js → list-byYLBl1U.js} +1 -1
  139. package/dist/{load-BpEsAn51.js → load-SnZd7xG1.js} +1 -1
  140. package/dist/{local-H3uvqEbq.js → local-BRy1EUq2.js} +1 -1
  141. package/dist/log-view-DeJstSkw.js +3 -0
  142. package/dist/{login-DkkslfBx.js → login-C-ahtDKV.js} +1 -1
  143. package/dist/{login-BFxX4jJy.js → login-zpwke8g1.js} +1 -1
  144. package/dist/{logout-BHAtw4Z8.js → logout-CI6Kf-T6.js} +1 -1
  145. package/dist/{maintenance-C5FklUw3.js → maintenance-BAzr9Jlr.js} +1 -1
  146. package/dist/{match-CXAjDhg7.js → match-DxV1d49D.js} +1 -1
  147. package/dist/{mcp-BgKb2Cdk.js → mcp-CmcL1MCG.js} +1 -1
  148. package/dist/{mcp-CCZOAo06.js → mcp-mhXwtGQT.js} +1 -1
  149. package/dist/{migrate-N-85_N7J.js → migrate-Czh3TEK5.js} +1 -1
  150. package/dist/{migrate-C4vM7DQN.js → migrate-w7KfzUAR.js} +1 -1
  151. package/dist/{model-Bs1StDo3.js → model-JRoTH9QK.js} +1 -1
  152. package/dist/models-C-S7HqSb.js +1 -0
  153. package/dist/{prompt-CEuBMNhk.js → prompt-CMXmt2l9.js} +4 -4
  154. package/dist/{push-CUC55Bqd.js → push-B8BhTyZs.js} +1 -1
  155. package/dist/queue-CirjEskI.js +117 -0
  156. package/dist/refresh-Bmy2r1Ee.js +1 -0
  157. package/dist/{remote-miQNTVRa.js → remote-CxFnEjZl.js} +1 -1
  158. package/dist/{remove-B93LNkZI.js → remove-C15WLaXT.js} +1 -1
  159. package/dist/{remove-C5_xggx7.js → remove-CTZYjjSr.js} +1 -1
  160. package/dist/{remove-eQ8y5C5p.js → remove-CTl-H0f0.js} +1 -1
  161. package/dist/{remove-CuH8a3L9.js → remove-DX2FVo5b.js} +1 -1
  162. package/dist/rename-D1g4TnHQ.js +1 -0
  163. package/dist/{result-BEtQZHaY.js → result-D49VN8PM.js} +3 -3
  164. package/dist/result-DGWyUHYU.js +18 -0
  165. package/dist/{resume-DYzKvyEw.js → resume-ywzc7z6A.js} +2 -2
  166. package/dist/{review-oIBeECZE.js → review-ZC0xG8XY.js} +2 -2
  167. package/dist/{rotate-key-IdMYH7gg.js → rotate-key-Bf8_99ck.js} +1 -1
  168. package/dist/{run-CTtd0Znc.js → run-D7SJ-ieT.js} +2 -2
  169. package/dist/run-DoRQSC_K.js +2 -0
  170. package/dist/{run-CawRGnOg.js → run-ukCf2Mdy.js} +1 -1
  171. package/dist/runner-D-REfOUe.js +1 -0
  172. package/dist/{runner-sUpWJ_k0.js → runner-wDYhkVsM.js} +1 -1
  173. package/dist/schema-DoNO0dPh.js +1 -0
  174. package/dist/sdk.d.ts +4 -2
  175. package/dist/sdk.js +1 -1
  176. package/dist/serve-BJ_Mbm2m.js +8 -0
  177. package/dist/{serve-CPnmrKyf.js → serve-C1MMhM1F.js} +2 -2
  178. package/dist/{serve-GmRO89s5.js → serve-DtrOHaoS.js} +2 -2
  179. package/dist/{serve-CE8YV2e9.js → serve-P9pFkEnE.js} +1 -1
  180. package/dist/{serve-BTeomYxW.js → serve-yjSw0B1a.js} +1 -1
  181. package/dist/{server-Kb22cWfF.js → server-DDWTnmbx.js} +1 -1
  182. package/dist/{setup-host-GFTUzzZJ.js → setup-host-L6Rnn5Cz.js} +1 -1
  183. package/dist/{shared-DVtzWhUT.js → shared-XsUX_ZZb.js} +1 -1
  184. package/dist/{show-COTZEYgc.js → show-CU-jqJ90.js} +1 -1
  185. package/dist/{show-CMUg8SJu.js → show-DVJmB2u-.js} +1 -1
  186. package/dist/{status-D26U--p8.js → status-CBydR7LE.js} +1 -1
  187. package/dist/{steer-C6uARLp5.js → steer-Cm_sHZqs.js} +2 -2
  188. package/dist/{stop-BrGI3hSS.js → stop-DJS7DAPJ.js} +1 -1
  189. package/dist/{stop-ByCAlbmN.js → stop-TrebIIuv.js} +2 -2
  190. package/dist/store-BrNMqJgk.js +42 -0
  191. package/dist/store-j8icrG0v.js +19 -0
  192. package/dist/task-C8lmcNsf.js +1 -0
  193. package/dist/{task-DeglY79z.js → task-CpUI19o2.js} +4 -4
  194. package/dist/task-CvSqiwxo.js +1 -0
  195. package/dist/{test-NEbhlxvo.js → test-CDKz4jY_.js} +1 -1
  196. package/dist/{tools-D0Zfs8Hx.js → tools-DBFeoosk.js} +1 -1
  197. package/dist/{types-I5Cwtl_K.d.ts → types-DMGBYB_K.d.ts} +3 -1
  198. package/dist/{unalias-C9NqmSDq.js → unalias-BfQFBnuK.js} +1 -1
  199. package/dist/{update-BTxYQj7Z.js → update-C4FFOie8.js} +1 -1
  200. package/dist/{upgrade-hA0yWBvx.js → upgrade-DLJqMnUQ.js} +2 -2
  201. package/dist/{usage-BhqoCjvE.js → usage-CSh-xwQ2.js} +1 -1
  202. package/dist/{usage-C4d9X2Uq.js → usage-D8mc4qXK.js} +1 -1
  203. package/dist/{watch-DtRuC0Wc.js → watch-CQu-tJKZ.js} +2 -2
  204. package/dist/{watch-CSdj24ct.js → watch-DmwaEvoi.js} +2 -2
  205. package/dist/{wire-BeT1Axeo.js → wire-DzGLZ3-O.js} +1 -1
  206. package/dist/worker-BLKTMLqa.js +1 -0
  207. package/dist/worker-nHemduM_.js +9 -0
  208. package/dist/{workflow-Dcmdooi8.js → workflow-IrouAus_.js} +1 -1
  209. package/docs/cli.md +145 -0
  210. package/docs/mcp.md +1 -1
  211. package/migrations/0000_initial.sql +8 -0
  212. package/migrations/meta/0000_snapshot.json +75 -1
  213. package/migrations/meta/_journal.json +1 -1
  214. package/package.json +3 -2
  215. package/plugins/agents/skills/coder/SKILL.md +1 -0
  216. package/plugins/claude/.claude-plugin/plugin.json +1 -1
  217. package/plugins/claude/skills/dispatch/SKILL.md +1 -1
  218. package/plugins/cursor/.cursor-plugin/plugin.json +1 -1
  219. package/plugins/cursor/skills/coder/SKILL.md +1 -0
  220. package/src/client/index.ts +10 -2
  221. package/src/client/types.ts +18 -0
  222. package/src/core/defaults.ts +36 -0
  223. package/src/core/task/log-view.ts +120 -6
  224. package/src/server/dash/app/dash/agents/(list)/agent-menu.tsx +4 -0
  225. package/src/server/dash/app/dash/agents/(list)/agents-grid.tsx +18 -35
  226. package/src/server/dash/app/dash/agents/(list)/loading.tsx +7 -1
  227. package/src/server/dash/app/dash/agents/[slug]/(tabs)/layout.tsx +2 -1
  228. package/src/server/dash/app/dash/layout.css +58 -1
  229. package/src/server/dash/app/dash/layout.tsx +29 -7
  230. package/src/server/dash/app/dash/settings/[tab]/credentials-list.tsx +20 -13
  231. package/src/server/dash/app/dash/settings/[tab]/page.tsx +1 -1
  232. package/src/server/dash/app/dash/settings/[tab]/runners-list.tsx +13 -12
  233. package/src/server/dash/app/dash/tasks/[id]/activity.tsx +49 -4
  234. package/src/server/dash/app/dash/tasks/[id]/task-actions.tsx +43 -6
  235. package/src/server/dash/app/dash/tasks/[id]/task-view.css +52 -31
  236. package/src/server/dash/app/dash/tasks/[id]/task-view.tsx +143 -51
  237. package/src/server/dash/app/dash/tasks/composer.css +4 -0
  238. package/src/server/dash/app/dash/tasks/composer.tsx +6 -5
  239. package/src/server/dash/app/dash/tasks/list/task.ts +29 -1
  240. package/src/server/dash/app/dash/tasks/list/tasks-list.css +20 -7
  241. package/src/server/dash/app/dash/tasks/list/tasks-list.tsx +256 -109
  242. package/src/server/dash/app/dash/tasks/list/tasks-section.tsx +9 -13
  243. package/src/server/dash/app/dash/tasks/page.tsx +3 -35
  244. package/src/server/dash/comps/frame/loading-card.tsx +4 -3
  245. package/src/server/dash/comps/frame/page-head.css +10 -0
  246. package/src/server/dash/comps/frame/page-head.tsx +3 -2
  247. package/src/server/dash/comps/frame/task-toasts.tsx +196 -50
  248. package/src/server/dash/comps/nav/side-toggle.tsx +16 -5
  249. package/src/server/dash/comps/ui/card.css +1 -0
  250. package/src/server/dash/comps/ui/filter.css +64 -0
  251. package/src/server/dash/comps/ui/filter.tsx +336 -0
  252. package/src/server/dash/comps/ui/icons.ts +2 -0
  253. package/src/server/dash/comps/ui/menu.tsx +9 -1
  254. package/src/server/dash/comps/ui/select.tsx +2 -2
  255. package/src/server/dash/comps/ui/toast.css +3 -2
  256. package/src/server/dash/comps/ui/toolbar.css +14 -0
  257. package/src/server/dash/utils/client.ts +21 -0
  258. package/src/server/dash/utils/format.ts +12 -4
  259. package/src/server/dash/utils/paged.ts +14 -6
  260. package/dist/actions-Mk3FSlpJ.js +0 -20
  261. package/dist/archive-sweep-CtBcARgN.js +0 -1
  262. package/dist/auth-BFny--17.js +0 -1
  263. package/dist/auth-DWHIzqbA.js +0 -1
  264. package/dist/credentials-B1jv6dkg.js +0 -1
  265. package/dist/dash/public/assets/chunks/agents-grid-951584b6f4c4314e.js +0 -1
  266. package/dist/dash/public/assets/chunks/composer-5534be50bc12385e.js +0 -1
  267. package/dist/dash/public/assets/chunks/composer-d10d4b1d54c4f751.js +0 -1
  268. package/dist/dash/public/assets/chunks/credentials-list-bc5bfcab058176c5.js +0 -2
  269. package/dist/dash/public/assets/chunks/format-eb03fc9d9744d960.js +0 -1
  270. package/dist/dash/public/assets/chunks/heads-f3bcd289663d48fa.js +0 -1
  271. package/dist/dash/public/assets/chunks/instructions-d0a4b0d95009c262.js +0 -1
  272. package/dist/dash/public/assets/chunks/paged-bc6fa0c2b9d52ed7.js +0 -1
  273. package/dist/dash/public/assets/chunks/runners-list-1901af8a5dea1f09.js +0 -1
  274. package/dist/dash/public/assets/chunks/shared-init-88cce66bb3cfe1e5.js +0 -5
  275. package/dist/dash/public/assets/chunks/shared-init-ffb3397e494137c9.js +0 -2
  276. package/dist/dash/public/assets/chunks/task-actions-8e1d93c788d001df.js +0 -1
  277. package/dist/dash/public/assets/chunks/task-fa8b82e95e771c4a.js +0 -1
  278. package/dist/dash/public/assets/chunks/task-view-6d7618d2820a5cb4.js +0 -3
  279. package/dist/dash/public/assets/chunks/tasks-list-f4784e5cbd0ed785.js +0 -1
  280. package/dist/dash/public/assets/dash-9e02d5d1a6d42ee3.css +0 -1
  281. package/dist/dash/public/assets/dash-account-04859899c1838ada.css +0 -1
  282. package/dist/dash/public/assets/dash-agents-9e678137267dec07.css +0 -1
  283. package/dist/dash/public/assets/dash-agents-new-26fa27b17ef9b8d8.css +0 -1
  284. package/dist/dash/public/assets/dash-agents-param-slug-b975c48f8abf3444.css +0 -1
  285. package/dist/dash/public/assets/dash-agents-param-slug-edit-e13fda599bb04843.css +0 -1
  286. package/dist/dash/public/assets/dash-agents-param-slug-platforms-70292932cb27bc96.css +0 -1
  287. package/dist/dash/public/assets/dash-agents-param-slug-settings-71f9a86251723fcc.css +0 -1
  288. package/dist/dash/public/assets/dash-agents-param-slug-tasks-fb8eb2ed71006601.css +0 -1
  289. package/dist/dash/public/assets/dash-agents-param-slug-usage-7c8740f1cdd52c71.css +0 -1
  290. package/dist/dash/public/assets/dash-settings-8eb818da462227e8.css +0 -1
  291. package/dist/dash/public/assets/dash-settings-param-tab-849a1a9542e273f5.css +0 -1
  292. package/dist/dash/public/assets/dash-tasks-81e510e0b6931b42.css +0 -1
  293. package/dist/dash/public/assets/dash-tasks-param-id-bbd2a83342f2ec10.css +0 -1
  294. package/dist/dash/public/assets/dash-usage-8e0259e03eaed1bd.css +0 -1
  295. package/dist/dash/public/assets/pnext-client-03b03b254e525e82.js +0 -1
  296. package/dist/dash/public/assets/pnext-client-1c7859bb888f4ef0.js +0 -1
  297. package/dist/dash/public/assets/pnext-client-3c748afe963fb05d.js +0 -1
  298. package/dist/dash/public/assets/pnext-client-4f47c2cae220f107.js +0 -1
  299. package/dist/dash/public/assets/pnext-client-6ab9fd9b53b794d2.js +0 -1
  300. package/dist/dash/public/assets/pnext-client-6c241786342498e4.js +0 -1
  301. package/dist/dash/public/assets/pnext-client-80b56d420f02b808.js +0 -1
  302. package/dist/dash/public/assets/pnext-client-83135c17bae850a3.js +0 -1
  303. package/dist/dash/public/assets/pnext-client-8e6fa4302ae0396f.js +0 -1
  304. package/dist/dash/public/assets/pnext-client-932c9d8cc0717fc8.js +0 -1
  305. package/dist/dash/public/assets/pnext-client-a42ae63d4de113f9.js +0 -1
  306. package/dist/dash/public/assets/pnext-client-d2ee6f8c1e337032.js +0 -1
  307. package/dist/dash/public/assets/pnext-client-d513f65ec23b7f20.js +0 -1
  308. package/dist/dash/public/assets/pnext-client-ecb88e2a8a109954.js +0 -1
  309. package/dist/dash/public/assets/pnext-client-f1545ee6270bbf9a.js +0 -1
  310. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/boot-B2MFTRO2.js +0 -30
  311. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/build-tier-XJJSL5FR.js +0 -2704
  312. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-2HFY3DQT.js +0 -208
  313. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-2ICEVELW.js +0 -834
  314. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-3UPROT2C.js +0 -35
  315. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-4P5CMIYT.js +0 -1582
  316. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-4TKZKZ3Q.js +0 -131
  317. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-5RDEILQB.js +0 -437
  318. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-62KEQM43.js +0 -25
  319. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-6KQSWT6D.js +0 -831
  320. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-7DCNCW6O.js +0 -724
  321. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-B4THCTQP.js +0 -22
  322. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-C2LIV2MM.js +0 -172
  323. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-CCATPVTW.js +0 -378
  324. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-COXJAPTU.js +0 -89
  325. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-E6IXL2NJ.js +0 -6270
  326. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-FLGRBFAH.js +0 -1198
  327. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-FTJVHFWD.js +0 -61
  328. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-H523KSIH.js +0 -5151
  329. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-HT6KKX6A.js +0 -20
  330. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-JESFYECC.js +0 -438
  331. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-JRPJM2XY.js +0 -17
  332. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-L2IWDUXG.js +0 -107
  333. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-L5P4Y4UC.js +0 -183
  334. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-NQE46AZN.js +0 -647
  335. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-PA4QEARJ.js +0 -129
  336. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-PZ5AXOLW.js +0 -7146
  337. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-SNVPTULL.js +0 -2397
  338. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-T3QZT3PG.js +0 -220
  339. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-VC5O2SDP.js +0 -72
  340. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-WZX4V6CM.js +0 -231
  341. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-XUUIDXY5.js +0 -627
  342. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-ZHFDO3PR.js +0 -265
  343. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/compile-CE2DN7ZA.js +0 -18
  344. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/config-UREY7XJT.js +0 -16
  345. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/config-loader-UI2XE3PZ.js +0 -17
  346. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/entry.js +0 -219
  347. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/generate-I2PPTDFD.js +0 -16
  348. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/modules-UVOCE4C2.js +0 -48
  349. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/pipeline-UW47K537.js +0 -963
  350. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/proxy-ITGOVJBW.js +0 -26
  351. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/register-4SA55SWT.js +0 -12579
  352. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/router-JNKHLBCZ.js +0 -505
  353. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/routes-PD6J2NXW.js +0 -54
  354. package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/tsconfig-defaults-ZXEH7RQK.js +0 -15
  355. package/dist/default-Bobztoxf.js +0 -1
  356. package/dist/dispatch-BKeAch9E.js +0 -14
  357. package/dist/exec-RZFLclKX.js +0 -11
  358. package/dist/executor-BvAA7Cgw.js +0 -10
  359. package/dist/http-Bkg_OQ6r.js +0 -1
  360. package/dist/integrations-5xCaXSd-.js +0 -1
  361. package/dist/integrations-BAgdVDhj.js +0 -5
  362. package/dist/log-view-dg0TlKLA.js +0 -1
  363. package/dist/models-_5LVGC3m.js +0 -1
  364. package/dist/queue-6io_NOP3.js +0 -116
  365. package/dist/refresh-BIrmrWYq.js +0 -1
  366. package/dist/rename-CYfy03FE.js +0 -1
  367. package/dist/result-BzaM3inj.js +0 -15
  368. package/dist/run-BDYl0CKl.js +0 -2
  369. package/dist/runner-D7ScbIHJ.js +0 -1
  370. package/dist/schema-CU2iFkp8.js +0 -1
  371. package/dist/serve-CQKZxzFE.js +0 -4
  372. package/dist/store-B94tSate.js +0 -42
  373. package/dist/store-DzqXS2wT.js +0 -8
  374. package/dist/task-C6VAg5WU.js +0 -1
  375. package/dist/task-CgOKgkEG.js +0 -1
  376. package/dist/worker-CXndxmGF.js +0 -9
  377. package/dist/worker-DX7P9kWl.js +0 -1
  378. package/src/server/dash/app/dash/token-from-hash.tsx +0 -17
@@ -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';
@@ -13,6 +13,7 @@ export function Menu({
13
13
  summary,
14
14
  summaryClass,
15
15
  label,
16
+ tip,
16
17
  align = 'right',
17
18
  wide,
18
19
  class: cls,
@@ -21,6 +22,8 @@ export function Menu({
21
22
  summary: ComponentChildren;
22
23
  summaryClass?: string;
23
24
  label?: string;
25
+ /** A styled tooltip in place of the native title, where the layout shows one. */
26
+ tip?: string;
24
27
  align?: 'right' | 'up' | 'left';
25
28
  wide?: boolean;
26
29
  class?: string;
@@ -34,7 +37,8 @@ export function Menu({
34
37
  type="button"
35
38
  class={summaryClass}
36
39
  aria-label={label}
37
- title={label}
40
+ title={tip ? undefined : label}
41
+ data-tip={tip}
38
42
  >
39
43
  {summary}
40
44
  </button>
@@ -131,10 +135,13 @@ export function MoreList({ label, children }: { label: string; children: Compone
131
135
  export function MenuRadio({
132
136
  on,
133
137
  onPick,
138
+ icon,
134
139
  children,
135
140
  }: {
136
141
  on: boolean;
137
142
  onPick: () => void;
143
+ /** An icon path or a ready element. */
144
+ icon?: string | ComponentChildren;
138
145
  children: ComponentChildren;
139
146
  }) {
140
147
  return (
@@ -145,6 +152,7 @@ export function MenuRadio({
145
152
  class={on ? 'pop-item on' : 'pop-item'}
146
153
  onClick={onPick}
147
154
  >
155
+ {typeof icon === 'string' ? <Icon d={icon} /> : icon}
148
156
  <span class="grow">{children}</span>
149
157
  {on ? <Icon d={iCheck} /> : null}
150
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();
@@ -15,8 +15,9 @@
15
15
  .toast {
16
16
  position: relative;
17
17
  display: grid;
18
- gap: 4px;
19
- padding: 10px 12px;
18
+ grid-template-columns: minmax(0, 1fr);
19
+ gap: 6px;
20
+ padding: 14px 16px;
20
21
  border: 1px solid var(--line2);
21
22
  background: var(--tile);
22
23
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
@@ -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-BilSDkvE.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{i as e,l as t}from"./http-Bkg_OQ6r.js";import{Ft as n,dn as r,un as i}from"./store-DzqXS2wT.js";import{c as a}from"./schema-CU2iFkp8.js";import{a as o,i as s,o as c}from"./serve-CQKZxzFE.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-BilSDkvE.js";const t=e(`auth`,{login:async()=>(await import(`./login-BFxX4jJy.js`)).commandLogin,logout:async()=>(await import(`./logout-BHAtw4Z8.js`)).commandLogout,status:async()=>(await import(`./status-D26U--p8.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{s as e}from"./cli-BilSDkvE.js";const t=e(`credentials`,{list:async()=>(await import(`./list-BxEywhHU.js`)).commandCredentialsList,add:async()=>(await import(`./add-ej0X9e3a.js`)).commandCredentialsAdd,login:async()=>(await import(`./login-DkkslfBx.js`)).commandCredentialsLogin,remove:async()=>(await import(`./remove-eQ8y5C5p.js`)).commandCredentialsRemove,default:async()=>(await import(`./default-vYPT26DR.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-c9c4ac4d4a10df83.js";import{a as C}from"./tail-7c27aab8ba268bd9.js";import{a as w,b as A,c as v,d as P}from"./toolbar-a75d2570f07cbb70.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{$2a as p}from"./shared-init-ffb3397e494137c9.js";import"./shared-init-ffb3397e494137c9.js";import{$4a as g,$4d as l}from"./shared-init-ffb3397e494137c9.js";import"./shared-init-ffb3397e494137c9.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
- "use client";import{a,b,c,d}from"./composer-d10d4b1d54c4f751.js";import"./connect-repositories-5389ec8701a3deac.js";import"./composer-data-6f7608fed13f3dd7.js";import"./model-options-15c53331a2f28a4f.js";import"./select-7ae25fd8a7d6c338.js";import"./task-fa8b82e95e771c4a.js";import"./card-e0901d68b79dfa93.js";import"./field-901f1f35c18c39c9.js";import"./format-eb03fc9d9744d960.js";import"./shared-init-ffb3397e494137c9.js";import"./shared-init-ffb3397e494137c9.js";import"./wular-pnext-246221e985d863e5-0.js";import"./shared-init-ffb3397e494137c9.js";import"./shared-init-ffb3397e494137c9.js";import"./shared-init-ffb3397e494137c9.js";import"./shared-init-ffb3397e494137c9.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};