bazilion 0.15.0 → 0.16.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 +816 -681
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +6605 -4313
- package/dist/daemon.js.map +1 -1
- package/dist/migrations/0001_init.sql +47 -0
- package/dist/web/client/assets/ChatPane-CQZzxOir.js +76 -0
- package/dist/web/client/assets/{ConfirmDialog-CGZzom9E.js → ConfirmDialog-MicTTwdy.js} +1 -1
- package/dist/web/client/assets/{FieldRow-DYNU9gWb.js → FieldRow-DJ2Gx4Du.js} +1 -1
- package/dist/web/client/assets/{ProductionTeamPolicyEditor-DT5Sl8jd.js → ProductionTeamPolicyEditor-DqUnN_ce.js} +1 -1
- package/dist/web/client/assets/{ProfileCommunicationEditor-TyCU5vXX.js → ProfileCommunicationEditor-DArXub0b.js} +1 -1
- package/dist/web/client/assets/{ResultSourceConversation-CGhKTSTD.js → ResultSourceConversation-CtzJ8QA-.js} +1 -1
- package/dist/web/client/assets/{TeamTabs-BZHyRnbd.js → TeamTabs-DbIk5vvT.js} +1 -1
- package/dist/web/client/assets/{TemplatesTabs-BHzkPMRC.js → TemplatesTabs-CatJIjGi.js} +1 -1
- package/dist/web/client/assets/{UnsavedChangesGuard-CFQcKsrf.js → UnsavedChangesGuard-BCsLw-mU.js} +1 -1
- package/dist/web/client/assets/_id-B5Ov7cdO.js +1 -0
- package/dist/web/client/assets/{_id-D_eKokkd.js → _id-BEDmIXVf.js} +1 -1
- package/dist/web/client/assets/{_id-9nCIhbVd.js → _id-BFM_tn_s.js} +1 -1
- package/dist/web/client/assets/{_id-CGd21j3k.js → _id-CrnEVcw8.js} +1 -1
- package/dist/web/client/assets/{_id-BSu3AqKA.js → _id-DxopIW-y.js} +1 -1
- package/dist/web/client/assets/{activity-Cn2-9PpZ.js → activity-CrG8Bg60.js} +1 -1
- package/dist/web/client/assets/{agents-NY3VrZgB.js → agents-CMPOFcs-.js} +1 -1
- package/dist/web/client/assets/{agents-CCmiZek6.js → agents-O4soKZND.js} +1 -1
- package/dist/web/client/assets/{approvals-CPDAPgrM.js → approvals-CwDu_lrA.js} +1 -1
- package/dist/web/client/assets/{attention-Qra_9_OI.js → attention-BY8MMuM_.js} +1 -1
- package/dist/web/client/assets/chevron-right-Cf6vKeLq.js +1 -0
- package/dist/web/client/assets/{config-D8EO0LPB.js → config-Cn4iBJFz.js} +1 -1
- package/dist/web/client/assets/{inbox-C5W-sm1q.js → inbox-CWXql0K3.js} +1 -1
- package/dist/web/client/assets/{index-BUhhk_u9.js → index-Bq2zrG2_.js} +2 -2
- package/dist/web/client/assets/{learning-Dr-7_7J4.js → learning-DAm4dyyc.js} +1 -1
- package/dist/web/client/assets/{login-Bu5UxbJh.js → login-BsABI8Ux.js} +1 -1
- package/dist/web/client/assets/{mcp-BueuwQiv.js → mcp-loLB0wuh.js} +1 -1
- package/dist/web/client/assets/{members-ZikuYNcy.js → members-BJ0ikkTl.js} +1 -1
- package/dist/web/client/assets/{memory-1JUJlPrn.js → memory-Drn9Gv53.js} +1 -1
- package/dist/web/client/assets/{policy-DbkhsFNA.js → policy-pQadZyk0.js} +1 -1
- package/dist/web/client/assets/{results-mMr8Ar2u.js → results-9exU6f7m.js} +1 -1
- package/dist/web/client/assets/{routes-DJYB-MS9.js → routes-jw1PuqiR.js} +1 -1
- package/dist/web/client/assets/{services-kfQA9cpJ.js → services-BLso1BhA.js} +1 -1
- package/dist/web/client/assets/{skills-C6pcgxaC.js → skills-BodqX3OI.js} +1 -1
- package/dist/web/client/assets/styles-d1yjBpud.css +2 -0
- package/dist/web/client/assets/{teams-LB0KBXY9.js → teams-ByQedXZi.js} +1 -1
- package/dist/web/client/assets/{teams-C6_Noz5X.js → teams-SYsF1bOR.js} +1 -1
- package/dist/web/client/assets/{telegram-A2jaI1QM.js → telegram-DC9PLFbB.js} +1 -1
- package/dist/web/client/assets/{tokens-BGlUpJcL.js → tokens-DGy8Ijpo.js} +1 -1
- package/dist/web/client/assets/{triggers-C54_feGg.js → triggers-BXpVmHDG.js} +1 -1
- package/dist/web/client/assets/{welcome-DyUIswRi.js → welcome-BKsnsCxJ.js} +1 -1
- package/dist/web/client/assets/{x-BY2MPLr9.js → x-BK4xNCzS.js} +1 -1
- package/dist/web/server/assets/{ChatPane-DJ30FdFG.js → ChatPane-CS5oI7ef.js} +235 -13
- package/dist/web/server/assets/{ResultSourceConversation-zYogeOWp.js → ResultSourceConversation-BpVWBRYq.js} +1 -1
- package/dist/web/server/assets/{_id-1LwoHhJg.js → _id-5pgKoid8.js} +1 -1
- package/dist/web/server/assets/{_id-BvSWsPI5.js → _id-BG2nkGxa.js} +1 -1
- package/dist/web/server/assets/{_id-1hTvnKLN2.js → _id-BnqodC1c2.js} +3 -3
- package/dist/web/server/assets/{_id-DDNVQx3y.js → _id-CeyHEsCZ.js} +1 -1
- package/dist/web/server/assets/{_id-T_8btpbB.js → _id-DOnInzLb.js} +1 -1
- package/dist/web/server/assets/{_id-DxFLSIio.js → _id-DrB9uR1b.js} +1 -1
- package/dist/web/server/assets/{_id-B2EEyStS.js → _id-DtIYuJJX.js} +1 -1
- package/dist/web/server/assets/_id-DwZXhLlL.js +779 -0
- package/dist/web/server/assets/{_tanstack-start-manifest_v-DP4ZUBw3.js → _tanstack-start-manifest_v-D7gKv6m6.js} +85 -85
- package/dist/web/server/assets/{activity-D73w4mkZ.js → activity-0VUkStOu.js} +1 -1
- package/dist/web/server/assets/{agents-DB5hCSAI.js → agents-C86K6HvS.js} +1 -1
- package/dist/web/server/assets/{agents-DRSo7lRX.js → agents-CSXLaM2W.js} +1 -1
- package/dist/web/server/assets/{approvals-4y9bZF4r.js → approvals-C3MysI6l.js} +1 -1
- package/dist/web/server/assets/{attention-BFx8ZkmH.js → attention-DLeLCKah.js} +1 -1
- package/dist/web/server/assets/{auth-_eaCwhyq.js → auth-CDZp9aEk.js} +1 -1
- package/dist/web/server/assets/{config-B7JIfv_7.js → config-BVTHvljR.js} +1 -1
- package/dist/web/server/assets/{daemon-client-B06W1Qa2.js → daemon-client-xWyYKAcx.js} +5 -0
- package/dist/web/server/assets/{inbox-YRpDQcvp.js → inbox-PQTrjtOw.js} +1 -1
- package/dist/web/server/assets/{learning-UBZb6h6M.js → learning-K0cmDsZR.js} +1 -1
- package/dist/web/server/assets/{mcp-Dv6RXMaS.js → mcp-Rtraochg.js} +1 -1
- package/dist/web/server/assets/{members-BFTKSlOe.js → members-grAKFWgv.js} +1 -1
- package/dist/web/server/assets/{memory-D0PQgZAn.js → memory-egFpBD1g.js} +1 -1
- package/dist/web/server/assets/{policy-C-p8HIhA.js → policy-ooSBgiDS.js} +1 -1
- package/dist/web/server/assets/{results-Cj-Dlw3C.js → results-CfNsFncJ.js} +2 -2
- package/dist/web/server/assets/{results-Cfev4KNt.js → results-DXdYtHaq.js} +1 -1
- package/dist/web/server/assets/{results-CwEQ5EUL.js → results-N-kP4iFT.js} +1 -1
- package/dist/web/server/assets/{router-d3sTMpMX.js → router-B6g_s7W3.js} +6 -6
- package/dist/web/server/assets/{routes-cW4MWU18.js → routes-BqSaZvlu.js} +1 -1
- package/dist/web/server/assets/{routes-MIZz6uMr.js → routes-Dsh8F_7i.js} +2 -2
- package/dist/web/server/assets/{routes-B765DVhj.js → routes-pcRy_Sf8.js} +1 -1
- package/dist/web/server/assets/{services-BCbdn3R9.js → services-DlZA8fRL.js} +1 -1
- package/dist/web/server/assets/{skills-Bpoa8MIp.js → skills-i2duvgW-.js} +1 -1
- package/dist/web/server/assets/{teams-CXzwqzcE.js → teams-6RYIj1Xm.js} +1 -1
- package/dist/web/server/assets/{teams-hWGjbpUA.js → teams-B1AI3NfN.js} +1 -1
- package/dist/web/server/assets/{telegram-DhpvtGUc.js → telegram-C4q0YTVn.js} +1 -1
- package/dist/web/server/assets/{tokens-Bjp19Vkn.js → tokens-RFquA2Bx.js} +1 -1
- package/dist/web/server/assets/{triggers-DJlcvXzn.js → triggers-DVD-iE-N.js} +1 -1
- package/dist/web/server/server.js +28 -28
- package/dist/worker.js +1553 -688
- package/dist/worker.js.map +1 -1
- package/package.json +3 -3
- package/dist/web/client/assets/ChatPane-55j13bBj.js +0 -74
- package/dist/web/client/assets/_id-SRMFlIgP.js +0 -1
- package/dist/web/client/assets/chevron-right-DXE4CWf2.js +0 -1
- package/dist/web/client/assets/styles-CcNf8jT_.css +0 -2
- package/dist/web/server/assets/_id-CDBtO_jL.js +0 -381
|
@@ -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-MicTTwdy.js";import{T as a}from"./index-Bq2zrG2_.js";import{a as o,i as s,n as c,r as l,t as u}from"./Page-NV96O47A.js";import{t as d}from"./Button-ByiV6fpd.js";var f=e(n()),p=t();function m(){let{teams:e,memberCounts:t,policies:n,readiness:m}=a.useLoaderData(),g=r(),[_,v]=(0,f.useState)(null),[y,b]=(0,f.useState)(null);async function x(e){let t=n[e]?.revision;if(!t)throw Error(`The Team policy revision is unavailable. Nothing was removed.`);let r=await fetch(`/api/teams/${encodeURIComponent(e)}?expectedTeamPolicyRevision=${t}`,{method:`DELETE`});if(!r.ok&&r.status!==204){let e=await r.json().catch(()=>null);throw Error(e?.error??`Could not remove Team (${r.status})`)}await g.invalidate()}return(0,p.jsxs)(l,{size:`wide`,children:[(0,p.jsx)(c,{eyebrow:`Workspace`,title:`Teams`,description:`Each Team owns one workspace, one live membership roster, and one effective communication policy. Every agent belongs to exactly one Team.`}),(0,p.jsx)(s,{title:`Policy enforcement`,description:`Management contract v${m.contractVersion} is ready for this daemon.`,actions:(0,p.jsx)(o,{variant:m.enforcementActive?`success`:`warning`,children:m.enforcementActive?`Enforcement on`:`Enforcement off`}),"aria-label":`Team Policy enforcement readiness`,children:(0,p.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:m.enforcementActive?`Communication boundaries are currently enforcing each Team policy.`:(0,p.jsxs)(p.Fragment,{children:[`Set `,(0,p.jsx)(`code`,{children:`BAZILION_TEAM_POLICY_ENFORCEMENT=on`}),` and restart the daemon to enforce Team policies.`]})})}),(0,p.jsx)(h,{onRegistered:()=>g.invalidate()}),y&&(0,p.jsx)(`p`,{role:`alert`,className:`err`,children:y}),(0,p.jsx)(s,{title:`Registered teams`,description:`Open a Team to manage its context, members, shared memory, and policy.`,children:e.length===0?(0,p.jsx)(u,{title:`No teams registered`,description:`Register a Team above to create a workspace for your agents.`}):(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(`div`,{className:`hidden overflow-x-auto md:block`,children:(0,p.jsxs)(`table`,{className:`min-w-[820px]`,children:[(0,p.jsx)(`thead`,{children:(0,p.jsxs)(`tr`,{children:[(0,p.jsx)(`th`,{children:`ID`}),(0,p.jsx)(`th`,{children:`Name`}),(0,p.jsx)(`th`,{children:`Members`}),(0,p.jsx)(`th`,{children:`Policy`}),(0,p.jsx)(`th`,{children:`Baseline`}),(0,p.jsx)(`th`,{children:(0,p.jsx)(`span`,{className:`sr-only`,children:`Actions`})})]})}),(0,p.jsx)(`tbody`,{children:e.map(e=>{let r=t[e.id]??0,i=n[e.id];return(0,p.jsxs)(`tr`,{children:[(0,p.jsx)(`td`,{children:(0,p.jsx)(`code`,{children:e.id})}),(0,p.jsx)(`td`,{children:(0,p.jsx)(`a`,{href:`/teams/${e.id}`,children:e.name})}),(0,p.jsx)(`td`,{children:r}),(0,p.jsx)(`td`,{children:(0,p.jsx)(`a`,{href:`/teams/${e.id}/policy`,children:i?`r${i.revision} · ${i.edges} edges`:`Unavailable`})}),(0,p.jsx)(`td`,{children:i?.baseline??`None`}),(0,p.jsx)(`td`,{children:(0,p.jsx)(`div`,{className:`flex justify-end`,children:r===0?(0,p.jsx)(d,{variant:`danger`,onClick:()=>v(e),children:`Remove`}):(0,p.jsx)(o,{variant:`neutral`,title:`${r} agent(s) belong to this Team`,children:`In use`})})})]},e.id)})})]})}),(0,p.jsx)(`div`,{className:`grid gap-3 md:hidden`,children:e.map(e=>{let r=t[e.id]??0,i=n[e.id];return(0,p.jsxs)(`article`,{className:`min-w-0 rounded-xl border border-border bg-muted/20 p-4`,children:[(0,p.jsxs)(`div`,{className:`flex min-w-0 items-start justify-between gap-3`,children:[(0,p.jsxs)(`div`,{className:`min-w-0`,children:[(0,p.jsx)(`a`,{href:`/teams/${encodeURIComponent(e.id)}`,className:`block truncate font-semibold text-foreground`,children:e.name}),(0,p.jsx)(`p`,{className:`mt-0.5 truncate font-mono text-xs text-muted-foreground`,children:e.id})]}),(0,p.jsxs)(o,{variant:r>0?`success`:`neutral`,children:[r,` member`,r===1?``:`s`]})]}),(0,p.jsxs)(`dl`,{className:`mt-3 grid gap-2 text-xs sm:grid-cols-2`,children:[(0,p.jsxs)(`div`,{className:`rounded-lg bg-muted p-2`,children:[(0,p.jsx)(`dt`,{className:`font-semibold text-muted-foreground`,children:`Policy`}),(0,p.jsx)(`dd`,{className:`mt-0.5`,children:(0,p.jsx)(`a`,{href:`/teams/${encodeURIComponent(e.id)}/policy`,children:i?`Revision ${i.revision} · ${i.edges} edges`:`Unavailable`})})]}),(0,p.jsxs)(`div`,{className:`rounded-lg bg-muted p-2`,children:[(0,p.jsx)(`dt`,{className:`font-semibold text-muted-foreground`,children:`Baseline`}),(0,p.jsx)(`dd`,{className:`mt-0.5 break-words`,children:i?.baseline??`None`})]})]}),r===0&&(0,p.jsx)(`div`,{className:`mt-3`,children:(0,p.jsx)(d,{variant:`danger`,onClick:()=>v(e),children:`Remove Team`})})]},e.id)})})]})}),(0,p.jsx)(i,{open:_!==null,onOpenChange:e=>{e||v(null)},title:`Remove ${_?.name??`Team`}?`,description:(0,p.jsx)(`p`,{children:`This removes the empty Team registration and its Bazilion-managed workspace slot. If the slot is a symlink, its external target is not deleted. This action cannot be undone from the web UI.`}),confirmLabel:`Remove Team`,onConfirm:async()=>{if(_)try{await x(_.id)}catch(e){throw b(e instanceof Error?e.message:String(e)),e}}})]})}function h({onRegistered:e}){let[t,n]=(0,f.useState)(``),[r,i]=(0,f.useState)(``),[a,o]=(0,f.useState)(``),[c,l]=(0,f.useState)(null),[u,m]=(0,f.useState)(!1);async function h(s){if(s.preventDefault(),l(null),!t.trim()){l(`id is required`);return}m(!0);try{let s=await fetch(`/api/teams`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({id:t.trim(),name:r.trim()||void 0,link:a.trim()||void 0})});if(!s.ok){let e=await s.json().catch(()=>null);throw Error(e?.error??s.statusText)}n(``),i(``),o(``),e()}catch(e){l(e.message)}finally{m(!1)}}return(0,p.jsx)(s,{title:`Register a team`,description:(0,p.jsxs)(p.Fragment,{children:[`Teams live under `,(0,p.jsx)(`code`,{children:`~/.bazilion/teams/<slug>/`}),`. Link an existing project directory or leave the target blank to create a fresh workspace.`]}),children:(0,p.jsxs)(`form`,{onSubmit:h,children:[c&&(0,p.jsx)(`div`,{role:`alert`,className:`err`,children:c}),(0,p.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[(0,p.jsxs)(`label`,{children:[`ID (slug)`,(0,p.jsx)(`input`,{value:t,onChange:e=>n(e.target.value),required:!0,placeholder:`my-project`})]}),(0,p.jsxs)(`label`,{children:[`Name`,(0,p.jsx)(`input`,{value:r,onChange:e=>i(e.target.value),placeholder:`My project`})]}),(0,p.jsxs)(`label`,{className:`sm:col-span-2`,children:[`Link target (optional, absolute path)`,(0,p.jsx)(`input`,{value:a,onChange:e=>o(e.target.value),placeholder:`/home/user/projects/my-project`})]})]}),(0,p.jsx)(`div`,{className:`mt-4`,children:(0,p.jsx)(d,{variant:`primary`,type:`submit`,disabled:u,children:u?`Registering…`:`Register team`})})]})})}export{m 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-CGZzom9E.js";import{o as a}from"./index-BUhhk_u9.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-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 +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-MicTTwdy.js";import{v 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()),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-MicTTwdy.js";import{a}from"./index-Bq2zrG2_.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};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./jsx-runtime-DGeXAQPT.js";import{Y as t}from"./index-
|
|
1
|
+
import{t as e}from"./jsx-runtime-DGeXAQPT.js";import{Y as t}from"./index-Bq2zrG2_.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};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Y as e}from"./index-
|
|
1
|
+
import{Y as e}from"./index-Bq2zrG2_.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};
|
|
@@ -4,6 +4,173 @@ import { forwardRef, useCallback, useEffect, useImperativeHandle, useLayoutEffec
|
|
|
4
4
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import DOMPurify from "dompurify";
|
|
6
6
|
import { marked } from "marked";
|
|
7
|
+
//#region src/lib/coding-presentation.ts
|
|
8
|
+
/** Presentation only: excerpts are never used for authorization or receipt validity. */
|
|
9
|
+
function codingFailureSummary(diagnostic) {
|
|
10
|
+
const error = diagnostic.split("\n").map((line) => line.trim()).find((line) => /^(?:[A-Za-z]*Error(?: \[[A-Z_]+\])?:|ERR_[A-Z_]+\b)/.test(line));
|
|
11
|
+
if (!error) return null;
|
|
12
|
+
return error.length > 240 ? `${error.slice(0, 237)}…` : error;
|
|
13
|
+
}
|
|
14
|
+
function inboxUpdateLabel(body) {
|
|
15
|
+
const header = body.split("\n").find((line) => line.startsWith("--- from "));
|
|
16
|
+
if (!header) return "Teammate update received";
|
|
17
|
+
const match = /^--- from (.+?) \(message [0-9a-f-]+(?:, reply to [0-9a-f-]+)?\) ---$/.exec(header);
|
|
18
|
+
if (!match) return "Teammate update received";
|
|
19
|
+
const name = match[1]?.replace(/ \([0-9a-f-]{36}\)$/, "").trim();
|
|
20
|
+
if (!name || /^[0-9a-f-]{36}$/.test(name)) return "Teammate update received";
|
|
21
|
+
return `Update from ${name.slice(0, 100)}`;
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/components/CodingToolResult.tsx
|
|
25
|
+
/** Presents only already-authorized chat text; never fetches private receipt records. */
|
|
26
|
+
function CodingToolResult({ name, body, pending = false }) {
|
|
27
|
+
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
|
+
className: "py-1 text-xs font-sans",
|
|
29
|
+
"aria-label": "Private command details",
|
|
30
|
+
children: [/* @__PURE__ */ jsx("summary", {
|
|
31
|
+
className: "cursor-pointer",
|
|
32
|
+
children: "Detailed output isn’t included in this history view"
|
|
33
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
34
|
+
className: "mt-1",
|
|
35
|
+
children: "The Agent’s summary is shown in the conversation. Ask the Agent to summarize its retained command result if you need more detail."
|
|
36
|
+
})]
|
|
37
|
+
});
|
|
38
|
+
let parsed;
|
|
39
|
+
try {
|
|
40
|
+
parsed = JSON.parse(body);
|
|
41
|
+
} catch {
|
|
42
|
+
return /* @__PURE__ */ jsx("span", { children: body });
|
|
43
|
+
}
|
|
44
|
+
if (!parsed || typeof parsed !== "object") return /* @__PURE__ */ jsx("span", { children: body });
|
|
45
|
+
if (pending) {
|
|
46
|
+
const input = parsed;
|
|
47
|
+
return /* @__PURE__ */ jsxs("p", {
|
|
48
|
+
className: "py-1 break-words",
|
|
49
|
+
children: [
|
|
50
|
+
name === "coding_command" ? "Running" : "Inspecting",
|
|
51
|
+
":",
|
|
52
|
+
" ",
|
|
53
|
+
typeof input.command === "string" ? input.command : typeof input.target === "string" ? input.target : "command evidence"
|
|
54
|
+
]
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
if (name === "repository_context") {
|
|
58
|
+
const report = parsed;
|
|
59
|
+
if (!Array.isArray(report.instructions?.files)) return /* @__PURE__ */ jsx("span", { children: body });
|
|
60
|
+
return /* @__PURE__ */ jsxs("details", {
|
|
61
|
+
className: "py-1",
|
|
62
|
+
children: [
|
|
63
|
+
/* @__PURE__ */ jsxs("summary", {
|
|
64
|
+
className: "cursor-pointer",
|
|
65
|
+
children: [
|
|
66
|
+
"Repository: ",
|
|
67
|
+
report.target,
|
|
68
|
+
" ·",
|
|
69
|
+
" ",
|
|
70
|
+
report.instructions.state === "complete" ? `${report.instructions.files.length} instruction files` : "instructions unavailable"
|
|
71
|
+
]
|
|
72
|
+
}),
|
|
73
|
+
report.instructions.files.map((file) => /* @__PURE__ */ jsx("p", { children: file.path }, file.path)),
|
|
74
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
75
|
+
report.commands?.candidates?.length ?? 0,
|
|
76
|
+
" suggested commands ·",
|
|
77
|
+
" ",
|
|
78
|
+
report.git?.state === "available" ? report.git.branch : "Git unavailable"
|
|
79
|
+
] }),
|
|
80
|
+
/* @__PURE__ */ jsx("pre", {
|
|
81
|
+
className: "max-h-64 overflow-auto whitespace-pre-wrap break-words",
|
|
82
|
+
children: body
|
|
83
|
+
})
|
|
84
|
+
]
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (name === "coding_environment") {
|
|
88
|
+
const value = parsed;
|
|
89
|
+
if (typeof value.posture !== "string") return /* @__PURE__ */ jsx("span", { children: body });
|
|
90
|
+
return /* @__PURE__ */ jsxs("details", {
|
|
91
|
+
className: "py-1",
|
|
92
|
+
children: [
|
|
93
|
+
/* @__PURE__ */ jsxs("summary", {
|
|
94
|
+
className: "cursor-pointer",
|
|
95
|
+
children: [
|
|
96
|
+
"Environment: ",
|
|
97
|
+
value.posture,
|
|
98
|
+
" · ",
|
|
99
|
+
value.cwd
|
|
100
|
+
]
|
|
101
|
+
}),
|
|
102
|
+
/* @__PURE__ */ jsx("p", {
|
|
103
|
+
className: "break-all",
|
|
104
|
+
children: value.imageId ?? "Host runtime"
|
|
105
|
+
}),
|
|
106
|
+
Array.isArray(value.restrictions) && value.restrictions.filter((x) => typeof x === "string").map((text) => /* @__PURE__ */ jsx("p", { children: text }, text))
|
|
107
|
+
]
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const view = parsed;
|
|
111
|
+
const receipt = name === "coding_receipt" ? view.receipt : parsed;
|
|
112
|
+
if (!receipt || typeof receipt.state !== "string" || typeof receipt.input?.command !== "string" || typeof receipt.input?.cwd !== "string") return /* @__PURE__ */ jsx("span", { children: body });
|
|
113
|
+
const failure = receipt.state === "failed" && typeof receipt.diagnostic === "string" ? codingFailureSummary(receipt.diagnostic) : null;
|
|
114
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
115
|
+
className: "py-2",
|
|
116
|
+
"aria-label": "Coding command result",
|
|
117
|
+
children: [
|
|
118
|
+
/* @__PURE__ */ jsxs("p", {
|
|
119
|
+
className: "font-sans",
|
|
120
|
+
children: [
|
|
121
|
+
/* @__PURE__ */ jsx("strong", {
|
|
122
|
+
className: receipt.state === "succeeded" ? "text-sapphire-deep" : "text-mocha",
|
|
123
|
+
children: receipt.state.replaceAll("_", " ")
|
|
124
|
+
}),
|
|
125
|
+
" ",
|
|
126
|
+
"· ",
|
|
127
|
+
receipt.input.purpose,
|
|
128
|
+
typeof receipt.exitCode === "number" ? ` · exit ${receipt.exitCode}` : "",
|
|
129
|
+
name === "coding_receipt" ? ` · ${view.applicability}` : ""
|
|
130
|
+
]
|
|
131
|
+
}),
|
|
132
|
+
/* @__PURE__ */ jsx("p", {
|
|
133
|
+
className: "whitespace-pre-wrap break-words",
|
|
134
|
+
children: receipt.input.command
|
|
135
|
+
}),
|
|
136
|
+
/* @__PURE__ */ jsxs("p", {
|
|
137
|
+
className: "text-xs",
|
|
138
|
+
children: [
|
|
139
|
+
receipt.input.cwd,
|
|
140
|
+
" · ",
|
|
141
|
+
receipt.environment?.posture,
|
|
142
|
+
" · result at execution time"
|
|
143
|
+
]
|
|
144
|
+
}),
|
|
145
|
+
failure && /* @__PURE__ */ jsx("p", {
|
|
146
|
+
className: "mt-1 font-sans text-rose-baziu",
|
|
147
|
+
"aria-label": "Command failure summary",
|
|
148
|
+
children: failure
|
|
149
|
+
}),
|
|
150
|
+
typeof receipt.reason === "string" && /* @__PURE__ */ jsx("p", { children: receipt.reason }),
|
|
151
|
+
/* @__PURE__ */ jsxs("details", { children: [
|
|
152
|
+
/* @__PURE__ */ jsx("summary", {
|
|
153
|
+
className: "cursor-pointer",
|
|
154
|
+
children: "Output and evidence"
|
|
155
|
+
}),
|
|
156
|
+
/* @__PURE__ */ jsx("pre", {
|
|
157
|
+
className: "max-h-64 overflow-auto whitespace-pre-wrap break-words",
|
|
158
|
+
children: receipt.diagnostic
|
|
159
|
+
}),
|
|
160
|
+
receipt.truncated && /* @__PURE__ */ jsx("p", { children: "Output truncated." }),
|
|
161
|
+
/* @__PURE__ */ jsxs("p", {
|
|
162
|
+
className: "break-all",
|
|
163
|
+
children: ["coding-receipt:", receipt.id]
|
|
164
|
+
}),
|
|
165
|
+
receipt.environment?.imageId && /* @__PURE__ */ jsx("p", {
|
|
166
|
+
className: "break-all",
|
|
167
|
+
children: receipt.environment.imageId
|
|
168
|
+
})
|
|
169
|
+
] })
|
|
170
|
+
]
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
//#endregion
|
|
7
174
|
//#region src/lib/md.ts
|
|
8
175
|
var installed = false;
|
|
9
176
|
function install() {
|
|
@@ -1117,6 +1284,7 @@ function ChatPane({ agentId, agentName, initialMessages, initialSessionHead }) {
|
|
|
1117
1284
|
const markdownReady = useSyncExternalStore(subscribeToHydration, browserMarkdownReady, serverMarkdownReady);
|
|
1118
1285
|
const [serverMessages, setServerMessages] = useState(initialMessages);
|
|
1119
1286
|
const [liveEntries, setLiveEntries] = useState([]);
|
|
1287
|
+
const deliveredCoding = useRef(/* @__PURE__ */ new Map());
|
|
1120
1288
|
const [systemBubbles, setSystemBubbles] = useState([]);
|
|
1121
1289
|
const [thinking, setThinking] = useState(false);
|
|
1122
1290
|
const [streaming, setStreaming] = useState(false);
|
|
@@ -1154,6 +1322,7 @@ function ChatPane({ agentId, agentName, initialMessages, initialSessionHead }) {
|
|
|
1154
1322
|
currentAbortRef.current?.abort();
|
|
1155
1323
|
currentAbortRef.current = null;
|
|
1156
1324
|
commandApprovalTurnRef.current = false;
|
|
1325
|
+
deliveredCoding.current.clear();
|
|
1157
1326
|
setServerMessages(initialMessages);
|
|
1158
1327
|
setLiveEntries([]);
|
|
1159
1328
|
setSystemBubbles([]);
|
|
@@ -1691,6 +1860,15 @@ function ChatPane({ agentId, agentName, initialMessages, initialSessionHead }) {
|
|
|
1691
1860
|
name: ev.name,
|
|
1692
1861
|
body: ev.error
|
|
1693
1862
|
};
|
|
1863
|
+
if (ev.type === "tool_result" && [
|
|
1864
|
+
"repository_context",
|
|
1865
|
+
"coding_environment",
|
|
1866
|
+
"coding_command",
|
|
1867
|
+
"coding_receipt"
|
|
1868
|
+
].includes(ev.name)) {
|
|
1869
|
+
deliveredCoding.current.set(`${ev.name}:${ev.id}`, ev.result);
|
|
1870
|
+
while (deliveredCoding.current.size > 20) deliveredCoding.current.delete(deliveredCoding.current.keys().next().value);
|
|
1871
|
+
}
|
|
1694
1872
|
const images = ev.type === "tool_result" ? ev.images : void 0;
|
|
1695
1873
|
setLiveEntries((prev) => {
|
|
1696
1874
|
const next = [...prev];
|
|
@@ -1802,7 +1980,14 @@ function ChatPane({ agentId, agentName, initialMessages, initialSessionHead }) {
|
|
|
1802
1980
|
send(input);
|
|
1803
1981
|
}
|
|
1804
1982
|
}
|
|
1805
|
-
const baseEntries = projectMessages(serverMessages)
|
|
1983
|
+
const baseEntries = projectMessages(serverMessages.map((message) => {
|
|
1984
|
+
if (message.role !== "tool" || !message.toolCallId || !message.toolName) return message;
|
|
1985
|
+
const body = deliveredCoding.current.get(`${message.toolName}:${message.toolCallId}`);
|
|
1986
|
+
return body === void 0 ? message : {
|
|
1987
|
+
...message,
|
|
1988
|
+
content: body
|
|
1989
|
+
};
|
|
1990
|
+
}));
|
|
1806
1991
|
visibleEntryCountRef.current = baseEntries.length + liveEntries.length;
|
|
1807
1992
|
const lastUserIdx = (() => {
|
|
1808
1993
|
if (liveEntries.length > 0 || turnBusy) return -1;
|
|
@@ -2108,15 +2293,23 @@ function Bubble({ entry, markdownReady, isLastUser, isWillDrop, onEdit, onComman
|
|
|
2108
2293
|
if (entry.type === "user") {
|
|
2109
2294
|
if (entry.content.startsWith(INBOX_WAKE_PREFIX)) {
|
|
2110
2295
|
const body = entry.content.slice(24);
|
|
2111
|
-
return /* @__PURE__ */ jsxs("
|
|
2112
|
-
className: `my-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2296
|
+
return /* @__PURE__ */ jsxs("details", {
|
|
2297
|
+
className: `my-3 rounded-lg border border-fawn bg-ivory px-3 py-2 text-sm text-mocha ${dropCls}`,
|
|
2298
|
+
"aria-label": "Teammate update",
|
|
2299
|
+
children: [
|
|
2300
|
+
/* @__PURE__ */ jsx("summary", {
|
|
2301
|
+
className: "cursor-pointer font-medium",
|
|
2302
|
+
children: inboxUpdateLabel(body)
|
|
2303
|
+
}),
|
|
2304
|
+
/* @__PURE__ */ jsx("p", {
|
|
2305
|
+
className: "mt-2 text-xs",
|
|
2306
|
+
children: "Original message and Agent instructions"
|
|
2307
|
+
}),
|
|
2308
|
+
/* @__PURE__ */ jsx("pre", {
|
|
2309
|
+
className: "mt-1 max-h-64 overflow-auto whitespace-pre-wrap break-words text-xs",
|
|
2310
|
+
children: body
|
|
2311
|
+
})
|
|
2312
|
+
]
|
|
2120
2313
|
});
|
|
2121
2314
|
}
|
|
2122
2315
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -2355,6 +2548,15 @@ function commandApprovalStatusFromConflict(message) {
|
|
|
2355
2548
|
}
|
|
2356
2549
|
}
|
|
2357
2550
|
function ToolGroup({ items, dropCls }) {
|
|
2551
|
+
const codingNames = [
|
|
2552
|
+
"repository_context",
|
|
2553
|
+
"coding_command",
|
|
2554
|
+
"coding_environment",
|
|
2555
|
+
"coding_receipt",
|
|
2556
|
+
"send_message"
|
|
2557
|
+
];
|
|
2558
|
+
const hasCoding = items.some((item) => codingNames.includes(item.name));
|
|
2559
|
+
const visibleItems = items.filter((item) => !(item.kind === "call" && codingNames.includes(item.name) && items.some((other) => other.id === item.id && other.kind !== "call")));
|
|
2358
2560
|
const [expanded, setExpanded] = useState(false);
|
|
2359
2561
|
const contentRef = useRef(null);
|
|
2360
2562
|
const [overflows, setOverflows] = useState(false);
|
|
@@ -2368,12 +2570,12 @@ function ToolGroup({ items, dropCls }) {
|
|
|
2368
2570
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
2369
2571
|
ref: contentRef,
|
|
2370
2572
|
className: "relative overflow-hidden",
|
|
2371
|
-
style: { maxHeight: expanded ? "none" : `${TOOL_GROUP_MAX_HEIGHT_PX}px` },
|
|
2372
|
-
children: [
|
|
2573
|
+
style: { maxHeight: expanded || hasCoding ? "none" : `${TOOL_GROUP_MAX_HEIGHT_PX}px` },
|
|
2574
|
+
children: [visibleItems.map((it, i) => /* @__PURE__ */ jsx(ToolLine, { item: it }, i)), overflows && !expanded && !hasCoding && /* @__PURE__ */ jsx("div", {
|
|
2373
2575
|
className: "pointer-events-none absolute inset-x-0 bottom-0 h-10",
|
|
2374
2576
|
style: { background: "linear-gradient(to bottom, rgba(247,240,229,0), var(--color-ivory))" }
|
|
2375
2577
|
})]
|
|
2376
|
-
}), overflows && /* @__PURE__ */ jsx("button", {
|
|
2578
|
+
}), overflows && !hasCoding && /* @__PURE__ */ jsx("button", {
|
|
2377
2579
|
type: "button",
|
|
2378
2580
|
onClick: () => setExpanded((v) => !v),
|
|
2379
2581
|
className: "mt-2 rounded-sm border border-fawn bg-transparent px-2 py-0.5 text-[0.9em] text-mocha hover:border-sapphire hover:text-sapphire-deep",
|
|
@@ -2382,6 +2584,26 @@ function ToolGroup({ items, dropCls }) {
|
|
|
2382
2584
|
});
|
|
2383
2585
|
}
|
|
2384
2586
|
function ToolLine({ item }) {
|
|
2587
|
+
if (item.name === "send_message" && item.kind !== "error") return /* @__PURE__ */ jsxs("details", {
|
|
2588
|
+
className: "py-1 font-sans text-sm",
|
|
2589
|
+
children: [/* @__PURE__ */ jsx("summary", {
|
|
2590
|
+
className: "cursor-pointer",
|
|
2591
|
+
children: item.kind === "call" ? "Sending teammate message…" : item.body.startsWith("sent message ") ? "Teammate message sent" : "Teammate message status"
|
|
2592
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
2593
|
+
className: "mt-1 max-h-64 overflow-auto whitespace-pre-wrap break-words text-xs",
|
|
2594
|
+
children: item.body
|
|
2595
|
+
})]
|
|
2596
|
+
});
|
|
2597
|
+
if (item.kind !== "error" && [
|
|
2598
|
+
"repository_context",
|
|
2599
|
+
"coding_command",
|
|
2600
|
+
"coding_environment",
|
|
2601
|
+
"coding_receipt"
|
|
2602
|
+
].includes(item.name)) return /* @__PURE__ */ jsx(CodingToolResult, {
|
|
2603
|
+
name: item.name,
|
|
2604
|
+
body: item.body,
|
|
2605
|
+
pending: item.kind === "call"
|
|
2606
|
+
});
|
|
2385
2607
|
if (item.kind === "call") {
|
|
2386
2608
|
const args = prettyArgs(item.body);
|
|
2387
2609
|
const multiLine = args.includes("\n");
|
|
@@ -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-CS5oI7ef.js";
|
|
3
3
|
import { useEffect, useState } from "react";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/ResultSourceConversation.tsx
|
|
@@ -2,7 +2,7 @@ import { n as createServerFn } from "../server.js";
|
|
|
2
2
|
import { t as createSsrRpc } from "./createSsrRpc-6LHNEsSK.js";
|
|
3
3
|
import { createFileRoute, lazyRouteComponent, redirect } from "@tanstack/react-router";
|
|
4
4
|
//#region src/routes/agents/$id/index.tsx
|
|
5
|
-
var $$splitComponentImporter = () => import("./_id-
|
|
5
|
+
var $$splitComponentImporter = () => import("./_id-BnqodC1c2.js");
|
|
6
6
|
var fetchAgent = createServerFn({ method: "POST" }).validator((d) => d).handler(createSsrRpc("846c9081aed17057351730985f133b0aab67a5dabfca9562552829a90ff30849"));
|
|
7
7
|
var Route = createFileRoute("/agents/$id/")({
|
|
8
8
|
validateSearch: (search) => ({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as createServerFn } from "../server.js";
|
|
2
2
|
import { t as createServerRpc } from "./createServerRpc-B7Yr1K8i.js";
|
|
3
|
-
import { n as daemonClient, r as ApiClientError } from "./daemon-client-
|
|
3
|
+
import { n as daemonClient, r as ApiClientError } from "./daemon-client-xWyYKAcx.js";
|
|
4
4
|
//#region src/routes/agents/$id/index.tsx?tss-serverfn-split
|
|
5
5
|
var fetchAgent_createServerFn_handler = createServerRpc({
|
|
6
6
|
id: "846c9081aed17057351730985f133b0aab67a5dabfca9562552829a90ff30849",
|