bazilion 0.16.0 → 0.18.0
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/dist/cli.js +672 -87
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +3759 -432
- package/dist/daemon.js.map +1 -1
- package/dist/migrations/0001_init.sql +169 -0
- package/dist/web/client/assets/ChatPane-CAYS_fIQ.js +76 -0
- package/dist/web/client/assets/ConfirmDialog-BzIiABOP.js +1 -0
- package/dist/web/client/assets/{FieldRow-DJ2Gx4Du.js → FieldRow-W_54rw5c.js} +1 -1
- package/dist/web/client/assets/ProductionTeamPolicyEditor-DNXVX8Lz.js +7 -0
- package/dist/web/client/assets/ProfileCommunicationEditor-DN0fOzqn.js +1 -0
- package/dist/web/client/assets/{ResultSourceConversation-CtzJ8QA-.js → ResultSourceConversation-DoU4tOWc.js} +1 -1
- package/dist/web/client/assets/TeamTabs-BmTZRI4T.js +1 -0
- package/dist/web/client/assets/TemplatesTabs-Bs_OXKwx.js +1 -0
- package/dist/web/client/assets/{UnsavedChangesGuard-BCsLw-mU.js → UnsavedChangesGuard-CPRtFReU.js} +1 -1
- package/dist/web/client/assets/{_id-DxopIW-y.js → _id-CxAB4TDr.js} +1 -1
- package/dist/web/client/assets/_id-DL4tJFQB.js +1 -0
- package/dist/web/client/assets/{_id-BEDmIXVf.js → _id-DR9eFC17.js} +1 -1
- package/dist/web/client/assets/{_id-BFM_tn_s.js → _id-Dbmei5tg.js} +1 -1
- package/dist/web/client/assets/{_id-B5Ov7cdO.js → _id-ybF-pqmr.js} +1 -1
- package/dist/web/client/assets/activity-oUyy77jD.js +1 -0
- package/dist/web/client/assets/{agents-CMPOFcs-.js → agents-D_TrEqAg.js} +1 -1
- package/dist/web/client/assets/{agents-O4soKZND.js → agents-DkjJp7JP.js} +1 -1
- package/dist/web/client/assets/{approvals-CwDu_lrA.js → approvals-DhOerWdt.js} +1 -1
- package/dist/web/client/assets/{attention-BY8MMuM_.js → attention-DGwiF-Jy.js} +1 -1
- package/dist/web/client/assets/chevron-right-DSa4xPTs.js +1 -0
- package/dist/web/client/assets/config-BJ2ZzHPR.js +3 -0
- package/dist/web/client/assets/createServerFn-Dzfjt7mA.js +3 -0
- package/dist/web/client/assets/git-review-presentation-CzHQulDk.js +1 -0
- package/dist/web/client/assets/{inbox-CWXql0K3.js → inbox-BUElnGep.js} +1 -1
- package/dist/web/client/assets/index-Bi-HxcPG.js +50 -0
- package/dist/web/client/assets/{learning-DAm4dyyc.js → learning-BiTHNwB3.js} +1 -1
- package/dist/web/client/assets/login-BmcZvAH2.js +1 -0
- package/dist/web/client/assets/{mcp-loLB0wuh.js → mcp-Cwk9V82W.js} +1 -1
- package/dist/web/client/assets/{members-BJ0ikkTl.js → members-CHDNabFh.js} +1 -1
- package/dist/web/client/assets/{memory-Drn9Gv53.js → memory-Cx_Fpd4e.js} +1 -1
- package/dist/web/client/assets/policy-C0nMdwcG.js +1 -0
- package/dist/web/client/assets/{results-9exU6f7m.js → results-Bz3jASs-.js} +1 -1
- package/dist/web/client/assets/review-AK9WGmpv.js +1 -0
- package/dist/web/client/assets/routes-DsMY_6oy.js +1 -0
- package/dist/web/client/assets/{services-BLso1BhA.js → services-DItA6fJ7.js} +1 -1
- package/dist/web/client/assets/{skills-BodqX3OI.js → skills-DbNV2vgL.js} +1 -1
- package/dist/web/client/assets/{styles-d1yjBpud.css → styles-C6br2xxl.css} +1 -1
- package/dist/web/client/assets/{teams-ByQedXZi.js → teams-D83scDxw.js} +1 -1
- package/dist/web/client/assets/{teams-SYsF1bOR.js → teams-DAny1ypN.js} +1 -1
- package/dist/web/client/assets/{telegram-DC9PLFbB.js → telegram-BOmf9vUh.js} +1 -1
- package/dist/web/client/assets/{tokens-DGy8Ijpo.js → tokens-DBGH6Bw5.js} +1 -1
- package/dist/web/client/assets/{triggers-BXpVmHDG.js → triggers-D1_pseI3.js} +1 -1
- package/dist/web/client/assets/verifications-CBTo-FyV.js +2 -0
- package/dist/web/client/assets/welcome-DAfPOm15.js +1 -0
- package/dist/web/client/assets/x-CWY-gUaM.js +1 -0
- package/dist/web/server/assets/{ChatPane-CS5oI7ef.js → ChatPane-DybH39WK.js} +301 -14
- package/dist/web/server/assets/{ResultSourceConversation-BpVWBRYq.js → ResultSourceConversation-BmXTcEOA.js} +1 -1
- package/dist/web/server/assets/{TeamTabs-TCKjCvMA.js → TeamTabs-Dg4v6x0-.js} +8 -0
- package/dist/web/server/assets/{_id-DtIYuJJX.js → _id--onriuvj.js} +1 -1
- package/dist/web/server/assets/{_id-DOnInzLb.js → _id--zoh1vv7.js} +1 -1
- package/dist/web/server/assets/{_id-CeyHEsCZ.js → _id-6p-mDmI8.js} +1 -1
- package/dist/web/server/assets/{_id-5pgKoid8.js → _id-BN1BPEDI.js} +1 -1
- package/dist/web/server/assets/{_id-DFHB9JFQ.js → _id-BYKpT2Tu.js} +1 -1
- package/dist/web/server/assets/{_id-B_-CDHOi2.js → _id-BqWTB8Wl.js} +1 -1
- package/dist/web/server/assets/{_id-BnqodC1c2.js → _id-C_2er0_G.js} +3 -3
- package/dist/web/server/assets/{_id-BG2nkGxa.js → _id-DptBl3X8.js} +1 -1
- package/dist/web/server/assets/{_id-DwZXhLlL.js → _id-EAjRXNbD.js} +2 -2
- package/dist/web/server/assets/{_id-DrB9uR1b.js → _id-dUnXL-My2.js} +1 -1
- package/dist/web/server/assets/{_tanstack-start-manifest_v-D7gKv6m6.js → _tanstack-start-manifest_v-B3M-dfRO.js} +108 -84
- package/dist/web/server/assets/{activity-0VUkStOu.js → activity-C5jpoEQI.js} +1 -1
- package/dist/web/server/assets/{activity-C88qrNqv.js → activity-Cu7zKPGD.js} +1 -1
- package/dist/web/server/assets/{activity-5fWKPDxj.js → activity-Dn50vkQP.js} +2 -2
- package/dist/web/server/assets/{agents-CSXLaM2W.js → agents-RE6aYOb-.js} +1 -1
- package/dist/web/server/assets/{agents-C86K6HvS.js → agents-nAOx_H7s.js} +1 -1
- package/dist/web/server/assets/{approvals-C3MysI6l.js → approvals-DhHxIDrL.js} +1 -1
- package/dist/web/server/assets/{attention-DLeLCKah.js → attention-CBWzWRni.js} +1 -1
- package/dist/web/server/assets/{auth-CDZp9aEk.js → auth-tB3i6cFd.js} +1 -1
- package/dist/web/server/assets/{config-BVTHvljR.js → config-D1k_tTAw.js} +1 -1
- package/dist/web/server/assets/{daemon-client-xWyYKAcx.js → daemon-client-C7qjQ2iO.js} +45 -0
- package/dist/web/server/assets/git-review-BB3M9nYg.js +26 -0
- package/dist/web/server/assets/git-review-Bf5ABFJg.js +179 -0
- package/dist/web/server/assets/git-review-presentation-TJiHJhen.js +81 -0
- package/dist/web/server/assets/{inbox-PQTrjtOw.js → inbox-Dw4pTevh.js} +1 -1
- package/dist/web/server/assets/{learning-K0cmDsZR.js → learning-CF8ZzFVD.js} +1 -1
- package/dist/web/server/assets/{mcp-Rtraochg.js → mcp-D5dmBT82.js} +1 -1
- package/dist/web/server/assets/{members-CD3GiTfF.js → members-Bd0OtiTr.js} +1 -1
- package/dist/web/server/assets/{members-grAKFWgv.js → members-CvwEN9pm.js} +1 -1
- package/dist/web/server/assets/{members-cc5SeEaW.js → members-xSXoYUOd.js} +2 -2
- package/dist/web/server/assets/{memory-egFpBD1g.js → memory-CcPK7um7.js} +1 -1
- package/dist/web/server/assets/{memory-C5i_GxlY.js → memory-UP6AsRkO.js} +2 -2
- package/dist/web/server/assets/{memory-CVqnyUaM.js → memory-lo2vHRNw.js} +1 -1
- package/dist/web/server/assets/{policy-bLKwvnja.js → policy-B62WXIFo.js} +1 -1
- package/dist/web/server/assets/{policy-Dgjb0_gK.js → policy-Bze9Krhg.js} +2 -2
- package/dist/web/server/assets/{policy-ooSBgiDS.js → policy-Dh6wd2wN.js} +1 -1
- package/dist/web/server/assets/{results-N-kP4iFT.js → results-BFqs2iOu.js} +1 -1
- package/dist/web/server/assets/{results-DXdYtHaq.js → results-BWnu3gXP.js} +1 -1
- package/dist/web/server/assets/{results-CfNsFncJ.js → results-CzZk50Fu.js} +3 -3
- package/dist/web/server/assets/review-DUe3vHPU.js +393 -0
- package/dist/web/server/assets/review-c_-cFi7H.js +14 -0
- package/dist/web/server/assets/{router-B6g_s7W3.js → router-Deq94UJQ.js} +41 -27
- package/dist/web/server/assets/{routes-pcRy_Sf8.js → routes-B6x3pEW8.js} +1 -1
- package/dist/web/server/assets/{routes-BqSaZvlu.js → routes-CVKkvFVv.js} +1 -1
- package/dist/web/server/assets/{routes-Dsh8F_7i.js → routes-DsUzzxk4.js} +2 -2
- package/dist/web/server/assets/{services-DlZA8fRL.js → services-CEr61xb5.js} +1 -1
- package/dist/web/server/assets/{skills-i2duvgW-.js → skills-BImC3LTO.js} +1 -1
- package/dist/web/server/assets/{teams-6RYIj1Xm.js → teams-8zEIo08E.js} +1 -1
- package/dist/web/server/assets/{teams-B1AI3NfN.js → teams-D-yaAWLV.js} +1 -1
- package/dist/web/server/assets/{telegram-C4q0YTVn.js → telegram-CGl_LFtJ.js} +1 -1
- package/dist/web/server/assets/{tokens-RFquA2Bx.js → tokens-cB-uf7qm.js} +1 -1
- package/dist/web/server/assets/{triggers-DVD-iE-N.js → triggers-CtSj79L0.js} +1 -1
- package/dist/web/server/assets/verification-B5QjcpIo.js +97 -0
- package/dist/web/server/assets/verifications-BfQsfwSE.js +268 -0
- package/dist/web/server/assets/verifications-CUq_6ZqL.js +26 -0
- package/dist/web/server/server.js +72 -28
- package/dist/worker.js +470 -79
- package/dist/worker.js.map +1 -1
- package/package.json +3 -3
- package/dist/web/client/assets/ChatPane-CQZzxOir.js +0 -76
- package/dist/web/client/assets/ConfirmDialog-MicTTwdy.js +0 -1
- package/dist/web/client/assets/ProductionTeamPolicyEditor-DqUnN_ce.js +0 -7
- package/dist/web/client/assets/ProfileCommunicationEditor-DArXub0b.js +0 -1
- package/dist/web/client/assets/TeamTabs-DbIk5vvT.js +0 -1
- package/dist/web/client/assets/TemplatesTabs-CatJIjGi.js +0 -1
- package/dist/web/client/assets/_id-CrnEVcw8.js +0 -1
- package/dist/web/client/assets/activity-CrG8Bg60.js +0 -1
- package/dist/web/client/assets/chevron-right-Cf6vKeLq.js +0 -1
- package/dist/web/client/assets/config-Cn4iBJFz.js +0 -3
- package/dist/web/client/assets/index-Bq2zrG2_.js +0 -52
- package/dist/web/client/assets/login-BsABI8Ux.js +0 -1
- package/dist/web/client/assets/policy-pQadZyk0.js +0 -1
- package/dist/web/client/assets/routes-jw1PuqiR.js +0 -1
- package/dist/web/client/assets/welcome-BKsnsCxJ.js +0 -1
- package/dist/web/client/assets/x-BK4xNCzS.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e,t}from"./jsx-runtime-DGeXAQPT.js";import{t as n}from"./react-3W8R1pOO.js";import{d as r}from"./preload-helper-bztXdkDj.js";import{t as i}from"./ConfirmDialog-MicTTwdy.js";import{o as a}from"./index-Bq2zrG2_.js";import{t as o}from"./Button-ByiV6fpd.js";import{t as s}from"./ConfigPage-BCLp-FUC.js";var c=e(n(),1),l=t(),u={communication_approval:`Communication approvals`,lesson_proposal:`Lesson proposals`,review_failure:`Review failures`,trigger_failure:`Scheduled trigger failures`,agent_loop_break:`Agent message loop breaks`};async function d(e,t=`GET`,n){let r=await fetch(`/api/notifications${e}`,{method:t,cache:`no-store`,...n===void 0?{}:{headers:{"Content-Type":`application/json`},body:JSON.stringify(n)}}),i=await r.json();if(!r.ok)throw Error(i.error??`Notification request failed`);return i}function f(){let[e,t]=(0,c.useState)(null),[n,r]=(0,c.useState)(!1),[a,s]=(0,c.useState)(``),[f,p]=(0,c.useState)([]),[m,h]=(0,c.useState)(`UTC`),[g,_]=(0,c.useState)(!1),[v,y]=(0,c.useState)(`22:00`),[b,x]=(0,c.useState)(`07:00`),[S,C]=(0,c.useState)({receipts:[],nextCursor:null}),[w,T]=(0,c.useState)(!1),[E,D]=(0,c.useState)(null),[O,k]=(0,c.useState)(null),[A,j]=(0,c.useState)(null),[M,N]=(0,c.useState)(null);async function P(){let[e,n]=await Promise.all([d(``),d(`/receipts`)]);t(e),C(n),r(e.settings.enabled),s(e.settings.destination?.id??``),p(e.settings.kinds),h(e.settings.timezone),_(e.settings.quietHours!==null),y(e.settings.quietHours?.start??`22:00`),x(e.settings.quietHours?.end??`07:00`)}(0,c.useEffect)(()=>{P().catch(e=>D(String(e.message)))},[]);async function F(e){T(!0),D(null),k(null);try{await e()}catch(e){D(e instanceof Error?e.message:`Notification request failed`)}finally{T(!1)}}async function I(t){e&&(await d(``,`PUT`,{expectedRevision:e.settings.revision,enabled:n,destinationId:a||void 0,kinds:f,timezone:m,quietHours:g?{start:v,end:b}:null,includeOpenPreview:t}),await P(),j(null),k(`Notification settings saved. Delivery does not resolve Attention items.`))}return(0,l.jsxs)(`section`,{className:`card`,style:{marginTop:`1.5rem`,padding:`1.25rem`,minWidth:0},"aria-labelledby":`notification-title`,children:[(0,l.jsx)(`h2`,{id:`notification-title`,children:`Attention notifications`}),(0,l.jsx)(`p`,{className:`muted`,children:`Optional Telegram notices for items that need your attention. New enablement sends future items only. Agent-topic error mirrors may also report the same failure.`}),E&&(0,l.jsxs)(`p`,{role:`alert`,children:[E,`. Refresh settings before retrying a conflicting change.`]}),O&&(0,l.jsx)(`p`,{role:`status`,children:O}),e?(0,l.jsxs)(l.Fragment,{children:[e.settings.restorePaused&&(0,l.jsx)(`p`,{role:`status`,children:`Paused after restore. Telegram may have newer messages than this backup. Re-enable for future items, or explicitly preview old open items with possible duplicates.`}),!e.readiness.ready&&(0,l.jsx)(`p`,{children:`Destination unavailable. Configure and pair the private Telegram forum, start the bot, then refresh.`}),e.diagnostic&&(0,l.jsxs)(`p`,{role:`status`,children:[`Delivery status: `,e.diagnostic]}),(0,l.jsx)(`form`,{onSubmit:e=>{e.preventDefault(),F(()=>I())},children:(0,l.jsxs)(`fieldset`,{disabled:w,style:{border:0,padding:0,minWidth:0},children:[(0,l.jsxs)(`label`,{style:{display:`block`,marginBlock:`.75rem`},children:[(0,l.jsx)(`input`,{type:`checkbox`,checked:n,onChange:e=>r(e.target.checked)}),` `,`Enable Attention notifications`]}),(0,l.jsxs)(`label`,{style:{display:`grid`,gap:`.35rem`,marginBlock:`.75rem`},children:[`Destination`,(0,l.jsxs)(`select`,{value:a,onChange:e=>s(e.target.value),required:n,style:{maxWidth:`100%`},children:[(0,l.jsx)(`option`,{value:``,children:`Choose the paired service topic`}),e.readiness.destination&&(0,l.jsx)(`option`,{value:e.readiness.destination.id,children:`Paired group · Bazilion service topic`}),e.settings.destination&&e.settings.destination.id!==e.readiness.destination?.id&&(0,l.jsx)(`option`,{value:e.settings.destination.id,children:`Previous destination (unavailable)`})]})]}),(0,l.jsx)(`p`,{className:`m-0 text-sm text-mocha`,children:`Notices go to the operational thread in your paired Telegram group.`}),e.readiness.destination&&(0,l.jsxs)(`details`,{className:`mt-2 text-xs text-mocha`,children:[(0,l.jsx)(`summary`,{className:`cursor-pointer`,children:`Telegram destination IDs`}),(0,l.jsxs)(`p`,{className:`mt-2 break-all`,children:[`Group `,e.readiness.destination.chatId,` · Topic `,e.readiness.destination.topicId]})]}),(0,l.jsxs)(`fieldset`,{style:{marginBlock:`1rem`,minWidth:0},children:[(0,l.jsx)(`legend`,{children:`Include these Attention kinds`}),Object.keys(u).map(e=>(0,l.jsxs)(`label`,{style:{display:`block`,marginBlock:`.5rem`},children:[(0,l.jsx)(`input`,{type:`checkbox`,checked:f.includes(e),onChange:t=>p(t.target.checked?[...f,e]:f.filter(t=>t!==e))}),` `,u[e]]},e))]}),(0,l.jsxs)(`label`,{style:{display:`grid`,gap:`.35rem`},children:[`Timezone (IANA)`,(0,l.jsx)(`input`,{value:m,onChange:e=>h(e.target.value),placeholder:`Europe/Warsaw`,required:!0,style:{maxWidth:`100%`,minWidth:0}})]}),(0,l.jsxs)(`label`,{style:{display:`block`,marginBlock:`.75rem`},children:[(0,l.jsx)(`input`,{type:`checkbox`,checked:g,onChange:e=>_(e.target.checked)}),` `,`Use quiet hours for all selected kinds`]}),g&&(0,l.jsxs)(`div`,{style:{display:`flex`,flexWrap:`wrap`,gap:`1rem`},children:[(0,l.jsxs)(`label`,{children:[`Start`,` `,(0,l.jsx)(`input`,{type:`time`,value:v,required:!0,onChange:e=>y(e.target.value)})]}),(0,l.jsxs)(`label`,{children:[`End`,` `,(0,l.jsx)(`input`,{type:`time`,value:b,required:!0,onChange:e=>x(e.target.value)})]})]}),(0,l.jsxs)(`div`,{style:{display:`flex`,flexWrap:`wrap`,gap:`.5rem`,marginTop:`1rem`},children:[(0,l.jsx)(o,{variant:`primary`,type:`submit`,disabled:!f.length||n&&(!e.readiness.ready||!a),children:`Save settings`}),(0,l.jsx)(o,{variant:`ghost`,disabled:!n||!e.readiness.ready||!a||!f.length,onClick:()=>void F(async()=>j(await d(`/preview`,`POST`,{kinds:f}))),children:`Preview open items`})]})]})}),(0,l.jsxs)(`section`,{"aria-label":`Delivery receipts`,className:`mt-6 flex min-w-0 flex-col gap-4 border-t border-frost pt-5`,children:[(0,l.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,l.jsx)(`h3`,{className:`m-0`,children:`Delivery receipts`}),(0,l.jsx)(o,{variant:`ghost`,disabled:w,onClick:()=>void F(async()=>C(await d(`/receipts`))),children:`Refresh receipts`})]}),(0,l.jsx)(`p`,{className:`m-0 text-sm text-mocha`,children:`Delivery confirms Telegram received the notice. It does not approve or resolve the Attention item.`}),S.receipts.length===0&&(0,l.jsx)(`p`,{className:`m-0`,children:`No notification receipts yet.`}),(0,l.jsx)(`ul`,{className:`m-0 grid list-none gap-3 p-0`,children:S.receipts.map(t=>(0,l.jsxs)(`li`,{className:`flex min-w-0 flex-col gap-3 rounded-lg border border-frost bg-ivory p-4 [overflow-wrap:anywhere]`,children:[(0,l.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,l.jsx)(`strong`,{children:u[t.sourceKind]}),(0,l.jsx)(`span`,{className:`rounded-full bg-frost px-2 py-1 text-xs font-semibold capitalize`,children:t.state})]}),(0,l.jsxs)(`p`,{className:`m-0 text-xs text-mocha`,children:[new Date(t.updatedAt).toLocaleString(),` · `,t.attempts,` `,t.attempts===1?`attempt`:`attempts`]}),t.state===`uncertain`&&(0,l.jsx)(`p`,{className:`m-0 text-sm`,children:`Telegram may have received this notice. Retrying could send a duplicate.`}),t.state===`deferred`&&(0,l.jsx)(`p`,{className:`m-0 text-sm`,children:`Waiting for an eligible delivery opportunity.`}),t.state===`failed`&&(0,l.jsx)(`p`,{className:`m-0 text-sm`,children:`Delivery failed. Check the details before retrying.`}),(0,l.jsxs)(`details`,{className:`text-xs text-mocha`,children:[(0,l.jsx)(`summary`,{className:`cursor-pointer`,children:`Technical details`}),(0,l.jsxs)(`dl`,{className:`mt-3 grid min-w-0 gap-2`,children:[(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`dt`,{className:`font-semibold`,children:`Source`}),(0,l.jsx)(`dd`,{className:`m-0`,children:t.sourceId})]}),(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`dt`,{className:`font-semibold`,children:`Receipt`}),(0,l.jsx)(`dd`,{className:`m-0`,children:t.id})]}),t.telegramMessageId&&(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`dt`,{className:`font-semibold`,children:`Telegram message`}),(0,l.jsx)(`dd`,{className:`m-0`,children:t.telegramMessageId})]}),t.diagnostic&&(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`dt`,{className:`font-semibold`,children:`Diagnostic`}),(0,l.jsx)(`dd`,{className:`m-0`,children:t.diagnostic})]})]})]}),[`failed`,`uncertain`].includes(t.state)&&(0,l.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:(0,l.jsx)(o,{variant:`ghost`,disabled:w||!e.settings.enabled||e.settings.restorePaused,onClick:()=>N(t),children:`Retry notice`})})]},t.id))})]}),S.nextCursor&&(0,l.jsx)(o,{variant:`ghost`,disabled:w,onClick:()=>void F(async()=>{let e=await d(`/receipts?cursor=${encodeURIComponent(S.nextCursor)}`);C({receipts:[...S.receipts,...e.receipts],nextCursor:e.nextCursor})}),children:`More receipts`})]}):(0,l.jsx)(`p`,{children:`Loading notification settings…`}),(0,l.jsx)(o,{variant:`ghost`,className:`mt-4`,disabled:w,onClick:()=>void F(P),children:`Refresh settings and destination`}),(0,l.jsx)(i,{open:A!==null,title:`Include currently open items?`,confirmLabel:`Save and include preview`,confirmVariant:`primary`,description:(0,l.jsxs)(`p`,{children:[A?.count??0,` currently eligible items will be considered. Resolved items are omitted.`,` `,A?.possibleDuplicates?`This restored backup may be missing later Telegram receipts, so duplicate messages are possible.`:`Confirmed deliveries will not be repeated.`]}),onOpenChange:e=>{e||j(null)},onConfirm:()=>I(A?.id)}),(0,l.jsx)(i,{open:M!==null,title:`Retry this notification?`,confirmLabel:`Retry, allowing a possible duplicate`,confirmVariant:`primary`,description:`Telegram may already have received this notice. Retry only if you accept a possible duplicate. The source, destination and policy will be checked again.`,onOpenChange:e=>{e||N(null)},onConfirm:async()=>{M&&(await d(`/receipts/${encodeURIComponent(M.id)}/retry`,`POST`,{expectedUpdatedAt:M.updatedAt,acknowledgePossibleDuplicate:!0}),C(await d(`/receipts`)),N(null))}})]})}function p(){let e=a.useLoaderData(),t=r(),[n,u]=(0,c.useState)(``),[d,p]=(0,c.useState)(e.chatId),[y,b]=(0,c.useState)(!1),[x,S]=(0,c.useState)(null),[C,w]=(0,c.useState)(!1),[T,E]=(0,c.useState)(!1),[D,O]=(0,c.useState)(null),[k,A]=(0,c.useState)(!1);async function j(r){if(r.preventDefault(),e.configured&&n.trim().length===0){w(!1),S(d.trim()===e.chatId?`Nothing changed. Paste a replacement token to update credentials.`:`Paste the bot token again when changing the supergroup, so the existing secret is never cleared or reused silently.`);return}b(!0),S(null),w(!1);try{let e=await fetch(`/api/config/telegram`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({botToken:n,chatId:d})});if(!e.ok){let t=await e.json().catch(()=>({}));throw Error(t.error??`${e.status} ${e.statusText}`)}u(``),w(!0),await t.invalidate()}catch(e){S(e.message)}finally{b(!1)}}async function M(){let e=await fetch(`/api/config/telegram`,{method:`DELETE`});if(!e.ok&&e.status!==204){let t=await e.json().catch(()=>null);throw Error(t?.error??`Could not clear Telegram credentials (${e.status})`)}u(``),p(``),O(null),w(!1),S(null),await t.invalidate()}async function N(){A(!0),O(null);try{O(await(await fetch(`/api/config/telegram/health`)).json())}catch(e){O({configured:!0,preflight:null,error:{step:`getMe`,message:e.message},polling:null})}finally{A(!1)}}return(0,l.jsxs)(s,{active:`integrations`,title:`Telegram`,description:`Connect one forum-supergroup bot with one topic per agent, so conversations stay reachable from your phone.`,size:`narrow`,children:[e.migratedChatId&&(0,l.jsx)(g,{toChatId:e.migratedChatId}),(0,l.jsxs)(`section`,{className:`rounded-lg border bg-card p-5`,children:[(0,l.jsx)(`h3`,{className:`text-sm font-semibold uppercase tracking-wide text-muted-foreground mb-3`,children:`Credentials`}),e.configured&&(0,l.jsxs)(`p`,{className:`text-xs text-success mb-3`,children:[`✓ Stored: `,(0,l.jsx)(`code`,{className:`font-mono`,children:e.botTokenPreview}),` `,e.chatId&&(0,l.jsxs)(l.Fragment,{children:[`· chat `,(0,l.jsx)(`code`,{className:`font-mono`,children:e.chatId})]})]}),(0,l.jsxs)(`form`,{onSubmit:j,className:`space-y-3`,children:[(0,l.jsxs)(`label`,{className:`block`,children:[(0,l.jsx)(`span`,{className:`block text-sm font-medium mb-1`,children:`Bot token`}),(0,l.jsx)(`input`,{type:`password`,autoComplete:`off`,value:n,onChange:e=>{u(e.target.value),S(null)},placeholder:e.configured?`(leave blank to keep stored value)`:`1234567890:ABC...`,className:`w-full rounded-md border bg-background px-2 py-1.5 font-mono text-sm outline-none focus:ring-2 focus:ring-ring/30`,required:!e.configured}),(0,l.jsxs)(`p`,{className:`text-xs text-muted-foreground mt-1`,children:[`From @BotFather → /newbot. Disable Privacy Mode in `,(0,l.jsx)(`em`,{children:`Bot Settings → Team Privacy → Turn off`}),`.`]}),e.configured&&(0,l.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`Blank preserves the stored token. To remove it, use clear credentials and confirm the integration shutdown.`})]}),(0,l.jsxs)(`label`,{className:`block`,children:[(0,l.jsx)(`span`,{className:`block text-sm font-medium mb-1`,children:`Supergroup chat ID`}),(0,l.jsx)(`input`,{type:`text`,value:d,onChange:e=>{p(e.target.value),S(null)},placeholder:`-1001234567890`,className:`w-full rounded-md border bg-background px-2 py-1.5 font-mono text-sm outline-none focus:ring-2 focus:ring-ring/30`,required:!0}),(0,l.jsxs)(`p`,{className:`text-xs text-muted-foreground mt-1`,children:[`Forum-enabled supergroup the bot is admin in (with`,` `,(0,l.jsx)(`code`,{className:`font-mono`,children:`can_manage_topics`}),`).`]})]}),(0,l.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 pt-1`,children:[(0,l.jsx)(o,{variant:`primary`,type:`submit`,disabled:y,children:y?`saving…`:`save credentials`}),e.configured&&(0,l.jsx)(o,{variant:`danger`,onClick:()=>E(!0),children:`clear credentials`}),C&&(0,l.jsx)(`span`,{className:`text-xs text-success`,children:`saved ✓`}),x&&(0,l.jsxs)(`span`,{role:`alert`,className:`text-xs text-danger`,children:[`error: `,x]})]})]})]}),(0,l.jsxs)(`section`,{className:`rounded-lg border bg-card p-5`,children:[(0,l.jsxs)(`div`,{className:`mb-3 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between`,children:[(0,l.jsx)(`h3`,{className:`text-sm font-semibold uppercase tracking-wide text-muted-foreground`,children:`Preflight checks`}),(0,l.jsx)(o,{variant:`ghost`,onClick:N,disabled:k||!e.configured,children:k?`checking…`:`run preflight`})]}),!e.configured&&(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground italic`,children:`Save credentials above first.`}),e.configured&&!D&&!k&&(0,l.jsxs)(`p`,{className:`text-xs text-muted-foreground italic`,children:[`Click `,(0,l.jsx)(`em`,{children:`run preflight`}),` to validate the stored credentials against the Telegram Bot API.`]}),D&&(0,l.jsx)(v,{health:D}),D?.polling&&(0,l.jsx)(_,{polling:D.polling})]}),e.configured&&(0,l.jsx)(m,{}),(0,l.jsx)(f,{}),e.configured&&(0,l.jsx)(h,{}),(0,l.jsx)(i,{open:T,title:`Disconnect Telegram?`,description:(0,l.jsx)(`p`,{children:`This permanently removes the saved bot token and supergroup ID. Telegram polling, ingress, and outbound delivery stop until new credentials are saved and pairing is completed again.`}),confirmLabel:`clear credentials and disconnect`,onConfirm:async()=>{try{await M()}catch(e){throw S(e instanceof Error?e.message:String(e)),e}},onOpenChange:E})]})}function m(){let[e,t]=(0,c.useState)(null),[n,r]=(0,c.useState)(null),[a,s]=(0,c.useState)(null),[u,d]=(0,c.useState)(!1),f=async()=>{let e=await fetch(`/api/config/telegram/pairing`);if(!e.ok)throw Error(e.statusText);t(await e.json())};(0,c.useEffect)(()=>{f().catch(e=>s(e.message))},[]);async function p(){s(null);let e=await fetch(`/api/config/telegram/pairing/challenge`,{method:`POST`}),n=await e.json().catch(()=>({}));if(!e.ok||!n.code)return s(n.error??e.statusText);r(n.code),t(n)}async function m(){let e=await fetch(`/api/config/telegram/pairing/challenge`,{method:`DELETE`});if(!e.ok&&e.status!==204){let t=await e.json().catch(()=>null);throw Error(t?.error??`Could not cancel the pairing code`)}r(null),await f()}async function h(){let e=await fetch(`/api/config/telegram/pairing/reset`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({confirm:!0})});if(!e.ok){let t=await e.json().catch(()=>null);throw Error(t?.error??`Could not reset Telegram owner`)}r(null),await f()}return(0,l.jsxs)(`section`,{className:`rounded-lg border bg-card p-5`,children:[(0,l.jsx)(`h3`,{className:`text-sm font-semibold uppercase tracking-wide text-muted-foreground mb-1`,children:`Owner pairing`}),(0,l.jsxs)(`p`,{className:`text-xs text-muted-foreground mb-3`,children:[`Telegram stays closed until one owner consumes a short-lived code in the configured`,` `,(0,l.jsx)(`code`,{className:`font-mono`,children:`⚙ bazilion`}),` service topic.`]}),e?.paired?(0,l.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,l.jsx)(`span`,{className:`text-sm text-success`,children:`✓ owner paired`}),(0,l.jsx)(o,{variant:`danger`,onClick:()=>d(!0),children:`reset owner`})]}):(0,l.jsxs)(`div`,{className:`space-y-2`,children:[(0,l.jsx)(`p`,{className:`text-sm text-warning`,children:`Unpaired — all Telegram ingress is closed.`}),n?(0,l.jsxs)(`div`,{className:`rounded-md border bg-muted/30 p-3 text-sm`,children:[`Send `,(0,l.jsxs)(`code`,{className:`font-mono`,children:[`/pair `,n]}),` in the service topic. This code is shown once and expires in ten minutes.`]}):null,(0,l.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,l.jsx)(o,{variant:`primary`,onClick:p,children:`generate pairing code`}),e?.challengeActive&&(0,l.jsx)(o,{variant:`ghost`,onClick:()=>void m().catch(e=>s(e instanceof Error?e.message:String(e))),children:`cancel code`})]})]}),a&&(0,l.jsx)(`p`,{role:`alert`,className:`mt-2 text-xs text-danger`,children:a}),(0,l.jsx)(i,{open:u,title:`Revoke the paired Telegram owner?`,description:(0,l.jsx)(`p`,{children:`This immediately revokes the current owner and closes all Telegram ingress. No one can use the bot until a new one-time pairing code is generated and consumed.`}),confirmLabel:`revoke owner and close ingress`,onConfirm:async()=>{try{await h()}catch(e){throw s(e instanceof Error?e.message:String(e)),e}},onOpenChange:d})]})}function h(){let[e,t]=(0,c.useState)(null),[n,r]=(0,c.useState)(``),[a,s]=(0,c.useState)(``),[u,d]=(0,c.useState)(!1),[f,p]=(0,c.useState)(null),[m,h]=(0,c.useState)(null);async function g(){try{let e=await fetch(`/api/config/telegram/acl`);if(!e.ok)throw Error(e.statusText);t(await e.json())}catch(e){p(e.message)}}(0,c.useEffect)(()=>{g()},[]);async function _(e){e.preventDefault();let t=Number(n);if(!Number.isInteger(t)){p(`user id must be an integer`);return}d(!0),p(null);try{let e=await fetch(`/api/config/telegram/acl`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({userId:t,label:a.trim()||null})});if(!e.ok){let t=await e.json().catch(()=>({}));throw Error(t.error??e.statusText)}r(``),s(``),await g()}catch(e){p(e.message)}finally{d(!1)}}async function v(e){p(null);let t=await fetch(`/api/config/telegram/acl/${e}`,{method:`DELETE`});if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e.error??t.statusText)}await g()}return(0,l.jsxs)(`section`,{className:`rounded-lg border bg-card p-5`,children:[(0,l.jsx)(`h3`,{className:`text-sm font-semibold uppercase tracking-wide text-muted-foreground mb-1`,children:`Access control`}),(0,l.jsxs)(`p`,{className:`text-xs text-muted-foreground mb-3`,children:[`Allowlisted Telegram users can use the bot (commands + chat). An empty list is closed; ownership begins only through the one-time pairing flow. Users find their id via`,` `,(0,l.jsx)(`code`,{className:`font-mono`,children:`/whoami`}),`.`]}),e===null?(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground italic`,children:`loading…`}):e.length===0?(0,l.jsx)(`p`,{className:`text-xs text-warning mb-3`,children:`Closed — no paired owner or allowlisted members.`}):(0,l.jsx)(`ul`,{className:`mb-3 space-y-1 text-sm`,children:e.map(e=>(0,l.jsxs)(`li`,{className:`flex flex-wrap items-center gap-2`,children:[(0,l.jsx)(`code`,{className:`font-mono`,children:e.userId}),(0,l.jsxs)(`span`,{className:`text-muted-foreground`,children:[e.label??(e.username?`@${e.username}`:`—`),` · `,e.role]}),e.role!==`owner`&&(0,l.jsx)(o,{variant:`danger`,className:`text-xs`,onClick:()=>h(e),children:`remove`})]},e.userId))}),(0,l.jsxs)(`form`,{onSubmit:_,className:`flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-end`,children:[(0,l.jsxs)(`label`,{className:`m-0 flex flex-col gap-1 text-xs font-medium text-foreground`,children:[`Telegram user ID`,(0,l.jsx)(`input`,{value:n,onChange:e=>r(e.target.value),placeholder:`123456789`,inputMode:`numeric`,className:`w-full rounded-md border bg-background px-2 py-1 font-mono text-sm sm:w-32`})]}),(0,l.jsxs)(`label`,{className:`m-0 flex flex-col gap-1 text-xs font-medium text-foreground`,children:[`Label `,(0,l.jsx)(`span`,{className:`font-normal text-muted-foreground`,children:`(optional)`}),(0,l.jsx)(`input`,{value:a,onChange:e=>s(e.target.value),placeholder:`e.g. Pat`,className:`w-full rounded-md border bg-background px-2 py-1 text-sm sm:w-40`})]}),(0,l.jsx)(o,{variant:`ghost`,type:`submit`,disabled:u,children:`add`}),f&&(0,l.jsx)(`span`,{role:`alert`,className:`text-xs text-danger`,children:f})]}),(0,l.jsx)(i,{open:m!==null,title:`Remove ${m?.label??m?.username??m?.userId??``}?`,description:(0,l.jsxs)(`p`,{children:[`Telegram user `,(0,l.jsx)(`code`,{className:`font-mono`,children:m?.userId}),` immediately loses command and chat access. Their Telegram account is not changed, and they can be allowlisted again later.`]}),confirmLabel:`remove Telegram access`,onConfirm:async()=>{if(m)try{await v(m.userId)}catch(e){throw p(e instanceof Error?e.message:String(e)),e}},onOpenChange:e=>{e||h(null)}})]})}function g({toChatId:e}){let[t,n]=(0,c.useState)(!1),[r,i]=(0,c.useState)(null);async function a(){n(!0),i(null);try{let e=await fetch(`/api/config/telegram/reconnect`,{method:`POST`});if(!e.ok){let t=await e.json().catch(()=>({}));throw Error(t.error??e.statusText)}window.location.reload()}catch(e){i(e.message),n(!1)}}return(0,l.jsxs)(`div`,{className:`rounded-md border-2 border-danger/25 bg-danger/10 px-4 py-3 text-sm`,children:[(0,l.jsx)(`div`,{className:`font-semibold text-danger mb-1`,children:`Supergroup chat id changed`}),(0,l.jsxs)(`p`,{className:`text-danger mb-2`,children:[`Telegram migrated this supergroup to a new chat id (`,(0,l.jsx)(`code`,{className:`font-mono`,children:e}),`). The bot is still pointed at the old id. Reconnect to repoint it and re-create the `,(0,l.jsx)(`code`,{className:`font-mono`,children:`⚙ bazilion`}),` `,`service chat in the new team. Agent topic bindings will reconcile on next use.`]}),(0,l.jsx)(o,{variant:`primary`,onClick:a,disabled:t,children:t?`reconnecting…`:`Reconnect to ${e}`}),r&&(0,l.jsx)(`span`,{role:`alert`,className:`ml-3 text-xs text-danger`,children:r})]})}function _({polling:e}){let t=e.startedAt?new Date(e.startedAt).toISOString():null,n=e.lastSuccessfulPollAt?new Date(e.lastSuccessfulPollAt).toISOString():null;return(0,l.jsxs)(`div`,{className:`mt-4 rounded-md border bg-muted/30 px-3 py-2 text-xs space-y-1`,children:[(0,l.jsx)(`p`,{className:`font-semibold uppercase tracking-wide text-muted-foreground`,children:`Polling state`}),(0,l.jsxs)(`div`,{className:`flex flex-wrap gap-x-4 gap-y-1 font-mono`,children:[(0,l.jsx)(`span`,{className:e.running?`text-success`:`text-danger`,children:e.running?`running`:`stopped`}),(0,l.jsx)(`span`,{className:e.activated?`text-success`:`text-warning`,children:e.activated?`activated`:`awaiting activation`}),e.lastUpdateId!==null&&(0,l.jsxs)(`span`,{children:[`last update `,e.lastUpdateId]}),t&&(0,l.jsxs)(`span`,{children:[`started `,t]}),n&&(0,l.jsxs)(`span`,{children:[`last poll `,n]})]}),e.error&&(0,l.jsxs)(`p`,{role:`alert`,className:`text-danger`,children:[`error: `,e.error]})]})}function v({health:e}){if(e.error)return(0,l.jsxs)(`div`,{role:`alert`,className:`rounded-md border border-danger/25 bg-danger/10 px-3 py-2 text-sm`,children:[(0,l.jsxs)(`p`,{className:`font-semibold text-danger`,children:[`Failed at `,(0,l.jsx)(`code`,{className:`font-mono`,children:e.error.step})]}),(0,l.jsx)(`p`,{className:`text-danger mt-1`,children:e.error.message}),b(e.error.step)]});if(!e.preflight)return(0,l.jsx)(`p`,{role:`status`,className:`text-xs text-muted-foreground italic`,children:`No preflight data.`});let t=e.preflight;return(0,l.jsxs)(`ul`,{role:`status`,"aria-live":`polite`,"aria-atomic":`true`,className:`space-y-1.5`,children:[(0,l.jsxs)(y,{ok:t.botUsername.length>0,label:`Bot identity`,children:[`@`,t.botUsername]}),(0,l.jsx)(y,{ok:t.chatTitle.length>0,label:`Supergroup reachable`,children:t.chatTitle}),(0,l.jsx)(y,{ok:t.isForum,label:`Forum topics enabled`,children:t.isForum?`is_forum: true`:`is_forum: false — the supergroup owner must enable Topics in team settings`}),(0,l.jsx)(y,{ok:t.hasManageTopics,label:`Bot has can_manage_topics`,children:t.hasManageTopics?`admin with can_manage_topics`:`promote the bot to admin in the supergroup with the "Manage topics" permission`}),(0,l.jsx)(y,{ok:t.privacyModeOff,label:`Privacy Mode is OFF`,children:t.privacyModeOff?`can_read_all_group_messages: true`:`BotFather → /mybots → select bot → Bot Settings → Team Privacy → Turn off`}),(0,l.jsx)(y,{ok:t.chatIsPrivate,label:`Supergroup is private`,children:t.chatIsPrivate?`no public @username`:`public groups expose topic content to readers`}),(0,l.jsx)(y,{ok:t.memberCount===2,label:`Expected membership`,children:t.memberCount===null?`member count unavailable — verify one owner plus the bot manually`:`${t.memberCount} members reported; secure posture is one owner plus the bot`}),t.ownerPresent!==null&&(0,l.jsx)(y,{ok:t.ownerPresent,label:`Paired owner is present`,children:t.ownerPresent?`owner membership confirmed`:`owner missing — Telegram ingress is degraded`})]})}function y({ok:e,label:t,children:n}){return(0,l.jsxs)(`li`,{className:`flex items-start gap-2 text-sm`,children:[(0,l.jsx)(`span`,{className:`mt-0.5 inline-flex h-4 w-4 items-center justify-center rounded-full text-[10px] font-bold leading-none ${e?`bg-success/10 text-success`:`bg-danger/10 text-danger`}`,"aria-hidden":!0,children:e?`✓`:`✕`}),(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`span`,{className:`font-medium`,children:t}),(0,l.jsx)(`span`,{className:`ml-2 text-xs ${e?`text-muted-foreground`:`text-danger`}`,children:n})]})]})}function b(e){switch(e){case`getMe`:return(0,l.jsx)(`p`,{className:`text-xs text-danger mt-1`,children:`The token is invalid or revoked. Re-issue with @BotFather → /token, or paste a fresh one above.`});case`getChat`:return(0,l.jsx)(`p`,{className:`text-xs text-danger mt-1`,children:`The chat id either doesn't exist, points at a basic team (not a supergroup), or the bot isn't a member. Forward any message from the supergroup to the bot to double-check the id, then add the bot to the team.`});case`getChatMember`:return(0,l.jsx)(`p`,{className:`text-xs text-danger mt-1`,children:`The bot is in the chat but the membership lookup failed. Usually means the bot was kicked or the chat id was migrated — confirm the bot is still in the supergroup.`})}}export{p as component};
|
|
1
|
+
import{r as e,t}from"./jsx-runtime-DGeXAQPT.js";import{t as n}from"./react-3W8R1pOO.js";import{d as r}from"./preload-helper-bztXdkDj.js";import{t as i}from"./ConfirmDialog-BzIiABOP.js";import{o as a}from"./index-Bi-HxcPG.js";import{t as o}from"./Button-ByiV6fpd.js";import{t as s}from"./ConfigPage-BCLp-FUC.js";var c=e(n(),1),l=t(),u={communication_approval:`Communication approvals`,lesson_proposal:`Lesson proposals`,review_failure:`Review failures`,trigger_failure:`Scheduled trigger failures`,agent_loop_break:`Agent message loop breaks`};async function d(e,t=`GET`,n){let r=await fetch(`/api/notifications${e}`,{method:t,cache:`no-store`,...n===void 0?{}:{headers:{"Content-Type":`application/json`},body:JSON.stringify(n)}}),i=await r.json();if(!r.ok)throw Error(i.error??`Notification request failed`);return i}function f(){let[e,t]=(0,c.useState)(null),[n,r]=(0,c.useState)(!1),[a,s]=(0,c.useState)(``),[f,p]=(0,c.useState)([]),[m,h]=(0,c.useState)(`UTC`),[g,_]=(0,c.useState)(!1),[v,y]=(0,c.useState)(`22:00`),[b,x]=(0,c.useState)(`07:00`),[S,C]=(0,c.useState)({receipts:[],nextCursor:null}),[w,T]=(0,c.useState)(!1),[E,D]=(0,c.useState)(null),[O,k]=(0,c.useState)(null),[A,j]=(0,c.useState)(null),[M,N]=(0,c.useState)(null);async function P(){let[e,n]=await Promise.all([d(``),d(`/receipts`)]);t(e),C(n),r(e.settings.enabled),s(e.settings.destination?.id??``),p(e.settings.kinds),h(e.settings.timezone),_(e.settings.quietHours!==null),y(e.settings.quietHours?.start??`22:00`),x(e.settings.quietHours?.end??`07:00`)}(0,c.useEffect)(()=>{P().catch(e=>D(String(e.message)))},[]);async function F(e){T(!0),D(null),k(null);try{await e()}catch(e){D(e instanceof Error?e.message:`Notification request failed`)}finally{T(!1)}}async function I(t){e&&(await d(``,`PUT`,{expectedRevision:e.settings.revision,enabled:n,destinationId:a||void 0,kinds:f,timezone:m,quietHours:g?{start:v,end:b}:null,includeOpenPreview:t}),await P(),j(null),k(`Notification settings saved. Delivery does not resolve Attention items.`))}return(0,l.jsxs)(`section`,{className:`card`,style:{marginTop:`1.5rem`,padding:`1.25rem`,minWidth:0},"aria-labelledby":`notification-title`,children:[(0,l.jsx)(`h2`,{id:`notification-title`,children:`Attention notifications`}),(0,l.jsx)(`p`,{className:`muted`,children:`Optional Telegram notices for items that need your attention. New enablement sends future items only. Agent-topic error mirrors may also report the same failure.`}),E&&(0,l.jsxs)(`p`,{role:`alert`,children:[E,`. Refresh settings before retrying a conflicting change.`]}),O&&(0,l.jsx)(`p`,{role:`status`,children:O}),e?(0,l.jsxs)(l.Fragment,{children:[e.settings.restorePaused&&(0,l.jsx)(`p`,{role:`status`,children:`Paused after restore. Telegram may have newer messages than this backup. Re-enable for future items, or explicitly preview old open items with possible duplicates.`}),!e.readiness.ready&&(0,l.jsx)(`p`,{children:`Destination unavailable. Configure and pair the private Telegram forum, start the bot, then refresh.`}),e.diagnostic&&(0,l.jsxs)(`p`,{role:`status`,children:[`Delivery status: `,e.diagnostic]}),(0,l.jsx)(`form`,{onSubmit:e=>{e.preventDefault(),F(()=>I())},children:(0,l.jsxs)(`fieldset`,{disabled:w,style:{border:0,padding:0,minWidth:0},children:[(0,l.jsxs)(`label`,{style:{display:`block`,marginBlock:`.75rem`},children:[(0,l.jsx)(`input`,{type:`checkbox`,checked:n,onChange:e=>r(e.target.checked)}),` `,`Enable Attention notifications`]}),(0,l.jsxs)(`label`,{style:{display:`grid`,gap:`.35rem`,marginBlock:`.75rem`},children:[`Destination`,(0,l.jsxs)(`select`,{value:a,onChange:e=>s(e.target.value),required:n,style:{maxWidth:`100%`},children:[(0,l.jsx)(`option`,{value:``,children:`Choose the paired service topic`}),e.readiness.destination&&(0,l.jsx)(`option`,{value:e.readiness.destination.id,children:`Paired group · Bazilion service topic`}),e.settings.destination&&e.settings.destination.id!==e.readiness.destination?.id&&(0,l.jsx)(`option`,{value:e.settings.destination.id,children:`Previous destination (unavailable)`})]})]}),(0,l.jsx)(`p`,{className:`m-0 text-sm text-mocha`,children:`Notices go to the operational thread in your paired Telegram group.`}),e.readiness.destination&&(0,l.jsxs)(`details`,{className:`mt-2 text-xs text-mocha`,children:[(0,l.jsx)(`summary`,{className:`cursor-pointer`,children:`Telegram destination IDs`}),(0,l.jsxs)(`p`,{className:`mt-2 break-all`,children:[`Group `,e.readiness.destination.chatId,` · Topic `,e.readiness.destination.topicId]})]}),(0,l.jsxs)(`fieldset`,{style:{marginBlock:`1rem`,minWidth:0},children:[(0,l.jsx)(`legend`,{children:`Include these Attention kinds`}),Object.keys(u).map(e=>(0,l.jsxs)(`label`,{style:{display:`block`,marginBlock:`.5rem`},children:[(0,l.jsx)(`input`,{type:`checkbox`,checked:f.includes(e),onChange:t=>p(t.target.checked?[...f,e]:f.filter(t=>t!==e))}),` `,u[e]]},e))]}),(0,l.jsxs)(`label`,{style:{display:`grid`,gap:`.35rem`},children:[`Timezone (IANA)`,(0,l.jsx)(`input`,{value:m,onChange:e=>h(e.target.value),placeholder:`Europe/Warsaw`,required:!0,style:{maxWidth:`100%`,minWidth:0}})]}),(0,l.jsxs)(`label`,{style:{display:`block`,marginBlock:`.75rem`},children:[(0,l.jsx)(`input`,{type:`checkbox`,checked:g,onChange:e=>_(e.target.checked)}),` `,`Use quiet hours for all selected kinds`]}),g&&(0,l.jsxs)(`div`,{style:{display:`flex`,flexWrap:`wrap`,gap:`1rem`},children:[(0,l.jsxs)(`label`,{children:[`Start`,` `,(0,l.jsx)(`input`,{type:`time`,value:v,required:!0,onChange:e=>y(e.target.value)})]}),(0,l.jsxs)(`label`,{children:[`End`,` `,(0,l.jsx)(`input`,{type:`time`,value:b,required:!0,onChange:e=>x(e.target.value)})]})]}),(0,l.jsxs)(`div`,{style:{display:`flex`,flexWrap:`wrap`,gap:`.5rem`,marginTop:`1rem`},children:[(0,l.jsx)(o,{variant:`primary`,type:`submit`,disabled:!f.length||n&&(!e.readiness.ready||!a),children:`Save settings`}),(0,l.jsx)(o,{variant:`ghost`,disabled:!n||!e.readiness.ready||!a||!f.length,onClick:()=>void F(async()=>j(await d(`/preview`,`POST`,{kinds:f}))),children:`Preview open items`})]})]})}),(0,l.jsxs)(`section`,{"aria-label":`Delivery receipts`,className:`mt-6 flex min-w-0 flex-col gap-4 border-t border-frost pt-5`,children:[(0,l.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,l.jsx)(`h3`,{className:`m-0`,children:`Delivery receipts`}),(0,l.jsx)(o,{variant:`ghost`,disabled:w,onClick:()=>void F(async()=>C(await d(`/receipts`))),children:`Refresh receipts`})]}),(0,l.jsx)(`p`,{className:`m-0 text-sm text-mocha`,children:`Delivery confirms Telegram received the notice. It does not approve or resolve the Attention item.`}),S.receipts.length===0&&(0,l.jsx)(`p`,{className:`m-0`,children:`No notification receipts yet.`}),(0,l.jsx)(`ul`,{className:`m-0 grid list-none gap-3 p-0`,children:S.receipts.map(t=>(0,l.jsxs)(`li`,{className:`flex min-w-0 flex-col gap-3 rounded-lg border border-frost bg-ivory p-4 [overflow-wrap:anywhere]`,children:[(0,l.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,l.jsx)(`strong`,{children:u[t.sourceKind]}),(0,l.jsx)(`span`,{className:`rounded-full bg-frost px-2 py-1 text-xs font-semibold capitalize`,children:t.state})]}),(0,l.jsxs)(`p`,{className:`m-0 text-xs text-mocha`,children:[new Date(t.updatedAt).toLocaleString(),` · `,t.attempts,` `,t.attempts===1?`attempt`:`attempts`]}),t.state===`uncertain`&&(0,l.jsx)(`p`,{className:`m-0 text-sm`,children:`Telegram may have received this notice. Retrying could send a duplicate.`}),t.state===`deferred`&&(0,l.jsx)(`p`,{className:`m-0 text-sm`,children:`Waiting for an eligible delivery opportunity.`}),t.state===`failed`&&(0,l.jsx)(`p`,{className:`m-0 text-sm`,children:`Delivery failed. Check the details before retrying.`}),(0,l.jsxs)(`details`,{className:`text-xs text-mocha`,children:[(0,l.jsx)(`summary`,{className:`cursor-pointer`,children:`Technical details`}),(0,l.jsxs)(`dl`,{className:`mt-3 grid min-w-0 gap-2`,children:[(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`dt`,{className:`font-semibold`,children:`Source`}),(0,l.jsx)(`dd`,{className:`m-0`,children:t.sourceId})]}),(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`dt`,{className:`font-semibold`,children:`Receipt`}),(0,l.jsx)(`dd`,{className:`m-0`,children:t.id})]}),t.telegramMessageId&&(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`dt`,{className:`font-semibold`,children:`Telegram message`}),(0,l.jsx)(`dd`,{className:`m-0`,children:t.telegramMessageId})]}),t.diagnostic&&(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`dt`,{className:`font-semibold`,children:`Diagnostic`}),(0,l.jsx)(`dd`,{className:`m-0`,children:t.diagnostic})]})]})]}),[`failed`,`uncertain`].includes(t.state)&&(0,l.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:(0,l.jsx)(o,{variant:`ghost`,disabled:w||!e.settings.enabled||e.settings.restorePaused,onClick:()=>N(t),children:`Retry notice`})})]},t.id))})]}),S.nextCursor&&(0,l.jsx)(o,{variant:`ghost`,disabled:w,onClick:()=>void F(async()=>{let e=await d(`/receipts?cursor=${encodeURIComponent(S.nextCursor)}`);C({receipts:[...S.receipts,...e.receipts],nextCursor:e.nextCursor})}),children:`More receipts`})]}):(0,l.jsx)(`p`,{children:`Loading notification settings…`}),(0,l.jsx)(o,{variant:`ghost`,className:`mt-4`,disabled:w,onClick:()=>void F(P),children:`Refresh settings and destination`}),(0,l.jsx)(i,{open:A!==null,title:`Include currently open items?`,confirmLabel:`Save and include preview`,confirmVariant:`primary`,description:(0,l.jsxs)(`p`,{children:[A?.count??0,` currently eligible items will be considered. Resolved items are omitted.`,` `,A?.possibleDuplicates?`This restored backup may be missing later Telegram receipts, so duplicate messages are possible.`:`Confirmed deliveries will not be repeated.`]}),onOpenChange:e=>{e||j(null)},onConfirm:()=>I(A?.id)}),(0,l.jsx)(i,{open:M!==null,title:`Retry this notification?`,confirmLabel:`Retry, allowing a possible duplicate`,confirmVariant:`primary`,description:`Telegram may already have received this notice. Retry only if you accept a possible duplicate. The source, destination and policy will be checked again.`,onOpenChange:e=>{e||N(null)},onConfirm:async()=>{M&&(await d(`/receipts/${encodeURIComponent(M.id)}/retry`,`POST`,{expectedUpdatedAt:M.updatedAt,acknowledgePossibleDuplicate:!0}),C(await d(`/receipts`)),N(null))}})]})}function p(){let e=a.useLoaderData(),t=r(),[n,u]=(0,c.useState)(``),[d,p]=(0,c.useState)(e.chatId),[y,b]=(0,c.useState)(!1),[x,S]=(0,c.useState)(null),[C,w]=(0,c.useState)(!1),[T,E]=(0,c.useState)(!1),[D,O]=(0,c.useState)(null),[k,A]=(0,c.useState)(!1);async function j(r){if(r.preventDefault(),e.configured&&n.trim().length===0){w(!1),S(d.trim()===e.chatId?`Nothing changed. Paste a replacement token to update credentials.`:`Paste the bot token again when changing the supergroup, so the existing secret is never cleared or reused silently.`);return}b(!0),S(null),w(!1);try{let e=await fetch(`/api/config/telegram`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({botToken:n,chatId:d})});if(!e.ok){let t=await e.json().catch(()=>({}));throw Error(t.error??`${e.status} ${e.statusText}`)}u(``),w(!0),await t.invalidate()}catch(e){S(e.message)}finally{b(!1)}}async function M(){let e=await fetch(`/api/config/telegram`,{method:`DELETE`});if(!e.ok&&e.status!==204){let t=await e.json().catch(()=>null);throw Error(t?.error??`Could not clear Telegram credentials (${e.status})`)}u(``),p(``),O(null),w(!1),S(null),await t.invalidate()}async function N(){A(!0),O(null);try{O(await(await fetch(`/api/config/telegram/health`)).json())}catch(e){O({configured:!0,preflight:null,error:{step:`getMe`,message:e.message},polling:null})}finally{A(!1)}}return(0,l.jsxs)(s,{active:`integrations`,title:`Telegram`,description:`Connect one forum-supergroup bot with one topic per agent, so conversations stay reachable from your phone.`,size:`narrow`,children:[e.migratedChatId&&(0,l.jsx)(g,{toChatId:e.migratedChatId}),(0,l.jsxs)(`section`,{className:`rounded-lg border bg-card p-5`,children:[(0,l.jsx)(`h3`,{className:`text-sm font-semibold uppercase tracking-wide text-muted-foreground mb-3`,children:`Credentials`}),e.configured&&(0,l.jsxs)(`p`,{className:`text-xs text-success mb-3`,children:[`✓ Stored: `,(0,l.jsx)(`code`,{className:`font-mono`,children:e.botTokenPreview}),` `,e.chatId&&(0,l.jsxs)(l.Fragment,{children:[`· chat `,(0,l.jsx)(`code`,{className:`font-mono`,children:e.chatId})]})]}),(0,l.jsxs)(`form`,{onSubmit:j,className:`space-y-3`,children:[(0,l.jsxs)(`label`,{className:`block`,children:[(0,l.jsx)(`span`,{className:`block text-sm font-medium mb-1`,children:`Bot token`}),(0,l.jsx)(`input`,{type:`password`,autoComplete:`off`,value:n,onChange:e=>{u(e.target.value),S(null)},placeholder:e.configured?`(leave blank to keep stored value)`:`1234567890:ABC...`,className:`w-full rounded-md border bg-background px-2 py-1.5 font-mono text-sm outline-none focus:ring-2 focus:ring-ring/30`,required:!e.configured}),(0,l.jsxs)(`p`,{className:`text-xs text-muted-foreground mt-1`,children:[`From @BotFather → /newbot. Disable Privacy Mode in `,(0,l.jsx)(`em`,{children:`Bot Settings → Team Privacy → Turn off`}),`.`]}),e.configured&&(0,l.jsx)(`p`,{className:`mt-1 text-xs text-muted-foreground`,children:`Blank preserves the stored token. To remove it, use clear credentials and confirm the integration shutdown.`})]}),(0,l.jsxs)(`label`,{className:`block`,children:[(0,l.jsx)(`span`,{className:`block text-sm font-medium mb-1`,children:`Supergroup chat ID`}),(0,l.jsx)(`input`,{type:`text`,value:d,onChange:e=>{p(e.target.value),S(null)},placeholder:`-1001234567890`,className:`w-full rounded-md border bg-background px-2 py-1.5 font-mono text-sm outline-none focus:ring-2 focus:ring-ring/30`,required:!0}),(0,l.jsxs)(`p`,{className:`text-xs text-muted-foreground mt-1`,children:[`Forum-enabled supergroup the bot is admin in (with`,` `,(0,l.jsx)(`code`,{className:`font-mono`,children:`can_manage_topics`}),`).`]})]}),(0,l.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 pt-1`,children:[(0,l.jsx)(o,{variant:`primary`,type:`submit`,disabled:y,children:y?`saving…`:`save credentials`}),e.configured&&(0,l.jsx)(o,{variant:`danger`,onClick:()=>E(!0),children:`clear credentials`}),C&&(0,l.jsx)(`span`,{className:`text-xs text-success`,children:`saved ✓`}),x&&(0,l.jsxs)(`span`,{role:`alert`,className:`text-xs text-danger`,children:[`error: `,x]})]})]})]}),(0,l.jsxs)(`section`,{className:`rounded-lg border bg-card p-5`,children:[(0,l.jsxs)(`div`,{className:`mb-3 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between`,children:[(0,l.jsx)(`h3`,{className:`text-sm font-semibold uppercase tracking-wide text-muted-foreground`,children:`Preflight checks`}),(0,l.jsx)(o,{variant:`ghost`,onClick:N,disabled:k||!e.configured,children:k?`checking…`:`run preflight`})]}),!e.configured&&(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground italic`,children:`Save credentials above first.`}),e.configured&&!D&&!k&&(0,l.jsxs)(`p`,{className:`text-xs text-muted-foreground italic`,children:[`Click `,(0,l.jsx)(`em`,{children:`run preflight`}),` to validate the stored credentials against the Telegram Bot API.`]}),D&&(0,l.jsx)(v,{health:D}),D?.polling&&(0,l.jsx)(_,{polling:D.polling})]}),e.configured&&(0,l.jsx)(m,{}),(0,l.jsx)(f,{}),e.configured&&(0,l.jsx)(h,{}),(0,l.jsx)(i,{open:T,title:`Disconnect Telegram?`,description:(0,l.jsx)(`p`,{children:`This permanently removes the saved bot token and supergroup ID. Telegram polling, ingress, and outbound delivery stop until new credentials are saved and pairing is completed again.`}),confirmLabel:`clear credentials and disconnect`,onConfirm:async()=>{try{await M()}catch(e){throw S(e instanceof Error?e.message:String(e)),e}},onOpenChange:E})]})}function m(){let[e,t]=(0,c.useState)(null),[n,r]=(0,c.useState)(null),[a,s]=(0,c.useState)(null),[u,d]=(0,c.useState)(!1),f=async()=>{let e=await fetch(`/api/config/telegram/pairing`);if(!e.ok)throw Error(e.statusText);t(await e.json())};(0,c.useEffect)(()=>{f().catch(e=>s(e.message))},[]);async function p(){s(null);let e=await fetch(`/api/config/telegram/pairing/challenge`,{method:`POST`}),n=await e.json().catch(()=>({}));if(!e.ok||!n.code)return s(n.error??e.statusText);r(n.code),t(n)}async function m(){let e=await fetch(`/api/config/telegram/pairing/challenge`,{method:`DELETE`});if(!e.ok&&e.status!==204){let t=await e.json().catch(()=>null);throw Error(t?.error??`Could not cancel the pairing code`)}r(null),await f()}async function h(){let e=await fetch(`/api/config/telegram/pairing/reset`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({confirm:!0})});if(!e.ok){let t=await e.json().catch(()=>null);throw Error(t?.error??`Could not reset Telegram owner`)}r(null),await f()}return(0,l.jsxs)(`section`,{className:`rounded-lg border bg-card p-5`,children:[(0,l.jsx)(`h3`,{className:`text-sm font-semibold uppercase tracking-wide text-muted-foreground mb-1`,children:`Owner pairing`}),(0,l.jsxs)(`p`,{className:`text-xs text-muted-foreground mb-3`,children:[`Telegram stays closed until one owner consumes a short-lived code in the configured`,` `,(0,l.jsx)(`code`,{className:`font-mono`,children:`⚙ bazilion`}),` service topic.`]}),e?.paired?(0,l.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,l.jsx)(`span`,{className:`text-sm text-success`,children:`✓ owner paired`}),(0,l.jsx)(o,{variant:`danger`,onClick:()=>d(!0),children:`reset owner`})]}):(0,l.jsxs)(`div`,{className:`space-y-2`,children:[(0,l.jsx)(`p`,{className:`text-sm text-warning`,children:`Unpaired — all Telegram ingress is closed.`}),n?(0,l.jsxs)(`div`,{className:`rounded-md border bg-muted/30 p-3 text-sm`,children:[`Send `,(0,l.jsxs)(`code`,{className:`font-mono`,children:[`/pair `,n]}),` in the service topic. This code is shown once and expires in ten minutes.`]}):null,(0,l.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,l.jsx)(o,{variant:`primary`,onClick:p,children:`generate pairing code`}),e?.challengeActive&&(0,l.jsx)(o,{variant:`ghost`,onClick:()=>void m().catch(e=>s(e instanceof Error?e.message:String(e))),children:`cancel code`})]})]}),a&&(0,l.jsx)(`p`,{role:`alert`,className:`mt-2 text-xs text-danger`,children:a}),(0,l.jsx)(i,{open:u,title:`Revoke the paired Telegram owner?`,description:(0,l.jsx)(`p`,{children:`This immediately revokes the current owner and closes all Telegram ingress. No one can use the bot until a new one-time pairing code is generated and consumed.`}),confirmLabel:`revoke owner and close ingress`,onConfirm:async()=>{try{await h()}catch(e){throw s(e instanceof Error?e.message:String(e)),e}},onOpenChange:d})]})}function h(){let[e,t]=(0,c.useState)(null),[n,r]=(0,c.useState)(``),[a,s]=(0,c.useState)(``),[u,d]=(0,c.useState)(!1),[f,p]=(0,c.useState)(null),[m,h]=(0,c.useState)(null);async function g(){try{let e=await fetch(`/api/config/telegram/acl`);if(!e.ok)throw Error(e.statusText);t(await e.json())}catch(e){p(e.message)}}(0,c.useEffect)(()=>{g()},[]);async function _(e){e.preventDefault();let t=Number(n);if(!Number.isInteger(t)){p(`user id must be an integer`);return}d(!0),p(null);try{let e=await fetch(`/api/config/telegram/acl`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({userId:t,label:a.trim()||null})});if(!e.ok){let t=await e.json().catch(()=>({}));throw Error(t.error??e.statusText)}r(``),s(``),await g()}catch(e){p(e.message)}finally{d(!1)}}async function v(e){p(null);let t=await fetch(`/api/config/telegram/acl/${e}`,{method:`DELETE`});if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e.error??t.statusText)}await g()}return(0,l.jsxs)(`section`,{className:`rounded-lg border bg-card p-5`,children:[(0,l.jsx)(`h3`,{className:`text-sm font-semibold uppercase tracking-wide text-muted-foreground mb-1`,children:`Access control`}),(0,l.jsxs)(`p`,{className:`text-xs text-muted-foreground mb-3`,children:[`Allowlisted Telegram users can use the bot (commands + chat). An empty list is closed; ownership begins only through the one-time pairing flow. Users find their id via`,` `,(0,l.jsx)(`code`,{className:`font-mono`,children:`/whoami`}),`.`]}),e===null?(0,l.jsx)(`p`,{className:`text-xs text-muted-foreground italic`,children:`loading…`}):e.length===0?(0,l.jsx)(`p`,{className:`text-xs text-warning mb-3`,children:`Closed — no paired owner or allowlisted members.`}):(0,l.jsx)(`ul`,{className:`mb-3 space-y-1 text-sm`,children:e.map(e=>(0,l.jsxs)(`li`,{className:`flex flex-wrap items-center gap-2`,children:[(0,l.jsx)(`code`,{className:`font-mono`,children:e.userId}),(0,l.jsxs)(`span`,{className:`text-muted-foreground`,children:[e.label??(e.username?`@${e.username}`:`—`),` · `,e.role]}),e.role!==`owner`&&(0,l.jsx)(o,{variant:`danger`,className:`text-xs`,onClick:()=>h(e),children:`remove`})]},e.userId))}),(0,l.jsxs)(`form`,{onSubmit:_,className:`flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-end`,children:[(0,l.jsxs)(`label`,{className:`m-0 flex flex-col gap-1 text-xs font-medium text-foreground`,children:[`Telegram user ID`,(0,l.jsx)(`input`,{value:n,onChange:e=>r(e.target.value),placeholder:`123456789`,inputMode:`numeric`,className:`w-full rounded-md border bg-background px-2 py-1 font-mono text-sm sm:w-32`})]}),(0,l.jsxs)(`label`,{className:`m-0 flex flex-col gap-1 text-xs font-medium text-foreground`,children:[`Label `,(0,l.jsx)(`span`,{className:`font-normal text-muted-foreground`,children:`(optional)`}),(0,l.jsx)(`input`,{value:a,onChange:e=>s(e.target.value),placeholder:`e.g. Pat`,className:`w-full rounded-md border bg-background px-2 py-1 text-sm sm:w-40`})]}),(0,l.jsx)(o,{variant:`ghost`,type:`submit`,disabled:u,children:`add`}),f&&(0,l.jsx)(`span`,{role:`alert`,className:`text-xs text-danger`,children:f})]}),(0,l.jsx)(i,{open:m!==null,title:`Remove ${m?.label??m?.username??m?.userId??``}?`,description:(0,l.jsxs)(`p`,{children:[`Telegram user `,(0,l.jsx)(`code`,{className:`font-mono`,children:m?.userId}),` immediately loses command and chat access. Their Telegram account is not changed, and they can be allowlisted again later.`]}),confirmLabel:`remove Telegram access`,onConfirm:async()=>{if(m)try{await v(m.userId)}catch(e){throw p(e instanceof Error?e.message:String(e)),e}},onOpenChange:e=>{e||h(null)}})]})}function g({toChatId:e}){let[t,n]=(0,c.useState)(!1),[r,i]=(0,c.useState)(null);async function a(){n(!0),i(null);try{let e=await fetch(`/api/config/telegram/reconnect`,{method:`POST`});if(!e.ok){let t=await e.json().catch(()=>({}));throw Error(t.error??e.statusText)}window.location.reload()}catch(e){i(e.message),n(!1)}}return(0,l.jsxs)(`div`,{className:`rounded-md border-2 border-danger/25 bg-danger/10 px-4 py-3 text-sm`,children:[(0,l.jsx)(`div`,{className:`font-semibold text-danger mb-1`,children:`Supergroup chat id changed`}),(0,l.jsxs)(`p`,{className:`text-danger mb-2`,children:[`Telegram migrated this supergroup to a new chat id (`,(0,l.jsx)(`code`,{className:`font-mono`,children:e}),`). The bot is still pointed at the old id. Reconnect to repoint it and re-create the `,(0,l.jsx)(`code`,{className:`font-mono`,children:`⚙ bazilion`}),` `,`service chat in the new team. Agent topic bindings will reconcile on next use.`]}),(0,l.jsx)(o,{variant:`primary`,onClick:a,disabled:t,children:t?`reconnecting…`:`Reconnect to ${e}`}),r&&(0,l.jsx)(`span`,{role:`alert`,className:`ml-3 text-xs text-danger`,children:r})]})}function _({polling:e}){let t=e.startedAt?new Date(e.startedAt).toISOString():null,n=e.lastSuccessfulPollAt?new Date(e.lastSuccessfulPollAt).toISOString():null;return(0,l.jsxs)(`div`,{className:`mt-4 rounded-md border bg-muted/30 px-3 py-2 text-xs space-y-1`,children:[(0,l.jsx)(`p`,{className:`font-semibold uppercase tracking-wide text-muted-foreground`,children:`Polling state`}),(0,l.jsxs)(`div`,{className:`flex flex-wrap gap-x-4 gap-y-1 font-mono`,children:[(0,l.jsx)(`span`,{className:e.running?`text-success`:`text-danger`,children:e.running?`running`:`stopped`}),(0,l.jsx)(`span`,{className:e.activated?`text-success`:`text-warning`,children:e.activated?`activated`:`awaiting activation`}),e.lastUpdateId!==null&&(0,l.jsxs)(`span`,{children:[`last update `,e.lastUpdateId]}),t&&(0,l.jsxs)(`span`,{children:[`started `,t]}),n&&(0,l.jsxs)(`span`,{children:[`last poll `,n]})]}),e.error&&(0,l.jsxs)(`p`,{role:`alert`,className:`text-danger`,children:[`error: `,e.error]})]})}function v({health:e}){if(e.error)return(0,l.jsxs)(`div`,{role:`alert`,className:`rounded-md border border-danger/25 bg-danger/10 px-3 py-2 text-sm`,children:[(0,l.jsxs)(`p`,{className:`font-semibold text-danger`,children:[`Failed at `,(0,l.jsx)(`code`,{className:`font-mono`,children:e.error.step})]}),(0,l.jsx)(`p`,{className:`text-danger mt-1`,children:e.error.message}),b(e.error.step)]});if(!e.preflight)return(0,l.jsx)(`p`,{role:`status`,className:`text-xs text-muted-foreground italic`,children:`No preflight data.`});let t=e.preflight;return(0,l.jsxs)(`ul`,{role:`status`,"aria-live":`polite`,"aria-atomic":`true`,className:`space-y-1.5`,children:[(0,l.jsxs)(y,{ok:t.botUsername.length>0,label:`Bot identity`,children:[`@`,t.botUsername]}),(0,l.jsx)(y,{ok:t.chatTitle.length>0,label:`Supergroup reachable`,children:t.chatTitle}),(0,l.jsx)(y,{ok:t.isForum,label:`Forum topics enabled`,children:t.isForum?`is_forum: true`:`is_forum: false — the supergroup owner must enable Topics in team settings`}),(0,l.jsx)(y,{ok:t.hasManageTopics,label:`Bot has can_manage_topics`,children:t.hasManageTopics?`admin with can_manage_topics`:`promote the bot to admin in the supergroup with the "Manage topics" permission`}),(0,l.jsx)(y,{ok:t.privacyModeOff,label:`Privacy Mode is OFF`,children:t.privacyModeOff?`can_read_all_group_messages: true`:`BotFather → /mybots → select bot → Bot Settings → Team Privacy → Turn off`}),(0,l.jsx)(y,{ok:t.chatIsPrivate,label:`Supergroup is private`,children:t.chatIsPrivate?`no public @username`:`public groups expose topic content to readers`}),(0,l.jsx)(y,{ok:t.memberCount===2,label:`Expected membership`,children:t.memberCount===null?`member count unavailable — verify one owner plus the bot manually`:`${t.memberCount} members reported; secure posture is one owner plus the bot`}),t.ownerPresent!==null&&(0,l.jsx)(y,{ok:t.ownerPresent,label:`Paired owner is present`,children:t.ownerPresent?`owner membership confirmed`:`owner missing — Telegram ingress is degraded`})]})}function y({ok:e,label:t,children:n}){return(0,l.jsxs)(`li`,{className:`flex items-start gap-2 text-sm`,children:[(0,l.jsx)(`span`,{className:`mt-0.5 inline-flex h-4 w-4 items-center justify-center rounded-full text-[10px] font-bold leading-none ${e?`bg-success/10 text-success`:`bg-danger/10 text-danger`}`,"aria-hidden":!0,children:e?`✓`:`✕`}),(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`span`,{className:`font-medium`,children:t}),(0,l.jsx)(`span`,{className:`ml-2 text-xs ${e?`text-muted-foreground`:`text-danger`}`,children:n})]})]})}function b(e){switch(e){case`getMe`:return(0,l.jsx)(`p`,{className:`text-xs text-danger mt-1`,children:`The token is invalid or revoked. Re-issue with @BotFather → /token, or paste a fresh one above.`});case`getChat`:return(0,l.jsx)(`p`,{className:`text-xs text-danger mt-1`,children:`The chat id either doesn't exist, points at a basic team (not a supergroup), or the bot isn't a member. Forward any message from the supergroup to the bot to double-check the id, then add the bot to the team.`});case`getChatMember`:return(0,l.jsx)(`p`,{className:`text-xs text-danger mt-1`,children:`The bot is in the chat but the membership lookup failed. Usually means the bot was kicked or the chat id was migrated — confirm the bot is still in the supergroup.`})}}export{p as component};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e,t}from"./jsx-runtime-DGeXAQPT.js";import{t as n}from"./react-3W8R1pOO.js";import{d as r}from"./preload-helper-bztXdkDj.js";import{t as i}from"./ConfirmDialog-
|
|
1
|
+
import{r as e,t}from"./jsx-runtime-DGeXAQPT.js";import{t as n}from"./react-3W8R1pOO.js";import{d as r}from"./preload-helper-bztXdkDj.js";import{t as i}from"./ConfirmDialog-BzIiABOP.js";import{j as a}from"./index-Bi-HxcPG.js";import{t as o}from"./Button-ByiV6fpd.js";import{t as s}from"./ConfigPage-BCLp-FUC.js";var c=e(n()),l=t();function u(e){return new Date(e).toISOString().slice(0,16).replace(`T`,` `)}function d(){let{tokens:e,sessions:t}=a.useLoaderData(),{all:n}=a.useSearch(),d=n===`1`,f=r(),[p,m]=(0,c.useState)(``),[h,g]=(0,c.useState)(null),[_,v]=(0,c.useState)(`90`),[y,b]=(0,c.useState)(null),[x,S]=(0,c.useState)(!1),[C,w]=(0,c.useState)(null),[T,E]=(0,c.useState)(null);async function D(e){e.preventDefault(),b(null),S(!0);try{let e=await fetch(`/api/tokens`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({label:p,expiresInDays:Number(_)})});if(!e.ok){let t=await e.json().catch(()=>({}));throw Error(t.error??`${e.status} ${e.statusText}`)}g((await e.json()).token),m(``),await f.invalidate()}catch(e){b(e.message)}finally{S(!1)}}async function O(e,t){let n=await fetch(`/api/tokens/${encodeURIComponent(e)}`,{method:`DELETE`});if(!n.ok&&n.status!==204){let e=await n.json().catch(()=>({}));throw Error(e.error??`Could not revoke API token`)}t?window.location.assign(`/login`):await f.invalidate()}async function k(e,t){let n=await fetch(`/api/sessions/${encodeURIComponent(e)}`,{method:`DELETE`});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.error??`Could not revoke browser session`)}t?window.location.assign(`/login`):await f.invalidate()}return(0,l.jsxs)(s,{active:`tokens`,title:`API tokens`,description:(0,l.jsxs)(l.Fragment,{children:[`Manage per-client credentials for the HTTP API and CLI. The`,` `,(0,l.jsx)(`code`,{className:`font-mono`,children:`bootstrap`}),` token from`,` `,(0,l.jsx)(`code`,{className:`font-mono`,children:`~/.bazilion/auth.json`}),` remains protected; mint separate credentials for mobile, LAN, and remote clients.`]}),children:[(0,l.jsxs)(`section`,{className:`rounded-lg border bg-card p-5`,children:[(0,l.jsx)(`h3`,{className:`font-serif text-xl mb-3`,children:`Mint a new token`}),(0,l.jsxs)(`form`,{onSubmit:D,className:`mb-3 flex flex-col items-stretch gap-2 sm:flex-row sm:items-end`,children:[(0,l.jsxs)(`label`,{className:`w-full text-sm sm:w-auto`,children:[`Label`,(0,l.jsx)(`input`,{type:`text`,value:p,onChange:e=>m(e.target.value),required:!0,placeholder:`e.g. laptop-tailscale`,autoComplete:`off`,className:`mt-1 block w-full rounded-md border bg-background px-3 py-2 text-sm sm:w-72`})]}),(0,l.jsxs)(`label`,{className:`w-full text-sm sm:w-auto`,children:[`Expires in days`,(0,l.jsx)(`input`,{type:`number`,min:1,max:365,value:_,onChange:e=>v(e.target.value),required:!0,className:`mt-1 block w-full rounded-md border bg-background px-3 py-2 text-sm sm:w-36`})]}),(0,l.jsx)(o,{variant:`primary`,type:`submit`,disabled:x,children:x?`creating…`:`create`})]}),h&&(0,l.jsxs)(`div`,{className:`rounded-md border border-warning/25 bg-warning/10 p-3`,children:[(0,l.jsx)(`p`,{className:`text-xs text-warning mb-1`,children:`copy this token now — it is not recoverable later.`}),(0,l.jsx)(`pre`,{className:`font-mono text-xs whitespace-pre-wrap break-all`,children:h})]}),y&&(0,l.jsx)(`p`,{role:`alert`,className:`text-sm text-danger`,children:y})]}),(0,l.jsx)(`div`,{children:(0,l.jsxs)(`label`,{className:`text-sm flex items-center gap-2`,children:[(0,l.jsx)(`input`,{type:`checkbox`,checked:d,onChange:e=>{window.location.assign(e.target.checked?`/config/tokens?all=1`:`/config/tokens`)}}),`show revoked`]})}),(0,l.jsx)(`div`,{className:`overflow-x-auto`,children:(0,l.jsxs)(`table`,{className:`w-full min-w-[720px] text-sm`,children:[(0,l.jsx)(`thead`,{className:`text-left text-muted-foreground border-b`,children:(0,l.jsxs)(`tr`,{children:[(0,l.jsx)(`th`,{className:`py-2`,children:`label`}),(0,l.jsx)(`th`,{children:`kind`}),(0,l.jsx)(`th`,{children:`id`}),(0,l.jsx)(`th`,{children:`state`}),(0,l.jsx)(`th`,{children:`created`}),(0,l.jsx)(`th`,{children:`last used`}),(0,l.jsx)(`th`,{children:`expires`}),(0,l.jsx)(`th`,{})]})}),(0,l.jsxs)(`tbody`,{children:[e.length===0&&(0,l.jsx)(`tr`,{children:(0,l.jsx)(`td`,{colSpan:8,className:`py-6 text-center text-muted-foreground italic`,children:`no tokens yet — mint one above`})}),e.map(e=>{let t=e.kind===`bootstrap`;return(0,l.jsxs)(`tr`,{className:`border-b last:border-0 hover:bg-accent/30`,children:[(0,l.jsxs)(`td`,{className:`py-2`,children:[e.label,t&&(0,l.jsx)(`span`,{className:`ml-2 text-[0.7em] uppercase tracking-wide text-muted-foreground`,children:`auth.json`})]}),(0,l.jsx)(`td`,{children:e.kind}),(0,l.jsx)(`td`,{children:(0,l.jsx)(`code`,{className:`font-mono text-xs`,children:e.id})}),(0,l.jsx)(`td`,{children:e.revokedAt?(0,l.jsx)(`span`,{className:`text-muted-foreground`,children:`revoked`}):(0,l.jsx)(`span`,{className:`text-success`,children:`active`})}),(0,l.jsx)(`td`,{className:`text-muted-foreground text-xs`,children:u(e.createdAt)}),(0,l.jsx)(`td`,{className:`text-muted-foreground text-xs`,children:e.lastUsedAt?u(e.lastUsedAt):`(never)`}),(0,l.jsx)(`td`,{className:`text-muted-foreground text-xs`,children:e.expiresAt?u(e.expiresAt):`(never)`}),(0,l.jsx)(`td`,{children:!e.revokedAt&&!t&&(0,l.jsx)(o,{variant:`danger`,className:`text-xs`,onClick:()=>{b(null),w(e)},children:`revoke`})})]},e.id)})]})]})}),(0,l.jsxs)(`section`,{className:`space-y-3`,children:[(0,l.jsxs)(`div`,{children:[(0,l.jsx)(`h3`,{className:`font-serif text-xl`,children:`Browser sessions`}),(0,l.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Sessions expire after 12 idle hours or seven days absolute. Revoking a device also revokes every session created from it.`})]}),(0,l.jsx)(`div`,{className:`overflow-x-auto`,children:(0,l.jsxs)(`table`,{className:`w-full min-w-[720px] text-sm`,children:[(0,l.jsx)(`thead`,{className:`border-b text-left text-muted-foreground`,children:(0,l.jsxs)(`tr`,{children:[(0,l.jsx)(`th`,{className:`py-2`,children:`device`}),(0,l.jsx)(`th`,{children:`session`}),(0,l.jsx)(`th`,{children:`last seen`}),(0,l.jsx)(`th`,{children:`idle expiry`}),(0,l.jsx)(`th`,{children:`absolute expiry`}),(0,l.jsx)(`th`,{})]})}),(0,l.jsxs)(`tbody`,{children:[t.length===0&&(0,l.jsx)(`tr`,{children:(0,l.jsx)(`td`,{colSpan:6,className:`py-6 text-center italic text-muted-foreground`,children:`no active browser sessions`})}),t.map(e=>(0,l.jsxs)(`tr`,{className:`border-b last:border-0 hover:bg-accent/30`,children:[(0,l.jsxs)(`td`,{className:`py-2`,children:[e.deviceLabel,` `,e.current&&(0,l.jsx)(`span`,{className:`text-xs text-success`,children:`current`})]}),(0,l.jsx)(`td`,{children:(0,l.jsx)(`code`,{className:`font-mono text-xs`,children:e.id})}),(0,l.jsx)(`td`,{className:`text-xs text-muted-foreground`,children:u(e.lastSeenAt)}),(0,l.jsx)(`td`,{className:`text-xs text-muted-foreground`,children:u(e.idleExpiresAt)}),(0,l.jsx)(`td`,{className:`text-xs text-muted-foreground`,children:u(e.absoluteExpiresAt)}),(0,l.jsx)(`td`,{children:(0,l.jsx)(o,{variant:`danger`,className:`text-xs`,onClick:()=>{b(null),E(e)},children:`revoke`})})]},e.id))]})]})})]}),(0,l.jsx)(i,{open:C!==null,title:`Revoke ${C?.label??``}?`,description:(0,l.jsxs)(`p`,{children:[`This permanently revokes device token`,` `,(0,l.jsx)(`code`,{className:`font-mono`,children:C?.id}),` and every browser session created from it. Clients using it will be signed out and cannot reconnect with this credential.`,t.some(e=>e.current&&e.deviceTokenId===C?.id)&&` This includes the browser session you are using now.`]}),confirmLabel:`revoke token and sessions`,onConfirm:async()=>{if(C)try{await O(C.id,t.some(e=>e.current&&e.deviceTokenId===C.id))}catch(e){throw b(e instanceof Error?e.message:String(e)),e}},onOpenChange:e=>{e||w(null)}}),(0,l.jsx)(i,{open:T!==null,title:`Revoke ${T?.deviceLabel??``} browser session?`,description:(0,l.jsxs)(`p`,{children:[`This ends browser session `,(0,l.jsx)(`code`,{className:`font-mono`,children:T?.id}),T?.current?` and signs this browser out immediately.`:`. The device token remains active for future logins.`]}),confirmLabel:T?.current?`sign out this browser`:`revoke session`,onConfirm:async()=>{if(T)try{await k(T.id,T.current)}catch(e){throw b(e instanceof Error?e.message:String(e)),e}},onOpenChange:e=>{e||E(null)}})]})}export{d as component};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e,t}from"./jsx-runtime-DGeXAQPT.js";import{t as n}from"./react-3W8R1pOO.js";import{d as r}from"./preload-helper-bztXdkDj.js";import{t as i}from"./ConfirmDialog-
|
|
1
|
+
import{r as e,t}from"./jsx-runtime-DGeXAQPT.js";import{t as n}from"./react-3W8R1pOO.js";import{d as r}from"./preload-helper-bztXdkDj.js";import{t as i}from"./ConfirmDialog-BzIiABOP.js";import{a}from"./index-Bi-HxcPG.js";import{r as o}from"./Page-NV96O47A.js";import{t as s}from"./AgentTabs-BcmmwYJc.js";import{t as c}from"./Button-ByiV6fpd.js";var l=e(n()),u=t();function d(){let{resolved:e,triggers:t,dispatches:n}=a.useLoaderData(),d=r(),[p,m]=(0,l.useState)(null),[h,g]=(0,l.useState)(null),[_,v]=(0,l.useState)(null);async function y(e){v(e.id),g(null);try{let t=await fetch(`/api/triggers/${encodeURIComponent(e.id)}`,{method:`PATCH`,headers:{"content-type":`application/json`},body:JSON.stringify({enabled:!e.enabled})});if(!t.ok){let n=await t.json().catch(()=>null);throw Error(n?.error??`Could not ${e.enabled?`disable`:`enable`} trigger`)}await d.invalidate()}catch(e){g(e instanceof Error?e.message:String(e))}finally{v(null)}}async function b(e){let t=await fetch(`/api/triggers/${encodeURIComponent(e)}`,{method:`DELETE`});if(!t.ok&&t.status!==204){let e=await t.json().catch(()=>null);throw Error(e?.error??`Could not delete trigger`)}await d.invalidate()}return(0,u.jsxs)(o,{children:[(0,u.jsx)(`header`,{className:`mb-6`,children:(0,u.jsx)(`h1`,{children:e.agent.name})}),(0,u.jsx)(s,{agentId:e.agent.id,active:`triggers`,archived:e.agent.status===`archived`}),(0,u.jsx)(f,{agentId:e.agent.id,onAdded:()=>d.invalidate()}),h&&(0,u.jsx)(`p`,{role:`alert`,className:`err mt-4`,children:h}),(0,u.jsx)(`h3`,{className:`mb-3 mt-6 font-body text-[0.85em] font-semibold uppercase tracking-wider text-mocha-light`,children:`Active triggers`}),t.length===0?(0,u.jsx)(`p`,{className:`muted`,children:`no triggers yet — add one above.`}):(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(`div`,{className:`grid gap-3 md:hidden`,children:t.map(e=>{let t=e.kind===`interval`?`every ${e.intervalSec}s`:e.cronExpr,n=e.lastFiredAt?new Date(e.lastFiredAt).toLocaleString():`Never`;return(0,u.jsxs)(`article`,{className:`card min-w-0 ${e.enabled?``:`opacity-60`}`,children:[(0,u.jsxs)(`div`,{className:`flex min-w-0 items-start justify-between gap-3`,children:[(0,u.jsxs)(`div`,{className:`min-w-0`,children:[(0,u.jsx)(`p`,{className:`m-0 break-all font-mono text-xs text-muted-foreground`,children:e.id}),(0,u.jsx)(`p`,{className:`mb-0 mt-1 font-medium text-foreground`,children:t})]}),(0,u.jsx)(`span`,{className:`shrink-0 rounded-sm border border-frost bg-ivory px-2 py-0.5 font-mono text-xs text-mocha`,children:e.kind})]}),(0,u.jsx)(`p`,{className:`my-3 break-words text-sm text-foreground`,children:e.message}),(0,u.jsxs)(`p`,{className:`mb-3 text-xs text-muted-foreground`,children:[`Last fired: `,n]}),(0,u.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,u.jsx)(c,{variant:`ghost`,disabled:_===e.id,onClick:()=>void y(e),children:_===e.id?`Working…`:e.enabled?`Disable`:`Enable`}),(0,u.jsx)(c,{variant:`danger`,disabled:_===e.id,onClick:()=>{g(null),m(e)},children:`Delete`})]})]},e.id)})}),(0,u.jsx)(`div`,{className:`hidden overflow-x-auto md:block`,children:(0,u.jsxs)(`table`,{className:`min-w-full`,children:[(0,u.jsx)(`thead`,{children:(0,u.jsxs)(`tr`,{children:[(0,u.jsx)(`th`,{children:`id`}),(0,u.jsx)(`th`,{children:`kind`}),(0,u.jsx)(`th`,{children:`spec`}),(0,u.jsx)(`th`,{children:`message`}),(0,u.jsx)(`th`,{children:`last fired`}),(0,u.jsx)(`th`,{})]})}),(0,u.jsx)(`tbody`,{children:t.map(e=>{let t=e.kind===`interval`?`every ${e.intervalSec}s`:e.cronExpr,n=e.lastFiredAt?new Date(e.lastFiredAt).toLocaleString():`(never)`;return(0,u.jsxs)(`tr`,{className:e.enabled?``:`opacity-60`,children:[(0,u.jsx)(`td`,{children:(0,u.jsxs)(`code`,{children:[e.id.slice(0,8),`…`]})}),(0,u.jsx)(`td`,{children:(0,u.jsx)(`span`,{className:`inline-block rounded-sm border border-frost bg-ivory px-2 py-0.5 font-mono text-[0.8em] text-mocha`,children:e.kind})}),(0,u.jsx)(`td`,{children:(0,u.jsx)(`code`,{children:t})}),(0,u.jsx)(`td`,{children:e.message.length>60?`${e.message.slice(0,60)}…`:e.message}),(0,u.jsx)(`td`,{className:`text-[0.82em] text-mocha-light`,children:n}),(0,u.jsx)(`td`,{children:(0,u.jsxs)(`div`,{className:`flex gap-1.5`,children:[(0,u.jsx)(c,{variant:`ghost`,disabled:_===e.id,onClick:()=>void y(e),children:_===e.id?`working…`:e.enabled?`disable`:`enable`}),(0,u.jsx)(c,{variant:`danger`,disabled:_===e.id,onClick:()=>{g(null),m(e)},children:`delete`})]})})]},e.id)})})]})})]}),(0,u.jsx)(`h3`,{className:`mb-3 mt-8 font-body text-[0.85em] font-semibold uppercase tracking-wider text-mocha-light`,children:`Recent dispatches`}),n.length===0?(0,u.jsx)(`p`,{className:`muted`,children:`no scheduled occurrences yet.`}):(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(`div`,{className:`grid gap-3 md:hidden`,children:n.map(e=>(0,u.jsxs)(`article`,{className:`card min-w-0`,children:[(0,u.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[(0,u.jsx)(`time`,{className:`text-sm text-foreground`,children:new Date(e.scheduledAt).toLocaleString()}),(0,u.jsx)(`code`,{className:`shrink-0`,children:e.status})]}),(0,u.jsxs)(`p`,{className:`mb-0 mt-2 text-xs text-muted-foreground`,children:[e.attemptCount,` attempt`,e.attemptCount===1?``:`s`]}),e.lastError&&(0,u.jsx)(`p`,{className:`mb-0 mt-2 break-words text-sm text-danger`,children:e.lastError})]},e.id))}),(0,u.jsx)(`div`,{className:`hidden overflow-x-auto md:block`,children:(0,u.jsxs)(`table`,{className:`min-w-full`,children:[(0,u.jsx)(`thead`,{children:(0,u.jsxs)(`tr`,{children:[(0,u.jsx)(`th`,{children:`scheduled`}),(0,u.jsx)(`th`,{children:`status`}),(0,u.jsx)(`th`,{children:`attempts`}),(0,u.jsx)(`th`,{children:`error`})]})}),(0,u.jsx)(`tbody`,{children:n.map(e=>(0,u.jsxs)(`tr`,{children:[(0,u.jsx)(`td`,{className:`text-[0.82em]`,children:new Date(e.scheduledAt).toLocaleString()}),(0,u.jsx)(`td`,{children:(0,u.jsx)(`code`,{children:e.status})}),(0,u.jsx)(`td`,{children:e.attemptCount}),(0,u.jsx)(`td`,{className:`text-[0.82em] text-mocha-light`,children:e.lastError??`—`})]},e.id))})]})})]}),(0,u.jsx)(i,{open:p!==null,title:`Delete ${p?.kind??``} trigger?`,description:(0,u.jsxs)(`p`,{children:[`This permanently removes trigger`,` `,(0,u.jsx)(`code`,{className:`font-mono`,children:p?.id}),`, its recorded dispatch history, and every future scheduled occurrence for `,e.agent.name,`. The Agent itself is not deleted.`]}),confirmLabel:`delete trigger and history`,onConfirm:async()=>{if(p)try{await b(p.id)}catch(e){throw g(e instanceof Error?e.message:String(e)),e}},onOpenChange:e=>{e||m(null)}})]})}function f({agentId:e,onAdded:t}){let[n,r]=(0,l.useState)(`interval`),[i,a]=(0,l.useState)(300),[o,s]=(0,l.useState)(``),[d,f]=(0,l.useState)(``),[p,m]=(0,l.useState)(null),[h,g]=(0,l.useState)(!1);async function _(r){if(r.preventDefault(),m(null),!d.trim()){m(`message is required`);return}if(n===`interval`&&(!Number.isFinite(i)||i<=0)){m(`interval must be a positive number`);return}if(n===`cron`&&!o.trim()){m(`cron expression is required`);return}g(!0);try{let r={kind:n,message:d.trim()};n===`interval`?r.intervalSec=i:r.cronExpr=o.trim();let c=await fetch(`/api/agents/${encodeURIComponent(e)}/triggers`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(r)});if(!c.ok){let e=await c.json().catch(()=>null);throw Error(e?.error??c.statusText)}f(``),s(``),a(300),t()}catch(e){m(e.message)}finally{g(!1)}}return(0,u.jsxs)(`form`,{className:`card`,onSubmit:_,children:[(0,u.jsx)(`h3`,{children:`Add trigger`}),(0,u.jsxs)(`div`,{className:`mb-3 flex gap-3`,children:[(0,u.jsxs)(`label`,{className:`m-0 inline-flex cursor-pointer items-center gap-1`,children:[(0,u.jsx)(`input`,{type:`radio`,checked:n===`interval`,onChange:()=>r(`interval`)}),`interval (every N seconds)`]}),(0,u.jsxs)(`label`,{className:`m-0 inline-flex cursor-pointer items-center gap-1`,children:[(0,u.jsx)(`input`,{type:`radio`,checked:n===`cron`,onChange:()=>r(`cron`)}),`cron (5-field)`]})]}),n===`interval`?(0,u.jsxs)(`label`,{children:[`interval (seconds)`,(0,u.jsx)(`input`,{type:`number`,min:1,value:i,onChange:e=>a(Number(e.target.value))})]}):(0,u.jsxs)(`label`,{children:[`cron expression (minute hour dom month dow)`,(0,u.jsx)(`input`,{type:`text`,placeholder:`*/15 * * * *`,value:o,onChange:e=>s(e.target.value)})]}),(0,u.jsxs)(`label`,{children:[`message`,(0,u.jsx)(`textarea`,{placeholder:`e.g. check your inbox and act on anything new`,value:d,onChange:e=>f(e.target.value),className:`font-mono text-[0.9em] min-h-[80px]`})]}),(0,u.jsxs)(`div`,{className:`mt-3 flex items-center gap-3`,children:[(0,u.jsx)(c,{variant:`primary`,type:`submit`,disabled:h,children:h?`adding…`:`add`}),p&&(0,u.jsx)(`span`,{role:`alert`,className:`text-[0.85em] text-danger`,children:p})]})]})}export{d as component};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as e,t}from"./jsx-runtime-DGeXAQPT.js";import{t as n}from"./react-3W8R1pOO.js";import{a as r}from"./preload-helper-bztXdkDj.js";import{C as i,S as a,b as o,w as s,x as c}from"./index-Bi-HxcPG.js";import{r as l}from"./Page-NV96O47A.js";import{t as u}from"./Button-ByiV6fpd.js";import{t as d}from"./TeamTabs-BmTZRI4T.js";var f=e(n()),p=t();function m(e){return e===`identical`?`unchanged since capture`:e===`changed`?`changed since capture — re-verify`:`not checked`}function h(e,t){return e===`not_executed`?`not run`:e===`succeeded`?`ok${t===null?``:` (exit ${t})`}`:e===`failed`?`failed${t===null?``:` (exit ${t})`}`:e.replace(/_/g,` `)}function g(){let e=o.useLoaderData(),t=o.useParams().id,[n,g]=(0,f.useState)(e.requests),[_,v]=(0,f.useState)(e.unavailable),[y,b]=(0,f.useState)(()=>e.members[0]?.id??``),[x,S]=(0,f.useState)(``),[C,w]=(0,f.useState)(`pnpm test :: unit suite`),[T,E]=(0,f.useState)(``),[D,O]=(0,f.useState)(null),[k,A]=(0,f.useState)(!1),[j,M]=(0,f.useState)({});async function N(){let e=await i({data:{id:t}});e&&(g(e.requests),v(e.unavailable))}async function P(){A(!0),O({kind:`info`,message:`Capturing the request…`});try{let e=await a({data:{id:t,recipientAgentId:y,snapshotId:x,checks:C.split(`
|
|
2
|
+
`).map(e=>e.trim()).filter(Boolean).map(e=>{let[t,n,r,i]=e.split(`::`).map(e=>e?.trim());return{command:t??``,purpose:n??``,cwd:r||`.`,timeoutMs:Math.round((i?Number(i):120)*1e3)}}),...T?{summary:T}:{}}});if(`blocker`in e&&e.blocker){O({kind:`error`,message:`Blocked: ${e.blocker.detail}`});return}if(`ok`in e&&e.ok){O({kind:`info`,message:`Captured. The specialist is admitted by the scheduler.`}),S(``),await N();return}O({kind:`error`,message:`message`in e?e.message??`Request failed`:`Request failed`})}finally{A(!1)}}async function F(e){A(!0);try{let n=await s({data:{id:t,requestId:e}});M(t=>({...t,[e]:`report`in n?m(n.report.applicability.comparison):`unavailable`}))}finally{A(!1)}}async function I(e){A(!0);try{let n=await c({data:{id:t,requestId:e}});O(n.ok?{kind:`info`,message:`Cancellation requested.`}:{kind:`error`,message:n.message??`Cancel failed`}),await N()}finally{A(!1)}}return(0,p.jsxs)(l,{children:[(0,p.jsx)(d,{teamId:t}),(0,p.jsx)(`h2`,{children:`Specialist verification`}),_?(0,p.jsx)(`p`,{className:`muted`,children:_.message}):null,D?(0,p.jsx)(`p`,{className:D.kind===`error`?`error`:`muted`,role:`status`,children:D.message}):null,(0,p.jsxs)(`section`,{"aria-label":`Request verification`,className:`card`,children:[(0,p.jsx)(`h3`,{children:`Request verification of a captured change`}),(0,p.jsxs)(`p`,{className:`muted`,children:[`Capture a source snapshot on the`,` `,(0,p.jsx)(r,{to:`/teams/$id/review`,params:{id:t},children:`Review`}),` `,`page first, then name it here with the checks you want run. Nothing runs until the daemon admits the request.`]}),(0,p.jsxs)(`label`,{children:[`Specialist`,(0,p.jsx)(`select`,{value:y,onChange:e=>b(e.target.value),children:e.members.map(e=>(0,p.jsx)(`option`,{value:e.id,children:e.name},e.id))})]}),(0,p.jsxs)(`label`,{children:[`Snapshot id`,(0,p.jsx)(`input`,{value:x,onChange:e=>S(e.target.value),placeholder:`captured snapshot id`})]}),(0,p.jsxs)(`label`,{children:[`Checks (one per line: command :: purpose [:: cwd] [:: seconds])`,(0,p.jsx)(`textarea`,{value:C,onChange:e=>w(e.target.value),rows:4})]}),(0,p.jsxs)(`label`,{children:[`Acceptance summary (optional)`,(0,p.jsx)(`input`,{value:T,onChange:e=>E(e.target.value)})]}),(0,p.jsx)(u,{variant:`primary`,disabled:k||!y||!x||!C.trim(),onClick:P,children:`Request verification`})]}),(0,p.jsxs)(`section`,{"aria-label":`Verification requests`,children:[(0,p.jsx)(`h3`,{children:`Requests`}),n.length===0?(0,p.jsx)(`p`,{className:`muted`,children:`No verification requests yet.`}):(0,p.jsx)(`ul`,{className:`list`,children:n.map(e=>{let t=[...e.attempts].sort((e,t)=>t.attemptNumber-e.attemptNumber)[0],n=new Map((t?.outcomes??[]).map(e=>[e.ordinal,e])),r=e.request.state===`pending`||e.request.state===`awaiting_approval`||e.request.state===`running`;return(0,p.jsxs)(`li`,{className:`card`,children:[(0,p.jsxs)(`div`,{children:[(0,p.jsx)(`strong`,{children:e.request.state}),` `,(0,p.jsxs)(`span`,{className:`muted`,children:[e.request.recipientAgentId,` · `,e.request.id]})]}),(0,p.jsxs)(`p`,{className:`muted`,children:[`change `,e.request.snapshot.id.slice(0,12),` ·`,` `,e.request.environment.image,` (shell `,e.request.environment.sandbox,`)`]}),(0,p.jsx)(`ul`,{children:e.checks.map(e=>{let t=n.get(e.ordinal);return(0,p.jsxs)(`li`,{children:[`[`,e.ordinal,`] `,h(t?.state??`not_executed`,t?.exitCode??null),` `,`— `,(0,p.jsx)(`code`,{children:e.command}),t?.commandId?(0,p.jsxs)(p.Fragment,{children:[` `,(0,p.jsxs)(`span`,{className:`muted`,children:[`receipt `,t.commandId.slice(0,8)]})]}):t?.receiptUnavailable?(0,p.jsxs)(p.Fragment,{children:[` `,(0,p.jsx)(`span`,{className:`muted`,children:`receipt no longer available`})]}):null]},e.ordinal)})}),t?.error?(0,p.jsxs)(`p`,{className:`muted`,children:[`note: `,t.error]}):null,(0,p.jsxs)(`p`,{className:`muted`,children:[`applicability: `,j[e.request.id]??`not checked`]}),(0,p.jsx)(u,{variant:`ghost`,disabled:k,onClick:()=>F(e.request.id),children:`Check applicability`}),` `,r?(0,p.jsx)(u,{variant:`danger`,disabled:k,onClick:()=>I(e.request.id),children:`Cancel`}):null]},e.request.id)})})]})]})}export{g as component};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"./jsx-runtime-DGeXAQPT.js";import{ct as t}from"./index-Bi-HxcPG.js";import{i as n,n as r,r as i}from"./Page-NV96O47A.js";var a=t(`arrow-right`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]),o=e();function s(){return(0,o.jsxs)(i,{size:`narrow`,children:[(0,o.jsx)(r,{eyebrow:`First run`,title:`Welcome to bazilion`,description:`Configure one model provider to prepare your defaults, then test it before the first conversation.`}),(0,o.jsxs)(n,{title:`Three steps to your first conversation`,children:[(0,o.jsxs)(`p`,{className:`text-sm leading-6 text-muted-foreground`,children:[`Before you can spawn agents, enable a provider and save at least one concrete model id. Bazilion then creates a `,(0,o.jsx)(`code`,{children:`default`}),` Agent template and `,(0,o.jsx)(`code`,{children:`default`}),` Team. Send the small connection test before relying on that model.`]}),(0,o.jsxs)(`ol`,{className:`my-5 space-y-4`,children:[(0,o.jsxs)(c,{n:1,children:[(0,o.jsx)(`strong`,{children:`Choose a provider.`}),` Head to the`,` `,(0,o.jsx)(`a`,{href:`/config`,children:`providers tab`}),`, pick a provider, and set credentials or a local endpoint if that provider needs one. Local providers like Ollama and LM Studio can use their default loopback URLs.`]}),(0,o.jsxs)(c,{n:2,children:[(0,o.jsx)(`strong`,{children:`Enable it and save a model.`}),` Flip the provider's toggle on, then click a catalog chip or type one exact model id (for example`,` `,(0,o.jsx)(`code`,{children:`claude-opus-5`}),`, `,(0,o.jsx)(`code`,{children:`gpt-6-astra`}),`, or `,(0,o.jsx)(`code`,{children:`llama3.3`}),`) and press `,(0,o.jsx)(`em`,{children:`save models`}),`.`]}),(0,o.jsxs)(c,{n:3,children:[(0,o.jsx)(`strong`,{children:`Verify and spawn.`}),` Send the short real-model test. When setup is configured, the page gives you a direct action to spawn the first agent from the`,` `,(0,o.jsx)(`code`,{children:`default`}),` template.`]})]}),(0,o.jsxs)(`a`,{href:`/config`,className:`btn-primary no-underline`,children:[`Configure providers `,(0,o.jsx)(a,{className:`h-4 w-4`,"aria-hidden":`true`})]})]})]})}function c({n:e,children:t}){return(0,o.jsxs)(`li`,{className:`grid grid-cols-[2rem_1fr] gap-3 border-t border-frost pt-3 first:border-t-0 first:pt-0`,children:[(0,o.jsx)(`span`,{className:`text-center font-display text-xl text-sapphire`,children:e}),(0,o.jsx)(`div`,{className:`text-[0.92em] leading-relaxed text-mocha`,children:t})]})}export{s as component};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ct as e}from"./index-Bi-HxcPG.js";var t=e(`plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]),n=e(`x`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]);export{t as n,n as t};
|