agim-cli 1.2.128 → 1.2.130
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/CHANGELOG.md +93 -0
- package/dist/core/llm/agent-loop.d.ts.map +1 -1
- package/dist/core/llm/agent-loop.js +9 -1
- package/dist/core/llm/agent-loop.js.map +1 -1
- package/dist/web/public/assets/{a2a-CbxNgf9H.js → a2a-Bp_OpTfW.js} +2 -2
- package/dist/web/public/assets/{a2a-CbxNgf9H.js.map → a2a-Bp_OpTfW.js.map} +1 -1
- package/dist/web/public/assets/{activity-C6r508cN.js → activity-B5erGuWa.js} +2 -2
- package/dist/web/public/assets/{activity-C6r508cN.js.map → activity-B5erGuWa.js.map} +1 -1
- package/dist/web/public/assets/{admins-C0BJw6X9.js → admins-D3j7wkvL.js} +3 -3
- package/dist/web/public/assets/{admins-C0BJw6X9.js.map → admins-D3j7wkvL.js.map} +1 -1
- package/dist/web/public/assets/{agents-DOW1_NGT.js → agents-Cb3Vb2-8.js} +3 -3
- package/dist/web/public/assets/{agents-DOW1_NGT.js.map → agents-Cb3Vb2-8.js.map} +1 -1
- package/dist/web/public/assets/{approvals-CyPhYcGG.js → approvals-BZULwrl5.js} +3 -3
- package/dist/web/public/assets/{approvals-CyPhYcGG.js.map → approvals-BZULwrl5.js.map} +1 -1
- package/dist/web/public/assets/arrow-down-OdSfpgG4.js +7 -0
- package/dist/web/public/assets/arrow-down-OdSfpgG4.js.map +1 -0
- package/dist/web/public/assets/arrow-up-DtrvOH7Z.js +7 -0
- package/dist/web/public/assets/arrow-up-DtrvOH7Z.js.map +1 -0
- package/dist/web/public/assets/{asks-B6L3PSml.js → asks-BaVT-eFe.js} +3 -3
- package/dist/web/public/assets/{asks-B6L3PSml.js.map → asks-BaVT-eFe.js.map} +1 -1
- package/dist/web/public/assets/audit-CSk2rv6z.js +2 -0
- package/dist/web/public/assets/{audit-CCGCdw6P.js.map → audit-CSk2rv6z.js.map} +1 -1
- package/dist/web/public/assets/{bell-OiL3Thk2.js → bell-DifbuUaI.js} +2 -2
- package/dist/web/public/assets/{bell-OiL3Thk2.js.map → bell-DifbuUaI.js.map} +1 -1
- package/dist/web/public/assets/{bgjobs-vhVtnLSx.js → bgjobs-D3wsuZBR.js} +3 -3
- package/dist/web/public/assets/{bgjobs-vhVtnLSx.js.map → bgjobs-D3wsuZBR.js.map} +1 -1
- package/dist/web/public/assets/{brain-n56pZ1TQ.js → brain-BH9ObIfA.js} +2 -2
- package/dist/web/public/assets/{brain-n56pZ1TQ.js.map → brain-BH9ObIfA.js.map} +1 -1
- package/dist/web/public/assets/{briefcase-BscVfAjp.js → briefcase-CZqK5oy3.js} +2 -2
- package/dist/web/public/assets/{briefcase-BscVfAjp.js.map → briefcase-CZqK5oy3.js.map} +1 -1
- package/dist/web/public/assets/{browser-ponyfill-BOcGq8h9.js → browser-ponyfill-BUutOaRz.js} +2 -2
- package/dist/web/public/assets/{browser-ponyfill-BOcGq8h9.js.map → browser-ponyfill-BUutOaRz.js.map} +1 -1
- package/dist/web/public/assets/chat-gOU1pe0E.js +7 -0
- package/dist/web/public/assets/chat-gOU1pe0E.js.map +1 -0
- package/dist/web/public/assets/chevron-left-BtuaBNRZ.js +7 -0
- package/dist/web/public/assets/chevron-left-BtuaBNRZ.js.map +1 -0
- package/dist/web/public/assets/{chevron-right-trO6yoBr.js → chevron-right-uDVVnuGu.js} +2 -2
- package/dist/web/public/assets/{chevron-right-trO6yoBr.js.map → chevron-right-uDVVnuGu.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-B_d7dBl5.js → circle-check-VgYKnBhy.js} +2 -2
- package/dist/web/public/assets/{circle-check-B_d7dBl5.js.map → circle-check-VgYKnBhy.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-big-D6TvCoDM.js → circle-check-big-7idAFtyL.js} +2 -2
- package/dist/web/public/assets/{circle-check-big-D6TvCoDM.js.map → circle-check-big-7idAFtyL.js.map} +1 -1
- package/dist/web/public/assets/{circle-x-OcRzGLRb.js → circle-x-8dhkvHlT.js} +2 -2
- package/dist/web/public/assets/{circle-x-OcRzGLRb.js.map → circle-x-8dhkvHlT.js.map} +1 -1
- package/dist/web/public/assets/confirm-dialog-_BtUs6oW.js +2 -0
- package/dist/web/public/assets/{confirm-dialog-DD1ZW1XE.js.map → confirm-dialog-_BtUs6oW.js.map} +1 -1
- package/dist/web/public/assets/copy-Ba1min4z.js +7 -0
- package/dist/web/public/assets/copy-Ba1min4z.js.map +1 -0
- package/dist/web/public/assets/{data-table-bhqK389v.js → data-table-BVcXWtPw.js} +3 -3
- package/dist/web/public/assets/{data-table-bhqK389v.js.map → data-table-BVcXWtPw.js.map} +1 -1
- package/dist/web/public/assets/dialog-BVYFRXlI.js +6 -0
- package/dist/web/public/assets/{dialog-D5BsJN2q.js.map → dialog-BVYFRXlI.js.map} +1 -1
- package/dist/web/public/assets/{download-CcO4RAuC.js → download-DYc5g_1W.js} +3 -3
- package/dist/web/public/assets/{download-CcO4RAuC.js.map → download-DYc5g_1W.js.map} +1 -1
- package/dist/web/public/assets/{email-Dy3UoyzF.js → email-6vlGBJXY.js} +3 -3
- package/dist/web/public/assets/{email-Dy3UoyzF.js.map → email-6vlGBJXY.js.map} +1 -1
- package/dist/web/public/assets/{empty-state-CwUKG8xX.js → empty-state-WHzNYVaT.js} +2 -2
- package/dist/web/public/assets/{empty-state-CwUKG8xX.js.map → empty-state-WHzNYVaT.js.map} +1 -1
- package/dist/web/public/assets/{external-link-wf5VhNXd.js → external-link-CfQZDer8.js} +2 -2
- package/dist/web/public/assets/{external-link-wf5VhNXd.js.map → external-link-CfQZDer8.js.map} +1 -1
- package/dist/web/public/assets/{eye-8lKlwbZE.js → eye-PzqPB6N6.js} +3 -3
- package/dist/web/public/assets/{eye-8lKlwbZE.js.map → eye-PzqPB6N6.js.map} +1 -1
- package/dist/web/public/assets/facts-NmBeyMpC.js +2 -0
- package/dist/web/public/assets/{facts-Cfu6Lg3H.js.map → facts-NmBeyMpC.js.map} +1 -1
- package/dist/web/public/assets/{goals-BQkhal_h.js → goals-BfMwQtYm.js} +4 -4
- package/dist/web/public/assets/{goals-BQkhal_h.js.map → goals-BfMwQtYm.js.map} +1 -1
- package/dist/web/public/assets/health-D46iQ6Hj.js +2 -0
- package/dist/web/public/assets/{health-BObMAngj.js.map → health-D46iQ6Hj.js.map} +1 -1
- package/dist/web/public/assets/{heart-pulse-DI33Rxyr.js → heart-pulse-BHz53Ggd.js} +2 -2
- package/dist/web/public/assets/{heart-pulse-DI33Rxyr.js.map → heart-pulse-BHz53Ggd.js.map} +1 -1
- package/dist/web/public/assets/{heartbeat-Bc4SZawQ.js → heartbeat-DBpc9rKL.js} +3 -3
- package/dist/web/public/assets/{heartbeat-Bc4SZawQ.js.map → heartbeat-DBpc9rKL.js.map} +1 -1
- package/dist/web/public/assets/{hot-BXYotT26.js → hot-D_-tARKX.js} +4 -9
- package/dist/web/public/assets/hot-D_-tARKX.js.map +1 -0
- package/dist/web/public/assets/{index-CGaI-i4K.js → index-DXI13nSQ.js} +29 -29
- package/dist/web/public/assets/index-DXI13nSQ.js.map +1 -0
- package/dist/web/public/assets/index-f1K5Q2Yz.css +1 -0
- package/dist/web/public/assets/{installed-DswmDcea.js → installed-BtOgT0Ea.js} +2 -2
- package/dist/web/public/assets/{installed-DswmDcea.js.map → installed-BtOgT0Ea.js.map} +1 -1
- package/dist/web/public/assets/jobs-DUoPbupO.js +2 -0
- package/dist/web/public/assets/{jobs-DWBDqKx-.js.map → jobs-DUoPbupO.js.map} +1 -1
- package/dist/web/public/assets/layout-BpS7td-S.js +2 -0
- package/dist/web/public/assets/layout-BpS7td-S.js.map +1 -0
- package/dist/web/public/assets/layout-C1EVvCs8.js +2 -0
- package/dist/web/public/assets/{layout-D7gNMUDZ.js.map → layout-C1EVvCs8.js.map} +1 -1
- package/dist/web/public/assets/layout-C3e8vPrG.js +2 -0
- package/dist/web/public/assets/{layout-DJKxW33x.js.map → layout-C3e8vPrG.js.map} +1 -1
- package/dist/web/public/assets/layout-DkoRqhBs.js +2 -0
- package/dist/web/public/assets/{layout-B5rK_h6Q.js.map → layout-DkoRqhBs.js.map} +1 -1
- package/dist/web/public/assets/layout-wuoOyazR.js +2 -0
- package/dist/web/public/assets/{layout-ByUY6XZQ.js.map → layout-wuoOyazR.js.map} +1 -1
- package/dist/web/public/assets/{llm-CPOd98Hy.js → llm-iuvigJxr.js} +2 -2
- package/dist/web/public/assets/{llm-CPOd98Hy.js.map → llm-iuvigJxr.js.map} +1 -1
- package/dist/web/public/assets/{loader-circle-BBIfyATA.js → loader-circle-BS5FFFg-.js} +2 -2
- package/dist/web/public/assets/{loader-circle-BBIfyATA.js.map → loader-circle-BS5FFFg-.js.map} +1 -1
- package/dist/web/public/assets/{map-pin-Bg7JuU7F.js → map-pin-CRS6YW4i.js} +2 -2
- package/dist/web/public/assets/{map-pin-Bg7JuU7F.js.map → map-pin-CRS6YW4i.js.map} +1 -1
- package/dist/web/public/assets/{mcp-DGxGN2iX.js → mcp-PWEuZOJ_.js} +3 -3
- package/dist/web/public/assets/{mcp-DGxGN2iX.js.map → mcp-PWEuZOJ_.js.map} +1 -1
- package/dist/web/public/assets/{memos-LpUpTmYL.js → memos-C6i1hbv9.js} +3 -3
- package/dist/web/public/assets/{memos-LpUpTmYL.js.map → memos-C6i1hbv9.js.map} +1 -1
- package/dist/web/public/assets/messengers-CZ3eL15d.js +2 -0
- package/dist/web/public/assets/messengers-CZ3eL15d.js.map +1 -0
- package/dist/web/public/assets/mobile-_rEEG_kX.js +7 -0
- package/dist/web/public/assets/mobile-_rEEG_kX.js.map +1 -0
- package/dist/web/public/assets/{native-agent-CPkYGY3I.js → native-agent-B-Id8sOl.js} +4 -4
- package/dist/web/public/assets/{native-agent-CPkYGY3I.js.map → native-agent-B-Id8sOl.js.map} +1 -1
- package/dist/web/public/assets/{network-DHrX3RcZ.js → network-MVE8s4TA.js} +2 -2
- package/dist/web/public/assets/{network-DHrX3RcZ.js.map → network-MVE8s4TA.js.map} +1 -1
- package/dist/web/public/assets/{outbox-T3NnYmK0.js → outbox-BRpgAP1d.js} +3 -3
- package/dist/web/public/assets/{outbox-T3NnYmK0.js.map → outbox-BRpgAP1d.js.map} +1 -1
- package/dist/web/public/assets/pagination-dm3r6K_2.js +12 -0
- package/dist/web/public/assets/pagination-dm3r6K_2.js.map +1 -0
- package/dist/web/public/assets/persona-Oq3C-gEw.js +2 -0
- package/dist/web/public/assets/{persona-CHz80XDk.js.map → persona-Oq3C-gEw.js.map} +1 -1
- package/dist/web/public/assets/{play-BNtSkb5l.js → play-COQw7BqX.js} +2 -2
- package/dist/web/public/assets/{play-BNtSkb5l.js.map → play-COQw7BqX.js.map} +1 -1
- package/dist/web/public/assets/{plus-CYsjCf6w.js → plus-CdOyGoU1.js} +2 -2
- package/dist/web/public/assets/{plus-CYsjCf6w.js.map → plus-CdOyGoU1.js.map} +1 -1
- package/dist/web/public/assets/policy-docXezae.js +2 -0
- package/dist/web/public/assets/{policy-CtKRzual.js.map → policy-docXezae.js.map} +1 -1
- package/dist/web/public/assets/qr-code-8putJTrW.js +7 -0
- package/dist/web/public/assets/qr-code-8putJTrW.js.map +1 -0
- package/dist/web/public/assets/{react-C9F3QeMB.js → react-Cb2sDjhD.js} +2 -2
- package/dist/web/public/assets/{react-C9F3QeMB.js.map → react-Cb2sDjhD.js.map} +1 -1
- package/dist/web/public/assets/{refresh-ccw-DpPWcwTg.js → refresh-ccw-BPKXoMZa.js} +2 -2
- package/dist/web/public/assets/{refresh-ccw-DpPWcwTg.js.map → refresh-ccw-BPKXoMZa.js.map} +1 -1
- package/dist/web/public/assets/{reminders-R14lWHEJ.js → reminders-CP2qtNSr.js} +3 -3
- package/dist/web/public/assets/{reminders-R14lWHEJ.js.map → reminders-CP2qtNSr.js.map} +1 -1
- package/dist/web/public/assets/{save-beGooRNy.js → save-BXCmgeEj.js} +2 -2
- package/dist/web/public/assets/{save-beGooRNy.js.map → save-BXCmgeEj.js.map} +1 -1
- package/dist/web/public/assets/{schedules-fxKnDnxp.js → schedules-DVaY38v1.js} +3 -3
- package/dist/web/public/assets/{schedules-fxKnDnxp.js.map → schedules-DVaY38v1.js.map} +1 -1
- package/dist/web/public/assets/{search-DzgimpPy.js → search-B-wDhzjs.js} +3 -3
- package/dist/web/public/assets/{search-DzgimpPy.js.map → search-B-wDhzjs.js.map} +1 -1
- package/dist/web/public/assets/{search-BzOAg0Rb.js → search-DzexDAbr.js} +2 -2
- package/dist/web/public/assets/{search-BzOAg0Rb.js.map → search-DzexDAbr.js.map} +1 -1
- package/dist/web/public/assets/security-FHN-b43T.js +2 -0
- package/dist/web/public/assets/{security-Dw1mh68G.js.map → security-FHN-b43T.js.map} +1 -1
- package/dist/web/public/assets/{service-CB55xtmh.js → service-DXGUZTCp.js} +3 -3
- package/dist/web/public/assets/{service-CB55xtmh.js.map → service-DXGUZTCp.js.map} +1 -1
- package/dist/web/public/assets/{shield-alert-C2IO43co.js → shield-alert-BM0-khVy.js} +2 -2
- package/dist/web/public/assets/{shield-alert-C2IO43co.js.map → shield-alert-BM0-khVy.js.map} +1 -1
- package/dist/web/public/assets/{status-badge-wL5IXJx_.js → status-badge-DeESb2dc.js} +2 -2
- package/dist/web/public/assets/{status-badge-wL5IXJx_.js.map → status-badge-DeESb2dc.js.map} +1 -1
- package/dist/web/public/assets/{subtasks-CbLAkygG.js → subtasks-DOwo6FnZ.js} +3 -3
- package/dist/web/public/assets/{subtasks-CbLAkygG.js.map → subtasks-DOwo6FnZ.js.map} +1 -1
- package/dist/web/public/assets/table-oUi0mGOn.js +2 -0
- package/dist/web/public/assets/{table-9FRavyyI.js.map → table-oUi0mGOn.js.map} +1 -1
- package/dist/web/public/assets/{topn-BE7RU5cV.js → topn-D1LQXoLo.js} +3 -3
- package/dist/web/public/assets/{topn-BE7RU5cV.js.map → topn-D1LQXoLo.js.map} +1 -1
- package/dist/web/public/assets/{trash-2-DL2FAuYX.js → trash-2-CTkSvnZX.js} +2 -2
- package/dist/web/public/assets/{trash-2-DL2FAuYX.js.map → trash-2-CTkSvnZX.js.map} +1 -1
- package/dist/web/public/assets/use-background-tasks-BkUIDOxX.js +2 -0
- package/dist/web/public/assets/{use-background-tasks-XHuIYwrT.js.map → use-background-tasks-BkUIDOxX.js.map} +1 -1
- package/dist/web/public/assets/{use-event-stream-BGeFcayX.js → use-event-stream-DgGpGKop.js} +2 -2
- package/dist/web/public/assets/{use-event-stream-BGeFcayX.js.map → use-event-stream-DgGpGKop.js.map} +1 -1
- package/dist/web/public/assets/use-llm-admin-BrJMMEz5.js +2 -0
- package/dist/web/public/assets/{use-llm-admin-Dm8PcjN-.js.map → use-llm-admin-BrJMMEz5.js.map} +1 -1
- package/dist/web/public/assets/use-memory-CbTYEBTc.js +2 -0
- package/dist/web/public/assets/{use-memory-C3GgMqiJ.js.map → use-memory-CbTYEBTc.js.map} +1 -1
- package/dist/web/public/assets/{use-observability-BQa4b0Uk.js → use-observability-Bum0mmDO.js} +2 -2
- package/dist/web/public/assets/{use-observability-BQa4b0Uk.js.map → use-observability-Bum0mmDO.js.map} +1 -1
- package/dist/web/public/assets/use-settings-DJlVLnjo.js +2 -0
- package/dist/web/public/assets/{use-settings-CrkXdLrr.js.map → use-settings-DJlVLnjo.js.map} +1 -1
- package/dist/web/public/assets/use-workspace-BJZUfkqw.js +2 -0
- package/dist/web/public/assets/{use-workspace-Csq4sxlY.js.map → use-workspace-BJZUfkqw.js.map} +1 -1
- package/dist/web/public/assets/useQuery-CEwGD94N.js +2 -0
- package/dist/web/public/assets/{useQuery-ByZlZXlw.js.map → useQuery-CEwGD94N.js.map} +1 -1
- package/dist/web/public/assets/vector-BqffHZmp.js +2 -0
- package/dist/web/public/assets/{vector-BmpvJTWt.js.map → vector-BqffHZmp.js.map} +1 -1
- package/dist/web/public/assets/{viewer-BOSX-lUS.js → viewer-CKTTV-Wt.js} +4 -4
- package/dist/web/public/assets/{viewer-BOSX-lUS.js.map → viewer-CKTTV-Wt.js.map} +1 -1
- package/dist/web/public/assets/{workspace-DTbEdEyD.js → workspace-DQphgYwy.js} +3 -3
- package/dist/web/public/assets/{workspace-DTbEdEyD.js.map → workspace-DQphgYwy.js.map} +1 -1
- package/dist/web/public/assets/workspaces-BOA3TuDS.js +7 -0
- package/dist/web/public/assets/{workspaces-BIZGVK8F.js.map → workspaces-BOA3TuDS.js.map} +1 -1
- package/dist/web/public/assets/{x-BLllJ8d_.js → x-OHUicFfn.js} +2 -2
- package/dist/web/public/assets/{x-BLllJ8d_.js.map → x-OHUicFfn.js.map} +1 -1
- package/dist/web/public/index.html +3 -3
- package/dist/web/public/m/login.html +124 -0
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +103 -1
- package/dist/web/server.js.map +1 -1
- package/package.json +1 -1
- package/dist/web/public/assets/arrow-up-CZr2LH5e.js +0 -12
- package/dist/web/public/assets/arrow-up-CZr2LH5e.js.map +0 -1
- package/dist/web/public/assets/audit-CCGCdw6P.js +0 -2
- package/dist/web/public/assets/confirm-dialog-DD1ZW1XE.js +0 -2
- package/dist/web/public/assets/dialog-D5BsJN2q.js +0 -6
- package/dist/web/public/assets/facts-Cfu6Lg3H.js +0 -2
- package/dist/web/public/assets/health-BObMAngj.js +0 -2
- package/dist/web/public/assets/hot-BXYotT26.js.map +0 -1
- package/dist/web/public/assets/index-CGaI-i4K.js.map +0 -1
- package/dist/web/public/assets/index-De8LfCtL.css +0 -1
- package/dist/web/public/assets/jobs-DWBDqKx-.js +0 -2
- package/dist/web/public/assets/layout-B5rK_h6Q.js +0 -2
- package/dist/web/public/assets/layout-ByUY6XZQ.js +0 -2
- package/dist/web/public/assets/layout-CX3nXpWb.js +0 -2
- package/dist/web/public/assets/layout-CX3nXpWb.js.map +0 -1
- package/dist/web/public/assets/layout-D7gNMUDZ.js +0 -2
- package/dist/web/public/assets/layout-DJKxW33x.js +0 -2
- package/dist/web/public/assets/messengers-CWMsJz1e.js +0 -7
- package/dist/web/public/assets/messengers-CWMsJz1e.js.map +0 -1
- package/dist/web/public/assets/pagination-ANxQzaRV.js +0 -17
- package/dist/web/public/assets/pagination-ANxQzaRV.js.map +0 -1
- package/dist/web/public/assets/persona-CHz80XDk.js +0 -2
- package/dist/web/public/assets/policy-CtKRzual.js +0 -2
- package/dist/web/public/assets/security-Dw1mh68G.js +0 -2
- package/dist/web/public/assets/table-9FRavyyI.js +0 -2
- package/dist/web/public/assets/use-background-tasks-XHuIYwrT.js +0 -2
- package/dist/web/public/assets/use-llm-admin-Dm8PcjN-.js +0 -2
- package/dist/web/public/assets/use-memory-C3GgMqiJ.js +0 -2
- package/dist/web/public/assets/use-settings-CrkXdLrr.js +0 -2
- package/dist/web/public/assets/use-workspace-Csq4sxlY.js +0 -2
- package/dist/web/public/assets/useQuery-ByZlZXlw.js +0 -2
- package/dist/web/public/assets/vector-BmpvJTWt.js +0 -2
- package/dist/web/public/assets/workspaces-BIZGVK8F.js +0 -7
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover" />
|
|
6
|
+
<meta name="theme-color" content="#0b0c0e" />
|
|
7
|
+
<title>agim · 手机登录</title>
|
|
8
|
+
<style>
|
|
9
|
+
:root {
|
|
10
|
+
color-scheme: light dark;
|
|
11
|
+
--bg: #fafafa; --fg: #111; --dim: #6b7280; --card: #fff; --border: #e5e7eb;
|
|
12
|
+
--accent: #2563eb; --danger: #b91c1c; --ok: #047857;
|
|
13
|
+
}
|
|
14
|
+
@media (prefers-color-scheme: dark) {
|
|
15
|
+
:root { --bg: #0b0c0e; --fg: #e5e7eb; --dim: #9ca3af; --card: #1a1b1e; --border: #2a2c30; }
|
|
16
|
+
}
|
|
17
|
+
* { box-sizing: border-box; }
|
|
18
|
+
html, body { margin: 0; padding: 0; }
|
|
19
|
+
body {
|
|
20
|
+
background: var(--bg); color: var(--fg);
|
|
21
|
+
font: 15px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
22
|
+
min-height: 100dvh; display: flex; flex-direction: column;
|
|
23
|
+
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
|
|
24
|
+
}
|
|
25
|
+
main {
|
|
26
|
+
flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
27
|
+
padding: 24px;
|
|
28
|
+
}
|
|
29
|
+
.card {
|
|
30
|
+
width: 100%; max-width: 360px; background: var(--card); border: 1px solid var(--border);
|
|
31
|
+
border-radius: 14px; padding: 24px 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.06);
|
|
32
|
+
}
|
|
33
|
+
h1 { margin: 0 0 6px; font-size: 18px; font-weight: 600; }
|
|
34
|
+
.sub { margin: 0 0 18px; color: var(--dim); font-size: 13px; }
|
|
35
|
+
.spinner {
|
|
36
|
+
width: 22px; height: 22px; border: 2px solid var(--border); border-top-color: var(--accent);
|
|
37
|
+
border-radius: 50%; animation: spin 0.9s linear infinite; display: inline-block; vertical-align: middle;
|
|
38
|
+
}
|
|
39
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
40
|
+
.msg { margin-top: 10px; font-size: 13px; }
|
|
41
|
+
.msg.err { color: var(--danger); }
|
|
42
|
+
.msg.ok { color: var(--ok); }
|
|
43
|
+
.retry {
|
|
44
|
+
margin-top: 14px; display: inline-block; padding: 8px 14px; border-radius: 8px;
|
|
45
|
+
background: var(--accent); color: white; text-decoration: none; font-size: 14px;
|
|
46
|
+
}
|
|
47
|
+
.hint { margin-top: 10px; font-size: 12px; color: var(--dim); }
|
|
48
|
+
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
|
|
49
|
+
background: var(--bg); padding: 1px 6px; border-radius: 4px; }
|
|
50
|
+
</style>
|
|
51
|
+
</head>
|
|
52
|
+
<body>
|
|
53
|
+
<main>
|
|
54
|
+
<div class="card">
|
|
55
|
+
<h1 id="title">登录手机版 agim chat…</h1>
|
|
56
|
+
<p class="sub" id="sub">正在验证扫码 token,请稍候</p>
|
|
57
|
+
<div id="state"><span class="spinner"></span></div>
|
|
58
|
+
<div id="msg" class="msg"></div>
|
|
59
|
+
<div class="hint" id="hint">扫码生成的链接只能用一次性进入;如需重新进入,请回到桌面 admin 重新生成二维码。</div>
|
|
60
|
+
</div>
|
|
61
|
+
</main>
|
|
62
|
+
<script>
|
|
63
|
+
(function(){
|
|
64
|
+
var L = (navigator.language || 'zh').toLowerCase().slice(0,2) === 'en' ? 'en' : 'zh';
|
|
65
|
+
var T = {
|
|
66
|
+
zh: { title: '登录手机版 agim chat…', sub: '正在验证扫码 token,请稍候',
|
|
67
|
+
bad: 'Token 已失效或被撤销。请回到桌面 admin 重新扫码。',
|
|
68
|
+
missing: '链接里没有 token。请通过 admin 后台「Mobile / 手机端」生成二维码后扫码。',
|
|
69
|
+
neterr: '网络错误:', ok: '验证通过,正在跳转聊天界面…',
|
|
70
|
+
retry: '回到登录页' },
|
|
71
|
+
en: { title: 'Signing in to mobile agim chat…', sub: 'Verifying the QR token, please wait',
|
|
72
|
+
bad: 'Token expired or revoked. Re-generate the QR from the desktop admin.',
|
|
73
|
+
missing: 'No token in the URL. Generate a QR from admin → Mobile.',
|
|
74
|
+
neterr: 'Network error: ', ok: 'Verified, opening chat…',
|
|
75
|
+
retry: 'Back to login' },
|
|
76
|
+
};
|
|
77
|
+
var t = T[L];
|
|
78
|
+
document.getElementById('title').textContent = t.title;
|
|
79
|
+
document.getElementById('sub').textContent = t.sub;
|
|
80
|
+
var msg = document.getElementById('msg');
|
|
81
|
+
var state = document.getElementById('state');
|
|
82
|
+
function fail(text){
|
|
83
|
+
state.innerHTML = '';
|
|
84
|
+
msg.className = 'msg err';
|
|
85
|
+
msg.textContent = text;
|
|
86
|
+
var a = document.createElement('a');
|
|
87
|
+
a.className = 'retry'; a.href = '/login'; a.textContent = t.retry;
|
|
88
|
+
msg.appendChild(document.createElement('br'));
|
|
89
|
+
msg.appendChild(a);
|
|
90
|
+
}
|
|
91
|
+
function next(){
|
|
92
|
+
var p = new URLSearchParams(location.search);
|
|
93
|
+
var n = p.get('next') || '/m/chat';
|
|
94
|
+
try {
|
|
95
|
+
var u = new URL(n, location.origin);
|
|
96
|
+
if (u.origin !== location.origin) return '/m/chat';
|
|
97
|
+
return u.pathname + u.search;
|
|
98
|
+
} catch (e) { return '/m/chat'; }
|
|
99
|
+
}
|
|
100
|
+
var raw = new URLSearchParams(location.search).get('t');
|
|
101
|
+
if (!raw) { fail(t.missing); return; }
|
|
102
|
+
fetch('/api/auth/login', {
|
|
103
|
+
method: 'POST',
|
|
104
|
+
headers: { 'Content-Type': 'application/json' },
|
|
105
|
+
body: JSON.stringify({ token: raw }),
|
|
106
|
+
}).then(function(r){
|
|
107
|
+
if (r.status === 401) { fail(t.bad); return; }
|
|
108
|
+
if (!r.ok) {
|
|
109
|
+
return r.text().then(function(b){ fail(t.neterr + r.status + ' ' + b.slice(0,200)); });
|
|
110
|
+
}
|
|
111
|
+
// localStorage mirror so the legacy fallback code paths keep working
|
|
112
|
+
// in case some component reads it instead of the cookie.
|
|
113
|
+
try { localStorage.setItem('agim_token', raw); } catch (e) {}
|
|
114
|
+
state.innerHTML = '';
|
|
115
|
+
msg.className = 'msg ok';
|
|
116
|
+
msg.textContent = t.ok;
|
|
117
|
+
setTimeout(function(){ location.replace(next()); }, 300);
|
|
118
|
+
}).catch(function(err){
|
|
119
|
+
fail(t.neterr + (err && err.message || String(err)));
|
|
120
|
+
});
|
|
121
|
+
})();
|
|
122
|
+
</script>
|
|
123
|
+
</body>
|
|
124
|
+
</html>
|
package/dist/web/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web/server.ts"],"names":[],"mappings":"AA8QA,wBAAgB,iBAAiB,IAAI,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAOrE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;CACrB,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAitC/C"}
|
package/dist/web/server.js
CHANGED
|
@@ -46,6 +46,11 @@ const PUBLIC_EXACT_PATHS = new Set([
|
|
|
46
46
|
// "submit my coordinates" endpoint. It's authenticated by the single-use
|
|
47
47
|
// location token in the request body, NOT by the web access token.
|
|
48
48
|
'/api/loc',
|
|
49
|
+
// v1.2.129 — mobile QR landing. The static page reads `?t=<raw>` and
|
|
50
|
+
// POSTs to /api/auth/login to set the cookie, then redirects to
|
|
51
|
+
// /m/chat. Public on purpose: the raw token IS the auth credential
|
|
52
|
+
// for that single redirect (same model as /login + ?token= fallback).
|
|
53
|
+
'/m/login', '/m/login.html',
|
|
49
54
|
'/favicon.ico', '/favicon.svg',
|
|
50
55
|
]);
|
|
51
56
|
const PUBLIC_PREFIX_PATHS = ['/l/', '/v/', '/api/loc/', '/vendor/'];
|
|
@@ -381,7 +386,10 @@ export async function startWebServer(options) {
|
|
|
381
386
|
const isSse = p === '/events';
|
|
382
387
|
const isVendor = p.startsWith('/vendor/');
|
|
383
388
|
const isPublicSsr = p === '/loc' || p === '/loc.html' || p.startsWith('/l/') || p.startsWith('/v/');
|
|
384
|
-
|
|
389
|
+
// v1.2.129 — /m/login is a static HTML handed back below; don't let
|
|
390
|
+
// the SPA fallback swallow it (the SPA can't auto-submit the token).
|
|
391
|
+
const isMobileLogin = p === '/m/login' || p === '/m/login.html';
|
|
392
|
+
if (!isApi && !isWs && !isSse && !isVendor && !isPublicSsr && !isMobileLogin) {
|
|
385
393
|
// SPA static asset (assets/index-xxx.js, /manifest.webmanifest,
|
|
386
394
|
// /favicon.svg) → return the file if it exists in PUBLIC_DIR.
|
|
387
395
|
// Otherwise fall back to /index.html so the router handles it.
|
|
@@ -419,6 +427,12 @@ export async function startWebServer(options) {
|
|
|
419
427
|
if (url.pathname === '/login' && req.method === 'GET') {
|
|
420
428
|
return serveStatic(res, join(PUBLIC_DIR, 'login.html'), 'text/html; charset=utf-8');
|
|
421
429
|
}
|
|
430
|
+
// v1.2.129 — mobile QR landing. Static page reads ?t=<raw>, POSTs
|
|
431
|
+
// to /api/auth/login, then redirects to ?next=/m/chat. Public so the
|
|
432
|
+
// scanner doesn't bounce through /login first.
|
|
433
|
+
if ((url.pathname === '/m/login' || url.pathname === '/m/login.html') && req.method === 'GET') {
|
|
434
|
+
return serveStatic(res, join(PUBLIC_DIR, 'm', 'login.html'), 'text/html; charset=utf-8');
|
|
435
|
+
}
|
|
422
436
|
// v1.2.3 — vendored third-party assets (Chart.js etc). Whitelist by
|
|
423
437
|
// filename pattern to keep the static surface tight. Public on
|
|
424
438
|
// purpose — no auth gate (third-party libs aren't secrets).
|
|
@@ -725,6 +739,16 @@ export async function startWebServer(options) {
|
|
|
725
739
|
return;
|
|
726
740
|
return handleSearchTest(req, res);
|
|
727
741
|
}
|
|
742
|
+
// v1.2.129 — mobile QR. Admin generates a fresh role=user token with
|
|
743
|
+
// a date-stamped label and gets back a QR data URL + the raw login
|
|
744
|
+
// URL. The token persists until the admin revokes it via the regular
|
|
745
|
+
// /settings/security/tokens UI — there's no auto-expiry in this
|
|
746
|
+
// version (operator-managed lifecycle).
|
|
747
|
+
if (url.pathname === '/api/mobile/qr' && req.method === 'POST') {
|
|
748
|
+
if (!requireAdmin(req, res))
|
|
749
|
+
return;
|
|
750
|
+
return handleMobileQR(req, res);
|
|
751
|
+
}
|
|
728
752
|
if (url.pathname === '/api/workspaces' && req.method === 'GET') {
|
|
729
753
|
return handleListWorkspaces(req, res, url);
|
|
730
754
|
}
|
|
@@ -3062,6 +3086,84 @@ async function handleSearchTest(req, res) {
|
|
|
3062
3086
|
sendJson(res, 500, { error: err instanceof Error ? err.message : String(err) });
|
|
3063
3087
|
}
|
|
3064
3088
|
}
|
|
3089
|
+
/** POST /api/mobile/qr — admin generates a role=user token + QR data URL
|
|
3090
|
+
* pointing the scanner at /m/login?t=<raw>&next=/m/chat. The token is
|
|
3091
|
+
* long-lived (until the admin revokes it on /settings/security/tokens);
|
|
3092
|
+
* rationale: a 30-min TTL would invalidate the QR before the operator
|
|
3093
|
+
* can show it to anyone, and access-token.ts has no per-token TTL field.
|
|
3094
|
+
*
|
|
3095
|
+
* Body: `{ host?: string, baseUrl?: string }` — optional override for
|
|
3096
|
+
* the URL embedded in the QR. Defaults to `<scheme>://<req.host>` so
|
|
3097
|
+
* the QR works on whatever hostname the admin reached the panel on
|
|
3098
|
+
* (loopback / LAN IP / cloudflared tunnel / reverse proxy). */
|
|
3099
|
+
async function handleMobileQR(req, res) {
|
|
3100
|
+
try {
|
|
3101
|
+
const body = await readBody(req, res);
|
|
3102
|
+
const parsed = (() => {
|
|
3103
|
+
try {
|
|
3104
|
+
return JSON.parse(body || '{}');
|
|
3105
|
+
}
|
|
3106
|
+
catch {
|
|
3107
|
+
return {};
|
|
3108
|
+
}
|
|
3109
|
+
})();
|
|
3110
|
+
// Pick the base URL the QR scanner will hit. Priority:
|
|
3111
|
+
// 1) caller-supplied baseUrl (admin can paste a public domain)
|
|
3112
|
+
// 2) caller-supplied host (just the host:port, scheme auto-picked)
|
|
3113
|
+
// 3) the Host header of THIS admin request (works for cloudflared
|
|
3114
|
+
// tunnels that the admin opened the panel through)
|
|
3115
|
+
const isHttps = req.socket.encrypted === true
|
|
3116
|
+
|| String(req.headers['x-forwarded-proto'] || '').toLowerCase() === 'https';
|
|
3117
|
+
const scheme = isHttps ? 'https' : 'http';
|
|
3118
|
+
let base = (parsed.baseUrl || '').trim().replace(/\/+$/, '');
|
|
3119
|
+
if (!base) {
|
|
3120
|
+
const host = (parsed.host || req.headers.host || 'localhost').toString();
|
|
3121
|
+
base = `${scheme}://${host}`;
|
|
3122
|
+
}
|
|
3123
|
+
// Token label: human-readable + sortable + revoke-friendly.
|
|
3124
|
+
const now = new Date();
|
|
3125
|
+
const stamp = `${now.getUTCFullYear()}${String(now.getUTCMonth() + 1).padStart(2, '0')}${String(now.getUTCDate()).padStart(2, '0')}-${String(now.getUTCHours()).padStart(2, '0')}${String(now.getUTCMinutes()).padStart(2, '0')}`;
|
|
3126
|
+
if (!_tokenModule) {
|
|
3127
|
+
sendError(res, 503, 'AUTH_NOT_READY', { message: 'auth module not ready' });
|
|
3128
|
+
return;
|
|
3129
|
+
}
|
|
3130
|
+
const { createToken } = _tokenModule;
|
|
3131
|
+
const created = createToken(`mobile-via-qr-${stamp}`, {
|
|
3132
|
+
role: 'user',
|
|
3133
|
+
actor: 'mobile-qr',
|
|
3134
|
+
});
|
|
3135
|
+
// URL the scanner hits. /m/login is public; it pulls t out of the
|
|
3136
|
+
// URL, POSTs to /api/auth/login, drops the cookie, redirects.
|
|
3137
|
+
// encodeURIComponent so a raw token with weird chars wouldn't break
|
|
3138
|
+
// the URL — current raw tokens are URL-safe but be defensive.
|
|
3139
|
+
const loginUrl = `${base}/m/login?t=${encodeURIComponent(created.raw)}&next=%2Fm%2Fchat`;
|
|
3140
|
+
const QRCode = (await import('qrcode')).default;
|
|
3141
|
+
// M error correction is enough for an opaque token; bigger margin
|
|
3142
|
+
// helps phone scanners through screen glare.
|
|
3143
|
+
const qrDataUrl = await QRCode.toDataURL(loginUrl, {
|
|
3144
|
+
errorCorrectionLevel: 'M',
|
|
3145
|
+
margin: 2,
|
|
3146
|
+
width: 280,
|
|
3147
|
+
});
|
|
3148
|
+
// Audit: caller is already logged in admin (requireAdmin); we just
|
|
3149
|
+
// emit the create event from createToken. Surface the URL+QR.
|
|
3150
|
+
res.writeHead(200, {
|
|
3151
|
+
'Content-Type': 'application/json; charset=utf-8',
|
|
3152
|
+
'Cache-Control': 'no-store',
|
|
3153
|
+
});
|
|
3154
|
+
res.end(JSON.stringify({
|
|
3155
|
+
ok: true,
|
|
3156
|
+
tokenId: created.id,
|
|
3157
|
+
label: `mobile-via-qr-${stamp}`,
|
|
3158
|
+
loginUrl,
|
|
3159
|
+
qrDataUrl,
|
|
3160
|
+
revokeHint: '/settings/security/tokens',
|
|
3161
|
+
}));
|
|
3162
|
+
}
|
|
3163
|
+
catch (err) {
|
|
3164
|
+
sendJson(res, 500, { error: err instanceof Error ? err.message : String(err) });
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3065
3167
|
async function handleListBgjobs(_req, res, url) {
|
|
3066
3168
|
try {
|
|
3067
3169
|
const { resolveRoots, listJobsForRoot, listAllJobs } = await import('../core/bgjob-reader.js');
|