bazilion 0.16.0 → 0.17.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 +399 -83
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +1840 -132
- package/dist/daemon.js.map +1 -1
- package/dist/migrations/0001_init.sql +62 -0
- package/dist/web/client/assets/ChatPane-BI3QVX2A.js +76 -0
- package/dist/web/client/assets/{ConfirmDialog-MicTTwdy.js → ConfirmDialog-Qam6Ut08.js} +1 -1
- package/dist/web/client/assets/{FieldRow-DJ2Gx4Du.js → FieldRow-swJ5qn2h.js} +1 -1
- package/dist/web/client/assets/ProductionTeamPolicyEditor-LGw1UuF-.js +7 -0
- package/dist/web/client/assets/ProfileCommunicationEditor-raoau_YB.js +1 -0
- package/dist/web/client/assets/{ResultSourceConversation-CtzJ8QA-.js → ResultSourceConversation-BEwkhFog.js} +1 -1
- package/dist/web/client/assets/TeamTabs-BDdTLGIf.js +1 -0
- package/dist/web/client/assets/TemplatesTabs-BX5hhEJ7.js +1 -0
- package/dist/web/client/assets/{UnsavedChangesGuard-BCsLw-mU.js → UnsavedChangesGuard-CVJtmR1D.js} +1 -1
- package/dist/web/client/assets/{_id-BEDmIXVf.js → _id-BQPOE3gj.js} +1 -1
- package/dist/web/client/assets/{_id-BFM_tn_s.js → _id-BkYrUP0R.js} +1 -1
- package/dist/web/client/assets/{_id-B5Ov7cdO.js → _id-CriixlZD.js} +1 -1
- package/dist/web/client/assets/_id-DHqq2W34.js +1 -0
- package/dist/web/client/assets/{_id-DxopIW-y.js → _id-DmEVZIlx.js} +1 -1
- package/dist/web/client/assets/activity-Bzr8R18n.js +1 -0
- package/dist/web/client/assets/{agents-CMPOFcs-.js → agents-13oafeOA.js} +1 -1
- package/dist/web/client/assets/{agents-O4soKZND.js → agents-DF4NALmJ.js} +1 -1
- package/dist/web/client/assets/{approvals-CwDu_lrA.js → approvals-DsG0Ijls.js} +1 -1
- package/dist/web/client/assets/{attention-BY8MMuM_.js → attention-DG7K25mz.js} +1 -1
- package/dist/web/client/assets/chevron-right-DFqFHtLy.js +1 -0
- package/dist/web/client/assets/config-DAaDbFhS.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-C9e7QjsX.js} +1 -1
- package/dist/web/client/assets/index-Dsstm2hf.js +50 -0
- package/dist/web/client/assets/{learning-DAm4dyyc.js → learning-23arTd21.js} +1 -1
- package/dist/web/client/assets/login-BIXnBsuj.js +1 -0
- package/dist/web/client/assets/{mcp-loLB0wuh.js → mcp-Cdx9qAl8.js} +1 -1
- package/dist/web/client/assets/{members-BJ0ikkTl.js → members-fotOz4rR.js} +1 -1
- package/dist/web/client/assets/{memory-Drn9Gv53.js → memory-C7UznVot.js} +1 -1
- package/dist/web/client/assets/policy-CactLW1X.js +1 -0
- package/dist/web/client/assets/{results-9exU6f7m.js → results-DqEuYnQH.js} +1 -1
- package/dist/web/client/assets/review-CnBSYclb.js +1 -0
- package/dist/web/client/assets/routes-COxMuwVz.js +1 -0
- package/dist/web/client/assets/{services-BLso1BhA.js → services-xEANwZAu.js} +1 -1
- package/dist/web/client/assets/{skills-BodqX3OI.js → skills-CamV6wYM.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-B12dMSjW.js} +1 -1
- package/dist/web/client/assets/{teams-SYsF1bOR.js → teams-CbH43zSG.js} +1 -1
- package/dist/web/client/assets/{telegram-DC9PLFbB.js → telegram-muIql4u-.js} +1 -1
- package/dist/web/client/assets/{tokens-DGy8Ijpo.js → tokens-DGFmApdF.js} +1 -1
- package/dist/web/client/assets/{triggers-BXpVmHDG.js → triggers-D8n3sCBW.js} +1 -1
- package/dist/web/client/assets/welcome-CMHWRZhs.js +1 -0
- package/dist/web/client/assets/x-BGCHwZOH.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-DQXh-3ij.js} +4 -0
- 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-BG2nkGxa.js → _id-CPfILjMa.js} +1 -1
- package/dist/web/server/assets/{_id-BnqodC1c2.js → _id-C_2er0_G.js} +3 -3
- package/dist/web/server/assets/{_id-DtIYuJJX.js → _id-DDyA9CGX.js} +1 -1
- package/dist/web/server/assets/{_id-DrB9uR1b.js → _id-DSPFJMzf.js} +1 -1
- package/dist/web/server/assets/{_id-DwZXhLlL.js → _id-DtJn-yzu.js} +2 -2
- package/dist/web/server/assets/{_id-CeyHEsCZ.js → _id-Dw3gKOGv.js} +1 -1
- package/dist/web/server/assets/{_id-DOnInzLb.js → _id-XkxlX036.js} +1 -1
- package/dist/web/server/assets/{_tanstack-start-manifest_v-D7gKv6m6.js → _tanstack-start-manifest_v-vOXRfKJD.js} +91 -78
- package/dist/web/server/assets/{activity-C88qrNqv.js → activity-BX1jZBPQ.js} +1 -1
- package/dist/web/server/assets/{activity-5fWKPDxj.js → activity-bozPMU2v.js} +2 -2
- package/dist/web/server/assets/{activity-0VUkStOu.js → activity-pYQPT3QT.js} +1 -1
- package/dist/web/server/assets/{agents-CSXLaM2W.js → agents-BKBfW700.js} +1 -1
- package/dist/web/server/assets/{agents-C86K6HvS.js → agents-CVCfxnE2.js} +1 -1
- package/dist/web/server/assets/{approvals-C3MysI6l.js → approvals-C3ya6B6U.js} +1 -1
- package/dist/web/server/assets/{attention-DLeLCKah.js → attention-l28hGCHS.js} +1 -1
- package/dist/web/server/assets/{auth-CDZp9aEk.js → auth-AvDFNeOv.js} +1 -1
- package/dist/web/server/assets/{config-BVTHvljR.js → config-BWKn4XII.js} +1 -1
- package/dist/web/server/assets/{daemon-client-xWyYKAcx.js → daemon-client-Cgx-YW4l.js} +30 -0
- package/dist/web/server/assets/git-review-BB3M9nYg.js +26 -0
- package/dist/web/server/assets/git-review-f_uta4Mx.js +179 -0
- package/dist/web/server/assets/git-review-presentation-TJiHJhen.js +81 -0
- package/dist/web/server/assets/{inbox-PQTrjtOw.js → inbox-BBZiOOQs.js} +1 -1
- package/dist/web/server/assets/{learning-K0cmDsZR.js → learning-CheVay1i.js} +1 -1
- package/dist/web/server/assets/{mcp-Rtraochg.js → mcp-DCBDmNtQ.js} +1 -1
- package/dist/web/server/assets/{members-grAKFWgv.js → members-C2He8mrU.js} +1 -1
- package/dist/web/server/assets/{members-CD3GiTfF.js → members-C5FQruRZ.js} +1 -1
- package/dist/web/server/assets/{members-cc5SeEaW.js → members-C_2xB9pr.js} +2 -2
- package/dist/web/server/assets/{memory-CVqnyUaM.js → memory-4tI-UbOf.js} +1 -1
- package/dist/web/server/assets/{memory-C5i_GxlY.js → memory-BTcmf0sD.js} +2 -2
- package/dist/web/server/assets/{memory-egFpBD1g.js → memory-rmiFNj7T.js} +1 -1
- package/dist/web/server/assets/{policy-Dgjb0_gK.js → policy-BGILKGHz.js} +2 -2
- package/dist/web/server/assets/{policy-bLKwvnja.js → policy-C3D2Q1EA.js} +1 -1
- package/dist/web/server/assets/{policy-ooSBgiDS.js → policy-DS7LGe--.js} +1 -1
- package/dist/web/server/assets/{results-DXdYtHaq.js → results-C6H42tjq.js} +1 -1
- package/dist/web/server/assets/{results-CfNsFncJ.js → results-Cgx7SrFt.js} +3 -3
- package/dist/web/server/assets/{results-N-kP4iFT.js → results-_6K_zXQS.js} +1 -1
- package/dist/web/server/assets/review-DHhiL-JQ.js +393 -0
- package/dist/web/server/assets/review-DSTMCwP4.js +14 -0
- package/dist/web/server/assets/{router-B6g_s7W3.js → router-ElARvZzI.js} +34 -27
- package/dist/web/server/assets/{routes-pcRy_Sf8.js → routes-B6x3pEW8.js} +1 -1
- package/dist/web/server/assets/{routes-BqSaZvlu.js → routes-BgMvLvS-.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-yHZroxsi.js} +1 -1
- package/dist/web/server/assets/{skills-i2duvgW-.js → skills--bIKID1Q.js} +1 -1
- package/dist/web/server/assets/{teams-B1AI3NfN.js → teams--a956vWL.js} +1 -1
- package/dist/web/server/assets/{teams-6RYIj1Xm.js → teams-BbRfuVXY.js} +1 -1
- package/dist/web/server/assets/{telegram-C4q0YTVn.js → telegram-4kMxRtVZ.js} +1 -1
- package/dist/web/server/assets/{tokens-RFquA2Bx.js → tokens-BYwTN9JZ.js} +1 -1
- package/dist/web/server/assets/{triggers-DVD-iE-N.js → triggers-BM6mzLuH.js} +1 -1
- package/dist/web/server/server.js +56 -28
- package/dist/worker.js +292 -75
- 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/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-Qam6Ut08.js";import{o as a}from"./index-Dsstm2hf.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-Qam6Ut08.js";import{E as a}from"./index-Dsstm2hf.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-Qam6Ut08.js";import{a}from"./index-Dsstm2hf.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 @@
|
|
|
1
|
+
import{t as e}from"./jsx-runtime-DGeXAQPT.js";import{rt as t}from"./index-Dsstm2hf.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{rt as e}from"./index-Dsstm2hf.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};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { r as fetchSnapshotApplicability } from "./git-review-BB3M9nYg.js";
|
|
1
2
|
import { t as Button } from "./Button-Dsnw22OF.js";
|
|
3
|
+
import { n as applicabilityWarns, t as applicabilityLabel } from "./git-review-presentation-TJiHJhen.js";
|
|
2
4
|
import { t as ResultCard } from "./ResultCard-B3zD9N0t.js";
|
|
3
5
|
import { forwardRef, useCallback, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
4
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -21,19 +23,92 @@ function inboxUpdateLabel(body) {
|
|
|
21
23
|
return `Update from ${name.slice(0, 100)}`;
|
|
22
24
|
}
|
|
23
25
|
//#endregion
|
|
26
|
+
//#region src/lib/coding-log.ts
|
|
27
|
+
/** Bounded first page. Larger reads and search are a later iteration. */
|
|
28
|
+
var CODING_LOG_PAGE_BYTES = 65536;
|
|
29
|
+
/**
|
|
30
|
+
* Read a retained coding log through the same-origin `/api` proxy.
|
|
31
|
+
*
|
|
32
|
+
* The daemon stays the authority: it re-checks Team membership and disclosure
|
|
33
|
+
* state on every call, so holding an opaque reference in history grants nothing
|
|
34
|
+
* on its own. `fetchImpl` is injectable for tests.
|
|
35
|
+
*/
|
|
36
|
+
async function fetchRetainedCodingLog(reference, fetchImpl = fetch) {
|
|
37
|
+
const base = `/api/teams/${encodeURIComponent(reference.teamId)}/coding-commands/${encodeURIComponent(reference.commandId)}/log`;
|
|
38
|
+
try {
|
|
39
|
+
const response = await fetchImpl(`${base}?limit=${CODING_LOG_PAGE_BYTES}`, { headers: { accept: "application/json" } });
|
|
40
|
+
if (response.status === 403) return { status: "not-shared" };
|
|
41
|
+
if (response.status === 404) return { status: "missing" };
|
|
42
|
+
if (!response.ok) return {
|
|
43
|
+
status: "unavailable",
|
|
44
|
+
message: `Request failed (${response.status}).`
|
|
45
|
+
};
|
|
46
|
+
const body = await response.json();
|
|
47
|
+
const view = readView(body);
|
|
48
|
+
if (!view) return {
|
|
49
|
+
status: "unavailable",
|
|
50
|
+
message: "Unexpected response from the daemon."
|
|
51
|
+
};
|
|
52
|
+
if (field(body, "page") === null) return { status: "not-shared" };
|
|
53
|
+
const page = readPage(field(body, "page"));
|
|
54
|
+
if (!page) return {
|
|
55
|
+
status: "unavailable",
|
|
56
|
+
message: "Unexpected response from the daemon."
|
|
57
|
+
};
|
|
58
|
+
return {
|
|
59
|
+
status: "available",
|
|
60
|
+
page,
|
|
61
|
+
view
|
|
62
|
+
};
|
|
63
|
+
} catch {
|
|
64
|
+
return {
|
|
65
|
+
status: "unavailable",
|
|
66
|
+
message: "The daemon could not be reached."
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function readView(body) {
|
|
71
|
+
const view = field(body, "view");
|
|
72
|
+
if (!isRecord(view)) return null;
|
|
73
|
+
if (typeof view.commandId !== "string" || typeof view.availability !== "string") return null;
|
|
74
|
+
if (typeof view.byteLength !== "number") return null;
|
|
75
|
+
return view;
|
|
76
|
+
}
|
|
77
|
+
function readPage(page) {
|
|
78
|
+
if (!isRecord(page)) return null;
|
|
79
|
+
if (typeof page.text !== "string" || typeof page.availability !== "string") return null;
|
|
80
|
+
if (typeof page.offset !== "number" || typeof page.hasMore !== "boolean") return null;
|
|
81
|
+
if (typeof page.byteLength !== "number") return null;
|
|
82
|
+
return page;
|
|
83
|
+
}
|
|
84
|
+
function field(body, key) {
|
|
85
|
+
return isRecord(body) ? body[key] : void 0;
|
|
86
|
+
}
|
|
87
|
+
function isRecord(value) {
|
|
88
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
24
91
|
//#region src/components/CodingToolResult.tsx
|
|
25
|
-
/**
|
|
26
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Presents already-authorized chat text. A masked history card may additionally
|
|
94
|
+
* offer retained output, but that read is an explicit operator action through
|
|
95
|
+
* the daemon's releasing route — nothing is disclosed by rendering the card.
|
|
96
|
+
*/
|
|
97
|
+
function CodingToolResult({ name, body, pending = false, log }) {
|
|
27
98
|
if (!pending && body === "Coding context or command evidence retained privately. Captured transport output follows its communication approval; ask the Agent for the relevant result.") return /* @__PURE__ */ jsxs("details", {
|
|
28
99
|
className: "py-1 text-xs font-sans",
|
|
29
100
|
"aria-label": "Private command details",
|
|
30
|
-
children: [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
101
|
+
children: [
|
|
102
|
+
/* @__PURE__ */ jsx("summary", {
|
|
103
|
+
className: "cursor-pointer",
|
|
104
|
+
children: "Detailed output isn’t included in this history view"
|
|
105
|
+
}),
|
|
106
|
+
/* @__PURE__ */ jsx("p", {
|
|
107
|
+
className: "mt-1",
|
|
108
|
+
children: "The Agent’s summary is shown in the conversation. Ask the Agent to summarize its retained command result if you need more detail."
|
|
109
|
+
}),
|
|
110
|
+
log && /* @__PURE__ */ jsx(RetainedLogControl, { reference: log })
|
|
111
|
+
]
|
|
37
112
|
});
|
|
38
113
|
let parsed;
|
|
39
114
|
try {
|
|
@@ -84,6 +159,40 @@ function CodingToolResult({ name, body, pending = false }) {
|
|
|
84
159
|
]
|
|
85
160
|
});
|
|
86
161
|
}
|
|
162
|
+
if (name === "coding_log") {
|
|
163
|
+
const page = parsed;
|
|
164
|
+
if (typeof page.text !== "string" || typeof page.availability !== "string") return /* @__PURE__ */ jsx("span", { children: body });
|
|
165
|
+
return /* @__PURE__ */ jsxs("details", {
|
|
166
|
+
className: "py-1",
|
|
167
|
+
"aria-label": "Retained command output",
|
|
168
|
+
children: [
|
|
169
|
+
/* @__PURE__ */ jsxs("summary", {
|
|
170
|
+
className: "cursor-pointer",
|
|
171
|
+
children: [
|
|
172
|
+
"Retained output: ",
|
|
173
|
+
page.availability,
|
|
174
|
+
page.hasMore ? " · more available" : ""
|
|
175
|
+
]
|
|
176
|
+
}),
|
|
177
|
+
/* @__PURE__ */ jsx("pre", {
|
|
178
|
+
className: "max-h-64 overflow-auto whitespace-pre-wrap break-words",
|
|
179
|
+
children: page.text
|
|
180
|
+
}),
|
|
181
|
+
/* @__PURE__ */ jsxs("p", {
|
|
182
|
+
className: "text-xs",
|
|
183
|
+
children: [
|
|
184
|
+
"bytes ",
|
|
185
|
+
typeof page.offset === "number" ? page.offset : 0,
|
|
186
|
+
"–",
|
|
187
|
+
(typeof page.offset === "number" ? page.offset : 0) + page.text.length,
|
|
188
|
+
" of",
|
|
189
|
+
" ",
|
|
190
|
+
typeof page.byteLength === "number" ? page.byteLength : 0
|
|
191
|
+
]
|
|
192
|
+
})
|
|
193
|
+
]
|
|
194
|
+
});
|
|
195
|
+
}
|
|
87
196
|
if (name === "coding_environment") {
|
|
88
197
|
const value = parsed;
|
|
89
198
|
if (typeof value.posture !== "string") return /* @__PURE__ */ jsx("span", { children: body });
|
|
@@ -162,6 +271,11 @@ function CodingToolResult({ name, body, pending = false }) {
|
|
|
162
271
|
className: "break-all",
|
|
163
272
|
children: ["coding-receipt:", receipt.id]
|
|
164
273
|
}),
|
|
274
|
+
/* @__PURE__ */ jsx(SourceApplicability, {
|
|
275
|
+
teamId: receipt.teamId,
|
|
276
|
+
after: receipt.sourceAfter ?? null,
|
|
277
|
+
before: receipt.sourceBefore ?? null
|
|
278
|
+
}),
|
|
165
279
|
receipt.environment?.imageId && /* @__PURE__ */ jsx("p", {
|
|
166
280
|
className: "break-all",
|
|
167
281
|
children: receipt.environment.imageId
|
|
@@ -170,6 +284,111 @@ function CodingToolResult({ name, body, pending = false }) {
|
|
|
170
284
|
]
|
|
171
285
|
});
|
|
172
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* Whether this result's tested source still matches the current source (BAZ-042 criterion 4).
|
|
289
|
+
*
|
|
290
|
+
* Nothing is assumed from the fact that a result exists: a receipt with no captured source reads as
|
|
291
|
+
* **Not checked**, and the verdict is loaded only when the operator asks for it.
|
|
292
|
+
*/
|
|
293
|
+
function SourceApplicability({ teamId, after, before }) {
|
|
294
|
+
const [state, setState] = useState(null);
|
|
295
|
+
const [loading, setLoading] = useState(false);
|
|
296
|
+
async function check() {
|
|
297
|
+
if (!after) return;
|
|
298
|
+
setLoading(true);
|
|
299
|
+
try {
|
|
300
|
+
setState(await fetchSnapshotApplicability({ data: {
|
|
301
|
+
teamId,
|
|
302
|
+
snapshotId: after.id
|
|
303
|
+
} }));
|
|
304
|
+
} finally {
|
|
305
|
+
setLoading(false);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
const verdict = state?.status === "ok" ? state : null;
|
|
309
|
+
const label = applicabilityLabel(verdict);
|
|
310
|
+
return /* @__PURE__ */ jsxs("p", {
|
|
311
|
+
className: applicabilityWarns(verdict) ? "text-rose-baziu" : void 0,
|
|
312
|
+
children: [
|
|
313
|
+
label,
|
|
314
|
+
after ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
315
|
+
" · tested version ",
|
|
316
|
+
/* @__PURE__ */ jsx("span", {
|
|
317
|
+
className: "break-all font-mono",
|
|
318
|
+
children: after.id.slice(0, 12)
|
|
319
|
+
}),
|
|
320
|
+
after.complete ? "" : " (incomplete)",
|
|
321
|
+
verdict === null && /* @__PURE__ */ jsxs(Fragment, { children: [" ", /* @__PURE__ */ jsx(Button, {
|
|
322
|
+
variant: "ghost",
|
|
323
|
+
disabled: loading,
|
|
324
|
+
onClick: () => void check(),
|
|
325
|
+
children: loading ? "Checking…" : "Check applicability"
|
|
326
|
+
})] }),
|
|
327
|
+
state?.status === "unavailable" && /* @__PURE__ */ jsxs("span", { children: [" · ", state.message] })
|
|
328
|
+
] }) : " · no source snapshot was captured for this result",
|
|
329
|
+
before && /* @__PURE__ */ jsxs(Fragment, { children: [" · started from ", /* @__PURE__ */ jsx("span", {
|
|
330
|
+
className: "break-all font-mono",
|
|
331
|
+
children: before.id.slice(0, 12)
|
|
332
|
+
})] })
|
|
333
|
+
]
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Explicit operator read of a retained log. Loads a single bounded first page
|
|
338
|
+
* on demand; the daemon re-authorizes every call and reports a held log as
|
|
339
|
+
* `not-shared` so it can never be mistaken for an empty result.
|
|
340
|
+
*/
|
|
341
|
+
function RetainedLogControl({ reference }) {
|
|
342
|
+
const [result, setResult] = useState(null);
|
|
343
|
+
const [loading, setLoading] = useState(false);
|
|
344
|
+
async function load() {
|
|
345
|
+
setLoading(true);
|
|
346
|
+
try {
|
|
347
|
+
setResult(await fetchRetainedCodingLog(reference));
|
|
348
|
+
} finally {
|
|
349
|
+
setLoading(false);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (result === null) return /* @__PURE__ */ jsx("p", {
|
|
353
|
+
className: "mt-2",
|
|
354
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
355
|
+
variant: "ghost",
|
|
356
|
+
disabled: loading,
|
|
357
|
+
onClick: () => void load(),
|
|
358
|
+
children: loading ? "Loading…" : "Show retained output"
|
|
359
|
+
})
|
|
360
|
+
});
|
|
361
|
+
if (result.status === "not-shared") return /* @__PURE__ */ jsx("p", {
|
|
362
|
+
className: "mt-2",
|
|
363
|
+
children: "This command’s output hasn’t been shared with the conversation yet."
|
|
364
|
+
});
|
|
365
|
+
if (result.status === "missing") return /* @__PURE__ */ jsx("p", {
|
|
366
|
+
className: "mt-2",
|
|
367
|
+
children: "This retained output is no longer available."
|
|
368
|
+
});
|
|
369
|
+
if (result.status === "unavailable") return /* @__PURE__ */ jsx("p", {
|
|
370
|
+
className: "mt-2",
|
|
371
|
+
role: "alert",
|
|
372
|
+
children: result.message
|
|
373
|
+
});
|
|
374
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
375
|
+
className: "mt-2",
|
|
376
|
+
children: [/* @__PURE__ */ jsx("pre", {
|
|
377
|
+
className: "max-h-64 overflow-auto whitespace-pre-wrap break-words rounded-sm bg-[rgba(42,31,22,0.04)] p-2",
|
|
378
|
+
children: result.page.text
|
|
379
|
+
}), /* @__PURE__ */ jsxs("p", { children: [
|
|
380
|
+
"Retained output: ",
|
|
381
|
+
result.page.availability,
|
|
382
|
+
result.page.hasMore ? " · earlier output omitted" : "",
|
|
383
|
+
" · bytes ",
|
|
384
|
+
result.page.offset,
|
|
385
|
+
"–",
|
|
386
|
+
result.page.offset + result.page.text.length,
|
|
387
|
+
" of ",
|
|
388
|
+
result.page.byteLength
|
|
389
|
+
] })]
|
|
390
|
+
});
|
|
391
|
+
}
|
|
173
392
|
//#endregion
|
|
174
393
|
//#region src/lib/md.ts
|
|
175
394
|
var installed = false;
|
|
@@ -1261,7 +1480,8 @@ function projectMessages(msgs) {
|
|
|
1261
1480
|
kind: isError ? "error" : "result",
|
|
1262
1481
|
id: m.toolCallId ?? "",
|
|
1263
1482
|
name: m.toolName ?? "",
|
|
1264
|
-
body: m.content
|
|
1483
|
+
body: m.content,
|
|
1484
|
+
...m.codingLog ? { codingLog: m.codingLog } : {}
|
|
1265
1485
|
});
|
|
1266
1486
|
if (m.result) {
|
|
1267
1487
|
entries.push({
|
|
@@ -1842,6 +2062,10 @@ function ChatPane({ agentId, agentName, initialMessages, initialSessionHead }) {
|
|
|
1842
2062
|
setLiveEntries((entries) => upsertCommandApprovalEntry(entries, ev.approval));
|
|
1843
2063
|
return;
|
|
1844
2064
|
}
|
|
2065
|
+
if (ev.type === "coding_progress") {
|
|
2066
|
+
setLiveEntries((prev) => upsertCodingProgress(prev, ev));
|
|
2067
|
+
return;
|
|
2068
|
+
}
|
|
1845
2069
|
if (ev.type === "tool_call" || ev.type === "tool_result" || ev.type === "tool_error") {
|
|
1846
2070
|
setThinking(ev.type !== "tool_call");
|
|
1847
2071
|
const item = ev.type === "tool_call" ? {
|
|
@@ -1864,14 +2088,19 @@ function ChatPane({ agentId, agentName, initialMessages, initialSessionHead }) {
|
|
|
1864
2088
|
"repository_context",
|
|
1865
2089
|
"coding_environment",
|
|
1866
2090
|
"coding_command",
|
|
1867
|
-
"coding_receipt"
|
|
2091
|
+
"coding_receipt",
|
|
2092
|
+
"coding_log",
|
|
2093
|
+
"source_snapshot"
|
|
1868
2094
|
].includes(ev.name)) {
|
|
1869
2095
|
deliveredCoding.current.set(`${ev.name}:${ev.id}`, ev.result);
|
|
1870
2096
|
while (deliveredCoding.current.size > 20) deliveredCoding.current.delete(deliveredCoding.current.keys().next().value);
|
|
1871
2097
|
}
|
|
1872
2098
|
const images = ev.type === "tool_result" ? ev.images : void 0;
|
|
1873
2099
|
setLiveEntries((prev) => {
|
|
1874
|
-
const next = [...prev
|
|
2100
|
+
const next = [...prev.map((entry) => entry.type === "tool" ? {
|
|
2101
|
+
...entry,
|
|
2102
|
+
items: entry.items.filter((i) => !(i.kind === "progress" && i.id === ev.id))
|
|
2103
|
+
} : entry)];
|
|
1875
2104
|
const last = next[next.length - 1];
|
|
1876
2105
|
if (last?.type === "tool") next[next.length - 1] = {
|
|
1877
2106
|
type: "tool",
|
|
@@ -2547,12 +2776,48 @@ function commandApprovalStatusFromConflict(message) {
|
|
|
2547
2776
|
default: return null;
|
|
2548
2777
|
}
|
|
2549
2778
|
}
|
|
2779
|
+
/** Insert or replace the live progress tail for one coding tool call. */
|
|
2780
|
+
function upsertCodingProgress(entries, ev) {
|
|
2781
|
+
const progress = {
|
|
2782
|
+
kind: "progress",
|
|
2783
|
+
id: ev.id,
|
|
2784
|
+
name: "coding_command",
|
|
2785
|
+
body: ev.output,
|
|
2786
|
+
elapsedMs: ev.elapsedMs,
|
|
2787
|
+
truncated: ev.truncated
|
|
2788
|
+
};
|
|
2789
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
2790
|
+
const entry = entries[i];
|
|
2791
|
+
if (entry?.type !== "tool") continue;
|
|
2792
|
+
const at = entry.items.findIndex((item) => item.id === ev.id);
|
|
2793
|
+
if (at < 0) continue;
|
|
2794
|
+
const items = [...entry.items];
|
|
2795
|
+
items[at] = progress;
|
|
2796
|
+
const next = [...entries];
|
|
2797
|
+
next[i] = {
|
|
2798
|
+
type: "tool",
|
|
2799
|
+
items
|
|
2800
|
+
};
|
|
2801
|
+
return next;
|
|
2802
|
+
}
|
|
2803
|
+
const last = entries[entries.length - 1];
|
|
2804
|
+
if (last?.type === "tool") return [...entries.slice(0, -1), {
|
|
2805
|
+
type: "tool",
|
|
2806
|
+
items: [...last.items, progress]
|
|
2807
|
+
}];
|
|
2808
|
+
return [...entries, {
|
|
2809
|
+
type: "tool",
|
|
2810
|
+
items: [progress]
|
|
2811
|
+
}];
|
|
2812
|
+
}
|
|
2550
2813
|
function ToolGroup({ items, dropCls }) {
|
|
2551
2814
|
const codingNames = [
|
|
2552
2815
|
"repository_context",
|
|
2553
2816
|
"coding_command",
|
|
2554
2817
|
"coding_environment",
|
|
2555
2818
|
"coding_receipt",
|
|
2819
|
+
"coding_log",
|
|
2820
|
+
"source_snapshot",
|
|
2556
2821
|
"send_message"
|
|
2557
2822
|
];
|
|
2558
2823
|
const hasCoding = items.some((item) => codingNames.includes(item.name));
|
|
@@ -2594,15 +2859,37 @@ function ToolLine({ item }) {
|
|
|
2594
2859
|
children: item.body
|
|
2595
2860
|
})]
|
|
2596
2861
|
});
|
|
2862
|
+
if (item.kind === "progress") return /* @__PURE__ */ jsxs("div", {
|
|
2863
|
+
className: "py-1",
|
|
2864
|
+
"aria-label": "Live coding progress",
|
|
2865
|
+
children: [
|
|
2866
|
+
/* @__PURE__ */ jsxs("p", {
|
|
2867
|
+
className: "font-sans",
|
|
2868
|
+
children: [
|
|
2869
|
+
"Running coding command · ",
|
|
2870
|
+
Math.max(0, Math.round((item.elapsedMs ?? 0) / 1e3)),
|
|
2871
|
+
"s"
|
|
2872
|
+
]
|
|
2873
|
+
}),
|
|
2874
|
+
/* @__PURE__ */ jsx("pre", {
|
|
2875
|
+
className: "max-h-64 overflow-auto whitespace-pre-wrap break-words",
|
|
2876
|
+
children: item.body
|
|
2877
|
+
}),
|
|
2878
|
+
item.truncated && /* @__PURE__ */ jsx("p", { children: "Earlier output omitted; the retained log holds more." })
|
|
2879
|
+
]
|
|
2880
|
+
});
|
|
2597
2881
|
if (item.kind !== "error" && [
|
|
2598
2882
|
"repository_context",
|
|
2599
2883
|
"coding_command",
|
|
2600
2884
|
"coding_environment",
|
|
2601
|
-
"coding_receipt"
|
|
2885
|
+
"coding_receipt",
|
|
2886
|
+
"coding_log",
|
|
2887
|
+
"source_snapshot"
|
|
2602
2888
|
].includes(item.name)) return /* @__PURE__ */ jsx(CodingToolResult, {
|
|
2603
2889
|
name: item.name,
|
|
2604
2890
|
body: item.body,
|
|
2605
|
-
pending: item.kind === "call"
|
|
2891
|
+
pending: item.kind === "call",
|
|
2892
|
+
log: item.codingLog
|
|
2606
2893
|
});
|
|
2607
2894
|
if (item.kind === "call") {
|
|
2608
2895
|
const args = prettyArgs(item.body);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as Button } from "./Button-Dsnw22OF.js";
|
|
2
|
-
import { n as ResultTranscript } from "./ChatPane-
|
|
2
|
+
import { n as ResultTranscript } from "./ChatPane-DybH39WK.js";
|
|
3
3
|
import { useEffect, useState } from "react";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/ResultSourceConversation.tsx
|