@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.
- package/README.md +69 -70
- package/dist/actions-FzDNxMFf.js +20 -0
- package/dist/{adapter-BKVzTDnn.js → adapter-7SEiVsmp.js} +1 -1
- package/dist/{adapter-B0oYCI0S.js → adapter-BLEfUqoQ.js} +1 -1
- package/dist/{adapter-DPInwbJG.js → adapter-H4GlcKQz.js} +1 -1
- package/dist/{add-CE-70LFs.js → add-B50dIJGd.js} +1 -1
- package/dist/{add-BxpLHnvD.js → add-D7X3gxap.js} +1 -1
- package/dist/{add-ej0X9e3a.js → add-DOEUHIe7.js} +1 -1
- package/dist/{add-U-pty9qJ.js → add-QExQhTzi.js} +1 -1
- package/dist/{add-json-CEa-6luW.js → add-json-Ck4KIZrT.js} +1 -1
- package/dist/{agent-JdtZozvP.js → agent-BPtnEf1q.js} +1 -1
- package/dist/{agent-BsYx3Odz.js → agent-BlQ_dNNm.js} +2 -2
- package/dist/{alias-DX-Bm86x.js → alias-BwQBovke.js} +1 -1
- package/dist/{app-BT5f7zL5.js → app-y6BYm2eH.js} +1 -1
- package/dist/{approvals-C-AvFt6s.js → approvals-Cc9cq5T1.js} +2 -2
- package/dist/{approve-DOmpQRNd.js → approve-oO9k2fnK.js} +2 -2
- package/dist/{apps-CjfrZyM5.js → apps-CU2YalX8.js} +1 -1
- package/dist/{archive-BziJ1rQ-.js → archive-C5c_HQS1.js} +2 -2
- package/dist/{archive-BUB8gFKD.js → archive-CemlWlVY.js} +2 -2
- package/dist/archive-sweep-ehg-fWIt.js +1 -0
- package/dist/{args-BOEEdpWk.js → args-DcBCtXhz.js} +1 -1
- package/dist/{ask-dE3U3ss2.js → ask-Chu7Twu_.js} +2 -2
- package/dist/auth-BOyXPOtu.js +1 -0
- package/dist/auth-XbqKSbcD.js +1 -0
- package/dist/{chat-bridge-BS9WtP3X.js → chat-bridge-DXgZItGP.js} +1 -1
- package/dist/{chat-B_yhNTo0.js → chat-cknlIhVh.js} +1 -1
- package/dist/{cli-BilSDkvE.js → cli-B1ObVrL4.js} +5 -5
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +1 -1
- package/dist/{client-D9IoAuDD.js → client-31YzOj-i.js} +1 -1
- package/dist/{config-Da_cwoxI.js → config-DAE_qHYA.js} +1 -1
- package/dist/{create-C_iMJV4Y.js → create-CM8B8JxD.js} +1 -1
- package/dist/credentials-BXD4Qptk.js +1 -0
- package/dist/dash/manifest.json +934 -1014
- package/dist/dash/public/assets/chunks/{agent-pills-c9c4ac4d4a10df83.js → agent-pills-b6a6da91c9559d9f.js} +1 -1
- package/dist/dash/public/assets/chunks/{agent-settings-form-8be2ddab074aba6d.js → agent-settings-form-b615c677046cd6f2.js} +1 -1
- package/dist/dash/public/assets/chunks/agents-grid-f2e7b4ff9e11b6e3.js +1 -0
- package/dist/dash/public/assets/chunks/{badge-676b01e0c615bf7b.js → badge-215c7b2631dafc69.js} +1 -1
- package/dist/dash/public/assets/chunks/{card-e0901d68b79dfa93.js → card-e86dcc81326d2b14.js} +1 -1
- package/dist/dash/public/assets/chunks/{combo-41234c24668b1db1.js → combo-09e246dc9a517fa8.js} +1 -1
- package/dist/dash/public/assets/chunks/composer-417166b029f48c47.js +1 -0
- package/dist/dash/public/assets/chunks/composer-645ae8fa97a35280.js +1 -0
- package/dist/dash/public/assets/chunks/{confirm-f2fe4ba9905a89c6.js → confirm-5ae484241ad888fd.js} +1 -1
- package/dist/dash/public/assets/chunks/{connect-apps-aa2a3d82e48ed8c3.js → connect-apps-4147c45f45fde2b1.js} +1 -1
- package/dist/dash/public/assets/chunks/{connect-repositories-5389ec8701a3deac.js → connect-repositories-77591110836bdf03.js} +1 -1
- package/dist/dash/public/assets/chunks/credentials-list-e005a0783ec93465.js +2 -0
- package/dist/dash/public/assets/chunks/{custom-range-4761ab14f05149df.js → custom-range-463e119af4681c61.js} +1 -1
- package/dist/dash/public/assets/chunks/{editor-bfe8cd854f8001be.js → editor-804b84f4fe6539cd.js} +4 -4
- package/dist/dash/public/assets/chunks/{engines-list-f1191390f5715b39.js → engines-list-ceab51f13c690e8c.js} +1 -1
- package/dist/dash/public/assets/chunks/{field-901f1f35c18c39c9.js → field-aa0a4b98a976781e.js} +1 -1
- package/dist/dash/public/assets/chunks/filter-91144ac2eec6297f.js +1 -0
- package/dist/dash/public/assets/chunks/format-105c706345987fb2.js +1 -0
- package/dist/dash/public/assets/chunks/heads-a42817b32d2d7f08.js +1 -0
- package/dist/dash/public/assets/chunks/{instructions-052fa45a9daf6db6.js → instructions-3a1dcaff2d868aa5.js} +1 -1
- package/dist/dash/public/assets/chunks/instructions-6c6f981fffaa31e4.js +1 -0
- package/dist/dash/public/assets/chunks/{list-1d259660d7612c5f.js → list-7270361464fc3c04.js} +1 -1
- package/dist/dash/public/assets/chunks/{mcp-list-e3bebbbe831393b8.js → mcp-list-2e715d48666b54ad.js} +1 -1
- package/dist/dash/public/assets/chunks/{models-list-44f857a469ca04d5.js → models-list-d3c40f94c761a6e5.js} +1 -1
- package/dist/dash/public/assets/chunks/paged-3ddb6077bef42752.js +1 -0
- package/dist/dash/public/assets/chunks/{platform-actions-d1426602049926d2.js → platform-actions-271ec3b99a64280b.js} +1 -1
- package/dist/dash/public/assets/chunks/runners-list-767e49c7d0ec833a.js +1 -0
- package/dist/dash/public/assets/chunks/{segmented-358ff2b4992b8384.js → segmented-de4386ccaac7304d.js} +1 -1
- package/dist/dash/public/assets/chunks/{select-7ae25fd8a7d6c338.js → select-a90307706cffa6e0.js} +1 -1
- package/dist/dash/public/assets/chunks/{sentinel-c972a33dc69a5135.js → sentinel-b5e032b38604dfd3.js} +1 -1
- package/dist/dash/public/assets/chunks/shared-init-7f81ae7bc8c82438.js +2 -0
- package/dist/dash/public/assets/chunks/shared-init-933c7f9ee85be766.js +5 -0
- package/dist/dash/public/assets/chunks/{tail-7c27aab8ba268bd9.js → tail-4891e727ee526792.js} +1 -1
- package/dist/dash/public/assets/chunks/task-actions-ce854925a2dc78fd.js +1 -0
- package/dist/dash/public/assets/chunks/task-ddfddeaf07fb684c.js +1 -0
- package/dist/dash/public/assets/chunks/task-view-c37dcee08f21a279.js +5 -0
- package/dist/dash/public/assets/chunks/tasks-list-baef587999f322d8.js +1 -0
- package/dist/dash/public/assets/chunks/{toolbar-a75d2570f07cbb70.js → toolbar-8d98313606ad8a2d.js} +1 -1
- package/dist/dash/public/assets/chunks/{versions-list-fc2e0d2a7382e049.js → versions-list-532690efd9f1b0ea.js} +1 -1
- package/dist/dash/public/assets/dash-49ca85b59ac65c20.css +1 -0
- package/dist/dash/public/assets/dash-account-edc56e85dbaaabe0.css +1 -0
- package/dist/dash/public/assets/dash-agents-edba57b67e4005d0.css +1 -0
- package/dist/dash/public/assets/dash-agents-new-fe22253fbada2fbf.css +1 -0
- package/dist/dash/public/assets/dash-agents-param-slug-adf52e9dacb2d825.css +1 -0
- package/dist/dash/public/assets/dash-agents-param-slug-edit-a2937a347689ef29.css +1 -0
- package/dist/dash/public/assets/dash-agents-param-slug-platforms-265ba13db32a460d.css +1 -0
- package/dist/dash/public/assets/dash-agents-param-slug-settings-8afc52eb0372bc4b.css +1 -0
- package/dist/dash/public/assets/dash-agents-param-slug-tasks-6193e646be68dbd2.css +1 -0
- package/dist/dash/public/assets/dash-agents-param-slug-usage-ceadb3a1c911c402.css +1 -0
- package/dist/dash/public/assets/dash-settings-cf1997cd7f72e518.css +1 -0
- package/dist/dash/public/assets/dash-settings-param-tab-b44dac8e79a560e6.css +1 -0
- package/dist/dash/public/assets/dash-tasks-916c7100a8058aa3.css +1 -0
- package/dist/dash/public/assets/dash-tasks-param-id-194a6ffc20e872f2.css +1 -0
- package/dist/dash/public/assets/dash-usage-40940b289f85e0b6.css +1 -0
- package/dist/dash/public/assets/pnext-client-13aee92bef5c9e3f.js +1 -0
- package/dist/dash/public/assets/pnext-client-1f2686b2044f0df6.js +1 -0
- package/dist/dash/public/assets/pnext-client-26130234ebad7067.js +1 -0
- package/dist/dash/public/assets/pnext-client-311e35b0076bf406.js +1 -0
- package/dist/dash/public/assets/pnext-client-4ade1bf75c9c3d87.js +1 -0
- package/dist/dash/public/assets/pnext-client-61cd31b687ede1da.js +1 -0
- package/dist/dash/public/assets/pnext-client-61db65dc4223217a.js +1 -0
- package/dist/dash/public/assets/pnext-client-6ea656e7705e3f2a.js +1 -0
- package/dist/dash/public/assets/pnext-client-7fd0f793f0322cb9.js +1 -0
- package/dist/dash/public/assets/pnext-client-88159c0840fcfa4a.js +1 -0
- package/dist/dash/public/assets/pnext-client-b03f0c47c066b4f3.js +1 -0
- package/dist/dash/public/assets/{pnext-client-1b9ab0963a8ff77b.js → pnext-client-d6478835f543f901.js} +1 -1
- package/dist/dash/public/assets/pnext-client-dadb8359021ed590.js +1 -0
- package/dist/dash/public/assets/pnext-client-de07532d6aaebf2c.js +1 -0
- package/dist/dash/public/assets/pnext-client-f87a31890c8ff224.js +1 -0
- package/dist/dash/public/assets/pnext-client-ffe1c123a8e2a350.js +1 -0
- package/dist/dash/server/bundle-0.1.6-b29ec45cb963d47f/entry.js +2 -0
- package/dist/{default-vYPT26DR.js → default-BMvUMTFp.js} +1 -1
- package/dist/default-B_nKaX0-.js +1 -0
- package/dist/{delete-D8gEwoOj.js → delete-Bjteibld.js} +2 -2
- package/dist/{delete-z1_86nf6.js → delete-riCIKZwj.js} +2 -2
- package/dist/{disable-DVKd-0Xb.js → disable-DQC56YFy.js} +1 -1
- package/dist/{discover-Dvr_3_Xr.js → discover-Qanr5TEO.js} +1 -1
- package/dist/{discover-Df-a8K4R.js → discover-lgTYwoQp.js} +2 -2
- package/dist/dispatch-BsW_1m7e.js +14 -0
- package/dist/{docs-DKJnqZqt.js → docs-DFs7lOJp.js} +1 -1
- package/dist/{docs-BX65z2Iu.js → docs-DKROso-4.js} +2 -2
- package/dist/{enable-C8Zf_wpN.js → enable-D2DqZvcU.js} +1 -1
- package/dist/{env-CRf6wkM2.js → env-YRY3I60r.js} +1 -1
- package/dist/exec-DuUkLMqg.js +11 -0
- package/dist/executor-vMppVLB6.js +10 -0
- package/dist/flow/builtin/review.js +1 -1
- package/dist/flow/index.d.ts +1 -1
- package/dist/flow/index.js +1 -1
- package/dist/{flow-17k25MHt.js → flow-DmERAnR8.js} +1 -1
- package/dist/{github-actions-DwUzm4hC.js → github-actions-C_NkHVJq.js} +1 -1
- package/dist/http-D01Udu4u.js +1 -0
- package/dist/{index-CZjFX5zV.d.ts → index-B1L4zXZH.d.ts} +2 -1
- package/dist/{init-CoMfFxbG.js → init-Bd6JHzBc.js} +1 -1
- package/dist/integrations-B2CavXR1.js +5 -0
- package/dist/integrations-D1Dwy1kt.js +1 -0
- package/dist/lib/broker.js +2 -2
- package/dist/{list-DX-z3SBp.js → list-4Uo-0v9s.js} +1 -1
- package/dist/{list-BAKvxSbh.js → list-B0ujEZhd.js} +3 -3
- package/dist/{list-BYiG8Zav.js → list-B5oa1Bhy.js} +2 -2
- package/dist/{list-BxEywhHU.js → list-BjE_l6la.js} +1 -1
- package/dist/{list-VToARh3C.js → list-Ck9ibCs1.js} +1 -1
- package/dist/{list-CIW2joV1.js → list-DhgK4Zc4.js} +1 -1
- package/dist/{list-DpCf4G-H.js → list-KvL7AUhD.js} +2 -2
- package/dist/{list-C5w01-8q.js → list-byYLBl1U.js} +1 -1
- package/dist/{load-BpEsAn51.js → load-SnZd7xG1.js} +1 -1
- package/dist/{local-H3uvqEbq.js → local-BRy1EUq2.js} +1 -1
- package/dist/log-view-DeJstSkw.js +3 -0
- package/dist/{login-DkkslfBx.js → login-C-ahtDKV.js} +1 -1
- package/dist/{login-BFxX4jJy.js → login-zpwke8g1.js} +1 -1
- package/dist/{logout-BHAtw4Z8.js → logout-CI6Kf-T6.js} +1 -1
- package/dist/{maintenance-C5FklUw3.js → maintenance-BAzr9Jlr.js} +1 -1
- package/dist/{match-CXAjDhg7.js → match-DxV1d49D.js} +1 -1
- package/dist/{mcp-BgKb2Cdk.js → mcp-CmcL1MCG.js} +1 -1
- package/dist/{mcp-CCZOAo06.js → mcp-mhXwtGQT.js} +1 -1
- package/dist/{migrate-N-85_N7J.js → migrate-Czh3TEK5.js} +1 -1
- package/dist/{migrate-C4vM7DQN.js → migrate-w7KfzUAR.js} +1 -1
- package/dist/{model-Bs1StDo3.js → model-JRoTH9QK.js} +1 -1
- package/dist/models-C-S7HqSb.js +1 -0
- package/dist/{prompt-CEuBMNhk.js → prompt-CMXmt2l9.js} +4 -4
- package/dist/{push-CUC55Bqd.js → push-B8BhTyZs.js} +1 -1
- package/dist/queue-CirjEskI.js +117 -0
- package/dist/refresh-Bmy2r1Ee.js +1 -0
- package/dist/{remote-miQNTVRa.js → remote-CxFnEjZl.js} +1 -1
- package/dist/{remove-B93LNkZI.js → remove-C15WLaXT.js} +1 -1
- package/dist/{remove-C5_xggx7.js → remove-CTZYjjSr.js} +1 -1
- package/dist/{remove-eQ8y5C5p.js → remove-CTl-H0f0.js} +1 -1
- package/dist/{remove-CuH8a3L9.js → remove-DX2FVo5b.js} +1 -1
- package/dist/rename-D1g4TnHQ.js +1 -0
- package/dist/{result-BEtQZHaY.js → result-D49VN8PM.js} +3 -3
- package/dist/result-DGWyUHYU.js +18 -0
- package/dist/{resume-DYzKvyEw.js → resume-ywzc7z6A.js} +2 -2
- package/dist/{review-oIBeECZE.js → review-ZC0xG8XY.js} +2 -2
- package/dist/{rotate-key-IdMYH7gg.js → rotate-key-Bf8_99ck.js} +1 -1
- package/dist/{run-CTtd0Znc.js → run-D7SJ-ieT.js} +2 -2
- package/dist/run-DoRQSC_K.js +2 -0
- package/dist/{run-CawRGnOg.js → run-ukCf2Mdy.js} +1 -1
- package/dist/runner-D-REfOUe.js +1 -0
- package/dist/{runner-sUpWJ_k0.js → runner-wDYhkVsM.js} +1 -1
- package/dist/schema-DoNO0dPh.js +1 -0
- package/dist/sdk.d.ts +4 -2
- package/dist/sdk.js +1 -1
- package/dist/serve-BJ_Mbm2m.js +8 -0
- package/dist/{serve-CPnmrKyf.js → serve-C1MMhM1F.js} +2 -2
- package/dist/{serve-GmRO89s5.js → serve-DtrOHaoS.js} +2 -2
- package/dist/{serve-CE8YV2e9.js → serve-P9pFkEnE.js} +1 -1
- package/dist/{serve-BTeomYxW.js → serve-yjSw0B1a.js} +1 -1
- package/dist/{server-Kb22cWfF.js → server-DDWTnmbx.js} +1 -1
- package/dist/{setup-host-GFTUzzZJ.js → setup-host-L6Rnn5Cz.js} +1 -1
- package/dist/{shared-DVtzWhUT.js → shared-XsUX_ZZb.js} +1 -1
- package/dist/{show-COTZEYgc.js → show-CU-jqJ90.js} +1 -1
- package/dist/{show-CMUg8SJu.js → show-DVJmB2u-.js} +1 -1
- package/dist/{status-D26U--p8.js → status-CBydR7LE.js} +1 -1
- package/dist/{steer-C6uARLp5.js → steer-Cm_sHZqs.js} +2 -2
- package/dist/{stop-BrGI3hSS.js → stop-DJS7DAPJ.js} +1 -1
- package/dist/{stop-ByCAlbmN.js → stop-TrebIIuv.js} +2 -2
- package/dist/store-BrNMqJgk.js +42 -0
- package/dist/store-j8icrG0v.js +19 -0
- package/dist/task-C8lmcNsf.js +1 -0
- package/dist/{task-DeglY79z.js → task-CpUI19o2.js} +4 -4
- package/dist/task-CvSqiwxo.js +1 -0
- package/dist/{test-NEbhlxvo.js → test-CDKz4jY_.js} +1 -1
- package/dist/{tools-D0Zfs8Hx.js → tools-DBFeoosk.js} +1 -1
- package/dist/{types-I5Cwtl_K.d.ts → types-DMGBYB_K.d.ts} +3 -1
- package/dist/{unalias-C9NqmSDq.js → unalias-BfQFBnuK.js} +1 -1
- package/dist/{update-BTxYQj7Z.js → update-C4FFOie8.js} +1 -1
- package/dist/{upgrade-hA0yWBvx.js → upgrade-DLJqMnUQ.js} +2 -2
- package/dist/{usage-BhqoCjvE.js → usage-CSh-xwQ2.js} +1 -1
- package/dist/{usage-C4d9X2Uq.js → usage-D8mc4qXK.js} +1 -1
- package/dist/{watch-DtRuC0Wc.js → watch-CQu-tJKZ.js} +2 -2
- package/dist/{watch-CSdj24ct.js → watch-DmwaEvoi.js} +2 -2
- package/dist/{wire-BeT1Axeo.js → wire-DzGLZ3-O.js} +1 -1
- package/dist/worker-BLKTMLqa.js +1 -0
- package/dist/worker-nHemduM_.js +9 -0
- package/dist/{workflow-Dcmdooi8.js → workflow-IrouAus_.js} +1 -1
- package/docs/cli.md +145 -0
- package/docs/mcp.md +1 -1
- package/migrations/0000_initial.sql +8 -0
- package/migrations/meta/0000_snapshot.json +75 -1
- package/migrations/meta/_journal.json +1 -1
- package/package.json +3 -2
- package/plugins/agents/skills/coder/SKILL.md +1 -0
- package/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/skills/dispatch/SKILL.md +1 -1
- package/plugins/cursor/.cursor-plugin/plugin.json +1 -1
- package/plugins/cursor/skills/coder/SKILL.md +1 -0
- package/src/client/index.ts +10 -2
- package/src/client/types.ts +18 -0
- package/src/core/defaults.ts +36 -0
- package/src/core/task/log-view.ts +120 -6
- package/src/server/dash/app/dash/agents/(list)/agent-menu.tsx +4 -0
- package/src/server/dash/app/dash/agents/(list)/agents-grid.tsx +18 -35
- package/src/server/dash/app/dash/agents/(list)/loading.tsx +7 -1
- package/src/server/dash/app/dash/agents/[slug]/(tabs)/layout.tsx +2 -1
- package/src/server/dash/app/dash/layout.css +58 -1
- package/src/server/dash/app/dash/layout.tsx +29 -7
- package/src/server/dash/app/dash/settings/[tab]/credentials-list.tsx +20 -13
- package/src/server/dash/app/dash/settings/[tab]/page.tsx +1 -1
- package/src/server/dash/app/dash/settings/[tab]/runners-list.tsx +13 -12
- package/src/server/dash/app/dash/tasks/[id]/activity.tsx +49 -4
- package/src/server/dash/app/dash/tasks/[id]/task-actions.tsx +43 -6
- package/src/server/dash/app/dash/tasks/[id]/task-view.css +52 -31
- package/src/server/dash/app/dash/tasks/[id]/task-view.tsx +143 -51
- package/src/server/dash/app/dash/tasks/composer.css +4 -0
- package/src/server/dash/app/dash/tasks/composer.tsx +6 -5
- package/src/server/dash/app/dash/tasks/list/task.ts +29 -1
- package/src/server/dash/app/dash/tasks/list/tasks-list.css +20 -7
- package/src/server/dash/app/dash/tasks/list/tasks-list.tsx +256 -109
- package/src/server/dash/app/dash/tasks/list/tasks-section.tsx +9 -13
- package/src/server/dash/app/dash/tasks/page.tsx +3 -35
- package/src/server/dash/comps/frame/loading-card.tsx +4 -3
- package/src/server/dash/comps/frame/page-head.css +10 -0
- package/src/server/dash/comps/frame/page-head.tsx +3 -2
- package/src/server/dash/comps/frame/task-toasts.tsx +196 -50
- package/src/server/dash/comps/nav/side-toggle.tsx +16 -5
- package/src/server/dash/comps/ui/card.css +1 -0
- package/src/server/dash/comps/ui/filter.css +64 -0
- package/src/server/dash/comps/ui/filter.tsx +336 -0
- package/src/server/dash/comps/ui/icons.ts +2 -0
- package/src/server/dash/comps/ui/menu.tsx +9 -1
- package/src/server/dash/comps/ui/select.tsx +2 -2
- package/src/server/dash/comps/ui/toast.css +3 -2
- package/src/server/dash/comps/ui/toolbar.css +14 -0
- package/src/server/dash/utils/client.ts +21 -0
- package/src/server/dash/utils/format.ts +12 -4
- package/src/server/dash/utils/paged.ts +14 -6
- package/dist/actions-Mk3FSlpJ.js +0 -20
- package/dist/archive-sweep-CtBcARgN.js +0 -1
- package/dist/auth-BFny--17.js +0 -1
- package/dist/auth-DWHIzqbA.js +0 -1
- package/dist/credentials-B1jv6dkg.js +0 -1
- package/dist/dash/public/assets/chunks/agents-grid-951584b6f4c4314e.js +0 -1
- package/dist/dash/public/assets/chunks/composer-5534be50bc12385e.js +0 -1
- package/dist/dash/public/assets/chunks/composer-d10d4b1d54c4f751.js +0 -1
- package/dist/dash/public/assets/chunks/credentials-list-bc5bfcab058176c5.js +0 -2
- package/dist/dash/public/assets/chunks/format-eb03fc9d9744d960.js +0 -1
- package/dist/dash/public/assets/chunks/heads-f3bcd289663d48fa.js +0 -1
- package/dist/dash/public/assets/chunks/instructions-d0a4b0d95009c262.js +0 -1
- package/dist/dash/public/assets/chunks/paged-bc6fa0c2b9d52ed7.js +0 -1
- package/dist/dash/public/assets/chunks/runners-list-1901af8a5dea1f09.js +0 -1
- package/dist/dash/public/assets/chunks/shared-init-88cce66bb3cfe1e5.js +0 -5
- package/dist/dash/public/assets/chunks/shared-init-ffb3397e494137c9.js +0 -2
- package/dist/dash/public/assets/chunks/task-actions-8e1d93c788d001df.js +0 -1
- package/dist/dash/public/assets/chunks/task-fa8b82e95e771c4a.js +0 -1
- package/dist/dash/public/assets/chunks/task-view-6d7618d2820a5cb4.js +0 -3
- package/dist/dash/public/assets/chunks/tasks-list-f4784e5cbd0ed785.js +0 -1
- package/dist/dash/public/assets/dash-9e02d5d1a6d42ee3.css +0 -1
- package/dist/dash/public/assets/dash-account-04859899c1838ada.css +0 -1
- package/dist/dash/public/assets/dash-agents-9e678137267dec07.css +0 -1
- package/dist/dash/public/assets/dash-agents-new-26fa27b17ef9b8d8.css +0 -1
- package/dist/dash/public/assets/dash-agents-param-slug-b975c48f8abf3444.css +0 -1
- package/dist/dash/public/assets/dash-agents-param-slug-edit-e13fda599bb04843.css +0 -1
- package/dist/dash/public/assets/dash-agents-param-slug-platforms-70292932cb27bc96.css +0 -1
- package/dist/dash/public/assets/dash-agents-param-slug-settings-71f9a86251723fcc.css +0 -1
- package/dist/dash/public/assets/dash-agents-param-slug-tasks-fb8eb2ed71006601.css +0 -1
- package/dist/dash/public/assets/dash-agents-param-slug-usage-7c8740f1cdd52c71.css +0 -1
- package/dist/dash/public/assets/dash-settings-8eb818da462227e8.css +0 -1
- package/dist/dash/public/assets/dash-settings-param-tab-849a1a9542e273f5.css +0 -1
- package/dist/dash/public/assets/dash-tasks-81e510e0b6931b42.css +0 -1
- package/dist/dash/public/assets/dash-tasks-param-id-bbd2a83342f2ec10.css +0 -1
- package/dist/dash/public/assets/dash-usage-8e0259e03eaed1bd.css +0 -1
- package/dist/dash/public/assets/pnext-client-03b03b254e525e82.js +0 -1
- package/dist/dash/public/assets/pnext-client-1c7859bb888f4ef0.js +0 -1
- package/dist/dash/public/assets/pnext-client-3c748afe963fb05d.js +0 -1
- package/dist/dash/public/assets/pnext-client-4f47c2cae220f107.js +0 -1
- package/dist/dash/public/assets/pnext-client-6ab9fd9b53b794d2.js +0 -1
- package/dist/dash/public/assets/pnext-client-6c241786342498e4.js +0 -1
- package/dist/dash/public/assets/pnext-client-80b56d420f02b808.js +0 -1
- package/dist/dash/public/assets/pnext-client-83135c17bae850a3.js +0 -1
- package/dist/dash/public/assets/pnext-client-8e6fa4302ae0396f.js +0 -1
- package/dist/dash/public/assets/pnext-client-932c9d8cc0717fc8.js +0 -1
- package/dist/dash/public/assets/pnext-client-a42ae63d4de113f9.js +0 -1
- package/dist/dash/public/assets/pnext-client-d2ee6f8c1e337032.js +0 -1
- package/dist/dash/public/assets/pnext-client-d513f65ec23b7f20.js +0 -1
- package/dist/dash/public/assets/pnext-client-ecb88e2a8a109954.js +0 -1
- package/dist/dash/public/assets/pnext-client-f1545ee6270bbf9a.js +0 -1
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/boot-B2MFTRO2.js +0 -30
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/build-tier-XJJSL5FR.js +0 -2704
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-2HFY3DQT.js +0 -208
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-2ICEVELW.js +0 -834
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-3UPROT2C.js +0 -35
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-4P5CMIYT.js +0 -1582
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-4TKZKZ3Q.js +0 -131
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-5RDEILQB.js +0 -437
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-62KEQM43.js +0 -25
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-6KQSWT6D.js +0 -831
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-7DCNCW6O.js +0 -724
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-B4THCTQP.js +0 -22
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-C2LIV2MM.js +0 -172
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-CCATPVTW.js +0 -378
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-COXJAPTU.js +0 -89
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-E6IXL2NJ.js +0 -6270
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-FLGRBFAH.js +0 -1198
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-FTJVHFWD.js +0 -61
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-H523KSIH.js +0 -5151
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-HT6KKX6A.js +0 -20
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-JESFYECC.js +0 -438
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-JRPJM2XY.js +0 -17
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-L2IWDUXG.js +0 -107
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-L5P4Y4UC.js +0 -183
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-NQE46AZN.js +0 -647
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-PA4QEARJ.js +0 -129
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-PZ5AXOLW.js +0 -7146
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-SNVPTULL.js +0 -2397
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-T3QZT3PG.js +0 -220
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-VC5O2SDP.js +0 -72
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-WZX4V6CM.js +0 -231
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-XUUIDXY5.js +0 -627
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/chunk-ZHFDO3PR.js +0 -265
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/compile-CE2DN7ZA.js +0 -18
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/config-UREY7XJT.js +0 -16
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/config-loader-UI2XE3PZ.js +0 -17
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/entry.js +0 -219
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/generate-I2PPTDFD.js +0 -16
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/modules-UVOCE4C2.js +0 -48
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/pipeline-UW47K537.js +0 -963
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/proxy-ITGOVJBW.js +0 -26
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/register-4SA55SWT.js +0 -12579
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/router-JNKHLBCZ.js +0 -505
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/routes-PD6J2NXW.js +0 -54
- package/dist/dash/server/bundle-0.1.5-1508b6c99c0d1e68/tsconfig-defaults-ZXEH7RQK.js +0 -15
- package/dist/default-Bobztoxf.js +0 -1
- package/dist/dispatch-BKeAch9E.js +0 -14
- package/dist/exec-RZFLclKX.js +0 -11
- package/dist/executor-BvAA7Cgw.js +0 -10
- package/dist/http-Bkg_OQ6r.js +0 -1
- package/dist/integrations-5xCaXSd-.js +0 -1
- package/dist/integrations-BAgdVDhj.js +0 -5
- package/dist/log-view-dg0TlKLA.js +0 -1
- package/dist/models-_5LVGC3m.js +0 -1
- package/dist/queue-6io_NOP3.js +0 -116
- package/dist/refresh-BIrmrWYq.js +0 -1
- package/dist/rename-CYfy03FE.js +0 -1
- package/dist/result-BzaM3inj.js +0 -15
- package/dist/run-BDYl0CKl.js +0 -2
- package/dist/runner-D7ScbIHJ.js +0 -1
- package/dist/schema-CU2iFkp8.js +0 -1
- package/dist/serve-CQKZxzFE.js +0 -4
- package/dist/store-B94tSate.js +0 -42
- package/dist/store-DzqXS2wT.js +0 -8
- package/dist/task-C6VAg5WU.js +0 -1
- package/dist/task-CgOKgkEG.js +0 -1
- package/dist/worker-CXndxmGF.js +0 -9
- package/dist/worker-DX7P9kWl.js +0 -1
- package/src/server/dash/app/dash/token-from-hash.tsx +0 -17
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { TaskRow } from '@coder/client/types';
|
|
2
|
+
import { byListKey, listRank } from '@coder/core/defaults';
|
|
2
3
|
|
|
3
4
|
/** Task statuses a list filters by. */
|
|
4
5
|
export const STATUSES: Array<[string, string]> = [
|
|
@@ -32,9 +33,36 @@ export const SOURCES: Array<[string, string]> = [
|
|
|
32
33
|
export const sourceLabel = (value: string) =>
|
|
33
34
|
(SOURCES.find(([key]) => key === value) ?? [value, value])[1];
|
|
34
35
|
|
|
35
|
-
export const taskActive = (task: TaskRow) =>
|
|
36
|
+
export const taskActive = (task: Pick<TaskRow, 'status'>) =>
|
|
36
37
|
task.status === 'queued' || task.status === 'running' || task.status === 'waiting';
|
|
37
38
|
|
|
39
|
+
const listKey = (row: TaskRow) => ({
|
|
40
|
+
rank: listRank(row.status),
|
|
41
|
+
createdAt: row.createdAt,
|
|
42
|
+
id: row.task.id,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/** The server's list order. */
|
|
46
|
+
export const listOrder = (a: TaskRow, b: TaskRow) => byListKey(listKey(a), listKey(b));
|
|
47
|
+
|
|
48
|
+
/** Rows refetched first pages added so far, the newest copy of each, in list order. */
|
|
49
|
+
export function addRows(previous: TaskRow[], page: TaskRow[]): TaskRow[] {
|
|
50
|
+
const fetched = new Set(page.map(row => row.task.id));
|
|
51
|
+
return [...page, ...previous.filter(row => !fetched.has(row.task.id))].sort(listOrder);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** The loaded rows with the added ones they lack, each at its latest, in list order. */
|
|
55
|
+
export function withAdded(
|
|
56
|
+
rows: TaskRow[],
|
|
57
|
+
added: TaskRow[],
|
|
58
|
+
latest: Record<string, TaskRow> = {},
|
|
59
|
+
): TaskRow[] {
|
|
60
|
+
const listed = new Set(rows.map(row => row.task.id));
|
|
61
|
+
return [...added.filter(row => !listed.has(row.task.id)), ...rows]
|
|
62
|
+
.map(row => latest[row.task.id] ?? row)
|
|
63
|
+
.sort(listOrder);
|
|
64
|
+
}
|
|
65
|
+
|
|
38
66
|
export const taskTitle = (task: TaskRow) =>
|
|
39
67
|
task.task.name?.trim() ||
|
|
40
68
|
task.task.prompt?.trim() ||
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
width: 160px;
|
|
7
7
|
}
|
|
8
8
|
.tasks th:nth-child(3) {
|
|
9
|
-
width:
|
|
9
|
+
width: 130px;
|
|
10
10
|
}
|
|
11
11
|
.tasks th:nth-child(4) {
|
|
12
|
-
width:
|
|
12
|
+
width: 100px;
|
|
13
13
|
}
|
|
14
14
|
.tasks th:nth-child(5) {
|
|
15
|
-
width:
|
|
15
|
+
width: 204px;
|
|
16
16
|
}
|
|
17
17
|
.tasks td {
|
|
18
18
|
padding-block: 9px;
|
|
@@ -33,12 +33,25 @@
|
|
|
33
33
|
.tasks td:first-child .sub {
|
|
34
34
|
margin-top: 1px;
|
|
35
35
|
}
|
|
36
|
+
.tasks .sub .ic {
|
|
37
|
+
width: 12px;
|
|
38
|
+
height: 12px;
|
|
39
|
+
margin-right: 5px;
|
|
40
|
+
color: var(--dim);
|
|
41
|
+
vertical-align: -2px;
|
|
42
|
+
}
|
|
36
43
|
|
|
37
44
|
@media (max-width: 760px) {
|
|
38
45
|
.tasks {
|
|
39
46
|
min-width: 0;
|
|
40
47
|
}
|
|
41
|
-
.tasks td
|
|
48
|
+
.tasks td {
|
|
49
|
+
padding-block: 0;
|
|
50
|
+
}
|
|
51
|
+
.tasks td:is(.when, .num) {
|
|
52
|
+
order: 1;
|
|
53
|
+
}
|
|
54
|
+
.tasks td:last-child {
|
|
42
55
|
display: flex;
|
|
43
56
|
align-items: center;
|
|
44
57
|
justify-self: end;
|
|
@@ -63,11 +76,11 @@
|
|
|
63
76
|
}
|
|
64
77
|
|
|
65
78
|
/* a row's menu waits at its right edge, above the cover link, and shows on hover, focus or while open */
|
|
66
|
-
.tasks th
|
|
67
|
-
.tasks td
|
|
79
|
+
.tasks th:last-child,
|
|
80
|
+
.tasks td:last-child {
|
|
68
81
|
padding-right: 64px;
|
|
69
82
|
}
|
|
70
|
-
.tasks td
|
|
83
|
+
.tasks td:last-child {
|
|
71
84
|
position: relative;
|
|
72
85
|
}
|
|
73
86
|
.row-acts {
|
|
@@ -2,15 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
import './tasks-list.css';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { dynamic } from '@wular/pnext/dynamic';
|
|
6
|
+
import { useEffect, useRef, useState } from 'preact/hooks';
|
|
6
7
|
|
|
7
8
|
import { client } from '@/utils/client';
|
|
8
9
|
import { formatCount, formatDate, formatDay, formatDuration } from '@/utils/format';
|
|
9
|
-
import {
|
|
10
|
-
|
|
10
|
+
import {
|
|
11
|
+
iAgent,
|
|
12
|
+
iClock,
|
|
13
|
+
iDots,
|
|
14
|
+
iFolder,
|
|
15
|
+
iMonitor,
|
|
16
|
+
iPlug,
|
|
17
|
+
iPlus,
|
|
18
|
+
iTerminal,
|
|
19
|
+
} from '@/comps/ui/icons';
|
|
20
|
+
import { Menu, MenuItem } from '@/comps/ui/menu';
|
|
11
21
|
import { Link } from '@wular/pnext/link';
|
|
22
|
+
import { useRouter } from '@wular/pnext/navigation/client';
|
|
12
23
|
import { usePaged } from '@/utils/paged';
|
|
13
|
-
import type {
|
|
24
|
+
import type {
|
|
25
|
+
IntegrationInfo,
|
|
26
|
+
TaskCounts,
|
|
27
|
+
TaskEvent,
|
|
28
|
+
TaskRow,
|
|
29
|
+
TasksPage,
|
|
30
|
+
} from '@coder/client/types';
|
|
31
|
+
import { BrandIcon } from '@/app/dash/agents/agent/agent-pills';
|
|
14
32
|
import { Card, Empty } from '@/comps/ui/card';
|
|
15
33
|
import { Id } from '@/comps/ui/badge';
|
|
16
34
|
import { ConfirmDialog } from '@/comps/ui/confirm';
|
|
@@ -19,8 +37,8 @@ import { approvalParts } from '@/app/dash/tasks/[id]/task-actions';
|
|
|
19
37
|
import { reasonText } from '@/utils/format';
|
|
20
38
|
import { Status } from './status';
|
|
21
39
|
import { Icon } from '@/comps/ui/icon';
|
|
22
|
-
import {
|
|
23
|
-
import { taskActive } from '@/app/dash/tasks/list/task';
|
|
40
|
+
import { Filter, type Facet } from '@/comps/ui/filter';
|
|
41
|
+
import { addRows, listOrder, taskActive, withAdded } from '@/app/dash/tasks/list/task';
|
|
24
42
|
import { taskTitle } from '@/app/dash/tasks/list/task';
|
|
25
43
|
import { LIST_PAGE } from '@/utils/paged';
|
|
26
44
|
import { Search, Toolbar, queryOf, useFilters } from '@/comps/ui/toolbar';
|
|
@@ -33,6 +51,20 @@ import {
|
|
|
33
51
|
sourceLabel,
|
|
34
52
|
} from '@/app/dash/tasks/list/task';
|
|
35
53
|
import { NeedsCredential } from '@/app/dash/tasks/composer';
|
|
54
|
+
import { useTaskEvents } from '@/comps/frame/task-toasts';
|
|
55
|
+
|
|
56
|
+
const NewTaskButton = dynamic(
|
|
57
|
+
() => import('@/app/dash/tasks/composer').then(m => m.NewTaskButton),
|
|
58
|
+
{
|
|
59
|
+
// TODO: stays disabled after client navigation until pnext SSRs nested dynamic() like Next.js.
|
|
60
|
+
loading: () => (
|
|
61
|
+
<button type="button" class="btn new-task" disabled>
|
|
62
|
+
<Icon d={iPlus} />
|
|
63
|
+
New task
|
|
64
|
+
</button>
|
|
65
|
+
),
|
|
66
|
+
},
|
|
67
|
+
);
|
|
36
68
|
|
|
37
69
|
type Keys = 'q' | 'status' | 'source' | 'agent';
|
|
38
70
|
|
|
@@ -41,9 +73,7 @@ const SOURCE_ICONS: Record<string, string> = {
|
|
|
41
73
|
cli: iTerminal,
|
|
42
74
|
schedule: iClock,
|
|
43
75
|
};
|
|
44
|
-
|
|
45
|
-
/** How often a list with running tasks refreshes their status. */
|
|
46
|
-
const LIVE_MS = 4000;
|
|
76
|
+
const sourceIcon = (source: string) => SOURCE_ICONS[source] ?? iPlug;
|
|
47
77
|
|
|
48
78
|
/** How long ago, under a day; the date after that. */
|
|
49
79
|
function ago(value: number, now: number, tz: string) {
|
|
@@ -56,6 +86,7 @@ function ago(value: number, now: number, tz: string) {
|
|
|
56
86
|
|
|
57
87
|
function TaskRowView({
|
|
58
88
|
task,
|
|
89
|
+
brand,
|
|
59
90
|
back,
|
|
60
91
|
scoped,
|
|
61
92
|
tz,
|
|
@@ -64,6 +95,8 @@ function TaskRowView({
|
|
|
64
95
|
onError,
|
|
65
96
|
}: {
|
|
66
97
|
task: TaskRow;
|
|
98
|
+
/** The source platform's brand art, when it has one. */
|
|
99
|
+
brand?: IntegrationInfo['brand'];
|
|
67
100
|
onDone: (what: RowAction) => void;
|
|
68
101
|
onError: (message: string) => void;
|
|
69
102
|
/** The list to return to, when it is not the plain Tasks page. */
|
|
@@ -90,28 +123,37 @@ function TaskRowView({
|
|
|
90
123
|
{taskTitle(task)}
|
|
91
124
|
</Link>
|
|
92
125
|
<span class="sub">
|
|
93
|
-
{scoped ? null :
|
|
126
|
+
{scoped ? null : (
|
|
127
|
+
<>
|
|
128
|
+
<Icon d={iAgent} />
|
|
129
|
+
{`${task.task.agent} · `}
|
|
130
|
+
</>
|
|
131
|
+
)}
|
|
94
132
|
<Id value={task.task.id} />
|
|
95
133
|
{kind ? ` · ${kind}` : null}
|
|
96
134
|
{task.task.cwd ? (
|
|
97
|
-
|
|
135
|
+
<>
|
|
136
|
+
{' · '}
|
|
137
|
+
<span title={task.task.cwd}>
|
|
138
|
+
<Icon d={iFolder} />
|
|
139
|
+
{folderName(task.task.cwd)}
|
|
140
|
+
</span>
|
|
141
|
+
</>
|
|
98
142
|
) : null}
|
|
99
143
|
</span>
|
|
100
144
|
</td>
|
|
101
145
|
<td>
|
|
102
146
|
<Status status={task.status} />
|
|
103
147
|
</td>
|
|
148
|
+
<td class="when" title={formatDate(task.createdAt, tz)}>
|
|
149
|
+
{ago(task.createdAt, now, tz)}
|
|
150
|
+
</td>
|
|
151
|
+
<td class="num">{formatDuration(elapsed)}</td>
|
|
104
152
|
<td>
|
|
105
153
|
<span class="source" title={sourceLabel(source)}>
|
|
106
|
-
<Icon d={
|
|
154
|
+
{brand ? <BrandIcon brand={brand} /> : <Icon d={sourceIcon(source)} />}
|
|
107
155
|
{sourceLabel(source)}
|
|
108
156
|
</span>
|
|
109
|
-
</td>
|
|
110
|
-
<td class="when" title={formatDate(task.createdAt, tz)}>
|
|
111
|
-
{ago(task.createdAt, now, tz)}
|
|
112
|
-
</td>
|
|
113
|
-
<td class="num">
|
|
114
|
-
{formatDuration(elapsed)}
|
|
115
157
|
<span class="row-acts">
|
|
116
158
|
<RowActions task={task} onDone={onDone} onError={onError} />
|
|
117
159
|
</span>
|
|
@@ -184,6 +226,7 @@ function RowActions({
|
|
|
184
226
|
export function TasksList({
|
|
185
227
|
first,
|
|
186
228
|
platforms,
|
|
229
|
+
brands = {},
|
|
187
230
|
agents = [],
|
|
188
231
|
filters,
|
|
189
232
|
agent,
|
|
@@ -195,7 +238,9 @@ export function TasksList({
|
|
|
195
238
|
first: TasksPage;
|
|
196
239
|
/** Platform ids, the sources besides the dashboard, CLI and schedule. */
|
|
197
240
|
platforms: [string, string][];
|
|
198
|
-
/**
|
|
241
|
+
/** Each platform's brand art, as the Agents page shows it. */
|
|
242
|
+
brands?: Record<string, IntegrationInfo['brand']>;
|
|
243
|
+
/** The first agents, for the agent filter before typing. */
|
|
199
244
|
agents?: [string, string][];
|
|
200
245
|
filters: Record<Keys, string>;
|
|
201
246
|
agent?: string;
|
|
@@ -218,6 +263,26 @@ export function TasksList({
|
|
|
218
263
|
...listFilters(values),
|
|
219
264
|
agent: agent ?? values.agent,
|
|
220
265
|
};
|
|
266
|
+
const facets: Facet<Keys>[] = [
|
|
267
|
+
{ key: 'status', label: 'Status', options: STATUSES, inline: true },
|
|
268
|
+
{
|
|
269
|
+
key: 'source',
|
|
270
|
+
label: 'Source',
|
|
271
|
+
options: [...SOURCES, ...platforms],
|
|
272
|
+
icon: value => (brands[value] ? <BrandIcon brand={brands[value]} /> : sourceIcon(value)),
|
|
273
|
+
},
|
|
274
|
+
];
|
|
275
|
+
if (!agent)
|
|
276
|
+
facets.push({
|
|
277
|
+
key: 'agent',
|
|
278
|
+
label: 'Agent',
|
|
279
|
+
options: agents,
|
|
280
|
+
icon: () => iAgent,
|
|
281
|
+
search: (q, limit) =>
|
|
282
|
+
client.agents
|
|
283
|
+
.list({ cursor: '', limit, q })
|
|
284
|
+
.then(page => page.items.map((row): [string, string] => [row.id, row.name])),
|
|
285
|
+
});
|
|
221
286
|
const list = usePaged<TaskRow>({
|
|
222
287
|
name: `tasks${scope}`,
|
|
223
288
|
fetchPage: cursor => client.tasks.list({ ...options, cursor }),
|
|
@@ -227,97 +292,190 @@ export function TasksList({
|
|
|
227
292
|
});
|
|
228
293
|
const [fresh, setFresh] = useState<{
|
|
229
294
|
rows: Record<string, TaskRow>;
|
|
295
|
+
/** Tasks newer than the loaded pages, on top. */
|
|
296
|
+
added: TaskRow[];
|
|
230
297
|
counts?: TaskCounts;
|
|
231
298
|
query?: string;
|
|
232
|
-
}>({ rows: {} });
|
|
299
|
+
}>({ rows: {}, added: [] });
|
|
233
300
|
const [gone, setGone] = useState<string[]>([]);
|
|
234
301
|
// Rows hidden after an archive or delete come back into view when the filters change.
|
|
235
302
|
useEffect(() => setGone([]), [query]);
|
|
236
303
|
const [actionError, setActionError] = useState('');
|
|
237
|
-
const rows = list.rows
|
|
238
|
-
|
|
239
|
-
|
|
304
|
+
const rows = withAdded(list.rows, fresh.query === query ? fresh.added : [], fresh.rows).filter(
|
|
305
|
+
task => !gone.includes(task.task.id),
|
|
306
|
+
);
|
|
240
307
|
const counts =
|
|
241
308
|
(fresh.query === query ? fresh.counts : undefined) ??
|
|
242
309
|
(list.meta.counts as TaskCounts | undefined);
|
|
243
|
-
const live = rows.some(taskActive) || !!counts?.active;
|
|
244
310
|
|
|
245
|
-
//
|
|
311
|
+
// One first-page refetch at a time and a second apart, longer after failures; a change meanwhile asks for one more, with the filters then; a hidden tab waits to show.
|
|
312
|
+
const refetching = useRef<number>();
|
|
313
|
+
const again = useRef(false);
|
|
314
|
+
const hidden = useRef(false);
|
|
315
|
+
const spaced = useRef<ReturnType<typeof setTimeout>>();
|
|
316
|
+
const left = useRef(false);
|
|
317
|
+
const failures = useRef(0);
|
|
318
|
+
// Bumped by a reset, so a fetch started before it never writes over the page that follows.
|
|
319
|
+
const era = useRef(0);
|
|
320
|
+
// When each row last took an event, so an older page never undoes it.
|
|
321
|
+
const touched = useRef<Record<string, number>>({});
|
|
322
|
+
// The minute's resync reads every loaded row, not just the first page.
|
|
323
|
+
const deep = useRef(false);
|
|
324
|
+
const refresh = (all = false) => {
|
|
325
|
+
deep.current ||= all;
|
|
326
|
+
if (document.visibilityState === 'hidden') return void (hidden.current = true);
|
|
327
|
+
if (refetching.current) return void (again.current = true);
|
|
328
|
+
const started = (refetching.current = Date.now());
|
|
329
|
+
const before = era.current;
|
|
330
|
+
const loaded = deep.current ? rows : [];
|
|
331
|
+
deep.current = false;
|
|
332
|
+
// Pages of up to 200 until every loaded row is covered.
|
|
333
|
+
const read = async () => {
|
|
334
|
+
const first = await client.tasks.list({
|
|
335
|
+
...options,
|
|
336
|
+
limit: Math.min(200, Math.max(LIST_PAGE, loaded.length)),
|
|
337
|
+
cursor: '',
|
|
338
|
+
});
|
|
339
|
+
let page = first;
|
|
340
|
+
const items = [...first.items];
|
|
341
|
+
while (page.next && items.length < loaded.length) {
|
|
342
|
+
page = await client.tasks.list({ ...options, limit: 200, cursor: page.next });
|
|
343
|
+
items.push(...page.items);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
return { ...page, items, counts: first.counts };
|
|
347
|
+
};
|
|
348
|
+
void read()
|
|
349
|
+
.then(page => {
|
|
350
|
+
if (era.current !== before) return;
|
|
351
|
+
// A loaded row the read covers but no longer lists has left this view.
|
|
352
|
+
const last = page.items.at(-1);
|
|
353
|
+
const fetched = new Set(page.items.map(row => row.task.id));
|
|
354
|
+
const left = loaded.filter(
|
|
355
|
+
row =>
|
|
356
|
+
!fetched.has(row.task.id) &&
|
|
357
|
+
(touched.current[row.task.id] ?? 0) <= started &&
|
|
358
|
+
(!page.next || (last && listOrder(row, last) < 0)),
|
|
359
|
+
);
|
|
360
|
+
if (left.length) setGone(current => [...current, ...left.map(row => row.task.id)]);
|
|
361
|
+
setFresh(current => ({
|
|
362
|
+
rows: {
|
|
363
|
+
...current.rows,
|
|
364
|
+
// A page row is a summary, so what events added to the row stays.
|
|
365
|
+
...Object.fromEntries(
|
|
366
|
+
page.items
|
|
367
|
+
.filter(row => (touched.current[row.task.id] ?? 0) <= started)
|
|
368
|
+
.map(row => [row.task.id, { ...current.rows[row.task.id], ...row }]),
|
|
369
|
+
),
|
|
370
|
+
},
|
|
371
|
+
added: addRows(current.query === query ? current.added : [], page.items),
|
|
372
|
+
counts: page.counts,
|
|
373
|
+
query,
|
|
374
|
+
}));
|
|
375
|
+
failures.current = 0;
|
|
376
|
+
})
|
|
377
|
+
// A failed read stays wanted, and tries again later each time.
|
|
378
|
+
.catch(() => {
|
|
379
|
+
failures.current++;
|
|
380
|
+
again.current = true;
|
|
381
|
+
})
|
|
382
|
+
.finally(() => {
|
|
383
|
+
if (left.current) return;
|
|
384
|
+
if (!again.current) return void (refetching.current = undefined);
|
|
385
|
+
again.current = false;
|
|
386
|
+
spaced.current = setTimeout(
|
|
387
|
+
() => {
|
|
388
|
+
refetching.current = undefined;
|
|
389
|
+
latest.current();
|
|
390
|
+
},
|
|
391
|
+
Math.min(30_000, 1000 * 2 ** failures.current),
|
|
392
|
+
);
|
|
393
|
+
});
|
|
394
|
+
};
|
|
395
|
+
const latest = useRef(refresh);
|
|
396
|
+
latest.current = refresh;
|
|
246
397
|
useEffect(() => {
|
|
247
|
-
|
|
398
|
+
const show = () => {
|
|
399
|
+
if (document.visibilityState !== 'visible' || !hidden.current) return;
|
|
400
|
+
hidden.current = false;
|
|
401
|
+
latest.current();
|
|
402
|
+
};
|
|
403
|
+
addEventListener('visibilitychange', show);
|
|
404
|
+
return () => {
|
|
405
|
+
removeEventListener('visibilitychange', show);
|
|
406
|
+
clearTimeout(spaced.current);
|
|
407
|
+
left.current = true;
|
|
408
|
+
};
|
|
409
|
+
}, []);
|
|
410
|
+
|
|
411
|
+
// Changes were missed, so every loaded page goes: the page renders again from the server.
|
|
412
|
+
const nav = useRouter();
|
|
413
|
+
const reset = () => {
|
|
414
|
+
era.current++;
|
|
415
|
+
touched.current = {};
|
|
416
|
+
setFresh({ rows: {}, added: [] });
|
|
417
|
+
setGone([]);
|
|
418
|
+
nav.refresh();
|
|
419
|
+
};
|
|
248
420
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
421
|
+
// Rows follow the events stream at once; counts, and tasks the list lacks, come with its first page again.
|
|
422
|
+
useTaskEvents(
|
|
423
|
+
(event: TaskEvent) => {
|
|
424
|
+
const row = rows.find(task => task.task.id === event.id);
|
|
425
|
+
if (!row) {
|
|
426
|
+
// A deleted or archived task stays out even if a read from before it brings it; an unarchived one comes back.
|
|
427
|
+
if (event.deleted || (event.archivedAt && values.status !== 'archived'))
|
|
428
|
+
setGone(current => [...current, event.id]);
|
|
429
|
+
else
|
|
430
|
+
setGone(current =>
|
|
431
|
+
current.includes(event.id) ? current.filter(id => id !== event.id) : current,
|
|
432
|
+
);
|
|
433
|
+
// A row kept from another view would outlive this change, so it goes.
|
|
434
|
+
setFresh(current => {
|
|
435
|
+
const { [event.id]: _kept, ...rows } = current.rows;
|
|
436
|
+
return _kept ? { ...current, rows } : current;
|
|
437
|
+
});
|
|
438
|
+
if (event.deleted || (agent || values.agent || event.agent) === event.agent) refresh();
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
touched.current[event.id] = Date.now();
|
|
442
|
+
if (refetching.current) again.current = true;
|
|
443
|
+
// A change that moves the counts asks the server; a continued task also brings its new prompt.
|
|
444
|
+
if (
|
|
445
|
+
event.deleted ||
|
|
446
|
+
event.status !== row.status ||
|
|
447
|
+
Boolean(event.archivedAt) !== Boolean(row.archivedAt)
|
|
448
|
+
)
|
|
449
|
+
refresh();
|
|
450
|
+
if (event.deleted || (event.archivedAt && values.status !== 'archived'))
|
|
451
|
+
return setGone(current => [...current, event.id]);
|
|
452
|
+
setFresh(current => {
|
|
453
|
+
const was = current.rows[event.id] ?? row;
|
|
454
|
+
return {
|
|
455
|
+
...current,
|
|
456
|
+
rows: {
|
|
457
|
+
...current.rows,
|
|
458
|
+
[event.id]: {
|
|
459
|
+
...was,
|
|
460
|
+
status: event.status,
|
|
461
|
+
approval: event.approval ?? undefined,
|
|
462
|
+
archivedAt: event.archivedAt,
|
|
463
|
+
startedAt: event.startedAt,
|
|
464
|
+
finishedAt: event.finishedAt,
|
|
465
|
+
},
|
|
466
|
+
},
|
|
467
|
+
};
|
|
468
|
+
});
|
|
469
|
+
},
|
|
470
|
+
reset,
|
|
471
|
+
() => refresh(true),
|
|
472
|
+
);
|
|
269
473
|
|
|
270
474
|
return (
|
|
271
475
|
<>
|
|
272
|
-
<Toolbar head={head}>
|
|
476
|
+
<Toolbar head={head} action={head ? <NewTaskButton /> : undefined}>
|
|
273
477
|
<Search value={values.q} label="Search tasks" onInput={value => set('q', value, 250)} />
|
|
274
|
-
<
|
|
275
|
-
label="Status"
|
|
276
|
-
value={values.status}
|
|
277
|
-
options={STATUSES}
|
|
278
|
-
onChange={value => set('status', value)}
|
|
279
|
-
/>
|
|
280
|
-
<Menu
|
|
281
|
-
class="filter-more"
|
|
282
|
-
label="More filters"
|
|
283
|
-
summaryClass={`field-btn${values.source || values.agent ? ' on' : ''}`}
|
|
284
|
-
summary="Filter"
|
|
285
|
-
>
|
|
286
|
-
<p class="pop-label">Source</p>
|
|
287
|
-
<div role="group" aria-label="Source">
|
|
288
|
-
{[...SOURCES, ...platforms].map(([value, label]) => (
|
|
289
|
-
<MenuRadio
|
|
290
|
-
key={value}
|
|
291
|
-
on={values.source === value}
|
|
292
|
-
onPick={() => set('source', value)}
|
|
293
|
-
>
|
|
294
|
-
{label}
|
|
295
|
-
</MenuRadio>
|
|
296
|
-
))}
|
|
297
|
-
</div>
|
|
298
|
-
{agent ? null : (
|
|
299
|
-
<>
|
|
300
|
-
<p class="pop-label">Agent</p>
|
|
301
|
-
<div role="group" aria-label="Agent">
|
|
302
|
-
{[
|
|
303
|
-
['', 'All agents'] as [string, string],
|
|
304
|
-
...(values.agent && !agents.some(([id]) => id === values.agent)
|
|
305
|
-
? [[values.agent, values.agent] as [string, string]]
|
|
306
|
-
: []),
|
|
307
|
-
...agents,
|
|
308
|
-
].map(([value, label]) => (
|
|
309
|
-
<MenuRadio
|
|
310
|
-
key={value}
|
|
311
|
-
on={values.agent === value}
|
|
312
|
-
onPick={() => set('agent', value)}
|
|
313
|
-
>
|
|
314
|
-
{label}
|
|
315
|
-
</MenuRadio>
|
|
316
|
-
))}
|
|
317
|
-
</div>
|
|
318
|
-
</>
|
|
319
|
-
)}
|
|
320
|
-
</Menu>
|
|
478
|
+
<Filter name="tasks" facets={facets} values={values} onChange={set} />
|
|
321
479
|
</Toolbar>
|
|
322
480
|
{missing ? <NeedsCredential /> : null}
|
|
323
481
|
<Card
|
|
@@ -348,9 +506,9 @@ export function TasksList({
|
|
|
348
506
|
<tr>
|
|
349
507
|
<th>Task</th>
|
|
350
508
|
<th>Status</th>
|
|
351
|
-
<th>Source</th>
|
|
352
509
|
<th>Created</th>
|
|
353
510
|
<th class="num">Duration</th>
|
|
511
|
+
<th>Source</th>
|
|
354
512
|
</tr>
|
|
355
513
|
</thead>
|
|
356
514
|
<tbody>
|
|
@@ -358,6 +516,7 @@ export function TasksList({
|
|
|
358
516
|
<TaskRowView
|
|
359
517
|
key={task.task.id}
|
|
360
518
|
task={task}
|
|
519
|
+
brand={brands[task.task.event?.integration ?? task.task.source]}
|
|
361
520
|
back={back}
|
|
362
521
|
scoped={Boolean(agent)}
|
|
363
522
|
tz={tz}
|
|
@@ -367,19 +526,7 @@ export function TasksList({
|
|
|
367
526
|
// An archived row leaves every view but the archive; a stopped one just refreshes.
|
|
368
527
|
if (what === 'delete' || (what === 'archive' && values.status !== 'archived'))
|
|
369
528
|
setGone(current => [...current, task.task.id]);
|
|
370
|
-
|
|
371
|
-
.list({ ...options, cursor: '' })
|
|
372
|
-
.then(page =>
|
|
373
|
-
setFresh(current => ({
|
|
374
|
-
rows: {
|
|
375
|
-
...current.rows,
|
|
376
|
-
...Object.fromEntries(page.items.map(row => [row.task.id, row])),
|
|
377
|
-
},
|
|
378
|
-
counts: page.counts,
|
|
379
|
-
query,
|
|
380
|
-
})),
|
|
381
|
-
)
|
|
382
|
-
.catch(() => {});
|
|
529
|
+
refresh();
|
|
383
530
|
}}
|
|
384
531
|
/>
|
|
385
532
|
))}
|
|
@@ -392,7 +539,7 @@ export function TasksList({
|
|
|
392
539
|
<Empty title="No tasks yet">
|
|
393
540
|
{agent
|
|
394
541
|
? 'Tasks appear here as this agent runs.'
|
|
395
|
-
: '
|
|
542
|
+
: 'Start one with New task. Tasks from the dashboard, the CLI and platforms like GitHub show up here, newest first.'}
|
|
396
543
|
</Empty>
|
|
397
544
|
)}
|
|
398
545
|
<Tail noun="tasks" {...list} />
|
|
@@ -2,11 +2,11 @@ import './tasks-list.css';
|
|
|
2
2
|
import { dynamic } from '@wular/pnext/dynamic';
|
|
3
3
|
|
|
4
4
|
import { zoneOf } from '@/utils/format';
|
|
5
|
-
import { LIST_PAGE } from '@/utils/paged';
|
|
5
|
+
import { FILTER_ROWS, LIST_PAGE } from '@/utils/paged';
|
|
6
6
|
import { load } from '@/api/load';
|
|
7
7
|
import { Settle } from '@/comps/frame/stream';
|
|
8
8
|
import { LoadingCard, LoadingToolbar } from '@/comps/frame/loading-card';
|
|
9
|
-
import {
|
|
9
|
+
import { listFilters } from '@/app/dash/tasks/list/task';
|
|
10
10
|
|
|
11
11
|
// Rows arrive rendered; paging and filters hydrate once the list is in view.
|
|
12
12
|
const TasksList = dynamic(() => import('./tasks-list').then(m => m.TasksList), {
|
|
@@ -18,18 +18,14 @@ const TasksList = dynamic(() => import('./tasks-list').then(m => m.TasksList), {
|
|
|
18
18
|
export function TasksLoading({ head, agent }: { head?: { title: string }; agent?: boolean }) {
|
|
19
19
|
return (
|
|
20
20
|
<>
|
|
21
|
-
<LoadingToolbar head={head} search="Search tasks"
|
|
21
|
+
<LoadingToolbar head={head} search="Search tasks" more />
|
|
22
22
|
<LoadingCard title="Tasks" label="Loading tasks" />
|
|
23
23
|
</>
|
|
24
24
|
);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/** The tasks the address bar's filters select; the page starts these loads before it renders. */
|
|
28
|
-
export function loadTasks(
|
|
29
|
-
request: Request,
|
|
30
|
-
agent?: string,
|
|
31
|
-
agentChoices?: Promise<[string, string][]>,
|
|
32
|
-
) {
|
|
28
|
+
export function loadTasks(request: Request, agent?: string) {
|
|
33
29
|
const params = new URL(request.url).searchParams;
|
|
34
30
|
const filters = {
|
|
35
31
|
q: params.get('q') ?? '',
|
|
@@ -47,16 +43,15 @@ export function loadTasks(
|
|
|
47
43
|
agent: agent ?? filters.agent,
|
|
48
44
|
});
|
|
49
45
|
const catalog = load(request).integrations.list();
|
|
50
|
-
// The agent filter's
|
|
46
|
+
// The agent filter's first rows, one past what it shows so it knows to offer typing; an agent's own tab has none.
|
|
51
47
|
const agents = agent
|
|
52
48
|
? undefined
|
|
53
|
-
: (
|
|
54
|
-
|
|
55
|
-
.agents.list({ cursor: '', limit: 100 })
|
|
49
|
+
: load(request)
|
|
50
|
+
.agents.list({ cursor: '', limit: FILTER_ROWS + 1 })
|
|
56
51
|
.then(
|
|
57
52
|
page => page.items.map((row): [string, string] => [row.id, row.name]),
|
|
58
53
|
() => [],
|
|
59
|
-
)
|
|
54
|
+
);
|
|
60
55
|
return { filters, first, catalog, agents, tz: zoneOf(request) };
|
|
61
56
|
}
|
|
62
57
|
|
|
@@ -80,6 +75,7 @@ export function TasksSection({
|
|
|
80
75
|
<TasksList
|
|
81
76
|
first={page}
|
|
82
77
|
platforms={integrations.map((entry): [string, string] => [entry.id, entry.name])}
|
|
78
|
+
brands={Object.fromEntries(integrations.map(entry => [entry.id, entry.brand]))}
|
|
83
79
|
agents={ids}
|
|
84
80
|
filters={filters}
|
|
85
81
|
agent={agent}
|